Merge "ARM: dts: msm: add perf-events support for msm8x10, msm8x12"
diff --git a/Documentation/devicetree/bindings/input/misc/bmp180.txt b/Documentation/devicetree/bindings/input/misc/bmp180.txt
new file mode 100644
index 0000000..13e0839
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/misc/bmp180.txt
@@ -0,0 +1,35 @@
+Bosch BMP18x-series altimeter driver
+
+Required properties:
+
+ - compatible : Should be "bosch,bmp180".
+ - reg : i2c slave address of the device.
+ - vdd-supply : Analog power supply needed to power device.
+ - vddio-supply : Digital IO power supply needed for IO and I2C.
+ - bosch,chip-id : Chip id for the bmp18x altimeter sensor.
+ - bosch,oversample : Sensor default oversampling value.
+ Default oversampling value to be used at startup.
+ Value range is 0-3 with rising sensitivity.
+ - bosch,period : Temperature measurement period (milliseconds).
+ Set to zero if unsure.
+
+Optional properties:
+
+ - bosch,sw-oversample : Boolean to enable software oversampling if
+ this property is defined. Only take effect when
+ default_oversampling is 3.
+
+Example:
+ i2c@f9925000 {
+ bmp180@77 {
+ status = "okay";
+ reg = <0x77>;
+ compatible = "bosch,bmp180";
+ vdd-supply = <&pm8110_l19>;
+ vddio-supply = <&pm8110_l14>;
+ bosch,chip-id = <0x55>;
+ bosch,oversample = <3>;
+ bosch,period = <1000>;
+ bosch,sw-oversample;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/input/misc/mma8x5x.txt b/Documentation/devicetree/bindings/input/misc/mma8x5x.txt
new file mode 100644
index 0000000..854939c
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/misc/mma8x5x.txt
@@ -0,0 +1,39 @@
+Freescale MMA8x5x 3-Axis Orientation/Motion Detection Sensor series
+(MMA8451/MMA8452/MMA8453/MMA8652/MMA8653)
+
+The Freescale 3-Axis Orientation/Motion Detection Sensor is
+connected to host processor via i2c.
+The sensor can be polling for acceleration data or configure to
+generates interrupts when a motion is detected.
+
+Required properties:
+
+ - compatible : should be "fsl,mma8x5x"
+ - reg : i2c slave address of the device
+ - vdd-supply : power supply needed to power up the device.
+ - vio-supply : power supply needed for device IO and to pullup i2c bus.
+ - fsl,sensors-position : select from 0 to 7 depends on how the sensor is
+ mounting on the board, this will decide how the 3-axis reading
+ of data will be translated to X/Y/Z axis of acceleration data.
+
+Optional properties:
+ Sensor can work on polling mode or interrupt mode, following interrupt
+ is required if the sensor need to work on interrupt mode.
+ - interrupt-parent : parent of interrupt.
+ - interrupts : sensor signal interrupt to indicate new data ready or
+ a motion is detected.
+ - fsl,irq-gpio : First irq gpio which is to provide interrupts to host, same
+ as "interrupts" node. It will also contain active low or active
+ high information.
+
+Example:
+ fsl@1c {
+ compatible = "fsl,mma8x5x";
+ reg = <0x1c>;
+ interrupt-parent = <&msmgpio>;
+ interrupts = <81 0x2>;
+ vdd-supply = <&pm8110_l19>;
+ vio-supply = <&pm8110_l14>;
+ fsl,sensors-position = <5>;
+ fsl,irq-gpio = <&msmgpio 0x81 0x02>;
+ };
\ No newline at end of file
diff --git a/Documentation/devicetree/bindings/input/touchscreen/atmel-mxt-ts.txt b/Documentation/devicetree/bindings/input/touchscreen/atmel-mxt-ts.txt
index 6fe88a9..4c6ae93 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/atmel-mxt-ts.txt
+++ b/Documentation/devicetree/bindings/input/touchscreen/atmel-mxt-ts.txt
@@ -35,6 +35,8 @@
needed during wakeup.
- atmel,no-force-update : flag that signifies whether force configuration
update is applicable or not
+ - atmel,no-lpm-support : flag that signifies whether low power mode is
+ supported or not on this platform
Example:
i2c@f9966000 {
diff --git a/Documentation/devicetree/bindings/leds/leds-qpnp.txt b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
index ff95d43..e9c5061 100644
--- a/Documentation/devicetree/bindings/leds/leds-qpnp.txt
+++ b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
@@ -81,7 +81,9 @@
- qcom,source-sel: select power source, default 1 (enabled)
- qcom,mode-ctrl: select operation mode, default 0x60 = Mode Sink
- qcom,mode: mode the led should operate in, options "pwm", "lpg" and "manual"
+- qcom,vin-ctrl: select input source, supported values are 0 to 3
- qcom,use-blink: Use blink sysfs entry for switching into lpg mode. For optimal use, set default mode to pwm. All required lpg parameters must be supplied.
+- qcom,min-brightness - Lowest possible brightness supported on this LED other than 0.
Required properties for PWM mode only:
- qcom,pwm-channel: pwm channel the led will operate on
@@ -136,6 +138,8 @@
qcom,id = <6>;
qcom,source-sel = <1>;
qcom,mode-ctrl = <0x10>;
+ qcom,vin-ctrl = <0x03>;
+ qcom,min-brightness = <20>;
};
};
diff --git a/Documentation/devicetree/bindings/media/video/msm-cci.txt b/Documentation/devicetree/bindings/media/video/msm-cci.txt
index 583fbfa..8e988be 100644
--- a/Documentation/devicetree/bindings/media/video/msm-cci.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-cci.txt
@@ -95,6 +95,11 @@
#gpio-cells specifying specific gpio (controller specific)
- qcom,gpio-reset : should contain index to gpio used by sensors reset_n
- qcom,gpio-standby : should contain index to gpio used by sensors standby_n
+- qcom,gpio-vio : should contain index to gpio used by sensors io vreg enable
+- qcom,gpio-vana : should contain index to gpio used by sensors analog vreg enable
+- qcom,gpio-vdig : should contain index to gpio used by sensors digital vreg enable
+- qcom,gpio-vaf : should contain index to gpio used by sensors af vreg enable
+- qcom,gpio-af-pwdm : should contain index to gpio used by sensors af pwdm_n
- qcom,gpio-req-tbl-num : should contain index to gpios specific to this sensor
- qcom,gpio-req-tbl-flags : should contain direction of gpios present in
qcom,gpio-req-tbl-num property (in the same order)
diff --git a/Documentation/devicetree/bindings/power/qpnp-bms.txt b/Documentation/devicetree/bindings/power/qpnp-bms.txt
index 3cac311..3e7a578 100644
--- a/Documentation/devicetree/bindings/power/qpnp-bms.txt
+++ b/Documentation/devicetree/bindings/power/qpnp-bms.txt
@@ -77,6 +77,10 @@
number of the FCC measurement cycles required to
generate an FCC update. This is applicable only
if the FCC learning is enabled.
+- qcom,fcc-resolution: An integer which defines the fcc resolution used
+ for storing the FCC(mAh) in the 8-bit BMS register.
+ For example - A value of 10 indicates:
+ FCC value (in mAh) = (8-bit register value) * 10.
Parent node optional properties:
- qcom,ignore-shutdown-soc: A boolean that controls whether BMS will
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index b4bcaf6..a3a3807 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -8,6 +8,7 @@
apm Applied Micro Circuits Corporation (APM)
arm ARM Ltd.
atmel Atmel Corporation
+bosch Bosch Sensortec GmbH
cavium Cavium, Inc.
chrp Common Hardware Reference Platform
cortina Cortina Systems, Inc.
diff --git a/arch/arm/boot/dts/mpq8092-iommu.dtsi b/arch/arm/boot/dts/mpq8092-iommu.dtsi
index 4fb2b24..3a86814 100644
--- a/arch/arm/boot/dts/mpq8092-iommu.dtsi
+++ b/arch/arm/boot/dts/mpq8092-iommu.dtsi
@@ -212,3 +212,7 @@
0x10
0x0>;
};
+
+&vpu_iommu {
+ status = "ok";
+};
diff --git a/arch/arm/boot/dts/mpq8092-rumi.dtsi b/arch/arm/boot/dts/mpq8092-rumi.dtsi
index 2016998..cc345d8 100644
--- a/arch/arm/boot/dts/mpq8092-rumi.dtsi
+++ b/arch/arm/boot/dts/mpq8092-rumi.dtsi
@@ -24,13 +24,13 @@
};
qcom,sdcc@f9824000 {
- status = "disabled";
qcom,clk-rates = <400000 19200000>;
+ status = "ok";
};
qcom,sdcc@f98a4000 {
- status = "disabled";
qcom,clk-rates = <400000 19200000>;
+ status = "ok";
};
qcom,sps@f998000 {
diff --git a/arch/arm/boot/dts/mpq8092.dtsi b/arch/arm/boot/dts/mpq8092.dtsi
index 7dd3ea8..04f0945 100644
--- a/arch/arm/boot/dts/mpq8092.dtsi
+++ b/arch/arm/boot/dts/mpq8092.dtsi
@@ -291,6 +291,10 @@
status = "ok";
};
+&gdsc_vpu {
+ status = "ok";
+};
+
&gdsc_oxili_gx {
status = "ok";
};
diff --git a/arch/arm/boot/dts/msm8226-regulator.dtsi b/arch/arm/boot/dts/msm8226-regulator.dtsi
index 3e89c3a..571ddc3 100644
--- a/arch/arm/boot/dts/msm8226-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8226-regulator.dtsi
@@ -44,8 +44,8 @@
qcom,pvs-bin-process = <0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2
2 2 2 2 3 3 3 3 3 3 3 3 0 0 0 0>;
qcom,pvs-corner-ceiling-slow = <1155000 1160000 1275000>;
- qcom,pvs-corner-ceiling-nom = <975000 1075000 1200000>;
- qcom,pvs-corner-ceiling-fast = <900000 1000000 1140000>;
+ qcom,pvs-corner-ceiling-nom = <1050000 1075000 1200000>;
+ qcom,pvs-corner-ceiling-fast = <1050000 1050000 1140000>;
vdd-apc-supply = <&pm8226_s2>;
vdd-mx-supply = <&pm8226_l3_ao>;
diff --git a/arch/arm/boot/dts/msm8226-v2.dtsi b/arch/arm/boot/dts/msm8226-v2.dtsi
index d16718c..b44cb681 100644
--- a/arch/arm/boot/dts/msm8226-v2.dtsi
+++ b/arch/arm/boot/dts/msm8226-v2.dtsi
@@ -43,8 +43,8 @@
qcom,pvs-bin-process = <1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2
2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 3>;
qcom,pvs-corner-ceiling-slow = <1160000 1160000 1280000>;
- qcom,pvs-corner-ceiling-nom = <980000 1080000 1200000>;
- qcom,pvs-corner-ceiling-fast = <900000 1000000 1140000>;
+ qcom,pvs-corner-ceiling-nom = <1050000 1080000 1200000>;
+ qcom,pvs-corner-ceiling-fast = <1050000 1050000 1140000>;
qcom,cpr-step-quotient = <30>;
qcom,cpr-up-threshold = <0>;
qcom,cpr-down-threshold = <5>;
diff --git a/arch/arm/boot/dts/msm8610-cdp.dts b/arch/arm/boot/dts/msm8610-cdp.dts
index 6b61317..a62a53c 100644
--- a/arch/arm/boot/dts/msm8610-cdp.dts
+++ b/arch/arm/boot/dts/msm8610-cdp.dts
@@ -222,9 +222,13 @@
qcom,default-state = "on";
qcom,max-current = <40>;
qcom,id = <6>;
- qcom,source-sel = <1>;
+ qcom,source-sel = <8>;
qcom,mode-ctrl = <0x10>;
- qcom,mode = "manual";
+ qcom,pwm-channel = <0>;
+ qcom,pwm-us = <14>;
+ qcom,vin-ctrl = <0x03>;
+ qcom,mode = "pwm";
+ qcom,min-brightness = <19>;
};
};
};
diff --git a/arch/arm/boot/dts/msm8610-mtp.dts b/arch/arm/boot/dts/msm8610-mtp.dts
index 16fc2e7..72a6efb 100644
--- a/arch/arm/boot/dts/msm8610-mtp.dts
+++ b/arch/arm/boot/dts/msm8610-mtp.dts
@@ -42,6 +42,7 @@
atmel,display-coords = <0 0 480 800>;
atmel,i2c-pull-up;
atmel,no-force-update;
+ atmel,no-lpm-support;
atmel,cfg_1 {
atmel,family-id = <0x81>;
atmel,variant-id = <0x15>;
@@ -105,6 +106,16 @@
invn,gpio-en = <&pm8110_gpios 2 0x2>;
invn,poll-interval = <200>;
};
+
+ bmp180@77 {
+ reg = <0x77>;
+ compatible = "bosch,bmp18x";
+ vdd-supply = <&pm8110_l19>;
+ vddio-supply = <&pm8110_l14>;
+ bosch,chip-id = <0x55>;
+ bosch,oversample = <3>;
+ bosch,period = <1000>;
+ };
};
gen-vkeys {
@@ -239,9 +250,13 @@
qcom,default-state = "on";
qcom,max-current = <40>;
qcom,id = <6>;
- qcom,source-sel = <1>;
+ qcom,source-sel = <8>;
qcom,mode-ctrl = <0x10>;
- qcom,mode = "manual";
+ qcom,pwm-channel = <0>;
+ qcom,pwm-us = <14>;
+ qcom,vin-ctrl = <0x03>;
+ qcom,mode = "pwm";
+ qcom,min-brightness = <19>;
};
};
};
diff --git a/arch/arm/boot/dts/msm8610-qrd.dtsi b/arch/arm/boot/dts/msm8610-qrd.dtsi
index 5a30d40..bd1705f 100644
--- a/arch/arm/boot/dts/msm8610-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8610-qrd.dtsi
@@ -213,9 +213,13 @@
qcom,default-state = "on";
qcom,max-current = <40>;
qcom,id = <6>;
- qcom,source-sel = <1>;
+ qcom,source-sel = <8>;
qcom,mode-ctrl = <0x10>;
- qcom,mode = "manual";
+ qcom,pwm-channel = <0>;
+ qcom,pwm-us = <14>;
+ qcom,vin-ctrl = <0x03>;
+ qcom,mode = "pwm";
+ qcom,min-brightness = <19>;
};
};
};
diff --git a/arch/arm/boot/dts/msm8610-regulator.dtsi b/arch/arm/boot/dts/msm8610-regulator.dtsi
index 38f587b..cf54098 100644
--- a/arch/arm/boot/dts/msm8610-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8610-regulator.dtsi
@@ -197,6 +197,7 @@
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1200000>;
qcom,init-voltage = <1200000>;
+ regulator-always-on;
status = "okay";
};
};
diff --git a/arch/arm/boot/dts/msm8974-fluid.dtsi b/arch/arm/boot/dts/msm8974-fluid.dtsi
index 57ce130..af21e43 100644
--- a/arch/arm/boot/dts/msm8974-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-fluid.dtsi
@@ -406,6 +406,7 @@
qcom,min-fcc-learning-soc = <20>;
qcom,min-fcc-ocv-pc = <30>;
qcom,min-fcc-learning-samples = <5>;
+ qcom,fcc-resolution = <10>;
status = "ok";
};
diff --git a/arch/arm/boot/dts/msm8974-mtp.dtsi b/arch/arm/boot/dts/msm8974-mtp.dtsi
index 7b43d9b..8e3b7cc 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-mtp.dtsi
@@ -355,6 +355,7 @@
qcom,min-fcc-learning-soc = <20>;
qcom,min-fcc-ocv-pc = <30>;
qcom,min-fcc-learning-samples = <5>;
+ qcom,fcc-resolution = <10>;
status = "ok";
};
diff --git a/arch/arm/boot/dts/msm9625-pm.dtsi b/arch/arm/boot/dts/msm9625-pm.dtsi
index 24c6143..e18e143 100644
--- a/arch/arm/boot/dts/msm9625-pm.dtsi
+++ b/arch/arm/boot/dts/msm9625-pm.dtsi
@@ -271,8 +271,9 @@
<37 71>;
};
- qcom,pm-8x60 {
+ qcom,pm-8x60@fe805664 {
compatible = "qcom,pm-8x60";
+ reg = <0xfe805664 0x40>;
qcom,pc-mode = "tz_l2_ext";
qcom,use-sync-timer;
};
diff --git a/arch/arm/boot/dts/msmkrypton.dtsi b/arch/arm/boot/dts/msmkrypton.dtsi
index 35d6d2a..3743c54 100644
--- a/arch/arm/boot/dts/msmkrypton.dtsi
+++ b/arch/arm/boot/dts/msmkrypton.dtsi
@@ -128,6 +128,15 @@
status = "disabled";
};
+ qcom,sps@f9980000 {
+ compatible = "qcom,msm_sps";
+ reg = <0xf9984000 0x15000>,
+ <0xf9999000 0xb000>,
+ <0xfe803000 0xd000>,
+ <0xfe805000 0x1000>;
+ interrupts = <0 94 0>;
+ };
+
spi_6: spi@f9928000 { /* BLSP1 QUP6 */
cell-index = <0>;
compatible = "qcom,spi-qup-v2";
diff --git a/arch/arm/configs/msm8226_defconfig b/arch/arm/configs/msm8226_defconfig
index fa86cc8..6c59c38 100644
--- a/arch/arm/configs/msm8226_defconfig
+++ b/arch/arm/configs/msm8226_defconfig
@@ -71,6 +71,7 @@
CONFIG_MSM_RTB_SEPARATE_CPUS=y
CONFIG_MSM_ENABLE_WDOG_DEBUG_CONTROL=y
CONFIG_MSM_BOOT_STATS=y
+CONFIG_MSM_XPU_ERR_FATAL=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_SMP=y
diff --git a/arch/arm/configs/msm8610-perf_defconfig b/arch/arm/configs/msm8610-perf_defconfig
index 894b0b9..5e39b1f 100644
--- a/arch/arm/configs/msm8610-perf_defconfig
+++ b/arch/arm/configs/msm8610-perf_defconfig
@@ -242,6 +242,8 @@
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_QUP=y
CONFIG_INPUT_MPU3050=y
+CONFIG_BMP18X=y
+CONFIG_BMP18X_I2C=y
CONFIG_MSM_BUSPM_DEV=m
CONFIG_SPI=y
CONFIG_SPI_QUP=y
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index 505e883..0305580 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -240,6 +240,8 @@
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_QUP=y
CONFIG_INPUT_MPU3050=y
+CONFIG_BMP18X=y
+CONFIG_BMP18X_I2C=y
CONFIG_MSM_BUSPM_DEV=m
CONFIG_SPI=y
CONFIG_SPI_QUP=y
diff --git a/arch/arm/configs/msmkrypton_defconfig b/arch/arm/configs/msmkrypton_defconfig
index f073d2b..6609c32 100644
--- a/arch/arm/configs/msmkrypton_defconfig
+++ b/arch/arm/configs/msmkrypton_defconfig
@@ -104,6 +104,9 @@
CONFIG_SPI_SPIDEV=m
CONFIG_DEBUG_GPIO=y
CONFIG_GPIO_SYSFS=y
+CONFIG_SPS=y
+CONFIG_SPS_SUPPORT_BAMDMA=y
+CONFIG_SPS_SUPPORT_NDP_BAM=y
CONFIG_MMC=y
CONFIG_MMC_PERF_PROFILING=y
CONFIG_MMC_UNSAFE_RESUME=y
diff --git a/arch/arm/mach-msm/clock-8084.c b/arch/arm/mach-msm/clock-8084.c
index c54c3db..184338e 100644
--- a/arch/arm/mach-msm/clock-8084.c
+++ b/arch/arm/mach-msm/clock-8084.c
@@ -137,7 +137,8 @@
CLK_DUMMY("", gcc_lpass_mport_axi_clk.c, "", OFF),
CLK_DUMMY("", gcc_lpass_q6_axi_clk.c, "", OFF),
CLK_DUMMY("", gcc_lpass_sway_clk.c, "", OFF),
- CLK_DUMMY("", gcc_mmss_bimc_gfx_clk.c, "", OFF),
+ CLK_DUMMY("mem_iface_clk", gcc_mmss_bimc_gfx_clk.c,
+ "fdb00000.qcom,kgsl-3d0", OFF),
CLK_DUMMY("", gcc_mmss_vpu_maple_sys_noc_axi_clk.c, "", OFF),
CLK_DUMMY("", gcc_ocmem_noc_cfg_ahb_clk.c, "", OFF),
CLK_DUMMY("", gcc_msg_ram_ahb_clk.c, "", OFF),
@@ -337,9 +338,11 @@
CLK_DUMMY("iface_clk", ocmemcx_ocmemnoc_clk.c,
"fdd00000.qcom,ocmem", OFF),
CLK_DUMMY("", oxili_ocmemgx_clk.c, "", OFF),
- CLK_DUMMY("", oxili_gfx3d_clk.c, "", OFF),
+ CLK_DUMMY("core_clk", oxili_gfx3d_clk.c,
+ "fdb00000.qcom,kgsl-3d0", OFF),
CLK_DUMMY("", oxili_rbbmtimer_clk.c, "", OFF),
- CLK_DUMMY("", oxilicx_ahb_clk.c, "", OFF),
+ CLK_DUMMY("iface_clk", oxilicx_ahb_clk.c,
+ "fdb00000.qcom,kgsl-3d0", OFF),
CLK_DUMMY("", venus0_ahb_clk.c, "", OFF),
CLK_DUMMY("", venus0_axi_clk.c, "", OFF),
CLK_DUMMY("", venus0_core0_vcodec_clk.c, "", OFF),
diff --git a/arch/arm/mach-msm/clock-krypton.c b/arch/arm/mach-msm/clock-krypton.c
index aaee003..0b615cc 100644
--- a/arch/arm/mach-msm/clock-krypton.c
+++ b/arch/arm/mach-msm/clock-krypton.c
@@ -46,6 +46,8 @@
CLK_DUMMY("mem_clk", bimc_msmbus_clk.c, "msm_bimc", OFF),
CLK_DUMMY("mem_a_clk", bimc_msmbus_a_clk.c, "msm_bimc", OFF),
CLK_DUMMY("mem_clk", bimc_acpu_a_clk.c, "", OFF),
+ CLK_DUMMY("dfab_clk", DFAB_CLK, "msm_sps", OFF),
+ CLK_DUMMY("dma_bam_pclk", DMA_BAM_P_CLK, "msm_sps", OFF),
CLK_DUMMY("clktype", gcc_imem_axi_clk , "drivername", OFF),
CLK_DUMMY("clktype", gcc_imem_cfg_ahb_clk , "drivername", OFF),
diff --git a/arch/arm/mach-msm/clock-rpm.c b/arch/arm/mach-msm/clock-rpm.c
index 8356207..1d7a5e2 100644
--- a/arch/arm/mach-msm/clock-rpm.c
+++ b/arch/arm/mach-msm/clock-rpm.c
@@ -42,7 +42,7 @@
int rc;
struct msm_rpm_iv_pair iv = { .id = r->rpm_status_id, };
rc = msm_rpm_get_status(&iv, 1);
- return (rc < 0) ? rc : iv.value * r->factor;
+ return (rc < 0) ? rc : iv.value * 1000;
}
static int clk_rpmrs_handoff(struct rpm_clk *r)
@@ -54,7 +54,7 @@
return rc;
if (!r->branch)
- r->c.rate = iv.value * r->factor;
+ r->c.rate = iv.value * 1000;
return 0;
}
@@ -122,7 +122,7 @@
unsigned long *active_khz, unsigned long *sleep_khz)
{
/* Convert the rate (hz) to khz */
- *active_khz = DIV_ROUND_UP(rate, r->factor);
+ *active_khz = DIV_ROUND_UP(rate, 1000);
/*
* Active-only clocks don't care what the rate is during sleep. So,
diff --git a/arch/arm/mach-msm/clock-rpm.h b/arch/arm/mach-msm/clock-rpm.h
index b20c3d6..d283861 100644
--- a/arch/arm/mach-msm/clock-rpm.h
+++ b/arch/arm/mach-msm/clock-rpm.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -39,9 +39,7 @@
const bool active_only;
bool enabled;
bool branch; /* true: RPM only accepts 1 for ON and 0 for OFF */
- unsigned factor;
struct clk_rpmrs_data *rpmrs_data;
-
struct rpm_clk *peer;
struct clk c;
};
@@ -69,7 +67,6 @@
.rpm_status_id = (stat_id), \
.rpm_key = (key), \
.peer = &active, \
- .factor = 1000, \
.rpmrs_data = (rpmrsdata),\
.c = { \
.ops = &clk_ops_rpm, \
@@ -85,7 +82,6 @@
.rpm_key = (key), \
.peer = &name, \
.active_only = true, \
- .factor = 1000, \
.rpmrs_data = (rpmrsdata),\
.c = { \
.ops = &clk_ops_rpm, \
@@ -104,7 +100,6 @@
.rpm_status_id = (stat_id), \
.rpm_key = (key), \
.peer = &active, \
- .factor = 1000, \
.branch = true, \
.rpmrs_data = (rpmrsdata),\
.c = { \
@@ -121,7 +116,6 @@
.rpm_key = (key), \
.peer = &name, \
.active_only = true, \
- .factor = 1000, \
.branch = true, \
.rpmrs_data = (rpmrsdata),\
.c = { \
@@ -132,46 +126,13 @@
}, \
};
-#define __DEFINE_CLK_RPM_QDSS(name, active, type, r_id, stat_id, \
- key, rpmrsdata) \
- static struct rpm_clk active; \
- static struct rpm_clk name = { \
- .rpm_res_type = (type), \
- .rpm_clk_id = (r_id), \
- .rpm_status_id = (stat_id), \
- .rpm_key = (key), \
- .peer = &active, \
- .factor = 1, \
- .rpmrs_data = (rpmrsdata),\
- .c = { \
- .ops = &clk_ops_rpm, \
- .dbg_name = #name, \
- CLK_INIT(name.c), \
- }, \
- }; \
- static struct rpm_clk active = { \
- .rpm_res_type = (type), \
- .rpm_clk_id = (r_id), \
- .rpm_status_id = (stat_id), \
- .rpm_key = (key), \
- .peer = &name, \
- .active_only = true, \
- .factor = 1, \
- .rpmrs_data = (rpmrsdata),\
- .c = { \
- .ops = &clk_ops_rpm, \
- .dbg_name = #active, \
- CLK_INIT(active.c), \
- }, \
- };
-
#define DEFINE_CLK_RPM(name, active, r_id, dep) \
__DEFINE_CLK_RPM(name, active, 0, MSM_RPM_ID_##r_id##_CLK, \
MSM_RPM_STATUS_ID_##r_id##_CLK, dep, 0, &clk_rpmrs_data)
#define DEFINE_CLK_RPM_QDSS(name, active) \
- __DEFINE_CLK_RPM_QDSS(name, active, 0, MSM_RPM_ID_QDSS_CLK, \
- MSM_RPM_STATUS_ID_QDSS_CLK, 0, &clk_rpmrs_data)
+ __DEFINE_CLK_RPM(name, active, 0, MSM_RPM_ID_QDSS_CLK, \
+ MSM_RPM_STATUS_ID_QDSS_CLK, 0, 0, &clk_rpmrs_data)
#define DEFINE_CLK_RPM_BRANCH(name, active, r_id, r) \
__DEFINE_CLK_RPM_BRANCH(name, active, 0, MSM_RPM_ID_##r_id##_CLK, \
@@ -186,8 +147,8 @@
RPM_SMD_KEY_ENABLE, &clk_rpmrs_data_smd)
#define DEFINE_CLK_RPM_SMD_QDSS(name, active, type, r_id) \
- __DEFINE_CLK_RPM_QDSS(name, active, type, r_id, \
- 0, RPM_SMD_KEY_STATE, &clk_rpmrs_data_smd)
+ __DEFINE_CLK_RPM(name, active, type, r_id, \
+ 0, 0, RPM_SMD_KEY_STATE, &clk_rpmrs_data_smd)
/*
* The RPM XO buffer clock management code aggregates votes for pin-control mode
* and software mode separately. Software-enable has higher priority over pin-
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index 7b26bd6..6370bd4 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -183,7 +183,7 @@
};
struct msm_camera_gpio_num_info {
- uint16_t gpio_num[2];
+ uint16_t gpio_num[7];
};
struct msm_camera_gpio_conf {
diff --git a/arch/arm/mach-msm/include/mach/ocmem_priv.h b/arch/arm/mach-msm/include/mach/ocmem_priv.h
index 6f83c53..32d58d4 100644
--- a/arch/arm/mach-msm/include/mach/ocmem_priv.h
+++ b/arch/arm/mach-msm/include/mach/ocmem_priv.h
@@ -174,8 +174,8 @@
/* Request Power State */
unsigned power_state;
struct ocmem_eviction_data *edata;
- /* Request that triggered eviction */
- struct ocmem_req *e_handle;
+ /* Eviction data of the request being evicted */
+ struct ocmem_eviction_data *eviction_info;
};
struct ocmem_handle {
diff --git a/arch/arm/mach-msm/ocmem_sched.c b/arch/arm/mach-msm/ocmem_sched.c
index a3fd6b2..cbf7933 100644
--- a/arch/arm/mach-msm/ocmem_sched.c
+++ b/arch/arm/mach-msm/ocmem_sched.c
@@ -1192,19 +1192,23 @@
}
/* Remove the request from eviction lists */
-static void cancel_restore(struct ocmem_req *e_handle,
- struct ocmem_req *req)
+static void cancel_restore(struct ocmem_req *req)
{
- struct ocmem_eviction_data *edata = e_handle->edata;
+ struct ocmem_eviction_data *edata;
- if (!edata || !req)
+ if (!req)
+ return;
+
+ edata = req->eviction_info;
+
+ if (!edata)
return;
if (list_empty(&edata->req_list))
return;
list_del_init(&req->eviction_list);
- req->e_handle = NULL;
+ req->eviction_info = NULL;
return;
}
@@ -1499,8 +1503,8 @@
}
/* Remove the request from any restore lists */
- if (req->e_handle)
- cancel_restore(req->e_handle, req);
+ if (req->eviction_info)
+ cancel_restore(req);
/* Remove the request from any pending opreations */
if (TEST_STATE(req, R_ENQUEUED)) {
@@ -1747,12 +1751,7 @@
goto shrink_fail;
}
- if (!req->e_handle) {
- pr_err("Unable to find evicting request\n");
- goto shrink_fail;
- }
-
- edata = req->e_handle->edata;
+ edata = req->eviction_info;
if (!edata) {
pr_err("Unable to find eviction data\n");
@@ -1905,7 +1904,7 @@
&e_req->eviction_list,
&edata->req_list);
atomic_inc(&edata->pending);
- e_req->e_handle = req;
+ e_req->eviction_info = edata;
}
}
} else {
@@ -2037,7 +2036,7 @@
pr_debug("ocmem: restoring evicted request %p\n",
req);
req->edata = NULL;
- req->e_handle = NULL;
+ req->eviction_info = NULL;
req->op = SCHED_ALLOCATE;
inc_ocmem_stat(zone_of(req), NR_RESTORES);
sched_enqueue(req);
@@ -2076,8 +2075,11 @@
struct ocmem_eviction_data *edata = evictions[id];
int rc = 0;
- if (!edata)
+ if (!edata) {
+ pr_err("Client %s invoked restore without any eviction\n",
+ get_name(id));
return -EINVAL;
+ }
mutex_lock(&free_mutex);
rc = __restore_common(edata);
diff --git a/arch/arm/mach-msm/pil-dsps.c b/arch/arm/mach-msm/pil-dsps.c
index 73b58ab..f0a5ebf 100644
--- a/arch/arm/mach-msm/pil-dsps.c
+++ b/arch/arm/mach-msm/pil-dsps.c
@@ -23,6 +23,7 @@
#include <mach/msm_smsm.h>
#include <mach/ramdump.h>
#include <mach/msm_smem.h>
+#include <mach/msm_bus_board.h>
#include "peripheral-loader.h"
#include "scm-pas.h"
@@ -317,6 +318,8 @@
goto err_subsys;
}
+ scm_pas_init(MSM_BUS_MASTER_SPS);
+
ret = smsm_state_cb_register(SMSM_DSPS_STATE, SMSM_RESET,
dsps_smsm_state_cb, drv);
if (ret)
diff --git a/arch/arm/mach-msm/pil-gss.c b/arch/arm/mach-msm/pil-gss.c
index 840c90f..b209a25 100644
--- a/arch/arm/mach-msm/pil-gss.c
+++ b/arch/arm/mach-msm/pil-gss.c
@@ -571,6 +571,8 @@
goto err_smem;
}
+ scm_pas_init(MSM_BUS_MASTER_SPS);
+
ret = devm_request_irq(&pdev->dev, drv->irq, gss_wdog_bite_irq,
IRQF_TRIGGER_RISING, "gss_a5_wdog", drv);
if (ret < 0)
diff --git a/arch/arm/mach-msm/pil-modem.c b/arch/arm/mach-msm/pil-modem.c
index 8398206..f6a853e 100644
--- a/arch/arm/mach-msm/pil-modem.c
+++ b/arch/arm/mach-msm/pil-modem.c
@@ -25,6 +25,7 @@
#include <mach/subsystem_restart.h>
#include <mach/msm_smsm.h>
#include <mach/ramdump.h>
+#include <mach/msm_bus_board.h>
#include "modem_notifier.h"
#include "peripheral-loader.h"
@@ -490,6 +491,8 @@
goto err_ramdump;
}
+ scm_pas_init(MSM_BUS_MASTER_SPS);
+
ret = devm_request_irq(&pdev->dev, drv->irq, modem_wdog_bite_irq,
IRQF_TRIGGER_RISING, "modem_watchdog", drv);
if (ret)
diff --git a/arch/arm/mach-msm/pil-pronto.c b/arch/arm/mach-msm/pil-pronto.c
index 80c0862..6e4aa02 100644
--- a/arch/arm/mach-msm/pil-pronto.c
+++ b/arch/arm/mach-msm/pil-pronto.c
@@ -31,6 +31,7 @@
#include <mach/msm_smsm.h>
#include <mach/ramdump.h>
#include <mach/msm_smem.h>
+#include <mach/msm_bus_board.h>
#include "peripheral-loader.h"
#include "scm-pas.h"
@@ -504,6 +505,8 @@
if (IS_ERR(drv->cxo))
return PTR_ERR(drv->cxo);
+ scm_pas_init(MSM_BUS_MASTER_CRYPTO_CORE0);
+
ret = pil_desc_init(desc);
if (ret)
return ret;
diff --git a/arch/arm/mach-msm/pil-q6v3.c b/arch/arm/mach-msm/pil-q6v3.c
index a369878..58d4301 100644
--- a/arch/arm/mach-msm/pil-q6v3.c
+++ b/arch/arm/mach-msm/pil-q6v3.c
@@ -24,6 +24,7 @@
#include <mach/subsystem_restart.h>
#include <mach/scm.h>
#include <mach/ramdump.h>
+#include <mach/msm_bus_board.h>
#include "peripheral-loader.h"
#include "scm-pas.h"
@@ -393,6 +394,8 @@
goto err_subsys;
}
+ scm_pas_init(MSM_BUS_MASTER_SPS);
+
ret = devm_request_irq(&pdev->dev, drv->irq, lpass_wdog_bite_irq,
IRQF_TRIGGER_RISING, "lpass_wdog", drv);
if (ret) {
diff --git a/arch/arm/mach-msm/pil-q6v4-lpass.c b/arch/arm/mach-msm/pil-q6v4-lpass.c
index 7acb599..6ec8430 100644
--- a/arch/arm/mach-msm/pil-q6v4-lpass.c
+++ b/arch/arm/mach-msm/pil-q6v4-lpass.c
@@ -26,6 +26,7 @@
#include <mach/subsystem_notif.h>
#include <mach/ramdump.h>
#include <mach/msm_smem.h>
+#include <mach/msm_bus_board.h>
#include "smd_private.h"
#include "sysmon.h"
@@ -356,6 +357,8 @@
goto err_notif_riva;
}
+ scm_pas_init(MSM_BUS_MASTER_SPS);
+
drv->modem_notif_hdle = subsys_notif_register_notifier("modem", &mnb);
if (IS_ERR(drv->modem_notif_hdle)) {
ret = PTR_ERR(drv->modem_notif_hdle);
diff --git a/arch/arm/mach-msm/pil-q6v4-mss.c b/arch/arm/mach-msm/pil-q6v4-mss.c
index c4b6038..6ee5965 100644
--- a/arch/arm/mach-msm/pil-q6v4-mss.c
+++ b/arch/arm/mach-msm/pil-q6v4-mss.c
@@ -24,6 +24,7 @@
#include <mach/msm_smsm.h>
#include <mach/ramdump.h>
#include <mach/msm_smem.h>
+#include <mach/msm_bus_board.h>
#include "smd_private.h"
#include "peripheral-loader.h"
@@ -462,6 +463,8 @@
if (ret)
goto err_irq;
+ scm_pas_init(MSM_BUS_MASTER_SPS);
+
ret = smsm_state_cb_register(SMSM_MODEM_STATE, SMSM_RESET,
smsm_state_cb, drv);
if (ret)
diff --git a/arch/arm/mach-msm/pil-q6v5-lpass.c b/arch/arm/mach-msm/pil-q6v5-lpass.c
index 6cd6ffe..3b88b10 100644
--- a/arch/arm/mach-msm/pil-q6v5-lpass.c
+++ b/arch/arm/mach-msm/pil-q6v5-lpass.c
@@ -30,6 +30,7 @@
#include <mach/scm.h>
#include <mach/ramdump.h>
#include <mach/msm_smem.h>
+#include <mach/msm_bus_board.h>
#include "peripheral-loader.h"
#include "pil-q6v5.h"
@@ -472,6 +473,8 @@
dev_info(&pdev->dev, "using non-secure boot\n");
}
+ scm_pas_init(MSM_BUS_MASTER_CRYPTO_CORE0);
+
ret = pil_desc_init(desc);
if (ret)
return ret;
diff --git a/arch/arm/mach-msm/pil-riva.c b/arch/arm/mach-msm/pil-riva.c
index bf7438b..9a364b7 100644
--- a/arch/arm/mach-msm/pil-riva.c
+++ b/arch/arm/mach-msm/pil-riva.c
@@ -25,6 +25,7 @@
#include <mach/subsystem_restart.h>
#include <mach/ramdump.h>
#include <mach/msm_smem.h>
+#include <mach/msm_bus_board.h>
#include "peripheral-loader.h"
#include "scm-pas.h"
@@ -534,6 +535,8 @@
goto err_subsys;
}
+ scm_pas_init(MSM_BUS_MASTER_SPS);
+
ret = devm_request_irq(&pdev->dev, drv->irq, riva_wdog_bite_irq_hdlr,
IRQF_TRIGGER_RISING, "riva_wdog", drv);
if (ret < 0)
diff --git a/arch/arm/mach-msm/pil-tzapps.c b/arch/arm/mach-msm/pil-tzapps.c
index 1410117..d9f5700 100644
--- a/arch/arm/mach-msm/pil-tzapps.c
+++ b/arch/arm/mach-msm/pil-tzapps.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -16,6 +16,7 @@
#include <linux/err.h>
#include <mach/subsystem_restart.h>
+#include <mach/msm_bus_board.h>
#include "peripheral-loader.h"
#include "scm-pas.h"
@@ -97,6 +98,9 @@
pil_desc_release(desc);
return PTR_ERR(drv->subsys);
}
+
+ scm_pas_init(MSM_BUS_MASTER_SPS);
+
return 0;
}
diff --git a/arch/arm/mach-msm/pil-venus.c b/arch/arm/mach-msm/pil-venus.c
index 4e9e54b..a7ebbf7 100644
--- a/arch/arm/mach-msm/pil-venus.c
+++ b/arch/arm/mach-msm/pil-venus.c
@@ -605,6 +605,8 @@
if (!drv->ramdump_dev)
return -ENOMEM;
+ scm_pas_init(MSM_BUS_MASTER_CRYPTO_CORE0);
+
rc = pil_desc_init(desc);
if (rc)
goto err_ramdump;
diff --git a/arch/arm/mach-msm/pil-vidc.c b/arch/arm/mach-msm/pil-vidc.c
index 629907f..3dbddae 100644
--- a/arch/arm/mach-msm/pil-vidc.c
+++ b/arch/arm/mach-msm/pil-vidc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -17,6 +17,7 @@
#include <linux/clk.h>
#include <mach/subsystem_restart.h>
+#include <mach/msm_bus_board.h>
#include "peripheral-loader.h"
#include "scm-pas.h"
@@ -122,6 +123,9 @@
pil_desc_release(desc);
return PTR_ERR(drv->subsys);
}
+
+ scm_pas_init(MSM_BUS_MASTER_SPS);
+
return 0;
}
diff --git a/arch/arm/mach-msm/scm-pas.c b/arch/arm/mach-msm/scm-pas.c
index b244c6f..57acdc4 100644
--- a/arch/arm/mach-msm/scm-pas.c
+++ b/arch/arm/mach-msm/scm-pas.c
@@ -255,9 +255,14 @@
}
EXPORT_SYMBOL(pas_supported);
-static int __init scm_pas_init(void)
+void scm_pas_init(enum msm_bus_fabric_master_type id)
{
int i, rate;
+ static int is_inited;
+
+ if (is_inited)
+ return;
+
for (i = 0; i < NUM_CLKS; i++) {
scm_clocks[i] = clk_get_sys("scm", scm_clock_names[i]);
if (IS_ERR(scm_clocks[i]))
@@ -268,20 +273,14 @@
rate = clk_round_rate(scm_clocks[CORE_CLK_SRC], 1);
clk_set_rate(scm_clocks[CORE_CLK_SRC], rate);
- if (soc_class_is_msm8974() || cpu_is_msm8226() || cpu_is_msm8610()) {
- scm_pas_bw_tbl[0].vectors[0].src = MSM_BUS_MASTER_CRYPTO_CORE0;
- scm_pas_bw_tbl[1].vectors[0].src = MSM_BUS_MASTER_CRYPTO_CORE0;
- } else {
- if (!IS_ERR(scm_clocks[BUS_CLK]))
- clk_set_rate(scm_clocks[BUS_CLK], 64000000);
- else
- pr_warn("unable to get bus clock\n");
- }
+ scm_pas_bw_tbl[0].vectors[0].src = id;
+ scm_pas_bw_tbl[1].vectors[0].src = id;
+
+ clk_set_rate(scm_clocks[BUS_CLK], 64000000);
scm_perf_client = msm_bus_scale_register_client(&scm_pas_bus_pdata);
if (!scm_perf_client)
pr_warn("unable to register bus client\n");
- return 0;
+ is_inited = 1;
}
-module_init(scm_pas_init);
diff --git a/arch/arm/mach-msm/scm-pas.h b/arch/arm/mach-msm/scm-pas.h
index f13757c..48bc558 100644
--- a/arch/arm/mach-msm/scm-pas.h
+++ b/arch/arm/mach-msm/scm-pas.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -9,6 +9,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
+
+#include <mach/msm_bus_board.h>
+
#ifndef __MSM_SCM_PAS_H
#define __MSM_SCM_PAS_H
@@ -31,6 +34,7 @@
extern int pas_auth_and_reset(enum pas_id id);
extern int pas_shutdown(enum pas_id id);
extern int pas_supported(enum pas_id id);
+extern void scm_pas_init(enum msm_bus_fabric_master_type id);
#else
static inline int pas_init_image(enum pas_id id, const u8 *metadata,
size_t size)
@@ -53,6 +57,9 @@
{
return 0;
}
+static inline void scm_pas_init(enum msm_bus_fabric_master_type id)
+{
+}
#endif
#endif
diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c
index d01496e..0c67ed8 100644
--- a/drivers/char/diag/diag_dci.c
+++ b/drivers/char/diag/diag_dci.c
@@ -20,6 +20,8 @@
#include <linux/workqueue.h>
#include <linux/pm_runtime.h>
#include <linux/platform_device.h>
+#include <linux/pm_wakeup.h>
+#include <linux/spinlock.h>
#include <asm/current.h>
#ifdef CONFIG_DIAG_OVER_USB
#include <mach/usbdiag.h>
@@ -39,6 +41,12 @@
struct mutex dci_event_mask_mutex;
struct mutex dci_health_mutex;
+spinlock_t ws_lock;
+unsigned long ws_lock_flags;
+
+/* Number of milliseconds anticipated to process the DCI data */
+#define DCI_WAKEUP_TIMEOUT 1
+
#define DCI_CHK_CAPACITY(entry, new_data_len) \
((entry->data_len + new_data_len > entry->total_capacity) ? 1 : 0) \
@@ -96,6 +104,11 @@
read_bytes += 5 + dci_pkt_len;
buf += 5 + dci_pkt_len; /* advance to next DCI pkt */
}
+ /* Release wakeup source when there are no more clients to
+ process DCI data */
+ if (driver->num_dci_client == 0)
+ diag_dci_try_deactivate_wakeup_source(smd_info->ch);
+
/* wake up all sleeping DCI clients which have some data */
for (i = 0; i < MAX_DCI_CLIENTS; i++) {
if (driver->dci_client_tbl[i].client &&
@@ -1101,6 +1114,9 @@
diag_smd_notify);
driver->smd_dci[index].ch_save =
driver->smd_dci[index].ch;
+ driver->dci_device = &pdev->dev;
+ driver->dci_device->power.wakeup = wakeup_source_register
+ ("DIAG_DCI_WS");
if (err)
pr_err("diag: In %s, cannot open DCI port, Id = %d, err: %d\n",
__func__, pdev->id, err);
@@ -1123,6 +1139,9 @@
diag_smd_notify);
driver->smd_dci_cmd[index].ch_save =
driver->smd_dci_cmd[index].ch;
+ driver->dci_cmd_device = &pdev->dev;
+ driver->dci_cmd_device->power.wakeup = wakeup_source_register
+ ("DIAG_DCI_CMD_WS");
if (err)
pr_err("diag: In %s, cannot open DCI port, Id = %d, err: %d\n",
__func__, pdev->id, err);
@@ -1174,10 +1193,13 @@
driver->dci_tag = 0;
driver->dci_client_id = 0;
driver->num_dci_client = 0;
+ driver->dci_device = NULL;
+ driver->dci_cmd_device = NULL;
mutex_init(&driver->dci_mutex);
mutex_init(&dci_log_mask_mutex);
mutex_init(&dci_event_mask_mutex);
mutex_init(&dci_health_mutex);
+ spin_lock_init(&ws_lock);
for (i = 0; i < NUM_SMD_DCI_CHANNELS; i++) {
success = diag_smd_constructor(&driver->smd_dci[i], i,
@@ -1408,3 +1430,26 @@
driver->dci_client_tbl[i].real_time = real_time;
return i;
}
+
+void diag_dci_try_activate_wakeup_source(smd_channel_t *channel)
+{
+ spin_lock_irqsave(&ws_lock, ws_lock_flags);
+ if (channel == driver->smd_dci[MODEM_DATA].ch) {
+ pm_wakeup_event(driver->dci_device, DCI_WAKEUP_TIMEOUT);
+ pm_stay_awake(driver->dci_device);
+ } else if (channel == driver->smd_dci_cmd[MODEM_DATA].ch) {
+ pm_wakeup_event(driver->dci_cmd_device, DCI_WAKEUP_TIMEOUT);
+ pm_stay_awake(driver->dci_cmd_device);
+ }
+ spin_unlock_irqrestore(&ws_lock, ws_lock_flags);
+}
+
+void diag_dci_try_deactivate_wakeup_source(smd_channel_t *channel)
+{
+ spin_lock_irqsave(&ws_lock, ws_lock_flags);
+ if (channel == driver->smd_dci[MODEM_DATA].ch)
+ pm_relax(driver->dci_device);
+ else if (channel == driver->smd_dci_cmd[MODEM_DATA].ch)
+ pm_relax(driver->dci_cmd_device);
+ spin_unlock_irqrestore(&ws_lock, ws_lock_flags);
+}
diff --git a/drivers/char/diag/diag_dci.h b/drivers/char/diag/diag_dci.h
index 2335d37..520995b 100644
--- a/drivers/char/diag/diag_dci.h
+++ b/drivers/char/diag/diag_dci.h
@@ -138,4 +138,7 @@
void diag_dci_smd_record_info(int read_bytes);
uint8_t diag_dci_get_cumulative_real_time(void);
int diag_dci_set_real_time(int client_id, uint8_t real_time);
+/* Functions related to DCI wakeup sources */
+void diag_dci_try_activate_wakeup_source(smd_channel_t *channel);
+void diag_dci_try_deactivate_wakeup_source(smd_channel_t *channel);
#endif
diff --git a/drivers/char/diag/diag_debugfs.c b/drivers/char/diag/diag_debugfs.c
index 0badda6..3d1a6cd 100644
--- a/drivers/char/diag/diag_debugfs.c
+++ b/drivers/char/diag/diag_debugfs.c
@@ -176,6 +176,26 @@
bytes_in_buf += bytes_written;
bytes_remaining -= bytes_written;
#endif
+ if (driver->dci_device) {
+ bytes_written = scnprintf(buf+bytes_in_buf,
+ bytes_remaining,
+ "dci power active, relax: %lu, %lu\n",
+ driver->dci_device->power.wakeup->active_count,
+ driver->dci_device->power.wakeup->relax_count);
+ bytes_in_buf += bytes_written;
+ bytes_remaining -= bytes_written;
+ }
+ if (driver->dci_cmd_device) {
+ bytes_written = scnprintf(buf+bytes_in_buf,
+ bytes_remaining,
+ "dci cmd power active, relax: %lu, %lu\n",
+ driver->dci_cmd_device->power.wakeup->
+ active_count,
+ driver->dci_cmd_device->power.wakeup->
+ relax_count);
+ bytes_in_buf += bytes_written;
+ bytes_remaining -= bytes_written;
+ }
}
temp_data += diag_dbgfs_dci_data_index;
for (i = diag_dbgfs_dci_data_index; i < DIAG_DCI_DEBUG_CNT; i++) {
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index b7784b5..3ae56c5 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -333,6 +333,8 @@
unsigned hdlc_count;
unsigned hdlc_escape;
int in_busy_pktdata;
+ struct device *dci_device;
+ struct device *dci_cmd_device;
/* Variables for non real time mode */
int real_time_mode;
int real_time_update_busy;
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 8df1b49..5e06f19 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -1453,19 +1453,25 @@
driver->data_ready[index] ^= DCI_DATA_TYPE;
for (i = 0; i < NUM_SMD_DCI_CHANNELS; i++) {
driver->smd_dci[i].in_busy_1 = 0;
- if (driver->smd_dci[i].ch)
+ if (driver->smd_dci[i].ch) {
+ diag_dci_try_deactivate_wakeup_source(
+ driver->smd_dci[i].ch);
queue_work(driver->diag_dci_wq,
&(driver->smd_dci[i].diag_read_smd_work));
+ }
}
if (driver->supports_separate_cmdrsp) {
for (i = 0; i < NUM_SMD_DCI_CMD_CHANNELS; i++) {
if (!driver->separate_cmdrsp[i])
continue;
driver->smd_dci_cmd[i].in_busy_1 = 0;
- if (driver->smd_dci_cmd[i].ch)
+ if (driver->smd_dci_cmd[i].ch) {
+ diag_dci_try_deactivate_wakeup_source(
+ driver->smd_dci_cmd[i].ch);
queue_work(driver->diag_dci_wq,
&(driver->smd_dci_cmd[i].
diag_read_smd_work));
+ }
}
}
goto exit;
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 6e7080e..de4433b 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -390,10 +390,18 @@
(smd_info->type == SMD_DATA_TYPE))
buf = smd_info->buf_in_2;
+ if (!buf && (smd_info->type == SMD_DCI_TYPE ||
+ smd_info->type == SMD_DCI_CMD_TYPE))
+ diag_dci_try_deactivate_wakeup_source(smd_info->ch);
+
if (smd_info->ch && buf) {
temp_buf = buf;
pkt_len = smd_cur_packet_size(smd_info->ch);
+ if (pkt_len == 0 && (smd_info->type == SMD_DCI_TYPE ||
+ smd_info->type == SMD_DCI_CMD_TYPE))
+ diag_dci_try_deactivate_wakeup_source(smd_info->ch);
+
while (pkt_len && (pkt_len != total_recd)) {
loop_count++;
r = smd_read_avail(smd_info->ch);
@@ -412,7 +420,7 @@
} else {
pr_debug("diag: In %s, return from wait_event ch closed\n",
__func__);
- return;
+ goto fail_return;
}
}
total_recd += r;
@@ -425,13 +433,13 @@
} else {
pr_err("diag: In %s, SMD sending in packets more than %d bytes\n",
__func__, MAX_IN_BUF_SIZE);
- return;
+ goto fail_return;
}
}
if (pkt_len < r) {
pr_err("diag: In %s, SMD sending incorrect pkt\n",
__func__);
- return;
+ goto fail_return;
}
if (pkt_len > r) {
pr_debug("diag: In %s, SMD sending partial pkt %d %d %d %d %d %d\n",
@@ -462,6 +470,13 @@
(driver->logging_mode == MEMORY_DEVICE_MODE)) {
chk_logging_wakeup();
}
+ return;
+
+fail_return:
+ if (smd_info->type == SMD_DCI_TYPE ||
+ smd_info->type == SMD_DCI_CMD_TYPE)
+ diag_dci_try_deactivate_wakeup_source(smd_info->ch);
+ return;
}
void diag_read_smd_work_fn(struct work_struct *work)
@@ -1705,10 +1720,12 @@
wake_up(&driver->smd_wait_q);
if (smd_info->type == SMD_DCI_TYPE ||
- smd_info->type == SMD_DCI_CMD_TYPE)
+ smd_info->type == SMD_DCI_CMD_TYPE) {
+ if (event == SMD_EVENT_DATA)
+ diag_dci_try_activate_wakeup_source(smd_info->ch);
queue_work(driver->diag_dci_wq,
&(smd_info->diag_read_smd_work));
- else
+ } else
queue_work(driver->diag_wq, &(smd_info->diag_read_smd_work));
}
diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c
index d069f2e..0e4b309 100644
--- a/drivers/crypto/msm/qcedev.c
+++ b/drivers/crypto/msm/qcedev.c
@@ -1937,7 +1937,7 @@
rc = misc_register(&podev->miscdevice);
qce_hw_support(podev->qce, &podev->ce_support);
if (podev->ce_support.bam) {
- podev->platform_support.ce_shared = podev->ce_support.is_shared;
+ podev->platform_support.ce_shared = 0;
podev->platform_support.shared_ce_resource = 0;
podev->platform_support.hw_key_support =
podev->ce_support.hw_key;
diff --git a/drivers/gpio/qpnp-pin.c b/drivers/gpio/qpnp-pin.c
index 64341e9..ed001f0 100644
--- a/drivers/gpio/qpnp-pin.c
+++ b/drivers/gpio/qpnp-pin.c
@@ -589,6 +589,9 @@
}
mutex_unlock(&qpnp_pin_chips_lock);
+ if (!q_spec)
+ return -ENODEV;
+
rc = _qpnp_pin_config(q_chip, q_spec, param);
return rc;
@@ -1225,6 +1228,8 @@
if (!res) {
dev_err(&spmi->dev, "%s: node %s is missing has no base address definition\n",
__func__, d_node->of_node->full_name);
+ rc = -EINVAL;
+ goto err_probe;
}
rc = of_property_read_u32(d_node->of_node,
diff --git a/drivers/gpu/ion/msm/msm_ion.c b/drivers/gpu/ion/msm/msm_ion.c
index f990ada..118c39a 100644
--- a/drivers/gpu/ion/msm/msm_ion.c
+++ b/drivers/gpu/ion/msm/msm_ion.c
@@ -264,6 +264,9 @@
}
}
+ if (!outer_cache_op)
+ return -EINVAL;
+
outer_cache_op(buff_phys_start + offset,
buff_phys_start + offset + length);
diff --git a/drivers/hwmon/qpnp-adc-common.c b/drivers/hwmon/qpnp-adc-common.c
index 8e350f0..4e77ca2 100644
--- a/drivers/hwmon/qpnp-adc-common.c
+++ b/drivers/hwmon/qpnp-adc-common.c
@@ -923,8 +923,12 @@
pr_err("Invalid channel fast average setup\n");
return -EINVAL;
}
- calibration_param = of_get_property(child,
- "qcom,calibration-type", NULL);
+ rc = of_property_read_string(child, "qcom,calibration-type",
+ &calibration_param);
+ if (rc) {
+ pr_err("Invalid calibration type\n");
+ return -EINVAL;
+ }
if (!strncmp(calibration_param, "absolute", 8))
calib_type = CALIB_ABSOLUTE;
else if (!strncmp(calibration_param, "ratiometric", 11))
diff --git a/drivers/hwmon/qpnp-adc-voltage.c b/drivers/hwmon/qpnp-adc-voltage.c
index 309944e..53e43d1 100644
--- a/drivers/hwmon/qpnp-adc-voltage.c
+++ b/drivers/hwmon/qpnp-adc-voltage.c
@@ -866,6 +866,11 @@
amux_prescaling =
vadc->adc->adc_channels[dt_index].chan_path_prescaling;
+ if (amux_prescaling >= PATH_SCALING_NONE) {
+ rc = -EINVAL;
+ goto fail_unlock;
+ }
+
vadc->adc->amux_prop->chan_prop->offset_gain_numerator =
qpnp_vadc_amux_scaling_ratio[amux_prescaling].num;
vadc->adc->amux_prop->chan_prop->offset_gain_denominator =
@@ -1016,6 +1021,11 @@
amux_prescaling =
vadc->adc->adc_channels[dt_index].chan_path_prescaling;
+ if (amux_prescaling >= PATH_SCALING_NONE) {
+ rc = -EINVAL;
+ goto fail;
+ }
+
vadc->adc->amux_prop->chan_prop->offset_gain_numerator =
qpnp_vadc_amux_scaling_ratio[amux_prescaling].num;
vadc->adc->amux_prop->chan_prop->offset_gain_denominator =
diff --git a/drivers/input/misc/bmp18x-core.c b/drivers/input/misc/bmp18x-core.c
index bac9059..4b5b710 100644
--- a/drivers/input/misc/bmp18x-core.c
+++ b/drivers/input/misc/bmp18x-core.c
@@ -441,7 +441,7 @@
mutex_unlock(&data->lock);
}
- return success;
+ return count;
}
static DEVICE_ATTR(enable, S_IWUSR | S_IRUGO,
show_enable, set_enable);
@@ -573,7 +573,7 @@
int err = 0;
if (pdata && pdata->init_hw) {
- err = pdata->init_hw();
+ err = pdata->init_hw(data_bus);
if (err) {
printk(KERN_ERR "%s: init_hw failed!\n",
BMP18X_NAME);
@@ -633,7 +633,7 @@
kfree(data);
exit:
if (pdata && pdata->deinit_hw)
- pdata->deinit_hw();
+ pdata->deinit_hw(data_bus);
return err;
}
EXPORT_SYMBOL(bmp18x_probe);
@@ -655,9 +655,9 @@
int bmp18x_disable(struct device *dev)
{
struct bmp18x_platform_data *pdata = dev->platform_data;
-
+ struct bmp18x_data *data = dev_get_drvdata(dev);
if (pdata && pdata->deinit_hw)
- pdata->deinit_hw();
+ pdata->deinit_hw(&data->data_bus);
return 0;
}
@@ -666,9 +666,9 @@
int bmp18x_enable(struct device *dev)
{
struct bmp18x_platform_data *pdata = dev->platform_data;
-
+ struct bmp18x_data *data = dev_get_drvdata(dev);
if (pdata && pdata->init_hw)
- return pdata->init_hw();
+ return pdata->init_hw(&data->data_bus);
return 0;
}
diff --git a/drivers/input/misc/bmp18x-i2c.c b/drivers/input/misc/bmp18x-i2c.c
index 6c01ad3..abbe6e5 100644
--- a/drivers/input/misc/bmp18x-i2c.c
+++ b/drivers/input/misc/bmp18x-i2c.c
@@ -22,8 +22,137 @@
#include <linux/module.h>
#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/regulator/consumer.h>
#include "bmp18x.h"
+struct sensor_regulator {
+ struct regulator *vreg;
+ const char *name;
+ u32 min_uV;
+ u32 max_uV;
+};
+
+struct sensor_regulator bmp_vreg[] = {
+ {NULL, "vdd", 2850000, 2850000},
+ {NULL, "vddio", 1800000, 1800000},
+};
+
+
+static int bmp18x_config_regulator(struct i2c_client *client, bool on)
+{
+ int rc = 0, i;
+ int num_vreg = ARRAY_SIZE(bmp_vreg);
+
+ if (on) {
+ for (i = 0; i < num_vreg; i++) {
+ bmp_vreg[i].vreg = regulator_get(&client->dev,
+ bmp_vreg[i].name);
+ if (IS_ERR(bmp_vreg[i].vreg)) {
+ rc = PTR_ERR(bmp_vreg[i].vreg);
+ dev_err(&client->dev, "%s:regulator get failed rc=%d\n",
+ __func__, rc);
+ bmp_vreg[i].vreg = NULL;
+ goto error_vdd;
+ }
+ if (regulator_count_voltages(bmp_vreg[i].vreg) > 0) {
+ rc = regulator_set_voltage(bmp_vreg[i].vreg,
+ bmp_vreg[i].min_uV, bmp_vreg[i].max_uV);
+ if (rc) {
+ dev_err(&client->dev, "%s:set_voltage failed rc=%d\n",
+ __func__, rc);
+ regulator_put(bmp_vreg[i].vreg);
+ bmp_vreg[i].vreg = NULL;
+ goto error_vdd;
+ }
+ }
+ rc = regulator_enable(bmp_vreg[i].vreg);
+ if (rc) {
+ dev_err(&client->dev, "%s: regulator_enable failed rc =%d\n",
+ __func__, rc);
+ if (regulator_count_voltages(bmp_vreg[i].vreg)
+ > 0) {
+ regulator_set_voltage(bmp_vreg[i].vreg,
+ 0, bmp_vreg[i].max_uV);
+ }
+ regulator_put(bmp_vreg[i].vreg);
+ bmp_vreg[i].vreg = NULL;
+ goto error_vdd;
+ }
+ }
+ return rc;
+ } else {
+ i = num_vreg;
+ }
+error_vdd:
+ while (--i >= 0) {
+ if (!IS_ERR_OR_NULL(bmp_vreg[i].vreg)) {
+ if (regulator_count_voltages(
+ bmp_vreg[i].vreg) > 0) {
+ regulator_set_voltage(bmp_vreg[i].vreg, 0,
+ bmp_vreg[i].max_uV);
+ }
+ regulator_disable(bmp_vreg[i].vreg);
+ regulator_put(bmp_vreg[i].vreg);
+ bmp_vreg[i].vreg = NULL;
+ }
+ }
+ return rc;
+}
+
+static int bmp18x_init_hw(struct bmp18x_data_bus *data_bus)
+{
+ if (data_bus->client)
+ return bmp18x_config_regulator(data_bus->client, 1);
+ return 0;
+}
+
+static void bmp18x_deinit_hw(struct bmp18x_data_bus *data_bus)
+{
+ if (data_bus->client)
+ bmp18x_config_regulator(data_bus->client, 0);
+}
+
+#ifdef CONFIG_OF
+static int bmp18x_parse_dt(struct device *dev,
+ struct bmp18x_platform_data *pdata)
+{
+ int ret = 0;
+ u32 val;
+
+ ret = of_property_read_u32(dev->of_node, "bosch,chip-id", &val);
+ if (ret) {
+ dev_err(dev, "no chip_id from dt\n");
+ return ret;
+ }
+ pdata->chip_id = (u8)val;
+
+ ret = of_property_read_u32(dev->of_node, "bosch,oversample", &val);
+ if (ret) {
+ dev_err(dev, "no default_oversampling from dt\n");
+ return ret;
+ }
+ pdata->default_oversampling = (u8)val;
+
+ ret = of_property_read_u32(dev->of_node, "bosch,period",
+ &pdata->temp_measurement_period);
+ if (ret) {
+ dev_err(dev, "no temp_measurement_period from dt\n");
+ return ret;
+ }
+
+ pdata->default_sw_oversampling = of_property_read_bool(dev->of_node,
+ "bosch,sw-oversample");
+ return 0;
+}
+#else
+static int bmp18x_parse_dt(struct device *dev,
+ struct bmp18x_platform_data *pdata)
+{
+ return -EINVAL;
+}
+#endif
+
static int bmp18x_i2c_read_block(void *client, u8 reg, int len, char *buf)
{
return i2c_smbus_read_i2c_block_data(client, reg, len, buf);
@@ -52,7 +181,25 @@
.bops = &bmp18x_i2c_bus_ops,
.client = client
};
+ struct bmp18x_platform_data *pdata;
+ int ret;
+ if (client->dev.of_node) {
+ pdata = devm_kzalloc(&client->dev,
+ sizeof(struct bmp18x_platform_data), GFP_KERNEL);
+ if (!pdata) {
+ dev_err(&client->dev, "Failed to allocate memory\n");
+ return -ENOMEM;
+ }
+ ret = bmp18x_parse_dt(&client->dev, pdata);
+ if (ret) {
+ dev_err(&client->dev, "Failed to parse device tree\n");
+ return ret;
+ }
+ pdata->init_hw = bmp18x_init_hw;
+ pdata->deinit_hw = bmp18x_deinit_hw;
+ client->dev.platform_data = pdata;
+ }
return bmp18x_probe(&client->dev, &data_bus);
}
@@ -89,6 +236,11 @@
};
MODULE_DEVICE_TABLE(i2c, bmp18x_id);
+static const struct of_device_id bmp18x_of_match[] = {
+ { .compatible = "bosch,bmp180", },
+ { },
+};
+
static struct i2c_driver bmp18x_i2c_driver = {
.driver = {
.owner = THIS_MODULE,
@@ -96,6 +248,7 @@
#ifdef CONFIG_PM
.pm = &bmp18x_i2c_pm_ops,
#endif
+ .of_match_table = bmp18x_of_match,
},
.id_table = bmp18x_id,
.probe = bmp18x_i2c_probe,
diff --git a/drivers/input/misc/bmp18x.h b/drivers/input/misc/bmp18x.h
index f9d55ec..d1b1ee7 100644
--- a/drivers/input/misc/bmp18x.h
+++ b/drivers/input/misc/bmp18x.h
@@ -34,14 +34,6 @@
* @init_hw: Callback for hw specific startup
* @deinit_hw: Callback for hw specific shutdown
*/
-struct bmp18x_platform_data {
- u8 chip_id;
- u8 default_oversampling;
- u8 default_sw_oversampling;
- u32 temp_measurement_period;
- int (*init_hw)(void);
- void (*deinit_hw)(void);
-};
struct bmp18x_bus_ops {
int (*read_block)(void *client, u8 reg, int len, char *buf);
@@ -50,10 +42,19 @@
};
struct bmp18x_data_bus {
- const struct bmp18x_bus_ops *bops;
+ const struct bmp18x_bus_ops *bops;
void *client;
};
+struct bmp18x_platform_data {
+ u8 chip_id;
+ u8 default_oversampling;
+ u8 default_sw_oversampling;
+ u32 temp_measurement_period;
+ int (*init_hw)(struct bmp18x_data_bus *);
+ void (*deinit_hw)(struct bmp18x_data_bus *);
+};
+
int bmp18x_probe(struct device *dev, struct bmp18x_data_bus *data_bus);
int bmp18x_remove(struct device *dev);
#ifdef CONFIG_PM
diff --git a/drivers/input/misc/mma8x5x.c b/drivers/input/misc/mma8x5x.c
index 8a0d4ab..f1ea705 100644
--- a/drivers/input/misc/mma8x5x.c
+++ b/drivers/input/misc/mma8x5x.c
@@ -2,6 +2,9 @@
* mma8x5x.c - Linux kernel modules for 3-Axis Orientation/Motion
* Detection Sensor MMA8451/MMA8452/MMA8453
*
+ * Copyright (c) 2013, The Linux Foundation. All Rights Reserved.
+ * Linux Foundation chooses to take subject only to the GPLv2 license
+ * terms, and distributes only under these terms.
* Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -18,23 +21,16 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-
+#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/init.h>
#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/pm.h>
-#include <linux/mutex.h>
#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/hwmon-sysfs.h>
-#include <linux/err.h>
-#include <linux/hwmon.h>
+#include <linux/i2c.h>
#include <linux/input-polldev.h>
#include <linux/regulator/consumer.h>
+#include <linux/of_gpio.h>
-#define MMA8X5X_I2C_ADDR 0x1D
+#define ACCEL_INPUT_DEV_NAME "accelerometer"
#define MMA8451_ID 0x1A
#define MMA8452_ID 0x2A
#define MMA8453_ID 0x3A
@@ -151,6 +147,8 @@
int position;
u8 chip_id;
int mode;
+ int int_pin;
+ u32 int_flags;
};
/* Addresses scanned */
static const unsigned short normal_i2c[] = {0x1c, 0x1d, I2C_CLIENT_END};
@@ -391,7 +389,8 @@
MMA8X5X_CTRL_REG1, val|0x01);
if (!ret) {
pdata->active = MMA_ACTIVED;
- printk(KERN_INFO "mma enable setting active\n");
+ dev_dbg(dev,
+ "%s:mma enable setting active.\n", __func__);
}
} else if (enable == 0 && pdata->active == MMA_ACTIVED) {
val = i2c_smbus_read_byte_data(client, MMA8X5X_CTRL_REG1);
@@ -399,7 +398,8 @@
MMA8X5X_CTRL_REG1, val & 0xFE);
if (!ret) {
pdata->active = MMA_STANDBY;
- printk(KERN_INFO "mma enable setting inactive\n");
+ dev_dbg(dev,
+ "%s:mma enable setting inactive.\n", __func__);
}
}
mutex_unlock(&pdata->data_lock);
@@ -458,11 +458,36 @@
chip_id = i2c_smbus_read_byte_data(client, MMA8X5X_WHO_AM_I);
if (!mma8x5x_check_id(chip_id))
return -ENODEV;
- printk(KERN_INFO "check %s i2c address 0x%x\n",
- mma8x5x_id2name(chip_id), client->addr);
+ dev_dbg(&client->dev, "%s,check %s i2c address 0x%x.\n",
+ __func__, mma8x5x_id2name(chip_id), client->addr);
strlcpy(info->type, "mma8x5x", I2C_NAME_SIZE);
return 0;
}
+
+static int mma8x5x_parse_dt(struct device *dev, struct mma8x5x_data *data)
+{
+ int rc;
+ struct device_node *np = dev->of_node;
+ u32 temp_val;
+
+ data->int_pin = of_get_named_gpio_flags(np, "fsl,irq-gpio",
+ 0, &data->int_flags);
+ if (data->int_pin < 0) {
+ dev_err(dev, "Unable to read irq-gpio\n");
+ return data->int_pin;
+ }
+
+ rc = of_property_read_u32(np, "fsl,sensors-position", &temp_val);
+ if (!rc)
+ data->position = temp_val;
+ else {
+ dev_err(dev, "Unable to read sensors-position\n");
+ return rc;
+ }
+
+ return 0;
+}
+
static int __devinit mma8x5x_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -500,11 +525,22 @@
dev_err(&client->dev, "alloc data memory error!\n");
goto err_out;
}
+
+ if (client->dev.of_node) {
+ result = mma8x5x_parse_dt(&client->dev, pdata);
+ if (result)
+ return result;
+ } else {
+ pdata->position = CONFIG_SENSORS_MMA_POSITION;
+ pdata->int_pin = -1;
+ pdata->int_flags = 0;
+ }
+
/* Initialize the MMA8X5X chip */
pdata->client = client;
pdata->chip_id = chip_id;
pdata->mode = MODE_2G;
- pdata->position = CONFIG_SENSORS_MMA_POSITION;
+
mutex_init(&pdata->data_lock);
i2c_set_clientdata(client, pdata);
/* Initialize the MMA8X5X chip */
@@ -522,7 +558,7 @@
poll_dev->poll_interval_max = POLL_INTERVAL_MAX;
poll_dev->private = pdata;
idev = poll_dev->input;
- idev->name = "accelerometer";
+ idev->name = ACCEL_INPUT_DEV_NAME;
idev->uniq = mma8x5x_id2name(pdata->chip_id);
idev->id.bustype = BUS_I2C;
idev->evbit[0] = BIT_MASK(EV_ABS);
@@ -541,7 +577,10 @@
result = -EINVAL;
goto err_create_sysfs;
}
- printk(KERN_INFO "mma8x5x device driver probe successfully\n");
+ dev_info(&client->dev,
+ "%s:mma8x5x device driver probe successfully, position =%d\n",
+ __func__, pdata->position);
+
return 0;
err_create_sysfs:
input_unregister_polled_device(pdata->poll_dev);
@@ -626,7 +665,7 @@
res = i2c_add_driver(&mma8x5x_driver);
if (res < 0) {
- printk(KERN_INFO "add mma8x5x i2c driver failed\n");
+ pr_info("%s:add mma8x5x i2c driver failed\n", __func__);
return -ENODEV;
}
return res;
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 479b788..5415f4e 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -393,6 +393,9 @@
bool update_cfg;
const char *fw_name;
bool no_force_update;
+ bool lpm_support;
+ bool regs_enabled;
+
#if defined(CONFIG_SECURE_TOUCH)
atomic_t st_enabled;
atomic_t st_pending_irqs;
@@ -2158,6 +2161,11 @@
if (on == false)
goto power_off;
+ if (data->regs_enabled) {
+ dev_dbg(&data->client->dev, "regs are already enabled\n");
+ return 0;
+ }
+
rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
if (rc < 0) {
dev_err(&data->client->dev,
@@ -2206,6 +2214,8 @@
}
}
+ data->regs_enabled = true;
+
msleep(130);
return 0;
@@ -2226,6 +2236,12 @@
return rc;
power_off:
+
+ if (!data->regs_enabled) {
+ dev_dbg(&data->client->dev, "regs are already disabled\n");
+ return 0;
+ }
+
reg_set_optimum_mode_check(data->vcc_ana, 0);
regulator_disable(data->vcc_ana);
if (data->pdata->digital_pwr_regulator) {
@@ -2236,6 +2252,9 @@
reg_set_optimum_mode_check(data->vcc_i2c, 0);
regulator_disable(data->vcc_i2c);
}
+
+ data->regs_enabled = false;
+
msleep(50);
return 0;
}
@@ -2435,8 +2454,9 @@
struct input_dev *input_dev = data->input_dev;
int error;
- mutex_lock(&input_dev->mutex);
+ disable_irq(data->irq);
+ mutex_lock(&input_dev->mutex);
if (input_dev->users) {
error = mxt_stop(data);
if (error < 0) {
@@ -2444,16 +2464,24 @@
mutex_unlock(&input_dev->mutex);
return error;
}
-
}
mutex_unlock(&input_dev->mutex);
+ mxt_release_all(data);
/* put regulators in low power mode */
- error = mxt_regulator_lpm(data, true);
- if (error < 0) {
- dev_err(dev, "failed to enter low power mode\n");
- return error;
+ if (data->lpm_support) {
+ error = mxt_regulator_lpm(data, true);
+ if (error < 0) {
+ dev_err(dev, "failed to enter low power mode\n");
+ return error;
+ }
+ } else {
+ error = mxt_power_on(data, false);
+ if (error < 0) {
+ dev_err(dev, "failed to disable regulators\n");
+ return error;
+ }
}
return 0;
@@ -2466,13 +2494,25 @@
struct input_dev *input_dev = data->input_dev;
int error;
- /* put regulators in high power mode */
- error = mxt_regulator_lpm(data, false);
- if (error < 0) {
- dev_err(dev, "failed to enter high power mode\n");
- return error;
+ /* put regulators back in active power mode */
+ if (data->lpm_support) {
+ error = mxt_regulator_lpm(data, false);
+ if (error < 0) {
+ dev_err(dev, "failed to enter high power mode\n");
+ return error;
+ }
+ } else {
+ error = mxt_power_on(data, true);
+ if (error < 0) {
+ dev_err(dev, "failed to enable regulators\n");
+ return error;
+ }
+ mxt_power_on_delay(data);
}
+ mxt_write_object(data, MXT_GEN_COMMAND_T6, MXT_COMMAND_RESET, 1);
+ mxt_reset_delay(data);
+
mutex_lock(&input_dev->mutex);
if (input_dev->users) {
@@ -2495,6 +2535,8 @@
mutex_unlock(&input_dev->mutex);
+ enable_irq(data->irq);
+
return 0;
}
@@ -2672,6 +2714,9 @@
pdata->no_force_update = of_property_read_bool(np,
"atmel,no-force-update");
+ pdata->no_lpm_support = of_property_read_bool(np,
+ "atmel,no-lpm-support");
+
/* reset, irq gpio info */
pdata->reset_gpio = of_get_named_gpio_flags(np, "atmel,reset-gpio",
0, &pdata->reset_gpio_flags);
@@ -2877,6 +2922,7 @@
data->input_dev = input_dev;
data->pdata = pdata;
data->no_force_update = pdata->no_force_update;
+ data->lpm_support = !pdata->no_lpm_support;
__set_bit(EV_ABS, input_dev->evbit);
__set_bit(EV_KEY, input_dev->evbit);
diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c
index fbcc243..e84b477 100644
--- a/drivers/leds/leds-qpnp.c
+++ b/drivers/leds/leds-qpnp.c
@@ -170,11 +170,13 @@
#define LED_MPP_SINK_CTRL(base) (base + 0x4C)
#define LED_MPP_CURRENT_DEFAULT 5
+#define LED_MPP_VIN_CTRL_DEFAULT 0
#define LED_MPP_CURRENT_PER_SETTING 5
#define LED_MPP_SOURCE_SEL_DEFAULT LED_MPP_MODE_ENABLE
#define LED_MPP_SINK_MASK 0x07
#define LED_MPP_MODE_MASK 0x7F
+#define LED_MPP_VIN_MASK 0x03
#define LED_MPP_EN_MASK 0x80
#define LED_MPP_SRC_MASK 0x0F
#define LED_MPP_MODE_CTRL_MASK 0x70
@@ -348,6 +350,8 @@
* @current_setting - current setting, 5ma-40ma in 5ma increments
* @source_sel - source selection
* @mode_ctrl - mode control
+ * @vin_ctrl - input control
+ * @min_brightness - minimum brightness supported
* @pwm_mode - pwm mode in use
*/
struct mpp_config_data {
@@ -355,6 +359,8 @@
u8 current_setting;
u8 source_sel;
u8 mode_ctrl;
+ u8 vin_ctrl;
+ u8 min_brightness;
u8 pwm_mode;
};
@@ -576,6 +582,13 @@
int duty_us;
if (led->cdev.brightness) {
+ if (led->cdev.brightness < led->mpp_cfg->min_brightness) {
+ dev_warn(&led->spmi_dev->dev,
+ "brightness is less than supported..." \
+ "set to minimum supported\n");
+ led->cdev.brightness = led->mpp_cfg->min_brightness;
+ }
+
if (led->mpp_cfg->pwm_mode != MANUAL_MODE) {
if (!led->mpp_cfg->pwm_cfg->blinking) {
led->mpp_cfg->pwm_cfg->mode =
@@ -2093,6 +2106,14 @@
if (val < 0)
val = 0;
+ rc = qpnp_led_masked_write(led, LED_MPP_VIN_CTRL(led->base),
+ LED_MPP_VIN_MASK, led->mpp_cfg->vin_ctrl);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Failed to write led vin control reg\n");
+ return rc;
+ }
+
rc = qpnp_led_masked_write(led, LED_MPP_SINK_CTRL(led->base),
LED_MPP_SINK_MASK, val);
if (rc) {
@@ -2677,6 +2698,20 @@
else if (rc != -EINVAL)
return rc;
+ led->mpp_cfg->vin_ctrl = LED_MPP_VIN_CTRL_DEFAULT;
+ rc = of_property_read_u32(node, "qcom,vin-ctrl", &val);
+ if (!rc)
+ led->mpp_cfg->vin_ctrl = (u8) val;
+ else if (rc != -EINVAL)
+ return rc;
+
+ led->mpp_cfg->min_brightness = 0;
+ rc = of_property_read_u32(node, "qcom,min-brightness", &val);
+ if (!rc)
+ led->mpp_cfg->min_brightness = (u8) val;
+ else if (rc != -EINVAL)
+ return rc;
+
rc = of_property_read_string(node, "qcom,mode", &mode);
if (!rc) {
led_mode = qpnp_led_get_mode(mode);
diff --git a/drivers/media/platform/msm/camera_v2/msm.c b/drivers/media/platform/msm/camera_v2/msm.c
index 8d53e35..07f3b40 100644
--- a/drivers/media/platform/msm/camera_v2/msm.c
+++ b/drivers/media/platform/msm/camera_v2/msm.c
@@ -519,6 +519,7 @@
struct msm_session *session;
unsigned int session_id;
unsigned int stream_id;
+ unsigned long spin_flags = 0;
event_data = (struct msm_v4l2_event_data *)
((struct v4l2_event *)arg)->u.data;
@@ -564,9 +565,13 @@
break;
}
+ spin_lock_irqsave(&(session->command_ack_q.lock),
+ spin_flags);
ret_cmd->event = *(struct v4l2_event *)arg;
msm_enqueue(&cmd_ack->command_q, &ret_cmd->list);
wake_up(&cmd_ack->wait);
+ spin_unlock_irqrestore(&(session->command_ack_q.lock),
+ spin_flags);
}
break;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/hi256.c b/drivers/media/platform/msm/camera_v2/sensor/hi256.c
index f1df703..de651df 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/hi256.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/hi256.c
@@ -1000,15 +1000,25 @@
{0x30, 0x06},
{0x31, 0x40},
{0x03, 0x20},
- {0x88, 0x05},
- {0x89, 0x7e},
- {0x8a, 0x40},
+ {0x88, 0x01},
+ {0x89, 0x5f},
+ {0x8a, 0x90},
{0x03, 0x20},
{0x10, 0x9c},
{0x03, 0x22},
{0x10, 0xe9},
};
+static struct msm_camera_i2c_reg_conf hi256_sleep_settings[] = {
+ {0x03, 0x00},
+ {0x01, 0xf1},
+ {0x03, 0x02},
+ {0x55, 0x10},
+ {0x01, 0xf1},
+ {0x01, 0xf3},
+ {0x01, 0xf1},
+};
+
static const struct i2c_device_id hi256_i2c_id[] = {
{HI256_SENSOR_NAME, (kernel_ulong_t)&hi256_s_ctrl},
@@ -1073,6 +1083,13 @@
}
+static int32_t hi256_sensor_power_down(struct msm_sensor_ctrl_t *s_ctrl)
+{
+ hi256_i2c_write_table(s_ctrl, &hi256_sleep_settings[0],
+ ARRAY_SIZE(hi256_sleep_settings));
+ return msm_sensor_power_down(s_ctrl);
+}
+
static int32_t hi256_platform_probe(struct platform_device *pdev)
{
int32_t rc;
@@ -1393,7 +1410,7 @@
static struct msm_sensor_fn_t hi256_sensor_func_tbl = {
.sensor_config = hi256_sensor_config,
.sensor_power_up = msm_sensor_power_up,
- .sensor_power_down = msm_sensor_power_down,
+ .sensor_power_down = hi256_sensor_power_down,
.sensor_match_id = hi256_sensor_match_id,
};
diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c
index 40d1155..3792247 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c
@@ -338,17 +338,11 @@
enum msm_camera_i2c_data_type data_type)
{
int32_t rc;
- int i;
S_I2C_DBG("%s: addr: 0x%x data: 0x%x dt: %d\n",
__func__, addr, data, data_type);
- for (i = 0; i < I2C_POLL_MAX_ITERATION; i++) {
- rc = msm_camera_cci_i2c_compare(client,
- addr, data, data_type);
- if (rc == 0 || rc < 0)
- break;
- usleep_range(10000, 11000);
- }
+ rc = msm_camera_cci_i2c_compare(client,
+ addr, data, data_type);
return rc;
}
diff --git a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
index 7f474bb..adbfbe7 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
@@ -569,7 +569,92 @@
CDBG("%s qcom,gpio-reset %d\n", __func__,
gconf->gpio_num_info->gpio_num[SENSOR_GPIO_STANDBY]);
}
- return rc;
+
+ rc = of_property_read_u32(of_node, "qcom,gpio-vio", &val);
+ if (!rc) {
+ if (val >= gpio_array_size) {
+ pr_err("%s:%d qcom,gpio-vio invalid %d\n",
+ __func__, __LINE__, val);
+ goto ERROR;
+ }
+ gconf->gpio_num_info->gpio_num[SENSOR_GPIO_VIO] =
+ gpio_array[val];
+ CDBG("%s qcom,gpio-vio %d\n", __func__,
+ gconf->gpio_num_info->gpio_num[SENSOR_GPIO_VIO]);
+ } else if (rc != -EINVAL) {
+ pr_err("%s:%d read qcom,gpio-vio failed rc %d\n",
+ __func__, __LINE__, rc);
+ goto ERROR;
+ }
+
+ rc = of_property_read_u32(of_node, "qcom,gpio-vana", &val);
+ if (!rc) {
+ if (val >= gpio_array_size) {
+ pr_err("%s:%d qcom,gpio-vana invalid %d\n",
+ __func__, __LINE__, val);
+ goto ERROR;
+ }
+ gconf->gpio_num_info->gpio_num[SENSOR_GPIO_VANA] =
+ gpio_array[val];
+ CDBG("%s qcom,gpio-vana %d\n", __func__,
+ gconf->gpio_num_info->gpio_num[SENSOR_GPIO_VANA]);
+ } else if (rc != -EINVAL) {
+ pr_err("%s:%d read qcom,gpio-vana failed rc %d\n",
+ __func__, __LINE__, rc);
+ goto ERROR;
+ }
+
+ rc = of_property_read_u32(of_node, "qcom,gpio-vdig", &val);
+ if (!rc) {
+ if (val >= gpio_array_size) {
+ pr_err("%s:%d qcom,gpio-vdig invalid %d\n",
+ __func__, __LINE__, val);
+ goto ERROR;
+ }
+ gconf->gpio_num_info->gpio_num[SENSOR_GPIO_VDIG] =
+ gpio_array[val];
+ CDBG("%s qcom,gpio-vdig %d\n", __func__,
+ gconf->gpio_num_info->gpio_num[SENSOR_GPIO_VDIG]);
+ } else if (rc != -EINVAL) {
+ pr_err("%s:%d read qcom,gpio-vdig failed rc %d\n",
+ __func__, __LINE__, rc);
+ goto ERROR;
+ }
+
+ rc = of_property_read_u32(of_node, "qcom,gpio-vaf", &val);
+ if (!rc) {
+ if (val >= gpio_array_size) {
+ pr_err("%s:%d qcom,gpio-vaf invalid %d\n",
+ __func__, __LINE__, val);
+ goto ERROR;
+ }
+ gconf->gpio_num_info->gpio_num[SENSOR_GPIO_VAF] =
+ gpio_array[val];
+ CDBG("%s qcom,gpio-vaf %d\n", __func__,
+ gconf->gpio_num_info->gpio_num[SENSOR_GPIO_VAF]);
+ } else if (rc != -EINVAL) {
+ pr_err("%s:%d read qcom,gpio-vaf failed rc %d\n",
+ __func__, __LINE__, rc);
+ goto ERROR;
+ }
+
+ rc = of_property_read_u32(of_node, "qcom,gpio-af-pwdm", &val);
+ if (!rc) {
+ if (val >= gpio_array_size) {
+ pr_err("%s:%d qcom,gpio-af-pwdm invalid %d\n",
+ __func__, __LINE__, val);
+ goto ERROR;
+ }
+ gconf->gpio_num_info->gpio_num[SENSOR_GPIO_AF_PWDM] =
+ gpio_array[val];
+ CDBG("%s qcom,gpio-af-pwdm %d\n", __func__,
+ gconf->gpio_num_info->gpio_num[SENSOR_GPIO_AF_PWDM]);
+ } else if (rc != -EINVAL) {
+ pr_err("%s:%d read qcom,gpio-af-pwdm failed rc %d\n",
+ __func__, __LINE__, rc);
+ goto ERROR;
+ }
+ return 0;
ERROR:
kfree(gconf->gpio_num_info);
@@ -1162,6 +1247,15 @@
return;
}
+static int msm_sensor_get_af_status(struct msm_sensor_ctrl_t *s_ctrl,
+ void __user *argp)
+{
+ /* TO-DO: Need to set AF status register address and expected value
+ We need to check the AF status in the sensor register and
+ set the status in the *status variable accordingly*/
+ return 0;
+}
+
static long msm_sensor_subdev_ioctl(struct v4l2_subdev *sd,
unsigned int cmd, void *arg)
{
@@ -1174,6 +1268,8 @@
switch (cmd) {
case VIDIOC_MSM_SENSOR_CFG:
return s_ctrl->func_tbl->sensor_config(s_ctrl, argp);
+ case VIDIOC_MSM_SENSOR_GET_AF_STATUS:
+ return msm_sensor_get_af_status(s_ctrl, argp);
case VIDIOC_MSM_SENSOR_RELEASE:
msm_sensor_stop_stream(s_ctrl);
return 0;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/mt9m114.c b/drivers/media/platform/msm/camera_v2/sensor/mt9m114.c
index c1cf862..de4fcd0 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/mt9m114.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/mt9m114.c
@@ -1424,8 +1424,51 @@
break;
}
break;
- }
- default:
+ }
+ case CFG_SET_SATURATION: {
+ int32_t sat_lev;
+ if (copy_from_user(&sat_lev, (void *)cdata->cfg.setting,
+ sizeof(int32_t))) {
+ pr_err("%s:%d failed\n", __func__, __LINE__);
+ rc = -EFAULT;
+ break;
+ }
+ pr_debug("%s: Saturation Value is %d", __func__, sat_lev);
+ break;
+ }
+ case CFG_SET_CONTRAST: {
+ int32_t con_lev;
+ if (copy_from_user(&con_lev, (void *)cdata->cfg.setting,
+ sizeof(int32_t))) {
+ pr_err("%s:%d failed\n", __func__, __LINE__);
+ rc = -EFAULT;
+ break;
+ }
+ pr_debug("%s: Contrast Value is %d", __func__, con_lev);
+ break;
+ }
+ case CFG_SET_SHARPNESS: {
+ int32_t shp_lev;
+ if (copy_from_user(&shp_lev, (void *)cdata->cfg.setting,
+ sizeof(int32_t))) {
+ pr_err("%s:%d failed\n", __func__, __LINE__);
+ rc = -EFAULT;
+ break;
+ }
+ pr_debug("%s: Sharpness Value is %d", __func__, shp_lev);
+ break;
+ }
+ case CFG_SET_AUTOFOCUS: {
+ /* TO-DO: set the Auto Focus */
+ pr_debug("%s: Setting Auto Focus", __func__);
+ break;
+ }
+ case CFG_CANCEL_AUTOFOCUS: {
+ /* TO-DO: Cancel the Auto Focus */
+ pr_debug("%s: Cancelling Auto Focus", __func__);
+ break;
+ }
+ default:
rc = -EFAULT;
break;
}
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 77f838c..3d2b3d8 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -69,6 +69,20 @@
return false;
}
+static bool is_thumbnail_session(struct msm_vidc_inst *inst)
+{
+ if (inst->session_type == MSM_VIDC_DECODER) {
+ int rc = 0;
+ struct v4l2_control ctrl = {
+ .id = V4L2_CID_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE
+ };
+ rc = v4l2_g_ctrl(&inst->ctrl_handler, &ctrl);
+ if (!rc && ctrl.value)
+ return true;
+ }
+ return false;
+}
+
static int msm_comm_get_load(struct msm_vidc_core *core,
enum session_type type)
{
@@ -83,7 +97,9 @@
if (inst->session_type == type &&
inst->state >= MSM_VIDC_OPEN_DONE &&
inst->state < MSM_VIDC_STOP_DONE) {
- num_mbs_per_sec += NUM_MBS_PER_SEC(inst->prop.height,
+ if (!is_thumbnail_session(inst))
+ num_mbs_per_sec += NUM_MBS_PER_SEC(
+ inst->prop.height,
inst->prop.width, inst->prop.fps);
}
mutex_unlock(&inst->lock);
diff --git a/drivers/platform/msm/ipa/ipa_client.c b/drivers/platform/msm/ipa/ipa_client.c
index f20f37f..3aaec07 100644
--- a/drivers/platform/msm/ipa/ipa_client.c
+++ b/drivers/platform/msm/ipa/ipa_client.c
@@ -45,7 +45,7 @@
if (ipa_ctx->ipa_hw_type == IPA_HW_v1_1) {
ipa_write_reg(ipa_ctx->mmio,
IPA_ENDP_INIT_CTRL_n_OFST(clnt_hdl), 1);
- usleep(IPA_PKT_FLUSH_TO_US);
+ udelay(IPA_PKT_FLUSH_TO_US);
if (IPA_CLIENT_IS_CONS(ep->client) &&
ep->cfg.aggr.aggr_en == IPA_ENABLE_AGGR &&
ep->cfg.aggr.aggr_time_limit)
diff --git a/drivers/platform/msm/ipa/ipa_utils.c b/drivers/platform/msm/ipa/ipa_utils.c
index e38b796..4a5fa4d 100644
--- a/drivers/platform/msm/ipa/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_utils.c
@@ -1396,12 +1396,8 @@
if (__ratelimit(&_rs)) {
ipa_inc_client_enable_clks();
pr_err("IPA BAM START\n");
- sps_get_bam_debug_info(ipa_ctx->bam_handle, 5, 1048575, 0, 0);
+ sps_get_bam_debug_info(ipa_ctx->bam_handle, 5, 479182, 0, 0);
sps_get_bam_debug_info(ipa_ctx->bam_handle, 93, 0, 0, 0);
- pr_err("BAM-DMA BAM START\n");
- sps_get_bam_debug_info(sps_dma_get_bam_handle(), 5, 1044480,
- 0, 0);
- sps_get_bam_debug_info(sps_dma_get_bam_handle(), 93, 0, 0, 0);
ipa_dec_client_disable_clks();
}
}
diff --git a/drivers/power/qpnp-bms.c b/drivers/power/qpnp-bms.c
index 14d5b6a..08995cc 100644
--- a/drivers/power/qpnp-bms.c
+++ b/drivers/power/qpnp-bms.c
@@ -64,11 +64,10 @@
/* Extra bms registers */
#define SOC_STORAGE_REG 0xB0
#define IAVG_STORAGE_REG 0xB1
-#define BMS_BATT_REMOVED_REG 0xB2
-#define BMS1_BMS_DATA_REG_3 0xB3
-#define CHARGE_INCREASE_STORAGE 0xB4
-#define FCC_BATT_TEMP_STORAGE 0xB5
-#define FCC_STORAGE_LSB 0xBC /* LSB=0xBC, MSB=0xBD */
+#define BMS_FCC_COUNT 0xB2
+#define BMS_FCC_BASE_REG 0xB3 /* FCC updates - 0xB3 to 0xB7 */
+#define BMS_CHGCYL_BASE_REG 0xB8 /* FCC chgcyl - 0xB8 to 0xBC */
+#define CHARGE_INCREASE_STORAGE 0xBD
#define CHARGE_CYCLE_STORAGE_LSB 0xBE /* LSB=0xBE, MSB=0xBF */
/* IADC Channel Select */
@@ -84,8 +83,11 @@
#define IAVG_SAMPLES 16
/* FCC learning constants */
+#define MAX_FCC_CYCLES 5
#define DELTA_FCC_PERCENT 5
#define VALID_FCC_CHGCYL_RANGE 50
+#define CHGCYL_RESOLUTION 20
+#define FCC_DEFAULT_TEMP 250
#define QPNP_BMS_DEV_NAME "qcom,qpnp-bms"
@@ -116,9 +118,8 @@
int last_good_ocv_uv;
};
-struct fcc_data {
+struct fcc_sample {
int fcc_new;
- int batt_temp;
int chargecycles;
};
@@ -244,7 +245,8 @@
int ocv_low_threshold_uv;
unsigned long last_recalc_time;
- struct fcc_data *fcc_table;
+ struct fcc_sample *fcc_learning_samples;
+ u8 fcc_sample_count;
int enable_fcc_learning;
int min_fcc_learning_soc;
int min_fcc_ocv_pc;
@@ -259,8 +261,8 @@
int fcc_new_batt_temp;
uint16_t charge_cycles;
u8 charge_increase;
- int fcc_new_sysfs;
- int fcc_update_complete;
+ int fcc_resolution;
+ bool battery_removed;
struct bms_irq sw_cc_thr_irq;
struct bms_irq ocv_thr_irq;
};
@@ -285,45 +287,10 @@
POWER_SUPPLY_PROP_CYCLE_COUNT,
};
+static int discard_backup_fcc_data(struct qpnp_bms_chip *chip);
+static void backup_charge_cycle(struct qpnp_bms_chip *chip);
+
static bool bms_reset;
-static int min_fcc_cycles = -EINVAL;
-static int last_fcc_update_count;
-static int battery_removed;
-
-static int
-bms_ro_ops_set(const char *val, const struct kernel_param *kp)
-{
- return -EINVAL;
-}
-
-static int
-bms_last_fcc_count_set(const char *val, const struct kernel_param *kp)
-{
- int rc;
-
- if (battery_removed) {
- last_fcc_update_count = 0;
- return 0;
- }
- rc = param_set_int(val, kp);
- if (rc)
- pr_err("Failed to set last_fcc_update_count rc=%d\n", rc);
-
- return rc;
-}
-
-static struct kernel_param_ops bms_ro_param_ops = {
- .set = bms_ro_ops_set,
- .get = param_get_int,
-};
-static struct kernel_param_ops bms_last_fcc_count_param_ops = {
- .set = bms_last_fcc_count_set,
- .get = param_get_int,
-};
-module_param_cb(min_fcc_cycles, &bms_ro_param_ops, &min_fcc_cycles, 0644);
-module_param_cb(battery_removed, &bms_ro_param_ops, &battery_removed, 0644);
-module_param_cb(last_fcc_update_count, &bms_last_fcc_count_param_ops,
- &last_fcc_update_count, 0644);
static int qpnp_read_wrapper(struct qpnp_bms_chip *chip, u8 *val,
u16 base, int count)
@@ -871,6 +838,19 @@
chip->last_cc_uah = INT_MIN;
chip->last_ocv_temp = batt_temp;
chip->prev_batt_terminal_uv = 0;
+ if (chip->enable_fcc_learning) {
+ chip->adjusted_fcc_temp_lut = NULL;
+ chip->fcc_new_mah = -EINVAL;
+ /* reset the charge-cycle and charge-increase registers */
+ chip->charge_increase = 0;
+ chip->charge_cycles = 0;
+ backup_charge_cycle(chip);
+ /* discard all the FCC learnt data and reset the local table */
+ discard_backup_fcc_data(chip);
+ memset(chip->fcc_learning_samples, 0,
+ chip->min_fcc_learning_samples *
+ sizeof(struct fcc_sample));
+ }
}
#define OCV_RAW_UNINITIALIZED 0xFFFF
@@ -2624,26 +2604,85 @@
kfree(old);
}
-
-static void backup_fcc_new(struct qpnp_bms_chip *chip)
+static int read_fcc_data_from_backup(struct qpnp_bms_chip *chip)
{
- int rc = 0;
- u8 temp = 0;
+ int rc, i;
+ u8 fcc = 0, chgcyl = 0;
- if (chip->fcc_new_mah > 0) {
- rc = qpnp_write_wrapper(chip, (u8 *)&chip->fcc_new_mah,
- chip->base + FCC_STORAGE_LSB, 2);
- if (rc)
- pr_err("Unable to backup new_fcc\n");
-
- temp = chip->fcc_new_batt_temp / 10;
- rc = qpnp_write_wrapper(chip, &temp,
- chip->base + FCC_BATT_TEMP_STORAGE, 1);
- if (rc)
- pr_err("Unable to backup fcc temp.\n");
+ for (i = 0; i < chip->min_fcc_learning_samples; i++) {
+ rc = qpnp_read_wrapper(chip, &fcc,
+ chip->base + BMS_FCC_BASE_REG + i, 1);
+ rc |= qpnp_read_wrapper(chip, &chgcyl,
+ chip->base + BMS_CHGCYL_BASE_REG + i, 1);
+ if (rc) {
+ pr_err("Unable to read FCC data\n");
+ return rc;
+ }
+ if (fcc == 0 || (fcc == 0xFF && chgcyl == 0xFF)) {
+ /* FCC invalid/not present */
+ chip->fcc_learning_samples[i].fcc_new = 0;
+ chip->fcc_learning_samples[i].chargecycles = 0;
+ } else {
+ /* valid FCC data */
+ chip->fcc_sample_count++;
+ chip->fcc_learning_samples[i].fcc_new =
+ fcc * chip->fcc_resolution;
+ chip->fcc_learning_samples[i].chargecycles =
+ chgcyl * CHGCYL_RESOLUTION;
+ }
}
+
+ return 0;
}
+static int discard_backup_fcc_data(struct qpnp_bms_chip *chip)
+{
+ int rc = 0, i;
+ u8 temp_u8 = 0;
+
+ chip->fcc_sample_count = 0;
+ for (i = 0; i < chip->min_fcc_learning_samples; i++) {
+ rc = qpnp_write_wrapper(chip, &temp_u8,
+ chip->base + BMS_FCC_BASE_REG + i, 1);
+ rc |= qpnp_write_wrapper(chip, &temp_u8,
+ chip->base + BMS_CHGCYL_BASE_REG + i, 1);
+ if (rc) {
+ pr_err("Unable to clear FCC data\n");
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
+static void
+average_fcc_samples_and_readjust_fcc_table(struct qpnp_bms_chip *chip)
+{
+ int i, temp_fcc_avg = 0, temp_fcc_delta = 0, new_fcc_avg = 0;
+ struct fcc_sample *ft;
+
+ for (i = 0; i < chip->min_fcc_learning_samples; i++)
+ temp_fcc_avg += chip->fcc_learning_samples[i].fcc_new;
+
+ temp_fcc_avg /= chip->min_fcc_learning_samples;
+ temp_fcc_delta = div_u64(temp_fcc_avg * DELTA_FCC_PERCENT, 100);
+
+ /* fix the fcc if its an outlier i.e. > 5% of the average */
+ for (i = 0; i < chip->min_fcc_learning_samples; i++) {
+ ft = &chip->fcc_learning_samples[i];
+ if (abs(ft->fcc_new - temp_fcc_avg) > temp_fcc_delta)
+ new_fcc_avg += temp_fcc_avg;
+ else
+ new_fcc_avg += ft->fcc_new;
+ }
+ new_fcc_avg /= chip->min_fcc_learning_samples;
+
+ chip->fcc_new_mah = new_fcc_avg;
+ chip->fcc_new_batt_temp = FCC_DEFAULT_TEMP;
+ pr_info("FCC update: New fcc_mah=%d, fcc_batt_temp=%d\n",
+ new_fcc_avg, FCC_DEFAULT_TEMP);
+ readjust_fcc_table(chip);
+}
static void backup_charge_cycle(struct qpnp_bms_chip *chip)
{
@@ -2651,7 +2690,7 @@
if (chip->charge_increase >= 0) {
rc = qpnp_write_wrapper(chip, &chip->charge_increase,
- chip->base + CHARGE_INCREASE_STORAGE, 1);
+ chip->base + CHARGE_INCREASE_STORAGE, 1);
if (rc)
pr_err("Unable to backup charge_increase\n");
}
@@ -2664,9 +2703,31 @@
}
}
-static void restore_fcc_data(struct qpnp_bms_chip *chip)
+static bool chargecycles_in_range(struct qpnp_bms_chip *chip)
{
- int rc = 0;
+ int i, min_cycle, max_cycle, valid_range;
+
+ /* find the smallest and largest charge cycle */
+ max_cycle = min_cycle = chip->fcc_learning_samples[0].chargecycles;
+ for (i = 1; i < chip->min_fcc_learning_samples; i++) {
+ if (min_cycle > chip->fcc_learning_samples[i].chargecycles)
+ min_cycle = chip->fcc_learning_samples[i].chargecycles;
+ if (max_cycle < chip->fcc_learning_samples[i].chargecycles)
+ max_cycle = chip->fcc_learning_samples[i].chargecycles;
+ }
+
+ /* check if chargecyles are in range to continue with FCC update */
+ valid_range = DIV_ROUND_UP(VALID_FCC_CHGCYL_RANGE,
+ CHGCYL_RESOLUTION) * CHGCYL_RESOLUTION;
+ if (abs(max_cycle - min_cycle) > valid_range)
+ return false;
+
+ return true;
+}
+
+static int read_chgcycle_data_from_backup(struct qpnp_bms_chip *chip)
+{
+ int rc;
uint16_t temp_u16 = 0;
u8 temp_u8 = 0;
@@ -2680,25 +2741,18 @@
if (!rc && temp_u16 != 0xFFFF)
chip->charge_cycles = temp_u16;
- rc = qpnp_read_wrapper(chip, (u8 *)&temp_u16,
- chip->base + FCC_STORAGE_LSB, 2);
- if (!rc && temp_u16 != 0xFFFF) {
- chip->fcc_new_mah = temp_u16;
- } else {
- pr_debug("Backed-up FCC not initialized, FCC not updated\n");
- return;
- }
+ return rc;
+}
- rc = qpnp_read_wrapper(chip, &temp_u8,
- chip->base + FCC_BATT_TEMP_STORAGE, 1);
- if (!rc && temp_u8 != 0xFF) {
- chip->fcc_new_batt_temp = (s8)temp_u8 * 10;
- } else {
- pr_debug("Backed-up temp. not initialized, FCC not updated\n");
- return;
- }
- /* readjust the FCC table if fcc and temp are valid */
- readjust_fcc_table(chip);
+static void
+attempt_learning_new_fcc(struct qpnp_bms_chip *chip)
+{
+ pr_debug("Total FCC sample count=%d\n", chip->fcc_sample_count);
+
+ /* update FCC if we have the required samples */
+ if ((chip->fcc_sample_count == chip->min_fcc_learning_samples) &&
+ chargecycles_in_range(chip))
+ average_fcc_samples_and_readjust_fcc_table(chip);
}
static int calculate_real_soc(struct qpnp_bms_chip *chip,
@@ -2712,82 +2766,80 @@
return ((rc_uah - cc_uah) * 100) / fcc_uah;
}
-static void update_fcc_table_for_temp(struct qpnp_bms_chip *chip,
- int batt_temp_final)
-{
- int i, fcc_t1, fcc_t2, fcc_final;
- struct fcc_data *ft;
+#define MAX_U8_VALUE ((u8)(~0U))
- /* Interpolate all the FCC entries to the same temperature */
- for (i = 0; i < chip->min_fcc_learning_samples; i++) {
- ft = &chip->fcc_table[i];
- if (ft->batt_temp == batt_temp_final)
- continue;
- fcc_t1 = interpolate_fcc(chip->fcc_temp_lut, ft->batt_temp);
- fcc_t2 = interpolate_fcc(chip->fcc_temp_lut, batt_temp_final);
- fcc_final = (ft->fcc_new / fcc_t1) * fcc_t2;
- ft->fcc_new = fcc_final;
- ft->batt_temp = batt_temp_final;
+static int backup_new_fcc(struct qpnp_bms_chip *chip, int fcc_mah,
+ int chargecycles)
+{
+ int rc, min_cycle, i;
+ u8 fcc_new, chgcyl, pos = 0;
+ struct fcc_sample *ft;
+
+ if ((fcc_mah > (chip->fcc_resolution * MAX_U8_VALUE)) ||
+ (chargecycles > (CHGCYL_RESOLUTION * MAX_U8_VALUE))) {
+ pr_warn("FCC/Chgcyl beyond storage limit. FCC=%d, chgcyl=%d\n",
+ fcc_mah, chargecycles);
+ return -EINVAL;
}
+
+ if (chip->fcc_sample_count == chip->min_fcc_learning_samples) {
+ /* search best location - oldest entry */
+ min_cycle = chip->fcc_learning_samples[0].chargecycles;
+ for (i = 1; i < chip->min_fcc_learning_samples; i++) {
+ if (min_cycle >
+ chip->fcc_learning_samples[i].chargecycles)
+ pos = i;
+ }
+ } else {
+ /* find an empty location */
+ for (i = 0; i < chip->min_fcc_learning_samples; i++) {
+ ft = &chip->fcc_learning_samples[i];
+ if (ft->fcc_new == 0 || (ft->fcc_new == 0xFF &&
+ ft->chargecycles == 0xFF)) {
+ pos = i;
+ break;
+ }
+ }
+ chip->fcc_sample_count++;
+ }
+ chip->fcc_learning_samples[pos].fcc_new = fcc_mah;
+ chip->fcc_learning_samples[pos].chargecycles = chargecycles;
+
+ fcc_new = DIV_ROUND_UP(fcc_mah, chip->fcc_resolution);
+ rc = qpnp_write_wrapper(chip, (u8 *)&fcc_new,
+ chip->base + BMS_FCC_BASE_REG + pos, 1);
+ if (rc)
+ return rc;
+
+ chgcyl = DIV_ROUND_UP(chargecycles, CHGCYL_RESOLUTION);
+ rc = qpnp_write_wrapper(chip, (u8 *)&chgcyl,
+ chip->base + BMS_CHGCYL_BASE_REG + pos, 1);
+ if (rc)
+ return rc;
+
+ pr_debug("Backup new FCC: fcc_new=%d, chargecycle=%d, pos=%d\n",
+ fcc_new, chgcyl, pos);
+
+ return rc;
}
static void update_fcc_learning_table(struct qpnp_bms_chip *chip,
- int fcc_uah, int new_fcc_uah, int chargecycles, int batt_temp)
+ int new_fcc_uah, int chargecycles, int batt_temp)
{
- int i, count, new_fcc_avg = 0, temp_fcc_avg = 0, temp_fcc_delta = 0;
- struct fcc_data *ft;
+ int rc, fcc_default, fcc_temp;
- count = last_fcc_update_count % chip->min_fcc_learning_samples;
- ft = &chip->fcc_table[count];
- ft->fcc_new = chip->fcc_new_sysfs = new_fcc_uah;
- ft->batt_temp = batt_temp;
- ft->chargecycles = chargecycles;
- last_fcc_update_count++;
- /* update userspace */
- sysfs_notify(&chip->dev->kobj, NULL, "fcc_data");
+ /* convert the fcc at batt_temp to new fcc at FCC_DEFAULT_TEMP */
+ fcc_default = calculate_fcc(chip, FCC_DEFAULT_TEMP) / 1000;
+ fcc_temp = calculate_fcc(chip, batt_temp) / 1000;
+ new_fcc_uah = (new_fcc_uah / fcc_temp) * fcc_default;
- pr_debug("Updated fcc table. new_fcc=%d, chargecycle=%d, temp=%d fcc_update_count=%d\n",
- new_fcc_uah, chargecycles, batt_temp, last_fcc_update_count);
-
- if (last_fcc_update_count < chip->min_fcc_learning_samples) {
- pr_debug("Not enough FCC samples. Current count = %d\n",
- last_fcc_update_count);
- return; /* Not enough samples to update fcc */
+ rc = backup_new_fcc(chip, new_fcc_uah / 1000, chargecycles);
+ if (rc) {
+ pr_err("Unable to backup new FCC\n");
+ return;
}
-
- /* reject entries if they are > 50 chargecycles apart */
- for (i = 0; i < chip->min_fcc_learning_samples; i++) {
- if ((chip->fcc_table[i].chargecycles + VALID_FCC_CHGCYL_RANGE)
- < chargecycles) {
- pr_debug("Charge cycle too old (> %d cycles apart)\n",
- VALID_FCC_CHGCYL_RANGE);
- return; /* Samples old, > 50 cycles apart*/
- }
- }
- /* update the fcc table for temperature difference*/
- update_fcc_table_for_temp(chip, batt_temp);
-
- for (i = 0; i < chip->min_fcc_learning_samples; i++)
- temp_fcc_avg += chip->fcc_table[i].fcc_new;
-
- temp_fcc_avg /= chip->min_fcc_learning_samples;
- temp_fcc_delta = div_u64(temp_fcc_avg * DELTA_FCC_PERCENT, 100);
-
- /* fix the fcc if its an outlier i.e. > 5% of the average */
- for (i = 0; i < chip->min_fcc_learning_samples; i++) {
- ft = &chip->fcc_table[i];
- if (abs(ft->fcc_new - temp_fcc_avg) > temp_fcc_delta)
- ft->fcc_new = temp_fcc_avg;
- new_fcc_avg += ft->fcc_new;
- }
- new_fcc_avg /= chip->min_fcc_learning_samples;
-
- chip->fcc_new_mah = new_fcc_avg / 1000;
- chip->fcc_new_batt_temp = batt_temp;
- pr_info("FCC update: New fcc_mah=%d, fcc_batt_temp=%d\n",
- new_fcc_avg, batt_temp);
- readjust_fcc_table(chip);
- backup_fcc_new(chip);
+ /* check if FCC can be updated */
+ attempt_learning_new_fcc(chip);
}
static bool is_new_fcc_valid(int new_fcc_uah, int fcc_uah)
@@ -2841,8 +2893,8 @@
chip->start_cc_uah, chip->end_cc_uah, new_fcc_uah);
if (is_new_fcc_valid(new_fcc_uah, fcc_uah))
- update_fcc_learning_table(chip, fcc_uah,
- new_fcc_uah, chip->charge_cycles, batt_temp);
+ update_fcc_learning_table(chip, new_fcc_uah,
+ chip->charge_cycles, batt_temp);
}
}
@@ -3013,123 +3065,6 @@
return 0;
}
-static ssize_t fcc_data_set(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct qpnp_bms_chip *chip = dev_get_drvdata(dev);
- static int i;
- int fcc_new = 0, rc;
-
- if (chip->fcc_update_complete) {
- pr_debug("Invalid FCC update\n");
- return count;
- }
-
- i %= chip->min_fcc_learning_samples;
- rc = sscanf(buf, "%d", &fcc_new);
- if (rc != 1)
- return -EINVAL;
- chip->fcc_table[i].fcc_new = fcc_new;
- pr_debug("Rcvd: [%d] fcc_new=%d\n", i, fcc_new);
- i++;
-
- return count;
-}
-
-static ssize_t fcc_data_get(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- int count = 0;
- struct qpnp_bms_chip *chip = dev_get_drvdata(dev);
-
- count = snprintf(buf, PAGE_SIZE, "%d", chip->fcc_new_sysfs);
- pr_debug("Sent: fcc_new=%d\n", chip->fcc_new_sysfs);
- chip->fcc_update_complete = 1;
-
- return count;
-}
-
-static ssize_t fcc_temp_set(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- static int i;
- int batt_temp = 0, rc;
- struct qpnp_bms_chip *chip = dev_get_drvdata(dev);
-
- if (chip->fcc_update_complete)
- return count;
-
- i %= chip->min_fcc_learning_samples;
- rc = sscanf(buf, "%d", &batt_temp);
- if (rc != 1)
- return -EINVAL;
- chip->fcc_table[i].batt_temp = batt_temp;
- pr_debug("Rcvd: [%d] batt_temp=%d\n", i, batt_temp);
- i++;
-
- return count;
-}
-
-static ssize_t fcc_chgcyl_set(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- static int i;
- int chargecycle = 0, rc;
- struct qpnp_bms_chip *chip = dev_get_drvdata(dev);
-
- if (chip->fcc_update_complete)
- return count;
-
- i %= chip->min_fcc_learning_samples;
- rc = sscanf(buf, "%d", &chargecycle);
- if (rc != 1)
- return -EINVAL;
- chip->fcc_table[i].chargecycles = chargecycle;
- pr_debug("Rcvd: [%d] chargecycle=%d\n", i, chargecycle);
- i++;
-
- return count;
-}
-
-static ssize_t fcc_list_get(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct qpnp_bms_chip *chip = dev_get_drvdata(dev);
- struct fcc_data *ft;
- int i = 0, j, count = 0;
-
- if (last_fcc_update_count < chip->min_fcc_learning_samples)
- i = last_fcc_update_count;
- else
- i = chip->min_fcc_learning_samples;
-
- for (j = 0; j < i; j++) {
- ft = &chip->fcc_table[j];
- count += snprintf(buf + count, PAGE_SIZE - count,
- "%d %d %d\n", ft->fcc_new, ft->chargecycles,
- ft->batt_temp);
- }
-
- return count;
-}
-
-static DEVICE_ATTR(fcc_data, 0664, fcc_data_get, fcc_data_set);
-static DEVICE_ATTR(fcc_temp, 0664, NULL, fcc_temp_set);
-static DEVICE_ATTR(fcc_chgcyl, 0664, NULL, fcc_chgcyl_set);
-static DEVICE_ATTR(fcc_list, 0664, fcc_list_get, NULL);
-
-static struct attribute *fcc_attrs[] = {
- &dev_attr_fcc_data.attr,
- &dev_attr_fcc_temp.attr,
- &dev_attr_fcc_chgcyl.attr,
- &dev_attr_fcc_list.attr,
- NULL
-};
-
-static const struct attribute_group fcc_attr_group = {
- .attrs = fcc_attrs,
-};
-
#define OCV_USE_LIMIT_EN BIT(7)
static int set_ocv_voltage_thresholds(struct qpnp_bms_chip *chip,
int low_voltage_threshold,
@@ -3213,10 +3148,19 @@
}
}
- pr_debug("shutdown_soc = %d shutdown_iavg = %d shutdown_soc_invalid = %d\n",
+ /* read the SOC storage to determine if there was a battery removal */
+ rc = qpnp_read_wrapper(chip, &temp, chip->base + SOC_STORAGE_REG, 1);
+ if (!rc) {
+ if (temp == SOC_INVALID)
+ chip->battery_removed = true;
+ }
+
+
+ pr_debug("shutdown_soc = %d shutdown_iavg = %d shutdown_soc_invalid = %d, battery_removed = %d\n",
chip->shutdown_soc,
chip->shutdown_iavg_ma,
- chip->shutdown_soc_invalid);
+ chip->shutdown_soc_invalid,
+ chip->battery_removed);
}
static irqreturn_t bms_ocv_thr_irq_handler(int irq, void *_chip)
@@ -3325,6 +3269,12 @@
} \
} while (0)
+#define SPMI_PROP_READ_BOOL(chip_prop, qpnp_spmi_property) \
+do { \
+ chip->chip_prop = of_property_read_bool(chip->spmi->dev.of_node,\
+ "qcom," qpnp_spmi_property); \
+} while (0)
+
static inline int bms_read_properties(struct qpnp_bms_chip *chip)
{
int rc;
@@ -3371,8 +3321,7 @@
if (chip->adjust_soc_low_threshold >= 45)
chip->adjust_soc_low_threshold = 45;
- chip->enable_fcc_learning = of_property_read_bool(
- chip->spmi->dev.of_node, "qcom,enable-fcc-learning");
+ SPMI_PROP_READ_BOOL(enable_fcc_learning, "enable-fcc-learning");
if (chip->enable_fcc_learning) {
SPMI_PROP_READ(min_fcc_learning_soc,
"min-fcc-learning-soc", rc);
@@ -3380,12 +3329,16 @@
"min-fcc-ocv-pc", rc);
SPMI_PROP_READ(min_fcc_learning_samples,
"min-fcc-learning-samples", rc);
- chip->fcc_table = kzalloc((sizeof(struct fcc_data) *
- chip->min_fcc_learning_samples), GFP_KERNEL);
+ SPMI_PROP_READ(fcc_resolution,
+ "fcc-resolution", rc);
+ if (chip->min_fcc_learning_samples > MAX_FCC_CYCLES)
+ chip->min_fcc_learning_samples = MAX_FCC_CYCLES;
+ chip->fcc_learning_samples = devm_kzalloc(&chip->spmi->dev,
+ (sizeof(struct fcc_sample) *
+ chip->min_fcc_learning_samples), GFP_KERNEL);
pr_debug("min-fcc-soc=%d, min-fcc-pc=%d, min-fcc-cycles=%d\n",
chip->min_fcc_learning_soc, chip->min_fcc_ocv_pc,
chip->min_fcc_learning_samples);
- min_fcc_cycles = chip->min_fcc_learning_samples;
}
pr_debug("dts data: r_sense_uohm:%d, v_cutoff_uv:%d, max_v:%d\n",
@@ -3662,28 +3615,6 @@
return 0;
}
-static void check_battery_removal(struct qpnp_bms_chip *chip)
-{
- int rc;
- u8 temp = 0;
-
- /* check if battery was removed at PON */
- rc = qpnp_read_wrapper(chip, &temp,
- chip->base + BMS_BATT_REMOVED_REG, 1);
- if (temp == 0xFF) {
- pr_debug("New battery inserted at PON\n");
- temp = battery_removed = 1;
- rc = qpnp_write_wrapper(chip, &temp,
- chip->base + BMS_BATT_REMOVED_REG, 1);
- if (rc)
- pr_err("Unable to set BMS_BATT_REMOVED_REG\n");
- } else {
- if (rc)
- pr_err("Unable to read BMS_BATT_REMOVED_REG\n");
- battery_removed = 0;
- }
-}
-
static int __devinit qpnp_bms_probe(struct spmi_device *spmi)
{
struct qpnp_bms_chip *chip;
@@ -3711,6 +3642,12 @@
goto error_read;
}
+ mutex_init(&chip->bms_output_lock);
+ mutex_init(&chip->last_ocv_uv_mutex);
+ mutex_init(&chip->vbat_monitor_mutex);
+ mutex_init(&chip->soc_invalidation_mutex);
+ mutex_init(&chip->last_soc_mutex);
+
warm_reset = qpnp_pon_is_warm_reset();
rc = warm_reset;
if (rc < 0)
@@ -3768,12 +3705,6 @@
bms_initialize_constants(chip);
- mutex_init(&chip->bms_output_lock);
- mutex_init(&chip->last_ocv_uv_mutex);
- mutex_init(&chip->vbat_monitor_mutex);
- mutex_init(&chip->soc_invalidation_mutex);
- mutex_init(&chip->last_soc_mutex);
-
wakeup_source_init(&chip->soc_wake_source.source, "qpnp_soc_wake");
wake_lock_init(&chip->low_voltage_wake_lock, WAKE_LOCK_SUSPEND,
"qpnp_low_voltage_lock");
@@ -3786,20 +3717,26 @@
read_shutdown_soc_and_iavg(chip);
if (chip->enable_fcc_learning) {
- restore_fcc_data(chip);
- rc = sysfs_create_group(&spmi->dev.kobj, &fcc_attr_group);
- if (rc) {
- pr_err("Unable to create sysfs entries\n");
- goto error_setup;
+ if (chip->battery_removed) {
+ rc = discard_backup_fcc_data(chip);
+ if (rc)
+ pr_err("Could not discard backed-up FCC data\n");
+ } else {
+ rc = read_chgcycle_data_from_backup(chip);
+ if (rc)
+ pr_err("Unable to restore charge-cycle data\n");
+
+ rc = read_fcc_data_from_backup(chip);
+ if (rc)
+ pr_err("Unable to restore FCC-learning data\n");
+ else
+ attempt_learning_new_fcc(chip);
}
}
dev_set_drvdata(&spmi->dev, chip);
device_init_wakeup(&spmi->dev, 1);
- check_battery_removal(chip);
-
-
rc = setup_vbat_monitoring(chip);
if (rc < 0) {
pr_err("failed to set up voltage notifications: %d\n", rc);
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 23941a9..3679aa9 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -1143,7 +1143,7 @@
val->intval = qpnp_chg_is_dc_chg_plugged_in(chip);
break;
case POWER_SUPPLY_PROP_CURRENT_MAX:
- val->intval = chip->maxinput_dc_ma;
+ val->intval = chip->maxinput_dc_ma * 1000;
break;
default:
return -EINVAL;
@@ -2767,13 +2767,6 @@
chip->duty_cycle_100p = of_property_read_bool(
chip->spmi->dev.of_node,
"qcom,duty-cycle-100p");
- if (chip->duty_cycle_100p) {
- rc = qpnp_buck_set_100_duty_cycle_enable(chip, 1);
- if (rc) {
- pr_err("failed to enable duty cycle %d\n", rc);
- return rc;
- }
- }
/* Get the fake-batt-values property */
chip->use_default_batt_values =
@@ -2939,6 +2932,16 @@
0xFF,
0x80, 1);
+ if (chip->duty_cycle_100p) {
+ rc = qpnp_buck_set_100_duty_cycle_enable(chip,
+ 1);
+ if (rc) {
+ pr_err("failed to set duty cycle %d\n",
+ rc);
+ goto fail_chg_enable;
+ }
+ }
+
break;
case SMBB_BAT_IF_SUBTYPE:
case SMBBP_BAT_IF_SUBTYPE:
diff --git a/drivers/spmi/qpnp-int.c b/drivers/spmi/qpnp-int.c
index 082c9ff..eedb1e5 100644
--- a/drivers/spmi/qpnp-int.c
+++ b/drivers/spmi/qpnp-int.c
@@ -578,11 +578,14 @@
unsigned long hwirq, busno;
int irq;
+ if (!spec || !spmi_ctrl)
+ return -EINVAL;
+
pr_debug("spec slave = %u per = %u irq = %u\n",
spec->slave, spec->per, spec->irq);
busno = spmi_ctrl->nr;
- if (!spec || !spmi_ctrl || busno >= QPNPINT_MAX_BUSSES)
+ if (busno >= QPNPINT_MAX_BUSSES)
return -EINVAL;
hwirq = qpnpint_encode_hwirq(spec);
diff --git a/drivers/thermal/msm8974-tsens.c b/drivers/thermal/msm8974-tsens.c
index 3450779..6933163 100644
--- a/drivers/thermal/msm8974-tsens.c
+++ b/drivers/thermal/msm8974-tsens.c
@@ -564,6 +564,9 @@
unsigned int reg_cntl;
int code, hi_code, lo_code, code_err_chk, sensor_sw_id = 0, rc = 0;
+ if (!tm_sensor || trip < 0 || !temp)
+ return -EINVAL;
+
rc = tsens_get_sw_id_mapping(tm_sensor->sensor_hw_num, &sensor_sw_id);
if (rc < 0) {
pr_err("tsens mapping index not found\n");
@@ -1343,7 +1346,7 @@
static int get_device_tree_data(struct platform_device *pdev)
{
- const struct device_node *of_node = pdev->dev.of_node;
+ struct device_node *of_node = pdev->dev.of_node;
struct resource *res_mem = NULL;
u32 *tsens_slope_data;
u32 *sensor_id;
@@ -1371,8 +1374,13 @@
return rc;
};
- tsens_calib_mode = of_get_property(of_node,
- "qcom,calib-mode", NULL);
+ rc = of_property_read_string(of_node,
+ "qcom,calib-mode", &tsens_calib_mode);
+ if (rc) {
+ dev_err(&pdev->dev, "missing calib-mode\n");
+ return -ENODEV;
+ }
+
if (!strncmp(tsens_calib_mode, "fuse_map1", 9))
calib_type = TSENS_CALIB_FUSE_MAP_8974;
else if (!strncmp(tsens_calib_mode, "fuse_map2", 9))
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 2487e3f..0f8a7f0 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -36,6 +36,7 @@
#include <linux/usb/msm_hsusb.h>
#include <linux/usb/msm_ext_chg.h>
#include <linux/regulator/consumer.h>
+#include <linux/pm_wakeup.h>
#include <linux/power_supply.h>
#include <linux/qpnp/qpnp-adc.h>
#include <linux/cdev.h>
@@ -196,7 +197,6 @@
bool lpm_irq_seen;
struct delayed_work resume_work;
struct work_struct restart_usb_work;
- struct wake_lock wlock;
struct dwc3_charger charger;
struct usb_phy *otg_xceiv;
struct delayed_work chg_work;
@@ -246,8 +246,6 @@
#define USB_SSPHY_1P8_VOL_MAX 1800000 /* uV */
#define USB_SSPHY_1P8_HPM_LOAD 23000 /* uA */
-static struct dwc3_msm *context;
-
static struct usb_ext_notification *usb_ext;
/**
@@ -343,8 +341,8 @@
tmp &= mask; /* clear other bits */
if (tmp != val)
- dev_err(context->dev, "%s: write: %x to QSCRATCH: %x FAILED\n",
- __func__, val, offset);
+ pr_err("%s: write: %x to QSCRATCH: %x FAILED\n",
+ __func__, val, offset);
}
/**
@@ -413,12 +411,12 @@
* Return DBM EP number according to usb endpoint number.
*
*/
-static int dwc3_msm_find_matching_dbm_ep(u8 usb_ep)
+static int dwc3_msm_find_matching_dbm_ep(struct dwc3_msm *mdwc, u8 usb_ep)
{
int i;
- for (i = 0; i < context->dbm_num_eps; i++)
- if (context->ep_num_mapping[i] == usb_ep)
+ for (i = 0; i < mdwc->dbm_num_eps; i++)
+ if (mdwc->ep_num_mapping[i] == usb_ep)
return i;
return -ENODEV; /* Not found */
@@ -428,13 +426,13 @@
* Return number of configured DBM endpoints.
*
*/
-static int dwc3_msm_configured_dbm_ep_num(void)
+static int dwc3_msm_configured_dbm_ep_num(struct dwc3_msm *mdwc)
{
int i;
int count = 0;
- for (i = 0; i < context->dbm_num_eps; i++)
- if (context->ep_num_mapping[i])
+ for (i = 0; i < mdwc->dbm_num_eps; i++)
+ if (mdwc->ep_num_mapping[i])
count++;
return count;
@@ -448,12 +446,13 @@
* @size - size of the event buffer.
*
*/
-static int dwc3_msm_event_buffer_config(u32 addr, u16 size)
+static int dwc3_msm_event_buffer_config(struct dwc3_msm *mdwc,
+ u32 addr, u16 size)
{
- dev_dbg(context->dev, "%s\n", __func__);
+ dev_dbg(mdwc->dev, "%s\n", __func__);
- dwc3_msm_write_reg(context->base, DBM_GEVNTADR, addr);
- dwc3_msm_write_reg_field(context->base, DBM_GEVNTSIZ,
+ dwc3_msm_write_reg(mdwc->base, DBM_GEVNTADR, addr);
+ dwc3_msm_write_reg_field(mdwc->base, DBM_GEVNTSIZ,
DBM_GEVNTSIZ_MASK, size);
return 0;
@@ -463,19 +462,19 @@
* Reset the DBM registers upon initialization.
*
*/
-static int dwc3_msm_dbm_soft_reset(int enter_reset)
+static int dwc3_msm_dbm_soft_reset(struct dwc3_msm *mdwc, int enter_reset)
{
- dev_dbg(context->dev, "%s\n", __func__);
+ dev_dbg(mdwc->dev, "%s\n", __func__);
if (enter_reset) {
- dev_dbg(context->dev, "enter DBM reset\n");
- dwc3_msm_write_reg_field(context->base, DBM_SOFT_RESET,
+ dev_dbg(mdwc->dev, "enter DBM reset\n");
+ dwc3_msm_write_reg_field(mdwc->base, DBM_SOFT_RESET,
DBM_SFT_RST_MASK, 1);
} else {
- dev_dbg(context->dev, "exit DBM reset\n");
- dwc3_msm_write_reg_field(context->base, DBM_SOFT_RESET,
+ dev_dbg(mdwc->dev, "exit DBM reset\n");
+ dwc3_msm_write_reg_field(mdwc->base, DBM_SOFT_RESET,
DBM_SFT_RST_MASK, 0);
/*enable DBM*/
- dwc3_msm_write_reg_field(context->base, QSCRATCH_GENERAL_CFG,
+ dwc3_msm_write_reg_field(mdwc->base, QSCRATCH_GENERAL_CFG,
DBM_EN_MASK, 0x1);
}
@@ -492,21 +491,21 @@
* @enter_reset - should we enter a reset state or get out of it.
*
*/
-static int dwc3_msm_dbm_ep_soft_reset(u8 dbm_ep, bool enter_reset)
+static int dwc3_msm_dbm_ep_soft_reset(struct dwc3_msm *mdwc,
+ u8 dbm_ep, bool enter_reset)
{
- dev_dbg(context->dev, "%s\n", __func__);
+ dev_dbg(mdwc->dev, "%s\n", __func__);
- if (dbm_ep >= context->dbm_num_eps) {
- dev_err(context->dev,
- "%s: Invalid DBM ep index\n", __func__);
+ if (dbm_ep >= mdwc->dbm_num_eps) {
+ dev_err(mdwc->dev, "%s: Invalid DBM ep index\n", __func__);
return -ENODEV;
}
if (enter_reset) {
- dwc3_msm_write_reg_field(context->base, DBM_SOFT_RESET,
+ dwc3_msm_write_reg_field(mdwc->base, DBM_SOFT_RESET,
DBM_SFT_RST_EPS_MASK & 1 << dbm_ep, 1);
} else {
- dwc3_msm_write_reg_field(context->base, DBM_SOFT_RESET,
+ dwc3_msm_write_reg_field(mdwc->base, DBM_SOFT_RESET,
DBM_SFT_RST_EPS_MASK & 1 << dbm_ep, 0);
}
@@ -525,43 +524,43 @@
*
* @return int - DBM ep number.
*/
-static int dwc3_msm_dbm_ep_config(u8 usb_ep, u8 bam_pipe,
+static int dwc3_msm_dbm_ep_config(struct dwc3_msm *mdwc, u8 usb_ep, u8 bam_pipe,
bool producer, bool disable_wb,
bool internal_mem, bool ioc)
{
u8 dbm_ep;
u32 ep_cfg;
- dev_dbg(context->dev, "%s\n", __func__);
+ dev_dbg(mdwc->dev, "%s\n", __func__);
- dbm_ep = dwc3_msm_find_matching_dbm_ep(usb_ep);
+ dbm_ep = dwc3_msm_find_matching_dbm_ep(mdwc, usb_ep);
if (dbm_ep < 0) {
- dev_err(context->dev,
+ dev_err(mdwc->dev,
"%s: Invalid usb ep index\n", __func__);
return -ENODEV;
}
/* First, reset the dbm endpoint */
- dwc3_msm_dbm_ep_soft_reset(dbm_ep, 0);
+ dwc3_msm_dbm_ep_soft_reset(mdwc, dbm_ep, 0);
/* Set ioc bit for dbm_ep if needed */
- dwc3_msm_write_reg_field(context->base, DBM_DBG_CNFG,
+ dwc3_msm_write_reg_field(mdwc->base, DBM_DBG_CNFG,
DBM_ENABLE_IOC_MASK & 1 << dbm_ep, ioc ? 1 : 0);
ep_cfg = (producer ? DBM_PRODUCER : 0) |
(disable_wb ? DBM_DISABLE_WB : 0) |
(internal_mem ? DBM_INT_RAM_ACC : 0);
- dwc3_msm_write_reg_field(context->base, DBM_EP_CFG(dbm_ep),
+ dwc3_msm_write_reg_field(mdwc->base, DBM_EP_CFG(dbm_ep),
DBM_PRODUCER | DBM_DISABLE_WB | DBM_INT_RAM_ACC, ep_cfg >> 8);
- dwc3_msm_write_reg_field(context->base, DBM_EP_CFG(dbm_ep), USB3_EPNUM,
+ dwc3_msm_write_reg_field(mdwc->base, DBM_EP_CFG(dbm_ep), USB3_EPNUM,
usb_ep);
- dwc3_msm_write_reg_field(context->base, DBM_EP_CFG(dbm_ep),
+ dwc3_msm_write_reg_field(mdwc->base, DBM_EP_CFG(dbm_ep),
DBM_BAM_PIPE_NUM, bam_pipe);
- dwc3_msm_write_reg_field(context->base, DBM_PIPE_CFG, 0x000000ff,
+ dwc3_msm_write_reg_field(mdwc->base, DBM_PIPE_CFG, 0x000000ff,
0xe4);
- dwc3_msm_write_reg_field(context->base, DBM_EP_CFG(dbm_ep), DBM_EN_EP,
+ dwc3_msm_write_reg_field(mdwc->base, DBM_EP_CFG(dbm_ep), DBM_EN_EP,
1);
return dbm_ep;
@@ -573,35 +572,34 @@
* @usb_ep - USB ep number.
*
*/
-static int dwc3_msm_dbm_ep_unconfig(u8 usb_ep)
+static int dwc3_msm_dbm_ep_unconfig(struct dwc3_msm *mdwc, u8 usb_ep)
{
u8 dbm_ep;
u32 data;
- dev_dbg(context->dev, "%s\n", __func__);
+ dev_dbg(mdwc->dev, "%s\n", __func__);
- dbm_ep = dwc3_msm_find_matching_dbm_ep(usb_ep);
+ dbm_ep = dwc3_msm_find_matching_dbm_ep(mdwc, usb_ep);
if (dbm_ep < 0) {
- dev_err(context->dev,
- "%s: Invalid usb ep index\n", __func__);
+ dev_err(mdwc->dev, "%s: Invalid usb ep index\n", __func__);
return -ENODEV;
}
- context->ep_num_mapping[dbm_ep] = 0;
+ mdwc->ep_num_mapping[dbm_ep] = 0;
- data = dwc3_msm_read_reg(context->base, DBM_EP_CFG(dbm_ep));
+ data = dwc3_msm_read_reg(mdwc->base, DBM_EP_CFG(dbm_ep));
data &= (~0x1);
- dwc3_msm_write_reg(context->base, DBM_EP_CFG(dbm_ep), data);
+ dwc3_msm_write_reg(mdwc->base, DBM_EP_CFG(dbm_ep), data);
/* Reset the dbm endpoint */
- dwc3_msm_dbm_ep_soft_reset(dbm_ep, true);
+ dwc3_msm_dbm_ep_soft_reset(mdwc, dbm_ep, true);
/*
* 10 usec delay is required before deasserting DBM endpoint reset
* according to hardware programming guide.
*/
udelay(10);
- dwc3_msm_dbm_ep_soft_reset(dbm_ep, false);
+ dwc3_msm_dbm_ep_soft_reset(mdwc, dbm_ep, false);
return 0;
}
@@ -620,15 +618,17 @@
{
u8 dbm_ep;
struct dwc3_ep *dep = to_dwc3_ep(ep);
+ struct dwc3 *dwc = dep->dwc;
+ struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
u8 bam_pipe = dst_pipe_idx;
- dev_dbg(context->dev, "%s\n", __func__);
+ dev_dbg(mdwc->dev, "%s\n", __func__);
dbm_ep = bam_pipe;
- context->ep_num_mapping[dbm_ep] = dep->number;
+ mdwc->ep_num_mapping[dbm_ep] = dep->number;
- dwc3_msm_write_reg(context->base, DBM_DATA_FIFO(dbm_ep), addr);
- dwc3_msm_write_reg_field(context->base, DBM_DATA_FIFO_SIZE(dbm_ep),
+ dwc3_msm_write_reg(mdwc->base, DBM_DATA_FIFO(dbm_ep), addr);
+ dwc3_msm_write_reg_field(mdwc->base, DBM_DATA_FIFO_SIZE(dbm_ep),
DBM_DATA_FIFO_SIZE_MASK, size);
return 0;
@@ -648,12 +648,12 @@
struct usb_request *request)
{
struct dwc3_ep *dep = to_dwc3_ep(ep);
+ struct dwc3 *dwc = dep->dwc;
+ struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
struct dwc3_msm_req_complete *req_complete = NULL;
/* Find original request complete function and remove it from list */
- list_for_each_entry(req_complete,
- &context->req_complete_list,
- list_item) {
+ list_for_each_entry(req_complete, &mdwc->req_complete_list, list_item) {
if (req_complete->req == request)
break;
}
@@ -672,14 +672,14 @@
dep->busy_slot++;
/* Unconfigure dbm ep */
- dwc3_msm_dbm_ep_unconfig(dep->number);
+ dwc3_msm_dbm_ep_unconfig(mdwc, dep->number);
/*
* If this is the last endpoint we unconfigured, than reset also
* the event buffers.
*/
- if (0 == dwc3_msm_configured_dbm_ep_num())
- dwc3_msm_event_buffer_config(0, 0);
+ if (0 == dwc3_msm_configured_dbm_ep_num(mdwc))
+ dwc3_msm_event_buffer_config(mdwc, 0, 0);
/*
* Call original complete function, notice that dwc->lock is already
@@ -792,6 +792,7 @@
struct dwc3_request *req = to_dwc3_request(request);
struct dwc3_ep *dep = to_dwc3_ep(ep);
struct dwc3 *dwc = dep->dwc;
+ struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
struct dwc3_msm_req_complete *req_complete;
unsigned long flags;
int ret = 0;
@@ -804,23 +805,23 @@
if (!(request->udc_priv & MSM_SPS_MODE)) {
/* Not SPS mode, call original queue */
- dev_vdbg(dwc->dev, "%s: not sps mode, use regular queue\n",
+ dev_vdbg(mdwc->dev, "%s: not sps mode, use regular queue\n",
__func__);
- return (context->original_ep_ops[dep->number])->queue(ep,
+ return (mdwc->original_ep_ops[dep->number])->queue(ep,
request,
gfp_flags);
}
if (!dep->endpoint.desc) {
- dev_err(dwc->dev,
+ dev_err(mdwc->dev,
"%s: trying to queue request %p to disabled ep %s\n",
__func__, request, ep->name);
return -EPERM;
}
if (dep->number == 0 || dep->number == 1) {
- dev_err(dwc->dev,
+ dev_err(mdwc->dev,
"%s: trying to queue dbm request %p to control ep %s\n",
__func__, request, ep->name);
return -EPERM;
@@ -829,7 +830,7 @@
if (dep->busy_slot != dep->free_slot || !list_empty(&dep->request_list)
|| !list_empty(&dep->req_queued)) {
- dev_err(dwc->dev,
+ dev_err(mdwc->dev,
"%s: trying to queue dbm request %p tp ep %s\n",
__func__, request, ep->name);
return -EPERM;
@@ -844,12 +845,12 @@
*/
req_complete = kzalloc(sizeof(*req_complete), GFP_KERNEL);
if (!req_complete) {
- dev_err(dep->dwc->dev, "%s: not enough memory\n", __func__);
+ dev_err(mdwc->dev, "%s: not enough memory\n", __func__);
return -ENOMEM;
}
req_complete->req = request;
req_complete->orig_complete = request->complete;
- list_add_tail(&req_complete->list_item, &context->req_complete_list);
+ list_add_tail(&req_complete->list_item, &mdwc->req_complete_list);
request->complete = dwc3_msm_req_complete_func;
/*
@@ -861,11 +862,11 @@
internal_mem = ((request->udc_priv & MSM_INTERNAL_MEM) ? true : false);
ioc = ((request->udc_priv & MSM_ETD_IOC) ? true : false);
- ret = dwc3_msm_dbm_ep_config(dep->number,
+ ret = dwc3_msm_dbm_ep_config(mdwc, dep->number,
bam_pipe, producer,
disable_wb, internal_mem, ioc);
if (ret < 0) {
- dev_err(context->dev,
+ dev_err(mdwc->dev,
"error %d after calling dwc3_msm_dbm_ep_config\n",
ret);
return ret;
@@ -885,13 +886,13 @@
ret = __dwc3_msm_ep_queue(dep, req);
spin_unlock_irqrestore(&dwc->lock, flags);
if (ret < 0) {
- dev_err(context->dev,
+ dev_err(mdwc->dev,
"error %d after calling __dwc3_msm_ep_queue\n", ret);
return ret;
}
speed = dwc3_readl(dwc->regs, DWC3_DSTS) & DWC3_DSTS_CONNECTSPD;
- dwc3_msm_write_reg(context->base, DBM_GEN_CFG, speed >> 2);
+ dwc3_msm_write_reg(mdwc->base, DBM_GEN_CFG, speed >> 2);
return 0;
}
@@ -913,25 +914,27 @@
int msm_ep_config(struct usb_ep *ep)
{
struct dwc3_ep *dep = to_dwc3_ep(ep);
+ struct dwc3 *dwc = dep->dwc;
+ struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
struct usb_ep_ops *new_ep_ops;
- dwc3_msm_event_buffer_config(dwc3_msm_read_reg(context->base,
- DWC3_GEVNTADRLO(0)),
- dwc3_msm_read_reg(context->base, DWC3_GEVNTSIZ(0)));
+ dwc3_msm_event_buffer_config(mdwc,
+ dwc3_msm_read_reg(mdwc->base, DWC3_GEVNTADRLO(0)),
+ dwc3_msm_read_reg(mdwc->base, DWC3_GEVNTSIZ(0)));
/* Save original ep ops for future restore*/
- if (context->original_ep_ops[dep->number]) {
- dev_err(context->dev,
+ if (mdwc->original_ep_ops[dep->number]) {
+ dev_err(mdwc->dev,
"ep [%s,%d] already configured as msm endpoint\n",
ep->name, dep->number);
return -EPERM;
}
- context->original_ep_ops[dep->number] = ep->ops;
+ mdwc->original_ep_ops[dep->number] = ep->ops;
/* Set new usb ops as we like */
new_ep_ops = kzalloc(sizeof(struct usb_ep_ops), GFP_KERNEL);
if (!new_ep_ops) {
- dev_err(context->dev,
+ dev_err(mdwc->dev,
"%s: unable to allocate mem for new usb ep ops\n",
__func__);
return -ENOMEM;
@@ -963,18 +966,20 @@
int msm_ep_unconfig(struct usb_ep *ep)
{
struct dwc3_ep *dep = to_dwc3_ep(ep);
+ struct dwc3 *dwc = dep->dwc;
+ struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
struct usb_ep_ops *old_ep_ops;
/* Restore original ep ops */
- if (!context->original_ep_ops[dep->number]) {
- dev_err(context->dev,
+ if (!mdwc->original_ep_ops[dep->number]) {
+ dev_err(mdwc->dev,
"ep [%s,%d] was not configured as msm endpoint\n",
ep->name, dep->number);
return -EINVAL;
}
old_ep_ops = (struct usb_ep_ops *)ep->ops;
- ep->ops = context->original_ep_ops[dep->number];
- context->original_ep_ops[dep->number] = NULL;
+ ep->ops = mdwc->original_ep_ops[dep->number];
+ mdwc->original_ep_ops[dep->number] = NULL;
kfree(old_ep_ops);
/*
@@ -1019,14 +1024,16 @@
* This performs full hardware reset and re-initialization which
* might be required by some DBM client driver during uninit/cleanup.
*/
-void msm_dwc3_restart_usb_session(void)
+void msm_dwc3_restart_usb_session(struct usb_gadget *gadget)
{
- struct dwc3_msm *mdwc = context;
+ struct dwc3 *dwc = container_of(gadget, struct dwc3, gadget);
+ struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
+
+ if (mdwc)
+ return;
dev_dbg(mdwc->dev, "%s\n", __func__);
queue_work(system_nrt_wq, &mdwc->restart_usb_work);
-
- return;
}
EXPORT_SYMBOL(msm_dwc3_restart_usb_session);
@@ -1058,10 +1065,9 @@
EXPORT_SYMBOL(msm_register_usb_ext_notification);
/* HSPHY */
-static int dwc3_hsusb_config_vddcx(int high)
+static int dwc3_hsusb_config_vddcx(struct dwc3_msm *dwc, int high)
{
int min_vol, max_vol, ret;
- struct dwc3_msm *dwc = context;
max_vol = dwc->vdd_high_vol_level;
min_vol = high ? dwc->vdd_low_vol_level : dwc->vdd_no_vol_level;
@@ -1077,10 +1083,9 @@
return ret;
}
-static int dwc3_hsusb_ldo_init(int init)
+static int dwc3_hsusb_ldo_init(struct dwc3_msm *dwc, int init)
{
int rc = 0;
- struct dwc3_msm *dwc = context;
if (!init) {
regulator_set_voltage(dwc->hsusb_1p8, 0, USB_HSPHY_1P8_VOL_MAX);
@@ -1121,10 +1126,9 @@
return rc;
}
-static int dwc3_hsusb_ldo_enable(int on)
+static int dwc3_hsusb_ldo_enable(struct dwc3_msm *dwc, int on)
{
int rc = 0;
- struct dwc3_msm *dwc = context;
dev_dbg(dwc->dev, "reg (%s)\n", on ? "HPM" : "LPM");
@@ -1182,10 +1186,9 @@
}
/* SSPHY */
-static int dwc3_ssusb_config_vddcx(int high)
+static int dwc3_ssusb_config_vddcx(struct dwc3_msm *dwc, int high)
{
int min_vol, max_vol, ret;
- struct dwc3_msm *dwc = context;
max_vol = dwc->vdd_high_vol_level;
min_vol = high ? dwc->vdd_low_vol_level : dwc->vdd_no_vol_level;
@@ -1201,10 +1204,9 @@
}
/* 3.3v supply not needed for SS PHY */
-static int dwc3_ssusb_ldo_init(int init)
+static int dwc3_ssusb_ldo_init(struct dwc3_msm *dwc, int init)
{
int rc = 0;
- struct dwc3_msm *dwc = context;
if (!init) {
regulator_set_voltage(dwc->ssusb_1p8, 0, USB_SSPHY_1P8_VOL_MAX);
@@ -1224,12 +1226,11 @@
return rc;
}
-static int dwc3_ssusb_ldo_enable(int on)
+static int dwc3_ssusb_ldo_enable(struct dwc3_msm *dwc, int on)
{
int rc = 0;
- struct dwc3_msm *dwc = context;
- dev_dbg(context->dev, "reg (%s)\n", on ? "HPM" : "LPM");
+ dev_dbg(dwc->dev, "reg (%s)\n", on ? "HPM" : "LPM");
if (!on)
goto disable_regulators;
@@ -1266,37 +1267,36 @@
* Config Global Distributed Switch Controller (GDSC)
* to support controller power collapse
*/
-static int dwc3_msm_config_gdsc(struct dwc3_msm *msm, int on)
+static int dwc3_msm_config_gdsc(struct dwc3_msm *mdwc, int on)
{
int ret = 0;
- if (IS_ERR(msm->dwc3_gdsc))
+ if (IS_ERR(mdwc->dwc3_gdsc))
return 0;
- if (!msm->dwc3_gdsc) {
- msm->dwc3_gdsc = devm_regulator_get(msm->dev,
+ if (!mdwc->dwc3_gdsc) {
+ mdwc->dwc3_gdsc = devm_regulator_get(mdwc->dev,
"USB3_GDSC");
- if (IS_ERR(msm->dwc3_gdsc))
+ if (IS_ERR(mdwc->dwc3_gdsc))
return 0;
}
if (on) {
- ret = regulator_enable(msm->dwc3_gdsc);
+ ret = regulator_enable(mdwc->dwc3_gdsc);
if (ret) {
- dev_err(msm->dev, "unable to enable usb3 gdsc\n");
+ dev_err(mdwc->dev, "unable to enable usb3 gdsc\n");
return ret;
}
} else {
- regulator_disable(msm->dwc3_gdsc);
+ regulator_disable(mdwc->dwc3_gdsc);
}
return 0;
}
-static int dwc3_msm_link_clk_reset(bool assert)
+static int dwc3_msm_link_clk_reset(struct dwc3_msm *mdwc, bool assert)
{
int ret = 0;
- struct dwc3_msm *mdwc = context;
if (assert) {
/* Using asynchronous block reset to the hardware */
@@ -1322,7 +1322,7 @@
}
/* Reinitialize SSPHY parameters by overriding using QSCRATCH CR interface */
-static void dwc3_msm_ss_phy_reg_init(struct dwc3_msm *msm)
+static void dwc3_msm_ss_phy_reg_init(struct dwc3_msm *mdwc)
{
u32 data = 0;
@@ -1331,14 +1331,14 @@
* in HS mode instead of SS mode. Workaround it by asserting
* LANE0.TX_ALT_BLOCK.EN_ALT_BUS to enable TX to use alt bus mode
*/
- data = dwc3_msm_ssusb_read_phycreg(msm->base, 0x102D);
+ data = dwc3_msm_ssusb_read_phycreg(mdwc->base, 0x102D);
data |= (1 << 7);
- dwc3_msm_ssusb_write_phycreg(msm->base, 0x102D, data);
+ dwc3_msm_ssusb_write_phycreg(mdwc->base, 0x102D, data);
- data = dwc3_msm_ssusb_read_phycreg(msm->base, 0x1010);
+ data = dwc3_msm_ssusb_read_phycreg(mdwc->base, 0x1010);
data &= ~0xFF0;
data |= 0x20;
- dwc3_msm_ssusb_write_phycreg(msm->base, 0x1010, data);
+ dwc3_msm_ssusb_write_phycreg(mdwc->base, 0x1010, data);
/*
* Fix RX Equalization setting as follows
@@ -1347,13 +1347,13 @@
* LANE0.RX_OVRD_IN_HI.RX_EQ set to 3
* LANE0.RX_OVRD_IN_HI.RX_EQ_OVRD set to 1
*/
- data = dwc3_msm_ssusb_read_phycreg(msm->base, 0x1006);
+ data = dwc3_msm_ssusb_read_phycreg(mdwc->base, 0x1006);
data &= ~(1 << 6);
data |= (1 << 7);
data &= ~(0x7 << 8);
data |= (0x3 << 8);
data |= (0x1 << 11);
- dwc3_msm_ssusb_write_phycreg(msm->base, 0x1006, data);
+ dwc3_msm_ssusb_write_phycreg(mdwc->base, 0x1006, data);
/*
* Set EQ and TX launch amplitudes as follows
@@ -1361,12 +1361,12 @@
* LANE0.TX_OVRD_DRV_LO.AMPLITUDE set to 127
* LANE0.TX_OVRD_DRV_LO.EN set to 1.
*/
- data = dwc3_msm_ssusb_read_phycreg(msm->base, 0x1002);
+ data = dwc3_msm_ssusb_read_phycreg(mdwc->base, 0x1002);
data &= ~0x3F80;
data |= (0x16 << 7);
data &= ~0x7F;
data |= (0x7F | (1 << 14));
- dwc3_msm_ssusb_write_phycreg(msm->base, 0x1002, data);
+ dwc3_msm_ssusb_write_phycreg(mdwc->base, 0x1002, data);
/*
* Set the QSCRATCH SS_PHY_PARAM_CTRL1 parameters as follows
@@ -1374,73 +1374,73 @@
* TX_DEEMPH_3_5DB [13:8] to 22
* LOS_BIAS [2:0] to 0x5
*/
- dwc3_msm_write_readback(msm->base, SS_PHY_PARAM_CTRL_1,
+ dwc3_msm_write_readback(mdwc->base, SS_PHY_PARAM_CTRL_1,
0x07f03f07, 0x07f01605);
}
/* Initialize QSCRATCH registers for HSPHY and SSPHY operation */
-static void dwc3_msm_qscratch_reg_init(struct dwc3_msm *msm)
+static void dwc3_msm_qscratch_reg_init(struct dwc3_msm *mdwc)
{
/* SSPHY Initialization: Use ref_clk from pads and set its parameters */
- dwc3_msm_write_reg(msm->base, SS_PHY_CTRL_REG, 0x10210002);
+ dwc3_msm_write_reg(mdwc->base, SS_PHY_CTRL_REG, 0x10210002);
msleep(30);
/* Assert SSPHY reset */
- dwc3_msm_write_reg(msm->base, SS_PHY_CTRL_REG, 0x10210082);
+ dwc3_msm_write_reg(mdwc->base, SS_PHY_CTRL_REG, 0x10210082);
usleep_range(2000, 2200);
/* De-assert SSPHY reset - power and ref_clock must be ON */
- dwc3_msm_write_reg(msm->base, SS_PHY_CTRL_REG, 0x10210002);
+ dwc3_msm_write_reg(mdwc->base, SS_PHY_CTRL_REG, 0x10210002);
usleep_range(2000, 2200);
/* Ref clock must be stable now, enable ref clock for HS mode */
- dwc3_msm_write_reg(msm->base, SS_PHY_CTRL_REG, 0x10210102);
+ dwc3_msm_write_reg(mdwc->base, SS_PHY_CTRL_REG, 0x10210102);
usleep_range(2000, 2200);
/*
* HSPHY Initialization: Enable UTMI clock and clamp enable HVINTs,
* and disable RETENTION (power-on default is ENABLED)
*/
- dwc3_msm_write_reg(msm->base, HS_PHY_CTRL_REG, 0x5220bb2);
+ dwc3_msm_write_reg(mdwc->base, HS_PHY_CTRL_REG, 0x5220bb2);
usleep_range(2000, 2200);
/* Disable (bypass) VBUS and ID filters */
- dwc3_msm_write_reg(msm->base, QSCRATCH_GENERAL_CFG, 0x78);
+ dwc3_msm_write_reg(mdwc->base, QSCRATCH_GENERAL_CFG, 0x78);
/*
* write HSPHY init value to QSCRATCH reg to set HSPHY parameters like
* VBUS valid threshold, disconnect valid threshold, DC voltage level,
* preempasis and rise/fall time.
*/
if (override_phy_init)
- msm->hsphy_init_seq = override_phy_init;
- if (msm->hsphy_init_seq)
- dwc3_msm_write_readback(msm->base,
+ mdwc->hsphy_init_seq = override_phy_init;
+ if (mdwc->hsphy_init_seq)
+ dwc3_msm_write_readback(mdwc->base,
PARAMETER_OVERRIDE_X_REG, 0x03FFFFFF,
- msm->hsphy_init_seq & 0x03FFFFFF);
+ mdwc->hsphy_init_seq & 0x03FFFFFF);
/* Enable master clock for RAMs to allow BAM to access RAMs when
* RAM clock gating is enabled via DWC3's GCTL. Otherwise, issues
* are seen where RAM clocks get turned OFF in SS mode
*/
- dwc3_msm_write_reg(msm->base, CGCTL_REG,
- dwc3_msm_read_reg(msm->base, CGCTL_REG) | 0x18);
+ dwc3_msm_write_reg(mdwc->base, CGCTL_REG,
+ dwc3_msm_read_reg(mdwc->base, CGCTL_REG) | 0x18);
- dwc3_msm_ss_phy_reg_init(msm);
+ dwc3_msm_ss_phy_reg_init(mdwc);
/*
* This is required to restore the POR value after userspace
* is done with charger detection.
*/
- msm->qscratch_ctl_val = dwc3_msm_read_reg(msm->base, QSCRATCH_CTRL_REG);
+ mdwc->qscratch_ctl_val =
+ dwc3_msm_read_reg(mdwc->base, QSCRATCH_CTRL_REG);
}
-static void dwc3_msm_block_reset(bool core_reset)
+static void dwc3_msm_block_reset(struct dwc3_ext_xceiv *xceiv, bool core_reset)
{
-
- struct dwc3_msm *mdwc = context;
+ struct dwc3_msm *mdwc = container_of(xceiv, struct dwc3_msm, ext_xceiv);
int ret = 0;
if (core_reset) {
- ret = dwc3_msm_link_clk_reset(1);
+ ret = dwc3_msm_link_clk_reset(mdwc, 1);
if (ret)
return;
usleep_range(1000, 1200);
- ret = dwc3_msm_link_clk_reset(0);
+ ret = dwc3_msm_link_clk_reset(mdwc, 0);
if (ret)
return;
@@ -1451,9 +1451,9 @@
}
/* Reset the DBM */
- dwc3_msm_dbm_soft_reset(1);
+ dwc3_msm_dbm_soft_reset(mdwc, 1);
usleep_range(1000, 1200);
- dwc3_msm_dbm_soft_reset(0);
+ dwc3_msm_dbm_soft_reset(mdwc, 0);
}
static void dwc3_chg_enable_secondary_det(struct dwc3_msm *mdwc)
@@ -1664,7 +1664,7 @@
static void dwc3_start_chg_det(struct dwc3_charger *charger, bool start)
{
- struct dwc3_msm *mdwc = context;
+ struct dwc3_msm *mdwc = container_of(charger, struct dwc3_msm, charger);
if (start == false) {
dev_dbg(mdwc->dev, "canceling charging detection work\n");
@@ -1796,13 +1796,13 @@
if (mdwc->otg_xceiv && mdwc->ext_xceiv.otg_capability && !dcp &&
!host_bus_suspend)
- dwc3_hsusb_ldo_enable(0);
+ dwc3_hsusb_ldo_enable(mdwc, 0);
- dwc3_ssusb_ldo_enable(0);
- dwc3_ssusb_config_vddcx(0);
+ dwc3_ssusb_ldo_enable(mdwc, 0);
+ dwc3_ssusb_config_vddcx(mdwc, 0);
if (!host_bus_suspend && !dcp)
- dwc3_hsusb_config_vddcx(0);
- wake_unlock(&mdwc->wlock);
+ dwc3_hsusb_config_vddcx(mdwc, 0);
+ pm_relax(mdwc->dev);
atomic_set(&mdwc->in_lpm, 1);
dev_info(mdwc->dev, "DWC3 in low power mode\n");
@@ -1830,7 +1830,7 @@
return 0;
}
- wake_lock(&mdwc->wlock);
+ pm_stay_awake(mdwc->dev);
if (mdwc->bus_perf_client) {
ret = msm_bus_scale_client_update_request(
@@ -1861,13 +1861,13 @@
if (mdwc->otg_xceiv && mdwc->ext_xceiv.otg_capability && !dcp &&
!host_bus_suspend)
- dwc3_hsusb_ldo_enable(1);
+ dwc3_hsusb_ldo_enable(mdwc, 1);
- dwc3_ssusb_ldo_enable(1);
- dwc3_ssusb_config_vddcx(1);
+ dwc3_ssusb_ldo_enable(mdwc, 1);
+ dwc3_ssusb_config_vddcx(mdwc, 1);
if (!host_bus_suspend && !dcp)
- dwc3_hsusb_config_vddcx(1);
+ dwc3_hsusb_config_vddcx(mdwc, 1);
clk_prepare_enable(mdwc->ref_clk);
usleep_range(1000, 1200);
@@ -2221,9 +2221,9 @@
static void dwc3_init_adc_work(struct work_struct *w);
-static void dwc3_ext_notify_online(int on)
+static void dwc3_ext_notify_online(void *ctx, int on)
{
- struct dwc3_msm *mdwc = context;
+ struct dwc3_msm *mdwc = ctx;
bool notify_otg = false;
if (!mdwc) {
@@ -2271,7 +2271,7 @@
disable_irq(mdwc->pmic_id_irq);
ret = usb_ext->notify(usb_ext->ctxt, mdwc->id_state,
- dwc3_ext_notify_online);
+ dwc3_ext_notify_online, mdwc);
dev_dbg(mdwc->dev, "%s: external handler returned %d\n",
__func__, ret);
@@ -2367,7 +2367,12 @@
static ssize_t adc_enable_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return snprintf(buf, PAGE_SIZE, "%s\n", context->id_adc_detect ?
+ struct dwc3_msm *mdwc = dev_get_drvdata(dev);
+
+ if (!mdwc)
+ return -EINVAL;
+
+ return snprintf(buf, PAGE_SIZE, "%s\n", mdwc->id_adc_detect ?
"enabled" : "disabled");
}
@@ -2375,13 +2380,18 @@
struct device_attribute *attr, const char
*buf, size_t size)
{
+ struct dwc3_msm *mdwc = dev_get_drvdata(dev);
+
+ if (!mdwc)
+ return -EINVAL;
+
if (!strnicmp(buf, "enable", 6)) {
- if (!context->id_adc_detect)
- dwc3_init_adc_work(&context->init_adc_work.work);
+ if (!mdwc->id_adc_detect)
+ dwc3_init_adc_work(&mdwc->init_adc_work.work);
return size;
} else if (!strnicmp(buf, "disable", 7)) {
qpnp_adc_tm_usbid_end();
- context->id_adc_detect = false;
+ mdwc->id_adc_detect = false;
return size;
}
@@ -2393,25 +2403,27 @@
static int dwc3_msm_ext_chg_open(struct inode *inode, struct file *file)
{
- struct dwc3_msm *mdwc = context;
+ struct dwc3_msm *mdwc =
+ container_of(inode->i_cdev, struct dwc3_msm, ext_chg_cdev);
pr_debug("dwc3-msm ext chg open\n");
-
+ file->private_data = mdwc;
mdwc->ext_chg_opened = true;
+
return 0;
}
static long
dwc3_msm_ext_chg_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
- struct dwc3_msm *mdwc = context;
+ struct dwc3_msm *mdwc = file->private_data;
struct msm_usb_chg_info info = {0};
int ret = 0, val;
switch (cmd) {
case MSM_USB_EXT_CHG_INFO:
info.chg_block_type = USB_CHG_BLOCK_QSCRATCH;
- info.page_offset = (context->io_res->start +
+ info.page_offset = (mdwc->io_res->start +
QSCRATCH_REG_OFFSET) & ~PAGE_MASK;
/*
* The charger block register address space is only
@@ -2454,7 +2466,7 @@
static int dwc3_msm_ext_chg_mmap(struct file *file, struct vm_area_struct *vma)
{
- struct dwc3_msm *mdwc = context;
+ struct dwc3_msm *mdwc = file->private_data;
unsigned long vsize = vma->vm_end - vma->vm_start;
int ret;
@@ -2475,7 +2487,7 @@
static int dwc3_msm_ext_chg_release(struct inode *inode, struct file *file)
{
- struct dwc3_msm *mdwc = context;
+ struct dwc3_msm *mdwc = file->private_data;
pr_debug("dwc3-msm ext chg release\n");
@@ -2540,7 +2552,7 @@
static int __devinit dwc3_msm_probe(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
- struct dwc3_msm *msm;
+ struct dwc3_msm *mdwc;
struct resource *res;
void __iomem *tcsr;
unsigned long flags;
@@ -2548,39 +2560,38 @@
int len = 0;
u32 tmp[3];
- msm = devm_kzalloc(&pdev->dev, sizeof(*msm), GFP_KERNEL);
- if (!msm) {
+ mdwc = devm_kzalloc(&pdev->dev, sizeof(*mdwc), GFP_KERNEL);
+ if (!mdwc) {
dev_err(&pdev->dev, "not enough memory\n");
return -ENOMEM;
}
- platform_set_drvdata(pdev, msm);
- context = msm;
- msm->dev = &pdev->dev;
+ platform_set_drvdata(pdev, mdwc);
+ mdwc->dev = &pdev->dev;
- INIT_LIST_HEAD(&msm->req_complete_list);
- INIT_DELAYED_WORK(&msm->chg_work, dwc3_chg_detect_work);
- INIT_DELAYED_WORK(&msm->resume_work, dwc3_resume_work);
- INIT_WORK(&msm->restart_usb_work, dwc3_restart_usb_work);
- INIT_WORK(&msm->id_work, dwc3_id_work);
- INIT_DELAYED_WORK(&msm->init_adc_work, dwc3_init_adc_work);
- init_completion(&msm->ext_chg_wait);
+ INIT_LIST_HEAD(&mdwc->req_complete_list);
+ INIT_DELAYED_WORK(&mdwc->chg_work, dwc3_chg_detect_work);
+ INIT_DELAYED_WORK(&mdwc->resume_work, dwc3_resume_work);
+ INIT_WORK(&mdwc->restart_usb_work, dwc3_restart_usb_work);
+ INIT_WORK(&mdwc->id_work, dwc3_id_work);
+ INIT_DELAYED_WORK(&mdwc->init_adc_work, dwc3_init_adc_work);
+ init_completion(&mdwc->ext_chg_wait);
- ret = dwc3_msm_config_gdsc(msm, 1);
+ ret = dwc3_msm_config_gdsc(mdwc, 1);
if (ret) {
dev_err(&pdev->dev, "unable to configure usb3 gdsc\n");
return ret;
}
- msm->xo_clk = clk_get(&pdev->dev, "xo");
- if (IS_ERR(msm->xo_clk)) {
+ mdwc->xo_clk = clk_get(&pdev->dev, "xo");
+ if (IS_ERR(mdwc->xo_clk)) {
dev_err(&pdev->dev, "%s unable to get TCXO buffer handle\n",
__func__);
- ret = PTR_ERR(msm->xo_clk);
+ ret = PTR_ERR(mdwc->xo_clk);
goto disable_dwc3_gdsc;
}
- ret = clk_prepare_enable(msm->xo_clk);
+ ret = clk_prepare_enable(mdwc->xo_clk);
if (ret) {
dev_err(&pdev->dev, "%s failed to vote for TCXO buffer%d\n",
__func__, ret);
@@ -2591,62 +2602,62 @@
* DWC3 Core requires its CORE CLK (aka master / bus clk) to
* run at 125Mhz in SSUSB mode and >60MHZ for HSUSB mode.
*/
- msm->core_clk = devm_clk_get(&pdev->dev, "core_clk");
- if (IS_ERR(msm->core_clk)) {
+ mdwc->core_clk = devm_clk_get(&pdev->dev, "core_clk");
+ if (IS_ERR(mdwc->core_clk)) {
dev_err(&pdev->dev, "failed to get core_clk\n");
- ret = PTR_ERR(msm->core_clk);
+ ret = PTR_ERR(mdwc->core_clk);
goto disable_xo;
}
- clk_set_rate(msm->core_clk, 125000000);
- clk_prepare_enable(msm->core_clk);
+ clk_set_rate(mdwc->core_clk, 125000000);
+ clk_prepare_enable(mdwc->core_clk);
- msm->iface_clk = devm_clk_get(&pdev->dev, "iface_clk");
- if (IS_ERR(msm->iface_clk)) {
+ mdwc->iface_clk = devm_clk_get(&pdev->dev, "iface_clk");
+ if (IS_ERR(mdwc->iface_clk)) {
dev_err(&pdev->dev, "failed to get iface_clk\n");
- ret = PTR_ERR(msm->iface_clk);
+ ret = PTR_ERR(mdwc->iface_clk);
goto disable_core_clk;
}
- clk_prepare_enable(msm->iface_clk);
+ clk_prepare_enable(mdwc->iface_clk);
- msm->sleep_clk = devm_clk_get(&pdev->dev, "sleep_clk");
- if (IS_ERR(msm->sleep_clk)) {
+ mdwc->sleep_clk = devm_clk_get(&pdev->dev, "sleep_clk");
+ if (IS_ERR(mdwc->sleep_clk)) {
dev_err(&pdev->dev, "failed to get sleep_clk\n");
- ret = PTR_ERR(msm->sleep_clk);
+ ret = PTR_ERR(mdwc->sleep_clk);
goto disable_iface_clk;
}
- clk_prepare_enable(msm->sleep_clk);
+ clk_prepare_enable(mdwc->sleep_clk);
- msm->hsphy_sleep_clk = devm_clk_get(&pdev->dev, "sleep_a_clk");
- if (IS_ERR(msm->hsphy_sleep_clk)) {
+ mdwc->hsphy_sleep_clk = devm_clk_get(&pdev->dev, "sleep_a_clk");
+ if (IS_ERR(mdwc->hsphy_sleep_clk)) {
dev_err(&pdev->dev, "failed to get sleep_a_clk\n");
- ret = PTR_ERR(msm->hsphy_sleep_clk);
+ ret = PTR_ERR(mdwc->hsphy_sleep_clk);
goto disable_sleep_clk;
}
- clk_prepare_enable(msm->hsphy_sleep_clk);
+ clk_prepare_enable(mdwc->hsphy_sleep_clk);
- msm->utmi_clk = devm_clk_get(&pdev->dev, "utmi_clk");
- if (IS_ERR(msm->utmi_clk)) {
+ mdwc->utmi_clk = devm_clk_get(&pdev->dev, "utmi_clk");
+ if (IS_ERR(mdwc->utmi_clk)) {
dev_err(&pdev->dev, "failed to get utmi_clk\n");
- ret = PTR_ERR(msm->utmi_clk);
+ ret = PTR_ERR(mdwc->utmi_clk);
goto disable_sleep_a_clk;
}
- clk_prepare_enable(msm->utmi_clk);
+ clk_prepare_enable(mdwc->utmi_clk);
- msm->ref_clk = devm_clk_get(&pdev->dev, "ref_clk");
- if (IS_ERR(msm->ref_clk)) {
+ mdwc->ref_clk = devm_clk_get(&pdev->dev, "ref_clk");
+ if (IS_ERR(mdwc->ref_clk)) {
dev_err(&pdev->dev, "failed to get ref_clk\n");
- ret = PTR_ERR(msm->ref_clk);
+ ret = PTR_ERR(mdwc->ref_clk);
goto disable_utmi_clk;
}
- clk_prepare_enable(msm->ref_clk);
+ clk_prepare_enable(mdwc->ref_clk);
of_get_property(node, "qcom,vdd-voltage-level", &len);
if (len == sizeof(tmp)) {
of_property_read_u32_array(node, "qcom,vdd-voltage-level",
tmp, len/sizeof(*tmp));
- msm->vdd_no_vol_level = tmp[0];
- msm->vdd_low_vol_level = tmp[1];
- msm->vdd_high_vol_level = tmp[2];
+ mdwc->vdd_no_vol_level = tmp[0];
+ mdwc->vdd_low_vol_level = tmp[1];
+ mdwc->vdd_high_vol_level = tmp[2];
} else {
dev_err(&pdev->dev, "no qcom,vdd-voltage-level property\n");
ret = -EINVAL;
@@ -2654,99 +2665,100 @@
}
/* SS PHY */
- msm->ssusb_vddcx = devm_regulator_get(&pdev->dev, "ssusb_vdd_dig");
- if (IS_ERR(msm->ssusb_vddcx)) {
+ mdwc->ssusb_vddcx = devm_regulator_get(&pdev->dev, "ssusb_vdd_dig");
+ if (IS_ERR(mdwc->ssusb_vddcx)) {
dev_err(&pdev->dev, "unable to get ssusb vddcx\n");
- ret = PTR_ERR(msm->ssusb_vddcx);
+ ret = PTR_ERR(mdwc->ssusb_vddcx);
goto disable_ref_clk;
}
- ret = dwc3_ssusb_config_vddcx(1);
+ ret = dwc3_ssusb_config_vddcx(mdwc, 1);
if (ret) {
dev_err(&pdev->dev, "ssusb vddcx configuration failed\n");
goto disable_ref_clk;
}
- ret = regulator_enable(context->ssusb_vddcx);
+ ret = regulator_enable(mdwc->ssusb_vddcx);
if (ret) {
dev_err(&pdev->dev, "unable to enable the ssusb vddcx\n");
goto unconfig_ss_vddcx;
}
- ret = dwc3_ssusb_ldo_init(1);
+ ret = dwc3_ssusb_ldo_init(mdwc, 1);
if (ret) {
dev_err(&pdev->dev, "ssusb vreg configuration failed\n");
goto disable_ss_vddcx;
}
- ret = dwc3_ssusb_ldo_enable(1);
+ ret = dwc3_ssusb_ldo_enable(mdwc, 1);
if (ret) {
dev_err(&pdev->dev, "ssusb vreg enable failed\n");
goto free_ss_ldo_init;
}
/* HS PHY */
- msm->hsusb_vddcx = devm_regulator_get(&pdev->dev, "hsusb_vdd_dig");
- if (IS_ERR(msm->hsusb_vddcx)) {
+ mdwc->hsusb_vddcx = devm_regulator_get(&pdev->dev, "hsusb_vdd_dig");
+ if (IS_ERR(mdwc->hsusb_vddcx)) {
dev_err(&pdev->dev, "unable to get hsusb vddcx\n");
- ret = PTR_ERR(msm->hsusb_vddcx);
+ ret = PTR_ERR(mdwc->hsusb_vddcx);
goto disable_ss_ldo;
}
- ret = dwc3_hsusb_config_vddcx(1);
+ ret = dwc3_hsusb_config_vddcx(mdwc, 1);
if (ret) {
dev_err(&pdev->dev, "hsusb vddcx configuration failed\n");
goto disable_ss_ldo;
}
- ret = regulator_enable(context->hsusb_vddcx);
+ ret = regulator_enable(mdwc->hsusb_vddcx);
if (ret) {
dev_err(&pdev->dev, "unable to enable the hsusb vddcx\n");
goto unconfig_hs_vddcx;
}
- ret = dwc3_hsusb_ldo_init(1);
+ ret = dwc3_hsusb_ldo_init(mdwc, 1);
if (ret) {
dev_err(&pdev->dev, "hsusb vreg configuration failed\n");
goto disable_hs_vddcx;
}
- ret = dwc3_hsusb_ldo_enable(1);
+ ret = dwc3_hsusb_ldo_enable(mdwc, 1);
if (ret) {
dev_err(&pdev->dev, "hsusb vreg enable failed\n");
goto free_hs_ldo_init;
}
- msm->id_state = msm->ext_xceiv.id = DWC3_ID_FLOAT;
- msm->ext_xceiv.otg_capability = of_property_read_bool(node,
+ mdwc->id_state = mdwc->ext_xceiv.id = DWC3_ID_FLOAT;
+ mdwc->ext_xceiv.otg_capability = of_property_read_bool(node,
"qcom,otg-capability");
- msm->charger.charging_disabled = of_property_read_bool(node,
+ mdwc->charger.charging_disabled = of_property_read_bool(node,
"qcom,charging-disabled");
- msm->charger.skip_chg_detect = of_property_read_bool(node,
+ mdwc->charger.skip_chg_detect = of_property_read_bool(node,
"qcom,skip-charger-detection");
/*
* DWC3 has separate IRQ line for OTG events (ID/BSV) and for
* DP and DM linestate transitions during low power mode.
*/
- msm->hs_phy_irq = platform_get_irq_byname(pdev, "hs_phy_irq");
- if (msm->hs_phy_irq < 0) {
+ mdwc->hs_phy_irq = platform_get_irq_byname(pdev, "hs_phy_irq");
+ if (mdwc->hs_phy_irq < 0) {
dev_dbg(&pdev->dev, "pget_irq for hs_phy_irq failed\n");
- msm->hs_phy_irq = 0;
+ mdwc->hs_phy_irq = 0;
} else {
- ret = devm_request_irq(&pdev->dev, msm->hs_phy_irq,
+ ret = devm_request_irq(&pdev->dev, mdwc->hs_phy_irq,
msm_dwc3_irq, IRQF_TRIGGER_RISING,
- "msm_dwc3", msm);
+ "msm_dwc3", mdwc);
if (ret) {
dev_err(&pdev->dev, "irqreq HSPHYINT failed\n");
goto disable_hs_ldo;
}
- enable_irq_wake(msm->hs_phy_irq);
+ enable_irq_wake(mdwc->hs_phy_irq);
}
- if (msm->ext_xceiv.otg_capability) {
- msm->pmic_id_irq = platform_get_irq_byname(pdev, "pmic_id_irq");
- if (msm->pmic_id_irq > 0) {
+ if (mdwc->ext_xceiv.otg_capability) {
+ mdwc->pmic_id_irq =
+ platform_get_irq_byname(pdev, "pmic_id_irq");
+ if (mdwc->pmic_id_irq > 0) {
/* check if PMIC ID IRQ is supported */
ret = qpnp_misc_irqs_available(&pdev->dev);
@@ -2754,14 +2766,15 @@
/* qpnp hasn't probed yet; defer dwc probe */
goto disable_hs_ldo;
} else if (ret == 0) {
- msm->pmic_id_irq = 0;
+ mdwc->pmic_id_irq = 0;
} else {
ret = devm_request_irq(&pdev->dev,
- msm->pmic_id_irq,
+ mdwc->pmic_id_irq,
dwc3_pmic_id_irq,
IRQF_TRIGGER_RISING |
IRQF_TRIGGER_FALLING,
- "dwc3_msm_pmic_id", msm);
+ "dwc3_msm_pmic_id",
+ mdwc);
if (ret) {
dev_err(&pdev->dev, "irqreq IDINT failed\n");
goto disable_hs_ldo;
@@ -2769,21 +2782,21 @@
local_irq_save(flags);
/* Update initial ID state */
- msm->id_state =
- !!irq_read_line(msm->pmic_id_irq);
- if (msm->id_state == DWC3_ID_GROUND)
+ mdwc->id_state =
+ !!irq_read_line(mdwc->pmic_id_irq);
+ if (mdwc->id_state == DWC3_ID_GROUND)
queue_work(system_nrt_wq,
- &msm->id_work);
+ &mdwc->id_work);
local_irq_restore(flags);
- enable_irq_wake(msm->pmic_id_irq);
+ enable_irq_wake(mdwc->pmic_id_irq);
}
}
- if (msm->pmic_id_irq <= 0) {
+ if (mdwc->pmic_id_irq <= 0) {
/* If no PMIC ID IRQ, use ADC for ID pin detection */
- queue_work(system_nrt_wq, &msm->init_adc_work.work);
+ queue_work(system_nrt_wq, &mdwc->init_adc_work.work);
device_create_file(&pdev->dev, &dev_attr_adc_enable);
- msm->pmic_id_irq = 0;
+ mdwc->pmic_id_irq = 0;
}
}
@@ -2813,59 +2826,60 @@
goto disable_hs_ldo;
}
- msm->base = devm_ioremap_nocache(&pdev->dev, res->start,
+ mdwc->base = devm_ioremap_nocache(&pdev->dev, res->start,
resource_size(res));
- if (!msm->base) {
+ if (!mdwc->base) {
dev_err(&pdev->dev, "ioremap failed\n");
ret = -ENODEV;
goto disable_hs_ldo;
}
- msm->io_res = res; /* used to calculate chg block offset */
+ mdwc->io_res = res; /* used to calculate chg block offset */
if (of_property_read_u32(node, "qcom,dwc-hsphy-init",
- &msm->hsphy_init_seq))
+ &mdwc->hsphy_init_seq))
dev_dbg(&pdev->dev, "unable to read hsphy init seq\n");
- else if (!msm->hsphy_init_seq)
+ else if (!mdwc->hsphy_init_seq)
dev_warn(&pdev->dev, "incorrect hsphyinitseq.Using PORvalue\n");
- dwc3_msm_qscratch_reg_init(msm);
+ dwc3_msm_qscratch_reg_init(mdwc);
- pm_runtime_set_active(msm->dev);
- pm_runtime_enable(msm->dev);
+ pm_runtime_set_active(mdwc->dev);
+ pm_runtime_enable(mdwc->dev);
if (of_property_read_u32(node, "qcom,dwc-usb3-msm-dbm-eps",
- &msm->dbm_num_eps)) {
+ &mdwc->dbm_num_eps)) {
dev_err(&pdev->dev,
"unable to read platform data num of dbm eps\n");
- msm->dbm_num_eps = DBM_MAX_EPS;
+ mdwc->dbm_num_eps = DBM_MAX_EPS;
}
- if (msm->dbm_num_eps > DBM_MAX_EPS) {
+ if (mdwc->dbm_num_eps > DBM_MAX_EPS) {
dev_err(&pdev->dev,
"Driver doesn't support number of DBM EPs. "
"max: %d, dbm_num_eps: %d\n",
- DBM_MAX_EPS, msm->dbm_num_eps);
+ DBM_MAX_EPS, mdwc->dbm_num_eps);
ret = -ENODEV;
goto disable_hs_ldo;
}
/* usb_psy required only for vbus_notifications or charging support */
- if (msm->ext_xceiv.otg_capability || !msm->charger.charging_disabled) {
- msm->usb_psy.name = "usb";
- msm->usb_psy.type = POWER_SUPPLY_TYPE_USB;
- msm->usb_psy.supplied_to = dwc3_msm_pm_power_supplied_to;
- msm->usb_psy.num_supplicants = ARRAY_SIZE(
+ if (mdwc->ext_xceiv.otg_capability ||
+ !mdwc->charger.charging_disabled) {
+ mdwc->usb_psy.name = "usb";
+ mdwc->usb_psy.type = POWER_SUPPLY_TYPE_USB;
+ mdwc->usb_psy.supplied_to = dwc3_msm_pm_power_supplied_to;
+ mdwc->usb_psy.num_supplicants = ARRAY_SIZE(
dwc3_msm_pm_power_supplied_to);
- msm->usb_psy.properties = dwc3_msm_pm_power_props_usb;
- msm->usb_psy.num_properties =
+ mdwc->usb_psy.properties = dwc3_msm_pm_power_props_usb;
+ mdwc->usb_psy.num_properties =
ARRAY_SIZE(dwc3_msm_pm_power_props_usb);
- msm->usb_psy.get_property = dwc3_msm_power_get_property_usb;
- msm->usb_psy.set_property = dwc3_msm_power_set_property_usb;
- msm->usb_psy.external_power_changed =
+ mdwc->usb_psy.get_property = dwc3_msm_power_get_property_usb;
+ mdwc->usb_psy.set_property = dwc3_msm_power_set_property_usb;
+ mdwc->usb_psy.external_power_changed =
dwc3_msm_external_power_changed;
- ret = power_supply_register(&pdev->dev, &msm->usb_psy);
+ ret = power_supply_register(&pdev->dev, &mdwc->usb_psy);
if (ret < 0) {
dev_err(&pdev->dev,
"%s:power_supply_register usb failed\n",
@@ -2883,27 +2897,28 @@
}
}
- msm->bus_scale_table = msm_bus_cl_get_pdata(pdev);
- if (!msm->bus_scale_table) {
+ mdwc->bus_scale_table = msm_bus_cl_get_pdata(pdev);
+ if (!mdwc->bus_scale_table) {
dev_err(&pdev->dev, "bus scaling is disabled\n");
} else {
- msm->bus_perf_client =
- msm_bus_scale_register_client(msm->bus_scale_table);
+ mdwc->bus_perf_client =
+ msm_bus_scale_register_client(mdwc->bus_scale_table);
ret = msm_bus_scale_client_update_request(
- msm->bus_perf_client, 1);
+ mdwc->bus_perf_client, 1);
if (ret)
dev_err(&pdev->dev, "Failed to vote for bus scaling\n");
}
- msm->otg_xceiv = usb_get_transceiver();
+ mdwc->otg_xceiv = usb_get_transceiver();
/* Register with OTG if present, ignore USB2 OTG using other PHY */
- if (msm->otg_xceiv && !(msm->otg_xceiv->flags & ENABLE_SECONDARY_PHY)) {
+ if (mdwc->otg_xceiv &&
+ !(mdwc->otg_xceiv->flags & ENABLE_SECONDARY_PHY)) {
/* Skip charger detection for simulator targets */
- if (!msm->charger.skip_chg_detect) {
- msm->charger.start_detection = dwc3_start_chg_det;
- ret = dwc3_set_charger(msm->otg_xceiv->otg,
- &msm->charger);
- if (ret || !msm->charger.notify_detection_complete) {
+ if (!mdwc->charger.skip_chg_detect) {
+ mdwc->charger.start_detection = dwc3_start_chg_det;
+ ret = dwc3_set_charger(mdwc->otg_xceiv->otg,
+ &mdwc->charger);
+ if (ret || !mdwc->charger.notify_detection_complete) {
dev_err(&pdev->dev,
"failed to register charger: %d\n",
ret);
@@ -2911,129 +2926,130 @@
}
}
- if (msm->ext_xceiv.otg_capability)
- msm->ext_xceiv.ext_block_reset = dwc3_msm_block_reset;
- ret = dwc3_set_ext_xceiv(msm->otg_xceiv->otg, &msm->ext_xceiv);
- if (ret || !msm->ext_xceiv.notify_ext_events) {
+ if (mdwc->ext_xceiv.otg_capability)
+ mdwc->ext_xceiv.ext_block_reset = dwc3_msm_block_reset;
+ ret = dwc3_set_ext_xceiv(mdwc->otg_xceiv->otg,
+ &mdwc->ext_xceiv);
+ if (ret || !mdwc->ext_xceiv.notify_ext_events) {
dev_err(&pdev->dev, "failed to register xceiver: %d\n",
ret);
goto put_xcvr;
}
} else {
dev_dbg(&pdev->dev, "No OTG, DWC3 running in host only mode\n");
- msm->host_mode = 1;
- msm->vbus_otg = devm_regulator_get(&pdev->dev, "vbus_dwc3");
- if (IS_ERR(msm->vbus_otg)) {
+ mdwc->host_mode = 1;
+ mdwc->vbus_otg = devm_regulator_get(&pdev->dev, "vbus_dwc3");
+ if (IS_ERR(mdwc->vbus_otg)) {
dev_dbg(&pdev->dev, "Failed to get vbus regulator\n");
- msm->vbus_otg = 0;
+ mdwc->vbus_otg = 0;
} else {
- ret = regulator_enable(msm->vbus_otg);
+ ret = regulator_enable(mdwc->vbus_otg);
if (ret) {
- msm->vbus_otg = 0;
+ mdwc->vbus_otg = 0;
dev_err(&pdev->dev, "Failed to enable vbus_otg\n");
}
}
- msm->otg_xceiv = NULL;
+ mdwc->otg_xceiv = NULL;
}
- if (msm->ext_xceiv.otg_capability && msm->charger.start_detection) {
- ret = dwc3_msm_setup_cdev(msm);
+ if (mdwc->ext_xceiv.otg_capability && mdwc->charger.start_detection) {
+ ret = dwc3_msm_setup_cdev(mdwc);
if (ret)
dev_err(&pdev->dev, "Fail to setup dwc3 setup cdev\n");
}
- wake_lock_init(&msm->wlock, WAKE_LOCK_SUSPEND, "msm_dwc3");
- wake_lock(&msm->wlock);
- dwc3_debugfs_init(msm);
+ device_init_wakeup(mdwc->dev, 1);
+ pm_stay_awake(mdwc->dev);
+ dwc3_debugfs_init(mdwc);
return 0;
put_xcvr:
- usb_put_transceiver(msm->otg_xceiv);
+ usb_put_transceiver(mdwc->otg_xceiv);
put_psupply:
- if (msm->usb_psy.dev)
- power_supply_unregister(&msm->usb_psy);
+ if (mdwc->usb_psy.dev)
+ power_supply_unregister(&mdwc->usb_psy);
disable_hs_ldo:
- dwc3_hsusb_ldo_enable(0);
+ dwc3_hsusb_ldo_enable(mdwc, 0);
free_hs_ldo_init:
- dwc3_hsusb_ldo_init(0);
+ dwc3_hsusb_ldo_init(mdwc, 0);
disable_hs_vddcx:
- regulator_disable(context->hsusb_vddcx);
+ regulator_disable(mdwc->hsusb_vddcx);
unconfig_hs_vddcx:
- dwc3_hsusb_config_vddcx(0);
+ dwc3_hsusb_config_vddcx(mdwc, 0);
disable_ss_ldo:
- dwc3_ssusb_ldo_enable(0);
+ dwc3_ssusb_ldo_enable(mdwc, 0);
free_ss_ldo_init:
- dwc3_ssusb_ldo_init(0);
+ dwc3_ssusb_ldo_init(mdwc, 0);
disable_ss_vddcx:
- regulator_disable(context->ssusb_vddcx);
+ regulator_disable(mdwc->ssusb_vddcx);
unconfig_ss_vddcx:
- dwc3_ssusb_config_vddcx(0);
+ dwc3_ssusb_config_vddcx(mdwc, 0);
disable_ref_clk:
- clk_disable_unprepare(msm->ref_clk);
+ clk_disable_unprepare(mdwc->ref_clk);
disable_utmi_clk:
- clk_disable_unprepare(msm->utmi_clk);
+ clk_disable_unprepare(mdwc->utmi_clk);
disable_sleep_a_clk:
- clk_disable_unprepare(msm->hsphy_sleep_clk);
+ clk_disable_unprepare(mdwc->hsphy_sleep_clk);
disable_sleep_clk:
- clk_disable_unprepare(msm->sleep_clk);
+ clk_disable_unprepare(mdwc->sleep_clk);
disable_iface_clk:
- clk_disable_unprepare(msm->iface_clk);
+ clk_disable_unprepare(mdwc->iface_clk);
disable_core_clk:
- clk_disable_unprepare(msm->core_clk);
+ clk_disable_unprepare(mdwc->core_clk);
disable_xo:
- clk_disable_unprepare(msm->xo_clk);
+ clk_disable_unprepare(mdwc->xo_clk);
put_xo:
- clk_put(msm->xo_clk);
+ clk_put(mdwc->xo_clk);
disable_dwc3_gdsc:
- dwc3_msm_config_gdsc(msm, 0);
+ dwc3_msm_config_gdsc(mdwc, 0);
return ret;
}
static int __devexit dwc3_msm_remove(struct platform_device *pdev)
{
- struct dwc3_msm *msm = platform_get_drvdata(pdev);
+ struct dwc3_msm *mdwc = platform_get_drvdata(pdev);
- if (!msm->ext_chg_device) {
- device_destroy(msm->ext_chg_class, msm->ext_chg_dev);
- cdev_del(&msm->ext_chg_cdev);
- class_destroy(msm->ext_chg_class);
- unregister_chrdev_region(msm->ext_chg_dev, 1);
+ if (!mdwc->ext_chg_device) {
+ device_destroy(mdwc->ext_chg_class, mdwc->ext_chg_dev);
+ cdev_del(&mdwc->ext_chg_cdev);
+ class_destroy(mdwc->ext_chg_class);
+ unregister_chrdev_region(mdwc->ext_chg_dev, 1);
}
- if (msm->id_adc_detect)
+ if (mdwc->id_adc_detect)
qpnp_adc_tm_usbid_end();
if (dwc3_debugfs_root)
debugfs_remove_recursive(dwc3_debugfs_root);
- if (msm->otg_xceiv) {
- dwc3_start_chg_det(&msm->charger, false);
- usb_put_transceiver(msm->otg_xceiv);
+ if (mdwc->otg_xceiv) {
+ dwc3_start_chg_det(&mdwc->charger, false);
+ usb_put_transceiver(mdwc->otg_xceiv);
}
- if (msm->usb_psy.dev)
- power_supply_unregister(&msm->usb_psy);
- if (msm->vbus_otg)
- regulator_disable(msm->vbus_otg);
+ if (mdwc->usb_psy.dev)
+ power_supply_unregister(&mdwc->usb_psy);
+ if (mdwc->vbus_otg)
+ regulator_disable(mdwc->vbus_otg);
- pm_runtime_disable(msm->dev);
- wake_lock_destroy(&msm->wlock);
+ pm_runtime_disable(mdwc->dev);
+ device_init_wakeup(mdwc->dev, 0);
- dwc3_hsusb_ldo_enable(0);
- dwc3_hsusb_ldo_init(0);
- regulator_disable(msm->hsusb_vddcx);
- dwc3_hsusb_config_vddcx(0);
- dwc3_ssusb_ldo_enable(0);
- dwc3_ssusb_ldo_init(0);
- regulator_disable(msm->ssusb_vddcx);
- dwc3_ssusb_config_vddcx(0);
- clk_disable_unprepare(msm->core_clk);
- clk_disable_unprepare(msm->iface_clk);
- clk_disable_unprepare(msm->sleep_clk);
- clk_disable_unprepare(msm->hsphy_sleep_clk);
- clk_disable_unprepare(msm->ref_clk);
- clk_disable_unprepare(msm->xo_clk);
- clk_put(msm->xo_clk);
+ dwc3_hsusb_ldo_enable(mdwc, 0);
+ dwc3_hsusb_ldo_init(mdwc, 0);
+ regulator_disable(mdwc->hsusb_vddcx);
+ dwc3_hsusb_config_vddcx(mdwc, 0);
+ dwc3_ssusb_ldo_enable(mdwc, 0);
+ dwc3_ssusb_ldo_init(mdwc, 0);
+ regulator_disable(mdwc->ssusb_vddcx);
+ dwc3_ssusb_config_vddcx(mdwc, 0);
+ clk_disable_unprepare(mdwc->core_clk);
+ clk_disable_unprepare(mdwc->iface_clk);
+ clk_disable_unprepare(mdwc->sleep_clk);
+ clk_disable_unprepare(mdwc->hsphy_sleep_clk);
+ clk_disable_unprepare(mdwc->ref_clk);
+ clk_disable_unprepare(mdwc->xo_clk);
+ clk_put(mdwc->xo_clk);
- dwc3_msm_config_gdsc(msm, 0);
+ dwc3_msm_config_gdsc(mdwc, 0);
return 0;
}
diff --git a/drivers/usb/dwc3/dwc3_otg.c b/drivers/usb/dwc3/dwc3_otg.c
index 1bc7757..a7bea63 100644
--- a/drivers/usb/dwc3/dwc3_otg.c
+++ b/drivers/usb/dwc3/dwc3_otg.c
@@ -218,7 +218,7 @@
*/
if (ext_xceiv && ext_xceiv->otg_capability &&
ext_xceiv->ext_block_reset)
- ext_xceiv->ext_block_reset(true);
+ ext_xceiv->ext_block_reset(ext_xceiv, true);
dwc3_otg_set_peripheral_regs(dotg);
@@ -285,7 +285,7 @@
* DBM reset is required, hence perform only DBM reset here */
if (ext_xceiv && ext_xceiv->otg_capability &&
ext_xceiv->ext_block_reset)
- ext_xceiv->ext_block_reset(false);
+ ext_xceiv->ext_block_reset(ext_xceiv, false);
dwc3_otg_set_peripheral_regs(dotg);
usb_gadget_vbus_connect(otg->gadget);
diff --git a/drivers/usb/dwc3/dwc3_otg.h b/drivers/usb/dwc3/dwc3_otg.h
index 28573a1..7adf874 100644
--- a/drivers/usb/dwc3/dwc3_otg.h
+++ b/drivers/usb/dwc3/dwc3_otg.h
@@ -114,7 +114,8 @@
void (*notify_ext_events)(struct usb_otg *otg,
enum dwc3_ext_events ext_event);
/* for block reset USB core */
- void (*ext_block_reset)(bool core_reset);
+ void (*ext_block_reset)(struct dwc3_ext_xceiv *ext_xceiv,
+ bool core_reset);
};
/* for external transceiver driver */
diff --git a/drivers/usb/gadget/f_qdss.c b/drivers/usb/gadget/f_qdss.c
index cece500..f90967f 100644
--- a/drivers/usb/gadget/f_qdss.c
+++ b/drivers/usb/gadget/f_qdss.c
@@ -790,6 +790,7 @@
void usb_qdss_close(struct usb_qdss_ch *ch)
{
struct f_qdss *qdss = ch->priv_usb;
+ struct usb_gadget *gadget = qdss->cdev->gadget;
unsigned long flags;
pr_debug("usb_qdss_close\n");
@@ -801,7 +802,7 @@
ch->app_conn = 0;
spin_unlock_irqrestore(&d_lock, flags);
- msm_dwc3_restart_usb_session();
+ msm_dwc3_restart_usb_session(gadget);
}
EXPORT_SYMBOL(usb_qdss_close);
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c
index 04cd78c..7edf3d2 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.c
+++ b/drivers/video/msm/mdss/mdp3_ctrl.c
@@ -871,7 +871,7 @@
ret = session->dma->get_histo(session->dma);
if (ret) {
- pr_err("mdp3_histogram_collect error = %d\n", ret);
+ pr_debug("mdp3_histogram_collect error = %d\n", ret);
return ret;
}
@@ -920,11 +920,53 @@
return ret;
}
+static int mdp3_csc_config(struct mdp3_session_data *session,
+ struct mdp_csc_cfg_data *data)
+{
+ struct mdp3_dma_color_correct_config config;
+ struct mdp3_dma_ccs ccs;
+ int ret = -EINVAL;
+
+ if (!data->csc_data.csc_mv || !data->csc_data.csc_pre_bv ||
+ !data->csc_data.csc_post_bv || !data->csc_data.csc_pre_lv ||
+ !data->csc_data.csc_post_lv) {
+ pr_err("%s : Invalid csc vectors", __func__);
+ return -EINVAL;
+ }
+
+ session->cc_vect_sel = (session->cc_vect_sel + 1) % 2;
+
+ config.ccs_enable = 1;
+ config.ccs_sel = session->cc_vect_sel;
+ config.pre_limit_sel = session->cc_vect_sel;
+ config.post_limit_sel = session->cc_vect_sel;
+ config.pre_bias_sel = session->cc_vect_sel;
+ config.post_bias_sel = session->cc_vect_sel;
+ config.ccs_dirty = true;
+
+ ccs.mv = data->csc_data.csc_mv;
+ ccs.pre_bv = data->csc_data.csc_pre_bv;
+ ccs.post_bv = data->csc_data.csc_post_bv;
+ ccs.pre_lv = data->csc_data.csc_pre_lv;
+ ccs.post_lv = data->csc_data.csc_post_lv;
+
+ mutex_lock(&session->lock);
+ ret = session->dma->config_ccs(session->dma, &config, &ccs);
+ mutex_unlock(&session->lock);
+ return ret;
+}
+
static int mdp3_pp_ioctl(struct msm_fb_data_type *mfd,
void __user *argp)
{
int ret = -EINVAL;
struct msmfb_mdp_pp mdp_pp;
+ struct mdp3_session_data *mdp3_session;
+
+ if (!mfd || !mfd->mdp.private1)
+ return -EINVAL;
+
+ mdp3_session = mfd->mdp.private1;
ret = copy_from_user(&mdp_pp, argp, sizeof(mdp_pp));
if (ret)
@@ -935,6 +977,11 @@
ret = mdp3_bl_scale_config(mfd, (struct mdp_bl_scale_data *)
&mdp_pp.data.bl_scale_data);
break;
+ case mdp_op_csc_cfg:
+ ret = mdp3_csc_config(mdp3_session,
+ &(mdp_pp.data.csc_cfg_data));
+ break;
+
default:
pr_err("Unsupported request to MDP_PP IOCTL.\n");
ret = -EINVAL;
@@ -1022,6 +1069,7 @@
lut_config.lut_enable = 7;
lut_config.lut_sel = mdp3_session->lut_sel;
lut_config.lut_position = 0;
+ lut_config.lut_dirty = true;
lut.color0_lut = r;
lut.color1_lut = g;
lut.color2_lut = b;
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.h b/drivers/video/msm/mdss/mdp3_ctrl.h
index 0bbc2ac..9ea1c91 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.h
+++ b/drivers/video/msm/mdss/mdp3_ctrl.h
@@ -50,6 +50,7 @@
int histo_status;
struct mutex histo_lock;
int lut_sel;
+ int cc_vect_sel;
};
int mdp3_ctrl_init(struct msm_fb_data_type *mfd);
diff --git a/drivers/video/msm/mdss/mdp3_dma.c b/drivers/video/msm/mdss/mdp3_dma.c
index 3b65405..2e9c787 100644
--- a/drivers/video/msm/mdss/mdp3_dma.c
+++ b/drivers/video/msm/mdss/mdp3_dma.c
@@ -219,6 +219,25 @@
}
}
+static void mdp3_dma_clk_auto_gating(struct mdp3_dma *dma, int enable)
+{
+ u32 cgc;
+ int clock_bit = 10;
+
+ clock_bit += dma->dma_sel;
+
+ if (enable) {
+ cgc = MDP3_REG_READ(MDP3_REG_CGC_EN);
+ cgc |= BIT(clock_bit);
+ MDP3_REG_WRITE(MDP3_REG_CGC_EN, cgc);
+
+ } else {
+ cgc = MDP3_REG_READ(MDP3_REG_CGC_EN);
+ cgc &= ~BIT(clock_bit);
+ MDP3_REG_WRITE(MDP3_REG_CGC_EN, cgc);
+ }
+}
+
static int mdp3_dma_sync_config(struct mdp3_dma *dma,
struct mdp3_dma_source *source_config)
{
@@ -347,11 +366,109 @@
return 0;
}
+static void mdp3_ccs_update(struct mdp3_dma *dma)
+{
+ u32 cc_config;
+ int updated = 0;
+
+ cc_config = MDP3_REG_READ(MDP3_REG_DMA_P_COLOR_CORRECT_CONFIG);
+
+ if (dma->ccs_config.ccs_dirty) {
+ cc_config &= DMA_CCS_CONFIG_MASK;
+ if (dma->ccs_config.ccs_enable)
+ cc_config |= BIT(3);
+ else
+ cc_config &= ~BIT(3);
+ cc_config |= dma->ccs_config.ccs_sel << 5;
+ cc_config |= dma->ccs_config.pre_bias_sel << 6;
+ cc_config |= dma->ccs_config.post_bias_sel << 7;
+ cc_config |= dma->ccs_config.pre_limit_sel << 8;
+ cc_config |= dma->ccs_config.post_limit_sel << 9;
+ dma->ccs_config.ccs_dirty = false;
+ updated = 1;
+ }
+
+ if (dma->lut_config.lut_dirty) {
+ cc_config &= DMA_LUT_CONFIG_MASK;
+ cc_config |= dma->lut_config.lut_enable;
+ cc_config |= dma->lut_config.lut_position << 4;
+ cc_config |= dma->lut_config.lut_sel << 10;
+ dma->lut_config.lut_dirty = false;
+ updated = 1;
+ }
+ if (updated) {
+ MDP3_REG_WRITE(MDP3_REG_DMA_P_COLOR_CORRECT_CONFIG, cc_config);
+
+ /* Make sure ccs configuration update is done before continuing
+ with the DMA transfer */
+ wmb();
+ }
+}
+
+static int mdp3_dmap_ccs_config(struct mdp3_dma *dma,
+ struct mdp3_dma_color_correct_config *config,
+ struct mdp3_dma_ccs *ccs)
+{
+ int i;
+ u32 addr;
+
+ if (!ccs)
+ return -EINVAL;
+
+ if (config->ccs_enable) {
+ addr = MDP3_REG_DMA_P_CSC_MV1;
+ if (config->ccs_sel)
+ addr = MDP3_REG_DMA_P_CSC_MV2;
+ for (i = 0; i < 9; i++) {
+ MDP3_REG_WRITE(addr, ccs->mv[i]);
+ addr += 4;
+ }
+
+ addr = MDP3_REG_DMA_P_CSC_PRE_BV1;
+ if (config->pre_bias_sel)
+ addr = MDP3_REG_DMA_P_CSC_PRE_BV2;
+ for (i = 0; i < 3; i++) {
+ MDP3_REG_WRITE(addr, ccs->pre_bv[i]);
+ addr += 4;
+ }
+
+ addr = MDP3_REG_DMA_P_CSC_POST_BV1;
+ if (config->post_bias_sel)
+ addr = MDP3_REG_DMA_P_CSC_POST_BV2;
+ for (i = 0; i < 3; i++) {
+ MDP3_REG_WRITE(addr, ccs->post_bv[i]);
+ addr += 4;
+ }
+
+ addr = MDP3_REG_DMA_P_CSC_PRE_LV1;
+ if (config->pre_limit_sel)
+ addr = MDP3_REG_DMA_P_CSC_PRE_LV2;
+ for (i = 0; i < 6; i++) {
+ MDP3_REG_WRITE(addr, ccs->pre_lv[i]);
+ addr += 4;
+ }
+
+ addr = MDP3_REG_DMA_P_CSC_POST_LV1;
+ if (config->post_limit_sel)
+ addr = MDP3_REG_DMA_P_CSC_POST_LV2;
+ for (i = 0; i < 6; i++) {
+ MDP3_REG_WRITE(addr, ccs->post_lv[i]);
+ addr += 4;
+ }
+ }
+ dma->ccs_config = *config;
+
+ if (dma->output_config.out_sel != MDP3_DMA_OUTPUT_SEL_DSI_CMD)
+ mdp3_ccs_update(dma);
+
+ return 0;
+}
+
static int mdp3_dmap_lut_config(struct mdp3_dma *dma,
struct mdp3_dma_lut_config *config,
struct mdp3_dma_lut *lut)
{
- u32 cc_config, addr, color;
+ u32 addr, color;
int i;
if (config->lut_enable && lut) {
@@ -368,119 +485,11 @@
}
}
- cc_config = MDP3_REG_READ(MDP3_REG_DMA_P_COLOR_CORRECT_CONFIG);
- cc_config &= DMA_LUT_CONFIG_MASK;
- cc_config |= config->lut_enable;
- cc_config |= config->lut_position << 4;
- cc_config |= config->lut_sel << 10;
- MDP3_REG_WRITE(MDP3_REG_DMA_P_COLOR_CORRECT_CONFIG, cc_config);
- wmb();
-
dma->lut_config = *config;
- return 0;
-}
-static int mdp3_dmap_ccs_config(struct mdp3_dma *dma,
- struct mdp3_dma_color_correct_config *config,
- struct mdp3_dma_ccs *ccs)
-{
- int i;
- u32 cc_config, addr;
+ if (dma->output_config.out_sel != MDP3_DMA_OUTPUT_SEL_DSI_CMD)
+ mdp3_ccs_update(dma);
- cc_config = MDP3_REG_READ(MDP3_REG_DMA_P_COLOR_CORRECT_CONFIG);
- cc_config &= DMA_CCS_CONFIG_MASK;
- cc_config |= BIT(3);
- cc_config |= config->ccs_sel << 5;
- cc_config |= config->pre_bias_sel << 6;
- cc_config |= config->post_bias_sel << 7;
- cc_config |= config->pre_limit_sel << 8;
- cc_config |= config->post_limit_sel << 9;
-
- MDP3_REG_WRITE(MDP3_REG_DMA_P_COLOR_CORRECT_CONFIG, cc_config);
-
- if (config->ccs_enable && ccs) {
- if (ccs->mv1) {
- addr = MDP3_REG_DMA_P_CSC_MV1;
- for (i = 0; i < 9; i++) {
- MDP3_REG_WRITE(addr, ccs->mv1[i]);
- addr += 4;
- }
- }
-
- if (ccs->mv2) {
- addr = MDP3_REG_DMA_P_CSC_MV2;
- for (i = 0; i < 9; i++) {
- MDP3_REG_WRITE(addr, ccs->mv2[i]);
- addr += 4;
- }
- }
-
- if (ccs->pre_bv1) {
- addr = MDP3_REG_DMA_P_CSC_PRE_BV1;
- for (i = 0; i < 3; i++) {
- MDP3_REG_WRITE(addr, ccs->pre_bv1[i]);
- addr += 4;
- }
- }
-
- if (ccs->pre_bv2) {
- addr = MDP3_REG_DMA_P_CSC_PRE_BV2;
- for (i = 0; i < 3; i++) {
- MDP3_REG_WRITE(addr, ccs->pre_bv2[i]);
- addr += 4;
- }
- }
-
- if (ccs->post_bv1) {
- addr = MDP3_REG_DMA_P_CSC_POST_BV1;
- for (i = 0; i < 3; i++) {
- MDP3_REG_WRITE(addr, ccs->post_bv1[i]);
- addr += 4;
- }
- }
-
- if (ccs->post_bv2) {
- addr = MDP3_REG_DMA_P_CSC_POST_BV2;
- for (i = 0; i < 3; i++) {
- MDP3_REG_WRITE(addr, ccs->post_bv2[i]);
- addr += 4;
- }
- }
-
- if (ccs->pre_lv1) {
- addr = MDP3_REG_DMA_P_CSC_PRE_LV1;
- for (i = 0; i < 6; i++) {
- MDP3_REG_WRITE(addr, ccs->pre_lv1[i]);
- addr += 4;
- }
- }
-
- if (ccs->pre_lv2) {
- addr = MDP3_REG_DMA_P_CSC_PRE_LV2;
- for (i = 0; i < 6; i++) {
- MDP3_REG_WRITE(addr, ccs->pre_lv2[i]);
- addr += 4;
- }
- }
-
- if (ccs->post_lv1) {
- addr = MDP3_REG_DMA_P_CSC_POST_LV1;
- for (i = 0; i < 6; i++) {
- MDP3_REG_WRITE(addr, ccs->post_lv1[i]);
- addr += 4;
- }
- }
-
- if (ccs->post_lv2) {
- addr = MDP3_REG_DMA_P_CSC_POST_LV2;
- for (i = 0; i < 6; i++) {
- MDP3_REG_WRITE(addr, ccs->post_lv2[i]);
- addr += 4;
- }
- }
- }
-
- dma->ccs_config = *config;
return 0;
}
@@ -528,8 +537,10 @@
spin_lock_irqsave(&dma->dma_lock, flag);
MDP3_REG_WRITE(MDP3_REG_DMA_P_IBUF_ADDR, (u32)buf);
dma->source_config.buf = buf;
- if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD)
+ if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
+ mdp3_ccs_update(dma);
MDP3_REG_WRITE(MDP3_REG_DMA_P_START, 1);
+ }
if (!intf->active) {
pr_debug("mdp3_dmap_update start interface\n");
@@ -610,7 +621,7 @@
ret = wait_for_completion_killable_timeout(&dma->histo_comp, timeout);
if (ret == 0) {
- pr_err("mdp3_dmap_histo_get time out\n");
+ pr_debug("mdp3_dmap_histo_get time out\n");
ret = -ETIMEDOUT;
} else if (ret < 0) {
pr_err("mdp3_dmap_histo_get interrupted\n");
@@ -682,7 +693,6 @@
{
unsigned long flag;
int ret;
- u32 cgc;
if (dma->histo_state == MDP3_DMA_HISTO_STATE_START)
return -EINVAL;
@@ -690,9 +700,8 @@
spin_lock_irqsave(&dma->histo_lock, flag);
init_completion(&dma->histo_comp);
- cgc = MDP3_REG_READ(MDP3_REG_CGC_EN);
- cgc &= ~BIT(10);
- MDP3_REG_WRITE(MDP3_REG_CGC_EN, cgc);
+
+ mdp3_dma_clk_auto_gating(dma, 0);
MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_INTR_ENABLE, BIT(0)|BIT(1));
MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_RESET_SEQ_START, 1);
@@ -714,8 +723,7 @@
ret = 0;
}
mdp3_dma_callback_disable(dma, MDP3_DMA_CALLBACK_TYPE_HIST_RESET_DONE);
- cgc |= BIT(10);
- MDP3_REG_WRITE(MDP3_REG_CGC_EN, cgc);
+ mdp3_dma_clk_auto_gating(dma, 1);
return ret;
}
@@ -732,6 +740,7 @@
MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_INTR_ENABLE, 0);
wmb();
dma->histo_state = MDP3_DMA_HISTO_STATE_IDLE;
+ complete(&dma->histo_comp);
spin_unlock_irqrestore(&dma->histo_lock, flag);
diff --git a/drivers/video/msm/mdss/mdp3_dma.h b/drivers/video/msm/mdss/mdp3_dma.h
index 518bd58..c652818 100644
--- a/drivers/video/msm/mdss/mdp3_dma.h
+++ b/drivers/video/msm/mdss/mdp3_dma.h
@@ -176,16 +176,11 @@
};
struct mdp3_dma_ccs {
- u32 *mv1; /*set1 matrix vector, 3x3 */
- u32 *mv2;
- u32 *pre_bv1; /*pre-bias vector for set1, 1x3*/
- u32 *pre_bv2;
- u32 *post_bv1; /*post-bias vecotr for set1, */
- u32 *post_bv2;
- u32 *pre_lv1; /*pre-limit vector for set 1, 1x6*/
- u32 *pre_lv2;
- u32 *post_lv1;
- u32 *post_lv2;
+ u32 *mv; /*set1 matrix vector, 3x3 */
+ u32 *pre_bv; /*pre-bias vector for set1, 1x3*/
+ u32 *post_bv; /*post-bias vecotr for set1, */
+ u32 *pre_lv; /*pre-limit vector for set 1, 1x6*/
+ u32 *post_lv;
};
struct mdp3_dma_lut {
@@ -198,6 +193,7 @@
int lut_enable;
u32 lut_sel;
u32 lut_position;
+ bool lut_dirty;
};
struct mdp3_dma_color_correct_config {
@@ -207,6 +203,7 @@
u32 post_bias_sel;
u32 pre_bias_sel;
u32 ccs_sel;
+ bool ccs_dirty;
};
struct mdp3_dma_histogram_config {
diff --git a/drivers/video/msm/mdss/mhl_sii8334.c b/drivers/video/msm/mdss/mhl_sii8334.c
index 3f03725..82b56e3 100644
--- a/drivers/video/msm/mdss/mhl_sii8334.c
+++ b/drivers/video/msm/mdss/mhl_sii8334.c
@@ -373,7 +373,7 @@
/* USB_HANDSHAKING FUNCTIONS */
static int mhl_sii_device_discovery(void *data, int id,
- void (*usb_notify_cb)(int online))
+ void (*usb_notify_cb)(void *, int), void *ctx)
{
int rc;
struct mhl_tx_ctrl *mhl_ctrl = data;
@@ -398,8 +398,10 @@
return -EINVAL;
}
- if (!mhl_ctrl->notify_usb_online)
+ if (!mhl_ctrl->notify_usb_online) {
mhl_ctrl->notify_usb_online = usb_notify_cb;
+ mhl_ctrl->notify_ctx = ctx;
+ }
if (!mhl_ctrl->disc_enabled) {
spin_lock_irqsave(&mhl_ctrl->lock, flags);
@@ -904,7 +906,7 @@
mhl_ctrl->mhl_mode = 1;
power_supply_changed(&mhl_ctrl->mhl_psy);
if (mhl_ctrl->notify_usb_online)
- mhl_ctrl->notify_usb_online(1);
+ mhl_ctrl->notify_usb_online(mhl_ctrl->notify_ctx, 1);
} else {
pr_debug("%s: non-mhl sink\n", __func__);
mhl_ctrl->mhl_mode = 0;
@@ -1004,7 +1006,7 @@
mhl_msm_disconnection(mhl_ctrl);
power_supply_changed(&mhl_ctrl->mhl_psy);
if (mhl_ctrl->notify_usb_online)
- mhl_ctrl->notify_usb_online(0);
+ mhl_ctrl->notify_usb_online(mhl_ctrl->notify_ctx, 0);
return 0;
}
@@ -1019,7 +1021,7 @@
mhl_msm_disconnection(mhl_ctrl);
power_supply_changed(&mhl_ctrl->mhl_psy);
if (mhl_ctrl->notify_usb_online)
- mhl_ctrl->notify_usb_online(0);
+ mhl_ctrl->notify_usb_online(mhl_ctrl->notify_ctx, 0);
return 0;
}
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index cfc690e..5b69884 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -39,8 +39,8 @@
enum coresight_clk_rate {
CORESIGHT_CLK_RATE_OFF,
- CORESIGHT_CLK_RATE_TRACE,
- CORESIGHT_CLK_RATE_HSTRACE,
+ CORESIGHT_CLK_RATE_TRACE = 1000,
+ CORESIGHT_CLK_RATE_HSTRACE = 2000,
};
enum coresight_dev_type {
diff --git a/include/linux/i2c/atmel_mxt_ts.h b/include/linux/i2c/atmel_mxt_ts.h
index b903dfb..e9fbf90 100644
--- a/include/linux/i2c/atmel_mxt_ts.h
+++ b/include/linux/i2c/atmel_mxt_ts.h
@@ -77,6 +77,7 @@
int *key_codes;
bool need_calibration;
bool no_force_update;
+ bool no_lpm_support;
u8 bl_addr;
u8(*read_chg) (void);
diff --git a/include/linux/mhl_8334.h b/include/linux/mhl_8334.h
index 7297ff3..560f75b 100644
--- a/include/linux/mhl_8334.h
+++ b/include/linux/mhl_8334.h
@@ -137,7 +137,8 @@
uint8_t chip_rev_id;
int mhl_mode;
struct completion rgnd_done;
- void (*notify_usb_online)(int online);
+ void (*notify_usb_online)(void *ctx, int online);
+ void *notify_ctx;
struct usb_ext_notification *mhl_info;
bool disc_enabled;
struct power_supply mhl_psy;
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index f48021b..f04d2bf 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -506,7 +506,7 @@
/**
* struct usb_ext_notification: event notification structure
* @notify: pointer to client function to call when ID event is detected.
- * The last parameter is provided by driver to be called back when
+ * The function parameter is provided by driver to be called back when
* external client indicates it is done using the USB. This function
* should return 0 if handled successfully, otherise an error code.
* @ctxt: client-specific context pointer
@@ -520,7 +520,7 @@
* called with the online parameter set to false.
*/
struct usb_ext_notification {
- int (*notify)(void *, int, void (*)(int online));
+ int (*notify)(void *, int, void (*)(void *, int online), void *);
void *ctxt;
};
#ifdef CONFIG_USB_BAM
@@ -550,7 +550,7 @@
int msm_data_fifo_config(struct usb_ep *ep, u32 addr, u32 size,
u8 dst_pipe_idx);
-void msm_dwc3_restart_usb_session(void);
+void msm_dwc3_restart_usb_session(struct usb_gadget *gadget);
int msm_register_usb_ext_notification(struct usb_ext_notification *info);
#else
@@ -570,7 +570,7 @@
return -ENODEV;
}
-static inline void msm_dwc3_restart_usb_session(void)
+static inline void msm_dwc3_restart_usb_session(struct usb_gadget *gadget)
{
return;
}
diff --git a/include/media/msm_cam_sensor.h b/include/media/msm_cam_sensor.h
index 6358f8a..2805401 100644
--- a/include/media/msm_cam_sensor.h
+++ b/include/media/msm_cam_sensor.h
@@ -46,6 +46,8 @@
#define MAX_EEPROM_NAME 32
+#define MAX_AF_ITERATIONS 3
+
enum msm_camera_i2c_reg_addr_type {
MSM_CAMERA_I2C_BYTE_ADDR = 1,
MSM_CAMERA_I2C_WORD_ADDR,
@@ -78,6 +80,11 @@
enum msm_sensor_power_seq_gpio_t {
SENSOR_GPIO_RESET,
SENSOR_GPIO_STANDBY,
+ SENSOR_GPIO_AF_PWDM,
+ SENSOR_GPIO_VIO,
+ SENSOR_GPIO_VANA,
+ SENSOR_GPIO_VDIG,
+ SENSOR_GPIO_VAF,
SENSOR_GPIO_MAX,
};
@@ -133,6 +140,11 @@
REG_GPIO,
};
+enum sensor_af_t {
+ SENSOR_AF_FOCUSSED,
+ SENSOR_AF_NOT_FOCUSSED,
+};
+
struct msm_sensor_power_setting {
enum msm_sensor_power_seq_type_t seq_type;
uint16_t seq_val;
@@ -346,6 +358,11 @@
CFG_SET_RESOLUTION,
CFG_SET_STOP_STREAM,
CFG_SET_START_STREAM,
+ CFG_SET_SATURATION,
+ CFG_SET_CONTRAST,
+ CFG_SET_SHARPNESS,
+ CFG_SET_AUTOFOCUS,
+ CFG_CANCEL_AUTOFOCUS,
};
enum msm_actuator_cfg_type_t {
@@ -509,6 +526,9 @@
#define VIDIOC_MSM_EEPROM_CFG \
_IOWR('V', BASE_VIDIOC_PRIVATE + 8, struct msm_eeprom_cfg_data)
+#define VIDIOC_MSM_SENSOR_GET_AF_STATUS \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 9, uint32_t)
+
#define MSM_V4L2_PIX_FMT_META v4l2_fourcc('M', 'E', 'T', 'A') /* META */
#endif /* __LINUX_MSM_CAM_SENSOR_H */
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.c b/sound/soc/codecs/wcd9xxx-mbhc.c
index e34dec1..d0c00a7 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.c
+++ b/sound/soc/codecs/wcd9xxx-mbhc.c
@@ -220,11 +220,15 @@
pr_debug("%s: leave\n", __func__);
}
-/* called under codec_resource_lock acquisition */
-static void __wcd9xxx_switch_micbias(struct wcd9xxx_mbhc *mbhc,
+/*
+ * called under codec_resource_lock acquisition
+ * return old status
+ */
+static bool __wcd9xxx_switch_micbias(struct wcd9xxx_mbhc *mbhc,
int vddio_switch, bool restartpolling,
bool checkpolling)
{
+ bool ret;
int cfilt_k_val;
bool override;
struct snd_soc_codec *codec;
@@ -234,9 +238,11 @@
if (mbhc->micbias_enable) {
pr_debug("%s: micbias is already on\n", __func__);
- return;
+ ret = mbhc->mbhc_micbias_switched;
+ return ret;
}
+ ret = mbhc->mbhc_micbias_switched;
if (vddio_switch && !mbhc->mbhc_micbias_switched &&
(!checkpolling || mbhc->polling_active)) {
if (restartpolling)
@@ -343,11 +349,13 @@
mbhc->mbhc_micbias_switched = false;
pr_debug("%s: VDDIO switch disabled\n", __func__);
}
+
+ return ret;
}
static void wcd9xxx_switch_micbias(struct wcd9xxx_mbhc *mbhc, int vddio_switch)
{
- return __wcd9xxx_switch_micbias(mbhc, vddio_switch, true, true);
+ __wcd9xxx_switch_micbias(mbhc, vddio_switch, true, true);
}
static s16 wcd9xxx_get_current_v(struct wcd9xxx_mbhc *mbhc,
@@ -1124,10 +1132,15 @@
/*
* wcd9xxx_find_plug_type : Find out and return the best plug type with given
* list of wcd9xxx_mbhc_detect structure.
+ * param mbhc wcd9xxx_mbhc structure
+ * param dt collected measurements
+ * param size array size of dt
+ * param event_state mbhc->event_state when dt is collected
*/
static enum wcd9xxx_mbhc_plug_type
wcd9xxx_find_plug_type(struct wcd9xxx_mbhc *mbhc,
- struct wcd9xxx_mbhc_detect *dt, const int size)
+ struct wcd9xxx_mbhc_detect *dt, const int size,
+ unsigned long event_state)
{
int i;
int ch;
@@ -1140,6 +1153,8 @@
const s16 hs_max = plug_type->v_hs_max;
const s16 no_mic = plug_type->v_no_mic;
+ pr_debug("%s: event_state 0x%lx\n", __func__, event_state);
+
for (i = 0, d = dt, ch = 0; i < size; i++, d++) {
vdce = wcd9xxx_codec_sta_dce_v(mbhc, true, d->dce);
if (d->vddio)
@@ -1181,7 +1196,10 @@
goto exit;
}
}
- if (ch != size && ch > 0) {
+
+ if (event_state & (1 << MBHC_EVENT_PA_HPHL)) {
+ pr_debug("%s: HPHL PA was ON\n", __func__);
+ } else if (ch != size && ch > 0) {
pr_debug("%s: Invalid, inconsistent HPHL\n", __func__);
type = PLUG_TYPE_INVALID;
goto exit;
@@ -1221,12 +1239,18 @@
maxv))
type = PLUG_TYPE_GND_MIC_SWAP;
}
- if (((type == PLUG_TYPE_HEADSET || type == PLUG_TYPE_HEADPHONE) &&
- ch != size) || (type == PLUG_TYPE_GND_MIC_SWAP && ch)) {
- pr_debug("%s: Invalid, not fully inserted, TYPE %d\n",
- __func__, type);
- type = PLUG_TYPE_INVALID;
+
+ /* if HPHL PA was on, we cannot use hphl status */
+ if (!(event_state & (1UL << MBHC_EVENT_PA_HPHL))) {
+ if (((type == PLUG_TYPE_HEADSET ||
+ type == PLUG_TYPE_HEADPHONE) && ch != size) ||
+ (type == PLUG_TYPE_GND_MIC_SWAP && ch)) {
+ pr_debug("%s: Invalid, not fully inserted, TYPE %d\n",
+ __func__, type);
+ type = PLUG_TYPE_INVALID;
+ }
}
+
if (type == PLUG_TYPE_HEADSET && dvddio) {
if ((dvddio->_vdces > hs_max) ||
(dvddio->_vdces > minv + WCD9XXX_THRESHOLD_MIC_THRESHOLD)) {
@@ -1294,6 +1318,7 @@
wcd9xxx_codec_get_plug_type(struct wcd9xxx_mbhc *mbhc, bool highhph)
{
int i;
+ bool vddioon;
struct wcd9xxx_mbhc_plug_type_cfg *plug_type_ptr;
struct wcd9xxx_mbhc_detect rt[NUM_DCE_PLUG_INS_DETECT];
enum wcd9xxx_mbhc_plug_type type = PLUG_TYPE_INVALID;
@@ -1308,6 +1333,13 @@
/* GND and MIC swap detection requires at least 2 rounds of DCE */
BUG_ON(NUM_DCE_PLUG_INS_DETECT < 2);
+ /*
+ * There are chances vddio switch is on and cfilt voltage is adjusted
+ * to vddio voltage even after plug type removal reported.
+ */
+ vddioon = __wcd9xxx_switch_micbias(mbhc, 0, false, false);
+ pr_debug("%s: vddio switch was %s\n", __func__, vddioon ? "on" : "off");
+
plug_type_ptr =
WCD9XXX_MBHC_CAL_PLUG_TYPE_PTR(mbhc->mbhc_cfg->calibration);
@@ -1350,7 +1382,11 @@
wcd9xxx_codec_hphr_gnd_switch(codec, false);
}
- type = wcd9xxx_find_plug_type(mbhc, rt, ARRAY_SIZE(rt));
+ if (vddioon)
+ __wcd9xxx_switch_micbias(mbhc, 1, false, false);
+
+ type = wcd9xxx_find_plug_type(mbhc, rt, ARRAY_SIZE(rt),
+ mbhc->event_state);
pr_debug("%s: leave\n", __func__);
return type;
@@ -2134,6 +2170,7 @@
unsigned long timeout;
int retry = 0, pt_gnd_mic_swap_cnt = 0;
bool correction = false;
+ bool wrk_complete = true;
pr_debug("%s: enter\n", __func__);
@@ -2159,12 +2196,14 @@
++retry;
rmb();
if (mbhc->hs_detect_work_stop) {
+ wrk_complete = false;
pr_debug("%s: stop requested\n", __func__);
break;
}
msleep(HS_DETECT_PLUG_INERVAL_MS);
if (wcd9xxx_swch_level_remove(mbhc)) {
+ wrk_complete = false;
pr_debug("%s: Switch level is low\n", __func__);
break;
}
@@ -2238,7 +2277,9 @@
if (plug_type == PLUG_TYPE_HIGH_HPH) {
pr_debug("%s: polling is done, still HPH, so enabling MIC trigger\n",
__func__);
+ WCD9XXX_BCL_LOCK(mbhc->resmgr);
wcd9xxx_find_plug_and_report(mbhc, plug_type);
+ WCD9XXX_BCL_UNLOCK(mbhc->resmgr);
}
/* Turn off override */
if (!correction)
@@ -2248,10 +2289,11 @@
if (mbhc->mbhc_cfg->detect_extn_cable) {
WCD9XXX_BCL_LOCK(mbhc->resmgr);
- if (mbhc->current_plug == PLUG_TYPE_HEADPHONE ||
+ if ((mbhc->current_plug == PLUG_TYPE_HEADPHONE &&
+ wrk_complete) ||
mbhc->current_plug == PLUG_TYPE_GND_MIC_SWAP ||
mbhc->current_plug == PLUG_TYPE_INVALID ||
- plug_type == PLUG_TYPE_INVALID) {
+ (plug_type == PLUG_TYPE_INVALID && wrk_complete)) {
/* Enable removal detection */
wcd9xxx_cleanup_hs_polling(mbhc);
wcd9xxx_enable_hs_detect(mbhc, 0, 0, false);
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index 2e5ff35..be62727 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -95,7 +95,6 @@
static int voice_alloc_and_map_oob_mem(struct voice_data *v);
static struct voice_data *voice_get_session_by_idx(int idx);
-static int voice_get_idx_for_session(u32 session_id);
static u16 voice_get_mvm_handle(struct voice_data *v)
{
@@ -240,7 +239,7 @@
return v;
}
-static int voice_get_idx_for_session(u32 session_id)
+int voice_get_idx_for_session(u32 session_id)
{
int idx = 0;
diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h
index 4a3ff2a..42b1800 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.h
+++ b/sound/soc/msm/qdsp6v2/q6voice.h
@@ -1384,4 +1384,6 @@
int voc_start_playback(uint32_t set, uint16_t port_id);
int voc_start_record(uint32_t port_id, uint32_t set);
+int voice_get_idx_for_session(u32 session_id);
+
#endif
diff --git a/sound/soc/msm/qdsp6v2/rtac.c b/sound/soc/msm/qdsp6v2/rtac.c
index 1f2a487..a4983d3 100644
--- a/sound/soc/msm/qdsp6v2/rtac.c
+++ b/sound/soc/msm/qdsp6v2/rtac.c
@@ -24,7 +24,7 @@
#include <sound/q6asm-v2.h>
#include <sound/q6afe-v2.h>
#include <sound/apr_audio-v2.h>
-
+#include <q6voice.h>
#include "audio_acdb.h"
@@ -352,13 +352,13 @@
return;
}
-static int get_voice_index_cvs(u32 cvs_handle)
+static u32 get_voice_session_id_cvs(u32 cvs_handle)
{
u32 i;
for (i = 0; i < rtac_voice_data.num_of_voice_combos; i++) {
if (rtac_voice_data.voice[i].cvs_handle == cvs_handle)
- return i;
+ return voice_session_id[i];
}
pr_err("%s: No voice index for CVS handle %d found returning 0\n",
@@ -366,13 +366,13 @@
return 0;
}
-static int get_voice_index_cvp(u32 cvp_handle)
+static u32 get_voice_session_id_cvp(u32 cvp_handle)
{
u32 i;
for (i = 0; i < rtac_voice_data.num_of_voice_combos; i++) {
if (rtac_voice_data.voice[i].cvp_handle == cvp_handle)
- return i;
+ return voice_session_id[i];
}
pr_err("%s: No voice index for CVP handle %d found returning 0\n",
@@ -383,9 +383,11 @@
static int get_voice_index(u32 mode, u32 handle)
{
if (mode == RTAC_CVP)
- return get_voice_index_cvp(handle);
+ return voice_get_idx_for_session(
+ get_voice_session_id_cvp(handle));
if (mode == RTAC_CVS)
- return get_voice_index_cvs(handle);
+ return voice_get_idx_for_session(
+ get_voice_session_id_cvs(handle));
pr_err("%s: Invalid mode %d, returning 0\n",
__func__, mode);
@@ -847,8 +849,7 @@
payload_size);
voice_params.src_svc = 0;
voice_params.src_domain = APR_DOMAIN_APPS;
- voice_params.src_port = voice_session_id[
- get_voice_index(mode, dest_port)];
+ voice_params.src_port = get_voice_index(mode, dest_port);
voice_params.dest_svc = 0;
voice_params.dest_domain = APR_DOMAIN_MODEM;
voice_params.dest_port = (u16)dest_port;