Merge "rmnet_smux: Increase Rmnet device instance count"
diff --git a/Documentation/devicetree/bindings/leds/leds-qpnp.txt b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
index 5a668b2..ff95d43 100644
--- a/Documentation/devicetree/bindings/leds/leds-qpnp.txt
+++ b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
@@ -71,6 +71,7 @@
- linux,default-trigger: trigger the led from external modules such as display
- qcom,default-state: default state of the led, should be "on" or "off"
- qcom,turn-off-delay-ms: delay in millisecond for turning off the led when its default-state is "on". Value is being ignored in case default-state is "off".
+- 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.
MPP LED is an LED controled through a Multi Purpose Pin.
@@ -80,6 +81,7 @@
- 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,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.
Required properties for PWM mode only:
- qcom,pwm-channel: pwm channel the led will operate on
@@ -161,8 +163,19 @@
label = "rgb";
linux,name = "led:rgb_red";
qcom,mode = "pwm";
- qcom,pwm-channel = <6>;
qcom,pwm-us = <1000>;
+ qcom,pwm-channel = <6>;
+ qcom,max-current = <12>;
+ qcom,default-state = "off";
+ qcom,id = <3>;
+ linux,default-trigger =
+ "battery-charging";
+ };
+ qcom,rgb_lpg {
+ label = "rgb";
+ linux,name = "led:rgb_green";
+ qcom,mode = "lpg";
+ qcom,pwm-channel = <5>;
qcom,duty-ms = <20>;
qcom,start-idx = <1>;
qcom,idx-len = <10>;
@@ -175,10 +188,10 @@
"battery-charging";
};
- qcom,rgb_lpg {
+ qcom,rgb_blink {
label = "rgb";
linux,name = "led:rgb_blue";
- qcom,mode = "lpg";
+ qcom,mode = "pwm";
qcom,pwm-channel = <4>;
qcom,start-idx = <1>;
qcom,idx-len = <10>;
@@ -193,6 +206,8 @@
qcom,turn-off-delay-ms = <500>;
qcom,id = <5>;
linux,default-trigger = "none";
+ qcom,pwm-us = <1000>;
+ qcom,use-blink;
};
};
diff --git a/arch/arm/boot/dts/msm8226-mtp.dtsi b/arch/arm/boot/dts/msm8226-mtp.dtsi
index 490188a..ae57797 100644
--- a/arch/arm/boot/dts/msm8226-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8226-mtp.dtsi
@@ -102,6 +102,21 @@
};
};
+&usb_otg {
+ #address-cells = <0>;
+ interrupt-parent = <&usb_otg>;
+ interrupts = <0 1 2>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0xffffffff>;
+ interrupt-map = <0 &intc 0 134 0
+ 1 &intc 0 140 0
+ 2 &spmi_bus 0x0 0x0 0x9 0x0>;
+ interrupt-names = "core_irq", "async_irq", "pmic_id_irq";
+
+ qcom,hsusb-otg-mode = <3>;
+ vbus_otg-supply = <&usb_otg_sw>;
+};
+
&sdcc1 {
vdd-supply = <&pm8226_l17>;
qcom,vdd-always-on;
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index 3c1f45b6..7c98104 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -241,7 +241,7 @@
};
};
- usb@f9a55000 {
+ usb_otg: usb@f9a55000 {
compatible = "qcom,hsusb-otg";
reg = <0xf9a55000 0x400>;
interrupts = <0 134 0>, <0 140 0>;
@@ -259,7 +259,7 @@
qcom,hsusb-otg-disable-reset;
qcom,dp-manual-pullup;
- qcom,msm-bus,name = "usb2";
+ qcom,msm-bus,name = "usb";
qcom,msm-bus,num-cases = <2>;
qcom,msm-bus,num-paths = <1>;
qcom,msm-bus,vectors-KBps =
@@ -1012,6 +1012,12 @@
<55 512 0 0>,
<55 512 3936000 393600>;
};
+
+ cpu-pmu {
+ compatible = "arm,cortex-a7-pmu";
+ qcom,irq-is-percpu;
+ interrupts = <1 7 0xf00>;
+ };
};
&gdsc_venus {
diff --git a/arch/arm/boot/dts/msm8610-qrd.dts b/arch/arm/boot/dts/msm8610-qrd.dts
index 38f714b..deeb051 100644
--- a/arch/arm/boot/dts/msm8610-qrd.dts
+++ b/arch/arm/boot/dts/msm8610-qrd.dts
@@ -22,6 +22,35 @@
};
&soc {
+ i2c@f9923000{
+ focaltech@38{
+ compatible = "focaltech,5x06";
+ reg = <0x38>;
+ interrupt-parent = <&msmgpio>;
+ interrupts = <1 0x2>;
+ vdd-supply = <&pm8110_l19>;
+ vcc_i2c-supply = <&pm8110_l14>;
+ focaltech,family-id = <0x06>;
+ focaltech,reset-gpio = <&msmgpio 0 0x00>;
+ focaltech,irq-gpio = <&msmgpio 1 0x00>;
+ focaltech,display-coords = <0 0 480 800>;
+ focaltech,panel-coords = <0 0 480 800>;
+ focaltech,button-map= <139 102 158>;
+ focaltech,no-force-update;
+ focaltech,i2c-pull-up;
+ };
+ };
+
+ gen-vkeys {
+ compatible = "qcom,gen-vkeys";
+ label = "ft5x06_ts";
+ qcom,disp-maxx = <480>;
+ qcom,disp-maxy = <800>;
+ qcom,panel-maxx = <481>;
+ qcom,panel-maxy = <940>;
+ qcom,key-codes = <139 0 102 158 0 0 0>;
+ qcom,y-offset = <0>;
+ };
serial@f991e000 {
status = "ok";
};
diff --git a/arch/arm/boot/dts/msm8974-cdp.dtsi b/arch/arm/boot/dts/msm8974-cdp.dtsi
index 3e65b8a..2a60df4 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8974-cdp.dtsi
@@ -599,6 +599,13 @@
};
gpio@e300 { /* GPIO 36 */
+ qcom,mode = <1>; /* QPNP_PIN_MODE_DIG_OUT */
+ qcom,output-type = <0>; /* QPNP_PIN_OUT_BUF_CMOS */
+ qcom,pull = <5>; /* QPNP_PIN_PULL_NO */
+ qcom,vin-sel = <2>; /* QPNP_PIN_VIN2 */
+ qcom,out-strength = <3>; /* QPNP_PIN_OUT_STRENGTH_HIGH */
+ qcom,src-sel = <3>; /* QPNP_PIN_SEL_FUNC_2 */
+ qcom,master-en = <1>;
};
};
diff --git a/arch/arm/configs/apq8084_defconfig b/arch/arm/configs/apq8084_defconfig
index 78eb352..a004835 100644
--- a/arch/arm/configs/apq8084_defconfig
+++ b/arch/arm/configs/apq8084_defconfig
@@ -355,6 +355,7 @@
CONFIG_QPNP_CLKDIV=y
CONFIG_MSM_IOMMU_V1=y
CONFIG_IOMMU_PGTABLES_L2=y
+CONFIG_IOMMU_NON_SECURE=y
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT3_FS=y
diff --git a/arch/arm/configs/msm8226-perf_defconfig b/arch/arm/configs/msm8226-perf_defconfig
index da77b69..d58f7fb 100644
--- a/arch/arm/configs/msm8226-perf_defconfig
+++ b/arch/arm/configs/msm8226-perf_defconfig
@@ -79,6 +79,9 @@
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
CONFIG_USE_OF=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
CONFIG_CPU_IDLE=y
CONFIG_VFP=y
CONFIG_NEON=y
diff --git a/arch/arm/configs/msm8226_defconfig b/arch/arm/configs/msm8226_defconfig
index 43ef0e0..07378b2 100644
--- a/arch/arm/configs/msm8226_defconfig
+++ b/arch/arm/configs/msm8226_defconfig
@@ -79,6 +79,9 @@
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
CONFIG_USE_OF=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
CONFIG_CPU_IDLE=y
CONFIG_VFP=y
CONFIG_NEON=y
diff --git a/arch/arm/configs/msm8610-perf_defconfig b/arch/arm/configs/msm8610-perf_defconfig
index 9eb53d0..3bbff5c 100644
--- a/arch/arm/configs/msm8610-perf_defconfig
+++ b/arch/arm/configs/msm8610-perf_defconfig
@@ -82,6 +82,9 @@
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
CONFIG_USE_OF=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
CONFIG_CPU_IDLE=y
CONFIG_VFP=y
CONFIG_NEON=y
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index d7194a4..d11773f 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -80,6 +80,9 @@
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
CONFIG_USE_OF=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
CONFIG_CPU_IDLE=y
CONFIG_VFP=y
CONFIG_NEON=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 86eb7d1..7824502 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -458,9 +458,6 @@
select MSM_BUS_SCALING
select CPU_FREQ_MSM
select CPU_FREQ
- select CPU_FREQ_GOV_USERSPACE
- select CPU_FREQ_GOV_ONDEMAND
- select CPU_FREQ_GOV_POWERSAVE
select MSM_PIL
select MSM_RUN_QUEUE_STATS
select ARM_HAS_SG_CHAIN
@@ -500,8 +497,6 @@
select MSM_BUS_SCALING
select CPU_FREQ_MSM
select CPU_FREQ
- select CPU_FREQ_GOV_USERSPACE
- select CPU_FREQ_GOV_ONDEMAND
select MSM_PIL
select MSM_RUN_QUEUE_STATS
select ARM_HAS_SG_CHAIN
diff --git a/arch/arm/mach-msm/include/mach/iommu_hw-v1.h b/arch/arm/mach-msm/include/mach/iommu_hw-v1.h
index 554f7e0..1c20d04 100644
--- a/arch/arm/mach-msm/include/mach/iommu_hw-v1.h
+++ b/arch/arm/mach-msm/include/mach/iommu_hw-v1.h
@@ -93,6 +93,8 @@
#define SET_NSCR0(b, v) SET_GLOBAL_REG(NSCR0, (b), (v))
#define SET_NSCR2(b, v) SET_GLOBAL_REG(NSCR2, (b), (v))
#define SET_NSACR(b, v) SET_GLOBAL_REG(NSACR, (b), (v))
+#define SET_NSGFAR(b, v) SET_GLOBAL_REG(NSGFAR, (b), (v))
+#define SET_NSGFSRRESTORE(b, v) SET_GLOBAL_REG(NSGFSRRESTORE, (b), (v))
#define SET_PMCR(b, v) SET_GLOBAL_REG(PMCR, (b), (v))
#define SET_SMR_N(b, N, v) SET_GLOBAL_REG_N(SMR, N, (b), (v))
#define SET_S2CR_N(b, N, v) SET_GLOBAL_REG_N(S2CR, N, (b), (v))
@@ -215,26 +217,34 @@
#define GET_ATSR(b, c) GET_CTX_REG(CB_ATSR, (b), (c))
/* Global Register field setters / getters */
-/* Configuration Register: CR0 */
+/* Configuration Register: CR0/NSCR0 */
#define SET_CR0_NSCFG(b, v) SET_GLOBAL_FIELD(b, CR0, NSCFG, v)
#define SET_CR0_WACFG(b, v) SET_GLOBAL_FIELD(b, CR0, WACFG, v)
#define SET_CR0_RACFG(b, v) SET_GLOBAL_FIELD(b, CR0, RACFG, v)
#define SET_CR0_SHCFG(b, v) SET_GLOBAL_FIELD(b, CR0, SHCFG, v)
#define SET_CR0_SMCFCFG(b, v) SET_GLOBAL_FIELD(b, CR0, SMCFCFG, v)
+#define SET_NSCR0_SMCFCFG(b, v) SET_GLOBAL_FIELD(b, NSCR0, SMCFCFG, v)
#define SET_CR0_MTCFG(b, v) SET_GLOBAL_FIELD(b, CR0, MTCFG, v)
#define SET_CR0_BSU(b, v) SET_GLOBAL_FIELD(b, CR0, BSU, v)
#define SET_CR0_FB(b, v) SET_GLOBAL_FIELD(b, CR0, FB, v)
#define SET_CR0_PTM(b, v) SET_GLOBAL_FIELD(b, CR0, PTM, v)
#define SET_CR0_VMIDPNE(b, v) SET_GLOBAL_FIELD(b, CR0, VMIDPNE, v)
#define SET_CR0_USFCFG(b, v) SET_GLOBAL_FIELD(b, CR0, USFCFG, v)
+#define SET_NSCR0_USFCFG(b, v) SET_GLOBAL_FIELD(b, NSCR0, USFCFG, v)
#define SET_CR0_GSE(b, v) SET_GLOBAL_FIELD(b, CR0, GSE, v)
#define SET_CR0_STALLD(b, v) SET_GLOBAL_FIELD(b, CR0, STALLD, v)
+#define SET_NSCR0_STALLD(b, v) SET_GLOBAL_FIELD(b, NSCR0, STALLD, v)
#define SET_CR0_TRANSIENTCFG(b, v) SET_GLOBAL_FIELD(b, CR0, TRANSIENTCFG, v)
#define SET_CR0_GCFGFIE(b, v) SET_GLOBAL_FIELD(b, CR0, GCFGFIE, v)
+#define SET_NSCR0_GCFGFIE(b, v) SET_GLOBAL_FIELD(b, NSCR0, GCFGFIE, v)
#define SET_CR0_GCFGFRE(b, v) SET_GLOBAL_FIELD(b, CR0, GCFGFRE, v)
+#define SET_NSCR0_GCFGFRE(b, v) SET_GLOBAL_FIELD(b, NSCR0, GCFGFRE, v)
#define SET_CR0_GFIE(b, v) SET_GLOBAL_FIELD(b, CR0, GFIE, v)
+#define SET_NSCR0_GFIE(b, v) SET_GLOBAL_FIELD(b, NSCR0, GFIE, v)
#define SET_CR0_GFRE(b, v) SET_GLOBAL_FIELD(b, CR0, GFRE, v)
+#define SET_NSCR0_GFRE(b, v) SET_GLOBAL_FIELD(b, NSCR0, GFRE, v)
#define SET_CR0_CLIENTPD(b, v) SET_GLOBAL_FIELD(b, CR0, CLIENTPD, v)
+#define SET_NSCR0_CLIENTPD(b, v) SET_GLOBAL_FIELD(b, NSCR0, CLIENTPD, v)
#define GET_CR0_NSCFG(b) GET_GLOBAL_FIELD(b, CR0, NSCFG)
#define GET_CR0_WACFG(b) GET_GLOBAL_FIELD(b, CR0, WACFG)
@@ -949,6 +959,8 @@
#define NSCR0 (0x0400)
#define NSCR2 (0x0408)
#define NSACR (0x0410)
+#define NSGFAR (0x0440)
+#define NSGFSRRESTORE (0x044C)
#define SMR (0x0800)
#define S2CR (0x0C00)
@@ -1400,6 +1412,7 @@
#define CR0_RACFG_MASK 0x03
#define CR0_SHCFG_MASK 0x03
#define CR0_SMCFCFG_MASK 0x01
+#define NSCR0_SMCFCFG_MASK 0x01
#define CR0_MTCFG_MASK 0x01
#define CR0_MEMATTR_MASK 0x0F
#define CR0_BSU_MASK 0x03
@@ -1407,14 +1420,21 @@
#define CR0_PTM_MASK 0x01
#define CR0_VMIDPNE_MASK 0x01
#define CR0_USFCFG_MASK 0x01
+#define NSCR0_USFCFG_MASK 0x01
#define CR0_GSE_MASK 0x01
#define CR0_STALLD_MASK 0x01
+#define NSCR0_STALLD_MASK 0x01
#define CR0_TRANSIENTCFG_MASK 0x03
#define CR0_GCFGFIE_MASK 0x01
+#define NSCR0_GCFGFIE_MASK 0x01
#define CR0_GCFGFRE_MASK 0x01
+#define NSCR0_GCFGFRE_MASK 0x01
#define CR0_GFIE_MASK 0x01
+#define NSCR0_GFIE_MASK 0x01
#define CR0_GFRE_MASK 0x01
+#define NSCR0_GFRE_MASK 0x01
#define CR0_CLIENTPD_MASK 0x01
+#define NSCR0_CLIENTPD_MASK 0x01
/* Configuration Register 2 */
#define CR2_BPVMID_MASK 0xFF
@@ -1764,6 +1784,7 @@
#define CR0_RACFG_SHIFT 24
#define CR0_SHCFG_SHIFT 22
#define CR0_SMCFCFG_SHIFT 21
+#define NSCR0_SMCFCFG_SHIFT 21
#define CR0_MTCFG_SHIFT 20
#define CR0_MEMATTR_SHIFT 16
#define CR0_BSU_SHIFT 14
@@ -1771,14 +1792,21 @@
#define CR0_PTM_SHIFT 12
#define CR0_VMIDPNE_SHIFT 11
#define CR0_USFCFG_SHIFT 10
+#define NSCR0_USFCFG_SHIFT 10
#define CR0_GSE_SHIFT 9
#define CR0_STALLD_SHIFT 8
+#define NSCR0_STALLD_SHIFT 8
#define CR0_TRANSIENTCFG_SHIFT 6
#define CR0_GCFGFIE_SHIFT 5
+#define NSCR0_GCFGFIE_SHIFT 5
#define CR0_GCFGFRE_SHIFT 4
+#define NSCR0_GCFGFRE_SHIFT 4
#define CR0_GFIE_SHIFT 2
+#define NSCR0_GFIE_SHIFT 2
#define CR0_GFRE_SHIFT 1
+#define NSCR0_GFRE_SHIFT 1
#define CR0_CLIENTPD_SHIFT 0
+#define NSCR0_CLIENTPD_SHIFT 0
/* Configuration Register: CR2 */
#define CR2_BPVMID_SHIFT 0
diff --git a/arch/arm/mach-msm/perf_debug.c b/arch/arm/mach-msm/perf_debug.c
index af71cc9..70420db 100644
--- a/arch/arm/mach-msm/perf_debug.c
+++ b/arch/arm/mach-msm/perf_debug.c
@@ -31,6 +31,7 @@
"6 Perf: Add cortex A5 device tree support\n"
"7 Perf: Add L1 counters to tracepoints\n"
"8 Perf: Add cortex A7 perf support\n"
+ "9 ARM: dts: msm: add perf-events support for msm8226\n"
;
static ssize_t desc_read(struct file *fp, char __user *buf,
diff --git a/drivers/gud/Makefile b/drivers/gud/Makefile
index 3a16bb7..ef0e083 100644
--- a/drivers/gud/Makefile
+++ b/drivers/gud/Makefile
@@ -10,7 +10,8 @@
mobicore_driver/ops.o \
mobicore_driver/mem.o \
mobicore_driver/api.o \
- mobicore_driver/main.o
+ mobicore_driver/main.o \
+ mobicore_driver/pm.o
mckernelapi-objs := mobicore_kernelapi/main.o \
mobicore_kernelapi/clientlib.o \
diff --git a/drivers/gud/mobicore_driver/main.c b/drivers/gud/mobicore_driver/main.c
index b5cb1a6..6f91974 100644
--- a/drivers/gud/mobicore_driver/main.c
+++ b/drivers/gud/mobicore_driver/main.c
@@ -51,7 +51,6 @@
};
struct device mcd_debug_subname = {
- .init_name = "", /* Set to 'mcd' at mc_init() time */
.driver = &mcd_debug_name
};
@@ -1343,6 +1342,10 @@
ret = mc_init_l2_tables();
+#ifdef MC_CRYPTO_CLOCK_MANAGEMENT
+ ret = mc_pm_clock_initialize();
+#endif
+
/*
* initialize unique number counter which we can use for
* handles. It is limited to 2^32, but this should be
@@ -1398,6 +1401,10 @@
mc_fastcall_destroy();
+#ifdef MC_CRYPTO_CLOCK_MANAGEMENT
+ mc_pm_clock_finalize();
+#endif
+
MCDRV_DBG_VERBOSE(mcd, "exit");
}
diff --git a/drivers/gud/mobicore_driver/ops.c b/drivers/gud/mobicore_driver/ops.c
index 05c80b7..9d4af72 100644
--- a/drivers/gud/mobicore_driver/ops.c
+++ b/drivers/gud/mobicore_driver/ops.c
@@ -60,7 +60,16 @@
{
struct fastcall_work *fc_work =
container_of(work, struct fastcall_work, work);
+
+#ifdef MC_CRYPTO_CLOCK_MANAGEMENT
+ mc_pm_clock_enable();
+#endif
+
smc(fc_work->data);
+
+#ifdef MC_CRYPTO_CLOCK_MANAGEMENT
+ mc_pm_clock_disable();
+#endif
}
void mc_fastcall(void *data)
@@ -114,7 +123,16 @@
{
struct fastcall_work_struct *fc_work =
container_of(work, struct fastcall_work_struct, work);
+
+#ifdef MC_CRYPTO_CLOCK_MANAGEMENT
+ mc_pm_clock_enable();
+#endif
+
smc(fc_work->data);
+
+#ifdef MC_CRYPTO_CLOCK_MANAGEMENT
+ mc_pm_clock_disable();
+#endif
}
void mc_fastcall(void *data)
diff --git a/drivers/gud/mobicore_driver/platforms/msm8960_surf_std/platform.h b/drivers/gud/mobicore_driver/platforms/msm8960_surf_std/platform.h
index 7febcb6..4768f39 100644
--- a/drivers/gud/mobicore_driver/platforms/msm8960_surf_std/platform.h
+++ b/drivers/gud/mobicore_driver/platforms/msm8960_surf_std/platform.h
@@ -43,4 +43,7 @@
*/
#define MC_VM_UNMAP
+/* Enable Power Management for Crypto Engine */
+#define MC_CRYPTO_CLOCK_MANAGEMENT
+
#endif /* _MC_PLATFORM_H_ */
diff --git a/drivers/gud/mobicore_driver/pm.c b/drivers/gud/mobicore_driver/pm.c
new file mode 100644
index 0000000..3ad2015
--- /dev/null
+++ b/drivers/gud/mobicore_driver/pm.c
@@ -0,0 +1,295 @@
+/*
+ * MobiCore Driver Kernel Module.
+ * This module is written as a Linux device driver.
+ * This driver represents the command proxy on the lowest layer, from the
+ * secure world to the non secure world, and vice versa.
+ * This driver is located in the non secure world (Linux).
+ * This driver offers IOCTL commands, for access to the secure world, and has
+ * the interface from the secure world to the normal world.
+ * The access to the driver is possible with a file descriptor,
+ * which has to be created by the fd = open(/dev/mobicore) command.
+ *
+ * <-- Copyright Giesecke & Devrient GmbH 2009-2012 -->
+ * <-- Copyright Trustonic Limited 2013 -->
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/module.h>
+#include <linux/timer.h>
+#include <linux/suspend.h>
+#include <linux/device.h>
+
+#include "main.h"
+#include "pm.h"
+#include "fastcall.h"
+#include "ops.h"
+#include "logging.h"
+#include "debug.h"
+
+#ifdef MC_CRYPTO_CLOCK_MANAGEMENT
+ #include <linux/clk.h>
+ #include <linux/err.h>
+
+ struct clk *mc_ce_iface_clk = NULL;
+ struct clk *mc_ce_core_clk = NULL;
+ struct clk *mc_ce_bus_clk = NULL;
+#endif /* MC_CRYPTO_CLOCK_MANAGEMENT */
+
+#ifdef MC_PM_RUNTIME
+
+static struct mc_context *ctx;
+
+static bool sleep_ready(void)
+{
+ if (!ctx->mcp)
+ return false;
+
+ if (!ctx->mcp->flags.sleep_mode.ReadyToSleep & READY_TO_SLEEP)
+ return false;
+
+ return true;
+}
+
+static void mc_suspend_handler(struct work_struct *work)
+{
+ if (!ctx->mcp)
+ return;
+
+ ctx->mcp->flags.sleep_mode.SleepReq = REQ_TO_SLEEP;
+ _nsiq();
+}
+DECLARE_WORK(suspend_work, mc_suspend_handler);
+
+static inline void dump_sleep_params(struct mc_flags *flags)
+{
+ MCDRV_DBG(mcd, "MobiCore IDLE=%d!", flags->schedule);
+ MCDRV_DBG(mcd,
+ "MobiCore Request Sleep=%d!", flags->sleep_mode.SleepReq);
+ MCDRV_DBG(mcd, "MobiCore Sleep Ready=%d!",
+ flags->sleep_mode.ReadyToSleep);
+}
+
+static int mc_suspend_notifier(struct notifier_block *nb,
+ unsigned long event, void *dummy)
+{
+ struct mc_mcp_buffer *mcp = ctx->mcp;
+ /* We have noting to say if MobiCore is not initialized */
+ if (!mcp)
+ return 0;
+
+#ifdef MC_MEM_TRACES
+ mobicore_log_read();
+#endif
+
+ switch (event) {
+ case PM_SUSPEND_PREPARE:
+ /*
+ * Make sure we have finished all the work otherwise
+ * we end up in a race condition
+ */
+ cancel_work_sync(&suspend_work);
+ /*
+ * We can't go to sleep if MobiCore is not IDLE
+ * or not Ready to sleep
+ */
+ dump_sleep_params(&mcp->flags);
+ if (!sleep_ready()) {
+ ctx->mcp->flags.sleep_mode.SleepReq = REQ_TO_SLEEP;
+ schedule_work_on(0, &suspend_work);
+ flush_work(&suspend_work);
+ if (!sleep_ready()) {
+ dump_sleep_params(&mcp->flags);
+ ctx->mcp->flags.sleep_mode.SleepReq = 0;
+ MCDRV_DBG_ERROR(mcd, "MobiCore can't SLEEP!");
+ return NOTIFY_BAD;
+ }
+ }
+ break;
+ case PM_POST_SUSPEND:
+ MCDRV_DBG(mcd, "Resume MobiCore system!");
+ ctx->mcp->flags.sleep_mode.SleepReq = 0;
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static struct notifier_block mc_notif_block = {
+ .notifier_call = mc_suspend_notifier,
+};
+
+#ifdef MC_BL_NOTIFIER
+
+static int bL_switcher_notifier_handler(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ unsigned int mpidr, cpu, cluster;
+ struct mc_mcp_buffer *mcp = ctx->mcp;
+
+ if (!mcp)
+ return 0;
+
+ asm volatile ("mrc\tp15, 0, %0, c0, c0, 5" : "=r" (mpidr));
+ cpu = mpidr & 0x3;
+ cluster = (mpidr >> 8) & 0xf;
+ MCDRV_DBG(mcd, "%s switching!!, cpu: %u, Out=%u\n",
+ (event == SWITCH_ENTER ? "Before" : "After"), cpu, cluster);
+
+ if (cpu != 0)
+ return 0;
+
+ switch (event) {
+ case SWITCH_ENTER:
+ if (!sleep_ready()) {
+ ctx->mcp->flags.sleep_mode.SleepReq = REQ_TO_SLEEP;
+ _nsiq();
+ /* By this time we should be ready for sleep or we are
+ * in the middle of something important */
+ if (!sleep_ready()) {
+ dump_sleep_params(&mcp->flags);
+ MCDRV_DBG(mcd,
+ "MobiCore: Don't allow switch!\n");
+ ctx->mcp->flags.sleep_mode.SleepReq = 0;
+ return -EPERM;
+ }
+ }
+ break;
+ case SWITCH_EXIT:
+ ctx->mcp->flags.sleep_mode.SleepReq = 0;
+ break;
+ default:
+ MCDRV_DBG(mcd, "MobiCore: Unknown switch event!\n");
+ }
+
+ return 0;
+}
+
+static struct notifier_block switcher_nb = {
+ .notifier_call = bL_switcher_notifier_handler,
+};
+#endif
+
+int mc_pm_initialize(struct mc_context *context)
+{
+ int ret = 0;
+
+ ctx = context;
+
+ ret = register_pm_notifier(&mc_notif_block);
+ if (ret)
+ MCDRV_DBG_ERROR(mcd, "device pm register failed\n");
+#ifdef MC_BL_NOTIFIER
+ if (register_bL_swicher_notifier(&switcher_nb))
+ MCDRV_DBG_ERROR(mcd,
+ "Failed to register to bL_switcher_notifier\n");
+#endif
+
+ return ret;
+}
+
+int mc_pm_free(void)
+{
+ int ret = unregister_pm_notifier(&mc_notif_block);
+ if (ret)
+ MCDRV_DBG_ERROR(mcd, "device pm unregister failed\n");
+#ifdef MC_BL_NOTIFIER
+ ret = unregister_bL_swicher_notifier(&switcher_nb);
+ if (ret)
+ MCDRV_DBG_ERROR(mcd, "device bl unregister failed\n");
+#endif
+ return ret;
+}
+
+#endif /* MC_PM_RUNTIME */
+
+#ifdef MC_CRYPTO_CLOCK_MANAGEMENT
+
+int mc_pm_clock_initialize(void)
+{
+ int ret = 0;
+
+ /* Get core clk */
+ mc_ce_core_clk = clk_get(mcd, "core_clk");
+ if (IS_ERR(mc_ce_core_clk)) {
+ ret = PTR_ERR(mc_ce_core_clk);
+ MCDRV_DBG_ERROR(mcd, "cannot get core clock\n");
+ goto error;
+ }
+ /* Get Interface clk */
+ mc_ce_iface_clk = clk_get(mcd, "iface_clk");
+ if (IS_ERR(mc_ce_iface_clk)) {
+ clk_put(mc_ce_core_clk);
+ ret = PTR_ERR(mc_ce_iface_clk);
+ MCDRV_DBG_ERROR(mcd, "cannot get iface clock\n");
+ goto error;
+ }
+ /* Get AXI clk */
+ mc_ce_bus_clk = clk_get(mcd, "bus_clk");
+ if (IS_ERR(mc_ce_bus_clk)) {
+ clk_put(mc_ce_iface_clk);
+ clk_put(mc_ce_core_clk);
+ ret = PTR_ERR(mc_ce_bus_clk);
+ MCDRV_DBG_ERROR(mcd, "cannot get AXI bus clock\n");
+ goto error;
+ }
+ return ret;
+
+error:
+ mc_ce_core_clk = NULL;
+ mc_ce_iface_clk = NULL;
+ mc_ce_bus_clk = NULL;
+
+ return ret;
+}
+
+void mc_pm_clock_finalize(void)
+{
+ if (mc_ce_iface_clk != NULL)
+ clk_put(mc_ce_iface_clk);
+
+ if (mc_ce_core_clk != NULL)
+ clk_put(mc_ce_core_clk);
+
+ if (mc_ce_bus_clk != NULL)
+ clk_put(mc_ce_bus_clk);
+}
+
+int mc_pm_clock_enable(void)
+{
+ int rc = 0;
+
+ rc = clk_prepare_enable(mc_ce_core_clk);
+ if (rc) {
+ MCDRV_DBG_ERROR(mcd, "cannot enable clock\n");
+ } else {
+ rc = clk_prepare_enable(mc_ce_iface_clk);
+ if (rc) {
+ clk_disable_unprepare(mc_ce_core_clk);
+ MCDRV_DBG_ERROR(mcd, "cannot enable clock\n");
+ } else {
+ rc = clk_prepare_enable(mc_ce_bus_clk);
+ if (rc) {
+ clk_disable_unprepare(mc_ce_iface_clk);
+ MCDRV_DBG_ERROR(mcd, "cannot enable clock\n");
+ }
+ }
+ }
+ return rc;
+}
+
+void mc_pm_clock_disable(void)
+{
+ if (mc_ce_iface_clk != NULL)
+ clk_disable_unprepare(mc_ce_iface_clk);
+
+ if (mc_ce_core_clk != NULL)
+ clk_disable_unprepare(mc_ce_core_clk);
+
+ if (mc_ce_bus_clk != NULL)
+ clk_disable_unprepare(mc_ce_bus_clk);
+}
+
+#endif /* MC_CRYPTO_CLOCK_MANAGEMENT */
diff --git a/drivers/gud/mobicore_driver/pm.h b/drivers/gud/mobicore_driver/pm.h
index 3e73b8b..332da34 100644
--- a/drivers/gud/mobicore_driver/pm.h
+++ b/drivers/gud/mobicore_driver/pm.h
@@ -31,5 +31,13 @@
int mc_pm_initialize(struct mc_context *context);
/* Free all Power Management resources*/
int mc_pm_free(void);
+/* Initialize secure crypto clocks */
+int mc_pm_clock_initialize(void);
+/* Free secure crypto clocks */
+void mc_pm_clock_finalize(void);
+/* Enable secure crypto clocks */
+int mc_pm_clock_enable(void);
+/* Disable secure crypto clocks */
+void mc_pm_clock_disable(void);
#endif /* _MC_PM_H_ */
diff --git a/drivers/input/touchscreen/ft5x06_ts.c b/drivers/input/touchscreen/ft5x06_ts.c
index 5cbe9ab..d43bfbe 100644
--- a/drivers/input/touchscreen/ft5x06_ts.c
+++ b/drivers/input/touchscreen/ft5x06_ts.c
@@ -451,7 +451,7 @@
static int ft5x06_parse_dt(struct device *dev,
struct ft5x06_ts_platform_data *pdata)
{
- int rc, i;
+ int rc;
struct device_node *np = dev->of_node;
struct property *prop;
u32 temp_val, num_buttons;
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 318b98f..6324dff 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -75,6 +75,20 @@
section mappings and TLB misses should be quite infrequent.
Most people can probably say Y here.
+config IOMMU_NON_SECURE
+ bool "Turns on programming of secure SMMU by kernel"
+ depends on MSM_IOMMU
+ help
+ Say Y here if you want the kernel to program all SMMUs regardless of
+ whether SMMUs are secure or not. A secure SMMU is an SMMU that has
+ its global address space programmed by the secure environment. In
+ addition some of the context banks might be owned/programmed by the
+ secure environment for a secure SMMU. Enabling this feature can be
+ used during testing when the secure environment is not available
+ and the kernel needs to program all the SMMUs.
+
+ If unsure, say N here.
+
# AMD IOMMU support
config AMD_IOMMU
bool "AMD IOMMU support"
diff --git a/drivers/iommu/msm_iommu-v1.c b/drivers/iommu/msm_iommu-v1.c
index 06c6d94..653487b 100644
--- a/drivers/iommu/msm_iommu-v1.c
+++ b/drivers/iommu/msm_iommu-v1.c
@@ -259,12 +259,46 @@
mb();
}
+#ifdef CONFIG_IOMMU_NON_SECURE
+static void __reset_iommu_secure(void __iomem *base)
+{
+ SET_NSACR(base, 0);
+ SET_NSCR2(base, 0);
+ SET_NSGFAR(base, 0);
+ SET_NSGFSRRESTORE(base, 0);
+ mb();
+}
+
+static void __program_iommu_secure(void __iomem *base)
+{
+ SET_NSCR0_SMCFCFG(base, 1);
+ SET_NSCR0_USFCFG(base, 1);
+ SET_NSCR0_STALLD(base, 1);
+ SET_NSCR0_GCFGFIE(base, 1);
+ SET_NSCR0_GCFGFRE(base, 1);
+ SET_NSCR0_GFIE(base, 1);
+ SET_NSCR0_GFRE(base, 1);
+ SET_NSCR0_CLIENTPD(base, 0);
+}
+
+#else
+static inline void __reset_iommu_secure(void __iomem *base)
+{
+}
+
+static inline void __program_iommu_secure(void __iomem *base)
+{
+}
+
+#endif
+
/*
* May only be called for non-secure iommus
*/
static void __program_iommu(void __iomem *base)
{
__reset_iommu(base);
+ __reset_iommu_secure(base);
SET_CR0_SMCFCFG(base, 1);
SET_CR0_USFCFG(base, 1);
@@ -275,6 +309,8 @@
SET_CR0_GFRE(base, 1);
SET_CR0_CLIENTPD(base, 0);
+ __program_iommu_secure(base);
+
mb(); /* Make sure writes complete before returning */
}
diff --git a/drivers/iommu/msm_iommu_dev-v1.c b/drivers/iommu/msm_iommu_dev-v1.c
index db7c378..119a126 100644
--- a/drivers/iommu/msm_iommu_dev-v1.c
+++ b/drivers/iommu/msm_iommu_dev-v1.c
@@ -118,6 +118,32 @@
drvdata->bus_client = 0;
}
+#ifdef CONFIG_IOMMU_NON_SECURE
+static inline void get_secure_id(struct device_node *node,
+ struct msm_iommu_drvdata *drvdata)
+{
+}
+
+static inline void get_secure_ctx(struct device_node *node,
+ struct msm_iommu_ctx_drvdata *ctx_drvdata)
+{
+ ctx_drvdata->secure_context = 0;
+}
+#else
+static void get_secure_id(struct device_node *node,
+ struct msm_iommu_drvdata *drvdata)
+{
+ of_property_read_u32(node, "qcom,iommu-secure-id", &drvdata->sec_id);
+}
+
+static void get_secure_ctx(struct device_node *node,
+ struct msm_iommu_ctx_drvdata *ctx_drvdata)
+{
+ ctx_drvdata->secure_context =
+ of_property_read_bool(node, "qcom,secure-context");
+}
+#endif
+
static int msm_iommu_parse_dt(struct platform_device *pdev,
struct msm_iommu_drvdata *drvdata)
{
@@ -154,8 +180,7 @@
goto fail;
drvdata->sec_id = -1;
- of_property_read_u32(pdev->dev.of_node, "qcom,iommu-secure-id",
- &drvdata->sec_id);
+ get_secure_id(pdev->dev.of_node, drvdata);
r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "clk_base");
if (r) {
@@ -361,8 +386,7 @@
int irq = 0, ret = 0;
u32 nsid;
- ctx_drvdata->secure_context = of_property_read_bool(pdev->dev.of_node,
- "qcom,secure-context");
+ get_secure_ctx(pdev->dev.of_node, ctx_drvdata);
if (ctx_drvdata->secure_context) {
irq = platform_get_irq(pdev, 1);
diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c
index 2ea7128..4835d62 100644
--- a/drivers/leds/leds-qpnp.c
+++ b/drivers/leds/leds-qpnp.c
@@ -308,6 +308,7 @@
struct pwm_duty_cycles *duty_cycles;
u8 mode;
u8 enable;
+ bool use_blink;
};
/**
@@ -1283,8 +1284,122 @@
return count;
}
+static int qpnp_pwm_init(struct pwm_config_data *pwm_cfg,
+ struct spmi_device *spmi_dev,
+ const char *name)
+{
+ int rc, start_idx, idx_len;
+
+ if (pwm_cfg->pwm_channel != -1) {
+ pwm_cfg->pwm_dev =
+ pwm_request(pwm_cfg->pwm_channel, name);
+
+ if (IS_ERR_OR_NULL(pwm_cfg->pwm_dev)) {
+ dev_err(&spmi_dev->dev,
+ "could not acquire PWM Channel %d, " \
+ "error %ld\n",
+ pwm_cfg->pwm_channel,
+ PTR_ERR(pwm_cfg->pwm_dev));
+ pwm_cfg->pwm_dev = NULL;
+ return -ENODEV;
+ }
+
+ if (pwm_cfg->mode == LPG_MODE) {
+ start_idx =
+ pwm_cfg->duty_cycles->start_idx;
+ idx_len =
+ pwm_cfg->duty_cycles->num_duty_pcts;
+
+ if (idx_len >= PWM_LUT_MAX_SIZE &&
+ start_idx) {
+ dev_err(&spmi_dev->dev,
+ "Wrong LUT size or index\n");
+ return -EINVAL;
+ }
+ if ((start_idx + idx_len) >
+ PWM_LUT_MAX_SIZE) {
+ dev_err(&spmi_dev->dev,
+ "Exceed LUT limit\n");
+ return -EINVAL;
+ }
+ rc = pwm_lut_config(pwm_cfg->pwm_dev,
+ PM_PWM_PERIOD_MIN, /* ignored by hardware */
+ pwm_cfg->duty_cycles->duty_pcts,
+ pwm_cfg->lut_params);
+ if (rc < 0) {
+ dev_err(&spmi_dev->dev, "Failed to " \
+ "configure pwm LUT\n");
+ return rc;
+ }
+ }
+ } else {
+ dev_err(&spmi_dev->dev,
+ "Invalid PWM channel\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void led_blink(struct qpnp_led_data *led,
+ struct pwm_config_data *pwm_cfg)
+{
+ u8 previous_mode;
+
+ previous_mode = pwm_cfg->mode;
+ if (pwm_cfg->use_blink) {
+ if (led->cdev.brightness) {
+ if (led->id == QPNP_ID_LED_MPP)
+ led->mpp_cfg->pwm_mode = LPG_MODE;
+ pwm_cfg->mode = LPG_MODE;
+ pwm_free(pwm_cfg->pwm_dev);
+ qpnp_pwm_init(pwm_cfg, led->spmi_dev, led->cdev.name);
+ qpnp_led_set(&led->cdev, led->cdev.brightness);
+ if (led->id == QPNP_ID_LED_MPP)
+ led->mpp_cfg->pwm_mode = previous_mode;
+ pwm_cfg->mode = previous_mode;
+ } else {
+ pwm_free(pwm_cfg->pwm_dev);
+ qpnp_pwm_init(pwm_cfg, led->spmi_dev, led->cdev.name);
+ qpnp_led_set(&led->cdev, led->cdev.brightness);
+ }
+ }
+}
+
+static ssize_t blink_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct qpnp_led_data *led;
+ unsigned long blinking;
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+ ssize_t ret = -EINVAL;
+
+ ret = kstrtoul(buf, 10, &blinking);
+ if (ret)
+ return ret;
+ led = container_of(led_cdev, struct qpnp_led_data, cdev);
+ led->cdev.brightness = blinking ? led->cdev.max_brightness : 0;
+
+ switch (led->id) {
+ case QPNP_ID_LED_MPP:
+ led_blink(led, led->mpp_cfg->pwm_cfg);
+ break;
+ case QPNP_ID_RGB_RED:
+ case QPNP_ID_RGB_GREEN:
+ case QPNP_ID_RGB_BLUE:
+ led_blink(led, led->rgb_cfg->pwm_cfg);
+ break;
+ default:
+ dev_err(&led->spmi_dev->dev, "Invalid LED id type for blink\n");
+ return -EINVAL;
+ }
+ return count;
+}
+
static DEVICE_ATTR(led_mode, 0664, NULL, led_mode_store);
static DEVICE_ATTR(strobe, 0664, NULL, led_strobe_type_store);
+static DEVICE_ATTR(blink, 0664, NULL, blink_store);
static struct attribute *led_attrs[] = {
&dev_attr_led_mode.attr,
@@ -1296,6 +1411,15 @@
.attrs = led_attrs,
};
+static struct attribute *blink_attrs[] = {
+ &dev_attr_blink.attr,
+ NULL
+};
+
+static const struct attribute_group blink_attr_group = {
+ .attrs = blink_attrs,
+};
+
static int __devinit qpnp_flash_init(struct qpnp_led_data *led)
{
int rc;
@@ -1387,63 +1511,6 @@
return 0;
}
-static int __devinit qpnp_pwm_init(struct pwm_config_data *pwm_cfg,
- struct spmi_device *spmi_dev,
- const char *name)
-{
- int rc, start_idx, idx_len;
-
- if (pwm_cfg->pwm_channel != -1) {
- pwm_cfg->pwm_dev =
- pwm_request(pwm_cfg->pwm_channel, name);
-
- if (IS_ERR_OR_NULL(pwm_cfg->pwm_dev)) {
- dev_err(&spmi_dev->dev,
- "could not acquire PWM Channel %d, " \
- "error %ld\n",
- pwm_cfg->pwm_channel,
- PTR_ERR(pwm_cfg->pwm_dev));
- pwm_cfg->pwm_dev = NULL;
- return -ENODEV;
- }
-
- if (pwm_cfg->mode == LPG_MODE) {
- start_idx =
- pwm_cfg->duty_cycles->start_idx;
- idx_len =
- pwm_cfg->duty_cycles->num_duty_pcts;
-
- if (idx_len >= PWM_LUT_MAX_SIZE &&
- start_idx) {
- dev_err(&spmi_dev->dev,
- "Wrong LUT size or index\n");
- return -EINVAL;
- }
- if ((start_idx + idx_len) >
- PWM_LUT_MAX_SIZE) {
- dev_err(&spmi_dev->dev,
- "Exceed LUT limit\n");
- return -EINVAL;
- }
- rc = pwm_lut_config(pwm_cfg->pwm_dev,
- PM_PWM_PERIOD_MIN, /* ignored by hardware */
- pwm_cfg->duty_cycles->duty_pcts,
- pwm_cfg->lut_params);
- if (rc < 0) {
- dev_err(&spmi_dev->dev, "Failed to " \
- "configure pwm LUT\n");
- return rc;
- }
- }
- } else {
- dev_err(&spmi_dev->dev,
- "Invalid PWM channel\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
static int __devinit qpnp_kpdbl_init(struct qpnp_led_data *led)
{
int rc;
@@ -1845,14 +1912,18 @@
return rc;
}
- if (pwm_cfg->mode == LPG_MODE) {
+ pwm_cfg->use_blink =
+ of_property_read_bool(node, "qcom,use-blink");
+
+ if (pwm_cfg->mode == LPG_MODE || pwm_cfg->use_blink) {
pwm_cfg->duty_cycles =
devm_kzalloc(&spmi_dev->dev,
sizeof(struct pwm_duty_cycles), GFP_KERNEL);
if (!pwm_cfg->duty_cycles) {
dev_err(&spmi_dev->dev,
"Unable to allocate memory\n");
- return -ENOMEM;
+ rc = -ENOMEM;
+ goto bad_lpg_params;
}
prop = of_find_property(node, "qcom,duty-pcts",
@@ -1860,11 +1931,13 @@
if (!prop) {
dev_err(&spmi_dev->dev, "Looking up property " \
"node qcom,duty-pcts failed\n");
- return -ENODEV;
+ rc = -ENODEV;
+ goto bad_lpg_params;
} else if (!pwm_cfg->duty_cycles->num_duty_pcts) {
dev_err(&spmi_dev->dev, "Invalid length of " \
"duty pcts\n");
- return -EINVAL;
+ rc = -EINVAL;
+ goto bad_lpg_params;
}
pwm_cfg->duty_cycles->duty_pcts =
@@ -1874,7 +1947,8 @@
if (!pwm_cfg->duty_cycles->duty_pcts) {
dev_err(&spmi_dev->dev,
"Unable to allocate memory\n");
- return -ENOMEM;
+ rc = -ENOMEM;
+ goto bad_lpg_params;
}
temp_cfg = devm_kzalloc(&spmi_dev->dev,
@@ -1883,7 +1957,8 @@
if (!temp_cfg) {
dev_err(&spmi_dev->dev, "Failed to allocate " \
"memory for duty pcts\n");
- return -ENOMEM;
+ rc = -ENOMEM;
+ goto bad_lpg_params;
}
memcpy(temp_cfg, prop->value,
@@ -1898,21 +1973,21 @@
pwm_cfg->lut_params.start_idx = val;
pwm_cfg->duty_cycles->start_idx = val;
} else
- return rc;
+ goto bad_lpg_params;
pwm_cfg->lut_params.lut_pause_hi = 0;
rc = of_property_read_u32(node, "qcom,pause-hi", &val);
if (!rc)
pwm_cfg->lut_params.lut_pause_hi = val;
else if (rc != -EINVAL)
- return rc;
+ goto bad_lpg_params;
pwm_cfg->lut_params.lut_pause_lo = 0;
rc = of_property_read_u32(node, "qcom,pause-lo", &val);
if (!rc)
pwm_cfg->lut_params.lut_pause_lo = val;
else if (rc != -EINVAL)
- return rc;
+ goto bad_lpg_params;
pwm_cfg->lut_params.ramp_step_ms =
QPNP_LUT_RAMP_STEP_DEFAULT;
@@ -1920,19 +1995,28 @@
if (!rc)
pwm_cfg->lut_params.ramp_step_ms = val;
else if (rc != -EINVAL)
- return rc;
+ goto bad_lpg_params;
pwm_cfg->lut_params.flags = QPNP_LED_PWM_FLAGS;
rc = of_property_read_u32(node, "qcom,lut-flags", &val);
if (!rc)
pwm_cfg->lut_params.flags = (u8) val;
else if (rc != -EINVAL)
- return rc;
+ goto bad_lpg_params;
pwm_cfg->lut_params.idx_len =
pwm_cfg->duty_cycles->num_duty_pcts;
}
return 0;
+
+bad_lpg_params:
+ pwm_cfg->use_blink = false;
+ if (pwm_cfg->mode == PWM_MODE) {
+ dev_err(&spmi_dev->dev, "LPG parameters not set for" \
+ " blink mode, defaulting to PWM mode\n");
+ return 0;
+ }
+ return rc;
};
static int qpnp_led_get_mode(const char *mode)
@@ -2273,6 +2357,26 @@
}
+ if (led->id == QPNP_ID_LED_MPP) {
+ if (!led->mpp_cfg->pwm_cfg)
+ break;
+ if (led->mpp_cfg->pwm_cfg->use_blink) {
+ rc = sysfs_create_group(&led->cdev.dev->kobj,
+ &blink_attr_group);
+ if (rc)
+ goto fail_id_check;
+ }
+ } else if ((led->id == QPNP_ID_RGB_RED) ||
+ (led->id == QPNP_ID_RGB_GREEN) ||
+ (led->id == QPNP_ID_RGB_BLUE)) {
+ if (led->rgb_cfg->pwm_cfg->use_blink) {
+ rc = sysfs_create_group(&led->cdev.dev->kobj,
+ &blink_attr_group);
+ if (rc)
+ goto fail_id_check;
+ }
+ }
+
/* configure default state */
if (led->default_on) {
led->cdev.brightness = led->cdev.max_brightness;
diff --git a/drivers/mfd/wcd9xxx-core.c b/drivers/mfd/wcd9xxx-core.c
index 130ff48..3d0abce 100644
--- a/drivers/mfd/wcd9xxx-core.c
+++ b/drivers/mfd/wcd9xxx-core.c
@@ -283,14 +283,6 @@
},
};
-
-enum wcd9xxx_chipid_major {
- TABLA_MAJOR = cpu_to_le16(0x100),
- SITAR_MAJOR = cpu_to_le16(0x101),
- TAIKO_MAJOR = cpu_to_le16(0x102),
- TAPAN_MAJOR = cpu_to_le16(0x103),
-};
-
static const struct wcd9xxx_codec_type wcd9xxx_codecs[] = {
{
TABLA_MAJOR, cpu_to_le16(0x1), tabla1x_devs,
@@ -1729,6 +1721,7 @@
.id_table = tapan_slimtest_id,
.resume = wcd9xxx_slim_resume,
.suspend = wcd9xxx_slim_suspend,
+ .device_up = wcd9xxx_slim_device_up,
};
static struct i2c_device_id wcd9xxx_id_table[] = {
diff --git a/drivers/mfd/wcd9xxx-irq.c b/drivers/mfd/wcd9xxx-irq.c
index 5efd905..062351d 100644
--- a/drivers/mfd/wcd9xxx-irq.c
+++ b/drivers/mfd/wcd9xxx-irq.c
@@ -193,10 +193,24 @@
mutex_unlock(&wcd9xxx->nested_irq_lock);
}
-static void wcd9xxx_irq_dispatch(struct wcd9xxx *wcd9xxx, int irqbit)
+static bool wcd9xxx_is_mbhc_irq(struct wcd9xxx *wcd9xxx, int irqbit)
{
if ((irqbit <= WCD9XXX_IRQ_MBHC_INSERTION) &&
- (irqbit >= WCD9XXX_IRQ_MBHC_REMOVAL)) {
+ (irqbit >= WCD9XXX_IRQ_MBHC_REMOVAL))
+ return true;
+ else if (wcd9xxx->codec_type->id_major == TAIKO_MAJOR &&
+ irqbit == WCD9320_IRQ_MBHC_JACK_SWITCH)
+ return true;
+ else if (wcd9xxx->codec_type->id_major == TAPAN_MAJOR &&
+ irqbit == WCD9306_IRQ_MBHC_JACK_SWITCH)
+ return true;
+ else
+ return false;
+}
+
+static void wcd9xxx_irq_dispatch(struct wcd9xxx *wcd9xxx, int irqbit)
+{
+ if (wcd9xxx_is_mbhc_irq(wcd9xxx, irqbit)) {
wcd9xxx_nested_irq_lock(wcd9xxx);
wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_INTR_CLEAR0 +
BIT_BYTE(irqbit),
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 232b99b..c73bf01 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -2238,16 +2238,16 @@
goto pclk_disable;
}
- ret = clk_prepare_enable(msm_host->clk);
- if (ret)
- goto pclk_disable;
-
/* Set to the minimum supported clock frequency */
ret = clk_set_rate(msm_host->clk, sdhci_msm_get_min_clock(host));
if (ret) {
dev_err(&pdev->dev, "MClk rate set failed (%d)\n", ret);
- goto clk_disable;
+ goto pclk_disable;
}
+ ret = clk_prepare_enable(msm_host->clk);
+ if (ret)
+ goto pclk_disable;
+
msm_host->clk_rate = sdhci_msm_get_min_clock(host);
atomic_set(&msm_host->clks_on, 1);
diff --git a/drivers/video/msm/mdss/mdss_dsi_host.c b/drivers/video/msm/mdss/mdss_dsi_host.c
index 6b210af..3ee4d08 100644
--- a/drivers/video/msm/mdss/mdss_dsi_host.c
+++ b/drivers/video/msm/mdss/mdss_dsi_host.c
@@ -237,7 +237,7 @@
struct dsi_ctrl_hdr *dchdr;
char *bp;
u32 *hp;
- int i, len;
+ int i, len = 0;
dchdr = &cm->dchdr;
bp = mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
@@ -268,8 +268,9 @@
*hp |= DSI_HDR_LAST;
mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+ len += DSI_HOST_HDR_SIZE;
- return dp->len;
+ return len;
}
/*
@@ -312,8 +313,7 @@
}
mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-
- return dp->len; /* 4 bytes */
+ return DSI_HOST_HDR_SIZE; /* 4 bytes */
}
/*
@@ -356,7 +356,7 @@
}
mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
- return dp->len; /* 4 bytes */
+ return DSI_HOST_HDR_SIZE; /* 4 bytes */
}
/*
@@ -367,7 +367,7 @@
struct dsi_ctrl_hdr *dchdr;
char *bp;
u32 *hp;
- int i, len;
+ int i, len = 0;
dchdr = &cm->dchdr;
bp = mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
@@ -402,7 +402,8 @@
mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
- return dp->len;
+ len += DSI_HOST_HDR_SIZE;
+ return len;
}
/*
@@ -436,7 +437,7 @@
*hp |= DSI_HDR_DATA2(0);
mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
- return dp->len;
+ return DSI_HOST_HDR_SIZE; /* 4 bytes */
}
/*
@@ -467,8 +468,7 @@
*hp |= DSI_HDR_DATA2(cm->payload[1]); /* parameter */
mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-
- return dp->len;
+ return DSI_HOST_HDR_SIZE; /* 4 bytes */
}
/*
* mipi dsi dcs read with 0 parameters
@@ -498,8 +498,7 @@
*hp |= DSI_HDR_DATA2(0);
mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-
- return dp->len; /* 4 bytes */
+ return DSI_HOST_HDR_SIZE; /* 4 bytes */
}
static int mdss_dsi_cm_on(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
@@ -517,8 +516,7 @@
*hp |= DSI_HDR_LAST;
mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-
- return dp->len; /* 4 bytes */
+ return DSI_HOST_HDR_SIZE; /* 4 bytes */
}
static int mdss_dsi_cm_off(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
@@ -536,8 +534,7 @@
*hp |= DSI_HDR_LAST;
mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-
- return dp->len; /* 4 bytes */
+ return DSI_HOST_HDR_SIZE; /* 4 bytes */
}
static int mdss_dsi_peripheral_on(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
@@ -555,8 +552,7 @@
*hp |= DSI_HDR_LAST;
mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-
- return dp->len; /* 4 bytes */
+ return DSI_HOST_HDR_SIZE; /* 4 bytes */
}
static int mdss_dsi_peripheral_off(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
@@ -574,8 +570,7 @@
*hp |= DSI_HDR_LAST;
mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-
- return dp->len; /* 4 bytes */
+ return DSI_HOST_HDR_SIZE; /* 4 bytes */
}
static int mdss_dsi_set_max_pktsize(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
@@ -601,8 +596,7 @@
*hp |= DSI_HDR_DATA2(cm->payload[1]);
mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-
- return dp->len; /* 4 bytes */
+ return DSI_HOST_HDR_SIZE; /* 4 bytes */
}
static int mdss_dsi_null_pkt(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
@@ -622,8 +616,7 @@
*hp |= DSI_HDR_LAST;
mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-
- return dp->len; /* 4 bytes */
+ return DSI_HOST_HDR_SIZE; /* 4 bytes */
}
static int mdss_dsi_blank_pkt(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
@@ -643,8 +636,7 @@
*hp |= DSI_HDR_LAST;
mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-
- return dp->len; /* 4 bytes */
+ return DSI_HOST_HDR_SIZE; /* 4 bytes */
}
/*
@@ -1134,12 +1126,44 @@
return 4;
}
-
static int mdss_dsi_cmd_dma_tx(struct mdss_dsi_ctrl_pdata *ctrl,
struct dsi_buf *tp);
static int mdss_dsi_cmd_dma_rx(struct mdss_dsi_ctrl_pdata *ctrl,
struct dsi_buf *rp, int rlen);
+
+static int mdss_dsi_cmds2buf_tx(struct mdss_dsi_ctrl_pdata *ctrl,
+ struct dsi_cmd_desc *cmds, int cnt)
+{
+ struct dsi_buf *tp;
+ struct dsi_cmd_desc *cm;
+ struct dsi_ctrl_hdr *dchdr;
+ int len, tot = 0;
+
+ tp = &ctrl->tx_buf;
+ mdss_dsi_buf_init(tp);
+ cm = cmds;
+ len = 0;
+ while (cnt--) {
+ dchdr = &cm->dchdr;
+ mdss_dsi_buf_reserve(tp, len);
+ len = mdss_dsi_cmd_dma_add(tp, cm);
+ tot += len;
+ if (dchdr->last) {
+ tp->data = tp->start; /* begin of buf */
+ mdss_dsi_enable_irq(ctrl, DSI_CMD_TERM);
+ mdss_dsi_cmd_dma_tx(ctrl, tp);
+ if (dchdr->wait)
+ usleep(dchdr->wait * 1000);
+
+ mdss_dsi_buf_init(tp);
+ len = 0;
+ }
+ cm++;
+ }
+ return tot;
+}
+
/*
* mdss_dsi_cmds_tx:
* thread context only
@@ -1147,11 +1171,8 @@
int mdss_dsi_cmds_tx(struct mdss_dsi_ctrl_pdata *ctrl,
struct dsi_cmd_desc *cmds, int cnt)
{
- struct dsi_buf *tp;
- struct dsi_cmd_desc *cm;
- struct dsi_ctrl_hdr *dchdr;
u32 dsi_ctrl, data;
- int i, video_mode;
+ int video_mode;
if (ctrl->shared_pdata.broadcast_enable) {
if (ctrl->ndx == DSI_CTRL_0) {
@@ -1187,18 +1208,7 @@
MIPI_OUTP((ctrl->ctrl_base) + 0x0004, data);
}
- tp = &ctrl->tx_buf;
- cm = cmds;
- for (i = 0; i < cnt; i++) {
- mdss_dsi_enable_irq(ctrl, DSI_CMD_TERM);
- mdss_dsi_buf_init(tp);
- mdss_dsi_cmd_dma_add(tp, cm);
- mdss_dsi_cmd_dma_tx(ctrl, tp);
- dchdr = &cm->dchdr;
- if (dchdr->wait)
- usleep(dchdr->wait * 1000);
- cm++;
- }
+ mdss_dsi_cmds2buf_tx(ctrl, cmds, cnt);
if (video_mode)
MIPI_OUTP((ctrl->ctrl_base) + 0x0004,
@@ -1438,6 +1448,13 @@
void mdss_dsi_wait4video_done(struct mdss_dsi_ctrl_pdata *ctrl)
{
unsigned long flag;
+ u32 data;
+
+ /* DSI_INTL_CTRL */
+ data = MIPI_INP((ctrl->ctrl_base) + 0x0110);
+ data |= DSI_INTR_VIDEO_DONE_MASK;
+
+ MIPI_OUTP((ctrl->ctrl_base) + 0x0110, data);
spin_lock_irqsave(&ctrl->mdp_lock, flag);
INIT_COMPLETION(ctrl->video_comp);
@@ -1446,6 +1463,10 @@
wait_for_completion_timeout(&ctrl->video_comp,
msecs_to_jiffies(VSYNC_PERIOD * 4));
+
+ data = MIPI_INP((ctrl->ctrl_base) + 0x0110);
+ data &= ~DSI_INTR_VIDEO_DONE_MASK;
+ MIPI_OUTP((ctrl->ctrl_base) + 0x0110, data);
}
static void mdss_dsi_wait4video_eng_busy(struct mdss_dsi_ctrl_pdata *ctrl)
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
index 238170d..bd4f3ea 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
@@ -440,7 +440,7 @@
null_handle.vsync_handler = NULL;
mdss_mdp_cmd_vsync_ctrl(ctl, &null_handle);
- mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_RD_PTR, ctl->intf_num,
+ mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_RD_PTR, ctx->pp_num,
NULL, NULL);
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_COMP, ctx->pp_num,
NULL, NULL);
diff --git a/drivers/video/msm/mdss/mdss_mdp_wb.c b/drivers/video/msm/mdss/mdss_mdp_wb.c
index 1f8244d..0bb68f9 100644
--- a/drivers/video/msm/mdss/mdss_mdp_wb.c
+++ b/drivers/video/msm/mdss/mdss_mdp_wb.c
@@ -251,8 +251,8 @@
if (wb->secure_pipe)
mdss_mdp_pipe_destroy(wb->secure_pipe);
mutex_unlock(&wb->lock);
-
- mdp5_data->ctl->is_secure = false;
+ if (mdp5_data->ctl)
+ mdp5_data->ctl->is_secure = false;
mdp5_data->wb = NULL;
mutex_unlock(&mdss_mdp_wb_buf_lock);
diff --git a/include/linux/coresight-stm.h b/include/linux/coresight-stm.h
index 3f35dd9..298fc9a 100644
--- a/include/linux/coresight-stm.h
+++ b/include/linux/coresight-stm.h
@@ -7,6 +7,7 @@
OST_ENTITY_TRACE_PRINTK = 0x02,
OST_ENTITY_TRACE_MARKER = 0x04,
OST_ENTITY_DEV_NODE = 0x08,
+ OST_ENTITY_DIAG = 0xEE,
OST_ENTITY_QVIEW = 0xFE,
OST_ENTITY_MAX = 0xFF,
};
diff --git a/include/linux/mfd/wcd9xxx/core.h b/include/linux/mfd/wcd9xxx/core.h
index 0d1f49f..e688bd9 100644
--- a/include/linux/mfd/wcd9xxx/core.h
+++ b/include/linux/mfd/wcd9xxx/core.h
@@ -76,7 +76,8 @@
WCD9XXX_IRQ_EAR_PA_OCPL_FAULT,
WCD9XXX_IRQ_HPH_L_PA_STARTUP,
WCD9XXX_IRQ_HPH_R_PA_STARTUP,
- WCD9XXX_IRQ_EAR_PA_STARTUP,
+ WCD9320_IRQ_EAR_PA_STARTUP,
+ WCD9306_IRQ_MBHC_JACK_SWITCH = WCD9320_IRQ_EAR_PA_STARTUP,
WCD9310_NUM_IRQS,
WCD9XXX_IRQ_RESERVED_0 = WCD9310_NUM_IRQS,
WCD9XXX_IRQ_RESERVED_1,
@@ -85,7 +86,7 @@
WCD9XXX_IRQ_MAD_BEACON,
WCD9XXX_IRQ_MAD_ULTRASOUND,
WCD9XXX_IRQ_SPEAKER_CLIPPING,
- WCD9XXX_IRQ_MBHC_JACK_SWITCH,
+ WCD9320_IRQ_MBHC_JACK_SWITCH,
WCD9XXX_IRQ_VBAT_MONITOR_ATTACK,
WCD9XXX_IRQ_VBAT_MONITOR_RELEASE,
WCD9XXX_NUM_IRQS,
@@ -153,6 +154,13 @@
#define WCD9XXX_CH(xport, xshift) \
{.port = xport, .shift = xshift}
+enum wcd9xxx_chipid_major {
+ TABLA_MAJOR = cpu_to_le16(0x100),
+ SITAR_MAJOR = cpu_to_le16(0x101),
+ TAIKO_MAJOR = cpu_to_le16(0x102),
+ TAPAN_MAJOR = cpu_to_le16(0x103),
+};
+
struct wcd9xxx_codec_type {
u16 id_major;
u16 id_minor;
diff --git a/sound/soc/codecs/wcd9306.c b/sound/soc/codecs/wcd9306.c
index 6cdbb8c..8ae6050 100644
--- a/sound/soc/codecs/wcd9306.c
+++ b/sound/soc/codecs/wcd9306.c
@@ -4325,6 +4325,23 @@
snd_soc_write(codec, TAPAN_A_SPKR_DRV_EN, 0xEF);
}
+static void tapan_update_reg_mclk_rate(struct wcd9xxx *wcd9xxx)
+{
+ struct snd_soc_codec *codec;
+
+ codec = (struct snd_soc_codec *)(wcd9xxx->ssr_priv);
+ dev_dbg(codec->dev, "%s: MCLK Rate = %x\n",
+ __func__, wcd9xxx->mclk_rate);
+
+ if (wcd9xxx->mclk_rate == TAPAN_MCLK_CLK_12P288MHZ) {
+ snd_soc_update_bits(codec, TAPAN_A_CHIP_CTL, 0x06, 0x0);
+ snd_soc_update_bits(codec, TAPAN_A_RX_COM_TIMER_DIV, 0x01,
+ 0x01);
+ } else if (wcd9xxx->mclk_rate == TAPAN_MCLK_CLK_9P6MHZ) {
+ snd_soc_update_bits(codec, TAPAN_A_CHIP_CTL, 0x06, 0x2);
+ }
+}
+
static const struct tapan_reg_mask_val tapan_codec_reg_init_val[] = {
/* Initialize current threshold to 350MA
* number of wait and run cycles to 4096
@@ -4395,26 +4412,29 @@
tapan_codec_reg_init_val[i].mask,
tapan_codec_reg_init_val[i].val);
}
-
-static int tapan_setup_irqs(struct tapan_priv *tapan)
+static void tapan_slim_interface_init_reg(struct snd_soc_codec *codec)
{
int i;
- int ret = 0;
- struct snd_soc_codec *codec = tapan->codec;
-
- ret = wcd9xxx_request_irq(codec->control_data, WCD9XXX_IRQ_SLIMBUS,
- tapan_slimbus_irq, "SLIMBUS Slave", tapan);
- if (ret) {
- pr_err("%s: Failed to request irq %d\n", __func__,
- WCD9XXX_IRQ_SLIMBUS);
- goto exit;
- }
for (i = 0; i < WCD9XXX_SLIM_NUM_PORT_REG; i++)
wcd9xxx_interface_reg_write(codec->control_data,
TAPAN_SLIM_PGD_PORT_INT_EN0 + i,
0xFF);
-exit:
+}
+
+static int tapan_setup_irqs(struct tapan_priv *tapan)
+{
+ int ret = 0;
+ struct snd_soc_codec *codec = tapan->codec;
+
+ ret = wcd9xxx_request_irq(codec->control_data, WCD9XXX_IRQ_SLIMBUS,
+ tapan_slimbus_irq, "SLIMBUS Slave", tapan);
+ if (ret)
+ pr_err("%s: Failed to request irq %d\n", __func__,
+ WCD9XXX_IRQ_SLIMBUS);
+ else
+ tapan_slim_interface_init_reg(codec);
+
return ret;
}
@@ -4432,9 +4452,74 @@
}
EXPORT_SYMBOL_GPL(tapan_hs_detect);
+static int tapan_post_reset_cb(struct wcd9xxx *wcd9xxx)
+{
+ int ret = 0;
+ int rco_clk_rate;
+ struct snd_soc_codec *codec;
+ struct tapan_priv *tapan;
+
+ codec = (struct snd_soc_codec *)(wcd9xxx->ssr_priv);
+ tapan = snd_soc_codec_get_drvdata(codec);
+ mutex_lock(&codec->mutex);
+ WCD9XXX_BCL_LOCK(&tapan->resmgr);
+
+ if (codec->reg_def_copy) {
+ pr_debug("%s: Update ASOC cache", __func__);
+ kfree(codec->reg_cache);
+ codec->reg_cache = kmemdup(codec->reg_def_copy,
+ codec->reg_size, GFP_KERNEL);
+ if (!codec->reg_cache) {
+ pr_err("%s: Cache update failed!\n", __func__);
+ WCD9XXX_BCL_UNLOCK(&tapan->resmgr);
+ mutex_unlock(&codec->mutex);
+ return -ENOMEM;
+ }
+ }
+
+ wcd9xxx_resmgr_post_ssr(&tapan->resmgr);
+ if (spkr_drv_wrnd == 1)
+ snd_soc_update_bits(codec, TAPAN_A_SPKR_DRV_EN, 0x80, 0x80);
+ WCD9XXX_BCL_UNLOCK(&tapan->resmgr);
+
+ tapan_update_reg_defaults(codec);
+ tapan_update_reg_mclk_rate(wcd9xxx);
+ tapan_codec_init_reg(codec);
+ ret = tapan_handle_pdata(tapan);
+ if (IS_ERR_VALUE(ret))
+ pr_err("%s: bad pdata\n", __func__);
+
+ tapan_slim_interface_init_reg(codec);
+
+ wcd9xxx_mbhc_deinit(&tapan->mbhc);
+
+ if (TAPAN_IS_1_0(wcd9xxx->version))
+ rco_clk_rate = TAPAN_MCLK_CLK_12P288MHZ;
+ else
+ rco_clk_rate = TAPAN_MCLK_CLK_9P6MHZ;
+
+ ret = wcd9xxx_mbhc_init(&tapan->mbhc, &tapan->resmgr, codec, NULL,
+ WCD9XXX_MBHC_VERSION_TAPAN,
+ rco_clk_rate);
+ if (ret)
+ pr_err("%s: mbhc init failed %d\n", __func__, ret);
+ else
+ wcd9xxx_mbhc_start(&tapan->mbhc, tapan->mbhc.mbhc_cfg);
+ mutex_unlock(&codec->mutex);
+ return ret;
+}
+
static struct wcd9xxx_reg_address tapan_reg_address = {
};
+static int wcd9xxx_ssr_register(struct wcd9xxx *control,
+ int (*post_reset_cb)(struct wcd9xxx *wcd9xxx), void *priv)
+{
+ control->post_reset = post_reset_cb;
+ control->ssr_priv = priv;
+ return 0;
+}
+
static int tapan_codec_probe(struct snd_soc_codec *codec)
{
struct wcd9xxx *control;
@@ -4449,6 +4534,8 @@
codec->control_data = dev_get_drvdata(codec->dev->parent);
control = codec->control_data;
+ wcd9xxx_ssr_register(control, tapan_post_reset_cb, (void *)codec);
+
dev_info(codec->dev, "%s()\n", __func__);
tapan = kzalloc(sizeof(struct tapan_priv), GFP_KERNEL);
@@ -4502,17 +4589,7 @@
tapan->aux_l_gain = 0x1F;
tapan->aux_r_gain = 0x1F;
tapan_update_reg_defaults(codec);
-
- dev_dbg(codec->dev, "%s: MCLK Rate = %x\n",
- __func__, wcd9xxx->mclk_rate);
-
- if (wcd9xxx->mclk_rate == TAPAN_MCLK_CLK_12P288MHZ) {
- snd_soc_update_bits(codec, TAPAN_A_CHIP_CTL, 0x06, 0x0);
- snd_soc_update_bits(codec, TAPAN_A_RX_COM_TIMER_DIV, 0x01,
- 0x01);
- } else if (wcd9xxx->mclk_rate == TAPAN_MCLK_CLK_9P6MHZ) {
- snd_soc_update_bits(codec, TAPAN_A_CHIP_CTL, 0x06, 0x2);
- }
+ tapan_update_reg_mclk_rate(wcd9xxx);
tapan_codec_init_reg(codec);
ret = tapan_handle_pdata(tapan);
if (IS_ERR_VALUE(ret)) {
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.c b/sound/soc/codecs/wcd9xxx-mbhc.c
index 6977400..e853061 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.c
+++ b/sound/soc/codecs/wcd9xxx-mbhc.c
@@ -94,9 +94,6 @@
#define WCD9XXX_USLEEP_RANGE_MARGIN_US 1000
-#define WCD9XXX_IRQ_MBHC_JACK_SWITCH_TAIKO 28
-#define WCD9XXX_IRQ_MBHC_JACK_SWITCH_TAPAN 21
-
static bool detect_use_vddio_switch = true;
struct wcd9xxx_mbhc_detect {
@@ -3115,10 +3112,10 @@
switch (mbhc->mbhc_version) {
case WCD9XXX_MBHC_VERSION_TAIKO:
- jack_irq = WCD9XXX_IRQ_MBHC_JACK_SWITCH_TAIKO;
+ jack_irq = WCD9320_IRQ_MBHC_JACK_SWITCH;
break;
case WCD9XXX_MBHC_VERSION_TAPAN:
- jack_irq = WCD9XXX_IRQ_MBHC_JACK_SWITCH_TAPAN;
+ jack_irq = WCD9306_IRQ_MBHC_JACK_SWITCH;
break;
default:
return -EINVAL;
@@ -3800,7 +3797,18 @@
wcd9xxx_free_irq(cdata, WCD9XXX_IRQ_MBHC_REMOVAL, mbhc);
wcd9xxx_free_irq(cdata, WCD9XXX_IRQ_MBHC_INSERTION, mbhc);
- wcd9xxx_free_irq(cdata, WCD9XXX_IRQ_MBHC_JACK_SWITCH, mbhc);
+ switch (mbhc->mbhc_version) {
+ case WCD9XXX_MBHC_VERSION_TAIKO:
+ wcd9xxx_free_irq(cdata, WCD9320_IRQ_MBHC_JACK_SWITCH, mbhc);
+ break;
+ case WCD9XXX_MBHC_VERSION_TAPAN:
+ wcd9xxx_free_irq(cdata, WCD9306_IRQ_MBHC_JACK_SWITCH, mbhc);
+ break;
+ default:
+ pr_err("%s: irq free failed! Invalid MBHC version %d\n",
+ __func__, mbhc->mbhc_version);
+ }
+
wcd9xxx_free_irq(cdata, WCD9XXX_IRQ_HPH_PA_OCPL_FAULT, mbhc);
wcd9xxx_free_irq(cdata, WCD9XXX_IRQ_HPH_PA_OCPR_FAULT, mbhc);