Merge "msm: sps: Add support to perform BAM reset with pipes connected"
diff --git a/Documentation/devicetree/bindings/arm/msm/msm.txt b/Documentation/devicetree/bindings/arm/msm/msm.txt
index 561a181..bacaeb6 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm.txt
@@ -366,3 +366,4 @@
compatible = "qcom,sdxpoorwills-rumi"
compatible = "qcom,sdxpoorwills-mtp"
compatible = "qcom,sdxpoorwills-cdp"
+compatible = "qcom,mdm9607-ttp"
diff --git a/Documentation/devicetree/bindings/arm/msm/msm_ion.txt b/Documentation/devicetree/bindings/arm/msm/msm_ion.txt
index 6527675..d3325e2 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm_ion.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm_ion.txt
@@ -22,6 +22,7 @@
- "SYSTEM"
- "SYSTEM_CONTIG"
- "CARVEOUT"
+ - "SECURE_CARVEOUT"
- "CHUNK"
- "CP"
- "DMA"
@@ -41,6 +42,7 @@
Will set to a reasonable default value (e.g. the maximum heap size)
if this option is not set.
+
Example:
qcom,ion {
compatible = "qcom,msm-ion";
@@ -70,3 +72,32 @@
qcom,ion-heap-type = "CARVEOUT";
};
};
+
+"SECURE_CARVEOUT"
+
+This heap type is expected to contain multiple child nodes. Each child node
+shall contain the following required properties:
+
+- memory-regions:
+Refer to Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt
+
+- token:
+A u32 containing the set of secure domains which will be able to access the
+memory-region.
+
+Example:
+qcom,ion {
+ compatible = "qcom,msm-ion";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ qcom,ion-heap@14 {
+ reg = <14>;
+ qcom,ion-heap-type = "SECURE_CARVEOUT";
+
+ node1 {
+ memory-regions = <&cp_region>;
+ token = <ION_FLAG_CP_TOUCH>;
+ };
+ };
+};
diff --git a/Documentation/devicetree/bindings/cnss/cnss-wlan.txt b/Documentation/devicetree/bindings/cnss/cnss-wlan.txt
index 9dff08d..ea3afc7 100644
--- a/Documentation/devicetree/bindings/cnss/cnss-wlan.txt
+++ b/Documentation/devicetree/bindings/cnss/cnss-wlan.txt
@@ -36,6 +36,8 @@
always on regulator in VDDmin.
- vdd-wlan-core-supply: phandle to the 1.3V CORE regulator for QCA6174
- vdd-wlan-sp2t-supply: phandle to the 2.7V SP2T regulator for QCA6174
+ - qcom,smmu-s1-enable: Boolean property to decide whether to enable SMMU
+ S1 stage or not
- qcom,wlan-smmu-iova-address: I/O virtual address range as <start length>
format to be used for allocations associated
between WLAN/PCIe and SMMU
diff --git a/Documentation/devicetree/bindings/input/touchscreen/focaltech_ts.txt b/Documentation/devicetree/bindings/input/touchscreen/focaltech_ts.txt
new file mode 100644
index 0000000..4a1b751
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/focaltech_ts.txt
@@ -0,0 +1,53 @@
+FocalTech touch controller
+
+The focaltech controller is connected to host processor
+via i2c. The controller generates interrupts when the
+user touches the panel. The host controller is expected
+to read the touch coordinates over i2c and pass the coordinates
+to the rest of the system.
+
+Required properties:
+
+ - compatible : should be "focaltech,fts".
+ - 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.
+ - vdd-supply : Power supply needed to power up the device.
+ - vcc-i2c-supply : Power source required to power up i2c bus.
+ - focaltech,irq-gpio : irq gpio which is to provide interrupts to host,
+ same as "interrupts" node. It will also
+ contain active low or active high information.
+ - focaltech,reset-gpio : reset gpio to control the reset of chip.
+ - focaltech,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:
+ - focaltech,max-touch-number : maximnum number of touch points supported.
+ - focaltech,have-key : specify whether virtual keys are present.
+ - focaltech,key-number : number of keys, maximum 3.
+ - focaltech,keys : array of key code.
+ - focaltech,key-y-coord : y coordinate for the keys.
+ - focaltech,key-x-coords : array of x coordinates for the keys.
+
+Example:
+ i2c@f9923000{
+ focaltech@38{
+ compatible = "focaltech,fts";
+ reg = <0x38>;
+ interrupt-parent = <&msmgpio>;
+ interrupts = <98 0x2008>;
+ vdd-supply = <&pm8110_l19>;
+ vcc_i2c-supply = <&pm8110_l14>;
+ focaltech,reset-gpio = <&msmgpio 16 0x00>;
+ focaltech,irq-gpio = <&msmgpio 98 0x2008>;
+ focaltech,display-coords = <0 0 480 800>;
+ focaltech,max-touch-number = <2>;
+ focaltech,have-key;
+ focaltech,key-number = <3>;
+ focaltech,keys = <139 142 140>;
+ focaltech,key-y-coord = <700>;
+ focaltech,key-x-coords = <80 240 400>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,mdm9607-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/qcom,mdm9607-pinctrl.txt
new file mode 100644
index 0000000..7d48334
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,mdm9607-pinctrl.txt
@@ -0,0 +1,191 @@
+Qualcomm Technologies, Inc. MDM9607 TLMM block
+
+This binding describes the Top Level Mode Multiplexer block found in the
+MDM9607 platform.
+
+- compatible:
+ Usage: required
+ Value type: <string>
+ Definition: must be "qcom,mdm9607-pinctrl"
+
+- reg:
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: the base address and size of the TLMM register space.
+
+- interrupts:
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: should specify the TLMM summary IRQ.
+
+- interrupt-controller:
+ Usage: required
+ Value type: <none>
+ Definition: identifies this node as an interrupt controller
+
+- #interrupt-cells:
+ Usage: required
+ Value type: <u32>
+ Definition: must be 2. Specifying the pin number and flags, as defined
+ in <dt-bindings/interrupt-controller/irq.h>
+
+- gpio-controller:
+ Usage: required
+ Value type: <none>
+ Definition: identifies this node as a gpio controller
+
+- #gpio-cells:
+ Usage: required
+ Value type: <u32>
+ Definition: must be 2. Specifying the pin number and flags, as defined
+ in <dt-bindings/gpio/gpio.h>
+
+- qcom,tlmm-emmc-boot-select:
+ Usage: optional
+ Value type: <u32>
+ Definition: selects the bit-field position to set.
+
+Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for
+a general description of GPIO and interrupt bindings.
+
+Please refer to pinctrl-bindings.txt in this directory for details of the
+common pinctrl bindings used by client devices, including the meaning of the
+phrase "pin configuration node".
+
+The pin configuration nodes act as a container for an arbitrary number of
+subnodes. Each of these subnodes represents some desired configuration for a
+pin, a group, or a list of pins or groups. This configuration can include the
+mux function to select on those pin(s)/group(s), and various pin configuration
+parameters, such as pull-up, drive strength, etc.
+
+
+PIN CONFIGURATION NODES:
+
+The name of each subnode is not important; all subnodes should be enumerated
+and processed purely based on their content.
+
+Each subnode only affects those parameters that are explicitly listed. In
+other words, a subnode that lists a mux function but no pin configuration
+parameters implies no information about any pin configuration parameters.
+Similarly, a pin subnode that describes a pullup parameter implies no
+information about e.g. the mux function.
+
+
+The following generic properties as defined in pinctrl-bindings.txt are valid
+to specify in a pin configuration subnode:
+
+- pins:
+ Usage: required
+ Value type: <string-array>
+ Definition: List of gpio pins affected by the properties specified in
+ this subnode. Valid pins are:
+ gpio0-gpio79,
+ sdc1_clk,
+ sdc1_cmd,
+ sdc1_data,
+ sdc2_clk,
+ sdc2_cmd,
+ sdc2_data,
+ qdsd_clk,
+ qdsd_cmd,
+ qdsd_data0,
+ qdsd_data1,
+ qdsd_data2,
+ qdsd_data3
+
+- function:
+ Usage: required
+ Value type: <string>
+ Definition: Specify the alternative function to be configured for the
+ specified pins. Functions are only valid for gpio pins.
+ Valid values are:
+
+ blsp_spi3, blsp_uart3, qdss_tracedata_a, bimc_dte1, blsp_i2c3,
+ qdss_traceclk_a, bimc_dte0, qdss_cti_trig_in_a1, blsp_spi2,
+ blsp_uart2, blsp_uim2, blsp_i2c2, qdss_tracectl_a, sensor_int2,
+ blsp_spi5, blsp_uart5, ebi2_lcd, m_voc, sensor_int3, sensor_en,
+ blsp_i2c5, ebi2_a, qdss_tracedata_b, sensor_rst, blsp2_spi,
+ blsp_spi1, blsp_uart1, blsp_uim1, blsp3_spi, gcc_gp2_clk_b,
+ gcc_gp3_clk_b, blsp_i2c1, gcc_gp1_clk_b, blsp_spi4, blsp_uart4,
+ rcm_marker1, blsp_i2c4, qdss_cti_trig_out_a1, rcm_marker2,
+ qdss_cti_trig_out_a0, blsp_spi6, blsp_uart6, pri_mi2s_ws_a,
+ ebi2_lcd_te_b, blsp1_spi, backlight_en_b, pri_mi2s_data0_a,
+ pri_mi2s_data1_a, blsp_i2c6, ebi2_a_d_8_b, pri_mi2s_sck_a,
+ ebi2_lcd_cs_n_b, touch_rst, pri_mi2s_mclk_a, pwr_nav_enabled_a,
+ ts_int, sd_write, pwr_crypto_enabled_a, codec_rst, adsp_ext,
+ atest_combodac_to_gpio_native, uim2_data, gmac_mdio, gcc_gp1_clk_a,
+ uim2_clk, gcc_gp2_clk_a, eth_irq, uim2_reset, gcc_gp3_clk_a,
+ eth_rst, uim2_present, prng_rosc, uim1_data, uim1_clk,
+ uim1_reset, uim1_present, gcc_plltest, uim_batt, coex_uart,
+ codec_int, qdss_cti_trig_in_a0, atest_bbrx1, cri_trng0, atest_bbrx0,
+ cri_trng, qdss_cti_trig_in_b0, atest_gpsadc_dtest0_native,
+ qdss_cti_trig_out_b0, qdss_tracectl_b, qdss_traceclk_b, pa_indicator,
+ modem_tsync, nav_tsync_out_a, nav_ptp_pps_in_a, ptp_pps_out_a,
+ gsm0_tx, qdss_cti_trig_in_b1, cri_trng1, qdss_cti_trig_out_b1,
+ ssbi1, atest_gpsadc_dtest1_native, ssbi2, atest_char3, atest_char2,
+ atest_char1, atest_char0, atest_char, ebi0_wrcdc, ldo_update,
+ gcc_tlmm, ldo_en, dbg_out, atest_tsens, lcd_rst, wlan_en1,
+ nav_tsync_out_b, nav_ptp_pps_in_b, ptp_pps_out_b, pbs0, sec_mi2s,
+ pwr_modem_enabled_a, pbs1, pwr_modem_enabled_b, pbs2, pwr_nav_enabled_b,
+ pwr_crypto_enabled_b, gpio
+
+- bias-disable:
+ Usage: optional
+ Value type: <none>
+ Definition: The specified pins should be configued as no pull.
+
+- bias-pull-down:
+ Usage: optional
+ Value type: <none>
+ Definition: The specified pins should be configued as pull down.
+
+- bias-pull-up:
+ Usage: optional
+ Value type: <none>
+ Definition: The specified pins should be configued as pull up.
+
+- output-high:
+ Usage: optional
+ Value type: <none>
+ Definition: The specified pins are configured in output mode, driven
+ high.
+ Not valid for sdc pins.
+
+- output-low:
+ Usage: optional
+ Value type: <none>
+ Definition: The specified pins are configured in output mode, driven
+ low.
+ Not valid for sdc pins.
+
+- drive-strength:
+ Usage: optional
+ Value type: <u32>
+ Definition: Selects the drive strength for the specified pins, in mA.
+ Valid values are: 2, 4, 6, 8, 10, 12, 14 and 16
+
+Example:
+
+ tlmm: pinctrl@01010000 {
+ compatible = "qcom,mdm9607-pinctrl";
+ reg = <0x01010000 0x300000>;
+ interrupts = <0 208 0>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ qcom,tlmm-emmc-boot-select = <0x1>;
+
+ uart_console_active: uart_console_active {
+ mux {
+ pins = "gpio8", "gpio9";
+ function = "blsp_uart5";
+ };
+
+ config {
+ pins = "gpio8", "gpio9";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/power/supply/qcom/smb1390-charger.txt b/Documentation/devicetree/bindings/power/supply/qcom/smb1390-charger.txt
new file mode 100644
index 0000000..b55d517
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/supply/qcom/smb1390-charger.txt
@@ -0,0 +1,73 @@
+Qualcomm Technologies, Inc. SMB1390 Charger Specific Bindings
+
+SMB1390 charge pump is paired with QTI family of standalone chargers to
+enable a high current, high efficiency Li+ battery charging system.
+
+=======================
+Required Node Structure
+=======================
+
+SMB1390 Charger must be described in two levels of device nodes.
+
+==================================
+First Level Node - SMB1390 Charger
+==================================
+
+Charger specific properties:
+- compatible
+ Usage: required
+ Value type: <string>
+ Definition: "qcom,smb1390-charger".
+
+- qcom,pmic-revid
+ Usage: required
+ Value type: phandle
+ Definition: Should specify the phandle of SMB's revid module. This is used
+ to identify the SMB subtype.
+
+- qcom,channel-num
+ Usage: required
+ Value type: <u32>
+ Definition: Specifies the ADC channel number for reading die temperature.
+
+================================================
+Second Level Nodes - SMB1390 Charger Peripherals
+================================================
+
+Peripheral specific properties:
+- interrupts
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: Peripheral interrupt specifier.
+
+- interrupt-names
+ Usage: required
+ Value type: <stringlist>
+ Definition: Interrupt names. This list must match up 1-to-1 with the
+ interrupts specified in the 'interrupts' property.
+
+=======
+Example
+=======
+
+smb1390_charger: qcom,charge_pump {
+ compatible = "qcom,smb1390-charger";
+ qcom,pmic-revid = <&smb1390_revid>;
+ qcom,channel-num = <15>
+ interrupt-parent = <&smb1390>;
+ qcom,smb-vadc = <&pm8998_vadc>;
+ status = "disabled";
+
+ qcom,core {
+ interrupts = <0x10 0x0 IRQ_TYPE_EDGE_RISING>,
+ <0x10 0x1 IRQ_TYPE_EDGE_RISING>,
+ <0x10 0x2 IRQ_TYPE_EDGE_RISING>,
+ <0x10 0x3 IRQ_TYPE_EDGE_RISING>,
+ <0x10 0x4 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "switcher-off-window",
+ "switcher-off-fault",
+ "vph-ov-soft",
+ "ilim",
+ "temp-alarm";
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/Makefile b/arch/arm/boot/dts/qcom/Makefile
index d9be3c3..29151fc 100644
--- a/arch/arm/boot/dts/qcom/Makefile
+++ b/arch/arm/boot/dts/qcom/Makefile
@@ -12,6 +12,9 @@
mdm9650-v1.1-nand-mtp.dtb \
mdm9650-v1.1-nand-cv2x.dtb
+dtb-$(CONFIG_ARCH_MDM9607) += mdm9607-mtp.dtb \
+ mdm9607-ttp.dtb
+
targets += dtbs
targets += $(addprefix ../, $(dtb-y))
diff --git a/arch/arm/boot/dts/qcom/mdm9607-bus.dtsi b/arch/arm/boot/dts/qcom/mdm9607-bus.dtsi
new file mode 100644
index 0000000..ffb466e
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/mdm9607-bus.dtsi
@@ -0,0 +1,677 @@
+/* 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.
+ */
+
+#include <dt-bindings/msm/msm-bus-ids.h>
+
+&soc {
+ /* Version = 1 */
+ ad_hoc_bus: ad-hoc-bus {
+ compatible = "qcom,msm-bus-device";
+ reg = <0x401000 0x58000>,
+ <0x500000 0x15080>;
+ reg-names = "bimc-base", "pcnoc-base";
+
+ /* Buses */
+
+ fab_bimc: fab-bimc {
+ cell-id = <MSM_BUS_FAB_BIMC>;
+ label = "fab-bimc";
+ qcom,fab-dev;
+ qcom,base-name = "bimc-base";
+ qcom,bus-type = <2>;
+ qcom,util-fact = <154>;
+ clock-names = "bus_clk", "bus_a_clk";
+ clocks = <&clock_gcc clk_bimc_msmbus_clk>,
+ <&clock_gcc clk_bimc_msmbus_a_clk>;
+
+ coresight-id = <203>;
+ coresight-name = "coresight-bimc";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in0>;
+ coresight-child-ports = <3>;
+ };
+
+ fab_pcnoc: fab-pcnoc {
+ cell-id = <MSM_BUS_FAB_PERIPH_NOC>;
+ label = "fab-pcnoc";
+ qcom,fab-dev;
+ qcom,base-name = "pcnoc-base";
+ qcom,base-offset = <0x7000>;
+ qcom,qos-off = <0x1000>;
+ qcom,bus-type = <1>;
+ clock-names = "bus_clk", "bus_a_clk";
+ clocks = <&clock_gcc clk_pcnoc_msmbus_clk>,
+ <&clock_gcc clk_pcnoc_msmbus_a_clk>;
+
+ coresight-id = <201>;
+ coresight-name = "coresight-pcnoc";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in2>;
+ coresight-child-ports = <0>;
+ };
+
+ /* Masters */
+
+ mas_apps_proc: mas-apps-proc {
+ cell-id = <MSM_BUS_MASTER_AMPSS_M0>;
+ label = "mas-apps-proc";
+ qcom,buswidth = <8>;
+ qcom,agg-ports = <1>;
+ qcom,ap-owned;
+ qcom,qport = <0>;
+ qcom,qos-mode = "fixed";
+ qcom,connections = < &slv_bimc_pcnoc &slv_ebi>;
+ qcom,prio-lvl = <0>;
+ qcom,prio-rd = <0>;
+ qcom,prio-wr = <0>;
+ qcom,bus-dev = <&fab_bimc>;
+ qcom,mas-rpm-id = <ICBID_MASTER_APPSS_PROC>;
+ };
+
+ mas_pcnoc_bimc_1: mas-pcnoc-bimc-1 {
+ cell-id = <MSM_BUS_MASTER_PCNOC_BIMC_1>;
+ label = "mas-pcnoc-bimc-1";
+ qcom,buswidth = <8>;
+ qcom,agg-ports = <1>;
+ qcom,connections = <&slv_ebi>;
+ qcom,bus-dev = <&fab_bimc>;
+ qcom,mas-rpm-id = <ICBID_MASTER_PCNOC_BIMC_1>;
+ };
+
+ mas_tcu_0: mas-tcu-0 {
+ cell-id = <MSM_BUS_MASTER_TCU_0>;
+ label = "mas-tcu-0";
+ qcom,buswidth = <8>;
+ qcom,agg-ports = <1>;
+ qcom,ap-owned;
+ qcom,qport = <5>;
+ qcom,qos-mode = "fixed";
+ qcom,connections = <&slv_ebi>;
+ qcom,prio-lvl = <2>;
+ qcom,prio-rd = <2>;
+ qcom,prio-wr = <2>;
+ qcom,bus-dev = <&fab_bimc>;
+ qcom,mas-rpm-id = <ICBID_MASTER_TCU_0>;
+ };
+
+ mas_qdss_bam: mas-qdss-bam {
+ cell-id = <MSM_BUS_MASTER_QDSS_BAM>;
+ label = "mas-qdss-bam";
+ qcom,buswidth = <4>;
+ qcom,agg-ports = <1>;
+ qcom,connections = <&qdss_int>;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,mas-rpm-id = <ICBID_MASTER_QDSS_BAM>;
+ qcom,blacklist = <&pcnoc_s_1 &pcnoc_s_2 &pcnoc_s_0
+ &pcnoc_s_4 &pcnoc_s_5 &pcnoc_s_3 &slv_tcu>;
+ };
+
+ mas_bimc_pcnoc: mas-bimc-pcnoc {
+ cell-id = <MSM_BUS_MASTER_BIMC_PCNOC>;
+ label = "mas-bimc-pcnoc";
+ qcom,buswidth = <8>;
+ qcom,agg-ports = <1>;
+ qcom,connections = <&pcnoc_int_0
+ &pcnoc_int_2 &slv_cats_0>;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,mas-rpm-id = <ICBID_MASTER_BIMC_PCNOC>;
+ };
+
+ mas_qdss_etr: mas-qdss-etr {
+ cell-id = <MSM_BUS_MASTER_QDSS_ETR>;
+ label = "mas-qdss-etr";
+ qcom,buswidth = <8>;
+ qcom,agg-ports = <1>;
+ qcom,connections = <&qdss_int>;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,mas-rpm-id = <ICBID_MASTER_QDSS_ETR>;
+ qcom,blacklist = <&pcnoc_s_0 &pcnoc_s_2
+ &pcnoc_s_3 &pcnoc_s_4 &pcnoc_s_5
+ &slv_crypto_0_cfg &slv_message_ram
+ &slv_pdm &slv_prng &slv_qdss_stm
+ &slv_tcu>;
+ };
+
+ mas_audio: mas-audio {
+ cell-id = <MSM_BUS_MASTER_AUDIO>;
+ label = "mas-audio";
+ qcom,buswidth = <4>;
+ qcom,agg-ports = <1>;
+ qcom,connections = <&pcnoc_m_0>;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,mas-rpm-id = <ICBID_MASTER_AUDIO>;
+ qcom,blacklist = <&pcnoc_s_0 &pcnoc_s_1
+ &pcnoc_s_2 &pcnoc_s_3
+ &pcnoc_s_4 &pcnoc_s_5 &slv_tcu>;
+ };
+
+ mas_qpic: mas-qpic {
+ cell-id = <MSM_BUS_MASTER_QPIC>;
+ label = "mas-qpic";
+ qcom,buswidth = <4>;
+ qcom,agg-ports = <1>;
+ qcom,connections = <&pcnoc_m_0>;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,mas-rpm-id = <ICBID_MASTER_QPIC>;
+ qcom,blacklist = <&pcnoc_s_0 &pcnoc_s_2
+ &pcnoc_s_3 &pcnoc_s_4
+ &pcnoc_s_5 &slv_tcu
+ &slv_crypto_0_cfg &slv_pdm
+ &slv_prng &slv_usb2 >;
+ };
+
+ mas_hsic: mas-hsic {
+ cell-id = <MSM_BUS_MASTER_USB_HSIC>;
+ label = "mas-hsic";
+ qcom,buswidth = <4>;
+ qcom,agg-ports = <1>;
+ qcom,connections = <&pcnoc_m_0>;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,mas-rpm-id = <ICBID_MASTER_USB_HSIC>;
+ };
+
+ mas_blsp_1: mas-blsp-1 {
+ cell-id = <MSM_BUS_MASTER_BLSP_1>;
+ label = "mas-blsp-1";
+ qcom,buswidth = <4>;
+ qcom,agg-ports = <1>;
+ qcom,connections = <&pcnoc_m_1>;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,mas-rpm-id = <ICBID_MASTER_BLSP_1>;
+ qcom,blacklist = <&pcnoc_s_0 &pcnoc_s_1
+ &pcnoc_s_2 &pcnoc_s_3
+ &pcnoc_s_4 &pcnoc_s_5 &slv_tcu >;
+ };
+
+ mas_usb_hs1: mas-usb-hs1 {
+ cell-id = <MSM_BUS_MASTER_USB_HS>;
+ label = "mas-usb-hs1";
+ qcom,buswidth = <4>;
+ qcom,agg-ports = <1>;
+ qcom,connections = <&pcnoc_m_1>;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,mas-rpm-id = <ICBID_MASTER_USB_HS1>;
+ qcom,blacklist = <&pcnoc_s_0 &pcnoc_s_2 &pcnoc_s_4
+ &pcnoc_s_5 &slv_tcu
+ &slv_crypto_0_cfg
+ &slv_pdm &slv_prng &slv_usb2
+ &slv_usb_phy> ;
+ };
+
+ mas_crypto: mas-crypto {
+ cell-id = <MSM_BUS_MASTER_CRYPTO>;
+ label = "mas-crypto";
+ qcom,buswidth = <8>;
+ qcom,agg-ports = <1>;
+ qcom,ap-owned;
+ qcom,qport = <0>;
+ qcom,qos-mode = "fixed";
+ qcom,connections = <&pcnoc_int_3>;
+ qcom,prio1 = <2>;
+ qcom,prio0 = <2>;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,mas-rpm-id = <ICBID_MASTER_CRYPTO>;
+ qcom,blacklist = <&pcnoc_s_0 &pcnoc_s_2 &pcnoc_s_3
+ &pcnoc_s_4 &pcnoc_s_5 &slv_tcu
+ &slv_crypto_0_cfg &slv_pdm
+ &slv_usb2 &slv_prng>;
+ };
+
+ mas_sdcc_1: mas-sdcc-1 {
+ cell-id = <MSM_BUS_MASTER_SDCC_1>;
+ label = "mas-sdcc-1";
+ qcom,buswidth = <8>;
+ qcom,agg-ports = <1>;
+ qcom,connections = <&pcnoc_int_3>;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,mas-rpm-id = <ICBID_MASTER_SDCC_1>;
+ qcom,blacklist = <&pcnoc_s_0 &pcnoc_s_2 &pcnoc_s_3
+ &pcnoc_s_4 &pcnoc_s_5 &slv_tcu
+ &slv_crypto_0_cfg &slv_pdm
+ &slv_usb2 &slv_prng>;
+ };
+
+ mas_sdcc_2: mas-sdcc-2 {
+ cell-id = <MSM_BUS_MASTER_SDCC_2>;
+ label = "mas-sdcc-2";
+ qcom,buswidth = <8>;
+ qcom,agg-ports = <1>;
+ qcom,connections = <&pcnoc_int_3>;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,mas-rpm-id = <ICBID_MASTER_SDCC_2>;
+ qcom,blacklist = <&pcnoc_s_0 &pcnoc_s_2 &pcnoc_s_3
+ &pcnoc_s_4 &pcnoc_s_5 &slv_tcu
+ &slv_crypto_0_cfg &slv_pdm
+ &slv_usb2 &slv_prng>;
+ };
+
+ mas_xi_usb_hs1: mas-xi-usb-hs1 {
+ cell-id = <MSM_BUS_MASTER_XM_USB_HS1>;
+ label = "mas-xi-usb-hs1";
+ qcom,buswidth = <8>;
+ qcom,agg-ports = <1>;
+ qcom,connections = <&slv_pcnoc_bimc_1 &pcnoc_int_2>;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,mas-rpm-id = <ICBID_MASTER_XI_USB_HS1>;
+ qcom,blacklist = <&pcnoc_s_0 &pcnoc_s_2 &pcnoc_s_4
+ &pcnoc_s_5 &slv_tcu &slv_crypto_0_cfg
+ &slv_pdm &slv_usb2 &slv_prng
+ &slv_usb_phy>;
+ };
+
+ mas_xi_hsic: mas-xi-hsic {
+ cell-id = <MSM_BUS_MASTER_XI_USB_HSIC>;
+ label = "mas-xi-hsic";
+ qcom,buswidth = <8>;
+ qcom,agg-ports = <1>;
+ qcom,connections = <&slv_pcnoc_bimc_1 &pcnoc_int_2>;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,mas-rpm-id = <ICBID_MASTER_XI_HSIC>;
+ qcom,blacklist = <&pcnoc_s_0 &pcnoc_s_2
+ &pcnoc_s_3 &pcnoc_s_4 &pcnoc_s_5
+ &slv_tcu &slv_crypto_0_cfg
+ &slv_pdm &slv_usb2 &slv_prng>;
+ };
+
+ mas_sgmii: mas-sgmii {
+ cell-id = <MSM_BUS_MASTER_SGMII>;
+ label = "mas-sgmii";
+ qcom,buswidth = <8>;
+ qcom,agg-ports = <1>;
+ qcom,ap-owned;
+ qcom,qport = <10>;
+ qcom,qos-mode = "fixed";
+ qcom,connections = <&slv_pcnoc_bimc_1 &pcnoc_int_2>;
+ qcom,prio1 = <1>;
+ qcom,prio0 = <1>;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,mas-rpm-id = <ICBID_MASTER_SGMII>;
+ qcom,blacklist = <&pcnoc_s_0 &pcnoc_s_2 &pcnoc_s_3
+ &pcnoc_s_4 &pcnoc_s_5 &slv_tcu
+ &slv_crypto_0_cfg &slv_pdm
+ &slv_usb2 &slv_prng>;
+ };
+
+ /* Internal nodes */
+
+ pcnoc_m_0: pcnoc-m-0 {
+ cell-id = <MSM_BUS_PNOC_M_0>;
+ label = "pcnoc-m-0";
+ qcom,buswidth = <4>;
+ qcom,agg-ports = <1>;
+ qcom,connections = <&slv_pcnoc_bimc_1 &pcnoc_int_2>;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,mas-rpm-id = <ICBID_MASTER_PCNOC_M_0>;
+ qcom,slv-rpm-id = <ICBID_SLAVE_PCNOC_M_0>;
+ };
+
+ pcnoc_m_1: pcnoc-m-1 {
+ cell-id = <MSM_BUS_PNOC_M_1>;
+ label = "pcnoc-m-1";
+ qcom,buswidth = <4>;
+ qcom,agg-ports = <1>;
+ qcom,connections = <&slv_pcnoc_bimc_1 &pcnoc_int_2>;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,mas-rpm-id = <ICBID_MASTER_PCNOC_M_1>;
+ qcom,slv-rpm-id = <ICBID_SLAVE_PCNOC_M_1>;
+ };
+
+ qdss_int: qdss-int {
+ cell-id = <MSM_BUS_SNOC_QDSS_INT>;
+ label = "qdss-int";
+ qcom,buswidth = <8>;
+ qcom,agg-ports = <1>;
+ qcom,connections = <&pcnoc_int_0 &slv_pcnoc_bimc_1>;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,mas-rpm-id = <ICBID_MASTER_QDSS_INT>;
+ qcom,slv-rpm-id = <ICBID_SLAVE_QDSS_INT>;
+ };
+
+ pcnoc_int_0: pcnoc-int-0 {
+ cell-id = <MSM_BUS_PNOC_INT_0>;
+ label = "pcnoc-int-0";
+ qcom,buswidth = <8>;
+ qcom,agg-ports = <1>;
+ qcom,ap-owned;
+ qcom,connections = <&slv_imem &slv_qdss_stm>;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,mas-rpm-id = <ICBID_MASTER_PCNOC_INT_0>;
+ qcom,slv-rpm-id = <ICBID_SLAVE_PCNOC_INT_0>;
+ };
+
+ pcnoc_int_2: pcnoc-int-2 {
+ cell-id = <MSM_BUS_PNOC_INT_2>;
+ label = "pcnoc-int-2";
+ qcom,buswidth = <8>;
+ qcom,agg-ports = <1>;
+ qcom,connections = <&pcnoc_s_1 &pcnoc_s_2
+ &pcnoc_s_0 &pcnoc_s_4
+ &pcnoc_s_5 &pcnoc_s_3
+ &slv_tcu >;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,mas-rpm-id = <ICBID_MASTER_PCNOC_INT_2>;
+ qcom,slv-rpm-id = <ICBID_SLAVE_PCNOC_INT_2>;
+ };
+
+ pcnoc_int_3: pcnoc-int-3 {
+ cell-id = <MSM_BUS_PNOC_INT_3>;
+ label = "pcnoc-int-3";
+ qcom,buswidth = <8>;
+ qcom,agg-ports = <1>;
+ qcom,connections = <&slv_pcnoc_bimc_1 &pcnoc_int_2>;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,mas-rpm-id = <ICBID_MASTER_PCNOC_INT_3>;
+ qcom,slv-rpm-id = <ICBID_SLAVE_PCNOC_INT_3>;
+ };
+
+ pcnoc_s_0: pcnoc-s-0 {
+ cell-id = <MSM_BUS_PNOC_SLV_0>;
+ label = "pcnoc-s-0";
+ qcom,buswidth = <4>;
+ qcom,agg-ports = <1>;
+ qcom,connections = <&slv_tcsr &slv_sdcc_1 &slv_blsp_1
+ &slv_sgmii>;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,mas-rpm-id = <ICBID_MASTER_PCNOC_S_0>;
+ qcom,slv-rpm-id = <ICBID_SLAVE_PCNOC_S_0>;
+ };
+
+ pcnoc_s_1: pcnoc-s-1 {
+ cell-id = <MSM_BUS_PNOC_SLV_1>;
+ label = "pcnoc-s-1";
+ qcom,buswidth = <4>;
+ qcom,agg-ports = <1>;
+ qcom,connections = <&slv_usb2 &slv_crypto_0_cfg
+ &slv_prng &slv_pdm
+ &slv_message_ram>;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,mas-rpm-id = <ICBID_MASTER_PCNOC_S_1>;
+ qcom,slv-rpm-id = <ICBID_SLAVE_PCNOC_S_1>;
+ };
+
+ pcnoc_s_2: pcnoc-s-2 {
+ cell-id = <MSM_BUS_PNOC_SLV_2>;
+ label = "pcnoc-s-2";
+ qcom,buswidth = <4>;
+ qcom,agg-ports = <1>;
+ qcom,connections = <&slv_hsic &slv_sdcc_2 &slv_audio>;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,mas-rpm-id = <ICBID_MASTER_PCNOC_S_2>;
+ qcom,slv-rpm-id = <ICBID_SLAVE_PCNOC_S_2>;
+ };
+
+ pcnoc_s_3: pcnoc-s-3 {
+ cell-id = <MSM_BUS_PNOC_SLV_3>;
+ label = "pcnoc-s-3";
+ qcom,buswidth = <4>;
+ qcom,agg-ports = <1>;
+ qcom,ap-owned;
+ qcom,connections = <&slv_usb_phy>;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,mas-rpm-id = <ICBID_MASTER_PCNOC_S_3>;
+ qcom,slv-rpm-id = <ICBID_SLAVE_PCNOC_S_3>;
+ };
+
+ pcnoc_s_4: pcnoc-s-4 {
+ cell-id = <MSM_BUS_PNOC_SLV_4>;
+ label = "pcnoc-s-4";
+ qcom,buswidth = <4>;
+ qcom,agg-ports = <1>;
+ qcom,connections = <&slv_imem_cfg &slv_pmic_arb>;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,mas-rpm-id = <ICBID_MASTER_PCNOC_S_4>;
+ qcom,slv-rpm-id = <ICBID_SLAVE_PCNOC_S_4>;
+ };
+
+ pcnoc_s_5: pcnoc-s-5 {
+ cell-id = <MSM_BUS_PNOC_SLV_5>;
+ label = "pcnoc-s-5";
+ qcom,buswidth = <4>;
+ qcom,agg-ports = <1>;
+ qcom,connections = <&slv_tlmm>;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,mas-rpm-id = <ICBID_MASTER_PCNOC_S_5>;
+ qcom,slv-rpm-id = <ICBID_SLAVE_PCNOC_S_5>;
+ };
+
+ /* Slaves */
+
+ slv_ebi:slv-ebi {
+ cell-id = <MSM_BUS_SLAVE_EBI_CH0>;
+ label = "slv-ebi";
+ qcom,buswidth = <8>;
+ qcom,agg-ports = <1>;
+ qcom,bus-dev = <&fab_bimc>;
+ qcom,slv-rpm-id = <ICBID_SLAVE_EBI1>;
+ };
+
+ slv_bimc_pcnoc:slv-bimc-pcnoc {
+ cell-id = <MSM_BUS_SLAVE_BIMC_PCNOC>;
+ label = "slv-bimc-pcnoc";
+ qcom,buswidth = <8>;
+ qcom,agg-ports = <1>;
+ qcom,bus-dev = <&fab_bimc>;
+ qcom,connections = <&mas_bimc_pcnoc>;
+ qcom,slv-rpm-id = <ICBID_SLAVE_BIMC_PCNOC>;
+ };
+
+ slv_pcnoc_bimc_1:slv-pcnoc-bimc-1 {
+ cell-id = <MSM_BUS_SLAVE_PCNOC_BIMC_1>;
+ label = "slv-pcnoc-bimc-1";
+ qcom,buswidth = <8>;
+ qcom,agg-ports = <1>;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,connections = <&mas_pcnoc_bimc_1>;
+ qcom,slv-rpm-id = <ICBID_SLAVE_PCNOC_BIMC_1>;
+ };
+
+ slv_qdss_stm:slv-qdss-stm {
+ cell-id = <MSM_BUS_SLAVE_QDSS_STM>;
+ label = "slv-qdss-stm";
+ qcom,buswidth = <4>;
+ qcom,agg-ports = <1>;
+ qcom,ap-owned;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,slv-rpm-id = <ICBID_SLAVE_QDSS_STM>;
+ };
+
+ slv_cats_0:slv-cats-0 {
+ cell-id = <MSM_BUS_SLAVE_CATS_128>;
+ label = "slv-cats-0";
+ qcom,buswidth = <8>;
+ qcom,agg-ports = <1>;
+ qcom,ap-owned;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,slv-rpm-id = <ICBID_SLAVE_CATS_0>;
+ };
+
+ slv_imem:slv-imem {
+ cell-id = <MSM_BUS_SLAVE_SYSTEM_IMEM>;
+ label = "slv-imem";
+ qcom,buswidth = <8>;
+ qcom,agg-ports = <1>;
+ qcom,ap-owned;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,slv-rpm-id = <ICBID_SLAVE_IMEM>;
+ };
+
+ slv_tcsr:slv-tcsr {
+ cell-id = <MSM_BUS_SLAVE_TCSR>;
+ label = "slv-tcsr";
+ qcom,buswidth = <4>;
+ qcom,agg-ports = <1>;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,slv-rpm-id = <ICBID_SLAVE_TCSR>;
+ };
+
+ slv_sdcc_1:slv-sdcc-1 {
+ cell-id = <MSM_BUS_SLAVE_SDCC_1>;
+ label = "slv-sdcc-1";
+ qcom,buswidth = <4>;
+ qcom,agg-ports = <1>;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,slv-rpm-id = <ICBID_SLAVE_SDCC_1>;
+ };
+
+ slv_blsp_1:slv-blsp-1 {
+ cell-id = <MSM_BUS_SLAVE_BLSP_1>;
+ label = "slv-blsp-1";
+ qcom,buswidth = <4>;
+ qcom,agg-ports = <1>;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,slv-rpm-id = <ICBID_SLAVE_BLSP_1>;
+ };
+
+ slv_sgmii:slv-sgmii {
+ cell-id = <MSM_BUS_SLAVE_SGMII>;
+ label = "slv-sgmii";
+ qcom,buswidth = <4>;
+ qcom,agg-ports = <1>;
+ qcom,ap-owned;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,slv-rpm-id = <ICBID_SLAVE_SGMII>;
+ };
+
+ slv_crypto_0_cfg:slv-crypto-0-cfg {
+ cell-id = <MSM_BUS_SLAVE_CRYPTO_0_CFG>;
+ label = "slv-crypto-0-cfg";
+ qcom,buswidth = <4>;
+ qcom,agg-ports = <1>;
+ qcom,ap-owned;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,slv-rpm-id = <ICBID_SLAVE_CRYPTO_0_CFG>;
+ };
+
+ slv_message_ram:slv-message-ram {
+ cell-id = <MSM_BUS_SLAVE_MESSAGE_RAM>;
+ label = "slv-message-ram";
+ qcom,buswidth = <4>;
+ qcom,agg-ports = <1>;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,slv-rpm-id = <ICBID_SLAVE_MESSAGE_RAM>;
+ };
+
+ slv_pdm:slv-pdm {
+ cell-id = <MSM_BUS_SLAVE_PDM>;
+ label = "slv-pdm";
+ qcom,buswidth = <4>;
+ qcom,agg-ports = <1>;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,slv-rpm-id = <ICBID_SLAVE_PDM>;
+ };
+
+ slv_prng:slv-prng {
+ cell-id = <MSM_BUS_SLAVE_PRNG>;
+ label = "slv-prng";
+ qcom,buswidth = <4>;
+ qcom,agg-ports = <1>;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,slv-rpm-id = <ICBID_SLAVE_PRNG>;
+ };
+
+ slv_usb2:slv-usb2 {
+ cell-id = <MSM_BUS_SLAVE_USB_HS>;
+ label = "slv-usb2";
+ qcom,buswidth = <4>;
+ qcom,agg-ports = <1>;
+ qcom,ap-owned;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,slv-rpm-id = <ICBID_SLAVE_USB_HS>;
+ };
+
+ slv_sdcc_2:slv-sdcc-2 {
+ cell-id = <MSM_BUS_SLAVE_SDCC_2>;
+ label = "slv-sdcc-2";
+ qcom,buswidth = <4>;
+ qcom,agg-ports = <1>;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,slv-rpm-id = <ICBID_SLAVE_SDCC_2>;
+ };
+
+ slv_audio:slv-audio {
+ cell-id = <MSM_BUS_SLAVE_AUDIO>;
+ label = "slv-audio";
+ qcom,buswidth = <4>;
+ qcom,agg-ports = <1>;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,slv-rpm-id = <ICBID_SLAVE_AUDIO>;
+ };
+
+ slv_hsic:slv-hsic {
+ cell-id = <MSM_BUS_SLAVE_USB_HSIC>;
+ label = "slv-hsic";
+ qcom,buswidth = <4>;
+ qcom,agg-ports = <1>;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,slv-rpm-id = <ICBID_SLAVE_USB_HSIC>;
+ };
+
+ slv_usb_phy:slv-usb-phy {
+ cell-id = <MSM_BUS_SLAVE_USB_PHYS_CFG>;
+ label = "slv-usb-phy";
+ qcom,buswidth = <4>;
+ qcom,agg-ports = <1>;
+ qcom,ap-owned;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,slv-rpm-id = <ICBID_SLAVE_USB_PHY_CFG>;
+ };
+
+ slv_tlmm:slv-tlmm {
+ cell-id = <MSM_BUS_SLAVE_TLMM>;
+ label = "slv-tlmm";
+ qcom,buswidth = <4>;
+ qcom,agg-ports = <1>;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,slv-rpm-id = <ICBID_SLAVE_TLMM>;
+ };
+
+ slv_imem_cfg:slv-imem-cfg {
+ cell-id = <MSM_BUS_SLAVE_IMEM_CFG>;
+ label = "slv-imem-cfg";
+ qcom,buswidth = <4>;
+ qcom,agg-ports = <1>;
+ qcom,ap-owned;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,slv-rpm-id = <ICBID_SLAVE_IMEM_CFG>;
+ };
+
+ slv_pmic_arb:slv-pmic-arb {
+ cell-id = <MSM_BUS_SLAVE_PMIC_ARB>;
+ label = "slv-pmic-arb";
+ qcom,buswidth = <4>;
+ qcom,agg-ports = <1>;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,slv-rpm-id = <ICBID_SLAVE_PMIC_ARB>;
+ };
+
+ slv_tcu:slv-tcu {
+ cell-id = <MSM_BUS_SLAVE_TCU>;
+ label = "slv-tcu";
+ qcom,buswidth = <8>;
+ qcom,agg-ports = <1>;
+ qcom,ap-owned;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,slv-rpm-id = <ICBID_SLAVE_TCU>;
+ };
+
+ slv_qipc {
+ cell-id = <MSM_BUS_SLAVE_QPIC>;
+ label = "slv-qpic";
+ qcom,buswidth = <4>;
+ qcom,agg-ports = <1>;
+ qcom,bus-dev = <&fab_pcnoc>;
+ qcom,slv-rpm-id = <ICBID_SLAVE_QPIC>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/mdm9607-cdp.dts b/arch/arm/boot/dts/qcom/mdm9607-cdp.dts
new file mode 100644
index 0000000..0133c16
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/mdm9607-cdp.dts
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+/dts-v1/;
+
+#include "mdm9607-cdp.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. MDM 9607 CDP";
+ compatible = "qcom,mdm9607-cdp", "qcom,mdm9607", "qcom,cdp";
+ qcom,board-id = <1 0>;
+};
diff --git a/arch/arm/boot/dts/qcom/mdm9607-cdp.dtsi b/arch/arm/boot/dts/qcom/mdm9607-cdp.dtsi
new file mode 100644
index 0000000..9940f56
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/mdm9607-cdp.dtsi
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2015-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.
+ */
+
+#include "mdm9607.dtsi"
+#include "mdm9607-pinctrl.dtsi"
+#include "mdm9607-display.dtsi"
+#include "qpic-panel-ili-hvga.dtsi"
+
+/ {
+ bluetooth: bt_qca6174 {
+ compatible = "qca,qca6174";
+ qca,bt-reset-gpio = <&pm8019_gpios 2 0>; /* BT_EN */
+ qca,bt-vdd-pa-supply = <&rome_vreg>;
+ qca,bt-vdd-io-supply = <&mdm9607_l11>;
+ qca,bt-vdd-xtal-supply = <&mdm9607_l2>;
+ qca,bt-vdd-io-voltage-level = <1800000 1800000>;
+ qca,bt-vdd-xtal-voltage-level = <1800000 1800000>;
+ };
+};
+
+&soc {
+};
+
+&blsp1_uart5 {
+ status = "ok";
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart_console_sleep>;
+};
+
+&i2c_4 {
+ status = "ok";
+};
+
+&spi_1 {
+ status = "ok";
+};
+
+&blsp1_uart3 {
+ status = "ok";
+};
+
+&qnand_1 {
+ status = "ok";
+};
+
+&emac0 {
+ status = "ok";
+};
+
+/* MPP pin 2 configs for SMB358 interrupt line */
+&pm8019_mpps {
+ mpp@a100 {
+ qcom,mode = <0>; /* Digital input */
+ qcom,vin-sel = <3>; /* 1.8V (L11) */
+ qcom,src-sel = <0>; /* QPNP_PIN_SEL_FUNC_CONSTANT */
+ qcom,pull = <2>; /* PULL UP 10KOHM */
+ qcom,master-en = <1>;
+ };
+};
+
+&pm8019_gpios {
+ gpio@c100 { /* BT_EN */
+ qcom,mode = <1>; /* Digital output*/
+ qcom,pull = <4>; /* Pulldown 10uA */
+ qcom,vin-sel = <2>; /* VIN2 */
+ qcom,src-sel = <0>; /* GPIO */
+ qcom,invert = <0>; /* Invert */
+ qcom,master-en = <1>; /* Enable GPIO */
+ status = "ok";
+ };
+
+ /* PMIC gpio for wlan power supply */
+ gpio@c200 {
+ qcom,mode = <1>; /* Digital output */
+ qcom,output-type = <0>; /* CMOS logic */
+ qcom,invert = <1>; /* Output high */
+ qcom,vin-sel = <3>; /* VPH_PWR */
+ qcom,src-sel = <0>; /* Constant */
+ qcom,out-strength = <1>; /* High drive strength */
+ qcom,master-en = <1>; /* Enable GPIO */
+ status = "okay";
+ };
+
+ /* ROME 32k Sleep Clock */
+ gpio@c500 {
+ qcom,mode = <1>; /* Digital output */
+ qcom,output-type = <0>; /* CMOS logic */
+ qcom,invert = <0>; /* no inversion */
+ qcom,vin-sel = <2>; /* VIN 2 */
+ qcom,src-sel = <2>; /* Function 2 */
+ qcom,out-strength = <2>; /* Medium */
+ qcom,master-en = <1>; /* Enable GPIO */
+ status = "ok";
+ };
+};
+
+/* MPP pin 4 configs for SGMII */
+&pm8019_mpps {
+ mpp@a300 { /* MPP 4 */
+ qcom,mode = <1>; /* Digital output */
+ qcom,vin-sel = <2>; /* 1.8V */
+ qcom,src-sel = <0>; /* Constant */
+ qcom,master-en = <1>; /* Enable GPIO */
+ status = "okay";
+ };
+};
+
+&sdhc_1 {
+ vdd-io-supply = <&mdm9607_l11>;
+ qcom,vdd-io-always-on;
+ qcom,vdd-io-voltage-level = <1800000 1800000>;
+ qcom,vdd-io-current-level = <0 30000>;
+
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&pmx_sdc1_clk_on &pmx_sdc1_cmd_on &pmx_sdc1_data_on
+ &sdc1_wlan_gpio_active>;
+ pinctrl-1 = <&pmx_sdc1_clk_off &pmx_sdc1_cmd_off &pmx_sdc1_data_off
+ &sdc1_wlan_gpio_sleep>;
+ qcom,nonremovable;
+ qcom,core_3_0v_support;
+ status = "ok";
+};
+
+&hsic {
+ status = "ok";
+};
+
+&android_usb_hsic {
+ status = "ok";
+};
+
+&sdhc_2 {
+ vdd-supply = <&sdcard_ext_vreg>;
+ qcom,vdd-voltage-level = <2850000 2850000>;
+ qcom,vdd-current-level = <15000 400000>;
+
+ vdd-io-supply = <&mdm9607_l13>;
+ qcom,vdd-io-voltage-level = <1800000 2850000>;
+ qcom,vdd-io-current-level = <200 50000>;
+
+ #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_pinmux 26 0>;
+ interrupt-names = "hc_irq", "pwr_irq", "status_irq";
+ cd-gpios = <&tlmm_pinmux 26 0x1>;
+
+ 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>;
+
+ status = "disabled";
+};
+
+/* Display */
+&mdss_qpic {
+ pinctrl-names= "mdss_default", "mdss_sleep";
+ pinctrl-0 = <&mdss_ldo_active &mdss_cs_active &mdss_te_active
+ &mdss_rs_active &mdss_ad_active &mdss_bl_active>;
+ pinctrl-1 = <&mdss_ldo_sleep &mdss_cs_sleep &mdss_te_sleep
+ &mdss_rs_sleep &mdss_ad_sleep &mdss_bl_sleep>;
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/qcom/mdm9607-coresight.dtsi b/arch/arm/boot/dts/qcom/mdm9607-coresight.dtsi
new file mode 100644
index 0000000..fd35177
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/mdm9607-coresight.dtsi
@@ -0,0 +1,462 @@
+/*
+ * 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.
+ */
+
+&soc {
+ tmc_etr: tmc@6026000 {
+ compatible = "arm,coresight-tmc";
+ reg = <0x6026000 0x1000>,
+ <0x6084000 0x15000>;
+ reg-names = "tmc-base", "bam-base";
+ interrupts = <0 166 0>;
+ interrupt-names = "byte-cntr-irq";
+
+ qcom,memory-size = <0x100000>;
+ qcom,sg-enable;
+
+ coresight-id = <0>;
+ coresight-name = "coresight-tmc-etr";
+ coresight-nr-inports = <1>;
+ coresight-ctis = <&cti0 &cti8>;
+
+ clocks = <&clock_gcc clk_qdss_clk>,
+ <&clock_gcc clk_qdss_a_clk>;
+ clock-names = "core_clk", "core_a_clk";
+ };
+
+ tpiu: tpiu@6020000 {
+ compatible = "arm,coresight-tpiu";
+ reg = <0x6020000 0x1000>,
+ <0x1100000 0xb0000>;
+ reg-names = "tpiu-base", "nidnt-base";
+
+ coresight-id = <1>;
+ coresight-name = "coresight-tpiu";
+ coresight-nr-inports = <1>;
+
+ pinctrl-names = "sdcard", "trace", "swduart",
+ "swdtrc", "jtag", "spmi";
+ /* NIDnT */
+ pinctrl-0 = <&qdsd_clk_sdcard &qdsd_cmd_sdcard
+ &qdsd_data0_sdcard &qdsd_data1_sdcard
+ &qdsd_data2_sdcard &qdsd_data3_sdcard>;
+ pinctrl-1 = <&qdsd_clk_trace &qdsd_cmd_trace
+ &qdsd_data0_trace &qdsd_data1_trace
+ &qdsd_data2_trace &qdsd_data3_trace>;
+ pinctrl-2 = <&qdsd_cmd_swduart &qdsd_data0_swduart
+ &qdsd_data1_swduart &qdsd_data2_swduart
+ &qdsd_data3_swduart>;
+ pinctrl-3 = <&qdsd_clk_swdtrc &qdsd_cmd_swdtrc
+ &qdsd_data0_swdtrc &qdsd_data1_swdtrc
+ &qdsd_data2_swdtrc &qdsd_data3_swdtrc>;
+ pinctrl-4 = <&qdsd_cmd_jtag &qdsd_data0_jtag
+ &qdsd_data1_jtag &qdsd_data2_jtag
+ &qdsd_data3_jtag>;
+ pinctrl-5 = <&qdsd_clk_spmi &qdsd_cmd_spmi
+ &qdsd_data0_spmi &qdsd_data3_spmi>;
+
+ qcom,nidnthw;
+ qcom,nidnt-swduart;
+ qcom,nidnt-swdtrc;
+ qcom,nidnt-jtag;
+ qcom,nidnt-spmi;
+ nidnt-gpio = <26>;
+ nidnt-gpio-polarity = <1>;
+
+ interrupts = <0 82 0>;
+ interrupt-names = "nidnt-irq";
+
+ vdd-supply = <&sdcard_ext_vreg>;
+ qcom,vdd-voltage-level = <2850000 2850000>;
+ qcom,vdd-current-level = <15 400000>;
+
+ vdd-io-supply = <&mdm9607_l13>;
+ qcom,vdd-io-voltage-level = <1800000 2950000>;
+ qcom,vdd-io-current-level = <200 300000>;
+
+ clocks = <&clock_gcc clk_qdss_clk>,
+ <&clock_gcc clk_qdss_a_clk>;
+ clock-names = "core_clk", "core_a_clk";
+ };
+
+ replicator: replicator@6024000 {
+ compatible = "qcom,coresight-replicator";
+ reg = <0x6024000 0x1000>;
+ reg-names = "replicator-base";
+
+ coresight-id = <2>;
+ coresight-name = "coresight-replicator";
+ coresight-nr-inports = <1>;
+ coresight-outports = <0 1>;
+ coresight-child-list = <&tmc_etr &tpiu>;
+ coresight-child-ports = <0 0>;
+
+ clocks = <&clock_gcc clk_qdss_clk>,
+ <&clock_gcc clk_qdss_a_clk>;
+ clock-names = "core_clk", "core_a_clk";
+ };
+
+ tmc_etf: tmc@6025000 {
+ compatible = "arm,coresight-tmc";
+ reg = <0x6025000 0x1000>;
+ reg-names = "tmc-base";
+
+ coresight-id = <3>;
+ coresight-name = "coresight-tmc-etf";
+ coresight-nr-inports = <1>;
+ coresight-outports = <0>;
+ coresight-child-list = <&replicator>;
+ coresight-child-ports = <0>;
+ coresight-default-sink;
+ coresight-ctis = <&cti0 &cti8>;
+
+ clocks = <&clock_gcc clk_qdss_clk>,
+ <&clock_gcc clk_qdss_a_clk>;
+ clock-names = "core_clk", "core_a_clk";
+ };
+
+ funnel_in0: funnel@6021000 {
+ compatible = "arm,coresight-funnel";
+ reg = <0x6021000 0x1000>;
+ reg-names = "funnel-base";
+
+ coresight-id = <4>;
+ coresight-name = "coresight-funnel-in0";
+ coresight-nr-inports = <8>;
+ coresight-outports = <0>;
+ coresight-child-list = <&tmc_etf>;
+ coresight-child-ports = <0>;
+
+ clocks = <&clock_gcc clk_qdss_clk>,
+ <&clock_gcc clk_qdss_a_clk>;
+ clock-names = "core_clk", "core_a_clk";
+ };
+
+ funnel_in2: funnel@6068000 {
+ compatible = "arm,coresight-funnel";
+ reg = <0x6068000 0x1000>;
+ reg-names = "funnel-base";
+
+ coresight-id = <5>;
+ coresight-name = "coresight-funnel-in2";
+ coresight-nr-inports = <2>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in0>;
+ coresight-child-ports = <6>;
+
+ clocks = <&clock_gcc clk_qdss_clk>,
+ <&clock_gcc clk_qdss_a_clk>;
+ clock-names = "core_clk", "core_a_clk";
+ };
+
+ cti0: cti@6010000 {
+ compatible = "arm,coresight-cti";
+ reg = <0x6010000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <6>;
+ coresight-name = "coresight-cti0";
+ coresight-nr-inports = <0>;
+
+ clocks = <&clock_gcc clk_qdss_clk>,
+ <&clock_gcc clk_qdss_a_clk>;
+ clock-names = "core_clk", "core_a_clk";
+ };
+
+ cti1: cti@6011000 {
+ compatible = "arm,coresight-cti";
+ reg = <0x6011000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <7>;
+ coresight-name = "coresight-cti1";
+ coresight-nr-inports = <0>;
+
+ clocks = <&clock_gcc clk_qdss_clk>,
+ <&clock_gcc clk_qdss_a_clk>;
+ clock-names = "core_clk", "core_a_clk";
+ };
+
+ cti2: cti@6012000 {
+ compatible = "arm,coresight-cti";
+ reg = <0x6012000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <8>;
+ coresight-name = "coresight-cti2";
+ coresight-nr-inports = <0>;
+
+ clocks = <&clock_gcc clk_qdss_clk>,
+ <&clock_gcc clk_qdss_a_clk>;
+ clock-names = "core_clk", "core_a_clk";
+ };
+
+ cti3: cti@6013000 {
+ compatible = "arm,coresight-cti";
+ reg = <0x6013000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <9>;
+ coresight-name = "coresight-cti3";
+ coresight-nr-inports = <0>;
+
+ clocks = <&clock_gcc clk_qdss_clk>,
+ <&clock_gcc clk_qdss_a_clk>;
+ clock-names = "core_clk", "core_a_clk";
+ };
+
+ cti4: cti@6014000 {
+ compatible = "arm,coresight-cti";
+ reg = <0x6014000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <10>;
+ coresight-name = "coresight-cti4";
+ coresight-nr-inports = <0>;
+
+ clocks = <&clock_gcc clk_qdss_clk>,
+ <&clock_gcc clk_qdss_a_clk>;
+ clock-names = "core_clk", "core_a_clk";
+ };
+
+ cti5: cti@6015000 {
+ compatible = "arm,coresight-cti";
+ reg = <0x6015000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <11>;
+ coresight-name = "coresight-cti5";
+ coresight-nr-inports = <0>;
+
+ clocks = <&clock_gcc clk_qdss_clk>,
+ <&clock_gcc clk_qdss_a_clk>;
+ clock-names = "core_clk", "core_a_clk";
+ };
+
+ cti6: cti@6016000 {
+ compatible = "arm,coresight-cti";
+ reg = <0x6016000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <12>;
+ coresight-name = "coresight-cti6";
+ coresight-nr-inports = <0>;
+
+ clocks = <&clock_gcc clk_qdss_clk>,
+ <&clock_gcc clk_qdss_a_clk>;
+ clock-names = "core_clk", "core_a_clk";
+ };
+
+ cti7: cti@6017000 {
+ compatible = "arm,coresight-cti";
+ reg = <0x6017000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <13>;
+ coresight-name = "coresight-cti7";
+ coresight-nr-inports = <0>;
+
+ clocks = <&clock_gcc clk_qdss_clk>,
+ <&clock_gcc clk_qdss_a_clk>;
+ clock-names = "core_clk", "core_a_clk";
+ };
+
+ cti8: cti@6018000 {
+ compatible = "arm,coresight-cti";
+ reg = <0x6018000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <14>;
+ coresight-name = "coresight-cti8";
+ coresight-nr-inports = <0>;
+
+ clocks = <&clock_gcc clk_qdss_clk>,
+ <&clock_gcc clk_qdss_a_clk>;
+ clock-names = "core_clk", "core_a_clk";
+ };
+
+ cti_cpu0: cti@6043000 {
+ compatible = "arm,coresight-cti";
+ reg = <0x6043000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <15>;
+ coresight-name = "coresight-cti-cpu0";
+ coresight-nr-inports = <0>;
+ coresight-cti-cpu = <&CPU0>;
+
+ qcom,cti-save;
+
+ clocks = <&clock_gcc clk_qdss_clk>,
+ <&clock_gcc clk_qdss_a_clk>;
+ clock-names = "core_clk", "core_a_clk";
+ };
+
+ cti_rpm_cpu0: cti@603c000 {
+ compatible = "arm,coresight-cti";
+ reg = <0x603c000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <16>;
+ coresight-name = "coresight-cti-rpm-cpu0";
+ coresight-nr-inports = <0>;
+
+ clocks = <&clock_gcc clk_qdss_clk>,
+ <&clock_gcc clk_qdss_a_clk>;
+ clock-names = "core_clk", "core_a_clk";
+ };
+
+ cti_modem_cpu0: cti@6038000 {
+ compatible = "arm,coresight-cti";
+ reg = <0x6038000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <17>;
+ coresight-name = "coresight-cti-modem-cpu0";
+ coresight-nr-inports = <0>;
+
+ clocks = <&clock_gcc clk_qdss_clk>,
+ <&clock_gcc clk_qdss_a_clk>;
+ clock-names = "core_clk", "core_a_clk";
+ };
+
+ stm: stm@6002000 {
+ compatible = "arm,coresight-stm";
+ reg = <0x6002000 0x1000>,
+ <0x9280000 0x180000>;
+ reg-names = "stm-base", "stm-data-base";
+
+ coresight-id = <18>;
+ coresight-name = "coresight-stm";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in0>;
+ coresight-child-ports = <7>;
+
+ clocks = <&clock_gcc clk_qdss_clk>,
+ <&clock_gcc clk_qdss_a_clk>;
+ clock-names = "core_clk", "core_a_clk";
+ };
+
+ csr: csr@6001000 {
+ compatible = "qcom,coresight-csr";
+ reg = <0x6001000 0x1000>;
+ reg-names = "csr-base";
+
+ coresight-id = <19>;
+ coresight-name = "coresight-csr";
+ coresight-nr-inports = <0>;
+
+ qcom,blk-size = <1>;
+
+ clocks = <&clock_gcc clk_qdss_clk>,
+ <&clock_gcc clk_qdss_a_clk>;
+ clock-names = "core_clk", "core_a_clk";
+ };
+
+ etm0: etm@6042000 {
+ compatible = "arm,coresight-etm";
+ reg = <0x6042000 0x1000>;
+ reg-names = "etm-base";
+
+ coresight-id = <20>;
+ coresight-name = "coresight-etm0";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in0>;
+ coresight-child-ports = <4>;
+ coresight-etm-cpu = <&CPU0>;
+
+ clocks = <&clock_gcc clk_qdss_clk>,
+ <&clock_gcc clk_qdss_a_clk>;
+ clock-names = "core_clk", "core_a_clk";
+ };
+
+ hwevent: hwevent@606c000 {
+ compatible = "qcom,coresight-hwevent";
+ reg = <0x606c000 0x148>,
+ <0x606cfb0 0x4>,
+ <0x78640cc 0x4>,
+ <0x78240cc 0x4>,
+ <0x7885010 0x4>,
+ <0x200c004 0x4>,
+ <0x78d90a0 0x4>;
+ reg-names = "wrapper-mux", "wrapper-lockaccess",
+ "wrapper-sdcc2", "wrapper-sdcc1",
+ "blsp-mux", "spmi-mux" ,"usb-mux";
+
+ coresight-id = <21>;
+ coresight-name = "coresight-hwevent";
+ coresight-nr-inports = <0>;
+
+ clocks = <&clock_gcc clk_qdss_clk>,
+ <&clock_gcc clk_qdss_a_clk>;
+ clock-names = "core_clk", "core_a_clk";
+ };
+
+ rpm_etm0 {
+ compatible = "qcom,coresight-remote-etm";
+
+ coresight-id = <22>;
+ coresight-name = "coresight-rpm-etm0";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in0>;
+ coresight-child-ports = <0>;
+
+ qcom,inst-id = <4>;
+ };
+
+ modem_etm0 {
+ compatible = "qcom,coresight-remote-etm";
+
+ coresight-id = <23>;
+ coresight-name = "coresight-modem-etm0";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in0>;
+ coresight-child-ports = <2>;
+
+ qcom,inst-id = <2>;
+ };
+
+ fuse: fuse@a601c {
+ compatible = "arm,coresight-fuse-v2";
+ reg = <0xa601c 0x8>;
+ reg-names = "fuse-base";
+
+ coresight-id = <24>;
+ coresight-name = "coresight-fuse";
+ coresight-nr-inports = <0>;
+ };
+
+ dbgui: dbgui@606d000 {
+ compatible = "qcom,coresight-dbgui";
+ reg = <0x606d000 0x1000>;
+ reg-names = "dbgui-base";
+
+ coresight-id = <25>;
+ coresight-name = "coresight-dbgui";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in2>;
+ coresight-child-ports = <1>;
+
+ qcom,dbgui-addr-offset = <0x30>;
+ qcom,dbgui-data-offset = <0xB0>;
+ qcom,dbgui-size = <32>;
+
+ clocks = <&clock_gcc clk_qdss_clk>,
+ <&clock_gcc clk_qdss_a_clk>;
+ clock-names = "core_clk", "core_a_clk";
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/mdm9607-display.dtsi b/arch/arm/boot/dts/qcom/mdm9607-display.dtsi
new file mode 100644
index 0000000..fd7f5ef
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/mdm9607-display.dtsi
@@ -0,0 +1,36 @@
+/* Copyright (c) 2015-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.
+ */
+
+/ {
+ mdss_qpic: qcom,msm_qpic@7980000 {
+ compatible = "qcom,mdss_qpic";
+ reg = <0x7980000 0x24000>;
+ reg-names = "qpic_base";
+ interrupts = <0 251 0>;
+
+ qcom,msm-bus,name = "mdss_qpic";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+
+ qcom,msm-bus,vectors-KBps =
+ <91 512 0 0>,
+ /* Voting for max b/w on PNOC bus for now */
+ <91 512 400000 800000>;
+
+ vdd-supply = <&mdm9607_l11>;
+
+ clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_gcc clk_qpic_clk>,
+ <&clock_gcc clk_qpic_a_clk>;
+
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/mdm9607-ion.dtsi b/arch/arm/boot/dts/qcom/mdm9607-ion.dtsi
new file mode 100644
index 0000000..6da25c2
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/mdm9607-ion.dtsi
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2015, 2017, 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.
+ */
+
+&soc {
+ qcom,ion {
+ compatible = "qcom,msm-ion";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ qcom,ion-heap@25 {
+ reg = <25>;
+ qcom,ion-heap-type = "SYSTEM";
+ };
+
+ qcom,ion-heap@28 { /* AUDIO HEAP */
+ reg = <28>;
+ 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";
+ };
+
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/mdm9607-mtp-sdcard.dts b/arch/arm/boot/dts/qcom/mdm9607-mtp-sdcard.dts
new file mode 100644
index 0000000..0cc1783
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/mdm9607-mtp-sdcard.dts
@@ -0,0 +1,56 @@
+/*
+ * 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
+ * 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 "mdm9607-mtp.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. MDM 9607 MTP SDCARD";
+ compatible = "qcom,mdm9607-mtp", "qcom,mdm9607", "qcom,mtp";
+ qcom,board-id = <8 1>;
+};
+
+&sdhc_2 {
+ /delete-property/cd-gpios;
+
+ qcom,vdd-io-always-on;
+ qcom,vdd-io-lpm-sup;
+
+ #address-cells = <0>;
+ interrupt-parent = <&sdhc_2>;
+ interrupts = <0 1>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0xffffffff>;
+ interrupt-map = <0 &intc 0 125 0
+ 1 &intc 0 221 0>;
+ interrupt-names = "hc_irq", "pwr_irq";
+
+ pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on>;
+
+ qcom,bus-speed-mode = "HS200_1p8v", "DDR_1p8v";
+ qcom,nonremovable;
+ status = "ok";
+};
+
+&pm8019_gpios {
+ gpio@c300 { /* GPIO 4 */
+ qcom,mode = <1>; /* Digital Output */
+ qcom,output-type = <0>; /* CMOS Logic */
+ qcom,invert = <0>; /* Output High */
+ qcom,vin-sel = <0>; /* VPH_PWR */
+ qcom,src-sel = <0>; /* GPIO */
+ qcom,out-strength = <1>; /* Low Drive Strength */
+ qcom,master-en = <1>; /* Enable GPIO */
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/mdm9607-mtp.dts b/arch/arm/boot/dts/qcom/mdm9607-mtp.dts
new file mode 100644
index 0000000..5334444
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/mdm9607-mtp.dts
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+/dts-v1/;
+
+#include "mdm9607-mtp.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. MDM 9607 MTP";
+ compatible = "qcom,mdm9607-mtp", "qcom,mdm9607", "qcom,mtp";
+ qcom,board-id = <8 0>;
+};
diff --git a/arch/arm/boot/dts/qcom/mdm9607-mtp.dtsi b/arch/arm/boot/dts/qcom/mdm9607-mtp.dtsi
new file mode 100644
index 0000000..df09bdf
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/mdm9607-mtp.dtsi
@@ -0,0 +1,158 @@
+/*
+ * 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.
+ */
+
+#include "mdm9607.dtsi"
+#include "mdm9607-pinctrl.dtsi"
+#include "mdm9607-display.dtsi"
+#include "qpic-panel-ili-hvga.dtsi"
+
+/ {
+ bluetooth: bt_qca6174 {
+ compatible = "qca,qca6174";
+ qca,bt-reset-gpio = <&pm8019_gpios 2 0>; /* BT_EN */
+ qca,bt-vdd-pa-supply = <&rome_vreg>;
+ qca,bt-vdd-io-supply = <&mdm9607_l11>;
+ qca,bt-vdd-xtal-supply = <&mdm9607_l2>;
+ qca,bt-vdd-io-voltage-level = <1800000 1800000>;
+ qca,bt-vdd-xtal-voltage-level = <1800000 1800000>;
+ };
+};
+
+&blsp1_uart5 {
+ status = "ok";
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart_console_sleep>;
+};
+
+&i2c_4 {
+ status = "ok";
+};
+
+&blsp1_uart3 {
+ status = "ok";
+};
+
+&qnand_1 {
+ status = "ok";
+};
+
+/* MPP pin 2 configs for SMB358 interrupt line */
+&pm8019_mpps {
+ mpp@a100 {
+ qcom,mode = <0>; /* Digital input */
+ qcom,vin-sel = <3>; /* 1.8V (L11) */
+ qcom,src-sel = <0>; /* QPNP_PIN_SEL_FUNC_CONSTANT */
+ qcom,pull = <2>; /* PULL UP 10KOHM */
+ qcom,master-en = <1>;
+ };
+};
+
+&pm8019_gpios {
+ gpio@c100 { /* BT_EN */
+ qcom,mode = <1>; /* Digital output*/
+ qcom,pull = <4>; /* Pulldown 10uA */
+ qcom,vin-sel = <2>; /* VIN2 */
+ qcom,src-sel = <0>; /* GPIO */
+ qcom,invert = <0>; /* Invert */
+ qcom,master-en = <1>; /* Enable GPIO */
+ status = "ok";
+ };
+
+ /* PMIC gpio for wlan power supply */
+ gpio@c200 {
+ qcom,mode = <1>; /* Digital output */
+ qcom,output-type = <0>; /* CMOS logic */
+ qcom,invert = <1>; /* Output high */
+ qcom,vin-sel = <3>; /* VPH_PWR */
+ qcom,src-sel = <0>; /* Constant */
+ qcom,out-strength = <1>; /* High drive strength */
+ qcom,master-en = <1>; /* Enable GPIO */
+ status = "okay";
+ };
+
+ /* ROME 32k Sleep Clock */
+ gpio@c500 {
+ qcom,mode = <1>; /* Digital output */
+ qcom,output-type = <0>; /* CMOS logic */
+ qcom,invert = <0>; /* no inversion */
+ qcom,vin-sel = <2>; /* VIN 2 */
+ qcom,src-sel = <2>; /* Function 2 */
+ qcom,out-strength = <2>; /* Medium */
+ qcom,master-en = <1>; /* Enable GPIO */
+ status = "ok";
+ };
+};
+
+&sdhc_1 {
+ vdd-io-supply = <&mdm9607_l11>;
+ qcom,vdd-io-always-on;
+ qcom,vdd-io-voltage-level = <1800000 1800000>;
+ qcom,vdd-io-current-level = <0 30000>;
+
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&pmx_sdc1_clk_on &pmx_sdc1_cmd_on &pmx_sdc1_data_on
+ &sdc1_wlan_gpio_active>;
+ pinctrl-1 = <&pmx_sdc1_clk_off &pmx_sdc1_cmd_off &pmx_sdc1_data_off
+ &sdc1_wlan_gpio_sleep>;
+ qcom,nonremovable;
+ qcom,core_3_0v_support;
+ status = "ok";
+};
+
+/* MPP pin 4 configs for SGMII */
+&pm8019_mpps {
+ mpp@a300 { /* MPP 4 */
+ qcom,mode = <1>; /* Digital output */
+ qcom,vin-sel = <2>; /* 1.8V */
+ qcom,src-sel = <0>; /* Constant */
+ qcom,master-en = <1>; /* Enable GPIO */
+ status = "okay";
+ };
+};
+
+&sdhc_2 {
+ vdd-supply = <&sdcard_ext_vreg>;
+ qcom,vdd-voltage-level = <2850000 2850000>;
+ qcom,vdd-current-level = <15000 400000>;
+
+ vdd-io-supply = <&mdm9607_l13>;
+ qcom,vdd-io-voltage-level = <1800000 2850000>;
+ qcom,vdd-io-current-level = <200 50000>;
+
+ #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_pinmux 26 0>;
+ interrupt-names = "hc_irq", "pwr_irq", "status_irq";
+ cd-gpios = <&tlmm_pinmux 26 0x1>;
+
+ 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>;
+
+ status = "disabled";
+};
+
+/* Display */
+&mdss_qpic {
+ pinctrl-names= "mdss_default", "mdss_sleep";
+ pinctrl-0 = <&mdss_ldo_active &mdss_cs_active &mdss_te_active
+ &mdss_rs_active &mdss_ad_active &mdss_bl_active>;
+ pinctrl-1 = <&mdss_ldo_sleep &mdss_cs_sleep &mdss_te_sleep
+ &mdss_rs_sleep &mdss_ad_sleep &mdss_bl_sleep>;
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/qcom/mdm9607-pinctrl.dtsi b/arch/arm/boot/dts/qcom/mdm9607-pinctrl.dtsi
new file mode 100644
index 0000000..670667d
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/mdm9607-pinctrl.dtsi
@@ -0,0 +1,1159 @@
+/*
+ * 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.
+ */
+
+&soc {
+ tlmm_pinmux: pinctrl@1000000 {
+ compatible = "qcom,mdm9607-pinctrl";
+ reg = <0x1000000 0x300000>;
+ interrupts = <0 208 0>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ qcom,tlmm-emmc-boot-select = <0x1>;
+
+ uart_console_sleep: uart_console_sleep {
+ mux {
+ pins = "gpio8", "gpio9";
+ function = "blsp_uart5";
+ };
+ config {
+ pins = "gpio8", "gpio9";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+ };
+
+ blsp1_uart3_active: blsp1_uart3_active {
+ mux {
+ pins = "gpio0", "gpio1", "gpio2", "gpio3";
+ function = "blsp_uart3";
+ };
+
+ config {
+ pins = "gpio0", "gpio1", "gpio2", "gpio3";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ blsp1_uart3_sleep: blsp1_uart3_sleep {
+ mux {
+ pins = "gpio0", "gpio1", "gpio2", "gpio3";
+ function = "gpio";
+ };
+
+
+ config {
+ pins = "gpio0", "gpio1", "gpio2", "gpio3";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ spi1 {
+
+ spi1_default: spi1_default {
+ /* active state */
+ mux {
+ /* MOSI, MISO, CLK */
+ pins = "gpio4", "gpio5", "gpio7";
+ function = "blsp_spi2";
+ };
+
+ config {
+ pins = "gpio4", "gpio5", "gpio7";
+ drive-strength = <12>; /* 12 MA */
+ bias-disable = <0>; /* No PULL */
+ };
+ };
+
+
+ spi1_sleep: spi1_sleep {
+ /* suspended state */
+ mux {
+ /* MOSI, MISO, CLK */
+ pins = "gpio4", "gpio5", "gpio7";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio4", "gpio5", "gpio7";
+ drive-strength = <2>; /* 2 MA */
+ bias-pull-down; /* PULL Down */
+ };
+ };
+
+ spi1_cs0_active: cs0_active {
+ /* CS */
+ mux {
+ pins = "gpio6";
+ function = "blsp_spi2";
+ };
+
+ config {
+ pins = "gpio6";
+ drive-strength = <2>;
+ bias-disable = <0>;
+ };
+ };
+
+ spi1_cs0_sleep: cs0_sleep {
+ /* CS */
+ mux {
+ pins = "gpio6";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio6";
+ drive-strength = <2>;
+ bias-disable = <0>;
+ };
+ };
+ };
+
+ /* SDC pin type */
+
+ pmx_sdc1_cmd {
+ pmx_sdc1_cmd_on: pmx_sdc1_cmd_on {
+ config {
+ pins = "sdc1_cmd";
+ drive-strength = <10>;
+ bias-pull-up;
+ };
+ };
+
+ pmx_sdc1_cmd_off: pmx_sdc1_cmd_off {
+ config {
+ pins = "sdc1_cmd";
+ bias-pull-up;
+ drive-strength = <2>;
+ };
+ };
+ };
+
+ pmx_sdc1_clk {
+ pmx_sdc1_clk_on: pmx_sdc1_clk_on {
+ config {
+ pins = "sdc1_clk";
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+
+ pmx_sdc1_clk_off: pmx_sdc1_clk_off {
+ config {
+ pins = "sdc1_clk";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+ };
+
+ pmx_sdc1_data {
+ pmx_sdc1_data_on: pmx_sdc1_data_on {
+ config {
+ pins = "sdc1_data";
+ bias-pull-up;
+ drive-strength = <10>;
+ };
+ };
+
+ pmx_sdc1_data_off: pmx_sdc1_data_off {
+ config {
+ pins = "sdc1_data";
+ bias-pull-up;
+ drive-strength = <2>;
+ };
+ };
+ };
+
+ sdc1_wlan_gpio {
+ sdc1_wlan_gpio_active: sdc1_wlan_gpio_active {
+ mux {
+ pins = "gpio38";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio38";
+ output-high;
+ drive-strength = <8>;
+ bias-pull-up;
+ };
+ };
+
+ sdc1_wlan_gpio_sleep: sdc1_wlan_gpio_sleep {
+ mux {
+ pins = "gpio38";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio38";
+ drive-strength = <2>;
+ bias-disable;
+ output-low;
+ };
+ };
+ };
+
+ i2c_4 {
+ i2c_4_active: i2c_4_active {
+ /* active state */
+ mux {
+ pins = "gpio18", "gpio19";
+ function = "blsp_i2c4";
+ };
+ config {
+ pins = "gpio18", "gpio19";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ i2c_4_sleep: i2c_4_sleep {
+ /* suspended state */
+ mux {
+ pins = "gpio18", "gpio19";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio18", "gpio19";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+ };
+ };
+
+ bmi160_int1_default: bmi160_int1_default {
+ mux {
+ pins = "gpio78";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio78";
+ drive-strength = <16>; /* 16 mA */
+ bias-pull-down; /* pull down */
+ };
+ };
+
+ bmi160_int2_default: bmi160_int2_default {
+ mux {
+ pins = "gpio79";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio79";
+ drive-strength = <16>; /* 16 mA */
+ bias-pull-down; /* pull down */
+ };
+ };
+
+ codec_reset {
+ codec_reset_active: codec_reset_active {
+ mux {
+ pins = "gpio26";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio26";
+ drive-strength = <8>; /* 8 MA */
+ bias-disable; /* No PULL */
+ output-high;
+ };
+ };
+ codec_reset_sleep: codec_reset_sleep {
+ mux {
+ pins = "gpio26";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio26";
+ drive-strength = <2>; /* 2 MA */
+ bias-pull-down; /* PULL DOWN */
+ };
+ };
+ };
+
+
+ pmx_pri_mi2s_aux {
+ pri_ws_active_master: pri_ws_active_master {
+ mux {
+ pins = "gpio20";
+ function = "pri_mi2s_ws_a";
+ };
+
+ config {
+ pins = "gpio20";
+ drive-strength = <8>; /* 8 MA */
+ bias-disable; /* No PULL */
+ output-high;
+ };
+ };
+
+ pri_sck_active_master: pri_sck_active_master {
+ mux {
+ pins = "gpio23";
+ function = "pri_mi2s_sck_a";
+ };
+
+ config {
+ pins = "gpio23";
+ drive-strength = <8>; /* 8 MA */
+ bias-disable; /* No PULL */
+ output-high;
+ };
+ };
+
+ pri_ws_active_slave: pri_ws_active_slave {
+ mux {
+ pins = "gpio20";
+ function = "pri_mi2s_ws_a";
+ };
+
+ config {
+ pins = "gpio20";
+ drive-strength = <8>; /* 8 MA */
+ bias-disable; /* No PULL */
+ };
+ };
+
+ pri_sck_active_slave: pri_sck_active_slave {
+ mux {
+ pins = "gpio23";
+ function = "pri_mi2s_sck_a";
+ };
+
+ config {
+ pins = "gpio23";
+ drive-strength = <8>; /* 8 MA */
+ bias-disable; /* No PULL */
+ };
+ };
+
+ pri_dout_active: pri_dout_active {
+ mux {
+ pins = "gpio22";
+ function = "pri_mi2s_data1_a";
+ };
+
+ config {
+ pins = "gpio22";
+ drive-strength = <8>; /* 8 MA */
+ bias-disable; /* No PULL */
+ output-high;
+ };
+ };
+
+ pri_ws_sleep: pri_ws_sleep {
+ mux {
+ pins = "gpio20";
+ function = "pri_mi2s_ws_a";
+ };
+
+ config {
+ pins = "gpio20";
+ drive-strength = <2>; /* 2 MA */
+ bias-pull-down; /* PULL DOWN */
+ };
+ };
+
+ pri_sck_sleep: pri_sck_sleep {
+ mux {
+ pins = "gpio23";
+ function = "pri_mi2s_sck_a";
+ };
+
+ config {
+ pins = "gpio23";
+ drive-strength = <2>; /* 2 MA */
+ bias-pull-down; /* PULL DOWN */
+ };
+ };
+
+ pri_dout_sleep: pri_dout_sleep {
+ mux {
+ pins = "gpio22";
+ function = "pri_mi2s_data1_a";
+ };
+
+ config {
+ pins = "gpio22";
+ drive-strength = <2>; /* 2 MA */
+ bias-pull-down; /* PULL DOWN */
+ };
+ };
+ };
+
+ pmx_pri_mi2s_aux_din {
+ pri_din_active: pri_din_active {
+ mux {
+ pins = "gpio21";
+ function = "pri_mi2s_data0_a";
+ };
+
+ config {
+ pins = "gpio21";
+ drive-strength = <8>; /* 8 MA */
+ bias-disable; /* No PULL */
+ };
+ };
+
+ pri_din_sleep: pri_din_sleep {
+ mux {
+ pins = "gpio21";
+ function = "pri_mi2s_data0_a";
+ };
+
+ config {
+ pins = "gpio21";
+ drive-strength = <2>; /* 2 MA */
+ bias-pull-down; /* PULL DOWN */
+ };
+ };
+ };
+
+ pmx_sec_mi2s_aux {
+ sec_ws_active_master: sec_ws_active_master {
+ mux {
+ pins = "gpio79";
+ function = "sec_mi2s";
+ };
+
+ config {
+ pins = "gpio79";
+ drive-strength = <8>; /* 8 MA */
+ bias-disable; /* No PULL */
+ output-high;
+ };
+ };
+
+ sec_sck_active_master: sec_sck_active_master {
+ mux {
+ pins = "gpio78";
+ function = "sec_mi2s";
+ };
+
+ config {
+ pins = "gpio78";
+ drive-strength = <8>; /* 8 MA */
+ bias-disable; /* No PULL */
+ output-high;
+ };
+ };
+
+ sec_ws_active_slave: sec_ws_active_slave {
+ mux {
+ pins = "gpio79";
+ function = "sec_mi2s";
+ };
+
+ config {
+ pins = "gpio79";
+ drive-strength = <8>; /* 8 MA */
+ bias-disable; /* No PULL */
+ };
+ };
+
+ sec_sck_active_slave: sec_sck_active_slave {
+ mux {
+ pins = "gpio78";
+ function = "sec_mi2s";
+ };
+
+ config {
+ pins = "gpio78";
+ drive-strength = <8>; /* 8 MA */
+ bias-disable; /* No PULL */
+ };
+ };
+
+ sec_dout_active: sec_dout_active {
+ mux {
+ pins = "gpio77";
+ function = "sec_mi2s";
+ };
+
+ config {
+ pins = "gpio77";
+ drive-strength = <8>; /* 8 MA */
+ bias-disable; /* No PULL */
+ output-high;
+ };
+ };
+
+ sec_ws_sleep: sec_ws_sleep {
+ mux {
+ pins = "gpio79";
+ function = "sec_mi2s";
+ };
+
+ config {
+ pins = "gpio79";
+ drive-strength = <2>; /* 2 MA */
+ bias-pull-down; /* PULL DOWN */
+ };
+ };
+
+ sec_sck_sleep: sec_sck_sleep {
+ mux {
+ pins = "gpio78";
+ function = "sec_mi2s";
+ };
+
+ config {
+ pins = "gpio78";
+ drive-strength = <2>; /* 2 MA */
+ bias-pull-down; /* PULL DOWN */
+ };
+ };
+
+ sec_dout_sleep: sec_dout_sleep {
+ mux {
+ pins = "gpio77";
+ function = "sec_mi2s";
+ };
+
+ config {
+ pins = "gpio77";
+ drive-strength = <2>; /* 2 MA */
+ bias-pull-down; /* PULL DOWN */
+ };
+ };
+ };
+
+ pmx_sec_mi2s_aux_din {
+ sec_din_active: sec_din_active {
+ mux {
+ pins = "gpio76";
+ function = "sec_mi2s";
+ };
+
+ config {
+ pins = "gpio76";
+ drive-strength = <8>; /* 8 MA */
+ bias-disable; /* No PULL */
+ };
+ };
+
+ sec_din_sleep: sec_din_sleep {
+ mux {
+ pins = "gpio76";
+ function = "sec_mi2s";
+ };
+
+ config {
+ pins = "gpio76";
+ drive-strength = <2>; /* 2 MA */
+ bias-pull-down; /* PULL DOWN */
+ };
+ };
+ };
+
+ pmx_qdsd_clk {
+ qdsd_clk_sdcard: clk_sdcard {
+ config {
+ pins = "qdsd_clk";
+ bias-disable; /* NO pull */
+ drive-strength = <16>; /* 16 MA */
+ };
+ };
+ qdsd_clk_trace: clk_trace {
+ config {
+ pins = "qdsd_clk";
+ bias-pull-down; /* pull down */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ qdsd_clk_swdtrc: clk_swdtrc {
+ config {
+ pins = "qdsd_clk";
+ bias-pull-down; /* pull down */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ qdsd_clk_spmi: clk_spmi {
+ config {
+ pins = "qdsd_clk";
+ bias-pull-down; /* pull down */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ };
+
+ pmx_qdsd_cmd {
+ qdsd_cmd_sdcard: cmd_sdcard {
+ config {
+ pins = "qdsd_cmd";
+ bias-pull-down; /* pull down */
+ drive-strength = <8>; /* 8 MA */
+ };
+ };
+ qdsd_cmd_trace: cmd_trace {
+ config {
+ pins = "qdsd_cmd";
+ bias-pull-down; /* pull down */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ qdsd_cmd_swduart: cmd_uart {
+ config {
+ pins = "qdsd_cmd";
+ bias-pull-up; /* pull up */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ qdsd_cmd_swdtrc: cmd_swdtrc {
+ config {
+ pins = "qdsd_cmd";
+ bias-pull-up; /* pull up */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ qdsd_cmd_jtag: cmd_jtag {
+ config {
+ pins = "qdsd_cmd";
+ bias-disable; /* NO pull */
+ drive-strength = <8>; /* 8 MA */
+ };
+ };
+ qdsd_cmd_spmi: cmd_spmi {
+ config {
+ pins = "qdsd_cmd";
+ bias-pull-down; /* pull down */
+ drive-strength = <10>; /* 10 MA */
+ };
+ };
+ };
+
+ pmx_qdsd_data0 {
+ qdsd_data0_sdcard: data0_sdcard {
+ config {
+ pins = "qdsd_data0";
+ bias-pull-down; /* pull down */
+ drive-strength = <8>; /* 8 MA */
+ };
+ };
+ qdsd_data0_trace: data0_trace {
+ config {
+ pins = "qdsd_data0";
+ bias-pull-down; /* pull down */
+ drive-strength = <8>; /* 8 MA */
+ };
+ };
+ qdsd_data0_swduart: data0_uart {
+ config {
+ pins = "qdsd_data0";
+ bias-pull-down; /* pull down */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ qdsd_data0_swdtrc: data0_swdtrc {
+ config {
+ pins = "qdsd_data0";
+ bias-pull-down; /* pull down */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ qdsd_data0_jtag: data0_jtag {
+ config {
+ pins = "qdsd_data0";
+ bias-pull-up; /* pull up */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ qdsd_data0_spmi: data0_spmi {
+ config {
+ pins = "qdsd_data0";
+ bias-pull-down; /* pull down */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ };
+
+ pmx_qdsd_data1 {
+ qdsd_data1_sdcard: data1_sdcard {
+ config {
+ pins = "qdsd_data1";
+ bias-pull-down; /* pull down */
+ drive-strength = <8>; /* 8 MA */
+ };
+ };
+ qdsd_data1_trace: data1_trace {
+ config {
+ pins = "qdsd_data1";
+ bias-pull-down; /* pull down */
+ drive-strength = <8>; /* 8 MA */
+ };
+ };
+ qdsd_data1_swduart: data1_uart {
+ config {
+ pins = "qdsd_data1";
+ bias-pull-down; /* pull down */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ qdsd_data1_swdtrc: data1_swdtrc {
+ config {
+ pins = "qdsd_data1";
+ bias-pull-down; /* pull down */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ qdsd_data1_jtag: data1_jtag {
+ config {
+ pins = "qdsd_data1";
+ bias-pull-down; /* pull down */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ };
+
+ pmx_qdsd_data2 {
+ qdsd_data2_sdcard: data2_sdcard {
+ config {
+ pins = "qdsd_data2";
+ bias-pull-down; /* pull down */
+ drive-strength = <8>; /* 8 MA */
+ };
+ };
+ qdsd_data2_trace: data2_trace {
+ config {
+ pins = "qdsd_data2";
+ bias-pull-down; /* pull down */
+ drive-strength = <8>; /* 8 MA */
+ };
+ };
+ qdsd_data2_swduart: data2_uart {
+ config {
+ pins = "qdsd_data2";
+ bias-pull-down; /* pull down */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ qdsd_data2_swdtrc: data2_swdtrc {
+ config {
+ pins = "qdsd_data2";
+ bias-pull-down; /* pull down */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ qdsd_data2_jtag: data2_jtag {
+ config {
+ pins = "qdsd_data2";
+ bias-pull-up; /* pull up */
+ drive-strength = <8>; /* 8 MA */
+ };
+ };
+ };
+
+ pmx_qdsd_data3 {
+ qdsd_data3_sdcard: data3_sdcard {
+ config {
+ pins = "qdsd_data3";
+ bias-pull-down; /* pull down */
+ drive-strength = <8>; /* 8 MA */
+ };
+ };
+ qdsd_data3_trace: data3_trace {
+ config {
+ pins = "qdsd_data3";
+ bias-pull-down; /* pull down */
+ drive-strength = <8>; /* 8 MA */
+ };
+ };
+ qdsd_data3_swduart: data3_uart {
+ config {
+ pins = "qdsd_data3";
+ bias-pull-up; /* pull up */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ qdsd_data3_swdtrc: data3_swdtrc {
+ config {
+ pins = "qdsd_data3";
+ bias-pull-up; /* pull up */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ qdsd_data3_jtag: data3_jtag {
+ config {
+ pins = "qdsd_data3";
+ bias-pull-up; /* pull up */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ qdsd_data3_spmi: data3_spmi {
+ config {
+ pins = "qdsd_data3";
+ bias-pull-down; /* pull down */
+ drive-strength = <8>; /* 8 MA */
+ };
+ };
+ };
+
+ pmx_sdc2_clk {
+ sdc2_clk_on: sdc2_clk_on {
+ config {
+ pins = "sdc2_clk";
+ drive-strength = <16>; /* 16 MA */
+ bias-disable; /* NO pull */
+ };
+ };
+ sdc2_clk_off: sdc2_clk_off {
+ config {
+ pins = "sdc2_clk";
+ bias-disable; /* NO pull */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ };
+
+ pmx_sdc2_cmd {
+ sdc2_cmd_on: sdc2_cmd_on {
+ config {
+ pins = "sdc2_cmd";
+ bias-pull-up; /* pull up */
+ drive-strength = <10>; /* 10 MA */
+ };
+ };
+ sdc2_cmd_off: sdc2_cmd_off {
+ config {
+ pins = "sdc2_cmd";
+ bias-pull-up; /* pull up */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ };
+
+ pmx_sdc2_data {
+ sdc2_data_on: sdc2_data_on {
+ config {
+ pins = "sdc2_data";
+ bias-pull-up; /* pull up */
+ drive-strength = <10>; /* 10 MA */
+ };
+ };
+ sdc2_data_off: sdc2_data_off {
+ config {
+ pins = "sdc2_data";
+ bias-pull-up; /* pull up */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ };
+
+ sdhc2_cd_pin {
+ sdc2_cd_on: cd_on {
+ mux {
+ pins = "gpio26";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio26";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+ sdc2_cd_off: cd_off {
+ mux {
+ pins = "gpio26";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio26";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+ };
+
+ emac0 {
+ emac0_mdio_active: emac0_mdio_active {
+ /* active state */
+ mux {
+ /* MDC MDIO */
+ pins = "gpio27", "gpio28";
+ function = "gmac_mdio";
+ };
+
+ config {
+ pins = "gpio27", "gpio28";
+ drive-strength = <16>; /* 16 MA */
+ bias-pull-up;
+ };
+ };
+
+ emac0_mdio_sleep: emac0_mdio_sleep {
+ /* suspended state */
+ mux {
+ /* MDC MDIO */
+ pins = "gpio27", "gpio28";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio27", "gpio28";
+ drive-strength = <2>; /* 2 MA */
+ bias-pull-down;
+ };
+ };
+
+ emac0_ephy_active: emac0_ephy_active {
+ /* active state */
+ mux {
+ /* EPHY RST */
+ pins = "gpio29";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio29";
+ drive-strength = <16>; /* 16 MA */
+ bias-pull-up;
+ output-high;
+ };
+ };
+
+ emac0_ephy_sleep: emac0_ephy_sleep {
+ /* suspended state */
+ mux {
+ /* EPHY RST */
+ pins = "gpio29";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio29";
+ drive-strength = <2>; /* 2 MA */
+ bias-disable;
+ output-low;
+ };
+ };
+ };
+
+ mdss_cs_active: mdss_cs_active {
+ mux {
+ pins = "gpio23";
+ function = "ebi2_lcd_cs_n_b";
+ };
+
+ config {
+ pins = "gpio23";
+ drive-strength = <10>;/*10mA*/
+ bias-disable;/*NOpull*/
+ };
+ };
+
+ mdss_cs_sleep:mdss_cs_sleep {
+ mux {
+ pins = "gpio23";
+ function = "ebi2_lcd_cs_n_b";
+ };
+
+ config {
+ pins = "gpio23";
+ drive-strength = <2>;/*2mA*/
+ bias-disable;/*NOpull*/
+ };
+ };
+
+ mdss_te_active:mdss_te_active {
+ mux {
+ pins = "gpio20";
+ function = "ebi2_lcd_te_b";
+ };
+
+ config {
+ pins = "gpio20";
+ drive-strength = <10>;/*10mA*/
+ bias-disable;/*NOpull*/
+ };
+ };
+
+ mdss_te_sleep:mdss_te_sleep {
+ mux {
+ pins = "gpio20";
+ function = "ebi2_lcd_te_b";
+ };
+
+ config {
+ pins = "gpio20";
+ drive-strength = <2>;/*2mA*/
+ bias-disable;/*NOpull*/
+ };
+ };
+
+ mdss_rs_active:mdss_rs_active {
+ mux {
+ pins = "gpio74";
+ function = "ebi2_lcd";
+ };
+
+ config {
+ pins = "gpio74";
+ drive-strength = <10>;/*10mA*/
+ bias-disable;/*NOpull*/
+ };
+ };
+
+ mdss_rs_sleep:mdss_rs_sleep {
+ mux {
+ pins = "gpio74";
+ function = "ebi2_lcd";
+ };
+
+ config {
+ pins = "gpio74";
+ drive-strength = <2>;/*2mA*/
+ bias-disable;/*NOpull*/
+ };
+ };
+
+ mdss_ad_active:mdss_ad_active {
+ mux {
+ pins = "gpio22";
+ function = "ebi2_a_d_8_b";
+ };
+
+ config {
+ pins = "gpio22";
+ drive-strength = <10>;/*10mA*/
+ bias-disable;/*NOpull*/
+ };
+ };
+
+ mdss_ad_sleep:mdss_ad_sleep {
+ mux {
+ pins = "gpio22";
+ function = "ebi2_a_d_8_b";
+ };
+
+ config {
+ pins = "gpio22";
+ drive-strength = <2>;/*2mA*/
+ bias-disable;/*NOpull*/
+ };
+ };
+
+ mdss_bl_active:mdss_bl_active {
+ mux {
+ pins = "gpio21";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio21";
+ drive-strength = <10>;/*10mA*/
+ bias-disable;/*NOpull*/
+ output-high;
+ };
+ };
+
+ mdss_bl_sleep:mdss_bl_sleep {
+ mux {
+ pins = "gpio21";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio21";
+ drive-strength = <2>;/*2mA*/
+ bias-disable;/*NOpull*/
+ };
+ };
+
+ mdss_ldo_active:mdss_ldo_active {
+ mux {
+ pins = "gpio10";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio10";
+ drive-strength = <10>;/*10mA*/
+ bias-disable;/*NOpull*/
+ output-high;
+ };
+ };
+
+ mdss_ldo_sleep:mdss_ldo_sleep {
+ mux {
+ pins = "gpio10";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio10";
+ drive-strength = <2>;/*2mA*/
+ bias-disable;/*NOpull*/
+ output-low;
+ };
+ };
+
+ pinctrl_pps: ppsgrp {
+ mux {
+ pins = "gpio53";
+ function = "nav_tsync_out_a";
+ };
+
+ config {
+ pins = "gpio53";
+ bias-pull-down;
+ };
+ };
+
+ can_reset {
+ can_rst_on: rst_on {
+ mux {
+ pins = "gpio11";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio11";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-up;
+ };
+ };
+
+ can_rst_off: rst_off {
+ mux {
+ pins = "gpio11";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio11";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-up;
+ output-high;
+ };
+ };
+ };
+
+ ntn_rst_gpio_default: ntn_rst_gpio_default {
+ mux {
+ pins = "gpio30";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio30";
+ drive-strength = <16>;
+ bias-pull-up;
+ output-high;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/mdm9607-pm.dtsi b/arch/arm/boot/dts/qcom/mdm9607-pm.dtsi
new file mode 100644
index 0000000..58ec0c0
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/mdm9607-pm.dtsi
@@ -0,0 +1,258 @@
+/* Copyright (c) 2015-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.
+ */
+
+#include <dt-bindings/msm/pm.h>
+
+&soc {
+ qcom,spm@b009000 {
+ compatible = "qcom,spm-v2";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xb009000 0x1000>;
+ qcom,name = "cpu0";
+ qcom,cpu = <&CPU0>;
+ qcom,saw2-ver-reg = <0xfd0>;
+ qcom,saw2-cfg = <0x1>;
+ qcom,saw2-spm-dly= <0x3c102800>;
+ qcom,saw2-spm-ctl = <0xe>;
+ qcom,mode0 {
+ qcom,label = "qcom,saw2-spm-cmd-wfi";
+ qcom,sequence = [04 03 04 0f];
+ qcom,spm_en;
+ };
+ qcom,mode1 {
+ qcom,label = "qcom,saw2-spm-cmd-spc";
+ qcom,sequence = [1f 34 04 44 24 54 03
+ 54 44 04 24 34 0f];
+ qcom,spm_en;
+ qcom,pc_mode;
+ };
+ qcom,mode2 {
+ qcom,label = "qcom,saw2-spm-cmd-pc";
+ qcom,sequence = [1f 34 04 44 14 24 54 03
+ 54 44 14 04 04 24 04 34 0f];
+ qcom,spm_en;
+ qcom,pc_mode;
+ qcom,slp_cmd_mode;
+ };
+ };
+
+ qcom,lpm-levels {
+ compatible = "qcom,lpm-levels";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ qcom,pm-cluster@0{
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ label = "system";
+ qcom,default-level=<0>;
+
+ qcom,pm-cluster-level@0 {
+ reg = <0>;
+ label = "l2-active";
+ qcom,latency-us = <270>;
+ qcom,ss-power = <455>;
+ qcom,energy-overhead = <270621>;
+ qcom,time-overhead = <500>;
+ };
+
+ qcom,pm-cluster-level@1 {
+ reg = <1>;
+ label = "l2-pc";
+ qcom,latency-us = <285>;
+ qcom,ss-power = <442>;
+ qcom,energy-overhead = <306621>;
+ qcom,time-overhead = <540>;
+ qcom,min-child-idx = <2>;
+ qcom,notify-rpm;
+ qcom,reset-level = <LPM_RESET_LVL_PC>;
+ };
+
+ qcom,pm-cpu {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ qcom,pm-cpu-level@0{
+ reg = <0>;
+ qcom,spm-cpu-mode = "wfi";
+ qcom,latency-us = <1>;
+ qcom,ss-power = <473>;
+ qcom,energy-overhead = <100000>;
+ qcom,time-overhead = <25>;
+ };
+
+ qcom,pm-cpu-level@1 {
+ reg = <1>;
+ qcom,spm-cpu-mode ="standalone_pc";
+ qcom,latency-us = <240>;
+ qcom,ss-power = <467>;
+ qcom,energy-overhead = <202781>;
+ qcom,time-overhead = <420>;
+ qcom,use-broadcast-timer;
+ qcom,is-reset;
+ qcom,reset-level = <LPM_RESET_LVL_PC>;
+ };
+
+ qcom,pm-cpu-level@2 {
+ reg = <2>;
+ qcom,spm-cpu-mode = "pc";
+ qcom,latency-us = <270>;
+ qcom,ss-power = <455>;
+ qcom,energy-overhead = <270621>;
+ qcom,time-overhead = <500>;
+ qcom,use-broadcast-timer;
+ qcom,is-reset;
+ qcom,reset-level = <LPM_RESET_LVL_PC>;
+ };
+ };
+ };
+ };
+
+ qcom,mpm@601d0 {
+ compatible = "qcom,mpm-v2";
+ reg = <0x601d0 0x1000>, /* MSM_RPM_MPM_BASE 4K */
+ <0xb011008 0x4>;
+ reg-names = "vmpm", "ipc";
+ interrupts = <0 171 1>;
+ clocks = <&clock_gcc clk_xo_lpm_clk>;
+ clock-names = "xo";
+ qcom,ipc-bit-offset = <1>;
+ qcom,gic-parent = <&intc>;
+ qcom,gic-map = <2 216>, /* tsens_upper_lower_int */
+ <49 172>, /* usb1_hs_async_wakeup_irq */
+ <51 174>, /* usb2_hs_async_wakeup_irq */
+ <53 104>, /* mdss_irq */
+ <58 166>, /* usb_hs_irq */
+ <62 222>, /* ee0_apps_hlos_spmi_periph_irq */
+ <0xff 18>, /* WDT_biteInt */
+ <0xff 19>, /* WDT_barkInt */
+ <0xff 35>, /* CTI_SPI_intx */
+ <0xff 38>, /* QTMR_qgicFrm0VirtIrq */
+ <0xff 47>,
+ <0xff 56>, /* q6_wdog_expired_irq */
+ <0xff 57>, /* mss_to_apps_irq(0) */
+ <0xff 58>, /* mss_to_apps_irq(1) */
+ <0xff 59>, /* mss_to_apps_irq(2) */
+ <0xff 60>, /* mss_to_apps_irq(3) */
+ <0xff 61>, /* mss_a2_bam_irq */
+ <0xff 77>, /* qpic_bam_irq[1] */
+ <0xff 114>, /* qdsd_intr_out */
+ <0xff 130>, /* peripheral_irq[9] */
+ <0xff 131>, /* qup_irq */
+ <0xff 140>, /* uart_dm_intr */
+ <0xff 153>, /* peripheral_irq[4] */
+ <0xff 155>, /* sdc1_irq(0) */
+ <0xff 157>, /* sdc2_irq(0) */
+ <0xff 161>, /* qpic_nandc_op_done_irq */
+ <0xff 163>, /* qpic_lcdc_irq */
+ <0xff 164>, /* qpic_bam_irq[0] */
+ <0xff 168>,
+ <0xff 170>, /* sdc1_pwr_cmd_irq */
+ <0xff 173>, /* hsic_core_irq */
+ <0xff 192>, /* audio_out0_irq */
+ <0xff 198>, /* qdss_etrbytecnt_irq */
+ <0xff 200>, /* rpm_ipc(4) */
+ <0xff 201>, /* rpm_ipc(5) */
+ <0xff 202>, /* rpm_ipc(6) */
+ <0xff 203>, /* rpm_ipc(7) */
+ <0xff 204>, /* rpm_ipc(24) */
+ <0xff 205>, /* rpm_ipc(25) */
+ <0xff 206>, /* rpm_ipc(26) */
+ <0xff 207>, /* rpm_ipc(27) */
+ <0xff 208>, /* rbif_irq[0] */
+ <0xff 215>, /* o_bimc_intr */
+ <0xff 224>, /* spdm_realtime_irq(1) */
+ <0xff 239>, /* crypto_bam_irq[1]*/
+ <0xff 240>, /* summary_irq_kpss */
+ <0xff 244>, /* bam_irq[2] */
+ <0xff 253>, /* sdc2_pwr_cmd_irq */
+ <0xff 269>, /* rpm_wdog_expired_irq */
+ <0xff 270>, /* bam_irq[0] */
+ <0xff 275>, /* rpm_ipc(30) */
+ <0xff 276>; /* rpm_ipc(31) */
+
+ qcom,gpio-parent = <&tlmm_pinmux>;
+ qcom,gpio-map = <3 16>,
+ <4 5>,
+ <5 11>,
+ <6 12>,
+ <7 3>,
+ <8 17>,
+ <9 9>,
+ <10 13>,
+ <11 1>,
+ <12 20>,
+ <13 21>,
+ <14 22>,
+ <15 75>,
+ <16 74>,
+ <17 28>,
+ <18 44>,
+ <19 26>,
+ <20 43>,
+ <21 42>,
+ <22 29>,
+ <23 69>,
+ <24 30>,
+ <25 37>,
+ <26 25>,
+ <27 71>,
+ <28 34>,
+ <29 55>,
+ <30 8>,
+ <31 40>,
+ <32 48>,
+ <33 52>,
+ <34 57>,
+ <35 62>,
+ <36 66>,
+ <37 59>,
+ <38 79>,
+ <39 38>,
+ <40 63>,
+ <41 76>;
+ };
+
+ qcom,pm@8600664 {
+ compatible = "qcom,pm";
+ reg = <0x8600664 0x40>;
+ clocks = <&clock_cpu clk_a7ssmux>;
+ clock-names = "cpu0_clk";
+ qcom,use-sync-timer;
+ qcom,synced-clocks;
+ qcom,tz-flushes-cache;
+ };
+
+ qcom,cpu-sleep-status@b088008{
+ compatible = "qcom,cpu-sleep-status";
+ reg = <0xb088008 0x100>;
+ qcom,cpu-alias-addr = <0x10000>;
+ qcom,sleep-status-mask= <0x80000>;
+ };
+
+ qcom,rpm-stats@29dba0 {
+ compatible = "qcom,rpm-stats";
+ reg = <0x29dba0 0x1000>;
+ reg-names = "phys_addr_base";
+ qcom,sleep-stats-version = <2>;
+ };
+
+ qcom,rpm-master-stats@60150 {
+ compatible = "qcom,rpm-master-stats";
+ reg = <0x60150 0x2030>;
+ qcom,masters = "APSS", "MPSS", "PRONTO";
+ qcom,master-stats-version = <2>;
+ qcom,master-offset = <4096>;
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/mdm9607-rcm.dts b/arch/arm/boot/dts/qcom/mdm9607-rcm.dts
new file mode 100644
index 0000000..cdf518c
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/mdm9607-rcm.dts
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+/dts-v1/;
+
+#include "mdm9607-cdp.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. MDM 9607 RCM";
+ compatible = "qcom,mdm9607-cdp", "qcom,mdm9607", "qcom,cdp";
+ qcom,board-id = <21 0>;
+};
+
+&emac0 {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/qcom/mdm9607-regulator.dtsi b/arch/arm/boot/dts/qcom/mdm9607-regulator.dtsi
new file mode 100644
index 0000000..3b4bb36
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/mdm9607-regulator.dtsi
@@ -0,0 +1,413 @@
+/* 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.
+ */
+
+&rpm_bus {
+ rpm-regulator-smpa2 {
+ status = "okay";
+ mdm9607_s2: regulator-s2 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "mdm9607_s2";
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <1275000>;
+ qcom,init-voltage = <750000>;
+ status = "okay";
+ };
+ };
+
+ /* CX supply */
+ rpm-regulator-smpa3 {
+ status = "okay";
+ mdm9607_s3_level: regulator-s3-level {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "mdm9607_s3_level";
+ qcom,set = <3>;
+ regulator-min-microvolt =
+ <RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+ regulator-max-microvolt =
+ <RPM_SMD_REGULATOR_LEVEL_TURBO_NO_CPR>;
+ qcom,use-voltage-level;
+ };
+
+ mdm9607_s3_level_ao: regulator-s3-level-ao {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "mdm9607_s3_level_ao";
+ qcom,set = <1>;
+ regulator-min-microvolt =
+ <RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+ regulator-max-microvolt =
+ <RPM_SMD_REGULATOR_LEVEL_TURBO_NO_CPR>;
+ qcom,use-voltage-level;
+ };
+
+ mdm9607_s3_floor_level: regulator-s3-floor-level {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "mdm9607_s3_floor_level";
+ qcom,set = <3>;
+ regulator-min-microvolt =
+ <RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+ regulator-max-microvolt =
+ <RPM_SMD_REGULATOR_LEVEL_TURBO_NO_CPR>;
+ qcom,use-voltage-floor-level;
+ qcom,always-send-voltage;
+ };
+
+ mdm9607_s3_level_so: regulator-s3-level-so {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "mdm9607_s3_level_so";
+ qcom,set = <2>;
+ regulator-min-microvolt =
+ <RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+ regulator-max-microvolt =
+ <RPM_SMD_REGULATOR_LEVEL_TURBO_NO_CPR>;
+ qcom,use-voltage-level;
+ };
+ };
+
+ rpm-regulator-smpa4 {
+ status = "okay";
+ mdm9607_s4: regulator-s4 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "mdm9607_s4";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1950000>;
+ qcom,init-voltage = <1800000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa1 {
+ status = "okay";
+ mdm9607_l1: regulator-l1 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "mdm9607_l1";
+ regulator-min-microvolt = <1250000>;
+ regulator-max-microvolt = <1250000>;
+ qcom,init-voltage = <1250000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa2 {
+ status = "okay";
+ mdm9607_l2: regulator-l2 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "mdm9607_l2";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,init-voltage = <1800000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa3 {
+ status = "okay";
+ mdm9607_l3: regulator-l3 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "mdm9607_l3";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,init-voltage = <1800000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa4 {
+ status = "okay";
+ mdm9607_l4: regulator-l4 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "mdm9607_l4";
+ regulator-min-microvolt = <3075000>;
+ regulator-max-microvolt = <3075000>;
+ qcom,init-voltage = <3075000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa5 {
+ status = "okay";
+ mdm9607_l5: regulator-l5 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "mdm9607_l5";
+ regulator-min-microvolt = <1700000>;
+ regulator-max-microvolt = <3050000>;
+ qcom,init-voltage = <1700000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa6 {
+ status = "okay";
+ mdm9607_l6: regulator-l6 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "mdm9607_l6";
+ regulator-min-microvolt = <1700000>;
+ regulator-max-microvolt = <3050000>;
+ qcom,init-voltage = <1700000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa7 {
+ status = "okay";
+ mdm9607_l7: regulator-l7 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "mdm9607_l7";
+ regulator-min-microvolt = <1700000>;
+ regulator-max-microvolt = <1900000>;
+ qcom,init-voltage = <1700000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa8 {
+ status = "okay";
+ mdm9607_l8: regulator-l8 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "mdm9607_l8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,init-voltage = <1800000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa9 {
+ status = "okay";
+ mdm9607_l9: regulator-l9 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "mdm9607_l9";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1250000>;
+ qcom,init-voltage = <1200000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa10 {
+ status = "okay";
+ mdm9607_l10: regulator-l10 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "mdm9607_l10";
+ regulator-min-microvolt = <1050000>;
+ regulator-max-microvolt = <1050000>;
+ qcom,init-voltage = <1050000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa11 {
+ status = "okay";
+ mdm9607_l11: regulator-l11 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "mdm9607_l11";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,init-voltage = <1800000>;
+ status = "okay";
+ };
+ };
+
+ /* MX supply */
+ rpm-regulator-ldoa12 {
+ status = "okay";
+ mdm9607_l12_level: regulator-l12-level {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "mdm9607_l12_level";
+ qcom,set = <3>;
+ regulator-min-microvolt =
+ <RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+ regulator-max-microvolt =
+ <RPM_SMD_REGULATOR_LEVEL_TURBO_NO_CPR>;
+ qcom,use-voltage-level;
+ };
+
+ mdm9607_l12_level_ao: regulator-l12-level-ao {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "mdm9607_l12_level_ao";
+ qcom,set = <1>;
+ regulator-min-microvolt =
+ <RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+ regulator-max-microvolt =
+ <RPM_SMD_REGULATOR_LEVEL_TURBO_NO_CPR>;
+ qcom,use-voltage-level;
+ qcom,always-send-voltage;
+ };
+
+ mdm9607_l12_level_so: regulator-l12-level-so {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "mdm9607_l12_level_so";
+ qcom,set = <2>;
+ regulator-min-microvolt =
+ <RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+ regulator-max-microvolt =
+ <RPM_SMD_REGULATOR_LEVEL_TURBO_NO_CPR>;
+ qcom,use-voltage-level;
+ };
+
+ mdm9607_l12_floor_level: regulator-l12-floor-level {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "mdm9607_l12_floor_lebel";
+ qcom,set = <3>;
+ regulator-min-microvolt =
+ <RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+ regulator-max-microvolt =
+ <RPM_SMD_REGULATOR_LEVEL_TURBO_NO_CPR>;
+ qcom,use-voltage-floor-level;
+ qcom,always-send-voltage;
+ };
+ };
+
+ rpm-regulator-ldoa13 {
+ status = "okay";
+ mdm9607_l13: regulator-l13 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "mdm9607_l13";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2850000>;
+ qcom,init-voltage = <2850000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa14 {
+ status = "okay";
+ mdm9607_l14: regulator-l14 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "mdm9607_l14";
+ regulator-min-microvolt = <2650000>;
+ regulator-max-microvolt = <3000000>;
+ qcom,init-voltage = <2650000>;
+ status = "okay";
+ };
+ };
+};
+
+&spmi_bus {
+ qcom,pm8019@1 {
+ /* APC supply */
+ mdm9607_s1: spm-regulator@1400 {
+ compatible = "qcom,spm-regulator";
+ reg = <0x1400 0x100>;
+ regulator-name = "mdm9607_s1";
+ regulator-min-microvolt = <1050000>;
+ regulator-max-microvolt = <1350000>;
+ qcom,bypass-spm; /* TODO: Remove once SPM is up */
+ };
+ };
+};
+
+&soc {
+ mem_acc_vreg_corner: regulator@1942130 {
+ compatible = "qcom,mem-acc-regulator";
+ reg = <0x1942130 0x4>;
+ reg-names = "acc-sel-l1";
+ regulator-name = "mem_acc_corner";
+ regulator-min-microvolt = <1>;
+ regulator-max-microvolt = <3>;
+
+ qcom,acc-sel-l1-bit-pos = <0>;
+ qcom,corner-acc-map = <0 1 1>;
+ };
+
+ apc_vreg_corner: regulator@b018000 {
+ compatible = "qcom,cpr-regulator";
+ reg = <0xb018000 0x1000>, <0xb010058 4>, <0xa4000 0x1000>;
+ reg-names = "rbcpr", "rbcpr_clk", "efuse_addr";
+ interrupts = <0 20 0>;
+ regulator-name = "apc_corner";
+ qcom,cpr-fuse-corners = <3>;
+ regulator-min-microvolt = <1>;
+ regulator-max-microvolt = <7>;
+
+ qcom,cpr-voltage-ceiling = <1050000 1225000 1350000>;
+ qcom,cpr-voltage-floor = <1050000 1050000 1150000>;
+ vdd-apc-supply = <&mdm9607_s1>;
+
+ vdd-mx-supply = <&mdm9607_l12_level_ao>;
+ qcom,vdd-mx-vmin-method = <4>;
+ qcom,vdd-mx-corner-map = < RPM_SMD_REGULATOR_LEVEL_SVS
+ RPM_SMD_REGULATOR_LEVEL_NOM
+ RPM_SMD_REGULATOR_LEVEL_TURBO>;
+ qcom,vdd-mx-vmax = <RPM_SMD_REGULATOR_LEVEL_TURBO_NO_CPR>;
+
+ mem-acc-supply = <&mem_acc_vreg_corner>;
+
+ qcom,cpr-ref-clk = <19200>;
+ qcom,cpr-timer-delay = <5000>;
+ qcom,cpr-timer-cons-up = <0>;
+ qcom,cpr-timer-cons-down = <2>;
+ qcom,cpr-irq-line = <0>;
+ qcom,cpr-step-quotient = <22 0 24 0 0 0 0 0>;
+ qcom,cpr-up-threshold = <2>;
+ qcom,cpr-down-threshold = <3>;
+ qcom,cpr-idle-clocks = <15>;
+ qcom,cpr-gcnt-time = <1>;
+ qcom,vdd-apc-step-up-limit = <1>;
+ qcom,vdd-apc-step-down-limit = <1>;
+ qcom,cpr-apc-volt-step = <12500>;
+
+ qcom,cpr-fuse-row = <65 0>;
+ qcom,cpr-fuse-target-quot = <24 12 0>;
+ qcom,cpr-fuse-ro-sel = <42 39 36>;
+ qcom,cpr-fuse-bp-cpr-disable = <54>;
+ qcom,cpr-fuse-init-voltage =
+ <66 6 6 0>,
+ <66 0 6 0>,
+ <65 45 6 0>;
+ qcom,cpr-fuse-revision = <65 51 3 0>;
+ qcom,cpr-init-voltage-ref = <1050000 1225000 1350000>;
+ qcom,cpr-init-voltage-step = <10000>;
+ qcom,cpr-corner-map = <1 2 3 3 3 3 3>;
+ qcom,cpr-init-voltage-as-ceiling;
+ qcom,cpr-corner-frequency-map =
+ <1 400000000>,
+ <2 800000000>,
+ <3 998400000>,
+ <4 1094400000>,
+ <5 1190400000>,
+ <6 1248000000>,
+ <7 1305600000>;
+ qcom,speed-bin-fuse-sel = <37 34 3 0>;
+ qcom,cpr-speed-bin-max-corners =
+ <0 0 1 2 7>;
+ qcom,cpr-quot-adjust-scaling-factor-max = <1400>;
+ qcom,disable-closed-loop-in-pc;
+ qcom,cpr-cpus = <&CPU0>;
+ qcom,cpr-enable;
+ };
+
+/* Miscellaneous regulators */
+ sdcard_ext_vreg: sdcard_ext_vreg {
+ compatible = "regulator-fixed";
+ regulator-name = "sdcard_ext_vreg";
+ startup-delay-us = <250>;
+ enable-active-high;
+ gpio = <&pm8019_gpios 4 0>;
+ };
+
+ /* Rome 3.3V supply */
+ rome_vreg: rome_vreg {
+ compatible = "regulator-fixed";
+ regulator-name = "rome_vreg";
+ startup-delay-us = <4000>;
+ enable-active-high;
+ gpio = <&pm8019_gpios 3 0>;
+ };
+
+ emac_lan_vreg: emac_lan_vreg {
+ compatible = "regulator-fixed";
+ regulator-name = "emac_lan_vreg";
+ startup-delay-us = <250>;
+ enable-active-high;
+ gpio = <&pm8019_mpps 4 0>;
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/mdm9607-rpm-regulator.dtsi b/arch/arm/boot/dts/qcom/mdm9607-rpm-regulator.dtsi
new file mode 100644
index 0000000..a085957
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/mdm9607-rpm-regulator.dtsi
@@ -0,0 +1,302 @@
+/*
+ * 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.
+ */
+
+&rpm_bus {
+ rpm-regulator-smpa1 {
+ qcom,resource-name = "smpa";
+ qcom,resource-id = <1>;
+ qcom,regulator-type = <1>;
+ qcom,hpm-min-load = <100000>;
+ compatible = "qcom,rpm-smd-regulator-resource";
+ status = "disabled";
+
+ regulator-s1 {
+ regulator-name = "mdm9607_s1";
+ qcom,set = <3>;
+ status = "disabled";
+ compatible = "qcom,rpm-smd-regulator";
+ };
+ };
+
+ rpm-regulator-smpa2 {
+ qcom,resource-name = "smpa";
+ qcom,resource-id = <2>;
+ qcom,regulator-type = <1>;
+ qcom,hpm-min-load = <100000>;
+ compatible = "qcom,rpm-smd-regulator-resource";
+ status = "disabled";
+
+ regulator-s2 {
+ regulator-name = "mdm9607_s2";
+ qcom,set = <3>;
+ status = "disabled";
+ compatible = "qcom,rpm-smd-regulator";
+ };
+ };
+
+ rpm-regulator-smpa3 {
+ qcom,resource-name = "smpa";
+ qcom,resource-id = <3>;
+ qcom,regulator-type = <1>;
+ qcom,hpm-min-load = <100000>;
+ compatible = "qcom,rpm-smd-regulator-resource";
+ status = "disabled";
+
+ regulator-s3 {
+ regulator-name = "mdm9607_s3";
+ qcom,set = <3>;
+ status = "disabled";
+ compatible = "qcom,rpm-smd-regulator";
+ };
+ };
+
+ rpm-regulator-smpa4 {
+ qcom,resource-name = "smpa";
+ qcom,resource-id = <4>;
+ qcom,regulator-type = <1>;
+ qcom,hpm-min-load = <100000>;
+ compatible = "qcom,rpm-smd-regulator-resource";
+ status = "disabled";
+
+ regulator-s4 {
+ regulator-name = "mdm9607_s4";
+ qcom,set = <3>;
+ status = "disabled";
+ compatible = "qcom,rpm-smd-regulator";
+ };
+ };
+
+ rpm-regulator-ldoa1 {
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <1>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ compatible = "qcom,rpm-smd-regulator-resource";
+ status = "disabled";
+
+ regulator-l1 {
+ regulator-name = "mdm9607_l1";
+ qcom,set = <3>;
+ status = "disabled";
+ compatible = "qcom,rpm-smd-regulator";
+ };
+ };
+
+ rpm-regulator-ldoa2 {
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <2>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <5000>;
+ compatible = "qcom,rpm-smd-regulator-resource";
+ status = "disabled";
+
+ regulator-l2 {
+ regulator-name = "mdm9607_l2";
+ qcom,set = <3>;
+ status = "disabled";
+ compatible = "qcom,rpm-smd-regulator";
+ };
+ };
+
+ rpm-regulator-ldoa3 {
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <3>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ compatible = "qcom,rpm-smd-regulator-resource";
+ status = "disabled";
+
+ regulator-l3 {
+ regulator-name = "mdm9607_l3";
+ qcom,set = <3>;
+ status = "disabled";
+ compatible = "qcom,rpm-smd-regulator";
+ };
+ };
+
+ rpm-regulator-ldoa4 {
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <4>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <5000>;
+ compatible = "qcom,rpm-smd-regulator-resource";
+ status = "disabled";
+
+ regulator-l4 {
+ regulator-name = "mdm9607_l4";
+ qcom,set = <3>;
+ status = "disabled";
+ compatible = "qcom,rpm-smd-regulator";
+ };
+ };
+
+ rpm-regulator-ldoa5 {
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <5>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ compatible = "qcom,rpm-smd-regulator-resource";
+ status = "disabled";
+
+ regulator-l5 {
+ regulator-name = "mdm9607_l5";
+ qcom,set = <3>;
+ status = "disabled";
+ compatible = "qcom,rpm-smd-regulator";
+ };
+ };
+
+ rpm-regulator-ldoa6 {
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <6>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ compatible = "qcom,rpm-smd-regulator-resource";
+ status = "disabled";
+
+ regulator-l6 {
+ regulator-name = "mdm9607_l6";
+ qcom,set = <3>;
+ status = "disabled";
+ compatible = "qcom,rpm-smd-regulator";
+ };
+ };
+
+ rpm-regulator-ldoa7 {
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <7>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ compatible = "qcom,rpm-smd-regulator-resource";
+ status = "disabled";
+
+ regulator-l7 {
+ regulator-name = "mdm9607_l7";
+ qcom,set = <3>;
+ status = "disabled";
+ compatible = "qcom,rpm-smd-regulator";
+ };
+ };
+
+ rpm-regulator-ldoa8 {
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <8>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ compatible = "qcom,rpm-smd-regulator-resource";
+ status = "disabled";
+
+ regulator-l8 {
+ regulator-name = "mdm9607_l8";
+ qcom,set = <3>;
+ status = "disabled";
+ compatible = "qcom,rpm-smd-regulator";
+ };
+ };
+
+ rpm-regulator-ldoa9 {
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <9>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ compatible = "qcom,rpm-smd-regulator-resource";
+ status = "disabled";
+
+ regulator-l9 {
+ regulator-name = "mdm9607_l9";
+ qcom,set = <3>;
+ status = "disabled";
+ compatible = "qcom,rpm-smd-regulator";
+ };
+ };
+
+ rpm-regulator-ldoa10 {
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <10>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ compatible = "qcom,rpm-smd-regulator-resource";
+ status = "disabled";
+
+ regulator-l10 {
+ regulator-name = "mdm9607_l10";
+ qcom,set = <3>;
+ status = "disabled";
+ compatible = "qcom,rpm-smd-regulator";
+ };
+ };
+
+ rpm-regulator-ldoa11 {
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <11>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ compatible = "qcom,rpm-smd-regulator-resource";
+ status = "disabled";
+
+ regulator-l11 {
+ regulator-name = "mdm9607_l11";
+ qcom,set = <3>;
+ status = "disabled";
+ compatible = "qcom,rpm-smd-regulator";
+ };
+ };
+
+ rpm-regulator-ldoa12 {
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <12>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ compatible = "qcom,rpm-smd-regulator-resource";
+ status = "disabled";
+
+ regulator-l12 {
+ regulator-name = "mdm9607_l12";
+ qcom,set = <3>;
+ status = "disabled";
+ compatible = "qcom,rpm-smd-regulator";
+ };
+ };
+
+ rpm-regulator-ldoa13 {
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <13>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ compatible = "qcom,rpm-smd-regulator-resource";
+ status = "disabled";
+
+ regulator-l13 {
+ regulator-name = "mdm9607_l13";
+ qcom,set = <3>;
+ status = "disabled";
+ compatible = "qcom,rpm-smd-regulator";
+ };
+ };
+
+ rpm-regulator-ldoa14 {
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <14>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ compatible = "qcom,rpm-smd-regulator-resource";
+ status = "disabled";
+
+ regulator-l14 {
+ regulator-name = "mdm9607_l14";
+ qcom,set = <3>;
+ status = "disabled";
+ compatible = "qcom,rpm-smd-regulator";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/mdm9607-rumi.dts b/arch/arm/boot/dts/qcom/mdm9607-rumi.dts
new file mode 100644
index 0000000..c4cec0b
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/mdm9607-rumi.dts
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2015-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 "mdm9607.dtsi"
+#include "mdm9607-pinctrl.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. MDM 9607 RUMI";
+ compatible = "qcom,mdm9607-rumi", "qcom,mdm9607", "qcom,rumi";
+ qcom,board-id = <15 0>;
+};
+
+&blsp1_uart5 {
+ status = "ok";
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart_console_sleep>;
+};
+
+&qnand_1 {
+ status = "ok";
+};
+
+&usb_otg {
+ qcom,hsusb-otg-mode = <1>; /* DEVICE only */
+ qcom,hsusb-otg-otg-control = <1>; /* PHY control */
+ qcom,emulation;
+ /delete-property/ qcom,boost-sysclk-with-streaming;
+ /delete-property/ vbus_otg-supply;
+};
+
+&clock_gcc {
+ compatible="qcom,dummycc";
+ #clock-cells = <1>;
+};
+
+&clock_debug {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/qcom/mdm9607-smp2p.dtsi b/arch/arm/boot/dts/qcom/mdm9607-smp2p.dtsi
new file mode 100644
index 0000000..609cf0d
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/mdm9607-smp2p.dtsi
@@ -0,0 +1,104 @@
+/* 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.
+ */
+
+&soc {
+ qcom,smp2p-modem {
+ compatible = "qcom,smp2p";
+ reg = <0x0b011008 0x4>;
+ qcom,remote-pid = <1>;
+ qcom,irq-bitmask = <0x4000>;
+ interrupts = <0 27 1>;
+ };
+
+ smp2pgpio_smp2p_15_in: qcom,smp2pgpio-smp2p-15-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <15>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_15_in {
+ compatible = "qcom,smp2pgpio_test_smp2p_15_in";
+ gpios = <&smp2pgpio_smp2p_15_in 0 0>;
+ };
+
+ smp2pgpio_smp2p_15_out: qcom,smp2pgpio-smp2p-15-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <15>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_15_out {
+ compatible = "qcom,smp2pgpio_test_smp2p_15_out";
+ gpios = <&smp2pgpio_smp2p_15_out 0 0>;
+ };
+
+ smp2pgpio_smp2p_1_in: qcom,smp2pgpio-smp2p-1-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <1>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_1_in {
+ compatible = "qcom,smp2pgpio_test_smp2p_1_in";
+ gpios = <&smp2pgpio_smp2p_1_in 0 0>;
+ };
+
+ smp2pgpio_smp2p_1_out: qcom,smp2pgpio-smp2p-1-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <1>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_1_out {
+ compatible = "qcom,smp2pgpio_test_smp2p_1_out";
+ gpios = <&smp2pgpio_smp2p_1_out 0 0>;
+ };
+
+ smp2pgpio_ssr_smp2p_1_in: qcom,smp2pgpio-ssr-smp2p-1-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "slave-kernel";
+ qcom,remote-pid = <1>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ smp2pgpio_ssr_smp2p_1_out: qcom,smp2pgpio-ssr-smp2p-1-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "master-kernel";
+ qcom,remote-pid = <1>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/mdm9607-ttp.dts b/arch/arm/boot/dts/qcom/mdm9607-ttp.dts
new file mode 100644
index 0000000..fb76558
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/mdm9607-ttp.dts
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+/dts-v1/;
+
+#include "mdm9607-mtp.dtsi"
+/ {
+ model = "Qualcomm Technologies, Inc. MDM 9206 TTP";
+ compatible = "qcom,mdm9607-ttp", "qcom,mdm9607", "qcom,ttp";
+ qcom,board-id = <0x1E 0>;
+};
+
+&emac_lan_vreg{
+ regulator-always-on;
+};
diff --git a/arch/arm/boot/dts/qcom/mdm9607.dtsi b/arch/arm/boot/dts/qcom/mdm9607.dtsi
new file mode 100644
index 0000000..ba6401e
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/mdm9607.dtsi
@@ -0,0 +1,1538 @@
+/*
+ * 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.
+ */
+
+#include "skeleton.dtsi"
+#include <dt-bindings/clock/mdm-clocks-9607.h>
+#include <dt-bindings/clock/msm-clocks-a7.h>
+#include <dt-bindings/regulator/qcom,rpm-smd-regulator.h>
+
+/ {
+ model = "Qualcomm Technologies, Inc. MDM 9607";
+ compatible = "qcom,mdm9607";
+ qcom,msm-id = <290 0x10000>, <296 0x10000>, <297 0x10000>,
+ <298 0x10000>, <299 0x10000>;
+ interrupt-parent = <&intc>;
+
+ aliases {
+ sdhc1 = &sdhc_1;/* SDC1 for SDIO slot */
+ qpic_nand1 = &qnand_1;
+ };
+
+ reserved-memory {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ modem_adsp_mem: modem_adsp_region@0 {
+ compatible = "removed-dma-pool";
+ no-map-fixup;
+ reg = <0x82a00000 0x5000000>;
+ };
+
+ cnss_debug_mem: cnss_debug_region@0 {
+ compatible = "removed-dma-pool";
+ no-map;
+ reg = <0x87a00000 0x200000>;
+ };
+
+ external_image_mem: external_image_region@0 {
+ compatible = "removed-dma-pool";
+ no-map;
+ reg = <0x87c00000 0x400000>;
+ };
+
+ audio_mem: audio_region@0 {
+ compatible = "shared-dma-pool";
+ reusable;
+ alignment = <0x400000>;
+ size = <0x400000>;
+ };
+
+ qseecom_mem: qseecom_region@0 {
+ compatible = "shared-dma-pool";
+ reusable;
+ alignment = <0x400000>;
+ size = <0x0400000>;
+ status = "disabled";
+ };
+ };
+
+ aliases {
+ /* smdtty devices */
+ smd7 = &smdtty_data1;
+ smd8 = &smdtty_data4;
+ smd11 = &smdtty_data11;
+ smd21 = &smdtty_data21;
+ smd36 = &smdtty_loopback;
+ /* spi device */
+ spi1 = &spi_1;
+ i2c4 = &i2c_4;
+ sdhc2 = &sdhc_2; /* SDC2 SD card slot */
+ };
+
+ cpus {
+ #size-cells = <0>;
+ #address-cells = <1>;
+
+ CPU0: cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a7";
+ reg = <0x0>;
+ qcom,limits-info = <&mitigation_profile0>;
+ };
+ };
+ soc: soc { };
+};
+
+#include "mdm9607-ion.dtsi"
+#include "mdm9607-smp2p.dtsi"
+#include "mdm9607-bus.dtsi"
+#include "mdm9607-coresight.dtsi"
+#include "mdm9607-pm.dtsi"
+
+&soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ intc: interrupt-controller@b000000 {
+ compatible = "qcom,msm-qgic2";
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ reg = <0x0b000000 0x1000>,
+ <0x0b002000 0x1000>;
+ };
+
+ qcom,mpm2-sleep-counter@4a3000 {
+ compatible = "qcom,mpm2-sleep-counter";
+ reg = <0x4a3000 0x1000>;
+ clock-frequency = <32768>;
+ };
+
+ timer@b020000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+ compatible = "arm,armv7-timer-mem";
+ reg = <0xb020000 0x1000>;
+ clock-frequency = <19200000>;
+
+ frame@b021000 {
+ frame-number = <0>;
+ interrupts = <0 7 0x4>,
+ <0 6 0x4>;
+ reg = <0xb021000 0x1000>,
+ <0xb022000 0x1000>;
+ };
+
+ frame@b023000 {
+ frame-number = <1>;
+ interrupts = <0 8 0x4>;
+ reg = <0xb023000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@b024000 {
+ frame-number = <2>;
+ interrupts = <0 9 0x4>;
+ reg = <0xb024000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@b025000 {
+ frame-number = <3>;
+ interrupts = <0 10 0x4>;
+ reg = <0xb025000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@b026000 {
+ frame-number = <4>;
+ interrupts = <0 11 0x4>;
+ reg = <0xb026000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@b027000 {
+ frame-number = <5>;
+ interrupts = <0 12 0x4>;
+ reg = <0xb027000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@b028000 {
+ frame-number = <6>;
+ interrupts = <0 13 0x4>;
+ reg = <0xb028000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@b029000 {
+ frame-number = <7>;
+ interrupts = <0 14 0x4>;
+ reg = <0xb029000 0x1000>;
+ status = "disabled";
+ };
+ };
+
+ qcom,wdt@b017000 {
+ compatible = "qcom,msm-watchdog";
+ reg = <0xb017000 0x1000>;
+ reg-names = "wdt-base";
+ interrupts = <0 3 0>, <0 4 0>;
+ qcom,bark-time = <11000>;
+ qcom,pet-time = <10000>;
+ qcom,wakeup-enable;
+ };
+
+ qcom,msm-rtb {
+ compatible = "qcom,msm-rtb";
+ qcom,rtb-size = <0x10000>; /* 64K EBI1 buffer */
+ };
+
+ qcom,msm-imem@8600000 {
+ compatible = "qcom,msm-imem";
+ reg = <0x08600000 0x1000>; /* Address and size of IMEM */
+ ranges = <0x0 0x08600000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ mem_dump_table@10 {
+ compatible = "qcom,msm-imem-mem_dump_table";
+ reg = <0x10 8>;
+ };
+
+ restart_reason@65c {
+ compatible = "qcom,msm-imem-restart_reason";
+ reg = <0x65c 4>;
+ };
+
+ boot_stats@6b0 {
+ compatible = "qcom,msm-imem-boot_stats";
+ reg = <0x6b0 32>;
+ };
+
+ pil@94c {
+ compatible = "qcom,msm-imem-pil";
+ reg = <0x94c 200>;
+ };
+ };
+
+ restart@4ab000 {
+ compatible = "qcom,pshold";
+ reg = <0x4ab000 0x4>,
+ <0x193d100 0x4>;
+ reg-names = "pshold-base", "tcsr-boot-misc-detect";
+ };
+
+ jtag_fuse: jtagfuse@a601c {
+ compatible = "qcom,jtag-fuse-v2";
+ reg = <0xa601c 0x8>;
+ reg-names = "fuse-base";
+ };
+
+ jtag_mm: jtagmm@6042000 {
+ compatible = "qcom,jtagv8-mm";
+ reg = <0x6042000 0x1000>,
+ <0x6040000 0x1000>;
+ reg-names = "etm-base", "debug-base";
+
+ clocks = <&clock_gcc clk_qdss_clk>,
+ <&clock_gcc clk_qdss_a_clk>;
+ clock-names = "core_clk", "core_a_clk";
+
+ qcom,coresight-jtagmm-cpu = <&CPU0>;
+ };
+
+ clock_gcc: qcom,gcc@1800000 {
+ compatible = "qcom,gcc-mdm9607";
+ reg = <0x1800000 0x80000>,
+ <0x0b008000 0x00050>;
+ reg-names = "cc_base", "apcs_base";
+ vdd_dig-supply = <&mdm9607_s3_level>;
+ vdd_stromer_dig-supply = <&mdm9607_s3_level_ao>;
+ #clock-cells = <1>;
+ };
+
+ clock_debug: qcom,debug@1874000 {
+ compatible = "qcom,cc-debug-mdm9607";
+ reg = <0x1800000 0x80000>,
+ <0xb01101c 0x8>;
+ reg-names = "cc_base", "meas";
+ #clock-cells = <1>;
+ };
+
+ clock_cpu: qcom,clock-a7@0b010008 {
+ compatible = "qcom,clock-a7-mdm9607";
+ reg = <0x0b010008 0x8>,
+ <0x000a412c 0x8>;
+ reg-names = "rcg-base", "efuse";
+ qcom,safe-freq = < 400000000 >;
+ cpu-vdd-supply = <&apc_vreg_corner>;
+ clocks = <&clock_gcc clk_gpll0_ao_clk_src>,
+ <&clock_gcc clk_a7sspll>;
+ clock-names = "clk-1", "clk-5";
+ qcom,speed4-bin-v0 =
+ < 0 0>,
+ < 400000000 1>,
+ < 800000000 2>,
+ < 998400000 3>,
+ < 1094400000 4>,
+ < 1190400000 5>,
+ < 1248000000 6>,
+ < 1305600000 7>;
+ qcom,a7ssmux-opp-store-vcorner = <&CPU0>;
+ #clock-cells = <1>;
+ };
+
+ cpubw: qcom,cpubw {
+ compatible = "qcom,devbw";
+ governor = "cpufreq";
+ qcom,src-dst-ports = <1 512>;
+ qcom,active-only;
+ qcom,bw-tbl =
+ < 366 /* 48 MHz */>,
+ < 732 /* 96 MHz */>,
+ < 915 /* 120 MHz */>,
+ < 1145 /* 150.15 MHz */>,
+ < 1831 /* 240 MHz */>,
+ < 2291 /* 300.3 MHZ */>;
+ };
+
+ devfreq-cpufreq {
+ cpubw-cpufreq {
+ target-dev = <&cpubw>;
+ cpu-to-dev-map =
+ < 400000 732>,
+ < 800000 915>,
+ < 998400 1145>,
+ < 1094400 1831>,
+ < 1305600 2291>;
+ };
+ };
+
+ qcom,cpu-bwmon {
+ compatible = "qcom,bimc-bwmon2";
+ reg = <0x408000 0x300>, <0x401000 0x200>;
+ reg-names = "base", "global_base";
+ interrupts = <0 183 4>;
+ qcom,mport = <0>;
+ qcom,target-dev = <&cpubw>;
+ };
+
+ qcom,msm-cpufreq {
+ reg = <0 4>;
+ compatible = "qcom,msm-cpufreq";
+ clocks = <&clock_cpu clk_a7ssmux>;
+ clock-names = "cpu0_clk";
+ qcom,cpufreq-table =
+ < 400000 >,
+ < 800000 >,
+ < 998400 >,
+ < 1094400 >,
+ < 1190400 >,
+ < 1248000 >,
+ < 1305600 >;
+ };
+
+ qcom,sps {
+ compatible = "qcom,msm_sps_4k";
+ qcom,pipe-attr-ee;
+ };
+
+ blsp1_uart5: serial@78b3000 { /* BLSP1 UART5 */
+ compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
+ reg = <0x78b3000 0x200>;
+ interrupts = <0 121 0>;
+ clocks = <&clock_gcc clk_gcc_blsp1_uart5_apps_clk>,
+ <&clock_gcc clk_gcc_blsp1_ahb_clk>;
+ clock-names = "core_clk", "iface_clk";
+ status = "disabled";
+ };
+
+ dma_blsp1: qcom,sps-dma@7884000 { /* BLSP1 */
+ #dma-cells = <4>;
+ compatible = "qcom,sps-dma";
+ reg = <0x7884000 0x2b000>;
+ interrupts = <0 238 0>;
+ qcom,summing-threshold = <10>;
+ };
+
+ i2c_4: i2c@78b8000 { /* BLSP1 QUP4 */
+ compatible = "qcom,i2c-msm-v2";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg-names = "qup_phys_addr";
+ reg = <0x78b8000 0x600>;
+ interrupt-names = "qup_irq";
+ interrupts = <0 98 0>;
+ qcom,clk-freq-out = <400000>;
+ qcom,clk-freq-in = <19200000>;
+ clock-names = "iface_clk", "core_clk";
+ clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>,
+ <&clock_gcc clk_gcc_blsp1_qup4_i2c_apps_clk>;
+
+ pinctrl-names = "i2c_active", "i2c_sleep";
+ pinctrl-0 = <&i2c_4_active>;
+ pinctrl-1 = <&i2c_4_sleep>;
+ qcom,noise-rjct-scl = <0>;
+ qcom,noise-rjct-sda = <0>;
+ qcom,master-id = <86>;
+ dmas = <&dma_blsp1 18 64 0x20000020 0x20>,
+ <&dma_blsp1 19 32 0x20000020 0x20>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+
+ wcd9xxx_tomtom_codec@0d{
+ compatible = "qcom,wcd9xxx-i2c";
+ reg = <0x0d>;
+
+ qcom,cdc-reset-gpio = <&tlmm_pinmux 26 0>;
+ pinctrl-names = "default", "idle";
+ pinctrl-0 = <&codec_reset_active>;
+ pinctrl-1 = <&codec_reset_sleep>;
+
+ qcom,cdc-micbias1-ext-cap;
+
+ 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>;
+ cdc-vdd-buck-supply = <&mdm9607_s4>;
+ qcom,cdc-vdd-buck-voltage = <1950000 1950000>;
+ qcom,cdc-vdd-buck-current = <25000>;
+
+ cdc-vdd-tx-h-supply = <&mdm9607_l11>;
+ qcom,cdc-vdd-tx-h-voltage = <1800000 1800000>;
+ qcom,cdc-vdd-tx-h-current = <25000>;
+
+ cdc-vdd-rx-h-supply = <&mdm9607_l11>;
+ qcom,cdc-vdd-rx-h-voltage = <1800000 1800000>;
+ qcom,cdc-vdd-rx-h-current = <25000>;
+
+ cdc-vddpx-1-supply = <&mdm9607_l11>;
+ qcom,cdc-vddpx-1-voltage = <1800000 1800000>;
+ qcom,cdc-vddpx-1-current = <10000>;
+
+ cdc-vdd-a-1p2v-supply = <&mdm9607_l9>;
+ qcom,cdc-vdd-a-1p2v-voltage = <1225000 1225000>;
+ qcom,cdc-vdd-a-1p2v-current = <10000>;
+
+ cdc-vddcx-1-supply = <&mdm9607_l9>;
+ qcom,cdc-vddcx-1-voltage = <1225000 1225000>;
+ qcom,cdc-vddcx-1-current = <10000>;
+
+ cdc-vddcx-2-supply = <&mdm9607_l9>;
+ qcom,cdc-vddcx-2-voltage = <1225000 1225000>;
+ qcom,cdc-vddcx-2-current = <10000>;
+
+ qcom,cdc-static-supplies = "cdc-vdd-buck",
+ "cdc-vdd-tx-h",
+ "cdc-vdd-rx-h",
+ "cdc-vddpx-1",
+ "cdc-vdd-a-1p2v",
+ "cdc-vddcx-1",
+ "cdc-vddcx-2";
+
+ qcom,cdc-micbias-ldoh-v = <0x3>;
+ qcom,cdc-micbias-cfilt1-mv = <1800>;
+ qcom,cdc-micbias-cfilt2-mv = <2700>;
+ qcom,cdc-micbias-cfilt3-mv = <1800>;
+ qcom,cdc-micbias1-cfilt-sel = <0x0>;
+ qcom,cdc-micbias2-cfilt-sel = <0x1>;
+ qcom,cdc-micbias3-cfilt-sel = <0x2>;
+ qcom,cdc-micbias4-cfilt-sel = <0x2>;
+ qcom,cdc-mclk-clk-rate = <12288000>;
+ qcom,cdc-dmic-sample-rate = <4800000>;
+ qcom,cdc-variant = "WCD9330";
+ };
+
+ wcd9xxx_tapan_codec@0d{
+ compatible = "qcom,wcd9xxx-i2c";
+ reg = <0x0d>;
+
+ status = "disabled";
+ qcom,cdc-reset-gpio = <&tlmm_pinmux 26 0>;
+ pinctrl-names = "default", "idle";
+ pinctrl-0 = <&codec_reset_active>;
+ pinctrl-1 = <&codec_reset_sleep>;
+
+ qcom,cdc-micbias1-ext-cap;
+
+ 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>;
+ cdc-vdd-buck-supply = <&mdm9607_s4>;
+ qcom,cdc-vdd-buck-voltage = <1950000 1950000>;
+ qcom,cdc-vdd-buck-current = <25000>;
+
+ cdc-vdd-tx-h-supply = <&mdm9607_l11>;
+ qcom,cdc-vdd-tx-h-voltage = <1800000 1800000>;
+ qcom,cdc-vdd-tx-h-current = <25000>;
+
+ cdc-vdd-rx-h-supply = <&mdm9607_l11>;
+ qcom,cdc-vdd-rx-h-voltage = <1800000 1800000>;
+ qcom,cdc-vdd-rx-h-current = <25000>;
+
+ cdc-vddpx-1-supply = <&mdm9607_l11>;
+ qcom,cdc-vddpx-1-voltage = <1800000 1800000>;
+ qcom,cdc-vddpx-1-current = <10000>;
+
+ cdc-vdd-cx-supply = <&mdm9607_l9>;
+ qcom,cdc-vdd-cx-voltage = <1225000 1225000>;
+ qcom,cdc-vdd-cx-current = <10000>;
+
+ qcom,cdc-static-supplies = "cdc-vdd-buck",
+ "cdc-vdd-tx-h",
+ "cdc-vdd-rx-h",
+ "cdc-vddpx-1",
+ "cdc-vdd-cx";
+
+ qcom,cdc-micbias-ldoh-v = <0x3>;
+ qcom,cdc-micbias-cfilt1-mv = <1800>;
+ qcom,cdc-micbias-cfilt2-mv = <2700>;
+ qcom,cdc-micbias-cfilt3-mv = <1800>;
+ qcom,cdc-micbias1-cfilt-sel = <0x0>;
+ qcom,cdc-micbias2-cfilt-sel = <0x1>;
+ qcom,cdc-micbias3-cfilt-sel = <0x2>;
+ qcom,cdc-micbias4-cfilt-sel = <0x2>;
+ qcom,cdc-mclk-clk-rate = <12288000>;
+ qcom,cdc-dmic-sample-rate = <4800000>;
+ qcom,cdc-variant = "WCD9306";
+ };
+
+ wcd9xxx_codec@77{
+ compatible = "qcom,wcd9xxx-i2c";
+ reg = <0x77>;
+ };
+
+ wcd9xxx_codec@66{
+ compatible = "qcom,wcd9xxx-i2c";
+ reg = <0x66>;
+ };
+
+ wcd9xxx_codec@55{
+ compatible = "qcom,wcd9xxx-i2c";
+ reg = <0x55>;
+ };
+
+ };
+
+ blsp1_uart3: uart@78b1000 {
+ compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
+ reg = <0x78b1000 0x200>,
+ <0x7884000 0x2b000>;
+ reg-names = "core_mem", "bam_mem";
+ interrupt-names = "core_irq", "bam_irq", "wakeup_irq";
+ #address-cells = <0>;
+ interrupt-parent = <&blsp1_uart3>;
+ interrupts = <0 1 2>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0xffffffff>;
+ interrupt-map = <0 &intc 0 119 0
+ 1 &intc 0 238 0
+ 2 &tlmm_pinmux 1 0>;
+
+ qcom,inject-rx-on-wakeup;
+ qcom,rx-char-to-inject = <0xFD>;
+
+ qcom,bam-tx-ep-pipe-index = <4>;
+ qcom,bam-rx-ep-pipe-index = <5>;
+ qcom,master-id = <86>;
+ clock-names = "core_clk", "iface_clk";
+ clocks = <&clock_gcc clk_gcc_blsp1_uart3_apps_clk>,
+ <&clock_gcc clk_gcc_blsp1_ahb_clk>;
+ pinctrl-names = "sleep", "default";
+ pinctrl-0 = <&blsp1_uart3_sleep>;
+ pinctrl-1 = <&blsp1_uart3_active>;
+ qcom,msm-bus,name = "blsp1_uart3";
+ 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 = "disabled";
+ };
+
+ qcom,cnss-sdio {
+ compatible = "qcom,cnss_sdio";
+ reg = <0x87a00000 0x200000>;
+ reg-names = "ramdump";
+ subsys-name = "AR6320";
+ vdd-wlan-supply = <&rome_vreg>;
+ vdd-wlan-dsrc-supply = <&sdcard_ext_vreg>;
+ vdd-wlan-io-supply = <&mdm9607_l11>;
+ vdd-wlan-xtal-supply = <&mdm9607_l2>;
+ };
+
+ usb_otg: usb@78d9000 {
+ compatible = "qcom,hsusb-otg";
+ reg = <0x78d9000 0x400>, <0x6c000 0x200>;
+ reg-names = "core", "phy_csr";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ interrupts = <0 134 0>, <0 140 0>;
+ interrupt-names = "core_irq", "async_irq";
+
+ hsusb_vdd_dig-supply = <&mdm9607_l9>;
+ HSUSB_1p8-supply = <&mdm9607_l2>;
+ HSUSB_3p3-supply = <&mdm9607_l4>;
+ qcom,vdd-voltage-level = <0 1225000 1225000>;
+
+ qcom,hsusb-otg-phy-init-seq =
+ <0x44 0x80 0x38 0x81 0x24 0x82 0x13 0x83 0xffffffff>;
+
+ qcom,hsusb-otg-phy-type = <3>; /* SNPS Femto PHY */
+ qcom,hsusb-otg-mode = <3>; /* OTG mode */
+ qcom,hsusb-otg-otg-control = <2>; /* PMIC control */
+ qcom,usbid-gpio = <&pm8019_mpps 1 0>;
+ qcom,hsusb-log2-itc = <4>;
+ qcom,dp-manual-pullup;
+ qcom,boost-sysclk-with-streaming;
+ qcom,phy-dvdd-always-on;
+ qcom,hsusb-otg-lpm-on-dev-suspend;
+ qcom,axi-prefetch-enable;
+ qcom,hsusb-otg-mpm-dpsehv-int = <49>;
+ qcom,hsusb-otg-mpm-dmsehv-int = <58>;
+ qcom,hsusb-otg-delay-lpm;
+ qcom,enable-phy-id-pullup;
+
+ qcom,msm-bus,name = "usb2";
+ qcom,msm-bus,num-cases = <3>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <87 512 0 0>,
+ <87 512 80000 0>,
+ <87 512 6000 6000>;
+ clocks = <&clock_gcc clk_gcc_usb_hs_ahb_clk>,
+ <&clock_gcc clk_gcc_usb_hs_system_clk>,
+ <&clock_gcc clk_gcc_usb2a_phy_sleep_clk>,
+ <&clock_gcc clk_bimc_usb_a_clk>,
+ <&clock_gcc clk_pcnoc_usb_a_clk>,
+ <&clock_gcc clk_gcc_qusb2_phy_clk>,
+ <&clock_gcc clk_gcc_usb2_hs_phy_only_clk>,
+ <&clock_gcc clk_gcc_usb_hs_phy_cfg_ahb_clk>,
+ <&clock_gcc clk_xo_otg_clk>;
+ clock-names = "iface_clk", "core_clk", "sleep_clk",
+ "bimc_clk", "pcnoc_clk", "phy_reset_clk",
+ "phy_por_clk", "phy_csr_clk", "xo";
+ qcom,bus-clk-rate = <240000000 0 100000000
+ 120000000 0 50000000>;
+ qcom,max-nominal-sysclk-rate = <133330000>;
+ qcom,max-svs-sysclk-rate = <69500000>;
+ qcom,default-mode-svs;
+
+ qcom,usbbam@78c4000 {
+ compatible = "qcom,usb-bam-msm";
+ reg = <0x78c4000 0x15000>;
+ interrupt-parent = <&intc>;
+ interrupts = <0 135 0>;
+ qcom,bam-type = <1>;
+ qcom,usb-bam-num-pipes = <2>;
+ qcom,usb-bam-fifo-baseaddr = <0x08603800>;
+ qcom,ignore-core-reset-ack;
+ qcom,disable-clk-gating;
+ qcom,reset-bam-on-disconnect;
+
+ qcom,pipe0 {
+ label = "hsusb-qdss-in-0";
+ qcom,usb-bam-mem-type = <2>;
+ qcom,dir = <1>;
+ qcom,pipe-num = <0>;
+ qcom,peer-bam = <0>;
+ qcom,peer-bam-physical-address = <0x6084000>;
+ qcom,src-bam-pipe-index = <0>;
+ qcom,dst-bam-pipe-index = <0>;
+ qcom,data-fifo-offset = <0x0>;
+ qcom,data-fifo-size = <0x600>;
+ qcom,descriptor-fifo-offset = <0x600>;
+ qcom,descriptor-fifo-size = <0x200>;
+ };
+ };
+ };
+
+ android_usb: android_usb@086000c8 {
+ compatible = "qcom,android-usb";
+ reg = <0x086000c8 0xc8>;
+ qcom,pm-qos-latency = <2 1001 12701>;
+ };
+
+ android_usb_hsic: android_usb-hsic {
+ compatible = "qcom,android-usb";
+ qcom,usb-core-id = <1>;
+ status = "disabled";
+ };
+
+ qnand_1: nand@7980000 {
+ compatible = "qcom,msm-nand";
+ reg = <0x07980000 0x1000>,
+ <0x07984000 0x1a000>;
+ reg-names = "nand_phys",
+ "bam_phys";
+ qcom,reg-adjustment-offset = <0x4000>;
+
+ interrupts = <0 132 0>;
+ interrupt-names = "bam_irq";
+
+ qcom,msm-bus,name = "qpic_nand";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+
+ qcom,msm-bus,vectors-KBps =
+ <91 512 0 0>,
+ /* Voting for max b/w on PNOC bus for now */
+ <91 512 400000 400000>;
+
+ clock-names = "core_clk";
+ clocks = <&clock_gcc clk_qpic_clk>;
+ status = "disabled";
+ };
+
+ sdhc_1: sdhci@7824900 {
+ compatible = "qcom,sdhci-msm";
+ reg = <0x7824900 0x200>, <0x7824000 0x800>, <0x01111000 0x4>;
+ reg-names = "hc_mem", "core_mem", "tlmm_mem";
+
+ qcom,cpu-dma-latency-us = <701>;
+ qcom,bus-width = <4>;
+ gpios = <&tlmm_pinmux 16 0>, /* CLK */
+ <&tlmm_pinmux 17 0>, /* CMD */
+ <&tlmm_pinmux 15 0>, /* DATA0 */
+ <&tlmm_pinmux 14 0>, /* DATA1 */
+ <&tlmm_pinmux 13 0>, /* DATA2 */
+ <&tlmm_pinmux 12 0>; /* DATA3 */
+ qcom,gpio-names = "CLK", "CMD", "DAT0", "DAT1", "DAT2", "DAT3";
+
+ qcom,clk-rates = <400000 20000000 25000000 50000000 100000000
+ 200000000>;
+
+ clock-names = "iface_clk", "core_clk";
+ clocks = <&clock_gcc clk_gcc_sdcc1_ahb_clk>,
+ <&clock_gcc clk_gcc_sdcc1_apps_clk>;
+
+ qcom,msm-bus,name = "sdhc1";
+ qcom,msm-bus,num-cases = <8>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps = <78 512 0 0>, /* No vote */
+ <78 512 1600 3200>, /* 400 KB/s*/
+ <78 512 80000 160000>, /* 20 MB/s */
+ <78 512 100000 200000>, /* 25 MB/s */
+ <78 512 200000 400000>, /* 50 MB/s */
+ <78 512 400000 800000>, /* 100 MB/s */
+ <78 512 800000 800000>, /* 200 MB/s */
+ <78 512 2048000 4096000>; /* Max. bandwidth */
+ qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000
+ 50000000 100000000 200000000 4294967295>;
+
+ #address-cells = <0>;
+ interrupt-parent = <&sdhc_1>;
+ interrupts = <0 1 2>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0xffffffff>;
+ interrupt-map = <0 &intc 0 123 0
+ 1 &intc 0 138 0
+ 2 &tlmm_pinmux 59 0x4>;
+ interrupt-names = "hc_irq", "pwr_irq", "sdiowakeup_irq";
+
+ qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50",
+ "DDR50","SDR104";
+
+ qcom,pm-qos-irq-type = "affine_irq";
+ qcom,pm-qos-irq-latency = <2 250>;
+
+ status = "disabled";
+ };
+
+ wcd9xxx_intc: wcd9xxx-irq {
+ compatible = "qcom,wcd9xxx-irq";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ interrupt-parent = <&tlmm_pinmux>;
+ qcom,gpio-connect = <&tlmm_pinmux 75 0>;
+ interrupt-names = "cdc-int";
+ };
+
+ qcom,msm-adsp-loader {
+ compatible = "qcom,adsp-loader";
+ qcom,adsp-state = <0>;
+ qcom,proc-img-to-load = "modem";
+ };
+
+ qcom,msm-audio-ion {
+ compatible = "qcom,msm-audio-ion";
+ qcom,scm-mp-enabled;
+ memory-region = <&audio_mem>;
+ };
+
+ pcm0: qcom,msm-pcm {
+ compatible = "qcom,msm-pcm-dsp";
+ qcom,msm-pcm-dsp-id = <0>;
+ };
+
+ routing: qcom,msm-pcm-routing {
+ compatible = "qcom,msm-pcm-routing";
+ };
+
+ pcm1: qcom,msm-pcm-low-latency {
+ compatible = "qcom,msm-pcm-dsp";
+ qcom,msm-pcm-dsp-id = <1>;
+ qcom,msm-pcm-low-latency;
+ qcom,latency-level = "ultra";
+ };
+
+ qcom,msm-compr-dsp {
+ compatible = "qcom,msm-compr-dsp";
+ };
+
+ voip: qcom,msm-voip-dsp {
+ compatible = "qcom,msm-voip-dsp";
+ };
+
+ voice: qcom,msm-pcm-voice {
+ compatible = "qcom,msm-pcm-voice";
+ qcom,destroy-cvd;
+ };
+
+ stub_codec: qcom,msm-stub-codec {
+ compatible = "qcom,msm-stub-codec";
+ };
+
+ qcom,msm-dai-fe {
+ compatible = "qcom,msm-dai-fe";
+ };
+
+ afe: qcom,msm-pcm-afe {
+ compatible = "qcom,msm-pcm-afe";
+ };
+
+ hostless: qcom,msm-pcm-hostless {
+ compatible = "qcom,msm-pcm-hostless";
+ };
+
+ host_pcm: qcom,msm-voice-host-pcm {
+ compatible = "qcom,msm-voice-host-pcm";
+ };
+
+ loopback: qcom,msm-pcm-loopback {
+ compatible = "qcom,msm-pcm-loopback";
+ };
+
+ compress: qcom,msm-compress-dsp {
+ compatible = "qcom,msm-compress-dsp";
+ qcom,adsp-version = "MDSP 2.8";
+ };
+
+ qcom,msm-dai-stub {
+ compatible = "qcom,msm-dai-stub";
+ dtmf_tx: qcom,msm-dai-stub-dtmf-tx {
+ compatible = "qcom,msm-dai-stub-dev";
+ qcom,msm-dai-stub-dev-id = <4>;
+ };
+
+ rx_capture_tx: qcom,msm-dai-stub-host-rx-capture-tx {
+ compatible = "qcom,msm-dai-stub-dev";
+ qcom,msm-dai-stub-dev-id = <5>;
+ };
+
+ rx_playback_rx: qcom,msm-dai-stub-host-rx-playback-rx {
+ compatible = "qcom,msm-dai-stub-dev";
+ qcom,msm-dai-stub-dev-id = <6>;
+ };
+
+ tx_capture_tx: qcom,msm-dai-stub-host-tx-capture-tx {
+ compatible = "qcom,msm-dai-stub-dev";
+ qcom,msm-dai-stub-dev-id = <7>;
+ };
+
+ tx_playback_rx: qcom,msm-dai-stub-host-tx-playback-rx {
+ compatible = "qcom,msm-dai-stub-dev";
+ qcom,msm-dai-stub-dev-id = <8>;
+ };
+ };
+
+ qcom,msm-dai-q6 {
+ compatible = "qcom,msm-dai-q6";
+ afe_pcm_rx: qcom,msm-dai-q6-be-afe-pcm-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <224>;
+ };
+
+ afe_pcm_tx: qcom,msm-dai-q6-be-afe-pcm-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <225>;
+ };
+
+ afe_proxy_rx: qcom,msm-dai-q6-afe-proxy-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <241>;
+ };
+
+ afe_proxy_tx: qcom,msm-dai-q6-afe-proxy-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <240>;
+ };
+
+ incall_record_rx: qcom,msm-dai-q6-incall-record-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <32771>;
+ };
+
+ incall_record_tx: qcom,msm-dai-q6-incall-record-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <32772>;
+ };
+
+ incall_music_rx: qcom,msm-dai-q6-incall-music-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <32773>;
+ };
+ };
+
+ pcm_dtmf: qcom,msm-pcm-dtmf {
+ compatible = "qcom,msm-pcm-dtmf";
+ };
+
+ dai_pri_auxpcm: qcom,msm-pri-auxpcm {
+ compatible = "qcom,msm-auxpcm-dev";
+ qcom,msm-cpudai-auxpcm-mode = <0>, <0>;
+ qcom,msm-cpudai-auxpcm-sync = <1>, <1>;
+ qcom,msm-cpudai-auxpcm-frame = <5>, <4>;
+ qcom,msm-cpudai-auxpcm-quant = <2>, <2>;
+ qcom,msm-cpudai-auxpcm-num-slots = <1>, <1>;
+ qcom,msm-cpudai-auxpcm-slot-mapping = <1>, <1>;
+ qcom,msm-cpudai-auxpcm-data = <0>, <0>;
+ qcom,msm-cpudai-auxpcm-pcm-clk-rate = <2048000>, <2048000>;
+ qcom,msm-auxpcm-interface = "primary";
+ qcom,msm-cpudai-afe-clk-ver = <2>;
+ };
+
+ dai_sec_auxpcm: qcom,msm-sec-auxpcm {
+ compatible = "qcom,msm-auxpcm-dev";
+ qcom,msm-cpudai-auxpcm-mode = <0>, <0>;
+ qcom,msm-cpudai-auxpcm-sync = <1>, <1>;
+ qcom,msm-cpudai-auxpcm-frame = <5>, <4>;
+ qcom,msm-cpudai-auxpcm-quant = <2>, <2>;
+ qcom,msm-cpudai-auxpcm-num-slots = <1>, <1>;
+ qcom,msm-cpudai-auxpcm-slot-mapping = <1>, <1>;
+ qcom,msm-cpudai-auxpcm-data = <0>, <0>;
+ qcom,msm-cpudai-auxpcm-pcm-clk-rate = <2048000>, <2048000>;
+ qcom,msm-auxpcm-interface = "secondary";
+ qcom,msm-cpudai-afe-clk-ver = <2>;
+ };
+
+ qcom,msm-dai-mi2s {
+ compatible = "qcom,msm-dai-mi2s";
+ mi2s_prim: qcom,msm-dai-q6-mi2s-prim {
+ compatible = "qcom,msm-dai-q6-mi2s";
+ qcom,msm-dai-q6-mi2s-dev-id = <0>;
+ qcom,msm-mi2s-rx-lines = <2>;
+ qcom,msm-mi2s-tx-lines = <1>;
+ };
+ mi2s_sec: qcom,msm-dai-q6-mi2s-sec {
+ compatible = "qcom,msm-dai-q6-mi2s";
+ qcom,msm-dai-q6-mi2s-dev-id = <1>;
+ qcom,msm-mi2s-rx-lines = <2>;
+ qcom,msm-mi2s-tx-lines = <1>;
+ };
+ };
+
+ qcom,msm-thermal {
+ compatible = "qcom,msm-thermal";
+ qcom,sensor-id = <4>;
+ qcom,poll-ms = <250>;
+ qcom,limit-temp = <60>;
+ qcom,temp-hysteresis = <10>;
+ qcom,freq-step = <2>;
+ qcom,freq-mitigation-temp = <105>;
+ qcom,freq-mitigation-temp-hysteresis = <15>;
+ qcom,freq-mitigation-value = <800000>;
+ qcom,disable-cx-phase-ctrl;
+ qcom,disable-gfx-phase-ctrl;
+ qcom,disable-psm;
+ qcom,disable-ocr;
+ qcom,mx-restriction-temp = <10>;
+ qcom,mx-restriction-temp-hysteresis = <5>;
+ qcom,mx-retention-min =
+ <RPM_SMD_REGULATOR_LEVEL_NOM_PLUS>;
+ vdd-mx-supply = <&mdm9607_l12_floor_level>;
+ qcom,vdd-restriction-temp = <10>;
+ qcom,vdd-restriction-temp-hysteresis = <15>;
+ vdd-dig-supply = <&mdm9607_s3_floor_level>;
+ qcom,therm-ddr-lm-info = <2 78 70>;
+
+ qcom,vdd-dig-rstr{
+ qcom,vdd-rstr-reg = "vdd-dig";
+ qcom,levels = <RPM_SMD_REGULATOR_LEVEL_TURBO_NO_CPR
+ RPM_SMD_REGULATOR_LEVEL_BINNING
+ RPM_SMD_REGULATOR_LEVEL_BINNING>;
+ qcom,min-level = <RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+ };
+
+ msm_thermal_freq: qcom,vdd-apps-rstr {
+ qcom,vdd-rstr-reg = "vdd-apps";
+ qcom,levels = <998400>;
+ qcom,freq-req;
+ };
+ };
+
+ qcom,sensor-information {
+ compatible = "qcom,sensor-information";
+ sensor_information0: qcom,sensor-information-0 {
+ qcom,sensor-type = "tsens";
+ qcom,sensor-name = "tsens_tz_sensor0";
+ };
+
+ sensor_information1: qcom,sensor-information-1 {
+ qcom,sensor-type = "tsens";
+ qcom,sensor-name = "tsens_tz_sensor1";
+ };
+
+ sensor_information2: qcom,sensor-information-2 {
+ qcom,sensor-type = "tsens";
+ qcom,sensor-name = "tsens_tz_sensor2";
+ };
+
+ sensor_information3: qcom,sensor-information-3 {
+ qcom,sensor-type = "tsens";
+ qcom,sensor-name = "tsens_tz_sensor3";
+ };
+
+ sensor_information4: qcom,sensor-information-4 {
+ qcom,sensor-type = "tsens";
+ qcom,sensor-name = "tsens_tz_sensor4";
+ };
+
+ sensor_information5: qcom,sensor-information-5 {
+ qcom,sensor-type = "adc";
+ qcom,sensor-name = "pa_therm0";
+ };
+
+ sensor_information6: qcom,sensor-information-6 {
+ qcom,sensor-type = "adc";
+ qcom,sensor-name = "pa_therm1";
+ };
+
+ sensor_information7: qcom,sensor-information-7 {
+ qcom,sensor-type = "adc";
+ qcom,sensor-name = "xo_therm";
+ };
+
+ sensor_information8: qcom,sensor-information-8 {
+ qcom,sensor-type = "adc";
+ qcom,sensor-name = "xo_therm_amux";
+ };
+ };
+
+ mitigation_profile0: qcom,limit_info-0 {
+ qcom,temperature-sensor = <&sensor_information4>;
+ qcom,boot-frequency-mitigate;
+ qcom,emergency-frequency-mitigate;
+ };
+
+ qcom,ipc-spinlock@1905000 {
+ compatible = "qcom,ipc-spinlock-sfpb";
+ reg = <0x1905000 0x8000>;
+ qcom,num-locks = <8>;
+ };
+
+ qcom,smem@87d00000 {
+ compatible = "qcom,smem";
+ reg = <0x87d00000 0x100000>,
+ <0x0b011008 0x4>,
+ <0x60000 0x8000>,
+ <0x193d000 0x8>;
+ reg-names = "smem", "irq-reg-base", "aux-mem1",
+ "smem_targ_info_reg";
+ qcom,mpu-enabled;
+
+ qcom,smd-modem {
+ compatible = "qcom,smd";
+ qcom,smd-edge = <0>;
+ qcom,smd-irq-offset = <0x0>;
+ qcom,smd-irq-bitmask = <0x1000>;
+ interrupts = <0 25 1>;
+ label = "modem";
+ qcom,not-loadable;
+ };
+
+ qcom,smsm-modem {
+ compatible = "qcom,smsm";
+ qcom,smsm-edge = <0>;
+ qcom,smsm-irq-offset = <0x0>;
+ qcom,smsm-irq-bitmask = <0x2000>;
+ interrupts = <0 26 1>;
+ };
+
+ qcom,smd-rpm {
+ compatible = "qcom,smd";
+ qcom,smd-edge = <15>;
+ qcom,smd-irq-offset = <0x0>;
+ qcom,smd-irq-bitmask = <0x1>;
+ interrupts = <0 168 1>;
+ label = "rpm";
+ qcom,irq-no-suspend;
+ qcom,not-loadable;
+ };
+ };
+
+ rpm_bus: qcom,rpm-smd {
+ compatible = "qcom,rpm-smd";
+ rpm-channel-name = "rpm_requests";
+ rpm-channel-type = <15>; /* SMD_APPS_RPM */
+ };
+
+ qcom,smdtty {
+ compatible = "qcom,smdtty";
+
+ smdtty_data1: qcom,smdtty-data1 {
+ qcom,smdtty-remote = "modem";
+ qcom,smdtty-port-name = "DATA1";
+ };
+
+ smdtty_data4: qcom,smdtty-data4 {
+ qcom,smdtty-remote = "modem";
+ qcom,smdtty-port-name = "DATA4";
+ };
+
+ smdtty_data11: qcom,smdtty-data11 {
+ qcom,smdtty-remote = "modem";
+ qcom,smdtty-port-name = "DATA11";
+ };
+
+ smdtty_data21: qcom,smdtty-data21 {
+ qcom,smdtty-remote = "modem";
+ qcom,smdtty-port-name = "DATA21";
+ };
+
+ smdtty_loopback: smdtty-loopback {
+ qcom,smdtty-remote = "modem";
+ qcom,smdtty-port-name = "LOOPBACK";
+ qcom,smdtty-dev-name = "LOOPBACK_TTY";
+ };
+ };
+
+ qcom,smdpkt {
+ compatible = "qcom,smdpkt";
+
+ qcom,smdpkt-data5-cntl {
+ qcom,smdpkt-remote = "modem";
+ qcom,smdpkt-port-name = "DATA5_CNTL";
+ qcom,smdpkt-dev-name = "smdcntl0";
+ };
+
+ qcom,smdpkt-data22 {
+ qcom,smdpkt-remote = "modem";
+ qcom,smdpkt-port-name = "DATA22";
+ qcom,smdpkt-dev-name = "smd22";
+ };
+
+ qcom,smdpkt-data40-cntl {
+ qcom,smdpkt-remote = "modem";
+ qcom,smdpkt-port-name = "DATA40_CNTL";
+ qcom,smdpkt-dev-name = "smdcntl8";
+ };
+
+ qcom,smdpkt-apr-apps2 {
+ qcom,smdpkt-remote = "modem";
+ qcom,smdpkt-port-name = "apr_apps2";
+ qcom,smdpkt-dev-name = "apr_apps2";
+ };
+
+ qcom,smdpkt-loopback {
+ qcom,smdpkt-remote = "modem";
+ qcom,smdpkt-port-name = "LOOPBACK";
+ qcom,smdpkt-dev-name = "smd_pkt_loopback";
+ };
+ };
+
+ qcom,ipc_router {
+ compatible = "qcom,ipc_router";
+ qcom,node-id = <1>;
+ };
+
+ qcom,ipc_router_modem_xprt {
+ compatible = "qcom,ipc_router_smd_xprt";
+ qcom,ch-name = "IPCRTR";
+ qcom,xprt-remote = "modem";
+ qcom,xprt-linkid = <1>;
+ qcom,xprt-version = <1>;
+ qcom,fragmented-data;
+ qcom,disable-pil-loading;
+ };
+
+ qcom,bam_dmux@4044000 {
+ compatible = "qcom,bam_dmux";
+ reg = <0x4044000 0x19000>;
+ interrupts = <0 29 1>;
+ qcom,rx-ring-size = <32>;
+ qcom,max-rx-mtu = <4096>;
+ qcom,fast-shutdown;
+ };
+
+ spmi_bus: qcom,spmi@200f000 {
+ compatible = "qcom,spmi-pmic-arb";
+ reg = <0x200f000 0x1000>,
+ <0x2400000 0x800000>,
+ <0x2c00000 0x800000>,
+ <0x3800000 0x200000>,
+ <0x200a000 0x2100>;
+ reg-names = "core", "chnls", "obsrvr", "intr", "cnfg";
+ interrupts = <0 190 0>;
+ qcom,pmic-arb-channel = <0>;
+ qcom,pmic-arb-max-peripherals = <128>;
+ qcom,pmic-arb-max-periph-interrupts = <128>;
+ qcom,pmic-arb-ee = <0>;
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <0>;
+ };
+
+ spi_1: spi@78b6000 { /* BLSP1 QUP1 */
+ compatible = "qcom,spi-qup-v2";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg-names = "spi_physical", "spi_bam_physical";
+ reg = <0x78b6000 0x600>,
+ <0x7884000 0x2b000>;
+ interrupt-names = "spi_irq", "spi_bam_irq";
+ interrupts = <0 96 0>, <0 238 0>;
+ spi-max-frequency = <19200000>;
+ pinctrl-names = "spi_default", "spi_sleep";
+ pinctrl-0 = <&spi1_default &spi1_cs0_active>;
+ pinctrl-1 = <&spi1_sleep &spi1_cs0_sleep>;
+ clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>,
+ <&clock_gcc clk_gcc_blsp1_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 = <14>;
+ qcom,bam-producer-pipe-index = <15>;
+ qcom,master-id = <86>;
+ status = "disabled";
+ };
+
+ qcom,mss@4080000 {
+ compatible = "qcom,pil-q6v55-mss";
+ reg = <0x04080000 0x100>,
+ <0x0194f000 0x010>,
+ <0x01950000 0x008>,
+ <0x01951000 0x008>,
+ <0x04020000 0x040>,
+ <0x0183e000 0x004>;
+ reg-names = "qdsp6_base", "halt_q6", "halt_modem", "halt_nc",
+ "rmb_base", "restart_reg";
+
+ interrupts = <0 24 1>;
+ vdd_cx-supply = <&mdm9607_s3_level>;
+ vdd_cx-voltage = <RPM_SMD_REGULATOR_LEVEL_TURBO>;
+ vdd_mx-supply = <&mdm9607_l12_level>;
+ vdd_pll-supply = <&mdm9607_l3>;
+ qcom,vdd_pll = <1800000>;
+
+ clocks = <&clock_gcc clk_xo_pil_mss_clk>,
+ <&clock_gcc clk_gcc_mss_cfg_ahb_clk>,
+ <&clock_gcc clk_gcc_mss_q6_bimc_axi_clk>,
+ <&clock_gcc clk_gcc_boot_rom_ahb_clk>;
+ clock-names = "xo", "iface_clk", "bus_clk", "mem_clk";
+ qcom,proxy-clock-names = "xo";
+ qcom,active-clock-names = "iface_clk", "bus_clk", "mem_clk";
+
+ qcom,firmware-name = "modem";
+ qcom,pil-self-auth;
+ qcom,override-acc-1 = <0x80800000>;
+ qcom,sysmon-id = <0>;
+ qcom,ssctl-instance-id = <0x12>;
+ qcom,qdsp6v56-1-8-inrush-current;
+
+ /* GPIO inputs from mss */
+ qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_1_in 0 0>;
+ qcom,gpio-err-ready = <&smp2pgpio_ssr_smp2p_1_in 1 0>;
+ qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_1_in 2 0>;
+ qcom,gpio-stop-ack = <&smp2pgpio_ssr_smp2p_1_in 3 0>;
+ qcom,gpio-shutdown-ack = <&smp2pgpio_ssr_smp2p_1_in 7 0>;
+
+ /* GPIO output to mss */
+ qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_1_out 0 0>;
+ memory-region = <&modem_adsp_mem>;
+ };
+
+ sdhc_2: sdhci@07864900 {
+ compatible = "qcom,sdhci-msm";
+ reg = <0x07864900 0x200>, <0x07864000 0x800>;
+ reg-names = "hc_mem", "core_mem";
+
+ interrupts = <0 125 0>, <0 221 0>;
+ interrupt-names = "hc_irq", "pwr_irq";
+
+ qcom,bus-width = <4>;
+
+ qcom,devfreq,freq-table = <50000000 200000000>;
+
+ qcom,msm-bus,name = "sdhc2";
+ qcom,msm-bus,num-cases = <8>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps = <81 512 0 0>, /* No vote */
+ <81 512 1600 3200>, /* 400 KB/s*/
+ <81 512 80000 160000>, /* 20 MB/s */
+ <81 512 100000 200000>, /* 25 MB/s */
+ <81 512 200000 400000>, /* 50 MB/s */
+ <81 512 400000 800000>, /* 100 MB/s */
+ <81 512 800000 800000>, /* 200 MB/s */
+ <81 512 2048000 4096000>; /* Max. bandwidth */
+ qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000 50000000
+ 100000000 200000000 4294967295>;
+
+ clocks = <&clock_gcc clk_gcc_sdcc2_ahb_clk>,
+ <&clock_gcc clk_gcc_sdcc2_apps_clk>;
+ clock-names = "iface_clk", "core_clk";
+
+ qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>;
+
+ qcom,pm-qos-irq-type = "affine_irq";
+ qcom,pm-qos-irq-latency = <2 250>;
+
+ status = "disabled";
+ };
+
+ qrng: rng@22000 {
+ compatible = "qcom,msm-rng";
+ reg = <0x22000 0x140>;
+ qcom,msm-rng-iface-clk;
+ qcom,msm-bus,name = "msm-rng-noc";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <1 618 0 0>,
+ <1 618 0 800>;
+ clocks = <&clock_gcc clk_gcc_prng_ahb_clk>;
+ clock-names = "iface_clk";
+ };
+
+ qcom_crypto: qcrypto@720000 {
+ compatible = "qcom,qcrypto";
+ reg = <0x720000 0x20000>,
+ <0x704000 0x20000>;
+ reg-names = "crypto-base","crypto-bam-base";
+ interrupts = <0 207 0>;
+ qcom,bam-pipe-pair = <2>;
+ qcom,ce-hw-instance = <0>;
+ qcom,ce-device = <0>;
+ qcom,clk-mgmt-sus-res;
+ qcom,msm-bus,name = "qcrypto-noc";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <47 512 0 0>,
+ <47 512 393600 800000>;
+ clocks = <&clock_gcc clk_crypto_clk_src>,
+ <&clock_gcc clk_gcc_crypto_clk>,
+ <&clock_gcc clk_gcc_crypto_ahb_clk>,
+ <&clock_gcc clk_gcc_crypto_axi_clk>;
+ clock-names = "core_clk_src", "core_clk",
+ "iface_clk", "bus_clk";
+ qcom,use-sw-aes-cbc-ecb-ctr-algo;
+ qcom,use-sw-aes-xts-algo;
+ qcom,use-sw-aes-ccm-algo;
+ qcom,use-sw-ahash-algo;
+ qcom,use-sw-hmac-algo;
+ qcom,use-sw-aead-algo;
+ qcom,ce-opp-freq = <100000000>;
+ };
+
+ qcom_qcedev: qcedev@720000 {
+ compatible = "qcom,qcedev";
+ reg = <0x720000 0x20000>,
+ <0x704000 0x20000>;
+ reg-names = "crypto-base","crypto-bam-base";
+ interrupts = <0 207 0>;
+ qcom,bam-pipe-pair = <1>;
+ qcom,ce-hw-instance = <0>;
+ qcom,ce-device = <0>;
+ qcom,ce-hw-shared;
+ qcom,msm-bus,name = "qcedev-noc";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <47 512 0 0>,
+ <47 512 3936000 393600>;
+ clocks = <&clock_gcc clk_crypto_clk_src>,
+ <&clock_gcc clk_gcc_crypto_clk>,
+ <&clock_gcc clk_gcc_crypto_ahb_clk>,
+ <&clock_gcc clk_gcc_crypto_axi_clk>;
+ clock-names = "core_clk_src", "core_clk",
+ "iface_clk", "bus_clk";
+ qcom,ce-opp-freq = <100000000>;
+ };
+
+ qcom_seecom: qseecom@87a80000 {
+ compatible = "qcom,qseecom";
+ reg = <0x87a80000 0x100000>;
+ reg-names = "secapp-region";
+ qcom,hlos-ce-hw-instance = <0>;
+ qcom,qsee-ce-hw-instance = <0>;
+ qcom,msm-bus,name = "qseecom-noc";
+ qcom,msm-bus,num-cases = <4>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <47 512 0 0>,
+ <47 512 0 0>,
+ <47 512 120000 1200000>,
+ <47 512 393600 3936000>;
+ clocks = <&clock_gcc clk_crypto_clk_src>,
+ <&clock_gcc clk_gcc_crypto_clk>,
+ <&clock_gcc clk_gcc_crypto_ahb_clk>,
+ <&clock_gcc clk_gcc_crypto_axi_clk>;
+ clock-names = "core_clk_src", "core_clk",
+ "iface_clk", "bus_clk";
+ qcom,ce-opp-freq = <100000000>;
+ status = "disabled";
+ };
+
+ pps {
+ compatible = "pps-gpio";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pps>;
+ gpios = <&tlmm_pinmux 53 0>;
+ status = "okay";
+ };
+};
+
+#include "mdm9607-rpm-regulator.dtsi"
+#include "msm-pm8019.dtsi"
+#include "mdm9607-regulator.dtsi"
+
+/* MPP pin 1 config for USB ID interrupt line */
+&pm8019_mpps {
+ mpp@a000 {
+ qcom,mode = <0>; /* Digital input */
+ qcom,vin-sel = <3>; /* 1.8V (L11) */
+ qcom,src-sel = <0>; /* QPNP_PIN_SEL_FUNC_CONSTANT */
+ qcom,pull = <2>; /* PULL UP 10KOHM */
+ qcom,master-en = <1>;
+ status = "okay";
+ };
+};
+
+&pm8019_vadc {
+ chan@6 {
+ label = "vbat_sns";
+ reg = <6>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <1>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@7 {
+ label = "vph_pwr";
+ reg = <7>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <1>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@31 {
+ label = "batt_id_therm";
+ reg = <0x31>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@33 {
+ label = "pa_therm0";
+ reg = <0x33>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@34 {
+ label = "pa_therm1";
+ reg = <0x34>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@32 {
+ label = "xo_therm";
+ reg = <0x32>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <4>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@3c {
+ label = "xo_therm_amux";
+ reg = <0x3c>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <4>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ };
+};
+
+&pm8019_adc_tm {
+ /* Channel Node */
+ chan@33 {
+ label = "pa_therm0";
+ reg = <0x33>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ qcom,btm-channel-number = <0x48>;
+ qcom,thermal-node;
+ };
+
+ chan@34 {
+ label = "pa_therm1";
+ reg = <0x34>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ qcom,btm-channel-number = <0x68>;
+ qcom,thermal-node;
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/msm-pm8019.dtsi b/arch/arm/boot/dts/qcom/msm-pm8019.dtsi
new file mode 100644
index 0000000..afb4723
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/msm-pm8019.dtsi
@@ -0,0 +1,421 @@
+/* Copyright (c) 2012, 2013, 2015, 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.
+ */
+
+&spmi_bus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+
+ qcom,pm8019@0 {
+ spmi-slave-container;
+ reg = <0x0>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ pm8019_revid: qcom,revid@100 {
+ compatible = "qcom,qpnp-revid";
+ reg = <0x100 0x100>;
+ };
+
+ qcom,power_on@800 {
+ compatible = "qcom,qpnp-power-on";
+ reg = <0x800 0x100>;
+ interrupts = <0x0 0x8 0x2>;
+ interrupt-names = "cblpwr";
+ qcom,pon-dbc-delay = <15625>;
+ qcom,system-reset;
+
+ qcom,pon_1 {
+ qcom,pon-type = <2>;
+ qcom,pull-up = <1>;
+ linux,code = <116>;
+ };
+ };
+
+ clkdiv@5b00 {
+ reg = <0x5b00 0x100>;
+ compatible = "qcom,qpnp-clkdiv";
+ qcom,cxo-freq = <19200000>;
+ };
+
+ clkdiv@5c00 {
+ reg = <0x5c00 0x100>;
+ compatible = "qcom,qpnp-clkdiv";
+ qcom,cxo-freq = <19200000>;
+ };
+
+ clkdiv@5d00 {
+ reg = <0x5d00 0x100>;
+ compatible = "qcom,qpnp-clkdiv";
+ qcom,cxo-freq = <19200000>;
+ };
+
+ rtc {
+ spmi-dev-container;
+ compatible = "qcom,qpnp-rtc";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ qcom,qpnp-rtc-write = <0>;
+ qcom,qpnp-rtc-alarm-pwrup = <0>;
+
+ qcom,pm8019_rtc_rw@6000 {
+ reg = <0x6000 0x100>;
+ };
+
+ qcom,pm8019_rtc_alarm@6100 {
+ reg = <0x6100 0x100>;
+ interrupts = <0x0 0x61 0x1>;
+ };
+ };
+
+ pm8019_gpios: gpios {
+ spmi-dev-container;
+ compatible = "qcom,qpnp-pin";
+ gpio-controller;
+ #gpio-cells = <2>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ label = "pm8019-gpio";
+
+ gpio@c000 {
+ reg = <0xc000 0x100>;
+ qcom,pin-num = <1>;
+ };
+
+ gpio@c100 {
+ reg = <0xc100 0x100>;
+ qcom,pin-num = <2>;
+ };
+
+ gpio@c200 {
+ reg = <0xc200 0x100>;
+ qcom,pin-num = <3>;
+ };
+
+ gpio@c300 {
+ reg = <0xc300 0x100>;
+ qcom,pin-num = <4>;
+ };
+
+ gpio@c400 {
+ reg = <0xc400 0x100>;
+ qcom,pin-num = <5>;
+ };
+
+ gpio@c500 {
+ reg = <0xc500 0x100>;
+ qcom,pin-num = <6>;
+ };
+ };
+
+ pm8019_mpps: mpps {
+ spmi-dev-container;
+ compatible = "qcom,qpnp-pin";
+ gpio-controller;
+ #gpio-cells = <2>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ label = "pm8019-mpp";
+
+ mpp@a000 {
+ reg = <0xa000 0x100>;
+ qcom,pin-num = <1>;
+ };
+
+ mpp@a100 {
+ reg = <0xa100 0x100>;
+ qcom,pin-num = <2>;
+ };
+
+ mpp@a200 {
+ reg = <0xa200 0x100>;
+ qcom,pin-num = <3>;
+ };
+
+ mpp@a300 {
+ reg = <0xa300 0x100>;
+ qcom,pin-num = <4>;
+ };
+
+ mpp@a400 {
+ reg = <0xa400 0x100>;
+ qcom,pin-num = <5>;
+ };
+
+ mpp@a500 {
+ reg = <0xa500 0x100>;
+ qcom,pin-num = <6>;
+ };
+ };
+
+ pm8019_vadc: vadc@3100 {
+ compatible = "qcom,qpnp-vadc";
+ reg = <0x3100 0x100>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <0x0 0x31 0x0>;
+ interrupt-names = "eoc-int-en-set";
+ qcom,adc-bit-resolution = <15>;
+ qcom,adc-vdd-reference = <1800>;
+ qcom,vadc-poll-eoc;
+
+ chan@8 {
+ label = "die_temp";
+ reg = <8>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <3>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@9 {
+ label = "ref_625mv";
+ reg = <9>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@a {
+ label = "ref_1250v";
+ reg = <0xa>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+ };
+
+ pm8019_adc_tm: vadc@3400 {
+ compatible = "qcom,qpnp-adc-tm";
+ reg = <0x3400 0x100>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <0x0 0x34 0x0>,
+ <0x0 0x34 0x3>,
+ <0x0 0x34 0x4>;
+ interrupt-names = "eoc-int-en-set",
+ "high-thr-en-set",
+ "low-thr-en-set";
+ qcom,adc-bit-resolution = <15>;
+ qcom,adc_tm-vadc = <&pm8019_vadc>;
+ qcom,adc-vdd-reference = <1800>;
+ };
+ };
+
+ qcom,pm8019@1 {
+ spmi-slave-container;
+ reg = <0x1>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ regulator@1400 {
+ regulator-name = "8019_s1";
+ spmi-dev-container;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "qcom,qpnp-regulator";
+ reg = <0x1400 0x300>;
+ status = "disabled";
+
+ qcom,ctl@1400 {
+ reg = <0x1400 0x100>;
+ };
+ qcom,ps@1500 {
+ reg = <0x1500 0x100>;
+ };
+ qcom,freq@1600 {
+ reg = <0x1600 0x100>;
+ };
+ };
+
+ regulator@1700 {
+ regulator-name = "8019_s2";
+ spmi-dev-container;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "qcom,qpnp-regulator";
+ reg = <0x1700 0x300>;
+ status = "disabled";
+
+ qcom,ctl@1700 {
+ reg = <0x1700 0x100>;
+ };
+ qcom,ps@1800 {
+ reg = <0x1800 0x100>;
+ };
+ qcom,freq@1900 {
+ reg = <0x1900 0x100>;
+ };
+ };
+
+ regulator@1a00 {
+ regulator-name = "8019_s3";
+ spmi-dev-container;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "qcom,qpnp-regulator";
+ reg = <0x1a00 0x300>;
+ status = "disabled";
+
+ qcom,ctl@1a00 {
+ reg = <0x1a00 0x100>;
+ };
+ qcom,ps@1b00 {
+ reg = <0x1b00 0x100>;
+ };
+ qcom,freq@1c00 {
+ reg = <0x1c00 0x100>;
+ };
+ };
+
+ regulator@1d00 {
+ regulator-name = "8019_s4";
+ spmi-dev-container;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "qcom,qpnp-regulator";
+ reg = <0x1d00 0x300>;
+ status = "disabled";
+
+ qcom,ctl@1d00 {
+ reg = <0x1d00 0x100>;
+ };
+ qcom,ps@1e00 {
+ reg = <0x1e00 0x100>;
+ };
+ qcom,freq@1f00 {
+ reg = <0x1f00 0x100>;
+ };
+ };
+
+ regulator@4000 {
+ regulator-name = "8019_l1";
+ reg = <0x4000 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@4100 {
+ regulator-name = "8019_l2";
+ reg = <0x4100 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@4200 {
+ regulator-name = "8019_l3";
+ reg = <0x4200 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@4300 {
+ regulator-name = "8019_l4";
+ reg = <0x4300 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@4400 {
+ regulator-name = "8019_l5";
+ reg = <0x4400 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@4500 {
+ regulator-name = "8019_l6";
+ reg = <0x4500 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@4600 {
+ regulator-name = "8019_l7";
+ reg = <0x4600 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@4700 {
+ regulator-name = "8019_l8";
+ reg = <0x4700 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@4800 {
+ regulator-name = "8019_l9";
+ reg = <0x4800 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@4900 {
+ regulator-name = "8019_l10";
+ reg = <0x4900 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@4a00 {
+ regulator-name = "8019_l11";
+ reg = <0x4a00 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@4b00 {
+ regulator-name = "8019_l12";
+ reg = <0x4b00 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@4c00 {
+ regulator-name = "8019_l13";
+ reg = <0x4c00 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@4d00 {
+ regulator-name = "8019_l14";
+ reg = <0x4d00 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@4e00 {
+ regulator-name = "8019_ldo_xo";
+ reg = <0x4e00 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@4f00 {
+ regulator-name = "8019_ldo_rfclk";
+ reg = <0x4f00 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+ };
+};
diff --git a/arch/arm/configs/mdm9607-perf_defconfig b/arch/arm/configs/mdm9607-perf_defconfig
new file mode 100644
index 0000000..1728981
--- /dev/null
+++ b/arch/arm/configs/mdm9607-perf_defconfig
@@ -0,0 +1,293 @@
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_EMBEDDED=y
+CONFIG_PROFILING=y
+CONFIG_CC_STACKPROTECTOR_REGULAR=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_ARCH_QCOM=y
+CONFIG_ARCH_MDM9607=y
+# CONFIG_VDSO is not set
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_CMA=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_GOV_INTERACTIVE=y
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_XFRM_SUB_POLICY=y
+CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_NET_IPGRE_DEMUX=y
+CONFIG_NET_IPGRE=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_INET6_ESP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=y
+CONFIG_IPV6_GRE=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_IPV6_MROUTE=y
+CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
+CONFIG_IPV6_PIMSM_V2=y
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_DEBUG=y
+CONFIG_BRIDGE_NETFILTER=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CONNTRACK_TIMEOUT=y
+CONFIG_NF_CONNTRACK_TIMESTAMP=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_SNMP=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SIP=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NF_CT_NETLINK_TIMEOUT=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_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_TRACE=y
+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y
+CONFIG_NETFILTER_XT_MATCH_CONNLABEL=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_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_IP_SET=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_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_NATTYPE_MODULE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_TARGET_ECN=y
+CONFIG_IP_NF_TARGET_TTL=y
+CONFIG_IP_NF_RAW=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_AH=y
+CONFIG_IP6_NF_MATCH_FRAG=y
+CONFIG_IP6_NF_MATCH_OPTS=y
+CONFIG_IP6_NF_MATCH_HL=y
+CONFIG_IP6_NF_MATCH_IPV6HEADER=y
+CONFIG_IP6_NF_MATCH_MH=y
+CONFIG_IP6_NF_MATCH_RT=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_BRIDGE_EBT_T_FILTER=y
+CONFIG_BRIDGE_EBT_T_NAT=y
+CONFIG_BRIDGE_EBT_ARP=y
+CONFIG_BRIDGE_EBT_IP=y
+CONFIG_BRIDGE_EBT_IP6=y
+CONFIG_BRIDGE_EBT_ARPREPLY=y
+CONFIG_BRIDGE_EBT_DNAT=y
+CONFIG_BRIDGE_EBT_SNAT=y
+CONFIG_BRIDGE=y
+CONFIG_VLAN_8021Q=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_PRIO=y
+CONFIG_RMNET_DATA=y
+CONFIG_RMNET_DATA_FC=y
+CONFIG_RMNET_DATA_DEBUG_PKT=y
+CONFIG_CAN=y
+CONFIG_CAN_VCAN=y
+CONFIG_BT=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_CFG80211=y
+CONFIG_CFG80211_DEBUGFS=y
+CONFIG_CFG80211_INTERNAL_REGDB=y
+CONFIG_CFG80211_WEXT=y
+CONFIG_RFKILL=y
+CONFIG_IPC_ROUTER=y
+CONFIG_IPC_ROUTER_SECURITY=y
+CONFIG_DMA_CMA=y
+CONFIG_CMA_SIZE_MBYTES=4
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+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
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_NETDEVICES=y
+CONFIG_TUN=y
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+CONFIG_KS8851=y
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+CONFIG_QCOM_EMAC=m
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+CONFIG_AT803X_PHY=m
+CONFIG_PPP=y
+CONFIG_PPP_ASYNC=y
+CONFIG_USB_USBNET=y
+CONFIG_WCNSS_MEM_PRE_ALLOC=y
+CONFIG_CNSS=y
+CONFIG_CNSS_SDIO=y
+# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_INPUT_GPIO=m
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_MSM=y
+CONFIG_SERIAL_MSM_HS=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_SPI=y
+CONFIG_SPI_SPIDEV=m
+CONFIG_PPS_CLIENT_GPIO=y
+CONFIG_PTP_1588_CLOCK=y
+CONFIG_PINCTRL_MDM9607=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_SMB1351_USB_CHARGER=y
+CONFIG_THERMAL=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_ACM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DEBUG=y
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_STORAGE_ONETOUCH=y
+CONFIG_USB_STORAGE_KARMA=y
+CONFIG_USB_STORAGE_CYPRESS_ATACB=y
+CONFIG_USB_EHSET_TEST_FIXTURE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DEBUG_FILES=y
+CONFIG_USB_GADGET_DEBUG_FS=y
+CONFIG_USB_GADGET_VBUS_DRAW=500
+CONFIG_USB_CI13XXX_MSM=y
+CONFIG_MMC=y
+CONFIG_MMC_PERF_PROFILING=y
+CONFIG_MMC_PARANOID_SD_INIT=y
+CONFIG_MMC_CLKGATE=y
+CONFIG_MMC_BLOCK_MINORS=32
+CONFIG_MMC_TEST=m
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_MSM=y
+CONFIG_RTC_CLASS=y
+CONFIG_DMADEVICES=y
+CONFIG_UIO=y
+CONFIG_STAGING=y
+CONFIG_ION=y
+CONFIG_ION_MSM=y
+CONFIG_SPS=y
+CONFIG_SPS_SUPPORT_NDP_BAM=y
+CONFIG_USB_BAM=y
+CONFIG_COMMON_CLK_MSM=y
+CONFIG_MAILBOX=y
+CONFIG_MSM_SPM=y
+CONFIG_MSM_BOOT_STATS=y
+CONFIG_TRACER_PKT=y
+CONFIG_MSM_SUBSYSTEM_RESTART=y
+CONFIG_MSM_PIL=y
+CONFIG_MSM_PIL_MSS_QDSP6V5=y
+CONFIG_CNSS_CRYPTO=y
+CONFIG_IIO=y
+CONFIG_IIO_BUFFER=y
+CONFIG_IIO_BUFFER_CB=y
+CONFIG_RESET_CONTROLLER=y
+CONFIG_ANDROID=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_UBIFS_FS=y
+CONFIG_UBIFS_FS_ADVANCED_COMPR=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_INFO=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_PAGE_POISONING=y
+CONFIG_PANIC_TIMEOUT=5
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_IPC_LOGGING=y
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_PANIC_ON_DATA_CORRUPTION=y
+CONFIG_DEBUG_USER=y
diff --git a/arch/arm/configs/mdm9607_defconfig b/arch/arm/configs/mdm9607_defconfig
new file mode 100644
index 0000000..f6dfe7f
--- /dev/null
+++ b/arch/arm/configs/mdm9607_defconfig
@@ -0,0 +1,300 @@
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_EMBEDDED=y
+CONFIG_PROFILING=y
+CONFIG_CC_STACKPROTECTOR_REGULAR=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_ARCH_QCOM=y
+CONFIG_ARCH_MDM9607=y
+# CONFIG_VDSO is not set
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_CMA=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_GOV_INTERACTIVE=y
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_XFRM_SUB_POLICY=y
+CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_NET_IPGRE_DEMUX=y
+CONFIG_NET_IPGRE=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_INET6_ESP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=y
+CONFIG_IPV6_GRE=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_IPV6_MROUTE=y
+CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
+CONFIG_IPV6_PIMSM_V2=y
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_DEBUG=y
+CONFIG_BRIDGE_NETFILTER=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CONNTRACK_TIMEOUT=y
+CONFIG_NF_CONNTRACK_TIMESTAMP=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_SNMP=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SIP=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NF_CT_NETLINK_TIMEOUT=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_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_TRACE=y
+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y
+CONFIG_NETFILTER_XT_MATCH_CONNLABEL=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_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_IP_SET=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_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_NATTYPE_MODULE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_TARGET_ECN=y
+CONFIG_IP_NF_TARGET_TTL=y
+CONFIG_IP_NF_RAW=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_AH=y
+CONFIG_IP6_NF_MATCH_FRAG=y
+CONFIG_IP6_NF_MATCH_OPTS=y
+CONFIG_IP6_NF_MATCH_HL=y
+CONFIG_IP6_NF_MATCH_IPV6HEADER=y
+CONFIG_IP6_NF_MATCH_MH=y
+CONFIG_IP6_NF_MATCH_RT=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_BRIDGE_EBT_T_FILTER=y
+CONFIG_BRIDGE_EBT_T_NAT=y
+CONFIG_BRIDGE_EBT_ARP=y
+CONFIG_BRIDGE_EBT_IP=y
+CONFIG_BRIDGE_EBT_IP6=y
+CONFIG_BRIDGE_EBT_ARPREPLY=y
+CONFIG_BRIDGE_EBT_DNAT=y
+CONFIG_BRIDGE_EBT_SNAT=y
+CONFIG_BRIDGE=y
+CONFIG_VLAN_8021Q=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_PRIO=y
+CONFIG_RMNET_DATA=y
+CONFIG_RMNET_DATA_FC=y
+CONFIG_RMNET_DATA_DEBUG_PKT=y
+CONFIG_CAN=y
+CONFIG_CAN_VCAN=y
+CONFIG_BT=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_CFG80211=y
+CONFIG_CFG80211_DEBUGFS=y
+CONFIG_CFG80211_INTERNAL_REGDB=y
+CONFIG_CFG80211_WEXT=y
+CONFIG_RFKILL=y
+CONFIG_IPC_ROUTER=y
+CONFIG_IPC_ROUTER_SECURITY=y
+CONFIG_DMA_CMA=y
+CONFIG_CMA_SIZE_MBYTES=4
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+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
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_NETDEVICES=y
+CONFIG_TUN=y
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+CONFIG_KS8851=y
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+CONFIG_QCOM_EMAC=m
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+CONFIG_AT803X_PHY=m
+CONFIG_PPP=y
+CONFIG_PPP_ASYNC=y
+CONFIG_USB_USBNET=y
+CONFIG_WCNSS_MEM_PRE_ALLOC=y
+CONFIG_CNSS=y
+CONFIG_CNSS_SDIO=y
+# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_INPUT_GPIO=m
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_MSM=y
+CONFIG_SERIAL_MSM_CONSOLE=y
+CONFIG_SERIAL_MSM_HS=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_SPI=y
+CONFIG_SPI_SPIDEV=m
+CONFIG_PPS_CLIENT_GPIO=y
+CONFIG_PTP_1588_CLOCK=y
+CONFIG_PINCTRL_MDM9607=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_SMB1351_USB_CHARGER=y
+CONFIG_THERMAL=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_ACM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DEBUG=y
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_STORAGE_ONETOUCH=y
+CONFIG_USB_STORAGE_KARMA=y
+CONFIG_USB_STORAGE_CYPRESS_ATACB=y
+CONFIG_USB_EHSET_TEST_FIXTURE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DEBUG_FILES=y
+CONFIG_USB_GADGET_DEBUG_FS=y
+CONFIG_USB_GADGET_VBUS_DRAW=500
+CONFIG_USB_CI13XXX_MSM=y
+CONFIG_MMC=y
+CONFIG_MMC_PERF_PROFILING=y
+CONFIG_MMC_PARANOID_SD_INIT=y
+CONFIG_MMC_CLKGATE=y
+CONFIG_MMC_BLOCK_MINORS=32
+CONFIG_MMC_TEST=m
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_MSM=y
+CONFIG_RTC_CLASS=y
+CONFIG_DMADEVICES=y
+CONFIG_UIO=y
+CONFIG_STAGING=y
+CONFIG_ION=y
+CONFIG_ION_MSM=y
+CONFIG_SPS=y
+CONFIG_SPS_SUPPORT_NDP_BAM=y
+CONFIG_USB_BAM=y
+CONFIG_COMMON_CLK_MSM=y
+CONFIG_MAILBOX=y
+CONFIG_MSM_SPM=y
+CONFIG_MSM_BOOT_STATS=y
+CONFIG_TRACER_PKT=y
+CONFIG_MSM_SUBSYSTEM_RESTART=y
+CONFIG_MSM_PIL=y
+CONFIG_MSM_PIL_MSS_QDSP6V5=y
+CONFIG_CNSS_CRYPTO=y
+CONFIG_IIO=y
+CONFIG_IIO_BUFFER=y
+CONFIG_IIO_BUFFER_CB=y
+CONFIG_RESET_CONTROLLER=y
+CONFIG_ANDROID=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_UBIFS_FS=y
+CONFIG_UBIFS_FS_ADVANCED_COMPR=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_DEBUG_INFO=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_PAGEALLOC=y
+CONFIG_DEBUG_KMEMLEAK=y
+CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y
+CONFIG_DEBUG_STACK_USAGE=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_PANIC_TIMEOUT=5
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_ATOMIC_SLEEP=y
+CONFIG_IPC_LOGGING=y
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_PANIC_ON_DATA_CORRUPTION=y
+CONFIG_DEBUG_USER=y
diff --git a/arch/arm/configs/msm8909w-perf_defconfig b/arch/arm/configs/msm8909w-perf_defconfig
index 8b6a931..7c10cdd 100644
--- a/arch/arm/configs/msm8909w-perf_defconfig
+++ b/arch/arm/configs/msm8909w-perf_defconfig
@@ -26,6 +26,7 @@
CONFIG_NAMESPACES=y
CONFIG_SCHED_AUTOGROUP=y
CONFIG_SCHED_TUNE=y
+CONFIG_DEFAULT_USE_ENERGY_AWARE=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_KALLSYMS_ALL=y
CONFIG_BPF_SYSCALL=y
@@ -53,6 +54,7 @@
CONFIG_BALANCE_ANON_FILE_RECLAIM=y
CONFIG_SECCOMP=y
CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE=y
+CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
CONFIG_CPU_IDLE=y
CONFIG_VFP=y
CONFIG_NEON=y
diff --git a/arch/arm/configs/msm8909w_defconfig b/arch/arm/configs/msm8909w_defconfig
index 8b6a931..7c10cdd 100644
--- a/arch/arm/configs/msm8909w_defconfig
+++ b/arch/arm/configs/msm8909w_defconfig
@@ -26,6 +26,7 @@
CONFIG_NAMESPACES=y
CONFIG_SCHED_AUTOGROUP=y
CONFIG_SCHED_TUNE=y
+CONFIG_DEFAULT_USE_ENERGY_AWARE=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_KALLSYMS_ALL=y
CONFIG_BPF_SYSCALL=y
@@ -53,6 +54,7 @@
CONFIG_BALANCE_ANON_FILE_RECLAIM=y
CONFIG_SECCOMP=y
CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE=y
+CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
CONFIG_CPU_IDLE=y
CONFIG_VFP=y
CONFIG_NEON=y
diff --git a/arch/arm/configs/msm8953-perf_defconfig b/arch/arm/configs/msm8953-perf_defconfig
index 62c90b3..722845e 100644
--- a/arch/arm/configs/msm8953-perf_defconfig
+++ b/arch/arm/configs/msm8953-perf_defconfig
@@ -316,6 +316,7 @@
CONFIG_POWER_RESET=y
CONFIG_POWER_RESET_QCOM=y
CONFIG_QCOM_DLOAD_MODE=y
+CONFIG_POWER_RESET_SYSCON=y
CONFIG_POWER_SUPPLY=y
CONFIG_QPNP_FG=y
CONFIG_SMB135X_CHARGER=y
@@ -351,7 +352,37 @@
CONFIG_MEDIA_CAMERA_SUPPORT=y
CONFIG_MEDIA_CONTROLLER=y
CONFIG_VIDEO_V4L2_SUBDEV_API=y
+CONFIG_MEDIA_USB_SUPPORT=y
+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
+CONFIG_MSM_CSI20_HEADER=y
+CONFIG_MSM_CSI22_HEADER=y
+CONFIG_MSM_CSI30_HEADER=y
+CONFIG_MSM_CSI31_HEADER=y
+CONFIG_MSM_CSIPHY=y
+CONFIG_MSM_CSID=y
+CONFIG_MSM_EEPROM=y
+CONFIG_MSM_ISPIF_V2=y
+CONFIG_IMX134=y
+CONFIG_IMX132=y
+CONFIG_OV9724=y
+CONFIG_OV5648=y
+CONFIG_GC0339=y
+CONFIG_OV8825=y
+CONFIG_OV8865=y
+CONFIG_s5k4e1=y
+CONFIG_OV12830=y
+CONFIG_MSM_V4L2_VIDEO_OVERLAY_DEVICE=y
+CONFIG_MSMB_JPEG=y
+CONFIG_MSM_FD=y
+CONFIG_MSM_JPEGDMA=y
CONFIG_MSM_VIDC_3X_V4L2=y
CONFIG_MSM_VIDC_3X_GOVERNORS=y
CONFIG_QCOM_KGSL=y
@@ -444,8 +475,6 @@
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_QTI_TRI_LED=y
CONFIG_LEDS_QPNP=y
CONFIG_LEDS_QPNP_FLASH=y
diff --git a/arch/arm/configs/msm8953_defconfig b/arch/arm/configs/msm8953_defconfig
index 144235f..26d9717 100644
--- a/arch/arm/configs/msm8953_defconfig
+++ b/arch/arm/configs/msm8953_defconfig
@@ -327,6 +327,7 @@
CONFIG_POWER_RESET=y
CONFIG_POWER_RESET_QCOM=y
CONFIG_QCOM_DLOAD_MODE=y
+CONFIG_POWER_RESET_SYSCON=y
CONFIG_POWER_SUPPLY=y
CONFIG_QPNP_FG=y
CONFIG_SMB135X_CHARGER=y
@@ -362,7 +363,37 @@
CONFIG_MEDIA_CAMERA_SUPPORT=y
CONFIG_MEDIA_CONTROLLER=y
CONFIG_VIDEO_V4L2_SUBDEV_API=y
+CONFIG_MEDIA_USB_SUPPORT=y
+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
+CONFIG_MSM_CSI20_HEADER=y
+CONFIG_MSM_CSI22_HEADER=y
+CONFIG_MSM_CSI30_HEADER=y
+CONFIG_MSM_CSI31_HEADER=y
+CONFIG_MSM_CSIPHY=y
+CONFIG_MSM_CSID=y
+CONFIG_MSM_EEPROM=y
+CONFIG_MSM_ISPIF_V2=y
+CONFIG_IMX134=y
+CONFIG_IMX132=y
+CONFIG_OV9724=y
+CONFIG_OV5648=y
+CONFIG_GC0339=y
+CONFIG_OV8825=y
+CONFIG_OV8865=y
+CONFIG_s5k4e1=y
+CONFIG_OV12830=y
+CONFIG_MSM_V4L2_VIDEO_OVERLAY_DEVICE=y
+CONFIG_MSMB_JPEG=y
+CONFIG_MSM_FD=y
+CONFIG_MSM_JPEGDMA=y
CONFIG_MSM_VIDC_3X_V4L2=y
CONFIG_MSM_VIDC_3X_GOVERNORS=y
CONFIG_QCOM_KGSL=y
@@ -457,8 +488,6 @@
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_QTI_TRI_LED=y
CONFIG_LEDS_QPNP=y
CONFIG_LEDS_QPNP_FLASH=y
diff --git a/arch/arm/configs/sdxpoorwills-perf_defconfig b/arch/arm/configs/sdxpoorwills-perf_defconfig
index b2dc7f7..32ff446 100644
--- a/arch/arm/configs/sdxpoorwills-perf_defconfig
+++ b/arch/arm/configs/sdxpoorwills-perf_defconfig
@@ -330,6 +330,7 @@
CONFIG_EP_PCIE=y
CONFIG_EP_PCIE_HW=y
CONFIG_QPNP_REVID=y
+CONFIG_MSM_MHI_DEV=y
CONFIG_USB_BAM=y
CONFIG_MSM_CLK_RPMH=y
CONFIG_MSM_CLK_AOP_QMP=y
diff --git a/arch/arm/configs/sdxpoorwills_defconfig b/arch/arm/configs/sdxpoorwills_defconfig
index ac15d6ea..a6063c8 100644
--- a/arch/arm/configs/sdxpoorwills_defconfig
+++ b/arch/arm/configs/sdxpoorwills_defconfig
@@ -335,6 +335,7 @@
CONFIG_EP_PCIE=y
CONFIG_EP_PCIE_HW=y
CONFIG_QPNP_REVID=y
+CONFIG_MSM_MHI_DEV=y
CONFIG_USB_BAM=y
CONFIG_MSM_CLK_RPMH=y
CONFIG_MSM_CLK_AOP_QMP=y
diff --git a/arch/arm/include/asm/fixmap.h b/arch/arm/include/asm/fixmap.h
index 5c17d2d..92fb518 100644
--- a/arch/arm/include/asm/fixmap.h
+++ b/arch/arm/include/asm/fixmap.h
@@ -10,6 +10,7 @@
enum fixed_addresses {
FIX_EARLYCON_MEM_BASE,
+ FIX_SMP_MEM_BASE,
__end_of_permanent_fixed_addresses,
FIX_KMAP_BEGIN = __end_of_permanent_fixed_addresses,
diff --git a/arch/arm/mach-qcom/Kconfig b/arch/arm/mach-qcom/Kconfig
index e8d96df..65b43ea 100644
--- a/arch/arm/mach-qcom/Kconfig
+++ b/arch/arm/mach-qcom/Kconfig
@@ -152,5 +152,27 @@
select MSM_RPM_STATS_LOG
select HAVE_CLK_PREPARE
+config ARCH_MDM9607
+ bool "MDM9607"
+ select ARM_GIC
+ select CPU_V7
+ select REGULATOR
+ select REGULATOR_RPM_SMD
+ select HAVE_ARM_ARCH_TIMER
+ select MSM_RPM_SMD
+ select MEMORY_HOLE_CARVEOUT
+ select MSM_CORTEX_A7
+ select PINCTRL
+ select PINCTRL_MSM_TLMM
+ select USE_PINCTRL_IRQ
+ select MSM_IRQ
+ select MSM_PM if PM
+ select PM_DEVFREQ
+ select MSM_DEVFREQ_DEVBW
+ select MSM_BIMC_BWMON
+ select DEVFREQ_GOV_MSM_BW_HWMON
+ select ARM_HAS_SG_CHAIN
+ select HAVE_CLK_PREPARE
+
endmenu
endif
diff --git a/arch/arm/mach-qcom/Makefile b/arch/arm/mach-qcom/Makefile
index cfc4eac..c167075 100644
--- a/arch/arm/mach-qcom/Makefile
+++ b/arch/arm/mach-qcom/Makefile
@@ -7,3 +7,4 @@
obj-$(CONFIG_ARCH_MSM8917) += board-msm8917.o
obj-$(CONFIG_ARCH_SDM450) += board-sdm450.o
obj-$(CONFIG_ARCH_MDM9650) += board-9650.o
+obj-$(CONFIG_ARCH_MDM9607) += board-9607.o
diff --git a/arch/arm/mach-qcom/board-9607.c b/arch/arm/mach-qcom/board-9607.c
new file mode 100644
index 0000000..fc18b90
--- /dev/null
+++ b/arch/arm/mach-qcom/board-9607.c
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <asm/mach/map.h>
+#include <asm/mach/arch.h>
+#include "board-dt.h"
+
+static const char *mdm9607_dt_match[] __initconst = {
+ "qcom,mdm9607",
+ NULL
+};
+
+static void __init mdm9607_init(void)
+{
+ board_dt_populate(NULL);
+}
+
+DT_MACHINE_START(MDM9607_DT,
+ "Qualcomm Technologies, Inc. MDM 9607 (Flattened Device Tree)")
+ .init_machine = mdm9607_init,
+ .dt_compat = mdm9607_dt_match,
+MACHINE_END
diff --git a/arch/arm/mach-qcom/board-msm8909.c b/arch/arm/mach-qcom/board-msm8909.c
index da9ca7d..3c5928d 100644
--- a/arch/arm/mach-qcom/board-msm8909.c
+++ b/arch/arm/mach-qcom/board-msm8909.c
@@ -15,6 +15,7 @@
#include <asm/mach/map.h>
#include <asm/mach/arch.h>
#include "board-dt.h"
+#include "platsmp.h"
static const char *msm8909_dt_match[] __initconst = {
"qcom,msm8909",
@@ -30,4 +31,5 @@
"Qualcomm Technologies, Inc. MSM 8909 (Flattened Device Tree)")
.init_machine = msm8909_init,
.dt_compat = msm8909_dt_match,
+ .smp = &msm8909_smp_ops,
MACHINE_END
diff --git a/arch/arm/mach-qcom/platsmp.c b/arch/arm/mach-qcom/platsmp.c
index 5494c9e..c422ac3 100644
--- a/arch/arm/mach-qcom/platsmp.c
+++ b/arch/arm/mach-qcom/platsmp.c
@@ -20,7 +20,13 @@
#include <linux/qcom_scm.h>
#include <asm/smp_plat.h>
+#include <asm/fixmap.h>
+#include "platsmp.h"
+#define MSM_APCS_IDR 0x0B011030
+
+/* Base Address of APC IPC block */
+#define APCS_ALIAS0_APC_SECURE 0x0B088000
#define VDD_SC1_ARRAY_CLAMP_GFS_CTL 0x35a0
#define SCSS_CPU1CORE_RESET 0x2d80
@@ -29,9 +35,12 @@
#define APCS_CPU_PWR_CTL 0x04
#define PLL_CLAMP BIT(8)
#define CORE_PWRD_UP BIT(7)
+#define GATE_CLK BIT(6)
#define COREPOR_RST BIT(5)
#define CORE_RST BIT(4)
#define L2DT_SLP BIT(3)
+#define L1_RST_DIS BIT(2)
+#define CORE_MEM_CLAMP BIT(1)
#define CLAMP BIT(0)
#define APC_PWR_GATE_CTL 0x14
@@ -270,6 +279,67 @@
static DEFINE_PER_CPU(int, cold_boot_done);
+/*
+ * writing to physical address:
+ * 0xb088000 + (cpu * 0x10000) + 0x04 and
+ * 0xb088000 + (cpu * 0x10000) + 0x014
+ * For each secondary cpu
+ */
+
+static int arm_release_secondary(unsigned int cpu)
+{
+ phys_addr_t base = APCS_ALIAS0_APC_SECURE;
+ void __iomem *base_ptr;
+ unsigned int reg_val;
+
+ base_ptr = ioremap_nocache(base + (cpu * 0x10000), SZ_4K);
+
+ if (!base_ptr)
+ return -ENODEV;
+
+ reg_val = COREPOR_RST | CORE_RST | CORE_MEM_CLAMP | CLAMP;
+ writel_relaxed(reg_val, base_ptr + APCS_CPU_PWR_CTL);
+ /* memory barrier */
+ mb();
+
+ /* Turn on the BHS, set the BHS_CNT value with 16 */
+ reg_val = (0x10 << BHS_CNT_SHIFT) | BHS_EN;
+ writel_relaxed(reg_val, base_ptr + APC_PWR_GATE_CTL);
+ /* memory barrier */
+ mb();
+ udelay(2);
+
+ reg_val = COREPOR_RST | CORE_RST | CLAMP;
+ writel_relaxed(reg_val, base_ptr + APCS_CPU_PWR_CTL);
+ /* memory barrier */
+ mb();
+
+ reg_val = COREPOR_RST | CORE_RST | L2DT_SLP | CLAMP;
+ writel_relaxed(reg_val, base_ptr + APCS_CPU_PWR_CTL);
+ /* memory barrier */
+ mb();
+ udelay(2);
+
+ reg_val = COREPOR_RST | CORE_RST | L2DT_SLP;
+ writel_relaxed(reg_val, base_ptr + APCS_CPU_PWR_CTL);
+ /* memory barrier */
+ mb();
+ udelay(2);
+
+ reg_val = L2DT_SLP;
+ writel_relaxed(reg_val, base_ptr + APCS_CPU_PWR_CTL);
+ /* memory barrier */
+ mb();
+
+ reg_val = CORE_PWRD_UP | L2DT_SLP;
+ writel_relaxed(reg_val, base_ptr + APCS_CPU_PWR_CTL);
+ /* memory barrier */
+ mb();
+
+ iounmap(base_ptr);
+ return 0;
+}
+
static int qcom_boot_secondary(unsigned int cpu, int (*func)(unsigned int))
{
int ret = 0;
@@ -302,6 +372,40 @@
return ret;
}
+/*
+ * Initialise the CPU possible map early - this describes the CPUs
+ * which may be present or become present in the system.
+ */
+
+static void __init arm_smp_init_cpus(void)
+{
+ unsigned int i, ncores;
+ void __iomem *base;
+
+ set_fixmap_io(FIX_SMP_MEM_BASE, MSM_APCS_IDR & PAGE_MASK);
+ base = (void __iomem *)__fix_to_virt(FIX_SMP_MEM_BASE);
+
+ if (!base)
+ return;
+
+ base += MSM_APCS_IDR & ~PAGE_MASK;
+
+ ncores = (__raw_readl(base)) & 0xF;
+ if (ncores > nr_cpu_ids) {
+ pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
+ ncores, nr_cpu_ids);
+ ncores = nr_cpu_ids;
+ }
+ for (i = 0; i < ncores; i++)
+ set_cpu_possible(i, true);
+}
+
+static int msm8909_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+ pr_debug("Starting secondary CPU %d\n", cpu);
+ return qcom_boot_secondary(cpu, arm_release_secondary);
+}
+
static int msm8660_boot_secondary(unsigned int cpu, struct task_struct *idle)
{
return qcom_boot_secondary(cpu, scss_release_secondary);
@@ -361,3 +465,15 @@
#endif
};
CPU_METHOD_OF_DECLARE(qcom_smp_kpssv2, "qcom,kpss-acc-v2", &qcom_smp_kpssv2_ops);
+
+struct smp_operations msm8909_smp_ops __initdata = {
+ .smp_init_cpus = arm_smp_init_cpus,
+ .smp_prepare_cpus = qcom_smp_prepare_cpus,
+ .smp_secondary_init = qcom_secondary_init,
+ .smp_boot_secondary = msm8909_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+ .cpu_die = qcom_cpu_die,
+#endif
+};
+
+CPU_METHOD_OF_DECLARE(qcom_smp_8909, "qcom,apss-8909", &msm8909_smp_ops);
diff --git a/arch/arm/mach-qcom/platsmp.h b/arch/arm/mach-qcom/platsmp.h
new file mode 100644
index 0000000..a497693
--- /dev/null
+++ b/arch/arm/mach-qcom/platsmp.h
@@ -0,0 +1,13 @@
+/* Copyright (c) 2012-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.
+ */
+
+extern struct smp_operations msm8909_smp_ops;
diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-truly-720p-cmd.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-truly-720p-cmd.dtsi
new file mode 100644
index 0000000..db3abf1
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-truly-720p-cmd.dtsi
@@ -0,0 +1,255 @@
+/* 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_truly_720_cmd: qcom,mdss_dsi_truly_720p_cmd {
+ qcom,mdss-dsi-panel-name = "truly 720p cmd mode dsi panel";
+ qcom,mdss-dsi-panel-type = "dsi_cmd_mode";
+ qcom,mdss-dsi-panel-framerate = <60>;
+ qcom,mdss-dsi-virtual-channel-id = <0>;
+ qcom,mdss-dsi-stream = <0>;
+ qcom,mdss-dsi-panel-width = <720>;
+ qcom,mdss-dsi-panel-height = <1280>;
+ qcom,mdss-dsi-h-front-porch = <100>;
+ qcom,mdss-dsi-h-back-porch = <100>;
+ qcom,mdss-dsi-h-pulse-width = <6>;
+ qcom,mdss-dsi-h-sync-skew = <0>;
+ qcom,mdss-dsi-v-back-porch = <32>;
+ qcom,mdss-dsi-v-front-porch = <32>;
+ qcom,mdss-dsi-v-pulse-width = <2>;
+ 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-underflow-color = <0xff>;
+ qcom,mdss-dsi-border-color = <0>;
+ qcom,mdss-dsi-h-sync-pulse = <0>;
+ qcom,mdss-dsi-traffic-mode = "burst_mode";
+ qcom,mdss-dsi-bllp-eof-power-mode;
+ qcom,mdss-dsi-bllp-power-mode;
+ 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-panel-timings = [87 2c 12 00 40 44 16 1e 17 03
+ 04 00];
+ qcom,mdss-dsi-t-clk-post = <0x04>;
+ qcom,mdss-dsi-t-clk-pre = <0x1b>;
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,mdss-dsi-dma-trigger = "trigger_sw";
+ qcom,mdss-dsi-mdp-trigger = "none";
+ qcom,mdss-dsi-te-pin-select = <1>;
+ qcom,mdss-dsi-te-dcs-command = <1>;
+ qcom,mdss-dsi-te-check-enable;
+ qcom,mdss-dsi-te-using-te-pin;
+ qcom,mdss-dsi-on-command = [29 01 00 00 00 00 06 f0 55 aa 52
+ 08 00
+ 29 01 00 00 00 00 03 b1 78 21
+ 23 01 00 00 00 00 02 b6 0f
+ 29 01 00 00 00 00 03 bc 00 00
+ 29 01 00 00 00 00 06 bd 02 67 20 20 00
+ 29 01 00 00 00 00 0b e7 f2 e6 d8 cc bf b2 a5 99 99 95
+ 29 01 00 00 00 00 0b e8 f2 e6 d8 cc bf b2 a5 99 99 95
+ 29 01 00 00 00 00 06 f0 55 aa 52 08 01
+ 29 01 00 00 00 00 03 bc a0 00
+ 29 01 00 00 00 00 03 bd a0 00
+ 23 01 00 00 00 00 02 ca 01
+ 23 01 00 00 00 00 02 c0 0c
+ 23 01 00 00 00 00 02 be 4e
+ 29 01 00 00 00 00 03 b3 38 38
+ 29 01 00 00 00 00 03 b4 11 11
+ 29 01 00 00 00 00 03 b6 05 05
+ 29 01 00 00 00 00 03 b9 45 45
+ 29 01 00 00 00 00 03 ba 25 25
+ 29 01 00 00 00 00 03 c4 11 11
+ 23 01 00 00 00 00 02 c6 66
+ 29 01 00 00 00 00 06 f0 55 aa 52 08 02
+ 23 01 00 00 00 00 02 ee 00
+ 29 01 00 00 00 00 11 b0 00 37 00 48 00 69 00 8a 00 ab 00
+ cb 00 eb 01 1c
+ 29 01 00 00 00 00 11 b1 01 41 01 7c 01 aa 01 f3 02 2d 02
+ 2e 02 63 02 9d
+ 29 01 00 00 00 00 11 b2 02 c3 02 f6 03 19 03 54 03 85 03
+ b2 03 c1 03 d1
+ 29 01 00 00 00 00 05 b3 03 e0 03 e8
+ 29 01 00 00 00 00 11 bc 00 37 00 48 00 69 00 8a 00 ab 00
+ cb 00 eb 01 1c
+ 29 01 00 00 00 00 11 bd 01 41 01 7c 01 aa 01 f3 02 2d 02
+ 2e 02 63 02 9d
+ 29 01 00 00 00 00 11 be 02 c3 02 f6 03 19 03 54 03 85 03
+ b2 03 c1 03 d1
+ 29 01 00 00 00 00 05 bf 03 e0 03 e8
+ 29 01 00 00 00 00 11 b4 00 d1 00 d7 00 e4 00 f1 00 fe 01
+ 12 01 26 01 48
+ 29 01 00 00 00 00 11 b5 01 64 01 95 01 bd 02 01 02 36 02
+ 38 02 6c 02 a7
+ 29 01 00 00 00 00 11 b6 02 ce 03 04 03 2b 03 5b 03 89 03
+ b2 03 c1 03 d1
+ 29 01 00 00 00 00 05 b7 03 e0 03 e8
+ 29 01 00 00 00 00 11 c0 00 d1 00 d7 00 e4 00 f1 00 fe 01
+ 12 01 26 01 48
+ 29 01 00 00 00 00 11 c1 01 64 01 95 01 bd 02 01 02 36 02
+ 38 02 6c 02 a7
+ 29 01 00 00 00 00 11 c2 02 ce 03 04 03 2b 03 5b 03 89 03
+ b2 03 c1 03 d1
+ 29 01 00 00 00 00 05 c3 03 e0 03 e8
+ 29 01 00 00 00 00 11 b8 00 37 00 45 00 61 00 7d 00 9a 00
+ bb 00 dc 01 0b
+ 29 01 00 00 00 00 11 b9 01 31 01 6e 01 9e 01 ea 02 24 02
+ 25 02 58 02 90
+ 29 01 00 00 00 00 11 ba 02 b4 02 e4 03 04 03 44 03 7f 03
+ b2 03 c1 03 d1
+ 29 01 00 00 00 00 05 bb 03 e0 03 e8
+ 29 01 00 00 00 00 11 c4 00 37 00 45 00 61 00 7d 00 9a 00
+ bb 00 dc 01 0b
+ 29 01 00 00 00 00 11 c5 01 31 01 6e 01 9e 01 ea 02 24 02
+ 25 02 58 02 90
+ 29 01 00 00 00 00 11 c6 02 b4 02 e4 03 04 03 44 03 7f 03
+ b2 03 c1 03 d1
+ 29 01 00 00 00 00 05 c7 03 e0 03 e8
+ 29 01 00 00 00 00 06 f0 55 aa 52 08 06
+ 29 01 00 00 00 00 03 b0 29 2a
+ 29 01 00 00 00 00 03 b1 10 12
+ 29 01 00 00 00 00 03 b2 14 16
+ 29 01 00 00 00 00 03 b3 18 1a
+ 29 01 00 00 00 00 03 b4 02 04
+ 29 01 00 00 00 00 03 b5 34 34
+ 29 01 00 00 00 00 03 b6 34 2e
+ 29 01 00 00 00 00 03 b7 2e 2e
+ 29 01 00 00 00 00 03 b8 34 00
+ 29 01 00 00 00 00 03 b9 34 34
+ 29 01 00 00 00 00 03 ba 34 34
+ 29 01 00 00 00 00 03 bb 01 34
+ 29 01 00 00 00 00 03 bc 2e 2e
+ 29 01 00 00 00 00 03 bd 2e 34
+ 29 01 00 00 00 00 03 be 34 34
+ 29 01 00 00 00 00 03 bf 05 03
+ 29 01 00 00 00 00 03 c0 1b 19
+ 29 01 00 00 00 00 03 c1 17 15
+ 29 01 00 00 00 00 03 c2 13 11
+ 29 01 00 00 00 00 03 c3 2a 29
+ 29 01 00 00 00 00 03 e5 2e 2e
+ 29 01 00 00 00 00 03 c4 29 2a
+ 29 01 00 00 00 00 03 c5 1b 19
+ 29 01 00 00 00 00 03 c6 17 15
+ 29 01 00 00 00 00 03 c7 13 11
+ 29 01 00 00 00 00 03 c8 01 05
+ 29 01 00 00 00 00 03 c9 34 34
+ 29 01 00 00 00 00 03 ca 34 2e
+ 29 01 00 00 00 00 03 cb 2e 2e
+ 29 01 00 00 00 00 03 cc 34 03
+ 29 01 00 00 00 00 03 cd 34 34
+ 29 01 00 00 00 00 03 ce 34 34
+ 29 01 00 00 00 00 03 cf 02 34
+ 29 01 00 00 00 00 03 d0 2e 2e
+ 29 01 00 00 00 00 03 d1 2e 34
+ 29 01 00 00 00 00 03 d2 34 34
+ 29 01 00 00 00 00 03 d3 04 00
+ 29 01 00 00 00 00 03 d4 10 12
+ 29 01 00 00 00 00 03 d5 14 16
+ 29 01 00 00 00 00 03 d6 18 1a
+ 29 01 00 00 00 00 03 d7 2a 29
+ 29 01 00 00 00 00 03 e6 2e 2e
+ 29 01 00 00 00 00 06 d8 00 00 00 54 00
+ 29 01 00 00 00 00 06 d9 00 15 00 00 00
+ 23 01 00 00 00 00 02 e7 00
+ 29 01 00 00 00 00 06 f0 55 aa 52 08 03
+ 29 01 00 00 00 00 03 b1 00 00
+ 29 01 00 00 00 00 03 b0 00 00
+ 29 01 00 00 00 00 06 b2 05 00 00 00 00
+ 29 01 00 00 00 00 06 b3 05 00 00 00 00
+ 29 01 00 00 00 00 06 b4 05 00 00 00 00
+ 29 01 00 00 00 00 06 b5 05 00 17 00 00
+ 29 01 00 00 00 00 06 b6 12 00 19 00 00
+ 29 01 00 00 00 00 06 b7 12 00 19 00 00
+ 29 01 00 00 00 00 06 b8 12 00 19 00 00
+ 29 01 00 00 00 00 06 b9 12 00 19 00 00
+ 29 01 00 00 00 00 06 ba 57 00 00 00 00
+ 29 01 00 00 00 00 06 bb 57 00 00 00 00
+ 29 01 00 00 00 00 06 bc 75 00 1a 00 00
+ 29 01 00 00 00 00 06 bd 53 00 1a 00 00
+ 29 01 00 00 00 00 05 c0 00 34 00 00
+ 29 01 00 00 00 00 05 c1 00 34 00 00
+ 29 01 00 00 00 00 05 c2 00 34 00 00
+ 29 01 00 00 00 00 05 c3 00 34 00 00
+ 23 01 00 00 00 00 02 c4 20
+ 23 01 00 00 00 00 02 c5 00
+ 23 01 00 00 00 00 02 c6 00
+ 23 01 00 00 00 00 02 c7 00
+ 29 01 00 00 00 00 06 f0 55 aa 52 08 05
+ 23 01 00 00 00 00 02 ed 30
+ 29 01 00 00 00 00 03 b0 17 06
+ 23 01 00 00 00 00 02 b8 08
+ 29 01 00 00 00 00 06 bd 03 07 00 03 00
+ 29 01 00 00 00 00 03 b1 17 06
+ 23 01 00 00 00 00 02 b9 00
+ 29 01 00 00 00 00 03 b2 00 00
+ 23 01 00 00 00 00 02 ba 00
+ 29 01 00 00 00 00 03 b3 17 06
+ 23 01 00 00 00 00 02 bb 0a
+ 29 01 00 00 00 00 03 b4 17 06
+ 29 01 00 00 00 00 03 b5 17 06
+ 29 01 00 00 00 00 03 b6 14 03
+ 29 01 00 00 00 00 03 b7 00 00
+ 23 01 00 00 00 00 02 bc 02
+ 23 01 00 00 00 00 02 e5 06
+ 23 01 00 00 00 00 02 e6 06
+ 23 01 00 00 00 00 02 e7 00
+ 23 01 00 00 00 00 02 e8 06
+ 23 01 00 00 00 00 02 e9 06
+ 23 01 00 00 00 00 02 ea 06
+ 23 01 00 00 00 00 02 eb 00
+ 23 01 00 00 00 00 02 ec 00
+ 23 01 00 00 00 00 02 c0 07
+ 23 01 00 00 00 00 02 c1 80
+ 23 01 00 00 00 00 02 c2 a4
+ 23 01 00 00 00 00 02 c3 05
+ 23 01 00 00 00 00 02 c4 00
+ 23 01 00 00 00 00 02 c5 02
+ 23 01 00 00 00 00 02 c6 22
+ 23 01 00 00 00 00 02 c7 03
+ 29 01 00 00 00 00 03 c8 05 30
+ 29 01 00 00 00 00 03 c9 01 31
+ 29 01 00 00 00 00 03 ca 03 21
+ 29 01 00 00 00 00 03 cb 01 20
+ 29 01 00 00 00 00 06 d1 00 05 09 07 10
+ 29 01 00 00 00 00 06 d2 10 05 0e 03 10
+ 29 01 00 00 00 00 06 d3 20 00 48 07 10
+ 29 01 00 00 00 00 06 d4 30 00 43 07 10
+ 23 01 00 00 00 00 02 d0 00
+ 29 01 00 00 00 00 04 cc 00 00 3e
+ 29 01 00 00 00 00 04 cd 00 00 3e
+ 29 01 00 00 00 00 04 ce 00 00 02
+ 29 01 00 00 00 00 04 cf 00 00 02
+ 23 01 00 00 00 00 02 6f 11
+ 23 01 00 00 00 00 02 f3 01
+ 15 01 00 00 00 00 02 51 ff
+ 15 01 00 00 00 00 02 53 2c
+ 15 01 00 00 00 00 02 55 03
+ 15 01 00 00 c8 00 02 35 00
+ 05 01 00 00 78 00 02 11 00
+ 05 01 00 00 0a 00 02 29 00];
+ qcom,mdss-dsi-off-command = [05 01 00 00 14 00 02 28 00
+ 05 01 00 00 78 00 02 10 00];
+ qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+ qcom,mdss-dsi-off-command-state = "dsi_lp_mode";
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-reset-sequence = <1 10>, <0 10>, <1 10>;
+ qcom,mdss-dsi-tx-eot-append;
+ qcom,mdss-dsi-lp11-init;
+ qcom,mdss-dsi-post-init-delay = <1>;
+ qcom,mdss-dsi-wr-mem-start = <0x2c>;
+ qcom,mdss-dsi-wr-mem-continue = <0x3c>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-truly-720p-video.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-truly-720p-video.dtsi
new file mode 100644
index 0000000..80ead08
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-truly-720p-video.dtsi
@@ -0,0 +1,249 @@
+/* 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_truly_720_vid: qcom,mdss_dsi_truly_720p_video {
+ qcom,mdss-dsi-panel-name = "truly 720p video mode dsi panel";
+ qcom,mdss-dsi-panel-type = "dsi_video_mode";
+ qcom,mdss-dsi-panel-framerate = <60>;
+ qcom,mdss-dsi-virtual-channel-id = <0>;
+ qcom,mdss-dsi-stream = <0>;
+ qcom,mdss-dsi-panel-width = <720>;
+ qcom,mdss-dsi-panel-height = <1280>;
+ qcom,mdss-dsi-h-front-porch = <100>;
+ qcom,mdss-dsi-h-back-porch = <100>;
+ qcom,mdss-dsi-h-pulse-width = <6>;
+ qcom,mdss-dsi-h-sync-skew = <0>;
+ qcom,mdss-dsi-v-back-porch = <32>;
+ qcom,mdss-dsi-v-front-porch = <32>;
+ qcom,mdss-dsi-v-pulse-width = <2>;
+ 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-underflow-color = <0xff>;
+ qcom,mdss-dsi-border-color = <0>;
+ qcom,mdss-dsi-h-sync-pulse = <0>;
+ qcom,mdss-dsi-traffic-mode = "burst_mode";
+ qcom,mdss-dsi-bllp-eof-power-mode;
+ qcom,mdss-dsi-bllp-power-mode;
+ 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-panel-timings = [87 2c 12 00 40 44 16 1e 17 03
+ 04 00];
+ qcom,mdss-dsi-t-clk-post = <0x04>;
+ qcom,mdss-dsi-t-clk-pre = <0x1b>;
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,mdss-dsi-dma-trigger = "trigger_sw";
+ qcom,mdss-dsi-mdp-trigger = "none";
+ qcom,mdss-dsi-on-command = [29 01 00 00 00 00 06 f0 55 aa 52
+ 08 00
+ 29 01 00 00 00 00 03 b1 78 21
+ 23 01 00 00 00 00 02 b6 0f
+ 29 01 00 00 00 00 03 bc 00 00
+ 29 01 00 00 00 00 06 bd 02 b0 1e 1e 00
+ 29 01 00 00 00 00 0b e7 f2 e6 d8 cc bf b2 a5 99 99 95
+ 29 01 00 00 00 00 0b e8 f2 e6 d8 cc bf b2 a5 99 99 95
+ 29 01 00 00 00 00 06 f0 55 aa 52 08 01
+ 29 01 00 00 00 00 03 bc a0 00
+ 29 01 00 00 00 00 03 bd a0 00
+ 23 01 00 00 00 00 02 ca 01
+ 23 01 00 00 00 00 02 c0 0c
+ 23 01 00 00 00 00 02 be 4e
+ 29 01 00 00 00 00 03 b3 38 38
+ 29 01 00 00 00 00 03 b4 11 11
+ 29 01 00 00 00 00 03 b6 05 05
+ 29 01 00 00 00 00 03 b9 45 45
+ 29 01 00 00 00 00 03 ba 25 25
+ 29 01 00 00 00 00 03 c4 11 11
+ 23 01 00 00 00 00 02 c6 66
+ 29 01 00 00 00 00 06 f0 55 aa 52 08 02
+ 23 01 00 00 00 00 02 ee 00
+ 29 01 00 00 00 00 11 b0 00 37 00 48 00 69 00 8a 00 ab 00
+ cb 00 eb 01 1c
+ 29 01 00 00 00 00 11 b1 01 41 01 7c 01 aa 01 f3 02 2d 02
+ 2e 02 63 02 9d
+ 29 01 00 00 00 00 11 b2 02 c3 02 f6 03 19 03 54 03 85 03
+ b2 03 c1 03 d1
+ 29 01 00 00 00 00 05 b3 03 e0 03 e8
+ 29 01 00 00 00 00 11 bc 00 37 00 48 00 69 00 8a 00 ab 00
+ cb 00 eb 01 1c
+ 29 01 00 00 00 00 11 bd 01 41 01 7c 01 aa 01 f3 02 2d 02
+ 2e 02 63 02 9d
+ 29 01 00 00 00 00 11 be 02 c3 02 f6 03 19 03 54 03 85 03
+ b2 03 c1 03 d1
+ 29 01 00 00 00 00 05 bf 03 e0 03 e8
+ 29 01 00 00 00 00 11 b4 00 d1 00 d7 00 e4 00 f1 00 fe 01
+ 12 01 26 01 48
+ 29 01 00 00 00 00 11 b5 01 64 01 95 01 bd 02 01 02 36 02
+ 38 02 6c 02 a7
+ 29 01 00 00 00 00 11 b6 02 ce 03 04 03 2b 03 5b 03 89 03
+ b2 03 c1 03 d1
+ 29 01 00 00 00 00 05 b7 03 e0 03 e8
+ 29 01 00 00 00 00 11 c0 00 d1 00 d7 00 e4 00 f1 00 fe 01
+ 12 01 26 01 48
+ 29 01 00 00 00 00 11 c1 01 64 01 95 01 bd 02 01 02 36 02
+ 38 02 6c 02 a7
+ 29 01 00 00 00 00 11 c2 02 ce 03 04 03 2b 03 5b 03 89 03
+ b2 03 c1 03 d1
+ 29 01 00 00 00 00 05 c3 03 e0 03 e8
+ 29 01 00 00 00 00 11 b8 00 37 00 45 00 61 00 7d 00 9a 00
+ bb 00 dc 01 0b
+ 29 01 00 00 00 00 11 b9 01 31 01 6e 01 9e 01 ea 02 24 02
+ 25 02 58 02 90
+ 29 01 00 00 00 00 11 ba 02 b4 02 e4 03 04 03 44 03 7f 03
+ b2 03 c1 03 d1
+ 29 01 00 00 00 00 05 bb 03 e0 03 e8
+ 29 01 00 00 00 00 11 c4 00 37 00 45 00 61 00 7d 00 9a 00
+ bb 00 dc 01 0b
+ 29 01 00 00 00 00 11 c5 01 31 01 6e 01 9e 01 ea 02 24 02
+ 25 02 58 02 90
+ 29 01 00 00 00 00 11 c6 02 b4 02 e4 03 04 03 44 03 7f 03
+ b2 03 c1 03 d1
+ 29 01 00 00 00 00 05 c7 03 e0 03 e8
+ 29 01 00 00 00 00 06 f0 55 aa 52 08 06
+ 29 01 00 00 00 00 03 b0 29 2a
+ 29 01 00 00 00 00 03 b1 10 12
+ 29 01 00 00 00 00 03 b2 14 16
+ 29 01 00 00 00 00 03 b3 18 1a
+ 29 01 00 00 00 00 03 b4 02 04
+ 29 01 00 00 00 00 03 b5 34 34
+ 29 01 00 00 00 00 03 b6 34 2e
+ 29 01 00 00 00 00 03 b7 2e 2e
+ 29 01 00 00 00 00 03 b8 34 00
+ 29 01 00 00 00 00 03 b9 34 34
+ 29 01 00 00 00 00 03 ba 34 34
+ 29 01 00 00 00 00 03 bb 01 34
+ 29 01 00 00 00 00 03 bc 2e 2e
+ 29 01 00 00 00 00 03 bd 2e 34
+ 29 01 00 00 00 00 03 be 34 34
+ 29 01 00 00 00 00 03 bf 05 03
+ 29 01 00 00 00 00 03 c0 1b 19
+ 29 01 00 00 00 00 03 c1 17 15
+ 29 01 00 00 00 00 03 c2 13 11
+ 29 01 00 00 00 00 03 c3 2a 29
+ 29 01 00 00 00 00 03 e5 2e 2e
+ 29 01 00 00 00 00 03 c4 29 2a
+ 29 01 00 00 00 00 03 c5 1b 19
+ 29 01 00 00 00 00 03 c6 17 15
+ 29 01 00 00 00 00 03 c7 13 11
+ 29 01 00 00 00 00 03 c8 01 05
+ 29 01 00 00 00 00 03 c9 34 34
+ 29 01 00 00 00 00 03 ca 34 2e
+ 29 01 00 00 00 00 03 cb 2e 2e
+ 29 01 00 00 00 00 03 cc 34 03
+ 29 01 00 00 00 00 03 cd 34 34
+ 29 01 00 00 00 00 03 ce 34 34
+ 29 01 00 00 00 00 03 cf 02 34
+ 29 01 00 00 00 00 03 d0 2e 2e
+ 29 01 00 00 00 00 03 d1 2e 34
+ 29 01 00 00 00 00 03 d2 34 34
+ 29 01 00 00 00 00 03 d3 04 00
+ 29 01 00 00 00 00 03 d4 10 12
+ 29 01 00 00 00 00 03 d5 14 16
+ 29 01 00 00 00 00 03 d6 18 1a
+ 29 01 00 00 00 00 03 d7 2a 29
+ 29 01 00 00 00 00 03 e6 2e 2e
+ 29 01 00 00 00 00 06 d8 00 00 00 54 00
+ 29 01 00 00 00 00 06 d9 00 15 00 00 00
+ 23 01 00 00 00 00 02 e7 00
+ 29 01 00 00 00 00 06 f0 55 aa 52 08 03
+ 29 01 00 00 00 00 03 b1 00 00
+ 29 01 00 00 00 00 03 b0 00 00
+ 29 01 00 00 00 00 06 b2 05 00 00 00 00
+ 29 01 00 00 00 00 06 b3 05 00 00 00 00
+ 29 01 00 00 00 00 06 b4 05 00 00 00 00
+ 29 01 00 00 00 00 06 b5 05 00 17 00 00
+ 29 01 00 00 00 00 06 b6 12 00 19 00 00
+ 29 01 00 00 00 00 06 b7 12 00 19 00 00
+ 29 01 00 00 00 00 06 b8 12 00 19 00 00
+ 29 01 00 00 00 00 06 b9 12 00 19 00 00
+ 29 01 00 00 00 00 06 ba 57 00 00 00 00
+ 29 01 00 00 00 00 06 bb 57 00 00 00 00
+ 29 01 00 00 00 00 06 bc 75 00 1a 00 00
+ 29 01 00 00 00 00 06 bd 53 00 1a 00 00
+ 29 01 00 00 00 00 05 c0 00 34 00 00
+ 29 01 00 00 00 00 05 c1 00 34 00 00
+ 29 01 00 00 00 00 05 c2 00 34 00 00
+ 29 01 00 00 00 00 05 c3 00 34 00 00
+ 23 01 00 00 00 00 02 c4 20
+ 23 01 00 00 00 00 02 c5 00
+ 23 01 00 00 00 00 02 c6 00
+ 23 01 00 00 00 00 02 c7 00
+ 29 01 00 00 00 00 06 f0 55 aa 52 08 05
+ 23 01 00 00 00 00 02 ed 30
+ 29 01 00 00 00 00 03 b0 17 06
+ 23 01 00 00 00 00 02 b8 08
+ 29 01 00 00 00 00 06 bd 03 07 00 03 00
+ 29 01 00 00 00 00 03 b1 17 06
+ 23 01 00 00 00 00 02 b9 00
+ 29 01 00 00 00 00 03 b2 00 00
+ 23 01 00 00 00 00 02 ba 00
+ 29 01 00 00 00 00 03 b3 17 06
+ 23 01 00 00 00 00 02 bb 0a
+ 29 01 00 00 00 00 03 b4 17 06
+ 29 01 00 00 00 00 03 b5 17 06
+ 29 01 00 00 00 00 03 b6 14 03
+ 29 01 00 00 00 00 03 b7 00 00
+ 23 01 00 00 00 00 02 bc 02
+ 23 01 00 00 00 00 02 e5 06
+ 23 01 00 00 00 00 02 e6 06
+ 23 01 00 00 00 00 02 e7 00
+ 23 01 00 00 00 00 02 e8 06
+ 23 01 00 00 00 00 02 e9 06
+ 23 01 00 00 00 00 02 ea 06
+ 23 01 00 00 00 00 02 eb 00
+ 23 01 00 00 00 00 02 ec 00
+ 23 01 00 00 00 00 02 c0 07
+ 23 01 00 00 00 00 02 c1 80
+ 23 01 00 00 00 00 02 c2 a4
+ 23 01 00 00 00 00 02 c3 05
+ 23 01 00 00 00 00 02 c4 00
+ 23 01 00 00 00 00 02 c5 02
+ 23 01 00 00 00 00 02 c6 22
+ 23 01 00 00 00 00 02 c7 03
+ 29 01 00 00 00 00 03 c8 05 30
+ 29 01 00 00 00 00 03 c9 01 31
+ 29 01 00 00 00 00 03 ca 03 21
+ 29 01 00 00 00 00 03 cb 01 20
+ 29 01 00 00 00 00 06 d1 00 05 09 07 10
+ 29 01 00 00 00 00 06 d2 10 05 0e 03 10
+ 29 01 00 00 00 00 06 d3 20 00 48 07 10
+ 29 01 00 00 00 00 06 d4 30 00 43 07 10
+ 23 01 00 00 00 00 02 d0 00
+ 29 01 00 00 00 00 04 cc 00 00 3e
+ 29 01 00 00 00 00 04 cd 00 00 3e
+ 29 01 00 00 00 00 04 ce 00 00 02
+ 29 01 00 00 00 00 04 cf 00 00 02
+ 23 01 00 00 00 00 02 6f 11
+ 23 01 00 00 00 00 02 f3 01
+ 15 01 00 00 00 00 02 51 ff
+ 15 01 00 00 00 00 02 53 2c
+ 15 01 00 00 00 00 02 55 03
+ 15 01 00 00 c8 00 02 35 00
+ 05 01 00 00 78 00 02 11 00
+ 05 01 00 00 0a 00 02 29 00];
+ qcom,mdss-dsi-off-command = [05 01 00 00 14 00 02 28 00
+ 05 01 00 00 78 00 02 10 00];
+ qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+ qcom,mdss-dsi-off-command-state = "dsi_lp_mode";
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-reset-sequence = <1 10>, <0 10>, <1 10>;
+ qcom,mdss-dsi-tx-eot-append;
+ qcom,mdss-dsi-lp11-init;
+ qcom,mdss-dsi-post-init-delay = <1>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/msm-arm-smmu-8917.dtsi b/arch/arm64/boot/dts/qcom/msm-arm-smmu-8917.dtsi
new file mode 100644
index 0000000..603ba40
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm-arm-smmu-8917.dtsi
@@ -0,0 +1,92 @@
+/*
+ * 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.
+ */
+
+&soc {
+ gfx_iommu: qcom,iommu@1f00000 {
+ status = "ok";
+ compatible = "qcom,qsmmu-v500";
+ reg = <0x1f00000 0x10000>,
+ <0x1ee2000 0x20>;
+ reg-names = "base", "tcu-base";
+ #iommu-cells = <1>;
+ qcom,tz-device-id = "GPU";
+ qcom,skip-init;
+ qcom,enable-static-cb;
+ qcom,dynamic;
+ qcom,use-3-lvl-tables;
+ #global-interrupts = <0>;
+ #size-cells = <1>;
+ #address-cells = <1>;
+ ranges;
+ interrupts = <GIC_SPI 240 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 241 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 242 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 243 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clock_gcc clk_gcc_smmu_cfg_clk>,
+ <&clock_gcc clk_gcc_gfx_tcu_clk>;
+ clock-names = "iface_clk", "core_clk";
+ };
+
+ apps_iommu: qcom,iommu@1e00000 {
+ status = "okay";
+ compatible = "qcom,qsmmu-v500";
+ reg = <0x1e00000 0x40000>,
+ <0x1ee2000 0x20>;
+ reg-names = "base", "tcu-base";
+ #iommu-cells = <2>;
+ qcom,tz-device-id = "APPS";
+ qcom,skip-init;
+ qcom,disable-atos;
+ ranges;
+ qcom,enable-static-cb;
+ qcom,use-3-lvl-tables;
+ #global-interrupts = <0>;
+ #size-cells = <1>;
+ #address-cells = <1>;
+ interrupts = <GIC_SPI 253 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 254 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 255 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clock_gcc clk_gcc_smmu_cfg_clk>,
+ <&clock_gcc clk_gcc_apss_tcu_clk>;
+ clock-names = "iface_clk", "core_clk";
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-mdss-pll.dtsi b/arch/arm64/boot/dts/qcom/msm8917-mdss-pll.dtsi
new file mode 100644
index 0000000..c099044
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-mdss-pll.dtsi
@@ -0,0 +1,18 @@
+/* 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 "msm8937-mdss-pll.dtsi"
+
+&mdss_dsi0_pll {
+ vddio-supply = <&pm8937_l6>;
+};
+/delete-node/ &mdss_dsi1_pll;
diff --git a/arch/arm64/boot/dts/qcom/msm8917-mdss.dtsi b/arch/arm64/boot/dts/qcom/msm8917-mdss.dtsi
new file mode 100644
index 0000000..010b1e9
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-mdss.dtsi
@@ -0,0 +1,96 @@
+/* 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 "msm8937-mdss.dtsi"
+
+&mdss_dsi {
+ vdda-supply = <&pm8937_l2>;
+ vddio-supply = <&pm8937_l6>;
+
+ ranges = <0x1a94000 0x1a94000 0x300
+ 0x1a94400 0x1a94400 0x280
+ 0x1a94b80 0x1a94b80 0x30
+ 0x193e000 0x193e000 0x30>;
+
+ clocks = <&clock_gcc_mdss clk_mdss_mdp_vote_clk>,
+ <&clock_gcc clk_gcc_mdss_ahb_clk>,
+ <&clock_gcc clk_gcc_mdss_axi_clk>,
+ <&clock_gcc_mdss clk_ext_byte0_clk_src>,
+ <&clock_gcc_mdss clk_ext_pclk0_clk_src>;
+ clock-names = "mdp_core_clk", "iface_clk", "bus_clk",
+ "ext_byte0_clk", "ext_pixel0_clk";
+
+ /delete-property/ qcom,mdss-fb-map-sec;
+
+};
+
+&mdss_dsi0 {
+ vdd-supply = <&pm8937_l17>;
+ vddio-supply = <&pm8937_l6>;
+};
+
+/delete-node/ &mdss_dsi1;
+
+&mdss_mdp {
+ qcom,max-bandwidth-low-kbps = <1800000>;
+ qcom,max-bandwidth-high-kbps = <1800000>;
+ qcom,max-bandwidth-per-pipe-kbps = <1000000>;
+
+ qcom,mdss-intf-off = <0x00000000 0x0006B800>;
+ qcom,mdss-pingpong-off = <0x00071000>;
+ qcom,mdss-mixer-intf-off = <0x00045000>;
+ qcom,mdss-mixer-wb-off = <0x00046000>;
+ qcom,mdss-wfd-mode = "dedicated";
+ qcom,mdss-per-pipe-panic-luts = <0x000f>,
+ <0x0>,
+ <0xfffc>,
+ <0x0>;
+
+ /delete-property/ qcom,mdss-highest-bank-bit;
+ /delete-property/ qcom,vbif-settings;
+
+ qcom,regs-dump-mdp = <0x01000 0x01454>,
+ <0x02000 0x02064>,
+ <0x02200 0x02264>,
+ <0x02400 0x02464>,
+ <0x05000 0x05150>,
+ <0x05200 0x05230>,
+ <0x15000 0x15150>,
+ <0x17000 0x17150>,
+ <0x25000 0x25150>,
+ <0x35000 0x35150>,
+ <0x45000 0x452bc>,
+ <0x46000 0x462bc>,
+ <0x55000 0x5522c>,
+ <0x65000 0x652c0>,
+ <0x66000 0x662c0>,
+ <0x6b800 0x6ba68>,
+ <0x71000 0x710d4>;
+
+ qcom,regs-dump-names-mdp = "MDP",
+ "CTL_0", "CTL_1", "CTL_2",
+ "VIG0_SSPP", "VIG0",
+ "RGB0_SSPP", "RGB1_SSPP",
+ "DMA0_SSPP",
+ "CURSOR0_SSPP",
+ "LAYER_0", "LAYER_1",
+ "DSPP_0",
+ "WB_0", "WB_2",
+ "INTF_1",
+ "PP_0";
+};
+
+&mdss_rotator {
+ /delete-property/ qcom,mdss-has-ubwc;
+};
+
+/delete-node/ &mdss_fb2;
diff --git a/arch/arm64/boot/dts/qcom/msm8917-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8917-mtp.dtsi
index a558c8e..800ea1c 100644
--- a/arch/arm64/boot/dts/qcom/msm8917-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8917-mtp.dtsi
@@ -11,6 +11,8 @@
* GNU General Public License for more details.
*/
+#include "msm8917-pinctrl.dtsi"
+
&blsp1_uart2 {
status = "ok";
pinctrl-names = "default";
@@ -65,3 +67,36 @@
status = "ok";
};
+
+#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>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-pmi8950-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8917-pmi8950-mtp.dtsi
index a194cea..4da1384 100644
--- a/arch/arm64/boot/dts/qcom/msm8917-pmi8950-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8917-pmi8950-mtp.dtsi
@@ -74,3 +74,8 @@
&ibb_regulator {
qcom,qpnp-ibb-discharge-resistor = <32>;
};
+
+&mdss_dsi0 {
+ lab-supply = <&lab_regulator>;
+ ibb-supply = <&ibb_regulator>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-thermal.dtsi b/arch/arm64/boot/dts/qcom/msm8917-thermal.dtsi
new file mode 100644
index 0000000..98ad44c
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-thermal.dtsi
@@ -0,0 +1,155 @@
+/* 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 <dt-bindings/thermal/thermal.h>
+
+&thermal_zones {
+ aoss0-usr {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "user_space";
+ thermal-sensors = <&tsens0 0>;
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ mdm-core-usr {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "user_space";
+ thermal-sensors = <&tsens0 1>;
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ mdss-usr {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "user_space";
+ thermal-sensors = <&tsens0 2>;
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ camera-usr {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "user_space";
+ thermal-sensors = <&tsens0 3>;
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ cpuss-0-usr {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens0 4>;
+ thermal-governor = "user_space";
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ apc1-cpu1-usr {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens0 5>;
+ thermal-governor = "user_space";
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ apc1-cpu2-usr {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens0 6>;
+ thermal-governor = "user_space";
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ apc1-cpu3-usr {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens0 7>;
+ thermal-governor = "user_space";
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ apc1-cpu4-usr {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens0 8>;
+ thermal-governor = "user_space";
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ gpu0-usr {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens0 9>;
+ thermal-governor = "user_space";
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917.dtsi b/arch/arm64/boot/dts/qcom/msm8917.dtsi
index 6f0da53..a85d6d2 100644
--- a/arch/arm64/boot/dts/qcom/msm8917.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8917.dtsi
@@ -162,6 +162,9 @@
#include "msm8917-ion.dtsi"
#include "msm8917-smp2p.dtsi"
#include "msm8917-bus.dtsi"
+#include "msm8917-mdss.dtsi"
+#include "msm8917-mdss-pll.dtsi"
+#include "msm-arm-smmu-8917.dtsi"
&soc {
#address-cells = <1>;
@@ -211,6 +214,20 @@
qcom,pipe-attr-ee;
};
+ thermal_zones: thermal-zones {};
+
+ tsens0: tsens@4a8000 {
+ compatible = "qcom,msm8937-tsens";
+ reg = <0x4a8000 0x1000>,
+ <0x4a9000 0x1000>,
+ <0xa4000 0x1000>;
+ reg-names = "tsens_srot_physical",
+ "tsens_tm_physical", "tsens_eeprom_physical";
+ interrupts = <0 184 0>;
+ interrupt-names = "tsens-upper-lower";
+ #thermal-sensor-cells = <1>;
+ };
+
timer@b120000 {
#address-cells = <1>;
#size-cells = <1>;
@@ -427,6 +444,14 @@
#clock-cells = <1>;
};
+ clock_gcc_mdss: qcom,gcc-mdss@1800000 {
+ compatible = "qcom,gcc-mdss-8917";
+ clocks = <&mdss_dsi0_pll clk_dsi_pll0_pixel_clk_src>,
+ <&mdss_dsi0_pll clk_dsi_pll0_byte_clk_src>;
+ clock-names = "pclk0_src", "byte0_src";
+ #clock-cells = <1>;
+ };
+
clock_cpu: qcom,cpu-clock-8939@b111050 {
compatible = "qcom,cpu-clock-8917";
reg = <0xb011050 0x8>,
@@ -1223,6 +1248,7 @@
#include "msm8917-regulator.dtsi"
#include "pm8937.dtsi"
#include "msm-gdsc-8916.dtsi"
+#include "msm8917-thermal.dtsi"
&gdsc_venus {
clock-names = "bus_clk", "core_clk";
diff --git a/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm439.dtsi b/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm439.dtsi
index 477802a..a6918b9 100644
--- a/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm439.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm439.dtsi
@@ -161,4 +161,10 @@
<0 0 0>;
qcom,cpr-enable;
};
+
+ qcom,cpu-clock-8939@b111050 {
+ vdd-c0-supply = <&apc_vreg_corner>;
+ vdd-c1-supply = <&apc_vreg_corner>;
+ vdd-cci-supply = <&apc_vreg_corner>;
+ };
};
diff --git a/arch/arm64/boot/dts/qcom/msm8937-mdss-panels.dtsi b/arch/arm64/boot/dts/qcom/msm8937-mdss-panels.dtsi
index ab2a365..8d18bdd 100644
--- a/arch/arm64/boot/dts/qcom/msm8937-mdss-panels.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937-mdss-panels.dtsi
@@ -14,6 +14,8 @@
#include "dsi-panel-sim-cmd.dtsi"
#include "dsi-panel-truly-1080p-video.dtsi"
#include "dsi-panel-truly-1080p-cmd.dtsi"
+#include "dsi-panel-truly-720p-video.dtsi"
+#include "dsi-panel-truly-720p-cmd.dtsi"
#include "dsi-panel-r69006-1080p-cmd.dtsi"
#include "dsi-panel-r69006-1080p-video.dtsi"
#include "dsi-adv7533-1080p.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/msm8937.dtsi b/arch/arm64/boot/dts/qcom/msm8937.dtsi
index 09890bb..3518473 100644
--- a/arch/arm64/boot/dts/qcom/msm8937.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937.dtsi
@@ -124,6 +124,11 @@
reg = <0x0 0x90000000 0x0 0x1400000>;
};
+ dump_mem: mem_dump_region {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0 0x2400000>;
+ };
};
aliases {
@@ -305,6 +310,57 @@
thermal_zones: thermal-zones {};
+ mem_dump {
+ compatible = "qcom,mem-dump";
+ memory-region = <&dump_mem>;
+
+ rpmh_dump {
+ qcom,dump-size = <0x2000000>;
+ qcom,dump-id = <0xec>;
+ };
+
+ fcm_dump {
+ qcom,dump-size = <0x8400>;
+ qcom,dump-id = <0xee>;
+ };
+
+ rpm_sw_dump {
+ qcom,dump-size = <0x28000>;
+ qcom,dump-id = <0xea>;
+ };
+
+ pmic_dump {
+ qcom,dump-size = <0x10000>;
+ qcom,dump-id = <0xe4>;
+ };
+
+ vsense_dump {
+ qcom,dump-size = <0x1000>;
+ qcom,dump-id = <0xe9>;
+ };
+
+ tmc_etf_dump {
+ qcom,dump-size = <0x10000>;
+ qcom,dump-id = <0xf0>;
+ };
+
+ tmc_etr_reg_dump {
+ qcom,dump-size = <0x1000>;
+ qcom,dump-id = <0x100>;
+ };
+
+ tmc_etf_reg_dump {
+ qcom,dump-size = <0x1000>;
+ qcom,dump-id = <0x101>;
+ };
+
+ misc_data_dump {
+ qcom,dump-size = <0x1000>;
+ qcom,dump-id = <0xe8>;
+ };
+
+ };
+
tsens0: tsens@4a8000 {
compatible = "qcom,msm8937-tsens";
reg = <0x4a8000 0x1000>,
diff --git a/arch/arm64/boot/dts/qcom/msm8953-camera-sensor-cdp.dtsi b/arch/arm64/boot/dts/qcom/msm8953-camera-sensor-cdp.dtsi
index a46bce3..db9fb13 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-camera-sensor-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-camera-sensor-cdp.dtsi
@@ -190,7 +190,7 @@
qcom,clock-rates = <19200000 0>;
};
- qcom,camera@0 {
+ camera0: qcom,camera@0 {
cell-index = <0>;
compatible = "qcom,camera";
reg = <0x0>;
@@ -203,10 +203,13 @@
cam_vio-supply = <&pm8953_l6>;
cam_vdig-supply = <&pm8953_l2>;
cam_vaf-supply = <&pm8953_l17>;
- qcom,cam-vreg-name = "cam_vio", "cam_vdig", "cam_vaf";
- qcom,cam-vreg-min-voltage = <0 1100000 2850000>;
- qcom,cam-vreg-max-voltage = <0 1100000 2850000>;
- qcom,cam-vreg-op-mode = <0 105000 100000>;
+ cam_vana-supply = <&pm8953_l22>;
+ cam_v_custom1-supply = <&pm8953_l23>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vdig", "cam_vaf",
+ "cam_vana", "cam_v_custom1";
+ qcom,cam-vreg-min-voltage = <0 1100000 2850000 2800000 1220000>;
+ qcom,cam-vreg-max-voltage = <0 1100000 2850000 2800000 1220000>;
+ qcom,cam-vreg-op-mode = <0 105000 100000 80000 105000>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk0_default
&cam_sensor_rear_default
diff --git a/arch/arm64/boot/dts/qcom/msm8953-camera-sensor-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8953-camera-sensor-mtp.dtsi
index a7688f0..db9fb13 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-camera-sensor-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-camera-sensor-mtp.dtsi
@@ -190,7 +190,7 @@
qcom,clock-rates = <19200000 0>;
};
- qcom,camera@0 {
+ camera0: qcom,camera@0 {
cell-index = <0>;
compatible = "qcom,camera";
reg = <0x0>;
@@ -204,11 +204,12 @@
cam_vdig-supply = <&pm8953_l2>;
cam_vaf-supply = <&pm8953_l17>;
cam_vana-supply = <&pm8953_l22>;
+ cam_v_custom1-supply = <&pm8953_l23>;
qcom,cam-vreg-name = "cam_vio", "cam_vdig", "cam_vaf",
- "cam_vana";
- qcom,cam-vreg-min-voltage = <0 1100000 2850000 2800000>;
- qcom,cam-vreg-max-voltage = <0 1100000 2850000 2800000>;
- qcom,cam-vreg-op-mode = <0 105000 100000 80000>;
+ "cam_vana", "cam_v_custom1";
+ qcom,cam-vreg-min-voltage = <0 1100000 2850000 2800000 1220000>;
+ qcom,cam-vreg-max-voltage = <0 1100000 2850000 2800000 1220000>;
+ qcom,cam-vreg-op-mode = <0 105000 100000 80000 105000>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk0_default
&cam_sensor_rear_default
diff --git a/arch/arm64/boot/dts/qcom/msm8953-cdp.dts b/arch/arm64/boot/dts/qcom/msm8953-cdp.dts
index 6105b52..34c5f8f 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-cdp.dts
+++ b/arch/arm64/boot/dts/qcom/msm8953-cdp.dts
@@ -17,7 +17,6 @@
#include "pmi8950.dtsi"
#include "msm8953-cdp.dtsi"
#include "msm8953-pmi8950.dtsi"
-#include "msm8953-camera-sensor-cdp.dtsi"
/ {
model = "Qualcomm Technologies, Inc. MSM8953 + PMI8950 CDP";
diff --git a/arch/arm64/boot/dts/qcom/msm8953-cdp.dtsi b/arch/arm64/boot/dts/qcom/msm8953-cdp.dtsi
index 5680409..8782325 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-cdp.dtsi
@@ -14,6 +14,7 @@
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/clock/msm-clocks-8953.h>
#include "msm8953-audio-cdp.dtsi"
+#include "msm8953-camera-sensor-cdp.dtsi"
&blsp1_uart0 {
status = "ok";
diff --git a/arch/arm64/boot/dts/qcom/msm8953-ext-codec-mtp.dts b/arch/arm64/boot/dts/qcom/msm8953-ext-codec-mtp.dts
index ee22633..e3a5b4a 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-ext-codec-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/msm8953-ext-codec-mtp.dts
@@ -17,7 +17,6 @@
#include "pmi8950.dtsi"
#include "msm8953-mtp.dtsi"
#include "msm8953-pmi8950.dtsi"
-#include "msm8953-camera-sensor-mtp.dtsi"
/ {
model = "Qualcomm Technologies, Inc. MSM8953 + PMI8950 Ext Codec MTP";
diff --git a/arch/arm64/boot/dts/qcom/msm8953-mtp.dts b/arch/arm64/boot/dts/qcom/msm8953-mtp.dts
index 82f6315..97c6db3 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/msm8953-mtp.dts
@@ -17,7 +17,6 @@
#include "pmi8950.dtsi"
#include "msm8953-mtp.dtsi"
#include "msm8953-pmi8950.dtsi"
-#include "msm8953-camera-sensor-mtp.dtsi"
/ {
model = "Qualcomm Technologies, Inc. MSM8953 + PMI8950 MTP";
diff --git a/arch/arm64/boot/dts/qcom/msm8953-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8953-mtp.dtsi
index 93565cf..a3bd5e9 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-mtp.dtsi
@@ -13,6 +13,7 @@
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/clock/msm-clocks-8953.h>
+#include "msm8953-camera-sensor-mtp.dtsi"
&blsp1_uart0 {
status = "ok";
diff --git a/arch/arm64/boot/dts/qcom/msm8953-pm.dtsi b/arch/arm64/boot/dts/qcom/msm8953-pm.dtsi
index da4f4df..b40b668 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-pm.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-pm.dtsi
@@ -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
@@ -144,6 +144,7 @@
#size-cells = <0>;
qcom,psci-mode-shift = <0>;
qcom,psci-mode-mask = <0xf>;
+ qcom,use-prediction;
qcom,cpu = <&CPU0 &CPU1 &CPU2 &CPU3>;
qcom,pm-cpu-level@0 {
@@ -235,6 +236,7 @@
#size-cells = <0>;
qcom,psci-mode-shift = <0>;
qcom,psci-mode-mask = <0xf>;
+ qcom,use-prediction;
qcom,cpu = <&CPU4 &CPU5 &CPU6 &CPU7>;
qcom,pm-cpu-level@0 {
diff --git a/arch/arm64/boot/dts/qcom/msm8953-pmi632-cdp-s2.dts b/arch/arm64/boot/dts/qcom/msm8953-pmi632-cdp-s2.dts
index 4639f02..78ff97f 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-pmi632-cdp-s2.dts
+++ b/arch/arm64/boot/dts/qcom/msm8953-pmi632-cdp-s2.dts
@@ -16,7 +16,6 @@
#include "msm8953.dtsi"
#include "sdm450-pmi632-cdp-s2.dtsi"
#include "sdm450-pmi632.dtsi"
-#include "sdm632-camera-sensor-cdp.dtsi"
/ {
model = "Qualcomm Technologies, Inc. msm8953 + PMI632 CDP S2";
diff --git a/arch/arm64/boot/dts/qcom/qcs605.dtsi b/arch/arm64/boot/dts/qcom/qcs605.dtsi
index 5adbbb8..1e1d82c 100644
--- a/arch/arm64/boot/dts/qcom/qcs605.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs605.dtsi
@@ -54,6 +54,18 @@
reg = <0 0x91c15000 0 0x2000>;
};
+&adsp_mem {
+ size = <0 0x800000>;
+};
+
+&secure_display_memory {
+ status = "disabled";
+};
+
+&sp_mem {
+ status = "disabled";
+};
+
&soc {
qcom,rmnet-ipa {
status = "disabled";
diff --git a/arch/arm64/boot/dts/qcom/sdm439-pm8953.dtsi b/arch/arm64/boot/dts/qcom/sdm439-pm8953.dtsi
index 289d5bf..87e2a28 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-pm8953.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439-pm8953.dtsi
@@ -82,6 +82,11 @@
/delete-property/ vdd_sr2_pll-supply;
/delete-property/ vdd_hf_dig-supply;
/delete-property/ vdd_hf_pll-supply;
+ vdd_dig-supply = <&pm8953_s2_level>;
+ vdd_sr2_dig-supply = <&pm8953_s2_level_ao>;
+ vdd_sr2_pll-supply = <&pm8953_l7_ao>;
+ vdd_hf_dig-supply = <&pm8953_s2_level_ao>;
+ vdd_hf_pll-supply = <&pm8953_l7_ao>;
};
qcom,cpu-clock-8939@b111050 {
diff --git a/arch/arm64/boot/dts/qcom/sdm450-cdp.dts b/arch/arm64/boot/dts/qcom/sdm450-cdp.dts
index 0458650..c55622a 100644
--- a/arch/arm64/boot/dts/qcom/sdm450-cdp.dts
+++ b/arch/arm64/boot/dts/qcom/sdm450-cdp.dts
@@ -17,7 +17,6 @@
#include "pmi8950.dtsi"
#include "msm8953-cdp.dtsi"
#include "msm8953-pmi8950.dtsi"
-#include "msm8953-camera-sensor-cdp.dtsi"
/ {
model = "Qualcomm Technologies, Inc. SDM450 + PMI8950 CDP";
diff --git a/arch/arm64/boot/dts/qcom/sdm450-mtp.dts b/arch/arm64/boot/dts/qcom/sdm450-mtp.dts
index f097895..5744390 100644
--- a/arch/arm64/boot/dts/qcom/sdm450-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/sdm450-mtp.dts
@@ -17,7 +17,6 @@
#include "pmi8950.dtsi"
#include "msm8953-mtp.dtsi"
#include "msm8953-pmi8950.dtsi"
-#include "msm8953-camera-sensor-mtp.dtsi"
/ {
model = "Qualcomm Technologies, Inc. SDM450 + PMI8950 MTP";
diff --git a/arch/arm64/boot/dts/qcom/sdm450-pmi632-cdp-s2.dts b/arch/arm64/boot/dts/qcom/sdm450-pmi632-cdp-s2.dts
index 004186b6be..692da7f 100644
--- a/arch/arm64/boot/dts/qcom/sdm450-pmi632-cdp-s2.dts
+++ b/arch/arm64/boot/dts/qcom/sdm450-pmi632-cdp-s2.dts
@@ -16,7 +16,6 @@
#include "sdm450.dtsi"
#include "sdm450-pmi632-cdp-s2.dtsi"
#include "sdm450-pmi632.dtsi"
-#include "sdm632-camera-sensor-cdp.dtsi"
/ {
model = "Qualcomm Technologies, Inc. SDM450 + PMI632 CDP S2";
@@ -25,3 +24,16 @@
qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
};
+&pm8953_vadc {
+ pinctrl-0 = <&pa_therm1_default>;
+ /delete-node/ chan@13;
+};
+
+&pm8953_mpps {
+ /delete-node/ case_therm;
+};
+
+&thermal_zones {
+ /delete-node/ case-therm-adc;
+ /delete-node/ case-therm-step;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm450-pmi632-cdp-s2.dtsi b/arch/arm64/boot/dts/qcom/sdm450-pmi632-cdp-s2.dtsi
index d8a0e9d..ae8e473 100644
--- a/arch/arm64/boot/dts/qcom/sdm450-pmi632-cdp-s2.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm450-pmi632-cdp-s2.dtsi
@@ -13,6 +13,14 @@
#include "msm8953-cdp.dtsi"
+&eeprom0 {
+ cam_vdig-supply = <&pm8953_l23>;
+};
+
+&camera0 {
+ cam_vdig-supply = <&pm8953_l23>;
+};
+
&mdss_dsi0 {
qcom,dsi-pref-prim-pan = <&dsi_hx8399c_truly_vid>;
pinctrl-names = "mdss_default", "mdss_sleep";
diff --git a/arch/arm64/boot/dts/qcom/sdm450-pmi632-mtp-s3.dts b/arch/arm64/boot/dts/qcom/sdm450-pmi632-mtp-s3.dts
index 1a2309f..02bf751 100644
--- a/arch/arm64/boot/dts/qcom/sdm450-pmi632-mtp-s3.dts
+++ b/arch/arm64/boot/dts/qcom/sdm450-pmi632-mtp-s3.dts
@@ -16,7 +16,6 @@
#include "sdm450.dtsi"
#include "sdm450-pmi632-mtp-s3.dtsi"
#include "sdm450-pmi632.dtsi"
-#include "sdm632-camera-sensor-mtp.dtsi"
/ {
model = "Qualcomm Technologies, Inc. SDM450 + PMI632 MTP S3";
@@ -25,3 +24,16 @@
qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
};
+&pm8953_vadc {
+ pinctrl-0 = <&pa_therm1_default>;
+ /delete-node/ chan@13;
+};
+
+&pm8953_mpps {
+ /delete-node/ case_therm;
+};
+
+&thermal_zones {
+ /delete-node/ case-therm-adc;
+ /delete-node/ case-therm-step;
+};
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 129d507..64d9e64 100644
--- a/arch/arm64/boot/dts/qcom/sdm450-pmi632-mtp-s3.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm450-pmi632-mtp-s3.dtsi
@@ -13,6 +13,14 @@
#include "msm8953-mtp.dtsi"
+&eeprom0 {
+ cam_vdig-supply = <&pm8953_l23>;
+};
+
+&camera0 {
+ cam_vdig-supply = <&pm8953_l23>;
+};
+
&mdss_dsi0 {
qcom,dsi-pref-prim-pan = <&dsi_hx8399c_truly_vid>;
pinctrl-names = "mdss_default", "mdss_sleep";
diff --git a/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dts b/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dts
index 1dc8874..b0cb955 100644
--- a/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dts
+++ b/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dts
@@ -16,7 +16,6 @@
#include "sdm450.dtsi"
#include "sdm450-qrd-sku4.dtsi"
#include "sdm450-pmi632.dtsi"
-#include "msm8953-camera-sensor-qrd.dtsi"
/ {
model = "Qualcomm Technologies, Inc. SDM450 + PMI632 QRD SKU4";
@@ -30,3 +29,17 @@
qcom,scale-function = <22>;
};
};
+
+&pm8953_vadc {
+ pinctrl-0 = <&pa_therm1_default>;
+ /delete-node/ chan@13;
+};
+
+&pm8953_mpps {
+ /delete-node/ case_therm;
+};
+
+&thermal_zones {
+ /delete-node/ case-therm-adc;
+ /delete-node/ case-therm-step;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dtsi b/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dtsi
index 4a63f9e..bdefdc9 100644
--- a/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dtsi
@@ -13,6 +13,7 @@
#include "msm8953-qrd.dtsi"
#include "msm8953-mdss-panels.dtsi"
+#include "msm8953-camera-sensor-qrd.dtsi"
&qusb_phy {
qcom,qusb-phy-init-seq = <0x78 0x80
diff --git a/arch/arm64/boot/dts/qcom/sdm450.dtsi b/arch/arm64/boot/dts/qcom/sdm450.dtsi
index 38eacd1..1d2abd7c 100644
--- a/arch/arm64/boot/dts/qcom/sdm450.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm450.dtsi
@@ -128,6 +128,7 @@
qcom,gpu-freq = <19200000>;
qcom,bus-freq = <0>;
qcom,bus-min = <0>;
+ qcom,bus-max = <0>;
};
};
};
diff --git a/arch/arm64/boot/dts/qcom/sdm632-camera-sensor-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdm632-camera-sensor-cdp.dtsi
deleted file mode 100644
index e9295ad..0000000
--- a/arch/arm64/boot/dts/qcom/sdm632-camera-sensor-cdp.dtsi
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * 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 = <&pm8953_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 = <1>;
- cam_vaf-supply = <&pm8953_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_vio-supply = <&pm8953_l6>;
- cam_vdig-supply = <&pm8953_l23>;
- cam_vaf-supply = <&pm8953_l17>;
- qcom,cam-vreg-name = "cam_vio", "cam_vdig", "cam_vaf";
- qcom,cam-vreg-min-voltage = <0 1100000 2850000>;
- qcom,cam-vreg-max-voltage = <0 1100000 2850000>;
- qcom,cam-vreg-op-mode = <0 105000 100000>;
- pinctrl-names = "cam_default", "cam_suspend";
- pinctrl-0 = <&cam_sensor_mclk0_default
- &cam_sensor_rear_default
- &cam_sensor_rear_vana>;
- pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep
- &cam_sensor_rear_vana_sleep>;
- gpios = <&tlmm 26 0>,
- <&tlmm 40 0>,
- <&tlmm 39 0>,
- <&tlmm 134 0>;
- qcom,gpio-reset = <1>;
- qcom,gpio-standby = <2>;
- qcom,gpio-vana = <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_VANA";
- 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 = <&pm8953_l23>;
- 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_mclk1_default
- &cam_sensor_front1_default>;
- pinctrl-1 = <&cam_sensor_mclk1_sleep &cam_sensor_front1_sleep>;
- gpios = <&tlmm 27 0>,
- <&tlmm 129 0>,
- <&tlmm 130 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_mclk1_clk_src>,
- <&clock_gcc clk_gcc_camss_mclk1_clk>;
- clock-names = "cam_src_clk", "cam_clk";
- 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_l23>;
- 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 = <200000 0 80000 100000>;
- pinctrl-names = "cam_default", "cam_suspend";
- pinctrl-0 = <&cam_sensor_mclk2_default
- &cam_sensor_front_default>;
- pinctrl-1 = <&cam_sensor_mclk2_sleep
- &cam_sensor_front_sleep>;
- gpios = <&tlmm 28 0>,
- <&tlmm 131 0>,
- <&tlmm 132 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";
- 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";
- 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_vio-supply = <&pm8953_l6>;
- cam_vdig-supply = <&pm8953_l23>;
- cam_vaf-supply = <&pm8953_l17>;
- qcom,cam-vreg-name = "cam_vio", "cam_vdig", "cam_vaf";
- qcom,cam-vreg-min-voltage = <0 1100000 2850000>;
- qcom,cam-vreg-max-voltage = <0 1100000 2850000>;
- qcom,cam-vreg-op-mode = <0 105000 100000>;
- pinctrl-names = "cam_default", "cam_suspend";
- pinctrl-0 = <&cam_sensor_mclk0_default
- &cam_sensor_rear_default
- &cam_sensor_rear_vana>;
- pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep
- &cam_sensor_rear_vana_sleep>;
- gpios = <&tlmm 26 0>,
- <&tlmm 40 0>,
- <&tlmm 39 0>,
- <&tlmm 134 0>;
- qcom,gpio-reset = <1>;
- qcom,gpio-standby = <2>;
- qcom,gpio-vana = <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_VANA";
- 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>;
- qcom,eeprom-src = <&eeprom2>;
- qcom,actuator-src = <&actuator1>;
- cam_vdig-supply = <&pm8953_l23>;
- 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 = <200000 0 80000 100000>;
- pinctrl-names = "cam_default", "cam_suspend";
- pinctrl-0 = <&cam_sensor_mclk2_default
- &cam_sensor_front_default>;
- pinctrl-1 = <&cam_sensor_mclk2_sleep
- &cam_sensor_front_sleep>;
- gpios = <&tlmm 28 0>,
- <&tlmm 131 0>,
- <&tlmm 132 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>;
- 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>;
- };
-
- qcom,camera@2 {
- cell-index = <2>;
- compatible = "qcom,camera";
- reg = <0x02>;
- qcom,csiphy-sd-index = <2>;
- qcom,csid-sd-index = <2>;
- qcom,mount-angle = <90>;
- qcom,eeprom-src = <&eeprom1>;
- qcom,actuator-src = <&actuator1>;
- cam_vdig-supply = <&pm8953_l23>;
- cam_vio-supply = <&pm8953_l6>;
- cam_vana-supply = <&pm8953_l22>;
- cam_vaf-supply = <&pm8953_l17>;
- qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
- "cam_vaf";
- qcom,cam-vreg-min-voltage = <1175000 0 2800000 2850000>;
- qcom,cam-vreg-max-voltage = <1175000 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_mclk1_default
- &cam_sensor_front1_default>;
- pinctrl-1 = <&cam_sensor_mclk1_sleep
- &cam_sensor_front1_sleep>;
- gpios = <&tlmm 27 0>,
- <&tlmm 129 0>,
- <&tlmm 130 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 = <1>;
- status = "ok";
- 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>;
- };
-};
diff --git a/arch/arm64/boot/dts/qcom/sdm632-camera-sensor-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm632-camera-sensor-mtp.dtsi
deleted file mode 100644
index 07b3811..0000000
--- a/arch/arm64/boot/dts/qcom/sdm632-camera-sensor-mtp.dtsi
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
- * 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 = <&pm8953_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 = <1>;
- cam_vaf-supply = <&pm8953_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_vio-supply = <&pm8953_l6>;
- cam_vdig-supply = <&pm8953_l23>;
- cam_vaf-supply = <&pm8953_l17>;
- qcom,cam-vreg-name = "cam_vio", "cam_vdig", "cam_vaf";
- qcom,cam-vreg-min-voltage = <0 1100000 2850000>;
- qcom,cam-vreg-max-voltage = <0 1100000 2850000>;
- qcom,cam-vreg-op-mode = <0 105000 100000>;
- pinctrl-names = "cam_default", "cam_suspend";
- pinctrl-0 = <&cam_sensor_mclk0_default
- &cam_sensor_rear_default
- &cam_sensor_rear_vana>;
- pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep
- &cam_sensor_rear_vana_sleep>;
- gpios = <&tlmm 26 0>,
- <&tlmm 40 0>,
- <&tlmm 39 0>,
- <&tlmm 134 0>;
- qcom,gpio-reset = <1>;
- qcom,gpio-standby = <2>;
- qcom,gpio-vana = <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_VANA";
- 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 = <&pm8953_l23>;
- 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_mclk1_default
- &cam_sensor_front1_default>;
- pinctrl-1 = <&cam_sensor_mclk1_sleep &cam_sensor_front1_sleep>;
- gpios = <&tlmm 27 0>,
- <&tlmm 129 0>,
- <&tlmm 130 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_mclk1_clk_src>,
- <&clock_gcc clk_gcc_camss_mclk1_clk>;
- clock-names = "cam_src_clk", "cam_clk";
- 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_l23>;
- 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 = <200000 0 80000 100000>;
- pinctrl-names = "cam_default", "cam_suspend";
- pinctrl-0 = <&cam_sensor_mclk2_default
- &cam_sensor_front_default>;
- pinctrl-1 = <&cam_sensor_mclk2_sleep
- &cam_sensor_front_sleep>;
- gpios = <&tlmm 28 0>,
- <&tlmm 131 0>,
- <&tlmm 132 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";
- 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";
- 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_vio-supply = <&pm8953_l6>;
- cam_vdig-supply = <&pm8953_l23>;
- cam_vaf-supply = <&pm8953_l17>;
- cam_vana-supply = <&pm8953_l22>;
- qcom,cam-vreg-name = "cam_vio", "cam_vdig", "cam_vaf",
- "cam_vana";
- qcom,cam-vreg-min-voltage = <0 1100000 2850000 2800000>;
- qcom,cam-vreg-max-voltage = <0 1100000 2850000 2800000>;
- qcom,cam-vreg-op-mode = <0 105000 100000 80000>;
- pinctrl-names = "cam_default", "cam_suspend";
- pinctrl-0 = <&cam_sensor_mclk0_default
- &cam_sensor_rear_default
- &cam_sensor_rear_vana>;
- pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep
- &cam_sensor_rear_vana_sleep>;
- gpios = <&tlmm 26 0>,
- <&tlmm 40 0>,
- <&tlmm 39 0>,
- <&tlmm 134 0>;
- qcom,gpio-reset = <1>;
- qcom,gpio-standby = <2>;
- qcom,gpio-vana = <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_VANA";
- 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>;
- qcom,eeprom-src = <&eeprom2>;
- qcom,actuator-src = <&actuator1>;
- cam_vdig-supply = <&pm8953_l23>;
- 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 = <200000 0 80000 100000>;
- pinctrl-names = "cam_default", "cam_suspend";
- pinctrl-0 = <&cam_sensor_mclk2_default
- &cam_sensor_front_default>;
- pinctrl-1 = <&cam_sensor_mclk2_sleep
- &cam_sensor_front_sleep>;
- gpios = <&tlmm 28 0>,
- <&tlmm 131 0>,
- <&tlmm 132 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>;
- 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>;
- };
-
- qcom,camera@2 {
- cell-index = <2>;
- compatible = "qcom,camera";
- reg = <0x02>;
- qcom,csiphy-sd-index = <2>;
- qcom,csid-sd-index = <2>;
- qcom,mount-angle = <90>;
- qcom,eeprom-src = <&eeprom1>;
- qcom,actuator-src = <&actuator1>;
- cam_vdig-supply = <&pm8953_l23>;
- cam_vio-supply = <&pm8953_l6>;
- cam_vana-supply = <&pm8953_l22>;
- cam_vaf-supply = <&pm8953_l17>;
- qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
- "cam_vaf";
- qcom,cam-vreg-min-voltage = <1175000 0 2800000 2850000>;
- qcom,cam-vreg-max-voltage = <1175000 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_mclk1_default
- &cam_sensor_front1_default>;
- pinctrl-1 = <&cam_sensor_mclk1_sleep
- &cam_sensor_front1_sleep>;
- gpios = <&tlmm 27 0>,
- <&tlmm 129 0>,
- <&tlmm 130 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 = <1>;
- status = "ok";
- 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>;
- };
-};
diff --git a/arch/arm64/boot/dts/qcom/sdm632-cdp-s2.dts b/arch/arm64/boot/dts/qcom/sdm632-cdp-s2.dts
index 51c323c..2c3e830 100644
--- a/arch/arm64/boot/dts/qcom/sdm632-cdp-s2.dts
+++ b/arch/arm64/boot/dts/qcom/sdm632-cdp-s2.dts
@@ -16,7 +16,6 @@
#include "sdm632.dtsi"
#include "sdm450-pmi632-cdp-s2.dtsi"
#include "sdm450-pmi632.dtsi"
-#include "sdm632-camera-sensor-cdp.dtsi"
/ {
model = "Qualcomm Technologies, Inc. SDM632 + PMI632 + PMI8004 CDP S2";
@@ -55,3 +54,17 @@
};
};
};
+
+&pm8953_vadc {
+ pinctrl-0 = <&pa_therm1_default>;
+ /delete-node/ chan@13;
+};
+
+&pm8953_mpps {
+ /delete-node/ case_therm;
+};
+
+&thermal_zones {
+ /delete-node/ case-therm-adc;
+ /delete-node/ case-therm-step;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm632-mtp-s3.dts b/arch/arm64/boot/dts/qcom/sdm632-mtp-s3.dts
index f7770af..0566fbb 100644
--- a/arch/arm64/boot/dts/qcom/sdm632-mtp-s3.dts
+++ b/arch/arm64/boot/dts/qcom/sdm632-mtp-s3.dts
@@ -16,7 +16,6 @@
#include "sdm632.dtsi"
#include "sdm450-pmi632-mtp-s3.dtsi"
#include "sdm450-pmi632.dtsi"
-#include "sdm632-camera-sensor-mtp.dtsi"
/ {
model = "Qualcomm Technologies, Inc. SDM632 + PMI632 + PMI8004 MTP S3";
@@ -25,3 +24,16 @@
qcom,pmic-id = <0x010016 0x25 0xC 0x0>;
};
+&pm8953_vadc {
+ pinctrl-0 = <&pa_therm1_default>;
+ /delete-node/ chan@13;
+};
+
+&pm8953_mpps {
+ /delete-node/ case_therm;
+};
+
+&thermal_zones {
+ /delete-node/ case-therm-adc;
+ /delete-node/ case-therm-step;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm632-qrd-sku4.dts b/arch/arm64/boot/dts/qcom/sdm632-qrd-sku4.dts
index c3cc988..fe1ac73 100644
--- a/arch/arm64/boot/dts/qcom/sdm632-qrd-sku4.dts
+++ b/arch/arm64/boot/dts/qcom/sdm632-qrd-sku4.dts
@@ -50,3 +50,17 @@
};
};
};
+
+&pm8953_vadc {
+ pinctrl-0 = <&pa_therm1_default>;
+ /delete-node/ chan@13;
+};
+
+&pm8953_mpps {
+ /delete-node/ case_therm;
+};
+
+&thermal_zones {
+ /delete-node/ case-therm-adc;
+ /delete-node/ case-therm-step;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm632.dtsi b/arch/arm64/boot/dts/qcom/sdm632.dtsi
index e397355..be5168f 100644
--- a/arch/arm64/boot/dts/qcom/sdm632.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm632.dtsi
@@ -544,7 +544,7 @@
};
&soc {
- /delete-node/ msm_cpufreq;
+ /delete-node/ qcom,msm-cpufreq;
msm_cpufreq: qcom,msm-cpufreq {
compatible = "qcom,msm-cpufreq";
clock-names =
diff --git a/arch/arm64/boot/dts/qcom/sdm670-gpu.dtsi b/arch/arm64/boot/dts/qcom/sdm670-gpu.dtsi
index a77f4a0..f6ce559 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-gpu.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-gpu.dtsi
@@ -517,8 +517,70 @@
};
};
- };
+ qcom,gpu-pwrlevels-4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ qcom,speed-bin = <105>;
+
+ qcom,initial-pwrlevel = <4>;
+ qcom,ca-target-pwrlevel = <2>;
+
+ /* NOM */
+ qcom,gpu-pwrlevel@0 {
+ reg = <0>;
+ qcom,gpu-freq = <504000000>;
+ qcom,bus-freq = <11>;
+ qcom,bus-min = <9>;
+ qcom,bus-max = <11>;
+ };
+
+ /* SVS_L1 */
+ qcom,gpu-pwrlevel@1 {
+ reg = <1>;
+ qcom,gpu-freq = <430000000>;
+ qcom,bus-freq = <11>;
+ qcom,bus-min = <8>;
+ qcom,bus-max = <11>;
+ };
+
+ /* SVS */
+ qcom,gpu-pwrlevel@2 {
+ reg = <2>;
+ qcom,gpu-freq = <355000000>;
+ qcom,bus-freq = <8>;
+ qcom,bus-min = <5>;
+ qcom,bus-max = <9>;
+ };
+
+ /* LOW SVS */
+ qcom,gpu-pwrlevel@3 {
+ reg = <3>;
+ qcom,gpu-freq = <267000000>;
+ qcom,bus-freq = <6>;
+ qcom,bus-min = <4>;
+ qcom,bus-max = <8>;
+ };
+
+ /* MIN SVS */
+ qcom,gpu-pwrlevel@4 {
+ reg = <4>;
+ qcom,gpu-freq = <180000000>;
+ qcom,bus-freq = <4>;
+ qcom,bus-min = <3>;
+ qcom,bus-max = <4>;
+ };
+
+ /* XO */
+ qcom,gpu-pwrlevel@5 {
+ reg = <5>;
+ qcom,gpu-freq = <0>;
+ qcom,bus-freq = <0>;
+ qcom,bus-min = <0>;
+ qcom,bus-max = <0>;
+ };
+ };
+ };
};
kgsl_msm_iommu: qcom,kgsl-iommu {
diff --git a/arch/arm64/configs/sdm670-perf_defconfig b/arch/arm64/configs/sdm670-perf_defconfig
index c2a9aa5..5297e3f 100644
--- a/arch/arm64/configs/sdm670-perf_defconfig
+++ b/arch/arm64/configs/sdm670-perf_defconfig
@@ -328,6 +328,7 @@
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_WRITABLE_TRIPS=y
diff --git a/arch/arm64/configs/sdm670_defconfig b/arch/arm64/configs/sdm670_defconfig
index 961864b..ad75f53 100644
--- a/arch/arm64/configs/sdm670_defconfig
+++ b/arch/arm64/configs/sdm670_defconfig
@@ -334,6 +334,7 @@
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_WRITABLE_TRIPS=y
diff --git a/arch/arm64/configs/sdm845-perf_defconfig b/arch/arm64/configs/sdm845-perf_defconfig
index b8f98df..8f213f4 100644
--- a/arch/arm64/configs/sdm845-perf_defconfig
+++ b/arch/arm64/configs/sdm845-perf_defconfig
@@ -331,6 +331,7 @@
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_WRITABLE_TRIPS=y
diff --git a/arch/arm64/configs/sdm845_defconfig b/arch/arm64/configs/sdm845_defconfig
index 7868efe..d3ae4a5 100644
--- a/arch/arm64/configs/sdm845_defconfig
+++ b/arch/arm64/configs/sdm845_defconfig
@@ -336,6 +336,7 @@
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_WRITABLE_TRIPS=y
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index b4e526d..d8cdb16 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -67,7 +67,10 @@
unsigned long size;
};
-static struct dma_contig_early_reserve dma_mmu_remap[MAX_CMA_AREAS];
+/* allocate the memory for the fixup regions as well */
+#define MAX_FIXUP_AREAS MAX_CMA_AREAS
+static struct dma_contig_early_reserve
+ dma_mmu_remap[MAX_CMA_AREAS + MAX_FIXUP_AREAS];
static int dma_mmu_remap_num;
void __init dma_contiguous_early_fixup(phys_addr_t base, unsigned long size)
diff --git a/drivers/clk/msm/clock-cpu-sdm632.c b/drivers/clk/msm/clock-cpu-sdm632.c
index b59739a..357c49c 100644
--- a/drivers/clk/msm/clock-cpu-sdm632.c
+++ b/drivers/clk/msm/clock-cpu-sdm632.c
@@ -56,7 +56,9 @@
static struct clk_ops clk_ops_variable_rate;
DEFINE_EXT_CLK(xo_a_clk, NULL);
-DEFINE_VDD_REGS_INIT(vdd_cpu, 1);
+static DEFINE_VDD_REGS_INIT(vdd_cpu_perf, 1);
+static DEFINE_VDD_REGS_INIT(vdd_cpu_pwr, 1);
+static DEFINE_VDD_REGS_INIT(vdd_cci, 1);
enum {
APCS_C0_PLL_BASE,
@@ -70,6 +72,7 @@
VDD_MX_MIN,
VDD_MX_LOWER,
VDD_MX_SVS,
+ VDD_MX_TUR,
VDD_MX_NUM,
};
@@ -78,6 +81,7 @@
RPM_REGULATOR_LEVEL_MIN_SVS, /* VDD_PLL_MIN */
RPM_REGULATOR_LEVEL_LOW_SVS, /* VDD_PLL_LOW_SVS */
RPM_REGULATOR_LEVEL_SVS, /* VDD_PLL_SVS */
+ RPM_REGULATOR_LEVEL_TURBO, /* VDD_PLL_TUR */
};
static DEFINE_VDD_REGULATORS(vdd_mx, VDD_MX_NUM, 1,
@@ -124,7 +128,7 @@
.test_ctl_hi_val = 0x00004000,
.test_ctl_lo_val = 0x1C000000,
},
- .max_rate = 1785600000UL,
+ .max_rate = 2016000000UL,
.min_rate = 614400000UL,
.src_rate = 19200000UL,
.base = &virt_bases[APCS_C0_PLL_BASE],
@@ -132,7 +136,7 @@
.parent = &xo_a_clk.c,
.dbg_name = "apcs_c0_pll",
.ops = &clk_ops_variable_rate,
- VDD_MX_FMAX_MAP2(MIN, 1200000000UL, LOWER, 2400000000UL),
+ VDD_MX_FMAX_MAP2(MIN, 1200000000UL, LOWER, 2016000000UL),
CLK_INIT(apcs_c0_pll.c),
},
};
@@ -161,7 +165,7 @@
.test_ctl_hi_val = 0x00004000,
.test_ctl_lo_val = 0x1C000000,
},
- .max_rate = 2054400000UL,
+ .max_rate = 2016000000UL,
.min_rate = 633600000UL,
.src_rate = 19200000UL,
.base = &virt_bases[APCS_C1_PLL_BASE],
@@ -169,7 +173,7 @@
.parent = &xo_a_clk.c,
.dbg_name = "apcs_c1_pll",
.ops = &clk_ops_variable_rate,
- VDD_MX_FMAX_MAP2(MIN, 1200000000UL, LOWER, 2400000000UL),
+ VDD_MX_FMAX_MAP2(MIN, 1200000000UL, LOWER, 2016000000UL),
CLK_INIT(apcs_c1_pll.c),
},
};
@@ -190,7 +194,7 @@
static struct alpha_pll_clk apcs_cci_pll = {
.masks = &pll_masks_p,
- .offset = 0x1D0000,
+ .offset = 0x00,
.vco_tbl = apcs_cci_pll_vco,
.num_vco = ARRAY_SIZE(apcs_cci_pll_vco),
.enable_config = 0x8, /* Early output */
@@ -203,7 +207,6 @@
.rate = 787200000,
.dbg_name = "apcs_cci_pll",
.ops = &clk_ops_dyna_alpha_pll,
- /* TODO: FMAX */
VDD_MX_FMAX_MAP1(SVS, 1000000000UL),
CLK_INIT(apcs_cci_pll.c),
},
@@ -229,7 +232,7 @@
s32 cpu_latency_no_l2_pc_us;
};
-static struct mux_div_clk a53ssmux_perf = {
+static struct mux_div_clk perf_cpussmux = {
.ops = &rcg_mux_div_ops,
.data = {
.max_div = 32,
@@ -237,9 +240,9 @@
.is_half_divider = true,
},
.c = {
- .dbg_name = "a53ssmux_perf",
+ .dbg_name = "perf_cpussmux",
.ops = &clk_ops_mux_div_clk,
- CLK_INIT(a53ssmux_perf.c),
+ CLK_INIT(perf_cpussmux.c),
},
.div_mask = BM(4, 0),
.src_mask = BM(10, 8) >> 8,
@@ -249,7 +252,7 @@
),
};
-static struct mux_div_clk a53ssmux_pwr = {
+static struct mux_div_clk pwr_cpussmux = {
.ops = &rcg_mux_div_ops,
.data = {
.max_div = 32,
@@ -257,9 +260,9 @@
.is_half_divider = true,
},
.c = {
- .dbg_name = "a53ssmux_pwr",
+ .dbg_name = "pwr_cpussmux",
.ops = &clk_ops_mux_div_clk,
- CLK_INIT(a53ssmux_pwr.c),
+ CLK_INIT(pwr_cpussmux.c),
},
.div_mask = BM(4, 0),
.src_mask = BM(10, 8) >> 8,
@@ -269,17 +272,18 @@
),
};
-static struct mux_div_clk a53ssmux_cci = {
+static struct mux_div_clk cci_cpussmux = {
.ops = &rcg_mux_div_ops,
.data = {
+ .skip_odd_div = true,
.max_div = 32,
.min_div = 2,
.is_half_divider = true,
},
.c = {
- .dbg_name = "a53ssmux_cci",
+ .dbg_name = "cci_cpussmux",
.ops = &clk_ops_mux_div_clk,
- CLK_INIT(a53ssmux_cci.c),
+ CLK_INIT(cci_cpussmux.c),
},
.div_mask = BM(4, 0),
.src_mask = BM(10, 8) >> 8,
@@ -289,9 +293,9 @@
),
};
-static struct a53_cpu_clk a53_pwr_clk;
-static struct a53_cpu_clk a53_perf_clk;
-static struct a53_cpu_clk a53_cci_clk;
+static struct a53_cpu_clk pwr_clk;
+static struct a53_cpu_clk perf_clk;
+static struct a53_cpu_clk cci_clk;
static void do_nothing(void *unused) { }
@@ -370,7 +374,7 @@
.handoff = a53_cpu_clk_handoff,
};
-static struct a53_cpu_clk a53_perf_clk = {
+static struct a53_cpu_clk perf_clk = {
.cpu_reg_mask = 0x103,
.latency_lvl = {
.affinity_level = LPM_AFF_LVL_L2,
@@ -379,15 +383,15 @@
},
.cpu_latency_no_l2_pc_us = 280,
.c = {
- .parent = &a53ssmux_perf.c,
+ .parent = &perf_cpussmux.c,
.ops = &clk_ops_cpu,
- .vdd_class = &vdd_cpu,
- .dbg_name = "a53_perf_clk",
- CLK_INIT(a53_perf_clk.c),
+ .vdd_class = &vdd_cpu_perf,
+ .dbg_name = "perf_clk",
+ CLK_INIT(perf_clk.c),
},
};
-static struct a53_cpu_clk a53_pwr_clk = {
+static struct a53_cpu_clk pwr_clk = {
.cpu_reg_mask = 0x3,
.latency_lvl = {
.affinity_level = LPM_AFF_LVL_L2,
@@ -396,21 +400,21 @@
},
.cpu_latency_no_l2_pc_us = 280,
.c = {
- .parent = &a53ssmux_pwr.c,
+ .parent = &pwr_cpussmux.c,
.ops = &clk_ops_cpu,
- .vdd_class = &vdd_cpu,
- .dbg_name = "a53_pwr_clk",
- CLK_INIT(a53_pwr_clk.c),
+ .vdd_class = &vdd_cpu_pwr,
+ .dbg_name = "pwr_clk",
+ CLK_INIT(pwr_clk.c),
},
};
-static struct a53_cpu_clk a53_cci_clk = {
+static struct a53_cpu_clk cci_clk = {
.c = {
- .parent = &a53ssmux_cci.c,
+ .parent = &cci_cpussmux.c,
.ops = &clk_ops_cpu,
- .vdd_class = &vdd_cpu,
- .dbg_name = "a53_cci_clk",
- CLK_INIT(a53_cci_clk.c),
+ .vdd_class = &vdd_cci,
+ .dbg_name = "cci_clk",
+ CLK_INIT(cci_clk.c),
},
};
@@ -500,14 +504,14 @@
CLK_LIST(apcs_cci_pll),
/* Muxes */
- CLK_LIST(a53ssmux_pwr),
- CLK_LIST(a53ssmux_perf),
- CLK_LIST(a53ssmux_cci),
+ CLK_LIST(pwr_cpussmux),
+ CLK_LIST(perf_cpussmux),
+ CLK_LIST(cci_cpussmux),
/* CPU clocks */
- CLK_LIST(a53_pwr_clk),
- CLK_LIST(a53_perf_clk),
- CLK_LIST(a53_cci_clk),
+ CLK_LIST(pwr_clk),
+ CLK_LIST(perf_clk),
+ CLK_LIST(cci_clk),
/* debug clocks */
CLK_LIST(apc0_m_clk),
@@ -516,13 +520,11 @@
CLK_LIST(cpu_debug_pri_mux),
};
-static struct pll_clk *a53sspll[] = { &apcs_c1_pll, &apcs_c0_pll };
+static struct mux_div_clk *a53ssmux[] = { &perf_cpussmux, &pwr_cpussmux,
+ &cci_cpussmux };
-static struct mux_div_clk *a53ssmux[] = { &a53ssmux_perf, &a53ssmux_pwr,
- &a53ssmux_cci };
-
-static struct a53_cpu_clk *cpuclk[] = { &a53_perf_clk, &a53_pwr_clk,
- &a53_cci_clk };
+static struct a53_cpu_clk *cpuclk[] = { &perf_clk, &pwr_clk,
+ &cci_clk };
static struct clk *logical_cpu_to_clk(int cpu)
{
@@ -530,12 +532,12 @@
u32 reg;
if (cpu_node && !of_property_read_u32(cpu_node, "reg", ®)) {
- if ((reg | a53_pwr_clk.cpu_reg_mask) ==
- a53_pwr_clk.cpu_reg_mask)
- return &a53_pwr_clk.c;
- if ((reg | a53_perf_clk.cpu_reg_mask) ==
- a53_perf_clk.cpu_reg_mask)
- return &a53_perf_clk.c;
+ if ((reg | pwr_clk.cpu_reg_mask) ==
+ pwr_clk.cpu_reg_mask)
+ return &pwr_clk.c;
+ if ((reg | perf_clk.cpu_reg_mask) ==
+ perf_clk.cpu_reg_mask)
+ return &perf_clk.c;
}
return NULL;
@@ -629,54 +631,6 @@
*version);
}
-static int cpu_parse_pll_data(struct platform_device *pdev, int pll_count)
-{
- int pll_num;
- struct resource *res;
- struct clk *c;
- char pll_name[] = "apcs-xxx-pll-base";
-
- for (pll_num = 0; pll_num < pll_count; pll_num++) {
- snprintf(pll_name, ARRAY_SIZE(pll_name), "apcs-%s-pll-base",
- pll_names[pll_num]);
-
- res = platform_get_resource_byname(pdev,
- IORESOURCE_MEM, pll_name);
- if (!res) {
- dev_err(&pdev->dev, "missing %s\n", pll_name);
- return -EINVAL;
- }
-
- if (pll_num < APCS_CCI_PLL_BASE) {
- a53sspll[pll_num]->base = devm_ioremap(&pdev->dev,
- res->start, resource_size(res));
- if (!a53sspll[pll_num]->base) {
- dev_err(&pdev->dev, "ioremap failed for %s\n",
- pll_name);
- return -ENOMEM;
- }
- } else {
- apcs_cci_pll.base = devm_ioremap(&pdev->dev,
- res->start, resource_size(res));
- if (!apcs_cci_pll.base) {
- dev_err(&pdev->dev, "ioremap failed for %s\n",
- pll_name);
- return -ENOMEM;
- }
- }
- }
-
- c = devm_clk_get(&pdev->dev, "xo_a");
- if (IS_ERR(c)) {
- if (PTR_ERR(c) != -EPROBE_DEFER)
- dev_err(&pdev->dev, "Unable to get xo clock\n");
- return PTR_ERR(c);
- }
- xo_a_clk.c.parent = c;
-
- return 0;
-}
-
static int cpu_parse_devicetree(struct platform_device *pdev, int mux_id)
{
struct resource *res;
@@ -714,7 +668,7 @@
return 0;
}
-static int add_opp(struct clk *c, struct device *cpudev, struct device *vregdev,
+static int add_opp(struct clk *c, struct device *cpudev,
unsigned long max_rate)
{
unsigned long rate = 0;
@@ -756,13 +710,6 @@
return ret;
}
- ret = dev_pm_opp_add(vregdev, rate, uv);
- if (ret) {
- pr_warn("clock-cpu: couldn't add OPP for %lu\n",
- rate);
- return ret;
- }
-
if (rate >= max_rate)
break;
}
@@ -775,10 +722,10 @@
struct dev_pm_opp *oppfmax, *oppfmin;
unsigned long apc0_fmax, apc1_fmax, apc0_fmin, apc1_fmin;
- apc0_fmax = a53_pwr_clk.c.fmax[a53_pwr_clk.c.num_fmax - 1];
- apc0_fmin = a53_pwr_clk.c.fmax[1];
- apc1_fmax = a53_perf_clk.c.fmax[a53_perf_clk.c.num_fmax - 1];
- apc1_fmin = a53_perf_clk.c.fmax[1];
+ apc0_fmax = pwr_clk.c.fmax[pwr_clk.c.num_fmax - 1];
+ apc0_fmin = pwr_clk.c.fmax[1];
+ apc1_fmax = perf_clk.c.fmax[perf_clk.c.num_fmax - 1];
+ apc1_fmin = perf_clk.c.fmax[1];
rcu_read_lock();
oppfmax = dev_pm_opp_find_freq_exact(get_cpu_device(a53_c0_cpu),
@@ -808,51 +755,36 @@
static void populate_opp_table(struct platform_device *pdev)
{
- struct platform_device *apc0_dev, *apc1_dev;
- struct device_node *apc0_node = NULL, *apc1_node;
unsigned long apc0_fmax, apc1_fmax;
int cpu, a53_c0_cpu = 0, a53_c1_cpu = 0;
+ struct device *dev;
- apc0_node = of_parse_phandle(pdev->dev.of_node,
- "vdd-c0-supply", 0);
- if (!apc0_node) {
- pr_err("can't find the apc0 dt node.\n");
- return;
- }
+ apc0_fmax = pwr_clk.c.fmax[pwr_clk.c.num_fmax - 1];
- apc1_node = of_parse_phandle(pdev->dev.of_node, "vdd-c1-supply", 0);
- if (!apc1_node) {
- pr_err("can't find the apc1 dt node.\n");
- return;
- }
-
- apc0_dev = of_find_device_by_node(apc0_node);
- if (!apc0_dev) {
- pr_err("can't find the apc0 device node.\n");
- return;
- }
-
- apc1_dev = of_find_device_by_node(apc1_node);
- if (!apc1_dev) {
- pr_err("can't find the apc1 device node.\n");
- return;
- }
-
- apc0_fmax = a53_pwr_clk.c.fmax[a53_pwr_clk.c.num_fmax - 1];
-
- apc1_fmax = a53_perf_clk.c.fmax[a53_perf_clk.c.num_fmax - 1];
+ apc1_fmax = perf_clk.c.fmax[perf_clk.c.num_fmax - 1];
for_each_possible_cpu(cpu) {
- if (logical_cpu_to_clk(cpu) == &a53_pwr_clk.c) {
+ if (logical_cpu_to_clk(cpu) == &pwr_clk.c) {
a53_c0_cpu = cpu;
- WARN(add_opp(&a53_pwr_clk.c, get_cpu_device(cpu),
- &apc0_dev->dev, apc0_fmax),
+ dev = get_cpu_device(cpu);
+ if (!dev) {
+ pr_err("can't find cpu device for attaching OPPs\n");
+ return;
+ }
+
+ WARN(add_opp(&pwr_clk.c, dev, apc0_fmax),
"Failed to add OPP levels for %d\n", cpu);
}
- if (logical_cpu_to_clk(cpu) == &a53_perf_clk.c) {
+
+ if (logical_cpu_to_clk(cpu) == &perf_clk.c) {
a53_c1_cpu = cpu;
- WARN(add_opp(&a53_perf_clk.c, get_cpu_device(cpu),
- &apc1_dev->dev, apc1_fmax),
+ dev = get_cpu_device(cpu);
+ if (!dev) {
+ pr_err("can't find cpu device for attaching OPPs\n");
+ return;
+ }
+
+ WARN(add_opp(&perf_clk.c, dev, apc1_fmax),
"Failed to add OPP levels for %d\n", cpu);
}
}
@@ -870,15 +802,15 @@
switch (event) {
case PM_POST_HIBERNATION:
case PM_POST_SUSPEND:
- clk_unprepare(&a53_pwr_clk.c);
- clk_unprepare(&a53_perf_clk.c);
- clk_unprepare(&a53_cci_clk.c);
+ clk_unprepare(&pwr_clk.c);
+ clk_unprepare(&perf_clk.c);
+ clk_unprepare(&cci_clk.c);
break;
case PM_HIBERNATION_PREPARE:
case PM_SUSPEND_PREPARE:
- clk_prepare(&a53_pwr_clk.c);
- clk_prepare(&a53_perf_clk.c);
- clk_prepare(&a53_cci_clk.c);
+ clk_prepare(&pwr_clk.c);
+ clk_prepare(&perf_clk.c);
+ clk_prepare(&cci_clk.c);
break;
default:
break;
@@ -904,11 +836,11 @@
{
unsigned long rate;
- rate = (a53_perf_clk.c.count) ? a53_perf_clk.c.rate : 0;
- pr_err("%s frequency: %10lu Hz\n", a53_perf_clk.c.dbg_name, rate);
+ rate = (perf_clk.c.count) ? perf_clk.c.rate : 0;
+ pr_err("%s frequency: %10lu Hz\n", perf_clk.c.dbg_name, rate);
- rate = (a53_pwr_clk.c.count) ? a53_pwr_clk.c.rate : 0;
- pr_err("%s frequency: %10lu Hz\n", a53_pwr_clk.c.dbg_name, rate);
+ rate = (pwr_clk.c.count) ? pwr_clk.c.rate : 0;
+ pr_err("%s frequency: %10lu Hz\n", pwr_clk.c.dbg_name, rate);
return NOTIFY_OK;
}
@@ -928,12 +860,17 @@
int speed_bin, version, rc, cpu, mux_id;
char prop_name[] = "qcom,speedX-bin-vX-XXX";
int mux_num = A53SS_MUX_NUM;
+ struct clk *xo_clk;
get_speed_bin(pdev, &speed_bin, &version);
- rc = cpu_parse_pll_data(pdev, N_PLL_BASES);
- if (rc)
- return rc;
+ xo_clk = devm_clk_get(&pdev->dev, "xo_a");
+ if (IS_ERR(xo_clk)) {
+ if (PTR_ERR(xo_clk) != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "Unable to get xo clock\n");
+ return PTR_ERR(xo_clk);
+ }
+ xo_a_clk.c.parent = xo_clk;
/* PLL core logic */
vdd_mx.regulator[0] = devm_regulator_get(&pdev->dev, "vdd-mx");
@@ -990,16 +927,16 @@
}
/* Force to move to PLL configuartion */
- rc = clk_set_rate(&a53_cci_clk.c, cci_early_boot_rate);
+ rc = clk_set_rate(&cci_clk.c, cci_early_boot_rate);
if (rc)
dev_err(&pdev->dev, "Can't set CCI PLL rate for CCI\n");
- rc = clk_set_rate(&a53_pwr_clk.c, pwrcl_early_boot_rate);
+ rc = clk_set_rate(&pwr_clk.c, pwrcl_early_boot_rate);
if (rc)
dev_err(&pdev->dev, "Can't set pwr PLL rate for Cluster-0 %ld\n",
pwrcl_early_boot_rate);
- rc = clk_set_rate(&a53_perf_clk.c, perfcl_early_boot_rate);
+ rc = clk_set_rate(&perf_clk.c, perfcl_early_boot_rate);
if (rc)
dev_err(&pdev->dev, "Can't set perf PLL rate for Cluster-1 %ld\n",
perfcl_early_boot_rate);
@@ -1019,20 +956,20 @@
for_each_online_cpu(cpu) {
WARN(clk_prepare_enable(&cpuclk[cpu/4]->c),
"Unable to turn on CPU clock");
- WARN(clk_prepare_enable(&a53_cci_clk.c),
+ WARN(clk_prepare_enable(&cci_clk.c),
"Unable to turn on CCI clock");
}
put_online_cpus();
for_each_possible_cpu(cpu) {
- if (logical_cpu_to_clk(cpu) == &a53_perf_clk.c)
- cpumask_set_cpu(cpu, &a53_perf_clk.cpumask);
- if (logical_cpu_to_clk(cpu) == &a53_pwr_clk.c)
- cpumask_set_cpu(cpu, &a53_pwr_clk.cpumask);
+ if (logical_cpu_to_clk(cpu) == &perf_clk.c)
+ cpumask_set_cpu(cpu, &perf_clk.cpumask);
+ if (logical_cpu_to_clk(cpu) == &pwr_clk.c)
+ cpumask_set_cpu(cpu, &pwr_clk.cpumask);
}
- a53_pwr_clk.hw_low_power_ctrl = true;
- a53_perf_clk.hw_low_power_ctrl = true;
+ pwr_clk.hw_low_power_ctrl = true;
+ perf_clk.hw_low_power_ctrl = true;
register_pm_notifier(&clock_sdm632_pm_notifier);
@@ -1073,19 +1010,19 @@
if (!ofnode)
return 0;
- rc = lpm_get_latency(&a53_perf_clk.latency_lvl,
- &a53_perf_clk.cpu_latency_no_l2_pc_us);
+ rc = lpm_get_latency(&perf_clk.latency_lvl,
+ &perf_clk.cpu_latency_no_l2_pc_us);
if (rc < 0)
pr_err("Failed to get the L2 PC value for perf\n");
- rc = lpm_get_latency(&a53_pwr_clk.latency_lvl,
- &a53_pwr_clk.cpu_latency_no_l2_pc_us);
+ rc = lpm_get_latency(&pwr_clk.latency_lvl,
+ &pwr_clk.cpu_latency_no_l2_pc_us);
if (rc < 0)
pr_err("Failed to get the L2 PC value for pwr\n");
pr_debug("Latency for pwr/perf cluster %d : %d\n",
- a53_pwr_clk.cpu_latency_no_l2_pc_us,
- a53_perf_clk.cpu_latency_no_l2_pc_us);
+ pwr_clk.cpu_latency_no_l2_pc_us,
+ perf_clk.cpu_latency_no_l2_pc_us);
return rc;
}
@@ -1100,6 +1037,9 @@
#define SRC_SEL 0x4
#define SRC_DIV 0x1
+/* Dummy clock for setting the rate of CCI PLL in early_init*/
+DEFINE_CLK_DUMMY(p_clk, 19200000);
+
static int __init cpu_clock_init(void)
{
void __iomem *base;
@@ -1127,6 +1067,7 @@
apcs_c1_pll.c.ops->set_rate(&apcs_c1_pll.c, perfcl_early_boot_rate);
clk_ops_variable_rate_pll.enable(&apcs_c1_pll.c);
+ apcs_cci_pll.c.parent = (struct clk *)&p_clk;
apcs_cci_pll.c.ops->set_rate(&apcs_cci_pll.c, cci_early_boot_rate);
clk_ops_dyna_alpha_pll.enable(&apcs_cci_pll.c);
diff --git a/drivers/clk/qcom/gpucc-sdm845.c b/drivers/clk/qcom/gpucc-sdm845.c
index 53446a2..8dfdf85 100644
--- a/drivers/clk/qcom/gpucc-sdm845.c
+++ b/drivers/clk/qcom/gpucc-sdm845.c
@@ -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
@@ -290,6 +290,7 @@
F(267000000, P_CRC_DIV, 1, 0, 0),
F(355000000, P_CRC_DIV, 1, 0, 0),
F(430000000, P_CRC_DIV, 1, 0, 0),
+ F(504000000, P_CRC_DIV, 1, 0, 0),
F(565000000, P_CRC_DIV, 1, 0, 0),
F(650000000, P_CRC_DIV, 1, 0, 0),
F(700000000, P_CRC_DIV, 1, 0, 0),
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
index 5b19aee..12ca46e 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
@@ -1791,7 +1791,8 @@
enum dsi_engine_state host_state = DSI_CTRL_ENGINE_ON;
/* Sequence does not matter for split dsi usecases */
- for (i = 0; i < display->ctrl_count; i++) {
+ for (i = 0; (i < display->ctrl_count) &&
+ (i < MAX_DSI_CTRLS_PER_DISPLAY); i++) {
ctrl = &display->ctrl[i];
if (!ctrl->ctrl)
continue;
@@ -3958,8 +3959,13 @@
struct dsi_display *display = dsi_display;
int rc = 0;
+ if (!display) {
+ pr_err("Invalid display\n");
+ return -EINVAL;
+ }
+
/* Continuous splash not supported by external bridge */
- if (!display || dsi_display_has_ext_bridge(display)) {
+ if (dsi_display_has_ext_bridge(display)) {
display->is_cont_splash_enabled = false;
return 0;
}
@@ -5835,18 +5841,19 @@
goto error_host_engine_off;
}
- rc = dsi_display_soft_reset(display);
- if (rc) {
- pr_err("[%s] failed soft reset, rc=%d\n", display->name, rc);
- goto error_ctrl_link_off;
- }
-
if (!display->is_cont_splash_enabled) {
/*
- * For continuous splash usecase we skip panel
- * prepare since the pnael is already in
- * active state and panel on commands are not needed
+ * For continuous splash usecase, skip panel prepare and
+ * ctl reset since the pnael and ctrl is already in active
+ * state and panel on commands are not needed
*/
+ rc = dsi_display_soft_reset(display);
+ if (rc) {
+ pr_err("[%s] failed soft reset, rc=%d\n",
+ display->name, rc);
+ goto error_ctrl_link_off;
+ }
+
rc = dsi_panel_prepare(display->panel);
if (rc) {
pr_err("[%s] panel prepare failed, rc=%d\n",
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c
index 7649012..7bc01c3 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.c
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.c
@@ -4080,6 +4080,7 @@
static void sde_crtc_disable(struct drm_crtc *crtc)
{
+ struct sde_kms *sde_kms;
struct sde_crtc *sde_crtc;
struct sde_crtc_state *cstate;
struct drm_encoder *encoder;
@@ -4095,6 +4096,12 @@
return;
}
+ sde_kms = _sde_crtc_get_kms(crtc);
+ if (!sde_kms) {
+ SDE_ERROR("invalid kms\n");
+ return;
+ }
+
if (!sde_kms_power_resource_is_enabled(crtc->dev)) {
SDE_ERROR("power resource is not enabled\n");
return;
@@ -4160,7 +4167,9 @@
}
spin_unlock_irqrestore(&sde_crtc->spin_lock, flags);
- sde_core_perf_crtc_update(crtc, 0, true);
+ /* avoid clk/bw downvote if cont-splash is enabled */
+ if (!sde_kms->splash_data.cont_splash_en)
+ sde_core_perf_crtc_update(crtc, 0, true);
drm_for_each_encoder(encoder, crtc->dev) {
if (encoder->crtc != crtc)
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index 5e41611..0ed17d8 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -719,8 +719,6 @@
if (device->ftbl->snapshot)
device->ftbl->snapshot(device, snapshot, context);
- if (device->ftbl->snapshot_gmu)
- device->ftbl->snapshot_gmu(device, snapshot);
}
/*
diff --git a/drivers/i2c/busses/i2c-msm-v2.c b/drivers/i2c/busses/i2c-msm-v2.c
index ad77697..99e7c97 100644
--- a/drivers/i2c/busses/i2c-msm-v2.c
+++ b/drivers/i2c/busses/i2c-msm-v2.c
@@ -3027,7 +3027,7 @@
{
return platform_driver_register(&i2c_msm_driver);
}
-arch_initcall(i2c_msm_init);
+subsys_initcall(i2c_msm_init);
static void i2c_msm_exit(void)
{
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 86168b9..bcb861ec 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -1225,5 +1225,6 @@
If unsure, say N.
source "drivers/input/touchscreen/synaptics_dsx/Kconfig"
+source "drivers/input/touchscreen/focaltech_touch/Kconfig"
endif
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 7ac5a98..f2749e4 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -101,3 +101,4 @@
obj-$(CONFIG_TOUCHSCREEN_ZFORCE) += zforce_ts.o
obj-$(CONFIG_TOUCHSCREEN_COLIBRI_VF50) += colibri-vf50-ts.o
obj-$(CONFIG_TOUCHSCREEN_ROHM_BU21023) += rohm_bu21023.o
+obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_touch/
diff --git a/drivers/input/touchscreen/focaltech_touch/Kconfig b/drivers/input/touchscreen/focaltech_touch/Kconfig
new file mode 100644
index 0000000..00deec7
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/Kconfig
@@ -0,0 +1,18 @@
+#
+# Focaltech Touchscreen driver configuration
+#
+menuconfig TOUCHSCREEN_FTS
+ bool "Focaltech Touchscreen"
+ depends on I2C
+ default n
+ help
+ Say Y here if you have Focaltech touch panel.
+ If unsure, say N.
+
+config TOUCHSCREEN_FTS_DIRECTORY
+ string "Focaltech ts directory name"
+ default "focaltech_touch"
+ depends on TOUCHSCREEN_FTS
+ help
+ Specify the path for the driver directory.
+ Path should be relative to driver/input/touchscreen/.
diff --git a/drivers/input/touchscreen/focaltech_touch/Makefile b/drivers/input/touchscreen/focaltech_touch/Makefile
new file mode 100644
index 0000000..c582416
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/Makefile
@@ -0,0 +1,17 @@
+#
+# Makefile for the focaltech touchscreen drivers.
+#
+
+# Each configuration option enables a list of files.
+
+obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_core.o
+obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_ex_fun.o
+obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_ex_mode.o
+obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_flash.o
+obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_gesture.o
+obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_esdcheck.o
+obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_i2c.o
+obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_sensor.o
+obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_point_report_check.o
+obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_flash/
+
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_common.h b/drivers/input/touchscreen/focaltech_touch/focaltech_common.h
new file mode 100644
index 0000000..209f0a9
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_common.h
@@ -0,0 +1,217 @@
+/*
+ *
+ * FocalTech fts TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, Focaltech Ltd. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+/*****************************************************************************
+ *
+ * File Name: focaltech_common.h
+ *
+ * Author: Focaltech Driver Team
+ *
+ * Created: 2016-08-16
+ *
+ * Abstract:
+ *
+ * Reference:
+ *
+ *****************************************************************************/
+
+#ifndef __LINUX_FOCALTECH_COMMON_H__
+#define __LINUX_FOCALTECH_COMMON_H__
+
+#include "focaltech_config.h"
+
+/*****************************************************************************
+ * Macro definitions using #define
+ *****************************************************************************/
+#define FTS_DRIVER_VERSION "Focaltech V1.3 20170306"
+
+#define FLAGBIT(x) (0x00000001 << (x))
+#define FLAGBITS(x, y) ((0xFFFFFFFF >> (32 - (y) - 1)) << (x))
+
+#define FLAG_ICSERIALS_LEN 5
+#define FLAG_IDC_BIT 11
+
+#define IC_SERIALS (FTS_CHIP_TYPE & \
+ FLAGBITS(0, FLAG_ICSERIALS_LEN-1))
+#define FTS_CHIP_IDC ((FTS_CHIP_TYPE & FLAGBIT(FLAG_IDC_BIT)) \
+ == FLAGBIT(FLAG_IDC_BIT))
+
+#define FTS_CHIP_TYPE_MAPPING { \
+ {0x01, 0x58, 0x22, 0x58, 0x22, 0x00, 0x00, 0x58, 0x2C}, \
+ {0x02, 0x54, 0x22, 0x54, 0x22, 0x00, 0x00, 0x54, 0x2C}, \
+ {0x03, 0x64, 0x26, 0x64, 0x26, 0x00, 0x00, 0x79, 0x1C}, \
+ {0x04, 0x33, 0x67, 0x64, 0x26, 0x00, 0x00, 0x79, 0x1C}, \
+ {0x05, 0x87, 0x16, 0x87, 0x16, 0x87, 0xA6, 0x00, 0x00}, \
+ {0x06, 0x87, 0x36, 0x87, 0x36, 0x87, 0xC6, 0x00, 0x00}, \
+ {0x07, 0x80, 0x06, 0x80, 0x06, 0x80, 0xC6, 0x80, 0xB6}, \
+ {0x08, 0x86, 0x06, 0x86, 0x06, 0x86, 0xA6, 0x00, 0x00}, \
+ {0x09, 0x86, 0x07, 0x86, 0x07, 0x86, 0xA7, 0x00, 0x00}, \
+ {0x0A, 0xE7, 0x16, 0x87, 0x16, 0xE7, 0xA6, 0x87, 0xB6}, \
+}
+
+#define I2C_BUFFER_LENGTH_MAXINUM 256
+#define FILE_NAME_LENGTH 128
+#define ENABLE 1
+#define DISABLE 0
+/*register address*/
+#define FTS_REG_INT_CNT 0x8F
+#define FTS_REG_FLOW_WORK_CNT 0x91
+#define FTS_REG_WORKMODE 0x00
+#define FTS_REG_WORKMODE_FACTORY_VALUE 0x40
+#define FTS_REG_WORKMODE_WORK_VALUE 0x00
+#define FTS_REG_CHIP_ID 0xA3
+#define FTS_REG_CHIP_ID2 0x9F
+#define FTS_REG_POWER_MODE 0xA5
+#define FTS_REG_POWER_MODE_SLEEP_VALUE 0x03
+#define FTS_REG_FW_VER 0xA6
+#define FTS_REG_VENDOR_ID 0xA8
+#define FTS_REG_LCD_BUSY_NUM 0xAB
+#define FTS_REG_FACE_DEC_MODE_EN 0xB0
+#define FTS_REG_GLOVE_MODE_EN 0xC0
+#define FTS_REG_COVER_MODE_EN 0xC1
+#define FTS_REG_CHARGER_MODE_EN 0x8B
+#define FTS_REG_GESTURE_EN 0xD0
+#define FTS_REG_GESTURE_OUTPUT_ADDRESS 0xD3
+#define FTS_REG_ESD_SATURATE 0xED
+
+
+
+/*****************************************************************************
+ * Alternative mode (When something goes wrong,
+ * the modules may be able to solve the problem.)
+ *****************************************************************************/
+/*
+ * point report check
+ * default: disable
+ */
+#define FTS_POINT_REPORT_CHECK_EN 0
+
+
+/*****************************************************************************
+ * Global variable or extern global variabls/functions
+ *****************************************************************************/
+struct ft_chip_t {
+ unsigned long type;
+ unsigned char chip_idh;
+ unsigned char chip_idl;
+ unsigned char rom_idh;
+ unsigned char rom_idl;
+ unsigned char pramboot_idh;
+ unsigned char pramboot_idl;
+ unsigned char bootloader_idh;
+ unsigned char bootloader_idl;
+};
+
+/* i2c communication*/
+int fts_i2c_write_reg(struct i2c_client *client, u8 regaddr, u8 regvalue);
+int fts_i2c_read_reg(struct i2c_client *client, u8 regaddr, u8 *regvalue);
+int fts_i2c_read(struct i2c_client *client, char *writebuf, int writelen,
+ char *readbuf, int readlen);
+int fts_i2c_write(struct i2c_client *client, char *writebuf, int writelen);
+int fts_i2c_init(void);
+int fts_i2c_exit(void);
+
+/* Gesture functions */
+#if FTS_GESTURE_EN
+int fts_gesture_init(struct input_dev *input_dev, struct i2c_client *client);
+int fts_gesture_exit(struct i2c_client *client);
+void fts_gesture_recovery(struct i2c_client *client);
+int fts_gesture_readdata(struct i2c_client *client);
+int fts_gesture_suspend(struct i2c_client *i2c_client);
+int fts_gesture_resume(struct i2c_client *client);
+#endif
+
+/* Apk and functions */
+#if FTS_APK_NODE_EN
+int fts_create_apk_debug_channel(struct i2c_client *client);
+void fts_release_apk_debug_channel(void);
+#endif
+
+/* ADB functions */
+#if FTS_SYSFS_NODE_EN
+int fts_create_sysfs(struct i2c_client *client);
+int fts_remove_sysfs(struct i2c_client *client);
+#endif
+
+/* ESD */
+#if FTS_ESDCHECK_EN
+int fts_esdcheck_init(void);
+int fts_esdcheck_exit(void);
+int fts_esdcheck_switch(bool enable);
+int fts_esdcheck_proc_busy(bool proc_debug);
+int fts_esdcheck_set_intr(bool intr);
+int fts_esdcheck_suspend(void);
+int fts_esdcheck_resume(void);
+int fts_esdcheck_get_status(void);
+#endif
+
+/* Production test */
+#if FTS_TEST_EN
+int fts_test_init(struct i2c_client *client);
+int fts_test_exit(struct i2c_client *client);
+#endif
+
+/* Point Report Check*/
+#if FTS_POINT_REPORT_CHECK_EN
+int fts_point_report_check_init(void);
+int fts_point_report_check_exit(void);
+void fts_point_report_check_queue_work(void);
+#endif
+
+/* Other */
+extern int g_show_log;
+int fts_reset_proc(int hdelayms);
+int fts_wait_tp_to_valid(struct i2c_client *client);
+void fts_tp_state_recovery(struct i2c_client *client);
+int fts_ex_mode_init(struct i2c_client *client);
+int fts_ex_mode_exit(struct i2c_client *client);
+int fts_ex_mode_recovery(struct i2c_client *client);
+
+void fts_irq_disable(void);
+void fts_irq_enable(void);
+
+/*****************************************************************************
+ * DEBUG function define here
+ *****************************************************************************/
+#if FTS_DEBUG_EN
+#define FTS_DEBUG_LEVEL 1
+
+#if (FTS_DEBUG_LEVEL == 2)
+#define FTS_DEBUG(fmt, args...) pr_err("[FTS][%s]"fmt"\n", __func__, ##args)
+#else
+#define FTS_DEBUG(fmt, args...) pr_err("[FTS]"fmt"\n", ##args)
+#endif
+
+#define FTS_FUNC_ENTER() pr_err("[FTS]%s: Enter\n", __func__)
+#define FTS_FUNC_EXIT() pr_err("[FTS]%s: Exit(%d)\n", __func__, __LINE__)
+#else
+#define FTS_DEBUG(fmt, args...)
+#define FTS_FUNC_ENTER()
+#define FTS_FUNC_EXIT()
+#endif
+
+#define FTS_INFO(fmt, args...) do { \
+ if (g_show_log) \
+ pr_err("[FTS][Info]"fmt"\n", ##args); \
+ } while (0)
+
+#define FTS_ERROR(fmt, args...) do { \
+ if (g_show_log) \
+ pr_err("[FTS][Error]"fmt"\n", ##args); \
+ } while (0)
+
+
+#endif /* __LINUX_FOCALTECH_COMMON_H__ */
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_config.h b/drivers/input/touchscreen/focaltech_touch/focaltech_config.h
new file mode 100644
index 0000000..157f0df
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_config.h
@@ -0,0 +1,248 @@
+/*
+ *
+ * FocalTech TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, FocalTech Systems, Ltd., all rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+/************************************************************************
+ *
+ * File Name: focaltech_config.h
+ *
+ * Author: Focaltech Driver Team
+ *
+ * Created: 2016-08-08
+ *
+ * Abstract: global configurations
+ *
+ * Version: v1.0
+ *
+ ************************************************************************/
+#ifndef _LINUX_FOCLATECH_CONFIG_H_
+#define _LINUX_FOCLATECH_CONFIG_H_
+
+/**************************************************/
+/****** G: A, I: B, S: C, U: D ******************/
+/****** chip type defines, do not modify *********/
+#define _FT8716 0x87160805
+#define _FT8736 0x87360806
+#define _FT8006 0x80060807
+#define _FT8606 0x86060808
+#define _FT8607 0x86070809
+#define _FTE716 0xE716080a
+
+#define _FT5416 0x54160002
+#define _FT5426 0x54260002
+#define _FT5435 0x54350002
+#define _FT5436 0x54360002
+#define _FT5526 0x55260002
+#define _FT5526I 0x5526B002
+#define _FT5446 0x54460002
+#define _FT5346 0x53460002
+#define _FT5446I 0x5446B002
+#define _FT5346I 0x5346B002
+#define _FT7661 0x76610002
+#define _FT7511 0x75110002
+#define _FT7421 0x74210002
+#define _FT7681 0x76810002
+#define _FT3C47U 0x3C47D002
+#define _FT3417 0x34170002
+#define _FT3517 0x35170002
+#define _FT3327 0x33270002
+#define _FT3427 0x34270002
+
+#define _FT5626 0x56260001
+#define _FT5726 0x57260001
+#define _FT5826B 0x5826B001
+#define _FT5826S 0x5826C001
+#define _FT7811 0x78110001
+#define _FT3D47 0x3D470001
+#define _FT3617 0x36170001
+#define _FT3717 0x37170001
+#define _FT3817B 0x3817B001
+
+#define _FT6236U 0x6236D003
+#define _FT6336G 0x6336A003
+#define _FT6336U 0x6336D003
+#define _FT6436U 0x6436D003
+
+#define _FT3267 0x32670004
+#define _FT3367 0x33670004
+
+
+
+/*************************************************/
+
+/*
+ * choose your ic chip type of focaltech
+ */
+#define FTS_CHIP_TYPE _FT3267
+
+/******************* Enables *********************/
+/*********** 1 to enable, 0 to disable ***********/
+
+/*
+ * show debug log info
+ * enable it for debug, disable it for release
+ */
+#define FTS_DEBUG_EN 0
+
+/*
+ * Linux MultiTouch Protocol
+ * 1: Protocol B(default), 0: Protocol A
+ */
+#define FTS_MT_PROTOCOL_B_EN 1
+
+
+/*
+ * Report Pressure in multitouch
+ * 1:enable(default),0:disable
+ */
+#define FTS_REPORT_PRESSURE_EN 1
+
+/*
+ * Force touch support
+ * different pressure for multitouch
+ * 1: true pressure for force touch
+ * 0: constant pressure(default)
+ */
+#define FTS_FORCE_TOUCH_EN 0
+
+/*
+ * Gesture function enable
+ * default: disable
+ */
+#define FTS_GESTURE_EN 0
+
+/*
+ * ESD check & protection
+ * default: disable
+ */
+#define FTS_ESDCHECK_EN 0
+
+/*
+ * Production test enable
+ * 1: enable, 0:disable(default)
+ */
+#define FTS_TEST_EN 0
+
+/*
+ * Glove mode enable
+ * 1: enable, 0:disable(default)
+ */
+#define FTS_GLOVE_EN 0
+/*
+ * cover enable
+ * 1: enable, 0:disable(default)
+ */
+#define FTS_COVER_EN 0
+/*
+ * Charger enable
+ * 1: enable, 0:disable(default)
+ */
+#define FTS_CHARGER_EN 0
+
+/*
+ * Proximity sensor
+ * default: disable
+ */
+#define FTS_PSENSOR_EN 0
+
+/*
+ * Nodes for tools, please keep enable
+ */
+#define FTS_SYSFS_NODE_EN 1
+#define FTS_APK_NODE_EN 1
+
+/*
+ * Customer power enable
+ * enable it when customer need control TP power
+ * default: disable
+ */
+#define FTS_POWER_SOURCE_CUST_EN 1
+
+/****************************************************/
+
+/********************** Upgrade ****************************/
+/*
+ * auto upgrade, please keep enable
+ */
+#define FTS_AUTO_UPGRADE_EN 1
+
+/*
+ * auto upgrade for lcd cfg
+ * default: 0
+ */
+#define FTS_AUTO_UPGRADE_FOR_LCD_CFG_EN 0
+
+/* auto cb check
+ * default: disable
+ */
+#define FTS_AUTO_CLB_EN 0
+
+/*
+ * Check vendor_id number
+ * 0:No check vendor_id (default)
+ * 1/2/3: Check vendor_id for vendor compatibility
+ */
+#define FTS_GET_VENDOR_ID_NUM 0
+
+/*
+ * vendor_id(s) for vendor(s) to be compatible with.
+ * a confirmation of vendor_id(s) is recommended.
+ * FTS_GET_VENDOR_ID_NUM == 0, no check vendor id, you may ignore them
+ * FTS_GET_VENDOR_ID_NUM >= 1, compatible with FTS_VENDOR_1_ID
+ * FTS_GET_VENDOR_ID_NUM >= 2, compatible with FTS_VENDOR_2_ID
+ * FTS_GET_VENDOR_ID_NUM == 3, compatible with FTS_VENDOR_3_ID
+ */
+#define FTS_VENDOR_1_ID 0x00
+#define FTS_VENDOR_2_ID 0x00
+#define FTS_VENDOR_3_ID 0x00
+
+/*
+ * FW_APP.i file for auto upgrade, you must replace it with your own
+ * define your own fw_app, the sample one to be replaced is invalid
+ * NOTE: if FTS_GET_VENDOR_ID_NUM >= 1,
+ * it's the fw corresponding with FTS_VENDOR_1_ID
+ */
+#define FTS_UPGRADE_FW_APP "include/firmware/FT8716_app_sample.i"
+
+/*
+ * if FTS_GET_VENDOR_ID_NUM >= 2, fw corrsponding with FTS_VENDOR_2_ID
+ * define your own fw_app, the sample one is invalid
+ */
+#define FTS_UPGRADE_FW2_APP "include/firmware/FT8716_app_sample.i"
+
+/*
+ * if FTS_GET_VENDOR_ID_NUM == 3, fw corrsponding with FTS_VENDOR_3_ID
+ * define your own fw_app, the sample one is invalid
+ */
+#define FTS_UPGRADE_FW3_APP "include/firmware/FT8716_app_sample.i"
+
+/*
+ * lcd_cfg.i file for lcd cfg upgrade
+ * define your own lcd_cfg.i, the sample one is invalid
+ */
+#define FTS_UPGRADE_LCD_CFG "include/firmware/lcd_cfg.i"
+
+/*
+ * upgrade stress test for debug
+ * enable it for upgrade debug if needed
+ * default: disable
+ */
+#define FTS_UPGRADE_STRESS_TEST 0
+/* stress test times, default: 1000 */
+#define FTS_UPGRADE_TEST_NUMBER 1000
+
+/*********************************************************/
+
+#endif /* _LINUX_FOCLATECH_CONFIG_H_ */
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_core.c b/drivers/input/touchscreen/focaltech_touch/focaltech_core.c
new file mode 100644
index 0000000..27bb390
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_core.c
@@ -0,0 +1,1469 @@
+/*
+ *
+ * FocalTech TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, FocalTech Systems, Ltd., all rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+/*****************************************************************************
+ *
+ * File Name: focaltech_core.c
+ *
+ * Author: Focaltech Driver Team
+ *
+ * Created: 2016-08-08
+ *
+ * Abstract:
+ *
+ * Reference:
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Included header files
+ *****************************************************************************/
+#include "focaltech_core.h"
+
+
+#if defined(CONFIG_FB)
+#include <linux/notifier.h>
+#include <linux/fb.h>
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+#include <linux/earlysuspend.h>
+#define FTS_SUSPEND_LEVEL 1 /* Early-suspend level */
+#endif
+
+/*****************************************************************************
+ * Private constant and macro definitions using #define
+ *****************************************************************************/
+#define FTS_DRIVER_NAME "fts_ts"
+#define INTERVAL_READ_REG 20 /* interval time per read reg unit:ms */
+#define TIMEOUT_READ_REG 300 /* timeout of read reg unit:ms */
+#if FTS_POWER_SOURCE_CUST_EN
+#define FTS_VTG_MIN_UV 2600000
+#define FTS_VTG_MAX_UV 3300000
+#define FTS_I2C_VTG_MIN_UV 1800000
+#define FTS_I2C_VTG_MAX_UV 1800000
+#endif
+#define FTS_READ_TOUCH_BUFFER_DIVIDED 0
+/*****************************************************************************
+ * Global variable or extern global variabls/functions
+ ******************************************************************************/
+struct i2c_client *fts_i2c_client;
+struct fts_ts_data *fts_wq_data;
+struct input_dev *fts_input_dev;
+
+#if FTS_DEBUG_EN
+int g_show_log = 1;
+#else
+int g_show_log;
+#endif
+
+#if (FTS_DEBUG_EN && (FTS_DEBUG_LEVEL == 2))
+char g_sz_debug[1024] = {0};
+#endif
+
+/*****************************************************************************
+ * Static function prototypes
+ *****************************************************************************/
+static void fts_release_all_finger(void);
+static int fts_ts_suspend(struct device *dev);
+static int fts_ts_resume(struct device *dev);
+
+
+/*****************************************************************************
+ * Name: fts_wait_tp_to_valid
+ * Brief: Read chip id until TP FW become valid,
+ * need call when reset/power on/resume...
+ * 1. Read Chip ID per INTERVAL_READ_REG(20ms)
+ * 2. Timeout: TIMEOUT_READ_REG(300ms)
+ * Input:
+ * Output:
+ * Return: 0 - Get correct Device ID
+ *****************************************************************************/
+int fts_wait_tp_to_valid(struct i2c_client *client)
+{
+ int ret = 0;
+ int cnt = 0;
+ u8 reg_value = 0;
+
+ do {
+ ret = fts_i2c_read_reg(client, FTS_REG_CHIP_ID, ®_value);
+ if ((ret < 0) || (reg_value != chip_types.chip_idh)) {
+ FTS_INFO("TP Not Ready, ReadData = 0x%x", reg_value);
+ } else if (reg_value == chip_types.chip_idh) {
+ FTS_INFO("TP Ready, Device ID = 0x%x", reg_value);
+ return 0;
+ }
+ cnt++;
+ msleep(INTERVAL_READ_REG);
+ } while ((cnt * INTERVAL_READ_REG) < TIMEOUT_READ_REG);
+
+ /* error: not get correct reg data */
+ return -EINVAL;
+}
+
+/*****************************************************************************
+ * Name: fts_recover_state
+ * Brief: Need execute this function when reset
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+void fts_tp_state_recovery(struct i2c_client *client)
+{
+ /* wait tp stable */
+ fts_wait_tp_to_valid(client);
+ /* recover TP charger state 0x8B */
+ /* recover TP glove state 0xC0 */
+ /* recover TP cover state 0xC1 */
+ fts_ex_mode_recovery(client);
+ /* recover TP gesture state 0xD0 */
+#if FTS_GESTURE_EN
+ fts_gesture_recovery(client);
+#endif
+}
+
+
+/*****************************************************************************
+ * Name: fts_reset_proc
+ * Brief: Execute reset operation
+ * Input: hdelayms - delay time unit:ms
+ * Output:
+ * Return:
+ *****************************************************************************/
+int fts_reset_proc(int hdelayms)
+{
+ gpio_direction_output(fts_wq_data->pdata->reset_gpio, 0);
+ msleep(20);
+ gpio_direction_output(fts_wq_data->pdata->reset_gpio, 1);
+ msleep(hdelayms);
+
+ return 0;
+}
+
+/*****************************************************************************
+ * Name: fts_irq_disable
+ * Brief: disable irq
+ * Input:
+ * sync:
+ * Output:
+ * Return:
+ *****************************************************************************/
+void fts_irq_disable(void)
+{
+ unsigned long irqflags;
+
+ spin_lock_irqsave(&fts_wq_data->irq_lock, irqflags);
+
+ if (!fts_wq_data->irq_disable) {
+ disable_irq_nosync(fts_wq_data->client->irq);
+ fts_wq_data->irq_disable = 1;
+ }
+
+ spin_unlock_irqrestore(&fts_wq_data->irq_lock, irqflags);
+}
+
+/*****************************************************************************
+ * Name: fts_irq_enable
+ * Brief: enable irq
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+void fts_irq_enable(void)
+{
+ unsigned long irqflags = 0;
+
+ spin_lock_irqsave(&fts_wq_data->irq_lock, irqflags);
+
+ if (fts_wq_data->irq_disable) {
+ enable_irq(fts_wq_data->client->irq);
+ fts_wq_data->irq_disable = 0;
+ }
+
+ spin_unlock_irqrestore(&fts_wq_data->irq_lock, irqflags);
+}
+
+/*****************************************************************************
+ * Name: fts_input_dev_init
+ * Brief: input dev init
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static int fts_input_dev_init(struct i2c_client *client,
+ struct fts_ts_data *data, struct input_dev *input_dev,
+ struct fts_ts_platform_data *pdata)
+{
+ int err, len;
+
+ FTS_FUNC_ENTER();
+
+ /* Init and register Input device */
+ input_dev->name = FTS_DRIVER_NAME;
+ input_dev->id.bustype = BUS_I2C;
+ input_dev->dev.parent = &client->dev;
+
+ input_set_drvdata(input_dev, data);
+ i2c_set_clientdata(client, data);
+
+ __set_bit(EV_KEY, input_dev->evbit);
+ if (data->pdata->have_key) {
+ FTS_DEBUG("set key capabilities");
+ for (len = 0; len < data->pdata->key_number; len++)
+ input_set_capability(input_dev, EV_KEY,
+ data->pdata->keys[len]);
+ }
+ __set_bit(EV_ABS, input_dev->evbit);
+ __set_bit(BTN_TOUCH, input_dev->keybit);
+ __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+
+#if FTS_MT_PROTOCOL_B_EN
+ input_mt_init_slots(input_dev, pdata->max_touch_number,
+ INPUT_MT_DIRECT);
+#else
+ input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0, 0x0f, 0, 0);
+#endif
+ input_set_abs_params(input_dev, ABS_MT_POSITION_X, pdata->x_min,
+ pdata->x_max, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_POSITION_Y, pdata->y_min,
+ pdata->y_max, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 0xFF, 0, 0);
+#if FTS_REPORT_PRESSURE_EN
+ input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, 0xFF, 0, 0);
+#endif
+
+ err = input_register_device(input_dev);
+ if (err) {
+ FTS_ERROR("Input device registration failed");
+ goto free_inputdev;
+ }
+
+ FTS_FUNC_EXIT();
+
+ return 0;
+
+free_inputdev:
+ input_free_device(input_dev);
+ FTS_FUNC_EXIT();
+ return err;
+
+}
+
+/*****************************************************************************
+ * Power Control
+ *****************************************************************************/
+#if FTS_POWER_SOURCE_CUST_EN
+static int fts_power_source_init(struct fts_ts_data *data)
+{
+ int rc;
+
+ FTS_FUNC_ENTER();
+
+ data->vdd = regulator_get(&data->client->dev, "vdd");
+ if (IS_ERR(data->vdd)) {
+ rc = PTR_ERR(data->vdd);
+ FTS_ERROR("Regulator get failed vdd rc=%d", rc);
+ }
+
+ if (regulator_count_voltages(data->vdd) > 0) {
+ rc = regulator_set_voltage(data->vdd, FTS_VTG_MIN_UV,
+ FTS_VTG_MAX_UV);
+ if (rc) {
+ FTS_ERROR("Regulator set_vtg failed vdd rc=%d", rc);
+ goto reg_vdd_put;
+ }
+ }
+
+ data->vcc_i2c = regulator_get(&data->client->dev, "vcc-i2c");
+ if (IS_ERR(data->vcc_i2c)) {
+ rc = PTR_ERR(data->vcc_i2c);
+ FTS_ERROR("Regulator get failed vcc-i2c rc=%d", rc);
+ goto reg_vdd_set_vtg;
+ }
+
+ if (regulator_count_voltages(data->vcc_i2c) > 0) {
+ rc = regulator_set_voltage(data->vcc_i2c, FTS_I2C_VTG_MIN_UV,
+ FTS_I2C_VTG_MAX_UV);
+ if (rc) {
+ FTS_ERROR("Regulator set_vtg failed vcc-i2c rc=%d",
+ rc);
+ goto reg_vcc_i2c_put;
+ }
+ }
+
+ FTS_FUNC_EXIT();
+ return 0;
+
+reg_vcc_i2c_put:
+ regulator_put(data->vcc_i2c);
+reg_vdd_set_vtg:
+ if (regulator_count_voltages(data->vdd) > 0)
+ regulator_set_voltage(data->vdd, 0, FTS_VTG_MAX_UV);
+reg_vdd_put:
+ regulator_put(data->vdd);
+ FTS_FUNC_EXIT();
+ return rc;
+}
+
+static int fts_power_source_ctrl(struct fts_ts_data *data, int enable)
+{
+ int rc;
+
+ FTS_FUNC_ENTER();
+ if (enable) {
+ rc = regulator_enable(data->vdd);
+ if (rc)
+ FTS_ERROR("Regulator vdd enable failed rc=%d", rc);
+
+ rc = regulator_enable(data->vcc_i2c);
+ if (rc)
+ FTS_ERROR("Regulator vcc_i2c enable failed rc=%d", rc);
+ } else {
+ rc = regulator_disable(data->vdd);
+ if (rc)
+ FTS_ERROR("Regulator vdd disable failed rc=%d", rc);
+
+ rc = regulator_disable(data->vcc_i2c);
+ if (rc)
+ FTS_ERROR("Regulator vcc_i2c disable failed rc=%d",
+ rc);
+ }
+ FTS_FUNC_EXIT();
+ return 0;
+}
+
+#endif
+
+
+/*****************************************************************************
+ * Reprot related
+ *****************************************************************************/
+/*****************************************************************************
+ * Name: fts_release_all_finger
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static void fts_release_all_finger(void)
+{
+#if FTS_MT_PROTOCOL_B_EN
+ unsigned int finger_count = 0;
+#endif
+
+ mutex_lock(&fts_wq_data->report_mutex);
+#if FTS_MT_PROTOCOL_B_EN
+ for (finger_count = 0;
+ finger_count < fts_wq_data->pdata->max_touch_number;
+ finger_count++) {
+ input_mt_slot(fts_input_dev, finger_count);
+ input_mt_report_slot_state(fts_input_dev, MT_TOOL_FINGER,
+ false);
+ }
+#else
+ input_mt_sync(fts_input_dev);
+#endif
+ input_report_key(fts_input_dev, BTN_TOUCH, 0);
+ input_sync(fts_input_dev);
+ mutex_unlock(&fts_wq_data->report_mutex);
+}
+
+
+#if (FTS_DEBUG_EN && (FTS_DEBUG_LEVEL == 2))
+static void fts_show_touch_buffer(u8 *buf, int point_num)
+{
+ int len = point_num * FTS_ONE_TCH_LEN;
+ int count = 0;
+ int i;
+
+ memset(g_sz_debug, 0, 1024);
+ if (len > (POINT_READ_BUF-3))
+ len = POINT_READ_BUF-3;
+ else if (len == 0) {
+ len += FTS_ONE_TCH_LEN;
+
+ count += snprintf(g_sz_debug, 1024, "%02X,%02X,%02X",
+ buf[0], buf[1], buf[2]);
+ for (i = 0; i < len; i++)
+ count += snprintf(g_sz_debug+count, 1024-count,
+ ",%02X", buf[i+3]);
+
+ FTS_DEBUG("buffer: %s", g_sz_debug);
+}
+#endif
+
+static int fts_input_dev_report_key_event(struct ts_event *event,
+ struct fts_ts_data *data)
+{
+ int i;
+
+ if (!data->pdata->have_key)
+ return -EINVAL;
+
+ if ((1 == event->touch_point || 1 == event->point_num) &&
+ (event->au16_y[0] == data->pdata->key_y_coord)) {
+
+ if (event->point_num == 0) {
+ FTS_DEBUG("Keys All Up!");
+ for (i = 0; i < data->pdata->key_number; i++) {
+ input_report_key(data->input_dev,
+ data->pdata->keys[i], 0);
+ }
+
+ input_sync(data->input_dev);
+ return 0;
+ }
+ for (i = 0; i < data->pdata->key_number; i++) {
+ if (event->au16_x[0] > (data->pdata->key_x_coords[i]
+ - FTS_KEY_WIDTH) && (event->au16_x[0] <
+ (data->pdata->key_x_coords[i]
+ + FTS_KEY_WIDTH))) {
+ if (event->au8_touch_event[i] == 0 ||
+ event->au8_touch_event[i] == 2) {
+ input_report_key(data->input_dev,
+ data->pdata->keys[i], 1);
+ FTS_DEBUG("Key%d(%d, %d) DOWN!",
+ i, event->au16_x[0],
+ event->au16_y[0]);
+ } else {
+ input_report_key(data->input_dev,
+ data->pdata->keys[i], 0);
+ FTS_DEBUG("Key%d(%d, %d) Up!",
+ i, event->au16_x[0],
+ event->au16_y[0]);
+ }
+ break;
+ }
+ }
+ input_sync(data->input_dev);
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+#if FTS_MT_PROTOCOL_B_EN
+static int fts_input_dev_report_b(struct ts_event *event,
+ struct fts_ts_data *data)
+{
+ int i = 0;
+ int uppoint = 0;
+ int touchs = 0;
+
+ for (i = 0; i < event->touch_point; i++) {
+ if (event->au8_finger_id[i] >= data->pdata->max_touch_number)
+ break;
+
+ input_mt_slot(data->input_dev, event->au8_finger_id[i]);
+
+ if (event->au8_touch_event[i] == FTS_TOUCH_DOWN ||
+ event->au8_touch_event[i] == FTS_TOUCH_CONTACT) {
+ input_mt_report_slot_state(data->input_dev,
+ MT_TOOL_FINGER, true);
+
+#if FTS_REPORT_PRESSURE_EN
+#if FTS_FORCE_TOUCH_EN
+ if (event->pressure[i] <= 0) {
+ FTS_ERROR("[B]Illegal pressure: %d",
+ event->pressure[i]);
+ event->pressure[i] = 1;
+ }
+#else
+ event->pressure[i] = 0x3f;
+#endif
+ input_report_abs(data->input_dev, ABS_MT_PRESSURE,
+ event->pressure[i]);
+#endif
+
+ if (event->area[i] <= 0) {
+ FTS_ERROR("[B]Illegal touch-major: %d",
+ event->area[i]);
+ event->area[i] = 1;
+ }
+ input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR,
+ event->area[i]);
+
+ input_report_abs(data->input_dev, ABS_MT_POSITION_X,
+ event->au16_x[i]);
+ input_report_abs(data->input_dev, ABS_MT_POSITION_Y,
+ event->au16_y[i]);
+ touchs |= BIT(event->au8_finger_id[i]);
+ data->touchs |= BIT(event->au8_finger_id[i]);
+
+#if FTS_REPORT_PRESSURE_EN
+ FTS_DEBUG("[B]P%d(%d, %d)[p:%d,tm:%d] DOWN!",
+ event->au8_finger_id[i],
+ event->au16_x[i], event->au16_y[i],
+ event->pressure[i], event->area[i]);
+#else
+ FTS_DEBUG("[B]P%d(%d, %d)[tm:%d] DOWN!",
+ event->au8_finger_id[i],
+ event->au16_x[i], event->au16_y[i],
+ event->area[i]);
+#endif
+ } else {
+ uppoint++;
+ input_mt_report_slot_state(data->input_dev,
+ MT_TOOL_FINGER, false);
+#if FTS_REPORT_PRESSURE_EN
+ input_report_abs(data->input_dev, ABS_MT_PRESSURE, 0);
+#endif
+ data->touchs &= ~BIT(event->au8_finger_id[i]);
+ FTS_DEBUG("[B]P%d UP!", event->au8_finger_id[i]);
+ }
+ }
+
+ if (unlikely(data->touchs ^ touchs)) {
+ for (i = 0; i < data->pdata->max_touch_number; i++) {
+ if (BIT(i) & (data->touchs ^ touchs)) {
+ FTS_DEBUG("[B]P%d UP!", i);
+ input_mt_slot(data->input_dev, i);
+ input_mt_report_slot_state(data->input_dev,
+ MT_TOOL_FINGER, false);
+#if FTS_REPORT_PRESSURE_EN
+ input_report_abs(data->input_dev,
+ ABS_MT_PRESSURE, 0);
+#endif
+ }
+ }
+ }
+
+ data->touchs = touchs;
+ if (event->touch_point == uppoint) {
+ FTS_DEBUG("Points All Up!");
+ input_report_key(data->input_dev, BTN_TOUCH, 0);
+ } else {
+ input_report_key(data->input_dev, BTN_TOUCH,
+ event->touch_point > 0);
+ }
+
+ input_sync(data->input_dev);
+
+ return 0;
+
+}
+
+#else
+static int fts_input_dev_report_a(struct ts_event *event,
+ struct fts_ts_data *data)
+{
+ int i = 0;
+ int uppoint = 0;
+ int touchs = 0;
+
+ for (i = 0; i < event->touch_point; i++) {
+
+ if (event->au8_touch_event[i] == FTS_TOUCH_DOWN ||
+ event->au8_touch_event[i] == FTS_TOUCH_CONTACT) {
+ input_report_abs(data->input_dev, ABS_MT_TRACKING_ID,
+ event->au8_finger_id[i]);
+#if FTS_REPORT_PRESSURE_EN
+#if FTS_FORCE_TOUCH_EN
+ if (event->pressure[i] <= 0) {
+ FTS_ERROR("[B]Illegal pressure: %d",
+ event->pressure[i]);
+ event->pressure[i] = 1;
+ }
+#else
+ event->pressure[i] = 0x3f;
+#endif
+ input_report_abs(data->input_dev, ABS_MT_PRESSURE,
+ event->pressure[i]);
+#endif
+
+ if (event->area[i] <= 0) {
+ FTS_ERROR("[B]Illegal touch-major: %d",
+ event->area[i]);
+ event->area[i] = 1;
+ }
+
+ input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR,
+ event->area[i]);
+
+ input_report_abs(data->input_dev, ABS_MT_POSITION_X,
+ event->au16_x[i]);
+ input_report_abs(data->input_dev, ABS_MT_POSITION_Y,
+ event->au16_y[i]);
+
+ input_mt_sync(data->input_dev);
+
+#if FTS_REPORT_PRESSURE_EN
+ FTS_DEBUG("[B]P%d(%d, %d)[p:%d,tm:%d] DOWN!",
+ event->au8_finger_id[i],
+ event->au16_x[i], event->au16_y[i],
+ event->pressure[i], event->area[i]);
+#else
+ FTS_DEBUG("[B]P%d(%d, %d)[tm:%d] DOWN!",
+ event->au8_finger_id[i],
+ event->au16_x[i], event->au16_y[i],
+ event->area[i]);
+#endif
+ } else {
+ uppoint++;
+ }
+ }
+
+ data->touchs = touchs;
+ if (event->touch_point == uppoint) {
+ FTS_DEBUG("Points All Up!");
+ input_report_key(data->input_dev, BTN_TOUCH, 0);
+ input_mt_sync(data->input_dev);
+ } else {
+ input_report_key(data->input_dev, BTN_TOUCH,
+ event->touch_point > 0);
+ }
+
+ input_sync(data->input_dev);
+
+ return 0;
+}
+#endif
+
+/*****************************************************************************
+ * Name: fts_read_touchdata
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static int fts_read_touchdata(struct fts_ts_data *data)
+{
+ u8 buf[POINT_READ_BUF] = { 0 };
+ u8 pointid = FTS_MAX_ID;
+ int ret = -1;
+ int i;
+ struct ts_event *event = &(data->event);
+
+#if FTS_GESTURE_EN
+ u8 state;
+
+ if (data->suspended) {
+ fts_i2c_read_reg(data->client, FTS_REG_GESTURE_EN, &state);
+ if (state == 1) {
+ fts_gesture_readdata(data->client);
+ return 1;
+ }
+ }
+#endif
+
+#if FTS_PSENSOR_EN
+ if ((fts_sensor_read_data(data) != 0) && (data->suspended == 1))
+ return 1;
+#endif
+
+
+#if FTS_READ_TOUCH_BUFFER_DIVIDED
+ memset(buf, 0xFF, POINT_READ_BUF);
+ memset(event, 0, sizeof(struct ts_event));
+
+ buf[0] = 0x00;
+ ret = fts_i2c_read(data->client, buf, 1, buf, (3 + FTS_ONE_TCH_LEN));
+ if (ret < 0) {
+ FTS_ERROR("%s read touchdata failed.", __func__);
+ return ret;
+ }
+ event->touch_point = 0;
+ event->point_num = buf[FTS_TOUCH_POINT_NUM] & 0x0F;
+ if (event->point_num > data->pdata->max_touch_number)
+ event->point_num = data->pdata->max_touch_number;
+
+ if (event->point_num > 1) {
+ buf[9] = 0x09;
+ fts_i2c_read(data->client, buf+9, 1, buf+9,
+ (event->point_num - 1) * FTS_ONE_TCH_LEN);
+ }
+#else
+ ret = fts_i2c_read(data->client, buf, 1, buf, POINT_READ_BUF);
+ if (ret < 0) {
+ FTS_ERROR("[B]Read touchdata failed, ret: %d", ret);
+ return ret;
+ }
+
+#if FTS_POINT_REPORT_CHECK_EN
+ fts_point_report_check_queue_work();
+#endif
+
+ memset(event, 0, sizeof(struct ts_event));
+ event->point_num = buf[FTS_TOUCH_POINT_NUM] & 0x0F;
+ if (event->point_num > data->pdata->max_touch_number)
+ event->point_num = data->pdata->max_touch_number;
+ event->touch_point = 0;
+#endif
+
+#if (FTS_DEBUG_EN && (FTS_DEBUG_LEVEL == 2))
+ fts_show_touch_buffer(buf, event->point_num);
+#endif
+
+ for (i = 0; i < data->pdata->max_touch_number; i++) {
+ pointid = (buf[FTS_TOUCH_ID_POS + FTS_ONE_TCH_LEN * i]) >> 4;
+ if (pointid >= FTS_MAX_ID)
+ break;
+
+ event->touch_point++;
+
+ event->au16_x[i] =
+ (s16) (buf[FTS_TOUCH_X_H_POS + FTS_ONE_TCH_LEN * i]
+ & 0x0F) << 8 | (s16) buf[FTS_TOUCH_X_L_POS +
+ FTS_ONE_TCH_LEN * i];
+ event->au16_y[i] =
+ (s16) (buf[FTS_TOUCH_Y_H_POS + FTS_ONE_TCH_LEN * i]
+ & 0x0F) << 8 | (s16) buf[FTS_TOUCH_Y_L_POS +
+ FTS_ONE_TCH_LEN * i];
+ event->au8_touch_event[i] =
+ buf[FTS_TOUCH_EVENT_POS + FTS_ONE_TCH_LEN * i] >> 6;
+ event->au8_finger_id[i] =
+ (buf[FTS_TOUCH_ID_POS + FTS_ONE_TCH_LEN * i]) >> 4;
+ event->area[i] =
+ (buf[FTS_TOUCH_AREA_POS + FTS_ONE_TCH_LEN * i]) >> 4;
+ event->pressure[i] =
+ (s16) buf[FTS_TOUCH_PRE_POS + FTS_ONE_TCH_LEN * i];
+
+ if (event->area[i] == 0)
+ event->area[i] = 0x09;
+
+ if (event->pressure[i] == 0)
+ event->pressure[i] = 0x3f;
+
+ if ((event->au8_touch_event[i] == 0 ||
+ event->au8_touch_event[i] == 2) &&
+ (event->point_num == 0)) {
+ FTS_DEBUG("abnormal touch data from fw");
+ return -EINVAL;
+ }
+ }
+
+ if (event->touch_point == 0)
+ return -EINVAL;
+
+ return 0;
+}
+
+/*****************************************************************************
+ * Name: fts_report_value
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static void fts_report_value(struct fts_ts_data *data)
+{
+ struct ts_event *event = &data->event;
+
+
+ FTS_DEBUG("point number: %d, touch point: %d", event->point_num,
+ event->touch_point);
+
+ if (fts_input_dev_report_key_event(event, data) == 0)
+ return;
+
+#if FTS_MT_PROTOCOL_B_EN
+ fts_input_dev_report_b(event, data);
+#else
+ fts_input_dev_report_a(event, data);
+#endif
+
+
+ return;
+
+}
+
+/*****************************************************************************
+ * Name: fts_ts_interrupt
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static irqreturn_t fts_ts_interrupt(int irq, void *dev_id)
+{
+ struct fts_ts_data *fts_ts = dev_id;
+ int ret = -1;
+
+ if (!fts_ts) {
+ FTS_ERROR("[INTR]: Invalid fts_ts");
+ return IRQ_HANDLED;
+ }
+
+#if FTS_ESDCHECK_EN
+ fts_esdcheck_set_intr(1);
+#endif
+
+ ret = fts_read_touchdata(fts_wq_data);
+
+ if (ret == 0) {
+ mutex_lock(&fts_wq_data->report_mutex);
+ fts_report_value(fts_wq_data);
+ mutex_unlock(&fts_wq_data->report_mutex);
+ }
+
+#if FTS_ESDCHECK_EN
+ fts_esdcheck_set_intr(0);
+#endif
+
+ return IRQ_HANDLED;
+}
+
+/*****************************************************************************
+ * Name: fts_gpio_configure
+ * Brief: Configure IRQ&RESET GPIO
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static int fts_gpio_configure(struct fts_ts_data *data)
+{
+ int err = 0;
+
+ FTS_FUNC_ENTER();
+ /* request irq gpio */
+ if (gpio_is_valid(data->pdata->irq_gpio)) {
+ err = gpio_request(data->pdata->irq_gpio, "fts_irq_gpio");
+ if (err) {
+ FTS_ERROR("[GPIO]irq gpio request failed");
+ goto err_irq_gpio_req;
+ }
+
+ err = gpio_direction_input(data->pdata->irq_gpio);
+ if (err) {
+ FTS_ERROR("[GPIO]set_direction for irq gpio failed");
+ goto err_irq_gpio_dir;
+ }
+ }
+ /* request reset gpio */
+ if (gpio_is_valid(data->pdata->reset_gpio)) {
+ err = gpio_request(data->pdata->reset_gpio, "fts_reset_gpio");
+ if (err) {
+ FTS_ERROR("[GPIO]reset gpio request failed");
+ goto err_irq_gpio_dir;
+ }
+
+ err = gpio_direction_output(data->pdata->reset_gpio, 1);
+ if (err) {
+ FTS_ERROR("[GPIO]set_direction for reset gpio failed");
+ goto err_reset_gpio_dir;
+ }
+ }
+
+ FTS_FUNC_EXIT();
+ return 0;
+
+err_reset_gpio_dir:
+ if (gpio_is_valid(data->pdata->reset_gpio))
+ gpio_free(data->pdata->reset_gpio);
+err_irq_gpio_dir:
+ if (gpio_is_valid(data->pdata->irq_gpio))
+ gpio_free(data->pdata->irq_gpio);
+err_irq_gpio_req:
+ FTS_FUNC_EXIT();
+ return err;
+}
+
+
+/*****************************************************************************
+ * Name: fts_get_dt_coords
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static int fts_get_dt_coords(struct device *dev, char *name,
+ struct fts_ts_platform_data *pdata)
+{
+ u32 coords[FTS_COORDS_ARR_SIZE];
+ struct property *prop;
+ struct device_node *np = dev->of_node;
+ int coords_size, rc;
+
+ prop = of_find_property(np, name, NULL);
+ if (!prop)
+ return -EINVAL;
+ if (!prop->value)
+ return -ENODATA;
+
+
+ coords_size = prop->length / sizeof(u32);
+ if (coords_size != FTS_COORDS_ARR_SIZE) {
+ FTS_ERROR("invalid %s", name);
+ return -EINVAL;
+ }
+
+ rc = of_property_read_u32_array(np, name, coords, coords_size);
+ if (rc && (rc != -EINVAL)) {
+ FTS_ERROR("Unable to read %s", name);
+ return rc;
+ }
+
+ if (!strcmp(name, "focaltech,display-coords")) {
+ pdata->x_min = coords[0];
+ pdata->y_min = coords[1];
+ pdata->x_max = coords[2];
+ pdata->y_max = coords[3];
+ } else {
+ FTS_ERROR("unsupported property %s", name);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+ * Name: fts_parse_dt
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static int fts_parse_dt(struct device *dev, struct fts_ts_platform_data *pdata)
+{
+ int rc;
+ struct device_node *np = dev->of_node;
+ u32 temp_val;
+
+ FTS_FUNC_ENTER();
+
+ rc = fts_get_dt_coords(dev, "focaltech,display-coords", pdata);
+ if (rc)
+ FTS_ERROR("Unable to get display-coords");
+
+ /* key */
+ pdata->have_key = of_property_read_bool(np, "focaltech,have-key");
+ if (pdata->have_key) {
+ rc = of_property_read_u32(np, "focaltech,key-number",
+ &pdata->key_number);
+ if (rc)
+ FTS_ERROR("Key number undefined!");
+
+ rc = of_property_read_u32_array(np, "focaltech,keys",
+ pdata->keys, pdata->key_number);
+ if (rc)
+ FTS_ERROR("Keys undefined!");
+
+ rc = of_property_read_u32(np, "focaltech,key-y-coord",
+ &pdata->key_y_coord);
+ if (rc)
+ FTS_ERROR("Key Y Coord undefined!");
+
+ rc = of_property_read_u32_array(np, "focaltech,key-x-coords",
+ pdata->key_x_coords, pdata->key_number);
+ if (rc)
+ FTS_ERROR("Key X Coords undefined!");
+
+ FTS_DEBUG("%d: (%d, %d, %d), [%d, %d, %d][%d]",
+ pdata->key_number, pdata->keys[0],
+ pdata->keys[1], pdata->keys[2],
+ pdata->key_x_coords[0],
+ pdata->key_x_coords[1],
+ pdata->key_x_coords[2],
+ pdata->key_y_coord);
+ }
+
+ /* reset, irq gpio info */
+ pdata->reset_gpio = of_get_named_gpio_flags(np,
+ "focaltech,reset-gpio", 0,
+ &pdata->reset_gpio_flags);
+ if (pdata->reset_gpio < 0)
+ FTS_ERROR("Unable to get reset_gpio");
+
+ pdata->irq_gpio = of_get_named_gpio_flags(np, "focaltech,irq-gpio",
+ 0, &pdata->irq_gpio_flags);
+ if (pdata->irq_gpio < 0)
+ FTS_ERROR("Unable to get irq_gpio");
+
+ rc = of_property_read_u32(np, "focaltech,max-touch-number", &temp_val);
+ if (!rc) {
+ pdata->max_touch_number = temp_val;
+ FTS_DEBUG("max_touch_number=%d", pdata->max_touch_number);
+ } else {
+ FTS_ERROR("Unable to get max-touch-number");
+ pdata->max_touch_number = FTS_MAX_POINTS;
+ }
+
+
+ FTS_FUNC_EXIT();
+ return 0;
+}
+
+#if defined(CONFIG_FB)
+/*****************************************************************************
+ * Name: fb_notifier_callback
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static int fb_notifier_callback(struct notifier_block *self,
+ unsigned long event, void *data)
+{
+ struct fb_event *evdata = data;
+ int *blank;
+ struct fts_ts_data *fts_data =
+ container_of(self, struct fts_ts_data, fb_notif);
+
+ if (evdata && evdata->data && event == FB_EVENT_BLANK &&
+ fts_data && fts_data->client) {
+ blank = evdata->data;
+ if (*blank == FB_BLANK_UNBLANK)
+ fts_ts_resume(&fts_data->client->dev);
+ else if (*blank == FB_BLANK_POWERDOWN ||
+ *blank == FB_BLANK_VSYNC_SUSPEND)
+ fts_ts_suspend(&fts_data->client->dev);
+ }
+
+ return 0;
+}
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+/*****************************************************************************
+ * Name: fts_ts_early_suspend
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static void fts_ts_early_suspend(struct early_suspend *handler)
+{
+ struct fts_ts_data *data = container_of(handler,
+ struct fts_ts_data,
+ early_suspend);
+
+ fts_ts_suspend(&data->client->dev);
+}
+
+/*****************************************************************************
+ * Name: fts_ts_late_resume
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static void fts_ts_late_resume(struct early_suspend *handler)
+{
+ struct fts_ts_data *data = container_of(handler,
+ struct fts_ts_data,
+ early_suspend);
+
+ fts_ts_resume(&data->client->dev);
+}
+#endif
+
+/*****************************************************************************
+ * Name: fts_ts_probe
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static int fts_ts_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct fts_ts_platform_data *pdata;
+ struct fts_ts_data *data;
+ struct input_dev *input_dev;
+ int err;
+
+ FTS_FUNC_ENTER();
+ /* 1. Get Platform data */
+ if (client->dev.of_node) {
+ pdata = devm_kzalloc(&client->dev,
+ sizeof(struct fts_ts_platform_data),
+ GFP_KERNEL);
+ if (!pdata) {
+ FTS_ERROR("[MEMORY]Failed to allocate memory");
+ FTS_FUNC_EXIT();
+ return -ENOMEM;
+ }
+
+ err = fts_parse_dt(&client->dev, pdata);
+ if (err)
+ FTS_ERROR("[DTS]DT parsing failed");
+ } else {
+ pdata = client->dev.platform_data;
+ }
+
+ if (!pdata) {
+ FTS_ERROR("Invalid pdata");
+ FTS_FUNC_EXIT();
+ return -EINVAL;
+ }
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ FTS_ERROR("I2C not supported");
+ FTS_FUNC_EXIT();
+ return -ENODEV;
+ }
+
+ data = devm_kzalloc(&client->dev, sizeof(struct fts_ts_data),
+ GFP_KERNEL);
+ if (!data) {
+ FTS_ERROR("[MEMORY]Failed to allocate memory");
+ FTS_FUNC_EXIT();
+ return -ENOMEM;
+ }
+
+ input_dev = input_allocate_device();
+ if (!input_dev) {
+ FTS_ERROR("[INPUT]Failed to allocate input device");
+ FTS_FUNC_EXIT();
+ return -ENOMEM;
+ }
+
+ data->input_dev = input_dev;
+ data->client = client;
+ data->pdata = pdata;
+
+ fts_wq_data = data;
+ fts_i2c_client = client;
+ fts_input_dev = input_dev;
+
+ spin_lock_init(&fts_wq_data->irq_lock);
+ mutex_init(&fts_wq_data->report_mutex);
+
+ fts_input_dev_init(client, data, input_dev, pdata);
+
+#if FTS_POWER_SOURCE_CUST_EN
+ fts_power_source_init(data);
+ fts_power_source_ctrl(data, 1);
+#endif
+
+ fts_ctpm_get_upgrade_array();
+
+ err = fts_gpio_configure(data);
+ if (err < 0) {
+ FTS_ERROR("[GPIO]Failed to configure the gpios");
+ goto free_gpio;
+ }
+
+ fts_reset_proc(200);
+ fts_wait_tp_to_valid(client);
+
+ err = request_threaded_irq(client->irq, NULL, fts_ts_interrupt,
+ pdata->irq_gpio_flags | IRQF_ONESHOT |
+ IRQF_TRIGGER_FALLING,
+ client->dev.driver->name, data);
+ if (err) {
+ FTS_ERROR("Request irq failed!");
+ goto free_gpio;
+ }
+
+ fts_irq_disable();
+
+#if FTS_PSENSOR_EN
+ if (fts_sensor_init(data) != 0) {
+ FTS_ERROR("fts_sensor_init failed!");
+ FTS_FUNC_EXIT();
+ return 0;
+ }
+#endif
+
+#if FTS_APK_NODE_EN
+ fts_create_apk_debug_channel(client);
+#endif
+
+#if FTS_SYSFS_NODE_EN
+ fts_create_sysfs(client);
+#endif
+
+#if FTS_POINT_REPORT_CHECK_EN
+ fts_point_report_check_init();
+#endif
+
+ fts_ex_mode_init(client);
+
+#if FTS_GESTURE_EN
+ fts_gesture_init(input_dev, client);
+#endif
+
+#if FTS_ESDCHECK_EN
+ fts_esdcheck_init();
+#endif
+
+ fts_irq_enable();
+
+#if FTS_AUTO_UPGRADE_EN
+ fts_ctpm_upgrade_init();
+#endif
+
+#if FTS_TEST_EN
+ fts_test_init(client);
+#endif
+
+#if defined(CONFIG_FB)
+ data->fb_notif.notifier_call = fb_notifier_callback;
+ err = fb_register_client(&data->fb_notif);
+ if (err)
+ FTS_ERROR("[FB]Unable to register fb_notifier: %d", err);
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+ data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN +
+ FTS_SUSPEND_LEVEL;
+ data->early_suspend.suspend = fts_ts_early_suspend;
+ data->early_suspend.resume = fts_ts_late_resume;
+ register_early_suspend(&data->early_suspend);
+#endif
+
+ FTS_FUNC_EXIT();
+ return 0;
+
+free_gpio:
+ if (gpio_is_valid(pdata->reset_gpio))
+ gpio_free(pdata->reset_gpio);
+ if (gpio_is_valid(pdata->irq_gpio))
+ gpio_free(pdata->irq_gpio);
+ return err;
+
+}
+
+/*****************************************************************************
+ * Name: fts_ts_remove
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static int fts_ts_remove(struct i2c_client *client)
+{
+ struct fts_ts_data *data = i2c_get_clientdata(client);
+
+ FTS_FUNC_ENTER();
+ cancel_work_sync(&data->touch_event_work);
+
+#if FTS_PSENSOR_EN
+ fts_sensor_remove(data);
+#endif
+
+#if FTS_POINT_REPORT_CHECK_EN
+ fts_point_report_check_exit();
+#endif
+
+#if FTS_APK_NODE_EN
+ fts_release_apk_debug_channel();
+#endif
+
+#if FTS_SYSFS_NODE_EN
+ fts_remove_sysfs(client);
+#endif
+
+ fts_ex_mode_exit(client);
+
+#if FTS_AUTO_UPGRADE_EN
+ cancel_work_sync(&fw_update_work);
+#endif
+
+#if defined(CONFIG_FB)
+ if (fb_unregister_client(&data->fb_notif))
+ FTS_ERROR("Error occurred while unregistering fb_notifier.");
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+ unregister_early_suspend(&data->early_suspend);
+#endif
+ free_irq(client->irq, data);
+
+ if (gpio_is_valid(data->pdata->reset_gpio))
+ gpio_free(data->pdata->reset_gpio);
+
+ if (gpio_is_valid(data->pdata->irq_gpio))
+ gpio_free(data->pdata->irq_gpio);
+
+ input_unregister_device(data->input_dev);
+
+#if FTS_TEST_EN
+ fts_test_exit(client);
+#endif
+
+#if FTS_ESDCHECK_EN
+ fts_esdcheck_exit();
+#endif
+
+ FTS_FUNC_EXIT();
+ return 0;
+}
+
+/*****************************************************************************
+ * Name: fts_ts_suspend
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static int fts_ts_suspend(struct device *dev)
+{
+ struct fts_ts_data *data = dev_get_drvdata(dev);
+ int retval = 0;
+
+ FTS_FUNC_ENTER();
+ if (data->suspended) {
+ FTS_INFO("Already in suspend state");
+ FTS_FUNC_EXIT();
+ return -EINVAL;
+ }
+
+#if FTS_ESDCHECK_EN
+ fts_esdcheck_suspend();
+#endif
+
+#if FTS_GESTURE_EN
+ retval = fts_gesture_suspend(data->client);
+ if (retval == 0) {
+ /* Enter into gesture mode(suspend) */
+ retval = enable_irq_wake(fts_wq_data->client->irq);
+ if (retval)
+ FTS_ERROR("%s: set_irq_wake failed", __func__);
+ data->suspended = true;
+ FTS_FUNC_EXIT();
+ return 0;
+ }
+#endif
+
+#if FTS_PSENSOR_EN
+ if (fts_sensor_suspend(data) != 0) {
+ enable_irq_wake(data->client->irq);
+ data->suspended = true;
+ return 0;
+ }
+#endif
+
+ fts_irq_disable();
+
+ /* TP enter sleep mode */
+ retval = fts_i2c_write_reg(data->client, FTS_REG_POWER_MODE,
+ FTS_REG_POWER_MODE_SLEEP_VALUE);
+ if (retval < 0)
+ FTS_ERROR("Set TP to sleep mode fail, ret=%d!", retval);
+
+ data->suspended = true;
+
+ FTS_FUNC_EXIT();
+
+ return 0;
+}
+
+/*****************************************************************************
+ * Name: fts_ts_resume
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static int fts_ts_resume(struct device *dev)
+{
+ struct fts_ts_data *data = dev_get_drvdata(dev);
+
+ FTS_FUNC_ENTER();
+ if (!data->suspended) {
+ FTS_DEBUG("Already in awake state");
+ FTS_FUNC_EXIT();
+ return -EINVAL;
+ }
+
+ fts_release_all_finger();
+
+#if (!FTS_CHIP_IDC)
+ fts_reset_proc(200);
+#endif
+
+ fts_tp_state_recovery(data->client);
+
+#if FTS_ESDCHECK_EN
+ fts_esdcheck_resume();
+#endif
+
+#if FTS_GESTURE_EN
+ if (fts_gesture_resume(data->client) == 0) {
+ int err;
+
+ err = disable_irq_wake(data->client->irq);
+ if (err)
+ FTS_ERROR("%s: disable_irq_wake failed", __func__);
+ data->suspended = false;
+ FTS_FUNC_EXIT();
+ return 0;
+ }
+#endif
+
+#if FTS_PSENSOR_EN
+ if (fts_sensor_resume(data) != 0) {
+ disable_irq_wake(data->client->irq);
+ data->suspended = false;
+ FTS_FUNC_EXIT();
+ return 0;
+ }
+#endif
+
+ data->suspended = false;
+
+ fts_irq_enable();
+
+ FTS_FUNC_EXIT();
+ return 0;
+}
+
+/*****************************************************************************
+ * I2C Driver
+ *****************************************************************************/
+static const struct i2c_device_id fts_ts_id[] = {
+ {FTS_DRIVER_NAME, 0},
+ {},
+};
+MODULE_DEVICE_TABLE(i2c, fts_ts_id);
+
+static const struct of_device_id fts_match_table[] = {
+ { .compatible = "focaltech,fts", },
+ { },
+};
+
+static struct i2c_driver fts_ts_driver = {
+ .probe = fts_ts_probe,
+ .remove = fts_ts_remove,
+ .driver = {
+ .name = FTS_DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = fts_match_table,
+ },
+ .id_table = fts_ts_id,
+};
+
+/*****************************************************************************
+ * Name: fts_ts_init
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static int __init fts_ts_init(void)
+{
+ int ret = 0;
+
+ FTS_FUNC_ENTER();
+ ret = i2c_add_driver(&fts_ts_driver);
+ if (ret != 0)
+ FTS_ERROR("Focaltech touch screen driver init failed!");
+
+ FTS_FUNC_EXIT();
+ return ret;
+}
+
+/*****************************************************************************
+ * Name: fts_ts_exit
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static void __exit fts_ts_exit(void)
+{
+ i2c_del_driver(&fts_ts_driver);
+}
+
+module_init(fts_ts_init);
+module_exit(fts_ts_exit);
+
+MODULE_DESCRIPTION("FocalTech Touchscreen Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_core.h b/drivers/input/touchscreen/focaltech_touch/focaltech_core.h
new file mode 100644
index 0000000..52b4ffe
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_core.h
@@ -0,0 +1,194 @@
+/*
+ *
+ * FocalTech TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, Focaltech Ltd. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+/*****************************************************************************
+ *
+ * File Name: focaltech_core.h
+ *
+ * Author: Focaltech Driver Team
+ *
+ * Created: 2016-08-08
+ *
+ * Abstract:
+ *
+ * Reference:
+ *
+ *****************************************************************************/
+
+#ifndef __LINUX_FOCALTECH_CORE_H__
+#define __LINUX_FOCALTECH_CORE_H__
+/*****************************************************************************
+ * Included header files
+ *****************************************************************************/
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/input/mt.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/regulator/consumer.h>
+#include <linux/firmware.h>
+#include <linux/debugfs.h>
+#include <linux/mutex.h>
+#include <linux/wait.h>
+#include <linux/time.h>
+#include <linux/workqueue.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <linux/uaccess.h>
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/kthread.h>
+#include <linux/init.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/mount.h>
+#include <linux/netdevice.h>
+#include <linux/unistd.h>
+#include <linux/ioctl.h>
+#include "focaltech_common.h"
+#include "focaltech_flash.h"
+#if FTS_PSENSOR_EN
+#include <linux/sensors.h>
+#endif
+/*****************************************************************************
+ * Private constant and macro definitions using #define
+ *****************************************************************************/
+#define LEN_FLASH_ECC_MAX 0xFFFE
+
+#define FTS_WORKQUEUE_NAME "fts_wq"
+
+#define FTS_MAX_POINTS 10
+#define FTS_KEY_WIDTH 50
+#define FTS_ONE_TCH_LEN 6
+#define POINT_READ_BUF (3 + FTS_ONE_TCH_LEN * FTS_MAX_POINTS)
+
+#define FTS_MAX_ID 0x0F
+#define FTS_TOUCH_X_H_POS 3
+#define FTS_TOUCH_X_L_POS 4
+#define FTS_TOUCH_Y_H_POS 5
+#define FTS_TOUCH_Y_L_POS 6
+#define FTS_TOUCH_PRE_POS 7
+#define FTS_TOUCH_AREA_POS 8
+#define FTS_TOUCH_POINT_NUM 2
+#define FTS_TOUCH_EVENT_POS 3
+#define FTS_TOUCH_ID_POS 5
+#define FTS_COORDS_ARR_SIZE 4
+
+#define FTS_TOUCH_DOWN 0
+#define FTS_TOUCH_UP 1
+#define FTS_TOUCH_CONTACT 2
+
+#define FTS_SYSFS_ECHO_ON(buf) ((strnicmp(buf, "1", 1) == 0) || \
+ (strnicmp(buf, "on", 2) == 0))
+#define FTS_SYSFS_ECHO_OFF(buf) ((strnicmp(buf, "0", 1) == 0) || \
+ (strnicmp(buf, "off", 3) == 0))
+
+/*****************************************************************************
+ * Private enumerations, structures and unions using typedef
+ *****************************************************************************/
+
+
+struct fts_ts_platform_data {
+ int irq_gpio;
+ u32 irq_gpio_flags;
+ int reset_gpio;
+ u32 reset_gpio_flags;
+ bool have_key;
+ u32 key_number;
+ u32 keys[4];
+ u32 key_y_coord;
+ u32 key_x_coords[4];
+ u32 x_max;
+ u32 y_max;
+ u32 x_min;
+ u32 y_min;
+ u32 max_touch_number;
+};
+
+struct ts_event {
+ u16 au16_x[FTS_MAX_POINTS]; /*x coordinate */
+ u16 au16_y[FTS_MAX_POINTS]; /*y coordinate */
+ u16 pressure[FTS_MAX_POINTS];
+ u8 au8_touch_event[FTS_MAX_POINTS]; /* touch event:
+ * 0 -- down;
+ * 1 -- up;
+ * 2 -- contact
+ */
+ u8 au8_finger_id[FTS_MAX_POINTS]; /* touch ID */
+ u8 area[FTS_MAX_POINTS];
+ u8 touch_point;
+ u8 point_num;
+};
+
+struct fts_ts_data {
+ struct i2c_client *client;
+ struct input_dev *input_dev;
+ struct ts_event event;
+ const struct fts_ts_platform_data *pdata;
+#if FTS_PSENSOR_EN
+ struct fts_psensor_platform_data *psensor_pdata;
+#endif
+ struct work_struct touch_event_work;
+ struct workqueue_struct *ts_workqueue;
+ struct regulator *vdd;
+ struct regulator *vcc_i2c;
+ spinlock_t irq_lock;
+ struct mutex report_mutex;
+ u16 addr;
+ bool suspended;
+ u8 fw_ver[3];
+ u8 fw_vendor_id;
+ int touchs;
+ int irq_disable;
+
+#if defined(CONFIG_FB)
+ struct notifier_block fb_notif;
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+ struct early_suspend early_suspend;
+#endif
+};
+
+
+#if FTS_PSENSOR_EN
+struct fts_psensor_platform_data {
+ struct input_dev *input_psensor_dev;
+ struct sensors_classdev ps_cdev;
+ int tp_psensor_opened;
+ char tp_psensor_data; /* 0 near, 1 far */
+ struct fts_ts_data *data;
+};
+
+int fts_sensor_init(struct fts_ts_data *data);
+int fts_sensor_read_data(struct fts_ts_data *data);
+int fts_sensor_suspend(struct fts_ts_data *data);
+int fts_sensor_resume(struct fts_ts_data *data);
+int fts_sensor_remove(struct fts_ts_data *data);
+#endif
+
+/*****************************************************************************
+ * Static variables
+ *****************************************************************************/
+extern struct i2c_client *fts_i2c_client;
+extern struct fts_ts_data *fts_wq_data;
+extern struct input_dev *fts_input_dev;
+
+#endif /* __LINUX_FOCALTECH_CORE_H__ */
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_esdcheck.c b/drivers/input/touchscreen/focaltech_touch/focaltech_esdcheck.c
new file mode 100644
index 0000000..0b2fc53
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_esdcheck.c
@@ -0,0 +1,478 @@
+/*
+ *
+ * FocalTech TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, FocalTech Systems, Ltd., all rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/*****************************************************************************
+ *
+ * File Name: focaltech_esdcheck.c
+ *
+ * Author: luoguojin
+ *
+ * Created: 2016-08-03
+ *
+ * Abstract: ESD check function
+ *
+ * Version: v1.0
+ *
+ * Revision History:
+ * v1.0:
+ * First release. By luougojin 2016-08-03
+ * v1.1: By luougojin 2017-02-15
+ * 1. Add LCD_ESD_PATCH to control idc_esdcheck_lcderror
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Included header files
+ *****************************************************************************/
+#include "focaltech_core.h"
+
+#if FTS_ESDCHECK_EN
+/*****************************************************************************
+ * Private constant and macro definitions using #define
+ *****************************************************************************/
+#define ESDCHECK_WAIT_TIME 1000 /* ms */
+#define LCD_ESD_PATCH 0
+
+/*****************************************************************************
+ * Private enumerations, structures and unions using typedef
+ *****************************************************************************/
+struct fts_esdcheck_st {
+ u8 active : 1; /* 1- esd check active, need check esd
+ * 0- no esd check
+ */
+ u8 suspend : 1;
+ u8 proc_debug : 1; /* apk or adb is accessing I2C */
+ u8 intr : 1; /* 1- Interrupt trigger */
+ u8 unused : 4;
+ u8 flow_work_hold_cnt; /* Flow Work Cnt(reg0x91)
+ * keep a same value for x times.
+ * >=5 times is ESD, need reset
+ */
+ u8 flow_work_cnt_last; /* Save Flow Work Cnt(reg0x91) value */
+ u32 hardware_reset_cnt;
+ u32 i2c_nack_cnt;
+ u32 i2c_dataerror_cnt;
+};
+
+/*****************************************************************************
+ * Static variables
+ *****************************************************************************/
+static struct delayed_work fts_esdcheck_work;
+static struct workqueue_struct *fts_esdcheck_workqueue;
+static struct fts_esdcheck_st fts_esdcheck_data;
+
+/*****************************************************************************
+ * Global variable or extern global variabls/functions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Static function prototypes
+ *****************************************************************************/
+
+/*****************************************************************************
+ * functions body
+ *****************************************************************************/
+#if LCD_ESD_PATCH
+/*****************************************************************************
+ * Name: lcd_esdcheck
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+int lcd_need_reset;
+static int tp_need_recovery; /* LCD reset cause Tp reset */
+int idc_esdcheck_lcderror(void)
+{
+ u8 val;
+ int ret;
+
+ FTS_DEBUG("[ESD]Check LCD ESD");
+ if ((tp_need_recovery == 1) && (lcd_need_reset == 0)) {
+ tp_need_recovery = 0;
+ /* LCD reset, need recover TP state */
+ fts_tp_state_recovery(fts_i2c_client);
+ }
+
+ ret = fts_i2c_read_reg(fts_i2c_client, FTS_REG_ESD_SATURATE, &val);
+ if (ret < 0) {
+ FTS_ERROR("[ESD]: Read ESD_SATURATE(0xED) failed ret=%d", ret);
+ return -EIO;
+ }
+
+ if (val == 0xAA) {
+ /*
+ * 1. Set flag lcd_need_reset = 1;
+ * 2. LCD driver need reset(recovery) LCD and
+ * set lcd_need_reset to 0
+ * 3. recover TP state
+ */
+ FTS_INFO("LCD ESD, Execute LCD reset!");
+ lcd_need_reset = 1;
+ tp_need_recovery = 1;
+ }
+
+ return 0;
+}
+#endif
+
+/*****************************************************************************
+ * Name: fts_esdcheck_tp_reset
+ * Brief: esd check algorithm
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static int fts_esdcheck_tp_reset(void)
+{
+ FTS_FUNC_ENTER();
+
+ fts_esdcheck_data.flow_work_hold_cnt = 0;
+ fts_esdcheck_data.hardware_reset_cnt++;
+
+ fts_reset_proc(200);
+ fts_tp_state_recovery(fts_i2c_client);
+
+ FTS_FUNC_EXIT();
+ return 0;
+}
+
+/*****************************************************************************
+ * Name: get_chip_id
+ * Brief: Read Chip Id 3 times
+ * Input:
+ * Output:
+ * Return: 1 - Read Chip Id 3 times failed
+ * 0 - Read Chip Id pass
+ *****************************************************************************/
+static bool get_chip_id(void)
+{
+ int err = 0;
+ int i = 0;
+ u8 reg_value = 0;
+ u8 reg_addr = 0;
+
+ for (i = 0; i < 3; i++) {
+ reg_addr = FTS_REG_CHIP_ID;
+ err = fts_i2c_read(fts_i2c_client, ®_addr, 1,
+ ®_value, 1);
+
+ if (err < 0) {
+ FTS_ERROR("[ESD]: Read Reg 0xA3 failed ret = %d!!",
+ err);
+ fts_esdcheck_data.i2c_nack_cnt++;
+ } else {
+ /* Upgrade sometimes can't detect */
+ if ((reg_value == chip_types.chip_idh)
+ || (reg_value == 0xEF))
+ break;
+
+ fts_esdcheck_data.i2c_dataerror_cnt++;
+ }
+ }
+
+ /* if can't get correct data in 3 times, then need hardware reset */
+ if (i >= 3) {
+ FTS_ERROR("[ESD]: Read Chip id failed, need TP reset!!");
+ return 1;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+ * Name: get_flow_cnt
+ * Brief: Read flow cnt(0x91)
+ * Input:
+ * Output:
+ * Return: 1 - Reg 0x91(flow cnt) abnormal: hold a value for 5 times
+ * 0 - Reg 0x91(flow cnt) normal
+ *****************************************************************************/
+static bool get_flow_cnt(void)
+{
+ int err = 0;
+ u8 reg_value = 0;
+ u8 reg_addr = 0;
+
+ reg_addr = FTS_REG_FLOW_WORK_CNT;
+ err = fts_i2c_read(fts_i2c_client, ®_addr, 1, ®_value, 1);
+ if (err < 0) {
+ FTS_ERROR("[ESD]: Read Reg 0x91 failed ret = %d!!", err);
+ fts_esdcheck_data.i2c_nack_cnt++;
+ } else {
+ if (reg_value == fts_esdcheck_data.flow_work_cnt_last)
+ fts_esdcheck_data.flow_work_hold_cnt++;
+ else
+ fts_esdcheck_data.flow_work_hold_cnt = 0;
+
+ fts_esdcheck_data.flow_work_cnt_last = reg_value;
+ }
+
+ /* if read flow work cnt 5 times and the value are all the same,
+ * then need hardware_reset.
+ */
+ if (fts_esdcheck_data.flow_work_hold_cnt >= 5) {
+ FTS_DEBUG("[ESD]: Flow Work Cnt, need execute TP reset!!");
+ return 1;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+ * Name: esdcheck_algorithm
+ * Brief: esd check algorithm
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static int esdcheck_algorithm(void)
+{
+ int err = 0;
+ u8 reg_value = 0;
+ u8 reg_addr = 0;
+ bool hardware_reset = 0;
+
+ /* 1. esdcheck is interrupt, then return */
+ if (fts_esdcheck_data.intr == 1) {
+ FTS_INFO("[ESD]: In interrupt state, not check esd, return!!");
+ return 0;
+ }
+
+ /* 2. check power state, if suspend, no need check esd */
+ if (fts_esdcheck_data.suspend == 1) {
+ FTS_INFO("[ESD]: In suspend, not check esd, return!!");
+ /* because in suspend state, adb can be used, when upgrade FW,
+ * will active ESD check(active = 1).
+ * But in suspend, then will don't queue_delayed_work,
+ * when resume, don't check ESD again
+ */
+ fts_esdcheck_data.active = 0;
+ return 0;
+ }
+
+ /* 3. check fts_esdcheck_data.proc_debug state,
+ * if 1-proc busy, no need check esd
+ */
+ if (fts_esdcheck_data.proc_debug == 1) {
+ FTS_INFO("[ESD]: In cmd mode, not check esd, return!!");
+ return 0;
+ }
+
+ /* 4. In factory mode, can't check esd */
+ reg_addr = FTS_REG_WORKMODE;
+ err = fts_i2c_read(fts_i2c_client, ®_addr, 1, ®_value, 1);
+ if (err < 0) {
+ fts_esdcheck_data.i2c_nack_cnt++;
+ } else if ((reg_value & 0x70) == FTS_REG_WORKMODE_FACTORY_VALUE) {
+ FTS_INFO("[ESD]: In factory mode, not check esd, return!!");
+ return 0;
+ }
+
+ /* 5. IDC esd check lcd default:close */
+#if LCD_ESD_PATCH
+ idc_esdcheck_lcderror();
+#endif
+
+ /* 6. Get Chip ID */
+ hardware_reset = get_chip_id();
+
+ /* 7. get Flow work cnt: 0x91 If no change for 5 times,
+ * then ESD and reset
+ */
+ if (!hardware_reset)
+ hardware_reset = get_flow_cnt();
+
+ /* 8. If need hardware reset, then handle it here */
+ if (hardware_reset == 1)
+ fts_esdcheck_tp_reset();
+
+ FTS_INFO("[ESD]: NoACK=%d, Error Data=%d, Hardware Reset=%d\n",
+ fts_esdcheck_data.i2c_nack_cnt,
+ fts_esdcheck_data.i2c_dataerror_cnt,
+ fts_esdcheck_data.hardware_reset_cnt);
+ return 0;
+}
+
+/*****************************************************************************
+ * Name: fts_esdcheck_func
+ * Brief: fts_esdcheck_func
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static void esdcheck_func(struct work_struct *work)
+{
+ FTS_FUNC_ENTER();
+
+ esdcheck_algorithm();
+
+ if (fts_esdcheck_data.suspend == 0) {
+ queue_delayed_work(fts_esdcheck_workqueue,
+ &fts_esdcheck_work,
+ msecs_to_jiffies(ESDCHECK_WAIT_TIME));
+ }
+
+ FTS_FUNC_EXIT();
+}
+
+/*****************************************************************************
+ * Name: fts_esdcheck_set_intr
+ * Brief: interrupt flag (main used in interrupt tp report)
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+int fts_esdcheck_set_intr(bool intr)
+{
+ /* interrupt don't add debug message */
+ fts_esdcheck_data.intr = intr;
+ return 0;
+}
+
+/*****************************************************************************
+ * Name: fts_esdcheck_get_status(void)
+ * Brief: get current status
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+int fts_esdcheck_get_status(void)
+{
+ /* interrupt don't add debug message */
+ return fts_esdcheck_data.active;
+}
+
+/*****************************************************************************
+ * Name: fts_esdcheck_proc_busy
+ * Brief: When APK or ADB command access TP via driver, then need
+ * set proc_debug, then will not check ESD.
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+int fts_esdcheck_proc_busy(bool proc_debug)
+{
+ fts_esdcheck_data.proc_debug = proc_debug;
+ return 0;
+}
+
+/*****************************************************************************
+ * Name: fts_esdcheck_switch
+ * Brief: FTS esd check function switch.
+ * Input: enable: 1 - Enable esd check
+ * 0 - Disable esd check
+ * Output:
+ * Return:
+ *****************************************************************************/
+int fts_esdcheck_switch(bool enable)
+{
+ FTS_FUNC_ENTER();
+ if (enable == 1) {
+ if (fts_esdcheck_data.active == 0) {
+ FTS_INFO("[ESD]: ESD check start!!");
+ fts_esdcheck_data.active = 1;
+ queue_delayed_work(fts_esdcheck_workqueue,
+ &fts_esdcheck_work,
+ msecs_to_jiffies(ESDCHECK_WAIT_TIME));
+ }
+ } else {
+ if (fts_esdcheck_data.active == 1) {
+ FTS_INFO("[ESD]: ESD check stop!!");
+ fts_esdcheck_data.active = 0;
+ cancel_delayed_work_sync(&fts_esdcheck_work);
+ }
+ }
+
+ FTS_FUNC_EXIT();
+ return 0;
+}
+
+/*****************************************************************************
+ * Name: fts_esdcheck_suspend
+ * Brief: Run when tp enter into suspend
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+int fts_esdcheck_suspend(void)
+{
+ FTS_FUNC_ENTER();
+ fts_esdcheck_switch(DISABLE);
+ fts_esdcheck_data.suspend = 1;
+ FTS_FUNC_EXIT();
+ return 0;
+}
+
+/*****************************************************************************
+ * Name: fts_esdcheck_resume
+ * Brief: Run when tp resume
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+int fts_esdcheck_resume(void)
+{
+ FTS_FUNC_ENTER();
+ fts_esdcheck_switch(ENABLE);
+ fts_esdcheck_data.suspend = 0;
+ FTS_FUNC_EXIT();
+ return 0;
+}
+
+
+/*****************************************************************************
+ * Name: fts_esdcheck_init
+ * Brief: Init and create a queue work to check esd
+ * Input:
+ * Output:
+ * Return: < 0: Fail to create esd check queue
+ *****************************************************************************/
+int fts_esdcheck_init(void)
+{
+ FTS_FUNC_ENTER();
+
+ INIT_DELAYED_WORK(&fts_esdcheck_work, esdcheck_func);
+ fts_esdcheck_workqueue = create_workqueue("fts_esdcheck_wq");
+ if (fts_esdcheck_workqueue == NULL)
+ FTS_INFO("[ESD]: Failed to create esd work queue!!");
+
+ memset((u8 *)&fts_esdcheck_data, 0, sizeof(struct fts_esdcheck_st));
+
+ fts_esdcheck_switch(ENABLE);
+ FTS_FUNC_EXIT();
+ return 0;
+}
+
+/*****************************************************************************
+ * Name: fts_esdcheck_exit
+ * Brief: When FTS TP driver is removed, then call this function
+ * to destroy work queue
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+int fts_esdcheck_exit(void)
+{
+ FTS_FUNC_ENTER();
+
+ destroy_workqueue(fts_esdcheck_workqueue);
+
+ FTS_FUNC_EXIT();
+ return 0;
+}
+#endif /* FTS_ESDCHECK_EN */
+
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_ex_fun.c b/drivers/input/touchscreen/focaltech_touch/focaltech_ex_fun.c
new file mode 100644
index 0000000..6b21aca
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_ex_fun.c
@@ -0,0 +1,1145 @@
+/*
+ *
+ * FocalTech TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, Focaltech Ltd. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/*****************************************************************************
+ *
+ * File Name: Focaltech_ex_fun.c
+ *
+ * Author: Focaltech Driver Team
+ *
+ * Created: 2016-08-08
+ *
+ * Abstract:
+ *
+ * Reference:
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * 1.Included header files
+ *****************************************************************************/
+#include "focaltech_core.h"
+
+/*****************************************************************************
+ * Private constant and macro definitions using #define
+ *****************************************************************************/
+/*create apk debug channel*/
+#define PROC_UPGRADE 0
+#define PROC_READ_REGISTER 1
+#define PROC_WRITE_REGISTER 2
+#define PROC_AUTOCLB 4
+#define PROC_UPGRADE_INFO 5
+#define PROC_WRITE_DATA 6
+#define PROC_READ_DATA 7
+#define PROC_SET_TEST_FLAG 8
+#define PROC_SET_SLAVE_ADDR 10
+#define PROC_HW_RESET 11
+#define PROC_NAME "ftxxxx-debug"
+#define WRITE_BUF_SIZE 512
+#define READ_BUF_SIZE 512
+
+/*****************************************************************************
+ * Private enumerations, structures and unions using typedef
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Static variables
+ *****************************************************************************/
+static unsigned char proc_operate_mode = PROC_UPGRADE;
+static struct proc_dir_entry *fts_proc_entry;
+static struct
+{
+ int op; /* 0: read, 1: write */
+ int reg; /* register */
+ int value; /* read: return value, write: op return */
+ int result; /* 0: success, otherwise: fail */
+} g_rwreg_result;
+
+/*****************************************************************************
+ * Global variable or extern global variabls/functions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Static function prototypes
+ *****************************************************************************/
+#if FTS_ESDCHECK_EN
+static void esd_process(u8 *writebuf, int buflen, bool flag)
+{
+ if (flag) {
+ if ((writebuf[1] == 0xFC) && (writebuf[2] == 0x55)
+ && (buflen == 0x03)) {
+ /* Upgrade command */
+ FTS_DEBUG("[ESD]: Upgrade command(%x %x %x)!!",
+ writebuf[0], writebuf[1], writebuf[2]);
+ fts_esdcheck_switch(DISABLE);
+ } else if ((writebuf[1] == 0x00) && (writebuf[2] == 0x40)
+ && (buflen == 0x03)) {
+ /* factory mode bit 4 5 6 */
+ FTS_DEBUG("[ESD]: Entry factory mode(%x %x %x)!!",
+ writebuf[0], writebuf[1], writebuf[2]);
+ fts_esdcheck_switch(DISABLE);
+ } else if ((writebuf[1] == 0x00) && (writebuf[2] == 0x00)
+ && (buflen == 0x03)) {
+ /* normal mode bit 4 5 6 */
+ FTS_DEBUG("[ESD]: Exit factory mode(%x %x %x)!!",
+ writebuf[0], writebuf[1], writebuf[2]);
+ fts_esdcheck_switch(ENABLE);
+ } else {
+ fts_esdcheck_proc_busy(1);
+ }
+ } else {
+ if ((writebuf[1] == 0x07) && (buflen == 0x02)) {
+ FTS_DEBUG("[ESD]: Upgrade finish-trigger (07)(%x %x)!!",
+ writebuf[0], writebuf[1]);
+ fts_esdcheck_switch(ENABLE);
+ } else {
+ fts_esdcheck_proc_busy(0);
+ }
+ }
+}
+#endif
+
+/*interface of write proc*/
+/************************************************************************
+ * Name: fts_debug_write
+ * Brief:interface of write proc
+ * Input: file point, data buf, data len, no use
+ * Output: no
+ * Return: data len
+ ***********************************************************************/
+static ssize_t fts_debug_write(struct file *filp, const char __user *buff,
+ size_t count, loff_t *ppos)
+{
+ unsigned char writebuf[WRITE_BUF_SIZE];
+ char upgrade_file_path[FILE_NAME_LENGTH];
+ int buflen = count;
+ int writelen = 0;
+ int ret = 0;
+ char tmp[25];
+
+ if (copy_from_user(&writebuf, buff, buflen)) {
+ FTS_DEBUG("[APK]: copy from user error!!");
+ return -EFAULT;
+ }
+#if FTS_ESDCHECK_EN
+ esd_process(writebuf, buflen, 1);
+#endif
+ proc_operate_mode = writebuf[0];
+ switch (proc_operate_mode) {
+ case PROC_UPGRADE:
+
+ memset(upgrade_file_path, 0, sizeof(upgrade_file_path));
+ snprintf(upgrade_file_path, FILE_NAME_LENGTH,
+ "%s", writebuf + 1);
+ upgrade_file_path[buflen-1] = '\0';
+ FTS_DEBUG("%s\n", upgrade_file_path);
+ fts_irq_disable();
+#if FTS_ESDCHECK_EN
+ fts_esdcheck_switch(DISABLE);
+#endif
+ if (fts_updatefun_curr.upgrade_with_app_bin_file)
+ ret = fts_updatefun_curr.
+ upgrade_with_app_bin_file(fts_i2c_client,
+ upgrade_file_path);
+#if FTS_ESDCHECK_EN
+ fts_esdcheck_switch(ENABLE);
+#endif
+ fts_irq_enable();
+ if (ret < 0)
+ FTS_ERROR("[APK]: upgrade failed!!");
+ break;
+
+ case PROC_SET_TEST_FLAG:
+ FTS_DEBUG("[APK]: PROC_SET_TEST_FLAG = %x!!", writebuf[1]);
+#if FTS_ESDCHECK_EN
+ if (writebuf[1] == 0)
+ fts_esdcheck_switch(DISABLE);
+ else
+ fts_esdcheck_switch(ENABLE);
+#endif
+ break;
+ case PROC_READ_REGISTER:
+ writelen = 1;
+ ret = fts_i2c_write(fts_i2c_client, writebuf + 1, writelen);
+ if (ret < 0)
+ FTS_ERROR("[APK]: write iic error!!");
+ break;
+ case PROC_WRITE_REGISTER:
+ writelen = 2;
+ ret = fts_i2c_write(fts_i2c_client, writebuf + 1, writelen);
+ if (ret < 0)
+ FTS_ERROR("[APK]: write iic error!!");
+ break;
+ case PROC_SET_SLAVE_ADDR:
+ ret = fts_i2c_client->addr;
+ FTS_DEBUG("Original i2c addr 0x%x ", ret << 1);
+ if (writebuf[1] != fts_i2c_client->addr) {
+ fts_i2c_client->addr = writebuf[1];
+ FTS_DEBUG("Change i2c addr 0x%x to 0x%x", ret << 1,
+ writebuf[1] << 1);
+
+ }
+ break;
+
+ case PROC_HW_RESET:
+
+ snprintf(tmp, 25, "%s", writebuf + 1);
+ tmp[buflen - 1] = '\0';
+ if (memcmp(tmp, "focal_driver", 12) == 0) {
+ FTS_DEBUG("Begin HW Reset");
+ fts_reset_proc(1);
+ }
+
+ break;
+
+ case PROC_AUTOCLB:
+ FTS_DEBUG("[APK]: autoclb!!");
+ fts_ctpm_auto_clb(fts_i2c_client);
+ break;
+ case PROC_READ_DATA:
+ case PROC_WRITE_DATA:
+ writelen = count - 1;
+ if (writelen > 0) {
+ ret = fts_i2c_write(fts_i2c_client, writebuf + 1,
+ writelen);
+ if (ret < 0)
+ FTS_ERROR("[APK]: write iic error!!");
+ }
+ break;
+ default:
+ break;
+ }
+
+#if FTS_ESDCHECK_EN
+ esd_process(writebuf, buflen, 0);
+#endif
+
+ if (ret < 0)
+ return ret;
+ else
+ return count;
+}
+
+/* interface of read proc */
+/************************************************************************
+ * Name: fts_debug_read
+ * Brief:interface of read proc
+ * Input: point to the data, no use, no use, read len, no use, no use
+ * Output: page point to data
+ * Return: read char number
+ ***********************************************************************/
+static ssize_t fts_debug_read(struct file *filp, char __user *buff,
+ size_t count, loff_t *ppos)
+{
+ int ret = 0;
+ int num_read_chars = 0;
+ int readlen = 0;
+ u8 regvalue = 0x00, regaddr = 0x00;
+ unsigned char buf[READ_BUF_SIZE];
+
+ memset(buf, 0, READ_BUF_SIZE);
+#if FTS_ESDCHECK_EN
+ fts_esdcheck_proc_busy(1);
+#endif
+ switch (proc_operate_mode) {
+ case PROC_UPGRADE:
+ /* after calling fts_debug_write to upgrade */
+ regaddr = FTS_REG_FW_VER;
+ ret = fts_i2c_read_reg(fts_i2c_client, regaddr, ®value);
+ if (ret < 0)
+ num_read_chars = snprintf(buf, READ_BUF_SIZE, "%s",
+ "get fw version failed.\n");
+ else
+ num_read_chars = snprintf(buf, READ_BUF_SIZE,
+ "current fw ver:0x%02x\n", regvalue);
+ break;
+ case PROC_READ_REGISTER:
+ readlen = 1;
+ ret = fts_i2c_read(fts_i2c_client, NULL, 0, buf, readlen);
+ if (ret < 0) {
+#if FTS_ESDCHECK_EN
+ fts_esdcheck_proc_busy(0);
+#endif
+ FTS_ERROR("[APK]: read iic error!!");
+ return ret;
+ }
+ num_read_chars = 1;
+ break;
+ case PROC_READ_DATA:
+ readlen = count;
+ ret = fts_i2c_read(fts_i2c_client, NULL, 0, buf, readlen);
+ if (ret < 0) {
+#if FTS_ESDCHECK_EN
+ fts_esdcheck_proc_busy(0);
+#endif
+ FTS_ERROR("[APK]: read iic error!!");
+ return ret;
+ }
+
+ num_read_chars = readlen;
+ break;
+ case PROC_WRITE_DATA:
+ break;
+ default:
+ break;
+ }
+
+#if FTS_ESDCHECK_EN
+ fts_esdcheck_proc_busy(0);
+#endif
+
+ if (copy_to_user(buff, buf, num_read_chars)) {
+ FTS_ERROR("[APK]: copy to user error!!");
+ return -EFAULT;
+ }
+
+ return num_read_chars;
+}
+
+static const struct file_operations fts_proc_fops = {
+ .owner = THIS_MODULE,
+ .read = fts_debug_read,
+ .write = fts_debug_write,
+};
+
+/************************************************************************
+ * Name: fts_create_apk_debug_channel
+ * Brief: create apk debug channel
+ * Input: i2c info
+ * Output: no
+ * Return: success =0
+ ***********************************************************************/
+int fts_create_apk_debug_channel(struct i2c_client *client)
+{
+ fts_proc_entry = proc_create(PROC_NAME, 0644, NULL, &fts_proc_fops);
+ if (fts_proc_entry == NULL) {
+ FTS_ERROR("Couldn't create proc entry!");
+ return -ENOMEM;
+ }
+
+ FTS_INFO("Create proc entry success!");
+
+ return 0;
+}
+
+/************************************************************************
+ * Name: fts_release_apk_debug_channel
+ * Brief: release apk debug channel
+ * Input: no
+ * Output: no
+ * Return: no
+ ***********************************************************************/
+void fts_release_apk_debug_channel(void)
+{
+ if (fts_proc_entry)
+ proc_remove(fts_proc_entry);
+}
+
+/*
+ * fts_hw_reset interface
+ */
+static ssize_t fts_hw_reset_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ return -EPERM;
+}
+static ssize_t fts_hw_reset_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t count = 0;
+
+ fts_reset_proc(200);
+
+ count = snprintf(buf, PAGE_SIZE, "hw reset executed\n");
+
+ return count;
+}
+
+/*
+ * fts_irq interface
+ */
+static ssize_t fts_irq_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ if (FTS_SYSFS_ECHO_ON(buf)) {
+ FTS_INFO("[EX-FUN]enable irq");
+ fts_irq_enable();
+ } else if (FTS_SYSFS_ECHO_OFF(buf)) {
+ FTS_INFO("[EX-FUN]disable irq");
+ fts_irq_disable();
+ }
+
+ return count;
+}
+
+static ssize_t fts_irq_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return -EPERM;
+}
+
+/************************************************************************
+ * Name: fts_tpfwver_show
+ * Brief: show tp fw vwersion
+ * Input: device, device attribute, char buf
+ * Output: no
+ * Return: char number
+ ***********************************************************************/
+static ssize_t fts_tpfwver_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t num_read_chars = 0;
+ u8 fwver = 0;
+
+ mutex_lock(&fts_input_dev->mutex);
+
+#if FTS_ESDCHECK_EN
+ fts_esdcheck_proc_busy(1);
+#endif
+ if (fts_i2c_read_reg(fts_i2c_client, FTS_REG_FW_VER, &fwver) < 0)
+ num_read_chars = snprintf(buf, PAGE_SIZE,
+ "I2c transfer error!\n");
+#if FTS_ESDCHECK_EN
+ fts_esdcheck_proc_busy(0);
+#endif
+ if (fwver == 255)
+ num_read_chars = snprintf(buf, PAGE_SIZE,
+ "get tp fw version fail!\n");
+ else
+ num_read_chars = snprintf(buf, PAGE_SIZE, "%02X\n", fwver);
+
+ mutex_unlock(&fts_input_dev->mutex);
+
+ return num_read_chars;
+}
+/************************************************************************
+ * Name: fts_tpfwver_store
+ * Brief: no
+ * Input: device, device attribute, char buf, char count
+ * Output: no
+ * Return: EPERM
+ ***********************************************************************/
+static ssize_t fts_tpfwver_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ /* place holder for future use */
+ return -EPERM;
+}
+
+static int fts_is_hex_char(const char ch)
+{
+ int result = 0;
+
+ if (ch >= '0' && ch <= '9')
+ result = 1;/* (int)(ch - '0'); */
+ else if (ch >= 'a' && ch <= 'f')
+ result = 1;/* (int)(ch - 'a') + 10; */
+ else if (ch >= 'A' && ch <= 'F')
+ result = 1;/* (int)(ch - 'A') + 10; */
+ else
+ result = 0;
+
+ return result;
+}
+
+static int fts_hex_char_to_int(const char ch)
+{
+ int result = 0;
+
+ if (ch >= '0' && ch <= '9')
+ result = (int)(ch - '0');
+ else if (ch >= 'a' && ch <= 'f')
+ result = (int)(ch - 'a') + 10;
+ else if (ch >= 'A' && ch <= 'F')
+ result = (int)(ch - 'A') + 10;
+ else
+ result = -1;
+
+ return result;
+}
+
+static int fts_hex_to_str(char *hex, int iHexLen, char *ch, int *iChLen)
+{
+ int high = 0;
+ int low = 0;
+ int tmp = 0;
+ int i = 0;
+ int iCharLen = 0;
+
+ if (hex == NULL || ch == NULL)
+ return -EINVAL;
+
+ FTS_DEBUG("iHexLen: %d in function:%s!!\n\n", iHexLen, __func__);
+
+ if (iHexLen % 2 == 1)
+ return -EINVAL;
+
+ for (i = 0; i < iHexLen; i += 2) {
+ high = fts_hex_char_to_int(hex[i]);
+ if (high < 0) {
+ ch[iCharLen] = '\0';
+ return -EINVAL;
+ }
+
+ low = fts_hex_char_to_int(hex[i+1]);
+ if (low < 0) {
+ ch[iCharLen] = '\0';
+ return -EINVAL;
+ }
+
+ tmp = (high << 4) + low;
+ ch[iCharLen++] = (char)tmp;
+ }
+
+ ch[iCharLen] = '\0';
+ *iChLen = iCharLen;
+ FTS_DEBUG("iCharLen: %d, iChLen: %d in function:%s!!\n\n", iCharLen,
+ *iChLen, __func__);
+
+ return 0;
+}
+
+static void fts_str_to_bytes(char *bufStr, int iLen,
+ char *uBytes, int *iBytesLen)
+{
+ int i = 0;
+ int iNumChLen = 0;
+
+ *iBytesLen = 0;
+
+ for (i = 0; i < iLen; i++) {
+ if (fts_is_hex_char(bufStr[i])) /* filter illegal chars */
+ bufStr[iNumChLen++] = bufStr[i];
+ }
+
+ bufStr[iNumChLen] = '\0';
+
+ fts_hex_to_str(bufStr, iNumChLen, uBytes, iBytesLen);
+}
+/************************************************************************
+ * Name: fts_tprwreg_show
+ * Brief: no
+ * Input: device, device attribute, char buf
+ * Output: no
+ * Return: EPERM
+ ***********************************************************************/
+static ssize_t fts_tprwreg_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int count;
+
+ mutex_lock(&fts_input_dev->mutex);
+
+ if (!g_rwreg_result.op) {
+ if (g_rwreg_result.result == 0)
+ count = snprintf(buf, PAGE_SIZE, "Read %02X: %02X\n",
+ g_rwreg_result.reg,
+ g_rwreg_result.value);
+ else
+ count = snprintf(buf, PAGE_SIZE,
+ "Read %02X failed, ret: %d\n",
+ g_rwreg_result.reg,
+ g_rwreg_result.result);
+ } else {
+ if (g_rwreg_result.result == 0)
+ count = snprintf(buf, PAGE_SIZE,
+ "Write %02X, %02X success\n",
+ g_rwreg_result.reg,
+ g_rwreg_result.value);
+ else
+ count = snprintf(buf, PAGE_SIZE,
+ "Write %02X failed, ret: %d\n",
+ g_rwreg_result.reg,
+ g_rwreg_result.result);
+ }
+
+ mutex_unlock(&fts_input_dev->mutex);
+
+ return count;
+}
+/************************************************************************
+ * Name: fts_tprwreg_store
+ * Brief: read/write register
+ * Input: device, device attribute, char buf, char count
+ * Output: print register value
+ * Return: char count
+ ***********************************************************************/
+static ssize_t fts_tprwreg_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+ ssize_t num_read_chars = 0;
+ int retval;
+ unsigned long int wmreg = 0;
+ u8 regaddr = 0xff, regvalue = 0xff;
+ u8 valbuf[5] = {0};
+
+ memset(valbuf, 0, sizeof(valbuf));
+ mutex_lock(&fts_input_dev->mutex);
+ num_read_chars = count - 1;
+ if (num_read_chars != 2) {
+ if (num_read_chars != 4) {
+ FTS_ERROR("please input 2 or 4 character");
+ goto error_return;
+ }
+ }
+ memcpy(valbuf, buf, num_read_chars);
+ retval = kstrtoul(valbuf, 16, &wmreg);
+ fts_str_to_bytes((char *)buf, num_read_chars, valbuf, &retval);
+
+ if (retval == 1) {
+ regaddr = valbuf[0];
+ retval = 0;
+ } else if (retval == 2) {
+ regaddr = valbuf[0];
+ regvalue = valbuf[1];
+ retval = 0;
+ } else
+ retval = -1;
+
+ if (retval != 0) {
+ FTS_ERROR("ERROR: Can't convert to number %s", buf);
+ goto error_return;
+ }
+#if FTS_ESDCHECK_EN
+ fts_esdcheck_proc_busy(1);
+#endif
+ if (num_read_chars == 2) {
+ g_rwreg_result.op = 0;
+ g_rwreg_result.reg = regaddr;
+ /*read register*/
+ regaddr = wmreg;
+ g_rwreg_result.result = fts_i2c_read_reg(client, regaddr,
+ ®value);
+ if (g_rwreg_result.result < 0) {
+ FTS_ERROR("Could not read the register(0x%02x)",
+ regaddr);
+ } else {
+ FTS_INFO("the register(0x%02x) is 0x%02x", regaddr,
+ regvalue);
+ g_rwreg_result.value = regvalue;
+ g_rwreg_result.result = 0;
+ }
+ } else {
+ regaddr = wmreg>>8;
+ regvalue = wmreg;
+
+ g_rwreg_result.op = 1;
+ g_rwreg_result.reg = regaddr;
+ g_rwreg_result.value = regvalue;
+ g_rwreg_result.result = fts_i2c_write_reg(client, regaddr,
+ regvalue);
+ if (g_rwreg_result.result < 0) {
+ FTS_ERROR("Could not write the register(0x%02x)",
+ regaddr);
+
+ } else {
+ FTS_INFO("Write 0x%02x to (0x%02x) successful",
+ regvalue, regaddr);
+ g_rwreg_result.result = 0;
+ }
+ }
+#if FTS_ESDCHECK_EN
+ fts_esdcheck_proc_busy(0);
+#endif
+error_return:
+ mutex_unlock(&fts_input_dev->mutex);
+
+ return count;
+}
+/************************************************************************
+ * Name: fts_fwupdate_show
+ * Brief: no
+ * Input: device, device attribute, char buf
+ * Output: no
+ * Return: EPERM
+ ***********************************************************************/
+static ssize_t fts_fwupdate_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ /* place holder for future use */
+ return -EPERM;
+}
+
+/************************************************************************
+ * Name: fts_fwupdate_store
+ * Brief: upgrade from *.i
+ * Input: device, device attribute, char buf, char count
+ * Output: no
+ * Return: char count
+ ***********************************************************************/
+static ssize_t fts_fwupdate_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+ mutex_lock(&fts_input_dev->mutex);
+ fts_irq_disable();
+#if FTS_ESDCHECK_EN
+ fts_esdcheck_switch(DISABLE);
+#endif
+ if (fts_updatefun_curr.upgrade_with_app_i_file)
+ fts_updatefun_curr.upgrade_with_app_i_file(client);
+#if FTS_ESDCHECK_EN
+ fts_esdcheck_switch(ENABLE);
+#endif
+ fts_irq_enable();
+ mutex_unlock(&fts_input_dev->mutex);
+
+ return count;
+}
+/************************************************************************
+ * Name: fts_fwupgradeapp_show
+ * Brief: no
+ * Input: device, device attribute, char buf
+ * Output: no
+ * Return: EPERM
+ ***********************************************************************/
+static ssize_t fts_fwupgradeapp_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ /* place holder for future use */
+ return -EPERM;
+}
+
+/************************************************************************
+ * Name: fts_fwupgradeapp_store
+ * Brief: upgrade from app.bin
+ * Input: device, device attribute, char buf, char count
+ * Output: no
+ * Return: char count
+ ***********************************************************************/
+static ssize_t fts_fwupgradeapp_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ char fwname[FILE_NAME_LENGTH];
+ struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+ memset(fwname, 0, sizeof(fwname));
+ snprintf(fwname, FILE_NAME_LENGTH, "%s", buf);
+ fwname[count-1] = '\0';
+
+ mutex_lock(&fts_input_dev->mutex);
+ fts_irq_disable();
+#if FTS_ESDCHECK_EN
+ fts_esdcheck_switch(DISABLE);
+#endif
+ if (fts_updatefun_curr.upgrade_with_app_bin_file)
+ fts_updatefun_curr.upgrade_with_app_bin_file(client, fwname);
+#if FTS_ESDCHECK_EN
+ fts_esdcheck_switch(ENABLE);
+#endif
+ fts_irq_enable();
+ mutex_unlock(&fts_input_dev->mutex);
+
+ return count;
+}
+/************************************************************************
+ * Name: fts_driverversion_show
+ * Brief: no
+ * Input: device, device attribute, char buf
+ * Output: no
+ * Return: EPERM
+ ***********************************************************************/
+static ssize_t fts_driverversion_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int count;
+
+ mutex_lock(&fts_input_dev->mutex);
+
+ count = snprintf(buf, PAGE_SIZE, FTS_DRIVER_VERSION "\n");
+
+ mutex_unlock(&fts_input_dev->mutex);
+
+ return count;
+}
+/************************************************************************
+ * Name: fts_driverversion_store
+ * Brief: no
+ * Input: device, device attribute, char buf, char count
+ * Output: no
+ * Return: EPERM
+ ***********************************************************************/
+static ssize_t fts_driverversion_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ /* place holder for future use */
+ return -EPERM;
+}
+
+#if FTS_ESDCHECK_EN
+/************************************************************************
+ * Name: fts_esdcheck_store
+ * Brief: no
+ * Input: device, device attribute, char buf, char count
+ * Output: no
+ * Return: EPERM
+ ***********************************************************************/
+static ssize_t fts_esdcheck_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ mutex_lock(&fts_input_dev->mutex);
+
+ if (FTS_SYSFS_ECHO_ON(buf)) {
+ FTS_DEBUG("enable esdcheck");
+ fts_esdcheck_switch(ENABLE);
+ } else if (FTS_SYSFS_ECHO_OFF(buf)) {
+ FTS_DEBUG("disable esdcheck");
+ fts_esdcheck_switch(DISABLE);
+ }
+
+ mutex_unlock(&fts_input_dev->mutex);
+
+ return -EPERM;
+}
+
+/************************************************************************
+ * Name: fts_esdcheck_show
+ * Brief: no
+ * Input: device, device attribute, char buf
+ * Output: no
+ * Return: EPERM
+ ***********************************************************************/
+static ssize_t fts_esdcheck_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int count;
+
+ mutex_lock(&fts_input_dev->mutex);
+
+ count = snprintf(buf, PAGE_SIZE, "Esd check: %s\n",
+ fts_esdcheck_get_status() ? "On" : "Off");
+
+ mutex_unlock(&fts_input_dev->mutex);
+
+ return count;
+}
+#endif
+/************************************************************************
+ * Name: fts_module_config_show
+ * Brief: no
+ * Input: device, device attribute, char buf
+ * Output: no
+ * Return: EPERM
+ ***********************************************************************/
+static ssize_t fts_module_config_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int count = 0;
+
+ mutex_lock(&fts_input_dev->mutex);
+
+ count += snprintf(buf, PAGE_SIZE, "FTS_CHIP_TYPE: \t\t\t%04X\n",
+ FTS_CHIP_TYPE);
+ count += snprintf(buf+count, PAGE_SIZE - count,
+ "FTS_DEBUG_EN: \t\t\t%s\n",
+ FTS_DEBUG_EN ? "ON" : "OFF");
+#if defined(FTS_MT_PROTOCOL_B_EN)
+ count += snprintf(buf+count, PAGE_SIZE - count,
+ "FTS_MT_PROTOCOL_B_EN: \t\t%s\n",
+ FTS_MT_PROTOCOL_B_EN ? "ON" : "OFF");
+#endif
+ count += snprintf(buf+count, PAGE_SIZE - count,
+ "FTS_GESTURE_EN: \t\t%s\n",
+ FTS_GESTURE_EN ? "ON" : "OFF");
+ count += snprintf(buf+count, PAGE_SIZE - count,
+ "FTS_ESDCHECK_EN: \t\t%s\n",
+ FTS_ESDCHECK_EN ? "ON" : "OFF");
+#if defined(FTS_PSENSOR_EN)
+ count += snprintf(buf+count, PAGE_SIZE - count,
+ "FTS_PSENSOR_EN: \t\t%s\n",
+ FTS_PSENSOR_EN ? "ON" : "OFF");
+#endif
+ count += snprintf(buf+count, PAGE_SIZE - count,
+ "FTS_GLOVE_EN: \t\t\t%s\n",
+ FTS_GLOVE_EN ? "ON" : "OFF");
+ count += snprintf(buf+count, PAGE_SIZE - count,
+ "FTS_COVER_EN: \t\t%s\n",
+ FTS_COVER_EN ? "ON" : "OFF");
+ count += snprintf(buf+count, PAGE_SIZE - count,
+ "FTS_CHARGER_EN: \t\t\t%s\n",
+ FTS_CHARGER_EN ? "ON" : "OFF");
+
+ count += snprintf(buf+count, PAGE_SIZE - count,
+ "FTS_REPORT_PRESSURE_EN: \t\t%s\n",
+ FTS_REPORT_PRESSURE_EN ? "ON" : "OFF");
+ count += snprintf(buf+count, PAGE_SIZE - count,
+ "FTS_FORCE_TOUCH_EN: \t\t%s\n",
+ FTS_FORCE_TOUCH_EN ? "ON" : "OFF");
+
+ count += snprintf(buf+count, PAGE_SIZE - count,
+ "FTS_TEST_EN: \t\t\t%s\n",
+ FTS_TEST_EN ? "ON" : "OFF");
+ count += snprintf(buf+count, PAGE_SIZE - count,
+ "FTS_APK_NODE_EN: \t\t%s\n",
+ FTS_APK_NODE_EN ? "ON" : "OFF");
+ count += snprintf(buf+count, PAGE_SIZE - count,
+ "FTS_POWER_SOURCE_CUST_EN: \t%s\n",
+ FTS_POWER_SOURCE_CUST_EN ? "ON" : "OFF");
+ count += snprintf(buf+count, PAGE_SIZE - count,
+ "FTS_AUTO_UPGRADE_EN: \t\t%s\n",
+ FTS_AUTO_UPGRADE_EN ? "ON" : "OFF");
+
+ mutex_unlock(&fts_input_dev->mutex);
+
+ return count;
+}
+/************************************************************************
+ * Name: fts_module_config_store
+ * Brief: no
+ * Input: device, device attribute, char buf, char count
+ * Output: no
+ * Return: EPERM
+ ***********************************************************************/
+static ssize_t fts_module_config_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ /* place holder for future use */
+ return -EPERM;
+}
+
+/************************************************************************
+ * Name: fts_show_log_show
+ * Brief: no
+ * Input: device, device attribute, char buf
+ * Output: no
+ * Return: EPERM
+ ***********************************************************************/
+static ssize_t fts_show_log_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int count;
+
+ mutex_lock(&fts_input_dev->mutex);
+
+ count = snprintf(buf, PAGE_SIZE,
+ "Log: %s\n", g_show_log ? "On" : "Off");
+
+ mutex_unlock(&fts_input_dev->mutex);
+
+ return count;
+}
+/************************************************************************
+ * Name: fts_show_log_store
+ * Brief: no
+ * Input: device, device attribute, char buf, char count
+ * Output: no
+ * Return: EPERM
+ ***********************************************************************/
+static ssize_t fts_show_log_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ /* place holder for future use */
+
+ mutex_lock(&fts_input_dev->mutex);
+
+ if (FTS_SYSFS_ECHO_ON(buf)) {
+ FTS_DEBUG("enable show log info/error");
+ g_show_log = 1;
+ } else if (FTS_SYSFS_ECHO_OFF(buf)) {
+ FTS_DEBUG("disable show log info/error");
+ g_show_log = 0;
+ }
+
+ mutex_unlock(&fts_input_dev->mutex);
+ return count;
+}
+/************************************************************************
+ * Name: fts_dumpreg_store
+ * Brief: no
+ * Input: device, device attribute, char buf, char count
+ * Output: no
+ * Return: EPERM
+ ***********************************************************************/
+static ssize_t fts_dumpreg_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ /* place holder for future use */
+ return -EPERM;
+}
+
+/************************************************************************
+ * Name: fts_dumpreg_show
+ * Brief: no
+ * Input: device, device attribute, char buf
+ * Output: no
+ * Return: EPERM
+ ***********************************************************************/
+static ssize_t fts_dumpreg_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ char tmp[256];
+ int count = 0;
+ u8 regvalue = 0;
+ struct i2c_client *client;
+
+ mutex_lock(&fts_input_dev->mutex);
+#if FTS_ESDCHECK_EN
+ fts_esdcheck_proc_busy(1);
+#endif
+ client = container_of(dev, struct i2c_client, dev);
+ /* power mode 0:active 1:monitor 3:sleep */
+ fts_i2c_read_reg(client, FTS_REG_POWER_MODE, ®value);
+ count += snprintf(tmp + count, PAGE_SIZE - count,
+ "Power Mode:0x%02x\n", regvalue);
+
+ /* FWver */
+ fts_i2c_read_reg(client, FTS_REG_FW_VER, ®value);
+ count += snprintf(tmp + count, PAGE_SIZE - count,
+ "FW Ver:0x%02x\n", regvalue);
+
+ /* Vendor ID */
+ fts_i2c_read_reg(client, FTS_REG_VENDOR_ID, ®value);
+ count += snprintf(tmp + count, PAGE_SIZE - count,
+ "Vendor ID:0x%02x\n", regvalue);
+
+ /* LCD Busy number */
+ fts_i2c_read_reg(client, FTS_REG_LCD_BUSY_NUM, ®value);
+ count += snprintf(tmp + count, PAGE_SIZE - count,
+ "LCD Busy Number:0x%02x\n", regvalue);
+
+ /* 1 Gesture mode,0 Normal mode */
+ fts_i2c_read_reg(client, FTS_REG_GESTURE_EN, ®value);
+ count += snprintf(tmp + count, PAGE_SIZE - count,
+ "Gesture Mode:0x%02x\n", regvalue);
+
+ /* 3 charge in */
+ fts_i2c_read_reg(client, FTS_REG_CHARGER_MODE_EN, ®value);
+ count += snprintf(tmp + count, PAGE_SIZE - count,
+ "charge stat:0x%02x\n", regvalue);
+
+ /* Interrupt counter */
+ fts_i2c_read_reg(client, FTS_REG_INT_CNT, ®value);
+ count += snprintf(tmp + count, PAGE_SIZE - count,
+ "INT count:0x%02x\n", regvalue);
+
+ /* Flow work counter */
+ fts_i2c_read_reg(client, FTS_REG_FLOW_WORK_CNT, ®value);
+ count += snprintf(tmp + count, PAGE_SIZE - count,
+ "ESD count:0x%02x\n", regvalue);
+#if FTS_ESDCHECK_EN
+ fts_esdcheck_proc_busy(0);
+#endif
+ memcpy(buf, tmp, count);
+ mutex_unlock(&fts_input_dev->mutex);
+ return count;
+}
+
+/****************************************/
+/* sysfs */
+/* get the fw version
+ * example:cat fw_version
+ */
+static DEVICE_ATTR(fts_fw_version, 0644,
+ fts_tpfwver_show, fts_tpfwver_store);
+
+/* upgrade from *.i
+ * example: echo 1 > fw_update
+ */
+static DEVICE_ATTR(fts_fw_update, 0644,
+ fts_fwupdate_show, fts_fwupdate_store);
+
+/* read and write register
+ * read example: echo 88 > rw_reg ---read register 0x88
+ * write example:echo 8807 > rw_reg ---write 0x07 into register 0x88
+ *
+ * note:the number of input must be 2 or 4.if it not enough,
+ * please fill in the 0.
+ */
+static DEVICE_ATTR(fts_rw_reg, 0644,
+ fts_tprwreg_show, fts_tprwreg_store);
+
+/* upgrade from app.bin
+ * example:echo "*_app.bin" > upgrade_app
+ */
+static DEVICE_ATTR(fts_upgrade_app, 0644,
+ fts_fwupgradeapp_show, fts_fwupgradeapp_store);
+static DEVICE_ATTR(fts_driver_version, 0644,
+ fts_driverversion_show, fts_driverversion_store);
+static DEVICE_ATTR(fts_dump_reg, 0644,
+ fts_dumpreg_show, fts_dumpreg_store);
+static DEVICE_ATTR(fts_show_log, 0644,
+ fts_show_log_show, fts_show_log_store);
+static DEVICE_ATTR(fts_module_config, 0644,
+ fts_module_config_show, fts_module_config_store);
+static DEVICE_ATTR(fts_hw_reset, 0644,
+ fts_hw_reset_show, fts_hw_reset_store);
+static DEVICE_ATTR(fts_irq, 0644,
+ fts_irq_show, fts_irq_store);
+
+#if FTS_ESDCHECK_EN
+static DEVICE_ATTR(fts_esd_check, 0644,
+ fts_esdcheck_show, fts_esdcheck_store);
+#endif
+
+/* add your attr in here*/
+static struct attribute *fts_attributes[] = {
+ &dev_attr_fts_fw_version.attr,
+ &dev_attr_fts_fw_update.attr,
+ &dev_attr_fts_rw_reg.attr,
+ &dev_attr_fts_dump_reg.attr,
+ &dev_attr_fts_upgrade_app.attr,
+ &dev_attr_fts_driver_version.attr,
+ &dev_attr_fts_show_log.attr,
+ &dev_attr_fts_module_config.attr,
+ &dev_attr_fts_hw_reset.attr,
+ &dev_attr_fts_irq.attr,
+#if FTS_ESDCHECK_EN
+ &dev_attr_fts_esd_check.attr,
+#endif
+ NULL
+};
+
+static struct attribute_group fts_attribute_group = {
+ .attrs = fts_attributes
+};
+
+/************************************************************************
+ * Name: fts_create_sysfs
+ * Brief: create sysfs for debug
+ * Input: i2c info
+ * Output: no
+ * Return: success =0
+ ***********************************************************************/
+int fts_create_sysfs(struct i2c_client *client)
+{
+ int err;
+
+ err = sysfs_create_group(&client->dev.kobj, &fts_attribute_group);
+ if (err != 0) {
+ FTS_ERROR("[EX]: sysfs_create_group() failed!!");
+ sysfs_remove_group(&client->dev.kobj, &fts_attribute_group);
+ return -EIO;
+ }
+
+ FTS_INFO("[EX]: sysfs_create_group() succeeded!!");
+
+ return err;
+}
+/************************************************************************
+ * Name: fts_remove_sysfs
+ * Brief: remove sys
+ * Input: i2c info
+ * Output: no
+ * Return: no
+ ***********************************************************************/
+int fts_remove_sysfs(struct i2c_client *client)
+{
+ sysfs_remove_group(&client->dev.kobj, &fts_attribute_group);
+ return 0;
+}
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_ex_mode.c b/drivers/input/touchscreen/focaltech_touch/focaltech_ex_mode.c
new file mode 100644
index 0000000..6e007f6
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_ex_mode.c
@@ -0,0 +1,347 @@
+/*
+ *
+ * FocalTech ftxxxx TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, Focaltech Ltd. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/*****************************************************************************
+ *
+ * File Name: focaltech_ex_mode.c
+ *
+ * Author: Liu WeiGuang
+ *
+ * Created: 2016-08-31
+ *
+ * Abstract:
+ *
+ * Reference:
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * 1.Included header files
+ *****************************************************************************/
+#include "focaltech_core.h"
+
+/*****************************************************************************
+ * 2.Private constant and macro definitions using #define
+ *****************************************************************************/
+
+/*****************************************************************************
+ * 3.Private enumerations, structures and unions using typedef
+ *****************************************************************************/
+struct fts_mode_flag {
+ int fts_glove_mode_flag;
+ int fts_cover_mode_flag;
+ int fts_charger_mode_flag;
+};
+
+static struct fts_mode_flag g_fts_mode_flag;
+
+/*****************************************************************************
+ * 4.Static variables
+ *****************************************************************************/
+
+/*****************************************************************************
+ * 5.Global variable or extern global variabls/functions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * 6.Static function prototypes
+ *****************************************************************************/
+
+#if FTS_GLOVE_EN
+static ssize_t fts_touch_glove_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "Glove: %s\n",
+ g_fts_mode_flag.fts_glove_mode_flag ? "On" : "Off");
+}
+
+static ssize_t fts_touch_glove_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ int ret;
+
+ if (FTS_SYSFS_ECHO_ON(buf)) {
+ if (!g_fts_mode_flag.fts_glove_mode_flag) {
+ FTS_INFO("[Mode]enter glove mode");
+ ret = fts_enter_glove_mode(fts_i2c_client, true);
+ if (ret >= 0)
+ g_fts_mode_flag.fts_glove_mode_flag = true;
+ }
+ } else if (FTS_SYSFS_ECHO_OFF(buf)) {
+ if (g_fts_mode_flag.fts_glove_mode_flag) {
+ FTS_INFO("[Mode]exit glove mode");
+ ret = fts_enter_glove_mode(fts_i2c_client, false);
+ if (ret >= 0)
+ g_fts_mode_flag.fts_glove_mode_flag = false;
+ }
+ }
+
+ FTS_INFO("[Mode]glove mode status: %d",
+ g_fts_mode_flag.fts_glove_mode_flag);
+ return count;
+}
+
+/************************************************************************
+ * Name: fts_enter_glove_mode
+ * Brief: change glove mode
+ * Input: glove mode
+ * Output: no
+ * Return: success >=0, otherwise failed
+ ***********************************************************************/
+int fts_enter_glove_mode(struct i2c_client *client, int mode)
+{
+ int ret = 0;
+ static u8 buf_addr[2] = { 0 };
+ static u8 buf_value[2] = { 0 };
+
+ buf_addr[0] = FTS_REG_GLOVE_MODE_EN; /* glove control */
+
+ if (mode)
+ buf_value[0] = 0x01;
+ else
+ buf_value[0] = 0x00;
+
+ ret = fts_i2c_write_reg(client, buf_addr[0], buf_value[0]);
+ if (ret < 0)
+ FTS_ERROR("[Mode]fts_enter_glove_mode write value fail");
+
+ return ret;
+
+}
+
+/* read and write glove mode
+ * read example: cat fts_touch_glove_mode---read glove mode
+ * write example:echo 01 > fts_touch_glove_mode ---write glove mode to 01
+ *
+ */
+static DEVICE_ATTR(fts_glove_mode, 0644,
+ fts_touch_glove_show, fts_touch_glove_store);
+
+#endif
+
+#if FTS_COVER_EN
+static ssize_t fts_touch_cover_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "Cover: %s\n",
+ g_fts_mode_flag.fts_cover_mode_flag ? "On" : "Off");
+}
+
+static ssize_t fts_touch_cover_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ int ret;
+
+ if (FTS_SYSFS_ECHO_ON(buf)) {
+ if (!g_fts_mode_flag.fts_cover_mode_flag) {
+ FTS_INFO("[Mode]enter cover mode");
+ ret = fts_enter_cover_mode(fts_i2c_client, true);
+ if (ret >= 0)
+ g_fts_mode_flag.fts_cover_mode_flag = true;
+ }
+ } else if (FTS_SYSFS_ECHO_OFF(buf)) {
+ if (g_fts_mode_flag.fts_cover_mode_flag) {
+ FTS_INFO("[Mode]exit cover mode");
+ ret = fts_enter_cover_mode(fts_i2c_client, false);
+ if (ret >= 0)
+ g_fts_mode_flag.fts_cover_mode_flag = false;
+ }
+ }
+
+ FTS_INFO("[Mode]cover mode status: %d",
+ g_fts_mode_flag.fts_cover_mode_flag);
+ return count;
+}
+
+/************************************************************************
+ * Name: fts_enter_cover_mode
+ * Brief: change cover mode
+ * Input: cover mode
+ * Output: no
+ * Return: success >=0, otherwise failed
+ ***********************************************************************/
+int fts_enter_cover_mode(struct i2c_client *client, int mode)
+{
+ int ret = 0;
+ static u8 buf_addr[2] = { 0 };
+ static u8 buf_value[2] = { 0 };
+
+ buf_addr[0] = FTS_REG_COVER_MODE_EN; /* cover control */
+
+ if (mode)
+ buf_value[0] = 0x01;
+ else
+ buf_value[0] = 0x00;
+
+ ret = fts_i2c_write_reg(client, buf_addr[0], buf_value[0]);
+ if (ret < 0)
+ FTS_ERROR("[Mode] fts_enter_cover_mode write value fail\n");
+
+ return ret;
+
+}
+
+/* read and write cover mode
+ * read example: cat fts_touch_cover_mode---read cover mode
+ * write example:echo 01 > fts_touch_cover_mode ---write cover mode to 01
+ *
+ */
+static DEVICE_ATTR(fts_cover_mode, 0644,
+ fts_touch_cover_show, fts_touch_cover_store);
+
+#endif
+
+#if FTS_CHARGER_EN
+static ssize_t fts_touch_charger_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "Charger: %s\n",
+ g_fts_mode_flag.fts_charger_mode_flag ? "On" : "Off");
+}
+
+static ssize_t fts_touch_charger_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ int ret;
+
+ if (FTS_SYSFS_ECHO_ON(buf)) {
+ if (!g_fts_mode_flag.fts_charger_mode_flag) {
+ FTS_INFO("[Mode]enter charger mode");
+ ret = fts_enter_charger_mode(fts_i2c_client, true);
+ if (ret >= 0)
+ g_fts_mode_flag.fts_charger_mode_flag = true;
+ }
+ } else if (FTS_SYSFS_ECHO_OFF(buf)) {
+ if (g_fts_mode_flag.fts_charger_mode_flag) {
+ FTS_INFO("[Mode]exit charger mode");
+ ret = fts_enter_charger_mode(fts_i2c_client, false);
+ if (ret >= 0)
+ g_fts_mode_flag.fts_charger_mode_flag = false;
+ }
+ }
+
+ FTS_INFO("[Mode]charger mode status: %d",
+ g_fts_mode_flag.fts_charger_mode_flag);
+ return count;
+}
+
+/************************************************************************
+ * Name: fts_enter_charger_mode
+ * Brief: change charger mode
+ * Input: charger mode
+ * Output: no
+ * Return: success >=0, otherwise failed
+ ***********************************************************************/
+int fts_enter_charger_mode(struct i2c_client *client, int mode)
+{
+ int ret = 0;
+ static u8 buf_addr[2] = { 0 };
+ static u8 buf_value[2] = { 0 };
+
+ buf_addr[0] = FTS_REG_CHARGER_MODE_EN; /* charger control */
+
+ if (mode)
+ buf_value[0] = 0x01;
+ else
+ buf_value[0] = 0x00;
+
+ ret = fts_i2c_write_reg(client, buf_addr[0], buf_value[0]);
+ if (ret < 0)
+ FTS_DEBUG("[Mode]fts_enter_charger_mode write value fail");
+
+ return ret;
+
+}
+
+/* read and write charger mode
+ * read example: cat fts_touch_charger_mode---read charger mode
+ * write example:echo 01 > fts_touch_charger_mode ---write charger mode to 01
+ *
+ */
+static DEVICE_ATTR(fts_charger_mode, 0644,
+ fts_touch_charger_show, fts_touch_charger_store);
+
+#endif
+
+static struct attribute *fts_touch_mode_attrs[] = {
+#if FTS_GLOVE_EN
+ &dev_attr_fts_glove_mode.attr,
+#endif
+
+#if FTS_COVER_EN
+ &dev_attr_fts_cover_mode.attr,
+#endif
+
+#if FTS_CHARGER_EN
+ &dev_attr_fts_charger_mode.attr,
+#endif
+
+ NULL,
+};
+
+static struct attribute_group fts_touch_mode_group = {
+ .attrs = fts_touch_mode_attrs,
+};
+
+int fts_ex_mode_init(struct i2c_client *client)
+{
+ int err = 0;
+
+ g_fts_mode_flag.fts_glove_mode_flag = false;
+ g_fts_mode_flag.fts_cover_mode_flag = false;
+ g_fts_mode_flag.fts_charger_mode_flag = false;
+
+ err = sysfs_create_group(&client->dev.kobj, &fts_touch_mode_group);
+ if (err != 0) {
+ FTS_ERROR("[Mode]create sysfs failed.");
+ sysfs_remove_group(&client->dev.kobj, &fts_touch_mode_group);
+ return -EIO;
+ }
+
+ FTS_DEBUG("[Mode]create sysfs succeeded");
+
+ return err;
+
+}
+
+int fts_ex_mode_exit(struct i2c_client *client)
+{
+ sysfs_remove_group(&client->dev.kobj, &fts_touch_mode_group);
+ return 0;
+}
+
+int fts_ex_mode_recovery(struct i2c_client *client)
+{
+ int ret = 0;
+#if FTS_GLOVE_EN
+ if (g_fts_mode_flag.fts_glove_mode_flag)
+ ret = fts_enter_glove_mode(client, true);
+#endif
+
+#if FTS_COVER_EN
+ if (g_fts_mode_flag.fts_cover_mode_flag)
+ ret = fts_enter_cover_mode(client, true);
+#endif
+
+#if FTS_CHARGER_EN
+ if (g_fts_mode_flag.fts_charger_mode_flag)
+ ret = fts_enter_charger_mode(client, true);
+#endif
+
+ return ret;
+}
+
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_flash.c b/drivers/input/touchscreen/focaltech_touch/focaltech_flash.c
new file mode 100644
index 0000000..ed2148f
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_flash.c
@@ -0,0 +1,665 @@
+/*
+ *
+ * FocalTech fts TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, Focaltech Ltd. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/*****************************************************************************
+ *
+ * File Name: focaltech_flash.c
+ *
+ * Author: fupeipei
+ *
+ * Created: 2016-08-08
+ *
+ * Abstract:
+ *
+ * Reference:
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * 1.Included header files
+ *****************************************************************************/
+#include "focaltech_core.h"
+#include "focaltech_flash.h"
+
+/*****************************************************************************
+ * Static variables
+ *****************************************************************************/
+struct ft_chip_t chip_types;
+
+/*****************************************************************************
+ * Global variable or extern global variabls/functions
+ *****************************************************************************/
+/* Upgrade FW/PRAMBOOT/LCD CFG */
+#if (FTS_GET_VENDOR_ID_NUM >= 1)
+u8 CTPM_FW[] = {
+#include FTS_UPGRADE_FW_APP
+};
+#endif
+
+#if (FTS_GET_VENDOR_ID_NUM >= 2)
+u8 CTPM_FW2[] = {
+#include FTS_UPGRADE_FW2_APP
+};
+#endif
+
+#if (FTS_GET_VENDOR_ID_NUM >= 3)
+u8 CTPM_FW3[] = {
+#include FTS_UPGRADE_FW3_APP
+};
+#endif
+
+u8 aucFW_PRAM_BOOT[] = {
+#ifdef FTS_UPGRADE_PRAMBOOT
+#include FTS_UPGRADE_PRAMBOOT
+#endif
+};
+
+#if (FTS_CHIP_TYPE == _FT8006)
+u8 CTPM_LCD_CFG[] = {
+#ifdef FTS_UPGRADE_LCD_CFG
+#include FTS_UPGRADE_LCD_CFG
+#endif
+};
+#endif
+
+struct fts_upgrade_fun fts_updatefun_curr;
+struct workqueue_struct *touch_wq;
+struct work_struct fw_update_work;
+u8 *g_fw_file;
+int g_fw_len;
+/*****************************************************************************
+ * Static function prototypes
+ *****************************************************************************/
+
+/************************************************************************
+ * Name: fts_ctpm_upgrade_delay
+ * Brief: 0
+ * Input: 0
+ * Output: 0
+ * Return: 0
+ ***********************************************************************/
+void fts_ctpm_upgrade_delay(u32 i)
+{
+ do {
+ i--;
+ } while (i > 0);
+}
+
+/************************************************************************
+ * Name: fts_ctpm_i2c_hid2std
+ * Brief: HID to I2C
+ * Input: i2c info
+ * Output: no
+ * Return: fail =0
+ ***********************************************************************/
+int fts_ctpm_i2c_hid2std(struct i2c_client *client)
+{
+#if (FTS_CHIP_IDC)
+ return 0;
+#else
+ u8 buf[5] = {0};
+ int bRet = 0;
+
+ buf[0] = 0xeb;
+ buf[1] = 0xaa;
+ buf[2] = 0x09;
+ bRet = fts_i2c_write(client, buf, 3);
+ msleep(20);
+ buf[0] = buf[1] = buf[2] = 0;
+ fts_i2c_read(client, buf, 0, buf, 3);
+
+ if ((buf[0] == 0xeb) && (buf[1] == 0xaa) && (buf[2] == 0x08)) {
+ FTS_DEBUG("hidi2c change to stdi2c successful!!");
+ bRet = 1;
+ } else {
+ FTS_ERROR("hidi2c change to stdi2c error!!");
+ bRet = 0;
+ }
+
+ return bRet;
+#endif
+}
+
+/************************************************************************
+ * Name: fts_get_chip_types
+ * Brief: get correct chip information
+ * Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+static void fts_get_chip_types(void)
+{
+ struct ft_chip_t ctype[] = FTS_CHIP_TYPE_MAPPING;
+ int ic_type = 0;
+
+ if (sizeof(ctype) != sizeof(struct ft_chip_t)) /* only one array */
+ ic_type = IC_SERIALS - 1;
+
+ chip_types = ctype[ic_type];
+
+ FTS_INFO("CHIP TYPE ID = 0x%02x%02x",
+ chip_types.chip_idh, chip_types.chip_idl);
+}
+
+/************************************************************************
+ * Name: fts_ctpm_get_upgrade_array
+ * Brief: decide which ic
+ * Input: no
+ * Output: get ic info in fts_updateinfo_curr
+ * Return: no
+ ***********************************************************************/
+void fts_ctpm_get_upgrade_array(void)
+{
+
+ FTS_FUNC_ENTER();
+
+ fts_get_chip_types();
+
+ fts_ctpm_i2c_hid2std(fts_i2c_client);
+
+ /* Get functin pointer */
+ memcpy(&fts_updatefun_curr, &fts_updatefun,
+ sizeof(struct fts_upgrade_fun));
+
+ FTS_FUNC_EXIT();
+}
+
+/************************************************************************
+ * Name: fts_ctpm_rom_or_pram_reset
+ * Brief: RST CMD(07), reset to romboot(maybe->bootloader)
+ * Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+void fts_ctpm_rom_or_pram_reset(struct i2c_client *client)
+{
+ u8 rst_cmd = FTS_REG_RESET_FW;
+
+ FTS_INFO("[UPGRADE]******Reset to romboot/bootloader******");
+ fts_i2c_write(client, &rst_cmd, 1);
+ /* The delay can't be changed */
+ msleep(300);
+}
+
+/************************************************************************
+ * Name: fts_ctpm_auto_clb
+ * Brief: auto calibration
+ * Input: i2c info
+ * Output: no
+ * Return: 0
+ ***********************************************************************/
+int fts_ctpm_auto_clb(struct i2c_client *client)
+{
+#if FTS_AUTO_CLB_EN
+ u8 uc_temp = 0x00;
+ u8 i = 0;
+
+ /*start auto CLB */
+ msleep(200);
+
+ fts_i2c_write_reg(client, 0, FTS_REG_WORKMODE_FACTORY_VALUE);
+ /*make sure already enter factory mode */
+ msleep(100);
+ /*write command to start calibration */
+ fts_i2c_write_reg(client, 2, 0x4);
+ msleep(300);
+ if ((chip_types.chip_idh == 0x11) || (chip_types.chip_idh == 0x12)
+ || (chip_types.chip_idh == 0x13)
+ || (chip_types.chip_idh == 0x14)) {
+ /* 5x36,5x36i */
+ for (i = 0; i < 100; i++) {
+ fts_i2c_read_reg(client, 0x02, &uc_temp);
+ if ((uc_temp == 0x02) ||
+ (uc_temp == 0xFF))
+ break;
+ msleep(20);
+ }
+ } else {
+ for (i = 0; i < 100; i++) {
+ fts_i2c_read_reg(client, 0, &uc_temp);
+ if (((uc_temp&0x70)>>4) == 0x0)
+ break;
+ msleep(20);
+ }
+ }
+
+ fts_i2c_write_reg(client, 0, 0x40);
+ msleep(200);
+ fts_i2c_write_reg(client, 2, 0x5);
+ msleep(300);
+ fts_i2c_write_reg(client, 0, FTS_REG_WORKMODE_WORK_VALUE);
+ msleep(300);
+#endif
+
+ return 0;
+}
+
+/************************************************************************
+ * Name: fts_getsize
+ * Brief: Get different file's size
+ * Input:
+ * Output:
+ * Return: file's size
+ ***********************************************************************/
+u32 fts_getsize(u8 fw_type)
+{
+ int fw_len = 0;
+
+#if FTS_CHIP_IDC
+ if (fw_type == PRAMBOOT_SIZE)
+ fw_len = sizeof(aucFW_PRAM_BOOT);
+#endif
+#if (FTS_GET_VENDOR_ID_NUM >= 1)
+ else if (fw_type == FW_SIZE)
+ fw_len = sizeof(CTPM_FW);
+#endif
+#if (FTS_GET_VENDOR_ID_NUM >= 2)
+ else if (fw_type == FW2_SIZE)
+ fw_len = sizeof(CTPM_FW2);
+#endif
+#if (FTS_GET_VENDOR_ID_NUM >= 3)
+ else if (fw_type == FW3_SIZE)
+ fw_len = sizeof(CTPM_FW3);
+#endif
+#if (FTS_CHIP_TYPE == _FT8006)
+ else if (fw_type == LCD_CFG_SIZE)
+ fw_len = sizeof(CTPM_LCD_CFG);
+#endif
+
+ return fw_len;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_get_pram_or_rom_id
+ * Brief: 0
+ * Input: 0
+ * Output: 0
+ * Return: 0
+ ***********************************************************************/
+enum FW_STATUS fts_ctpm_get_pram_or_rom_id(struct i2c_client *client)
+{
+ u8 buf[4];
+ u8 reg_val[2] = {0};
+ enum FW_STATUS inRomBoot = FTS_RUN_IN_ERROR;
+
+ fts_ctpm_i2c_hid2std(client);
+
+ /*Enter upgrade mode*/
+ /*send 0x55 in time windows*/
+ buf[0] = FTS_UPGRADE_55;
+ buf[1] = FTS_UPGRADE_AA;
+ fts_i2c_write(client, buf, 2);
+
+ msleep(20);
+
+ buf[0] = 0x90;
+ buf[1] = buf[2] = buf[3] = 0x00;
+ fts_i2c_read(client, buf, 4, reg_val, 2);
+
+ FTS_DEBUG("[UPGRADE] Read ROM/PRAM/Bootloader id:0x%02x%02x",
+ reg_val[0], reg_val[1]);
+ if ((reg_val[0] == 0x00) || (reg_val[0] == 0xFF))
+ inRomBoot = FTS_RUN_IN_ERROR;
+ else if (reg_val[0] == chip_types.pramboot_idh
+ && reg_val[1] == chip_types.pramboot_idl)
+ inRomBoot = FTS_RUN_IN_PRAM;
+ else if (reg_val[0] == chip_types.rom_idh
+ && reg_val[1] == chip_types.rom_idl)
+ inRomBoot = FTS_RUN_IN_ROM;
+ else if (reg_val[0] == chip_types.bootloader_idh
+ && reg_val[1] == chip_types.bootloader_idl)
+ inRomBoot = FTS_RUN_IN_BOOTLOADER;
+
+ return inRomBoot;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_get_app_file
+ * Brief: get app file by Vendor ID
+ * Input:
+ * Output:
+ * Return: <0: vendor id not correct,not upgrade
+ ***********************************************************************/
+static int fts_ctpm_get_i_file(struct i2c_client *client, int fw_valid)
+{
+ int ret;
+
+ if (fts_updatefun_curr.get_i_file)
+ ret = fts_updatefun_curr.get_i_file(client, fw_valid);
+ else
+ ret = -EIO;
+
+ return ret;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_get_app_ver
+ * Brief: get app file version
+ * Input:
+ * Output:
+ * Return: fw version
+ ***********************************************************************/
+int fts_ctpm_get_app_ver(void)
+{
+ int i_ret = 0;
+
+ if (fts_updatefun_curr.get_app_i_file_ver)
+ i_ret = fts_updatefun_curr.get_app_i_file_ver();
+
+ return i_ret;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_fw_upgrade
+ * Brief: fw upgrade entry funciotn
+ * Input:
+ * Output:
+ * Return: 0 - upgrade successfully
+ * <0 - upgrade failed
+ ***********************************************************************/
+int fts_ctpm_fw_upgrade(struct i2c_client *client)
+{
+ int i_ret = 0;
+
+ if (fts_updatefun_curr.upgrade_with_app_i_file)
+ i_ret = fts_updatefun_curr.upgrade_with_app_i_file(client);
+
+ return i_ret;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_fw_upgrade
+ * Brief: fw upgrade entry funciotn
+ * Input:
+ * Output:
+ * Return: 0 - upgrade successfully
+ * <0 - upgrade failed
+ ***********************************************************************/
+int fts_ctpm_lcd_cfg_upgrade(struct i2c_client *client)
+{
+ int i_ret = 0;
+
+ if (fts_updatefun_curr.upgrade_with_lcd_cfg_i_file)
+ i_ret = fts_updatefun_curr.upgrade_with_lcd_cfg_i_file(client);
+
+ return i_ret;
+}
+
+#if (!(FTS_UPGRADE_STRESS_TEST))
+/************************************************************************
+ * Name: fts_ctpm_check_fw_status
+ * Brief: Check App is valid or not
+ * Input:
+ * Output:
+ * Return: -EIO - I2C communication error
+ * FTS_RUN_IN_APP - APP valid
+ * 0 - APP invalid
+ ***********************************************************************/
+static int fts_ctpm_check_fw_status(struct i2c_client *client)
+{
+ u8 chip_id1 = 0;
+ u8 chip_id2 = 0;
+ int fw_status = FTS_RUN_IN_ERROR;
+ int i = 0;
+ int ret = 0;
+ int i2c_noack_retry = 0;
+
+ for (i = 0; i < 5; i++) {
+ ret = fts_i2c_read_reg(client, FTS_REG_CHIP_ID, &chip_id1);
+ if (ret < 0) {
+ i2c_noack_retry++;
+ continue;
+ }
+
+ ret = fts_i2c_read_reg(client, FTS_REG_CHIP_ID2, &chip_id2);
+ if (ret < 0) {
+ i2c_noack_retry++;
+ continue;
+ }
+
+ if ((chip_id1 == chip_types.chip_idh)
+#if FTS_CHIP_IDC
+ && (chip_id2 == chip_types.chip_idl)
+#endif
+ ) {
+ fw_status = FTS_RUN_IN_APP;
+ break;
+ }
+ }
+
+ FTS_DEBUG("[UPGRADE]: chip_id = %02x%02x", chip_id1, chip_id2);
+ FTS_DEBUG("[UPGRADE]:chip_types.chip_idh = %02x%02x",
+ chip_types.chip_idh, chip_types.chip_idl);
+
+ /* I2C No ACK 5 times, then return -EIO */
+ if (i2c_noack_retry >= 5)
+ return -EIO;
+
+ /* I2C communication ok, but not get correct ID,
+ * need check pram/rom/bootloader
+ */
+ if (i >= 5)
+ fw_status = fts_ctpm_get_pram_or_rom_id(client);
+
+ return fw_status;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_check_fw_ver
+ * Brief: Check vendor id is valid or not
+ * Input:
+ * Output:
+ * Return: 1 - vendor id valid
+ * 0 - vendor id invalid
+ ***********************************************************************/
+static int fts_ctpm_check_fw_ver(struct i2c_client *client)
+{
+ u8 uc_tp_fm_ver = 0;
+ u8 uc_host_fm_ver = 0;
+
+ fts_i2c_read_reg(client, FTS_REG_FW_VER, &uc_tp_fm_ver);
+ uc_host_fm_ver = fts_ctpm_get_app_ver();
+
+ FTS_DEBUG("[UPGRADE]: uc_tp_fm_ver = 0x%x, uc_host_fm_ver = 0x%x!!",
+ uc_tp_fm_ver, uc_host_fm_ver);
+ if (uc_tp_fm_ver < uc_host_fm_ver)
+ return 1;
+
+ return 0;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_check_need_upgrade
+ * Brief:
+ * Input:
+ * Output:
+ * Return: 1 - Need upgrade
+ * 0 - No upgrade
+ ***********************************************************************/
+static int fts_ctpm_check_need_upgrade(struct i2c_client *client)
+{
+ int fw_status = 0;
+ int bUpgradeFlag = false;
+
+ FTS_FUNC_ENTER();
+
+ /* 1. veriry FW APP is valid or not */
+ fw_status = fts_ctpm_check_fw_status(client);
+ FTS_DEBUG("[UPGRADE]: fw_status = %d!!", fw_status);
+ if (fw_status < 0) {
+ /* I2C no ACK, return immediately */
+ FTS_ERROR("[UPGRADE]******I2C NO ACK,exit upgrade******");
+ return -EIO;
+ } else if (fw_status == FTS_RUN_IN_ERROR) {
+ FTS_ERROR("[UPGRADE]******IC Type Fail******");
+ } else if (fw_status == FTS_RUN_IN_APP) {
+ FTS_INFO("[UPGRADE]**********FW APP valid**********");
+
+ if (fts_ctpm_get_i_file(client, 1) != 0) {
+ FTS_DEBUG("[UPGRADE]***Get upgrade file(fw) fail***");
+ return -EIO;
+ }
+
+ if (fts_ctpm_check_fw_ver(client) == 1) {
+ FTS_DEBUG("[UPGRADE]******need upgrade fw******");
+ bUpgradeFlag = true;
+ } else {
+ FTS_DEBUG("[UPGRADE]****Don't need upgrade fw****");
+ bUpgradeFlag = false;
+ }
+ } else {
+ /* if app is invalid, reset to run ROM */
+ FTS_INFO("[UPGRADE]**********FW APP invalid**********");
+ fts_ctpm_rom_or_pram_reset(client);
+ if (fts_ctpm_get_i_file(client, 0) != 0) {
+ FTS_DEBUG("[UPGRADE]**Get upgrade file(flash) fail**");
+ fts_ctpm_rom_or_pram_reset(client);
+ return -EIO;
+ }
+ fts_ctpm_rom_or_pram_reset(client);
+ bUpgradeFlag = true;
+ }
+
+ FTS_FUNC_EXIT();
+
+ return bUpgradeFlag;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_auto_upgrade
+ * Brief: auto upgrade
+ * Input:
+ * Output:
+ * Return: 0 - no upgrade
+ ***********************************************************************/
+int fts_ctpm_auto_upgrade(struct i2c_client *client)
+{
+ u8 uc_tp_fm_ver = 0;
+ int i_ret = 0;
+ int bUpgradeFlag = false;
+ u8 uc_upgrade_times = 0;
+
+ FTS_DEBUG("[UPGRADE]**********check upgrade need or not**********");
+ bUpgradeFlag = fts_ctpm_check_need_upgrade(client);
+ FTS_DEBUG("[UPGRADE]**********bUpgradeFlag = 0x%x**********",
+ bUpgradeFlag);
+
+ if (bUpgradeFlag <= 0) {
+ FTS_DEBUG("[UPGRADE]**********No Upgrade, exit**********");
+ return 0;
+ }
+
+ /* FW Upgrade */
+ do {
+ uc_upgrade_times++;
+ FTS_DEBUG("[UPGRADE]*********star upgrade(%d)*************",
+ uc_upgrade_times);
+
+ i_ret = fts_ctpm_fw_upgrade(client);
+ if (i_ret == 0) {
+ /* upgrade success */
+ fts_i2c_read_reg(client, FTS_REG_FW_VER, &uc_tp_fm_ver);
+ FTS_DEBUG("[UPGRADE] Success upgrade to ver 0x%x",
+ uc_tp_fm_ver);
+
+ fts_ctpm_auto_clb(client);
+ break;
+ }
+
+ /* upgrade fail, reset to run ROM BOOT..
+ * if app in flash is ok, TP will work success
+ */
+ FTS_ERROR("[UPGRADE]*****upgrade fail, reset now*****");
+ fts_ctpm_rom_or_pram_reset(client);
+
+ /* if upgrade fail, upgrade again. then return */
+ } while (uc_upgrade_times < 2);
+
+ return i_ret;
+}
+#endif
+
+#if FTS_AUTO_UPGRADE_EN
+static void fts_ctpm_update_work_func(struct work_struct *work)
+{
+ int i_ret = 0;
+
+ FTS_DEBUG("[UPGRADE]*****FTS enter upgrade*******");
+ fts_irq_disable();
+
+ /* esd check */
+#if FTS_ESDCHECK_EN
+ fts_esdcheck_switch(DISABLE);
+#endif
+
+ i_ret = fts_ctpm_auto_upgrade(fts_i2c_client);
+ if (i_ret < 0)
+ FTS_ERROR("[UPGRADE]**********TP FW upgrade failed**********");
+
+#if FTS_AUTO_UPGRADE_FOR_LCD_CFG_EN
+ msleep(2000);
+
+ /* lcd_cfg upgrade */
+ i_ret = fts_ctpm_lcd_cfg_upgrade(fts_i2c_client);
+ if (i_ret < 0)
+ FTS_ERROR("[UPGRADE]**********LCD cfg upgrade failed*********");
+#endif
+
+#if FTS_ESDCHECK_EN
+ fts_esdcheck_switch(ENABLE);
+#endif
+ fts_irq_enable();
+
+ FTS_DEBUG("[UPGRADE]**********FTS exit upgrade*************");
+}
+
+/*****************************************************************************
+ * Name: fts_ctpm_upgrade_init
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+void fts_ctpm_upgrade_init(void)
+{
+ FTS_FUNC_ENTER();
+
+ touch_wq = create_singlethread_workqueue("touch_wq");
+ if (touch_wq) {
+ INIT_WORK(&fw_update_work, fts_ctpm_update_work_func);
+ queue_work(touch_wq, &fw_update_work);
+ } else
+ FTS_ERROR("[UPGRADE]create_singlethread_workqueue failed\n");
+
+ FTS_FUNC_EXIT();
+}
+
+/*****************************************************************************
+ * Name: fts_ctpm_upgrade_exit
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+void fts_ctpm_upgrade_exit(void)
+{
+ FTS_FUNC_ENTER();
+ destroy_workqueue(touch_wq);
+ FTS_FUNC_EXIT();
+}
+
+#endif /* #if FTS_AUTO_UPGRADE_EN */
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_flash.h b/drivers/input/touchscreen/focaltech_touch/focaltech_flash.h
new file mode 100644
index 0000000..d1acff2
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_flash.h
@@ -0,0 +1,137 @@
+/************************************************************************
+ * Copyright (C) 2010-2017, Focaltech Systems (R)£¬All Rights Reserved.
+ *
+ * File Name: focaltech_flash.h
+ *
+ * Author: fupeipei
+ *
+ * Created: 2016-08-07
+ *
+ * Abstract:
+ *
+ ************************************************************************/
+#ifndef __LINUX_FOCALTECH_FLASH_H__
+#define __LINUX_FOCALTECH_FLASH_H__
+
+/*****************************************************************************
+ * 1.Included header files
+ *****************************************************************************/
+#include "focaltech_flash/focaltech_upgrade_common.h"
+
+/*****************************************************************************
+ * Private constant and macro definitions using #define
+ *****************************************************************************/
+#define FTS_REG_ECC 0xCC
+#define FTS_RST_CMD_REG2 0xBC
+#define FTS_READ_ID_REG 0x90
+#define FTS_ERASE_APP_REG 0x61
+#define FTS_ERASE_PARAMS_CMD 0x63
+#define FTS_FW_WRITE_CMD 0xBF
+#define FTS_REG_RESET_FW 0x07
+#define FTS_RST_CMD_REG1 0xFC
+#define LEN_FLASH_ECC_MAX 0xFFFE
+
+#define FTS_PACKET_LENGTH 128
+#define FTS_SETTING_BUF_LEN 128
+
+#define FTS_UPGRADE_LOOP 30
+#define AUTO_CLB_NEED 1
+#define AUTO_CLB_NONEED 0
+#define FTS_UPGRADE_AA 0xAA
+#define FTS_UPGRADE_55 0x55
+#define FTXXXX_INI_FILEPATH_CONFIG "/sdcard/"
+
+enum FW_STATUS {
+ FTS_RUN_IN_ERROR,
+ FTS_RUN_IN_APP,
+ FTS_RUN_IN_ROM,
+ FTS_RUN_IN_PRAM,
+ FTS_RUN_IN_BOOTLOADER
+};
+
+enum FILE_SIZE_TYPE {
+ FW_SIZE,
+ FW2_SIZE,
+ FW3_SIZE,
+ PRAMBOOT_SIZE,
+ LCD_CFG_SIZE
+};
+
+/* pramboot */
+#define FTS_PRAMBOOT_8716 "include/pramboot/FT8716_Pramboot_V0.5_20160723.i"
+#define FTS_PRAMBOOT_E716 "include/pramboot/FT8716_Pramboot_V0.5_20160723.i"
+#define FTS_PRAMBOOT_8736 "include/pramboot/FT8736_Pramboot_V0.4_20160627.i"
+#define FTS_PRAMBOOT_8607 "include/pramboot/FT8607_Pramboot_V0.3_20160727.i"
+#define FTS_PRAMBOOT_8606 "include/pramboot/FT8606_Pramboot_V0.7_20150507.i"
+
+/* ic types */
+#if (FTS_CHIP_TYPE == _FT8716)
+#define FTS_UPGRADE_PRAMBOOT FTS_PRAMBOOT_8716
+#elif (FTS_CHIP_TYPE == _FTE716)
+#define FTS_UPGRADE_PRAMBOOT FTS_PRAMBOOT_E716
+#elif (FTS_CHIP_TYPE == _FT8736)
+#define FTS_UPGRADE_PRAMBOOT FTS_PRAMBOOT_8736
+#elif (FTS_CHIP_TYPE == _FT8607)
+#define FTS_UPGRADE_PRAMBOOT FTS_PRAMBOOT_8607
+#elif (FTS_CHIP_TYPE == _FT8606)
+#define FTS_UPGRADE_PRAMBOOT FTS_PRAMBOOT_8606
+#endif
+
+/* remove pramboot */
+#undef FTS_UPGRADE_PRAMBOOT
+
+/*****************************************************************************
+ * Private enumerations, structures and unions using typedef
+ *****************************************************************************/
+/* IC info */
+
+struct fts_upgrade_fun {
+ int (*get_i_file)(struct i2c_client *, int);
+ int (*get_app_bin_file_ver)(struct i2c_client *, char *);
+ int (*get_app_i_file_ver)(void);
+ int (*upgrade_with_app_i_file)(struct i2c_client *);
+ int (*upgrade_with_app_bin_file)(struct i2c_client *, char *);
+ int (*upgrade_with_lcd_cfg_i_file)(struct i2c_client *);
+ int (*upgrade_with_lcd_cfg_bin_file)(struct i2c_client *, char *);
+};
+extern struct fts_upgrade_fun fts_updatefun;
+
+/*****************************************************************************
+ * Static variables
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Global variable or extern global variabls/functions
+ *****************************************************************************/
+extern u8 CTPM_FW[];
+extern u8 CTPM_FW2[];
+extern u8 CTPM_FW3[];
+extern u8 aucFW_PRAM_BOOT[];
+extern u8 CTPM_LCD_CFG[];
+extern u8 *g_fw_file;
+extern int g_fw_len;
+extern struct fts_upgrade_fun fts_updatefun_curr;
+extern struct ft_chip_t chip_types;
+
+#if FTS_AUTO_UPGRADE_EN
+extern struct workqueue_struct *touch_wq;
+extern struct work_struct fw_update_work;
+#endif
+
+void fts_ctpm_upgrade_init(void);
+void fts_ctpm_upgrade_exit(void);
+void fts_ctpm_upgrade_delay(u32 i);
+void fts_ctpm_get_upgrade_array(void);
+int fts_ctpm_auto_upgrade(struct i2c_client *client);
+int fts_fw_upgrade(struct device *dev, bool force);
+int fts_ctpm_auto_clb(struct i2c_client *client);
+
+/*****************************************************************************
+ * Static function prototypes
+ *****************************************************************************/
+u32 fts_getsize(u8 fw_type);
+int fts_ctpm_i2c_hid2std(struct i2c_client *client);
+void fts_ctpm_rom_or_pram_reset(struct i2c_client *client);
+enum FW_STATUS fts_ctpm_get_pram_or_rom_id(struct i2c_client *client);
+#endif
+
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_flash/Makefile b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/Makefile
new file mode 100644
index 0000000..9b3a4bb
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/Makefile
@@ -0,0 +1,17 @@
+#
+# Makefile for the focaltech touchscreen drivers.
+#
+
+# Each configuration option enables a list of files.
+
+
+obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_upgrade_ft5x46.o
+obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_upgrade_ft5822.o
+obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_upgrade_ft6336gu.o
+obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_upgrade_ft8006.o
+obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_upgrade_ft8606.o
+obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_upgrade_ft8607.o
+obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_upgrade_ft8716.o
+obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_upgrade_ft8736.o
+obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_upgrade_idc.o
+obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_upgrade_test.o
\ No newline at end of file
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_common.h b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_common.h
new file mode 100644
index 0000000..e3b00e5
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_common.h
@@ -0,0 +1,60 @@
+/************************************************************************
+ * Copyright (C) 2010-2017, Focaltech Systems (R)£¬All Rights Reserved.
+ *
+ * File Name: focaltech_upgrade_common.h
+ *
+ * Author: fupeipei
+ *
+ * Created: 2016-08-16
+ *
+ * Abstract:
+ *
+ ************************************************************************/
+#ifndef __LINUX_FOCALTECH_UPGRADE_COMMON_H__
+#define __LINUX_FOCALTECH_UPGRADE_COMMON_H__
+
+/*****************************************************************************
+ * 1.Included header files
+ *****************************************************************************/
+#include "../focaltech_flash.h"
+
+/*****************************************************************************
+ * Private constant and macro definitions using #define
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Private enumerations, structures and unions using typedef
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Static variables
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Global variable or extern global variabls/functions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Static function prototypes
+ *****************************************************************************/
+int fts_ctpm_erase_flash(struct i2c_client *client);
+int fts_ctpm_pramboot_ecc(struct i2c_client *client);
+bool fts_ctpm_check_run_state(struct i2c_client *client, int state);
+void fts_ctpm_start_pramboot(struct i2c_client *client);
+int fts_ctpm_start_fw_upgrade(struct i2c_client *client);
+bool fts_ctpm_check_in_pramboot(struct i2c_client *client);
+int fts_ctpm_upgrade_idc_init(struct i2c_client *client);
+int fts_ctpm_write_app_for_idc(struct i2c_client *client,
+ u32 length, u8 *readbuf);
+int fts_ctpm_upgrade_ecc(struct i2c_client *client, u32 startaddr, u32 length);
+int fts_ctpm_write_pramboot_for_idc(struct i2c_client *client,
+ u32 length, u8 *readbuf);
+int fts_writeflash(struct i2c_client *client, u32 writeaddr,
+ u32 length, u8 *readbuf, u32 cnt);
+bool fts_check_app_bin_valid_idc(u8 *pbt_buf);
+
+int fts_ctpm_get_app_ver(void);
+int fts_ctpm_fw_upgrade(struct i2c_client *client);
+int fts_ctpm_lcd_cfg_upgrade(struct i2c_client *client);
+
+#endif
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft5822.c b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft5822.c
new file mode 100644
index 0000000..2133c06
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft5822.c
@@ -0,0 +1,645 @@
+/*
+ *
+ * FocalTech fts TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, Focaltech Ltd. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/*****************************************************************************
+ *
+ * File Name: focaltech_upgrade_ft5822.c
+ *
+ * Author: fupeipei
+ *
+ * Created: 2016-08-15
+ *
+ * Abstract:
+ *
+ * Reference:
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * 1.Included header files
+ *****************************************************************************/
+#include "../focaltech_core.h"
+
+#if (IC_SERIALS == 0x01)
+#include "../focaltech_flash.h"
+#include "focaltech_upgrade_common.h"
+
+/*****************************************************************************
+ * Static variables
+ *****************************************************************************/
+#define APP_FILE_MAX_SIZE (60 * 1024)
+#define APP_FILE_MIN_SIZE (8)
+#define APP_FILE_VER_MAPPING (0x10A)
+#define APP_FILE_VENDORID_MAPPING (0x108)
+#define APP_FILE_CHIPID_MAPPING (0x11E)
+#define CONFIG_START_ADDR (0xFFB0)
+#define CONFIG_VENDOR_ID_OFFSET (0x4)
+#define CONFIG_PROJECT_ID_OFFSET (0x20)
+#define CONFIG_VENDOR_ID_ADDR (CONFIG_START_ADDR+CONFIG_VENDOR_ID_OFFSET)
+#define CONFIG_PROJECT_ID_ADDR (CONFIG_START_ADDR+CONFIG_PROJECT_ID_OFFSET)
+
+/*****************************************************************************
+ * Global variable or extern global variabls/functions
+ *****************************************************************************/
+static int fts_ft5822_get_i_file(struct i2c_client *client, int fw_valid);
+static int fts_ft5822_get_app_i_file_ver(void);
+static int fts_ft5822_get_app_bin_file_ver(struct i2c_client *client,
+ char *firmware_name);
+static int fts_ft5822_upgrade_with_app_i_file(struct i2c_client *client);
+static int fts_ft5822_upgrade_with_app_bin_file(struct i2c_client *client,
+ char *firmware_name);
+
+struct fts_upgrade_fun fts_updatefun = {
+
+ .get_i_file = fts_ft5822_get_i_file,
+ .get_app_bin_file_ver = fts_ft5822_get_app_bin_file_ver,
+ .get_app_i_file_ver = fts_ft5822_get_app_i_file_ver,
+ .upgrade_with_app_i_file = fts_ft5822_upgrade_with_app_i_file,
+ .upgrade_with_app_bin_file = fts_ft5822_upgrade_with_app_bin_file,
+ .upgrade_with_lcd_cfg_i_file = NULL,
+ .upgrade_with_lcd_cfg_bin_file = NULL,
+};
+
+/*****************************************************************************
+ * Static function prototypes
+ *****************************************************************************/
+#if (FTS_GET_VENDOR_ID_NUM != 0)
+/************************************************************************
+ * Name: fts_ft5822_get_vendor_id_flash
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+static int fts_ft5822_get_vendor_id_flash(struct i2c_client *client,
+ u8 *vendor_id)
+{
+ u8 reg_val[2] = {0};
+ u32 i = 0;
+ u8 rw_buf[10];
+ int i_ret;
+
+ fts_ctpm_i2c_hid2std(client);
+
+ for (i = 0; i < FTS_UPGRADE_LOOP; i++) {
+ rw_buf[0] = FTS_UPGRADE_55;
+ rw_buf[1] = FTS_UPGRADE_AA;
+ i_ret = fts_i2c_write(client, rw_buf, 2);
+ if (i_ret < 0) {
+ FTS_ERROR("[UPGRADE]: failed writing 0x55 and 0xaa!!");
+ continue;
+ }
+
+ /*check run in bootloader or not*/
+ usleep_range(1000, 2000);
+ rw_buf[0] = FTS_READ_ID_REG;
+ rw_buf[1] = rw_buf[2] = rw_buf[3] = 0x00;
+ reg_val[0] = reg_val[1] = 0x00;
+ fts_i2c_read(client, rw_buf, 4, reg_val, 2);
+
+ FTS_DEBUG("[UPGRADE]: ID1 = 0x%x,ID2 = 0x%x!!",
+ reg_val[0], reg_val[1]);
+ if ((reg_val[0] == chip_types.bootloader_idh)
+ && (reg_val[1] == chip_types.bootloader_idl)) {
+ FTS_DEBUG("[UPGRADE]: read bootloader id ok!!");
+ break;
+ }
+
+ FTS_ERROR("[UPGRADE]: read bootloader id fail!!");
+ }
+
+ if (i >= FTS_UPGRADE_LOOP)
+ return -EIO;
+
+ /*read vendor id*/
+ rw_buf[0] = 0x03;
+ rw_buf[1] = 0x00;
+ rw_buf[2] = (u8)(CONFIG_VENDOR_ID_ADDR >> 8);
+ rw_buf[3] = (u8)(CONFIG_VENDOR_ID_ADDR);
+ i_ret = fts_i2c_write(client, rw_buf, 4);
+ usleep_range(10000, 20000); /*must wait, otherwise read vendor id fail*/
+ i_ret = fts_i2c_read(client, NULL, 0, vendor_id, 1);
+ if (i_ret < 0)
+ return -EIO;
+
+ FTS_DEBUG("Vendor ID from Flash:%x", *vendor_id);
+
+ return 0;
+}
+#endif
+
+/************************************************************************
+ * Name: fts_ft5822_get_i_file
+ * Brief: get .i file
+ * Input:
+ * Output:
+ * Return: 0 - ok
+ * <0 - fail
+ ***********************************************************************/
+static int fts_ft5822_get_i_file(struct i2c_client *client, int fw_valid)
+{
+ int ret = 0;
+
+#if (FTS_GET_VENDOR_ID_NUM != 0)
+ u8 vendor_id = 0;
+
+ if (fw_valid)
+ ret = fts_i2c_read_reg(client, FTS_REG_VENDOR_ID, &vendor_id);
+ else
+ ret = fts_ft5822_get_vendor_id_flash(client, &vendor_id);
+
+ FTS_DEBUG("[UPGRADE] tp_vendor_id=%x", vendor_id);
+ if (ret < 0) {
+ FTS_ERROR("Get upgrade file fail because of Vendor ID wrong");
+ return ret;
+ }
+
+ FTS_INFO("[UPGRADE]tp vendor id:%x, FTS_VENDOR_ID:%02x %02x %02x",
+ vendor_id, FTS_VENDOR_1_ID, FTS_VENDOR_2_ID, FTS_VENDOR_3_ID);
+ ret = 0;
+ switch (vendor_id) {
+#if (FTS_GET_VENDOR_ID_NUM >= 1)
+ case FTS_VENDOR_1_ID:
+ g_fw_file = CTPM_FW;
+ g_fw_len = fts_getsize(FW_SIZE);
+ FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW, SIZE:%x", g_fw_len);
+ break;
+#endif
+#if (FTS_GET_VENDOR_ID_NUM >= 2)
+ case FTS_VENDOR_2_ID:
+ g_fw_file = CTPM_FW2;
+ g_fw_len = fts_getsize(FW2_SIZE);
+ FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW2, SIZE:%x", g_fw_len);
+ break;
+#endif
+#if (FTS_GET_VENDOR_ID_NUM >= 3)
+ case FTS_VENDOR_3_ID:
+ g_fw_file = CTPM_FW3;
+ g_fw_len = fts_getsize(FW3_SIZE);
+ FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW3, SIZE:%x", g_fw_len);
+ break;
+#endif
+ default:
+ FTS_ERROR("[UPGRADE]Vendor ID check fail, get fw file fail");
+ ret = -EIO;
+ break;
+ }
+#else
+ /* (FTS_GET_VENDOR_ID_NUM == 0) */
+ g_fw_file = CTPM_FW;
+ g_fw_len = fts_getsize(FW_SIZE);
+ FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW, SIZE:%x", g_fw_len);
+#endif
+
+ return ret;
+}
+
+/************************************************************************
+ * Name: fts_ft5822_get_app_bin_file_ver
+ * Brief: get .i file version
+ * Input: no
+ * Output: no
+ * Return: fw version
+ ***********************************************************************/
+static int fts_ft5822_get_app_bin_file_ver(struct i2c_client *client,
+ char *firmware_name)
+{
+ const struct firmware *fw = NULL;
+ int fw_ver = 0;
+ int ret;
+
+ FTS_FUNC_ENTER();
+
+ ret = request_firmware(&fw, firmware_name, &client->dev);
+ if (ret) {
+ FTS_ERROR("[UPGRADE]: failed to get fw %s\n", firmware_name);
+ return ret;
+ }
+
+ if (fw->size < APP_FILE_MIN_SIZE || fw->size > APP_FILE_MAX_SIZE)
+ FTS_ERROR("[UPGRADE]: FW length(%x) error", fw->size);
+ else
+ fw_ver = fw->data[APP_FILE_VER_MAPPING];
+
+ release_firmware(fw);
+ FTS_FUNC_EXIT();
+
+ return fw_ver;
+}
+
+/************************************************************************
+ * Name: fts_ft5822_get_app_i_file_ver
+ * Brief: get .i file version
+ * Input: no
+ * Output: no
+ * Return: fw version
+ ***********************************************************************/
+static int fts_ft5822_get_app_i_file_ver(void)
+{
+ int fwsize = g_fw_len;
+
+ if (fwsize < APP_FILE_MIN_SIZE || fwsize > APP_FILE_MAX_SIZE) {
+ FTS_ERROR("[UPGRADE]: FW length(%x) error", fwsize);
+ return 0;
+ }
+
+ return g_fw_file[APP_FILE_VER_MAPPING];
+}
+
+#define AL2_FCS_COEF ((1 << 7) + (1 << 6) + (1 << 5))
+/*****************************************************************************
+ * Name: ecc_calc
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static u8 ecc_calc(u8 *pbt_buf, u16 start, u16 length)
+{
+ u8 cFcs = 0;
+ u16 i, j;
+
+ for (i = 0; i < length; i++) {
+ cFcs ^= pbt_buf[start++];
+ for (j = 0; j < 8; j++) {
+ if (cFcs & 1)
+ cFcs = (u8)((cFcs >> 1) ^ AL2_FCS_COEF);
+ else
+ cFcs >>= 1;
+ }
+ }
+ return cFcs;
+}
+
+/*****************************************************************************
+ * Name: fts_check_app_bin_valid
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static bool fts_check_app_bin_valid(u8 *pbt_buf)
+{
+ u8 ecc1;
+ u8 ecc2;
+ u8 ecc3;
+ u8 ecc4;
+ u16 len1;
+ u16 len2;
+ u8 cal_ecc1;
+ u8 cal_ecc2;
+ u16 usAddrInfo;
+
+ /* 1. First Byte */
+ if (pbt_buf[0] != 0x02) {
+ FTS_DEBUG("[UPGRADE]APP.BIN Verify- the first byte(%x) error",
+ pbt_buf[0]);
+ return false;
+ }
+
+ usAddrInfo = 0x100;
+
+ /* 2.len */
+ len1 = pbt_buf[usAddrInfo++] << 8;
+ len1 += pbt_buf[usAddrInfo++];
+
+ len2 = pbt_buf[usAddrInfo++] << 8;
+ len2 += pbt_buf[usAddrInfo++];
+
+ if ((len1 + len2) != 0xFFFF) {
+ FTS_DEBUG("[UPGRADE]APP.BIN Verify- LENGTH(%04x) XOR error",
+ len1);
+ return false;
+ }
+
+ /* 3.ecc */
+ ecc1 = pbt_buf[usAddrInfo++];
+ ecc2 = pbt_buf[usAddrInfo++];
+ ecc3 = pbt_buf[usAddrInfo++];
+ ecc4 = pbt_buf[usAddrInfo++];
+
+ if (((ecc1 + ecc2) != 0xFF) || ((ecc3 + ecc4) != 0xFF)) {
+ FTS_DEBUG("[UPGRADE]APP.BIN Verify- ECC(%x %x) XOR error",
+ ecc1, ecc2);
+ return false;
+ }
+
+ cal_ecc1 = ecc_calc(pbt_buf, 0x0, 0x100);
+ cal_ecc2 = ecc_calc(pbt_buf, 0x100 + 0x20, len1 - (0x100 + 0x20));
+ if ((ecc1 != cal_ecc1) || (ecc3 != cal_ecc2)) {
+ FTS_DEBUG("[UPGRADE]APP.BIN Verify- ECC calc error");
+ return false;
+ }
+ return true;
+}
+
+/************************************************************************
+ * Name: fts_ft5822_upgrade_use_buf
+ * Brief: fw upgrade
+ * Input: i2c info, file buf, file len
+ * Output: no
+ * Return: fail <0
+ ***********************************************************************/
+static int fts_ft5822_upgrade_use_buf(struct i2c_client *client,
+ u8 *pbt_buf, u32 dw_length)
+{
+ u8 reg_val[4] = {0};
+ u32 i = 0;
+ u32 packet_number;
+ u32 j = 0;
+ u32 temp;
+ u32 length;
+ u8 packet_buf[FTS_PACKET_LENGTH + 6];
+ u8 auc_i2c_write_buf[10];
+ u8 upgrade_ecc;
+ int i_ret;
+
+ fts_ctpm_i2c_hid2std(client);
+
+ for (i = 0; i < FTS_UPGRADE_LOOP; i++) {
+ /*********Step 1:Reset CTPM *****/
+ fts_i2c_write_reg(client, FTS_RST_CMD_REG1, FTS_UPGRADE_AA);
+ usleep_range(10000, 20000);
+ fts_i2c_write_reg(client, FTS_RST_CMD_REG1, FTS_UPGRADE_55);
+ msleep(200);
+
+ /*********Step 2:Enter upgrade mode *****/
+ fts_ctpm_i2c_hid2std(client);
+ usleep_range(5000, 10000);
+
+ auc_i2c_write_buf[0] = FTS_UPGRADE_55;
+ auc_i2c_write_buf[1] = FTS_UPGRADE_AA;
+ i_ret = fts_i2c_write(client, auc_i2c_write_buf, 2);
+ if (i_ret < 0) {
+ FTS_ERROR("[UPGRADE]: failed writing 0x55 and 0xaa!!");
+ continue;
+ }
+
+ /*********Step 3:Check bootloader ID *****/
+ usleep_range(1000, 2000);
+ auc_i2c_write_buf[0] = FTS_READ_ID_REG;
+ auc_i2c_write_buf[1] = auc_i2c_write_buf[2] =
+ auc_i2c_write_buf[3] = 0x00;
+ reg_val[0] = reg_val[1] = 0x00;
+ fts_i2c_read(client, auc_i2c_write_buf, 4, reg_val, 2);
+ FTS_DEBUG("[UPGRADE]:ID1 = 0x%x,ID2 = 0x%x!!",
+ reg_val[0], reg_val[1]);
+ if ((reg_val[0] == chip_types.bootloader_idh)
+ && (reg_val[1] == chip_types.bootloader_idl)) {
+ FTS_DEBUG("[UPGRADE]: read bootload id ok!!");
+ break;
+ }
+
+ FTS_ERROR("[UPGRADE]: read bootload id fail!!");
+ }
+
+ if (i >= FTS_UPGRADE_LOOP) {
+ FTS_ERROR("[UPGRADE]:failed writing 0x55 and 0xaa:i = %d!!", i);
+ return -EIO;
+ }
+
+ /*Step 4:erase app and panel paramenter area*/
+ FTS_DEBUG("[UPGRADE]: erase app and panel paramenter area!!");
+ auc_i2c_write_buf[0] = FTS_ERASE_APP_REG;
+ fts_i2c_write(client, auc_i2c_write_buf, 1);
+ msleep(1350);
+ for (i = 0; i < 15; i++) {
+ auc_i2c_write_buf[0] = 0x6a;
+ reg_val[0] = reg_val[1] = 0x00;
+ fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2);
+ if ((reg_val[0] == 0xF0) && (reg_val[1] == 0xAA))
+ break;
+ msleep(50);
+ }
+ FTS_DEBUG("[UPGRADE]:erase app area reg_val[0] = %x reg_val[1] = %x!!",
+ reg_val[0], reg_val[1]);
+
+ auc_i2c_write_buf[0] = 0xB0;
+ auc_i2c_write_buf[1] = (u8) ((dw_length >> 16) & 0xFF);
+ auc_i2c_write_buf[2] = (u8) ((dw_length >> 8) & 0xFF);
+ auc_i2c_write_buf[3] = (u8) (dw_length & 0xFF);
+ fts_i2c_write(client, auc_i2c_write_buf, 4);
+
+ /*********Step 5:write firmware(FW) to ctpm flash*********/
+ upgrade_ecc = 0;
+ FTS_DEBUG("[UPGRADE]: write FW to ctpm flash!!");
+ temp = 0;
+ packet_number = (dw_length) / FTS_PACKET_LENGTH;
+ packet_buf[0] = FTS_FW_WRITE_CMD;
+ packet_buf[1] = 0x00;
+
+ for (j = 0; j < packet_number; j++) {
+ temp = j * FTS_PACKET_LENGTH;
+ packet_buf[2] = (u8) (temp >> 8);
+ packet_buf[3] = (u8) temp;
+ length = FTS_PACKET_LENGTH;
+ packet_buf[4] = (u8) (length >> 8);
+ packet_buf[5] = (u8) length;
+ for (i = 0; i < FTS_PACKET_LENGTH; i++) {
+ packet_buf[6 + i] = pbt_buf[j * FTS_PACKET_LENGTH + i];
+ upgrade_ecc ^= packet_buf[6 + i];
+ }
+
+ fts_i2c_write(client, packet_buf, FTS_PACKET_LENGTH + 6);
+ usleep_range(10000, 20000);
+
+ for (i = 0; i < 30; i++) {
+ auc_i2c_write_buf[0] = 0x6a;
+ reg_val[0] = reg_val[1] = 0x00;
+ fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2);
+ if ((j + 0x1000) == (((reg_val[0]) << 8) | reg_val[1]))
+ break;
+ FTS_DEBUG("[UPGRADE]: reg_val[0] = %x reg_val[1] = %x",
+ reg_val[0], reg_val[1]);
+ /* msleep(1); */
+ fts_ctpm_upgrade_delay(1000);
+ }
+ }
+
+ if ((dw_length) % FTS_PACKET_LENGTH > 0) {
+ temp = packet_number * FTS_PACKET_LENGTH;
+ packet_buf[2] = (u8) (temp >> 8);
+ packet_buf[3] = (u8) temp;
+ temp = (dw_length) % FTS_PACKET_LENGTH;
+ packet_buf[4] = (u8) (temp >> 8);
+ packet_buf[5] = (u8) temp;
+ for (i = 0; i < temp; i++) {
+ packet_buf[6 + i] = pbt_buf[packet_number
+ * FTS_PACKET_LENGTH + i];
+ upgrade_ecc ^= packet_buf[6 + i];
+ }
+ fts_i2c_write(client, packet_buf, temp + 6);
+ usleep_range(10000, 20000);
+
+ for (i = 0; i < 30; i++) {
+ auc_i2c_write_buf[0] = 0x6a;
+ reg_val[0] = reg_val[1] = 0x00;
+ fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2);
+
+ if ((0x1000 + ((packet_number * FTS_PACKET_LENGTH)
+ /((dw_length) % FTS_PACKET_LENGTH)))
+ == (((reg_val[0]) << 8) | reg_val[1]))
+ break;
+ FTS_DEBUG("[UPGRADE]: reg_val[0] = %x!!", reg_val[0]);
+ FTS_DEBUG("[UPGRADE]: reg_val[1] = %x!!", reg_val[1]);
+ FTS_DEBUG("[UPGRADE]: reg_val[2] = %x!!",
+ (((packet_number * FTS_PACKET_LENGTH)
+ /((dw_length) % FTS_PACKET_LENGTH))+0x1000));
+ /* msleep(1); */
+ fts_ctpm_upgrade_delay(1000);
+ }
+ }
+
+ msleep(50);
+
+ /*********Step 6: read out checksum***********************/
+ /*send the opration head */
+ FTS_DEBUG("[UPGRADE]: read out checksum!!");
+ auc_i2c_write_buf[0] = 0x64;
+ fts_i2c_write(client, auc_i2c_write_buf, 1);
+ msleep(300);
+
+ temp = 0;
+ auc_i2c_write_buf[0] = 0x65;
+ auc_i2c_write_buf[1] = (u8)(temp >> 16);
+ auc_i2c_write_buf[2] = (u8)(temp >> 8);
+ auc_i2c_write_buf[3] = (u8)(temp);
+ temp = dw_length;
+ auc_i2c_write_buf[4] = (u8)(temp >> 8);
+ auc_i2c_write_buf[5] = (u8)(temp);
+ i_ret = fts_i2c_write(client, auc_i2c_write_buf, 6);
+ msleep(dw_length/256);
+
+ for (i = 0; i < 100; i++) {
+ auc_i2c_write_buf[0] = 0x6a;
+ reg_val[0] = reg_val[1] = 0x00;
+ fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2);
+ FTS_DEBUG("[UPGRADE]: reg_val[0]=%02x reg_val[0]=%02x!!",
+ reg_val[0], reg_val[1]);
+ if ((reg_val[0] == 0xF0) && (reg_val[1] == 0x55))
+ break;
+ usleep_range(1000, 2000);
+ }
+ auc_i2c_write_buf[0] = 0x66;
+ fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 1);
+ if (reg_val[0] != upgrade_ecc) {
+ FTS_ERROR("[UPGRADE]: ecc error! FW=%02x upgrade_ecc=%02x!!",
+ reg_val[0], upgrade_ecc);
+ return -EIO;
+ }
+
+ FTS_DEBUG("[UPGRADE]: checksum %x %x!!", reg_val[0], upgrade_ecc);
+
+ FTS_DEBUG("[UPGRADE]: reset the new FW!!");
+ auc_i2c_write_buf[0] = FTS_REG_RESET_FW;
+ fts_i2c_write(client, auc_i2c_write_buf, 1);
+ msleep(200);
+
+ fts_ctpm_i2c_hid2std(client);
+
+ return 0;
+}
+
+/************************************************************************
+ * Name: fts_ft5822_upgrade_with_app_i_file
+ * Brief: upgrade with *.i file
+ * Input: i2c info
+ * Output:
+ * Return: fail < 0
+ ***********************************************************************/
+static int fts_ft5822_upgrade_with_app_i_file(struct i2c_client *client)
+{
+ int i_ret = 0;
+ u32 fw_len;
+ u8 *fw_buf;
+
+ FTS_INFO("[UPGRADE]**********start upgrade with app.i**********");
+
+ fw_len = g_fw_len;
+ fw_buf = g_fw_file;
+ if (fw_len < APP_FILE_MIN_SIZE || fw_len > APP_FILE_MAX_SIZE) {
+ FTS_ERROR("[UPGRADE]: FW length(%x) error", fw_len);
+ return -EIO;
+ }
+
+ i_ret = fts_ft5822_upgrade_use_buf(client, fw_buf, fw_len);
+ if (i_ret != 0)
+ FTS_ERROR("[UPGRADE] upgrade app.i failed");
+ else
+ FTS_INFO("[UPGRADE]: upgrade app.i succeed");
+
+ return i_ret;
+}
+
+/************************************************************************
+ * Name: fts_ft5822_upgrade_with_app_bin_file
+ * Brief: upgrade with *.bin file
+ * Input: i2c info, file name
+ * Output: no
+ * Return: success =0
+ ***********************************************************************/
+static int fts_ft5822_upgrade_with_app_bin_file(struct i2c_client *client,
+ char *firmware_name)
+{
+ const struct firmware *fw = NULL;
+ u8 *pbt_buf = NULL;
+ int i_ret = 0;
+ bool ecc_ok = false;
+ int fwsize = 0;
+
+ FTS_INFO("[UPGRADE]**********start upgrade with app.bin**********");
+
+ i_ret = request_firmware(&fw, firmware_name, &client->dev);
+ if (i_ret) {
+ FTS_ERROR("[UPGRADE]: failed to get fw %s\n", firmware_name);
+ return i_ret;
+ }
+
+ if (fw->size < APP_FILE_MIN_SIZE || fw->size > APP_FILE_MAX_SIZE) {
+ FTS_ERROR("[UPGRADE]: app.bin length(%x) error, upgrade fail",
+ fwsize);
+ goto ERROR_BIN;
+ }
+
+ /*check the app.bin invalid or not*/
+ pbt_buf = (u8 *)fw->data;
+ if (pbt_buf[APP_FILE_CHIPID_MAPPING] != chip_types.chip_idh) {
+ FTS_ERROR("[UPGRADE]: chip id error, app.bin upgrade failed!!");
+ goto ERROR_BIN;
+ }
+
+ /*check the app.bin invalid or not*/
+ ecc_ok = fts_check_app_bin_valid(pbt_buf);
+ if (ecc_ok) {
+ FTS_INFO("[UPGRADE] app.bin ecc ok");
+ i_ret = fts_ft5822_upgrade_use_buf(client, pbt_buf, fw->size);
+ if (i_ret != 0) {
+ FTS_ERROR("[UPGRADE]: upgrade app.bin failed");
+ goto ERROR_BIN;
+ } else {
+ FTS_INFO("[UPGRADE]: upgrade app.bin succeed");
+ }
+ } else {
+ FTS_ERROR("[UPGRADE] app.bin ecc failed");
+ goto ERROR_BIN;
+ }
+
+ERROR_BIN:
+ release_firmware(fw);
+ return i_ret;
+}
+#endif /* FT5822 */
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft5x46.c b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft5x46.c
new file mode 100644
index 0000000..77f3c58
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft5x46.c
@@ -0,0 +1,625 @@
+/*
+ *
+ * FocalTech fts TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, Focaltech Ltd. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/*****************************************************************************
+ *
+ * File Name: focaltech_upgrade_ft5x46.c
+ *
+ * Author: fupeipei
+ *
+ * Created: 2016-08-15
+ *
+ * Abstract:
+ *
+ * Reference:
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * 1.Included header files
+ *****************************************************************************/
+#include "../focaltech_core.h"
+
+#if (IC_SERIALS == 0x02)
+#include "../focaltech_flash.h"
+#include "focaltech_upgrade_common.h"
+
+/*****************************************************************************
+ * Static variables
+ *****************************************************************************/
+#define APP_FILE_MAX_SIZE (60 * 1024)
+#define APP_FILE_MIN_SIZE (8)
+#define CONFIG_START_ADDR (0xD780)
+#define CONFIG_VENDOR_ID_OFFSET (0x04)
+#define CONFIG_PROJECT_ID_OFFSET (0x20)
+#define CONFIG_VENDOR_ID_ADDR (CONFIG_START_ADDR+CONFIG_VENDOR_ID_OFFSET)
+#define CONFIG_PROJECT_ID_ADDR (CONFIG_START_ADDR+CONFIG_PROJECT_ID_OFFSET)
+/*****************************************************************************
+ * Global variable or extern global variabls/functions
+ *****************************************************************************/
+static int fts_ft5x46_get_i_file(struct i2c_client *client, int fw_valid);
+static int fts_ft5x46_get_app_i_file_ver(void);
+static int fts_ft5x46_get_app_bin_file_ver(struct i2c_client *client,
+ char *firmware_name);
+static int fts_ft5x46_upgrade_with_app_i_file(struct i2c_client *client);
+static int fts_ft5x46_upgrade_with_app_bin_file(struct i2c_client *client,
+ char *firmware_name);
+
+struct fts_upgrade_fun fts_updatefun = {
+
+ .get_i_file = fts_ft5x46_get_i_file,
+ .get_app_bin_file_ver = fts_ft5x46_get_app_bin_file_ver,
+ .get_app_i_file_ver = fts_ft5x46_get_app_i_file_ver,
+ .upgrade_with_app_i_file = fts_ft5x46_upgrade_with_app_i_file,
+ .upgrade_with_app_bin_file = fts_ft5x46_upgrade_with_app_bin_file,
+ .upgrade_with_lcd_cfg_i_file = NULL,
+ .upgrade_with_lcd_cfg_bin_file = NULL,
+};
+
+/*****************************************************************************
+ * Static function prototypes
+ *****************************************************************************/
+#if (FTS_GET_VENDOR_ID_NUM != 0)
+/************************************************************************
+ * Name: fts_ft5x46_get_vendor_id_flash
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+static int fts_ft5x46_get_vendor_id_flash(struct i2c_client *client,
+ u8 *vendor_id)
+{
+ u8 reg_val[2] = {0};
+ u32 i = 0;
+ u8 rw_buf[10];
+ int i_ret;
+
+ fts_ctpm_i2c_hid2std(client);
+
+ for (i = 0; i < FTS_UPGRADE_LOOP; i++) {
+ rw_buf[0] = FTS_UPGRADE_55;
+ rw_buf[1] = FTS_UPGRADE_AA;
+ i_ret = fts_i2c_write(client, rw_buf, 2);
+ if (i_ret < 0) {
+ FTS_ERROR("[UPGRADE]: failed writing 0x55 and 0xaa!!");
+ continue;
+ }
+
+ /*check run in bootloader or not*/
+ usleep_range(1000, 2000);
+ rw_buf[0] = FTS_READ_ID_REG;
+ rw_buf[1] = rw_buf[2] = rw_buf[3] = 0x00;
+ reg_val[0] = reg_val[1] = 0x00;
+ fts_i2c_read(client, rw_buf, 4, reg_val, 2);
+
+ FTS_DEBUG("[UPGRADE]:ID1 = 0x%x,ID2 = 0x%x!!",
+ reg_val[0], reg_val[1]);
+ if ((reg_val[0] == chip_types.bootloader_idh)
+ && (reg_val[1] == chip_types.bootloader_idl)) {
+ FTS_DEBUG("[UPGRADE]: read bootloader id ok!!");
+ break;
+ }
+
+ FTS_ERROR("[UPGRADE]: read bootloader id fail!!");
+ }
+
+ if (i >= FTS_UPGRADE_LOOP)
+ return -EIO;
+
+ /*read vendor id*/
+ rw_buf[0] = 0x03;
+ rw_buf[1] = 0x00;
+ rw_buf[2] = (u8)(CONFIG_VENDOR_ID_ADDR >> 8);
+ rw_buf[3] = (u8)(CONFIG_VENDOR_ID_ADDR);
+ i_ret = fts_i2c_write(client, rw_buf, 4);
+ usleep_range(10000, 20000); /*must wait, otherwise read vendor id fail*/
+ i_ret = fts_i2c_read(client, NULL, 0, vendor_id, 1);
+ if (i_ret < 0)
+ return -EIO;
+ FTS_DEBUG("Vendor ID from Flash:%x", *vendor_id);
+ return 0;
+}
+#endif
+
+/************************************************************************
+ * Name: fts_ft5x46_get_i_file
+ * Brief: get .i file
+ * Input:
+ * Output:
+ * Return: 0 - ok
+ * <0 - fail
+ ***********************************************************************/
+static int fts_ft5x46_get_i_file(struct i2c_client *client, int fw_valid)
+{
+ int ret = 0;
+
+#if (FTS_GET_VENDOR_ID_NUM != 0)
+ u8 vendor_id = 0;
+
+ if (fw_valid)
+ ret = fts_i2c_read_reg(client, FTS_REG_VENDOR_ID, &vendor_id);
+ else
+ ret = fts_ft5x46_get_vendor_id_flash(client, &vendor_id);
+
+ FTS_DEBUG("[UPGRADE] tp_vendor_id=%x", vendor_id);
+ if (ret < 0) {
+ FTS_ERROR("Get upgrade file fail because of Vendor ID wrong");
+ return ret;
+ }
+
+ FTS_INFO("[UPGRADE]tp vendor id:%x, FTS_VENDOR_ID:%02x %02x %02x",
+ vendor_id, FTS_VENDOR_1_ID, FTS_VENDOR_2_ID, FTS_VENDOR_3_ID);
+ ret = 0;
+ switch (vendor_id) {
+#if (FTS_GET_VENDOR_ID_NUM >= 1)
+ case FTS_VENDOR_1_ID:
+ g_fw_file = CTPM_FW;
+ g_fw_len = fts_getsize(FW_SIZE);
+ FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW, SIZE:%x", g_fw_len);
+ break;
+#endif
+#if (FTS_GET_VENDOR_ID_NUM >= 2)
+ case FTS_VENDOR_2_ID:
+ g_fw_file = CTPM_FW2;
+ g_fw_len = fts_getsize(FW2_SIZE);
+ FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW2, SIZE:%x", g_fw_len);
+ break;
+#endif
+#if (FTS_GET_VENDOR_ID_NUM >= 3)
+ case FTS_VENDOR_3_ID:
+ g_fw_file = CTPM_FW3;
+ g_fw_len = fts_getsize(FW3_SIZE);
+ FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW3, SIZE:%x", g_fw_len);
+ break;
+#endif
+ default:
+ FTS_ERROR("[UPGRADE]Vendor ID check fail, get fw file fail");
+ ret = -EIO;
+ break;
+ }
+#else
+ /* (FTS_GET_VENDOR_ID_NUM == 0) */
+ g_fw_file = CTPM_FW;
+ g_fw_len = fts_getsize(FW_SIZE);
+ FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW, SIZE:%x", g_fw_len);
+#endif
+
+ return ret;
+}
+
+/************************************************************************
+ * Name: fts_ft5x46_get_app_bin_file_ver
+ * Brief: get .i file version
+ * Input: no
+ * Output: no
+ * Return: fw version
+ ***********************************************************************/
+static int fts_ft5x46_get_app_bin_file_ver(struct i2c_client *client,
+ char *firmware_name)
+{
+ const struct firmware *fw = NULL;
+ int fw_ver = 0;
+ int ret;
+
+ FTS_FUNC_ENTER();
+
+ ret = request_firmware(&fw, firmware_name, &client->dev);
+ if (ret) {
+ FTS_ERROR("[UPGRADE]: failed to get fw %s\n", firmware_name);
+ return ret;
+ }
+
+ if (fw->size > 2)
+ fw_ver = fw->data[fw->size - 2];
+
+ release_firmware(fw);
+ FTS_FUNC_EXIT();
+
+ return fw_ver;
+}
+
+/************************************************************************
+ * Name: fts_ft5x46_get_app_i_file_ver
+ * Brief: get .i file version
+ * Input: no
+ * Output: no
+ * Return: fw version
+ ***********************************************************************/
+static int fts_ft5x46_get_app_i_file_ver(void)
+{
+ int fwsize = g_fw_len;
+
+ if (fwsize < APP_FILE_MIN_SIZE || fwsize > APP_FILE_MAX_SIZE) {
+ FTS_ERROR("[UPGRADE]: FW length(%x) error", fwsize);
+ return 0;
+ }
+
+ return g_fw_file[fwsize-2];
+}
+
+#define AL2_FCS_COEF ((1 << 7) + (1 << 6) + (1 << 5))
+/*****************************************************************************
+ * Name: ecc_calc
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static u8 ecc_calc(u8 *pbt_buf, u16 start, u16 length)
+{
+ u8 cFcs = 0;
+ u16 i, j;
+
+ for (i = 0; i < length; i++) {
+ cFcs ^= pbt_buf[start++];
+ for (j = 0; j < 8; j++) {
+ if (cFcs & 1)
+ cFcs = (u8)((cFcs >> 1) ^ AL2_FCS_COEF);
+ else
+ cFcs >>= 1;
+ }
+ }
+ return cFcs;
+}
+
+/*****************************************************************************
+ * Name: fts_check_app_bin_valid
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static bool fts_check_app_bin_valid(u8 *pbt_buf, u32 dw_length)
+{
+ u8 ecc1;
+ u8 ecc2;
+ u16 len1;
+ u16 len2;
+ u8 cal_ecc;
+ u16 usAddrInfo;
+
+ /* 1. First Byte */
+ if (pbt_buf[0] != 0x02) {
+ FTS_DEBUG("[UPGRADE]APP.BIN Verify- the first byte(%x) error",
+ pbt_buf[0]);
+ return false;
+ }
+
+ usAddrInfo = dw_length - 8;
+
+ /* 2.len */
+ len1 = pbt_buf[usAddrInfo++] << 8;
+ len1 += pbt_buf[usAddrInfo++];
+
+ len2 = pbt_buf[usAddrInfo++] << 8;
+ len2 += pbt_buf[usAddrInfo++];
+
+ if ((len1 + len2) != 0xFFFF) {
+ FTS_DEBUG("[UPGRADE]APP.BIN Verify- LENGTH(%04x) XOR error",
+ len1);
+ return false;
+ }
+
+ /* 3.ecc */
+ ecc1 = pbt_buf[usAddrInfo++];
+ ecc2 = pbt_buf[usAddrInfo++];
+
+ if ((ecc1 + ecc2) != 0xFF) {
+ FTS_DEBUG("[UPGRADE]APP.BIN Verify- ECC(%x) XOR error", ecc1);
+ return false;
+ }
+
+ cal_ecc = ecc_calc(pbt_buf, 0x0, len1);
+
+ if (ecc1 != cal_ecc) {
+ FTS_DEBUG("[UPGRADE]APP.BIN Verify- ECC calc error");
+ return false;
+ }
+ return true;
+}
+
+
+/************************************************************************
+ * Name: fts_ft5x46_upgrade_use_buf
+ * Brief: fw upgrade
+ * Input: i2c info, file buf, file len
+ * Output: no
+ * Return: fail <0
+ ***********************************************************************/
+static int fts_ft5x46_upgrade_use_buf(struct i2c_client *client,
+ u8 *pbt_buf, u32 dw_length)
+{
+ u8 reg_val[4] = {0};
+ u32 i = 0;
+ u32 packet_number;
+ u32 j = 0;
+ u32 temp;
+ u32 length;
+ u8 packet_buf[FTS_PACKET_LENGTH + 6];
+ u8 auc_i2c_write_buf[10];
+ u8 upgrade_ecc;
+ int i_ret;
+
+ fts_ctpm_i2c_hid2std(client);
+
+ for (i = 0; i < FTS_UPGRADE_LOOP; i++) {
+ /*********Step 1:Reset CTPM *****/
+ fts_i2c_write_reg(client, FTS_RST_CMD_REG1, FTS_UPGRADE_AA);
+ usleep_range(10000, 20000);
+ fts_i2c_write_reg(client, FTS_RST_CMD_REG1, FTS_UPGRADE_55);
+ msleep(200);
+
+ /*********Step 2:Enter upgrade mode *****/
+ fts_ctpm_i2c_hid2std(client);
+ usleep_range(5000, 10000);
+
+ auc_i2c_write_buf[0] = FTS_UPGRADE_55;
+ auc_i2c_write_buf[1] = FTS_UPGRADE_AA;
+ i_ret = fts_i2c_write(client, auc_i2c_write_buf, 2);
+ if (i_ret < 0) {
+ FTS_ERROR("[UPGRADE]: failed writing 0x55 and 0xaa!!");
+ continue;
+ }
+
+ /*********Step 3:Check bootloader ID *****/
+ usleep_range(1000, 2000);
+ auc_i2c_write_buf[0] = FTS_READ_ID_REG;
+ auc_i2c_write_buf[1] = auc_i2c_write_buf[2] =
+ auc_i2c_write_buf[3] = 0x00;
+ reg_val[0] = reg_val[1] = 0x00;
+ fts_i2c_read(client, auc_i2c_write_buf, 4, reg_val, 2);
+ FTS_DEBUG("[UPGRADE]: ID1 = 0x%x,ID2 = 0x%x!!",
+ reg_val[0], reg_val[1]);
+ if ((reg_val[0] == chip_types.bootloader_idh)
+ && (reg_val[1] == chip_types.bootloader_idl)) {
+ FTS_DEBUG("[UPGRADE]: read bootload id ok!!");
+ break;
+ }
+
+ FTS_ERROR("[UPGRADE]: read bootload id fail!!");
+ }
+
+ if (i >= FTS_UPGRADE_LOOP) {
+ FTS_ERROR("[UPGRADE]:failed writing 0x55 and 0xaa:i = %d!!", i);
+ return -EIO;
+ }
+
+ /*Step 4:erase app and panel paramenter area*/
+ FTS_DEBUG("[UPGRADE]: erase app and panel paramenter area!!");
+ auc_i2c_write_buf[0] = FTS_ERASE_APP_REG;
+ fts_i2c_write(client, auc_i2c_write_buf, 1);
+ msleep(1350);
+ for (i = 0; i < 15; i++) {
+ auc_i2c_write_buf[0] = 0x6a;
+ reg_val[0] = reg_val[1] = 0x00;
+ fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2);
+ if ((reg_val[0] == 0xF0) && (reg_val[1] == 0xAA))
+ break;
+ msleep(50);
+ }
+ FTS_DEBUG("[UPGRADE]:erase app area reg_val[0] = %x reg_val[1] = %x!!",
+ reg_val[0], reg_val[1]);
+
+ auc_i2c_write_buf[0] = 0xB0;
+ auc_i2c_write_buf[1] = (u8) ((dw_length >> 16) & 0xFF);
+ auc_i2c_write_buf[2] = (u8) ((dw_length >> 8) & 0xFF);
+ auc_i2c_write_buf[3] = (u8) (dw_length & 0xFF);
+ fts_i2c_write(client, auc_i2c_write_buf, 4);
+
+ /*********Step 5:write firmware(FW) to ctpm flash*********/
+ upgrade_ecc = 0;
+ FTS_DEBUG("[UPGRADE]: write FW to ctpm flash!!");
+ temp = 0;
+ packet_number = (dw_length) / FTS_PACKET_LENGTH;
+ packet_buf[0] = FTS_FW_WRITE_CMD;
+ packet_buf[1] = 0x00;
+
+ for (j = 0; j < packet_number; j++) {
+ temp = j * FTS_PACKET_LENGTH;
+ packet_buf[2] = (u8) (temp >> 8);
+ packet_buf[3] = (u8) temp;
+ length = FTS_PACKET_LENGTH;
+ packet_buf[4] = (u8) (length >> 8);
+ packet_buf[5] = (u8) length;
+ for (i = 0; i < FTS_PACKET_LENGTH; i++) {
+ packet_buf[6 + i] = pbt_buf[j * FTS_PACKET_LENGTH + i];
+ upgrade_ecc ^= packet_buf[6 + i];
+ }
+ fts_i2c_write(client, packet_buf, FTS_PACKET_LENGTH + 6);
+ usleep_range(10000, 20000);
+
+ for (i = 0; i < 30; i++) {
+ auc_i2c_write_buf[0] = 0x6a;
+ reg_val[0] = reg_val[1] = 0x00;
+ fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2);
+ if ((j + 0x1000) == (((reg_val[0]) << 8) | reg_val[1]))
+ break;
+ FTS_DEBUG("[UPGRADE]:reg_val[0] = %x reg_val[1] = %x!!",
+ reg_val[0], reg_val[1]);
+ /* usleep_range(1000, 2000); */
+ fts_ctpm_upgrade_delay(1000);
+ }
+ }
+
+ if ((dw_length) % FTS_PACKET_LENGTH > 0) {
+ temp = packet_number * FTS_PACKET_LENGTH;
+ packet_buf[2] = (u8) (temp >> 8);
+ packet_buf[3] = (u8) temp;
+ temp = (dw_length) % FTS_PACKET_LENGTH;
+ packet_buf[4] = (u8) (temp >> 8);
+ packet_buf[5] = (u8) temp;
+ for (i = 0; i < temp; i++) {
+ packet_buf[6 + i] = pbt_buf[packet_number
+ * FTS_PACKET_LENGTH + i];
+ upgrade_ecc ^= packet_buf[6 + i];
+ }
+ fts_i2c_write(client, packet_buf, temp + 6);
+ usleep_range(10000, 20000);
+
+ for (i = 0; i < 30; i++) {
+ auc_i2c_write_buf[0] = 0x6a;
+ reg_val[0] = reg_val[1] = 0x00;
+ fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2);
+
+ if ((0x1000 + ((packet_number * FTS_PACKET_LENGTH)
+ /((dw_length) % FTS_PACKET_LENGTH))) ==
+ (((reg_val[0]) << 8) | reg_val[1]))
+ break;
+ FTS_DEBUG("[UPGRADE]: reg_val[0] = %x!!", reg_val[0]);
+ FTS_DEBUG("[UPGRADE]: reg_val[1] = %x!!", reg_val[1]);
+ FTS_DEBUG("[UPGRADE]: reg_val[2] = 0x%x!!",
+ (((packet_number * FTS_PACKET_LENGTH)
+ /((dw_length) % FTS_PACKET_LENGTH))+0x1000));
+ /* usleep_range(1000, 2000); */
+ fts_ctpm_upgrade_delay(1000);
+ }
+ }
+
+ msleep(50);
+
+ /*********Step 6: read out checksum***********************/
+ /*send the opration head */
+ FTS_DEBUG("[UPGRADE]: read out checksum!!");
+ auc_i2c_write_buf[0] = 0x64;
+ fts_i2c_write(client, auc_i2c_write_buf, 1);
+ msleep(300);
+
+ temp = 0;
+ auc_i2c_write_buf[0] = 0x65;
+ auc_i2c_write_buf[1] = (u8)(temp >> 16);
+ auc_i2c_write_buf[2] = (u8)(temp >> 8);
+ auc_i2c_write_buf[3] = (u8)(temp);
+ temp = dw_length;
+ auc_i2c_write_buf[4] = (u8)(temp >> 8);
+ auc_i2c_write_buf[5] = (u8)(temp);
+ i_ret = fts_i2c_write(client, auc_i2c_write_buf, 6);
+ msleep(dw_length/256);
+
+ for (i = 0; i < 100; i++) {
+ auc_i2c_write_buf[0] = 0x6a;
+ reg_val[0] = reg_val[1] = 0x00;
+ fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2);
+ FTS_DEBUG("[UPGRADE]: reg_val[0]=%02x reg_val[0]=%02x!!",
+ reg_val[0], reg_val[1]);
+ if ((reg_val[0] == 0xF0) && (reg_val[1] == 0x55))
+ break;
+ usleep_range(1000, 2000);
+ }
+ auc_i2c_write_buf[0] = 0x66;
+ fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 1);
+ if (reg_val[0] != upgrade_ecc) {
+ FTS_ERROR("[UPGRADE]: ecc error! FW=%02x upgrade_ecc=%02x!!",
+ reg_val[0], upgrade_ecc);
+ return -EIO;
+ }
+ FTS_DEBUG("[UPGRADE]: checksum %x %x!!", reg_val[0], upgrade_ecc);
+
+ FTS_DEBUG("[UPGRADE]: reset the new FW!!");
+ auc_i2c_write_buf[0] = FTS_REG_RESET_FW;
+ fts_i2c_write(client, auc_i2c_write_buf, 1);
+ msleep(200);
+
+ fts_ctpm_i2c_hid2std(client);
+
+ return 0;
+}
+
+/************************************************************************
+ * Name: fts_ft5x46_upgrade_with_app_i_file
+ * Brief: upgrade with *.i file
+ * Input: i2c info
+ * Output:
+ * Return: fail < 0
+ ***********************************************************************/
+static int fts_ft5x46_upgrade_with_app_i_file(struct i2c_client *client)
+{
+ int i_ret = 0;
+ u32 fw_len;
+ u8 *fw_buf;
+
+ FTS_INFO("[UPGRADE]**********start upgrade with app.i**********");
+
+ fw_len = g_fw_len;
+ fw_buf = g_fw_file;
+ if (fw_len < APP_FILE_MIN_SIZE || fw_len > APP_FILE_MAX_SIZE) {
+ FTS_ERROR("[UPGRADE]: FW length(%x) error", fw_len);
+ return -EIO;
+ }
+
+ i_ret = fts_ft5x46_upgrade_use_buf(client, fw_buf, fw_len);
+ if (i_ret != 0)
+ FTS_ERROR("[UPGRADE] upgrade app.i failed");
+ else
+ FTS_INFO("[UPGRADE]: upgrade app.i succeed");
+
+ return i_ret;
+}
+
+/************************************************************************
+ * Name: fts_ft5x46_upgrade_with_app_bin_file
+ * Brief: upgrade with *.bin file
+ * Input: i2c info, file name
+ * Output: no
+ * Return: success =0
+ ***********************************************************************/
+static int fts_ft5x46_upgrade_with_app_bin_file(struct i2c_client *client,
+ char *firmware_name)
+{
+ const struct firmware *fw = NULL;
+ u8 *pbt_buf = NULL;
+ int i_ret = 0;
+ bool ecc_ok = false;
+ int fwsize = 0;
+
+ FTS_INFO("[UPGRADE]**********start upgrade with app.bin**********");
+
+ i_ret = request_firmware(&fw, firmware_name, &client->dev);
+ if (i_ret) {
+ FTS_ERROR("[UPGRADE]: failed to get fw %s\n", firmware_name);
+ return i_ret;
+ }
+
+ if (fw->size < APP_FILE_MIN_SIZE || fw->size > APP_FILE_MAX_SIZE) {
+ FTS_ERROR("[UPGRADE]: app.bin length(%x) error, upgrade fail",
+ fwsize);
+ goto ERROR_BIN;
+ }
+
+ /*check the app.bin invalid or not*/
+ pbt_buf = (u8 *)fw->data;
+ ecc_ok = fts_check_app_bin_valid(pbt_buf, fw->size);
+
+ if (ecc_ok) {
+ FTS_INFO("[UPGRADE] app.bin ecc ok");
+ i_ret = fts_ft5x46_upgrade_use_buf(client, pbt_buf, fw->size);
+ if (i_ret != 0) {
+ FTS_ERROR("[UPGRADE]: upgrade app.bin failed");
+ goto ERROR_BIN;
+ } else {
+ FTS_INFO("[UPGRADE]: upgrade app.bin succeed");
+ }
+ } else {
+ FTS_ERROR("[UPGRADE] app.bin ecc failed");
+ goto ERROR_BIN;
+ }
+
+ERROR_BIN:
+ release_firmware(fw);
+ return i_ret;
+}
+#endif /* FT5X46 */
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft6336gu.c b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft6336gu.c
new file mode 100644
index 0000000..7516ab2
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft6336gu.c
@@ -0,0 +1,606 @@
+/*
+ *
+ * FocalTech fts TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, Focaltech Ltd. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/*****************************************************************************
+ *
+ * File Name: focaltech_upgrade_ft6336GU.c
+ *
+ * Author: fupeipei
+ *
+ * Created: 2016-08-15
+ *
+ * Abstract:
+ *
+ * Reference:
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * 1.Included header files
+ *****************************************************************************/
+#include "../focaltech_core.h"
+
+#if ((IC_SERIALS == 0x03) || (IC_SERIALS == 0x04))
+#include "../focaltech_flash.h"
+#include "focaltech_upgrade_common.h"
+
+/*****************************************************************************
+ * Static variables
+ *****************************************************************************/
+#define APP_FILE_MAX_SIZE (60 * 1024)
+#define APP_FILE_MIN_SIZE (8)
+#define APP_FILE_VER_MAPPING (0x10A)
+#define APP_FILE_VENDORID_MAPPING (0x10C)
+#define CONFIG_START_ADDR (0x7B0)
+#define CONFIG_VENDOR_ID_OFFSET (0x4)
+#define CONFIG_PROJECT_ID_OFFSET (0x20)
+#define CONFIG_VENDOR_ID_ADDR (CONFIG_START_ADDR+CONFIG_VENDOR_ID_OFFSET)
+#define CONFIG_PROJECT_ID_ADDR (CONFIG_START_ADDR+CONFIG_PROJECT_ID_OFFSET)
+
+#define APP_LEN 0x00
+#define APP_LEN_NE 0x02
+#define APP_P1_ECC 0x04
+#define APP_P1_ECC_NE 0x05
+#define APP_P2_ECC 0x06
+#define APP_P2_ECC_NE 0x07
+
+#define APP1_START 0x00
+#define APP1_LEN 0x100
+#define APP_VERIF_ADDR (APP1_START + APP1_LEN)
+#define APP_VERIF_LEN 0x20
+#define APP1_ECC_ADDR (APP_VERIF_ADDR + APP_P1_ECC)
+#define APP2_START (APP_VERIF_ADDR + APP_VERIF_LEN)
+#define APP2_ECC_ADDR (APP_VERIF_ADDR + APP_P2_ECC)
+/*****************************************************************************
+ * Global variable or extern global variabls/functions
+ *****************************************************************************/
+static int fts_ft6x36gu_get_i_file(struct i2c_client *client, int fw_valid);
+static int fts_ft6x36gu_get_app_i_file_ver(void);
+static int fts_ft6x36gu_get_app_bin_file_ver(struct i2c_client *client,
+ char *firmware_name);
+static int fts_ft6x36gu_upgrade_with_app_i_file(struct i2c_client *client);
+static int fts_ft6x36gu_upgrade_with_app_bin_file(struct i2c_client *client,
+ char *firmware_name);
+
+struct fts_upgrade_fun fts_updatefun = {
+
+ .get_i_file = fts_ft6x36gu_get_i_file,
+ .get_app_bin_file_ver = fts_ft6x36gu_get_app_bin_file_ver,
+ .get_app_i_file_ver = fts_ft6x36gu_get_app_i_file_ver,
+ .upgrade_with_app_i_file = fts_ft6x36gu_upgrade_with_app_i_file,
+ .upgrade_with_app_bin_file = fts_ft6x36gu_upgrade_with_app_bin_file,
+ .upgrade_with_lcd_cfg_i_file = NULL,
+ .upgrade_with_lcd_cfg_bin_file = NULL,
+};
+
+/*****************************************************************************
+ * Static function prototypes
+ *****************************************************************************/
+#if (FTS_GET_VENDOR_ID_NUM != 0)
+/************************************************************************
+ * Name: fts_ft6x36gu_get_vendor_id_flash
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+static int fts_ft6x36gu_get_vendor_id_flash(struct i2c_client *client,
+ u8 *vendor_id)
+{
+ u8 reg_val[2] = {0};
+ u32 i = 0;
+ u8 rw_buf[10];
+ int i_ret;
+
+ for (i = 0; i < FTS_UPGRADE_LOOP; i++) {
+ rw_buf[0] = FTS_UPGRADE_55;
+ rw_buf[1] = FTS_UPGRADE_AA;
+ i_ret = fts_i2c_write(client, rw_buf, 2);
+ if (i_ret < 0) {
+ FTS_ERROR("[UPGRADE]: failed writing 0x55 and 0xaa!!");
+ continue;
+ }
+
+ /*check run in bootloader or not*/
+ usleep_range(1000, 2000);
+ rw_buf[0] = FTS_READ_ID_REG;
+ rw_buf[1] = rw_buf[2] = rw_buf[3] = 0x00;
+ reg_val[0] = reg_val[1] = 0x00;
+ fts_i2c_read(client, rw_buf, 4, reg_val, 2);
+
+ FTS_DEBUG("[UPGRADE]: ID1 = 0x%x,ID2 = 0x%x!!",
+ reg_val[0], reg_val[1]);
+ if ((reg_val[0] == chip_types.bootloader_idh)
+ && (reg_val[1] == chip_types.bootloader_idl)) {
+ FTS_DEBUG("[UPGRADE]: read bootloader id ok!! ");
+ break;
+ }
+ FTS_ERROR("[UPGRADE]: read bootloader id fail!!");
+ }
+
+ if (i >= FTS_UPGRADE_LOOP)
+ return -EIO;
+
+ /*read vendor id*/
+ rw_buf[0] = 0x03;
+ rw_buf[1] = 0x00;
+ rw_buf[2] = (u8)(CONFIG_VENDOR_ID_ADDR >> 8);
+ rw_buf[3] = (u8)(CONFIG_VENDOR_ID_ADDR);
+ i_ret = fts_i2c_write(client, rw_buf, 4);
+ usleep_range(10000, 20000); /*must wait, otherwise read vendor id fail*/
+ i_ret = fts_i2c_read(client, NULL, 0, vendor_id, 1);
+ if (i_ret < 0)
+ return -EIO;
+ FTS_DEBUG("Vendor ID from Flash:%x", *vendor_id);
+ return 0;
+}
+#endif
+
+/************************************************************************
+ * Name: fts_ft6x36gu_get_i_file
+ * Brief: get .i file
+ * Input:
+ * Output:
+ * Return: 0 - ok
+ * <0 - fail
+ ***********************************************************************/
+static int fts_ft6x36gu_get_i_file(struct i2c_client *client, int fw_valid)
+{
+ int ret = -EIO;
+
+#if (FTS_GET_VENDOR_ID_NUM != 0)
+ u8 vendor_id = 0;
+
+ if (fw_valid)
+ ret = fts_i2c_read_reg(client, FTS_REG_VENDOR_ID, &vendor_id);
+ else
+ ret = fts_ft6x36gu_get_vendor_id_flash(client, &vendor_id);
+
+ FTS_DEBUG("[UPGRADE] tp_vendor_id=%x", vendor_id);
+ if (ret < 0) {
+ FTS_ERROR("Get upgrade file fail because of Vendor ID wrong");
+ return ret;
+ }
+
+ FTS_INFO("[UPGRADE]tp vendor id:%x, FTS_VENDOR_ID:%02x %02x %02x",
+ vendor_id, FTS_VENDOR_1_ID, FTS_VENDOR_2_ID, FTS_VENDOR_3_ID);
+ ret = 0;
+ switch (vendor_id) {
+#if (FTS_GET_VENDOR_ID_NUM >= 1)
+ case FTS_VENDOR_1_ID:
+ g_fw_file = CTPM_FW;
+ g_fw_len = fts_getsize(FW_SIZE);
+ FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW, SIZE:%x", g_fw_len);
+ break;
+#endif
+#if (FTS_GET_VENDOR_ID_NUM >= 2)
+ case FTS_VENDOR_2_ID:
+ g_fw_file = CTPM_FW2;
+ g_fw_len = fts_getsize(FW2_SIZE);
+ FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW2, SIZE:%x", g_fw_len);
+ break;
+#endif
+#if (FTS_GET_VENDOR_ID_NUM >= 3)
+ case FTS_VENDOR_3_ID:
+ g_fw_file = CTPM_FW3;
+ g_fw_len = fts_getsize(FW3_SIZE);
+ FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW3, SIZE:%x", g_fw_len);
+ break;
+#endif
+ default:
+ FTS_ERROR("[UPGRADE]Vendor ID check fail, get fw file fail");
+ ret = -EIO;
+ break;
+ }
+#endif
+
+ return ret;
+}
+
+/************************************************************************
+ * Name: fts_ft6x36gu_get_app_bin_file_ver
+ * Brief: get .i file version
+ * Input: no
+ * Output: no
+ * Return: fw version
+ ***********************************************************************/
+static int fts_ft6x36gu_get_app_bin_file_ver(struct i2c_client *client,
+ char *firmware_name)
+{
+ const struct firmware *fw = NULL;
+ int fw_ver = 0;
+ int ret;
+
+ FTS_FUNC_ENTER();
+
+ ret = request_firmware(&fw, firmware_name, &client->dev);
+ if (ret) {
+ FTS_ERROR("[UPGRADE]: failed to get fw %s\n", firmware_name);
+ return ret;
+ }
+
+ if (fw->size < APP_FILE_MIN_SIZE || fw->size > APP_FILE_MAX_SIZE)
+ FTS_ERROR("[UPGRADE]: FW length(%x) error", fw->size);
+ else
+ fw_ver = fw->data[APP_FILE_VER_MAPPING];
+
+ release_firmware(fw);
+ FTS_FUNC_EXIT();
+
+ return fw_ver;
+}
+
+/************************************************************************
+ * Name: fts_ft6x36gu_get_app_i_file_ver
+ * Brief: get .i file version
+ * Input: no
+ * Output: no
+ * Return: fw version
+ ***********************************************************************/
+static int fts_ft6x36gu_get_app_i_file_ver(void)
+{
+ int fwsize = g_fw_len;
+
+ if (fwsize < APP_FILE_MIN_SIZE || fwsize > APP_FILE_MAX_SIZE) {
+ FTS_ERROR("[UPGRADE]: FW length(%x) error", fwsize);
+ return 0;
+ }
+
+ return g_fw_file[APP_FILE_VER_MAPPING];
+}
+
+/*****************************************************************************
+ * Name: fts_check_app_bin_valid
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static bool fts_check_app_bin_valid(u8 *buf)
+{
+ int i;
+ u16 len;
+ u16 len_neg;
+ u16 ecc2_len = 0;
+ u8 cal_ecc = 0;
+ u8 cal_ecc2 = 0;
+
+ FTS_INFO("[UPGRADE] Check APP.BIN ECC");
+
+ /* 1. start code byte */
+ if (buf[0] != 0x02) {
+ FTS_DEBUG("[UPGRADE]APP.BIN Verify- the first byte(%x) error",
+ buf[0]);
+ return false;
+ }
+
+ /* 2. len */
+ len = ((u16)buf[APP_VERIF_ADDR + APP_LEN] << 8)
+ + buf[APP_VERIF_ADDR + APP_LEN + 1];
+ len_neg = (u16)(buf[APP_VERIF_ADDR + APP_LEN_NE] << 8)
+ + buf[APP_VERIF_ADDR + APP_LEN_NE + 1];
+ if ((len ^ len_neg) != 0xFFFF) {
+ FTS_DEBUG("[UPGRADE]APP.BIN Verify- LENGTH(%04x) XOR error",
+ len);
+ return false;
+ }
+
+ /* 3. ecc */
+ if (((buf[APP1_ECC_ADDR] ^ buf[APP1_ECC_ADDR+1]) != 0xFF)
+ || ((buf[APP2_ECC_ADDR] ^ buf[APP2_ECC_ADDR+1]) != 0xFF)) {
+ FTS_DEBUG("[UPGRADE]APP.BIN Verify- ECC(%x %x) XOR error",
+ buf[APP1_ECC_ADDR], buf[APP2_ECC_ADDR]);
+ return false;
+ }
+
+ /* APP1 */
+ for (i = 0; i < APP1_LEN; i++)
+ cal_ecc ^= buf[APP1_START+i];
+ /* APP2 */
+ ecc2_len = ((u16)buf[APP_VERIF_ADDR+0x10] << 8)
+ + buf[APP_VERIF_ADDR+0x11];
+ ecc2_len = len - APP1_LEN - APP_VERIF_LEN - ecc2_len;
+ for (i = 0; i < ecc2_len; i++)
+ cal_ecc2 ^= buf[APP2_START+i];
+
+ if ((cal_ecc != buf[APP1_ECC_ADDR])
+ || (cal_ecc2 != buf[APP2_ECC_ADDR])) {
+ FTS_DEBUG("[UPGRADE]APP.BIN Verify- ECC(%x %x) calc error",
+ cal_ecc, cal_ecc2);
+ return false;
+ }
+
+ return true;
+}
+
+
+/************************************************************************
+ * Name: fts_ft6x36gu_upgrade_use_buf
+ * Brief: fw upgrade
+ * Input: i2c info, file buf, file len
+ * Output: no
+ * Return: fail <0
+ ***********************************************************************/
+static int fts_ft6x36gu_upgrade_use_buf(struct i2c_client *client,
+ u8 *pbt_buf, u32 dw_length)
+{
+ u8 reg_val[2] = {0};
+ u32 i = 0;
+ u32 packet_number;
+ u32 j;
+ u32 temp;
+ u32 length;
+ u32 fw_length;
+ u8 packet_buf[FTS_PACKET_LENGTH + 6];
+ u8 auc_i2c_write_buf[10];
+ u8 upgrade_ecc;
+
+ FTS_FUNC_ENTER();
+
+ /*if the first byte of app is not 0x02,
+ *the app is invaild, can not upgrade
+ */
+ if (pbt_buf[0] != 0x02) {
+ FTS_ERROR("[UPGRADE]: app first byte != 0x02. cannot upgrade!");
+ return -EINVAL;
+ }
+
+ /*check app length*/
+ if (dw_length > 0x11f) {
+ fw_length = ((u32)pbt_buf[0x100]<<8) + pbt_buf[0x101];
+ if (dw_length < fw_length) {
+ FTS_ERROR("[UPGRADE]: Fw length error!!");
+ return -EINVAL;
+ }
+ } else {
+ FTS_ERROR("[UPGRADE]: Fw length error!!");
+ return -EINVAL;
+ }
+
+ /*send upgrade commond*/
+ for (i = 0; i < FTS_UPGRADE_LOOP; i++) {
+ /*send 0xAA and 0x55 to fw(0xFC reg), and start upgrade*/
+ fts_i2c_write_reg(client, FTS_RST_CMD_REG2, FTS_UPGRADE_AA);
+ usleep_range(10000, 20000);
+ fts_i2c_write_reg(client, FTS_RST_CMD_REG2, FTS_UPGRADE_55);
+ usleep_range(10000, 20000);
+
+ /*upgrade init in ROM*/
+ auc_i2c_write_buf[0] = FTS_UPGRADE_55;
+ fts_i2c_write(client, auc_i2c_write_buf, 1);
+ auc_i2c_write_buf[0] = FTS_UPGRADE_AA;
+ fts_i2c_write(client, auc_i2c_write_buf, 1);
+ usleep_range(10000, 20000);
+
+ /*check run in ROM now*/
+ auc_i2c_write_buf[0] = FTS_READ_ID_REG;
+ auc_i2c_write_buf[1] = auc_i2c_write_buf[2]
+ = auc_i2c_write_buf[3] = 0x00;
+ reg_val[0] = 0x00;
+ reg_val[1] = 0x00;
+ fts_i2c_read(client, auc_i2c_write_buf, 4, reg_val, 2);
+
+ if (reg_val[0] == chip_types.bootloader_idh
+ && reg_val[1] == chip_types.bootloader_idl)
+ break;
+ }
+
+ if (i >= FTS_UPGRADE_LOOP) {
+ FTS_ERROR("[UPGRADE]: get bootload id error !!");
+ return -EIO;
+ }
+
+ /*erase app in flash*/
+ FTS_INFO("[UPGRADE]: erase app!!");
+ auc_i2c_write_buf[0] = FTS_ERASE_APP_REG;
+ fts_i2c_write(client, auc_i2c_write_buf, 1);
+ msleep(2000);
+
+ for (i = 0; i < 200; i++) {
+ auc_i2c_write_buf[0] = 0x6a;
+ auc_i2c_write_buf[1] = 0x00;
+ auc_i2c_write_buf[2] = 0x00;
+ auc_i2c_write_buf[3] = 0x00;
+ reg_val[0] = 0x00;
+ reg_val[1] = 0x00;
+ fts_i2c_read(client, auc_i2c_write_buf, 4, reg_val, 2);
+ if (0xb0 == reg_val[0] && 0x02 == reg_val[1]) {
+ FTS_INFO("[UPGRADE]: erase app finished!!");
+ break;
+ }
+ msleep(50);
+ }
+
+ /*write app to flash*/
+ upgrade_ecc = 0;
+ FTS_INFO("[UPGRADE]: write app to flash!!");
+
+ dw_length = fw_length;
+ packet_number = (dw_length) / FTS_PACKET_LENGTH;
+ packet_buf[0] = FTS_FW_WRITE_CMD;
+ packet_buf[1] = 0x00;
+
+ for (j = 0; j < packet_number; j++) {
+ temp = j * FTS_PACKET_LENGTH;
+ packet_buf[2] = (u8) (temp >> 8);
+ packet_buf[3] = (u8) temp;
+ length = FTS_PACKET_LENGTH;
+ packet_buf[4] = (u8) (length >> 8);
+ packet_buf[5] = (u8) length;
+
+ for (i = 0; i < FTS_PACKET_LENGTH; i++) {
+ packet_buf[6 + i] = pbt_buf[j * FTS_PACKET_LENGTH + i];
+ upgrade_ecc ^= packet_buf[6 + i];
+ }
+
+ fts_i2c_write(client, packet_buf, FTS_PACKET_LENGTH + 6);
+
+ for (i = 0; i < 30; i++) {
+ auc_i2c_write_buf[0] = 0x6a;
+ auc_i2c_write_buf[1] = 0x00;
+ auc_i2c_write_buf[2] = 0x00;
+ auc_i2c_write_buf[3] = 0x00;
+ reg_val[0] = 0x00;
+ reg_val[1] = 0x00;
+ fts_i2c_read(client, auc_i2c_write_buf, 4, reg_val, 2);
+ if (0xb0 == (reg_val[0] & 0xf0) && (0x03 + (j % 0x0ffd))
+ == (((reg_val[0] & 0x0f) << 8) | reg_val[1]))
+ break;
+ /* usleep_range(1000, 2000); */
+ fts_ctpm_upgrade_delay(1000);
+ }
+ }
+
+ if ((dw_length) % FTS_PACKET_LENGTH > 0) {
+ temp = packet_number * FTS_PACKET_LENGTH;
+ packet_buf[2] = (u8) (temp >> 8);
+ packet_buf[3] = (u8) temp;
+ temp = (dw_length) % FTS_PACKET_LENGTH;
+ packet_buf[4] = (u8) (temp >> 8);
+ packet_buf[5] = (u8) temp;
+
+ for (i = 0; i < temp; i++) {
+ packet_buf[6 + i] = pbt_buf[packet_number
+ * FTS_PACKET_LENGTH + i];
+ upgrade_ecc ^= packet_buf[6 + i];
+ }
+
+ fts_i2c_write(client, packet_buf, temp + 6);
+
+ for (i = 0; i < 30; i++) {
+ auc_i2c_write_buf[0] = 0x6a;
+ auc_i2c_write_buf[1] = 0x00;
+ auc_i2c_write_buf[2] = 0x00;
+ auc_i2c_write_buf[3] = 0x00;
+ reg_val[0] = 0x00;
+ reg_val[1] = 0x00;
+ fts_i2c_read(client, auc_i2c_write_buf, 4, reg_val, 2);
+ if (0xb0 == (reg_val[0] & 0xf0) && (0x03 + (j % 0x0ffd))
+ == (((reg_val[0] & 0x0f) << 8) | reg_val[1]))
+ break;
+ /* usleep_range(1000, 2000); */
+ fts_ctpm_upgrade_delay(1000);
+ }
+ }
+
+ /*read out checksum*/
+ FTS_INFO("[UPGRADE]: read out checksum!!");
+ auc_i2c_write_buf[0] = FTS_REG_ECC;
+ fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 1);
+ /*check sum error, upgrade fail*/
+ if (reg_val[0] != upgrade_ecc) {
+ FTS_ERROR("[UPGRADE]: ecc error : FW=%02x upgrade_ecc=%02x!!",
+ reg_val[0], upgrade_ecc);
+ return -EIO;
+ }
+ FTS_INFO("[UPGRADE]: ecc ok!!");
+
+ /*upgrade success, reset the new FW*/
+ FTS_INFO("[UPGRADE]: reset the new FW!!");
+ auc_i2c_write_buf[0] = 0x07;
+ fts_i2c_write(client, auc_i2c_write_buf, 1);
+ msleep(300);
+
+ FTS_FUNC_EXIT();
+
+ return 0;
+}
+
+/************************************************************************
+ * Name: fts_ft6x36gu_upgrade_with_app_i_file
+ * Brief: upgrade with *.i file
+ * Input: i2c info
+ * Output:
+ * Return: fail < 0
+ ***********************************************************************/
+static int fts_ft6x36gu_upgrade_with_app_i_file(struct i2c_client *client)
+{
+ int i_ret = 0;
+ u32 fw_len;
+ u8 *fw_buf;
+
+ FTS_INFO("[UPGRADE]**********start upgrade with app.i**********");
+
+ fw_len = g_fw_len;
+ fw_buf = g_fw_file;
+ if (fw_len < APP_FILE_MIN_SIZE || fw_len > APP_FILE_MAX_SIZE) {
+ FTS_ERROR("[UPGRADE]: FW length(%x) error", fw_len);
+ return -EIO;
+ }
+
+ i_ret = fts_ft6x36gu_upgrade_use_buf(client, fw_buf, fw_len);
+ if (i_ret != 0)
+ FTS_ERROR("[UPGRADE] upgrade app.i failed");
+ else
+ FTS_INFO("[UPGRADE]: upgrade app.i succeed");
+
+ return i_ret;
+}
+
+/************************************************************************
+ * Name: fts_ft6x36gu_upgrade_with_app_bin_file
+ * Brief: upgrade with *.bin file
+ * Input: i2c info, file name
+ * Output: no
+ * Return: success =0
+ ***********************************************************************/
+static int fts_ft6x36gu_upgrade_with_app_bin_file(struct i2c_client *client,
+ char *firmware_name)
+{
+ const struct firmware *fw = NULL;
+ u8 *pbt_buf = NULL;
+ int i_ret = 0;
+ bool ecc_ok = false;
+ int fwsize = 0;
+
+ FTS_INFO("[UPGRADE]**********start upgrade with app.bin**********");
+
+ i_ret = request_firmware(&fw, firmware_name, &client->dev);
+ if (i_ret) {
+ FTS_ERROR("[UPGRADE]: failed to get fw %s\n", firmware_name);
+ return i_ret;
+ }
+
+ if (fw->size < APP_FILE_MIN_SIZE || fw->size > APP_FILE_MAX_SIZE) {
+ FTS_ERROR("[UPGRADE]: app.bin length(%x) error, upgrade fail",
+ fwsize);
+ goto ERROR_BIN;
+ }
+
+ /*check the app.bin invalid or not*/
+ pbt_buf = (u8 *)fw->data;
+ ecc_ok = fts_check_app_bin_valid(pbt_buf);
+
+ if (ecc_ok) {
+ FTS_INFO("[UPGRADE] app.bin ecc ok");
+ i_ret = fts_ft6x36gu_upgrade_use_buf(client, pbt_buf, fw->size);
+ if (i_ret != 0) {
+ FTS_ERROR("[UPGRADE]: upgrade app.bin failed");
+ goto ERROR_BIN;
+ } else {
+ FTS_INFO("[UPGRADE]: upgrade app.bin succeed");
+ }
+ } else {
+ FTS_ERROR("[UPGRADE] app.bin ecc failed");
+ goto ERROR_BIN;
+ }
+
+ERROR_BIN:
+ release_firmware(fw);
+ return i_ret;
+}
+#endif /* FT6x36GU */
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft8006.c b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft8006.c
new file mode 100644
index 0000000..246d2b9
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft8006.c
@@ -0,0 +1,895 @@
+/*
+ *
+ * FocalTech fts TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, Focaltech Ltd. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/*****************************************************************************
+ *
+ * File Name: focaltech_upgrade_ft8006.c
+ *
+ * Author: fupeipei
+ *
+ * Created: 2016-08-15
+ *
+ * Abstract:
+ *
+ * Reference:
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * 1.Included header files
+ *****************************************************************************/
+#include "../focaltech_core.h"
+
+#if (FTS_CHIP_TYPE == _FT8006)
+#include "../focaltech_flash.h"
+#include "focaltech_upgrade_common.h"
+
+/*****************************************************************************
+ * Static variables
+ *****************************************************************************/
+#define APP_FILE_MAX_SIZE (93 * 1024)
+#define APP_FILE_MIN_SIZE (8)
+#define APP_FILE_VER_MAPPING (0x10E)
+#define APP_FILE_VENDORID_MAPPING (0x10C)
+#define APP_FILE_CHIPID_MAPPING (0x11E)
+#define CONFIG_START_ADDR (0xF80)
+#define CONFIG_START_ADDR_LEN (0x80)
+#define CONFIG_VENDOR_ID_OFFSET (0x04)
+#define CONFIG_PROJECT_ID_OFFSET (0x20)
+#define CONFIG_VENDOR_ID_ADDR (CONFIG_START_ADDR+CONFIG_VENDOR_ID_OFFSET)
+#define CONFIG_PROJECT_ID_ADDR (CONFIG_START_ADDR+CONFIG_PROJECT_ID_OFFSET)
+#define LCD_CFG_MAX_SIZE (4 * 1024)
+#define LCD_CFG_MIN_SIZE (8)
+
+/*****************************************************************************
+ * Global variable or extern global variabls/functions
+ *****************************************************************************/
+static int fts_ctpm_get_i_file(struct i2c_client *client, int fw_valid);
+static int fts_ctpm_get_app_i_file_ver(void);
+static int fts_ctpm_get_app_bin_file_ver(char *firmware_name);
+static int fts_ctpm_fw_upgrade_with_app_i_file(struct i2c_client *client);
+static int fts_ctpm_fw_upgrade_with_app_bin_file(struct i2c_client *client,
+ char *firmware_name);
+static int fts_ctpm_fw_upgrade_with_lcd_cfg_i_file(struct i2c_client *client);
+static int fts_ctpm_fw_upgrade_with_lcd_cfg_bin_file(struct i2c_client *client,
+ char *firmware_name);
+
+struct fts_upgrade_fun fts_updatefun = {
+
+ .get_i_file = fts_ctpm_get_i_file,
+ .get_app_bin_file_ver = fts_ctpm_get_app_bin_file_ver,
+ .get_app_i_file_ver = fts_ctpm_get_app_i_file_ver,
+ .upgrade_with_app_i_file = fts_ctpm_fw_upgrade_with_app_i_file,
+ .upgrade_with_app_bin_file = fts_ctpm_fw_upgrade_with_app_bin_file,
+ .upgrade_with_lcd_cfg_i_file = fts_ctpm_fw_upgrade_with_lcd_cfg_i_file,
+ .upgrade_with_lcd_cfg_bin_file =
+ fts_ctpm_fw_upgrade_with_lcd_cfg_bin_file,
+};
+
+/*****************************************************************************
+ * Static function prototypes
+ *****************************************************************************/
+#if (FTS_GET_VENDOR_ID_NUM != 0)
+/************************************************************************
+ * Name: fts_ctpm_get_vendor_id_flash
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+static int fts_ctpm_get_vendor_id_flash(struct i2c_client *client,
+ u8 *vendor_id)
+{
+ bool inbootloader = false;
+ u8 rw_buf[10];
+ int i_ret;
+
+ fts_ctpm_i2c_hid2std(client);
+
+ i_ret = fts_ctpm_start_fw_upgrade(client);
+ if (i_ret < 0) {
+ FTS_ERROR("[UPGRADE]: send upgrade cmd to FW error!!");
+ return i_ret;
+ }
+
+ /*Enter upgrade mode*/
+ fts_ctpm_i2c_hid2std(client);
+ usleep_range(10000, 20000);
+
+ inbootloader = fts_ctpm_check_run_state(client, FTS_RUN_IN_BOOTLOADER);
+ if (!inbootloader) {
+ FTS_ERROR("[UPGRADE]: not run in bootloader, upgrade fail!!");
+ return -EIO;
+ }
+
+ /*read vendor id*/
+ rw_buf[0] = 0x03;
+ rw_buf[1] = 0x00;
+ rw_buf[2] = (u8)(CONFIG_VENDOR_ID_ADDR >> 8);
+ rw_buf[3] = (u8)(CONFIG_VENDOR_ID_ADDR);
+ i_ret = fts_i2c_write(client, rw_buf, 4);
+ /* must wait, otherwise read vendor id wrong */
+ usleep_range(10000, 20000);
+ i_ret = fts_i2c_read(client, NULL, 0, vendor_id, 1);
+ if (i_ret < 0)
+ return -EIO;
+ FTS_DEBUG("Vendor ID from Flash:%x", *vendor_id);
+ return 0;
+}
+#endif
+
+/************************************************************************
+ * Name: fts_ft5x46_get_i_file
+ * Brief: get .i file
+ * Input:
+ * Output:
+ * Return: 0 - ok
+ * <0 - fail
+ ***********************************************************************/
+static int fts_ctpm_get_i_file(struct i2c_client *client, int fw_valid)
+{
+ int ret = 0;
+
+#if (FTS_GET_VENDOR_ID_NUM != 0)
+ u8 vendor_id = 0;
+
+ if (fw_valid)
+ ret = fts_i2c_read_reg(client, FTS_REG_VENDOR_ID, &vendor_id);
+ else
+ ret = fts_ctpm_get_vendor_id_flash(client, &vendor_id);
+ if (ret < 0) {
+ FTS_ERROR("Get upgrade file fail because of Vendor ID wrong");
+ return ret;
+ }
+ FTS_INFO("[UPGRADE] vendor id tp=%x", vendor_id);
+ FTS_INFO("[UPGRADE] vendor id driver:%x, FTS_VENDOR_ID:%02x %02x %02x",
+ vendor_id, FTS_VENDOR_1_ID, FTS_VENDOR_2_ID, FTS_VENDOR_3_ID);
+
+ ret = 0;
+ switch (vendor_id) {
+#if (FTS_GET_VENDOR_ID_NUM >= 1)
+ case FTS_VENDOR_1_ID:
+ g_fw_file = CTPM_FW;
+ g_fw_len = fts_getsize(FW_SIZE);
+ FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW, SIZE:%x", g_fw_len);
+ break;
+#endif
+#if (FTS_GET_VENDOR_ID_NUM >= 2)
+ case FTS_VENDOR_2_ID:
+ g_fw_file = CTPM_FW2;
+ g_fw_len = fts_getsize(FW2_SIZE);
+ FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW2, SIZE:%x", g_fw_len);
+ break;
+#endif
+#if (FTS_GET_VENDOR_ID_NUM >= 3)
+ case FTS_VENDOR_3_ID:
+ g_fw_file = CTPM_FW3;
+ g_fw_len = fts_getsize(FW3_SIZE);
+ FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW3, SIZE:%x", g_fw_len);
+ break;
+#endif
+ default:
+ FTS_ERROR("[UPGRADE]Vendor ID check fail, get fw file fail");
+ ret = -EIO;
+ break;
+ }
+#else
+ /* (FTS_GET_VENDOR_ID_NUM == 0) */
+ g_fw_file = CTPM_FW;
+ g_fw_len = fts_getsize(FW_SIZE);
+ FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW, SIZE:%x", g_fw_len);
+#endif
+
+ return ret;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_get_app_bin_file_ver
+ * Brief: get .i file version
+ * Input: no
+ * Output: no
+ * Return: fw version
+ ***********************************************************************/
+static int fts_ctpm_get_app_bin_file_ver(char *firmware_name)
+{
+ u8 *pbt_buf = NULL;
+ int fwsize = 0;
+ int fw_ver = 0;
+
+ FTS_FUNC_ENTER();
+
+ fwsize = fts_GetFirmwareSize(firmware_name);
+ if (fwsize < APP_FILE_MIN_SIZE || fwsize > APP_FILE_MAX_SIZE) {
+ FTS_ERROR("[UPGRADE]: FW length(%x) error", fwsize);
+ return -EIO;
+ }
+
+ pbt_buf = kmalloc(fwsize + 1, GFP_KERNEL);
+ if (fts_ReadFirmware(firmware_name, pbt_buf)) {
+ FTS_ERROR("[UPGRADE]: request_firmware failed!!");
+ kfree(pbt_buf);
+ return -EIO;
+ }
+
+ fw_ver = pbt_buf[APP_FILE_VER_MAPPING];
+
+ kfree(pbt_buf);
+ FTS_FUNC_EXIT();
+
+ return fw_ver;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_get_app_i_file_ver
+ * Brief: get .i file version
+ * Input: no
+ * Output: no
+ * Return: fw version
+ ***********************************************************************/
+static int fts_ctpm_get_app_i_file_ver(void)
+{
+ int fwsize = g_fw_len;
+
+ if (fwsize < APP_FILE_MIN_SIZE || fwsize > APP_FILE_MAX_SIZE) {
+ FTS_ERROR("[UPGRADE]: FW length(%x) error", fwsize);
+ return 0;
+ }
+
+ return g_fw_file[APP_FILE_VER_MAPPING];
+}
+
+/************************************************************************
+ * Name: fts_ctpm_fw_upgrade_use_buf
+ * Brief: fw upgrade
+ * Input: i2c info, file buf, file len
+ * Output: no
+ * Return: fail <0
+ ***********************************************************************/
+static int fts_ctpm_fw_upgrade_use_buf(struct i2c_client *client,
+ u8 *pbt_buf, u32 dw_length)
+{
+ u8 reg_val[4] = {0};
+ u32 i = 0;
+ u32 packet_number;
+ u32 j = 0;
+ u32 temp;
+ u32 length;
+ u8 packet_buf[FTS_PACKET_LENGTH + 6];
+ u8 auc_i2c_write_buf[10];
+ u8 upgrade_ecc;
+ int i_ret = 0;
+ bool inbootloader = false;
+
+ fts_ctpm_i2c_hid2std(client);
+
+ i_ret = fts_ctpm_start_fw_upgrade(client);
+ if (i_ret < 0) {
+ FTS_ERROR("[UPGRADE]: send upgrade cmd to FW error!!");
+ return i_ret;
+ }
+
+ /*Enter upgrade mode*/
+ fts_ctpm_i2c_hid2std(client);
+ usleep_range(10000, 20000);
+
+ inbootloader = fts_ctpm_check_run_state(client, FTS_RUN_IN_BOOTLOADER);
+ if (!inbootloader) {
+ FTS_ERROR("[UPGRADE]: not run in bootloader, upgrade fail!!");
+ return -EIO;
+ }
+
+ /*send upgrade type to reg 0x09: 0x0B: upgrade; 0x0A: download*/
+ auc_i2c_write_buf[0] = 0x09;
+ auc_i2c_write_buf[1] = 0x0B;
+ fts_i2c_write(client, auc_i2c_write_buf, 2);
+
+ /*
+ * All.bin <= 128K
+ * APP.bin <= 94K
+ * LCD_CFG <= 4K
+ */
+ auc_i2c_write_buf[0] = 0xB0;
+ auc_i2c_write_buf[1] = (u8) ((dw_length >> 16) & 0xFF);
+ auc_i2c_write_buf[2] = (u8) ((dw_length >> 8) & 0xFF);
+ auc_i2c_write_buf[3] = (u8) (dw_length & 0xFF);
+ fts_i2c_write(client, auc_i2c_write_buf, 4);
+
+
+ /*erase the app erea in flash*/
+ i_ret = fts_ctpm_erase_flash(client);
+ if (i_ret < 0) {
+ FTS_ERROR("[UPGRADE]: erase flash error!!");
+ return i_ret;
+ }
+
+ /*write FW to ctpm flash*/
+ upgrade_ecc = 0;
+ FTS_DEBUG("[UPGRADE]: write FW to ctpm flash!!");
+ temp = 0;
+ packet_number = (dw_length) / FTS_PACKET_LENGTH;
+ packet_buf[0] = FTS_FW_WRITE_CMD;
+
+ for (j = 0; j < packet_number; j++) {
+ temp = 0x5000 + j * FTS_PACKET_LENGTH;
+ packet_buf[1] = (u8) (temp >> 16);
+ packet_buf[2] = (u8) (temp >> 8);
+ packet_buf[3] = (u8) temp;
+ length = FTS_PACKET_LENGTH;
+ packet_buf[4] = (u8) (length >> 8);
+ packet_buf[5] = (u8) length;
+ for (i = 0; i < FTS_PACKET_LENGTH; i++) {
+ packet_buf[6 + i] = pbt_buf[j * FTS_PACKET_LENGTH + i];
+ upgrade_ecc ^= packet_buf[6 + i];
+ }
+ fts_i2c_write(client, packet_buf, FTS_PACKET_LENGTH + 6);
+ /* usleep_range(1000, 2000); */
+
+ for (i = 0; i < 30; i++) {
+ auc_i2c_write_buf[0] = 0x6a;
+ reg_val[0] = reg_val[1] = 0x00;
+ fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2);
+
+ if ((j + 0x1000 + (0x5000/FTS_PACKET_LENGTH))
+ == (((reg_val[0]) << 8) | reg_val[1]))
+ break;
+
+ if (i > 15) {
+ usleep_range(1000, 2000);
+ FTS_DEBUG("[UPGRADE]: write flash:host :%x!!",
+ (j + 0x1000
+ + (0x5000/FTS_PACKET_LENGTH)));
+ FTS_DEBUG("[UPGRADE]: write flash:status :%x!!",
+ (((reg_val[0]) << 8) | reg_val[1]));
+ }
+ /* usleep_range(1000, 2000); */
+ fts_ctpm_upgrade_delay(10000);
+ }
+ }
+
+ if ((dw_length) % FTS_PACKET_LENGTH > 0) {
+ temp = 0x5000 + packet_number * FTS_PACKET_LENGTH;
+ packet_buf[1] = (u8) (temp >> 16);
+ packet_buf[2] = (u8) (temp >> 8);
+ packet_buf[3] = (u8) temp;
+ temp = (dw_length) % FTS_PACKET_LENGTH;
+ packet_buf[4] = (u8) (temp >> 8);
+ packet_buf[5] = (u8) temp;
+ for (i = 0; i < temp; i++) {
+ packet_buf[6 + i] = pbt_buf[packet_number
+ * FTS_PACKET_LENGTH + i];
+ upgrade_ecc ^= packet_buf[6 + i];
+ }
+ fts_i2c_write(client, packet_buf, temp + 6);
+ /* usleep_range(1000, 2000); */
+
+ for (i = 0; i < 30; i++) {
+ auc_i2c_write_buf[0] = 0x6a;
+ reg_val[0] = reg_val[1] = 0x00;
+ fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2);
+
+ if ((0x1000 + ((0x5000 + packet_number
+ * FTS_PACKET_LENGTH)/((dw_length)
+ % FTS_PACKET_LENGTH)))
+ == (((reg_val[0]) << 8) | reg_val[1]))
+ break;
+
+ if (i > 15) {
+ usleep_range(1000, 2000);
+ FTS_DEBUG("[UPGRADE]: write flash:host :%x!!",
+ (j + 0x1000
+ + (0x5000/FTS_PACKET_LENGTH)));
+ FTS_DEBUG("[UPGRADE]: write flash:status :%x!!",
+ (((reg_val[0]) << 8) | reg_val[1]));
+ }
+ /* usleep_range(1000, 2000); */
+ fts_ctpm_upgrade_delay(10000);
+ }
+ }
+
+ msleep(50);
+
+ /*********Step 6: read out checksum***********************/
+ /*send the opration head */
+ FTS_DEBUG("[UPGRADE]: read out checksum!!");
+ auc_i2c_write_buf[0] = 0x64;
+ fts_i2c_write(client, auc_i2c_write_buf, 1);
+ msleep(300);
+
+ temp = 0x5000;
+ auc_i2c_write_buf[0] = 0x65;
+ auc_i2c_write_buf[1] = (u8)(temp >> 16);
+ auc_i2c_write_buf[2] = (u8)(temp >> 8);
+ auc_i2c_write_buf[3] = (u8)(temp);
+ temp = (64*1024-1);
+ auc_i2c_write_buf[4] = (u8)(temp >> 8);
+ auc_i2c_write_buf[5] = (u8)(temp);
+ i_ret = fts_i2c_write(client, auc_i2c_write_buf, 6);
+ msleep(dw_length/256);
+
+ temp = (0x5000+(64*1024-1));
+ auc_i2c_write_buf[0] = 0x65;
+ auc_i2c_write_buf[1] = (u8)(temp >> 16);
+ auc_i2c_write_buf[2] = (u8)(temp >> 8);
+ auc_i2c_write_buf[3] = (u8)(temp);
+ temp = (dw_length-(64*1024-1));
+ auc_i2c_write_buf[4] = (u8)(temp >> 8);
+ auc_i2c_write_buf[5] = (u8)(temp);
+ i_ret = fts_i2c_write(client, auc_i2c_write_buf, 6);
+ msleep(dw_length/256);
+
+ for (i = 0; i < 100; i++) {
+ auc_i2c_write_buf[0] = 0x6a;
+ reg_val[0] = reg_val[1] = 0x00;
+ fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2);
+
+ if (0xF0 == reg_val[0] && 0x55 == reg_val[1]) {
+ FTS_DEBUG("[UPGRADE]: reg_val[0]=%02x reg_val[0]=%02x!",
+ reg_val[0], reg_val[1]);
+ break;
+ }
+ usleep_range(1000, 2000);
+
+ }
+ auc_i2c_write_buf[0] = 0x66;
+ fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 1);
+ if (reg_val[0] != upgrade_ecc) {
+ FTS_ERROR("[UPGRADE]: ecc error! FW=%02x upgrade_ecc=%02x!!",
+ reg_val[0], upgrade_ecc);
+ return -EIO;
+ }
+ FTS_DEBUG("[UPGRADE]: checksum %x %x!!", reg_val[0], upgrade_ecc);
+
+ FTS_DEBUG("[UPGRADE]: reset the new FW!!");
+ auc_i2c_write_buf[0] = FTS_REG_RESET_FW;
+ fts_i2c_write(client, auc_i2c_write_buf, 1);
+ msleep(1000);
+
+ fts_ctpm_i2c_hid2std(client);
+
+ return 0;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_fw_upgrade_use_buf
+ * Brief: fw upgrade
+ * Input: i2c info, file buf, file len
+ * Output: no
+ * Return: fail <0
+ ***********************************************************************/
+static int fts_ctpm_lcd_cfg_upgrade_use_buf(struct i2c_client *client,
+ u8 *pbt_buf, u32 dw_length)
+{
+ u8 reg_val[4] = {0};
+ u8 cfg_backup[CONFIG_START_ADDR_LEN+1] = { 0 };
+ u32 i = 0;
+ u32 packet_number;
+ u32 j = 0;
+ u32 temp;
+ u32 length;
+ u8 packet_buf[FTS_PACKET_LENGTH + 6];
+ u8 auc_i2c_write_buf[10];
+ u8 upgrade_ecc;
+ int i_ret;
+
+ fts_ctpm_i2c_hid2std(client);
+
+ for (i = 0; i < FTS_UPGRADE_LOOP; i++) {
+ /*write 0xaa to register FTS_RST_CMD_REG1 */
+ fts_i2c_write_reg(client, FTS_RST_CMD_REG1, FTS_UPGRADE_AA);
+ usleep_range(10000, 20000);
+
+ /*write 0x55 to register FTS_RST_CMD_REG1*/
+ fts_i2c_write_reg(client, FTS_RST_CMD_REG1, FTS_UPGRADE_55);
+ msleep(200);
+
+ /*Enter upgrade mode*/
+ fts_ctpm_i2c_hid2std(client);
+
+ usleep_range(10000, 20000);
+ auc_i2c_write_buf[0] = FTS_UPGRADE_55;
+ auc_i2c_write_buf[1] = FTS_UPGRADE_AA;
+ i_ret = fts_i2c_write(client, auc_i2c_write_buf, 2);
+ if (i_ret < 0) {
+ FTS_ERROR("[UPGRADE]: failed writing 0x55 and 0xaa!!");
+ continue;
+ }
+
+ /*check run in bootloader or not*/
+ usleep_range(1000, 2000);
+ auc_i2c_write_buf[0] = FTS_READ_ID_REG;
+ auc_i2c_write_buf[1] = auc_i2c_write_buf[2]
+ = auc_i2c_write_buf[3] = 0x00;
+ reg_val[0] = reg_val[1] = 0x00;
+ fts_i2c_read(client, auc_i2c_write_buf, 4, reg_val, 2);
+ FTS_DEBUG("[UPGRADE]:ID1 = 0x%x,ID2 = 0x%x!!",
+ reg_val[0], reg_val[1]);
+
+ if (reg_val[0] == chip_types.bootloader_idh
+ && reg_val[1] == chip_types.bootloader_idl) {
+ FTS_DEBUG("[UPGRADE]: read bootloader id ok!!");
+ break;
+ }
+ FTS_DEBUG("[UPGRADE]: read bootloader id fail!!");
+ }
+
+ if (i >= FTS_UPGRADE_LOOP)
+ return -EIO;
+
+ /* Backup FW configuratin area */
+ reg_val[0] = 0x03;
+ reg_val[1] = (u8)((CONFIG_START_ADDR-1) >> 16);
+ reg_val[2] = (u8)((CONFIG_START_ADDR-1) >> 8);
+ reg_val[3] = (u8)((CONFIG_START_ADDR-1));
+ i_ret = fts_i2c_read(client, reg_val, 4,
+ cfg_backup, CONFIG_START_ADDR_LEN+1);
+ if (i_ret < 0) {
+ FTS_ERROR("[UPGRADE] Read Config area error, don't upgrade");
+ return -EIO;
+ }
+
+ /*send upgrade type to reg 0x09: 0x0B: upgrade; 0x0A: download*/
+ auc_i2c_write_buf[0] = 0x09;
+ auc_i2c_write_buf[1] = 0x0C;
+ fts_i2c_write(client, auc_i2c_write_buf, 2);
+
+ /*Step 4:erase app and panel paramenter area*/
+ FTS_DEBUG("[UPGRADE]: erase app and panel paramenter area!!");
+ auc_i2c_write_buf[0] = FTS_ERASE_APP_REG;
+ fts_i2c_write(client, auc_i2c_write_buf, 1);
+ msleep(1000);
+
+ for (i = 0; i < 15; i++) {
+ auc_i2c_write_buf[0] = 0x6a;
+ reg_val[0] = reg_val[1] = 0x00;
+ fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2);
+ if (0xF0 == reg_val[0] && 0xAA == reg_val[1])
+ break;
+ msleep(50);
+ }
+ FTS_DEBUG("[UPGRADE]: erase app area reg_val = %x %x!!",
+ reg_val[0], reg_val[1]);
+
+ auc_i2c_write_buf[0] = 0xB0;
+ auc_i2c_write_buf[1] = 0;
+ auc_i2c_write_buf[2] = (u8) ((dw_length >> 8) & 0xFF);
+ auc_i2c_write_buf[3] = (u8) (dw_length & 0xFF);
+ fts_i2c_write(client, auc_i2c_write_buf, 4);
+
+ /*write FW to ctpm flash*/
+ upgrade_ecc = 0;
+ FTS_DEBUG("[UPGRADE]: write FW to ctpm flash!!");
+ temp = 0;
+ packet_number = (dw_length) / FTS_PACKET_LENGTH;
+ packet_buf[0] = FTS_FW_WRITE_CMD;
+ packet_buf[1] = 0;
+ for (j = 0; j < packet_number; j++) {
+ temp = j * FTS_PACKET_LENGTH;
+ packet_buf[2] = (u8) (temp >> 8);
+ packet_buf[3] = (u8) temp;
+ length = FTS_PACKET_LENGTH;
+ packet_buf[4] = (u8) (length >> 8);
+ packet_buf[5] = (u8) length;
+ for (i = 0; i < FTS_PACKET_LENGTH; i++) {
+ packet_buf[6 + i] = pbt_buf[j * FTS_PACKET_LENGTH + i];
+ upgrade_ecc ^= packet_buf[6 + i];
+ }
+ fts_i2c_write(client, packet_buf, FTS_PACKET_LENGTH + 6);
+ /* usleep_range(1000, 2000); */
+
+ for (i = 0; i < 30; i++) {
+ auc_i2c_write_buf[0] = 0x6a;
+ reg_val[0] = reg_val[1] = 0x00;
+ fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2);
+
+ if ((j + 0x1000) == (((reg_val[0]) << 8) | reg_val[1]))
+ break;
+
+ if (i > 15) {
+ usleep_range(1000, 2000);
+ FTS_DEBUG("[UPGRADE]: write flash:host : %x!",
+ (j + 0x1000 +
+ (0x5000/FTS_PACKET_LENGTH)),
+ (((reg_val[0]) << 8) | reg_val[1]));
+ FTS_DEBUG("[UPGRADE]: write flash:status : %x!",
+ (((reg_val[0]) << 8) | reg_val[1]));
+ }
+ /* usleep_range(1000, 2000); */
+ fts_ctpm_upgrade_delay(10000);
+ }
+ }
+
+ if ((dw_length) % FTS_PACKET_LENGTH > 0) {
+ temp = packet_number * FTS_PACKET_LENGTH;
+ packet_buf[2] = (u8) (temp >> 8);
+ packet_buf[3] = (u8) temp;
+ temp = (dw_length) % FTS_PACKET_LENGTH;
+ packet_buf[4] = (u8) (temp >> 8);
+ packet_buf[5] = (u8) temp;
+ for (i = 0; i < temp; i++) {
+ packet_buf[6 + i] = pbt_buf[packet_number
+ * FTS_PACKET_LENGTH + i];
+ upgrade_ecc ^= packet_buf[6 + i];
+ }
+ fts_i2c_write(client, packet_buf, temp + 6);
+ /* usleep_range(1000, 2000); */
+
+ for (i = 0; i < 30; i++) {
+ auc_i2c_write_buf[0] = 0x6a;
+ reg_val[0] = reg_val[1] = 0x00;
+ fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2);
+
+ if ((0x1000 + ((packet_number * FTS_PACKET_LENGTH)
+ /((dw_length) % FTS_PACKET_LENGTH)))
+ == (((reg_val[0]) << 8) | reg_val[1]))
+ break;
+
+ if (i > 15) {
+ usleep_range(1000, 2000);
+ FTS_DEBUG("[UPGRADE]: write flash:host : %x!",
+ (j + 0x1000 +
+ (0x5000/FTS_PACKET_LENGTH)),
+ (((reg_val[0]) << 8) | reg_val[1]));
+ FTS_DEBUG("[UPGRADE]: write flash:status : %x!",
+ (((reg_val[0]) << 8) | reg_val[1]));
+ }
+ /* usleep_range(1000, 2000); */
+ fts_ctpm_upgrade_delay(10000);
+ }
+ }
+
+ /* Write Back FW configuratin area */
+ packet_buf[0] = FTS_FW_WRITE_CMD;
+ packet_buf[1] = (u8)(CONFIG_START_ADDR >> 16);
+ packet_buf[2] = (u8)(CONFIG_START_ADDR >> 8);
+ packet_buf[3] = (u8)(CONFIG_START_ADDR);
+ packet_buf[4] = (u8)(CONFIG_START_ADDR_LEN >> 8);
+ packet_buf[5] = (u8)(CONFIG_START_ADDR_LEN);
+ memcpy(&packet_buf[6], &cfg_backup[1], CONFIG_START_ADDR_LEN);
+ i_ret = fts_i2c_write(client, packet_buf, CONFIG_START_ADDR_LEN + 6);
+ if (i_ret < 0)
+ FTS_ERROR("[UPGRADE] Write Configuration area error");
+
+ msleep(50);
+
+ /*********Step 6: read out checksum***********************/
+ /*send the opration head */
+ FTS_DEBUG("[UPGRADE]: read out checksum!!");
+ auc_i2c_write_buf[0] = 0x64;
+ fts_i2c_write(client, auc_i2c_write_buf, 1);
+ msleep(300);
+
+ temp = 0x00;
+ auc_i2c_write_buf[0] = 0x65;
+ auc_i2c_write_buf[1] = 0;
+ auc_i2c_write_buf[2] = (u8)(temp >> 8);
+ auc_i2c_write_buf[3] = (u8)(temp);
+ temp = dw_length;
+ auc_i2c_write_buf[4] = (u8)(temp >> 8);
+ auc_i2c_write_buf[5] = (u8)(temp);
+ i_ret = fts_i2c_write(client, auc_i2c_write_buf, 6);
+ msleep(dw_length/256);
+
+ for (i = 0; i < 100; i++) {
+ auc_i2c_write_buf[0] = 0x6a;
+ reg_val[0] = reg_val[1] = 0x00;
+ fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2);
+
+ if (0xF0 == reg_val[0] && 0x55 == reg_val[1]) {
+ FTS_DEBUG("[UPGRADE]:reg_val[0]=%02x reg_val[0]=%02x!",
+ reg_val[0], reg_val[1]);
+ break;
+ }
+ usleep_range(1000, 2000);
+
+ }
+ auc_i2c_write_buf[0] = 0x66;
+ fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 1);
+ if (reg_val[0] != upgrade_ecc) {
+ FTS_ERROR("[UPGRADE]: ecc error! FW=%02x upgrade_ecc=%02x!!",
+ reg_val[0], upgrade_ecc);
+ return -EIO;
+ }
+ FTS_DEBUG("[UPGRADE]: checksum %x %x!!", reg_val[0], upgrade_ecc);
+
+ FTS_DEBUG("[UPGRADE]: reset the new FW!!");
+ auc_i2c_write_buf[0] = FTS_REG_RESET_FW;
+ fts_i2c_write(client, auc_i2c_write_buf, 1);
+ msleep(1000);
+
+ fts_ctpm_i2c_hid2std(client);
+
+ return 0;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_fw_upgrade_with_app_i_file
+ * Brief: upgrade with *.i file
+ * Input: i2c info
+ * Output:
+ * Return: fail < 0
+ ***********************************************************************/
+static int fts_ctpm_fw_upgrade_with_app_i_file(struct i2c_client *client)
+{
+ int i_ret = 0;
+ u32 fw_len;
+ u8 *fw_buf;
+
+ FTS_INFO("[UPGRADE]**********start upgrade with app.i**********");
+
+ fw_len = g_fw_len;
+ fw_buf = g_fw_file;
+ if (fw_len < APP_FILE_MIN_SIZE || fw_len > APP_FILE_MAX_SIZE) {
+ FTS_ERROR("[UPGRADE]: FW length(%x) error", fw_len);
+ return -EIO;
+ }
+
+ i_ret = fts_ctpm_fw_upgrade_use_buf(client, fw_buf, fw_len);
+ if (i_ret != 0)
+ FTS_ERROR("[UPGRADE] upgrade app.i failed");
+ else
+ FTS_INFO("[UPGRADE]: upgrade app.i succeed");
+
+ return i_ret;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_fw_upgrade_with_app_bin_file
+ * Brief: upgrade with *.bin file
+ * Input: i2c info, file name
+ * Output: no
+ * Return: success =0
+ ***********************************************************************/
+static int fts_ctpm_fw_upgrade_with_app_bin_file(struct i2c_client *client,
+ char *firmware_name)
+{
+ u8 *pbt_buf = NULL;
+ int i_ret = 0;
+ bool ecc_ok = false;
+ int fwsize = 0;
+
+ FTS_INFO("[UPGRADE]**********start upgrade with app.bin**********");
+
+ fwsize = fts_GetFirmwareSize(firmware_name);
+ if (fwsize < APP_FILE_MIN_SIZE || fwsize > APP_FILE_MAX_SIZE) {
+ FTS_ERROR("[UPGRADE]: app.bin length(%x) error, upgrade fail",
+ fwsize);
+ return -EIO;
+ }
+
+ pbt_buf = kmalloc(fwsize + 1, GFP_KERNEL);
+ if (pbt_buf == NULL) {
+ FTS_ERROR(" malloc pbt_buf failed ");
+ goto ERROR_BIN;
+ }
+
+ if (fts_ReadFirmware(firmware_name, pbt_buf)) {
+ FTS_ERROR("[UPGRADE]: request_firmware failed!!");
+ goto ERROR_BIN;
+ }
+
+ /*check the app.bin invalid or not*/
+ ecc_ok = fts_check_app_bin_valid_idc(pbt_buf);
+
+ if (ecc_ok) {
+ FTS_INFO("[UPGRADE] app.bin ecc ok");
+ i_ret = fts_ctpm_fw_upgrade_use_buf(client, pbt_buf, fwsize);
+ if (i_ret != 0) {
+ FTS_ERROR("[UPGRADE]: upgrade app.bin failed");
+ goto ERROR_BIN;
+ } else {
+ FTS_INFO("[UPGRADE]: upgrade app.bin succeed");
+ }
+ } else {
+ FTS_ERROR("[UPGRADE] app.bin ecc failed");
+ goto ERROR_BIN;
+ }
+
+ kfree(pbt_buf);
+ return i_ret;
+ERROR_BIN:
+ kfree(pbt_buf);
+ return -EIO;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_fw_upgrade_with_lcd_cfg_i_file
+ * Brief: upgrade with *.i file
+ * Input: i2c info
+ * Output: no
+ * Return: fail <0
+ ***********************************************************************/
+static int fts_ctpm_fw_upgrade_with_lcd_cfg_i_file(struct i2c_client *client)
+{
+ int i_ret = 0;
+ int lcd_cfg_size = 0;
+
+ FTS_DEBUG("[UPGRADE]**********upgrade with lcd_cfg.i**********");
+
+ lcd_cfg_size = fts_getsize(LCD_CFG_SIZE);
+ if (lcd_cfg_size < LCD_CFG_MIN_SIZE
+ || lcd_cfg_size > LCD_CFG_MAX_SIZE) {
+ FTS_ERROR("[UPGRADE] lcd_cfg.i length(%x) error", lcd_cfg_size);
+ return -EIO;
+ }
+
+ /*FW upgrade*/
+ i_ret = fts_ctpm_lcd_cfg_upgrade_use_buf(client,
+ CTPM_LCD_CFG, lcd_cfg_size);
+ if (i_ret != 0)
+ FTS_ERROR("[UPGRADE] lcd_cfg.i upgrade fail, ret=%d", i_ret);
+ else
+ FTS_INFO("[UPGRADE] lcd_cfg.i upgrade succeed");
+
+ return i_ret;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_fw_upgrade_with_lcd_cfg_bin_file
+ * Brief: upgrade with *.bin file
+ * Input: i2c info, file name
+ * Output: no
+ * Return: success =0
+ ***********************************************************************/
+static int fts_ctpm_fw_upgrade_with_lcd_cfg_bin_file(struct i2c_client *client,
+ char *firmware_name)
+{
+ u8 *pbt_buf = NULL;
+ int i_ret = 0;
+ bool ecc_ok = false;
+ int lcd_cfg_size = fts_GetFirmwareSize(firmware_name);
+
+ FTS_DEBUG("[UPGRADE]**********upgrade with lcd_cfg.bin**********");
+
+ if (lcd_cfg_size < LCD_CFG_MIN_SIZE
+ || lcd_cfg_size > LCD_CFG_MAX_SIZE) {
+ FTS_ERROR("[UPGRADE] lcd_cfg.bin length(%x) error",
+ lcd_cfg_size);
+ return -EIO;
+ }
+
+ pbt_buf = kmalloc(lcd_cfg_size + 1, GFP_KERNEL);
+ if (fts_ReadFirmware(firmware_name, pbt_buf)) {
+ FTS_ERROR("[UPGRADE]: request_firmware failed!!");
+ goto ERROR_LCD_CFG_BIN;
+ }
+
+ /*check the app.bin invalid or not*/
+ ecc_ok = 1;
+
+ if (ecc_ok) {
+ FTS_INFO("[UPGRADE]: lcd_cfg.bin ecc ok!!");
+ i_ret = fts_ctpm_lcd_cfg_upgrade_use_buf(client,
+ pbt_buf, lcd_cfg_size);
+ if (i_ret != 0) {
+ FTS_ERROR("[UPGRADE]: lcd_cfg.bin upgrade failed!!");
+ goto ERROR_LCD_CFG_BIN;
+ } else {
+ FTS_INFO("[UPGRADE]: lcd_cfg.bin upgrade succeed!!");
+ }
+ } else {
+ FTS_ERROR("[UPGRADE]: lcd_cfg.bin ecc failed!!");
+
+ }
+
+ kfree(pbt_buf);
+ return i_ret;
+
+ERROR_LCD_CFG_BIN:
+ kfree(pbt_buf);
+ return -EIO;
+}
+#endif /* #if (FTS_CHIP_TYPE == _FT8006) */
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft8606.c b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft8606.c
new file mode 100644
index 0000000..3589ba5
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft8606.c
@@ -0,0 +1,587 @@
+/*
+ *
+ * FocalTech fts TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, Focaltech Ltd. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/*****************************************************************************
+ *
+ * File Name: focaltech_upgrade_ft8606.c
+ *
+ * Author: fupeipei
+ *
+ * Created: 2016-08-15
+ *
+ * Abstract:
+ *
+ * Reference:
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * 1.Included header files
+ *****************************************************************************/
+#include "../focaltech_core.h"
+
+#if (FTS_CHIP_TYPE == _FT8606)
+#include "../focaltech_flash.h"
+#include "focaltech_upgrade_common.h"
+
+/*****************************************************************************
+ * Static variables
+ *****************************************************************************/
+#define APP_FILE_MAX_SIZE (64 * 1024)
+#define APP_FILE_MIN_SIZE (8)
+#define APP_FILE_VER_MAPPING (0x10A)
+#define APP_FILE_VENDORID_MAPPING (0x108)
+#define APP_FILE_CHIPID_MAPPING (0x11E)
+#define CONFIG_START_ADDR (0x0780)
+#define CONFIG_VENDOR_ID_OFFSET (0x04)
+#define CONFIG_PROJECT_ID_OFFSET (0x20)
+#define CONFIG_VENDOR_ID_ADDR (CONFIG_START_ADDR+CONFIG_VENDOR_ID_OFFSET)
+#define CONFIG_PROJECT_ID_ADDR (CONFIG_START_ADDR+CONFIG_PROJECT_ID_OFFSET)
+#define AL2_FCS_COEF ((1 << 7) + (1 << 6) + (1 << 5))
+
+/*****************************************************************************
+ * Global variable or extern global variabls/functions
+ *****************************************************************************/
+static int fts_ctpm_get_i_file(struct i2c_client *client, int fw_valid);
+static int fts_ctpm_get_app_i_file_ver(void);
+static int fts_ctpm_get_app_bin_file_ver(struct i2c_client *client,
+ char *firmware_name);
+static int fts_ctpm_write_pram(struct i2c_client *client,
+ u8 *pbt_buf, u32 dw_length);
+static int fts_ctpm_fw_upgrade_with_app_i_file(struct i2c_client *client);
+static int fts_ctpm_fw_upgrade_with_app_bin_file(struct i2c_client *client,
+ char *firmware_name);
+
+struct fts_upgrade_fun fts_updatefun = {
+ .get_i_file = fts_ctpm_get_i_file,
+ .get_app_bin_file_ver = fts_ctpm_get_app_bin_file_ver,
+ .get_app_i_file_ver = fts_ctpm_get_app_i_file_ver,
+ .upgrade_with_app_i_file = fts_ctpm_fw_upgrade_with_app_i_file,
+ .upgrade_with_app_bin_file = fts_ctpm_fw_upgrade_with_app_bin_file,
+ .upgrade_with_lcd_cfg_i_file = NULL,
+ .upgrade_with_lcd_cfg_bin_file = NULL,
+};
+
+/*****************************************************************************
+ * Static function prototypes
+ *****************************************************************************/
+#if (FTS_GET_VENDOR_ID_NUM != 0)
+/************************************************************************
+ * Name: fts_ctpm_get_vendor_id_flash
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+static int fts_ctpm_get_vendor_id_flash(struct i2c_client *client,
+ u8 *vendor_id)
+{
+ u8 rw_buf[10];
+ int i_ret;
+ int fw_len;
+ bool inpram = false;
+
+ FTS_FUNC_ENTER();
+
+ /*write pramboot*/
+ fw_len = fts_getsize(PRAMBOOT_SIZE);
+ FTS_DEBUG("[UPGRADE]: pramboot size : %d!!", fw_len);
+ i_ret = fts_ctpm_write_pram(client, aucFW_PRAM_BOOT, fw_len);
+ if (i_ret != 0) {
+ FTS_ERROR("[UPGRADE]: write pram failed!!");
+ return -EIO;
+ }
+
+ /*check run in pramboot or not!
+ *if not rum in pramboot, cannot upgrade
+ */
+ inpram = fts_ctpm_check_run_state(client, FTS_RUN_IN_PRAM);
+ if (!inpram) {
+ FTS_ERROR("[UPGRADE]: not run in pram, upgrade fail!!");
+ return -EIO;
+ }
+
+ /*read vendor id*/
+ rw_buf[0] = 0x03;
+ rw_buf[1] = 0x00;
+ rw_buf[2] = (u8)(CONFIG_VENDOR_ID_ADDR >> 8);
+ rw_buf[3] = (u8)(CONFIG_VENDOR_ID_ADDR);
+ i_ret = fts_i2c_write(client, rw_buf, 4);
+ /* must wait, otherwise read vendor id wrong */
+ usleep_range(10000, 20000);
+ i_ret = fts_i2c_read(client, NULL, 0, vendor_id, 1);
+ if (i_ret < 0)
+ return -EIO;
+ FTS_DEBUG("Vendor ID from Flash:%x", *vendor_id);
+ return 0;
+}
+#endif
+
+/************************************************************************
+ * Name: fts_ctpm_get_i_file
+ * Brief: get .i file
+ * Input:
+ * Output:
+ * Return: 0 - ok
+ * <0 - fail
+ ***********************************************************************/
+static int fts_ctpm_get_i_file(struct i2c_client *client, int fw_valid)
+{
+ int ret = 0;
+
+#if (FTS_GET_VENDOR_ID_NUM != 0)
+ u8 vendor_id = 0;
+
+ if (fw_valid) {
+ ret = fts_i2c_read_reg(client, FTS_REG_VENDOR_ID, &vendor_id);
+ } else {
+ ret = fts_i2c_read_reg(client, FTS_REG_VENDOR_ID, &vendor_id);
+ if ((ret < 0) || (vendor_id == 0xEF) || (vendor_id == 0xED)) {
+ /* 8736 can't read vendor id from A8 command */
+ ret = fts_ctpm_get_vendor_id_flash(client, &vendor_id);
+ }
+ }
+ if (ret < 0) {
+ FTS_ERROR("Get upgrade file fail because of Vendor ID wrong");
+ return ret;
+ }
+ FTS_INFO("[UPGRADE] vendor id tp=%x", vendor_id);
+ FTS_INFO("[UPGRADE] vendor id driver:%x, FTS_VENDOR_ID:%02x %02x %02x",
+ vendor_id, FTS_VENDOR_1_ID, FTS_VENDOR_2_ID, FTS_VENDOR_3_ID);
+
+ ret = 0;
+ switch (vendor_id) {
+#if (FTS_GET_VENDOR_ID_NUM >= 1)
+ case FTS_VENDOR_1_ID:
+ g_fw_file = CTPM_FW;
+ g_fw_len = fts_getsize(FW_SIZE);
+ FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW, SIZE:%x", g_fw_len);
+ break;
+#endif
+#if (FTS_GET_VENDOR_ID_NUM >= 2)
+ case FTS_VENDOR_2_ID:
+ g_fw_file = CTPM_FW2;
+ g_fw_len = fts_getsize(FW2_SIZE);
+ FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW2, SIZE:%x", g_fw_len);
+ break;
+#endif
+#if (FTS_GET_VENDOR_ID_NUM >= 3)
+ case FTS_VENDOR_3_ID:
+ g_fw_file = CTPM_FW3;
+ g_fw_len = fts_getsize(FW3_SIZE);
+ FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW3, SIZE:%x", g_fw_len);
+ break;
+#endif
+ default:
+ FTS_ERROR("[UPGRADE]Vendor ID check fail, get fw file fail");
+ ret = -EIO;
+ break;
+ }
+#else
+ /* (FTS_GET_VENDOR_ID_NUM == 0) */
+ g_fw_file = CTPM_FW;
+ g_fw_len = fts_getsize(FW_SIZE);
+ FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW, SIZE:%x", g_fw_len);
+#endif
+
+ return ret;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_get_app_bin_file_ver
+ * Brief: get .i file version
+ * Input: no
+ * Output: no
+ * Return: fw version
+ ***********************************************************************/
+static int fts_ctpm_get_app_bin_file_ver(struct i2c_client *client,
+ char *firmware_name)
+{
+ const struct firmware *fw = NULL;
+ int fw_ver = 0;
+ int ret;
+
+ FTS_FUNC_ENTER();
+
+ ret = request_firmware(&fw, firmware_name, &client->dev);
+ if (ret) {
+ FTS_ERROR("[UPGRADE]: failed to get fw %s\n", firmware_name);
+ return ret;
+ }
+
+ if (fw->size < APP_FILE_MIN_SIZE || fw->size > APP_FILE_MAX_SIZE)
+ FTS_ERROR("[UPGRADE]: FW length(%x) error", fw->size);
+ else
+ fw_ver = fw->data[APP_FILE_VER_MAPPING];
+
+ release_firmware(fw);
+ FTS_FUNC_EXIT();
+
+ return fw_ver;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_get_app_i_file_ver
+ * Brief: get .i file version
+ * Input: no
+ * Output: no
+ * Return: fw version
+ ***********************************************************************/
+static int fts_ctpm_get_app_i_file_ver(void)
+{
+ int fwsize = g_fw_len;
+
+ if (fwsize < APP_FILE_MIN_SIZE || fwsize > APP_FILE_MAX_SIZE) {
+ FTS_ERROR("[UPGRADE]: FW length(%x) error", fwsize);
+ return 0;
+ }
+
+ return g_fw_file[APP_FILE_VER_MAPPING];
+}
+
+/************************************************************************
+ * Name: fts_ctpm_write_pram
+ * Brief: fw upgrade
+ * Input: i2c info, file buf, file len
+ * Output: no
+ * Return: fail <0
+ ***********************************************************************/
+static int fts_ctpm_write_pram(struct i2c_client *client,
+ u8 *pbt_buf, u32 dw_length)
+{
+ int i_ret;
+ bool inrom = false;
+
+ FTS_FUNC_ENTER();
+
+ /*check the length of the pramboot*/
+ if (dw_length > APP_FILE_MAX_SIZE || dw_length < APP_FILE_MIN_SIZE) {
+ FTS_ERROR("[UPGRADE] pramboot length(%d) fail", dw_length);
+ return -EIO;
+ }
+
+ /*send comond to FW, reset and start write pramboot*/
+ i_ret = fts_ctpm_start_fw_upgrade(client);
+ if (i_ret < 0) {
+ FTS_ERROR("[UPGRADE]: send upgrade cmd to FW error!!");
+ return i_ret;
+ }
+
+ /*check run in rom or not! if run in rom, will write pramboot*/
+ inrom = fts_ctpm_check_run_state(client, FTS_RUN_IN_ROM);
+ if (!inrom) {
+ FTS_ERROR("[UPGRADE]: not run in rom, write pramboot fail!!");
+ return -EIO;
+ }
+
+ /*write pramboot to pram*/
+ i_ret = fts_ctpm_write_pramboot_for_idc(client,
+ dw_length, aucFW_PRAM_BOOT);
+ if (i_ret < 0) {
+ FTS_ERROR("[UPGRADE]: write pramboot fail!!");
+ return i_ret;
+ }
+
+ /*read out checksum*/
+ i_ret = fts_ctpm_pramboot_ecc(client);
+ if (i_ret < 0) {
+ FTS_ERROR("[UPGRADE]: write pramboot ecc error!!");
+ return i_ret;
+ }
+
+ /*start pram*/
+ fts_ctpm_start_pramboot(client);
+
+ FTS_FUNC_EXIT();
+
+ return 0;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_write_app
+ * Brief: fw upgrade
+ * Input: i2c info, file buf, file len
+ * Output: no
+ * Return: fail <0
+ ***********************************************************************/
+static int fts_ctpm_write_app(struct i2c_client *client,
+ u8 *pbt_buf, u32 dw_length)
+{
+ u32 temp;
+ int i_ret;
+ bool inpram = false;
+
+ FTS_FUNC_ENTER();
+
+ /*check run in pramboot or not!
+ *if not rum in pramboot, can not upgrade
+ */
+ inpram = fts_ctpm_check_run_state(client, FTS_RUN_IN_PRAM);
+ if (!inpram) {
+ FTS_ERROR("[UPGRADE]: not run in pram, upgrade fail!!");
+ return -EIO;
+ }
+
+ /*upgrade init*/
+ i_ret = fts_ctpm_upgrade_idc_init(client);
+ if (i_ret < 0) {
+ FTS_ERROR("[UPGRADE]: upgrade init error, upgrade fail!!");
+ return i_ret;
+ }
+
+ /*erase the app erea in flash*/
+ i_ret = fts_ctpm_erase_flash(client);
+ if (i_ret < 0) {
+ FTS_ERROR("[UPGRADE]: erase flash error!!");
+ return i_ret;
+ }
+
+ /*start to write app*/
+ i_ret = fts_ctpm_write_app_for_idc(client, dw_length, pbt_buf);
+ if (i_ret < 0) {
+ FTS_ERROR("[UPGRADE]: write app error!!");
+ return i_ret;
+ }
+
+ /*read check sum*/
+ temp = 0x1000;
+ i_ret = fts_ctpm_upgrade_ecc(client, temp, dw_length);
+ if (i_ret < 0) {
+ FTS_ERROR("[UPGRADE]: ecc error!!");
+ return i_ret;
+ }
+
+ /*upgrade success, reset the FW*/
+ fts_ctpm_rom_or_pram_reset(client);
+
+ FTS_FUNC_EXIT();
+
+ return 0;
+}
+
+/*****************************************************************************
+ * Name: ecc_calc
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static u8 ecc_calc(u8 *pbt_buf, u16 start, u16 length)
+{
+ u8 cFcs = 0;
+ u16 i, j;
+
+ for (i = 0; i < length; i++) {
+ cFcs ^= pbt_buf[start++];
+ for (j = 0; j < 8; j++) {
+ if (cFcs & 1)
+ cFcs = (u8)((cFcs >> 1) ^ AL2_FCS_COEF);
+ else
+ cFcs >>= 1;
+ }
+ }
+ return cFcs;
+}
+
+
+/*****************************************************************************
+ * Name: fts_8606_check_app_bin_valid
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static bool fts_8606_check_app_bin_valid(u8 *pbt_buf)
+{
+ u8 ecc1;
+ u8 ecc2;
+ u8 ecc3;
+ u8 ecc4;
+ u16 len1;
+ u16 len2;
+ u8 cal_ecc1;
+ u8 cal_ecc2;
+ u16 usAddrInfo;
+
+ /* 1. First Byte */
+ if (pbt_buf[0] != 0x02) {
+ FTS_DEBUG("[UPGRADE]APP.BIN Verify- the first byte(%x) error",
+ pbt_buf[0]);
+ return false;
+ }
+
+ usAddrInfo = 0x100;
+
+ /* 2.len */
+ len1 = pbt_buf[usAddrInfo++] << 8;
+ len1 += pbt_buf[usAddrInfo++];
+
+ len2 = pbt_buf[usAddrInfo++] << 8;
+ len2 += pbt_buf[usAddrInfo++];
+
+ if ((len1 + len2) != 0xFFFF) {
+ FTS_DEBUG("[UPGRADE]APP.BIN Verify- LENGTH(%04x) XOR error",
+ len1);
+ return false;
+ }
+
+ /* 3.ecc */
+ ecc1 = pbt_buf[usAddrInfo++];
+ ecc2 = pbt_buf[usAddrInfo++];
+ ecc3 = pbt_buf[usAddrInfo++];
+ ecc4 = pbt_buf[usAddrInfo++];
+
+ if (((ecc1 + ecc2) != 0xFF) || ((ecc3 + ecc4) != 0xFF)) {
+ FTS_DEBUG("[UPGRADE]APP.BIN Verify- ECC(%x %x) XOR error",
+ ecc1, ecc2);
+ return false;
+ }
+
+ cal_ecc1 = ecc_calc(pbt_buf, 0x0, 0x100);
+ cal_ecc2 = ecc_calc(pbt_buf, 0x100 + 0x20, len1 - (0x100 + 0x20));
+ if ((ecc1 != cal_ecc1) || (ecc3 != cal_ecc2)) {
+ FTS_DEBUG("[UPGRADE]APP.BIN Verify- ECC calc error");
+ return false;
+ }
+ return true;
+}
+
+
+/************************************************************************
+ * Name: fts_ctpm_fw_upgrade_use_buf
+ * Brief: fw upgrade
+ * Input: i2c info, file buf, file len
+ * Output: no
+ * Return: fail <0
+ * success =0
+ ***********************************************************************/
+static int fts_ctpm_fw_upgrade_use_buf(struct i2c_client *client,
+ u8 *pbt_buf, u32 fwsize)
+{
+ int i_ret = 0;
+ int fw_len;
+
+ FTS_FUNC_ENTER();
+
+ /*write pramboot*/
+ fw_len = fts_getsize(PRAMBOOT_SIZE);
+ FTS_DEBUG("[UPGRADE]: pramboot size : %d!!", fw_len);
+ i_ret = fts_ctpm_write_pram(client, aucFW_PRAM_BOOT, fw_len);
+ if (i_ret != 0) {
+ FTS_ERROR("[UPGRADE]: write pram failed!!");
+ return -EIO;
+ }
+
+ /*write app*/
+ i_ret = fts_ctpm_write_app(client, pbt_buf, fwsize);
+
+ FTS_FUNC_EXIT();
+
+ return i_ret;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_fw_upgrade_with_app_i_file
+ * Brief: upgrade with *.i file
+ * Input: i2c info
+ * Output:
+ * Return: fail < 0
+ ***********************************************************************/
+static int fts_ctpm_fw_upgrade_with_app_i_file(struct i2c_client *client)
+{
+ int i_ret = 0;
+ u32 fw_len;
+ u8 *fw_buf;
+
+ FTS_INFO("[UPGRADE]**********start upgrade with app.i**********");
+
+ fw_len = g_fw_len;
+ fw_buf = g_fw_file;
+ if (fw_len < APP_FILE_MIN_SIZE || fw_len > APP_FILE_MAX_SIZE) {
+ FTS_ERROR("[UPGRADE]: FW length(%x) error", fw_len);
+ return -EIO;
+ }
+
+ i_ret = fts_ctpm_fw_upgrade_use_buf(client, fw_buf, fw_len);
+ if (i_ret != 0)
+ FTS_ERROR("[UPGRADE] upgrade app.i failed");
+ else
+ FTS_INFO("[UPGRADE]: upgrade app.i succeed");
+
+ return i_ret;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_fw_upgrade_with_app_bin_file
+ * Brief: upgrade with *.bin file
+ * Input: i2c info, file name
+ * Output: no
+ * Return: success =0
+ ***********************************************************************/
+static int fts_ctpm_fw_upgrade_with_app_bin_file(struct i2c_client *client,
+ char *firmware_name)
+{
+ const struct firmware *fw = NULL;
+ u8 *pbt_buf = NULL;
+ int i_ret = 0;
+ bool ecc_ok = false;
+ int fwsize = 0;
+
+ FTS_INFO("[UPGRADE]**********start upgrade with app.bin**********");
+
+ i_ret = request_firmware(&fw, firmware_name, &client->dev);
+ if (i_ret) {
+ FTS_ERROR("[UPGRADE]: failed to get fw %s\n", firmware_name);
+ return i_ret;
+ }
+
+ if (fw->size < APP_FILE_MIN_SIZE || fw->size > APP_FILE_MAX_SIZE) {
+ FTS_ERROR("[UPGRADE]: app.bin length(%x) error, upgrade fail",
+ fwsize);
+ goto ERROR_BIN;
+ }
+
+ pbt_buf = (u8 *)fw->data;
+ if ((pbt_buf[APP_FILE_CHIPID_MAPPING] != chip_types.pramboot_idh)
+ || (pbt_buf[APP_FILE_CHIPID_MAPPING+1]
+ != chip_types.pramboot_idl)) {
+ FTS_ERROR("[UPGRADE]: chip id error, app.bin upgrade failed!");
+ goto ERROR_BIN;
+ }
+
+ /*check the app.bin invalid or not*/
+ ecc_ok = fts_8606_check_app_bin_valid(pbt_buf);
+
+ if (ecc_ok) {
+ FTS_INFO("[UPGRADE] app.bin ecc ok");
+ i_ret = fts_ctpm_fw_upgrade_use_buf(client, pbt_buf, fw->size);
+ if (i_ret != 0) {
+ FTS_ERROR("[UPGRADE]: upgrade app.bin failed");
+ goto ERROR_BIN;
+ } else {
+ FTS_INFO("[UPGRADE]: upgrade app.bin succeed");
+ }
+ } else {
+ FTS_ERROR("[UPGRADE] app.bin ecc failed");
+ goto ERROR_BIN;
+ }
+
+ERROR_BIN:
+ release_firmware(fw);
+ return i_ret;
+}
+#endif /* #if (FTS_CHIP_TYPE == _FT8606) */
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft8607.c b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft8607.c
new file mode 100644
index 0000000..604edbd
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft8607.c
@@ -0,0 +1,499 @@
+/*
+ *
+ * FocalTech fts TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, Focaltech Ltd. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/*****************************************************************************
+ *
+ * File Name: focaltech_upgrade_ft8607.c
+ *
+ * Author: fupeipei
+ *
+ * Created: 2016-08-15
+ *
+ * Abstract:
+ *
+ * Reference:
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * 1.Included header files
+ *****************************************************************************/
+#include "../focaltech_core.h"
+
+#if (FTS_CHIP_TYPE == _FT8607)
+#include "../focaltech_flash.h"
+#include "focaltech_upgrade_common.h"
+
+/*****************************************************************************
+ * Static variables
+ *****************************************************************************/
+#define APP_FILE_MAX_SIZE (64 * 1024)
+#define APP_FILE_MIN_SIZE (8)
+#define APP_FILE_VER_MAPPING (0x10E)
+#define APP_FILE_VENDORID_MAPPING (0x10C)
+#define APP_FILE_CHIPID_MAPPING (0x11E)
+#define CONFIG_START_ADDR (0x0780)
+#define CONFIG_VENDOR_ID_OFFSET (0x04)
+#define CONFIG_PROJECT_ID_OFFSET (0x20)
+#define CONFIG_VENDOR_ID_ADDR (CONFIG_START_ADDR+CONFIG_VENDOR_ID_OFFSET)
+#define CONFIG_PROJECT_ID_ADDR (CONFIG_START_ADDR+CONFIG_PROJECT_ID_OFFSET)
+
+/*****************************************************************************
+ * Global variable or extern global variabls/functions
+ *****************************************************************************/
+static int fts_ctpm_get_i_file(struct i2c_client *client, int fw_valid);
+static int fts_ctpm_get_app_i_file_ver(void);
+static int fts_ctpm_get_app_bin_file_ver(struct i2c_client *client,
+ char *firmware_name);
+static int fts_ctpm_write_pram(struct i2c_client *client,
+ u8 *pbt_buf, u32 dw_length);
+static int fts_ctpm_fw_upgrade_with_app_i_file(struct i2c_client *client);
+static int fts_ctpm_fw_upgrade_with_app_bin_file(struct i2c_client *client,
+ char *firmware_name);
+
+struct fts_upgrade_fun fts_updatefun = {
+ .get_i_file = fts_ctpm_get_i_file,
+ .get_app_bin_file_ver = fts_ctpm_get_app_bin_file_ver,
+ .get_app_i_file_ver = fts_ctpm_get_app_i_file_ver,
+ .upgrade_with_app_i_file = fts_ctpm_fw_upgrade_with_app_i_file,
+ .upgrade_with_app_bin_file = fts_ctpm_fw_upgrade_with_app_bin_file,
+ .upgrade_with_lcd_cfg_i_file = NULL,
+ .upgrade_with_lcd_cfg_bin_file = NULL,
+};
+
+/*****************************************************************************
+ * Static function prototypes
+ *****************************************************************************/
+#if (FTS_GET_VENDOR_ID_NUM != 0)
+/************************************************************************
+ * Name: fts_ctpm_get_vendor_id_flash
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+static int fts_ctpm_get_vendor_id_flash(struct i2c_client *client,
+ u8 *vendor_id)
+{
+ u8 rw_buf[10];
+ int i_ret;
+ int fw_len;
+ bool inpram = false;
+
+ FTS_FUNC_ENTER();
+
+ /*write pramboot*/
+ fw_len = fts_getsize(PRAMBOOT_SIZE);
+ FTS_DEBUG("[UPGRADE]: pramboot size : %d!!", fw_len);
+ i_ret = fts_ctpm_write_pram(client, aucFW_PRAM_BOOT, fw_len);
+ if (i_ret != 0) {
+ FTS_ERROR("[UPGRADE]: write pram failed!!");
+ return -EIO;
+ }
+
+ /*check run in pramboot or not!
+ *if not rum in pramboot, can not upgrade
+ */
+ inpram = fts_ctpm_check_run_state(client, FTS_RUN_IN_PRAM);
+ if (!inpram) {
+ FTS_ERROR("[UPGRADE]: not run in pram, upgrade fail!!");
+ return -EIO;
+ }
+
+ /*read vendor id*/
+ rw_buf[0] = 0x03;
+ rw_buf[1] = 0x00;
+ rw_buf[2] = (u8)(CONFIG_VENDOR_ID_ADDR >> 8);
+ rw_buf[3] = (u8)(CONFIG_VENDOR_ID_ADDR);
+ i_ret = fts_i2c_write(client, rw_buf, 4);
+ /* must wait, otherwise read vendor id wrong */
+ usleep_range(10000, 20000);
+ i_ret = fts_i2c_read(client, NULL, 0, vendor_id, 1);
+ if (i_ret < 0)
+ return -EIO;
+ FTS_DEBUG("Vendor ID from Flash:%x", *vendor_id);
+ return 0;
+}
+#endif
+
+/************************************************************************
+ * Name: fts_ctpm_get_i_file
+ * Brief: get .i file
+ * Input:
+ * Output:
+ * Return: 0 - ok
+ * <0 - fail
+ ***********************************************************************/
+static int fts_ctpm_get_i_file(struct i2c_client *client, int fw_valid)
+{
+ int ret = 0;
+
+#if (FTS_GET_VENDOR_ID_NUM != 0)
+ u8 vendor_id = 0;
+
+ if (fw_valid) {
+ ret = fts_i2c_read_reg(client, FTS_REG_VENDOR_ID, &vendor_id);
+ } else {
+ ret = fts_i2c_read_reg(client, FTS_REG_VENDOR_ID, &vendor_id);
+ if ((ret < 0) || (vendor_id == 0xEF) || (vendor_id == 0xED)) {
+ /* 8736 can't read vendor id from A8 command */
+ ret = fts_ctpm_get_vendor_id_flash(client, &vendor_id);
+ }
+ }
+
+ if (ret < 0) {
+ FTS_ERROR("Get upgrade file fail because of Vendor ID wrong");
+ return ret;
+ }
+ FTS_INFO("[UPGRADE] vendor id tp=%x", vendor_id);
+ FTS_INFO("[UPGRADE] vendor id driver:%x, FTS_VENDOR_ID:%02x %02x %02x",
+ vendor_id, FTS_VENDOR_1_ID, FTS_VENDOR_2_ID, FTS_VENDOR_3_ID);
+
+ ret = 0;
+ switch (vendor_id) {
+#if (FTS_GET_VENDOR_ID_NUM >= 1)
+ case FTS_VENDOR_1_ID:
+ g_fw_file = CTPM_FW;
+ g_fw_len = fts_getsize(FW_SIZE);
+ FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW, SIZE:%x", g_fw_len);
+ break;
+#endif
+#if (FTS_GET_VENDOR_ID_NUM >= 2)
+ case FTS_VENDOR_2_ID:
+ g_fw_file = CTPM_FW2;
+ g_fw_len = fts_getsize(FW2_SIZE);
+ FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW2, SIZE:%x", g_fw_len);
+ break;
+#endif
+#if (FTS_GET_VENDOR_ID_NUM >= 3)
+ case FTS_VENDOR_3_ID:
+ g_fw_file = CTPM_FW3;
+ g_fw_len = fts_getsize(FW3_SIZE);
+ FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW3, SIZE:%x", g_fw_len);
+ break;
+#endif
+ default:
+ FTS_ERROR("[UPGRADE]Vendor ID check fail, get fw file fail");
+ ret = -EIO;
+ break;
+ }
+#else
+ /* (FTS_GET_VENDOR_ID_NUM == 0) */
+ g_fw_file = CTPM_FW;
+ g_fw_len = fts_getsize(FW_SIZE);
+ FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW, SIZE:%x", g_fw_len);
+#endif
+
+ return ret;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_get_app_bin_file_ver
+ * Brief: get .i file version
+ * Input: no
+ * Output: no
+ * Return: fw version
+ ***********************************************************************/
+static int fts_ctpm_get_app_bin_file_ver(struct i2c_client *client,
+ char *firmware_name)
+{
+ const struct firmware *fw = NULL;
+ int fw_ver = 0;
+ int ret;
+
+ FTS_FUNC_ENTER();
+
+ ret = request_firmware(&fw, firmware_name, &client->dev);
+ if (ret) {
+ FTS_ERROR("[UPGRADE]: failed to get fw %s\n", firmware_name);
+ return ret;
+ }
+
+ if (fw->size < APP_FILE_MIN_SIZE || fw->size > APP_FILE_MAX_SIZE)
+ FTS_ERROR("[UPGRADE]: FW length(%x) error", fw->size);
+ else
+ fw_ver = fw->data[APP_FILE_VER_MAPPING];
+
+ release_firmware(fw);
+ FTS_FUNC_EXIT();
+
+ return fw_ver;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_get_app_i_file_ver
+ * Brief: get .i file version
+ * Input: no
+ * Output: no
+ * Return: fw version
+ ***********************************************************************/
+static int fts_ctpm_get_app_i_file_ver(void)
+{
+ int fwsize = g_fw_len;
+
+ if (fwsize < APP_FILE_MIN_SIZE || fwsize > APP_FILE_MAX_SIZE) {
+ FTS_ERROR("[UPGRADE]: FW length(%x) error", fwsize);
+ return 0;
+ }
+
+ return g_fw_file[APP_FILE_VER_MAPPING];
+}
+
+/************************************************************************
+ * Name: fts_ctpm_write_pram
+ * Brief: fw upgrade
+ * Input: i2c info, file buf, file len
+ * Output: no
+ * Return: fail <0
+ ***********************************************************************/
+static int fts_ctpm_write_pram(struct i2c_client *client,
+ u8 *pbt_buf, u32 dw_length)
+{
+ int i_ret;
+ bool inrom = false;
+
+ FTS_FUNC_ENTER();
+
+ /*check the length of the pramboot*/
+ if (dw_length > APP_FILE_MAX_SIZE || dw_length < APP_FILE_MIN_SIZE) {
+ FTS_ERROR("[UPGRADE] pramboot length(%d) fail", dw_length);
+ return -EIO;
+ }
+
+ /*send comond to FW, reset and start write pramboot*/
+ i_ret = fts_ctpm_start_fw_upgrade(client);
+ if (i_ret < 0) {
+ FTS_ERROR("[UPGRADE]: send upgrade cmd to FW error!!");
+ return i_ret;
+ }
+
+ /*check run in rom or not! if run in rom, will write pramboot*/
+ inrom = fts_ctpm_check_run_state(client, FTS_RUN_IN_ROM);
+ if (!inrom) {
+ FTS_ERROR("[UPGRADE]: not run in rom, write pramboot fail!!");
+ return -EIO;
+ }
+
+ /*write pramboot to pram*/
+ i_ret = fts_ctpm_write_pramboot_for_idc(client,
+ dw_length, aucFW_PRAM_BOOT);
+ if (i_ret < 0) {
+ return i_ret;
+ FTS_ERROR("[UPGRADE]: write pramboot fail!!");
+ }
+
+ /*read out checksum*/
+ i_ret = fts_ctpm_pramboot_ecc(client);
+ if (i_ret < 0) {
+ return i_ret;
+ FTS_ERROR("[UPGRADE]: write pramboot ecc error!!");
+ }
+
+ /*start pram*/
+ fts_ctpm_start_pramboot(client);
+
+ FTS_FUNC_EXIT();
+
+ return 0;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_write_app
+ * Brief: fw upgrade
+ * Input: i2c info, file buf, file len
+ * Output: no
+ * Return: fail <0
+ ***********************************************************************/
+static int fts_ctpm_write_app(struct i2c_client *client,
+ u8 *pbt_buf, u32 dw_length)
+{
+ u32 temp;
+ int i_ret;
+ bool inpram = false;
+
+ FTS_FUNC_ENTER();
+
+ /*check run in pramboot or not!
+ *if not rum in pramboot, can not upgrade
+ */
+ inpram = fts_ctpm_check_run_state(client, FTS_RUN_IN_PRAM);
+ if (!inpram) {
+ FTS_ERROR("[UPGRADE]: not run in pram, upgrade fail!!");
+ return -EIO;
+ }
+
+ /*upgrade init*/
+ i_ret = fts_ctpm_upgrade_idc_init(client);
+ if (i_ret < 0) {
+ FTS_ERROR("[UPGRADE]: upgrade init error, upgrade fail!!");
+ return i_ret;
+ }
+
+ /*erase the app erea in flash*/
+ i_ret = fts_ctpm_erase_flash(client);
+ if (i_ret < 0) {
+ FTS_ERROR("[UPGRADE]: erase flash error!!");
+ return i_ret;
+ }
+
+ /*start to write app*/
+ i_ret = fts_ctpm_write_app_for_idc(client, dw_length, pbt_buf);
+ if (i_ret < 0) {
+ FTS_ERROR("[UPGRADE]: write app error!!");
+ return i_ret;
+ }
+
+ /*read check sum*/
+ temp = 0x1000;
+ i_ret = fts_ctpm_upgrade_ecc(client, temp, dw_length);
+ if (i_ret < 0) {
+ FTS_ERROR("[UPGRADE]: ecc error!!");
+ return i_ret;
+ }
+
+ /*upgrade success, reset the FW*/
+ fts_ctpm_rom_or_pram_reset(client);
+
+ FTS_FUNC_EXIT();
+
+ return 0;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_fw_upgrade_use_buf
+ * Brief: fw upgrade
+ * Input: i2c info, file buf, file len
+ * Output: no
+ * Return: fail <0
+ * success =0
+ ***********************************************************************/
+static int fts_ctpm_fw_upgrade_use_buf(struct i2c_client *client,
+ u8 *pbt_buf, u32 fwsize)
+{
+ int i_ret = 0;
+ int fw_len;
+
+ FTS_FUNC_ENTER();
+
+ /*write pramboot*/
+ fw_len = fts_getsize(PRAMBOOT_SIZE);
+ FTS_DEBUG("[UPGRADE]: pramboot size : %d!!", fw_len);
+ i_ret = fts_ctpm_write_pram(client, aucFW_PRAM_BOOT, fw_len);
+ if (i_ret != 0) {
+ FTS_ERROR("[UPGRADE]: write pram failed!!");
+ return -EIO;
+ }
+
+ /*write app*/
+ i_ret = fts_ctpm_write_app(client, pbt_buf, fwsize);
+
+ FTS_FUNC_EXIT();
+
+ return i_ret;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_fw_upgrade_with_app_i_file
+ * Brief: upgrade with *.i file
+ * Input: i2c info
+ * Output:
+ * Return: fail < 0
+ ***********************************************************************/
+static int fts_ctpm_fw_upgrade_with_app_i_file(struct i2c_client *client)
+{
+ int i_ret = 0;
+ u32 fw_len;
+ u8 *fw_buf;
+
+ FTS_INFO("[UPGRADE]**********start upgrade with app.i**********");
+
+ fw_len = g_fw_len;
+ fw_buf = g_fw_file;
+ if (fw_len < APP_FILE_MIN_SIZE || fw_len > APP_FILE_MAX_SIZE) {
+ FTS_ERROR("[UPGRADE]: FW length(%x) error", fw_len);
+ return -EIO;
+ }
+
+ i_ret = fts_ctpm_fw_upgrade_use_buf(client, fw_buf, fw_len);
+ if (i_ret != 0)
+ FTS_ERROR("[UPGRADE] upgrade app.i failed");
+ else
+ FTS_INFO("[UPGRADE]: upgrade app.i succeed");
+
+ return i_ret;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_fw_upgrade_with_app_bin_file
+ * Brief: upgrade with *.bin file
+ * Input: i2c info, file name
+ * Output: no
+ * Return: success =0
+ ***********************************************************************/
+static int fts_ctpm_fw_upgrade_with_app_bin_file(struct i2c_client *client,
+ char *firmware_name)
+{
+ const struct firmware *fw = NULL;
+ u8 *pbt_buf = NULL;
+ int i_ret = 0;
+ bool ecc_ok = false;
+ int fwsize = 0;
+
+ FTS_INFO("[UPGRADE]**********start upgrade with app.bin**********");
+
+ i_ret = request_firmware(&fw, firmware_name, &client->dev);
+ if (i_ret) {
+ FTS_ERROR("[UPGRADE]: failed to get fw %s\n", firmware_name);
+ return i_ret;
+ }
+
+ if (fw->size < APP_FILE_MIN_SIZE || fw->size > APP_FILE_MAX_SIZE) {
+ FTS_ERROR("[UPGRADE]: app.bin length(%x) error, upgrade fail",
+ fwsize);
+ goto ERROR_BIN;
+ }
+
+ pbt_buf = (u8 *)fw->data;
+ if ((pbt_buf[APP_FILE_CHIPID_MAPPING] != chip_types.pramboot_idh)
+ || (pbt_buf[APP_FILE_CHIPID_MAPPING+1]
+ != chip_types.pramboot_idl)) {
+ FTS_ERROR("[UPGRADE]: chip id error, app.bin upgrade failed!");
+ goto ERROR_BIN;
+ }
+
+ /*check the app.bin invalid or not*/
+ ecc_ok = fts_check_app_bin_valid_idc(pbt_buf);
+
+ if (ecc_ok) {
+ FTS_INFO("[UPGRADE] app.bin ecc ok");
+ i_ret = fts_ctpm_fw_upgrade_use_buf(client, pbt_buf, fw->size);
+ if (i_ret != 0) {
+ FTS_ERROR("[UPGRADE]: upgrade app.bin failed");
+ goto ERROR_BIN;
+ } else {
+ FTS_INFO("[UPGRADE]: upgrade app.bin succeed");
+ }
+ } else {
+ FTS_ERROR("[UPGRADE] app.bin ecc failed");
+ goto ERROR_BIN;
+ }
+
+ERROR_BIN:
+ release_firmware(fw);
+ return i_ret;
+}
+#endif /* #if (FTS_CHIP_TYPE == _FT8607) */
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft8716.c b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft8716.c
new file mode 100644
index 0000000..0df248b
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft8716.c
@@ -0,0 +1,487 @@
+/*
+ *
+ * FocalTech fts TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, Focaltech Ltd. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/*****************************************************************************
+ *
+ * File Name: focaltech_upgrade_ft8716.c
+ *
+ * Author: fupeipei
+ *
+ * Created: 2016-08-15
+ *
+ * Abstract:
+ *
+ * Reference:
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * 1.Included header files
+ *****************************************************************************/
+#include "../focaltech_core.h"
+
+#if ((FTS_CHIP_TYPE == _FT8716) || (FTS_CHIP_TYPE == _FTE716))
+#include "../focaltech_flash.h"
+#include "focaltech_upgrade_common.h"
+
+/*****************************************************************************
+ * Static variables
+ *****************************************************************************/
+#define APP_FILE_MAX_SIZE (64 * 1024)
+#define APP_FILE_MIN_SIZE (8)
+#define APP_FILE_VER_MAPPING (0x10E)
+#define APP_FILE_VENDORID_MAPPING (0x10C)
+#define APP_FILE_CHIPID_MAPPING (0x11E)
+#define CONFIG_START_ADDR (0x0000)
+#define CONFIG_VENDOR_ID_OFFSET (0x04)
+#define CONFIG_PROJECT_ID_OFFSET (0x20)
+#define CONFIG_VENDOR_ID_ADDR (CONFIG_START_ADDR+CONFIG_VENDOR_ID_OFFSET)
+#define CONFIG_PROJECT_ID_ADDR (CONFIG_START_ADDR+CONFIG_PROJECT_ID_OFFSET)
+
+/*****************************************************************************
+ * Global variable or extern global variabls/functions
+ *****************************************************************************/
+static int fts_ctpm_get_i_file(struct i2c_client *client, int fw_valid);
+static int fts_ctpm_get_app_i_file_ver(void);
+static int fts_ctpm_get_app_bin_file_ver(struct i2c_client *client,
+ char *firmware_name);
+static int fts_ctpm_write_pram(struct i2c_client *client,
+ u8 *pbt_buf, u32 dw_length);
+static int fts_ctpm_fw_upgrade_with_app_i_file(struct i2c_client *client);
+static int fts_ctpm_fw_upgrade_with_app_bin_file(struct i2c_client *client,
+ char *firmware_name);
+
+struct fts_upgrade_fun fts_updatefun = {
+ .get_i_file = fts_ctpm_get_i_file,
+ .get_app_bin_file_ver = fts_ctpm_get_app_bin_file_ver,
+ .get_app_i_file_ver = fts_ctpm_get_app_i_file_ver,
+ .upgrade_with_app_i_file = fts_ctpm_fw_upgrade_with_app_i_file,
+ .upgrade_with_app_bin_file = fts_ctpm_fw_upgrade_with_app_bin_file,
+ .upgrade_with_lcd_cfg_i_file = NULL,
+ .upgrade_with_lcd_cfg_bin_file = NULL,
+};
+
+/*****************************************************************************
+ * Static function prototypes
+ *****************************************************************************/
+#if (FTS_GET_VENDOR_ID_NUM != 0)
+/************************************************************************
+ * Name: fts_ctpm_get_vendor_id_flash
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+static int fts_ctpm_get_vendor_id_flash(struct i2c_client *client,
+ u8 *vendor_id)
+{
+ u8 rw_buf[10];
+ int i_ret;
+ int fw_len;
+ bool inpram = false;
+
+ FTS_FUNC_ENTER();
+
+ /*write pramboot*/
+ fw_len = fts_getsize(PRAMBOOT_SIZE);
+ FTS_DEBUG("[UPGRADE]: pramboot size : %d!!", fw_len);
+ i_ret = fts_ctpm_write_pram(client, aucFW_PRAM_BOOT, fw_len);
+ if (i_ret != 0) {
+ FTS_ERROR("[UPGRADE]: write pram failed!!");
+ return -EIO;
+ }
+
+ /*check run in pramboot or not!
+ *if not rum in pramboot, can not upgrade
+ */
+ inpram = fts_ctpm_check_run_state(client, FTS_RUN_IN_PRAM);
+ if (!inpram) {
+ FTS_ERROR("[UPGRADE]: not run in pram, upgrade fail!!");
+ return -EIO;
+ }
+
+ /*read vendor id*/
+ rw_buf[0] = 0x03;
+ rw_buf[1] = 0x00;
+ rw_buf[2] = (u8)(CONFIG_VENDOR_ID_ADDR >> 8);
+ rw_buf[3] = (u8)(CONFIG_VENDOR_ID_ADDR);
+ i_ret = fts_i2c_write(client, rw_buf, 4);
+ /* must wait, otherwise read vendor id wrong */
+ usleep_range(10000, 20000);
+ i_ret = fts_i2c_read(client, NULL, 0, vendor_id, 1);
+ if (i_ret < 0)
+ return -EIO;
+ FTS_DEBUG("Vendor ID from Flash:%x", *vendor_id);
+ return 0;
+}
+#endif
+
+/************************************************************************
+ * Name: fts_ctpm_get_i_file
+ * Brief: get .i file
+ * Input:
+ * Output:
+ * Return: 0 - ok
+ * <0 - fail
+ ***********************************************************************/
+static int fts_ctpm_get_i_file(struct i2c_client *client, int fw_valid)
+{
+ int ret = -EIO;
+
+#if (FTS_GET_VENDOR_ID_NUM != 0)
+ u8 vendor_id = 0;
+
+ if (fw_valid) {
+ ret = fts_i2c_read_reg(client, FTS_REG_VENDOR_ID, &vendor_id);
+ } else {
+ ret = fts_i2c_read_reg(client, FTS_REG_VENDOR_ID, &vendor_id);
+ if ((ret < 0) || (vendor_id == 0xEF) || (vendor_id == 0xED)) {
+ /* 8736 can't read vendor id from A8 command */
+ ret = fts_ctpm_get_vendor_id_flash(client, &vendor_id);
+ }
+ }
+
+ if (ret < 0) {
+ FTS_ERROR("Get upgrade file fail because of Vendor ID wrong");
+ return ret;
+ }
+ FTS_INFO("[UPGRADE] vendor id tp=%x", vendor_id);
+ FTS_INFO("[UPGRADE] vendor id driver:%x, FTS_VENDOR_ID:%02x %02x %02x",
+ vendor_id, FTS_VENDOR_1_ID, FTS_VENDOR_2_ID, FTS_VENDOR_3_ID);
+
+ ret = 0;
+ switch (vendor_id) {
+#if (FTS_GET_VENDOR_ID_NUM >= 1)
+ case FTS_VENDOR_1_ID:
+ g_fw_file = CTPM_FW;
+ g_fw_len = fts_getsize(FW_SIZE);
+ FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW, SIZE:%x", g_fw_len);
+ break;
+#endif
+#if (FTS_GET_VENDOR_ID_NUM >= 2)
+ case FTS_VENDOR_2_ID:
+ g_fw_file = CTPM_FW2;
+ g_fw_len = fts_getsize(FW2_SIZE);
+ FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW2, SIZE:%x", g_fw_len);
+ break;
+#endif
+#if (FTS_GET_VENDOR_ID_NUM >= 3)
+ case FTS_VENDOR_3_ID:
+ g_fw_file = CTPM_FW3;
+ g_fw_len = fts_getsize(FW3_SIZE);
+ FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW3, SIZE:%x", g_fw_len);
+ break;
+#endif
+ default:
+ FTS_ERROR("[UPGRADE]Vendor ID check fail, get fw file fail");
+ ret = -EIO;
+ break;
+ }
+#endif
+
+ return ret;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_get_app_bin_file_ver
+ * Brief: get .i file version
+ * Input: no
+ * Output: no
+ * Return: fw version
+ ***********************************************************************/
+static int fts_ctpm_get_app_bin_file_ver(struct i2c_client *client,
+ char *firmware_name)
+{
+ const struct firmware *fw = NULL;
+ int fw_ver = 0;
+ int ret;
+
+ FTS_FUNC_ENTER();
+
+ ret = request_firmware(&fw, firmware_name, &client->dev);
+ if (ret) {
+ FTS_ERROR("[UPGRADE]: failed to get fw %s\n", firmware_name);
+ return ret;
+ }
+
+ if (fw->size < APP_FILE_MIN_SIZE || fw->size > APP_FILE_MAX_SIZE)
+ FTS_ERROR("[UPGRADE]: FW length(%x) error", fw->size);
+ else
+ fw_ver = fw->data[APP_FILE_VER_MAPPING];
+
+ release_firmware(fw);
+ FTS_FUNC_EXIT();
+
+ return fw_ver;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_get_app_i_file_ver
+ * Brief: get .i file version
+ * Input: no
+ * Output: no
+ * Return: fw version
+ ***********************************************************************/
+static int fts_ctpm_get_app_i_file_ver(void)
+{
+ int fwsize = g_fw_len;
+
+ if (fwsize < APP_FILE_MIN_SIZE || fwsize > APP_FILE_MAX_SIZE) {
+ FTS_ERROR("[UPGRADE]: FW length(%x) error", fwsize);
+ return 0;
+ }
+
+ return g_fw_file[APP_FILE_VER_MAPPING];
+}
+
+/************************************************************************
+ * Name: fts_ctpm_write_pram
+ * Brief: fw upgrade
+ * Input: i2c info, file buf, file len
+ * Output: no
+ * Return: fail <0
+ ***********************************************************************/
+static int fts_ctpm_write_pram(struct i2c_client *client,
+ u8 *pbt_buf, u32 dw_length)
+{
+ int i_ret;
+ bool inrom = false;
+
+ FTS_FUNC_ENTER();
+
+ /*check the length of the pramboot*/
+ if (dw_length > APP_FILE_MAX_SIZE || dw_length < APP_FILE_MIN_SIZE) {
+ FTS_ERROR("[UPGRADE] pramboot length(%d) fail", dw_length);
+ return -EIO;
+ }
+
+ /*send comond to FW, reset and start write pramboot*/
+ i_ret = fts_ctpm_start_fw_upgrade(client);
+ if (i_ret < 0) {
+ FTS_ERROR("[UPGRADE]: send upgrade cmd to FW error!!");
+ return i_ret;
+ }
+
+ /*check run in rom or not! if run in rom, will write pramboot*/
+ inrom = fts_ctpm_check_run_state(client, FTS_RUN_IN_ROM);
+ if (!inrom) {
+ FTS_ERROR("[UPGRADE]: not run in rom, write pramboot fail!!");
+ return -EIO;
+ }
+
+ /*write pramboot to pram*/
+ i_ret = fts_ctpm_write_pramboot_for_idc(client,
+ dw_length, aucFW_PRAM_BOOT);
+ if (i_ret < 0) {
+ FTS_ERROR("[UPGRADE]: write pramboot fail!!");
+ return i_ret;
+ }
+
+ /*read out checksum*/
+ i_ret = fts_ctpm_pramboot_ecc(client);
+ if (i_ret < 0) {
+ FTS_ERROR("[UPGRADE]: write pramboot ecc error!!");
+ return i_ret;
+ }
+
+ /*start pram*/
+ fts_ctpm_start_pramboot(client);
+
+ FTS_FUNC_EXIT();
+
+ return 0;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_write_app
+ * Brief: fw upgrade
+ * Input: i2c info, file buf, file len
+ * Output: no
+ * Return: fail <0
+ ***********************************************************************/
+static int fts_ctpm_write_app(struct i2c_client *client,
+ u8 *pbt_buf, u32 dw_length)
+{
+ u32 temp;
+ int i_ret;
+ bool inpram = false;
+
+ FTS_FUNC_ENTER();
+
+ /*check run in pramboot or not!
+ *if not rum in pramboot, can not upgrade
+ */
+ inpram = fts_ctpm_check_run_state(client, FTS_RUN_IN_PRAM);
+ if (!inpram) {
+ FTS_ERROR("[UPGRADE]: not run in pram, upgrade fail!!");
+ return -EIO;
+ }
+
+ /*upgrade init*/
+ i_ret = fts_ctpm_upgrade_idc_init(client);
+ if (i_ret < 0) {
+ FTS_ERROR("[UPGRADE]: upgrade init error, upgrade fail!!");
+ return i_ret;
+ }
+
+ /*erase the app erea in flash*/
+ i_ret = fts_ctpm_erase_flash(client);
+ if (i_ret < 0) {
+ FTS_ERROR("[UPGRADE]: erase flash error!!");
+ return i_ret;
+ }
+
+ /*start to write app*/
+ i_ret = fts_ctpm_write_app_for_idc(client, dw_length, pbt_buf);
+ if (i_ret < 0) {
+ FTS_ERROR("[UPGRADE]: write app error!!");
+ return i_ret;
+ }
+
+ /*read check sum*/
+ temp = 0x1000;
+ i_ret = fts_ctpm_upgrade_ecc(client, temp, dw_length);
+ if (i_ret < 0) {
+ FTS_ERROR("[UPGRADE]: ecc error!!");
+ return i_ret;
+ }
+
+ /*upgrade success, reset the FW*/
+ fts_ctpm_rom_or_pram_reset(client);
+
+ FTS_FUNC_EXIT();
+
+ return 0;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_fw_upgrade_use_buf
+ * Brief: fw upgrade
+ * Input: i2c info, file buf, file len
+ * Output: no
+ * Return: fail <0
+ * success =0
+ ***********************************************************************/
+static int fts_ctpm_fw_upgrade_use_buf(struct i2c_client *client,
+ u8 *pbt_buf, u32 fwsize)
+{
+ int i_ret = 0;
+ int fw_len;
+
+ FTS_FUNC_ENTER();
+
+ /*write pramboot*/
+ fw_len = fts_getsize(PRAMBOOT_SIZE);
+ FTS_DEBUG("[UPGRADE]: pramboot size : %d!!", fw_len);
+ i_ret = fts_ctpm_write_pram(client, aucFW_PRAM_BOOT, fw_len);
+ if (i_ret != 0) {
+ FTS_ERROR("[UPGRADE]: write pram failed!!");
+ return -EIO;
+ }
+
+ /*write app*/
+ i_ret = fts_ctpm_write_app(client, pbt_buf, fwsize);
+
+ FTS_FUNC_EXIT();
+
+ return i_ret;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_fw_upgrade_with_app_i_file
+ * Brief: upgrade with *.i file
+ * Input: i2c info
+ * Output:
+ * Return: fail < 0
+ ***********************************************************************/
+static int fts_ctpm_fw_upgrade_with_app_i_file(struct i2c_client *client)
+{
+ int i_ret = 0;
+ u32 fw_len;
+ u8 *fw_buf;
+
+ FTS_INFO("[UPGRADE]**********start upgrade with app.i**********");
+
+ fw_len = g_fw_len;
+ fw_buf = g_fw_file;
+ if (fw_len < APP_FILE_MIN_SIZE || fw_len > APP_FILE_MAX_SIZE) {
+ FTS_ERROR("[UPGRADE]: FW length(%x) error", fw_len);
+ return -EIO;
+ }
+
+ i_ret = fts_ctpm_fw_upgrade_use_buf(client, fw_buf, fw_len);
+ if (i_ret != 0)
+ FTS_ERROR("[UPGRADE] upgrade app.i failed");
+ else
+ FTS_INFO("[UPGRADE]: upgrade app.i succeed");
+
+ return i_ret;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_fw_upgrade_with_app_bin_file
+ * Brief: upgrade with *.bin file
+ * Input: i2c info, file name
+ * Output: no
+ * Return: success =0
+ ***********************************************************************/
+static int fts_ctpm_fw_upgrade_with_app_bin_file(struct i2c_client *client,
+ char *firmware_name)
+{
+ const struct firmware *fw = NULL;
+ u8 *pbt_buf = NULL;
+ int i_ret = 0;
+ bool ecc_ok = false;
+ int fwsize = 0;
+
+ FTS_INFO("[UPGRADE]**********start upgrade with app.bin**********");
+
+ i_ret = request_firmware(&fw, firmware_name, &client->dev);
+ if (i_ret) {
+ FTS_ERROR("[UPGRADE]: failed to get fw %s\n", firmware_name);
+ return i_ret;
+ }
+
+ if (fw->size < APP_FILE_MIN_SIZE || fw->size > APP_FILE_MAX_SIZE) {
+ FTS_ERROR("[UPGRADE]: app.bin length(%x) error, upgrade fail",
+ fwsize);
+ goto ERROR_BIN;
+ }
+
+ /*check the app.bin invalid or not*/
+ pbt_buf = (u8 *)fw->data;
+ ecc_ok = fts_check_app_bin_valid_idc(pbt_buf);
+
+ if (ecc_ok) {
+ FTS_INFO("[UPGRADE] app.bin ecc ok");
+ i_ret = fts_ctpm_fw_upgrade_use_buf(client, pbt_buf, fw->size);
+ if (i_ret != 0) {
+ FTS_ERROR("[UPGRADE]: upgrade app.bin failed");
+ goto ERROR_BIN;
+ } else {
+ FTS_INFO("[UPGRADE]: upgrade app.bin succeed");
+ }
+ } else {
+ FTS_ERROR("[UPGRADE] app.bin ecc failed");
+ goto ERROR_BIN;
+ }
+
+ERROR_BIN:
+ release_firmware(fw);
+ return i_ret;
+}
+#endif /* #if (FTS_CHIP_TYPE == _FT8716) */
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft8736.c b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft8736.c
new file mode 100644
index 0000000..6f6544e
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft8736.c
@@ -0,0 +1,506 @@
+/*
+ *
+ * FocalTech fts TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, Focaltech Ltd. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/*****************************************************************************
+ *
+ * File Name: focaltech_upgrade_ft8736.c
+ *
+ * Author: fupeipei
+ *
+ * Created: 2016-10-25
+ *
+ * Abstract:
+ *
+ * Reference:
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * 1.Included header files
+ *****************************************************************************/
+#include "../focaltech_core.h"
+
+#if (FTS_CHIP_TYPE == _FT8736)
+#include "../focaltech_flash.h"
+#include "focaltech_upgrade_common.h"
+
+/*****************************************************************************
+ * Static variables
+ *****************************************************************************/
+#define APP_FILE_MAX_SIZE (64 * 1024)
+#define APP_FILE_MIN_SIZE (8)
+#define APP_FILE_VER_MAPPING (0x10E)
+#define APP_FILE_VENDORID_MAPPING (0x10C)
+#define APP_FILE_CHIPID_MAPPING (0x11E)
+#define CONFIG_START_ADDR (0x0F80)
+#define CONFIG_VENDOR_ID_OFFSET (0x4)
+#define CONFIG_PROJECT_ID_OFFSET (0x20)
+#define CONFIG_VENDOR_ID_ADDR (CONFIG_START_ADDR+CONFIG_VENDOR_ID_OFFSET)
+#define CONFIG_PROJECT_ID_ADDR (CONFIG_START_ADDR+CONFIG_PROJECT_ID_OFFSET)
+
+/*****************************************************************************
+ * Global variable or extern global variabls/functions
+ *****************************************************************************/
+static int fts_ctpm_get_i_file(struct i2c_client *client, int fw_valid);
+static int fts_ctpm_get_app_i_file_ver(void);
+static int fts_ctpm_get_app_bin_file_ver(struct i2c_client *client,
+ char *firmware_name);
+static int fts_ctpm_write_pram(struct i2c_client *client,
+ u8 *pbt_buf, u32 dw_length);
+static int fts_ctpm_fw_upgrade_with_app_i_file(struct i2c_client *client);
+static int fts_ctpm_fw_upgrade_with_app_bin_file(struct i2c_client *client,
+ char *firmware_name);
+
+struct fts_upgrade_fun fts_updatefun = {
+ .get_i_file = fts_ctpm_get_i_file,
+ .get_app_bin_file_ver = fts_ctpm_get_app_bin_file_ver,
+ .get_app_i_file_ver = fts_ctpm_get_app_i_file_ver,
+ .upgrade_with_app_i_file = fts_ctpm_fw_upgrade_with_app_i_file,
+ .upgrade_with_app_bin_file = fts_ctpm_fw_upgrade_with_app_bin_file,
+ .upgrade_with_lcd_cfg_i_file = NULL,
+ .upgrade_with_lcd_cfg_bin_file = NULL,
+};
+
+/*****************************************************************************
+ * Static function prototypes
+ *****************************************************************************/
+#if (FTS_GET_VENDOR_ID_NUM != 0)
+/************************************************************************
+ * Name: fts_ctpm_get_vendor_id_flash
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+static int fts_ctpm_get_vendor_id_flash(struct i2c_client *client,
+ u8 *vendor_id)
+{
+ u8 rw_buf[10];
+ int i_ret;
+ int fw_len;
+ bool inpram = false;
+
+ FTS_FUNC_ENTER();
+
+ /*write pramboot*/
+ fw_len = fts_getsize(PRAMBOOT_SIZE);
+ FTS_DEBUG("[UPGRADE]: pramboot size : %d!!", fw_len);
+ i_ret = fts_ctpm_write_pram(client, aucFW_PRAM_BOOT, fw_len);
+ if (i_ret != 0) {
+ FTS_ERROR("[UPGRADE]: write pram failed!!");
+ return -EIO;
+ }
+
+ /*check run in pramboot or not!
+ *if not rum in pramboot, can not upgrade
+ */
+ inpram = fts_ctpm_check_run_state(client, FTS_RUN_IN_PRAM);
+ if (!inpram) {
+ FTS_ERROR("[UPGRADE]: not run in pram, upgrade fail!!");
+ return -EIO;
+ }
+
+ /* initialization 0x05 0x80 */
+ i_ret = fts_ctpm_upgrade_idc_init(client);
+ if (i_ret < 0) {
+ FTS_ERROR("[UPGRADE]: upgrade init error, upgrade fail!!");
+ return i_ret;
+ }
+
+ /*read vendor id*/
+ rw_buf[0] = 0x03;
+ rw_buf[1] = 0x00;
+ rw_buf[2] = (u8)(CONFIG_VENDOR_ID_ADDR >> 8);
+ rw_buf[3] = (u8)(CONFIG_VENDOR_ID_ADDR);
+ i_ret = fts_i2c_write(client, rw_buf, 4);
+ /* must wait, otherwise read vendor id wrong */
+ usleep_range(10000, 20000);
+ i_ret = fts_i2c_read(client, NULL, 0, vendor_id, 1);
+ if (i_ret < 0)
+ return -EIO;
+ FTS_DEBUG("Vendor ID from Flash:%x", *vendor_id);
+ return 0;
+}
+#endif
+
+/************************************************************************
+ * Name: fts_ctpm_get_i_file
+ * Brief: get .i file
+ * Input:
+ * Output:
+ * Return: 0 - ok
+ * <0 - fail
+ ***********************************************************************/
+static int fts_ctpm_get_i_file(struct i2c_client *client, int fw_valid)
+{
+ int ret = 0;
+
+#if (FTS_GET_VENDOR_ID_NUM != 0)
+ u8 vendor_id = 0;
+
+ if (fw_valid) {
+ ret = fts_i2c_read_reg(client, FTS_REG_VENDOR_ID, &vendor_id);
+ } else {
+ ret = fts_i2c_read_reg(client, FTS_REG_VENDOR_ID, &vendor_id);
+ if ((ret < 0) || (vendor_id == 0xEF) || (vendor_id == 0xED)) {
+ /* 8736 can't read vendor id from A8 command */
+ ret = fts_ctpm_get_vendor_id_flash(client, &vendor_id);
+ }
+ }
+
+ if (ret < 0) {
+ FTS_ERROR("Get upgrade file fail because of Vendor ID wrong");
+ return ret;
+ }
+ FTS_INFO("[UPGRADE] vendor id tp=%x", vendor_id);
+ FTS_INFO("[UPGRADE] vendor id driver:%x, FTS_VENDOR_ID:%02x %02x %02x",
+ vendor_id, FTS_VENDOR_1_ID, FTS_VENDOR_2_ID, FTS_VENDOR_3_ID);
+
+ ret = 0;
+ switch (vendor_id) {
+#if (FTS_GET_VENDOR_ID_NUM >= 1)
+ case FTS_VENDOR_1_ID:
+ g_fw_file = CTPM_FW;
+ g_fw_len = fts_getsize(FW_SIZE);
+ FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW, SIZE:%x", g_fw_len);
+ break;
+#endif
+#if (FTS_GET_VENDOR_ID_NUM >= 2)
+ case FTS_VENDOR_2_ID:
+ g_fw_file = CTPM_FW2;
+ g_fw_len = fts_getsize(FW2_SIZE);
+ FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW2, SIZE:%x", g_fw_len);
+ break;
+#endif
+#if (FTS_GET_VENDOR_ID_NUM >= 3)
+ case FTS_VENDOR_3_ID:
+ g_fw_file = CTPM_FW3;
+ g_fw_len = fts_getsize(FW3_SIZE);
+ FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW3, SIZE:%x", g_fw_len);
+ break;
+#endif
+ default:
+ FTS_ERROR("[UPGRADE]Vendor ID check fail, get fw file fail");
+ ret = -EIO;
+ break;
+ }
+#else
+ /* (FTS_GET_VENDOR_ID_NUM == 0) */
+ g_fw_file = CTPM_FW;
+ g_fw_len = fts_getsize(FW_SIZE);
+ FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW, SIZE:%x", g_fw_len);
+#endif
+
+ return ret;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_get_app_bin_file_ver
+ * Brief: get .i file version
+ * Input: no
+ * Output: no
+ * Return: fw version
+ ***********************************************************************/
+static int fts_ctpm_get_app_bin_file_ver(struct i2c_client *client,
+ char *firmware_name)
+{
+ const struct firmware *fw = NULL;
+ int fw_ver = 0;
+ int ret;
+
+ FTS_FUNC_ENTER();
+
+ ret = request_firmware(&fw, firmware_name, &client->dev);
+ if (ret) {
+ FTS_ERROR("[UPGRADE]: failed to get fw %s\n", firmware_name);
+ return ret;
+ }
+
+ if (fw->size < APP_FILE_MIN_SIZE || fw->size > APP_FILE_MAX_SIZE)
+ FTS_ERROR("[UPGRADE]: FW length(%x) error", fw->size);
+ else
+ fw_ver = fw->data[APP_FILE_VER_MAPPING];
+
+ release_firmware(fw);
+ FTS_FUNC_EXIT();
+
+ return fw_ver;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_get_app_i_file_ver
+ * Brief: get .i file version
+ * Input: no
+ * Output: no
+ * Return: fw version
+ ***********************************************************************/
+static int fts_ctpm_get_app_i_file_ver(void)
+{
+ int fwsize = g_fw_len;
+
+ if (fwsize < APP_FILE_MIN_SIZE || fwsize > APP_FILE_MAX_SIZE) {
+ FTS_ERROR("[UPGRADE]: FW length(%x) error", fwsize);
+ return 0;
+ }
+
+ return g_fw_file[APP_FILE_VER_MAPPING];
+}
+
+/************************************************************************
+ * Name: fts_ctpm_write_pram
+ * Brief: fw upgrade
+ * Input: i2c info, file buf, file len
+ * Output: no
+ * Return: fail <0
+ ***********************************************************************/
+static int fts_ctpm_write_pram(struct i2c_client *client,
+ u8 *pbt_buf, u32 dw_length)
+{
+ int i_ret;
+ bool inrom = false;
+
+ FTS_FUNC_ENTER();
+
+ /*check the length of the pramboot*/
+ if (dw_length > APP_FILE_MAX_SIZE || dw_length < APP_FILE_MIN_SIZE) {
+ FTS_ERROR("[UPGRADE] pramboot length(%d) fail", dw_length);
+ return -EIO;
+ }
+
+ /*send comond to FW, reset and start write pramboot*/
+ i_ret = fts_ctpm_start_fw_upgrade(client);
+ if (i_ret < 0) {
+ FTS_ERROR("[UPGRADE]: send upgrade cmd to FW error!!");
+ return i_ret;
+ }
+
+ /*check run in rom or not! if run in rom, will write pramboot*/
+ inrom = fts_ctpm_check_run_state(client, FTS_RUN_IN_ROM);
+ if (!inrom) {
+ FTS_ERROR("[UPGRADE]: not run in rom, write pramboot fail!!");
+ return -EIO;
+ }
+
+ /*write pramboot to pram*/
+ i_ret = fts_ctpm_write_pramboot_for_idc(client,
+ dw_length, aucFW_PRAM_BOOT);
+ if (i_ret < 0) {
+ return i_ret;
+ FTS_ERROR("[UPGRADE]: write pramboot fail!!");
+ }
+
+ /*read out checksum*/
+ i_ret = fts_ctpm_pramboot_ecc(client);
+ if (i_ret < 0) {
+ return i_ret;
+ FTS_ERROR("[UPGRADE]: write pramboot ecc error!!");
+ }
+
+ /*start pram*/
+ fts_ctpm_start_pramboot(client);
+
+ FTS_FUNC_EXIT();
+
+ return 0;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_write_app
+ * Brief: fw upgrade
+ * Input: i2c info, file buf, file len
+ * Output: no
+ * Return: fail <0
+ ***********************************************************************/
+static int fts_ctpm_write_app(struct i2c_client *client,
+ u8 *pbt_buf, u32 dw_length)
+{
+ u32 temp;
+ int i_ret;
+ bool inpram = false;
+
+ FTS_FUNC_ENTER();
+
+ /*check run in pramboot or not!
+ *if not rum in pramboot, can not upgrade
+ */
+ inpram = fts_ctpm_check_run_state(client, FTS_RUN_IN_PRAM);
+ if (!inpram) {
+ FTS_ERROR("[UPGRADE]: not run in pram, upgrade fail!!");
+ return -EIO;
+ }
+
+ /*upgrade init*/
+ i_ret = fts_ctpm_upgrade_idc_init(client);
+ if (i_ret < 0) {
+ FTS_ERROR("[UPGRADE]: upgrade init error, upgrade fail!!");
+ return i_ret;
+ }
+
+ /*erase the app erea in flash*/
+ i_ret = fts_ctpm_erase_flash(client);
+ if (i_ret < 0) {
+ FTS_ERROR("[UPGRADE]: erase flash error!!");
+ return i_ret;
+ }
+
+ /*start to write app*/
+ i_ret = fts_ctpm_write_app_for_idc(client, dw_length, pbt_buf);
+ if (i_ret < 0) {
+ FTS_ERROR("[UPGRADE]: write app error!!");
+ return i_ret;
+ }
+
+ /*read check sum*/
+ temp = 0x1000;
+ i_ret = fts_ctpm_upgrade_ecc(client, temp, dw_length);
+ if (i_ret < 0) {
+ FTS_ERROR("[UPGRADE]: ecc error!!");
+ return i_ret;
+ }
+
+ /*upgrade success, reset the FW*/
+ fts_ctpm_rom_or_pram_reset(client);
+
+ FTS_FUNC_EXIT();
+
+ return 0;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_fw_upgrade_use_buf
+ * Brief: fw upgrade
+ * Input: i2c info, file buf, file len
+ * Output: no
+ * Return: fail <0
+ * success =0
+ ***********************************************************************/
+static int fts_ctpm_fw_upgrade_use_buf(struct i2c_client *client,
+ u8 *pbt_buf, u32 fwsize)
+{
+ int i_ret = 0;
+ int fw_len;
+
+ FTS_FUNC_ENTER();
+
+ /*write pramboot*/
+ fw_len = fts_getsize(PRAMBOOT_SIZE);
+ FTS_DEBUG("[UPGRADE]: pramboot size : %d!!", fw_len);
+ i_ret = fts_ctpm_write_pram(client, aucFW_PRAM_BOOT, fw_len);
+ if (i_ret != 0) {
+ FTS_ERROR("[UPGRADE]: write pram failed!!");
+ return -EIO;
+ }
+
+ /*write app*/
+ i_ret = fts_ctpm_write_app(client, pbt_buf, fwsize);
+
+ FTS_FUNC_EXIT();
+
+ return i_ret;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_fw_upgrade_with_app_i_file
+ * Brief: upgrade with *.i file
+ * Input: i2c info
+ * Output:
+ * Return: fail < 0
+ ***********************************************************************/
+static int fts_ctpm_fw_upgrade_with_app_i_file(struct i2c_client *client)
+{
+ int i_ret = 0;
+ u32 fw_len;
+ u8 *fw_buf;
+
+ FTS_INFO("[UPGRADE]**********start upgrade with app.i**********");
+
+ fw_len = g_fw_len;
+ fw_buf = g_fw_file;
+ if (fw_len < APP_FILE_MIN_SIZE || fw_len > APP_FILE_MAX_SIZE) {
+ FTS_ERROR("[UPGRADE]: FW length(%x) error", fw_len);
+ return -EIO;
+ }
+
+ i_ret = fts_ctpm_fw_upgrade_use_buf(client, fw_buf, fw_len);
+ if (i_ret != 0)
+ FTS_ERROR("[UPGRADE] upgrade app.i failed");
+ else
+ FTS_INFO("[UPGRADE]: upgrade app.i succeed");
+
+ return i_ret;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_fw_upgrade_with_app_bin_file
+ * Brief: upgrade with *.bin file
+ * Input: i2c info, file name
+ * Output: no
+ * Return: success =0
+ ***********************************************************************/
+static int fts_ctpm_fw_upgrade_with_app_bin_file(struct i2c_client *client,
+ char *firmware_name)
+{
+ const struct firmware *fw = NULL;
+ u8 *pbt_buf = NULL;
+ int i_ret = 0;
+ bool ecc_ok = false;
+ int fwsize = 0;
+
+ FTS_INFO("[UPGRADE]**********start upgrade with app.bin**********");
+
+ i_ret = request_firmware(&fw, firmware_name, &client->dev);
+ if (i_ret) {
+ FTS_ERROR("[UPGRADE]: failed to get fw %s\n", firmware_name);
+ return i_ret;
+ }
+
+ if (fw->size < APP_FILE_MIN_SIZE || fw->size > APP_FILE_MAX_SIZE) {
+ FTS_ERROR("[UPGRADE]: app.bin length(%x) error, upgrade fail",
+ fwsize);
+ goto ERROR_BIN;
+ }
+
+ pbt_buf = (u8 *)fw->data;
+ if ((pbt_buf[APP_FILE_CHIPID_MAPPING] != chip_types.pramboot_idh)
+ || (pbt_buf[APP_FILE_CHIPID_MAPPING+1]
+ != chip_types.pramboot_idl)) {
+ FTS_ERROR("[UPGRADE]: chip id error, app.bin upgrade failed!");
+ goto ERROR_BIN;
+ }
+
+ /*check the app.bin invalid or not*/
+ ecc_ok = fts_check_app_bin_valid_idc(pbt_buf);
+
+ if (ecc_ok) {
+ FTS_INFO("[UPGRADE] app.bin ecc ok");
+ i_ret = fts_ctpm_fw_upgrade_use_buf(client, pbt_buf, fw->size);
+ if (i_ret != 0) {
+ FTS_ERROR("[UPGRADE]: upgrade app.bin failed");
+ goto ERROR_BIN;
+ } else {
+ FTS_INFO("[UPGRADE]: upgrade app.bin succeed");
+ }
+ } else {
+ FTS_ERROR("[UPGRADE] app.bin ecc failed");
+ goto ERROR_BIN;
+ }
+
+ERROR_BIN:
+ release_firmware(fw);
+ return i_ret;
+}
+#endif /* #if (FTS_CHIP_TYPE == _FT8736) */
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_idc.c b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_idc.c
new file mode 100644
index 0000000..c91d7c80
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_idc.c
@@ -0,0 +1,592 @@
+/*
+ *
+ * FocalTech fts TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, Focaltech Ltd. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/*****************************************************************************
+ *
+ * File Name: focaltech_upgrade_idc.c
+ *
+ * Author: fupeipei
+ *
+ * Created: 2016-08-22
+ *
+ * Abstract:
+ *
+ * Reference:
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * 1.Included header files
+ *****************************************************************************/
+#include "../focaltech_core.h"
+
+#if (FTS_CHIP_IDC == 1)
+#include "../focaltech_flash.h"
+
+/*****************************************************************************
+ * Static variables
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Global variable or extern global variabls/functions
+ *****************************************************************************/
+static u8 upgrade_ecc;
+
+/*****************************************************************************
+ * Static function prototypes
+ *****************************************************************************/
+
+/************************************************************************
+ * Name: fts_ctpm_upgrade_idc_init
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+int fts_ctpm_upgrade_idc_init(struct i2c_client *client)
+{
+ int i_ret = 0;
+ u8 reg_val_id[4] = {0};
+ u8 auc_i2c_write_buf[10];
+
+ FTS_INFO("[UPGRADE]**********Upgrade setting Init**********");
+
+ /*read flash ID*/
+ auc_i2c_write_buf[0] = 0x05;
+ reg_val_id[0] = 0x00;
+ i_ret = fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val_id, 1);
+ if (i_ret < 0)
+ return -EIO;
+
+ /*set flash clk*/
+ auc_i2c_write_buf[0] = 0x05;
+ auc_i2c_write_buf[1] = reg_val_id[0];/* 0x80; */
+ auc_i2c_write_buf[2] = 0x00;
+ fts_i2c_write(client, auc_i2c_write_buf, 3);
+
+ /*send upgrade type to reg 0x09: 0x0B: upgrade; 0x0A: download*/
+ auc_i2c_write_buf[0] = 0x09;
+ auc_i2c_write_buf[1] = 0x0B;
+ fts_i2c_write(client, auc_i2c_write_buf, 2);
+
+ return 0;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_start_pramboot
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+void fts_ctpm_start_pramboot(struct i2c_client *client)
+{
+ u8 auc_i2c_write_buf[10];
+
+ FTS_INFO("[UPGRADE]**********start pramboot**********");
+ auc_i2c_write_buf[0] = 0x08;
+ fts_i2c_write(client, auc_i2c_write_buf, 1);
+ msleep(20);
+}
+
+/************************************************************************
+ * Name: fts_ctpm_start_fw_upgrade
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+int fts_ctpm_start_fw_upgrade(struct i2c_client *client)
+{
+ int i_ret = 0;
+
+ /*send the soft upgrade commond to FW, and start upgrade*/
+ FTS_INFO("[UPGRADE]***send 0xAA and 0x55 to FW, start upgrade***\n");
+
+ i_ret = fts_i2c_write_reg(client, FTS_RST_CMD_REG1, FTS_UPGRADE_AA);
+ msleep(20);
+ i_ret = fts_i2c_write_reg(client, FTS_RST_CMD_REG1, FTS_UPGRADE_55);
+ msleep(200);
+
+ return i_ret;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_check_run_state
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+bool fts_ctpm_check_run_state(struct i2c_client *client, int rstate)
+{
+ int i = 0;
+ enum FW_STATUS cstate = FTS_RUN_IN_ERROR;
+
+ for (i = 0; i < FTS_UPGRADE_LOOP; i++) {
+ cstate = fts_ctpm_get_pram_or_rom_id(client);
+ FTS_DEBUG("[UPGRADE]: run state = %d", cstate);
+
+ if (cstate == rstate)
+ return true;
+ msleep(20);
+ }
+
+ return false;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_pramboot_ecc
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+int fts_ctpm_pramboot_ecc(struct i2c_client *client)
+{
+ u8 auc_i2c_write_buf[10];
+ u8 reg_val[4] = {0};
+
+ FTS_FUNC_ENTER();
+
+ /* read out checksum,
+ * if pramboot checksum != host checksum, upgrade fail
+ */
+ FTS_INFO("[UPGRADE]******read out pramboot checksum******");
+ auc_i2c_write_buf[0] = 0xcc;
+ usleep_range(2000, 4000);
+ fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 1);
+ /*pramboot checksum != host checksum, upgrade fail*/
+ if (reg_val[0] != upgrade_ecc) {
+ FTS_ERROR("[UPGRADE]: checksum fail:pramboot = %X, host = %X!",
+ reg_val[0], upgrade_ecc);
+ return -EIO;
+ }
+
+ FTS_DEBUG("[UPGRADE]: checksum success:pramboot = %X, host = %X!!",
+ reg_val[0], upgrade_ecc);
+ msleep(100);
+
+ FTS_FUNC_EXIT();
+
+ return 0;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_upgrade_ecc
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+int fts_ctpm_upgrade_ecc(struct i2c_client *client, u32 startaddr, u32 length)
+{
+ u32 i = 0;
+ u8 auc_i2c_write_buf[10];
+ u32 temp;
+ u8 reg_val[4] = {0};
+ int i_ret = 0;
+
+ FTS_INFO("[UPGRADE]**********read out checksum**********");
+
+ /*check sum init*/
+ auc_i2c_write_buf[0] = 0x64;
+ fts_i2c_write(client, auc_i2c_write_buf, 1);
+ msleep(300);
+
+ /*send commond to pramboot to start checksum*/
+ auc_i2c_write_buf[0] = 0x65;
+ auc_i2c_write_buf[1] = (u8)(startaddr >> 16);
+ auc_i2c_write_buf[2] = (u8)(startaddr >> 8);
+ auc_i2c_write_buf[3] = (u8)(startaddr);
+
+ if (length > LEN_FLASH_ECC_MAX)
+ temp = LEN_FLASH_ECC_MAX;
+ else
+ temp = length;
+
+ auc_i2c_write_buf[4] = (u8)(temp >> 8);
+ auc_i2c_write_buf[5] = (u8)(temp);
+ i_ret = fts_i2c_write(client, auc_i2c_write_buf, 6);
+ msleep(length/256);
+
+ /*read status : if check sum is finished?*/
+ for (i = 0; i < 100; i++) {
+ auc_i2c_write_buf[0] = 0x6a;
+ reg_val[0] = reg_val[1] = 0x00;
+ fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2);
+
+ if (0xF0 == reg_val[0] && 0x55 == reg_val[1])
+ break;
+ usleep_range(1000, 2000);
+
+ }
+
+ if (length > LEN_FLASH_ECC_MAX) {
+ temp = LEN_FLASH_ECC_MAX;
+ auc_i2c_write_buf[0] = 0x65;
+ auc_i2c_write_buf[1] = (u8)(temp >> 16);
+ auc_i2c_write_buf[2] = (u8)(temp >> 8);
+ auc_i2c_write_buf[3] = (u8)(temp);
+ temp = length-LEN_FLASH_ECC_MAX;
+ auc_i2c_write_buf[4] = (u8)(temp >> 8);
+ auc_i2c_write_buf[5] = (u8)(temp);
+ i_ret = fts_i2c_write(client, auc_i2c_write_buf, 6);
+
+ msleep(length/256);
+
+ for (i = 0; i < 100; i++) {
+ auc_i2c_write_buf[0] = 0x6a;
+ reg_val[0] = reg_val[1] = 0x00;
+ fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2);
+
+ if (0xF0 == reg_val[0] && 0x55 == reg_val[1])
+ break;
+ usleep_range(1000, 2000);
+ }
+ }
+
+ /*read out check sum*/
+ auc_i2c_write_buf[0] = 0x66;
+ i_ret = fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 1);
+ /*if check sum fail, upgrade fail*/
+ if (reg_val[0] != upgrade_ecc) {
+ FTS_ERROR("[UPGRADE]: ecc error! FW=%02x upgrade_ecc=%02x!!",
+ reg_val[0], upgrade_ecc);
+ return -EIO;
+ }
+
+ FTS_DEBUG("[UPGRADE]: ecc success : FW=%02x upgrade_ecc=%02x!!",
+ reg_val[0], upgrade_ecc);
+
+ upgrade_ecc = 0;
+
+ return i_ret;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_erase_flash
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+int fts_ctpm_erase_flash(struct i2c_client *client)
+{
+ u32 i = 0;
+ u8 auc_i2c_write_buf[10];
+ u8 reg_val[4] = {0};
+
+ FTS_INFO("[UPGRADE]**********erase app now**********");
+
+ /*send to erase flash*/
+ auc_i2c_write_buf[0] = 0x61;
+ fts_i2c_write(client, auc_i2c_write_buf, 1);
+ msleep(1350);
+
+ for (i = 0; i < 15; i++) {
+ /* get the erase app status,
+ * if get 0xF0AA£¬erase flash success
+ */
+ auc_i2c_write_buf[0] = 0x6a;
+ reg_val[0] = reg_val[1] = 0x00;
+ fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2);
+ /*erase flash success*/
+ if (0xF0 == reg_val[0] && 0xAA == reg_val[1])
+ break;
+ msleep(50);
+ }
+
+ /*erase flash fail*/
+ if ((0xF0 != reg_val[0] || 0xAA != reg_val[1]) && (i >= 15)) {
+ FTS_ERROR("[UPGRADE]: erase app error.reset tp and reload FW!");
+ return -EIO;
+ }
+
+ FTS_DEBUG("[UPGRADE]: erase app ok!!");
+
+ return 0;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_write_pramboot_for_idc
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+int fts_ctpm_write_pramboot_for_idc(struct i2c_client *client,
+ u32 length, u8 *readbuf)
+{
+ u32 i = 0;
+ u32 j;
+ u32 temp;
+ u32 packet_number;
+ u8 packet_buf[FTS_PACKET_LENGTH + 6];
+
+ upgrade_ecc = 0;
+ FTS_INFO("[UPGRADE]**********write pramboot to pram**********");
+
+ temp = 0;
+ packet_number = (length) / FTS_PACKET_LENGTH;
+ if ((length) % FTS_PACKET_LENGTH > 0)
+ packet_number++;
+
+ packet_buf[0] = 0xae;
+ packet_buf[1] = 0x00;
+
+ for (j = 0; j < packet_number; j++) {
+ temp = j * FTS_PACKET_LENGTH;
+ packet_buf[2] = (u8) (temp >> 8);
+ packet_buf[3] = (u8) temp;
+ if (j < (packet_number-1))
+ temp = FTS_PACKET_LENGTH;
+ else
+ temp = (length) % FTS_PACKET_LENGTH;
+
+ packet_buf[4] = (u8) (temp >> 8);
+ packet_buf[5] = (u8) temp;
+
+ for (i = 0; i < temp; i++) {
+ packet_buf[6 + i] = readbuf[j * FTS_PACKET_LENGTH + i];
+ upgrade_ecc ^= packet_buf[6 + i];
+ }
+ fts_i2c_write(client, packet_buf, temp + 6);
+ }
+
+ return 0;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_write_app_for_idc
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+int fts_ctpm_write_app_for_idc(struct i2c_client *client,
+ u32 length, u8 *readbuf)
+{
+ u32 j;
+ u32 i = 0;
+ u32 packet_number;
+ u32 temp;
+ u32 writelenght;
+ u8 packet_buf[FTS_PACKET_LENGTH + 6];
+ u8 auc_i2c_write_buf[10];
+ u8 reg_val[4] = {0};
+
+ FTS_INFO("[UPGRADE]**********write app to flash**********");
+
+ upgrade_ecc = 0;
+
+ packet_number = (length) / FTS_PACKET_LENGTH;
+ if (((length) % FTS_PACKET_LENGTH) > 0)
+ packet_number++;
+
+ packet_buf[0] = 0xbf;
+
+ for (j = 0; j < packet_number; j++) {
+ temp = 0x1000+j * FTS_PACKET_LENGTH;
+
+ if (j < (packet_number-1))
+ writelenght = FTS_PACKET_LENGTH;
+ else
+ writelenght = ((length) % FTS_PACKET_LENGTH);
+
+ packet_buf[1] = (u8) (temp >> 16);
+ packet_buf[2] = (u8) (temp >> 8);
+ packet_buf[3] = (u8) temp;
+ packet_buf[4] = (u8) (writelenght >> 8);
+ packet_buf[5] = (u8) writelenght;
+
+ for (i = 0; i < writelenght; i++) {
+ packet_buf[6 + i] = readbuf[(temp - 0x1000+i)];
+ upgrade_ecc ^= packet_buf[6 + i];
+ }
+
+ fts_i2c_write(client, packet_buf, (writelenght + 6));
+
+ for (i = 0; i < 30; i++) {
+ /* read status and check
+ * if the app writing is finished
+ */
+ auc_i2c_write_buf[0] = 0x6a;
+ reg_val[0] = reg_val[1] = 0x00;
+ fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2);
+
+ if ((j + 0x20+0x1000) == (((reg_val[0]) << 8)
+ | reg_val[1]))
+ break;
+
+ fts_ctpm_upgrade_delay(1000);
+ }
+ }
+
+ msleep(50);
+
+ return 0;
+}
+
+#define APP_LEN 0x00
+#define APP_LEN_NE 0x02
+#define APP_P1_ECC 0x04
+#define APP_P1_ECC_NE 0x06
+#define APP_P2_ECC 0x08
+#define APP_P2_ECC_NE 0x0A
+#define APP_LEN_H 0x12
+#define APP_LEN_H_NE 0x14
+#define APP_BLR_ID 0x1C
+#define APP_BLR_ID_NE 0x1D
+#define PBOOT_ID_H 0x1E
+#define PBOOT_ID_L 0x1F
+
+#define AL2_FCS_COEF ((1 << 15) + (1 << 10) + (1 << 3))
+
+#if ((FTS_CHIP_TYPE == _FT8006) || (FTS_CHIP_TYPE == _FT8736))
+#define FW_CFG_TOTAL_SIZE 0x80
+#else
+#define FW_CFG_TOTAL_SIZE 0x00
+#endif
+#define APP1_START 0x00
+#define APP1_LEN 0x100
+#define APP_VERIF_ADDR (APP1_START + APP1_LEN)
+#define APP_VERIF_LEN 0x20
+#define APP1_ECC_ADDR (APP_VERIF_ADDR + APP_P1_ECC)
+#define APP2_START (APP_VERIF_ADDR + APP_VERIF_LEN + FW_CFG_TOTAL_SIZE)
+#define APP2_ECC_ADDR (APP_VERIF_ADDR + APP_P2_ECC)
+/*****************************************************************************
+ * Name: DrvReadPram16
+ * Brief: Get Word
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static u16 data_word(u8 *pbt_buf, u32 addr)
+{
+ return (((u16)pbt_buf[addr]<<8) + pbt_buf[addr+1]);
+}
+
+/******************************************************************************
+ * Name: GetCrc16
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static u16 crc_calc(u8 *pbt_buf, u32 addr, u16 length)
+{
+ u16 cFcs = 0;
+ u16 i, j;
+
+ FTS_DEBUG("[UPGRADE][ECC] : %04x data:%04x, len:%04x!!",
+ (addr), data_word(pbt_buf, (addr)), length);
+ for (i = 0; i < length; i++) {
+ cFcs ^= data_word(pbt_buf, (addr+i*2));
+ for (j = 0; j < 16; j++) {
+ if (cFcs & 1)
+ cFcs = (u16)((cFcs >> 1) ^ AL2_FCS_COEF);
+ else
+ cFcs >>= 1;
+ }
+ }
+
+ return cFcs;
+}
+
+/*****************************************************************************
+ * Name: task_check_mem
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static bool ecc_check(u8 *pbt_buf, u32 star_addr, u32 len, u16 ecc_addr)
+{
+ u16 ecc1;
+ u16 ecc2;
+ u16 cal_ecc;
+
+ ecc1 = data_word(pbt_buf, ecc_addr);
+ ecc2 = data_word(pbt_buf, ecc_addr+2);
+
+ if ((ecc1 + ecc2) != 0xFFFF)
+ return false;
+
+ cal_ecc = crc_calc(pbt_buf, star_addr, (len/2));
+
+ FTS_DEBUG("[UPGRADE][ECC] : ecc1 = %x, cal_ecc = %x", ecc1, cal_ecc);
+ if (ecc1 != cal_ecc) {
+ FTS_DEBUG("[UPGRADE][ECC] : ecc error!!");
+ return false;
+ }
+
+ return true;
+}
+
+/*****************************************************************************
+ * Name: fts_check_app_bin_valid_idc
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+bool fts_check_app_bin_valid_idc(u8 *pbt_buf)
+{
+ u32 len;
+#if (FTS_CHIP_TYPE != _FT8006)
+ /* 1. First Byte */
+ if (pbt_buf[0] != 0x02) {
+ FTS_DEBUG("[UPGRADE]APP.BIN Verify- the first byte(%x) error",
+ pbt_buf[0]);
+ return false;
+ }
+#endif
+ /* 2 PART1 ECC */
+ if (!ecc_check(pbt_buf, APP1_START, APP1_LEN, APP1_ECC_ADDR)) {
+ FTS_DEBUG("[UPGRADE]APP.BIN Verify- ecc1 error");
+ return false;
+ }
+
+ /* 3. PART2 ECC */
+ if ((data_word(pbt_buf, APP_VERIF_ADDR+APP_LEN)
+ + data_word(pbt_buf, APP_VERIF_ADDR+APP_LEN_NE)) != 0xFFFF) {
+ FTS_DEBUG("[UPGRADE]APP.BIN Verify- Length XOR error");
+ return false;
+ }
+
+ len = data_word(pbt_buf, APP_VERIF_ADDR+APP_LEN);
+#if (FTS_CHIP_TYPE == _FT8006)
+ if ((data_word(pbt_buf, APP_VERIF_ADDR+APP_LEN_H)
+ + data_word(pbt_buf, APP_VERIF_ADDR+APP_LEN_H_NE)) != 0xFFFF) {
+ FTS_DEBUG("[UPGRADE]APP.BIN Verify- Length2 XOR error");
+ return false;
+ }
+
+ len += ((u32)data_word(pbt_buf, APP_VERIF_ADDR+APP_LEN_H) << 16);
+#endif
+ FTS_DEBUG("%x %x %x %x", APP2_START, len,
+ ((u32)data_word(pbt_buf, APP_VERIF_ADDR+APP_LEN_H) << 16),
+ data_word(pbt_buf, APP_VERIF_ADDR+APP_LEN));
+
+ len -= APP2_START;
+
+ return ecc_check(pbt_buf, APP2_START, len, APP2_ECC_ADDR);
+}
+
+
+#endif /* IDC */
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_test.c b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_test.c
new file mode 100644
index 0000000..2041369
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_test.c
@@ -0,0 +1,175 @@
+/*
+ *
+ * FocalTech fts TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, Focaltech Ltd. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/*****************************************************************************
+ *
+ * File Name: focaltech_upgrade_test.c
+ *
+ * Author: fupeipei
+ *
+ * Created: 2016-08-22
+ *
+ * Abstract:
+ *
+ * Reference:
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * 1.Included header files
+ *****************************************************************************/
+#include "../focaltech_core.h"
+#include "../focaltech_flash.h"
+#include <linux/wakelock.h>
+#include <linux/timer.h>
+
+/*****************************************************************************
+ * Static variables
+ *****************************************************************************/
+#define FTS_GET_UPGRADE_TIME 0
+
+/*****************************************************************************
+ * Global variable or extern global variabls/functions
+ *****************************************************************************/
+
+#define FTS_DEBUG_UPGRADE(fmt, args...) do {\
+ pr_err("[FTS][UPGRADE]:################\n");\
+ pr_err("[FTS][UPGRADE]: "fmt"\n", ##args);\
+ pr_err("[FTS][UPGRADE]:################\n");\
+ } while (0)\
+
+/*****************************************************************************
+ * Static function prototypes
+ *****************************************************************************/
+#if (FTS_UPGRADE_STRESS_TEST)
+/************************************************************************
+ * Name: fts_ctpm_auto_upgrade_pingpong
+ * Brief: 0
+ * Input: 0
+ * Output: 0
+ * Return: 0
+ ***********************************************************************/
+static int fts_ctpm_auto_upgrade_pingpong(struct i2c_client *client)
+{
+ u8 uc_tp_fm_ver;
+ int i_ret = 0;
+ u8 uc_upgrade_times = 0;
+
+ FTS_FUNC_ENTER();
+
+ /* pingpong test mode, need upgrade */
+ FTS_INFO("[UPGRADE]: pingpong test mode, need upgrade!!");
+ do {
+ uc_upgrade_times++;
+
+ /* fw upgrade */
+ i_ret = fts_ctpm_fw_upgrade(client);
+
+ if (i_ret == 0) {
+ /* upgrade success */
+ fts_i2c_read_reg(client, FTS_REG_FW_VER, &uc_tp_fm_ver);
+ FTS_DEBUG("[UPGRADE]: upgrade to new version 0x%x",
+ uc_tp_fm_ver);
+ } else {
+ /* upgrade fail */
+ /* if upgrade fail, reset to run ROM.
+ * if app in flash is ok. TP will work success
+ */
+ FTS_INFO("[UPGRADE]: upgrade fail, reset now!!");
+ fts_ctpm_rom_or_pram_reset(client);
+ }
+ /* if upgrade fail, upgrade again. then return */
+ } while ((i_ret != 0) && (uc_upgrade_times < 2));
+
+ FTS_FUNC_EXIT();
+ return i_ret;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_auto_upgrade
+ * Brief: 0
+ * Input: 0
+ * Output: 0
+ * Return: 0
+ ***********************************************************************/
+void fts_ctpm_display_upgrade_time(bool start_time)
+{
+#if FTS_GET_UPGRADE_TIME
+ static struct timeval tpend;
+ static struct timeval tpstart;
+ static int timeuse;
+
+ if (start_time) {
+ do_gettimeofday(&tpstart);
+ } else {
+ do_gettimeofday(&tpend);
+ timeuse = 1000000 * (tpend.tv_sec-tpstart.tv_sec)
+ + tpend.tv_usec-tpstart.tv_usec;
+ timeuse /= 1000000;
+ FTS_DEBUG("[UPGRADE]: upgrade success : Use time: %d Seconds!!",
+ timeuse);
+ }
+#endif
+}
+
+/************************************************************************
+ * Name: fts_ctpm_auto_upgrade
+ * Brief: 0
+ * Input: 0
+ * Output: 0
+ * Return: 0
+ ***********************************************************************/
+int fts_ctpm_auto_upgrade(struct i2c_client *client)
+{
+ int i_ret = 0;
+ static int uc_ErrorTimes;
+ static int uc_UpgradeTimes;
+
+
+ device_init_wakeup(&client->dev, 1);
+ pm_stay_awake(&client->dev);
+
+ /* (FTS_GET_VENDOR_ID_NUM == 0) */
+ g_fw_file = CTPM_FW;
+ g_fw_len = fts_getsize(FW_SIZE);
+ FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW, SIZE:%x", g_fw_len);
+
+ do {
+ uc_UpgradeTimes++;
+
+ FTS_DEBUG_UPGRADE("start to upgrade %d times !!",
+ uc_UpgradeTimes);
+
+ fts_ctpm_display_upgrade_time(true);
+
+ i_ret = fts_ctpm_auto_upgrade_pingpong(client);
+ if (i_ret == 0)
+ fts_ctpm_display_upgrade_time(false);
+ else
+ uc_ErrorTimes++;
+
+ FTS_DEBUG_UPGRADE("upgrade %d times, error %d times!!",
+ uc_UpgradeTimes, uc_ErrorTimes);
+ } while (uc_UpgradeTimes < (FTS_UPGRADE_TEST_NUMBER));
+
+ pm_relax(&client->dev);
+ device_init_wakeup(&client->dev, 0);
+
+ return 0;
+}
+#endif
+
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_gesture.c b/drivers/input/touchscreen/focaltech_touch/focaltech_gesture.c
new file mode 100644
index 0000000..b3bb39e
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_gesture.c
@@ -0,0 +1,636 @@
+/*
+ *
+ * FocalTech TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, Focaltech Ltd. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/*****************************************************************************
+ *
+ * File Name: focaltech_gestrue.c
+ *
+ * Author: Focaltech Driver Team
+ *
+ * Created: 2016-08-08
+ *
+ * Abstract:
+ *
+ * Reference:
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * 1.Included header files
+ *****************************************************************************/
+#include "focaltech_core.h"
+#if FTS_GESTURE_EN
+/******************************************************************************
+ * Private constant and macro definitions using #define
+ *****************************************************************************/
+#define KEY_GESTURE_U KEY_U
+#define KEY_GESTURE_UP KEY_UP
+#define KEY_GESTURE_DOWN KEY_DOWN
+#define KEY_GESTURE_LEFT KEY_LEFT
+#define KEY_GESTURE_RIGHT KEY_RIGHT
+#define KEY_GESTURE_O KEY_O
+#define KEY_GESTURE_E KEY_E
+#define KEY_GESTURE_M KEY_M
+#define KEY_GESTURE_L KEY_L
+#define KEY_GESTURE_W KEY_W
+#define KEY_GESTURE_S KEY_S
+#define KEY_GESTURE_V KEY_V
+#define KEY_GESTURE_C KEY_C
+#define KEY_GESTURE_Z KEY_Z
+
+#define GESTURE_LEFT 0x20
+#define GESTURE_RIGHT 0x21
+#define GESTURE_UP 0x22
+#define GESTURE_DOWN 0x23
+#define GESTURE_DOUBLECLICK 0x24
+#define GESTURE_O 0x30
+#define GESTURE_W 0x31
+#define GESTURE_M 0x32
+#define GESTURE_E 0x33
+#define GESTURE_L 0x44
+#define GESTURE_S 0x46
+#define GESTURE_V 0x54
+#define GESTURE_Z 0x41
+#define GESTURE_C 0x34
+#define FTS_GESTRUE_POINTS 255
+#define FTS_GESTRUE_POINTS_HEADER 8
+
+/*****************************************************************************
+ * Private enumerations, structures and unions using typedef
+ *****************************************************************************/
+/*
+ * header - byte0:gesture id
+ * byte1:pointnum
+ * byte2~7:reserved
+ * coordinate_x - All gesture point x coordinate
+ * coordinate_y - All gesture point y coordinate
+ * mode - 1:enable gesture function(default)
+ * - 0:disable
+ * active - 1:enter into gesture(suspend)
+ * 0:gesture disable or resume
+ */
+struct fts_gesture_st {
+ u8 header[FTS_GESTRUE_POINTS_HEADER];
+ u16 coordinate_x[FTS_GESTRUE_POINTS];
+ u16 coordinate_y[FTS_GESTRUE_POINTS];
+ u8 mode;
+ u8 active;
+};
+
+/*****************************************************************************
+ * Static variables
+ *****************************************************************************/
+static struct fts_gesture_st fts_gesture_data;
+
+/*****************************************************************************
+ * Global variable or extern global variabls/functions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Static function prototypes
+ *****************************************************************************/
+static ssize_t fts_gesture_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+static ssize_t fts_gesture_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t fts_gesture_buf_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+static ssize_t fts_gesture_buf_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+
+/* sysfs gesture node
+ * read example: cat fts_gesture_mode ---read gesture mode
+ * write example:echo 01 > fts_gesture_mode ---write gesture mode to 01
+ *
+ */
+static DEVICE_ATTR(fts_gesture_mode, 0644,
+ fts_gesture_show, fts_gesture_store);
+/*
+ * read example: cat fts_gesture_buf ---read gesture buf
+ */
+static DEVICE_ATTR(fts_gesture_buf, 0644,
+ fts_gesture_buf_show, fts_gesture_buf_store);
+static struct attribute *fts_gesture_mode_attrs[] = {
+
+
+ &dev_attr_fts_gesture_mode.attr,
+ &dev_attr_fts_gesture_buf.attr,
+ NULL,
+};
+
+static struct attribute_group fts_gesture_group = {
+
+ .attrs = fts_gesture_mode_attrs,
+};
+
+/************************************************************************
+ * Name: fts_gesture_show
+ * Brief:
+ * Input: device, device attribute, char buf
+ * Output:
+ * Return:
+ ***********************************************************************/
+static ssize_t fts_gesture_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int count;
+ u8 val;
+ struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+ mutex_lock(&fts_input_dev->mutex);
+ fts_i2c_read_reg(client, FTS_REG_GESTURE_EN, &val);
+ count = snprintf(buf, PAGE_SIZE, "Gesture Mode: %s\n",
+ fts_gesture_data.mode ? "On" : "Off");
+ count += snprintf(buf + count, PAGE_SIZE - count,
+ "Reg(0xD0) = %d\n", val);
+ mutex_unlock(&fts_input_dev->mutex);
+
+ return count;
+}
+
+/************************************************************************
+ * Name: fts_gesture_store
+ * Brief:
+ * Input: device, device attribute, char buf, char count
+ * Output:
+ * Return:
+ ***********************************************************************/
+static ssize_t fts_gesture_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ mutex_lock(&fts_input_dev->mutex);
+
+ if (FTS_SYSFS_ECHO_ON(buf)) {
+ FTS_INFO("[GESTURE]enable gesture");
+ fts_gesture_data.mode = ENABLE;
+ } else if (FTS_SYSFS_ECHO_OFF(buf)) {
+ FTS_INFO("[GESTURE]disable gesture");
+ fts_gesture_data.mode = DISABLE;
+ }
+
+ mutex_unlock(&fts_input_dev->mutex);
+
+ return count;
+}
+
+/************************************************************************
+ * Name: fts_gesture_buf_show
+ * Brief:
+ * Input: device, device attribute, char buf
+ * Output:
+ * Return:
+ ***********************************************************************/
+static ssize_t fts_gesture_buf_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int count;
+ int i = 0;
+
+ mutex_lock(&fts_input_dev->mutex);
+ count = snprintf(buf, PAGE_SIZE, "Gesture ID: 0x%x\n",
+ fts_gesture_data.header[0]);
+ count += snprintf(buf + count, PAGE_SIZE, "Gesture PointNum: %d\n",
+ fts_gesture_data.header[1]);
+ count += snprintf(buf + count, PAGE_SIZE, "Gesture Point Buf:\n");
+
+ for (i = 0; i < fts_gesture_data.header[1]; i++) {
+ count += snprintf(buf + count, PAGE_SIZE, "%3d(%4d,%4d) ",
+ i, fts_gesture_data.coordinate_x[i],
+ fts_gesture_data.coordinate_y[i]);
+ if ((i + 1)%4 == 0)
+ count += snprintf(buf + count, PAGE_SIZE, "\n");
+ }
+ count += snprintf(buf + count, PAGE_SIZE, "\n");
+ mutex_unlock(&fts_input_dev->mutex);
+
+ return count;
+}
+
+/************************************************************************
+ * Name: fts_gesture_buf_store
+ * Brief:
+ * Input: device, device attribute, char buf, char count
+ * Output:
+ * Return:
+ ***********************************************************************/
+static ssize_t fts_gesture_buf_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ /* place holder for future use */
+ return -EPERM;
+}
+
+/*****************************************************************************
+ * Name: fts_create_gesture_sysfs
+ * Brief:
+ * Input:
+ * Output:
+ * Return: 0-success or others-error
+ *****************************************************************************/
+int fts_create_gesture_sysfs(struct i2c_client *client)
+{
+ int ret = 0;
+
+ ret = sysfs_create_group(&client->dev.kobj, &fts_gesture_group);
+ if (ret != 0) {
+ FTS_ERROR("[GESTURE]fts_gesture_group(sysfs) create failed!");
+ sysfs_remove_group(&client->dev.kobj, &fts_gesture_group);
+ return ret;
+ }
+ return 0;
+}
+
+/*****************************************************************************
+ * Name: fts_gesture_report
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static void fts_gesture_report(struct input_dev *input_dev, int gesture_id)
+{
+ int gesture;
+
+ FTS_FUNC_ENTER();
+ FTS_DEBUG("fts gesture_id==0x%x ", gesture_id);
+ switch (gesture_id) {
+ case GESTURE_LEFT:
+ gesture = KEY_GESTURE_LEFT;
+ break;
+ case GESTURE_RIGHT:
+ gesture = KEY_GESTURE_RIGHT;
+ break;
+ case GESTURE_UP:
+ gesture = KEY_GESTURE_UP;
+ break;
+ case GESTURE_DOWN:
+ gesture = KEY_GESTURE_DOWN;
+ break;
+ case GESTURE_DOUBLECLICK:
+ gesture = KEY_GESTURE_U;
+ break;
+ case GESTURE_O:
+ gesture = KEY_GESTURE_O;
+ break;
+ case GESTURE_W:
+ gesture = KEY_GESTURE_W;
+ break;
+ case GESTURE_M:
+ gesture = KEY_GESTURE_M;
+ break;
+ case GESTURE_E:
+ gesture = KEY_GESTURE_E;
+ break;
+ case GESTURE_L:
+ gesture = KEY_GESTURE_L;
+ break;
+ case GESTURE_S:
+ gesture = KEY_GESTURE_S;
+ break;
+ case GESTURE_V:
+ gesture = KEY_GESTURE_V;
+ break;
+ case GESTURE_Z:
+ gesture = KEY_GESTURE_Z;
+ break;
+ case GESTURE_C:
+ gesture = KEY_GESTURE_C;
+ break;
+ default:
+ gesture = -1;
+ break;
+ }
+
+ /* report event key */
+ if (gesture != -1) {
+ FTS_DEBUG("Gesture Code=%d", gesture);
+ input_report_key(input_dev, gesture, 1);
+ input_sync(input_dev);
+ input_report_key(input_dev, gesture, 0);
+ input_sync(input_dev);
+ }
+
+ FTS_FUNC_EXIT();
+}
+
+/************************************************************************
+ * Name: fts_gesture_readdata
+ * Brief: read data from TP register
+ * Input:
+ * Output:
+ * Return: fail <0
+ ***********************************************************************/
+static int fts_gesture_read_buffer(struct i2c_client *client,
+ u8 *buf, int read_bytes)
+{
+ int remain_bytes;
+ int ret;
+ int i;
+
+ if (read_bytes <= I2C_BUFFER_LENGTH_MAXINUM) {
+ ret = fts_i2c_read(client, buf, 1, buf, read_bytes);
+ } else {
+ ret = fts_i2c_read(client, buf, 1,
+ buf, I2C_BUFFER_LENGTH_MAXINUM);
+ remain_bytes = read_bytes - I2C_BUFFER_LENGTH_MAXINUM;
+ for (i = 1; remain_bytes > 0; i++) {
+ if (remain_bytes <= I2C_BUFFER_LENGTH_MAXINUM)
+ ret = fts_i2c_read(client, buf, 0, buf
+ + I2C_BUFFER_LENGTH_MAXINUM * i,
+ remain_bytes);
+ else
+ ret = fts_i2c_read(client, buf, 0, buf
+ + I2C_BUFFER_LENGTH_MAXINUM * i,
+ I2C_BUFFER_LENGTH_MAXINUM);
+ remain_bytes -= I2C_BUFFER_LENGTH_MAXINUM;
+ }
+ }
+
+ return ret;
+}
+
+/************************************************************************
+ * Name: fts_gesture_fw
+ * Brief: Check IC's gesture recognise by FW or not
+ * Input:
+ * Output:
+ * Return: 1- FW 0- Driver
+ ***********************************************************************/
+static int fts_gesture_fw(void)
+{
+ int ret = 0;
+
+ switch (chip_types.chip_idh) {
+ case 0x54:
+ case 0x58:
+ case 0x64:
+ case 0x87:
+ case 0x86:
+ case 0x80:
+ case 0xE7:
+ ret = 1;
+ break;
+ default:
+ ret = 0;
+ break;
+ }
+ return ret;
+}
+
+/************************************************************************
+ * Name: fts_gesture_readdata
+ * Brief: read data from TP register
+ * Input:
+ * Output:
+ * Return: fail <0
+ ***********************************************************************/
+int fts_gesture_readdata(struct i2c_client *client)
+{
+ u8 buf[FTS_GESTRUE_POINTS * 4] = { 0 };
+ int ret = -1;
+ int i = 0;
+ int gestrue_id = 0;
+ int read_bytes = 0;
+ u8 pointnum;
+
+ FTS_FUNC_ENTER();
+ /* init variable before read gesture point */
+ memset(fts_gesture_data.header, 0, FTS_GESTRUE_POINTS_HEADER);
+ memset(fts_gesture_data.coordinate_x, 0,
+ FTS_GESTRUE_POINTS * sizeof(u16));
+ memset(fts_gesture_data.coordinate_y, 0,
+ FTS_GESTRUE_POINTS * sizeof(u16));
+
+ buf[0] = FTS_REG_GESTURE_OUTPUT_ADDRESS;
+ ret = fts_i2c_read(client, buf, 1, buf, FTS_GESTRUE_POINTS_HEADER);
+ if (ret < 0) {
+ FTS_ERROR("[GESTURE]Read gesture header data failed!!");
+ FTS_FUNC_EXIT();
+ return ret;
+ }
+
+ /* FW recognize gesture */
+ if (fts_gesture_fw()) {
+ memcpy(fts_gesture_data.header, buf, FTS_GESTRUE_POINTS_HEADER);
+ gestrue_id = buf[0];
+ pointnum = buf[1];
+ read_bytes = ((int)pointnum) * 4 + 2;
+ buf[0] = FTS_REG_GESTURE_OUTPUT_ADDRESS;
+ FTS_DEBUG("[GESTURE]PointNum=%d", pointnum);
+ ret = fts_gesture_read_buffer(client, buf, read_bytes);
+ if (ret < 0) {
+ FTS_ERROR("[GESTURE]Read gesture touch data failed!!");
+ FTS_FUNC_EXIT();
+ return ret;
+ }
+
+ fts_gesture_report(fts_input_dev, gestrue_id);
+ for (i = 0; i < pointnum; i++) {
+ fts_gesture_data.coordinate_x[i] =
+ (((s16) buf[0 + (4 * i + 2)]) & 0x0F) << 8
+ | (((s16) buf[1 + (4 * i + 2)]) & 0xFF);
+ fts_gesture_data.coordinate_y[i] =
+ (((s16) buf[2 + (4 * i + 2)]) & 0x0F) << 8
+ | (((s16) buf[3 + (4 * i + 2)]) & 0xFF);
+ }
+
+ FTS_FUNC_EXIT();
+ return 0;
+ }
+
+ FTS_ERROR("[GESTURE]IC 0x%x need gesture lib to support gestures.",
+ chip_types.chip_idh);
+
+ return 0;
+}
+
+/*****************************************************************************
+ * Name: fts_gesture_recovery
+ * Brief: recovery gesture state when reset or power on
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+void fts_gesture_recovery(struct i2c_client *client)
+{
+ if (fts_gesture_data.mode && fts_gesture_data.active) {
+ fts_i2c_write_reg(client, 0xD1, 0xff);
+ fts_i2c_write_reg(client, 0xD2, 0xff);
+ fts_i2c_write_reg(client, 0xD5, 0xff);
+ fts_i2c_write_reg(client, 0xD6, 0xff);
+ fts_i2c_write_reg(client, 0xD7, 0xff);
+ fts_i2c_write_reg(client, 0xD8, 0xff);
+ fts_i2c_write_reg(client, FTS_REG_GESTURE_EN, ENABLE);
+ }
+}
+
+/*****************************************************************************
+ * Name: fts_gesture_suspend
+ * Brief:
+ * Input:
+ * Output: None
+ * Return: None
+ *****************************************************************************/
+int fts_gesture_suspend(struct i2c_client *i2c_client)
+{
+ int i;
+ u8 state;
+
+ FTS_FUNC_ENTER();
+
+ /* gesture not enable, return immediately */
+ if (fts_gesture_data.mode == 0) {
+ FTS_DEBUG("gesture is disabled");
+ FTS_FUNC_EXIT();
+ return -EINVAL;
+ }
+
+ for (i = 0; i < 5; i++) {
+ fts_i2c_write_reg(i2c_client, 0xd1, 0xff);
+ fts_i2c_write_reg(i2c_client, 0xd2, 0xff);
+ fts_i2c_write_reg(i2c_client, 0xd5, 0xff);
+ fts_i2c_write_reg(i2c_client, 0xd6, 0xff);
+ fts_i2c_write_reg(i2c_client, 0xd7, 0xff);
+ fts_i2c_write_reg(i2c_client, 0xd8, 0xff);
+ fts_i2c_write_reg(i2c_client, FTS_REG_GESTURE_EN, 0x01);
+ usleep_range(1000, 2000);
+ fts_i2c_read_reg(i2c_client, FTS_REG_GESTURE_EN, &state);
+ if (state == 1)
+ break;
+ }
+
+ if (i >= 5) {
+ FTS_ERROR("[GESTURE]Enter into gesture(suspend) failed!\n");
+ FTS_FUNC_EXIT();
+ return -EAGAIN;
+ }
+
+ fts_gesture_data.active = 1;
+ FTS_DEBUG("[GESTURE]Enter into gesture(suspend) successfully!");
+ FTS_FUNC_EXIT();
+ return 0;
+}
+
+/*****************************************************************************
+ * Name: fts_gesture_resume
+ * Brief:
+ * Input:
+ * Output: None
+ * Return: None
+ *****************************************************************************/
+int fts_gesture_resume(struct i2c_client *client)
+{
+ int i;
+ u8 state;
+
+ FTS_FUNC_ENTER();
+
+ /* gesture not enable, return immediately */
+ if (fts_gesture_data.mode == 0) {
+ FTS_DEBUG("gesture is disabled");
+ FTS_FUNC_EXIT();
+ return -EINVAL;
+ }
+
+ if (fts_gesture_data.active == 0) {
+ FTS_DEBUG("gesture is unactive");
+ FTS_FUNC_EXIT();
+ return -EINVAL;
+ }
+
+ fts_gesture_data.active = 0;
+ for (i = 0; i < 5; i++) {
+ fts_i2c_write_reg(client, FTS_REG_GESTURE_EN, 0x00);
+ usleep_range(1000, 2000);
+ fts_i2c_read_reg(client, FTS_REG_GESTURE_EN, &state);
+ if (state == 0)
+ break;
+ }
+
+ if (i >= 5)
+ FTS_ERROR("[GESTURE]Clear gesture(resume) failed!\n");
+
+ FTS_FUNC_EXIT();
+
+ return 0;
+}
+
+/*****************************************************************************
+ * Name: fts_gesture_init
+ * Brief:
+ * Input:
+ * Output: None
+ * Return: None
+ *****************************************************************************/
+int fts_gesture_init(struct input_dev *input_dev, struct i2c_client *client)
+{
+ FTS_FUNC_ENTER();
+ input_set_capability(input_dev, EV_KEY, KEY_POWER);
+ input_set_capability(input_dev, EV_KEY, KEY_GESTURE_U);
+ input_set_capability(input_dev, EV_KEY, KEY_GESTURE_UP);
+ input_set_capability(input_dev, EV_KEY, KEY_GESTURE_DOWN);
+ input_set_capability(input_dev, EV_KEY, KEY_GESTURE_LEFT);
+ input_set_capability(input_dev, EV_KEY, KEY_GESTURE_RIGHT);
+ input_set_capability(input_dev, EV_KEY, KEY_GESTURE_O);
+ input_set_capability(input_dev, EV_KEY, KEY_GESTURE_E);
+ input_set_capability(input_dev, EV_KEY, KEY_GESTURE_M);
+ input_set_capability(input_dev, EV_KEY, KEY_GESTURE_L);
+ input_set_capability(input_dev, EV_KEY, KEY_GESTURE_W);
+ input_set_capability(input_dev, EV_KEY, KEY_GESTURE_S);
+ input_set_capability(input_dev, EV_KEY, KEY_GESTURE_V);
+ input_set_capability(input_dev, EV_KEY, KEY_GESTURE_Z);
+ input_set_capability(input_dev, EV_KEY, KEY_GESTURE_C);
+
+ __set_bit(KEY_GESTURE_RIGHT, input_dev->keybit);
+ __set_bit(KEY_GESTURE_LEFT, input_dev->keybit);
+ __set_bit(KEY_GESTURE_UP, input_dev->keybit);
+ __set_bit(KEY_GESTURE_DOWN, input_dev->keybit);
+ __set_bit(KEY_GESTURE_U, input_dev->keybit);
+ __set_bit(KEY_GESTURE_O, input_dev->keybit);
+ __set_bit(KEY_GESTURE_E, input_dev->keybit);
+ __set_bit(KEY_GESTURE_M, input_dev->keybit);
+ __set_bit(KEY_GESTURE_W, input_dev->keybit);
+ __set_bit(KEY_GESTURE_L, input_dev->keybit);
+ __set_bit(KEY_GESTURE_S, input_dev->keybit);
+ __set_bit(KEY_GESTURE_V, input_dev->keybit);
+ __set_bit(KEY_GESTURE_C, input_dev->keybit);
+ __set_bit(KEY_GESTURE_Z, input_dev->keybit);
+
+ fts_create_gesture_sysfs(client);
+ fts_gesture_data.mode = 1;
+ fts_gesture_data.active = 0;
+ FTS_FUNC_EXIT();
+
+ return 0;
+}
+
+/************************************************************************
+ * Name: fts_gesture_exit
+ * Brief: call when driver removed
+ * Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+int fts_gesture_exit(struct i2c_client *client)
+{
+ FTS_FUNC_ENTER();
+ sysfs_remove_group(&client->dev.kobj, &fts_gesture_group);
+ FTS_FUNC_EXIT();
+
+ return 0;
+}
+#endif
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_i2c.c b/drivers/input/touchscreen/focaltech_touch/focaltech_i2c.c
new file mode 100644
index 0000000..fabedbf
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_i2c.c
@@ -0,0 +1,206 @@
+/*
+ *
+ * FocalTech TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, FocalTech Systems, Ltd., all rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/************************************************************************
+ *
+ * File Name: focaltech_i2c.c
+ *
+ * Author: fupeipei
+ *
+ * Created: 2016-08-04
+ *
+ * Abstract: i2c communication with TP
+ *
+ * Version: v1.0
+ *
+ * Revision History:
+ * v1.0:
+ * First release. By fupeipei 2016-08-04
+ ************************************************************************/
+
+/*****************************************************************************
+ * Included header files
+ *****************************************************************************/
+#include "focaltech_core.h"
+
+/*****************************************************************************
+ * Private constant and macro definitions using #define
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Private enumerations, structures and unions using typedef
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Static variables
+ *****************************************************************************/
+static DEFINE_MUTEX(i2c_rw_access);
+
+/*****************************************************************************
+ * Global variable or extern global variabls/functions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Static function prototypes
+ *****************************************************************************/
+
+/*****************************************************************************
+ * functions body
+ *****************************************************************************/
+
+/************************************************************************
+ * Name: fts_i2c_read
+ * Brief: i2c read
+ * Input: i2c info, write buf, write len, read buf, read len
+ * Output: get data in the 3rd buf
+ * Return: fail <0
+ ***********************************************************************/
+int fts_i2c_read(struct i2c_client *client, char *writebuf,
+ int writelen, char *readbuf, int readlen)
+{
+ int ret = -EIO;
+
+ mutex_lock(&i2c_rw_access);
+
+ if (readlen > 0) {
+ if (writelen > 0) {
+ struct i2c_msg msgs[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = writelen,
+ .buf = writebuf,
+ },
+ {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = readlen,
+ .buf = readbuf,
+ },
+ };
+ ret = i2c_transfer(client->adapter, msgs, 2);
+ if (ret < 0)
+ FTS_ERROR("[IIC]: i2c_write error %d!!", ret);
+ } else {
+ struct i2c_msg msgs[] = {
+ {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = readlen,
+ .buf = readbuf,
+ },
+ };
+ ret = i2c_transfer(client->adapter, msgs, 1);
+ if (ret < 0)
+ FTS_ERROR("[IIC]: i2c_read error %d!!", ret);
+ }
+ }
+
+ mutex_unlock(&i2c_rw_access);
+
+ return ret;
+}
+
+/************************************************************************
+ * Name: fts_i2c_write
+ * Brief: i2c write
+ * Input: i2c info, write buf, write len
+ * Output: no
+ * Return: fail <0
+ ***********************************************************************/
+int fts_i2c_write(struct i2c_client *client, char *writebuf, int writelen)
+{
+ int ret = 0;
+
+ mutex_lock(&i2c_rw_access);
+
+ if (writelen > 0) {
+ struct i2c_msg msgs[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = writelen,
+ .buf = writebuf,
+ },
+ };
+ ret = i2c_transfer(client->adapter, msgs, 1);
+ if (ret < 0)
+ FTS_ERROR("[IIC]: i2c_write error, ret=%d", ret);
+ }
+
+ mutex_unlock(&i2c_rw_access);
+
+ return ret;
+}
+
+/************************************************************************
+ * Name: fts_i2c_write_reg
+ * Brief: write register
+ * Input: i2c info, reg address, reg value
+ * Output: no
+ * Return: fail <0
+ ***********************************************************************/
+int fts_i2c_write_reg(struct i2c_client *client, u8 regaddr, u8 regvalue)
+{
+ u8 buf[2] = {0};
+
+ buf[0] = regaddr;
+ buf[1] = regvalue;
+ return fts_i2c_write(client, buf, sizeof(buf));
+}
+
+/************************************************************************
+ * Name: fts_i2c_read_reg
+ * Brief: read register
+ * Input: i2c info, reg address, reg value
+ * Output: get reg value
+ * Return: fail <0
+ ***********************************************************************/
+int fts_i2c_read_reg(struct i2c_client *client, u8 regaddr, u8 *regvalue)
+{
+ return fts_i2c_read(client, ®addr, 1, regvalue, 1);
+}
+
+/************************************************************************
+ * Name: fts_i2c_init
+ * Brief: fts i2c init
+ * Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+int fts_i2c_init(void)
+{
+ FTS_FUNC_ENTER();
+
+ FTS_FUNC_EXIT();
+ return 0;
+}
+/************************************************************************
+ * Name: fts_i2c_exit
+ * Brief: fts i2c exit
+ * Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+int fts_i2c_exit(void)
+{
+ FTS_FUNC_ENTER();
+
+ FTS_FUNC_EXIT();
+ return 0;
+}
+
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_point_report_check.c b/drivers/input/touchscreen/focaltech_touch/focaltech_point_report_check.c
new file mode 100644
index 0000000..eca1c2b
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_point_report_check.c
@@ -0,0 +1,155 @@
+/*
+ *
+ * FocalTech TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, FocalTech Systems, Ltd., all rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/*****************************************************************************
+ *
+ * File Name: focaltech_point_report_check.c
+ *
+ * Author: WangTao
+ *
+ * Created: 2016-11-16
+ *
+ * Abstract: point report check function
+ *
+ * Version: v1.0
+ *
+ * Revision History:
+ * v1.0:
+ * First release. By WangTao 2016-11-16
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Included header files
+ *****************************************************************************/
+#include "focaltech_core.h"
+
+#if FTS_POINT_REPORT_CHECK_EN
+/*****************************************************************************
+ * Private constant and macro definitions using #define
+ *****************************************************************************/
+#define POINT_REPORT_CHECK_WAIT_TIME 200 /* ms */
+
+/*****************************************************************************
+ * Private enumerations, structures and unions using typedef
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Static variables
+ *****************************************************************************/
+static struct delayed_work fts_point_report_check_work;
+static struct workqueue_struct *fts_point_report_check_workqueue;
+
+/*****************************************************************************
+ * Global variable or extern global variabls/functions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Static function prototypes
+ *****************************************************************************/
+
+/*****************************************************************************
+ * functions body
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ * Name: fts_point_report_check_func
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static void fts_point_report_check_func(struct work_struct *work)
+{
+
+#if FTS_MT_PROTOCOL_B_EN
+ unsigned int finger_count = 0;
+#endif
+
+ FTS_FUNC_ENTER();
+ mutex_lock(&fts_wq_data->report_mutex);
+
+#if FTS_MT_PROTOCOL_B_EN
+ for (finger_count = 0;
+ finger_count < fts_wq_data->pdata->max_touch_number;
+ finger_count++) {
+ input_mt_slot(fts_input_dev, finger_count);
+ input_mt_report_slot_state(fts_input_dev,
+ MT_TOOL_FINGER, false);
+ }
+#else
+ input_mt_sync(fts_input_dev);
+#endif
+ input_report_key(fts_input_dev, BTN_TOUCH, 0);
+ input_sync(fts_input_dev);
+
+ mutex_unlock(&fts_wq_data->report_mutex);
+
+ FTS_FUNC_EXIT();
+}
+
+void fts_point_report_check_queue_work(void)
+{
+ cancel_delayed_work(&fts_point_report_check_work);
+ queue_delayed_work(fts_point_report_check_workqueue,
+ &fts_point_report_check_work,
+ msecs_to_jiffies(POINT_REPORT_CHECK_WAIT_TIME));
+}
+
+/*****************************************************************************
+ * Name: fts_point_report_check_init
+ * Brief:
+ * Input:
+ * Output:
+ * Return: < 0: Fail to create esd check queue
+ *****************************************************************************/
+int fts_point_report_check_init(void)
+{
+ FTS_FUNC_ENTER();
+
+ INIT_DELAYED_WORK(&fts_point_report_check_work,
+ fts_point_report_check_func);
+ fts_point_report_check_workqueue =
+ create_workqueue("fts_point_report_check_func_wq");
+ if (fts_point_report_check_workqueue == NULL)
+ FTS_ERROR("[POINT_REPORT]: Failed to create workqueue!!");
+ else
+ FTS_DEBUG("[POINT_REPORT]: Success to create workqueue!!");
+
+ FTS_FUNC_EXIT();
+
+ return 0;
+}
+
+/*****************************************************************************
+ * Name: fts_point_report_check_exit
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+int fts_point_report_check_exit(void)
+{
+ FTS_FUNC_ENTER();
+
+ destroy_workqueue(fts_point_report_check_workqueue);
+
+ FTS_FUNC_EXIT();
+ return 0;
+}
+#endif /* FTS_POINT_REPORT_CHECK_EN */
+
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_sensor.c b/drivers/input/touchscreen/focaltech_touch/focaltech_sensor.c
new file mode 100644
index 0000000..e8e86b5
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_sensor.c
@@ -0,0 +1,326 @@
+/*
+ *
+ * FocalTech TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, FocalTech Systems, Ltd., all rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/*****************************************************************************
+ *
+ * File Name: focaltech_esdcheck.c
+ *
+ * Author: Focaltech Driver Team
+ *
+ * Created: 2016-08-03
+ *
+ * Abstract: Sensor
+ *
+ * Version: v1.0
+ *
+ * Revision History:
+ * v1.0:
+ * First release. By luougojin 2016-08-03
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Included header files
+ *****************************************************************************/
+#include "focaltech_core.h"
+
+#if FTS_PSENSOR_EN
+/*****************************************************************************
+ * Private constant and macro definitions using #define
+ *****************************************************************************/
+/* psensor register address*/
+#define FTS_REG_PSENSOR_ENABLE 0xB0
+#define FTS_REG_PSENSOR_STATUS 0x01
+
+/* psensor register bits*/
+#define FTS_PSENSOR_ENABLE_MASK 0x01
+#define FTS_PSENSOR_STATUS_NEAR 0xC0
+#define FTS_PSENSOR_STATUS_FAR 0xE0
+#define FTS_PSENSOR_FAR_TO_NEAR 0
+#define FTS_PSENSOR_NEAR_TO_FAR 1
+#define FTS_PSENSOR_ORIGINAL_STATE_FAR 1
+#define FTS_PSENSOR_WAKEUP_TIMEOUT 500
+
+/*****************************************************************************
+ * Static variables
+ *****************************************************************************/
+static struct sensors_classdev __maybe_unused sensors_proximity_cdev = {
+
+ .name = "fts-proximity",
+ .vendor = "FocalTech",
+ .version = 1,
+ .handle = SENSORS_PROXIMITY_HANDLE,
+ .type = SENSOR_TYPE_PROXIMITY,
+ .max_range = "5.0",
+ .resolution = "5.0",
+ .sensor_power = "0.1",
+ .min_delay = 0,
+ .fifo_reserved_event_count = 0,
+ .fifo_max_event_count = 0,
+ .enabled = 0,
+ .delay_msec = 200,
+ .sensors_enable = NULL,
+ .sensors_poll_delay = NULL,
+};
+
+/*****************************************************************************
+ * functions body
+ *****************************************************************************/
+/*****************************************************************************
+ * Name: fts_psensor_support_enabled
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static inline bool fts_psensor_support_enabled(void)
+{
+ /*return config_enabled(CONFIG_TOUCHSCREEN_FTS_PSENSOR);*/
+ return FTS_PSENSOR_EN;
+}
+
+/*****************************************************************************
+ * Name: fts_psensor_enable
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static void fts_psensor_enable(struct fts_ts_data *data, int enable)
+{
+ u8 state;
+ int ret = -1;
+
+ if (data->client == NULL)
+ return;
+
+ fts_i2c_read_reg(data->client, FTS_REG_PSENSOR_ENABLE, &state);
+ if (enable)
+ state |= FTS_PSENSOR_ENABLE_MASK;
+ else
+ state &= ~FTS_PSENSOR_ENABLE_MASK;
+
+ ret = fts_i2c_write_reg(data->client, FTS_REG_PSENSOR_ENABLE, state);
+ if (ret < 0)
+ FTS_ERROR("write psensor switch command failed");
+
+}
+
+/*****************************************************************************
+ * Name: fts_psensor_enable_set
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static int fts_psensor_enable_set(struct sensors_classdev *sensors_cdev,
+ unsigned int enable)
+{
+ struct fts_psensor_platform_data *psensor_pdata =
+ container_of(sensors_cdev,
+ struct fts_psensor_platform_data, ps_cdev);
+ struct fts_ts_data *data = psensor_pdata->data;
+ struct input_dev *input_dev = data->psensor_pdata->input_psensor_dev;
+
+ mutex_lock(&input_dev->mutex);
+ fts_psensor_enable(data, enable);
+ psensor_pdata->tp_psensor_data = FTS_PSENSOR_ORIGINAL_STATE_FAR;
+ if (enable)
+ psensor_pdata->tp_psensor_opened = 1;
+ else
+ psensor_pdata->tp_psensor_opened = 0;
+
+ mutex_unlock(&input_dev->mutex);
+
+ return enable;
+}
+
+/*****************************************************************************
+ * Name: fts_read_tp_psensor_data
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static int fts_read_tp_psensor_data(struct fts_ts_data *data)
+{
+ u8 psensor_status;
+ char tmp;
+ int ret = 1;
+
+ fts_i2c_read_reg(data->client,
+ FTS_REG_PSENSOR_STATUS, &psensor_status);
+
+ tmp = data->psensor_pdata->tp_psensor_data;
+ if (psensor_status == FTS_PSENSOR_STATUS_NEAR)
+ data->psensor_pdata->tp_psensor_data =
+ FTS_PSENSOR_FAR_TO_NEAR;
+ else if (psensor_status == FTS_PSENSOR_STATUS_FAR)
+ data->psensor_pdata->tp_psensor_data =
+ FTS_PSENSOR_NEAR_TO_FAR;
+
+ if (tmp != data->psensor_pdata->tp_psensor_data) {
+ FTS_ERROR("%s sensor data changed", __func__);
+ ret = 0;
+ }
+
+ return ret;
+}
+
+
+int fts_sensor_read_data(struct fts_ts_data *data)
+{
+ int ret = 0;
+
+ if (fts_psensor_support_enabled()
+ && data->psensor_pdata->tp_psensor_opened) {
+ ret = fts_read_tp_psensor_data(data);
+ if (!ret) {
+ if (data->suspended)
+ pm_wakeup_event(&data->client->dev,
+ FTS_PSENSOR_WAKEUP_TIMEOUT);
+
+ input_report_abs(data->psensor_pdata->input_psensor_dev,
+ ABS_DISTANCE,
+ data->psensor_pdata->tp_psensor_data);
+ input_sync(data->psensor_pdata->input_psensor_dev);
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
+int fts_sensor_suspend(struct fts_ts_data *data)
+{
+ int ret = 0;
+
+ if (fts_psensor_support_enabled() &&
+ device_may_wakeup(&data->client->dev) &&
+ data->psensor_pdata->tp_psensor_opened) {
+ ret = enable_irq_wake(data->client->irq);
+ if (ret != 0)
+ FTS_ERROR("%s: set_irq_wake failed", __func__);
+
+ data->suspended = true;
+ return 1;
+ }
+
+ return 0;
+}
+
+
+int fts_sensor_resume(struct fts_ts_data *data)
+{
+ int ret = 0;
+
+ if (fts_psensor_support_enabled()
+ && device_may_wakeup(&data->client->dev)
+ && data->psensor_pdata->tp_psensor_opened) {
+ ret = disable_irq_wake(data->client->irq);
+ if (ret)
+ FTS_ERROR("%s: disable_irq_wake failed", __func__);
+
+ data->suspended = false;
+ return 1;
+ }
+
+ return 0;
+}
+
+
+int fts_sensor_init(struct fts_ts_data *data)
+{
+ struct fts_psensor_platform_data *psensor_pdata;
+ struct input_dev *psensor_input_dev;
+ int err;
+
+ if (fts_psensor_support_enabled()) {
+ device_init_wakeup(&data->client->dev, 1);
+ psensor_pdata = devm_kzalloc(&data->client->dev,
+ sizeof(struct fts_psensor_platform_data),
+ GFP_KERNEL);
+ if (!psensor_pdata) {
+ FTS_ERROR("Failed to allocate memory");
+ goto irq_free;
+ }
+
+ data->psensor_pdata = psensor_pdata;
+
+ psensor_input_dev = input_allocate_device();
+ if (!psensor_input_dev) {
+ FTS_ERROR("Failed to allocate device");
+ goto free_psensor_pdata;
+ }
+
+ __set_bit(EV_ABS, psensor_input_dev->evbit);
+ input_set_abs_params(psensor_input_dev, ABS_DISTANCE,
+ 0, 1, 0, 0);
+ psensor_input_dev->name = "proximity";
+ psensor_input_dev->id.bustype = BUS_I2C;
+ psensor_input_dev->dev.parent = &data->client->dev;
+ data->psensor_pdata->input_psensor_dev = psensor_input_dev;
+
+ err = input_register_device(psensor_input_dev);
+ if (err) {
+ FTS_ERROR("Unable to register device, err=%d", err);
+ goto free_psensor_input_dev;
+ }
+
+ psensor_pdata->ps_cdev = sensors_proximity_cdev;
+ psensor_pdata->ps_cdev.sensors_enable = fts_psensor_enable_set;
+ psensor_pdata->data = data;
+
+ err = sensors_classdev_register(&data->client->dev,
+ &psensor_pdata->ps_cdev);
+ if (err)
+ goto unregister_psensor_input_device;
+ }
+
+ return 0;
+
+unregister_psensor_input_device:
+ if (fts_psensor_support_enabled())
+ input_unregister_device(data->psensor_pdata->input_psensor_dev);
+free_psensor_input_dev:
+ if (fts_psensor_support_enabled())
+ input_free_device(data->psensor_pdata->input_psensor_dev);
+free_psensor_pdata:
+ if (fts_psensor_support_enabled()) {
+ devm_kfree(&data->client->dev, psensor_pdata);
+ data->psensor_pdata = NULL;
+ }
+irq_free:
+ if (fts_psensor_support_enabled())
+ device_init_wakeup(&data->client->dev, 0);
+ free_irq(data->client->irq, data);
+
+ return 1;
+}
+
+int fts_sensor_remove(struct fts_ts_data *data)
+{
+ if (fts_psensor_support_enabled()) {
+ device_init_wakeup(&data->client->dev, 0);
+ sensors_classdev_unregister(&data->psensor_pdata->ps_cdev);
+ input_unregister_device(data->psensor_pdata->input_psensor_dev);
+ devm_kfree(&data->client->dev, data->psensor_pdata);
+ data->psensor_pdata = NULL;
+ }
+ return 0;
+}
+#endif /* FTS_PSENSOR_EN */
diff --git a/drivers/media/platform/msm/camera/cam_core/cam_context.c b/drivers/media/platform/msm/camera/cam_core/cam_context.c
index 98fff48..8beffc4 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_context.c
+++ b/drivers/media/platform/msm/camera/cam_core/cam_context.c
@@ -40,6 +40,7 @@
int cam_context_shutdown(struct cam_context *ctx)
{
int rc = 0;
+ int32_t ctx_hdl = ctx->dev_hdl;
if (ctx->state_machine[ctx->state].ioctl_ops.stop_dev) {
rc = ctx->state_machine[ctx->state].ioctl_ops.stop_dev(
@@ -54,6 +55,8 @@
CAM_ERR(CAM_CORE, "Error while dev release %d", rc);
}
+ if (!rc)
+ cam_destroy_device_hdl(ctx_hdl);
return rc;
}
diff --git a/drivers/media/platform/msm/camera/cam_core/cam_node.c b/drivers/media/platform/msm/camera/cam_core/cam_node.c
index 4e9034e..a943680 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_node.c
+++ b/drivers/media/platform/msm/camera/cam_core/cam_node.c
@@ -381,7 +381,6 @@
for (i = 0; i < node->ctx_size; i++) {
if (node->ctx_list[i].dev_hdl >= 0) {
cam_context_shutdown(&(node->ctx_list[i]));
- cam_destroy_device_hdl(node->ctx_list[i].dev_hdl);
cam_context_putref(&(node->ctx_list[i]));
}
}
diff --git a/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.c
index 9b703c0..74f349a 100644
--- a/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.c
+++ b/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.c
@@ -492,8 +492,9 @@
}
}
- if ((soc_private && soc_private->soc_id == SDM670_SOC_ID) &&
- (soc_private->hw_rev == SDM670_V1_1)) {
+ if ((soc_private && ((soc_private->soc_id == SDM710_SOC_ID) ||
+ ((soc_private->soc_id == SDM670_SOC_ID) &&
+ (soc_private->hw_rev == SDM670_V1_1))))) {
struct cam_cpas_reg *reg_info;
int tcsr_index;
@@ -551,8 +552,9 @@
}
}
- if ((soc_private && soc_private->soc_id == SDM670_SOC_ID) &&
- (soc_private->hw_rev == SDM670_V1_1)) {
+ if ((soc_private && ((soc_private->soc_id == SDM710_SOC_ID)
+ || ((soc_private->soc_id == SDM670_SOC_ID) &&
+ (soc_private->hw_rev == SDM670_V1_1))))) {
struct cam_cpas_reg *reg_info;
int tcsr_index;
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 bd5c9d0..c6c9b85 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
@@ -245,6 +245,38 @@
return 0;
}
+static bool cam_icp_frame_pending(struct cam_icp_hw_ctx_data *ctx_data)
+{
+ return !bitmap_empty(ctx_data->hfi_frame_process.bitmap,
+ CAM_FRAME_CMD_MAX);
+}
+
+static int cam_icp_ctx_timer_reset(struct cam_icp_hw_ctx_data *ctx_data)
+{
+ if (ctx_data && ctx_data->watch_dog) {
+ ctx_data->watch_dog_reset_counter++;
+ CAM_DBG(CAM_ICP, "reset timer : ctx_id = %d, counter=%d",
+ ctx_data->ctx_id, ctx_data->watch_dog_reset_counter);
+ crm_timer_reset(ctx_data->watch_dog);
+ }
+
+ return 0;
+}
+
+static void cam_icp_device_timer_reset(struct cam_icp_hw_mgr *hw_mgr,
+ int device_index)
+{
+ if ((device_index >= ICP_CLK_HW_MAX) || (!hw_mgr))
+ return;
+
+ if (hw_mgr->clk_info[device_index].watch_dog) {
+ CAM_DBG(CAM_ICP, "reset timer : device_index = %d",
+ device_index);
+ crm_timer_reset(hw_mgr->clk_info[device_index].watch_dog);
+ hw_mgr->clk_info[device_index].watch_dog_reset_counter++;
+ }
+}
+
static int32_t cam_icp_deinit_idle_clk(void *priv, void *data)
{
struct cam_icp_hw_mgr *hw_mgr = (struct cam_icp_hw_mgr *)priv;
@@ -259,6 +291,8 @@
struct cam_hw_intf *bps_dev_intf = NULL;
struct cam_hw_intf *dev_intf = NULL;
struct cam_a5_clk_update_cmd clk_upd_cmd;
+ int rc = 0;
+ bool busy = false;
ipe0_dev_intf = hw_mgr->ipe0_dev_intf;
ipe1_dev_intf = hw_mgr->ipe1_dev_intf;
@@ -268,19 +302,34 @@
clk_info->curr_clk = 0;
clk_info->over_clked = 0;
+ mutex_lock(&hw_mgr->hw_mgr_mutex);
+
for (i = 0; i < CAM_ICP_CTX_MAX; i++) {
ctx_data = &hw_mgr->ctx_data[i];
mutex_lock(&ctx_data->ctx_mutex);
if ((ctx_data->state == CAM_ICP_CTX_STATE_ACQUIRED) &&
(ICP_DEV_TYPE_TO_CLK_TYPE(ctx_data->
- icp_dev_acquire_info->dev_type) == clk_info->hw_type))
+ icp_dev_acquire_info->dev_type) == clk_info->hw_type)) {
+ busy = cam_icp_frame_pending(ctx_data);
+ if (busy) {
+ mutex_unlock(&ctx_data->ctx_mutex);
+ break;
+ }
cam_icp_ctx_clk_info_init(ctx_data);
+ }
mutex_unlock(&ctx_data->ctx_mutex);
}
+ if (busy) {
+ cam_icp_device_timer_reset(hw_mgr, clk_info->hw_type);
+ rc = -EBUSY;
+ goto done;
+ }
+
if ((!ipe0_dev_intf) || (!bps_dev_intf)) {
CAM_ERR(CAM_ICP, "dev intfs are wrong, failed to update clk");
- return -EINVAL;
+ rc = -EINVAL;
+ goto done;
}
if (clk_info->hw_type == ICP_CLK_HW_BPS) {
@@ -291,7 +340,7 @@
id = CAM_ICP_IPE_CMD_DISABLE_CLK;
} else {
CAM_ERR(CAM_ICP, "Error");
- return 0;
+ goto done;
}
CAM_DBG(CAM_ICP, "Disable %d", clk_info->hw_type);
@@ -308,7 +357,9 @@
&clk_upd_cmd,
sizeof(struct cam_a5_clk_update_cmd));
- return 0;
+done:
+ mutex_unlock(&hw_mgr->hw_mgr_mutex);
+ return rc;
}
static int32_t cam_icp_ctx_timer(void *priv, void *data)
@@ -339,6 +390,12 @@
return 0;
}
+ if (cam_icp_frame_pending(ctx_data)) {
+ cam_icp_ctx_timer_reset(ctx_data);
+ mutex_unlock(&ctx_data->ctx_mutex);
+ return -EBUSY;
+ }
+
CAM_DBG(CAM_ICP,
"E :ctx_id = %d ubw = %lld cbw = %lld curr_fc = %u bc = %u",
ctx_data->ctx_id,
@@ -533,30 +590,6 @@
}
}
-static int cam_icp_ctx_timer_reset(struct cam_icp_hw_ctx_data *ctx_data)
-{
- if (ctx_data && ctx_data->watch_dog) {
- ctx_data->watch_dog_reset_counter++;
- CAM_DBG(CAM_ICP, "reset timer : ctx_id = %d, counter=%d",
- ctx_data->ctx_id, ctx_data->watch_dog_reset_counter);
- crm_timer_reset(ctx_data->watch_dog);
- }
-
- return 0;
-}
-
-static void cam_icp_device_timer_reset(struct cam_icp_hw_mgr *hw_mgr,
- int device_index)
-{
- if ((device_index >= ICP_CLK_HW_MAX) || (!hw_mgr))
- return;
-
- if (hw_mgr->clk_info[device_index].watch_dog) {
- crm_timer_reset(hw_mgr->clk_info[device_index].watch_dog);
- hw_mgr->clk_info[device_index].watch_dog_reset_counter++;
- }
-}
-
static uint32_t cam_icp_mgr_calc_base_clk(uint32_t frame_cycles,
uint64_t budget)
{
@@ -1398,10 +1431,6 @@
CAM_DBG(CAM_ICP, "ctx : %pK, request_id :%lld",
(void *)ctx_data->context_priv, request_id);
- clk_type = ICP_DEV_TYPE_TO_CLK_TYPE(ctx_data->icp_dev_acquire_info->
- dev_type);
- cam_icp_device_timer_reset(&icp_hw_mgr, clk_type);
-
mutex_lock(&ctx_data->ctx_mutex);
cam_icp_ctx_timer_reset(ctx_data);
if (ctx_data->state != CAM_ICP_CTX_STATE_ACQUIRED) {
@@ -1411,6 +1440,10 @@
return 0;
}
+ clk_type = ICP_DEV_TYPE_TO_CLK_TYPE(
+ ctx_data->icp_dev_acquire_info->dev_type);
+ cam_icp_device_timer_reset(&icp_hw_mgr, clk_type);
+
hfi_frame_process = &ctx_data->hfi_frame_process;
for (i = 0; i < CAM_FRAME_CMD_MAX; i++)
if (hfi_frame_process->request_id[i] == request_id)
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h b/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h
index 1f2d46d..18fad8d 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h
@@ -42,6 +42,7 @@
/* soc id */
#define SDM670_SOC_ID 336
+#define SDM710_SOC_ID 360
/* Minor Version */
#define SDM670_V1_1 0x1
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
index 269d563..7a8e621 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
@@ -1048,15 +1048,18 @@
fe_cfg->stream_id);
vfe_dev->fetch_engine_info.bufq_handle = bufq_handle;
+ mutex_lock(&vfe_dev->buf_mgr->lock);
rc = vfe_dev->buf_mgr->ops->get_buf_by_index(
vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf);
if (rc < 0 || !buf) {
pr_err("%s: No fetch buffer rc= %d buf= %pK\n",
__func__, rc, buf);
+ mutex_unlock(&vfe_dev->buf_mgr->lock);
return -EINVAL;
}
mapped_info = buf->mapped_info[0];
buf->state = MSM_ISP_BUFFER_STATE_DISPATCHED;
+ mutex_unlock(&vfe_dev->buf_mgr->lock);
} else {
rc = vfe_dev->buf_mgr->ops->map_buf(vfe_dev->buf_mgr,
&mapped_info, fe_cfg->fd);
@@ -1109,14 +1112,15 @@
mutex_lock(&vfe_dev->buf_mgr->lock);
rc = vfe_dev->buf_mgr->ops->get_buf_by_index(
vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf);
- mutex_unlock(&vfe_dev->buf_mgr->lock);
if (rc < 0 || !buf) {
pr_err("%s: No fetch buffer rc= %d buf= %pK\n",
__func__, rc, buf);
+ mutex_unlock(&vfe_dev->buf_mgr->lock);
return -EINVAL;
}
mapped_info = buf->mapped_info[0];
buf->state = MSM_ISP_BUFFER_STATE_DISPATCHED;
+ mutex_unlock(&vfe_dev->buf_mgr->lock);
} else {
rc = vfe_dev->buf_mgr->ops->map_buf(vfe_dev->buf_mgr,
&mapped_info, fe_cfg->fd);
@@ -1214,6 +1218,10 @@
case V4L2_PIX_FMT_P16GBRG10:
case V4L2_PIX_FMT_P16GRBG10:
case V4L2_PIX_FMT_P16RGGB10:
+ case V4L2_PIX_FMT_P16BGGR12:
+ case V4L2_PIX_FMT_P16GBRG12:
+ case V4L2_PIX_FMT_P16GRBG12:
+ case V4L2_PIX_FMT_P16RGGB12:
main_unpack_pattern = 0xB210;
break;
default:
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c
index a9ff454..8bd50d5 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c
@@ -895,13 +895,14 @@
mutex_lock(&vfe_dev->buf_mgr->lock);
rc = vfe_dev->buf_mgr->ops->get_buf_by_index(
vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf);
- mutex_unlock(&vfe_dev->buf_mgr->lock);
if (rc < 0) {
pr_err("%s: No fetch buffer\n", __func__);
+ mutex_unlock(&vfe_dev->buf_mgr->lock);
return -EINVAL;
}
mapped_info = buf->mapped_info[0];
buf->state = MSM_ISP_BUFFER_STATE_DISPATCHED;
+ mutex_unlock(&vfe_dev->buf_mgr->lock);
} else {
rc = vfe_dev->buf_mgr->ops->map_buf(vfe_dev->buf_mgr,
&mapped_info, fe_cfg->fd);
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c
index 0239fe7..e0712f7 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c
@@ -833,14 +833,15 @@
mutex_lock(&vfe_dev->buf_mgr->lock);
rc = vfe_dev->buf_mgr->ops->get_buf_by_index(
vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf);
- mutex_unlock(&vfe_dev->buf_mgr->lock);
if (rc < 0 || !buf) {
pr_err("%s: No fetch buffer rc= %d buf= %pK\n",
__func__, rc, buf);
+ mutex_unlock(&vfe_dev->buf_mgr->lock);
return -EINVAL;
}
mapped_info = buf->mapped_info[0];
buf->state = MSM_ISP_BUFFER_STATE_DISPATCHED;
+ mutex_unlock(&vfe_dev->buf_mgr->lock);
} else {
rc = vfe_dev->buf_mgr->ops->map_buf(vfe_dev->buf_mgr,
&mapped_info, fe_cfg->fd);
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c
index 410689f..b867eb3 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c
@@ -1102,15 +1102,18 @@
fe_cfg->stream_id);
vfe_dev->fetch_engine_info.bufq_handle = bufq_handle;
+ mutex_lock(&vfe_dev->buf_mgr->lock);
rc = vfe_dev->buf_mgr->ops->get_buf_by_index(
vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf);
if (rc < 0 || !buf) {
pr_err("%s: No fetch buffer rc= %d buf= %pK\n",
__func__, rc, buf);
+ mutex_unlock(&vfe_dev->buf_mgr->lock);
return -EINVAL;
}
mapped_info = buf->mapped_info[0];
buf->state = MSM_ISP_BUFFER_STATE_DISPATCHED;
+ mutex_unlock(&vfe_dev->buf_mgr->lock);
} else {
rc = vfe_dev->buf_mgr->ops->map_buf(vfe_dev->buf_mgr,
&mapped_info, fe_cfg->fd);
@@ -1163,14 +1166,15 @@
mutex_lock(&vfe_dev->buf_mgr->lock);
rc = vfe_dev->buf_mgr->ops->get_buf_by_index(
vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf);
- mutex_unlock(&vfe_dev->buf_mgr->lock);
if (rc < 0 || !buf) {
pr_err("%s: No fetch buffer rc= %d buf= %pK\n",
__func__, rc, buf);
+ mutex_unlock(&vfe_dev->buf_mgr->lock);
return -EINVAL;
}
mapped_info = buf->mapped_info[0];
buf->state = MSM_ISP_BUFFER_STATE_DISPATCHED;
+ mutex_unlock(&vfe_dev->buf_mgr->lock);
} else {
rc = vfe_dev->buf_mgr->ops->map_buf(vfe_dev->buf_mgr,
&mapped_info, fe_cfg->fd);
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 5b1a804..73a5ebc 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
@@ -235,6 +235,10 @@
case V4L2_PIX_FMT_P16GBRG10:
case V4L2_PIX_FMT_P16GRBG10:
case V4L2_PIX_FMT_P16RGGB10:
+ case V4L2_PIX_FMT_P16BGGR12:
+ case V4L2_PIX_FMT_P16GBRG12:
+ case V4L2_PIX_FMT_P16GRBG12:
+ case V4L2_PIX_FMT_P16RGGB12:
case V4L2_PIX_FMT_JPEG:
case V4L2_PIX_FMT_META:
case V4L2_PIX_FMT_META10:
@@ -376,6 +380,10 @@
case V4L2_PIX_FMT_P16GBRG10:
case V4L2_PIX_FMT_P16GRBG10:
case V4L2_PIX_FMT_P16RGGB10:
+ case V4L2_PIX_FMT_P16BGGR12:
+ case V4L2_PIX_FMT_P16GBRG12:
+ case V4L2_PIX_FMT_P16GRBG12:
+ case V4L2_PIX_FMT_P16RGGB12:
size = plane_cfg[plane_idx].output_height *
plane_cfg[plane_idx].output_width;
break;
@@ -4032,10 +4040,12 @@
pr_err("%s: stream_info is null", __func__);
return -EINVAL;
}
+ mutex_lock(&vfe_dev->buf_mgr->lock);
rc = msm_isp_request_frame(vfe_dev, stream_info,
update_info->user_stream_id,
update_info->frame_id,
MSM_ISP_INVALID_BUF_INDEX);
+ mutex_unlock(&vfe_dev->buf_mgr->lock);
if (rc)
pr_err("%s failed to request frame!\n",
__func__);
@@ -4087,10 +4097,12 @@
pr_err("%s: stream_info is null", __func__);
return -EINVAL;
}
+ mutex_lock(&vfe_dev->buf_mgr->lock);
rc = msm_isp_request_frame(vfe_dev, stream_info,
req_frm->user_stream_id,
req_frm->frame_id,
req_frm->buf_index);
+ mutex_unlock(&vfe_dev->buf_mgr->lock);
if (rc)
pr_err("%s failed to request frame!\n",
__func__);
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 99dc054..d3a68b1 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
@@ -402,8 +402,10 @@
vfe_idx = msm_isp_get_vfe_idx_for_stream(vfe_dev, stream_info);
msm_isp_reset_framedrop(vfe_dev, stream_info);
+ mutex_lock(&vfe_dev->buf_mgr->lock);
rc = msm_isp_cfg_offline_ping_pong_address(vfe_dev, stream_info,
VFE_PING_FLAG, fe_cfg->output_buf_idx);
+ mutex_unlock(&vfe_dev->buf_mgr->lock);
if (rc < 0) {
pr_err("%s: Fetch engine config failed\n", __func__);
return -EINVAL;
@@ -894,7 +896,9 @@
case VIDIOC_MSM_ISP_CFG_STREAM:
mutex_lock(&vfe_dev->core_mutex);
MSM_ISP_DUAL_VFE_MUTEX_LOCK(vfe_dev);
+ mutex_lock(&vfe_dev->buf_mgr->lock);
rc = msm_isp_cfg_axi_stream(vfe_dev, arg);
+ mutex_unlock(&vfe_dev->buf_mgr->lock);
MSM_ISP_DUAL_VFE_MUTEX_UNLOCK(vfe_dev);
mutex_unlock(&vfe_dev->core_mutex);
break;
@@ -924,6 +928,7 @@
case VIDIOC_MSM_ISP_AXI_RESTART:
mutex_lock(&vfe_dev->core_mutex);
MSM_ISP_DUAL_VFE_MUTEX_LOCK(vfe_dev);
+ mutex_lock(&vfe_dev->buf_mgr->lock);
if (atomic_read(&vfe_dev->error_info.overflow_state)
!= HALT_ENFORCED) {
rc = msm_isp_stats_restart(vfe_dev);
@@ -934,6 +939,7 @@
pr_err_ratelimited("%s: no AXI restart, halt enforced.\n",
__func__);
}
+ mutex_unlock(&vfe_dev->buf_mgr->lock);
MSM_ISP_DUAL_VFE_MUTEX_UNLOCK(vfe_dev);
mutex_unlock(&vfe_dev->core_mutex);
break;
@@ -1009,7 +1015,9 @@
case VIDIOC_MSM_ISP_CFG_STATS_STREAM:
mutex_lock(&vfe_dev->core_mutex);
MSM_ISP_DUAL_VFE_MUTEX_LOCK(vfe_dev);
+ mutex_lock(&vfe_dev->buf_mgr->lock);
rc = msm_isp_cfg_stats_stream(vfe_dev, arg);
+ mutex_unlock(&vfe_dev->buf_mgr->lock);
MSM_ISP_DUAL_VFE_MUTEX_UNLOCK(vfe_dev);
mutex_unlock(&vfe_dev->core_mutex);
break;
@@ -1623,6 +1631,10 @@
case V4L2_PIX_FMT_P16GBRG10:
case V4L2_PIX_FMT_P16GRBG10:
case V4L2_PIX_FMT_P16RGGB10:
+ case V4L2_PIX_FMT_P16BGGR12:
+ case V4L2_PIX_FMT_P16GBRG12:
+ case V4L2_PIX_FMT_P16GRBG12:
+ case V4L2_PIX_FMT_P16RGGB12:
val = CAL_WORD(pixel_per_line, 1, 4);
break;
case V4L2_PIX_FMT_NV24:
@@ -1686,6 +1698,10 @@
case V4L2_PIX_FMT_P16GBRG10:
case V4L2_PIX_FMT_P16GRBG10:
case V4L2_PIX_FMT_P16RGGB10:
+ case V4L2_PIX_FMT_P16BGGR12:
+ case V4L2_PIX_FMT_P16GBRG12:
+ case V4L2_PIX_FMT_P16GRBG12:
+ case V4L2_PIX_FMT_P16RGGB12:
return PLAIN16;
default:
msm_isp_print_fourcc_error(__func__, output_format);
@@ -1770,6 +1786,10 @@
case V4L2_PIX_FMT_QGRBG12:
case V4L2_PIX_FMT_QRGGB12:
case V4L2_PIX_FMT_Y12:
+ case V4L2_PIX_FMT_P16BGGR12:
+ case V4L2_PIX_FMT_P16GBRG12:
+ case V4L2_PIX_FMT_P16GRBG12:
+ case V4L2_PIX_FMT_P16RGGB12:
return 12;
case V4L2_PIX_FMT_SBGGR14:
case V4L2_PIX_FMT_SGBRG14:
diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.c
index d044a50..9e99ba2 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.c
@@ -67,6 +67,8 @@
break;
}
}
+ if (j == num_vreg)
+ power_setting[i].seq_val = INVALID_VREG;
break;
case CAM_VIO:
@@ -86,6 +88,8 @@
break;
}
}
+ if (j == num_vreg)
+ power_setting[i].seq_val = INVALID_VREG;
break;
case CAM_VANA:
@@ -105,6 +109,8 @@
break;
}
}
+ if (j == num_vreg)
+ power_setting[i].seq_val = INVALID_VREG;
break;
case CAM_VAF:
@@ -124,6 +130,8 @@
break;
}
}
+ if (j == num_vreg)
+ power_setting[i].seq_val = INVALID_VREG;
break;
case CAM_V_CUSTOM1:
@@ -144,7 +152,9 @@
break;
}
}
-
+ if (j == num_vreg)
+ power_setting[i].seq_val = INVALID_VREG;
+ break;
case CAM_V_CUSTOM2:
for (j = 0; j < num_vreg; j++) {
if (!strcmp(cam_vreg[j].reg_name,
@@ -163,6 +173,8 @@
break;
}
}
+ if (j == num_vreg)
+ power_setting[i].seq_val = INVALID_VREG;
break;
default:
@@ -1489,6 +1501,9 @@
(int) power_setting->config_val);
break;
case SENSOR_VREG:
+ if (power_setting->seq_val == INVALID_VREG)
+ break;
+
if (power_setting->seq_val >= CAM_VREG_MAX) {
pr_err("%s vreg index %d >= max %d\n", __func__,
power_setting->seq_val,
diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c
index 3c5bc72..90be113 100644
--- a/drivers/net/wireless/cnss2/pci.c
+++ b/drivers/net/wireless/cnss2/pci.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
@@ -223,10 +223,13 @@
struct dma_iommu_mapping *mapping;
int atomic_ctx = 1;
int s1_bypass = 1;
+ int fast = 1;
+
+ cnss_pr_dbg("Initializing SMMU\n");
dev = &pci_priv->pci_dev->dev;
- mapping = arm_iommu_create_mapping(&platform_bus_type,
+ mapping = arm_iommu_create_mapping(dev->bus,
pci_priv->smmu_iova_start,
pci_priv->smmu_iova_len);
if (IS_ERR(mapping)) {
@@ -235,22 +238,35 @@
goto out;
}
- ret = iommu_domain_set_attr(mapping->domain,
- DOMAIN_ATTR_ATOMIC,
- &atomic_ctx);
- if (ret) {
- pr_err("Failed to set SMMU atomic_ctx attribute, err = %d\n",
- ret);
- goto release_mapping;
- }
+ if (pci_priv->smmu_s1_enable) {
+ cnss_pr_dbg("Enabling SMMU S1 stage\n");
- ret = iommu_domain_set_attr(mapping->domain,
- DOMAIN_ATTR_S1_BYPASS,
- &s1_bypass);
- if (ret) {
- pr_err("Failed to set SMMU s1_bypass attribute, err = %d\n",
- ret);
- goto release_mapping;
+ ret = iommu_domain_set_attr(mapping->domain,
+ DOMAIN_ATTR_ATOMIC,
+ &atomic_ctx);
+ if (ret) {
+ pr_err("Failed to set SMMU atomic_ctx attribute, err = %d\n",
+ ret);
+ goto release_mapping;
+ }
+
+ ret = iommu_domain_set_attr(mapping->domain,
+ DOMAIN_ATTR_FAST,
+ &fast);
+ if (ret) {
+ pr_err("Failed to set SMMU fast attribute, err = %d\n",
+ ret);
+ goto release_mapping;
+ }
+ } else {
+ ret = iommu_domain_set_attr(mapping->domain,
+ DOMAIN_ATTR_S1_BYPASS,
+ &s1_bypass);
+ if (ret) {
+ pr_err("Failed to set SMMU s1_bypass attribute, err = %d\n",
+ ret);
+ goto release_mapping;
+ }
}
ret = arm_iommu_attach_device(dev, mapping);
@@ -1443,6 +1459,10 @@
res = platform_get_resource_byname(plat_priv->plat_dev, IORESOURCE_MEM,
"smmu_iova_base");
if (res) {
+ if (of_property_read_bool(plat_priv->plat_dev->dev.of_node,
+ "qcom,smmu-s1-enable"))
+ pci_priv->smmu_s1_enable = true;
+
pci_priv->smmu_iova_start = res->start;
pci_priv->smmu_iova_len = resource_size(res);
cnss_pr_dbg("smmu_iova_start: %pa, smmu_iova_len: %zu\n",
diff --git a/drivers/net/wireless/cnss2/pci.h b/drivers/net/wireless/cnss2/pci.h
index 89edc60..4a82998 100644
--- a/drivers/net/wireless/cnss2/pci.h
+++ b/drivers/net/wireless/cnss2/pci.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
@@ -70,6 +70,7 @@
atomic_t auto_suspended;
bool monitor_wake_intr;
struct dma_iommu_mapping *smmu_mapping;
+ bool smmu_s1_enable;
dma_addr_t smmu_iova_start;
size_t smmu_iova_len;
void __iomem *bar;
diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig
index dab5db5..9413da3 100644
--- a/drivers/pinctrl/qcom/Kconfig
+++ b/drivers/pinctrl/qcom/Kconfig
@@ -73,6 +73,16 @@
platform.
Say Y here to enable pinctrl settings for MDM9650.
+config PINCTRL_MDM9607
+ tristate "QTI MDM9607 pin controller driver"
+ depends on GPIOLIB && OF
+ select PINCTRL_MSM
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver settings
+ for the QTI TLMM block which is found in the QTI 9607
+ platform.
+ Say Y here to enable pinctrl settings for MDM9607.
+
config PINCTRL_MSM8X74
tristate "Qualcomm 8x74 pin controller driver"
depends on GPIOLIB && OF
diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile
index 5389139..9b20604 100644
--- a/drivers/pinctrl/qcom/Makefile
+++ b/drivers/pinctrl/qcom/Makefile
@@ -23,3 +23,4 @@
obj-$(CONFIG_PINCTRL_SDM670) += pinctrl-sdm670.o
obj-$(CONFIG_PINCTRL_SDXPOORWILLS) += pinctrl-sdxpoorwills.o
obj-$(CONFIG_PINCTRL_MDM9650) += pinctrl-mdm9650.o
+obj-$(CONFIG_PINCTRL_MDM9607) += pinctrl-mdm9607.o
diff --git a/drivers/pinctrl/qcom/pinctrl-mdm9607.c b/drivers/pinctrl/qcom/pinctrl-mdm9607.c
new file mode 100644
index 0000000..59688ff
--- /dev/null
+++ b/drivers/pinctrl/qcom/pinctrl-mdm9607.c
@@ -0,0 +1,1128 @@
+/*
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-msm.h"
+
+#define FUNCTION(fname) \
+ [msm_mux_##fname] = { \
+ .name = #fname, \
+ .groups = fname##_groups, \
+ .ngroups = ARRAY_SIZE(fname##_groups), \
+ }
+
+#define REG_BASE 0x0
+#define REG_SIZE 0x1000
+#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
+ { \
+ .name = "gpio" #id, \
+ .pins = gpio##id##_pins, \
+ .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \
+ .funcs = (int[]){ \
+ msm_mux_gpio, /* gpio mode */ \
+ msm_mux_##f1, \
+ msm_mux_##f2, \
+ msm_mux_##f3, \
+ msm_mux_##f4, \
+ msm_mux_##f5, \
+ msm_mux_##f6, \
+ msm_mux_##f7, \
+ msm_mux_##f8, \
+ msm_mux_##f9 \
+ }, \
+ .nfuncs = 10, \
+ .ctl_reg = REG_BASE + REG_SIZE * id, \
+ .io_reg = REG_BASE + 0x4 + REG_SIZE * id, \
+ .intr_cfg_reg = REG_BASE + 0x8 + REG_SIZE * id, \
+ .intr_status_reg = REG_BASE + 0xc + REG_SIZE * id, \
+ .intr_target_reg = REG_BASE + 0x8 + REG_SIZE * id, \
+ .mux_bit = 2, \
+ .pull_bit = 0, \
+ .drv_bit = 6, \
+ .oe_bit = 9, \
+ .in_bit = 0, \
+ .out_bit = 1, \
+ .intr_enable_bit = 0, \
+ .intr_status_bit = 0, \
+ .intr_target_bit = 5, \
+ .intr_target_kpss_val = 4, \
+ .intr_raw_status_bit = 4, \
+ .intr_polarity_bit = 1, \
+ .intr_detection_bit = 2, \
+ .intr_detection_width = 2, \
+ }
+
+#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \
+ { \
+ .name = #pg_name, \
+ .pins = pg_name##_pins, \
+ .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \
+ .ctl_reg = ctl, \
+ .io_reg = 0, \
+ .intr_cfg_reg = 0, \
+ .intr_status_reg = 0, \
+ .intr_target_reg = 0, \
+ .mux_bit = -1, \
+ .pull_bit = pull, \
+ .drv_bit = drv, \
+ .oe_bit = -1, \
+ .in_bit = -1, \
+ .out_bit = -1, \
+ .intr_enable_bit = -1, \
+ .intr_status_bit = -1, \
+ .intr_target_bit = -1, \
+ .intr_raw_status_bit = -1, \
+ .intr_polarity_bit = -1, \
+ .intr_detection_bit = -1, \
+ .intr_detection_width = -1, \
+ }
+static const struct pinctrl_pin_desc mdm9607_pins[] = {
+ PINCTRL_PIN(0, "GPIO_0"),
+ PINCTRL_PIN(1, "GPIO_1"),
+ PINCTRL_PIN(2, "GPIO_2"),
+ PINCTRL_PIN(3, "GPIO_3"),
+ PINCTRL_PIN(4, "GPIO_4"),
+ PINCTRL_PIN(5, "GPIO_5"),
+ PINCTRL_PIN(6, "GPIO_6"),
+ PINCTRL_PIN(7, "GPIO_7"),
+ PINCTRL_PIN(8, "GPIO_8"),
+ PINCTRL_PIN(9, "GPIO_9"),
+ PINCTRL_PIN(10, "GPIO_10"),
+ PINCTRL_PIN(11, "GPIO_11"),
+ PINCTRL_PIN(12, "GPIO_12"),
+ PINCTRL_PIN(13, "GPIO_13"),
+ PINCTRL_PIN(14, "GPIO_14"),
+ PINCTRL_PIN(15, "GPIO_15"),
+ PINCTRL_PIN(16, "GPIO_16"),
+ PINCTRL_PIN(17, "GPIO_17"),
+ PINCTRL_PIN(18, "GPIO_18"),
+ PINCTRL_PIN(19, "GPIO_19"),
+ PINCTRL_PIN(20, "GPIO_20"),
+ PINCTRL_PIN(21, "GPIO_21"),
+ PINCTRL_PIN(22, "GPIO_22"),
+ PINCTRL_PIN(23, "GPIO_23"),
+ PINCTRL_PIN(24, "GPIO_24"),
+ PINCTRL_PIN(25, "GPIO_25"),
+ PINCTRL_PIN(26, "GPIO_26"),
+ PINCTRL_PIN(27, "GPIO_27"),
+ PINCTRL_PIN(28, "GPIO_28"),
+ PINCTRL_PIN(29, "GPIO_29"),
+ PINCTRL_PIN(30, "GPIO_30"),
+ PINCTRL_PIN(31, "GPIO_31"),
+ PINCTRL_PIN(32, "GPIO_32"),
+ PINCTRL_PIN(33, "GPIO_33"),
+ PINCTRL_PIN(34, "GPIO_34"),
+ PINCTRL_PIN(35, "GPIO_35"),
+ PINCTRL_PIN(36, "GPIO_36"),
+ PINCTRL_PIN(37, "GPIO_37"),
+ PINCTRL_PIN(38, "GPIO_38"),
+ PINCTRL_PIN(39, "GPIO_39"),
+ PINCTRL_PIN(40, "GPIO_40"),
+ PINCTRL_PIN(41, "GPIO_41"),
+ PINCTRL_PIN(42, "GPIO_42"),
+ PINCTRL_PIN(43, "GPIO_43"),
+ PINCTRL_PIN(44, "GPIO_44"),
+ PINCTRL_PIN(45, "GPIO_45"),
+ PINCTRL_PIN(46, "GPIO_46"),
+ PINCTRL_PIN(47, "GPIO_47"),
+ PINCTRL_PIN(48, "GPIO_48"),
+ PINCTRL_PIN(49, "GPIO_49"),
+ PINCTRL_PIN(50, "GPIO_50"),
+ PINCTRL_PIN(51, "GPIO_51"),
+ PINCTRL_PIN(52, "GPIO_52"),
+ PINCTRL_PIN(53, "GPIO_53"),
+ PINCTRL_PIN(54, "GPIO_54"),
+ PINCTRL_PIN(55, "GPIO_55"),
+ PINCTRL_PIN(56, "GPIO_56"),
+ PINCTRL_PIN(57, "GPIO_57"),
+ PINCTRL_PIN(58, "GPIO_58"),
+ PINCTRL_PIN(59, "GPIO_59"),
+ PINCTRL_PIN(60, "GPIO_60"),
+ PINCTRL_PIN(61, "GPIO_61"),
+ PINCTRL_PIN(62, "GPIO_62"),
+ PINCTRL_PIN(63, "GPIO_63"),
+ PINCTRL_PIN(64, "GPIO_64"),
+ PINCTRL_PIN(65, "GPIO_65"),
+ PINCTRL_PIN(66, "GPIO_66"),
+ PINCTRL_PIN(67, "GPIO_67"),
+ PINCTRL_PIN(68, "GPIO_68"),
+ PINCTRL_PIN(69, "GPIO_69"),
+ PINCTRL_PIN(70, "GPIO_70"),
+ PINCTRL_PIN(71, "GPIO_71"),
+ PINCTRL_PIN(72, "GPIO_72"),
+ PINCTRL_PIN(73, "GPIO_73"),
+ PINCTRL_PIN(74, "GPIO_74"),
+ PINCTRL_PIN(75, "GPIO_75"),
+ PINCTRL_PIN(76, "GPIO_76"),
+ PINCTRL_PIN(77, "GPIO_77"),
+ PINCTRL_PIN(78, "GPIO_78"),
+ PINCTRL_PIN(79, "GPIO_79"),
+ PINCTRL_PIN(80, "SDC1_CLK"),
+ PINCTRL_PIN(81, "SDC1_CMD"),
+ PINCTRL_PIN(82, "SDC1_DATA"),
+ PINCTRL_PIN(83, "SDC2_CLK"),
+ PINCTRL_PIN(84, "SDC2_CMD"),
+ PINCTRL_PIN(85, "SDC2_DATA"),
+ PINCTRL_PIN(86, "QDSD_CLK"),
+ PINCTRL_PIN(87, "QDSD_CMD"),
+ PINCTRL_PIN(88, "QDSD_DATA0"),
+ PINCTRL_PIN(89, "QDSD_DATA1"),
+ PINCTRL_PIN(90, "QDSD_DATA2"),
+ PINCTRL_PIN(91, "QDSD_DATA3"),
+};
+
+#define DECLARE_MSM_GPIO_PINS(pin) \
+ static const unsigned int gpio##pin##_pins[] = { pin }
+DECLARE_MSM_GPIO_PINS(0);
+DECLARE_MSM_GPIO_PINS(1);
+DECLARE_MSM_GPIO_PINS(2);
+DECLARE_MSM_GPIO_PINS(3);
+DECLARE_MSM_GPIO_PINS(4);
+DECLARE_MSM_GPIO_PINS(5);
+DECLARE_MSM_GPIO_PINS(6);
+DECLARE_MSM_GPIO_PINS(7);
+DECLARE_MSM_GPIO_PINS(8);
+DECLARE_MSM_GPIO_PINS(9);
+DECLARE_MSM_GPIO_PINS(10);
+DECLARE_MSM_GPIO_PINS(11);
+DECLARE_MSM_GPIO_PINS(12);
+DECLARE_MSM_GPIO_PINS(13);
+DECLARE_MSM_GPIO_PINS(14);
+DECLARE_MSM_GPIO_PINS(15);
+DECLARE_MSM_GPIO_PINS(16);
+DECLARE_MSM_GPIO_PINS(17);
+DECLARE_MSM_GPIO_PINS(18);
+DECLARE_MSM_GPIO_PINS(19);
+DECLARE_MSM_GPIO_PINS(20);
+DECLARE_MSM_GPIO_PINS(21);
+DECLARE_MSM_GPIO_PINS(22);
+DECLARE_MSM_GPIO_PINS(23);
+DECLARE_MSM_GPIO_PINS(24);
+DECLARE_MSM_GPIO_PINS(25);
+DECLARE_MSM_GPIO_PINS(26);
+DECLARE_MSM_GPIO_PINS(27);
+DECLARE_MSM_GPIO_PINS(28);
+DECLARE_MSM_GPIO_PINS(29);
+DECLARE_MSM_GPIO_PINS(30);
+DECLARE_MSM_GPIO_PINS(31);
+DECLARE_MSM_GPIO_PINS(32);
+DECLARE_MSM_GPIO_PINS(33);
+DECLARE_MSM_GPIO_PINS(34);
+DECLARE_MSM_GPIO_PINS(35);
+DECLARE_MSM_GPIO_PINS(36);
+DECLARE_MSM_GPIO_PINS(37);
+DECLARE_MSM_GPIO_PINS(38);
+DECLARE_MSM_GPIO_PINS(39);
+DECLARE_MSM_GPIO_PINS(40);
+DECLARE_MSM_GPIO_PINS(41);
+DECLARE_MSM_GPIO_PINS(42);
+DECLARE_MSM_GPIO_PINS(43);
+DECLARE_MSM_GPIO_PINS(44);
+DECLARE_MSM_GPIO_PINS(45);
+DECLARE_MSM_GPIO_PINS(46);
+DECLARE_MSM_GPIO_PINS(47);
+DECLARE_MSM_GPIO_PINS(48);
+DECLARE_MSM_GPIO_PINS(49);
+DECLARE_MSM_GPIO_PINS(50);
+DECLARE_MSM_GPIO_PINS(51);
+DECLARE_MSM_GPIO_PINS(52);
+DECLARE_MSM_GPIO_PINS(53);
+DECLARE_MSM_GPIO_PINS(54);
+DECLARE_MSM_GPIO_PINS(55);
+DECLARE_MSM_GPIO_PINS(56);
+DECLARE_MSM_GPIO_PINS(57);
+DECLARE_MSM_GPIO_PINS(58);
+DECLARE_MSM_GPIO_PINS(59);
+DECLARE_MSM_GPIO_PINS(60);
+DECLARE_MSM_GPIO_PINS(61);
+DECLARE_MSM_GPIO_PINS(62);
+DECLARE_MSM_GPIO_PINS(63);
+DECLARE_MSM_GPIO_PINS(64);
+DECLARE_MSM_GPIO_PINS(65);
+DECLARE_MSM_GPIO_PINS(66);
+DECLARE_MSM_GPIO_PINS(67);
+DECLARE_MSM_GPIO_PINS(68);
+DECLARE_MSM_GPIO_PINS(69);
+DECLARE_MSM_GPIO_PINS(70);
+DECLARE_MSM_GPIO_PINS(71);
+DECLARE_MSM_GPIO_PINS(72);
+DECLARE_MSM_GPIO_PINS(73);
+DECLARE_MSM_GPIO_PINS(74);
+DECLARE_MSM_GPIO_PINS(75);
+DECLARE_MSM_GPIO_PINS(76);
+DECLARE_MSM_GPIO_PINS(77);
+DECLARE_MSM_GPIO_PINS(78);
+DECLARE_MSM_GPIO_PINS(79);
+
+static const unsigned int sdc1_clk_pins[] = { 80 };
+static const unsigned int sdc1_cmd_pins[] = { 81 };
+static const unsigned int sdc1_data_pins[] = { 82 };
+static const unsigned int sdc2_clk_pins[] = { 83 };
+static const unsigned int sdc2_cmd_pins[] = { 84 };
+static const unsigned int sdc2_data_pins[] = { 85 };
+static const unsigned int qdsd_clk_pins[] = { 86 };
+static const unsigned int qdsd_cmd_pins[] = { 87 };
+static const unsigned int qdsd_data0_pins[] = { 88 };
+static const unsigned int qdsd_data1_pins[] = { 89 };
+static const unsigned int qdsd_data2_pins[] = { 90 };
+static const unsigned int qdsd_data3_pins[] = { 91 };
+
+enum mdm9607_functions {
+ msm_mux_blsp_spi3,
+ msm_mux_gpio,
+ msm_mux_blsp_uart3,
+ msm_mux_qdss_tracedata_a,
+ msm_mux_bimc_dte1,
+ msm_mux_blsp_i2c3,
+ msm_mux_qdss_traceclk_a,
+ msm_mux_bimc_dte0,
+ msm_mux_qdss_cti_trig_in_a1,
+ msm_mux_blsp_spi2,
+ msm_mux_blsp_uart2,
+ msm_mux_blsp_uim2,
+ msm_mux_blsp_i2c2,
+ msm_mux_qdss_tracectl_a,
+ msm_mux_sensor_int2,
+ msm_mux_blsp_spi5,
+ msm_mux_blsp_uart5,
+ msm_mux_ebi2_lcd,
+ msm_mux_m_voc,
+ msm_mux_sensor_int3,
+ msm_mux_sensor_en,
+ msm_mux_blsp_i2c5,
+ msm_mux_ebi2_a,
+ msm_mux_qdss_tracedata_b,
+ msm_mux_sensor_rst,
+ msm_mux_blsp2_spi,
+ msm_mux_blsp_spi1,
+ msm_mux_blsp_uart1,
+ msm_mux_blsp_uim1,
+ msm_mux_blsp3_spi,
+ msm_mux_gcc_gp2_clk_b,
+ msm_mux_gcc_gp3_clk_b,
+ msm_mux_blsp_i2c1,
+ msm_mux_gcc_gp1_clk_b,
+ msm_mux_blsp_spi4,
+ msm_mux_blsp_uart4,
+ msm_mux_rcm_marker1,
+ msm_mux_blsp_i2c4,
+ msm_mux_qdss_cti_trig_out_a1,
+ msm_mux_rcm_marker2,
+ msm_mux_qdss_cti_trig_out_a0,
+ msm_mux_blsp_spi6,
+ msm_mux_blsp_uart6,
+ msm_mux_pri_mi2s_ws_a,
+ msm_mux_ebi2_lcd_te_b,
+ msm_mux_blsp1_spi,
+ msm_mux_backlight_en_b,
+ msm_mux_pri_mi2s_data0_a,
+ msm_mux_pri_mi2s_data1_a,
+ msm_mux_blsp_i2c6,
+ msm_mux_ebi2_a_d_8_b,
+ msm_mux_pri_mi2s_sck_a,
+ msm_mux_ebi2_lcd_cs_n_b,
+ msm_mux_touch_rst,
+ msm_mux_pri_mi2s_mclk_a,
+ msm_mux_pwr_nav_enabled_a,
+ msm_mux_ts_int,
+ msm_mux_sd_write,
+ msm_mux_pwr_crypto_enabled_a,
+ msm_mux_codec_rst,
+ msm_mux_adsp_ext,
+ msm_mux_atest_combodac_to_gpio_native,
+ msm_mux_uim2_data,
+ msm_mux_gmac_mdio,
+ msm_mux_gcc_gp1_clk_a,
+ msm_mux_uim2_clk,
+ msm_mux_gcc_gp2_clk_a,
+ msm_mux_eth_irq,
+ msm_mux_uim2_reset,
+ msm_mux_gcc_gp3_clk_a,
+ msm_mux_eth_rst,
+ msm_mux_uim2_present,
+ msm_mux_prng_rosc,
+ msm_mux_uim1_data,
+ msm_mux_uim1_clk,
+ msm_mux_uim1_reset,
+ msm_mux_uim1_present,
+ msm_mux_gcc_plltest,
+ msm_mux_uim_batt,
+ msm_mux_coex_uart,
+ msm_mux_codec_int,
+ msm_mux_qdss_cti_trig_in_a0,
+ msm_mux_atest_bbrx1,
+ msm_mux_cri_trng0,
+ msm_mux_atest_bbrx0,
+ msm_mux_cri_trng,
+ msm_mux_qdss_cti_trig_in_b0,
+ msm_mux_atest_gpsadc_dtest0_native,
+ msm_mux_qdss_cti_trig_out_b0,
+ msm_mux_qdss_tracectl_b,
+ msm_mux_qdss_traceclk_b,
+ msm_mux_pa_indicator,
+ msm_mux_modem_tsync,
+ msm_mux_nav_tsync_out_a,
+ msm_mux_nav_ptp_pps_in_a,
+ msm_mux_ptp_pps_out_a,
+ msm_mux_gsm0_tx,
+ msm_mux_qdss_cti_trig_in_b1,
+ msm_mux_cri_trng1,
+ msm_mux_qdss_cti_trig_out_b1,
+ msm_mux_ssbi1,
+ msm_mux_atest_gpsadc_dtest1_native,
+ msm_mux_ssbi2,
+ msm_mux_atest_char3,
+ msm_mux_atest_char2,
+ msm_mux_atest_char1,
+ msm_mux_atest_char0,
+ msm_mux_atest_char,
+ msm_mux_ebi0_wrcdc,
+ msm_mux_ldo_update,
+ msm_mux_gcc_tlmm,
+ msm_mux_ldo_en,
+ msm_mux_dbg_out,
+ msm_mux_atest_tsens,
+ msm_mux_lcd_rst,
+ msm_mux_wlan_en1,
+ msm_mux_nav_tsync_out_b,
+ msm_mux_nav_ptp_pps_in_b,
+ msm_mux_ptp_pps_out_b,
+ msm_mux_pbs0,
+ msm_mux_sec_mi2s,
+ msm_mux_pwr_modem_enabled_a,
+ msm_mux_pbs1,
+ msm_mux_pwr_modem_enabled_b,
+ msm_mux_pbs2,
+ msm_mux_pwr_nav_enabled_b,
+ msm_mux_pwr_crypto_enabled_b,
+ msm_mux_NA,
+};
+
+static const char * const blsp_spi3_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3",
+};
+static const char * const gpio_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7",
+ "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14",
+ "gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21",
+ "gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28",
+ "gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35",
+ "gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42",
+ "gpio43", "gpio44", "gpio45", "gpio46", "gpio47", "gpio48", "gpio49",
+ "gpio50", "gpio51", "gpio52", "gpio53", "gpio54", "gpio55", "gpio56",
+ "gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63",
+ "gpio64", "gpio65", "gpio66", "gpio67", "gpio68", "gpio69", "gpio70",
+ "gpio71", "gpio72", "gpio73", "gpio74", "gpio75", "gpio76", "gpio77",
+ "gpio78", "gpio79",
+};
+static const char * const blsp_uart3_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3",
+};
+static const char * const qdss_tracedata_a_groups[] = {
+ "gpio0", "gpio1", "gpio4", "gpio5", "gpio20", "gpio21", "gpio22",
+ "gpio23", "gpio24", "gpio25", "gpio26", "gpio75", "gpio76", "gpio77",
+ "gpio78", "gpio79",
+};
+static const char * const bimc_dte1_groups[] = {
+ "gpio1", "gpio24",
+};
+static const char * const blsp_i2c3_groups[] = {
+ "gpio2", "gpio3",
+};
+static const char * const qdss_traceclk_a_groups[] = {
+ "gpio2",
+};
+static const char * const bimc_dte0_groups[] = {
+ "gpio2", "gpio15",
+};
+static const char * const qdss_cti_trig_in_a1_groups[] = {
+ "gpio3",
+};
+static const char * const blsp_spi2_groups[] = {
+ "gpio4", "gpio5", "gpio6", "gpio7",
+};
+static const char * const blsp_uart2_groups[] = {
+ "gpio4", "gpio5", "gpio6", "gpio7",
+};
+static const char * const blsp_uim2_groups[] = {
+ "gpio4", "gpio5",
+};
+static const char * const blsp_i2c2_groups[] = {
+ "gpio6", "gpio7",
+};
+static const char * const qdss_tracectl_a_groups[] = {
+ "gpio6",
+};
+static const char * const sensor_int2_groups[] = {
+ "gpio8",
+};
+static const char * const blsp_spi5_groups[] = {
+ "gpio8", "gpio9", "gpio10", "gpio11",
+};
+static const char * const blsp_uart5_groups[] = {
+ "gpio8", "gpio9", "gpio10", "gpio11",
+};
+static const char * const ebi2_lcd_groups[] = {
+ "gpio8", "gpio11", "gpio74", "gpio78",
+};
+static const char * const m_voc_groups[] = {
+ "gpio8", "gpio78",
+};
+static const char * const sensor_int3_groups[] = {
+ "gpio9",
+};
+static const char * const sensor_en_groups[] = {
+ "gpio10",
+};
+static const char * const blsp_i2c5_groups[] = {
+ "gpio10", "gpio11",
+};
+static const char * const ebi2_a_groups[] = {
+ "gpio10",
+};
+static const char * const qdss_tracedata_b_groups[] = {
+ "gpio10", "gpio39", "gpio40", "gpio41", "gpio42", "gpio43", "gpio46",
+ "gpio47", "gpio48", "gpio51", "gpio52", "gpio53", "gpio54", "gpio55",
+ "gpio58", "gpio59",
+};
+static const char * const sensor_rst_groups[] = {
+ "gpio11",
+};
+static const char * const blsp2_spi_groups[] = {
+ "gpio11", "gpio13", "gpio77",
+};
+static const char * const blsp_spi1_groups[] = {
+ "gpio12", "gpio13", "gpio14", "gpio15",
+};
+static const char * const blsp_uart1_groups[] = {
+ "gpio12", "gpio13", "gpio14", "gpio15",
+};
+static const char * const blsp_uim1_groups[] = {
+ "gpio12", "gpio13",
+};
+static const char * const blsp3_spi_groups[] = {
+ "gpio12", "gpio26", "gpio76",
+};
+static const char * const gcc_gp2_clk_b_groups[] = {
+ "gpio12",
+};
+static const char * const gcc_gp3_clk_b_groups[] = {
+ "gpio13",
+};
+static const char * const blsp_i2c1_groups[] = {
+ "gpio14", "gpio15",
+};
+static const char * const gcc_gp1_clk_b_groups[] = {
+ "gpio14",
+};
+static const char * const blsp_spi4_groups[] = {
+ "gpio16", "gpio17", "gpio18", "gpio19",
+};
+static const char * const blsp_uart4_groups[] = {
+ "gpio16", "gpio17", "gpio18", "gpio19",
+};
+static const char * const rcm_marker1_groups[] = {
+ "gpio18",
+};
+static const char * const blsp_i2c4_groups[] = {
+ "gpio18", "gpio19",
+};
+static const char * const qdss_cti_trig_out_a1_groups[] = {
+ "gpio18",
+};
+static const char * const rcm_marker2_groups[] = {
+ "gpio19",
+};
+static const char * const qdss_cti_trig_out_a0_groups[] = {
+ "gpio19",
+};
+static const char * const blsp_spi6_groups[] = {
+ "gpio20", "gpio21", "gpio22", "gpio23",
+};
+static const char * const blsp_uart6_groups[] = {
+ "gpio20", "gpio21", "gpio22", "gpio23",
+};
+static const char * const pri_mi2s_ws_a_groups[] = {
+ "gpio20",
+};
+static const char * const ebi2_lcd_te_b_groups[] = {
+ "gpio20",
+};
+static const char * const blsp1_spi_groups[] = {
+ "gpio20", "gpio21", "gpio78",
+};
+static const char * const backlight_en_b_groups[] = {
+ "gpio21",
+};
+static const char * const pri_mi2s_data0_a_groups[] = {
+ "gpio21",
+};
+static const char * const pri_mi2s_data1_a_groups[] = {
+ "gpio22",
+};
+static const char * const blsp_i2c6_groups[] = {
+ "gpio22", "gpio23",
+};
+static const char * const ebi2_a_d_8_b_groups[] = {
+ "gpio22",
+};
+static const char * const pri_mi2s_sck_a_groups[] = {
+ "gpio23",
+};
+static const char * const ebi2_lcd_cs_n_b_groups[] = {
+ "gpio23",
+};
+static const char * const touch_rst_groups[] = {
+ "gpio24",
+};
+static const char * const pri_mi2s_mclk_a_groups[] = {
+ "gpio24",
+};
+static const char * const pwr_nav_enabled_a_groups[] = {
+ "gpio24",
+};
+static const char * const ts_int_groups[] = {
+ "gpio25",
+};
+static const char * const sd_write_groups[] = {
+ "gpio25",
+};
+static const char * const pwr_crypto_enabled_a_groups[] = {
+ "gpio25",
+};
+static const char * const codec_rst_groups[] = {
+ "gpio26",
+};
+static const char * const adsp_ext_groups[] = {
+ "gpio26",
+};
+static const char * const atest_combodac_to_gpio_native_groups[] = {
+ "gpio26", "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32",
+ "gpio33", "gpio34", "gpio35", "gpio41", "gpio45", "gpio49", "gpio50",
+ "gpio51", "gpio52", "gpio54", "gpio55", "gpio57", "gpio59",
+};
+static const char * const uim2_data_groups[] = {
+ "gpio27",
+};
+static const char * const gmac_mdio_groups[] = {
+ "gpio27", "gpio28",
+};
+static const char * const gcc_gp1_clk_a_groups[] = {
+ "gpio27",
+};
+static const char * const uim2_clk_groups[] = {
+ "gpio28",
+};
+static const char * const gcc_gp2_clk_a_groups[] = {
+ "gpio28",
+};
+static const char * const eth_irq_groups[] = {
+ "gpio29",
+};
+static const char * const uim2_reset_groups[] = {
+ "gpio29",
+};
+static const char * const gcc_gp3_clk_a_groups[] = {
+ "gpio29",
+};
+static const char * const eth_rst_groups[] = {
+ "gpio30",
+};
+static const char * const uim2_present_groups[] = {
+ "gpio30",
+};
+static const char * const prng_rosc_groups[] = {
+ "gpio30",
+};
+static const char * const uim1_data_groups[] = {
+ "gpio31",
+};
+static const char * const uim1_clk_groups[] = {
+ "gpio32",
+};
+static const char * const uim1_reset_groups[] = {
+ "gpio33",
+};
+static const char * const uim1_present_groups[] = {
+ "gpio34",
+};
+static const char * const gcc_plltest_groups[] = {
+ "gpio34", "gpio35",
+};
+static const char * const uim_batt_groups[] = {
+ "gpio35",
+};
+static const char * const coex_uart_groups[] = {
+ "gpio36", "gpio37",
+};
+static const char * const codec_int_groups[] = {
+ "gpio38",
+};
+static const char * const qdss_cti_trig_in_a0_groups[] = {
+ "gpio38",
+};
+static const char * const atest_bbrx1_groups[] = {
+ "gpio39",
+};
+static const char * const cri_trng0_groups[] = {
+ "gpio40",
+};
+static const char * const atest_bbrx0_groups[] = {
+ "gpio40",
+};
+static const char * const cri_trng_groups[] = {
+ "gpio42",
+};
+static const char * const qdss_cti_trig_in_b0_groups[] = {
+ "gpio44",
+};
+static const char * const atest_gpsadc_dtest0_native_groups[] = {
+ "gpio44",
+};
+static const char * const qdss_cti_trig_out_b0_groups[] = {
+ "gpio45",
+};
+static const char * const qdss_tracectl_b_groups[] = {
+ "gpio49",
+};
+static const char * const qdss_traceclk_b_groups[] = {
+ "gpio50",
+};
+static const char * const pa_indicator_groups[] = {
+ "gpio51",
+};
+static const char * const modem_tsync_groups[] = {
+ "gpio53",
+};
+static const char * const nav_tsync_out_a_groups[] = {
+ "gpio53",
+};
+static const char * const nav_ptp_pps_in_a_groups[] = {
+ "gpio53",
+};
+static const char * const ptp_pps_out_a_groups[] = {
+ "gpio53",
+};
+static const char * const gsm0_tx_groups[] = {
+ "gpio55",
+};
+static const char * const qdss_cti_trig_in_b1_groups[] = {
+ "gpio56",
+};
+static const char * const cri_trng1_groups[] = {
+ "gpio57",
+};
+static const char * const qdss_cti_trig_out_b1_groups[] = {
+ "gpio57",
+};
+static const char * const ssbi1_groups[] = {
+ "gpio58",
+};
+static const char * const atest_gpsadc_dtest1_native_groups[] = {
+ "gpio58",
+};
+static const char * const ssbi2_groups[] = {
+ "gpio59",
+};
+static const char * const atest_char3_groups[] = {
+ "gpio60",
+};
+static const char * const atest_char2_groups[] = {
+ "gpio61",
+};
+static const char * const atest_char1_groups[] = {
+ "gpio62",
+};
+static const char * const atest_char0_groups[] = {
+ "gpio63",
+};
+static const char * const atest_char_groups[] = {
+ "gpio64",
+};
+static const char * const ebi0_wrcdc_groups[] = {
+ "gpio70",
+};
+static const char * const ldo_update_groups[] = {
+ "gpio72",
+};
+static const char * const gcc_tlmm_groups[] = {
+ "gpio72",
+};
+static const char * const ldo_en_groups[] = {
+ "gpio73",
+};
+static const char * const dbg_out_groups[] = {
+ "gpio73",
+};
+static const char * const atest_tsens_groups[] = {
+ "gpio73",
+};
+static const char * const lcd_rst_groups[] = {
+ "gpio74",
+};
+static const char * const wlan_en1_groups[] = {
+ "gpio75",
+};
+static const char * const nav_tsync_out_b_groups[] = {
+ "gpio75",
+};
+static const char * const nav_ptp_pps_in_b_groups[] = {
+ "gpio75",
+};
+static const char * const ptp_pps_out_b_groups[] = {
+ "gpio75",
+};
+static const char * const pbs0_groups[] = {
+ "gpio76",
+};
+static const char * const sec_mi2s_groups[] = {
+ "gpio76", "gpio77", "gpio78", "gpio79",
+};
+static const char * const pwr_modem_enabled_a_groups[] = {
+ "gpio76",
+};
+static const char * const pbs1_groups[] = {
+ "gpio77",
+};
+static const char * const pwr_modem_enabled_b_groups[] = {
+ "gpio77",
+};
+static const char * const pbs2_groups[] = {
+ "gpio78",
+};
+static const char * const pwr_nav_enabled_b_groups[] = {
+ "gpio78",
+};
+static const char * const pwr_crypto_enabled_b_groups[] = {
+ "gpio79",
+};
+
+static const struct msm_function mdm9607_functions[] = {
+ FUNCTION(blsp_spi3),
+ FUNCTION(gpio),
+ FUNCTION(blsp_uart3),
+ FUNCTION(qdss_tracedata_a),
+ FUNCTION(bimc_dte1),
+ FUNCTION(blsp_i2c3),
+ FUNCTION(qdss_traceclk_a),
+ FUNCTION(bimc_dte0),
+ FUNCTION(qdss_cti_trig_in_a1),
+ FUNCTION(blsp_spi2),
+ FUNCTION(blsp_uart2),
+ FUNCTION(blsp_uim2),
+ FUNCTION(blsp_i2c2),
+ FUNCTION(qdss_tracectl_a),
+ FUNCTION(sensor_int2),
+ FUNCTION(blsp_spi5),
+ FUNCTION(blsp_uart5),
+ FUNCTION(ebi2_lcd),
+ FUNCTION(m_voc),
+ FUNCTION(sensor_int3),
+ FUNCTION(sensor_en),
+ FUNCTION(blsp_i2c5),
+ FUNCTION(ebi2_a),
+ FUNCTION(qdss_tracedata_b),
+ FUNCTION(sensor_rst),
+ FUNCTION(blsp2_spi),
+ FUNCTION(blsp_spi1),
+ FUNCTION(blsp_uart1),
+ FUNCTION(blsp_uim1),
+ FUNCTION(blsp3_spi),
+ FUNCTION(gcc_gp2_clk_b),
+ FUNCTION(gcc_gp3_clk_b),
+ FUNCTION(blsp_i2c1),
+ FUNCTION(gcc_gp1_clk_b),
+ FUNCTION(blsp_spi4),
+ FUNCTION(blsp_uart4),
+ FUNCTION(rcm_marker1),
+ FUNCTION(blsp_i2c4),
+ FUNCTION(qdss_cti_trig_out_a1),
+ FUNCTION(rcm_marker2),
+ FUNCTION(qdss_cti_trig_out_a0),
+ FUNCTION(blsp_spi6),
+ FUNCTION(blsp_uart6),
+ FUNCTION(pri_mi2s_ws_a),
+ FUNCTION(ebi2_lcd_te_b),
+ FUNCTION(blsp1_spi),
+ FUNCTION(backlight_en_b),
+ FUNCTION(pri_mi2s_data0_a),
+ FUNCTION(pri_mi2s_data1_a),
+ FUNCTION(blsp_i2c6),
+ FUNCTION(ebi2_a_d_8_b),
+ FUNCTION(pri_mi2s_sck_a),
+ FUNCTION(ebi2_lcd_cs_n_b),
+ FUNCTION(touch_rst),
+ FUNCTION(pri_mi2s_mclk_a),
+ FUNCTION(pwr_nav_enabled_a),
+ FUNCTION(ts_int),
+ FUNCTION(sd_write),
+ FUNCTION(pwr_crypto_enabled_a),
+ FUNCTION(codec_rst),
+ FUNCTION(adsp_ext),
+ FUNCTION(atest_combodac_to_gpio_native),
+ FUNCTION(uim2_data),
+ FUNCTION(gmac_mdio),
+ FUNCTION(gcc_gp1_clk_a),
+ FUNCTION(uim2_clk),
+ FUNCTION(gcc_gp2_clk_a),
+ FUNCTION(eth_irq),
+ FUNCTION(uim2_reset),
+ FUNCTION(gcc_gp3_clk_a),
+ FUNCTION(eth_rst),
+ FUNCTION(uim2_present),
+ FUNCTION(prng_rosc),
+ FUNCTION(uim1_data),
+ FUNCTION(uim1_clk),
+ FUNCTION(uim1_reset),
+ FUNCTION(uim1_present),
+ FUNCTION(gcc_plltest),
+ FUNCTION(uim_batt),
+ FUNCTION(coex_uart),
+ FUNCTION(codec_int),
+ FUNCTION(qdss_cti_trig_in_a0),
+ FUNCTION(atest_bbrx1),
+ FUNCTION(cri_trng0),
+ FUNCTION(atest_bbrx0),
+ FUNCTION(cri_trng),
+ FUNCTION(qdss_cti_trig_in_b0),
+ FUNCTION(atest_gpsadc_dtest0_native),
+ FUNCTION(qdss_cti_trig_out_b0),
+ FUNCTION(qdss_tracectl_b),
+ FUNCTION(qdss_traceclk_b),
+ FUNCTION(pa_indicator),
+ FUNCTION(modem_tsync),
+ FUNCTION(nav_tsync_out_a),
+ FUNCTION(nav_ptp_pps_in_a),
+ FUNCTION(ptp_pps_out_a),
+ FUNCTION(gsm0_tx),
+ FUNCTION(qdss_cti_trig_in_b1),
+ FUNCTION(cri_trng1),
+ FUNCTION(qdss_cti_trig_out_b1),
+ FUNCTION(ssbi1),
+ FUNCTION(atest_gpsadc_dtest1_native),
+ FUNCTION(ssbi2),
+ FUNCTION(atest_char3),
+ FUNCTION(atest_char2),
+ FUNCTION(atest_char1),
+ FUNCTION(atest_char0),
+ FUNCTION(atest_char),
+ FUNCTION(ebi0_wrcdc),
+ FUNCTION(ldo_update),
+ FUNCTION(gcc_tlmm),
+ FUNCTION(ldo_en),
+ FUNCTION(dbg_out),
+ FUNCTION(atest_tsens),
+ FUNCTION(lcd_rst),
+ FUNCTION(wlan_en1),
+ FUNCTION(nav_tsync_out_b),
+ FUNCTION(nav_ptp_pps_in_b),
+ FUNCTION(ptp_pps_out_b),
+ FUNCTION(pbs0),
+ FUNCTION(sec_mi2s),
+ FUNCTION(pwr_modem_enabled_a),
+ FUNCTION(pbs1),
+ FUNCTION(pwr_modem_enabled_b),
+ FUNCTION(pbs2),
+ FUNCTION(pwr_nav_enabled_b),
+ FUNCTION(pwr_crypto_enabled_b),
+};
+
+static const struct msm_pingroup mdm9607_groups[] = {
+ PINGROUP(0, blsp_uart3, blsp_spi3, NA, NA, NA, NA, NA,
+ qdss_tracedata_a, NA),
+ PINGROUP(1, blsp_uart3, blsp_spi3, NA, NA, NA, NA, NA,
+ qdss_tracedata_a, bimc_dte1),
+ PINGROUP(2, blsp_uart3, blsp_i2c3, blsp_spi3, NA, NA, NA, NA, NA,
+ qdss_traceclk_a),
+ PINGROUP(3, blsp_uart3, blsp_i2c3, blsp_spi3, NA, NA, NA, NA, NA, NA),
+ PINGROUP(4, blsp_spi2, blsp_uart2, blsp_uim2, NA, NA, NA, NA,
+ qdss_tracedata_a, NA),
+ PINGROUP(5, blsp_spi2, blsp_uart2, blsp_uim2, NA, NA, NA, NA,
+ qdss_tracedata_a, NA),
+ PINGROUP(6, blsp_spi2, blsp_uart2, blsp_i2c2, NA, NA, NA, NA, NA, NA),
+ PINGROUP(7, blsp_spi2, blsp_uart2, blsp_i2c2, NA, NA, NA, NA, NA, NA),
+ PINGROUP(8, blsp_spi5, blsp_uart5, ebi2_lcd, m_voc, NA, NA, NA, NA, NA),
+ PINGROUP(9, blsp_spi5, blsp_uart5, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(10, blsp_spi5, blsp_i2c5, blsp_uart5, ebi2_a, NA, NA,
+ qdss_tracedata_b, NA, NA),
+ PINGROUP(11, blsp_spi5, blsp_i2c5, blsp_uart5, blsp2_spi, ebi2_lcd, NA,
+ NA, NA, NA),
+ PINGROUP(12, blsp_spi1, blsp_uart1, blsp_uim1, blsp3_spi,
+ gcc_gp2_clk_b, NA, NA, NA, NA),
+ PINGROUP(13, blsp_spi1, blsp_uart1, blsp_uim1, blsp2_spi,
+ gcc_gp3_clk_b, NA, NA, NA, NA),
+ PINGROUP(14, blsp_spi1, blsp_uart1, blsp_i2c1, gcc_gp1_clk_b, NA, NA,
+ NA, NA, NA),
+ PINGROUP(15, blsp_spi1, blsp_uart1, blsp_i2c1, NA, NA, NA, NA, NA, NA),
+ PINGROUP(16, blsp_spi4, blsp_uart4, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(17, blsp_spi4, blsp_uart4, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(18, blsp_spi4, blsp_uart4, blsp_i2c4, NA, NA, NA, NA, NA, NA),
+ PINGROUP(19, blsp_spi4, blsp_uart4, blsp_i2c4, NA, NA, NA, NA, NA, NA),
+ PINGROUP(20, blsp_spi6, blsp_uart6, pri_mi2s_ws_a, ebi2_lcd_te_b,
+ blsp1_spi, NA, NA, NA, qdss_tracedata_a),
+ PINGROUP(21, blsp_spi6, blsp_uart6, pri_mi2s_data0_a, blsp1_spi, NA,
+ NA, NA, NA, NA),
+ PINGROUP(22, blsp_spi6, blsp_uart6, pri_mi2s_data1_a, blsp_i2c6,
+ ebi2_a_d_8_b, NA, NA, NA, NA),
+ PINGROUP(23, blsp_spi6, blsp_uart6, pri_mi2s_sck_a, blsp_i2c6,
+ ebi2_lcd_cs_n_b, NA, NA, NA, NA),
+ PINGROUP(24, pri_mi2s_mclk_a, NA, pwr_nav_enabled_a, NA, NA, NA, NA,
+ qdss_tracedata_a, bimc_dte1),
+ PINGROUP(25, sd_write, NA, pwr_crypto_enabled_a, NA, NA, NA, NA,
+ qdss_tracedata_a, NA),
+ PINGROUP(26, blsp3_spi, adsp_ext, NA, qdss_tracedata_a, NA,
+ atest_combodac_to_gpio_native, NA, NA, NA),
+ PINGROUP(27, uim2_data, gmac_mdio, gcc_gp1_clk_a, NA, NA,
+ atest_combodac_to_gpio_native, NA, NA, NA),
+ PINGROUP(28, uim2_clk, gmac_mdio, gcc_gp2_clk_a, NA, NA,
+ atest_combodac_to_gpio_native, NA, NA, NA),
+ PINGROUP(29, uim2_reset, gcc_gp3_clk_a, NA, NA,
+ atest_combodac_to_gpio_native, NA, NA, NA, NA),
+ PINGROUP(30, uim2_present, prng_rosc, NA, NA,
+ atest_combodac_to_gpio_native, NA, NA, NA, NA),
+ PINGROUP(31, uim1_data, NA, NA, atest_combodac_to_gpio_native, NA, NA,
+ NA, NA, NA),
+ PINGROUP(32, uim1_clk, NA, NA, atest_combodac_to_gpio_native, NA, NA,
+ NA, NA, NA),
+ PINGROUP(33, uim1_reset, NA, NA, atest_combodac_to_gpio_native, NA, NA,
+ NA, NA, NA),
+ PINGROUP(34, uim1_present, gcc_plltest, NA, NA,
+ atest_combodac_to_gpio_native, NA, NA, NA, NA),
+ PINGROUP(35, uim_batt, gcc_plltest, NA, atest_combodac_to_gpio_native,
+ NA, NA, NA, NA, NA),
+ PINGROUP(36, coex_uart, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(37, coex_uart, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(38, NA, NA, NA, qdss_cti_trig_in_a0, NA, NA, NA, NA, NA),
+ PINGROUP(39, NA, NA, NA, qdss_tracedata_b, NA, atest_bbrx1, NA, NA, NA),
+ PINGROUP(40, NA, cri_trng0, NA, NA, NA, NA, qdss_tracedata_b, NA,
+ atest_bbrx0),
+ PINGROUP(41, NA, NA, NA, NA, NA, qdss_tracedata_b, NA,
+ atest_combodac_to_gpio_native, NA),
+ PINGROUP(42, NA, cri_trng, NA, NA, qdss_tracedata_b, NA, NA, NA, NA),
+ PINGROUP(43, NA, NA, NA, NA, qdss_tracedata_b, NA, NA, NA, NA),
+ PINGROUP(44, NA, NA, qdss_cti_trig_in_b0, NA,
+ atest_gpsadc_dtest0_native, NA, NA, NA, NA),
+ PINGROUP(45, NA, NA, qdss_cti_trig_out_b0, NA,
+ atest_combodac_to_gpio_native, NA, NA, NA, NA),
+ PINGROUP(46, NA, NA, qdss_tracedata_b, NA, NA, NA, NA, NA, NA),
+ PINGROUP(47, NA, NA, qdss_tracedata_b, NA, NA, NA, NA, NA, NA),
+ PINGROUP(48, NA, NA, qdss_tracedata_b, NA, NA, NA, NA, NA, NA),
+ PINGROUP(49, NA, NA, qdss_tracectl_b, NA,
+ atest_combodac_to_gpio_native, NA, NA, NA, NA),
+ PINGROUP(50, NA, NA, qdss_traceclk_b, NA,
+ atest_combodac_to_gpio_native, NA, NA, NA, NA),
+ PINGROUP(51, NA, pa_indicator, NA, qdss_tracedata_b, NA,
+ atest_combodac_to_gpio_native, NA, NA, NA),
+ PINGROUP(52, NA, NA, NA, qdss_tracedata_b, NA,
+ atest_combodac_to_gpio_native, NA, NA, NA),
+ PINGROUP(53, NA, modem_tsync, nav_tsync_out_a, nav_ptp_pps_in_a,
+ ptp_pps_out_a, qdss_tracedata_b, NA, NA, NA),
+ PINGROUP(54, NA, qdss_tracedata_b, NA, atest_combodac_to_gpio_native,
+ NA, NA, NA, NA, NA),
+ PINGROUP(55, gsm0_tx, NA, qdss_tracedata_b, NA,
+ atest_combodac_to_gpio_native, NA, NA, NA, NA),
+ PINGROUP(56, NA, NA, qdss_cti_trig_in_b1, NA, NA, NA, NA, NA, NA),
+ PINGROUP(57, NA, cri_trng1, NA, qdss_cti_trig_out_b1, NA,
+ atest_combodac_to_gpio_native, NA, NA, NA),
+ PINGROUP(58, NA, ssbi1, NA, qdss_tracedata_b, NA,
+ atest_gpsadc_dtest1_native, NA, NA, NA),
+ PINGROUP(59, NA, ssbi2, NA, qdss_tracedata_b, NA,
+ atest_combodac_to_gpio_native, NA, NA, NA),
+ PINGROUP(60, atest_char3, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(61, atest_char2, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(62, atest_char1, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(63, atest_char0, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(64, atest_char, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(65, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(66, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(67, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(68, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(69, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(70, NA, NA, ebi0_wrcdc, NA, NA, NA, NA, NA, NA),
+ PINGROUP(71, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(72, ldo_update, NA, gcc_tlmm, NA, NA, NA, NA, NA, NA),
+ PINGROUP(73, ldo_en, dbg_out, NA, NA, NA, atest_tsens, NA, NA, NA),
+ PINGROUP(74, ebi2_lcd, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(75, nav_tsync_out_b, nav_ptp_pps_in_b, ptp_pps_out_b, NA,
+ qdss_tracedata_a, NA, NA, NA, NA),
+ PINGROUP(76, pbs0, sec_mi2s, blsp3_spi, pwr_modem_enabled_a, NA,
+ qdss_tracedata_a, NA, NA, NA),
+ PINGROUP(77, pbs1, sec_mi2s, blsp2_spi, pwr_modem_enabled_b, NA,
+ qdss_tracedata_a, NA, NA, NA),
+ PINGROUP(78, pbs2, sec_mi2s, blsp1_spi, ebi2_lcd, m_voc,
+ pwr_nav_enabled_b, NA, qdss_tracedata_a, NA),
+ PINGROUP(79, sec_mi2s, NA, pwr_crypto_enabled_b, NA, qdss_tracedata_a,
+ NA, NA, NA, NA),
+ SDC_QDSD_PINGROUP(sdc1_clk, 0x10a000, 13, 6),
+ SDC_QDSD_PINGROUP(sdc1_cmd, 0x10a000, 11, 3),
+ SDC_QDSD_PINGROUP(sdc1_data, 0x10a000, 9, 0),
+ SDC_QDSD_PINGROUP(sdc2_clk, 0x109000, 14, 6),
+ SDC_QDSD_PINGROUP(sdc2_cmd, 0x109000, 11, 3),
+ SDC_QDSD_PINGROUP(sdc2_data, 0x109000, 9, 0),
+ SDC_QDSD_PINGROUP(qdsd_clk, 0x19c000, 3, 0),
+ SDC_QDSD_PINGROUP(qdsd_cmd, 0x19c000, 8, 5),
+ SDC_QDSD_PINGROUP(qdsd_data0, 0x19c000, 13, 10),
+ SDC_QDSD_PINGROUP(qdsd_data1, 0x19c000, 18, 15),
+ SDC_QDSD_PINGROUP(qdsd_data2, 0x19c000, 23, 20),
+ SDC_QDSD_PINGROUP(qdsd_data3, 0x19c000, 28, 25),
+};
+
+static const struct msm_pinctrl_soc_data mdm9607_pinctrl = {
+ .pins = mdm9607_pins,
+ .npins = ARRAY_SIZE(mdm9607_pins),
+ .functions = mdm9607_functions,
+ .nfunctions = ARRAY_SIZE(mdm9607_functions),
+ .groups = mdm9607_groups,
+ .ngroups = ARRAY_SIZE(mdm9607_groups),
+ .ngpios = 80,
+};
+
+static int mdm9607_pinctrl_probe(struct platform_device *pdev)
+{
+ return msm_pinctrl_probe(pdev, &mdm9607_pinctrl);
+}
+
+static const struct of_device_id mdm9607_pinctrl_of_match[] = {
+ { .compatible = "qcom,mdm9607-pinctrl", },
+ { },
+};
+
+static struct platform_driver mdm9607_pinctrl_driver = {
+ .driver = {
+ .name = "mdm9607-pinctrl",
+ .owner = THIS_MODULE,
+ .of_match_table = mdm9607_pinctrl_of_match,
+ },
+ .probe = mdm9607_pinctrl_probe,
+ .remove = msm_pinctrl_remove,
+};
+
+static int __init mdm9607_pinctrl_init(void)
+{
+ return platform_driver_register(&mdm9607_pinctrl_driver);
+}
+arch_initcall(mdm9607_pinctrl_init);
+
+static void __exit mdm9607_pinctrl_exit(void)
+{
+ platform_driver_unregister(&mdm9607_pinctrl_driver);
+}
+module_exit(mdm9607_pinctrl_exit);
+
+MODULE_DESCRIPTION("QTI mdm9607 pinctrl driver");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(of, mdm9607_pinctrl_of_match);
diff --git a/drivers/platform/msm/ep_pcie/ep_pcie_com.h b/drivers/platform/msm/ep_pcie/ep_pcie_com.h
index 00ca8dc4..33e0314 100644
--- a/drivers/platform/msm/ep_pcie/ep_pcie_com.h
+++ b/drivers/platform/msm/ep_pcie/ep_pcie_com.h
@@ -120,6 +120,12 @@
#define PCIE20_MHICFG 0x110
#define PCIE20_BHI_EXECENV 0x228
+#define PCIE20_MHIVER 0x108
+#define PCIE20_MHICTRL 0x138
+#define PCIE20_MHISTATUS 0x148
+#define PCIE20_BHI_VERSION_LOWER 0x200
+#define PCIE20_BHI_VERSION_UPPER 0x204
+#define PCIE20_BHI_INTVEC 0x220
#define PCIE20_AUX_CLK_FREQ_REG 0xB40
diff --git a/drivers/platform/msm/ep_pcie/ep_pcie_core.c b/drivers/platform/msm/ep_pcie/ep_pcie_core.c
index 055f026..db6f689 100644
--- a/drivers/platform/msm/ep_pcie/ep_pcie_core.c
+++ b/drivers/platform/msm/ep_pcie/ep_pcie_core.c
@@ -497,6 +497,22 @@
ep_pcie_write_mask(dev->dm_core + PCIE20_MISC_CONTROL_1, BIT(0), 0);
}
+static void ep_pcie_config_mmio(struct ep_pcie_dev_t *dev)
+{
+ EP_PCIE_DBG(dev,
+ "Initial version of MMIO is:0x%x\n",
+ readl_relaxed(dev->mmio + PCIE20_MHIVER));
+
+ ep_pcie_write_reg(dev->mmio, PCIE20_MHICFG, 0x02800880);
+ ep_pcie_write_reg(dev->mmio, PCIE20_BHI_EXECENV, 0x2);
+ ep_pcie_write_reg(dev->mmio, PCIE20_MHICTRL, 0x0);
+ ep_pcie_write_reg(dev->mmio, PCIE20_MHISTATUS, 0x0);
+ ep_pcie_write_reg(dev->mmio, PCIE20_MHIVER, 0x1000000);
+ ep_pcie_write_reg(dev->mmio, PCIE20_BHI_VERSION_LOWER, 0x2);
+ ep_pcie_write_reg(dev->mmio, PCIE20_BHI_VERSION_UPPER, 0x1);
+ ep_pcie_write_reg(dev->mmio, PCIE20_BHI_INTVEC, 0xffffffff);
+}
+
static void ep_pcie_core_init(struct ep_pcie_dev_t *dev, bool configured)
{
EP_PCIE_DBG(dev, "PCIe V%d\n", dev->rev);
@@ -667,9 +683,6 @@
/* Configure BARs */
ep_pcie_bar_init(dev);
-
- ep_pcie_write_reg(dev->mmio, PCIE20_MHICFG, 0x02800880);
- ep_pcie_write_reg(dev->mmio, PCIE20_BHI_EXECENV, 0x2);
}
/* Configure IRQ events */
@@ -690,6 +703,16 @@
dev->rev,
readl_relaxed(dev->parf + PCIE20_PARF_INT_ALL_MASK));
}
+
+ if (dev->active_config) {
+ ep_pcie_write_reg(dev->dm_core, PCIE20_AUX_CLK_FREQ_REG, 0x14);
+
+ EP_PCIE_DBG2(dev, "PCIe V%d: Enable L1.\n", dev->rev);
+ ep_pcie_write_mask(dev->parf + PCIE20_PARF_PM_CTRL, BIT(5), 0);
+ }
+
+ /* Configure MMIO */
+ ep_pcie_config_mmio(dev);
}
static void ep_pcie_config_inbound_iatu(struct ep_pcie_dev_t *dev)
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
index e88ab27..07773eb 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.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
@@ -1517,6 +1517,7 @@
char *entry;
size_t entry_size;
bool entry_zeroed;
+ bool entry_valid;
u32 i, num_entries = 0, id = *rule_id, pos = 0;
IPADBG("\n");
@@ -1538,20 +1539,33 @@
&entry_zeroed);
if (result) {
IPAERR(
- "Failed to determine whether the %s entry is definitely zero",
- ipahal_nat_type_str(nat_type));
+ "Failed to determine whether the %s entry is definitely zero\n"
+ , ipahal_nat_type_str(nat_type));
goto bail;
}
if (entry_zeroed)
continue;
- pos += scnprintf(buff + pos, buff_size - pos,
- "\tEntry_Index=%d\n", id);
+ result = ipahal_nat_is_entry_valid(nat_type, entry,
+ &entry_valid);
+ if (result) {
+ IPAERR(
+ "Failed to determine whether the %s entry is valid\n"
+ , ipahal_nat_type_str(nat_type));
+ goto bail;
+ }
+
+ if (entry_valid) {
+ ++num_entries;
+ pos += scnprintf(buff + pos, buff_size - pos,
+ "\tEntry_Index=%d\n", id);
+ } else {
+ pos += scnprintf(buff + pos, buff_size - pos,
+ "\tEntry_Index=%d - Invalid Entry\n", id);
+ }
pos += ipahal_nat_stringify_entry(nat_type, entry,
buff + pos, buff_size - pos);
-
- ++num_entries;
}
if (num_entries)
@@ -1637,6 +1651,7 @@
char *pdn_entry;
size_t pdn_entry_size;
bool entry_zeroed;
+ bool entry_valid;
u32 pos = 0;
IPADBG("\n");
@@ -1654,13 +1669,25 @@
pdn_entry, &entry_zeroed);
if (result) {
IPAERR(
- "Failed to determine whether the PDN entry is definitely zero");
+ "Failed to determine whether the PDN entry is definitely zero\n");
goto bail;
}
if (entry_zeroed)
continue;
- pos += scnprintf(buff + pos, buff_size - pos, "PDN %d: ", i);
+ result = ipahal_nat_is_entry_valid(IPAHAL_NAT_IPV4_PDN,
+ pdn_entry, &entry_valid);
+ if (result) {
+ IPAERR(
+ "Failed to determine whether the PDN entry is valid\n");
+ goto bail;
+ }
+ if (entry_valid)
+ pos += scnprintf(buff + pos, buff_size - pos,
+ "PDN %d: ", i);
+ else
+ pos += scnprintf(buff + pos, buff_size - pos,
+ "PDN %d - Invalid: ", i);
pos += ipahal_nat_stringify_entry(IPAHAL_NAT_IPV4_PDN,
pdn_entry, buff + pos, buff_size - pos);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_pm.h b/drivers/platform/msm/ipa/ipa_v3/ipa_pm.h
index ce9c684..0772dde 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_pm.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_pm.h
@@ -16,7 +16,7 @@
#include <linux/msm_ipa.h>
/* internal to ipa */
-#define IPA_PM_MAX_CLIENTS 11 /* actual max is value -1 since we start from 1*/
+#define IPA_PM_MAX_CLIENTS 12 /* actual max is value -1 since we start from 1*/
#define IPA_PM_MAX_EX_CL 64
#define IPA_PM_THRESHOLD_MAX 5
#define IPA_PM_EXCEPTION_MAX 2
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
index 897da58..5ea78b9 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
@@ -1972,6 +1972,49 @@
}
/**
+ * ipa_comp_cfg() - Configure QMB/Master port selection
+ *
+ * Returns: None
+ */
+static void ipa_comp_cfg(void)
+{
+ struct ipahal_reg_comp_cfg comp_cfg;
+
+ /* IPAv4 specific, on NON-MHI config*/
+ if ((ipa3_ctx->ipa_hw_type == IPA_HW_v4_0) &&
+ (ipa3_ctx->ipa_config_is_mhi == false)) {
+
+ ipahal_read_reg_fields(IPA_COMP_CFG, &comp_cfg);
+ IPADBG("Before comp config\n");
+ IPADBG("ipa_qmb_select_by_address_global_en = %d\n",
+ comp_cfg.ipa_qmb_select_by_address_global_en);
+
+ IPADBG("ipa_qmb_select_by_address_prod_en = %d\n",
+ comp_cfg.ipa_qmb_select_by_address_prod_en);
+
+ IPADBG("ipa_qmb_select_by_address_cons_en = %d\n",
+ comp_cfg.ipa_qmb_select_by_address_cons_en);
+
+ comp_cfg.ipa_qmb_select_by_address_global_en = false;
+ comp_cfg.ipa_qmb_select_by_address_prod_en = false;
+ comp_cfg.ipa_qmb_select_by_address_cons_en = false;
+
+ ipahal_write_reg_fields(IPA_COMP_CFG, &comp_cfg);
+
+ ipahal_read_reg_fields(IPA_COMP_CFG, &comp_cfg);
+ IPADBG("After comp config\n");
+ IPADBG("ipa_qmb_select_by_address_global_en = %d\n",
+ comp_cfg.ipa_qmb_select_by_address_global_en);
+
+ IPADBG("ipa_qmb_select_by_address_prod_en = %d\n",
+ comp_cfg.ipa_qmb_select_by_address_prod_en);
+
+ IPADBG("ipa_qmb_select_by_address_cons_en = %d\n",
+ comp_cfg.ipa_qmb_select_by_address_cons_en);
+ }
+}
+
+/**
* ipa3_cfg_qsb() - Configure IPA QSB maximal reads and writes
*
* Returns: None
@@ -2050,6 +2093,8 @@
ipa3_cfg_qsb();
+ ipa_comp_cfg();
+
return 0;
}
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_nat.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_nat.c
index d335ba6..016b4f3 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_nat.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_nat.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
@@ -17,6 +17,7 @@
#define IPA_64_LOW_32_MASK (0xFFFFFFFF)
#define IPA_64_HIGH_32_MASK (0xFFFFFFFF00000000ULL)
+#define IPAHAL_NAT_INVALID_PROTOCOL (0xFF)
static const char *ipahal_nat_type_to_str[IPA_NAT_MAX] = {
__stringify(IPAHAL_NAT_IPV4),
@@ -73,6 +74,40 @@
return (memcmp(&zero_entry, entry, sizeof(zero_entry))) ? false : true;
}
+static bool ipa_nat_ipv4_is_entry_valid_v_3_0(const void *entry)
+{
+ struct ipa_nat_hw_ipv4_entry *hw_entry =
+ (struct ipa_nat_hw_ipv4_entry *)entry;
+
+ return hw_entry->enable &&
+ hw_entry->protocol != IPAHAL_NAT_INVALID_PROTOCOL;
+}
+
+static bool ipa_nat_ipv4_is_index_entry_valid_v_3_0(const void *entry)
+{
+ struct ipa_nat_hw_indx_entry *hw_entry =
+ (struct ipa_nat_hw_indx_entry *)entry;
+
+ return hw_entry->tbl_entry != 0;
+}
+
+static bool ipa_nat_ipv4_is_pdn_entry_valid_v_4_0(const void *entry)
+{
+ struct ipa_nat_hw_pdn_entry *hw_entry =
+ (struct ipa_nat_hw_pdn_entry *)entry;
+
+ return hw_entry->public_ip != 0;
+}
+
+static bool ipa_nat_ipv6ct_is_entry_valid_v_4_0(const void *entry)
+{
+ struct ipa_nat_hw_ipv6ct_entry *hw_entry =
+ (struct ipa_nat_hw_ipv6ct_entry *)entry;
+
+ return hw_entry->enable &&
+ hw_entry->protocol != IPAHAL_NAT_INVALID_PROTOCOL;
+}
+
static int ipa_nat_ipv4_stringify_entry_v_3_0(const void *entry,
char *buff, size_t buff_size)
{
@@ -194,11 +229,15 @@
* struct ipahal_nat_obj - H/W information for specific IPA version
* @entry_size - CB to get the size of the entry
* @is_entry_zeroed - CB to determine whether an entry is definitely zero
+ * @is_entry_valid - CB to determine whether an entry is valid
+ * Validity criterium depends on entry type. E.g. for NAT base table
+ * Entry need to be with valid protocol and enabled.
* @stringify_entry - CB to create string that represents an entry
*/
struct ipahal_nat_obj {
size_t (*entry_size)(void);
bool (*is_entry_zeroed)(const void *entry);
+ bool (*is_entry_valid)(const void *entry);
int (*stringify_entry)(const void *entry, char *buff, size_t buff_size);
};
@@ -216,11 +255,13 @@
[IPA_HW_v3_0][IPAHAL_NAT_IPV4] = {
ipa_nat_ipv4_entry_size_v_3_0,
ipa_nat_ipv4_is_entry_zeroed_v_3_0,
+ ipa_nat_ipv4_is_entry_valid_v_3_0,
ipa_nat_ipv4_stringify_entry_v_3_0
},
[IPA_HW_v3_0][IPAHAL_NAT_IPV4_INDEX] = {
ipa_nat_ipv4_index_entry_size_v_3_0,
ipa_nat_ipv4_is_index_entry_zeroed_v_3_0,
+ ipa_nat_ipv4_is_index_entry_valid_v_3_0,
ipa_nat_ipv4_index_stringify_entry_v_3_0
},
@@ -228,16 +269,19 @@
[IPA_HW_v4_0][IPAHAL_NAT_IPV4] = {
ipa_nat_ipv4_entry_size_v_3_0,
ipa_nat_ipv4_is_entry_zeroed_v_3_0,
+ ipa_nat_ipv4_is_entry_valid_v_3_0,
ipa_nat_ipv4_stringify_entry_v_4_0
},
[IPA_HW_v4_0][IPAHAL_NAT_IPV4_PDN] = {
ipa_nat_ipv4_pdn_entry_size_v_4_0,
ipa_nat_ipv4_is_pdn_entry_zeroed_v_4_0,
+ ipa_nat_ipv4_is_pdn_entry_valid_v_4_0,
ipa_nat_ipv4_pdn_stringify_entry_v_4_0
},
[IPA_HW_v4_0][IPAHAL_NAT_IPV6CT] = {
ipa_nat_ipv6ct_entry_size_v_4_0,
ipa_nat_ipv6ct_is_entry_zeroed_v_4_0,
+ ipa_nat_ipv6ct_is_entry_valid_v_4_0,
ipa_nat_ipv6ct_stringify_entry_v_4_0
}
};
@@ -335,6 +379,25 @@
return 0;
}
+int ipahal_nat_is_entry_valid(enum ipahal_nat_type nat_type, void *entry,
+ bool *entry_valid)
+{
+ if (WARN(entry == NULL || entry_valid == NULL,
+ "NULL pointer received\n"))
+ return -EINVAL;
+ if (WARN(nat_type < 0 || nat_type >= IPA_NAT_MAX,
+ "requested NAT type %d is invalid\n", nat_type))
+ return -EINVAL;
+
+ IPAHAL_DBG("Determine whether the entry is valid for NAT type=%s\n",
+ ipahal_nat_type_str(nat_type));
+ *entry_valid = ipahal_nat_objs[ipahal_ctx->hw_type][nat_type].
+ is_entry_valid(entry);
+ IPAHAL_DBG("The entry is %svalid\n", (*entry_valid) ? "" : "not ");
+
+ return 0;
+}
+
int ipahal_nat_stringify_entry(enum ipahal_nat_type nat_type, void *entry,
char *buff, size_t buff_size)
{
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_nat.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_nat.h
index f99c1a0..2461d3e 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_nat.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_nat.h
@@ -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
@@ -53,6 +53,18 @@
bool *entry_zeroed);
/*
+ * ipahal_nat_is_entry_valid() - Determines whether HW NAT entry is
+ * valid.
+ * Validity criterium depends on entry type. E.g. for NAT base table
+ * Entry need to be with valid protocol and enabled.
+ * @nat_type: [in] The type of the NAT entry
+ * @entry: [in] The NAT entry
+ * @entry_valid: [out] True if the received entry is valid
+ */
+int ipahal_nat_is_entry_valid(enum ipahal_nat_type nat_type, void *entry,
+ bool *entry_valid);
+
+/*
* ipahal_nat_stringify_entry() - Creates a string for HW NAT entry
* @nat_type: [in] The type of the NAT entry
* @entry: [in] The NAT entry
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 c3422d1..66837d0 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
@@ -654,6 +654,202 @@
IPA_CLKON_CFG_OPEN_RX_BMSK);
}
+static void ipareg_construct_comp_cfg(
+ enum ipahal_reg_name reg, const void *fields, u32 *val)
+{
+ struct ipahal_reg_comp_cfg *comp_cfg =
+ (struct ipahal_reg_comp_cfg *)fields;
+
+ IPA_SETFIELD_IN_REG(*val,
+ comp_cfg->ipa_atomic_fetcher_arb_lock_dis,
+ IPA_COMP_CFG_IPA_ATOMIC_FETCHER_ARB_LOCK_DIS_SHFT,
+ IPA_COMP_CFG_IPA_ATOMIC_FETCHER_ARB_LOCK_DIS_BMSK);
+
+ IPA_SETFIELD_IN_REG(*val,
+ comp_cfg->ipa_qmb_select_by_address_global_en,
+ IPA_COMP_CFG_IPA_QMB_SELECT_BY_ADDRESS_GLOBAL_EN_SHFT,
+ IPA_COMP_CFG_IPA_QMB_SELECT_BY_ADDRESS_GLOBAL_EN_BMSK);
+
+ IPA_SETFIELD_IN_REG(*val,
+ comp_cfg->gsi_multi_axi_masters_dis,
+ IPA_COMP_CFG_GSI_MULTI_AXI_MASTERS_DIS_SHFT,
+ IPA_COMP_CFG_GSI_MULTI_AXI_MASTERS_DIS_BMSK);
+
+ IPA_SETFIELD_IN_REG(*val,
+ comp_cfg->gsi_snoc_cnoc_loop_protection_disable,
+ IPA_COMP_CFG_GSI_SNOC_CNOC_LOOP_PROTECTION_DISABLE_SHFT,
+ IPA_COMP_CFG_GSI_SNOC_CNOC_LOOP_PROTECTION_DISABLE_BMSK);
+
+ IPA_SETFIELD_IN_REG(*val,
+ comp_cfg->gen_qmb_0_snoc_cnoc_loop_protection_disable,
+ IPA_COMP_CFG_GEN_QMB_0_SNOC_CNOC_LOOP_PROTECTION_DISABLE_SHFT,
+ IPA_COMP_CFG_GEN_QMB_0_SNOC_CNOC_LOOP_PROTECTION_DISABLE_BMSK);
+
+ IPA_SETFIELD_IN_REG(*val,
+ comp_cfg->gen_qmb_1_multi_inorder_wr_dis,
+ IPA_COMP_CFG_GEN_QMB_1_MULTI_INORDER_WR_DIS_SHFT,
+ IPA_COMP_CFG_GEN_QMB_1_MULTI_INORDER_WR_DIS_BMSK);
+
+ IPA_SETFIELD_IN_REG(*val,
+ comp_cfg->gen_qmb_0_multi_inorder_wr_dis,
+ IPA_COMP_CFG_GEN_QMB_0_MULTI_INORDER_WR_DIS_SHFT,
+ IPA_COMP_CFG_GEN_QMB_0_MULTI_INORDER_WR_DIS_BMSK);
+
+ IPA_SETFIELD_IN_REG(*val,
+ comp_cfg->gen_qmb_1_multi_inorder_rd_dis,
+ IPA_COMP_CFG_GEN_QMB_1_MULTI_INORDER_RD_DIS_SHFT,
+ IPA_COMP_CFG_GEN_QMB_1_MULTI_INORDER_RD_DIS_BMSK);
+
+ IPA_SETFIELD_IN_REG(*val,
+ comp_cfg->gen_qmb_0_multi_inorder_rd_dis,
+ IPA_COMP_CFG_GEN_QMB_0_MULTI_INORDER_RD_DIS_SHFT,
+ IPA_COMP_CFG_GEN_QMB_0_MULTI_INORDER_RD_DIS_BMSK);
+
+ IPA_SETFIELD_IN_REG(*val,
+ comp_cfg->gsi_multi_inorder_wr_dis,
+ IPA_COMP_CFG_GSI_MULTI_INORDER_WR_DIS_SHFT,
+ IPA_COMP_CFG_GSI_MULTI_INORDER_WR_DIS_BMSK);
+
+ IPA_SETFIELD_IN_REG(*val,
+ comp_cfg->gsi_multi_inorder_rd_dis,
+ IPA_COMP_CFG_GSI_MULTI_INORDER_RD_DIS_SHFT,
+ IPA_COMP_CFG_GSI_MULTI_INORDER_RD_DIS_BMSK);
+
+ IPA_SETFIELD_IN_REG(*val,
+ comp_cfg->ipa_qmb_select_by_address_prod_en,
+ IPA_COMP_CFG_IPA_QMB_SELECT_BY_ADDRESS_PROD_EN_SHFT,
+ IPA_COMP_CFG_IPA_QMB_SELECT_BY_ADDRESS_PROD_EN_BMSK);
+
+ IPA_SETFIELD_IN_REG(*val,
+ comp_cfg->ipa_qmb_select_by_address_cons_en,
+ IPA_COMP_CFG_IPA_QMB_SELECT_BY_ADDRESS_CONS_EN_SHFT,
+ IPA_COMP_CFG_IPA_QMB_SELECT_BY_ADDRESS_CONS_EN_BMSK);
+
+ IPA_SETFIELD_IN_REG(*val,
+ comp_cfg->ipa_dcmp_fast_clk_en,
+ IPA_COMP_CFG_IPA_DCMP_FAST_CLK_EN_SHFT,
+ IPA_COMP_CFG_IPA_DCMP_FAST_CLK_EN_BMSK);
+
+ IPA_SETFIELD_IN_REG(*val,
+ comp_cfg->gen_qmb_1_snoc_bypass_dis,
+ IPA_COMP_CFG_GEN_QMB_1_SNOC_BYPASS_DIS_SHFT,
+ IPA_COMP_CFG_GEN_QMB_1_SNOC_BYPASS_DIS_BMSK);
+
+ IPA_SETFIELD_IN_REG(*val,
+ comp_cfg->gen_qmb_0_snoc_bypass_dis,
+ IPA_COMP_CFG_GEN_QMB_0_SNOC_BYPASS_DIS_SHFT,
+ IPA_COMP_CFG_GEN_QMB_0_SNOC_BYPASS_DIS_BMSK);
+
+ IPA_SETFIELD_IN_REG(*val,
+ comp_cfg->gsi_snoc_bypass_dis,
+ IPA_COMP_CFG_GSI_SNOC_BYPASS_DIS_SHFT,
+ IPA_COMP_CFG_GSI_SNOC_BYPASS_DIS_BMSK);
+
+ IPA_SETFIELD_IN_REG(*val,
+ comp_cfg->enable,
+ IPA_COMP_CFG_ENABLE_SHFT,
+ IPA_COMP_CFG_ENABLE_BMSK);
+}
+
+static void ipareg_parse_comp_cfg(
+ enum ipahal_reg_name reg, void *fields, u32 val)
+{
+ struct ipahal_reg_comp_cfg *comp_cfg =
+ (struct ipahal_reg_comp_cfg *)fields;
+
+ memset(comp_cfg, 0, sizeof(struct ipahal_reg_comp_cfg));
+
+ comp_cfg->ipa_atomic_fetcher_arb_lock_dis =
+ IPA_GETFIELD_FROM_REG(val,
+ IPA_COMP_CFG_IPA_ATOMIC_FETCHER_ARB_LOCK_DIS_SHFT,
+ IPA_COMP_CFG_IPA_ATOMIC_FETCHER_ARB_LOCK_DIS_BMSK);
+
+ comp_cfg->ipa_qmb_select_by_address_global_en =
+ IPA_GETFIELD_FROM_REG(val,
+ IPA_COMP_CFG_IPA_QMB_SELECT_BY_ADDRESS_GLOBAL_EN_SHFT,
+ IPA_COMP_CFG_IPA_QMB_SELECT_BY_ADDRESS_GLOBAL_EN_BMSK);
+
+ comp_cfg->gsi_multi_axi_masters_dis =
+ IPA_GETFIELD_FROM_REG(val,
+ IPA_COMP_CFG_GSI_MULTI_AXI_MASTERS_DIS_SHFT,
+ IPA_COMP_CFG_GSI_MULTI_AXI_MASTERS_DIS_BMSK);
+
+ comp_cfg->gsi_snoc_cnoc_loop_protection_disable =
+ IPA_GETFIELD_FROM_REG(val,
+ IPA_COMP_CFG_GSI_SNOC_CNOC_LOOP_PROTECTION_DISABLE_SHFT,
+ IPA_COMP_CFG_GSI_SNOC_CNOC_LOOP_PROTECTION_DISABLE_BMSK);
+
+ comp_cfg->gen_qmb_0_snoc_cnoc_loop_protection_disable =
+ IPA_GETFIELD_FROM_REG(val,
+ IPA_COMP_CFG_GEN_QMB_0_SNOC_CNOC_LOOP_PROTECTION_DISABLE_SHFT,
+ IPA_COMP_CFG_GEN_QMB_0_SNOC_CNOC_LOOP_PROTECTION_DISABLE_BMSK);
+
+ comp_cfg->gen_qmb_1_multi_inorder_wr_dis =
+ IPA_GETFIELD_FROM_REG(val,
+ IPA_COMP_CFG_GEN_QMB_1_MULTI_INORDER_WR_DIS_SHFT,
+ IPA_COMP_CFG_GEN_QMB_1_MULTI_INORDER_WR_DIS_BMSK);
+
+ comp_cfg->gen_qmb_0_multi_inorder_wr_dis =
+ IPA_GETFIELD_FROM_REG(val,
+ IPA_COMP_CFG_GEN_QMB_0_MULTI_INORDER_WR_DIS_SHFT,
+ IPA_COMP_CFG_GEN_QMB_0_MULTI_INORDER_WR_DIS_BMSK);
+
+ comp_cfg->gen_qmb_1_multi_inorder_rd_dis =
+ IPA_GETFIELD_FROM_REG(val,
+ IPA_COMP_CFG_GEN_QMB_1_MULTI_INORDER_RD_DIS_SHFT,
+ IPA_COMP_CFG_GEN_QMB_1_MULTI_INORDER_RD_DIS_BMSK);
+
+ comp_cfg->gen_qmb_0_multi_inorder_rd_dis =
+ IPA_GETFIELD_FROM_REG(val,
+ IPA_COMP_CFG_GEN_QMB_0_MULTI_INORDER_RD_DIS_SHFT,
+ IPA_COMP_CFG_GEN_QMB_0_MULTI_INORDER_RD_DIS_BMSK);
+
+ comp_cfg->gsi_multi_inorder_wr_dis =
+ IPA_GETFIELD_FROM_REG(val,
+ IPA_COMP_CFG_GSI_MULTI_INORDER_WR_DIS_SHFT,
+ IPA_COMP_CFG_GSI_MULTI_INORDER_WR_DIS_BMSK);
+
+ comp_cfg->gsi_multi_inorder_rd_dis =
+ IPA_GETFIELD_FROM_REG(val,
+ IPA_COMP_CFG_GSI_MULTI_INORDER_RD_DIS_SHFT,
+ IPA_COMP_CFG_GSI_MULTI_INORDER_RD_DIS_BMSK);
+
+ comp_cfg->ipa_qmb_select_by_address_prod_en =
+ IPA_GETFIELD_FROM_REG(val,
+ IPA_COMP_CFG_IPA_QMB_SELECT_BY_ADDRESS_PROD_EN_SHFT,
+ IPA_COMP_CFG_IPA_QMB_SELECT_BY_ADDRESS_PROD_EN_BMSK);
+
+ comp_cfg->ipa_qmb_select_by_address_cons_en =
+ IPA_GETFIELD_FROM_REG(val,
+ IPA_COMP_CFG_IPA_QMB_SELECT_BY_ADDRESS_CONS_EN_SHFT,
+ IPA_COMP_CFG_IPA_QMB_SELECT_BY_ADDRESS_CONS_EN_BMSK);
+
+ comp_cfg->ipa_dcmp_fast_clk_en =
+ IPA_GETFIELD_FROM_REG(val,
+ IPA_COMP_CFG_IPA_DCMP_FAST_CLK_EN_SHFT,
+ IPA_COMP_CFG_IPA_DCMP_FAST_CLK_EN_BMSK);
+
+ comp_cfg->gen_qmb_1_snoc_bypass_dis =
+ IPA_GETFIELD_FROM_REG(val,
+ IPA_COMP_CFG_GEN_QMB_1_SNOC_BYPASS_DIS_SHFT,
+ IPA_COMP_CFG_GEN_QMB_1_SNOC_BYPASS_DIS_BMSK);
+
+ comp_cfg->gen_qmb_0_snoc_bypass_dis =
+ IPA_GETFIELD_FROM_REG(val,
+ IPA_COMP_CFG_GEN_QMB_0_SNOC_BYPASS_DIS_SHFT,
+ IPA_COMP_CFG_GEN_QMB_0_SNOC_BYPASS_DIS_BMSK);
+
+ comp_cfg->gsi_snoc_bypass_dis =
+ IPA_GETFIELD_FROM_REG(val,
+ IPA_COMP_CFG_GSI_SNOC_BYPASS_DIS_SHFT,
+ IPA_COMP_CFG_GSI_SNOC_BYPASS_DIS_BMSK);
+
+ comp_cfg->enable =
+ IPA_GETFIELD_FROM_REG(val,
+ IPA_COMP_CFG_ENABLE_SHFT,
+ IPA_COMP_CFG_ENABLE_BMSK);
+}
+
static void ipareg_construct_qcncm(
enum ipahal_reg_name reg, const void *fields, u32 *val)
{
@@ -1518,7 +1714,7 @@
ipareg_construct_dummy, ipareg_parse_dummy,
0x00005094, 0},
[IPA_HW_v3_0][IPA_COMP_CFG] = {
- ipareg_construct_dummy, ipareg_parse_dummy,
+ ipareg_construct_comp_cfg, ipareg_parse_comp_cfg,
0x0000003C, 0},
[IPA_HW_v3_0][IPA_STATE_AGGR_ACTIVE] = {
ipareg_construct_dummy, ipareg_parse_dummy,
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 98481a1..2675771 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h
@@ -240,6 +240,34 @@
};
/*
+ * struct ipahal_reg_comp_cfg- IPA Core QMB/Master Port selection
+ *
+ * @all: QMB/Master port selection policy is configured via IPA_COMP_CFG
+ * - Address based Selection
+ * - Endpoint based selection / Legacy Mode
+ */
+struct ipahal_reg_comp_cfg {
+ bool ipa_atomic_fetcher_arb_lock_dis;
+ bool ipa_qmb_select_by_address_global_en;
+ bool gsi_multi_axi_masters_dis;
+ bool gsi_snoc_cnoc_loop_protection_disable;
+ bool gen_qmb_0_snoc_cnoc_loop_protection_disable;
+ bool gen_qmb_1_multi_inorder_wr_dis;
+ bool gen_qmb_0_multi_inorder_wr_dis;
+ bool gen_qmb_1_multi_inorder_rd_dis;
+ bool gen_qmb_0_multi_inorder_rd_dis;
+ bool gsi_multi_inorder_wr_dis;
+ bool gsi_multi_inorder_rd_dis;
+ bool ipa_qmb_select_by_address_prod_en;
+ bool ipa_qmb_select_by_address_cons_en;
+ bool ipa_dcmp_fast_clk_en;
+ bool gen_qmb_1_snoc_bypass_dis;
+ bool gen_qmb_0_snoc_bypass_dis;
+ bool gsi_snoc_bypass_dis;
+ bool enable;
+};
+
+/*
* struct ipa_hash_tuple - Hash tuple members for flt and rt
* the fields tells if to be masked or not
* @src_id: pipe number for flt, table index for rt
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg_i.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg_i.h
index 35a36e1..38a17bd 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg_i.h
@@ -422,4 +422,42 @@
#define IPA_HPS_FTCH_ARB_QUEUE_WEIGHTS_RX_HPS_QUEUE_WEIGHT_3_BMSK (0xf000)
#define IPA_HPS_FTCH_ARB_QUEUE_WEIGHTS_RX_HPS_QUEUE_WEIGHT_3_SHFT (0xc)
+/* IPA_COMP_CFG register*/
+#define IPA_COMP_CFG_IPA_ATOMIC_FETCHER_ARB_LOCK_DIS_BMSK 0x1E0000
+#define IPA_COMP_CFG_IPA_ATOMIC_FETCHER_ARB_LOCK_DIS_SHFT 17
+#define IPA_COMP_CFG_IPA_QMB_SELECT_BY_ADDRESS_GLOBAL_EN_BMSK 0x10000
+#define IPA_COMP_CFG_IPA_QMB_SELECT_BY_ADDRESS_GLOBAL_EN_SHFT 16
+#define IPA_COMP_CFG_GSI_MULTI_AXI_MASTERS_DIS_BMSK 0x8000
+#define IPA_COMP_CFG_GSI_MULTI_AXI_MASTERS_DIS_SHFT 15
+#define IPA_COMP_CFG_GSI_SNOC_CNOC_LOOP_PROTECTION_DISABLE_BMSK 0x4000
+#define IPA_COMP_CFG_GSI_SNOC_CNOC_LOOP_PROTECTION_DISABLE_SHFT 14
+#define IPA_COMP_CFG_GEN_QMB_0_SNOC_CNOC_LOOP_PROTECTION_DISABLE_BMSK 0x2000
+#define IPA_COMP_CFG_GEN_QMB_0_SNOC_CNOC_LOOP_PROTECTION_DISABLE_SHFT 13
+#define IPA_COMP_CFG_GEN_QMB_1_MULTI_INORDER_WR_DIS_BMSK 0x1000
+#define IPA_COMP_CFG_GEN_QMB_1_MULTI_INORDER_WR_DIS_SHFT 12
+#define IPA_COMP_CFG_GEN_QMB_0_MULTI_INORDER_WR_DIS_BMSK 0x800
+#define IPA_COMP_CFG_GEN_QMB_0_MULTI_INORDER_WR_DIS_SHFT 11
+#define IPA_COMP_CFG_GEN_QMB_1_MULTI_INORDER_RD_DIS_BMSK 0x400
+#define IPA_COMP_CFG_GEN_QMB_1_MULTI_INORDER_RD_DIS_SHFT 10
+#define IPA_COMP_CFG_GEN_QMB_0_MULTI_INORDER_RD_DIS_BMSK 0x200
+#define IPA_COMP_CFG_GEN_QMB_0_MULTI_INORDER_RD_DIS_SHFT 9
+#define IPA_COMP_CFG_GSI_MULTI_INORDER_WR_DIS_BMSK 0x100
+#define IPA_COMP_CFG_GSI_MULTI_INORDER_WR_DIS_SHFT 8
+#define IPA_COMP_CFG_GSI_MULTI_INORDER_RD_DIS_BMSK 0x80
+#define IPA_COMP_CFG_GSI_MULTI_INORDER_RD_DIS_SHFT 7
+#define IPA_COMP_CFG_IPA_QMB_SELECT_BY_ADDRESS_PROD_EN_BMSK 0x40
+#define IPA_COMP_CFG_IPA_QMB_SELECT_BY_ADDRESS_PROD_EN_SHFT 6
+#define IPA_COMP_CFG_IPA_QMB_SELECT_BY_ADDRESS_CONS_EN_BMSK 0x20
+#define IPA_COMP_CFG_IPA_QMB_SELECT_BY_ADDRESS_CONS_EN_SHFT 5
+#define IPA_COMP_CFG_IPA_DCMP_FAST_CLK_EN_BMSK 0x10
+#define IPA_COMP_CFG_IPA_DCMP_FAST_CLK_EN_SHFT 4
+#define IPA_COMP_CFG_GEN_QMB_1_SNOC_BYPASS_DIS_BMSK 0x8
+#define IPA_COMP_CFG_GEN_QMB_1_SNOC_BYPASS_DIS_SHFT 3
+#define IPA_COMP_CFG_GEN_QMB_0_SNOC_BYPASS_DIS_BMSK 0x4
+#define IPA_COMP_CFG_GEN_QMB_0_SNOC_BYPASS_DIS_SHFT 2
+#define IPA_COMP_CFG_GSI_SNOC_BYPASS_DIS_BMSK 0x2
+#define IPA_COMP_CFG_GSI_SNOC_BYPASS_DIS_SHFT 1
+#define IPA_COMP_CFG_ENABLE_BMSK 0x1
+#define IPA_COMP_CFG_ENABLE_SHFT 0
+
#endif /* _IPAHAL_REG_I_H_ */
diff --git a/drivers/platform/msm/mhi_dev/mhi.c b/drivers/platform/msm/mhi_dev/mhi.c
index c2187c6..47d5292 100644
--- a/drivers/platform/msm/mhi_dev/mhi.c
+++ b/drivers/platform/msm/mhi_dev/mhi.c
@@ -71,11 +71,12 @@
static void mhi_hwc_cb(void *priv, enum ipa_mhi_event_type event,
unsigned long data);
static void mhi_ring_init_cb(void *user_data);
-static void mhi_update_state_info(uint32_t info);
+static void mhi_update_state_info(uint32_t uevent_idx, enum mhi_ctrl_info info);
static int mhi_deinit(struct mhi_dev *mhi);
static void mhi_dev_resume_init_with_link_up(struct ep_pcie_notify *notify);
static int mhi_dev_pcie_notify_event;
static void mhi_dev_transfer_completion_cb(void *mreq);
+static struct mhi_dev_uevent_info channel_state_info[MHI_MAX_CHANNELS];
/*
* mhi_dev_ring_cache_completion_cb () - Call back function called
@@ -454,7 +455,7 @@
return;
}
- mhi_update_state_info(MHI_STATE_CONNECTED);
+ mhi_update_state_info(MHI_DEV_UEVENT_CTRL, MHI_STATE_CONNECTED);
ep_pcie_mask_irq_event(mhi_ctx->phandle,
EP_PCIE_INT_EVT_MHI_A7, true);
@@ -825,16 +826,14 @@
static void mhi_dev_trigger_cb(void)
{
struct mhi_dev_ready_cb_info *info;
- uint32_t state_data;
+ enum mhi_ctrl_info state_data;
- mutex_lock(&mhi_ctx->mhi_lock);
list_for_each_entry(info, &mhi_ctx->client_cb_list, list)
if (info->cb) {
- mhi_ctrl_state_info(&state_data);
+ mhi_ctrl_state_info(info->cb_data.channel, &state_data);
info->cb_data.ctrl_info = state_data;
info->cb(&info->cb_data);
}
- mutex_unlock(&mhi_ctx->mhi_lock);
}
int mhi_dev_trigger_hw_acc_wakeup(struct mhi_dev *mhi)
@@ -855,11 +854,18 @@
}
EXPORT_SYMBOL(mhi_dev_trigger_hw_acc_wakeup);
-static int mhi_dev_send_cmd_comp_event(struct mhi_dev *mhi)
+static int mhi_dev_send_cmd_comp_event(struct mhi_dev *mhi,
+ enum mhi_dev_cmd_completion_code code)
{
int rc = 0;
union mhi_dev_ring_element_type event;
+ if (code > MHI_CMD_COMPL_CODE_RES) {
+ mhi_log(MHI_MSG_ERROR,
+ "Invalid cmd compl code: %d\n", code);
+ return -EINVAL;
+ }
+
/* send the command completion event to the host */
event.evt_cmd_comp.ptr = mhi->cmd_ctx_cache->rbase
+ (mhi->ring[MHI_RING_CMD_ID].rd_offset *
@@ -867,11 +873,10 @@
mhi_log(MHI_MSG_VERBOSE, "evt cmd comp ptr :%d\n",
(uint32_t) event.evt_cmd_comp.ptr);
event.evt_cmd_comp.type = MHI_DEV_RING_EL_CMD_COMPLETION_EVT;
- event.evt_cmd_comp.code = MHI_CMD_COMPL_CODE_SUCCESS;
-
+ event.evt_cmd_comp.code = code;
rc = mhi_dev_send_event(mhi, 0, &event);
if (rc)
- pr_err("channel start command faied\n");
+ mhi_log(MHI_MSG_ERROR, "Send completion failed\n");
return rc;
}
@@ -914,7 +919,8 @@
mhi_dev_write_to_host(mhi, &data_transfer, NULL, MHI_DEV_DMA_SYNC);
/* send the completion event to the host */
- rc = mhi_dev_send_cmd_comp_event(mhi);
+ rc = mhi_dev_send_cmd_comp_event(mhi,
+ MHI_CMD_COMPL_CODE_SUCCESS);
if (rc)
pr_err("Error sending command completion event\n");
@@ -930,6 +936,8 @@
struct mhi_addr host_addr;
struct mhi_dev_channel *ch;
struct mhi_dev_ring *ring;
+ char *connected[2] = { "MHI_CHANNEL_STATE_12=CONNECTED", NULL};
+ char *disconnected[2] = { "MHI_CHANNEL_STATE_12=DISCONNECTED", NULL};
ch_id = el->generic.chid;
mhi_log(MHI_MSG_VERBOSE, "for channel:%d and cmd:%d\n",
@@ -942,7 +950,13 @@
if (ch_id >= (HW_CHANNEL_BASE)) {
rc = mhi_hwc_chcmd(mhi, ch_id, el->generic.type);
if (rc) {
- pr_err("Error with HW channel cmd :%d\n", rc);
+ mhi_log(MHI_MSG_ERROR,
+ "Error with HW channel cmd %d\n", rc);
+ rc = mhi_dev_send_cmd_comp_event(mhi,
+ MHI_CMD_COMPL_CODE_UNDEFINED);
+ if (rc)
+ mhi_log(MHI_MSG_ERROR,
+ "Error with compl event\n");
return;
}
goto send_start_completion_event;
@@ -958,6 +972,11 @@
if (rc) {
mhi_log(MHI_MSG_ERROR,
"start ring failed for ch %d\n", ch_id);
+ rc = mhi_dev_send_cmd_comp_event(mhi,
+ MHI_CMD_COMPL_CODE_UNDEFINED);
+ if (rc)
+ mhi_log(MHI_MSG_ERROR,
+ "Error with compl event\n");
return;
}
@@ -975,6 +994,11 @@
rc = mhi_dev_mmio_enable_chdb_a7(mhi, ch_id);
if (rc) {
pr_err("Failed to enable channel db\n");
+ rc = mhi_dev_send_cmd_comp_event(mhi,
+ MHI_CMD_COMPL_CODE_UNDEFINED);
+ if (rc)
+ mhi_log(MHI_MSG_ERROR,
+ "Error with compl event\n");
return;
}
@@ -991,22 +1015,25 @@
mhi_dev_write_to_host(mhi, &host_addr, NULL, MHI_DEV_DMA_SYNC);
send_start_completion_event:
- rc = mhi_dev_send_cmd_comp_event(mhi);
+ rc = mhi_dev_send_cmd_comp_event(mhi,
+ MHI_CMD_COMPL_CODE_SUCCESS);
if (rc)
pr_err("Error sending command completion event\n");
/* Trigger callback to clients */
mhi_dev_trigger_cb();
+ mhi_update_state_info(ch_id, MHI_STATE_CONNECTED);
+ if (ch_id == MHI_CLIENT_MBIM_OUT)
+ kobject_uevent_env(&mhi_ctx->dev->kobj,
+ KOBJ_CHANGE, connected);
break;
case MHI_DEV_RING_EL_STOP:
if (ch_id >= HW_CHANNEL_BASE) {
rc = mhi_hwc_chcmd(mhi, ch_id, el->generic.type);
- if (rc) {
+ if (rc)
mhi_log(MHI_MSG_ERROR,
"send channel stop cmd event failed\n");
- return;
- }
/* send the completion event to the host */
event.evt_cmd_comp.ptr = mhi->cmd_ctx_cache->rbase +
@@ -1052,6 +1079,10 @@
pr_err("stop event send failed\n");
mutex_unlock(&ch->ch_lock);
+ mhi_update_state_info(ch_id, MHI_STATE_DISCONNECTED);
+ if (ch_id == MHI_CLIENT_MBIM_OUT)
+ kobject_uevent_env(&mhi_ctx->dev->kobj,
+ KOBJ_CHANGE, disconnected);
}
break;
case MHI_DEV_RING_EL_RESET:
@@ -1059,11 +1090,9 @@
"received reset cmd for channel %d\n", ch_id);
if (ch_id >= HW_CHANNEL_BASE) {
rc = mhi_hwc_chcmd(mhi, ch_id, el->generic.type);
- if (rc) {
+ if (rc)
mhi_log(MHI_MSG_ERROR,
"send channel stop cmd event failed\n");
- return;
- }
/* send the completion event to the host */
event.evt_cmd_comp.ptr = mhi->cmd_ctx_cache->rbase +
@@ -1121,10 +1150,15 @@
MHI_DEV_DMA_SYNC);
/* send the completion event to the host */
- rc = mhi_dev_send_cmd_comp_event(mhi);
+ rc = mhi_dev_send_cmd_comp_event(mhi,
+ MHI_CMD_COMPL_CODE_SUCCESS);
if (rc)
pr_err("Error sending command completion event\n");
mutex_unlock(&ch->ch_lock);
+ mhi_update_state_info(ch_id, MHI_STATE_DISCONNECTED);
+ if (ch_id == MHI_CLIENT_MBIM_OUT)
+ kobject_uevent_env(&mhi_ctx->dev->kobj,
+ KOBJ_CHANGE, disconnected);
}
break;
default:
@@ -1306,7 +1340,7 @@
}
/* Update ctrl node */
- mhi_update_state_info(MHI_STATE_DISCONNECTED);
+ mhi_update_state_info(MHI_DEV_UEVENT_CTRL, MHI_STATE_DISCONNECTED);
flush_workqueue(mhi->ring_init_wq);
flush_workqueue(mhi->pending_ring_wq);
@@ -1787,7 +1821,7 @@
mhi_dev_write_to_host(mhi, &data_transfer, NULL,
MHI_DEV_DMA_SYNC);
}
- mhi_update_state_info(MHI_STATE_CONNECTED);
+ mhi_update_state_info(MHI_DEV_UEVENT_CTRL, MHI_STATE_CONNECTED);
atomic_set(&mhi->is_suspended, 0);
@@ -2348,7 +2382,7 @@
if (mhi_ctx->config_iatu || mhi_ctx->mhi_int)
enable_irq(mhi_ctx->mhi_irq);
- mhi_update_state_info(MHI_STATE_CONNECTED);
+ mhi_update_state_info(MHI_DEV_UEVENT_CTRL, MHI_STATE_CONFIGURED);
}
static void mhi_ring_init_cb(void *data)
@@ -2408,28 +2442,32 @@
}
EXPORT_SYMBOL(mhi_register_state_cb);
-static void mhi_update_state_info(uint32_t info)
+static void mhi_update_state_info(uint32_t uevent_idx, enum mhi_ctrl_info info)
{
struct mhi_dev_client_cb_reason reason;
- mhi_ctx->ctrl_info = info;
+ if (uevent_idx == MHI_DEV_UEVENT_CTRL)
+ mhi_ctx->ctrl_info = info;
- if (info == MHI_STATE_CONNECTED)
- return;
+ channel_state_info[uevent_idx].ctrl_info = info;
- reason.reason = MHI_DEV_CTRL_UPDATE;
- uci_ctrl_update(&reason);
-}
-
-int mhi_ctrl_state_info(uint32_t *info)
-{
- if (!info) {
- pr_err("Invalid info\n");
- return -EINVAL;
+ if (uevent_idx == MHI_CLIENT_QMI_OUT ||
+ uevent_idx == MHI_CLIENT_QMI_IN) {
+ /* For legacy reasons for QTI client */
+ reason.reason = MHI_DEV_CTRL_UPDATE;
+ uci_ctrl_update(&reason);
}
- *info = mhi_ctx->ctrl_info;
- mhi_log(MHI_MSG_VERBOSE, "ctrl:%d", mhi_ctx->ctrl_info);
+}
+
+int mhi_ctrl_state_info(uint32_t idx, uint32_t *info)
+{
+ if (idx == MHI_DEV_UEVENT_CTRL)
+ *info = mhi_ctx->ctrl_info;
+ else
+ *info = channel_state_info[idx].ctrl_info;
+
+ mhi_log(MHI_MSG_VERBOSE, "idx:%d, ctrl:%d", idx, *info);
return 0;
}
@@ -2924,7 +2962,8 @@
"Failed to create IPC logging context\n");
}
mhi_uci_init();
- mhi_update_state_info(MHI_STATE_CONFIGURED);
+ mhi_update_state_info(MHI_DEV_UEVENT_CTRL,
+ MHI_STATE_CONFIGURED);
}
INIT_WORK(&mhi_ctx->pcie_event, mhi_dev_pcie_handle_event);
diff --git a/drivers/platform/msm/mhi_dev/mhi.h b/drivers/platform/msm/mhi_dev/mhi.h
index 38e52e2..b9120fc 100644
--- a/drivers/platform/msm/mhi_dev/mhi.h
+++ b/drivers/platform/msm/mhi_dev/mhi.h
@@ -275,7 +275,7 @@
#define MHI_ENV_VALUE 2
#define MHI_MASK_ROWS_CH_EV_DB 4
#define TRB_MAX_DATA_SIZE 8192
-#define MHI_CTRL_STATE 25
+#define MHI_CTRL_STATE 100
#define IPA_DMA_SYNC 1
#define IPA_DMA_ASYNC 0
@@ -607,6 +607,8 @@
bool mhi_int;
/* Registered client callback list */
struct list_head client_cb_list;
+
+ struct kobj_uevent_env kobj_env;
};
struct mhi_req {
@@ -712,6 +714,14 @@
MHI_MAX_CHANNELS = 102,
};
+/* Use ID 0 for legacy /dev/mhi_ctrl. Channel 0 is used for internal only */
+#define MHI_DEV_UEVENT_CTRL 0
+
+struct mhi_dev_uevent_info {
+ enum mhi_client_channel channel;
+ enum mhi_ctrl_info ctrl_info;
+};
+
struct mhi_dev_iov {
void *addr;
uint32_t buf_size;
@@ -1251,6 +1261,9 @@
/**
* mhi_ctrl_state_info() - Provide MHI state info
+ * @idx: Channel number idx. Look at channel_state_info and
+ * pass the index for the corresponding channel.
+ * @info: Return the control info.
* MHI_STATE=CONFIGURED - MHI device is present but not ready
* for data traffic.
* MHI_STATE=CONNECTED - MHI device is ready for data transfer.
@@ -1258,7 +1271,7 @@
* exposes device nodes for the supported MHI software
* channels.
*/
-int mhi_ctrl_state_info(uint32_t *info);
+int mhi_ctrl_state_info(uint32_t idx, uint32_t *info);
/**
* uci_ctrl_update() - Update UCI once TRE's are available for clients to
diff --git a/drivers/platform/msm/mhi_dev/mhi_uci.c b/drivers/platform/msm/mhi_dev/mhi_uci.c
index 244cf04..ed02d0d 100644
--- a/drivers/platform/msm/mhi_dev/mhi_uci.c
+++ b/drivers/platform/msm/mhi_dev/mhi_uci.c
@@ -441,6 +441,61 @@
return rc;
}
+static void mhi_parse_state(char *buf, int *nbytes, uint32_t info)
+{
+ switch (info) {
+ case MHI_STATE_CONNECTED:
+ *nbytes = scnprintf(buf, MHI_CTRL_STATE,
+ "CONNECTED");
+ break;
+ case MHI_STATE_DISCONNECTED:
+ *nbytes = scnprintf(buf, MHI_CTRL_STATE,
+ "DISCONNECTED");
+ break;
+ case MHI_STATE_CONFIGURED:
+ default:
+ *nbytes = scnprintf(buf, MHI_CTRL_STATE,
+ "CONFIGURED");
+ break;
+ }
+}
+
+static int mhi_state_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+ int rc, nbytes = 0;
+ uint32_t info = 0;
+ char buf[MHI_CTRL_STATE];
+
+ rc = mhi_ctrl_state_info(MHI_DEV_UEVENT_CTRL, &info);
+ if (rc) {
+ pr_err("Failed to obtain MHI_STATE\n");
+ return -EINVAL;
+ }
+
+ mhi_parse_state(buf, &nbytes, info);
+ add_uevent_var(env, "MHI_STATE=%s", buf);
+
+ rc = mhi_ctrl_state_info(MHI_CLIENT_QMI_OUT, &info);
+ if (rc) {
+ pr_err("Failed to obtain channel 14 state\n");
+ return -EINVAL;
+ }
+ nbytes = 0;
+ mhi_parse_state(buf, &nbytes, info);
+ add_uevent_var(env, "MHI_CHANNEL_STATE_14=%s", buf);
+
+ rc = mhi_ctrl_state_info(MHI_CLIENT_MBIM_OUT, &info);
+ if (rc) {
+ pr_err("Failed to obtain channel 12 state\n");
+ return -EINVAL;
+ }
+ nbytes = 0;
+ mhi_parse_state(buf, &nbytes, info);
+ add_uevent_var(env, "MHI_CHANNEL_STATE_12=%s", buf);
+
+ return 0;
+}
+
static ssize_t mhi_uci_ctrl_client_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *offp)
@@ -455,7 +510,7 @@
return -EINVAL;
uci_ctrl_handle = file->private_data;
- rc = mhi_ctrl_state_info(&info);
+ rc = mhi_ctrl_state_info(MHI_CLIENT_QMI_OUT, &info);
if (rc)
return -EINVAL;
@@ -993,6 +1048,8 @@
uci_ctxt.cdev_ctrl = NULL;
}
+ uci_ctxt.mhi_uci_class->dev_uevent = mhi_state_uevent;
+
return 0;
failed_char_add:
diff --git a/drivers/platform/msm/sps/sps.c b/drivers/platform/msm/sps/sps.c
index e01839f..6e54fbf 100644
--- a/drivers/platform/msm/sps/sps.c
+++ b/drivers/platform/msm/sps/sps.c
@@ -2336,8 +2336,11 @@
mutex_lock(&bam->lock);
sps_bam_device_de_init(bam);
mutex_unlock(&bam->lock);
+ ipc_log_context_destroy(bam->ipc_log0);
ipc_log_context_destroy(bam->ipc_log1);
ipc_log_context_destroy(bam->ipc_log2);
+ ipc_log_context_destroy(bam->ipc_log3);
+ ipc_log_context_destroy(bam->ipc_log4);
if (bam->props.virt_size)
(void)iounmap(bam->props.virt_addr);
diff --git a/drivers/power/supply/power_supply_sysfs.c b/drivers/power/supply/power_supply_sysfs.c
index f4a36a3..35c8bb9 100644
--- a/drivers/power/supply/power_supply_sysfs.c
+++ b/drivers/power/supply/power_supply_sysfs.c
@@ -327,6 +327,7 @@
POWER_SUPPLY_ATTR(batt_profile_version),
POWER_SUPPLY_ATTR(batt_full_current),
POWER_SUPPLY_ATTR(recharge_soc),
+ POWER_SUPPLY_ATTR(toggle_stat),
/* Local extensions of type int64_t */
POWER_SUPPLY_ATTR(charge_counter_ext),
/* Properties of type `const char *' */
diff --git a/drivers/power/supply/qcom/Kconfig b/drivers/power/supply/qcom/Kconfig
index e653475..e571eb4 100644
--- a/drivers/power/supply/qcom/Kconfig
+++ b/drivers/power/supply/qcom/Kconfig
@@ -124,4 +124,12 @@
to determine the battery state-of-charge (SOC) and supports other
battery management features.
+config SMB1390_CHARGE_PUMP
+ tristate "SMB1390 Charge Pump"
+ depends on MFD_I2C_PMIC
+ help
+ Say Y to include support for SMB1390 Charge Pump.
+ SMB1390 is a div2 charge pump capable of delivering 6A charge current
+ with very high efficiency.
+
endmenu
diff --git a/drivers/power/supply/qcom/Makefile b/drivers/power/supply/qcom/Makefile
index 662f18d..de76a5b 100644
--- a/drivers/power/supply/qcom/Makefile
+++ b/drivers/power/supply/qcom/Makefile
@@ -10,3 +10,4 @@
obj-$(CONFIG_QPNP_QNOVO) += qpnp-qnovo.o battery.o
obj-$(CONFIG_QPNP_TYPEC) += qpnp-typec.o
obj-$(CONFIG_QPNP_SMB5) += step-chg-jeita.o battery.o qpnp-smb5.o smb5-lib.o pmic-voter.o storm-watch.o schgm-flash.o
+obj-$(CONFIG_SMB1390_CHARGE_PUMP) += smb1390-charger.o pmic-voter.o
diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c
index f9a29aa..ccc0d5d 100644
--- a/drivers/power/supply/qcom/qpnp-smb2.c
+++ b/drivers/power/supply/qcom/qpnp-smb2.c
@@ -716,6 +716,7 @@
POWER_SUPPLY_PROP_INPUT_VOLTAGE_SETTLED,
POWER_SUPPLY_PROP_FCC_DELTA,
POWER_SUPPLY_PROP_CURRENT_MAX,
+ POWER_SUPPLY_PROP_TOGGLE_STAT,
/*
* TODO move the TEMP and TEMP_MAX properties here,
* and update the thermal balancer to look here
@@ -753,6 +754,9 @@
case POWER_SUPPLY_PROP_CURRENT_MAX:
rc = smblib_get_icl_current(chg, &val->intval);
break;
+ case POWER_SUPPLY_PROP_TOGGLE_STAT:
+ val->intval = 0;
+ break;
default:
pr_debug("get prop %d is not supported in usb-main\n", psp);
rc = -EINVAL;
@@ -783,6 +787,9 @@
case POWER_SUPPLY_PROP_CURRENT_MAX:
rc = smblib_set_icl_current(chg, val->intval);
break;
+ case POWER_SUPPLY_PROP_TOGGLE_STAT:
+ rc = smblib_toggle_stat(chg, val->intval);
+ break;
default:
pr_err("set prop %d is not supported\n", psp);
rc = -EINVAL;
@@ -792,6 +799,23 @@
return rc;
}
+static int smb2_usb_main_prop_is_writeable(struct power_supply *psy,
+ enum power_supply_property psp)
+{
+ int rc;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_TOGGLE_STAT:
+ rc = 1;
+ break;
+ default:
+ rc = 0;
+ break;
+ }
+
+ return rc;
+}
+
static const struct power_supply_desc usb_main_psy_desc = {
.name = "main",
.type = POWER_SUPPLY_TYPE_MAIN,
@@ -799,6 +823,7 @@
.num_properties = ARRAY_SIZE(smb2_usb_main_props),
.get_property = smb2_usb_main_get_prop,
.set_property = smb2_usb_main_set_prop,
+ .property_is_writeable = smb2_usb_main_prop_is_writeable,
};
static int smb2_init_usb_main_psy(struct smb2 *chip)
diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c
index b91850d..20dd78e 100644
--- a/drivers/power/supply/qcom/qpnp-smb5.c
+++ b/drivers/power/supply/qcom/qpnp-smb5.c
@@ -1084,6 +1084,7 @@
{
int rc = 0;
struct smb_charger *chg = power_supply_get_drvdata(psy);
+ bool enable;
switch (prop) {
case POWER_SUPPLY_PROP_STATUS:
@@ -1106,11 +1107,16 @@
vote(chg->fv_votable, BATT_PROFILE_VOTER, true, val->intval);
break;
case POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED:
- chg->step_chg_enabled = !!val->intval;
+ enable = !!val->intval || chg->sw_jeita_enabled;
+ rc = smblib_configure_wdog(chg, enable);
+ if (rc == 0)
+ chg->step_chg_enabled = !!val->intval;
break;
case POWER_SUPPLY_PROP_SW_JEITA_ENABLED:
if (chg->sw_jeita_enabled != (!!val->intval)) {
rc = smblib_disable_hw_jeita(chg, !!val->intval);
+ enable = !!val->intval || chg->step_chg_enabled;
+ rc |= smblib_configure_wdog(chg, enable);
if (rc == 0)
chg->sw_jeita_enabled = !!val->intval;
}
@@ -1481,6 +1487,10 @@
return rc;
}
+ /*
+ * configure the one time watchdong periodic interval and
+ * disable "watchdog bite disable charging".
+ */
val = (ilog2(chip->dt.wd_bark_time / 16) << BARK_WDOG_TIMEOUT_SHIFT)
& BARK_WDOG_TIMEOUT_MASK;
val |= BITE_WDOG_TIMEOUT_8S;
@@ -1493,18 +1503,6 @@
return rc;
}
- /* enable WD BARK and enable it on plugin */
- rc = smblib_masked_write(chg, WD_CFG_REG,
- WATCHDOG_TRIGGER_AFP_EN_BIT |
- WDOG_TIMER_EN_ON_PLUGIN_BIT |
- BARK_WDOG_INT_EN_BIT,
- WDOG_TIMER_EN_ON_PLUGIN_BIT |
- BARK_WDOG_INT_EN_BIT);
- if (rc < 0) {
- pr_err("Couldn't configue WD config rc=%d\n", rc);
- return rc;
- }
-
/* configure float charger options */
switch (chip->dt.float_option) {
case FLOAT_DCP:
@@ -1643,6 +1641,14 @@
}
}
+ rc = smblib_configure_wdog(chg,
+ chg->step_chg_enabled || chg->sw_jeita_enabled);
+ if (rc < 0) {
+ dev_err(chg->dev, "Couldn't configure watchdog rc=%d\n",
+ rc);
+ return rc;
+ }
+
return rc;
}
@@ -1892,6 +1898,7 @@
[WDOG_BARK_IRQ] = {
.name = "wdog-bark",
.handler = wdog_bark_irq_handler,
+ .wake = true,
},
[AICL_FAIL_IRQ] = {
.name = "aicl-fail",
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c
index fe7ae5f..609005cc 100644
--- a/drivers/power/supply/qcom/smb-lib.c
+++ b/drivers/power/supply/qcom/smb-lib.c
@@ -1010,6 +1010,48 @@
return 0;
}
+int smblib_toggle_stat(struct smb_charger *chg, int reset)
+{
+ int rc = 0;
+
+ if (reset) {
+ rc = smblib_masked_write(chg, STAT_CFG_REG,
+ STAT_SW_OVERRIDE_CFG_BIT | STAT_SW_OVERRIDE_VALUE_BIT,
+ STAT_SW_OVERRIDE_CFG_BIT | 0);
+ if (rc < 0) {
+ smblib_err(chg,
+ "Couldn't pull STAT pin low rc=%d\n", rc);
+ return rc;
+ }
+
+ /*
+ * A minimum of 20us delay is expected before switching on STAT
+ * pin
+ */
+ usleep_range(20, 30);
+
+ rc = smblib_masked_write(chg, STAT_CFG_REG,
+ STAT_SW_OVERRIDE_CFG_BIT | STAT_SW_OVERRIDE_VALUE_BIT,
+ STAT_SW_OVERRIDE_CFG_BIT | STAT_SW_OVERRIDE_VALUE_BIT);
+ if (rc < 0) {
+ smblib_err(chg,
+ "Couldn't pull STAT pin high rc=%d\n", rc);
+ return rc;
+ }
+
+ rc = smblib_masked_write(chg, STAT_CFG_REG,
+ STAT_SW_OVERRIDE_CFG_BIT | STAT_SW_OVERRIDE_VALUE_BIT,
+ 0);
+ if (rc < 0) {
+ smblib_err(chg,
+ "Couldn't set hardware control rc=%d\n", rc);
+ return rc;
+ }
+ }
+
+ return rc;
+}
+
static int smblib_micro_usb_disable_power_role_switch(struct smb_charger *chg,
bool disable)
{
diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h
index 32f2b4d..141fa82 100644
--- a/drivers/power/supply/qcom/smb-lib.h
+++ b/drivers/power/supply/qcom/smb-lib.h
@@ -541,6 +541,7 @@
const union power_supply_propval *val);
int smblib_stat_sw_override_cfg(struct smb_charger *chg, bool override);
void smblib_usb_typec_change(struct smb_charger *chg);
+int smblib_toggle_stat(struct smb_charger *chg, int reset);
int smblib_init(struct smb_charger *chg);
int smblib_deinit(struct smb_charger *chg);
diff --git a/drivers/power/supply/qcom/smb1390-charger.c b/drivers/power/supply/qcom/smb1390-charger.c
new file mode 100644
index 0000000..636265b
--- /dev/null
+++ b/drivers/power/supply/qcom/smb1390-charger.c
@@ -0,0 +1,788 @@
+/* Copyright (c) 2017-18 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.
+ */
+
+#define pr_fmt(fmt) "SMB1390: %s: " fmt, __func__
+
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/pmic-voter.h>
+#include <linux/power_supply.h>
+#include <linux/qpnp/qpnp-adc.h>
+#include <linux/regmap.h>
+
+#define CORE_STATUS1_REG 0x1006
+#define WIN_OV_BIT BIT(0)
+#define WIN_UV_BIT BIT(1)
+#define EN_PIN_OUT_BIT BIT(2)
+#define LCM_AUTO_BIT BIT(3)
+#define LCM_PIN_BIT BIT(4)
+#define ILIM_BIT BIT(5)
+#define TEMP_ALARM_BIT BIT(6)
+#define VPH_OV_SOFT_BIT BIT(7)
+
+#define CORE_STATUS2_REG 0x1007
+#define SWITCHER_HOLD_OFF_BIT BIT(0)
+#define VPH_OV_HARD_BIT BIT(1)
+#define TSD_BIT BIT(2)
+#define IREV_BIT BIT(3)
+#define IOC_BIT BIT(4)
+#define VIN_UV_BIT BIT(5)
+#define VIN_OV_BIT BIT(6)
+#define EN_PIN_OUT2_BIT BIT(7)
+
+#define CORE_STATUS3_REG 0x1008
+#define EN_SL_BIT BIT(0)
+#define IIN_REF_SS_DONE_BIT BIT(1)
+#define FLYCAP_SS_DONE_BIT BIT(2)
+#define SL_DETECTED_BIT BIT(3)
+
+#define CORE_INT_RT_STS_REG 0x1010
+#define SWITCHER_OFF_WINDOW_STS_BIT BIT(0)
+#define SWITCHER_OFF_FAULT_STS_BIT BIT(1)
+#define TSD_STS_BIT BIT(2)
+#define IREV_STS_BIT BIT(3)
+#define VPH_OV_HARD_STS_BIT BIT(4)
+#define VPH_OV_SOFT_STS_BIT BIT(5)
+#define ILIM_STS_BIT BIT(6)
+#define TEMP_ALARM_STS_BIT BIT(7)
+
+#define CORE_CONTROL1_REG 0x1020
+#define CMD_EN_SWITCHER_BIT BIT(0)
+#define CMD_EN_SL_BIT BIT(1)
+
+#define CORE_FTRIM_ILIM_REG 0x1030
+#define CFG_ILIM_MASK GENMASK(4, 0)
+
+#define CP_VOTER "CP_VOTER"
+#define USER_VOTER "USER_VOTER"
+#define ILIM_VOTER "ILIM_VOTER"
+#define FCC_VOTER "FCC_VOTER"
+#define ICL_VOTER "ICL_VOTER"
+#define USB_VOTER "USB_VOTER"
+
+enum {
+ SWITCHER_OFF_WINDOW_IRQ = 0,
+ SWITCHER_OFF_FAULT_IRQ,
+ TSD_IRQ,
+ IREV_IRQ,
+ VPH_OV_HARD_IRQ,
+ VPH_OV_SOFT_IRQ,
+ ILIM_IRQ,
+ TEMP_ALARM_IRQ,
+ NUM_IRQS,
+};
+
+struct smb1390 {
+ struct device *dev;
+ struct regmap *regmap;
+ struct notifier_block nb;
+ struct class cp_class;
+
+ /* work structs */
+ struct work_struct status_change_work;
+ struct work_struct taper_work;
+
+ /* mutexes */
+ spinlock_t status_change_lock;
+
+ /* votables */
+ struct votable *disable_votable;
+ struct votable *ilim_votable;
+ struct votable *pl_disable_votable;
+ struct votable *fcc_votable;
+ struct votable *hvdcp_hw_inov_dis_votable;
+
+ /* power supplies */
+ struct power_supply *usb_psy;
+ struct power_supply *batt_psy;
+
+ struct qpnp_vadc_chip *vadc_dev;
+ int irqs[NUM_IRQS];
+ bool status_change_running;
+ bool taper_work_running;
+ int adc_channel;
+};
+
+struct smb_irq {
+ const char *name;
+ const irq_handler_t handler;
+ const bool wake;
+};
+
+static const struct smb_irq smb_irqs[];
+
+static int smb1390_read(struct smb1390 *chip, int reg, int *val)
+{
+ int rc;
+
+ rc = regmap_read(chip->regmap, reg, val);
+ if (rc < 0)
+ pr_err("Couldn't read 0x%04x\n", reg);
+
+ return rc;
+}
+
+static int smb1390_masked_write(struct smb1390 *chip, int reg, int mask,
+ int val)
+{
+ int rc;
+
+ pr_debug("Writing 0x%02x to 0x%04x with mask 0x%02x\n", val, reg, mask);
+ rc = regmap_update_bits(chip->regmap, reg, mask, val);
+ if (rc < 0)
+ pr_err("Couldn't write 0x%02x to 0x%04x with mask 0x%02x\n",
+ val, reg, mask);
+
+ return rc;
+}
+
+static bool is_psy_voter_available(struct smb1390 *chip)
+{
+ if (!chip->batt_psy) {
+ chip->batt_psy = power_supply_get_by_name("battery");
+ if (!chip->batt_psy) {
+ pr_debug("Couldn't find battery psy\n");
+ return false;
+ }
+ }
+
+ if (!chip->usb_psy) {
+ chip->usb_psy = power_supply_get_by_name("usb");
+ if (!chip->usb_psy) {
+ pr_debug("Couldn't find usb psy\n");
+ return false;
+ }
+ }
+
+ if (!chip->fcc_votable) {
+ chip->fcc_votable = find_votable("FCC");
+ if (!chip->fcc_votable) {
+ pr_debug("Couldn't find FCC votable\n");
+ return false;
+ }
+ }
+
+ if (!chip->pl_disable_votable) {
+ chip->pl_disable_votable = find_votable("PL_DISABLE");
+ if (!chip->pl_disable_votable) {
+ pr_debug("Couldn't find PL_DISABLE votable\n");
+ return false;
+ }
+ }
+
+ if (!chip->hvdcp_hw_inov_dis_votable) {
+ chip->hvdcp_hw_inov_dis_votable = find_votable("HVDCP_HW_INOV_DIS");
+ if (!chip->hvdcp_hw_inov_dis_votable) {
+ pr_debug("Couldn't find HVDCP_HW_INOV_DIS votable\n");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static irqreturn_t default_irq_handler(int irq, void *data)
+{
+ struct smb1390 *chip = data;
+ int i;
+
+ for (i = 0; i < NUM_IRQS; ++i) {
+ if (irq == chip->irqs[i])
+ pr_debug("%s IRQ triggered\n", smb_irqs[i].name);
+ }
+
+ kobject_uevent(&chip->dev->kobj, KOBJ_CHANGE);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t irev_irq_handler(int irq, void *data)
+{
+ struct smb1390 *chip = data;
+ int rc;
+
+ pr_debug("IREV IRQ triggered\n");
+
+ rc = smb1390_masked_write(chip, CORE_CONTROL1_REG,
+ CMD_EN_SWITCHER_BIT, 0);
+ if (rc < 0) {
+ pr_err("Couldn't disable switcher by command mode, rc=%d\n",
+ rc);
+ goto out;
+ }
+
+ rc = smb1390_masked_write(chip, CORE_CONTROL1_REG,
+ CMD_EN_SWITCHER_BIT, CMD_EN_SWITCHER_BIT);
+ if (rc < 0) {
+ pr_err("Couldn't enable switcher by command mode, rc=%d\n",
+ rc);
+ goto out;
+ }
+
+out:
+ kobject_uevent(&chip->dev->kobj, KOBJ_CHANGE);
+ return IRQ_HANDLED;
+}
+
+static const struct smb_irq smb_irqs[] = {
+ [SWITCHER_OFF_WINDOW_IRQ] = {
+ .name = "switcher-off-window",
+ .handler = default_irq_handler,
+ .wake = true,
+ },
+ [SWITCHER_OFF_FAULT_IRQ] = {
+ .name = "switcher-off-fault",
+ .handler = default_irq_handler,
+ .wake = true,
+ },
+ [TSD_IRQ] = {
+ .name = "tsd-fault",
+ .handler = default_irq_handler,
+ .wake = true,
+ },
+ [IREV_IRQ] = {
+ .name = "irev-fault",
+ .handler = irev_irq_handler,
+ .wake = true,
+ },
+ [VPH_OV_HARD_IRQ] = {
+ .name = "vph-ov-hard",
+ .handler = default_irq_handler,
+ .wake = true,
+ },
+ [VPH_OV_SOFT_IRQ] = {
+ .name = "vph-ov-soft",
+ .handler = default_irq_handler,
+ .wake = true,
+ },
+ [ILIM_IRQ] = {
+ .name = "ilim",
+ .handler = default_irq_handler,
+ .wake = true,
+ },
+ [TEMP_ALARM_IRQ] = {
+ .name = "temp-alarm",
+ .handler = default_irq_handler,
+ .wake = true,
+ },
+};
+
+/* SYSFS functions for reporting smb1390 charge pump state */
+static ssize_t stat1_show(struct class *c, struct class_attribute *attr,
+ char *buf)
+{
+ struct smb1390 *chip = container_of(c, struct smb1390, cp_class);
+ int rc, val;
+
+ rc = smb1390_read(chip, CORE_STATUS1_REG, &val);
+ if (rc < 0)
+ return -EINVAL;
+
+ return snprintf(buf, PAGE_SIZE, "%x\n", val);
+}
+
+static ssize_t stat2_show(struct class *c, struct class_attribute *attr,
+ char *buf)
+{
+ struct smb1390 *chip = container_of(c, struct smb1390, cp_class);
+ int rc, val;
+
+ rc = smb1390_read(chip, CORE_STATUS2_REG, &val);
+ if (rc < 0)
+ return -EINVAL;
+
+ return snprintf(buf, PAGE_SIZE, "%x\n", val);
+}
+
+static ssize_t enable_show(struct class *c, struct class_attribute *attr,
+ char *buf)
+{
+ struct smb1390 *chip = container_of(c, struct smb1390, cp_class);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ !get_effective_result(chip->disable_votable));
+}
+
+static ssize_t enable_store(struct class *c, struct class_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct smb1390 *chip = container_of(c, struct smb1390, cp_class);
+ unsigned long val;
+
+ if (kstrtoul(buf, 0, &val))
+ return -EINVAL;
+
+ vote(chip->disable_votable, USER_VOTER, !val, 0);
+ return count;
+}
+
+static ssize_t die_temp_show(struct class *c, struct class_attribute *attr,
+ char *buf)
+{
+ struct smb1390 *chip = container_of(c, struct smb1390, cp_class);
+ struct qpnp_vadc_result vadc_result;
+ int rc;
+
+ rc = qpnp_vadc_read(chip->vadc_dev, chip->adc_channel, &vadc_result);
+ if (rc < 0) {
+ pr_err("Couldn't read die temp rc=%d\n", rc);
+ return -EINVAL;
+ }
+
+ return snprintf(buf, PAGE_SIZE, "%lld\n", vadc_result.physical);
+}
+
+static struct class_attribute cp_class_attrs[] = {
+ __ATTR_RO(stat1),
+ __ATTR_RO(stat2),
+ __ATTR_RW(enable),
+ __ATTR_RO(die_temp),
+ __ATTR_NULL,
+};
+
+/* voter callbacks */
+static int smb1390_disable_vote_cb(struct votable *votable, void *data,
+ int disable, const char *client)
+{
+ struct smb1390 *chip = data;
+ int rc = 0;
+
+ if (!is_psy_voter_available(chip))
+ return -EAGAIN;
+
+ if (disable) {
+ rc = smb1390_masked_write(chip, CORE_CONTROL1_REG,
+ CMD_EN_SWITCHER_BIT, 0);
+ if (rc < 0)
+ return rc;
+
+ vote(chip->hvdcp_hw_inov_dis_votable, CP_VOTER, false, 0);
+ vote(chip->pl_disable_votable, CP_VOTER, false, 0);
+ } else {
+ vote(chip->hvdcp_hw_inov_dis_votable, CP_VOTER, true, 0);
+ vote(chip->pl_disable_votable, CP_VOTER, true, 0);
+ rc = smb1390_masked_write(chip, CORE_CONTROL1_REG,
+ CMD_EN_SWITCHER_BIT, CMD_EN_SWITCHER_BIT);
+ if (rc < 0)
+ return rc;
+ }
+ pr_debug("%s charge pump\n", disable ? "Disabled" : "Enabled");
+
+ /* charging may have been disabled by ILIM; send uevent */
+ kobject_uevent(&chip->dev->kobj, KOBJ_CHANGE);
+ return rc;
+}
+
+static int smb1390_ilim_vote_cb(struct votable *votable, void *data,
+ int ilim_uA, const char *client)
+{
+ struct smb1390 *chip = data;
+ int rc = 0;
+
+ if (!is_psy_voter_available(chip))
+ return -EAGAIN;
+
+ /* ILIM should always have at least one active vote */
+ if (!client) {
+ pr_err("Client missing\n");
+ return -EINVAL;
+ }
+
+ /* ILIM less than 1A is not accurate; disable charging */
+ if (ilim_uA < 1000000) {
+ pr_debug("ILIM %duA is too low to allow charging\n", ilim_uA);
+ vote(chip->disable_votable, ILIM_VOTER, true, 0);
+ } else {
+ pr_debug("setting ILIM to %duA\n", ilim_uA);
+ rc = smb1390_masked_write(chip, CORE_FTRIM_ILIM_REG,
+ CFG_ILIM_MASK,
+ DIV_ROUND_CLOSEST(ilim_uA - 500000, 100000));
+ if (rc < 0)
+ pr_err("Failed to write ILIM Register, rc=%d\n", rc);
+ else
+ vote(chip->disable_votable, ILIM_VOTER, false, 0);
+ }
+
+ return rc;
+}
+
+static int smb1390_notifier_cb(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ struct smb1390 *chip = container_of(nb, struct smb1390, nb);
+ struct power_supply *psy = data;
+ unsigned long flags;
+
+ if (event != PSY_EVENT_PROP_CHANGED)
+ return NOTIFY_OK;
+
+ if (strcmp(psy->desc->name, "battery") == 0
+ || strcmp(psy->desc->name, "usb") == 0
+ || strcmp(psy->desc->name, "main") == 0) {
+ spin_lock_irqsave(&chip->status_change_lock, flags);
+ if (!chip->status_change_running) {
+ chip->status_change_running = true;
+ pm_stay_awake(chip->dev);
+ schedule_work(&chip->status_change_work);
+ }
+ spin_unlock_irqrestore(&chip->status_change_lock, flags);
+ }
+
+ return NOTIFY_OK;
+}
+
+static void smb1390_status_change_work(struct work_struct *work)
+{
+ struct smb1390 *chip = container_of(work, struct smb1390,
+ status_change_work);
+ union power_supply_propval pval = {0, };
+ int rc;
+
+ if (!is_psy_voter_available(chip))
+ goto out;
+
+ /*
+ * Check for USB present status. The support for SMB1390 is
+ * limited to Type-C devices only, hence the check is limited
+ * to Type-C detection.
+ */
+ rc = power_supply_get_property(chip->usb_psy,
+ POWER_SUPPLY_PROP_TYPEC_MODE, &pval);
+ if (rc < 0) {
+ pr_err("Couldn't get usb present rc=%d\n", rc);
+ goto out;
+ }
+
+ if (pval.intval != POWER_SUPPLY_TYPEC_SOURCE_DEFAULT
+ && pval.intval != POWER_SUPPLY_TYPEC_SOURCE_MEDIUM
+ && pval.intval != POWER_SUPPLY_TYPEC_SOURCE_HIGH) {
+ vote(chip->disable_votable, USB_VOTER, true, 0);
+ vote(chip->fcc_votable, CP_VOTER, false, 0);
+ } else {
+ vote(chip->disable_votable, USB_VOTER, false, 0);
+
+ /*
+ * ILIM is set based on the primary chargers AICL result. This
+ * ensures VBUS does not collapse due to the current drawn via
+ * MID.
+ */
+ rc = power_supply_get_property(chip->usb_psy,
+ POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED, &pval);
+ if (rc < 0)
+ pr_err("Couldn't get usb icl rc=%d\n", rc);
+ else
+ vote(chip->ilim_votable, ICL_VOTER, true, pval.intval);
+
+ /* input current is always half the charge current */
+ vote(chip->ilim_votable, FCC_VOTER, true,
+ get_effective_result(chip->fcc_votable) / 2);
+
+ /*
+ * all votes that would result in disabling the charge pump have
+ * been cast; ensure the charhe pump is still enabled before
+ * continuing.
+ */
+ if (get_effective_result(chip->disable_votable))
+ goto out;
+
+ rc = power_supply_get_property(chip->batt_psy,
+ POWER_SUPPLY_PROP_CHARGE_TYPE, &pval);
+ if (rc < 0) {
+ pr_err("Couldn't get charge type rc=%d\n", rc);
+ } else if (pval.intval ==
+ POWER_SUPPLY_CHARGE_TYPE_TAPER) {
+ /*
+ * mutual exclusion is already guaranteed by
+ * chip->status_change_running
+ */
+ if (!chip->taper_work_running) {
+ chip->taper_work_running = true;
+ queue_work(system_long_wq,
+ &chip->taper_work);
+ }
+ }
+ }
+
+out:
+ pm_relax(chip->dev);
+ chip->status_change_running = false;
+}
+
+static void smb1390_taper_work(struct work_struct *work)
+{
+ struct smb1390 *chip = container_of(work, struct smb1390, taper_work);
+ union power_supply_propval pval = {0, };
+ int rc, fcc_uA;
+
+ if (!is_psy_voter_available(chip))
+ goto out;
+
+ do {
+ fcc_uA = get_effective_result(chip->fcc_votable) - 100000;
+ pr_debug("taper work reducing FCC to %duA\n", fcc_uA);
+ vote(chip->fcc_votable, CP_VOTER, true, fcc_uA);
+
+ rc = power_supply_get_property(chip->batt_psy,
+ POWER_SUPPLY_PROP_CHARGE_TYPE, &pval);
+ if (rc < 0) {
+ pr_err("Couldn't get charge type rc=%d\n", rc);
+ goto out;
+ }
+
+ msleep(500);
+ } while (fcc_uA >= 2000000
+ && pval.intval == POWER_SUPPLY_CHARGE_TYPE_TAPER);
+
+out:
+ pr_debug("taper work exit\n");
+ chip->taper_work_running = false;
+}
+
+static int smb1390_parse_dt(struct smb1390 *chip)
+{
+ int rc;
+
+ rc = of_property_read_u32(chip->dev->of_node, "qcom,channel-num",
+ &chip->adc_channel);
+ if (!rc) {
+ if (chip->adc_channel < 0 || chip->adc_channel >= ADC_MAX_NUM) {
+ pr_err("Invalid qcom,channel-num=%d specified\n",
+ chip->adc_channel);
+ return -EINVAL;
+ }
+ }
+
+ return rc;
+}
+
+static int smb1390_create_votables(struct smb1390 *chip)
+{
+ chip->disable_votable = create_votable("CP_DISABLE",
+ VOTE_SET_ANY, smb1390_disable_vote_cb, chip);
+ if (IS_ERR(chip->disable_votable))
+ return PTR_ERR(chip->disable_votable);
+
+ chip->ilim_votable = create_votable("CP_ILIM",
+ VOTE_MIN, smb1390_ilim_vote_cb, chip);
+ if (IS_ERR(chip->ilim_votable))
+ return PTR_ERR(chip->ilim_votable);
+
+ return 0;
+}
+
+static void smb1390_destroy_votables(struct smb1390 *chip)
+{
+ destroy_votable(chip->disable_votable);
+ destroy_votable(chip->ilim_votable);
+}
+
+static int smb1390_init_hw(struct smb1390 *chip)
+{
+ /*
+ * charge pump is initially disabled; this indirectly votes to allow
+ * traditional parallel charging if present
+ */
+ vote(chip->disable_votable, USER_VOTER, true, 0);
+ return 0;
+}
+
+static int smb1390_get_irq_index_byname(const char *irq_name)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(smb_irqs); i++) {
+ if (strcmp(smb_irqs[i].name, irq_name) == 0)
+ return i;
+ }
+
+ return -ENOENT;
+}
+
+static int smb1390_request_interrupt(struct smb1390 *chip,
+ struct device_node *node,
+ const char *irq_name)
+{
+ int rc = 0, irq, irq_index;
+
+ irq = of_irq_get_byname(node, irq_name);
+ if (irq < 0) {
+ pr_err("Couldn't get irq %s byname\n", irq_name);
+ return irq;
+ }
+
+ irq_index = smb1390_get_irq_index_byname(irq_name);
+ if (irq_index < 0) {
+ pr_err("%s is not a defined irq\n", irq_name);
+ return irq_index;
+ }
+
+ if (!smb_irqs[irq_index].handler)
+ return 0;
+
+ rc = devm_request_threaded_irq(chip->dev, irq, NULL,
+ smb_irqs[irq_index].handler,
+ IRQF_ONESHOT, irq_name, chip);
+ if (rc < 0) {
+ pr_err("Couldn't request irq %d rc=%d\n", irq, rc);
+ return rc;
+ }
+
+ chip->irqs[irq_index] = irq;
+ if (smb_irqs[irq_index].wake)
+ enable_irq_wake(irq);
+
+ return rc;
+}
+
+static int smb1390_request_interrupts(struct smb1390 *chip)
+{
+ struct device_node *node = chip->dev->of_node;
+ struct device_node *child;
+ int rc = 0;
+ const char *name;
+ struct property *prop;
+
+ for_each_available_child_of_node(node, child) {
+ of_property_for_each_string(child, "interrupt-names",
+ prop, name) {
+ rc = smb1390_request_interrupt(chip, child, name);
+ if (rc < 0) {
+ pr_err("Couldn't request interrupt %s rc=%d\n",
+ name, rc);
+ return rc;
+ }
+ }
+ }
+
+ return rc;
+}
+
+static int smb1390_probe(struct platform_device *pdev)
+{
+ struct smb1390 *chip;
+ int rc;
+
+ chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
+ if (!chip)
+ return -ENOMEM;
+
+ chip->dev = &pdev->dev;
+ spin_lock_init(&chip->status_change_lock);
+
+ chip->regmap = dev_get_regmap(chip->dev->parent, NULL);
+ if (!chip->regmap) {
+ pr_err("Couldn't get regmap\n");
+ return -EINVAL;
+ }
+
+ INIT_WORK(&chip->status_change_work, smb1390_status_change_work);
+ INIT_WORK(&chip->taper_work, smb1390_taper_work);
+
+ rc = smb1390_parse_dt(chip);
+ if (rc < 0) {
+ pr_err("Couldn't parse device tree rc=%d\n", rc);
+ goto out_work;
+ }
+
+ chip->vadc_dev = qpnp_get_vadc(chip->dev, "smb");
+ if (IS_ERR(chip->vadc_dev)) {
+ rc = PTR_ERR(chip->vadc_dev);
+ pr_err("Couldn't get vadc dev rc=%d\n", rc);
+ goto out_work;
+ }
+
+ rc = smb1390_create_votables(chip);
+ if (rc < 0) {
+ pr_err("Couldn't create votables rc=%d\n", rc);
+ goto out_work;
+ }
+
+ rc = smb1390_init_hw(chip);
+ if (rc < 0) {
+ pr_err("Couldn't init hardware rc=%d\n", rc);
+ goto out_votables;
+ }
+
+ chip->nb.notifier_call = smb1390_notifier_cb;
+ rc = power_supply_reg_notifier(&chip->nb);
+ if (rc < 0) {
+ pr_err("Couldn't register psy notifier rc=%d\n", rc);
+ goto out_votables;
+ }
+
+ chip->cp_class.name = "charge_pump",
+ chip->cp_class.owner = THIS_MODULE,
+ chip->cp_class.class_attrs = cp_class_attrs,
+ rc = class_register(&chip->cp_class);
+ if (rc < 0) {
+ pr_err("Couldn't register charge_pump sysfs class rc=%d\n", rc);
+ goto out_notifier;
+
+ }
+
+ rc = smb1390_request_interrupts(chip);
+ if (rc < 0) {
+ pr_err("Couldn't request interrupts rc=%d\n", rc);
+ goto out_class;
+ }
+
+ return 0;
+
+out_class:
+ class_unregister(&chip->cp_class);
+out_notifier:
+ power_supply_unreg_notifier(&chip->nb);
+out_votables:
+ smb1390_destroy_votables(chip);
+out_work:
+ cancel_work(&chip->taper_work);
+ cancel_work(&chip->status_change_work);
+ return rc;
+}
+
+static int smb1390_remove(struct platform_device *pdev)
+{
+ struct smb1390 *chip = platform_get_drvdata(pdev);
+
+ class_unregister(&chip->cp_class);
+ power_supply_unreg_notifier(&chip->nb);
+
+ /* explicitly disable charging */
+ vote(chip->disable_votable, USER_VOTER, true, 0);
+ cancel_work(&chip->taper_work);
+ cancel_work(&chip->status_change_work);
+ smb1390_destroy_votables(chip);
+ return 0;
+}
+
+static const struct of_device_id match_table[] = {
+ { .compatible = "qcom,smb1390-charger", },
+ { },
+};
+
+static struct platform_driver smb1390_driver = {
+ .driver = {
+ .name = "qcom,smb1390-charger",
+ .owner = THIS_MODULE,
+ .of_match_table = match_table,
+ },
+ .probe = smb1390_probe,
+ .remove = smb1390_remove,
+};
+module_platform_driver(smb1390_driver);
+
+MODULE_DESCRIPTION("SMB1390 Charge Pump Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c
index d20607c..5df7c9e 100644
--- a/drivers/power/supply/qcom/smb5-lib.c
+++ b/drivers/power/supply/qcom/smb5-lib.c
@@ -1682,6 +1682,27 @@
return 0;
}
+int smblib_configure_wdog(struct smb_charger *chg, bool enable)
+{
+ int rc;
+ u8 val = 0;
+
+ if (enable)
+ val = WDOG_TIMER_EN_ON_PLUGIN_BIT | BARK_WDOG_INT_EN_BIT;
+
+ /* enable WD BARK and enable it on plugin */
+ rc = smblib_masked_write(chg, WD_CFG_REG,
+ WATCHDOG_TRIGGER_AFP_EN_BIT |
+ WDOG_TIMER_EN_ON_PLUGIN_BIT |
+ BARK_WDOG_INT_EN_BIT, val);
+ if (rc < 0) {
+ pr_err("Couldn't configue WD config rc=%d\n", rc);
+ return rc;
+ }
+
+ return 0;
+}
+
/*******************
* DC PSY GETTERS *
*******************/
diff --git a/drivers/power/supply/qcom/smb5-lib.h b/drivers/power/supply/qcom/smb5-lib.h
index 335764e..39cc921 100644
--- a/drivers/power/supply/qcom/smb5-lib.h
+++ b/drivers/power/supply/qcom/smb5-lib.h
@@ -523,6 +523,7 @@
int smblib_set_prop_pr_swap_in_progress(struct smb_charger *chg,
const union power_supply_propval *val);
int smblib_stat_sw_override_cfg(struct smb_charger *chg, bool override);
+int smblib_configure_wdog(struct smb_charger *chg, bool enable);
int smblib_init(struct smb_charger *chg);
int smblib_deinit(struct smb_charger *chg);
diff --git a/drivers/power/supply/qcom/smb5-reg.h b/drivers/power/supply/qcom/smb5-reg.h
index afc45ab..3334f67 100644
--- a/drivers/power/supply/qcom/smb5-reg.h
+++ b/drivers/power/supply/qcom/smb5-reg.h
@@ -335,11 +335,6 @@
#define AICL_CMD_REG (MISC_BASE + 0x44)
#define RERUN_AICL_BIT BIT(0)
-#define SNARL_BARK_BITE_WD_CFG_REG (MISC_BASE + 0x43)
-#define BITE_WDOG_DISABLE_CHARGING_CFG_BIT BIT(7)
-#define BARK_WDOG_TIMEOUT_MASK GENMASK(3, 2)
-#define BITE_WDOG_TIMEOUT_MASK GENMASK(1, 0)
-
#define MISC_SMB_EN_CMD_REG (MISC_BASE + 0x48)
#define SMB_EN_OVERRIDE_VALUE_BIT BIT(4)
#define SMB_EN_OVERRIDE_BIT BIT(3)
@@ -352,6 +347,11 @@
#define BARK_WDOG_INT_EN_BIT BIT(6)
#define WDOG_TIMER_EN_ON_PLUGIN_BIT BIT(1)
+#define SNARL_BARK_BITE_WD_CFG_REG (MISC_BASE + 0x53)
+#define BITE_WDOG_DISABLE_CHARGING_CFG_BIT BIT(7)
+#define BARK_WDOG_TIMEOUT_MASK GENMASK(3, 2)
+#define BITE_WDOG_TIMEOUT_MASK GENMASK(1, 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 a75cbbb..2d147d4 100644
--- a/drivers/power/supply/qcom/step-chg-jeita.c
+++ b/drivers/power/supply/qcom/step-chg-jeita.c
@@ -82,6 +82,7 @@
struct wakeup_source *step_chg_ws;
struct power_supply *batt_psy;
struct power_supply *bms_psy;
+ struct power_supply *main_psy;
struct delayed_work status_change_work;
struct delayed_work get_config_work;
struct notifier_block nb;
@@ -534,6 +535,12 @@
update_time:
chip->jeita_last_update_time = ktime_get();
+
+ if (!chip->main_psy)
+ chip->main_psy = power_supply_get_by_name("main");
+ if (chip->main_psy)
+ power_supply_changed(chip->main_psy);
+
return 0;
reschedule:
diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index 1ddfabf..8811386 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -2626,7 +2626,7 @@
return;
host->testbus.select_major = TSTBUS_UTP_HCI;
- for (i = 0; i <= nminor; i++) {
+ for (i = 0; i < nminor; i++) {
host->testbus.select_minor = i;
ufs_qcom_testbus_config(host);
testbus[i] = ufshcd_readl(hba, UFS_TEST_BUS);
diff --git a/drivers/soc/qcom/ipc_router_smd_xprt.c b/drivers/soc/qcom/ipc_router_smd_xprt.c
index 513689a..c722451 100644
--- a/drivers/soc/qcom/ipc_router_smd_xprt.c
+++ b/drivers/soc/qcom/ipc_router_smd_xprt.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-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
@@ -296,8 +296,10 @@
spin_lock_irqsave(&smd_xprtp->ss_reset_lock, flags);
if (smd_xprtp->ss_reset) {
spin_unlock_irqrestore(&smd_xprtp->ss_reset_lock, flags);
- if (smd_xprtp->in_pkt)
+ if (smd_xprtp->in_pkt) {
release_pkt(smd_xprtp->in_pkt);
+ smd_xprtp->in_pkt = NULL;
+ }
smd_xprtp->is_partial_in_pkt = 0;
IPC_RTR_ERR("%s: %s channel reset\n",
__func__, smd_xprtp->xprt.name);
@@ -350,6 +352,7 @@
__func__, smd_xprtp->xprt.name);
kfree_skb(ipc_rtr_pkt);
release_pkt(smd_xprtp->in_pkt);
+ smd_xprtp->in_pkt = NULL;
smd_xprtp->is_partial_in_pkt = 0;
return;
}
diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c
index d5de12b..8713f73 100644
--- a/drivers/soc/qcom/socinfo.c
+++ b/drivers/soc/qcom/socinfo.c
@@ -578,6 +578,14 @@
[285] = {MSM_CPU_9650, "MDM9650"},
[286] = {MSM_CPU_9650, "MDM9650"},
+ /* 9607 IDs */
+ [290] = {MSM_CPU_9607, "MDM9607"},
+ [296] = {MSM_CPU_9607, "MDM8207"},
+ [297] = {MSM_CPU_9607, "MDM9207"},
+ [298] = {MSM_CPU_9607, "MDM9307"},
+ [299] = {MSM_CPU_9607, "MDM9628"},
+ [322] = {MSM_CPU_9607, "MDM9206"},
+
/* SDM670 ID */
[336] = {MSM_CPU_SDM670, "SDM670"},
@@ -1564,6 +1572,10 @@
dummy_socinfo.id = 354;
strlcpy(dummy_socinfo.build_id, "sdm429 - ",
sizeof(dummy_socinfo.build_id));
+ } else if (early_machine_is_mdm9607()) {
+ dummy_socinfo.id = 290;
+ strlcpy(dummy_socinfo.build_id, "mdm9607 - ",
+ sizeof(dummy_socinfo.build_id));
}
strlcat(dummy_socinfo.build_id, "Dummy socinfo",
diff --git a/drivers/soc/qcom/wcnss/wcnss_vreg.c b/drivers/soc/qcom/wcnss/wcnss_vreg.c
index 5ce2e82..29bc834 100644
--- a/drivers/soc/qcom/wcnss/wcnss_vreg.c
+++ b/drivers/soc/qcom/wcnss/wcnss_vreg.c
@@ -193,7 +193,7 @@
}
}
-static void wcnss_free_regulator(void)
+void wcnss_free_regulator(void)
{
int vreg_i;
@@ -587,13 +587,8 @@
pr_err("vreg %s disable failed (%d)\n",
regulators[i].name, rc);
}
-
- /* Free the regulator source */
- if (regulators[i].state & VREG_GET_REGULATOR_MASK)
- regulator_put(regulators[i].regulator);
-
- regulators[i].state = VREG_NULL_CONFIG;
}
+
}
/* Common helper routine to turn on all WCNSS & IRIS vregs */
diff --git a/drivers/soc/qcom/wcnss/wcnss_wlan.c b/drivers/soc/qcom/wcnss/wcnss_wlan.c
index db3974b..6d5ee04 100644
--- a/drivers/soc/qcom/wcnss/wcnss_wlan.c
+++ b/drivers/soc/qcom/wcnss/wcnss_wlan.c
@@ -2177,7 +2177,7 @@
return;
}
if (len < sizeof(struct smd_msg_hdr)) {
- pr_err("wcnss: incomplete header available len = %d\n", len);
+ pr_debug("wcnss: incomplete header available len = %d\n", len);
return;
}
@@ -3329,7 +3329,7 @@
return NOTIFY_DONE;
}
- pr_debug("%s: wcnss notification event: %lu : %s\n",
+ pr_info("%s: wcnss notification event: %lu : %s\n",
__func__, code, wcnss_subsys_notif_type[code]);
if (code == SUBSYS_PROXY_VOTE) {
@@ -3524,6 +3524,7 @@
static int
wcnss_wlan_remove(struct platform_device *pdev)
{
+ wcnss_free_regulator();
if (penv->wcnss_notif_hdle)
subsys_notif_unregister_notifier(penv->wcnss_notif_hdle, &wnb);
wcnss_cdev_unregister(pdev);
diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c
index e8028d2..492a93d 100644
--- a/drivers/staging/android/ion/ion_carveout_heap.c
+++ b/drivers/staging/android/ion/ion_carveout_heap.c
@@ -206,3 +206,224 @@
kfree(carveout_heap);
carveout_heap = NULL;
}
+
+#include "msm/msm_ion.h"
+#include <soc/qcom/secure_buffer.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/msm_ion.h>
+
+struct ion_sc_entry {
+ struct list_head list;
+ struct ion_heap *heap;
+ u32 token;
+};
+
+struct ion_sc_heap {
+ struct ion_heap heap;
+ struct device *dev;
+ struct list_head children;
+};
+
+static struct ion_heap *ion_sc_find_child(struct ion_heap *heap, u32 flags)
+{
+ struct ion_sc_heap *manager;
+ struct ion_sc_entry *entry;
+
+ manager = container_of(heap, struct ion_sc_heap, heap);
+ flags = flags & ION_FLAGS_CP_MASK;
+ list_for_each_entry(entry, &manager->children, list) {
+ if (entry->token == flags)
+ return entry->heap;
+ }
+ return NULL;
+}
+
+static int ion_sc_heap_allocate(struct ion_heap *heap,
+ struct ion_buffer *buffer, unsigned long len,
+ unsigned long align, unsigned long flags) {
+ struct ion_heap *child;
+
+ /* cache maintenance is not possible on secure memory */
+ flags &= ~((unsigned long)ION_FLAG_CACHED);
+ buffer->flags = flags;
+
+ child = ion_sc_find_child(heap, flags);
+ if (!child)
+ return -EINVAL;
+
+ return ion_carveout_heap_allocate(child, buffer, len, align, flags);
+}
+
+static void ion_sc_heap_free(struct ion_buffer *buffer)
+{
+ struct ion_heap *child;
+ struct sg_table *table = buffer->priv_virt;
+ struct page *page = sg_page(table->sgl);
+ ion_phys_addr_t paddr = PFN_PHYS(page_to_pfn(page));
+
+ child = ion_sc_find_child(buffer->heap, buffer->flags);
+ if (!child) {
+ WARN(1, "ion_secure_carvout: invalid buffer flags on free. Memory will be leaked\n.");
+ return;
+ }
+
+ ion_carveout_free(child, paddr, buffer->size);
+ sg_free_table(table);
+ kfree(table);
+}
+
+static struct ion_heap_ops ion_sc_heap_ops = {
+ .allocate = ion_sc_heap_allocate,
+ .free = ion_sc_heap_free,
+ .phys = ion_carveout_heap_phys,
+ .map_dma = ion_carveout_heap_map_dma,
+ .unmap_dma = ion_carveout_heap_unmap_dma,
+};
+
+static int ion_sc_get_dt_token(struct ion_sc_entry *entry,
+ struct device_node *np, u64 base, u64 size)
+{
+ u32 token;
+ u32 *vmids, *modes;
+ u32 nr, i;
+ int ret = -EINVAL;
+ u32 src_vm = VMID_HLOS;
+
+ if (of_property_read_u32(np, "token", &token))
+ return -EINVAL;
+
+ nr = count_set_bits(token);
+ vmids = kcalloc(nr, sizeof(*vmids), GFP_KERNEL);
+ if (!vmids)
+ return -ENOMEM;
+
+ modes = kcalloc(nr, sizeof(*modes), GFP_KERNEL);
+ if (!modes) {
+ kfree(vmids);
+ return -ENOMEM;
+ }
+
+ if ((token & ~ION_FLAGS_CP_MASK) ||
+ populate_vm_list(token, vmids, nr)) {
+ pr_err("secure_carveout_heap: Bad token %x\n", token);
+ goto out;
+ }
+
+ for (i = 0; i < nr; i++)
+ if (vmids[i] == VMID_CP_SEC_DISPLAY)
+ modes[i] = PERM_READ;
+ else
+ modes[i] = PERM_READ | PERM_WRITE;
+
+ ret = hyp_assign_phys(base, size, &src_vm, 1, vmids, modes, nr);
+ if (ret)
+ pr_err("secure_carveout_heap: Assign token 0x%x failed\n",
+ token);
+ else
+ entry->token = token;
+out:
+ kfree(modes);
+ kfree(vmids);
+ return ret;
+}
+
+static int ion_sc_add_child(struct ion_sc_heap *manager,
+ struct device_node *np)
+{
+ struct device *dev = manager->dev;
+ struct ion_platform_heap heap_data = {0};
+ struct ion_sc_entry *entry;
+ struct device_node *phandle;
+ const __be32 *basep;
+ u64 base, size;
+ int ret;
+
+ entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+ if (!entry)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&entry->list);
+
+ phandle = of_parse_phandle(np, "memory-region", 0);
+ if (!phandle)
+ goto out_free;
+
+ basep = of_get_address(phandle, 0, &size, NULL);
+ if (!basep)
+ goto out_free;
+
+ base = of_translate_address(phandle, basep);
+ if (base == OF_BAD_ADDR)
+ goto out_free;
+
+ heap_data.priv = dev;
+ heap_data.base = base;
+ heap_data.size = size;
+
+ /* This will zero memory initially */
+ entry->heap = ion_carveout_heap_create(&heap_data);
+ if (IS_ERR(entry->heap))
+ goto out_free;
+
+ ret = ion_sc_get_dt_token(entry, np, base, size);
+ if (ret)
+ goto out_free_carveout;
+
+ list_add(&entry->list, &manager->children);
+ dev_info(dev, "ion_secure_carveout: creating heap@0x%llx, size 0x%llx\n",
+ base, size);
+ return 0;
+
+out_free_carveout:
+ ion_carveout_heap_destroy(entry->heap);
+out_free:
+ kfree(entry);
+ return -EINVAL;
+}
+
+void ion_secure_carveout_heap_destroy(struct ion_heap *heap)
+{
+ struct ion_sc_heap *manager =
+ container_of(heap, struct ion_sc_heap, heap);
+ struct ion_sc_entry *entry, *tmp;
+
+ list_for_each_entry_safe(entry, tmp, &manager->children, list) {
+ ion_carveout_heap_destroy(entry->heap);
+ kfree(entry);
+ }
+ kfree(manager);
+}
+
+struct ion_heap *ion_secure_carveout_heap_create(
+ struct ion_platform_heap *heap_data)
+{
+ struct device *dev = heap_data->priv;
+ int ret;
+ struct ion_sc_heap *manager;
+ struct device_node *np;
+
+ manager = kzalloc(sizeof(*manager), GFP_KERNEL);
+ if (!manager)
+ return ERR_PTR(-ENOMEM);
+
+ INIT_LIST_HEAD(&manager->children);
+ manager->dev = dev;
+
+ for_each_child_of_node(dev->of_node, np) {
+ ret = ion_sc_add_child(manager, np);
+ if (ret) {
+ dev_err(dev, "Creating child pool %s failed\n",
+ np->name);
+ goto err;
+ }
+ }
+
+ manager->heap.ops = &ion_sc_heap_ops;
+ manager->heap.type = ION_HEAP_TYPE_SECURE_CARVEOUT;
+ return &manager->heap;
+
+err:
+ ion_secure_carveout_heap_destroy(&manager->heap);
+ return ERR_PTR(-EINVAL);
+}
diff --git a/drivers/staging/android/ion/msm/msm_ion.c b/drivers/staging/android/ion/msm/msm_ion.c
index 4b9e359..656eb49 100644
--- a/drivers/staging/android/ion/msm/msm_ion.c
+++ b/drivers/staging/android/ion/msm/msm_ion.c
@@ -122,6 +122,10 @@
{
.id = ION_SECURE_DISPLAY_HEAP_ID,
.name = ION_SECURE_DISPLAY_HEAP_NAME,
+ },
+ {
+ .id = ION_SECURE_CARVEOUT_HEAP_ID,
+ .name = ION_SECURE_CARVEOUT_HEAP_NAME,
}
};
#endif
@@ -443,6 +447,7 @@
MAKE_HEAP_TYPE_MAPPING(SYSTEM),
MAKE_HEAP_TYPE_MAPPING(SYSTEM_CONTIG),
MAKE_HEAP_TYPE_MAPPING(CARVEOUT),
+ MAKE_HEAP_TYPE_MAPPING(SECURE_CARVEOUT),
MAKE_HEAP_TYPE_MAPPING(CHUNK),
MAKE_HEAP_TYPE_MAPPING(DMA),
MAKE_HEAP_TYPE_MAPPING(SECURE_DMA),
@@ -1021,6 +1026,9 @@
case ION_HEAP_TYPE_HYP_CMA:
heap = ion_cma_secure_heap_create(heap_data);
break;
+ case ION_HEAP_TYPE_SECURE_CARVEOUT:
+ heap = ion_secure_carveout_heap_create(heap_data);
+ break;
default:
heap = ion_heap_create(heap_data);
}
@@ -1056,6 +1064,9 @@
case ION_HEAP_TYPE_HYP_CMA:
ion_cma_secure_heap_destroy(heap);
break;
+ case ION_HEAP_TYPE_SECURE_CARVEOUT:
+ ion_secure_carveout_heap_destroy(heap);
+ break;
default:
ion_heap_destroy(heap);
}
diff --git a/drivers/staging/android/ion/msm_ion_priv.h b/drivers/staging/android/ion/msm_ion_priv.h
index bbf2e8b..1318d1f 100644
--- a/drivers/staging/android/ion/msm_ion_priv.h
+++ b/drivers/staging/android/ion/msm_ion_priv.h
@@ -2,7 +2,7 @@
* drivers/staging/android/ion/msm_ion_priv.h
*
* Copyright (C) 2011 Google, Inc.
- * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -40,6 +40,10 @@
struct ion_heap *ion_cma_secure_heap_create(struct ion_platform_heap *heap);
void ion_cma_secure_heap_destroy(struct ion_heap *heap);
+struct ion_heap *ion_secure_carveout_heap_create(
+ struct ion_platform_heap *heap);
+void ion_secure_carveout_heap_destroy(struct ion_heap *heap);
+
long msm_ion_custom_ioctl(struct ion_client *client,
unsigned int cmd,
unsigned long arg);
diff --git a/drivers/staging/android/uapi/msm_ion.h b/drivers/staging/android/uapi/msm_ion.h
index eb60bad..a6672ff 100644
--- a/drivers/staging/android/uapi/msm_ion.h
+++ b/drivers/staging/android/uapi/msm_ion.h
@@ -10,6 +10,7 @@
ION_HEAP_TYPE_SECURE_DMA = ION_HEAP_TYPE_MSM_START,
ION_HEAP_TYPE_SYSTEM_SECURE,
ION_HEAP_TYPE_HYP_CMA,
+ ION_HEAP_TYPE_SECURE_CARVEOUT,
/*
* if you add a heap type here you should also add it to
* heap_types_info[] in msm_ion.c
@@ -32,6 +33,7 @@
ION_SECURE_DISPLAY_HEAP_ID = 10,
ION_CP_MFC_HEAP_ID = 12,
ION_SPSS_HEAP_ID = 13, /* Secure Processor ION heap */
+ ION_SECURE_CARVEOUT_HEAP_ID = 14,
ION_CP_WB_HEAP_ID = 16, /* 8660 only */
ION_QSECOM_TA_HEAP_ID = 19,
ION_CAMERA_HEAP_ID = 20, /* 8660 only */
@@ -133,6 +135,7 @@
#define ION_IOMMU_HEAP_NAME "iommu"
#define ION_MFC_HEAP_NAME "mfc"
#define ION_SPSS_HEAP_NAME "spss"
+#define ION_SECURE_CARVEOUT_HEAP_NAME "secure_carveout"
#define ION_WB_HEAP_NAME "wb"
#define ION_MM_FIRMWARE_HEAP_NAME "mm_fw"
#define ION_PIL1_HEAP_NAME "pil_1"
diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c
index 563305f..148568b 100644
--- a/drivers/tty/serial/msm_geni_serial.c
+++ b/drivers/tty/serial/msm_geni_serial.c
@@ -447,6 +447,8 @@
SE_UART_MANUAL_RFR);
/* Write to flow control must complete before return to client*/
mb();
+ IPC_LOG_MSG(port->ipc_log_misc, "%s: Manual_rfr 0x%x\n",
+ __func__, uart_manual_rfr);
}
static const char *msm_geni_serial_get_type(struct uart_port *uport)
@@ -2540,6 +2542,8 @@
* set this to manual flow on.
*/
if (!port->manual_flow) {
+ u32 geni_ios;
+
uart_manual_rfr |= (UART_MANUAL_RFR_EN | UART_RFR_READY);
geni_write_reg_nolog(uart_manual_rfr, port->uport.membase,
SE_UART_MANUAL_RFR);
@@ -2548,8 +2552,11 @@
* doing a stop_rx else we could end up flowing off the peer.
*/
mb();
- IPC_LOG_MSG(port->ipc_log_pwr, "%s: Manual Flow ON 0x%x\n",
- __func__, uart_manual_rfr);
+ geni_ios = geni_read_reg_nolog(port->uport.membase,
+ SE_GENI_IOS);
+ IPC_LOG_MSG(port->ipc_log_pwr, "%s: Manual Flow ON 0x%x 0x%x\n",
+ __func__, uart_manual_rfr, geni_ios);
+ udelay(10);
}
stop_rx_sequencer(&port->uport);
if ((geni_status & M_GENI_CMD_ACTIVE))
diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c
index b3c3f97..efaac5e 100644
--- a/drivers/tty/serial/msm_serial.c
+++ b/drivers/tty/serial/msm_serial.c
@@ -197,13 +197,13 @@
static
void msm_write(struct uart_port *port, unsigned int val, unsigned int off)
{
- writel_relaxed(val, port->membase + off);
+ writel_relaxed_no_log(val, port->membase + off);
}
static
unsigned int msm_read(struct uart_port *port, unsigned int off)
{
- return readl_relaxed(port->membase + off);
+ return readl_relaxed_no_log(port->membase + off);
}
/*
@@ -303,15 +303,17 @@
struct device *dev = msm_port->uart.dev;
struct dma_slave_config conf;
struct msm_dma *dma;
+ struct dma_chan *dma_chan;
u32 crci = 0;
int ret;
dma = &msm_port->tx_dma;
/* allocate DMA resources, if available */
- dma->chan = dma_request_slave_channel_reason(dev, "tx");
- if (IS_ERR(dma->chan))
+ dma_chan = dma_request_slave_channel_reason(dev, "tx");
+ if (IS_ERR(dma_chan))
goto no_tx;
+ dma->chan = dma_chan;
of_property_read_u32(dev->of_node, "qcom,tx-crci", &crci);
@@ -346,15 +348,17 @@
struct device *dev = msm_port->uart.dev;
struct dma_slave_config conf;
struct msm_dma *dma;
+ struct dma_chan *dma_chan;
u32 crci = 0;
int ret;
dma = &msm_port->rx_dma;
/* allocate DMA resources, if available */
- dma->chan = dma_request_slave_channel_reason(dev, "rx");
- if (IS_ERR(dma->chan))
+ dma_chan = dma_request_slave_channel_reason(dev, "rx");
+ if (IS_ERR(dma_chan))
goto no_rx;
+ dma->chan = dma_chan;
of_property_read_u32(dev->of_node, "qcom,rx-crci", &crci);
@@ -1157,15 +1161,6 @@
return baud;
}
-static void msm_init_clock(struct uart_port *port)
-{
- struct msm_port *msm_port = UART_TO_MSM(port);
-
- clk_prepare_enable(msm_port->clk);
- clk_prepare_enable(msm_port->pclk);
- msm_serial_set_mnd_regs(port);
-}
-
static int msm_startup(struct uart_port *port)
{
struct msm_port *msm_port = UART_TO_MSM(port);
@@ -1175,12 +1170,19 @@
snprintf(msm_port->name, sizeof(msm_port->name),
"msm_serial%d", port->line);
- ret = request_irq(port->irq, msm_uart_irq, IRQF_TRIGGER_HIGH,
- msm_port->name, port);
- if (unlikely(ret))
+ /*
+ * UART clk must be kept enabled to
+ * avoid losing received character
+ */
+ ret = clk_prepare_enable(msm_port->clk);
+ if (ret)
return ret;
- msm_init_clock(port);
+ ret = clk_prepare_enable(msm_port->pclk);
+ if (ret)
+ goto err_pclk;
+
+ msm_serial_set_mnd_regs(port);
if (likely(port->fifosize > 12))
rfr_level = port->fifosize - 12;
@@ -1206,7 +1208,23 @@
msm_request_rx_dma(msm_port, msm_port->uart.mapbase);
}
+ ret = request_irq(port->irq, msm_uart_irq, IRQF_TRIGGER_HIGH,
+ msm_port->name, port);
+ if (unlikely(ret))
+ goto err_irq;
+
return 0;
+
+err_irq:
+ if (msm_port->is_uartdm)
+ msm_release_dma(msm_port);
+
+ clk_disable_unprepare(msm_port->pclk);
+
+err_pclk:
+ clk_disable_unprepare(msm_port->clk);
+
+ return ret;
}
static void msm_shutdown(struct uart_port *port)
@@ -1219,6 +1237,7 @@
if (msm_port->is_uartdm)
msm_release_dma(msm_port);
+ clk_disable_unprepare(msm_port->pclk);
clk_disable_unprepare(msm_port->clk);
free_irq(port->irq, port);
@@ -1385,8 +1404,16 @@
switch (state) {
case 0:
- clk_prepare_enable(msm_port->clk);
- clk_prepare_enable(msm_port->pclk);
+ /*
+ * UART clk must be kept enabled to
+ * avoid losing received character
+ */
+ if (clk_prepare_enable(msm_port->clk))
+ return;
+ if (clk_prepare_enable(msm_port->pclk)) {
+ clk_disable_unprepare(msm_port->clk);
+ return;
+ }
break;
case 3:
clk_disable_unprepare(msm_port->clk);
@@ -1651,7 +1678,7 @@
if (unlikely(!port->membase))
return -ENXIO;
- msm_init_clock(port);
+ msm_serial_set_mnd_regs(port);
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
@@ -1813,12 +1840,37 @@
};
MODULE_DEVICE_TABLE(of, msm_match_table);
+#ifdef CONFIG_PM_SLEEP
+static int msm_serial_suspend(struct device *dev)
+{
+ struct uart_port *port = dev_get_drvdata(dev);
+
+ uart_suspend_port(&msm_uart_driver, port);
+
+ return 0;
+}
+
+static int msm_serial_resume(struct device *dev)
+{
+ struct uart_port *port = dev_get_drvdata(dev);
+
+ uart_resume_port(&msm_uart_driver, port);
+
+ return 0;
+}
+#endif
+
+static const struct dev_pm_ops msm_serial_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(msm_serial_suspend, msm_serial_resume)
+};
+
static struct platform_driver msm_platform_driver = {
.remove = msm_serial_remove,
.probe = msm_serial_probe,
.driver = {
.name = "msm_serial",
.of_match_table = msm_match_table,
+ .pm = &msm_serial_pm_ops,
},
};
diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c
index ae9b7cf..25d70f00 100644
--- a/drivers/video/fbdev/msm/mdss_fb.c
+++ b/drivers/video/fbdev/msm/mdss_fb.c
@@ -1320,14 +1320,7 @@
pr_err("cannot create release fence time line\n");
return -ENOMEM;
}
- snprintf(timeline_name, sizeof(timeline_name),
- "mdss_fb_%d_retire", mfd->index);
- mfd->mdp_sync_pt_data.timeline_retire =
- mdss_create_timeline(timeline_name);
- if (mfd->mdp_sync_pt_data.timeline == NULL) {
- pr_err("cannot create release fence time line\n");
- return -ENOMEM;
- }
+
mfd->mdp_sync_pt_data.notifier.notifier_call =
__mdss_fb_sync_buf_done_callback;
}
@@ -2979,15 +2972,26 @@
*/
void mdss_fb_signal_timeline(struct msm_sync_pt_data *sync_pt_data)
{
+ struct msm_fb_data_type *mfd;
+
+ mfd = container_of(sync_pt_data, typeof(*mfd), mdp_sync_pt_data);
mutex_lock(&sync_pt_data->sync_mutex);
- if (atomic_add_unless(&sync_pt_data->commit_cnt, -1, 0) &&
+ if (atomic_read(&sync_pt_data->commit_cnt) &&
sync_pt_data->timeline) {
mdss_inc_timeline(sync_pt_data->timeline, 1);
- mdss_inc_timeline(sync_pt_data->timeline_retire, 1);
+
+ /*
+ * For Command mode panels, the retire timeline is incremented
+ * whenever we receive a readptr_done. For all other panels,
+ * the retire fence should be signaled along with the release
+ * fence once the frame is done.
+ */
+ if (mfd->panel.type != MIPI_CMD_PANEL)
+ mdss_inc_timeline(sync_pt_data->timeline_retire, 1);
MDSS_XLOG(sync_pt_data->timeline_value);
sync_pt_data->timeline_value++;
- pr_debug("%s: buffer signaled! timeline val=%d remaining=%d\n",
+ pr_debug("%s: buffer signaled! timeline val=%d commit_cnt=%d\n",
sync_pt_data->fence_name, sync_pt_data->timeline_value,
atomic_read(&sync_pt_data->commit_cnt));
} else {
@@ -3016,9 +3020,10 @@
val = sync_pt_data->threshold +
atomic_read(&sync_pt_data->commit_cnt);
mdss_resync_timeline(sync_pt_data->timeline);
- mdss_resync_timeline(sync_pt_data->timeline_retire);
- sync_pt_data->timeline_value += val;
- atomic_set(&sync_pt_data->commit_cnt, 0);
+ if (mfd->panel.type != MIPI_CMD_PANEL)
+ mdss_resync_timeline(sync_pt_data->timeline_retire);
+ sync_pt_data->timeline_value = val;
+
}
mutex_unlock(&sync_pt_data->sync_mutex);
}
diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h
index 4307119..9497318 100644
--- a/drivers/video/fbdev/msm/mdss_mdp.h
+++ b/drivers/video/fbdev/msm/mdss_mdp.h
@@ -1009,7 +1009,6 @@
u32 splash_mem_size;
u32 sd_enabled;
- struct mdss_timeline *vsync_timeline;
struct mdss_mdp_vsync_handler vsync_retire_handler;
int retire_cnt;
bool kickoff_released;
diff --git a/drivers/video/fbdev/msm/mdss_mdp_layer.c b/drivers/video/fbdev/msm/mdss_mdp_layer.c
index b1c8041..d898e7e 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_layer.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_layer.c
@@ -734,11 +734,12 @@
if ((fence_type == MDSS_MDP_RETIRE_FENCE) &&
(mfd->panel.type == MIPI_CMD_PANEL)) {
- if (mdp5_data->vsync_timeline) {
- value = 1 + mdp5_data->retire_cnt++;
+ if (sync_pt_data->timeline_retire) {
+ value = sync_pt_data->timeline_retire->value + 1 +
+ mdp5_data->retire_cnt++;
sync_fence = mdss_fb_sync_get_fence(
- mdp5_data->vsync_timeline, fence_name,
- value);
+ sync_pt_data->timeline_retire,
+ fence_name, value);
} else {
return ERR_PTR(-EPERM);
}
diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
index da24e84..05f52a5 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
@@ -3619,9 +3619,8 @@
goto end;
}
- if (!ctl->panel_data->panel_info.cont_splash_enabled
- && (!mdss_mdp_ctl_is_power_on(ctl) ||
- mdss_panel_is_power_on_ulp(ctl->power_state))) {
+ if (!ctl->panel_data->panel_info.cont_splash_enabled &&
+ !mdss_mdp_ctl_is_power_on(ctl)) {
pr_debug("fb%d vsync pending first update en=%d, ctl power state:%d\n",
mfd->index, en, ctl->power_state);
rc = -EPERM;
@@ -5939,10 +5938,8 @@
rc = mdss_mdp_overlay_start(mfd);
if (rc)
goto end;
- if (mfd->panel_info->type != WRITEBACK_PANEL) {
- atomic_inc(&mfd->mdp_sync_pt_data.commit_cnt);
+ if (mfd->panel_info->type != WRITEBACK_PANEL)
rc = mdss_mdp_overlay_kickoff(mfd, NULL);
- }
} else {
rc = mdss_mdp_ctl_setup(ctl);
if (rc)
@@ -6340,10 +6337,11 @@
mutex_lock(&mfd->mdp_sync_pt_data.sync_mutex);
if (mdp5_data->retire_cnt > 0) {
- mdss_inc_timeline(mdp5_data->vsync_timeline, val);
+ mdss_inc_timeline(mfd->mdp_sync_pt_data.timeline_retire, val);
mdp5_data->retire_cnt -= min(val, mdp5_data->retire_cnt);
pr_debug("Retire signaled! timeline val=%d remaining=%d\n",
- mdss_get_timeline_retire_ts(mdp5_data->vsync_timeline),
+ mdss_get_timeline_retire_ts(
+ mfd->mdp_sync_pt_data.timeline_retire),
mdp5_data->retire_cnt);
if (mdp5_data->retire_cnt == 0) {
@@ -6382,7 +6380,7 @@
value = 1 + mdp5_data->retire_cnt;
mdp5_data->retire_cnt++;
- return mdss_fb_sync_get_fence(mdp5_data->vsync_timeline,
+ return mdss_fb_sync_get_fence(mfd->mdp_sync_pt_data.timeline_retire,
"mdp-retire", value);
}
@@ -6420,33 +6418,41 @@
struct sched_param param = { .sched_priority = 5 };
snprintf(name, sizeof(name), "mdss_fb%d_retire", mfd->index);
- mdp5_data->vsync_timeline = mdss_create_timeline(name);
- if (mdp5_data->vsync_timeline == NULL) {
+ mfd->mdp_sync_pt_data.timeline_retire = mdss_create_timeline(name);
+ if (mfd->mdp_sync_pt_data.timeline_retire == NULL) {
pr_err("cannot vsync create time line");
return -ENOMEM;
}
- kthread_init_worker(&mdp5_data->worker);
- kthread_init_work(&mdp5_data->vsync_work, __vsync_retire_work_handler);
+ /*
+ * vsync_work is required only for command mode panels and for panels
+ * with dynamic mode switch supported. For all other panels the retire
+ * fence is signaled along with the release fence once the frame
+ * transfer is done.
+ */
+ if ((mfd->panel_info->mipi.dms_mode) ||
+ (mfd->panel_info->type == MIPI_CMD_PANEL)) {
+ kthread_init_worker(&mdp5_data->worker);
+ kthread_init_work(&mdp5_data->vsync_work,
+ __vsync_retire_work_handler);
- mdp5_data->thread = kthread_run(kthread_worker_fn,
+ mdp5_data->thread = kthread_run(kthread_worker_fn,
&mdp5_data->worker,
"vsync_retire_work");
+ if (IS_ERR(mdp5_data->thread)) {
+ pr_err("unable to start vsync thread\n");
+ mdp5_data->thread = NULL;
+ return -ENOMEM;
+ }
- if (IS_ERR(mdp5_data->thread)) {
- pr_err("unable to start vsync thread\n");
- mdp5_data->thread = NULL;
- return -ENOMEM;
+ sched_setscheduler(mdp5_data->thread, SCHED_FIFO, ¶m);
+ mfd->mdp_sync_pt_data.get_retire_fence =
+ __vsync_retire_get_fence;
+ mdp5_data->vsync_retire_handler.vsync_handler =
+ __vsync_retire_handle_vsync;
+ mdp5_data->vsync_retire_handler.cmd_post_flush = false;
}
- sched_setscheduler(mdp5_data->thread, SCHED_FIFO, ¶m);
-
- mfd->mdp_sync_pt_data.get_retire_fence = __vsync_retire_get_fence;
-
- mdp5_data->vsync_retire_handler.vsync_handler =
- __vsync_retire_handle_vsync;
- mdp5_data->vsync_retire_handler.cmd_post_flush = false;
-
return 0;
}
@@ -6715,14 +6721,12 @@
}
}
- if (mfd->panel_info->mipi.dms_mode ||
- mfd->panel_info->type == MIPI_CMD_PANEL) {
- rc = __vsync_retire_setup(mfd);
- if (IS_ERR_VALUE((unsigned long)rc)) {
- pr_err("unable to create vsync timeline\n");
- goto init_fail;
- }
+ rc = __vsync_retire_setup(mfd);
+ if (IS_ERR_VALUE((unsigned long)rc)) {
+ pr_err("unable to create vsync timeline\n");
+ goto init_fail;
}
+
mfd->mdp_sync_pt_data.async_wait_fences = true;
pm_runtime_set_suspended(&mfd->pdev->dev);
diff --git a/drivers/video/fbdev/msm/mdss_rotator.c b/drivers/video/fbdev/msm/mdss_rotator.c
index 2dc9a1f..f51a1b8 100644
--- a/drivers/video/fbdev/msm/mdss_rotator.c
+++ b/drivers/video/fbdev/msm/mdss_rotator.c
@@ -387,7 +387,7 @@
rot_timeline = &entry->queue->timeline;
mutex_lock(&rot_timeline->lock);
- val = 1;
+ val = rot_timeline->next_value + 1;
fence = mdss_get_sync_fence(rot_timeline->timeline,
rot_timeline->fence_name, NULL, val);
diff --git a/drivers/video/fbdev/msm/mdss_sync.c b/drivers/video/fbdev/msm/mdss_sync.c
index 22fdcf5..6308162 100644
--- a/drivers/video/fbdev/msm/mdss_sync.c
+++ b/drivers/video/fbdev/msm/mdss_sync.c
@@ -37,28 +37,6 @@
struct list_head fence_list;
};
-/**
- * struct mdss_timeline - sync timeline context
- * @kref: reference count of timeline
- * @lock: serialization lock for timeline and fence update
- * @name: name of timeline
- * @fence_name: fence name prefix
- * @next_value: next commit sequence number
- * @value: current retired sequence number
- * @context: fence context identifier
- * @fence_list_head: linked list of outstanding sync fence
- */
-struct mdss_timeline {
- struct kref kref;
- spinlock_t lock;
- spinlock_t list_lock;
- char name[MDSS_SYNC_NAME_SIZE];
- u32 next_value;
- u32 value;
- u64 context;
- struct list_head fence_list_head;
-};
-
#if defined(CONFIG_SYNC_FILE)
/*
* to_mdss_fence - get mdss fence from fence base object
@@ -301,10 +279,9 @@
*/
struct mdss_fence *mdss_get_sync_fence(
struct mdss_timeline *tl, const char *fence_name,
- u32 *timestamp, int offset)
+ u32 *timestamp, int value)
{
struct mdss_fence *f;
- u32 val;
unsigned long flags;
if (!tl) {
@@ -318,22 +295,21 @@
INIT_LIST_HEAD(&f->fence_list);
spin_lock_irqsave(&tl->lock, flags);
- val = tl->next_value + offset;
- tl->next_value += 1;
- fence_init(&f->base, &mdss_fence_ops, &tl->lock, tl->context, val);
+ tl->next_value = value;
+ fence_init(&f->base, &mdss_fence_ops, &tl->lock, tl->context, value);
mdss_get_timeline(tl);
spin_unlock_irqrestore(&tl->lock, flags);
spin_lock(&tl->list_lock);
list_add_tail(&f->fence_list, &tl->fence_list_head);
spin_unlock(&tl->list_lock);
- snprintf(f->name, sizeof(f->name), "%s_%u", fence_name, val);
+ snprintf(f->name, sizeof(f->name), "%s_%u", fence_name, value);
if (timestamp)
- *timestamp = val;
+ *timestamp = value;
- pr_debug("fence created at val=%u tl->name %s next_value %d value %d offset %d\n",
- val, tl->name, tl->next_value, tl->value, offset);
+ pr_debug("fence created at val=%u tl->name= %s tl->value = %d tl->next_value =%d\n",
+ value, tl->name, tl->value, tl->next_value);
return (struct mdss_fence *) &f->base;
}
diff --git a/drivers/video/fbdev/msm/mdss_sync.h b/drivers/video/fbdev/msm/mdss_sync.h
index a2e84d4..7143863 100644
--- a/drivers/video/fbdev/msm/mdss_sync.h
+++ b/drivers/video/fbdev/msm/mdss_sync.h
@@ -17,8 +17,31 @@
#include <linux/types.h>
#include <linux/errno.h>
+#define MDSS_SYNC_NAME_SIZE 64
struct mdss_fence;
-struct mdss_timeline;
+
+/**
+ * struct mdss_timeline - sync timeline context
+ * @kref: reference count of timeline
+ * @lock: serialization lock for timeline and fence update
+ * @name: name of timeline
+ * @fence_name: fence name prefix
+ * @next_value: next commit sequence number
+ * @value: current retired sequence number
+ * @context: fence context identifier
+ * @fence_list_head: linked list of outstanding sync fence
+ */
+
+struct mdss_timeline {
+ struct kref kref;
+ spinlock_t lock;
+ spinlock_t list_lock;
+ char name[MDSS_SYNC_NAME_SIZE];
+ u32 next_value;
+ u32 value;
+ u64 context;
+ struct list_head fence_list_head;
+};
#if defined(CONFIG_SYNC_FILE)
struct mdss_timeline *mdss_create_timeline(const char *name);
diff --git a/include/dt-bindings/clock/msm-clocks-8953.h b/include/dt-bindings/clock/msm-clocks-8953.h
index 9550a41..a1b64cd 100644
--- a/include/dt-bindings/clock/msm-clocks-8953.h
+++ b/include/dt-bindings/clock/msm-clocks-8953.h
@@ -317,6 +317,11 @@
#define clk_apcs_c1_pll 0x17d32f1e
#define clk_apcs_cci_pll 0x09affb3c
#define clk_a53ssmux_cci 0x15560bd5
+#define clk_perf_cpussmux 0xe6532496
+#define clk_pwr_cpussmux 0xde339cf1
+#define clk_cci_cpussmux 0xcaeb1b94
+#define clk_pwr_clk 0x9283a6d8
+#define clk_perf_clk 0x98d6ee40
#define clk_a53_cci_clk 0x4cdbbe58
#define clk_audio_ap_clk 0x312ac429
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 43d801e..7c69d6c 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -278,6 +278,7 @@
POWER_SUPPLY_PROP_BATT_PROFILE_VERSION,
POWER_SUPPLY_PROP_BATT_FULL_CURRENT,
POWER_SUPPLY_PROP_RECHARGE_SOC,
+ POWER_SUPPLY_PROP_TOGGLE_STAT,
/* Local extensions of type int64_t */
POWER_SUPPLY_PROP_CHARGE_COUNTER_EXT,
/* Properties of type `const char *' */
diff --git a/include/linux/wcnss_wlan.h b/include/linux/wcnss_wlan.h
index b37f8df..47fb288 100644
--- a/include/linux/wcnss_wlan.h
+++ b/include/linux/wcnss_wlan.h
@@ -132,6 +132,7 @@
bool wcnss_cbc_complete(void);
int wcnss_device_is_shutdown(void);
void wcnss_riva_dump_pmic_regs(void);
+void wcnss_free_regulator(void);
int wcnss_xo_auto_detect_enabled(void);
u32 wcnss_get_wlan_rx_buff_count(void);
int wcnss_wlan_iris_xo_mode(void);
diff --git a/include/soc/qcom/socinfo.h b/include/soc/qcom/socinfo.h
index 280a6d9..b04052e 100644
--- a/include/soc/qcom/socinfo.h
+++ b/include/soc/qcom/socinfo.h
@@ -112,6 +112,8 @@
of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msm8953")
#define early_machine_is_msm8937() \
of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msm8937")
+#define early_machine_is_mdm9607() \
+ of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,mdm9607")
#define early_machine_is_sdm450() \
of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,sdm450")
#define early_machine_is_sdm632() \
@@ -159,6 +161,7 @@
#define early_machine_is_apqcobalt() 0
#define early_machine_is_msmhamster() 0
#define early_machine_is_msmfalcon() 0
+#define early_machine_is_mdm9607() 0
#define early_machine_is_sdxpoorwills() 0
#define early_machine_is_sdm845() 0
#define early_machine_is_sdm670() 0
@@ -242,6 +245,7 @@
MSM_CPU_SDM632,
MSM_CPU_SDA632,
MSM_CPU_8937,
+ MSM_CPU_9607,
MSM_CPU_SDM439,
MSM_CPU_SDM429,
MSM_CPU_9650,
diff --git a/include/uapi/media/msmb_isp.h b/include/uapi/media/msmb_isp.h
index 2b10748..053fa76 100644
--- a/include/uapi/media/msmb_isp.h
+++ b/include/uapi/media/msmb_isp.h
@@ -874,6 +874,10 @@
#define V4L2_PIX_FMT_P16GBRG10 v4l2_fourcc('P', 'G', 'B', '0')
#define V4L2_PIX_FMT_P16GRBG10 v4l2_fourcc('P', 'G', 'R', '0')
#define V4L2_PIX_FMT_P16RGGB10 v4l2_fourcc('P', 'R', 'G', '0')
+#define V4L2_PIX_FMT_P16BGGR12 v4l2_fourcc('P', 'B', 'G', '2')
+#define V4L2_PIX_FMT_P16GBRG12 v4l2_fourcc('P', 'G', 'B', '2')
+#define V4L2_PIX_FMT_P16GRBG12 v4l2_fourcc('P', 'G', 'R', '2')
+#define V4L2_PIX_FMT_P16RGGB12 v4l2_fourcc('P', 'R', 'G', '2')
#define V4L2_PIX_FMT_NV14 v4l2_fourcc('N', 'V', '1', '4')
#define V4L2_PIX_FMT_NV41 v4l2_fourcc('N', 'V', '4', '1')
#define V4L2_PIX_FMT_META v4l2_fourcc('Q', 'M', 'E', 'T')
diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c
index b2df539..78c0e04 100644
--- a/kernel/time/alarmtimer.c
+++ b/kernel/time/alarmtimer.c
@@ -348,6 +348,10 @@
alarm->timer.function = alarmtimer_fired;
alarm->function = function;
alarm->type = type;
+ if (type >= ALARM_NUMTYPE) {
+ /* use ALARM_BOOTTIME as the default */
+ alarm->type = ALARM_BOOTTIME;
+ }
alarm->state = ALARMTIMER_STATE_INACTIVE;
}
EXPORT_SYMBOL_GPL(alarm_init);
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 6fd9773..f99065f 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -202,13 +202,6 @@
atomic_long_read(&p->mm->nr_ptes) + mm_nr_pmds(p->mm);
task_unlock(p);
- /*
- * Root processes get 3% bonus, just like the __vm_enough_memory()
- * implementation used by LSMs.
- */
- if (has_capability_noaudit(p, CAP_SYS_ADMIN))
- points -= (points * 3) / 100;
-
/* Normalize to oom_score_adj units */
adj *= totalpages / 1000;
points += adj;
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 46e6b28..3b3455a 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -872,11 +872,6 @@
&x->replay);
if (ret)
goto out;
- if (x->props.output_mark) {
- ret = nla_put_u32(skb, XFRMA_OUTPUT_MARK, x->props.output_mark);
- if (ret)
- goto out;
- }
if (x->security)
ret = copy_sec_ctx(x->security, skb);
if (x->props.output_mark) {