Merge "msm: kgsl: Add MEM_WRITE type for postmortem dump"
diff --git a/Documentation/devicetree/bindings/platform/msm/qpnp-power-on.txt b/Documentation/devicetree/bindings/platform/msm/qpnp-power-on.txt
index 46b39ec..21d376a 100644
--- a/Documentation/devicetree/bindings/platform/msm/qpnp-power-on.txt
+++ b/Documentation/devicetree/bindings/platform/msm/qpnp-power-on.txt
@@ -13,7 +13,7 @@
- interrupts: Specifies the interrupt associated with PON.
Optional properties:
-- qcom,pon-dbc-delay: The debouce delay for the power-key interrupt
+- qcom,pon-dbc-delay The debouce delay for the power-key interrupt
specifed in us. The value ranges from 2 seconds
to 1/64 of a second. Possible values are -
- 2, 1, 1/2, 1/4, 1/8, 1/16, 1/32, 1/64
@@ -24,11 +24,15 @@
reset source. All the child nodes are optional,
if none of them are specified the driver fails
to register.
+- qcom,system-reset Specifies that this PON peripheral can be used
+ to reset the system. This property can only be
+ used by one device on the system. It is an error
+ to include it more than once.
All the below properties are in the sub-node section (properties of the child
node).
-- qcom,pull-up: The initial state of the reset pin under
+- qcom,pull-up The initial state of the reset pin under
consideration.
0 = No pull-up
1 = pull-up enabled
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index 0f5fd1c..facb1a8 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -30,6 +30,7 @@
<0x0 0x8 0x4>;
interrupt-names = "kpdpwr", "resin", "resin-bark";
qcom,pon-dbc-delay = <15625>;
+ qcom,system-reset;
qcom,pon_1 {
qcom,pon-type = <0>;
diff --git a/arch/arm/boot/dts/msm8974_pm.dtsi b/arch/arm/boot/dts/msm8974_pm.dtsi
index f3efbb8..8e3f4b8 100644
--- a/arch/arm/boot/dts/msm8974_pm.dtsi
+++ b/arch/arm/boot/dts/msm8974_pm.dtsi
@@ -309,8 +309,9 @@
qcom,ipc-bit-offset = <1>;
qcom,gic-parent = <&intc>;
- qcom,gic-map = <47 180>, /* usb2_hsic_async_wakeup_irq */
+ qcom,gic-map = <47 172>, /* usb2_hsic_async_wakeup_irq */
<53 104>, /* mdss_irq */
+ <62 222>, /* ee0_krait_hlos_spmi_periph_irq */
<0xff 57>, /* mss_to_apps_irq(0) */
<0xff 58>, /* mss_to_apps_irq(1) */
<0xff 59>, /* mss_to_apps_irq(2) */
diff --git a/arch/arm/configs/msm7627a-perf_defconfig b/arch/arm/configs/msm7627a-perf_defconfig
index 1b792d9..7f10641 100644
--- a/arch/arm/configs/msm7627a-perf_defconfig
+++ b/arch/arm/configs/msm7627a-perf_defconfig
@@ -283,6 +283,7 @@
CONFIG_ION=y
CONFIG_ION_MSM=y
CONFIG_MSM_KGSL=y
+CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES=y
CONFIG_FB=y
CONFIG_FB_MSM=y
# CONFIG_FB_MSM_BACKLIGHT is not set
diff --git a/arch/arm/configs/msm7627a_defconfig b/arch/arm/configs/msm7627a_defconfig
index aeb59af..0e0653f 100644
--- a/arch/arm/configs/msm7627a_defconfig
+++ b/arch/arm/configs/msm7627a_defconfig
@@ -285,6 +285,7 @@
CONFIG_ION=y
CONFIG_ION_MSM=y
CONFIG_MSM_KGSL=y
+CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES=y
CONFIG_FB=y
CONFIG_FB_MSM=y
# CONFIG_FB_MSM_BACKLIGHT is not set
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index b08869a..db184cd 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -69,6 +69,7 @@
CONFIG_MSM_DSPS=y
CONFIG_MSM_IPC_ROUTER=y
CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
+CONFIG_MSM_AVS_HW=y
# CONFIG_MSM_HW3D is not set
CONFIG_MSM_PIL_QDSP6V4=y
CONFIG_MSM_PIL_RIVA=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 26e7f32..5415425 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -68,6 +68,7 @@
CONFIG_MSM_DSPS=y
CONFIG_MSM_IPC_ROUTER=y
CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
+CONFIG_MSM_AVS_HW=y
# CONFIG_MSM_HW3D is not set
CONFIG_MSM_PIL_QDSP6V4=y
CONFIG_MSM_PIL_RIVA=y
diff --git a/arch/arm/mach-msm/acpuclock-8064.c b/arch/arm/mach-msm/acpuclock-8064.c
index 3c80875..06c2579 100644
--- a/arch/arm/mach-msm/acpuclock-8064.c
+++ b/arch/arm/mach-msm/acpuclock-8064.c
@@ -219,7 +219,7 @@
.l2_freq_tbl = l2_freq_tbl,
.l2_freq_tbl_size = sizeof(l2_freq_tbl),
.bus_scale = &bus_scale_data,
- .qfprom_phys_base = 0x00700000,
+ .pte_efuse_phys = 0x007000C0,
.stby_khz = 384000,
};
diff --git a/arch/arm/mach-msm/acpuclock-8627.c b/arch/arm/mach-msm/acpuclock-8627.c
index 07a7f8f..9e6662d 100644
--- a/arch/arm/mach-msm/acpuclock-8627.c
+++ b/arch/arm/mach-msm/acpuclock-8627.c
@@ -138,7 +138,7 @@
.l2_freq_tbl = l2_freq_tbl,
.l2_freq_tbl_size = sizeof(l2_freq_tbl),
.bus_scale = &bus_scale_data,
- .qfprom_phys_base = 0x00700000,
+ .pte_efuse_phys = 0x007000C0,
.stby_khz = 384000,
};
diff --git a/arch/arm/mach-msm/acpuclock-8930.c b/arch/arm/mach-msm/acpuclock-8930.c
index 77876ee..b8ca865 100644
--- a/arch/arm/mach-msm/acpuclock-8930.c
+++ b/arch/arm/mach-msm/acpuclock-8930.c
@@ -221,7 +221,7 @@
.l2_freq_tbl = l2_freq_tbl,
.l2_freq_tbl_size = sizeof(l2_freq_tbl),
.bus_scale = &bus_scale_data,
- .qfprom_phys_base = 0x00700000,
+ .pte_efuse_phys = 0x007000C0,
.stby_khz = 384000,
};
diff --git a/arch/arm/mach-msm/acpuclock-8930aa.c b/arch/arm/mach-msm/acpuclock-8930aa.c
index dbc3e32..d589f1a 100644
--- a/arch/arm/mach-msm/acpuclock-8930aa.c
+++ b/arch/arm/mach-msm/acpuclock-8930aa.c
@@ -200,7 +200,7 @@
.l2_freq_tbl = l2_freq_tbl,
.l2_freq_tbl_size = sizeof(l2_freq_tbl),
.bus_scale = &bus_scale_data,
- .qfprom_phys_base = 0x00700000,
+ .pte_efuse_phys = 0x007000C0,
.stby_khz = 384000,
};
diff --git a/arch/arm/mach-msm/acpuclock-8960.c b/arch/arm/mach-msm/acpuclock-8960.c
index 631bd7e..e16c6b6 100644
--- a/arch/arm/mach-msm/acpuclock-8960.c
+++ b/arch/arm/mach-msm/acpuclock-8960.c
@@ -112,8 +112,10 @@
{ }
};
+#define AVS(x) .avsdscr_setting = (x)
+
static struct acpu_level acpu_freq_tbl_slow[] __initdata = {
- { 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(0), 950000 },
+ { 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(0), 950000, AVS(0x40001F) },
{ 0, { 432000, HFPLL, 2, 0, 0x20 }, L2(6), 975000 },
{ 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(6), 975000 },
{ 0, { 540000, HFPLL, 2, 0, 0x28 }, L2(6), 1000000 },
@@ -126,20 +128,20 @@
{ 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(6), 1100000 },
{ 0, { 972000, HFPLL, 1, 0, 0x24 }, L2(6), 1125000 },
{ 1, { 1026000, HFPLL, 1, 0, 0x26 }, L2(6), 1125000 },
- { 0, { 1080000, HFPLL, 1, 0, 0x28 }, L2(18), 1175000 },
- { 1, { 1134000, HFPLL, 1, 0, 0x2A }, L2(18), 1175000 },
- { 0, { 1188000, HFPLL, 1, 0, 0x2C }, L2(18), 1200000 },
- { 1, { 1242000, HFPLL, 1, 0, 0x2E }, L2(18), 1200000 },
- { 0, { 1296000, HFPLL, 1, 0, 0x30 }, L2(18), 1225000 },
- { 1, { 1350000, HFPLL, 1, 0, 0x32 }, L2(18), 1225000 },
- { 0, { 1404000, HFPLL, 1, 0, 0x34 }, L2(18), 1237500 },
- { 1, { 1458000, HFPLL, 1, 0, 0x36 }, L2(18), 1237500 },
- { 1, { 1512000, HFPLL, 1, 0, 0x38 }, L2(18), 1250000 },
+ { 0, { 1080000, HFPLL, 1, 0, 0x28 }, L2(18), 1175000, AVS(0x400015) },
+ { 1, { 1134000, HFPLL, 1, 0, 0x2A }, L2(18), 1175000, AVS(0x400015) },
+ { 0, { 1188000, HFPLL, 1, 0, 0x2C }, L2(18), 1200000, AVS(0x400015) },
+ { 1, { 1242000, HFPLL, 1, 0, 0x2E }, L2(18), 1200000, AVS(0x400015) },
+ { 0, { 1296000, HFPLL, 1, 0, 0x30 }, L2(18), 1225000, AVS(0x400015) },
+ { 1, { 1350000, HFPLL, 1, 0, 0x32 }, L2(18), 1225000, AVS(0x400015) },
+ { 0, { 1404000, HFPLL, 1, 0, 0x34 }, L2(18), 1237500, AVS(0x400015) },
+ { 1, { 1458000, HFPLL, 1, 0, 0x36 }, L2(18), 1237500, AVS(0x100018) },
+ { 1, { 1512000, HFPLL, 1, 0, 0x38 }, L2(18), 1250000, AVS(0x400012) },
{ 0, { 0 } }
};
static struct acpu_level acpu_freq_tbl_nom[] __initdata = {
- { 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(0), 900000 },
+ { 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(0), 900000, AVS(0x40007F) },
{ 0, { 432000, HFPLL, 2, 0, 0x20 }, L2(6), 925000 },
{ 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(6), 925000 },
{ 0, { 540000, HFPLL, 2, 0, 0x28 }, L2(6), 950000 },
@@ -152,20 +154,20 @@
{ 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(6), 1050000 },
{ 0, { 972000, HFPLL, 1, 0, 0x24 }, L2(6), 1075000 },
{ 1, { 1026000, HFPLL, 1, 0, 0x26 }, L2(6), 1075000 },
- { 0, { 1080000, HFPLL, 1, 0, 0x28 }, L2(18), 1125000 },
- { 1, { 1134000, HFPLL, 1, 0, 0x2A }, L2(18), 1125000 },
- { 0, { 1188000, HFPLL, 1, 0, 0x2C }, L2(18), 1150000 },
- { 1, { 1242000, HFPLL, 1, 0, 0x2E }, L2(18), 1150000 },
- { 0, { 1296000, HFPLL, 1, 0, 0x30 }, L2(18), 1175000 },
- { 1, { 1350000, HFPLL, 1, 0, 0x32 }, L2(18), 1175000 },
- { 0, { 1404000, HFPLL, 1, 0, 0x34 }, L2(18), 1187500 },
- { 1, { 1458000, HFPLL, 1, 0, 0x36 }, L2(18), 1187500 },
- { 1, { 1512000, HFPLL, 1, 0, 0x38 }, L2(18), 1200000 },
+ { 0, { 1080000, HFPLL, 1, 0, 0x28 }, L2(18), 1125000, AVS(0x400015) },
+ { 1, { 1134000, HFPLL, 1, 0, 0x2A }, L2(18), 1125000, AVS(0x400015) },
+ { 0, { 1188000, HFPLL, 1, 0, 0x2C }, L2(18), 1150000, AVS(0x400015) },
+ { 1, { 1242000, HFPLL, 1, 0, 0x2E }, L2(18), 1150000, AVS(0x400015) },
+ { 0, { 1296000, HFPLL, 1, 0, 0x30 }, L2(18), 1175000, AVS(0x400015) },
+ { 1, { 1350000, HFPLL, 1, 0, 0x32 }, L2(18), 1175000, AVS(0x400015) },
+ { 0, { 1404000, HFPLL, 1, 0, 0x34 }, L2(18), 1187500, AVS(0x400015) },
+ { 1, { 1458000, HFPLL, 1, 0, 0x36 }, L2(18), 1187500, AVS(0x100018) },
+ { 1, { 1512000, HFPLL, 1, 0, 0x38 }, L2(18), 1200000, AVS(0x400012) },
{ 0, { 0 } }
};
static struct acpu_level acpu_freq_tbl_fast[] __initdata = {
- { 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(0), 850000 },
+ { 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(0), 850000, AVS(0x4000FF) },
{ 0, { 432000, HFPLL, 2, 0, 0x20 }, L2(6), 875000 },
{ 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(6), 875000 },
{ 0, { 540000, HFPLL, 2, 0, 0x28 }, L2(6), 900000 },
@@ -178,15 +180,15 @@
{ 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(6), 1000000 },
{ 0, { 972000, HFPLL, 1, 0, 0x24 }, L2(6), 1025000 },
{ 1, { 1026000, HFPLL, 1, 0, 0x26 }, L2(6), 1025000 },
- { 0, { 1080000, HFPLL, 1, 0, 0x28 }, L2(18), 1075000 },
- { 1, { 1134000, HFPLL, 1, 0, 0x2A }, L2(18), 1075000 },
- { 0, { 1188000, HFPLL, 1, 0, 0x2C }, L2(18), 1100000 },
- { 1, { 1242000, HFPLL, 1, 0, 0x2E }, L2(18), 1100000 },
- { 0, { 1296000, HFPLL, 1, 0, 0x30 }, L2(18), 1125000 },
- { 1, { 1350000, HFPLL, 1, 0, 0x32 }, L2(18), 1125000 },
- { 0, { 1404000, HFPLL, 1, 0, 0x34 }, L2(18), 1137500 },
- { 1, { 1458000, HFPLL, 1, 0, 0x36 }, L2(18), 1137500 },
- { 1, { 1512000, HFPLL, 1, 0, 0x38 }, L2(18), 1150000 },
+ { 0, { 1080000, HFPLL, 1, 0, 0x28 }, L2(18), 1075000, AVS(0x10001B) },
+ { 1, { 1134000, HFPLL, 1, 0, 0x2A }, L2(18), 1075000, AVS(0x10001B) },
+ { 0, { 1188000, HFPLL, 1, 0, 0x2C }, L2(18), 1100000, AVS(0x10001B) },
+ { 1, { 1242000, HFPLL, 1, 0, 0x2E }, L2(18), 1100000, AVS(0x10001B) },
+ { 0, { 1296000, HFPLL, 1, 0, 0x30 }, L2(18), 1125000, AVS(0x10001B) },
+ { 1, { 1350000, HFPLL, 1, 0, 0x32 }, L2(18), 1125000, AVS(0x400012) },
+ { 0, { 1404000, HFPLL, 1, 0, 0x34 }, L2(18), 1137500, AVS(0x400012) },
+ { 1, { 1458000, HFPLL, 1, 0, 0x36 }, L2(18), 1137500, AVS(0x400012) },
+ { 1, { 1512000, HFPLL, 1, 0, 0x38 }, L2(18), 1150000, AVS(0x400012) },
{ 0, { 0 } }
};
@@ -204,7 +206,7 @@
.l2_freq_tbl = l2_freq_tbl,
.l2_freq_tbl_size = sizeof(l2_freq_tbl),
.bus_scale = &bus_scale_data,
- .qfprom_phys_base = 0x00700000,
+ .pte_efuse_phys = 0x007000C0,
.stby_khz = 384000,
};
diff --git a/arch/arm/mach-msm/acpuclock-8960ab.c b/arch/arm/mach-msm/acpuclock-8960ab.c
index 63bff55..628e1ba 100644
--- a/arch/arm/mach-msm/acpuclock-8960ab.c
+++ b/arch/arm/mach-msm/acpuclock-8960ab.c
@@ -146,7 +146,7 @@
.l2_freq_tbl = l2_freq_tbl,
.l2_freq_tbl_size = sizeof(l2_freq_tbl),
.bus_scale = &bus_scale_data,
- .qfprom_phys_base = 0x00700000,
+ .pte_efuse_phys = 0x007000C0,
.stby_khz = 384000,
};
diff --git a/arch/arm/mach-msm/acpuclock-8974.c b/arch/arm/mach-msm/acpuclock-8974.c
index 16f77ba..ee2ca45 100644
--- a/arch/arm/mach-msm/acpuclock-8974.c
+++ b/arch/arm/mach-msm/acpuclock-8974.c
@@ -179,7 +179,7 @@
.l2_freq_tbl = l2_freq_tbl,
.l2_freq_tbl_size = sizeof(l2_freq_tbl),
.bus_scale = &bus_scale_data,
- .qfprom_phys_base = 0xFC4A8000,
+ .pte_efuse_phys = 0xFC4B80B0,
.stby_khz = 300000,
};
diff --git a/arch/arm/mach-msm/acpuclock-krait.c b/arch/arm/mach-msm/acpuclock-krait.c
index 9afa7c0..2951c1a 100644
--- a/arch/arm/mach-msm/acpuclock-krait.c
+++ b/arch/arm/mach-msm/acpuclock-krait.c
@@ -36,6 +36,7 @@
#include "acpuclock.h"
#include "acpuclock-krait.h"
+#include "avs.h"
/* MUX source selects. */
#define PRI_SRC_SEL_SEC_SRC 0
@@ -44,9 +45,6 @@
#define SEC_SRC_SEL_L2PLL 1
#define SEC_SRC_SEL_AUX 2
-/* PTE EFUSE register offset. */
-#define PTE_EFUSE 0xC0
-
static DEFINE_MUTEX(driver_lock);
static DEFINE_SPINLOCK(l2_lock);
@@ -472,6 +470,12 @@
vdd_data.vdd_core = calculate_vdd_core(tgt);
vdd_data.ua_core = tgt->ua_core;
+ /* Disable AVS before voltage switch */
+ if (reason == SETRATE_CPUFREQ && drv.scalable[cpu].avs_enabled) {
+ AVS_DISABLE(cpu);
+ drv.scalable[cpu].avs_enabled = false;
+ }
+
/* Increase VDD levels if needed. */
if (reason == SETRATE_CPUFREQ || reason == SETRATE_HOTPLUG) {
rc = increase_vdd(cpu, &vdd_data, reason);
@@ -507,6 +511,12 @@
/* Drop VDD levels if we can. */
decrease_vdd(cpu, &vdd_data, reason);
+ /* Re-enable AVS */
+ if (reason == SETRATE_CPUFREQ && tgt->avsdscr_setting) {
+ AVS_ENABLE(cpu, tgt->avsdscr_setting);
+ drv.scalable[cpu].avs_enabled = true;
+ }
+
dev_dbg(drv.dev, "ACPU%d speed change complete\n", cpu);
out:
@@ -926,25 +936,27 @@
static void krait_apply_vmin(struct acpu_level *tbl)
{
- for (; tbl->speed.khz != 0; tbl++)
+ for (; tbl->speed.khz != 0; tbl++) {
if (tbl->vdd_core < 1150000)
tbl->vdd_core = 1150000;
+ tbl->avsdscr_setting = 0;
+ }
}
-static int __init select_freq_plan(u32 qfprom_phys)
+static int __init select_freq_plan(u32 pte_efuse_phys)
{
- void __iomem *qfprom_base;
- u32 pte_efuse, pvs, tbl_idx;
+ void __iomem *pte_efuse;
+ u32 pte_efuse_val, pvs, tbl_idx;
char *pvs_names[] = { "Slow", "Nominal", "Fast", "Faster", "Unknown" };
- qfprom_base = ioremap(qfprom_phys, SZ_256);
+ pte_efuse = ioremap(pte_efuse_phys, 4);
/* Select frequency tables. */
- if (qfprom_base) {
- pte_efuse = readl_relaxed(qfprom_base + PTE_EFUSE);
- pvs = (pte_efuse >> 10) & 0x7;
- iounmap(qfprom_base);
+ if (pte_efuse) {
+ pte_efuse_val = readl_relaxed(pte_efuse);
+ pvs = (pte_efuse_val >> 10) & 0x7;
+ iounmap(pte_efuse);
if (pvs == 0x7)
- pvs = (pte_efuse >> 13) & 0x7;
+ pvs = (pte_efuse_val >> 13) & 0x7;
switch (pvs) {
case 0x0:
@@ -1005,7 +1017,7 @@
GFP_KERNEL);
BUG_ON(!drv.bus_scale->usecase);
- tbl_idx = select_freq_plan(params->qfprom_phys_base);
+ tbl_idx = select_freq_plan(params->pte_efuse_phys);
drv.acpu_freq_tbl = kmemdup(params->pvs_tables[tbl_idx].table,
params->pvs_tables[tbl_idx].size,
GFP_KERNEL);
diff --git a/arch/arm/mach-msm/acpuclock-krait.h b/arch/arm/mach-msm/acpuclock-krait.h
index 1b891b1..d615b85 100644
--- a/arch/arm/mach-msm/acpuclock-krait.h
+++ b/arch/arm/mach-msm/acpuclock-krait.h
@@ -143,6 +143,7 @@
* @l2_level: L2 configuration to use.
* @vdd_core: CPU core voltage in uV.
* @ua_core: CPU core current consumption in uA.
+ * @avsdscr_setting: AVS DSCR configuration.
*/
struct acpu_level {
const int use_for_scaling;
@@ -150,6 +151,7 @@
const unsigned int l2_level;
int vdd_core;
int ua_core;
+ unsigned int avsdscr_setting;
};
/**
@@ -203,6 +205,7 @@
* @l2_vote: L2 performance level vote associate with the current CPU speed.
* @vreg: Array of voltage regulators needed by the scalable.
* @initialized: Flag set to true when per_cpu_init() has been called.
+ * @avs_enabled: True if avs is enabled for the scalabale. False otherwise.
*/
struct scalable {
const phys_addr_t hfpll_phys_base;
@@ -214,6 +217,7 @@
unsigned int l2_vote;
struct vreg vreg[NUM_VREG];
bool initialized;
+ bool avs_enabled;
};
/**
@@ -236,7 +240,7 @@
* @pvs_tables: CPU frequency tables.
* @l2_freq_tbl: L2 frequency table.
* @l2_freq_tbl_size: Size of @l2_freq_tbl.
- * @qfprom_phys_base: Physical base address of QFPROM.
+ * @pte_efuse_phys: Physical address of PTE EFUSE.
* @bus_scale: MSM bus driver parameters.
* @stby_khz: KHz value corresponding to an always-on clock source.
*/
@@ -247,7 +251,7 @@
struct pvs_table *pvs_tables;
struct l2_level *l2_freq_tbl;
size_t l2_freq_tbl_size;
- phys_addr_t qfprom_phys_base;
+ phys_addr_t pte_efuse_phys;
struct msm_bus_scale_pdata *bus_scale;
unsigned long stby_khz;
};
diff --git a/arch/arm/mach-msm/board-8064-regulator.c b/arch/arm/mach-msm/board-8064-regulator.c
index bbb9a81..6cdafbc 100644
--- a/arch/arm/mach-msm/board-8064-regulator.c
+++ b/arch/arm/mach-msm/board-8064-regulator.c
@@ -189,6 +189,7 @@
REGULATOR_SUPPLY("vcc_i2c", "3-0024"),
REGULATOR_SUPPLY("vddp", "0-0048"),
REGULATOR_SUPPLY("hdmi_lvl_tsl", "hdmi_msm.0"),
+ REGULATOR_SUPPLY("vdd-io", "spi0.2"),
};
VREG_CONSUMERS(S5) = {
REGULATOR_SUPPLY("8921_s5", NULL),
@@ -252,7 +253,7 @@
};
VREG_CONSUMERS(EXT_3P3V) = {
REGULATOR_SUPPLY("ext_3p3v", NULL),
- REGULATOR_SUPPLY("vdd_io", "spi0.2"),
+ REGULATOR_SUPPLY("vdd-phy", "spi0.2"),
REGULATOR_SUPPLY("mhl_usb_hs_switch", "msm_otg"),
REGULATOR_SUPPLY("lvds_vccs_3p3v", "lvds.0"),
REGULATOR_SUPPLY("dsi1_vccs_3p3v", "mipi_dsi.1"),
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 7c9f652..06efc03 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -1688,8 +1688,8 @@
.reg_base_addr = MSM_SAW0_BASE,
.reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x1F,
#if defined(CONFIG_MSM_AVS_HW)
- .reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x00,
- .reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
+ .reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x50589464,
+ .reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00020000,
#endif
.reg_init_values[MSM_SPM_REG_SAW2_SPM_CTL] = 0x01,
.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x03020004,
@@ -1703,8 +1703,8 @@
.reg_base_addr = MSM_SAW1_BASE,
.reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x1F,
#if defined(CONFIG_MSM_AVS_HW)
- .reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x00,
- .reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
+ .reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x50589464,
+ .reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00020000,
#endif
.reg_init_values[MSM_SPM_REG_SAW2_SPM_CTL] = 0x01,
.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x02020204,
diff --git a/arch/arm/mach-msm/cpufreq.c b/arch/arm/mach-msm/cpufreq.c
index 05bd56ef..6c9b413 100644
--- a/arch/arm/mach-msm/cpufreq.c
+++ b/arch/arm/mach-msm/cpufreq.c
@@ -32,19 +32,6 @@
#include "acpuclock.h"
-#ifdef CONFIG_SMP
-struct cpufreq_work_struct {
- struct work_struct work;
- struct cpufreq_policy *policy;
- struct completion complete;
- int frequency;
- int status;
-};
-
-static DEFINE_PER_CPU(struct cpufreq_work_struct, cpufreq_work);
-static struct workqueue_struct *msm_cpufreq_wq;
-#endif
-
struct cpufreq_suspend_t {
struct mutex suspend_mutex;
int device_suspended;
@@ -91,45 +78,6 @@
return ret;
}
-#ifdef CONFIG_SMP
-static int __cpuinit msm_cpufreq_cpu_callback(struct notifier_block *nfb,
- unsigned long action, void *hcpu)
-{
- unsigned int cpu = (unsigned long)hcpu;
-
- switch (action) {
- case CPU_ONLINE:
- case CPU_ONLINE_FROZEN:
- per_cpu(cpufreq_suspend, cpu).device_suspended = 0;
- break;
- case CPU_DOWN_PREPARE:
- case CPU_DOWN_PREPARE_FROZEN:
- mutex_lock(&per_cpu(cpufreq_suspend, cpu).suspend_mutex);
- per_cpu(cpufreq_suspend, cpu).device_suspended = 1;
- mutex_unlock(&per_cpu(cpufreq_suspend, cpu).suspend_mutex);
- break;
- case CPU_DOWN_FAILED:
- case CPU_DOWN_FAILED_FROZEN:
- per_cpu(cpufreq_suspend, cpu).device_suspended = 0;
- break;
- }
- return NOTIFY_OK;
-}
-
-static struct notifier_block __refdata msm_cpufreq_cpu_notifier = {
- .notifier_call = msm_cpufreq_cpu_callback,
-};
-
-static void set_cpu_work(struct work_struct *work)
-{
- struct cpufreq_work_struct *cpu_work =
- container_of(work, struct cpufreq_work_struct, work);
-
- cpu_work->status = set_cpu_freq(cpu_work->policy, cpu_work->frequency);
- complete(&cpu_work->complete);
-}
-#endif
-
static int msm_cpufreq_target(struct cpufreq_policy *policy,
unsigned int target_freq,
unsigned int relation)
@@ -137,19 +85,12 @@
int ret = -EFAULT;
int index;
struct cpufreq_frequency_table *table;
-#ifdef CONFIG_SMP
- struct cpufreq_work_struct *cpu_work = NULL;
- cpumask_var_t mask;
if (!cpu_active(policy->cpu)) {
pr_info("cpufreq: cpu %d is not active.\n", policy->cpu);
return -ENODEV;
}
- if (!alloc_cpumask_var(&mask, GFP_KERNEL))
- return -ENOMEM;
-#endif
-
mutex_lock(&per_cpu(cpufreq_suspend, policy->cpu).suspend_mutex);
if (per_cpu(cpufreq_suspend, policy->cpu).device_suspended) {
@@ -167,39 +108,13 @@
goto done;
}
-#ifdef CONFIG_CPU_FREQ_DEBUG
pr_debug("CPU[%d] target %d relation %d (%d-%d) selected %d\n",
policy->cpu, target_freq, relation,
policy->min, policy->max, table[index].frequency);
-#endif
-#ifdef CONFIG_SMP
- cpu_work = &per_cpu(cpufreq_work, policy->cpu);
- cpu_work->policy = policy;
- cpu_work->frequency = table[index].frequency;
- cpu_work->status = -ENODEV;
-
- cpumask_clear(mask);
- cpumask_set_cpu(policy->cpu, mask);
- if (cpumask_equal(mask, ¤t->cpus_allowed)) {
- ret = set_cpu_freq(cpu_work->policy, cpu_work->frequency);
- goto done;
- } else {
- cancel_work_sync(&cpu_work->work);
- INIT_COMPLETION(cpu_work->complete);
- queue_work_on(policy->cpu, msm_cpufreq_wq, &cpu_work->work);
- wait_for_completion(&cpu_work->complete);
- }
-
- ret = cpu_work->status;
-#else
ret = set_cpu_freq(policy, table[index].frequency);
-#endif
done:
-#ifdef CONFIG_SMP
- free_cpumask_var(mask);
-#endif
mutex_unlock(&per_cpu(cpufreq_suspend, policy->cpu).suspend_mutex);
return ret;
}
@@ -282,10 +197,6 @@
int cur_freq;
int index;
struct cpufreq_frequency_table *table;
-#ifdef CONFIG_SMP
- struct cpufreq_work_struct *cpu_work = NULL;
-#endif
-
table = cpufreq_frequency_get_table(policy->cpu);
if (table == NULL)
@@ -314,7 +225,7 @@
CPUFREQ_RELATION_H, &index) &&
cpufreq_frequency_table_target(policy, table, cur_freq,
CPUFREQ_RELATION_L, &index)) {
- pr_info("cpufreq: cpu%d at invalid freq: %d\n",
+ pr_info("%s: cpu%d at invalid freq: %d\n", __func__,
policy->cpu, cur_freq);
return -EINVAL;
}
@@ -334,15 +245,39 @@
policy->cpuinfo.transition_latency =
acpuclk_get_switch_time() * NSEC_PER_USEC;
-#ifdef CONFIG_SMP
- cpu_work = &per_cpu(cpufreq_work, policy->cpu);
- INIT_WORK(&cpu_work->work, set_cpu_work);
- init_completion(&cpu_work->complete);
-#endif
return 0;
}
+static int __cpuinit msm_cpufreq_cpu_callback(struct notifier_block *nfb,
+ unsigned long action, void *hcpu)
+{
+ unsigned int cpu = (unsigned long)hcpu;
+
+ switch (action) {
+ case CPU_ONLINE:
+ case CPU_ONLINE_FROZEN:
+ per_cpu(cpufreq_suspend, cpu).device_suspended = 0;
+ break;
+ case CPU_DOWN_PREPARE:
+ case CPU_DOWN_PREPARE_FROZEN:
+ mutex_lock(&per_cpu(cpufreq_suspend, cpu).suspend_mutex);
+ per_cpu(cpufreq_suspend, cpu).device_suspended = 1;
+ mutex_unlock(&per_cpu(cpufreq_suspend, cpu).suspend_mutex);
+ break;
+ case CPU_DOWN_FAILED:
+ case CPU_DOWN_FAILED_FROZEN:
+ per_cpu(cpufreq_suspend, cpu).device_suspended = 0;
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block __refdata msm_cpufreq_cpu_notifier = {
+ .notifier_call = msm_cpufreq_cpu_callback,
+};
+
static int msm_cpufreq_suspend(void)
{
int cpu;
@@ -382,6 +317,10 @@
}
}
+static struct notifier_block msm_cpufreq_pm_notifier = {
+ .notifier_call = msm_cpufreq_pm_event,
+};
+
static struct freq_attr *msm_freq_attr[] = {
&cpufreq_freq_attr_scaling_available_freqs,
NULL,
@@ -398,10 +337,6 @@
.attr = msm_freq_attr,
};
-static struct notifier_block msm_cpufreq_pm_notifier = {
- .notifier_call = msm_cpufreq_pm_event,
-};
-
static int __init msm_cpufreq_register(void)
{
int cpu;
@@ -411,10 +346,7 @@
per_cpu(cpufreq_suspend, cpu).device_suspended = 0;
}
-#ifdef CONFIG_SMP
- msm_cpufreq_wq = create_workqueue("msm-cpufreq");
register_hotcpu_notifier(&msm_cpufreq_cpu_notifier);
-#endif
register_pm_notifier(&msm_cpufreq_pm_notifier);
return cpufreq_register_driver(&msm_cpufreq_driver);
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index cd5b2e5..c877ba9 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -1728,7 +1728,7 @@
uint32_t quot;
/* This formula is as per chip characterization data */
- quot = max_quot - ((max_freq / 10 - new_freq / 10) * 5);
+ quot = max_quot - (((max_freq - new_freq) * 5) / 10);
return quot;
}
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-9625.h b/arch/arm/mach-msm/include/mach/msm_iomap-9625.h
index 493cf36..eecdd67 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-9625.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-9625.h
@@ -23,7 +23,7 @@
*
*/
-#define MSM9625_SHARED_RAM_PHYS 0x18D00000
+#define MSM9625_SHARED_RAM_PHYS 0x00000000
#define MSM9625_APCS_GCC_PHYS 0xF9011000
#define MSM9625_APCS_GCC_SIZE SZ_4K
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h
index 21bea4f..6f925d4 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap.h
@@ -105,7 +105,7 @@
#if defined(CONFIG_ARCH_MSM9615) || defined(CONFIG_ARCH_MSM7X27) \
- || defined(CONFIG_ARCH_MSM7X30)
+ || defined(CONFIG_ARCH_MSM7X30) || defined(CONFIG_ARCH_MSM9625)
#define MSM_SHARED_RAM_SIZE SZ_1M
#else
#define MSM_SHARED_RAM_SIZE SZ_2M
diff --git a/arch/arm/mach-msm/ipc_router.c b/arch/arm/mach-msm/ipc_router.c
index 7dc8d0f..c82eac1 100644
--- a/arch/arm/mach-msm/ipc_router.c
+++ b/arch/arm/mach-msm/ipc_router.c
@@ -2096,7 +2096,7 @@
mutex_lock(&rt_entry->lock);
i += scnprintf(buf + i, max - i,
"Node Id: 0x%08x\n", rt_entry->node_id);
- if (j == IPC_ROUTER_NID_LOCAL) {
+ if (rt_entry->node_id == IPC_ROUTER_NID_LOCAL) {
i += scnprintf(buf + i, max - i,
"XPRT Name: Loopback\n");
i += scnprintf(buf + i, max - i,
diff --git a/arch/arm/mach-msm/lpm_levels.c b/arch/arm/mach-msm/lpm_levels.c
index f7456ef..8218a42 100644
--- a/arch/arm/mach-msm/lpm_levels.c
+++ b/arch/arm/mach-msm/lpm_levels.c
@@ -92,8 +92,8 @@
}
static void *msm_lpm_lowest_limits(bool from_idle,
- enum msm_pm_sleep_mode sleep_mode, uint32_t latency_us,
- uint32_t sleep_us, uint32_t *power)
+ enum msm_pm_sleep_mode sleep_mode,
+ struct msm_pm_time_params *time_param, uint32_t *power)
{
unsigned int cpu = smp_processor_id();
struct msm_rpmrs_level *best_level = NULL;
@@ -114,20 +114,22 @@
if (sleep_mode != level->sleep_mode)
continue;
- if (latency_us < level->latency_us)
+ if (time_param->latency_us < level->latency_us)
continue;
- if (sleep_us <= 1) {
+ if (time_param->sleep_us <= 1) {
pwr = level->energy_overhead;
- } else if (sleep_us <= level->time_overhead_us) {
- pwr = level->energy_overhead / sleep_us;
- } else if ((sleep_us >> 10) > level->time_overhead_us) {
+ } else if (time_param->sleep_us <= level->time_overhead_us) {
+ pwr = level->energy_overhead / time_param->sleep_us;
+ } else if ((time_param->sleep_us >> 10)
+ > level->time_overhead_us) {
pwr = level->steady_state_power;
} else {
pwr = level->steady_state_power;
pwr -= (level->time_overhead_us *
- level->steady_state_power)/sleep_us;
- pwr += level->energy_overhead / sleep_us;
+ level->steady_state_power) /
+ time_param->sleep_us;
+ pwr += level->energy_overhead / time_param->sleep_us;
}
if (!best_level || best_level->rs_limits.power[cpu] >= pwr) {
diff --git a/arch/arm/mach-msm/msm_cpr.c b/arch/arm/mach-msm/msm_cpr.c
index e2640a2..12f7d96 100644
--- a/arch/arm/mach-msm/msm_cpr.c
+++ b/arch/arm/mach-msm/msm_cpr.c
@@ -44,6 +44,8 @@
*/
#define TIMER_COUNT(freq, delay) ((freq * delay) / 1000)
#define ALL_CPR_IRQ 0x3F
+#define STEP_QUOT_MAX 25
+#define STEP_QUOT_MIN 12
/* Need platform device handle for suspend and resume APIs */
static struct platform_device *cpr_pdev;
@@ -269,8 +271,19 @@
goto err_poll_result;
}
quot2 = (cpr_read_reg(cpr, RBCPR_DEBUG1) & QUOT_SLOW_M) >> 12;
- chip_data->step_quot = (quot1 - quot2) / 4;
- pr_info("%s: Calculated Step Quot is %d\n",
+ /*
+ * Based on chip characterization data, it is good to add some
+ * margin on top of calculated step quot to help reduce the
+ * number of CPR interrupts. The present value suggested is 3.
+ * Further, if the step quot is outside range, clamp it to the
+ * maximum permitted value.
+ */
+ chip_data->step_quot = ((quot1 - quot2) / 4) + 3;
+ if (chip_data->step_quot < STEP_QUOT_MIN ||
+ chip_data->step_quot > STEP_QUOT_MAX)
+ chip_data->step_quot = STEP_QUOT_MAX;
+
+ pr_info("%s: Step Quot is %d\n",
__func__, chip_data->step_quot);
/* Disable the cpr */
cpr_modify_reg(cpr, RBCPR_CTL, LOOP_EN_M, DISABLE_CPR);
@@ -626,6 +639,8 @@
RBCPR_GCNT_TARGET(cpr->curr_osc)));
pr_debug("%s: new_freq: %d, set_freq: %d, quot: %d\n", __func__,
freqs->new, new_freq, quot);
+ pr_info("%s: PVS Voltage setting is: %d\n", __func__,
+ regulator_get_voltage(cpr->vreg_cx));
enable_irq(cpr->irq);
/**
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index dbb23d5..60ee8f0 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -49,6 +49,7 @@
#include "spm.h"
#include "timer.h"
#include "pm-boot.h"
+#include <mach/event_timer.h>
/******************************************************************************
* Debug Definitions
@@ -112,6 +113,7 @@
"standalone_power_collapse",
};
+static struct hrtimer pm_hrtimer;
static struct msm_pm_sleep_ops pm_sleep_ops;
/*
* Write out the attribute.
@@ -645,6 +647,28 @@
return time;
}
+/**
+ * pm_hrtimer_cb() : Callback function for hrtimer created if the
+ * core needs to be awake to handle an event.
+ * @hrtimer : Pointer to hrtimer
+ */
+static enum hrtimer_restart pm_hrtimer_cb(struct hrtimer *hrtimer)
+{
+ return HRTIMER_NORESTART;
+}
+
+/**
+ * msm_pm_set_timer() : Set an hrtimer to wakeup the core in time
+ * to handle an event.
+ */
+static void msm_pm_set_timer(uint32_t modified_time_us)
+{
+ u64 modified_time_ns = modified_time_us * NSEC_PER_USEC;
+ ktime_t modified_ktime = ns_to_ktime(modified_time_ns);
+ pm_hrtimer.function = pm_hrtimer_cb;
+ hrtimer_start(&pm_hrtimer, modified_ktime, HRTIMER_MODE_ABS);
+}
+
/******************************************************************************
* External Idle/Suspend Functions
*****************************************************************************/
@@ -657,15 +681,25 @@
int msm_pm_idle_prepare(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index)
{
- uint32_t latency_us;
- uint32_t sleep_us;
int i;
unsigned int power_usage = -1;
int ret = 0;
+ uint32_t modified_time_us = 0;
+ struct msm_pm_time_params time_param;
- latency_us = (uint32_t) pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
- sleep_us = (uint32_t) ktime_to_ns(tick_nohz_get_sleep_length());
- sleep_us = DIV_ROUND_UP(sleep_us, 1000);
+ time_param.latency_us =
+ (uint32_t) pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
+ time_param.sleep_us =
+ (uint32_t) (ktime_to_us(tick_nohz_get_sleep_length())
+ & UINT_MAX);
+ time_param.modified_time_us = 0;
+
+ if (!dev->cpu)
+ time_param.next_event_us =
+ (uint32_t) (ktime_to_us(get_next_event_time())
+ & UINT_MAX);
+ else
+ time_param.next_event_us = 0;
for (i = 0; i < dev->state_count; i++) {
struct cpuidle_state *state = &drv->states[i];
@@ -702,17 +736,18 @@
case MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT:
if (!allow)
break;
+ /* fall through */
if (pm_sleep_ops.lowest_limits)
rs_limits = pm_sleep_ops.lowest_limits(true,
- mode, latency_us, sleep_us,
- &power);
+ mode, &time_param, &power);
if (MSM_PM_DEBUG_IDLE & msm_pm_debug_mask)
pr_info("CPU%u: %s: %s, latency %uus, "
"sleep %uus, limit %p\n",
dev->cpu, __func__, state->desc,
- latency_us, sleep_us, rs_limits);
+ time_param.latency_us,
+ time_param.sleep_us, rs_limits);
if (!rs_limits)
allow = false;
@@ -730,6 +765,7 @@
if (allow) {
if (power < power_usage) {
power_usage = power;
+ modified_time_us = time_param.modified_time_us;
ret = mode;
}
@@ -738,6 +774,8 @@
}
}
+ if (modified_time_us && !dev->cpu)
+ msm_pm_set_timer(modified_time_us);
return ret;
}
@@ -850,6 +888,11 @@
int i;
int64_t period = 0;
int64_t time = msm_pm_timer_enter_suspend(&period);
+ struct msm_pm_time_params time_param;
+
+ time_param.latency_us = -1;
+ time_param.sleep_us = -1;
+ time_param.next_event_us = 0;
if (MSM_PM_DEBUG_SUSPEND & msm_pm_debug_mask)
pr_info("%s\n", __func__);
@@ -887,8 +930,7 @@
#endif /* CONFIG_MSM_SLEEP_TIME_OVERRIDE */
if (pm_sleep_ops.lowest_limits)
rs_limits = pm_sleep_ops.lowest_limits(false,
- MSM_PM_SLEEP_MODE_POWER_COLLAPSE, -1,
- -1, &power);
+ MSM_PM_SLEEP_MODE_POWER_COLLAPSE, &time_param, &power);
if (rs_limits) {
if (pm_sleep_ops.enter_sleep)
@@ -1046,6 +1088,7 @@
suspend_set_ops(&msm_pm_ops);
msm_pm_qtimer_available();
+ hrtimer_init(&pm_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
msm_cpuidle_init();
platform_driver_register(&msm_pc_counter_driver);
diff --git a/arch/arm/mach-msm/pm.h b/arch/arm/mach-msm/pm.h
index e2553e2..51256ca 100644
--- a/arch/arm/mach-msm/pm.h
+++ b/arch/arm/mach-msm/pm.h
@@ -57,6 +57,13 @@
#define MSM_PM_MODE(cpu, mode_nr) ((cpu) * MSM_PM_SLEEP_MODE_NR + (mode_nr))
+struct msm_pm_time_params {
+ uint32_t latency_us;
+ uint32_t sleep_us;
+ uint32_t next_event_us;
+ uint32_t modified_time_us;
+};
+
struct msm_pm_platform_data {
u8 idle_supported; /* Allow device to enter mode during idle */
u8 suspend_supported; /* Allow device to enter mode during suspend */
@@ -72,8 +79,8 @@
struct msm_pm_sleep_ops {
void *(*lowest_limits)(bool from_idle,
- enum msm_pm_sleep_mode sleep_mode, uint32_t latency_us,
- uint32_t sleep_us, uint32_t *power);
+ enum msm_pm_sleep_mode sleep_mode,
+ struct msm_pm_time_params *time_param, uint32_t *power);
int (*enter_sleep)(uint32_t sclk_count, void *limits,
bool from_idle, bool notify_rpm);
void (*exit_sleep)(void *limits, bool from_idle,
diff --git a/arch/arm/mach-msm/restart.c b/arch/arm/mach-msm/restart.c
index 53736ac..5883b0c 100644
--- a/arch/arm/mach-msm/restart.c
+++ b/arch/arm/mach-msm/restart.c
@@ -24,6 +24,7 @@
#include <linux/mfd/pmic8058.h>
#include <linux/mfd/pmic8901.h>
#include <linux/mfd/pm8xxx/misc.h>
+#include <linux/qpnp/power-on.h>
#include <asm/mach-types.h>
#include <asm/cacheflush.h>
@@ -128,6 +129,7 @@
set_dload_mode(0);
#endif
pm8xxx_reset_pwr_off(0);
+ qpnp_pon_system_pwr_off(0);
if (lower_pshold) {
if (!use_restart_v2())
@@ -208,6 +210,7 @@
#endif
pm8xxx_reset_pwr_off(1);
+ qpnp_pon_system_pwr_off(1);
if (cmd != NULL) {
if (!strncmp(cmd, "bootloader", 10)) {
diff --git a/arch/arm/mach-msm/rpm_resources.c b/arch/arm/mach-msm/rpm_resources.c
index 9d794e7..2a835f7 100644
--- a/arch/arm/mach-msm/rpm_resources.c
+++ b/arch/arm/mach-msm/rpm_resources.c
@@ -20,6 +20,7 @@
#include <linux/proc_fs.h>
#include <linux/spinlock.h>
#include <linux/cpu.h>
+#include <linux/hrtimer.h>
#include <mach/rpm.h>
#include <mach/msm_iomap.h>
#include <asm/mach-types.h>
@@ -37,6 +38,7 @@
enum {
MSM_RPMRS_DEBUG_OUTPUT = BIT(0),
MSM_RPMRS_DEBUG_BUFFER = BIT(1),
+ MSM_RPMRS_DEBUG_EVENT_TIMER = BIT(2),
};
static int msm_rpmrs_debug_mask;
@@ -891,8 +893,8 @@
}
static void *msm_rpmrs_lowest_limits(bool from_idle,
- enum msm_pm_sleep_mode sleep_mode, uint32_t latency_us,
- uint32_t sleep_us, uint32_t *power)
+ enum msm_pm_sleep_mode sleep_mode,
+ struct msm_pm_time_params *time_param, uint32_t *power)
{
unsigned int cpu = smp_processor_id();
struct msm_rpmrs_level *best_level = NULL;
@@ -900,6 +902,8 @@
bool gpio_detectable = false;
int i;
uint32_t pwr;
+ uint32_t next_wakeup_us = time_param->sleep_us;
+ bool modify_event_timer;
if (sleep_mode == MSM_PM_SLEEP_MODE_POWER_COLLAPSE) {
irqs_detectable = msm_mpm_irqs_detectable(from_idle);
@@ -909,16 +913,32 @@
for (i = 0; i < msm_rpmrs_level_count; i++) {
struct msm_rpmrs_level *level = &msm_rpmrs_levels[i];
+ modify_event_timer = false;
+
if (!level->available)
continue;
if (sleep_mode != level->sleep_mode)
continue;
- if (latency_us < level->latency_us)
+ if (time_param->latency_us < level->latency_us)
continue;
- if (sleep_us <= level->time_overhead_us)
+ if (time_param->next_event_us &&
+ time_param->next_event_us < level->latency_us)
+ continue;
+
+ if (time_param->next_event_us) {
+ if ((time_param->next_event_us < time_param->sleep_us)
+ || ((time_param->next_event_us - level->latency_us) <
+ time_param->sleep_us)) {
+ modify_event_timer = true;
+ next_wakeup_us = time_param->next_event_us -
+ level->latency_us;
+ }
+ }
+
+ if (next_wakeup_us <= level->time_overhead_us)
continue;
if (!msm_rpmrs_irqs_detectable(&level->rs_limits,
@@ -929,18 +949,17 @@
if (!cpu && msm_rpm_local_request_is_outstanding())
break;
-
- if (sleep_us <= 1) {
+ if (next_wakeup_us <= 1) {
pwr = level->energy_overhead;
- } else if (sleep_us <= level->time_overhead_us) {
- pwr = level->energy_overhead / sleep_us;
- } else if ((sleep_us >> 10) > level->time_overhead_us) {
+ } else if (next_wakeup_us <= level->time_overhead_us) {
+ pwr = level->energy_overhead / next_wakeup_us;
+ } else if ((next_wakeup_us >> 10) > level->time_overhead_us) {
pwr = level->steady_state_power;
} else {
pwr = level->steady_state_power;
pwr -= (level->time_overhead_us *
- level->steady_state_power)/sleep_us;
- pwr += level->energy_overhead / sleep_us;
+ level->steady_state_power)/next_wakeup_us;
+ pwr += level->energy_overhead / next_wakeup_us;
}
if (!best_level ||
@@ -950,6 +969,12 @@
best_level = level;
if (power)
*power = pwr;
+ if (modify_event_timer && best_level->latency_us > 1)
+ time_param->modified_time_us =
+ time_param->next_event_us -
+ best_level->latency_us;
+ else
+ time_param->modified_time_us = 0;
}
}
diff --git a/arch/arm/mach-msm/smd_pkt.c b/arch/arm/mach-msm/smd_pkt.c
index 5962d71..30acebf 100644
--- a/arch/arm/mach-msm/smd_pkt.c
+++ b/arch/arm/mach-msm/smd_pkt.c
@@ -65,6 +65,7 @@
wait_queue_head_t ch_opened_wait_queue;
int i;
+ int ref_cnt;
int blocking_write;
int is_open;
@@ -270,6 +271,7 @@
if (!smd_pkt_devp)
return -EINVAL;
+ mutex_lock(&smd_pkt_devp->ch_lock);
switch (cmd) {
case TIOCMGET:
D_STATUS("%s TIOCMGET command on smd_pkt_dev id:%d\n",
@@ -288,6 +290,7 @@
pr_err("%s: Unrecognized ioctl command %d\n", __func__, cmd);
ret = -1;
}
+ mutex_unlock(&smd_pkt_devp->ch_lock);
return ret;
}
@@ -867,9 +870,12 @@
smd_pkt_devp->ch_size =
smd_write_avail(smd_pkt_devp->ch);
r = 0;
+ smd_pkt_devp->ref_cnt++;
D_STATUS("Finished %s on smd_pkt_dev id:%d\n",
__func__, smd_pkt_devp->i);
}
+ } else {
+ smd_pkt_devp->ref_cnt++;
}
release_pil:
if (peripheral && (r < 0))
@@ -902,12 +908,14 @@
D_STATUS("Begin %s on smd_pkt_dev id:%d\n",
__func__, smd_pkt_devp->i);
- clean_and_signal(smd_pkt_devp);
-
mutex_lock(&smd_pkt_devp->ch_lock);
mutex_lock(&smd_pkt_devp->rx_lock);
mutex_lock(&smd_pkt_devp->tx_lock);
- if (smd_pkt_devp->ch != 0) {
+ if (smd_pkt_devp->ref_cnt > 0)
+ smd_pkt_devp->ref_cnt--;
+
+ if (smd_pkt_devp->ch != 0 && smd_pkt_devp->ref_cnt == 0) {
+ clean_and_signal(smd_pkt_devp);
r = smd_close(smd_pkt_devp->ch);
smd_pkt_devp->ch = 0;
smd_pkt_devp->blocking_write = 0;
@@ -916,15 +924,15 @@
smd_pkt_devp->driver.probe = NULL;
if (smd_pkt_devp->pil)
pil_put(smd_pkt_devp->pil);
+ smd_pkt_devp->has_reset = 0;
+ smd_pkt_devp->do_reset_notification = 0;
+ smd_pkt_devp->wakelock_locked = 0;
+ wake_lock_destroy(&smd_pkt_devp->pa_wake_lock);
}
mutex_unlock(&smd_pkt_devp->tx_lock);
mutex_unlock(&smd_pkt_devp->rx_lock);
mutex_unlock(&smd_pkt_devp->ch_lock);
- smd_pkt_devp->has_reset = 0;
- smd_pkt_devp->do_reset_notification = 0;
- smd_pkt_devp->wakelock_locked = 0;
- wake_lock_destroy(&smd_pkt_devp->pa_wake_lock);
D_STATUS("Finished %s on smd_pkt_dev id:%d\n",
__func__, smd_pkt_devp->i);
diff --git a/arch/arm/mach-msm/spm-v2.c b/arch/arm/mach-msm/spm-v2.c
index 26dfdff..1eab9bf 100644
--- a/arch/arm/mach-msm/spm-v2.c
+++ b/arch/arm/mach-msm/spm-v2.c
@@ -310,9 +310,43 @@
return 0;
}
+#ifdef CONFIG_MSM_AVS_HW
+static void msm_spm_drv_disable_avs(struct msm_spm_driver_data *dev)
+{
+ msm_spm_drv_load_shadow(dev, MSM_SPM_REG_SAW2_AVS_CTL);
+ dev->reg_shadow[MSM_SPM_REG_SAW2_AVS_CTL] &= ~BIT(27);
+ msm_spm_drv_flush_shadow(dev, MSM_SPM_REG_SAW2_AVS_CTL);
+}
+
+static void msm_spm_drv_enable_avs(struct msm_spm_driver_data *dev)
+{
+ dev->reg_shadow[MSM_SPM_REG_SAW2_AVS_CTL] |= BIT(27);
+ msm_spm_drv_flush_shadow(dev, MSM_SPM_REG_SAW2_AVS_CTL);
+}
+
+static void msm_spm_drv_set_avs_vlevel(struct msm_spm_driver_data *dev,
+ unsigned int vlevel)
+{
+ vlevel &= 0x3f;
+ dev->reg_shadow[MSM_SPM_REG_SAW2_AVS_CTL] &= ~0x7efc00;
+ dev->reg_shadow[MSM_SPM_REG_SAW2_AVS_CTL] |= ((vlevel - 4) << 10);
+ dev->reg_shadow[MSM_SPM_REG_SAW2_AVS_CTL] |= (vlevel << 17);
+ msm_spm_drv_flush_shadow(dev, MSM_SPM_REG_SAW2_AVS_CTL);
+}
+
+#else
+
+static void msm_spm_drv_disable_avs(struct msm_spm_driver_data *dev) { }
+
+static void msm_spm_drv_enable_avs(struct msm_spm_driver_data *dev) { }
+
+static void msm_spm_drv_set_avs_vlevel(struct msm_spm_driver_data *dev,
+ unsigned int vlevel) { }
+#endif
+
int msm_spm_drv_set_vdd(struct msm_spm_driver_data *dev, unsigned int vlevel)
{
- uint32_t timeout_us;
+ uint32_t timeout_us, new_level;
if (!dev)
return -EINVAL;
@@ -321,42 +355,46 @@
return -ENOSYS;
if (msm_spm_debug_mask & MSM_SPM_DEBUG_VCTL)
- pr_info("%s: requesting vlevel 0x%x\n",
- __func__, vlevel);
+ pr_info("%s: requesting vlevel %#x\n", __func__, vlevel);
+
+ msm_spm_drv_disable_avs(dev);
+
+ /* Kick the state machine back to idle */
+ dev->reg_shadow[MSM_SPM_REG_SAW2_RST] = 1;
+ msm_spm_drv_flush_shadow(dev, MSM_SPM_REG_SAW2_RST);
msm_spm_drv_apcs_set_vctl(dev, vlevel);
msm_spm_drv_flush_shadow(dev, MSM_SPM_REG_SAW2_VCTL);
msm_spm_drv_flush_shadow(dev, MSM_SPM_REG_SAW2_PMIC_DATA_0);
msm_spm_drv_flush_shadow(dev, MSM_SPM_REG_SAW2_PMIC_DATA_1);
- mb();
- /* Wait for PMIC state to return to idle or until timeout */
timeout_us = dev->vctl_timeout_us;
- while (msm_spm_drv_get_sts_pmic_state(dev) != MSM_SPM_PMIC_STATE_IDLE) {
- if (!timeout_us)
- goto set_vdd_bail;
-
- if (timeout_us > 10) {
- udelay(10);
- timeout_us -= 10;
- } else {
- udelay(timeout_us);
- timeout_us = 0;
- }
+ /* Confirm the voltage we set was what hardware sent */
+ do {
+ new_level = msm_spm_drv_get_sts_curr_pmic_data(dev);
+ if (new_level == vlevel)
+ break;
+ udelay(1);
+ } while (--timeout_us);
+ if (!timeout_us) {
+ pr_info("Wrong level %#x\n", new_level);
+ goto set_vdd_bail;
}
- if (msm_spm_drv_get_sts_curr_pmic_data(dev) != vlevel)
- goto set_vdd_bail;
+ /* Set AVS min/max */
+ msm_spm_drv_set_avs_vlevel(dev, vlevel);
if (msm_spm_debug_mask & MSM_SPM_DEBUG_VCTL)
pr_info("%s: done, remaining timeout %uus\n",
__func__, timeout_us);
+ msm_spm_drv_enable_avs(dev);
return 0;
set_vdd_bail:
- pr_err("%s: failed, remaining timeout %uus, vlevel 0x%x\n",
- __func__, timeout_us, msm_spm_drv_get_sts_curr_pmic_data(dev));
+ msm_spm_drv_enable_avs(dev);
+ pr_err("%s: failed %#x, remaining timeout %uus, vlevel %#x\n",
+ __func__, vlevel, timeout_us, new_level);
return -EIO;
}
diff --git a/arch/arm/mach-msm/spm_devices.c b/arch/arm/mach-msm/spm_devices.c
index 05d11d2..b87b0f1 100644
--- a/arch/arm/mach-msm/spm_devices.c
+++ b/arch/arm/mach-msm/spm_devices.c
@@ -38,16 +38,38 @@
uint32_t num_modes;
};
+struct msm_spm_vdd_info {
+ uint32_t cpu;
+ uint32_t vlevel;
+ int err;
+};
+
static struct msm_spm_device msm_spm_l2_device;
static DEFINE_PER_CPU_SHARED_ALIGNED(struct msm_spm_device, msm_cpu_spm_device);
-int msm_spm_set_vdd(unsigned int cpu, unsigned int vlevel)
+
+/* Must be called on the same cpu as the one being set to */
+static void msm_spm_smp_set_vdd(void *data)
{
struct msm_spm_device *dev;
- int ret = -EIO;
+ struct msm_spm_vdd_info *info = (struct msm_spm_vdd_info *)data;
- dev = &per_cpu(msm_cpu_spm_device, cpu);
- ret = msm_spm_drv_set_vdd(&dev->reg_data, vlevel);
+ dev = &per_cpu(msm_cpu_spm_device, info->cpu);
+ info->err = msm_spm_drv_set_vdd(&dev->reg_data, info->vlevel);
+}
+
+int msm_spm_set_vdd(unsigned int cpu, unsigned int vlevel)
+{
+ struct msm_spm_vdd_info info;
+ int ret;
+
+ info.cpu = cpu;
+ info.vlevel = vlevel;
+
+ /* Set to true to block on vdd change */
+ ret = smp_call_function_single(cpu, msm_spm_smp_set_vdd, &info, true);
+ if (!ret)
+ ret = info.err;
return ret;
}
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index 1f32e54..2388fff 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -1574,8 +1574,6 @@
return;
}
- KGSL_CTXT_INFO(device, "context flags %08x\n", context->flags);
-
cmds[0] = cp_nop_packet(1);
cmds[1] = KGSL_CONTEXT_TO_MEM_IDENTIFIER;
cmds[2] = cp_type3_packet(CP_MEM_WRITE, 2);
@@ -1710,18 +1708,24 @@
if (status & CP_INT_CNTL__RB_INT_MASK) {
/* signal intr completion event */
- unsigned int context_id;
- kgsl_sharedmem_readl(&device->memstore,
- &context_id,
+ unsigned int context_id, timestamp;
+ kgsl_sharedmem_readl(&device->memstore, &context_id,
KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
current_context));
+
+ kgsl_sharedmem_readl(&device->memstore, ×tamp,
+ KGSL_MEMSTORE_OFFSET(context_id,
+ eoptimestamp));
+
if (context_id < KGSL_MEMSTORE_MAX) {
kgsl_sharedmem_writel(&rb->device->memstore,
KGSL_MEMSTORE_OFFSET(context_id,
ts_cmp_enable), 0);
wmb();
}
- KGSL_CMD_WARN(rb->device, "ringbuffer rb interrupt\n");
+
+ KGSL_CMD_WARN(device, "<%d:0x%x> ringbuffer interrupt\n",
+ context_id, timestamp);
}
for (i = 0; i < ARRAY_SIZE(kgsl_cp_error_irqs); i++) {
@@ -1743,7 +1747,6 @@
adreno_regwrite(device, REG_CP_INT_ACK, status);
if (status & (CP_INT_CNTL__IB1_INT_MASK | CP_INT_CNTL__RB_INT_MASK)) {
- KGSL_CMD_WARN(rb->device, "ringbuffer ib1/rb interrupt\n");
queue_work(device->work_queue, &device->ts_expired_ws);
wake_up_interruptible_all(&device->wait_queue);
atomic_notifier_call_chain(&(device->ts_notifier_list),
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index d89e882..b8fca38 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -2409,8 +2409,6 @@
return;
}
- KGSL_CTXT_INFO(device, "context flags %08x\n", context->flags);
-
cmds[0] = cp_nop_packet(1);
cmds[1] = KGSL_CONTEXT_TO_MEM_IDENTIFIER;
cmds[2] = cp_type3_packet(CP_MEM_WRITE, 2);
@@ -2565,17 +2563,24 @@
struct kgsl_device *device = &adreno_dev->dev;
if (irq == A3XX_INT_CP_RB_INT) {
- unsigned int context_id;
+ unsigned int context_id, timestamp;
kgsl_sharedmem_readl(&device->memstore, &context_id,
KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
current_context));
+
+ kgsl_sharedmem_readl(&device->memstore, ×tamp,
+ KGSL_MEMSTORE_OFFSET(context_id,
+ eoptimestamp));
+
if (context_id < KGSL_MEMSTORE_MAX) {
kgsl_sharedmem_writel(&device->memstore,
KGSL_MEMSTORE_OFFSET(context_id,
ts_cmp_enable), 0);
wmb();
}
- KGSL_CMD_WARN(device, "ringbuffer rb interrupt\n");
+
+ KGSL_CMD_WARN(device, "<%d:0x%x> ringbuffer interrupt\n",
+ context_id, timestamp);
}
wake_up_interruptible_all(&device->wait_queue);
diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c
index b51342f..70ad81c 100644
--- a/drivers/gpu/msm/adreno_drawctxt.c
+++ b/drivers/gpu/msm/adreno_drawctxt.c
@@ -288,8 +288,10 @@
return;
}
- KGSL_CTXT_INFO(device, "from %p to %p flags %d\n",
- adreno_dev->drawctxt_active, drawctxt, flags);
+ KGSL_CTXT_INFO(device, "from %d to %d flags %d\n",
+ adreno_dev->drawctxt_active ?
+ adreno_dev->drawctxt_active->id : 0,
+ drawctxt ? drawctxt->id : 0, flags);
/* Save the old context */
adreno_dev->gpudev->ctxt_save(adreno_dev, adreno_dev->drawctxt_active);
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index db913a5..1ff219b 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -969,8 +969,8 @@
drawctxt, 0,
&link[0], (cmds - link));
- KGSL_CMD_INFO(device, "ctxt %d g %08x numibs %d ts %d\n",
- context->id, (unsigned int)ibdesc, numibs, *timestamp);
+ KGSL_CMD_INFO(device, "<%d:0x%x> g %08x numibs %d\n",
+ context->id, *timestamp, (unsigned int)ibdesc, numibs);
kfree(link);
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index f630f2a..21227a0 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -1107,9 +1107,6 @@
}
if (param->flags & KGSL_CONTEXT_SUBMIT_IB_LIST) {
- KGSL_DRV_INFO(dev_priv->device,
- "Using IB list mode for ib submission, numibs: %d\n",
- param->numibs);
if (!param->numibs) {
KGSL_DRV_ERR(dev_priv->device,
"Invalid numibs as parameter: %d\n",
diff --git a/drivers/media/video/vcap_v4l2.c b/drivers/media/video/vcap_v4l2.c
index 28abb36..48532e5 100644
--- a/drivers/media/video/vcap_v4l2.c
+++ b/drivers/media/video/vcap_v4l2.c
@@ -340,6 +340,7 @@
return -EINVAL;
}
+ vb->v4l2_buf.timestamp = b->timestamp;
list_add_tail(&vb->queued_entry, &q->queued_list);
vb->state = VB2_BUF_STATE_QUEUED;
diff --git a/drivers/media/video/vcap_vc.c b/drivers/media/video/vcap_vc.c
index 78e108f..5ae362f 100644
--- a/drivers/media/video/vcap_vc.c
+++ b/drivers/media/video/vcap_vc.c
@@ -122,6 +122,17 @@
return 0;
}
+static struct timeval interpolate_ts(struct timeval tv, uint32_t delta)
+{
+ if (tv.tv_usec < delta) {
+ tv.tv_sec--;
+ tv.tv_usec += VCAP_USEC - delta;
+ } else {
+ tv.tv_usec -= delta;
+ }
+ return tv;
+}
+
irqreturn_t vc_handler(struct vcap_dev *dev)
{
uint32_t irq, timestamp;
@@ -212,6 +223,20 @@
/* If here we know which buffers are done */
timestamp = readl_relaxed(VCAP_VC_TIMESTAMP);
+ if (timestamp < c_data->vc_action.last_ts) {
+ c_data->vc_action.vc_ts.tv_usec +=
+ (0xFFFFFFFF - c_data->vc_action.last_ts) +
+ timestamp + 1;
+ } else {
+ c_data->vc_action.vc_ts.tv_usec +=
+ timestamp - c_data->vc_action.last_ts;
+ }
+
+ c_data->vc_action.vc_ts.tv_sec +=
+ c_data->vc_action.vc_ts.tv_usec / VCAP_USEC;
+ c_data->vc_action.vc_ts.tv_usec =
+ c_data->vc_action.vc_ts.tv_usec % VCAP_USEC;
+ c_data->vc_action.last_ts = timestamp;
c_data->vc_action.buf_num = (buf_num + done_count) % tot;
for (i = 0; i < done_count; i++) {
@@ -232,9 +257,10 @@
/* Config vc with this new buffer */
config_buffer(c_data, buf, VCAP_VC_Y_ADDR_1 + 0x8 * idx,
VCAP_VC_C_ADDR_1 + 0x8 * idx);
- vb->v4l2_buf.timestamp.tv_usec = timestamp -
+ vb->v4l2_buf.timestamp = interpolate_ts(
+ c_data->vc_action.vc_ts,
1000000 / c_data->vc_format.frame_rate *
- (done_count - 1 - i);
+ (done_count - 1 - i));
vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
work_todo = true;
c_data->vc_action.buf[idx] = buf;
@@ -298,6 +324,12 @@
VCAP_VC_C_ADDR_1 + i * 8);
}
+ c_data->vc_action.last_ts = readl_relaxed(VCAP_VC_TIMESTAMP);
+ c_data->vc_action.vc_ts.tv_sec =
+ c_data->vc_action.last_ts / VCAP_USEC;
+ c_data->vc_action.vc_ts.tv_usec =
+ c_data->vc_action.last_ts % VCAP_USEC;
+
rc = 0;
for (i = 0; i < c_data->vc_action.tot_buf; i++)
rc = rc << 1 | 0x2;
diff --git a/drivers/media/video/vcap_vp.c b/drivers/media/video/vcap_vp.c
index 139de28..c81206f 100644
--- a/drivers/media/video/vcap_vp.c
+++ b/drivers/media/video/vcap_vp.c
@@ -233,6 +233,10 @@
queue_work(dev->vcap_wq, &dev->vp_to_vc_work.work);
}
+ if (vp_act->bufT0 != NULL && vp_act->vp_state == VP_NORMAL) {
+ vp_act->bufOut->vb.v4l2_buf.timestamp =
+ vp_act->bufT0->vb.v4l2_buf.timestamp;
+ }
vb2_buffer_done(&vp_act->bufOut->vb, VB2_BUF_STATE_DONE);
/* Cycle to next state */
diff --git a/drivers/platform/msm/qpnp-power-on.c b/drivers/platform/msm/qpnp-power-on.c
index 996456f..33b12ae 100644
--- a/drivers/platform/msm/qpnp-power-on.c
+++ b/drivers/platform/msm/qpnp-power-on.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, 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
@@ -35,6 +35,7 @@
#define QPNP_PON_RESIN_S1_TIMER(base) (base + 0x44)
#define QPNP_PON_RESIN_S2_TIMER(base) (base + 0x45)
#define QPNP_PON_RESIN_S2_CNTL(base) (base + 0x46)
+#define QPNP_PON_PS_HOLD_RST_CTL(base) (base + 0x5A)
#define QPNP_PON_RESIN_PULL_UP BIT(0)
#define QPNP_PON_KPDPWR_PULL_UP BIT(1)
@@ -50,6 +51,10 @@
#define QPNP_PON_RESIN_N_SET BIT(1)
#define QPNP_PON_RESIN_BARK_N_SET BIT(4)
+#define QPNP_PON_RESET_EN BIT(7)
+#define QPNP_PON_WARM_RESET BIT(0)
+#define QPNP_PON_SHUTDOWN BIT(2)
+
/* Ranges */
#define QPNP_PON_S1_TIMER_MAX 10256
#define QPNP_PON_S2_TIMER_MAX 2000
@@ -84,6 +89,8 @@
struct delayed_work bark_work;
};
+static struct qpnp_pon *sys_reset_dev;
+
static u32 s1_delay[PON_S1_COUNT_MAX + 1] = {
0 , 32, 56, 80, 138, 184, 272, 408, 608, 904, 1352, 2048,
3072, 4480, 6720, 10256
@@ -113,6 +120,57 @@
return rc;
}
+/**
+ * qpnp_pon_system_pwr_off - Configure system-reset PMIC for shutdown or reset
+ * @reset: Configures for shutdown if 0, or reset if 1.
+ *
+ * This function will only configure a single PMIC. The other PMICs in the
+ * system are slaved off of it and require no explicit configuration. Once
+ * the system-reset PMIC is configured properly, the MSM can drop PS_HOLD to
+ * activate the specified configuration.
+ */
+int qpnp_pon_system_pwr_off(bool reset)
+{
+ int rc;
+ struct qpnp_pon *pon = sys_reset_dev;
+
+ if (!pon)
+ return -ENODEV;
+
+ rc = qpnp_pon_masked_write(pon, QPNP_PON_PS_HOLD_RST_CTL(pon->base),
+ QPNP_PON_RESET_EN, 0);
+ if (rc)
+ dev_err(&pon->spmi->dev,
+ "Unable to write to addr=%x, rc(%d)\n",
+ QPNP_PON_PS_HOLD_RST_CTL(pon->base), rc);
+
+ /*
+ * We need 10 sleep clock cycles here. But since the clock is
+ * internally generated, we need to add 50% tolerance to be
+ * conservative.
+ */
+ udelay(500);
+
+ rc = qpnp_pon_masked_write(pon, QPNP_PON_PS_HOLD_RST_CTL(pon->base),
+ QPNP_PON_WARM_RESET | QPNP_PON_SHUTDOWN,
+ reset ? QPNP_PON_WARM_RESET : QPNP_PON_SHUTDOWN);
+ if (rc)
+ dev_err(&pon->spmi->dev,
+ "Unable to write to addr=%x, rc(%d)\n",
+ QPNP_PON_PS_HOLD_RST_CTL(pon->base), rc);
+
+ rc = qpnp_pon_masked_write(pon, QPNP_PON_PS_HOLD_RST_CTL(pon->base),
+ QPNP_PON_RESET_EN,
+ QPNP_PON_RESET_EN);
+ if (rc)
+ dev_err(&pon->spmi->dev,
+ "Unable to write to addr=%x, rc(%d)\n",
+ QPNP_PON_PS_HOLD_RST_CTL(pon->base), rc);
+
+ return rc;
+}
+EXPORT_SYMBOL(qpnp_pon_system_pwr_off);
+
static struct qpnp_pon_config *
qpnp_get_cfg(struct qpnp_pon *pon, u32 pon_type)
{
@@ -662,7 +720,7 @@
struct resource *pon_resource;
struct device_node *itr = NULL;
u32 delay = 0;
- int rc = 0;
+ int rc, sys_reset;
pon = devm_kzalloc(&spmi->dev, sizeof(struct qpnp_pon),
GFP_KERNEL);
@@ -671,6 +729,15 @@
return -ENOMEM;
}
+ sys_reset = of_property_read_bool(spmi->dev.of_node,
+ "qcom,system-reset");
+ if (sys_reset && sys_reset_dev) {
+ dev_err(&spmi->dev, "qcom,system-reset property can only be specified for one device on the system\n");
+ return -EINVAL;
+ } else if (sys_reset) {
+ sys_reset_dev = pon;
+ }
+
pon->spmi = spmi;
/* get the total number of pon configurations */
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 5637f19..998978c 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -69,6 +69,13 @@
#define USB_SUSPEND_DELAY_TIME (500 * HZ/1000) /* 500 msec */
+enum msm_otg_phy_reg_mode {
+ USB_PHY_REG_OFF,
+ USB_PHY_REG_ON,
+ USB_PHY_REG_LPM_ON,
+ USB_PHY_REG_LPM_OFF,
+};
+
static DECLARE_COMPLETION(pmic_vbus_init);
static struct msm_otg *the_msm_otg;
static bool debug_aca_enabled;
@@ -168,7 +175,8 @@
return ret;
}
-static int msm_hsusb_ldo_enable(struct msm_otg *motg, int on)
+static int msm_hsusb_ldo_enable(struct msm_otg *motg,
+ enum msm_otg_phy_reg_mode mode)
{
int ret = 0;
@@ -182,7 +190,8 @@
return -ENODEV;
}
- if (on) {
+ switch (mode) {
+ case USB_PHY_REG_ON:
ret = regulator_set_optimum_mode(hsusb_1p8,
USB_PHY_1P8_HPM_LOAD);
if (ret < 0) {
@@ -219,7 +228,9 @@
return ret;
}
- } else {
+ break;
+
+ case USB_PHY_REG_OFF:
ret = regulator_disable(hsusb_1p8);
if (ret) {
dev_err(motg->phy.dev, "%s: unable to disable the hsusb 1p8\n",
@@ -242,9 +253,55 @@
if (ret < 0)
pr_err("%s: Unable to set LPM of the regulator:"
"HSUSB_3p3\n", __func__);
+
+ break;
+
+ case USB_PHY_REG_LPM_ON:
+ ret = regulator_set_optimum_mode(hsusb_1p8,
+ USB_PHY_1P8_LPM_LOAD);
+ if (ret < 0) {
+ pr_err("%s: Unable to set LPM of the regulator: HSUSB_1p8\n",
+ __func__);
+ return ret;
+ }
+
+ ret = regulator_set_optimum_mode(hsusb_3p3,
+ USB_PHY_3P3_LPM_LOAD);
+ if (ret < 0) {
+ pr_err("%s: Unable to set LPM of the regulator: HSUSB_3p3\n",
+ __func__);
+ regulator_set_optimum_mode(hsusb_1p8, USB_PHY_REG_ON);
+ return ret;
+ }
+
+ break;
+
+ case USB_PHY_REG_LPM_OFF:
+ ret = regulator_set_optimum_mode(hsusb_1p8,
+ USB_PHY_1P8_HPM_LOAD);
+ if (ret < 0) {
+ pr_err("%s: Unable to set HPM of the regulator: HSUSB_1p8\n",
+ __func__);
+ return ret;
+ }
+
+ ret = regulator_set_optimum_mode(hsusb_3p3,
+ USB_PHY_3P3_HPM_LOAD);
+ if (ret < 0) {
+ pr_err("%s: Unable to set HPM of the regulator: HSUSB_3p3\n",
+ __func__);
+ regulator_set_optimum_mode(hsusb_1p8, USB_PHY_REG_ON);
+ return ret;
+ }
+
+ break;
+
+ default:
+ pr_err("%s: Unsupported mode (%d).", __func__, mode);
+ return -ENOTSUPP;
}
- pr_debug("reg (%s)\n", on ? "HPM" : "LPM");
+ pr_debug("%s: USB reg mode (%d) (OFF/HPM/LPM)\n", __func__, mode);
return ret < 0 ? ret : 0;
}
@@ -881,8 +938,12 @@
if (motg->caps & ALLOW_PHY_POWER_COLLAPSE &&
!host_bus_suspend && !dcp) {
- msm_hsusb_ldo_enable(motg, 0);
+ msm_hsusb_ldo_enable(motg, USB_PHY_REG_OFF);
motg->lpm_flags |= PHY_PWR_COLLAPSED;
+ } else if (motg->caps & ALLOW_PHY_REGULATORS_LPM &&
+ !host_bus_suspend && !device_bus_suspend && !dcp) {
+ msm_hsusb_ldo_enable(motg, USB_PHY_REG_LPM_ON);
+ motg->lpm_flags |= PHY_REGULATORS_LPM;
}
if (motg->lpm_flags & PHY_RETENTIONED) {
@@ -946,8 +1007,11 @@
}
if (motg->lpm_flags & PHY_PWR_COLLAPSED) {
- msm_hsusb_ldo_enable(motg, 1);
+ msm_hsusb_ldo_enable(motg, USB_PHY_REG_ON);
motg->lpm_flags &= ~PHY_PWR_COLLAPSED;
+ } else if (motg->lpm_flags & PHY_REGULATORS_LPM) {
+ msm_hsusb_ldo_enable(motg, USB_PHY_REG_LPM_OFF);
+ motg->lpm_flags &= ~PHY_REGULATORS_LPM;
}
if (motg->lpm_flags & PHY_RETENTIONED) {
@@ -3622,7 +3686,7 @@
}
}
- ret = msm_hsusb_ldo_enable(motg, 1);
+ ret = msm_hsusb_ldo_enable(motg, USB_PHY_REG_ON);
if (ret) {
dev_err(&pdev->dev, "hsusb vreg enable failed\n");
goto free_ldo_init;
@@ -3724,7 +3788,8 @@
ALLOW_PHY_RETENTION;
if (motg->pdata->otg_control == OTG_PHY_CONTROL)
- motg->caps = ALLOW_PHY_RETENTION;
+ motg->caps = ALLOW_PHY_RETENTION |
+ ALLOW_PHY_REGULATORS_LPM;
}
if (motg->pdata->enable_lpm_on_dev_suspend)
@@ -3756,7 +3821,7 @@
destroy_wlock:
wake_lock_destroy(&motg->wlock);
clk_disable_unprepare(motg->core_clk);
- msm_hsusb_ldo_enable(motg, 0);
+ msm_hsusb_ldo_enable(motg, USB_PHY_REG_OFF);
free_ldo_init:
msm_hsusb_ldo_init(motg, 0);
free_hsusb_vddcx:
@@ -3843,7 +3908,7 @@
clk_disable_unprepare(motg->pclk);
clk_disable_unprepare(motg->core_clk);
msm_xo_put(motg->xo_handle);
- msm_hsusb_ldo_enable(motg, 0);
+ msm_hsusb_ldo_enable(motg, USB_PHY_REG_OFF);
msm_hsusb_ldo_init(motg, 0);
regulator_disable(hsusb_vddcx);
regulator_set_voltage(hsusb_vddcx,
diff --git a/drivers/video/msm/mdss/mdss_mdp_wb.c b/drivers/video/msm/mdss/mdss_mdp_wb.c
index bd5f464..b0a67938 100644
--- a/drivers/video/msm/mdss/mdss_mdp_wb.c
+++ b/drivers/video/msm/mdss/mdss_mdp_wb.c
@@ -388,7 +388,7 @@
ret = -ENOBUFS;
}
mutex_unlock(&wb->lock);
- return 0;
+ return ret;
}
static void mdss_mdp_wb_callback(void *arg)
diff --git a/drivers/video/msm/mhl/mhl_8334.c b/drivers/video/msm/mhl/mhl_8334.c
index f3b8cd1..6c0778f 100644
--- a/drivers/video/msm/mhl/mhl_8334.c
+++ b/drivers/video/msm/mhl/mhl_8334.c
@@ -62,6 +62,9 @@
void (*notify_usb_online)(int online);
static void mhl_drive_hpd(uint8_t to_state);
static int mhl_send_msc_command(struct msc_command_struct *req);
+static void list_cmd_put(struct msc_command_struct *cmd);
+static struct msc_command_struct *list_cmd_get(void);
+static void mhl_msc_send_work(struct work_struct *work);
static struct i2c_driver mhl_sii_i2c_driver = {
.driver = {
@@ -618,7 +621,7 @@
list_add_tail(&new_cmd->msc_queue_envelope, &mhl_msm_state->list_cmd);
}
-struct msc_command_struct *list_cmd_get(void)
+static struct msc_command_struct *list_cmd_get(void)
{
struct msc_cmd_envelope *cmd_env =
list_first_entry(&mhl_msm_state->list_cmd,
diff --git a/include/linux/qpnp/power-on.h b/include/linux/qpnp/power-on.h
new file mode 100644
index 0000000..85dbce9
--- /dev/null
+++ b/include/linux/qpnp/power-on.h
@@ -0,0 +1,24 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef QPNP_PON_H
+#define QPNP_PON_H
+
+#include <linux/errno.h>
+
+#ifdef CONFIG_QPNP_POWER_ON
+int qpnp_pon_system_pwr_off(bool reset);
+#else
+static int qpnp_pon_system_pwr_off(bool reset) { return -ENODEV; }
+#endif
+
+#endif
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index adcc450..8e6550f 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -348,7 +348,7 @@
/*
* Allowing PHY power collpase turns off the HSUSB 3.3v and 1.8v
* analog regulators while going to low power mode.
- * Currently only 8960(28nm PHY) has the support to allowing PHY
+ * Currently only 28nm PHY has the support to allowing PHY
* power collapse since it doesn't have leakage currents while
* turning off the power rails.
*/
@@ -362,12 +362,18 @@
* Allow putting the core in Low Power mode, when
* USB bus is suspended but cable is connected.
*/
-#define ALLOW_LPM_ON_DEV_SUSPEND BIT(2)
+#define ALLOW_LPM_ON_DEV_SUSPEND BIT(2)
+ /*
+ * Allowing PHY regulators LPM puts the HSUSB 3.3v and 1.8v
+ * analog regulators into LPM while going to USB low power mode.
+ */
+#define ALLOW_PHY_REGULATORS_LPM BIT(3)
unsigned long lpm_flags;
#define PHY_PWR_COLLAPSED BIT(0)
#define PHY_RETENTIONED BIT(1)
#define XO_SHUTDOWN BIT(2)
#define CLOCKS_DOWN BIT(3)
+#define PHY_REGULATORS_LPM BIT(4)
int reset_counter;
unsigned long b_last_se0_sess;
unsigned long tmouts;
diff --git a/include/media/vcap_v4l2.h b/include/media/vcap_v4l2.h
index 1e18c9e..7b6d817 100644
--- a/include/media/vcap_v4l2.h
+++ b/include/media/vcap_v4l2.h
@@ -38,6 +38,7 @@
writel_relaxed(val, addr); \
} while (0)
+#define VCAP_USEC (1000000)
#define VCAP_BASE (dev->vcapbase)
#define VCAP_OFFSET(off) (VCAP_BASE + off)
@@ -87,6 +88,9 @@
uint8_t tot_buf;
uint8_t buf_num;
+ struct timeval vc_ts;
+ uint32_t last_ts;
+
/* Buffers inside vc */
struct vcap_buffer *buf[6];
};