Merge "msm: kgsl: Synchronize access to IOMMU cfg port"
diff --git a/Documentation/devicetree/bindings/arm/msm/lpm-resources.txt b/Documentation/devicetree/bindings/arm/msm/lpm-resources.txt
index 7f2a21b..ccb3465 100644
--- a/Documentation/devicetree/bindings/arm/msm/lpm-resources.txt
+++ b/Documentation/devicetree/bindings/arm/msm/lpm-resources.txt
@@ -23,6 +23,7 @@
- qcom,resource-type: The type of the LPM resource.
MSM_LPM_RPM_RS_TYPE = 0
MSM_LPM_LOCAL_RS_TYPE = 1
+- qcom,init-value: Initialization value of the LPM resource.
Optional Nodes:
@@ -41,5 +42,6 @@
qcom,type = <0x62706d73>; /* "smpb" */
qcom,id = <0x02>;
qcom,key = <0x6e726f63>; /* "corn" */
+ qcom,init-value= <5>; /* Active Corner*/
};
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 89c7417..53fd3b2 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1889,7 +1889,6 @@
config DONT_MAP_HOLE_AFTER_MEMBANK0
def_bool n
- depends on SPARSEMEM
config ARCH_ENABLE_MEMORY_HOTPLUG
def_bool n
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index 6538db5..7a9a80d 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -83,7 +83,7 @@
"ocv_for_r",
"cc_thr";
- qcom,bms-r-sense-mohm = <10>;
+ qcom,bms-r-sense-mohm = <2>;
qcom,bms-v-cutoff-uv = <3400000>;
qcom,bms-max-voltage-uv = <4200000>;
qcom,bms-r-conn-mohm = <18>;
@@ -95,7 +95,6 @@
qcom,bms-calculate-soc-ms = <20000>;
qcom,bms-chg-term-ua = <100000>;
qcom,bms-batt-type = <0>;
- qcom,bms-use-voltage-soc;
};
clkdiv@5b00 {
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index 927ebcd..a07788b 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -55,6 +55,13 @@
status = "disabled";
};
+ qcom,sps@f9984000 {
+ compatible = "qcom,msm_sps";
+ reg = <0xf9984000 0x15000>,
+ <0xf9999000 0xb000>;
+ interrupts = <0 94 0>;
+ };
+
usb@f9a55000 {
compatible = "qcom,hsusb-otg";
reg = <0xf9a55000 0x400>;
diff --git a/arch/arm/boot/dts/msm8974-pm.dtsi b/arch/arm/boot/dts/msm8974-pm.dtsi
index 52f2a41..c877134 100644
--- a/arch/arm/boot/dts/msm8974-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974-pm.dtsi
@@ -143,6 +143,7 @@
qcom,type = <0x62706d73>; /* "smpb" */
qcom,id = <0x02>;
qcom,key = <0x6e726f63>; /* "corn" */
+ qcom,init-value = <5>; /* Super Turbo */
};
qcom,lpm-resources@1 {
@@ -152,6 +153,7 @@
qcom,type = <0x62706d73>; /* "smpb" */
qcom,id = <0x01>;
qcom,key = <0x7675>; /* "uv" */
+ qcom,init-value = <1050000>; /* Super Turbo */
};
qcom,lpm-resources@2 {
@@ -161,12 +163,14 @@
qcom,type = <0x306b6c63>; /* "clk0" */
qcom,id = <0x00>;
qcom,key = <0x62616e45>; /* "Enab" */
+ qcom,init-value = <1>; /* On */
};
qcom,lpm-resources@3 {
reg = <0x3>;
qcom,name = "l2";
qcom,resource-type = <1>;
+ qcom,init-value = <2>; /* Retention */
};
};
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 6a7e81e..406be59 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -188,8 +188,6 @@
qcom,vdd-voltage-level = <2950000 2950000>;
qcom,vdd-current-level = <9000 800000>;
- qcom,vdd-io-always-on;
- qcom,vdd-io-lpm-sup;
qcom,vdd-io-voltage-level = <1800000 2950000>;
qcom,vdd-io-current-level = <6 22000>;
diff --git a/arch/arm/boot/dts/msm9625-pm.dtsi b/arch/arm/boot/dts/msm9625-pm.dtsi
index 2839864..dbdddb6 100644
--- a/arch/arm/boot/dts/msm9625-pm.dtsi
+++ b/arch/arm/boot/dts/msm9625-pm.dtsi
@@ -42,6 +42,7 @@
qcom,type = <0x616F646C>; /* "ldoa" */
qcom,id = <0x0A>;
qcom,key = <0x6e726f63>; /* "corn" */
+ qcom,init-value = <5>; /* Super Turbo */
};
qcom,lpm-resources@1 {
@@ -51,6 +52,7 @@
qcom,type = <0x616F646C>; /* "ldoa" */
qcom,id = <0x0C>;
qcom,key = <0x7675>; /* "uv" */
+ qcom,init-value = <1050000>; /* Super Turbo */
};
qcom,lpm-resources@2 {
@@ -60,6 +62,7 @@
qcom,type = <0x306b6c63>; /* "clk0" */
qcom,id = <0x00>;
qcom,key = <0x62616e45>; /* "Enab" */
+ qcom,init-value = <1>; /* On */
};
};
diff --git a/arch/arm/configs/msm8910_defconfig b/arch/arm/configs/msm8910_defconfig
index de78559..b49a83f 100644
--- a/arch/arm/configs/msm8910_defconfig
+++ b/arch/arm/configs/msm8910_defconfig
@@ -47,6 +47,7 @@
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_SMP=y
+CONFIG_SCHED_MC=y
CONFIG_ARM_ARCH_TIMER=y
CONFIG_HOTPLUG_CPU=y
CONFIG_PREEMPT=y
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index 1fe1eaa..e5fd0d5 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -100,6 +100,7 @@
CONFIG_HIGH_RES_TIMERS=y
CONFIG_SMP=y
# CONFIG_SMP_ON_UP is not set
+CONFIG_SCHED_MC=y
CONFIG_PREEMPT=y
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 01d1934..02756e9 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -105,6 +105,7 @@
CONFIG_HIGH_RES_TIMERS=y
CONFIG_SMP=y
# CONFIG_SMP_ON_UP is not set
+CONFIG_SCHED_MC=y
CONFIG_PREEMPT=y
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index 71e83f6..94e2f36 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -77,6 +77,7 @@
CONFIG_HIGH_RES_TIMERS=y
CONFIG_SMP=y
# CONFIG_SMP_ON_UP is not set
+CONFIG_SCHED_MC=y
CONFIG_ARM_ARCH_TIMER=y
CONFIG_PREEMPT=y
CONFIG_AEABI=y
@@ -283,6 +284,7 @@
CONFIG_SENSORS_QPNP_ADC_CURRENT=y
CONFIG_THERMAL=y
CONFIG_THERMAL_TSENS8974=y
+CONFIG_THERMAL_MONITOR=y
CONFIG_THERMAL_QPNP=y
CONFIG_WCD9320_CODEC=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index ffcc83f..0e9bf1d 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -79,6 +79,7 @@
CONFIG_HIGH_RES_TIMERS=y
CONFIG_SMP=y
# CONFIG_SMP_ON_UP is not set
+CONFIG_SCHED_MC=y
CONFIG_ARM_ARCH_TIMER=y
CONFIG_PREEMPT=y
CONFIG_AEABI=y
@@ -285,6 +286,7 @@
CONFIG_SENSORS_QPNP_ADC_CURRENT=y
CONFIG_THERMAL=y
CONFIG_THERMAL_TSENS8974=y
+CONFIG_THERMAL_MONTIOR=y
CONFIG_THERMAL_QPNP=y
CONFIG_WCD9320_CODEC=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 5e51bb8..e6255f2 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -505,7 +505,7 @@
config MSM_MPM_OF
bool "Modem Power Manager"
- depends on CONFIG_OF
+ depends on OF
help
MPM is a dedicated hardware resource responsible for entering and
waking up from a system wide low power mode. The MPM driver tracks
@@ -2112,7 +2112,7 @@
config MSM_BUSPM_DEV
tristate "MSM Bus Performance Monitor Kernel Module"
- depends on (ARCH_MSM8X60 || ARCH_MSM8960)
+ depends on (ARCH_MSM8X60 || ARCH_MSM8960 || ARCH_MSM8974)
default m
help
This kernel module is used to mmap() hardware registers for the
@@ -2265,7 +2265,7 @@
config MSM_RUN_QUEUE_STATS
bool "Enable collection and exporting of MSM Run Queue stats to userspace"
- depends on (MSM_SOC_REV_A || ARCH_MSM8X60 || ARCH_MSM8960)
+ default n
help
This option enalbes statistics collection on Run Queue. A daemon
in user mode, called MPDecision will be using this data to decide
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 26aa32c..af77726 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -28,7 +28,7 @@
ifdef CONFIG_ARCH_MSM_KRAIT
obj-$(CONFIG_DEBUG_FS) += acpuclock-krait-debug.o
endif
-obj-$(CONFIG_ARCH_MSM7X27) += acpuclock-7627.o clock-pll.o
+obj-$(CONFIG_ARCH_MSM7X27) += acpuclock-7627.o acpuclock-8625q.o clock-pll.o
obj-$(CONFIG_ARCH_MSM_SCORPION) += pmu.o
obj-$(CONFIG_ARCH_MSM_SCORPIONMP) += perf_event_msm_l2.o
obj-$(CONFIG_ARCH_MSM_KRAIT) += msm-krait-l2-accessors.o pmu.o perf_event_msm_krait_l2.o
diff --git a/arch/arm/mach-msm/acpuclock-8625q.c b/arch/arm/mach-msm/acpuclock-8625q.c
new file mode 100644
index 0000000..00022ff
--- /dev/null
+++ b/arch/arm/mach-msm/acpuclock-8625q.c
@@ -0,0 +1,762 @@
+/*
+ * Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 2007-2012, Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/cpufreq.h>
+#include <linux/mutex.h>
+#include <linux/io.h>
+#include <linux/sort.h>
+#include <linux/regulator/consumer.h>
+#include <linux/smp.h>
+
+#include <mach/board.h>
+#include <mach/msm_iomap.h>
+#include <mach/clk-provider.h>
+
+#include <asm/cpu.h>
+
+#include "acpuclock.h"
+#include "acpuclock-8625q.h"
+
+#define A11S_CLK_CNTL_ADDR (MSM_CSR_BASE + 0x100)
+#define A11S_CLK_SEL_ADDR (MSM_CSR_BASE + 0x104)
+
+#define PLL4_L_VAL_ADDR (MSM_CLK_CTL_BASE + 0x378)
+#define PLL4_M_VAL_ADDR (MSM_CLK_CTL_BASE + 0x37C)
+#define PLL4_N_VAL_ADDR (MSM_CLK_CTL_BASE + 0x380)
+
+#define POWER_COLLAPSE_KHZ 19200
+
+/* Max CPU frequency allowed by hardware while in standby waiting for an irq. */
+#define MAX_WAIT_FOR_IRQ_KHZ 128000
+
+/**
+ * enum - For acpuclock PLL IDs
+ */
+enum {
+ ACPU_PLL_0 = 0,
+ ACPU_PLL_1,
+ ACPU_PLL_2,
+ ACPU_PLL_3,
+ ACPU_PLL_4,
+ ACPU_PLL_TCXO,
+ ACPU_PLL_END,
+};
+
+struct acpu_clk_src {
+ struct clk *clk;
+ const char *name;
+};
+
+struct pll_config {
+ unsigned int l;
+ unsigned int m;
+ unsigned int n;
+};
+
+static struct acpu_clk_src pll_clk[ACPU_PLL_END] = {
+ [ACPU_PLL_0] = { .name = "pll0_clk" },
+ [ACPU_PLL_1] = { .name = "pll1_clk" },
+ [ACPU_PLL_2] = { .name = "pll2_clk" },
+ [ACPU_PLL_4] = { .name = "pll4_clk" },
+};
+
+static struct pll_config pll4_cfg_tbl[] = {
+ [0] = { 36, 1, 2 }, /* 700.8 MHz */
+ [1] = { 52, 1, 2 }, /* 1008 MHz */
+ [2] = { 63, 0, 1 }, /* 1209.6 MHz */
+ [3] = { 73, 0, 1 }, /* 1401.6 MHz */
+};
+
+struct clock_state {
+ struct clkctl_acpu_speed *current_speed;
+ struct mutex lock;
+ uint32_t max_speed_delta_khz;
+ struct clk *ebi1_clk;
+ struct regulator *vreg_cpu;
+};
+
+struct clkctl_acpu_speed {
+ unsigned int use_for_scaling;
+ unsigned int a11clk_khz;
+ int pll;
+ unsigned int a11clk_src_sel;
+ unsigned int a11clk_src_div;
+ unsigned int ahbclk_khz;
+ unsigned int ahbclk_div;
+ int vdd;
+ unsigned int axiclk_khz;
+ struct pll_config *pll_rate;
+ unsigned long lpj;
+};
+
+static struct clock_state drv_state = { 0 };
+
+/* PVS MAX Voltage in uV as per frequencies*/
+
+# define MAX_14GHZ_VOLTAGE 1350000
+# define MAX_12GHZ_VOLTAGE 1275000
+# define MAX_1GHZ_VOLTAGE 1175000
+# define MAX_NOMINAL_VOLTAGE 1150000
+
+/* PVS deltas as per formula*/
+# define DELTA_LEVEL_1_UV 0
+# define DELTA_LEVEL_2_UV 75000
+# define DELTA_LEVEL_3_UV 150000
+
+
+static struct clkctl_acpu_speed acpu_freq_tbl_cmn[] = {
+ { 0, 19200, ACPU_PLL_TCXO, 0, 0, 2400, 3, 0, 30720 },
+ { 1, 245760, ACPU_PLL_1, 1, 0, 30720, 3, MAX_NOMINAL_VOLTAGE, 61440 },
+ { 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, MAX_NOMINAL_VOLTAGE, 122880 },
+ { 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, MAX_NOMINAL_VOLTAGE, 122880 },
+ { 0, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 0, 160000 },
+ { 1, 700800, ACPU_PLL_4, 6, 0, 87500, 3, MAX_NOMINAL_VOLTAGE, 160000,
+ &pll4_cfg_tbl[0]},
+ { 1, 1008000, ACPU_PLL_4, 6, 0, 126000, 3, MAX_1GHZ_VOLTAGE, 200000,
+ &pll4_cfg_tbl[1]},
+};
+
+static struct clkctl_acpu_speed acpu_freq_tbl_1209[] = {
+ { 1, 1209600, ACPU_PLL_4, 6, 0, 151200, 3, MAX_12GHZ_VOLTAGE, 200000,
+ &pll4_cfg_tbl[2]},
+};
+
+static struct clkctl_acpu_speed acpu_freq_tbl_1401[] = {
+ { 1, 1401600, ACPU_PLL_4, 6, 0, 175000, 3, MAX_14GHZ_VOLTAGE, 200000,
+ &pll4_cfg_tbl[3]},
+};
+
+/* Entry corresponding to CDMA build*/
+static struct clkctl_acpu_speed acpu_freq_tbl_196608[] = {
+ { 1, 196608, ACPU_PLL_1, 1, 0, 65536, 2, MAX_NOMINAL_VOLTAGE, 98304 },
+};
+
+static struct clkctl_acpu_speed acpu_freq_tbl_null[] = {
+ { 0 },
+};
+
+static struct clkctl_acpu_speed acpu_freq_tbl[ARRAY_SIZE(acpu_freq_tbl_cmn)
+ + ARRAY_SIZE(acpu_freq_tbl_1209)
+ + ARRAY_SIZE(acpu_freq_tbl_1401)
+ + ARRAY_SIZE(acpu_freq_tbl_null)];
+
+/* Switch to this when reprogramming PLL4 */
+static struct clkctl_acpu_speed *backup_s;
+
+#ifdef CONFIG_CPU_FREQ_MSM
+static struct cpufreq_frequency_table freq_table[NR_CPUS][20];
+
+static void __devinit cpufreq_table_init(void)
+{
+ int cpu;
+ for_each_possible_cpu(cpu) {
+ unsigned int i, freq_cnt = 0;
+
+ /* Construct the freq_table table from acpu_freq_tbl since
+ * the freq_table values need to match frequencies specified
+ * in acpu_freq_tbl and acpu_freq_tbl needs to be fixed up
+ * during init.
+ */
+ for (i = 0; acpu_freq_tbl[i].a11clk_khz != 0
+ && freq_cnt < ARRAY_SIZE(*freq_table)-1; i++) {
+ if (acpu_freq_tbl[i].use_for_scaling) {
+ freq_table[cpu][freq_cnt].index = freq_cnt;
+ freq_table[cpu][freq_cnt].frequency
+ = acpu_freq_tbl[i].a11clk_khz;
+ freq_cnt++;
+ }
+ }
+
+ /* freq_table not big enough to store all usable freqs. */
+ BUG_ON(acpu_freq_tbl[i].a11clk_khz != 0);
+
+ freq_table[cpu][freq_cnt].index = freq_cnt;
+ freq_table[cpu][freq_cnt].frequency = CPUFREQ_TABLE_END;
+ /* Register table with CPUFreq. */
+ cpufreq_frequency_table_get_attr(freq_table[cpu], cpu);
+ pr_info("CPU%d: %d scaling frequencies supported.\n",
+ cpu, freq_cnt);
+ }
+}
+#else
+static void __devinit cpufreq_table_init(void) { }
+#endif
+
+static void update_jiffies(int cpu, unsigned long loops)
+{
+#ifdef CONFIG_SMP
+ for_each_possible_cpu(cpu) {
+ per_cpu(cpu_data, cpu).loops_per_jiffy =
+ loops;
+ }
+#endif
+ /* Adjust the global one */
+ loops_per_jiffy = loops;
+}
+
+/* Assumes PLL4 is off and the acpuclock isn't sourced from PLL4 */
+static void acpuclk_config_pll4(struct pll_config *pll)
+{
+ /*
+ * Make sure write to disable PLL_4 has completed
+ * before reconfiguring that PLL.
+ */
+ mb();
+ writel_relaxed(pll->l, PLL4_L_VAL_ADDR);
+ writel_relaxed(pll->m, PLL4_M_VAL_ADDR);
+ writel_relaxed(pll->n, PLL4_N_VAL_ADDR);
+ /* Make sure PLL is programmed before returning. */
+ mb();
+}
+
+/* Set proper dividers for the given clock speed. */
+static void acpuclk_set_div(const struct clkctl_acpu_speed *hunt_s)
+{
+ uint32_t reg_clkctl, reg_clksel, clk_div, src_sel;
+
+ reg_clksel = readl_relaxed(A11S_CLK_SEL_ADDR);
+
+ /* AHB_CLK_DIV */
+ clk_div = (reg_clksel >> 1) & 0x03;
+ /* CLK_SEL_SRC1NO */
+ src_sel = reg_clksel & 1;
+
+ /*
+ * If the new clock divider is higher than the previous, then
+ * program the divider before switching the clock
+ */
+ if (hunt_s->ahbclk_div > clk_div) {
+ reg_clksel &= ~(0x3 << 1);
+ reg_clksel |= (hunt_s->ahbclk_div << 1);
+ writel_relaxed(reg_clksel, A11S_CLK_SEL_ADDR);
+ }
+
+ /* Program clock source and divider */
+ reg_clkctl = readl_relaxed(A11S_CLK_CNTL_ADDR);
+ reg_clkctl &= ~(0xFF << (8 * src_sel));
+ reg_clkctl |= hunt_s->a11clk_src_sel << (4 + 8 * src_sel);
+ reg_clkctl |= hunt_s->a11clk_src_div << (0 + 8 * src_sel);
+ writel_relaxed(reg_clkctl, A11S_CLK_CNTL_ADDR);
+
+ /* Program clock source selection */
+ reg_clksel ^= 1;
+ writel_relaxed(reg_clksel, A11S_CLK_SEL_ADDR);
+
+ /* Wait for the clock switch to complete */
+ mb();
+ udelay(50);
+
+ /*
+ * If the new clock divider is lower than the previous, then
+ * program the divider after switching the clock
+ */
+ if (hunt_s->ahbclk_div < clk_div) {
+ reg_clksel &= ~(0x3 << 1);
+ reg_clksel |= (hunt_s->ahbclk_div << 1);
+ writel_relaxed(reg_clksel, A11S_CLK_SEL_ADDR);
+ }
+}
+
+static int acpuclk_set_vdd_level(int vdd)
+{
+ int rc;
+
+ rc = regulator_set_voltage(drv_state.vreg_cpu, vdd, vdd);
+ if (rc) {
+ pr_err("failed to set vdd=%d uV\n", vdd);
+ return rc;
+ }
+
+ return 0;
+}
+
+static int acpuclk_8625q_set_rate(int cpu, unsigned long rate,
+ enum setrate_reason reason)
+{
+ uint32_t reg_clkctl;
+ struct clkctl_acpu_speed *cur_s, *tgt_s, *strt_s;
+ int res, rc = 0;
+ unsigned int plls_enabled = 0, pll;
+ int delta;
+
+
+ if (reason == SETRATE_CPUFREQ)
+ mutex_lock(&drv_state.lock);
+
+ strt_s = cur_s = drv_state.current_speed;
+
+ WARN_ONCE(cur_s == NULL, "%s: not initialized\n", __func__);
+ if (cur_s == NULL) {
+ rc = -ENOENT;
+ goto out;
+ }
+
+ cur_s->vdd = regulator_get_voltage(drv_state.vreg_cpu);
+ if (cur_s->vdd <= 0)
+ goto out;
+
+ pr_debug("current freq=%dKhz vdd=%duV\n",
+ cur_s->a11clk_khz, cur_s->vdd);
+
+ if (rate == cur_s->a11clk_khz)
+ goto out;
+
+ for (tgt_s = acpu_freq_tbl; tgt_s->a11clk_khz != 0; tgt_s++) {
+ if (tgt_s->a11clk_khz == rate)
+ break;
+ }
+
+ if (tgt_s->a11clk_khz == 0) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ /* Choose the highest speed at or below 'rate' with same PLL. */
+ if (reason != SETRATE_CPUFREQ
+ && tgt_s->a11clk_khz < cur_s->a11clk_khz) {
+ while (tgt_s->pll != ACPU_PLL_TCXO &&
+ tgt_s->pll != cur_s->pll) {
+ pr_debug("Intermediate frequency changes: %u\n",
+ tgt_s->a11clk_khz);
+ tgt_s--;
+ }
+ }
+
+ if (strt_s->pll != ACPU_PLL_TCXO)
+ plls_enabled |= 1 << strt_s->pll;
+
+ /* Need to do this when coming out of power collapse since some modem
+ * firmwares reset the VDD when the application processor enters power
+ * collapse.
+ */
+ if (reason == SETRATE_CPUFREQ || reason == SETRATE_PC) {
+ /* Increase VDD if needed. */
+ if (tgt_s->vdd > cur_s->vdd) {
+ rc = acpuclk_set_vdd_level(tgt_s->vdd);
+ if (rc < 0) {
+ pr_err("Unable to switch ACPU vdd (%d)\n", rc);
+ goto out;
+ }
+ pr_debug("Increased Vdd to %duV\n", tgt_s->vdd);
+ }
+ }
+
+ /* Set wait states for CPU inbetween frequency changes */
+ reg_clkctl = readl_relaxed(A11S_CLK_CNTL_ADDR);
+ reg_clkctl |= (100 << 16); /* set WT_ST_CNT */
+ writel_relaxed(reg_clkctl, A11S_CLK_CNTL_ADDR);
+
+ pr_debug("Switching from ACPU rate %u KHz -> %u KHz\n",
+ strt_s->a11clk_khz, tgt_s->a11clk_khz);
+
+ delta = abs((int)(strt_s->a11clk_khz - tgt_s->a11clk_khz));
+
+ if (tgt_s->pll == ACPU_PLL_4) {
+ if (strt_s->pll == ACPU_PLL_4 ||
+ delta > drv_state.max_speed_delta_khz) {
+ /*
+ * Enable the backup PLL if required
+ * and switch to it.
+ */
+ clk_enable(pll_clk[backup_s->pll].clk);
+ acpuclk_set_div(backup_s);
+ update_jiffies(cpu, backup_s->lpj);
+ }
+ /* Make sure PLL4 is off before reprogramming */
+ if ((plls_enabled & (1 << tgt_s->pll))) {
+ clk_disable(pll_clk[tgt_s->pll].clk);
+ plls_enabled &= ~(1 << tgt_s->pll);
+ }
+ acpuclk_config_pll4(tgt_s->pll_rate);
+ pll_clk[tgt_s->pll].clk->rate = tgt_s->a11clk_khz*1000;
+
+ } else if (strt_s->pll == ACPU_PLL_4) {
+ if (delta > drv_state.max_speed_delta_khz) {
+ /*
+ * Enable the bcackup PLL if required
+ * and switch to it.
+ */
+ clk_enable(pll_clk[backup_s->pll].clk);
+ acpuclk_set_div(backup_s);
+ update_jiffies(cpu, backup_s->lpj);
+ }
+ }
+
+ if ((tgt_s->pll != ACPU_PLL_TCXO) &&
+ !(plls_enabled & (1 << tgt_s->pll))) {
+ rc = clk_enable(pll_clk[tgt_s->pll].clk);
+ if (rc < 0) {
+ pr_err("PLL%d enable failed (%d)\n",
+ tgt_s->pll, rc);
+ goto out;
+ }
+ plls_enabled |= 1 << tgt_s->pll;
+ }
+ acpuclk_set_div(tgt_s);
+ drv_state.current_speed = tgt_s;
+ pr_debug("The new clock speed is %u\n", tgt_s->a11clk_khz);
+ /* Re-adjust lpj for the new clock speed. */
+ update_jiffies(cpu, tgt_s->lpj);
+
+ /* Disable the backup PLL */
+ if ((delta > drv_state.max_speed_delta_khz)
+ || (strt_s->pll == ACPU_PLL_4 &&
+ tgt_s->pll == ACPU_PLL_4))
+ clk_disable(pll_clk[backup_s->pll].clk);
+
+ /* Nothing else to do for SWFI. */
+ if (reason == SETRATE_SWFI)
+ goto out;
+
+ /* Change the AXI bus frequency if we can. */
+ if (reason != SETRATE_PC &&
+ strt_s->axiclk_khz != tgt_s->axiclk_khz) {
+ res = clk_set_rate(drv_state.ebi1_clk,
+ tgt_s->axiclk_khz * 1000);
+ pr_debug("AXI bus set freq %d\n",
+ tgt_s->axiclk_khz * 1000);
+ if (res < 0)
+ pr_warning("Setting AXI min rate failed (%d)\n", res);
+ }
+
+ /* Disable PLLs we are not using anymore. */
+ if (tgt_s->pll != ACPU_PLL_TCXO)
+ plls_enabled &= ~(1 << tgt_s->pll);
+ for (pll = ACPU_PLL_0; pll < ACPU_PLL_END; pll++)
+ if (plls_enabled & (1 << pll))
+ clk_disable(pll_clk[pll].clk);
+
+ /* Nothing else to do for power collapse. */
+ if (reason == SETRATE_PC)
+ goto out;
+
+ /* Drop VDD level if we can. */
+ if (tgt_s->vdd < strt_s->vdd) {
+ res = acpuclk_set_vdd_level(tgt_s->vdd);
+ if (res < 0)
+ pr_warning("Unable to drop ACPU vdd (%d)\n", res);
+ pr_debug("Decreased Vdd to %duV\n", tgt_s->vdd);
+ }
+
+ pr_debug("ACPU speed change complete\n");
+out:
+ if (reason == SETRATE_CPUFREQ)
+ mutex_unlock(&drv_state.lock);
+
+ return rc;
+}
+
+static int __devinit acpuclk_hw_init(void)
+{
+ struct clkctl_acpu_speed *speed;
+ uint32_t div, sel, reg_clksel;
+ int res;
+
+ /*
+ * Prepare all the PLLs because we enable/disable them
+ * from atomic context and can't always ensure they're
+ * all prepared in non-atomic context. Same goes for
+ * ebi1_acpu_clk.
+ */
+ BUG_ON(clk_prepare(pll_clk[ACPU_PLL_0].clk));
+ BUG_ON(clk_prepare(pll_clk[ACPU_PLL_1].clk));
+ BUG_ON(clk_prepare(pll_clk[ACPU_PLL_2].clk));
+ BUG_ON(clk_prepare(pll_clk[ACPU_PLL_4].clk));
+ BUG_ON(clk_prepare(drv_state.ebi1_clk));
+
+ /*
+ * Determine the rate of ACPU clock
+ */
+
+ if (!(readl_relaxed(A11S_CLK_SEL_ADDR) & 0x01)) { /* CLK_SEL_SRC1N0 */
+ /* CLK_SRC0_SEL */
+ sel = (readl_relaxed(A11S_CLK_CNTL_ADDR) >> 12) & 0x7;
+ /* CLK_SRC0_DIV */
+ div = (readl_relaxed(A11S_CLK_CNTL_ADDR) >> 8) & 0x0f;
+ } else {
+ /* CLK_SRC1_SEL */
+ sel = (readl_relaxed(A11S_CLK_CNTL_ADDR) >> 4) & 0x07;
+ /* CLK_SRC1_DIV */
+ div = readl_relaxed(A11S_CLK_CNTL_ADDR) & 0x0f;
+ }
+
+ for (speed = acpu_freq_tbl; speed->a11clk_khz != 0; speed++) {
+ if (speed->a11clk_src_sel == sel
+ && (speed->a11clk_src_div == div))
+ break;
+ }
+ if (speed->a11clk_khz == 0) {
+ pr_err("Error - ACPU clock reports invalid speed\n");
+ return -EINVAL;
+ }
+
+ drv_state.current_speed = speed;
+ if (speed->pll != ACPU_PLL_TCXO) {
+ if (clk_enable(pll_clk[speed->pll].clk)) {
+ pr_warning("Failed to vote for boot PLL\n");
+ return -ENODEV;
+ }
+ }
+
+ reg_clksel = readl_relaxed(A11S_CLK_SEL_ADDR);
+ reg_clksel &= ~(0x3 << 14);
+ reg_clksel |= (0x1 << 14);
+ writel_relaxed(reg_clksel, A11S_CLK_SEL_ADDR);
+
+ res = clk_set_rate(drv_state.ebi1_clk, speed->axiclk_khz * 1000);
+ if (res < 0) {
+ pr_warning("Setting AXI min rate failed (%d)\n", res);
+ return -ENODEV;
+ }
+ res = clk_enable(drv_state.ebi1_clk);
+ if (res < 0) {
+ pr_warning("Enabling AXI clock failed (%d)\n", res);
+ return -ENODEV;
+ }
+
+ drv_state.vreg_cpu = regulator_get(NULL, "vddx_cx");
+ if (IS_ERR(drv_state.vreg_cpu)) {
+ res = PTR_ERR(drv_state.vreg_cpu);
+ pr_err("could not get regulator: %d\n", res);
+ }
+
+ pr_info("ACPU running at %d KHz\n", speed->a11clk_khz);
+ return 0;
+}
+
+static unsigned long acpuclk_8625q_get_rate(int cpu)
+{
+ WARN_ONCE(drv_state.current_speed == NULL,
+ "%s: not initialized\n", __func__);
+ if (drv_state.current_speed)
+ return drv_state.current_speed->a11clk_khz;
+ else
+ return 0;
+}
+
+#define MHZ 1000000
+
+static void __devinit select_freq_plan(unsigned int pvs_voltage)
+{
+ unsigned long pll_mhz[ACPU_PLL_END];
+ int i;
+ int size;
+ int delta[3] = {DELTA_LEVEL_1_UV, DELTA_LEVEL_2_UV, DELTA_LEVEL_3_UV};
+ struct clkctl_acpu_speed *tbl;
+
+ /* Get PLL clocks */
+ for (i = 0; i < ACPU_PLL_END; i++) {
+ if (pll_clk[i].name) {
+ pll_clk[i].clk = clk_get_sys("acpu", pll_clk[i].name);
+ if (IS_ERR(pll_clk[i].clk)) {
+ pll_mhz[i] = 0;
+ continue;
+ }
+ /* Get PLL's Rate */
+ pll_mhz[i] = clk_get_rate(pll_clk[i].clk)/MHZ;
+ }
+ }
+
+ memcpy(acpu_freq_tbl, acpu_freq_tbl_cmn, sizeof(acpu_freq_tbl_cmn));
+ size = ARRAY_SIZE(acpu_freq_tbl_cmn);
+
+ i = 0; /* needed if we have a 1Ghz part */
+ /* select if it is a 1.2Ghz part */
+ if (pll_mhz[ACPU_PLL_4] == 1209) {
+ memcpy(acpu_freq_tbl + size, acpu_freq_tbl_1209,
+ sizeof(acpu_freq_tbl_1209));
+ size += sizeof(acpu_freq_tbl_1209);
+ i = 1; /* set the delta index */
+ }
+ /* select if it is a 1.4Ghz part */
+ if (pll_mhz[ACPU_PLL_4] == 1401) {
+ memcpy(acpu_freq_tbl + size, acpu_freq_tbl_1209,
+ sizeof(acpu_freq_tbl_1209));
+ size += ARRAY_SIZE(acpu_freq_tbl_1209);
+ memcpy(acpu_freq_tbl + size, acpu_freq_tbl_1401,
+ sizeof(acpu_freq_tbl_1401));
+ size += ARRAY_SIZE(acpu_freq_tbl_1401);
+ i = 2; /* set the delta index */
+ }
+
+ memcpy(acpu_freq_tbl + size, acpu_freq_tbl_null,
+ sizeof(acpu_freq_tbl_null));
+ size += sizeof(acpu_freq_tbl_null);
+
+ /* Alter the freq value in freq_tbl if it is a CDMA build*/
+ if (pll_mhz[ACPU_PLL_1] == 196) {
+
+ for (tbl = acpu_freq_tbl; tbl->a11clk_khz; tbl++) {
+ if (tbl->a11clk_khz == 245760 &&
+ tbl->pll == ACPU_PLL_1) {
+ pr_debug("Upgrading pll1 freq to 196 Mhz\n");
+ memcpy(tbl, acpu_freq_tbl_196608,
+ sizeof(acpu_freq_tbl_196608));
+ break;
+ }
+ }
+ }
+
+ /*
+ *PVS Voltage calculation formula
+ *1.4 Ghz device
+ *1.4 Ghz: Max(PVS_voltage,1.35V)
+ *1.2 Ghz: Max(PVS_volatge - 75mV,1.275V)
+ *1.0 Ghz: Max(PVS_voltage - 150mV, 1.175V)
+ *1.2 Ghz device
+ *1.2 Ghz: Max(PVS_voltage,1.275V)
+ *1.0 Ghz: Max(PVS_volatge - 75mV,1.175V)
+ *Nominal Mode: 1.15V
+ */
+ for (tbl = acpu_freq_tbl; tbl->a11clk_khz; tbl++) {
+ if (tbl->a11clk_khz >= 1008000) {
+ /*
+ * Change voltage as per PVS formula,
+ * i is initialized above with 2 or 1
+ * depending upon whether it is a 1.4Ghz
+ * or 1.2Ghz, so, we get the proper value
+ * from delta[i] which is to be deducted
+ * from PVS voltage.
+ */
+
+ tbl->vdd = max((int)(pvs_voltage - delta[i]), tbl->vdd);
+ i--;
+ }
+ }
+
+
+ /* find the backup PLL entry from the table */
+ for (tbl = acpu_freq_tbl; tbl->a11clk_khz; tbl++) {
+ if (tbl->pll == ACPU_PLL_2 &&
+ tbl->a11clk_src_div == 1) {
+ backup_s = tbl;
+ break;
+ }
+ }
+
+ BUG_ON(!backup_s);
+
+}
+
+/*
+ * Hardware requires the CPU to be dropped to less than MAX_WAIT_FOR_IRQ_KHZ
+ * before entering a wait for irq low-power mode. Find a suitable rate.
+ */
+static unsigned long __devinit find_wait_for_irq_khz(void)
+{
+ unsigned long found_khz = 0;
+ int i;
+
+ for (i = 0; acpu_freq_tbl[i].a11clk_khz &&
+ acpu_freq_tbl[i].a11clk_khz <= MAX_WAIT_FOR_IRQ_KHZ; i++)
+ found_khz = acpu_freq_tbl[i].a11clk_khz;
+
+ return found_khz;
+}
+
+static void __devinit lpj_init(void)
+{
+ int i = 0, cpu;
+ const struct clkctl_acpu_speed *base_clk = drv_state.current_speed;
+ unsigned long loops;
+
+ for_each_possible_cpu(cpu) {
+#ifdef CONFIG_SMP
+ loops = per_cpu(cpu_data, cpu).loops_per_jiffy;
+#else
+ loops = loops_per_jiffy;
+#endif
+ for (i = 0; acpu_freq_tbl[i].a11clk_khz; i++) {
+ acpu_freq_tbl[i].lpj = cpufreq_scale(
+ loops,
+ base_clk->a11clk_khz,
+ acpu_freq_tbl[i].a11clk_khz);
+ }
+
+ }
+
+}
+
+static struct acpuclk_data acpuclk_8625q_data = {
+ .set_rate = acpuclk_8625q_set_rate,
+ .get_rate = acpuclk_8625q_get_rate,
+ .power_collapse_khz = POWER_COLLAPSE_KHZ,
+ .switch_time_us = 50,
+};
+
+static void __devinit print_acpu_freq_tbl(void)
+{
+ struct clkctl_acpu_speed *t;
+ int i;
+
+ pr_info("Id CPU-KHz PLL DIV AHB-KHz ADIV AXI-KHz Vdd\n");
+
+ t = &acpu_freq_tbl[0];
+ for (i = 0; t->a11clk_khz != 0; i++) {
+ pr_info("%2d %7d %3d %3d %7d %4d %7d %3d\n",
+ i, t->a11clk_khz, t->pll, t->a11clk_src_div + 1,
+ t->ahbclk_khz, t->ahbclk_div + 1, t->axiclk_khz,
+ t->vdd);
+ t++;
+ }
+}
+
+static int __devinit acpuclk_8625q_probe(struct platform_device *pdev)
+{
+ const struct acpuclk_pdata_8625q *pdata = pdev->dev.platform_data;
+ unsigned int pvs_voltage = pdata->pvs_voltage_uv;
+
+ drv_state.max_speed_delta_khz = pdata->acpu_clk_data->
+ max_speed_delta_khz;
+
+ drv_state.ebi1_clk = clk_get(NULL, "ebi1_acpu_clk");
+ BUG_ON(IS_ERR(drv_state.ebi1_clk));
+
+ mutex_init(&drv_state.lock);
+ select_freq_plan(pvs_voltage);
+ acpuclk_8625q_data.wait_for_irq_khz = find_wait_for_irq_khz();
+
+ if (acpuclk_hw_init() < 0)
+ pr_err("acpuclk_hw_init not successful.\n");
+
+ print_acpu_freq_tbl();
+ lpj_init();
+ acpuclk_register(&acpuclk_8625q_data);
+
+ cpufreq_table_init();
+
+ return 0;
+}
+
+static struct platform_driver acpuclk_8625q_driver = {
+ .probe = acpuclk_8625q_probe,
+ .driver = {
+ .name = "acpuclock-8625q",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init acpuclk_8625q_init(void)
+{
+
+ return platform_driver_register(&acpuclk_8625q_driver);
+}
+postcore_initcall(acpuclk_8625q_init);
diff --git a/arch/arm/mach-msm/acpuclock-8625q.h b/arch/arm/mach-msm/acpuclock-8625q.h
new file mode 100644
index 0000000..ca2058f
--- /dev/null
+++ b/arch/arm/mach-msm/acpuclock-8625q.h
@@ -0,0 +1,28 @@
+/*
+ * MSM architecture CPU clock driver header
+ *
+ * Copyright (c) 2012, Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef __ARCH_ARM_MACH_MSM_ACPUCLOCK_8625Q_H
+#define __ARCH_ARM_MACH_MSM_ACPUCLOCK_8625Q_H
+
+# include "acpuclock.h"
+/**
+ * struct acpuclk_pdata_8625q - Platform data for acpuclk
+ */
+struct acpuclk_pdata_8625q {
+ struct acpuclk_pdata *acpu_clk_data;
+ unsigned int pvs_voltage_uv;
+};
+
+#endif /* __ARCH_ARM_MACH_MSM_ACPUCLOCK_8625Q_H */
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index f70e41a..ed03e46 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -2719,6 +2719,11 @@
.id = -1,
};
+static struct platform_device sp_input_loopback_pdev = {
+ .name = "sp-user-input",
+ .id = -1,
+};
+
static int rf4ce_gpio_init(void)
{
if (!machine_is_mpq8064_cdp() &&
@@ -2800,6 +2805,7 @@
#endif
&rc_input_loopback_pdev,
&mpq8064_device_qup_spi_gsbi6,
+ &sp_input_loopback_pdev,
};
static struct msm_spi_platform_data apq8064_qup_spi_gsbi5_pdata = {
diff --git a/arch/arm/mach-msm/board-8960-camera.c b/arch/arm/mach-msm/board-8960-camera.c
index 7a2e9e1..3853e4c 100644
--- a/arch/arm/mach-msm/board-8960-camera.c
+++ b/arch/arm/mach-msm/board-8960-camera.c
@@ -15,6 +15,7 @@
#include <linux/gpio.h>
#include <mach/camera.h>
#include <mach/msm_bus_board.h>
+#include <mach/socinfo.h>
#include <mach/gpiomux.h>
#include "devices.h"
#include "board-8960.h"
@@ -182,6 +183,23 @@
},
};
+static struct msm_gpiomux_config msm8960_cam_2d_configs_sglte[] = {
+ {
+ .gpio = 20,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[3],
+ [GPIOMUX_SUSPENDED] = &cam_settings[8],
+ },
+ },
+ {
+ .gpio = 21,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[3],
+ [GPIOMUX_SUSPENDED] = &cam_settings[8],
+ },
+ },
+};
+
#define VFE_CAMIF_TIMER1_GPIO 2
#define VFE_CAMIF_TIMER2_GPIO 3
#define VFE_CAMIF_TIMER3_GPIO_INT 4
@@ -828,6 +846,16 @@
void __init msm8960_init_cam(void)
{
+ if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE) {
+ msm_8960_front_cam_gpio_conf.cam_gpiomux_conf_tbl =
+ msm8960_cam_2d_configs_sglte;
+ msm_8960_front_cam_gpio_conf.cam_gpiomux_conf_tbl_size =
+ ARRAY_SIZE(msm8960_cam_2d_configs_sglte);
+ msm_8960_back_cam_gpio_conf.cam_gpiomux_conf_tbl =
+ msm8960_cam_2d_configs_sglte;
+ msm_8960_back_cam_gpio_conf.cam_gpiomux_conf_tbl_size =
+ ARRAY_SIZE(msm8960_cam_2d_configs_sglte);
+ }
msm_gpiomux_install(msm8960_cam_common_configs,
ARRAY_SIZE(msm8960_cam_common_configs));
diff --git a/arch/arm/mach-msm/board-8974-gpiomux.c b/arch/arm/mach-msm/board-8974-gpiomux.c
index 0f6c000..28d50cc 100644
--- a/arch/arm/mach-msm/board-8974-gpiomux.c
+++ b/arch/arm/mach-msm/board-8974-gpiomux.c
@@ -68,6 +68,12 @@
};
#endif
+static struct gpiomux_setting gpio_epm_config = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
static struct gpiomux_setting wcnss_5wire_suspend_cfg = {
.func = GPIOMUX_FUNC_GPIO,
.drv = GPIOMUX_DRV_2MA,
@@ -411,6 +417,12 @@
[GPIOMUX_SUSPENDED] = &gpio_spi_config,
},
},
+ {
+ .gpio = 81, /* EPM enable */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gpio_epm_config,
+ },
+ },
};
static struct msm_gpiomux_config msm8974_slimbus_config[] __initdata = {
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index 9fd5218..5cabe64 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -954,7 +954,7 @@
}
rpc_adsp_pdev->prog = ADSP_RPC_PROG;
- if (cpu_is_msm8625())
+ if (cpu_is_msm8625() || cpu_is_msm8625q())
rpc_adsp_pdev->pdev = msm8625_device_adsp;
else
rpc_adsp_pdev->pdev = msm_adsp_device;
@@ -1031,7 +1031,7 @@
{
msm7x27a_cfg_uart2dm_serial();
msm_uart_dm1_pdata.wakeup_irq = gpio_to_irq(UART1DM_RX_GPIO);
- if (cpu_is_msm8625())
+ if (cpu_is_msm8625() || cpu_is_msm8625q())
msm8625_device_uart_dm1.dev.platform_data =
&msm_uart_dm1_pdata;
else
@@ -1040,7 +1040,7 @@
static void __init msm7x27a_otg_gadget(void)
{
- if (cpu_is_msm8625()) {
+ if (cpu_is_msm8625() || cpu_is_msm8625q()) {
msm_otg_pdata.swfi_latency =
msm8625_pm_data[MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT].latency;
msm8625_device_otg.dev.platform_data = &msm_otg_pdata;
@@ -1080,7 +1080,7 @@
/* Initialize regulators first so that other devices can use them */
msm7x27a_init_regulators();
msm_adsp_add_pdev();
- if (cpu_is_msm8625())
+ if (cpu_is_msm8625() || cpu_is_msm8625q())
msm8625_device_i2c_init();
else
msm7x27a_device_i2c_init();
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index 47a3120..d15b67d 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -933,7 +933,7 @@
}
rpc_adsp_pdev->prog = ADSP_RPC_PROG;
- if (cpu_is_msm8625())
+ if (cpu_is_msm8625() || cpu_is_msm8625q())
rpc_adsp_pdev->pdev = msm8625_device_adsp;
else
rpc_adsp_pdev->pdev = msm_adsp_device;
@@ -1041,7 +1041,7 @@
static void __init qrd7627a_uart1dm_config(void)
{
msm_uart_dm1_pdata.wakeup_irq = gpio_to_irq(UART1DM_RX_GPIO);
- if (cpu_is_msm8625())
+ if (cpu_is_msm8625() || cpu_is_msm8625q())
msm8625_device_uart_dm1.dev.platform_data =
&msm_uart_dm1_pdata;
else
@@ -1050,7 +1050,7 @@
static void __init qrd7627a_otg_gadget(void)
{
- if (cpu_is_msm8625()) {
+ if (cpu_is_msm8625() || cpu_is_msm8625q()) {
msm_otg_pdata.swfi_latency = msm8625_pm_data
[MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT].latency;
msm8625_device_otg.dev.platform_data = &msm_otg_pdata;
@@ -1069,7 +1069,7 @@
static void __init msm_pm_init(void)
{
- if (!cpu_is_msm8625()) {
+ if (!cpu_is_msm8625() && !cpu_is_msm8625q()) {
msm_pm_set_platform_data(msm7627a_pm_data,
ARRAY_SIZE(msm7627a_pm_data));
BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
@@ -1088,7 +1088,7 @@
msm7627a_init_regulators();
msmqrd_adsp_add_pdev();
- if (cpu_is_msm8625())
+ if (cpu_is_msm8625() || cpu_is_msm8625q())
msm8625_device_i2c_init();
else
msm7627a_device_i2c_init();
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 95f9327..445fc47 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -666,7 +666,8 @@
#define A1_ID 4
#define A2_ID 5
#define DIFF_CLK_ID 7
-#define DIV_CLK_ID 11
+#define DIV_CLK1_ID 11
+#define DIV_CLK2_ID 12
DEFINE_CLK_RPM_SMD(pnoc_clk, pnoc_a_clk, RPM_BUS_CLK_TYPE, PNOC_ID, NULL);
DEFINE_CLK_RPM_SMD(snoc_clk, snoc_a_clk, RPM_BUS_CLK_TYPE, SNOC_ID, NULL);
@@ -689,7 +690,8 @@
DEFINE_CLK_RPM_SMD_XO_BUFFER(cxo_a0, cxo_a0_a, A0_ID);
DEFINE_CLK_RPM_SMD_XO_BUFFER(cxo_a1, cxo_a1_a, A1_ID);
DEFINE_CLK_RPM_SMD_XO_BUFFER(cxo_a2, cxo_a2_a, A2_ID);
-DEFINE_CLK_RPM_SMD_XO_BUFFER(div_clk, div_a_clk, DIV_CLK_ID);
+DEFINE_CLK_RPM_SMD_XO_BUFFER(div_clk1, div_a_clk1, DIV_CLK1_ID);
+DEFINE_CLK_RPM_SMD_XO_BUFFER(div_clk2, div_a_clk2, DIV_CLK2_ID);
DEFINE_CLK_RPM_SMD_XO_BUFFER(diff_clk, diff_a_clk, DIFF_CLK_ID);
DEFINE_CLK_RPM_SMD_XO_BUFFER_PINCTRL(cxo_d0_pin, cxo_d0_a_pin, D0_ID);
@@ -5129,6 +5131,7 @@
CLK_LOOKUP("phy_clk", gcc_usb_hsic_clk.c, "msm_hsic_host"),
CLK_LOOKUP("cal_clk", gcc_usb_hsic_io_cal_clk.c, "msm_hsic_host"),
CLK_LOOKUP("core_clk", gcc_usb_hsic_system_clk.c, "msm_hsic_host"),
+ CLK_LOOKUP("ref_clk", div_clk2.c, "msm_smsc_hub"),
/* Multimedia clocks */
CLK_LOOKUP("bus_clk_src", axi_clk_src.c, ""),
diff --git a/arch/arm/mach-msm/cpufreq.c b/arch/arm/mach-msm/cpufreq.c
index e0d98b7..d862d6d 100644
--- a/arch/arm/mach-msm/cpufreq.c
+++ b/arch/arm/mach-msm/cpufreq.c
@@ -227,7 +227,7 @@
* be changed independently. Each cpu is bound to
* same frequency. Hence set the cpumask to all cpu.
*/
- if (cpu_is_msm8625())
+ if (cpu_is_msm8625() || cpu_is_msm8625q())
cpumask_setall(policy->cpus);
if (cpufreq_frequency_table_cpuinfo(policy, table)) {
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index 8fc5020..b3d887e 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -515,7 +515,7 @@
void __init msm_pm_register_irqs(void)
{
- if (cpu_is_msm8625())
+ if (cpu_is_msm8625() || cpu_is_msm8625q())
msm_pm_set_irq_extns(&msm8625_pm_irq_calls);
else
msm_pm_set_irq_extns(&msm7x27a_pm_irq_calls);
@@ -530,8 +530,9 @@
void __init msm_pm_register_cpr_ops(void)
{
/* CPR presents on revision >= v2.0 chipsets */
- if (cpu_is_msm8625() &&
+ if ((cpu_is_msm8625() &&
SOCINFO_VERSION_MAJOR(socinfo_get_version()) >= 2)
+ || cpu_is_msm8625q())
msm_pm_set_cpr_ops(&msm8625_pm_cpr_ops);
}
@@ -952,7 +953,7 @@
void __init msm8x25_kgsl_3d0_init(void)
{
- if (cpu_is_msm8625()) {
+ if (cpu_is_msm8625() || cpu_is_msm8625q()) {
kgsl_3d0_pdata.idle_timeout = HZ/5;
kgsl_3d0_pdata.strtstp_sleepwake = false;
@@ -1406,7 +1407,7 @@
if (controller < 1 || controller > 4)
return -EINVAL;
- if (cpu_is_msm8625())
+ if (cpu_is_msm8625() || cpu_is_msm8625q())
pdev = msm8625_sdcc_devices[controller-1];
else
pdev = msm_sdcc_devices[controller-1];
@@ -1495,7 +1496,7 @@
{
struct platform_device *pdev;
- if (cpu_is_msm8625())
+ if (cpu_is_msm8625() || cpu_is_msm8625q())
pdev = msm8625_host_devices[host];
else
pdev = msm_host_devices[host];
@@ -1598,12 +1599,12 @@
void __init msm_fb_register_device(char *name, void *data)
{
if (!strncmp(name, "mdp", 3)) {
- if (cpu_is_msm8625())
+ if (cpu_is_msm8625() || cpu_is_msm8625q())
msm_register_device(&msm8625_mdp_device, data);
else
msm_register_device(&msm_mdp_device, data);
} else if (!strncmp(name, "mipi_dsi", 8)) {
- if (cpu_is_msm8625()) {
+ if (cpu_is_msm8625() || cpu_is_msm8625q()) {
msm_register_device(&msm8625_mipi_dsi_device, data);
mipi_dsi_device = msm8625_mipi_dsi_device;
} else {
@@ -2046,7 +2047,7 @@
msm_clock_init(&msm7x27a_clock_init_data);
if (cpu_is_msm7x27aa() || cpu_is_msm7x25ab())
platform_device_register(&msm7x27aa_device_acpuclk);
- else if (cpu_is_msm8625()) {
+ else if (cpu_is_msm8625() || cpu_is_msm8625q()) {
if (msm8625_cpu_id() == MSM8625)
platform_device_register(&msm7x27aa_device_acpuclk);
else if (msm8625_cpu_id() == MSM8625A)
@@ -2057,11 +2058,11 @@
platform_device_register(&msm7x27a_device_acpuclk);
}
- if (cpu_is_msm8625() &&
- (SOCINFO_VERSION_MAJOR(socinfo_get_version()) >= 2))
+ if (cpu_is_msm8625() || (cpu_is_msm8625q() &&
+ SOCINFO_VERSION_MAJOR(socinfo_get_version()) >= 2))
msm_cpr_init();
- if (!cpu_is_msm8625())
+ if (!cpu_is_msm8625() && !cpu_is_msm8625q())
pl310_resources[1].start = INT_L2CC_INTR;
platform_device_register(&pl310_erp_device);
@@ -2083,7 +2084,7 @@
(0x2 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT) | \
(0x1 << L2X0_AUX_CTRL_EVNT_MON_BUS_EN_SHIFT);
- if (cpu_is_msm8625()) {
+ if (cpu_is_msm8625() || cpu_is_msm8625q()) {
/* Way Size 011(0x3) 64KB */
aux_ctrl |= (0x3 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT) | \
(0x1 << L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT) | \
@@ -2099,7 +2100,7 @@
}
l2x0_init(MSM_L2CC_BASE, aux_ctrl, L2X0_AUX_CTRL_MASK);
- if (cpu_is_msm8625()) {
+ if (cpu_is_msm8625() || cpu_is_msm8625q()) {
pctrl = readl_relaxed(MSM_L2CC_BASE + L2X0_PREFETCH_CTRL);
pr_info("Prfetch Ctrl: 0x%08x\n", pctrl);
}
@@ -2136,7 +2137,7 @@
static int msm7627a_init_gpio(void)
{
- if (cpu_is_msm8625())
+ if (cpu_is_msm8625() || cpu_is_msm8625q())
platform_device_register(&msm8625_device_gpio);
else
platform_device_register(&msm_device_gpio);
diff --git a/arch/arm/mach-msm/include/mach/msm_adsp.h b/arch/arm/mach-msm/include/mach/msm_adsp.h
index e40c07d..ea08f0c 100644
--- a/arch/arm/mach-msm/include/mach/msm_adsp.h
+++ b/arch/arm/mach-msm/include/mach/msm_adsp.h
@@ -39,6 +39,7 @@
void msm_adsp_put(struct msm_adsp_module *module);
int msm_adsp_enable(struct msm_adsp_module *module);
int msm_adsp_disable(struct msm_adsp_module *module);
+int msm_adsp_dump(struct msm_adsp_module *module);
int adsp_set_clkrate(struct msm_adsp_module *module, unsigned long clk_rate);
int msm_adsp_disable_event_rsp(struct msm_adsp_module *module);
int32_t get_adsp_resource(unsigned short client_idx,
diff --git a/arch/arm/mach-msm/lpm_resources.c b/arch/arm/mach-msm/lpm_resources.c
index c21ea33..5d7fc94 100644
--- a/arch/arm/mach-msm/lpm_resources.c
+++ b/arch/arm/mach-msm/lpm_resources.c
@@ -47,8 +47,6 @@
static bool msm_lpm_get_rpm_notif = true;
/*Macros*/
-#define VDD_DIG_ACTIVE (5)
-#define VDD_MEM_ACTIVE (1050000)
#define MAX_RS_NAME (16)
#define MAX_RS_SIZE (4)
#define IS_RPM_CTL(rs) \
@@ -133,10 +131,6 @@
.flush = msm_lpm_flush_l2,
.notify = NULL,
.valid = false,
- .rs_data = {
- .value = MSM_LPM_L2_CACHE_ACTIVE,
- .default_value = MSM_LPM_L2_CACHE_ACTIVE,
- },
.ko_attr = RPMRS_ATTR(l2),
};
@@ -147,10 +141,6 @@
.flush = msm_lpm_flush_vdd_dig,
.notify = msm_lpm_notify_vdd_dig,
.valid = false,
- .rs_data = {
- .value = VDD_DIG_ACTIVE,
- .default_value = VDD_DIG_ACTIVE,
- },
.ko_attr = RPMRS_ATTR(vdd_dig),
};
@@ -161,10 +151,6 @@
.flush = msm_lpm_flush_vdd_mem,
.notify = msm_lpm_notify_vdd_mem,
.valid = false,
- .rs_data = {
- .value = VDD_MEM_ACTIVE,
- .default_value = VDD_MEM_ACTIVE,
- },
.ko_attr = RPMRS_ATTR(vdd_mem),
};
@@ -175,10 +161,6 @@
.flush = msm_lpm_flush_pxo,
.notify = msm_lpm_notify_pxo,
.valid = false,
- .rs_data = {
- .value = MSM_LPM_PXO_ON,
- .default_value = MSM_LPM_PXO_ON,
- },
.ko_attr = RPMRS_ATTR(pxo),
};
@@ -421,13 +403,13 @@
trace_lpm_resources(rs->sleep_value, rs->name);
}
-static void msm_lpm_flush_l2(int notify_rpm)
+static void msm_lpm_set_l2_mode(int sleep_mode, int notify_rpm)
{
- struct msm_lpm_resource *rs = &msm_lpm_l2;
- int lpm;
- int rc;
+ int lpm, rc;
- switch (rs->sleep_value) {
+ msm_pm_set_l2_flush_flag(0);
+
+ switch (sleep_mode) {
case MSM_LPM_L2_CACHE_HSFS_OPEN:
lpm = MSM_SPM_L2_MODE_POWER_COLLAPSE;
msm_pm_set_l2_flush_flag(1);
@@ -455,6 +437,13 @@
__func__, lpm);
}
+static void msm_lpm_flush_l2(int notify_rpm)
+{
+ struct msm_lpm_resource *rs = &msm_lpm_l2;
+
+ msm_lpm_set_l2_mode(rs->sleep_value, notify_rpm);
+}
+
/* RPM CTL */
static void msm_lpm_flush_rpm_ctl(int notify_rpm)
{
@@ -679,8 +668,7 @@
}
msm_lpm_get_rpm_notif = true;
- if (msm_lpm_use_mpm(limits))
- msm_mpm_enter_sleep(sclk_count, from_idle);
+ msm_mpm_enter_sleep(sclk_count, from_idle);
return ret;
}
@@ -688,11 +676,11 @@
void msm_lpmrs_exit_sleep(struct msm_rpmrs_limits *limits,
bool from_idle, bool notify_rpm, bool collapsed)
{
- /* MPM exit sleep
if (msm_lpm_use_mpm(limits))
- msm_mpm_exit_sleep(from_idle);*/
+ msm_mpm_exit_sleep(from_idle);
- msm_spm_l2_set_low_power_mode(MSM_SPM_MODE_DISABLED, notify_rpm);
+ if (msm_lpm_l2.valid)
+ msm_lpm_set_l2_mode(msm_lpm_l2.rs_data.default_value, false);
}
static int msm_lpm_cpu_callback(struct notifier_block *cpu_nb,
@@ -702,12 +690,12 @@
switch (action) {
case CPU_UP_PREPARE:
case CPU_UP_PREPARE_FROZEN:
- rs->rs_data.value = MSM_LPM_L2_CACHE_ACTIVE;
+ rs->rs_data.value = rs->rs_data.default_value;
break;
case CPU_ONLINE_FROZEN:
case CPU_ONLINE:
if (num_online_cpus() > 1)
- rs->rs_data.value = MSM_LPM_L2_CACHE_ACTIVE;
+ rs->rs_data.value = rs->rs_data.default_value;
break;
case CPU_DEAD_FROZEN:
case CPU_DEAD:
@@ -825,6 +813,16 @@
continue;
}
+ key = "qcom,init-value";
+ ret = of_property_read_u32(node, key,
+ &rs->rs_data.default_value);
+ if (ret) {
+ pr_err("%s():Failed to read %s\n", __func__, key);
+ goto fail;
+ }
+
+ rs->rs_data.value = rs->rs_data.default_value;
+
key = "qcom,resource-type";
ret = of_property_read_u32(node, key, &resource_type);
if (ret) {
diff --git a/arch/arm/mach-msm/msm-buspm-dev.c b/arch/arm/mach-msm/msm-buspm-dev.c
index a818eed..ec0f1bd 100644
--- a/arch/arm/mach-msm/msm-buspm-dev.c
+++ b/arch/arm/mach-msm/msm-buspm-dev.c
@@ -22,10 +22,17 @@
#include <linux/uaccess.h>
#include <linux/miscdevice.h>
#include <linux/memory_alloc.h>
+#include <mach/rpm-smd.h>
#include "msm-buspm-dev.h"
#define MSM_BUSPM_DRV_NAME "msm-buspm-dev"
+enum msm_buspm_spdm_res {
+ SPDM_RES_ID = 0,
+ SPDM_RES_TYPE = 0x63707362,
+ SPDM_KEY = 0x00006e65,
+ SPDM_SIZE = 4,
+};
/*
* Allocate kernel buffer.
* Currently limited to one buffer per file descriptor. If alloc() is
@@ -113,6 +120,61 @@
return 0;
}
+static int msm_bus_rpm_req(u32 rsc_type, u32 key, u32 hwid,
+ int ctx, u32 val)
+{
+ struct msm_rpm_request *rpm_req;
+ int ret, msg_id;
+
+ rpm_req = msm_rpm_create_request(ctx, rsc_type, SPDM_RES_ID, 1);
+ if (rpm_req == NULL) {
+ pr_err("RPM: Couldn't create RPM Request\n");
+ return -ENXIO;
+ }
+
+ ret = msm_rpm_add_kvp_data(rpm_req, key, (const uint8_t *)&val,
+ (int)(sizeof(uint32_t)));
+ if (ret) {
+ pr_err("RPM: Add KVP failed for RPM Req:%u\n",
+ rsc_type);
+ goto err;
+ }
+
+ pr_debug("Added Key: %d, Val: %u, size: %d\n", key,
+ (uint32_t)val, sizeof(uint32_t));
+ msg_id = msm_rpm_send_request(rpm_req);
+ if (!msg_id) {
+ pr_err("RPM: No message ID for req\n");
+ ret = -ENXIO;
+ goto err;
+ }
+
+ ret = msm_rpm_wait_for_ack(msg_id);
+ if (ret) {
+ pr_err("RPM: Ack failed\n");
+ goto err;
+ }
+
+err:
+ msm_rpm_free_request(rpm_req);
+ return ret;
+}
+
+static int msm_buspm_ioc_cmds(uint32_t arg)
+{
+ switch (arg) {
+ case MSM_BUSPM_SPDM_CLK_DIS:
+ case MSM_BUSPM_SPDM_CLK_EN:
+ return msm_bus_rpm_req(SPDM_RES_TYPE, SPDM_KEY, 0,
+ MSM_RPM_CTX_ACTIVE_SET, arg);
+ default:
+ pr_warn("Unsupported ioctl command: %d\n", arg);
+ return -EINVAL;
+ }
+}
+
+
+
static long
msm_buspm_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
@@ -124,6 +186,11 @@
unsigned int buflen = msm_buspm_dev_get_buflen(filp);
unsigned char *dbgbuf = buf;
+ if (_IOC_TYPE(cmd) != MSM_BUSPM_IOC_MAGIC) {
+ pr_err("Wrong IOC_MAGIC.Exiting\n");
+ return -ENOTTY;
+ }
+
switch (cmd) {
case MSM_BUSPM_IOC_FREE:
pr_debug("cmd = 0x%x (FREE)\n", cmd);
@@ -193,6 +260,11 @@
}
break;
+ case MSM_BUSPM_IOC_CMD:
+ pr_debug("IOCTL command: cmd: %d arg: %lu\n", cmd, arg);
+ retval = msm_buspm_ioc_cmds(arg);
+ break;
+
default:
pr_debug("Unknown command 0x%x\n", cmd);
retval = -EINVAL;
diff --git a/arch/arm/mach-msm/msm-buspm-dev.h b/arch/arm/mach-msm/msm-buspm-dev.h
index 5839087..854626d 100644
--- a/arch/arm/mach-msm/msm-buspm-dev.h
+++ b/arch/arm/mach-msm/msm-buspm-dev.h
@@ -31,6 +31,11 @@
int size;
};
+enum msm_buspm_ioc_cmds {
+ MSM_BUSPM_SPDM_CLK_DIS = 0,
+ MSM_BUSPM_SPDM_CLK_EN,
+};
+
#define MSM_BUSPM_IOC_MAGIC 'p'
#define MSM_BUSPM_IOC_FREE \
@@ -47,4 +52,7 @@
#define MSM_BUSPM_IOC_RD_PHYS_ADDR \
_IOR(MSM_BUSPM_IOC_MAGIC, 4, unsigned long)
+
+#define MSM_BUSPM_IOC_CMD \
+ _IOR(MSM_BUSPM_IOC_MAGIC, 5, uint32_t)
#endif
diff --git a/arch/arm/mach-msm/msm7k_fiq.c b/arch/arm/mach-msm/msm7k_fiq.c
index 421b4f9..d644121 100644
--- a/arch/arm/mach-msm/msm7k_fiq.c
+++ b/arch/arm/mach-msm/msm7k_fiq.c
@@ -75,7 +75,7 @@
static int __init init7k_fiq(void)
{
- if (!cpu_is_msm8625())
+ if (!cpu_is_msm8625() && !cpu_is_msm8625q())
return 0;
if (msm_setup_fiq_handler())
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_arb.c b/arch/arm/mach-msm/msm_bus/msm_bus_arb.c
index 65539c6..e61eb6d 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_arb.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_arb.c
@@ -614,6 +614,15 @@
MSM_BUS_DBG("ab: %llu ib: %llu\n", curr_bw, curr_clk);
}
+ if (index == 0) {
+ /* This check protects the bus driver from clients
+ * that can leave non-zero requests after
+ * unregistering.
+ * */
+ req_clk = 0;
+ req_bw = 0;
+ }
+
if (!pdata->active_only) {
ret = update_path(src, pnode, req_clk, req_bw,
curr_clk, curr_bw, 0, pdata->active_only);
diff --git a/arch/arm/mach-msm/ocmem_rdm.c b/arch/arm/mach-msm/ocmem_rdm.c
index 818a20a..8962729 100644
--- a/arch/arm/mach-msm/ocmem_rdm.c
+++ b/arch/arm/mach-msm/ocmem_rdm.c
@@ -191,6 +191,7 @@
int table_end = 0;
int br_ctrl = 0;
int br_id = 0;
+ int client_id = 0;
int dm_ctrl = 0;
int i = 0;
int j = 0;
@@ -244,6 +245,8 @@
dm_ctrl |= (table_start << DM_TBL_START);
dm_ctrl |= (table_end << DM_TBL_END);
+ client_id = client_ctrl_id(id);
+ dm_ctrl |= (client_id << DM_CLIENT_SHIFT);
dm_ctrl |= (DM_BR_ID_LPASS << DM_BR_ID_SHIFT);
dm_ctrl |= (DM_BLOCK_256 << DM_BR_BLK_SHIFT);
dm_ctrl |= (direction << DM_DIR_SHIFT);
diff --git a/arch/arm/mach-msm/perf_event_msm_krait_l2.c b/arch/arm/mach-msm/perf_event_msm_krait_l2.c
index 103eef0..26c5e58 100644
--- a/arch/arm/mach-msm/perf_event_msm_krait_l2.c
+++ b/arch/arm/mach-msm/perf_event_msm_krait_l2.c
@@ -72,9 +72,11 @@
*/
struct pmu_constraints {
u64 pmu_bitmap;
+ u8 codes[64];
raw_spinlock_t lock;
} l2_pmu_constraints = {
.pmu_bitmap = 0,
+ .codes = {-1},
.lock = __RAW_SPIN_LOCK_UNLOCKED(l2_pmu_constraints.lock),
};
@@ -335,8 +337,10 @@
int ctr = 0;
if (hwc->config_base == L2CYCLE_CTR_RAW_CODE) {
- if (!test_and_set_bit(l2_cycle_ctr_idx, cpuc->used_mask))
- return l2_cycle_ctr_idx;
+ if (test_and_set_bit(l2_cycle_ctr_idx, cpuc->used_mask))
+ return -EAGAIN;
+
+ return l2_cycle_ctr_idx;
}
for (ctr = 0; ctr < total_l2_ctrs - 1; ctr++) {
@@ -453,22 +457,48 @@
{
u32 evt_type = event->attr.config & L2_EVT_MASK;
u8 reg = (evt_type & 0x0F000) >> 12;
- u8 group = evt_type & 0x0000F;
+ u8 group = evt_type & 0x0000F;
+ u8 code = (evt_type & 0x00FF0) >> 4;
unsigned long flags;
u32 err = 0;
u64 bitmap_t;
+ u32 shift_idx;
+
+ /*
+ * Cycle counter collision is detected in
+ * get_event_idx().
+ */
+ if (evt_type == L2CYCLE_CTR_RAW_CODE)
+ return err;
raw_spin_lock_irqsave(&l2_pmu_constraints.lock, flags);
- bitmap_t = 1 << ((reg * 4) + group);
+ shift_idx = ((reg * 4) + group);
+
+ bitmap_t = 1 << shift_idx;
if (!(l2_pmu_constraints.pmu_bitmap & bitmap_t)) {
l2_pmu_constraints.pmu_bitmap |= bitmap_t;
+ l2_pmu_constraints.codes[shift_idx] = code;
goto out;
+ } else {
+ /*
+ * If NRCCG's are identical,
+ * its not column exclusion.
+ */
+ if (l2_pmu_constraints.codes[shift_idx] != code)
+ err = -EPERM;
+ else
+ /*
+ * If the event is counted in syswide mode
+ * then we want to count only on one CPU
+ * and set its filter to count from all.
+ * This sets the event OFF on all but one
+ * CPU.
+ */
+ if (!(event->cpu < 0))
+ event->state = PERF_EVENT_STATE_OFF;
}
-
- /* Bit is already set. Constraint failed. */
- err = -EPERM;
out:
raw_spin_unlock_irqrestore(&l2_pmu_constraints.lock, flags);
return err;
@@ -481,14 +511,20 @@
u8 group = evt_type & 0x0000F;
unsigned long flags;
u64 bitmap_t;
+ u32 shift_idx;
raw_spin_lock_irqsave(&l2_pmu_constraints.lock, flags);
- bitmap_t = 1 << ((reg * 4) + group);
+ shift_idx = ((reg * 4) + group);
+
+ bitmap_t = 1 << shift_idx;
/* Clear constraint bit. */
l2_pmu_constraints.pmu_bitmap &= ~bitmap_t;
+ /* Clear code. */
+ l2_pmu_constraints.codes[shift_idx] = -1;
+
raw_spin_unlock_irqrestore(&l2_pmu_constraints.lock, flags);
return 1;
}
diff --git a/arch/arm/mach-msm/perf_event_msm_l2.c b/arch/arm/mach-msm/perf_event_msm_l2.c
index 2ad36df..c1b7d23 100644
--- a/arch/arm/mach-msm/perf_event_msm_l2.c
+++ b/arch/arm/mach-msm/perf_event_msm_l2.c
@@ -38,9 +38,11 @@
*/
struct pmu_constraints {
u64 pmu_bitmap;
+ u8 codes[64];
raw_spinlock_t lock;
} l2_pmu_constraints = {
.pmu_bitmap = 0,
+ .codes = {-1},
.lock = __RAW_SPIN_LOCK_UNLOCKED(l2_pmu_constraints.lock),
};
@@ -667,9 +669,11 @@
int ctr = 0;
if (hwc->config_base == SCORPION_L2CYCLE_CTR_RAW_CODE) {
- if (!test_and_set_bit(l2_cycle_ctr_idx,
+ if (test_and_set_bit(l2_cycle_ctr_idx,
cpuc->used_mask))
- return l2_cycle_ctr_idx;
+ return -EAGAIN;
+
+ return l2_cycle_ctr_idx;
}
for (ctr = 0; ctr < total_l2_ctrs - 1; ctr++) {
@@ -792,25 +796,50 @@
u8 prefix = (evt_type & 0xF0000) >> 16;
u8 reg = (evt_type & 0x0F000) >> 12;
u8 group = evt_type & 0x0000F;
+ u8 code = (evt_type & 0x00FF0) >> 4;
unsigned long flags;
u32 err = 0;
u64 bitmap_t;
+ u32 shift_idx;
if (!prefix)
return 0;
+ /*
+ * Cycle counter collision is detected in
+ * get_event_idx().
+ */
+ if (evt_type == SCORPION_L2CYCLE_CTR_RAW_CODE)
+ return err;
raw_spin_lock_irqsave(&l2_pmu_constraints.lock, flags);
- bitmap_t = 1 << ((reg * 4) + group);
+ shift_idx = ((reg * 4) + group);
+
+ bitmap_t = 1 << shift_idx;
if (!(l2_pmu_constraints.pmu_bitmap & bitmap_t)) {
l2_pmu_constraints.pmu_bitmap |= bitmap_t;
+ l2_pmu_constraints.codes[shift_idx] = code;
goto out;
+ } else {
+ /*
+ * If NRCCG's are identical,
+ * its not column exclusion.
+ */
+ if (l2_pmu_constraints.codes[shift_idx] != code)
+ err = -EPERM;
+ else
+ /*
+ * If the event is counted in syswide mode
+ * then we want to count only on one CPU
+ * and set its filter to count from all.
+ * This sets the event OFF on all but one
+ * CPU.
+ */
+ if (!(event->cpu < 0))
+ event->state = PERF_EVENT_STATE_OFF;
}
- /* Bit is already set. Constraint failed. */
- err = -EPERM;
-
out:
raw_spin_unlock_irqrestore(&l2_pmu_constraints.lock, flags);
return err;
@@ -824,13 +853,16 @@
u8 group = evt_type & 0x0000F;
unsigned long flags;
u64 bitmap_t;
+ u32 shift_idx;
if (!prefix)
return 0;
raw_spin_lock_irqsave(&l2_pmu_constraints.lock, flags);
- bitmap_t = 1 << ((reg * 4) + group);
+ shift_idx = ((reg * 4) + group);
+
+ bitmap_t = 1 << shift_idx;
/* Clear constraint bit. */
l2_pmu_constraints.pmu_bitmap &= ~bitmap_t;
diff --git a/arch/arm/mach-msm/peripheral-loader.c b/arch/arm/mach-msm/peripheral-loader.c
index e3a3563..88aae81 100644
--- a/arch/arm/mach-msm/peripheral-loader.c
+++ b/arch/arm/mach-msm/peripheral-loader.c
@@ -28,17 +28,24 @@
#include <linux/msm_ion.h>
#include <linux/list.h>
#include <linux/list_sort.h>
+#include <linux/idr.h>
#include <asm/uaccess.h>
#include <asm/setup.h>
+#include <asm-generic/io-64-nonatomic-lo-hi.h>
+
+#include <mach/msm_iomap.h>
#include "peripheral-loader.h"
+#include "ramdump.h"
#define pil_err(desc, fmt, ...) \
dev_err(desc->dev, "%s: " fmt, desc->name, ##__VA_ARGS__)
#define pil_info(desc, fmt, ...) \
dev_info(desc->dev, "%s: " fmt, desc->name, ##__VA_ARGS__)
+#define PIL_IMAGE_INFO_BASE (MSM_IMEM_BASE + 0x94c)
+
/**
* proxy_timeout - Override for proxy vote timeouts
* -1: Use driver-specified timeout
@@ -80,6 +87,18 @@
};
/**
+ * struct pil_image_info - information in IMEM about image and where it is loaded
+ * @name: name of image (may or may not be NULL terminated)
+ * @start: indicates physical address where image starts (little endian)
+ * @size: size of image (little endian)
+ */
+struct pil_image_info {
+ char name[8];
+ __le64 start;
+ __le32 size;
+} __attribute__((__packed__));
+
+/**
* struct pil_priv - Private state for a pil_desc
* @proxy: work item used to run the proxy unvoting routine
* @wlock: wakelock to prevent suspend during pil_boot
@@ -110,8 +129,46 @@
phys_addr_t region_start;
phys_addr_t region_end;
struct ion_handle *region;
+ struct pil_image_info __iomem *info;
+ int id;
};
+/**
+ * pil_do_ramdump() - Ramdump an image
+ * @desc: descriptor from pil_desc_init()
+ * @ramdump_dev: ramdump device returned from create_ramdump_device()
+ *
+ * Calls the ramdump API with a list of segments generated from the addresses
+ * that the descriptor corresponds to.
+ */
+int pil_do_ramdump(struct pil_desc *desc, void *ramdump_dev)
+{
+ struct pil_priv *priv = desc->priv;
+ struct pil_seg *seg;
+ int count = 0, ret;
+ struct ramdump_segment *ramdump_segs, *s;
+
+ list_for_each_entry(seg, &priv->segs, list)
+ count++;
+
+ ramdump_segs = kmalloc_array(count, sizeof(*ramdump_segs), GFP_KERNEL);
+ if (!ramdump_segs)
+ return -ENOMEM;
+
+ s = ramdump_segs;
+ list_for_each_entry(seg, &priv->segs, list) {
+ s->address = seg->paddr;
+ s->size = seg->sz;
+ s++;
+ }
+
+ ret = do_elf_ramdump(ramdump_dev, ramdump_segs, count);
+ kfree(ramdump_segs);
+
+ return ret;
+}
+EXPORT_SYMBOL(pil_do_ramdump);
+
static struct ion_client *ion;
/**
@@ -337,6 +394,10 @@
priv->base_addr = min_addr_n;
}
+ writeq(priv->region_start, &priv->info->start);
+ writel_relaxed(priv->region_end - priv->region_start,
+ &priv->info->size);
+
return ret;
}
@@ -380,6 +441,9 @@
struct pil_priv *priv = desc->priv;
struct pil_seg *p, *tmp;
+ writeq(0, &priv->info->start);
+ writel_relaxed(0, &priv->info->size);
+
if (priv->region)
ion_free(ion, priv->region);
priv->region = NULL;
@@ -593,6 +657,8 @@
}
EXPORT_SYMBOL(pil_shutdown);
+static DEFINE_IDA(pil_ida);
+
/**
* pil_desc_init() - Initialize a pil descriptor
* @desc: descriptor to intialize
@@ -605,6 +671,9 @@
int pil_desc_init(struct pil_desc *desc)
{
struct pil_priv *priv;
+ int id;
+ void __iomem *addr;
+ size_t len;
/* Ignore users who don't make any sense */
WARN(desc->ops->proxy_unvote && !desc->proxy_timeout,
@@ -619,6 +688,18 @@
desc->priv = priv;
priv->desc = desc;
+ priv->id = id = ida_simple_get(&pil_ida, 0, 10, GFP_KERNEL);
+ if (id < 0) {
+ kfree(priv);
+ return id;
+ }
+ addr = PIL_IMAGE_INFO_BASE + sizeof(struct pil_image_info) * id;
+ priv->info = (struct pil_image_info __iomem *)addr;
+
+ len = min(strlen(desc->name), sizeof(priv->info->name));
+ memset_io(priv->info->name, 0, sizeof(priv->info->name));
+ memcpy_toio(priv->info->name, desc->name, len);
+
snprintf(priv->wname, sizeof(priv->wname), "pil-%s", desc->name);
wake_lock_init(&priv->wlock, WAKE_LOCK_SUSPEND, priv->wname);
INIT_DELAYED_WORK(&priv->proxy, pil_proxy_work);
@@ -637,6 +718,7 @@
struct pil_priv *priv = desc->priv;
if (priv) {
+ ida_simple_remove(&pil_ida, priv->id);
flush_delayed_work(&priv->proxy);
wake_lock_destroy(&priv->wlock);
}
diff --git a/arch/arm/mach-msm/peripheral-loader.h b/arch/arm/mach-msm/peripheral-loader.h
index 1c2faf7..8442289 100644
--- a/arch/arm/mach-msm/peripheral-loader.h
+++ b/arch/arm/mach-msm/peripheral-loader.h
@@ -65,6 +65,7 @@
extern void pil_shutdown(struct pil_desc *desc);
extern void pil_desc_release(struct pil_desc *desc);
extern phys_addr_t pil_get_entry_addr(struct pil_desc *desc);
+extern int pil_do_ramdump(struct pil_desc *desc, void *ramdump_dev);
#else
static inline int pil_desc_init(struct pil_desc *desc) { return 0; }
static inline int pil_boot(struct pil_desc *desc) { return 0; }
@@ -74,6 +75,10 @@
{
return 0;
}
+static inline int pil_do_ramdump(struct pil_desc *desc, void *ramdump_dev)
+{
+ return 0;
+}
#endif
#endif
diff --git a/arch/arm/mach-msm/pil-dsps.c b/arch/arm/mach-msm/pil-dsps.c
index 519e1c9..d315d82 100644
--- a/arch/arm/mach-msm/pil-dsps.c
+++ b/arch/arm/mach-msm/pil-dsps.c
@@ -48,7 +48,6 @@
void __iomem *ppss_base;
void *ramdump_dev;
- struct ramdump_segment fw_ramdump_segments[4];
void *smem_ramdump_dev;
struct ramdump_segment smem_ramdump_segments[1];
@@ -212,16 +211,13 @@
if (!enable)
return 0;
- ret = do_ramdump(drv->ramdump_dev,
- drv->fw_ramdump_segments,
- ARRAY_SIZE(drv->fw_ramdump_segments));
+ ret = pil_do_ramdump(&drv->desc, drv->ramdump_dev);
if (ret < 0) {
pr_err("%s: Unable to dump DSPS memory (rc = %d).\n",
__func__, ret);
return ret;
}
- ret = do_ramdump(drv->smem_ramdump_dev,
- drv->smem_ramdump_segments,
+ ret = do_elf_ramdump(drv->smem_ramdump_dev, drv->smem_ramdump_segments,
ARRAY_SIZE(drv->smem_ramdump_segments));
if (ret < 0) {
pr_err("%s: Unable to dump smem memory (rc = %d).\n",
@@ -293,14 +289,6 @@
if (ret)
return ret;
- drv->fw_ramdump_segments[0].address = 0x12000000;
- drv->fw_ramdump_segments[0].size = 0x28000;
- drv->fw_ramdump_segments[1].address = 0x12040000;
- drv->fw_ramdump_segments[1].size = 0x4000;
- drv->fw_ramdump_segments[2].address = 0x12800000;
- drv->fw_ramdump_segments[2].size = 0x4000;
- drv->fw_ramdump_segments[3].address = 0x8fe00000;
- drv->fw_ramdump_segments[3].size = 0x100000;
drv->ramdump_dev = create_ramdump_device("dsps", &pdev->dev);
if (!drv->ramdump_dev) {
ret = -ENOMEM;
diff --git a/arch/arm/mach-msm/pil-gss.c b/arch/arm/mach-msm/pil-gss.c
index a6d13d0..f4d4449 100644
--- a/arch/arm/mach-msm/pil-gss.c
+++ b/arch/arm/mach-msm/pil-gss.c
@@ -404,11 +404,6 @@
smsm_reset_modem(SMSM_RESET);
}
-/* FIXME: Get address, size from PIL */
-static struct ramdump_segment gss_segments[] = {
- {0x89000000, 0x00D00000}
-};
-
static struct ramdump_segment smem_segments[] = {
{0x80000000, 0x00200000},
};
@@ -418,20 +413,20 @@
int ret;
struct gss_data *drv = container_of(desc, struct gss_data, subsys_desc);
- if (enable) {
- ret = do_ramdump(drv->ramdump_dev, gss_segments,
- ARRAY_SIZE(gss_segments));
- if (ret < 0) {
- pr_err("Unable to dump gss memory\n");
- return ret;
- }
+ if (!enable)
+ return 0;
- ret = do_ramdump(drv->smem_ramdump_dev, smem_segments,
- ARRAY_SIZE(smem_segments));
- if (ret < 0) {
- pr_err("Unable to dump smem memory (rc = %d).\n", ret);
- return ret;
- }
+ ret = pil_do_ramdump(&drv->pil_desc, drv->ramdump_dev);
+ if (ret < 0) {
+ pr_err("Unable to dump gss memory\n");
+ return ret;
+ }
+
+ ret = do_elf_ramdump(drv->smem_ramdump_dev, smem_segments,
+ ARRAY_SIZE(smem_segments));
+ if (ret < 0) {
+ pr_err("Unable to dump smem memory (rc = %d).\n", ret);
+ return ret;
}
return 0;
diff --git a/arch/arm/mach-msm/pil-modem.c b/arch/arm/mach-msm/pil-modem.c
index d3c832b..3546705 100644
--- a/arch/arm/mach-msm/pil-modem.c
+++ b/arch/arm/mach-msm/pil-modem.c
@@ -393,21 +393,15 @@
return ret;
}
-/* FIXME: Get address, size from PIL */
-static struct ramdump_segment modem_segments[] = {
- { 0x42F00000, 0x46000000 - 0x42F00000 },
-};
-
static int modem_ramdump(int enable, const struct subsys_desc *subsys)
{
struct modem_data *drv;
drv = container_of(subsys, struct modem_data, subsys_desc);
- if (enable)
- return do_ramdump(drv->ramdump_dev, modem_segments,
- ARRAY_SIZE(modem_segments));
- else
+ if (!enable)
return 0;
+
+ return pil_do_ramdump(&drv->pil_desc, drv->ramdump_dev);
}
static int __devinit pil_modem_driver_probe(struct platform_device *pdev)
diff --git a/arch/arm/mach-msm/pil-pronto.c b/arch/arm/mach-msm/pil-pronto.c
index 162a7f7..b457599 100644
--- a/arch/arm/mach-msm/pil-pronto.c
+++ b/arch/arm/mach-msm/pil-pronto.c
@@ -385,19 +385,14 @@
smsm_change_state(SMSM_APPS_STATE, SMSM_RESET, SMSM_RESET);
}
-static struct ramdump_segment pronto_segments[] = {
- { 0x0D200000, 0x0D980000 - 0x0D200000 }
-};
-
static int wcnss_ramdump(int enable, const struct subsys_desc *subsys)
{
struct pronto_data *drv = subsys_to_drv(subsys);
- if (enable)
- return do_ramdump(drv->ramdump_dev, pronto_segments,
- ARRAY_SIZE(pronto_segments));
- else
+ if (!enable)
return 0;
+
+ return pil_do_ramdump(&drv->desc, drv->ramdump_dev);
}
static int __devinit pil_pronto_probe(struct platform_device *pdev)
diff --git a/arch/arm/mach-msm/pil-q6v3.c b/arch/arm/mach-msm/pil-q6v3.c
index d7e712c..1f53f17 100644
--- a/arch/arm/mach-msm/pil-q6v3.c
+++ b/arch/arm/mach-msm/pil-q6v3.c
@@ -279,22 +279,15 @@
return ret;
}
-/* FIXME: Get address, size from PIL */
-static struct ramdump_segment q6_segments[] = {
- { 0x46700000, 0x47f00000 - 0x46700000 },
- { 0x28400000, 0x12800 }
-};
-
static int lpass_q6_ramdump(int enable, const struct subsys_desc *subsys)
{
struct q6v3_data *drv;
drv = container_of(subsys, struct q6v3_data, subsys_desc);
- if (enable)
- return do_ramdump(drv->ramdump_dev, q6_segments,
- ARRAY_SIZE(q6_segments));
- else
+ if (!enable)
return 0;
+
+ return pil_do_ramdump(&drv->pil_desc, drv->ramdump_dev);
}
static void lpass_q6_crash_shutdown(const struct subsys_desc *subsys)
diff --git a/arch/arm/mach-msm/pil-q6v4-lpass.c b/arch/arm/mach-msm/pil-q6v4-lpass.c
index 1e6c1f6..1387433 100644
--- a/arch/arm/mach-msm/pil-q6v4-lpass.c
+++ b/arch/arm/mach-msm/pil-q6v4-lpass.c
@@ -231,18 +231,14 @@
return ret;
}
-static struct ramdump_segment segments[] = {
- {0x8da00000, 0x8f200000 - 0x8da00000},
- {0x28400000, 0x20000}
-};
-
static int lpass_ramdump(int enable, const struct subsys_desc *subsys)
{
struct lpass_q6v4 *drv = subsys_to_lpass(subsys);
if (!enable)
return 0;
- return do_ramdump(drv->ramdump_dev, segments, ARRAY_SIZE(segments));
+
+ return pil_do_ramdump(&drv->q6.desc, drv->ramdump_dev);
}
static void lpass_crash_shutdown(const struct subsys_desc *subsys)
diff --git a/arch/arm/mach-msm/pil-q6v4-mss.c b/arch/arm/mach-msm/pil-q6v4-mss.c
index ee01f04..f2b090f 100644
--- a/arch/arm/mach-msm/pil-q6v4-mss.c
+++ b/arch/arm/mach-msm/pil-q6v4-mss.c
@@ -243,14 +243,6 @@
smsm_reset_modem(SMSM_RESET);
}
-static struct ramdump_segment sw_segments[] = {
- {0x89000000, 0x8D400000 - 0x89000000},
-};
-
-static struct ramdump_segment fw_segments[] = {
- {0x8D400000, 0x8DA00000 - 0x8D400000},
-};
-
static struct ramdump_segment smem_segments[] = {
{0x80000000, 0x00200000},
};
@@ -263,17 +255,15 @@
if (!enable)
return 0;
- ret = do_ramdump(drv->sw_ramdump_dev, sw_segments,
- ARRAY_SIZE(sw_segments));
+ ret = pil_do_ramdump(&drv->q6_sw.desc, drv->sw_ramdump_dev);
if (ret < 0)
return ret;
- ret = do_ramdump(drv->fw_ramdump_dev, fw_segments,
- ARRAY_SIZE(fw_segments));
+ ret = pil_do_ramdump(&drv->q6_fw.desc, drv->fw_ramdump_dev);
if (ret < 0)
return ret;
- ret = do_ramdump(drv->smem_ramdump_dev, smem_segments,
+ ret = do_elf_ramdump(drv->smem_ramdump_dev, smem_segments,
ARRAY_SIZE(smem_segments));
if (ret < 0)
return ret;
diff --git a/arch/arm/mach-msm/pil-q6v5-lpass.c b/arch/arm/mach-msm/pil-q6v5-lpass.c
index 662377d..94632da 100644
--- a/arch/arm/mach-msm/pil-q6v5-lpass.c
+++ b/arch/arm/mach-msm/pil-q6v5-lpass.c
@@ -307,15 +307,14 @@
return ret;
}
-static struct ramdump_segment segments = { 0xdc00000, 0x1800000 };
-
static int adsp_ramdump(int enable, const struct subsys_desc *subsys)
{
struct lpass_data *drv = subsys_to_lpass(subsys);
if (!enable)
return 0;
- return do_ramdump(drv->ramdump_dev, &segments, 1);
+
+ return pil_do_ramdump(&drv->q6->desc, drv->ramdump_dev);
}
static void adsp_crash_shutdown(const struct subsys_desc *subsys)
diff --git a/arch/arm/mach-msm/pil-q6v5-mss.c b/arch/arm/mach-msm/pil-q6v5-mss.c
index b8309e5..ed85c95 100644
--- a/arch/arm/mach-msm/pil-q6v5-mss.c
+++ b/arch/arm/mach-msm/pil-q6v5-mss.c
@@ -496,10 +496,6 @@
smsm_reset_modem(SMSM_RESET);
}
-static struct ramdump_segment modem_segments[] = {
- {0x08400000, 0x0D100000 - 0x08400000},
-};
-
static struct ramdump_segment smem_segments[] = {
{0x0FA00000, 0x0FC00000 - 0x0FA00000},
};
@@ -516,14 +512,13 @@
if (ret)
return ret;
- ret = do_ramdump(drv->ramdump_dev, modem_segments,
- ARRAY_SIZE(modem_segments));
+ ret = pil_do_ramdump(&drv->q6->desc, drv->ramdump_dev);
if (ret < 0) {
pr_err("Unable to dump modem fw memory (rc = %d).\n", ret);
goto out;
}
- ret = do_ramdump(drv->smem_ramdump_dev, smem_segments,
+ ret = do_elf_ramdump(drv->smem_ramdump_dev, smem_segments,
ARRAY_SIZE(smem_segments));
if (ret < 0) {
pr_err("Unable to dump smem memory (rc = %d).\n", ret);
diff --git a/arch/arm/mach-msm/pil-riva.c b/arch/arm/mach-msm/pil-riva.c
index 74fae98..96b9882 100644
--- a/arch/arm/mach-msm/pil-riva.c
+++ b/arch/arm/mach-msm/pil-riva.c
@@ -412,26 +412,16 @@
return ret;
}
-/*
- * 7MB RAM segments for Riva SS;
- * Riva 1.1 0x8f000000 - 0x8f700000
- * Riva 1.0 0x8f200000 - 0x8f700000
- */
-static struct ramdump_segment riva_segments[] = {
- {0x8f000000, 0x8f700000 - 0x8f000000}
-};
-
static int riva_ramdump(int enable, const struct subsys_desc *desc)
{
struct riva_data *drv;
drv = container_of(desc, struct riva_data, subsys_desc);
- if (enable)
- return do_ramdump(drv->ramdump_dev, riva_segments,
- ARRAY_SIZE(riva_segments));
- else
+ if (!enable)
return 0;
+
+ return pil_do_ramdump(&drv->pil_desc, drv->ramdump_dev);
}
/* Riva crash handler */
diff --git a/arch/arm/mach-msm/pm-boot.c b/arch/arm/mach-msm/pm-boot.c
index f32e149..53cc0f5 100644
--- a/arch/arm/mach-msm/pm-boot.c
+++ b/arch/arm/mach-msm/pm-boot.c
@@ -137,7 +137,7 @@
= msm_pm_config_rst_vector_after_pc;
break;
case MSM_PM_BOOT_CONFIG_REMAP_BOOT_ADDR:
- if (!cpu_is_msm8625()) {
+ if (!cpu_is_msm8625() && !cpu_is_msm8625q()) {
void *remapped;
/*
@@ -200,7 +200,7 @@
pdata->v_addr + mpa5_cfg_ctl[0]);
/* 8x25Q changes */
- if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) >= 3) {
+ if (cpu_is_msm8625q()) {
/* write 'entry' to boot remapper register */
__raw_writel(entry, (pdata->v_addr +
mpa5_boot_remap_addr[1]));
diff --git a/arch/arm/mach-msm/pm2.c b/arch/arm/mach-msm/pm2.c
index 96c1218..ec9f030 100644
--- a/arch/arm/mach-msm/pm2.c
+++ b/arch/arm/mach-msm/pm2.c
@@ -562,7 +562,7 @@
__raw_writel(0, APPS_PWRDOWN);
mb();
msm_spm_reinit();
- } else if (cpu_is_msm8625()) {
+ } else if (cpu_is_msm8625() || cpu_is_msm8625q()) {
__raw_writel(0, APPS_PWRDOWN);
mb();
@@ -881,7 +881,7 @@
memset(msm_pm_smem_data, 0, sizeof(*msm_pm_smem_data));
- if (cpu_is_msm8625()) {
+ if (cpu_is_msm8625() || cpu_is_msm8625q()) {
/* Program the SPM */
ret = msm_spm_set_low_power_mode(MSM_SPM_MODE_POWER_COLLAPSE,
false);
@@ -971,7 +971,7 @@
#endif
#ifdef CONFIG_CACHE_L2X0
- if (!cpu_is_msm8625())
+ if (!cpu_is_msm8625() && !cpu_is_msm8625q())
l2cc_suspend();
else
apps_power_collapse = 1;
@@ -983,7 +983,7 @@
* TBD: Currently recognise the MODEM early exit
* path by reading the MPA5_GDFS_CNT_VAL register.
*/
- if (cpu_is_msm8625()) {
+ if (cpu_is_msm8625() || cpu_is_msm8625q()) {
int cpu;
/*
* on system reset, default value of MPA5_GDFS_CNT_VAL
@@ -997,7 +997,7 @@
val = __raw_readl(MSM_CFG_CTL_BASE + 0x38);
/* 8x25Q */
- if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) >= 3) {
+ if (cpu_is_msm8625q()) {
if (val != 0x000F0002) {
for_each_possible_cpu(cpu) {
if (!cpu)
@@ -1031,7 +1031,7 @@
}
#ifdef CONFIG_CACHE_L2X0
- if (!cpu_is_msm8625())
+ if (!cpu_is_msm8625() && !cpu_is_msm8625q())
l2cc_resume();
else
apps_power_collapse = 0;
@@ -1153,7 +1153,7 @@
smd_sleep_exit();
- if (cpu_is_msm8625()) {
+ if (cpu_is_msm8625() || cpu_is_msm8625q()) {
ret = msm_spm_set_low_power_mode(MSM_SPM_MODE_CLOCK_GATING,
false);
WARN_ON(ret);
@@ -1220,7 +1220,7 @@
msm_cpr_ops->cpr_resume();
power_collapse_bail:
- if (cpu_is_msm8625()) {
+ if (cpu_is_msm8625() || cpu_is_msm8625q()) {
ret = msm_spm_set_low_power_mode(MSM_SPM_MODE_CLOCK_GATING,
false);
WARN_ON(ret);
@@ -1258,14 +1258,14 @@
#endif
#ifdef CONFIG_CACHE_L2X0
- if (!cpu_is_msm8625())
+ if (!cpu_is_msm8625() && !cpu_is_msm8625q())
l2cc_suspend();
#endif
collapsed = msm_pm_collapse();
#ifdef CONFIG_CACHE_L2X0
- if (!cpu_is_msm8625())
+ if (!cpu_is_msm8625() && !cpu_is_msm8625q())
l2cc_resume();
#endif
@@ -1310,7 +1310,7 @@
return -EIO;
}
- if (!cpu_is_msm8625())
+ if (!cpu_is_msm8625() && !cpu_is_msm8625q())
msm_pm_config_hw_before_swfi();
msm_arch_idle();
@@ -1713,7 +1713,7 @@
return ret;
}
- if (cpu_is_msm8625()) {
+ if (cpu_is_msm8625() || cpu_is_msm8625q()) {
target_type = TARGET_IS_8625;
clean_caches((unsigned long)&target_type, sizeof(target_type),
virt_to_phys(&target_type));
@@ -1725,7 +1725,7 @@
* MPA5_GDFS_CNT_VAL[9:0] = Delay counter for
* GDFS control.
*/
- if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) >= 3)
+ if (cpu_is_msm8625q())
val = 0x000F0002;
else
val = 0x00030002;
diff --git a/arch/arm/mach-msm/qdsp5/adsp.c b/arch/arm/mach-msm/qdsp5/adsp.c
index 6189da8..81af66b 100644
--- a/arch/arm/mach-msm/qdsp5/adsp.c
+++ b/arch/arm/mach-msm/qdsp5/adsp.c
@@ -1080,6 +1080,21 @@
return 0;
}
+int msm_adsp_dump(struct msm_adsp_module *module)
+{
+ int rc = 0;
+ if (!module) {
+ MM_INFO("Invalid module. Dumps are not collected\n");
+ return -EINVAL;
+ }
+ MM_INFO("starting DSP DUMP\n");
+ rc = rpc_adsp_rtos_app_to_modem(RPC_ADSP_RTOS_CMD_CORE_DUMP,
+ module->id, module);
+ MM_INFO("DSP DUMP done rc =%d\n", rc);
+ return rc;
+}
+EXPORT_SYMBOL(msm_adsp_dump);
+
int msm_adsp_enable(struct msm_adsp_module *module)
{
int rc = 0;
@@ -1123,6 +1138,7 @@
rc = 0;
} else {
MM_ERR("module '%s' enable timed out\n", module->name);
+ msm_adsp_dump(module);
rc = -ETIMEDOUT;
}
if (module->open_count++ == 0 && module->clk)
diff --git a/arch/arm/mach-msm/qdsp5/adsp.h b/arch/arm/mach-msm/qdsp5/adsp.h
index 50f5b83..4e9d311 100644
--- a/arch/arm/mach-msm/qdsp5/adsp.h
+++ b/arch/arm/mach-msm/qdsp5/adsp.h
@@ -152,6 +152,7 @@
RPC_ADSP_RTOS_CMD_SET_STATE,
RPC_ADSP_RTOS_CMD_REMOTE_INIT_INFO_EVENT,
RPC_ADSP_RTOS_CMD_GET_INIT_INFO,
+ RPC_ADSP_RTOS_CMD_CORE_DUMP,
};
enum rpc_adsp_rtos_mod_status_type {
diff --git a/arch/arm/mach-msm/qdsp5/audio_aac.c b/arch/arm/mach-msm/qdsp5/audio_aac.c
index 46a80d7..c36cac7 100644
--- a/arch/arm/mach-msm/qdsp5/audio_aac.c
+++ b/arch/arm/mach-msm/qdsp5/audio_aac.c
@@ -261,8 +261,10 @@
cfg.snd_method = RPC_SND_METHOD_MIDI;
rc = audmgr_enable(&audio->audmgr, &cfg);
- if (rc < 0)
+ if (rc < 0) {
+ msm_adsp_dump(audio->audplay);
return rc;
+ }
}
if (msm_adsp_enable(audio->audplay)) {
@@ -306,8 +308,12 @@
wake_up(&audio->read_wait);
msm_adsp_disable(audio->audplay);
audpp_disable(audio->dec_id, audio);
- if (audio->pcm_feedback == TUNNEL_MODE_PLAYBACK)
- audmgr_disable(&audio->audmgr);
+ if (audio->pcm_feedback == TUNNEL_MODE_PLAYBACK) {
+ rc = audmgr_disable(&audio->audmgr);
+ if (rc < 0)
+ msm_adsp_dump(audio->audplay);
+ }
+
audio->out_needed = 0;
rmt_put_resource(audio);
audio->rmt_resource_released = 1;
diff --git a/arch/arm/mach-msm/qdsp5/audio_ac3.c b/arch/arm/mach-msm/qdsp5/audio_ac3.c
index e453ec5..b5337bd 100644
--- a/arch/arm/mach-msm/qdsp5/audio_ac3.c
+++ b/arch/arm/mach-msm/qdsp5/audio_ac3.c
@@ -252,8 +252,10 @@
cfg.snd_method = RPC_SND_METHOD_MIDI;
rc = audmgr_enable(&audio->audmgr, &cfg);
- if (rc < 0)
+ if (rc < 0) {
+ msm_adsp_dump(audio->audplay);
return rc;
+ }
}
if (msm_adsp_enable(audio->audplay)) {
@@ -296,8 +298,11 @@
wake_up(&audio->read_wait);
msm_adsp_disable(audio->audplay);
audpp_disable(audio->dec_id, audio);
- if (audio->pcm_feedback == TUNNEL_MODE_PLAYBACK)
- audmgr_disable(&audio->audmgr);
+ if (audio->pcm_feedback == TUNNEL_MODE_PLAYBACK) {
+ rc = audmgr_disable(&audio->audmgr);
+ if (rc < 0)
+ msm_adsp_dump(audio->audplay);
+ }
audio->out_needed = 0;
rmt_put_resource(audio);
audio->rmt_resource_released = 1;
diff --git a/arch/arm/mach-msm/qdsp5/audio_amrnb.c b/arch/arm/mach-msm/qdsp5/audio_amrnb.c
index 0792e3f..4aa7403 100644
--- a/arch/arm/mach-msm/qdsp5/audio_amrnb.c
+++ b/arch/arm/mach-msm/qdsp5/audio_amrnb.c
@@ -265,8 +265,10 @@
cfg.snd_method = RPC_SND_METHOD_MIDI;
rc = audmgr_enable(&audio->audmgr, &cfg);
- if (rc < 0)
+ if (rc < 0) {
+ msm_adsp_dump(audio->audplay);
return rc;
+ }
}
if (msm_adsp_enable(audio->audplay)) {
@@ -310,8 +312,11 @@
wake_up(&audio->read_wait);
msm_adsp_disable(audio->audplay);
audpp_disable(audio->dec_id, audio);
- if (audio->pcm_feedback == TUNNEL_MODE_PLAYBACK)
- audmgr_disable(&audio->audmgr);
+ if (audio->pcm_feedback == TUNNEL_MODE_PLAYBACK) {
+ rc = audmgr_disable(&audio->audmgr);
+ if (rc < 0)
+ msm_adsp_dump(audio->audplay);
+ }
audio->out_needed = 0;
rmt_put_resource(audio);
audio->rmt_resource_released = 1;
diff --git a/arch/arm/mach-msm/qdsp5/audio_amrwb.c b/arch/arm/mach-msm/qdsp5/audio_amrwb.c
index 7d37cea..57df4ad 100644
--- a/arch/arm/mach-msm/qdsp5/audio_amrwb.c
+++ b/arch/arm/mach-msm/qdsp5/audio_amrwb.c
@@ -262,8 +262,10 @@
cfg.snd_method = RPC_SND_METHOD_MIDI;
rc = audmgr_enable(&audio->audmgr, &cfg);
- if (rc < 0)
+ if (rc < 0) {
+ msm_adsp_dump(audio->audplay);
return rc;
+ }
}
if (msm_adsp_enable(audio->audplay)) {
@@ -307,8 +309,11 @@
wake_up(&audio->read_wait);
msm_adsp_disable(audio->audplay);
audpp_disable(audio->dec_id, audio);
- if (audio->pcm_feedback == TUNNEL_MODE_PLAYBACK)
- audmgr_disable(&audio->audmgr);
+ if (audio->pcm_feedback == TUNNEL_MODE_PLAYBACK) {
+ rc = audmgr_disable(&audio->audmgr);
+ if (rc < 0)
+ msm_adsp_dump(audio->audplay);
+ }
audio->out_needed = 0;
rmt_put_resource(audio);
audio->rmt_resource_released = 1;
diff --git a/arch/arm/mach-msm/qdsp5/audio_evrc.c b/arch/arm/mach-msm/qdsp5/audio_evrc.c
index 155b0e1..0799ee1 100644
--- a/arch/arm/mach-msm/qdsp5/audio_evrc.c
+++ b/arch/arm/mach-msm/qdsp5/audio_evrc.c
@@ -255,8 +255,10 @@
cfg.snd_method = RPC_SND_METHOD_MIDI;
rc = audmgr_enable(&audio->audmgr, &cfg);
- if (rc < 0)
+ if (rc < 0) {
+ msm_adsp_dump(audio->audplay);
return rc;
+ }
}
if (msm_adsp_enable(audio->audplay)) {
@@ -299,8 +301,11 @@
wake_up(&audio->read_wait);
msm_adsp_disable(audio->audplay);
audpp_disable(audio->dec_id, audio);
- if (audio->pcm_feedback == TUNNEL_MODE_PLAYBACK)
- audmgr_disable(&audio->audmgr);
+ if (audio->pcm_feedback == TUNNEL_MODE_PLAYBACK) {
+ rc = audmgr_disable(&audio->audmgr);
+ if (rc < 0)
+ msm_adsp_dump(audio->audplay);
+ }
audio->out_needed = 0;
rmt_put_resource(audio);
audio->rmt_resource_released = 1;
diff --git a/arch/arm/mach-msm/qdsp5/audio_lpa.c b/arch/arm/mach-msm/qdsp5/audio_lpa.c
index 8120d7b..e896e85 100644
--- a/arch/arm/mach-msm/qdsp5/audio_lpa.c
+++ b/arch/arm/mach-msm/qdsp5/audio_lpa.c
@@ -293,9 +293,10 @@
cfg.snd_method = RPC_SND_METHOD_MIDI;
rc = audmgr_enable(&audio->audmgr, &cfg);
- if (rc < 0)
+ if (rc < 0) {
+ msm_adsp_dump(audio->audplay);
return rc;
-
+ }
if (msm_adsp_enable(audio->audplay)) {
MM_ERR("msm_adsp_enable(audplay) failed\n");
audmgr_disable(&audio->audmgr);
@@ -335,7 +336,9 @@
wake_up(&audio->write_wait);
msm_adsp_disable(audio->audplay);
audpp_disable(audio->dec_id, audio);
- audmgr_disable(&audio->audmgr);
+ rc = audmgr_disable(&audio->audmgr);
+ if (rc < 0)
+ msm_adsp_dump(audio->audplay);
audio->out_needed = 0;
rmt_put_resource(audio);
audio->rmt_resource_released = 1;
diff --git a/arch/arm/mach-msm/qdsp5/audio_mp3.c b/arch/arm/mach-msm/qdsp5/audio_mp3.c
index b8c64be..a606bd5 100644
--- a/arch/arm/mach-msm/qdsp5/audio_mp3.c
+++ b/arch/arm/mach-msm/qdsp5/audio_mp3.c
@@ -330,8 +330,10 @@
cfg.snd_method = RPC_SND_METHOD_MIDI;
rc = audmgr_enable(&audio->audmgr, &cfg);
- if (rc < 0)
+ if (rc < 0) {
+ msm_adsp_dump(audio->audplay);
return rc;
+ }
}
if (msm_adsp_enable(audio->audplay)) {
@@ -376,8 +378,11 @@
wake_up(&audio->read_wait);
msm_adsp_disable(audio->audplay);
audpp_disable(audio->dec_id, audio);
- if (audio->pcm_feedback == TUNNEL_MODE_PLAYBACK)
- audmgr_disable(&audio->audmgr);
+ if (audio->pcm_feedback == TUNNEL_MODE_PLAYBACK) {
+ rc = audmgr_disable(&audio->audmgr);
+ if (rc < 0)
+ msm_adsp_dump(audio->audplay);
+ }
audio->out_needed = 0;
rmt_put_resource(audio);
audio->rmt_resource_released = 1;
diff --git a/arch/arm/mach-msm/qdsp5/audio_pcm.c b/arch/arm/mach-msm/qdsp5/audio_pcm.c
index 3eb72c8..d19f80b 100644
--- a/arch/arm/mach-msm/qdsp5/audio_pcm.c
+++ b/arch/arm/mach-msm/qdsp5/audio_pcm.c
@@ -299,9 +299,10 @@
cfg.snd_method = RPC_SND_METHOD_MIDI;
rc = audmgr_enable(&audio->audmgr, &cfg);
- if (rc < 0)
+ if (rc < 0) {
+ msm_adsp_dump(audio->audplay);
return rc;
-
+ }
if (msm_adsp_enable(audio->audplay)) {
MM_ERR("msm_adsp_enable(audplay) failed\n");
audmgr_disable(&audio->audmgr);
@@ -341,7 +342,9 @@
wake_up(&audio->write_wait);
msm_adsp_disable(audio->audplay);
audpp_disable(audio->dec_id, audio);
- audmgr_disable(&audio->audmgr);
+ rc = audmgr_disable(&audio->audmgr);
+ if (rc < 0)
+ msm_adsp_dump(audio->audplay);
audio->out_needed = 0;
rmt_put_resource(audio);
audio->rmt_resource_released = 1;
diff --git a/arch/arm/mach-msm/qdsp5/audio_pcm_in.c b/arch/arm/mach-msm/qdsp5/audio_pcm_in.c
index 68ffcfef..7b2090d 100644
--- a/arch/arm/mach-msm/qdsp5/audio_pcm_in.c
+++ b/arch/arm/mach-msm/qdsp5/audio_pcm_in.c
@@ -218,9 +218,10 @@
cfg.snd_method = RPC_SND_METHOD_MIDI;
rc = audmgr_enable(&audio->audmgr, &cfg);
- if (rc < 0)
+ if (rc < 0) {
+ msm_adsp_dump(audio->audrec);
return rc;
-
+ }
if (audpreproc_enable(audio->enc_id, &audpre_dsp_event, audio)) {
MM_ERR("msm_adsp_enable(audpreproc) failed\n");
audmgr_disable(&audio->audmgr);
@@ -249,6 +250,8 @@
/* must be called with audio->lock held */
static int audpcm_in_disable(struct audio_in *audio)
{
+ int rc;
+
if (audio->enabled) {
audio->enabled = 0;
@@ -262,7 +265,9 @@
/*reset the sampling frequency information at audpreproc layer*/
audio->session_info.sampling_freq = 0;
audpreproc_update_audrec_info(&audio->session_info);
- audmgr_disable(&audio->audmgr);
+ rc = audmgr_disable(&audio->audmgr);
+ if (rc < 0)
+ msm_adsp_dump(audio->audrec);
}
return 0;
}
diff --git a/arch/arm/mach-msm/qdsp5/audio_qcelp.c b/arch/arm/mach-msm/qdsp5/audio_qcelp.c
index 876c909..3fc489c 100644
--- a/arch/arm/mach-msm/qdsp5/audio_qcelp.c
+++ b/arch/arm/mach-msm/qdsp5/audio_qcelp.c
@@ -251,8 +251,10 @@
cfg.snd_method = RPC_SND_METHOD_MIDI;
rc = audmgr_enable(&audio->audmgr, &cfg);
- if (rc < 0)
+ if (rc < 0) {
+ msm_adsp_dump(audio->audplay);
return rc;
+ }
}
if (msm_adsp_enable(audio->audplay)) {
@@ -296,8 +298,11 @@
wake_up(&audio->read_wait);
msm_adsp_disable(audio->audplay);
audpp_disable(audio->dec_id, audio);
- if (audio->pcm_feedback == TUNNEL_MODE_PLAYBACK)
- audmgr_disable(&audio->audmgr);
+ if (audio->pcm_feedback == TUNNEL_MODE_PLAYBACK) {
+ rc = audmgr_disable(&audio->audmgr);
+ if (rc < 0)
+ msm_adsp_dump(audio->audplay);
+ }
audio->out_needed = 0;
rmt_put_resource(audio);
audio->rmt_resource_released = 1;
diff --git a/arch/arm/mach-msm/qdsp5/audio_wma.c b/arch/arm/mach-msm/qdsp5/audio_wma.c
index 6d520b4..f7d54cc 100644
--- a/arch/arm/mach-msm/qdsp5/audio_wma.c
+++ b/arch/arm/mach-msm/qdsp5/audio_wma.c
@@ -268,8 +268,10 @@
cfg.snd_method = RPC_SND_METHOD_MIDI;
rc = audmgr_enable(&audio->audmgr, &cfg);
- if (rc < 0)
+ if (rc < 0) {
+ msm_adsp_dump(audio->audplay);
return rc;
+ }
}
if (msm_adsp_enable(audio->audplay)) {
@@ -314,8 +316,11 @@
wake_up(&audio->read_wait);
msm_adsp_disable(audio->audplay);
audpp_disable(audio->dec_id, audio);
- if (audio->pcm_feedback == TUNNEL_MODE_PLAYBACK)
- audmgr_disable(&audio->audmgr);
+ if (audio->pcm_feedback == TUNNEL_MODE_PLAYBACK) {
+ rc = audmgr_disable(&audio->audmgr);
+ if (rc < 0)
+ msm_adsp_dump(audio->audplay);
+ }
audio->out_needed = 0;
rmt_put_resource(audio);
audio->rmt_resource_released = 1;
diff --git a/arch/arm/mach-msm/qdsp5/audio_wmapro.c b/arch/arm/mach-msm/qdsp5/audio_wmapro.c
index a08f3c9..8dba4a6 100644
--- a/arch/arm/mach-msm/qdsp5/audio_wmapro.c
+++ b/arch/arm/mach-msm/qdsp5/audio_wmapro.c
@@ -266,8 +266,10 @@
cfg.snd_method = RPC_SND_METHOD_MIDI;
rc = audmgr_enable(&audio->audmgr, &cfg);
- if (rc < 0)
+ if (rc < 0) {
+ msm_adsp_dump(audio->audplay);
return rc;
+ }
if (msm_adsp_enable(audio->audplay)) {
MM_ERR("msm_adsp_enable(audplay) failed\n");
@@ -309,7 +311,10 @@
wake_up(&audio->read_wait);
msm_adsp_disable(audio->audplay);
audpp_disable(audio->dec_id, audio);
- audmgr_disable(&audio->audmgr);
+ rc = audmgr_disable(&audio->audmgr);
+ if (rc < 0)
+ msm_adsp_dump(audio->audplay);
+
audio->out_needed = 0;
rmt_put_resource(audio);
audio->rmt_resource_released = 1;
diff --git a/arch/arm/mach-msm/qdsp5/audpp.c b/arch/arm/mach-msm/qdsp5/audpp.c
index b4ead5c..b4b7338f 100644
--- a/arch/arm/mach-msm/qdsp5/audpp.c
+++ b/arch/arm/mach-msm/qdsp5/audpp.c
@@ -292,6 +292,7 @@
MM_INFO("ENABLE\n");
if (!audpp->enabled) {
audpp->enabled = 1;
+ wake_up(&audpp->event_wait);
audpp_broadcast(audpp, id, msg);
} else {
cid = msg[1];
@@ -344,6 +345,7 @@
struct audpp_state *audpp = &the_audpp_state;
uint16_t msg[8];
int res = 0;
+ int rc;
if (id < -1 || id > 4)
return -EINVAL;
@@ -374,6 +376,11 @@
LOG(EV_ENABLE, 2);
msm_adsp_enable(audpp->mod);
audpp_dsp_config(1);
+ rc = wait_event_timeout(audpp->event_wait,
+ (audpp->enabled == 1),
+ 3 * HZ);
+ if (rc == 0)
+ msm_adsp_dump(audpp->mod);
} else {
if (audpp->enabled) {
msg[0] = AUDPP_MSG_ENA_ENA;
@@ -424,13 +431,17 @@
MM_DBG("disable\n");
LOG(EV_DISABLE, 2);
audpp_dsp_config(0);
- rc = wait_event_interruptible(audpp->event_wait,
- (audpp->enabled == 0));
+ rc = wait_event_timeout(audpp->event_wait,
+ (audpp->enabled == 0),
+ 3 * HZ);
if (audpp->enabled == 0)
MM_INFO("Received CFG_MSG_DISABLE from ADSP\n");
- else
+ else {
MM_ERR("Didn't receive CFG_MSG DISABLE \
message from ADSP\n");
+ if (rc == 0)
+ msm_adsp_dump(audpp->mod);
+ }
msm_adsp_disable(audpp->mod);
msm_adsp_put(audpp->mod);
audpp->mod = NULL;
diff --git a/arch/arm/mach-msm/ramdump.c b/arch/arm/mach-msm/ramdump.c
index e33ec48..aac49d0 100644
--- a/arch/arm/mach-msm/ramdump.c
+++ b/arch/arm/mach-msm/ramdump.c
@@ -11,14 +11,10 @@
*/
#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/reboot.h>
#include <linux/workqueue.h>
#include <linux/io.h>
#include <linux/jiffies.h>
#include <linux/sched.h>
-#include <linux/stringify.h>
-#include <linux/delay.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
@@ -26,8 +22,8 @@
#include <linux/slab.h>
#include <linux/poll.h>
#include <linux/uaccess.h>
-
-#include <asm-generic/poll.h>
+#include <linux/elf.h>
+#include <linux/wait.h>
#include "ramdump.h"
@@ -46,6 +42,8 @@
wait_queue_head_t dump_wait_q;
int nsegments;
struct ramdump_segment *segments;
+ size_t elfcore_size;
+ char *elfcore_buf;
};
static int ramdump_open(struct inode *inode, struct file *filep)
@@ -107,13 +105,29 @@
size_t copy_size = 0;
int ret = 0;
- if (rd_dev->data_ready == 0) {
- pr_err("Ramdump(%s): Read when there's no dump available!",
- rd_dev->name);
- return -EPIPE;
+ if ((filep->f_flags & O_NONBLOCK) && !rd_dev->data_ready)
+ return -EAGAIN;
+
+ ret = wait_event_interruptible(rd_dev->dump_wait_q, rd_dev->data_ready);
+ if (ret)
+ return ret;
+
+ if (*pos < rd_dev->elfcore_size) {
+ copy_size = min(rd_dev->elfcore_size, count);
+
+ if (copy_to_user(buf, rd_dev->elfcore_buf, copy_size)) {
+ ret = -EFAULT;
+ goto ramdump_done;
+ }
+ *pos += copy_size;
+ count -= copy_size;
+ buf += copy_size;
+ if (count == 0)
+ return copy_size;
}
- addr = offset_translate(*pos, rd_dev, &data_left);
+ addr = offset_translate(*pos - rd_dev->elfcore_size, rd_dev,
+ &data_left);
/* EOF check */
if (data_left == 0) {
@@ -174,7 +188,7 @@
return mask;
}
-const struct file_operations ramdump_file_ops = {
+static const struct file_operations ramdump_file_ops = {
.open = ramdump_open,
.release = ramdump_release,
.read = ramdump_read,
@@ -234,11 +248,14 @@
kfree(rd_dev);
}
-int do_ramdump(void *handle, struct ramdump_segment *segments,
- int nsegments)
+static int _do_ramdump(void *handle, struct ramdump_segment *segments,
+ int nsegments, bool use_elf)
{
int ret, i;
struct ramdump_device *rd_dev = (struct ramdump_device *)handle;
+ Elf32_Phdr *phdr;
+ Elf32_Ehdr *ehdr;
+ unsigned long offset;
if (!rd_dev->consumer_present) {
pr_err("Ramdump(%s): No consumers. Aborting..\n", rd_dev->name);
@@ -251,6 +268,38 @@
rd_dev->segments = segments;
rd_dev->nsegments = nsegments;
+ if (use_elf) {
+ rd_dev->elfcore_size = sizeof(*ehdr) +
+ sizeof(*phdr) * nsegments;
+ ehdr = kzalloc(rd_dev->elfcore_size, GFP_KERNEL);
+ rd_dev->elfcore_buf = (char *)ehdr;
+ if (!rd_dev->elfcore_buf)
+ return -ENOMEM;
+
+ memcpy(ehdr->e_ident, ELFMAG, SELFMAG);
+ ehdr->e_ident[EI_CLASS] = ELFCLASS32;
+ ehdr->e_ident[EI_DATA] = ELFDATA2LSB;
+ ehdr->e_ident[EI_VERSION] = EV_CURRENT;
+ ehdr->e_ident[EI_OSABI] = ELFOSABI_NONE;
+ ehdr->e_type = ET_CORE;
+ ehdr->e_version = EV_CURRENT;
+ ehdr->e_phoff = sizeof(*ehdr);
+ ehdr->e_ehsize = sizeof(*ehdr);
+ ehdr->e_phentsize = sizeof(*phdr);
+ ehdr->e_phnum = nsegments;
+
+ offset = rd_dev->elfcore_size;
+ phdr = (Elf32_Phdr *)(ehdr + 1);
+ for (i = 0; i < nsegments; i++, phdr++) {
+ phdr->p_type = PT_LOAD;
+ phdr->p_offset = offset;
+ phdr->p_vaddr = phdr->p_paddr = segments[i].address;
+ phdr->p_filesz = phdr->p_memsz = segments[i].size;
+ phdr->p_flags = PF_R | PF_W | PF_X;
+ offset += phdr->p_filesz;
+ }
+ }
+
rd_dev->data_ready = 1;
rd_dev->ramdump_status = -1;
@@ -271,5 +320,20 @@
ret = (rd_dev->ramdump_status == 0) ? 0 : -EPIPE;
rd_dev->data_ready = 0;
+ rd_dev->elfcore_size = 0;
+ kfree(rd_dev->elfcore_buf);
+ rd_dev->elfcore_buf = NULL;
return ret;
+
+}
+
+int do_ramdump(void *handle, struct ramdump_segment *segments, int nsegments)
+{
+ return _do_ramdump(handle, segments, nsegments, false);
+}
+
+int
+do_elf_ramdump(void *handle, struct ramdump_segment *segments, int nsegments)
+{
+ return _do_ramdump(handle, segments, nsegments, true);
}
diff --git a/arch/arm/mach-msm/ramdump.h b/arch/arm/mach-msm/ramdump.h
index 3e5bfaf..5fb41ec 100644
--- a/arch/arm/mach-msm/ramdump.h
+++ b/arch/arm/mach-msm/ramdump.h
@@ -24,5 +24,7 @@
void destroy_ramdump_device(void *dev);
int do_ramdump(void *handle, struct ramdump_segment *segments,
int nsegments);
+int do_elf_ramdump(void *handle, struct ramdump_segment *segments,
+ int nsegments);
#endif
diff --git a/arch/arm/mach-msm/spm_devices.c b/arch/arm/mach-msm/spm_devices.c
index b378d3b..e77a7ac 100644
--- a/arch/arm/mach-msm/spm_devices.c
+++ b/arch/arm/mach-msm/spm_devices.c
@@ -374,7 +374,7 @@
};
struct mode_of of_l2_modes[] = {
- {"qcom,saw2-spm-cmd-ret", MSM_SPM_L2_MODE_RETENTION, 1},
+ {"qcom,saw2-spm-cmd-ret", MSM_SPM_L2_MODE_RETENTION, 0},
{"qcom,saw2-spm-cmd-gdhs", MSM_SPM_L2_MODE_GDHS, 1},
{"qcom,saw2-spm-cmd-pc", MSM_SPM_L2_MODE_POWER_COLLAPSE, 1},
};
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index 212ad77..e360906 100644
--- a/arch/arm/mach-msm/timer.c
+++ b/arch/arm/mach-msm/timer.c
@@ -1035,7 +1035,8 @@
if (cpu_is_msm7x01() || cpu_is_msm7x25() || cpu_is_msm7x27() ||
cpu_is_msm7x25a() || cpu_is_msm7x27a() || cpu_is_msm7x25aa() ||
- cpu_is_msm7x27aa() || cpu_is_msm8625() || cpu_is_msm7x25ab()) {
+ cpu_is_msm7x27aa() || cpu_is_msm8625() || cpu_is_msm7x25ab() ||
+ cpu_is_msm8625q()) {
dgt->shift = MSM_DGT_SHIFT;
dgt->freq = 19200000 >> MSM_DGT_SHIFT;
dgt->clockevent.shift = 32 + MSM_DGT_SHIFT;
@@ -1045,7 +1046,7 @@
gpt->flags |= MSM_CLOCK_FLAGS_UNSTABLE_COUNT
| MSM_CLOCK_FLAGS_ODD_MATCH_WRITE
| MSM_CLOCK_FLAGS_DELAYED_WRITE_POST;
- if (cpu_is_msm8625())
+ if (cpu_is_msm8625() || cpu_is_msm8625q())
fixup_msm8625_timer();
} else if (cpu_is_qsd8x50()) {
dgt->freq = 4800000;
@@ -1134,8 +1135,8 @@
ce->irq = clock->irq;
if (cpu_is_msm8x60() || cpu_is_msm9615() || cpu_is_msm8625() ||
- soc_class_is_msm8960() || soc_class_is_apq8064() ||
- soc_class_is_msm8930()) {
+ cpu_is_msm8625q() || soc_class_is_msm8960() ||
+ soc_class_is_apq8064() || soc_class_is_msm8930()) {
clock->percpu_evt = alloc_percpu(struct clock_event_device *);
if (!clock->percpu_evt) {
pr_err("msm_timer_init: memory allocation "
diff --git a/block/blk-core.c b/block/blk-core.c
index 68d7158..fe1c7e0 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -297,13 +297,26 @@
* Description:
* See @blk_run_queue. This variant must be called with the queue lock
* held and interrupts disabled.
+ * Device driver will be notified of an urgent request
+ * pending under the following conditions:
+ * 1. The driver and the current scheduler support urgent reques handling
+ * 2. There is an urgent request pending in the scheduler
+ * 3. There isn't already an urgent request in flight, meaning previously
+ * notified urgent request completed (!q->notified_urgent)
*/
void __blk_run_queue(struct request_queue *q)
{
if (unlikely(blk_queue_stopped(q)))
return;
- q->request_fn(q);
+ if (!q->notified_urgent &&
+ q->elevator->type->ops.elevator_is_urgent_fn &&
+ q->urgent_request_fn &&
+ q->elevator->type->ops.elevator_is_urgent_fn(q)) {
+ q->notified_urgent = true;
+ q->urgent_request_fn(q);
+ } else
+ q->request_fn(q);
}
EXPORT_SYMBOL(__blk_run_queue);
@@ -1070,6 +1083,50 @@
}
EXPORT_SYMBOL(blk_requeue_request);
+/**
+ * blk_reinsert_request() - Insert a request back to the scheduler
+ * @q: request queue
+ * @rq: request to be inserted
+ *
+ * This function inserts the request back to the scheduler as if
+ * it was never dispatched.
+ *
+ * Return: 0 on success, error code on fail
+ */
+int blk_reinsert_request(struct request_queue *q, struct request *rq)
+{
+ if (unlikely(!rq) || unlikely(!q))
+ return -EIO;
+
+ blk_delete_timer(rq);
+ blk_clear_rq_complete(rq);
+ trace_block_rq_requeue(q, rq);
+
+ if (blk_rq_tagged(rq))
+ blk_queue_end_tag(q, rq);
+
+ BUG_ON(blk_queued_rq(rq));
+
+ return elv_reinsert_request(q, rq);
+}
+EXPORT_SYMBOL(blk_reinsert_request);
+
+/**
+ * blk_reinsert_req_sup() - check whether the scheduler supports
+ * reinsertion of requests
+ * @q: request queue
+ *
+ * Returns true if the current scheduler supports reinserting
+ * request. False otherwise
+ */
+bool blk_reinsert_req_sup(struct request_queue *q)
+{
+ if (unlikely(!q))
+ return false;
+ return q->elevator->type->ops.elevator_reinsert_req_fn ? true : false;
+}
+EXPORT_SYMBOL(blk_reinsert_req_sup);
+
static void add_acct_request(struct request_queue *q, struct request *rq,
int where)
{
@@ -2073,8 +2130,17 @@
struct request *rq;
rq = blk_peek_request(q);
- if (rq)
+ if (rq) {
+ /*
+ * Assumption: the next request fetched from scheduler after we
+ * notified "urgent request pending" - will be the urgent one
+ */
+ if (q->notified_urgent && !q->dispatched_urgent) {
+ q->dispatched_urgent = true;
+ (void)blk_mark_rq_urgent(rq);
+ }
blk_start_request(rq);
+ }
return rq;
}
EXPORT_SYMBOL(blk_fetch_request);
diff --git a/block/blk-settings.c b/block/blk-settings.c
index d3234fc..579328c 100644
--- a/block/blk-settings.c
+++ b/block/blk-settings.c
@@ -100,6 +100,18 @@
EXPORT_SYMBOL_GPL(blk_queue_lld_busy);
/**
+ * blk_urgent_request() - Set an urgent_request handler function for queue
+ * @q: queue
+ * @fn: handler for urgent requests
+ *
+ */
+void blk_urgent_request(struct request_queue *q, request_fn_proc *fn)
+{
+ q->urgent_request_fn = fn;
+}
+EXPORT_SYMBOL(blk_urgent_request);
+
+/**
* blk_set_default_limits - reset limits to default values
* @lim: the queue_limits structure to reset
*
diff --git a/block/blk.h b/block/blk.h
index d45be87..a52209f 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -39,6 +39,7 @@
*/
enum rq_atomic_flags {
REQ_ATOM_COMPLETE = 0,
+ REQ_ATOM_URGENT = 1,
};
/*
@@ -55,6 +56,16 @@
clear_bit(REQ_ATOM_COMPLETE, &rq->atomic_flags);
}
+static inline int blk_mark_rq_urgent(struct request *rq)
+{
+ return test_and_set_bit(REQ_ATOM_URGENT, &rq->atomic_flags);
+}
+
+static inline void blk_clear_rq_urgent(struct request *rq)
+{
+ clear_bit(REQ_ATOM_URGENT, &rq->atomic_flags);
+}
+
/*
* Internal elevator interface
*/
diff --git a/block/elevator.c b/block/elevator.c
index 74fd51b..efec457 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -585,6 +585,41 @@
__elv_add_request(q, rq, ELEVATOR_INSERT_REQUEUE);
}
+/**
+ * elv_reinsert_request() - Insert a request back to the scheduler
+ * @q: request queue where request should be inserted
+ * @rq: request to be inserted
+ *
+ * This function returns the request back to the scheduler to be
+ * inserted as if it was never dispatched
+ *
+ * Return: 0 on success, error code on failure
+ */
+int elv_reinsert_request(struct request_queue *q, struct request *rq)
+{
+ int res;
+
+ if (!q->elevator->type->ops.elevator_reinsert_req_fn)
+ return -EPERM;
+
+ res = q->elevator->type->ops.elevator_reinsert_req_fn(q, rq);
+ if (!res) {
+ /*
+ * it already went through dequeue, we need to decrement the
+ * in_flight count again
+ */
+ if (blk_account_rq(rq)) {
+ q->in_flight[rq_is_sync(rq)]--;
+ if (rq->cmd_flags & REQ_SORTED)
+ elv_deactivate_rq(q, rq);
+ }
+ rq->cmd_flags &= ~REQ_STARTED;
+ q->nr_sorted++;
+ }
+
+ return res;
+}
+
void elv_drain_elevator(struct request_queue *q)
{
static int printed;
@@ -779,6 +814,11 @@
{
struct elevator_queue *e = q->elevator;
+ if (test_bit(REQ_ATOM_URGENT, &rq->atomic_flags)) {
+ q->notified_urgent = false;
+ q->dispatched_urgent = false;
+ blk_clear_rq_urgent(rq);
+ }
/*
* request is released from the driver, io must be done
*/
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index c1cbfea..55597fc 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -598,7 +598,7 @@
/* 8x25 returns 0 for minor id, but it should be 1 */
if (cpu_is_qsd8x50())
patchid = 1;
- else if (cpu_is_msm8625() && minorid == 0)
+ else if ((cpu_is_msm8625() || cpu_is_msm8625q()) && minorid == 0)
minorid = 1;
chipid |= (minorid << 8) | patchid;
diff --git a/drivers/hwmon/epm_adc.c b/drivers/hwmon/epm_adc.c
index 69a2f1c..606bc36 100644
--- a/drivers/hwmon/epm_adc.c
+++ b/drivers/hwmon/epm_adc.c
@@ -1324,6 +1324,10 @@
return -EINVAL;
}
+ psoc_get_data.reading_value = epm_psoc_scale_result(
+ psoc_get_data.reading_value,
+ psoc_get_data.chan_num);
+
if (copy_to_user((void __user *)arg, &psoc_get_data,
sizeof(struct epm_psoc_get_data)))
return -EFAULT;
@@ -1529,38 +1533,38 @@
}
static struct sensor_device_attribute epm_adc_psoc_in_attrs[] = {
- SENSOR_ATTR(ads0_chan0, S_IRUGO, epm_adc_psoc_show_in, NULL, 0),
- SENSOR_ATTR(ads0_chan1, S_IRUGO, epm_adc_psoc_show_in, NULL, 1),
- SENSOR_ATTR(ads0_chan2, S_IRUGO, epm_adc_psoc_show_in, NULL, 2),
- SENSOR_ATTR(ads0_chan3, S_IRUGO, epm_adc_psoc_show_in, NULL, 3),
- SENSOR_ATTR(ads0_chan4, S_IRUGO, epm_adc_psoc_show_in, NULL, 4),
- SENSOR_ATTR(ads0_chan5, S_IRUGO, epm_adc_psoc_show_in, NULL, 5),
- SENSOR_ATTR(ads0_chan6, S_IRUGO, epm_adc_psoc_show_in, NULL, 6),
- SENSOR_ATTR(ads0_chan7, S_IRUGO, epm_adc_psoc_show_in, NULL, 7),
- SENSOR_ATTR(ads0_chan8, S_IRUGO, epm_adc_psoc_show_in, NULL, 8),
- SENSOR_ATTR(ads0_chan9, S_IRUGO, epm_adc_psoc_show_in, NULL, 9),
- SENSOR_ATTR(ads0_chan10, S_IRUGO, epm_adc_psoc_show_in, NULL, 10),
- SENSOR_ATTR(ads0_chan11, S_IRUGO, epm_adc_psoc_show_in, NULL, 11),
- SENSOR_ATTR(ads0_chan12, S_IRUGO, epm_adc_psoc_show_in, NULL, 12),
- SENSOR_ATTR(ads0_chan13, S_IRUGO, epm_adc_psoc_show_in, NULL, 13),
- SENSOR_ATTR(ads0_chan14, S_IRUGO, epm_adc_psoc_show_in, NULL, 14),
- SENSOR_ATTR(ads0_chan15, S_IRUGO, epm_adc_psoc_show_in, NULL, 15),
- SENSOR_ATTR(ads1_chan0, S_IRUGO, epm_adc_psoc_show_in, NULL, 16),
- SENSOR_ATTR(ads1_chan1, S_IRUGO, epm_adc_psoc_show_in, NULL, 17),
- SENSOR_ATTR(ads1_chan2, S_IRUGO, epm_adc_psoc_show_in, NULL, 18),
- SENSOR_ATTR(ads1_chan3, S_IRUGO, epm_adc_psoc_show_in, NULL, 19),
- SENSOR_ATTR(ads1_chan4, S_IRUGO, epm_adc_psoc_show_in, NULL, 20),
- SENSOR_ATTR(ads1_chan5, S_IRUGO, epm_adc_psoc_show_in, NULL, 21),
- SENSOR_ATTR(ads1_chan6, S_IRUGO, epm_adc_psoc_show_in, NULL, 22),
- SENSOR_ATTR(ads1_chan7, S_IRUGO, epm_adc_psoc_show_in, NULL, 23),
- SENSOR_ATTR(ads1_chan8, S_IRUGO, epm_adc_psoc_show_in, NULL, 24),
- SENSOR_ATTR(ads1_chan9, S_IRUGO, epm_adc_psoc_show_in, NULL, 25),
- SENSOR_ATTR(ads1_chan10, S_IRUGO, epm_adc_psoc_show_in, NULL, 26),
- SENSOR_ATTR(ads1_chan11, S_IRUGO, epm_adc_psoc_show_in, NULL, 27),
- SENSOR_ATTR(ads1_chan12, S_IRUGO, epm_adc_psoc_show_in, NULL, 28),
- SENSOR_ATTR(ads1_chan13, S_IRUGO, epm_adc_psoc_show_in, NULL, 29),
- SENSOR_ATTR(ads1_chan14, S_IRUGO, epm_adc_psoc_show_in, NULL, 30),
- SENSOR_ATTR(ads1_chan15, S_IRUGO, epm_adc_psoc_show_in, NULL, 31),
+ SENSOR_ATTR(psoc0_chan0, S_IRUGO, epm_adc_psoc_show_in, NULL, 0),
+ SENSOR_ATTR(psoc0_chan1, S_IRUGO, epm_adc_psoc_show_in, NULL, 1),
+ SENSOR_ATTR(psoc0_chan2, S_IRUGO, epm_adc_psoc_show_in, NULL, 2),
+ SENSOR_ATTR(psoc0_chan3, S_IRUGO, epm_adc_psoc_show_in, NULL, 3),
+ SENSOR_ATTR(psoc0_chan4, S_IRUGO, epm_adc_psoc_show_in, NULL, 4),
+ SENSOR_ATTR(psoc0_chan5, S_IRUGO, epm_adc_psoc_show_in, NULL, 5),
+ SENSOR_ATTR(psoc0_chan6, S_IRUGO, epm_adc_psoc_show_in, NULL, 6),
+ SENSOR_ATTR(psoc0_chan7, S_IRUGO, epm_adc_psoc_show_in, NULL, 7),
+ SENSOR_ATTR(psoc0_chan8, S_IRUGO, epm_adc_psoc_show_in, NULL, 8),
+ SENSOR_ATTR(psoc0_chan9, S_IRUGO, epm_adc_psoc_show_in, NULL, 9),
+ SENSOR_ATTR(psoc0_chan10, S_IRUGO, epm_adc_psoc_show_in, NULL, 10),
+ SENSOR_ATTR(psoc0_chan11, S_IRUGO, epm_adc_psoc_show_in, NULL, 11),
+ SENSOR_ATTR(psoc0_chan12, S_IRUGO, epm_adc_psoc_show_in, NULL, 12),
+ SENSOR_ATTR(psoc0_chan13, S_IRUGO, epm_adc_psoc_show_in, NULL, 13),
+ SENSOR_ATTR(psoc0_chan14, S_IRUGO, epm_adc_psoc_show_in, NULL, 14),
+ SENSOR_ATTR(psoc0_chan15, S_IRUGO, epm_adc_psoc_show_in, NULL, 15),
+ SENSOR_ATTR(psoc0_chan16, S_IRUGO, epm_adc_psoc_show_in, NULL, 16),
+ SENSOR_ATTR(psoc0_chan17, S_IRUGO, epm_adc_psoc_show_in, NULL, 17),
+ SENSOR_ATTR(psoc0_chan18, S_IRUGO, epm_adc_psoc_show_in, NULL, 18),
+ SENSOR_ATTR(psoc0_chan19, S_IRUGO, epm_adc_psoc_show_in, NULL, 19),
+ SENSOR_ATTR(psoc0_chan20, S_IRUGO, epm_adc_psoc_show_in, NULL, 20),
+ SENSOR_ATTR(psoc0_chan21, S_IRUGO, epm_adc_psoc_show_in, NULL, 21),
+ SENSOR_ATTR(psoc0_chan22, S_IRUGO, epm_adc_psoc_show_in, NULL, 22),
+ SENSOR_ATTR(psoc0_chan23, S_IRUGO, epm_adc_psoc_show_in, NULL, 23),
+ SENSOR_ATTR(psoc0_chan24, S_IRUGO, epm_adc_psoc_show_in, NULL, 24),
+ SENSOR_ATTR(psoc0_chan25, S_IRUGO, epm_adc_psoc_show_in, NULL, 25),
+ SENSOR_ATTR(psoc0_chan26, S_IRUGO, epm_adc_psoc_show_in, NULL, 26),
+ SENSOR_ATTR(psoc0_chan27, S_IRUGO, epm_adc_psoc_show_in, NULL, 27),
+ SENSOR_ATTR(psoc0_chan28, S_IRUGO, epm_adc_psoc_show_in, NULL, 28),
+ SENSOR_ATTR(psoc0_chan29, S_IRUGO, epm_adc_psoc_show_in, NULL, 29),
+ SENSOR_ATTR(psoc0_chan30, S_IRUGO, epm_adc_psoc_show_in, NULL, 30),
+ SENSOR_ATTR(psoc0_chan31, S_IRUGO, epm_adc_psoc_show_in, NULL, 31),
};
static int __devinit epm_adc_psoc_init_hwmon(struct spi_device *spi,
@@ -1677,6 +1681,15 @@
epm_adc = epm_adc_drv;
epm_adc->misc.name = EPM_ADC_DRIVER_NAME;
epm_adc->misc.minor = MISC_DYNAMIC_MINOR;
+
+ if (node) {
+ epm_adc->misc.fops = &epm_adc_fops;
+ if (misc_register(&epm_adc->misc)) {
+ pr_err("Unable to register misc device!\n");
+ return -EFAULT;
+ }
+ }
+
epm_adc_drv->epm_spi_client = spi;
epm_adc_drv->epm_spi_client->bits_per_word =
EPM_ADC_ADS_SPI_BITS_PER_WORD;
diff --git a/drivers/input/touchscreen/cyttsp-i2c-qc.c b/drivers/input/touchscreen/cyttsp-i2c-qc.c
index f96348e..6eba5d1 100644
--- a/drivers/input/touchscreen/cyttsp-i2c-qc.c
+++ b/drivers/input/touchscreen/cyttsp-i2c-qc.c
@@ -2778,11 +2778,14 @@
return -EINVAL;
}
+ mutex_init(&ts->mutex);
i2c_set_clientdata(client, ts);
error = cyttsp_initialize(client, ts);
if (error) {
cyttsp_xdebug1("err cyttsp_initialize\n");
+ /* release mutex */
+ mutex_destroy(&ts->mutex);
/* deallocate memory */
kfree(ts);
/*
@@ -2801,7 +2804,6 @@
}
#endif /* CONFIG_HAS_EARLYSUSPEND */
device_init_wakeup(&client->dev, ts->platform_data->wakeup);
- mutex_init(&ts->mutex);
cyttsp_info("Start Probe %s\n", \
(retval < CY_OK) ? "FAIL" : "PASS");
diff --git a/drivers/leds/leds-pm8xxx.c b/drivers/leds/leds-pm8xxx.c
index a641ce9..f493129 100644
--- a/drivers/leds/leds-pm8xxx.c
+++ b/drivers/leds/leds-pm8xxx.c
@@ -70,6 +70,7 @@
#define WLED_CTL_DLY_BIT_SHFT 0x05
#define WLED_MAX_CURR 25
#define WLED_MAX_CURR_MASK 0x1F
+#define WLED_BRIGHTNESS_MSB_MASK 0x0F
#define WLED_OP_FDBCK_MASK 0x1C
#define WLED_OP_FDBCK_BIT_SHFT 0x02
@@ -283,7 +284,8 @@
return rc;
}
- val = (val & ~WLED_MAX_CURR_MASK) | (duty >> WLED_8_BIT_SHFT);
+ val = (val & ~WLED_BRIGHTNESS_MSB_MASK) |
+ (duty >> WLED_8_BIT_SHFT);
rc = pm8xxx_writeb(led->dev->parent,
WLED_BRIGHTNESS_CNTL_REG1(i), val);
if (rc) {
diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig
index d2ed996..f33122f 100644
--- a/drivers/media/rc/Kconfig
+++ b/drivers/media/rc/Kconfig
@@ -35,6 +35,17 @@
To compile this driver as a module, choose M here: the module will
be called user-rc-input.
+config USER_SP_RC_INPUT
+ tristate "User Space Input device wrapper for Standby Processor Remote Control"
+ depends on RC_CORE
+
+ ---help---
+ Say Y if you want to report remote control input events
+ from userspace.
+
+ To compile this driver as a module, choose M here: the module will
+ be called user-sp-input.
+
source "drivers/media/rc/keymaps/Kconfig"
config IR_NEC_DECODER
diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile
index be02eec..fdc3e99 100644
--- a/drivers/media/rc/Makefile
+++ b/drivers/media/rc/Makefile
@@ -14,6 +14,7 @@
obj-$(CONFIG_IR_MCE_KBD_DECODER) += ir-mce_kbd-decoder.o
obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o
obj-$(CONFIG_USER_RC_INPUT) += user-rc-input.o
+obj-$(CONFIG_USER_SP_RC_INPUT) += user-sp-rc-input.o
# stand-alone IR receivers/transmitters
obj-$(CONFIG_RC_ATI_REMOTE) += ati_remote.o
diff --git a/drivers/media/rc/user-sp-rc-input.c b/drivers/media/rc/user-sp-rc-input.c
new file mode 100644
index 0000000..83da95d
--- /dev/null
+++ b/drivers/media/rc/user-sp-rc-input.c
@@ -0,0 +1,246 @@
+/* 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.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/ioctl.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/platform_device.h>
+#include <linux/device.h>
+#include <linux/cdev.h>
+#include <linux/slab.h>
+
+#include <media/rc-core.h>
+#include <media/user-rc-input.h>
+
+#define MAX_SP_DEVICES 1
+#define USER_SP_INPUT_DEV_NAME "user-sp-input"
+#define USER_SP_INPUT_DRV_NAME "sp-user-input"
+
+struct user_sp_input_dev {
+ struct cdev sp_input_cdev;
+ struct class *sp_input_class;
+ struct device *sp_input_dev;
+ struct rc_dev *spdev;
+ dev_t sp_input_base_dev;
+ struct device *dev;
+ int in_use;
+};
+
+static int user_sp_input_open(struct inode *inode, struct file *file)
+{
+ struct cdev *input_cdev = inode->i_cdev;
+ struct user_sp_input_dev *input_dev =
+ container_of(input_cdev, struct user_sp_input_dev, sp_input_cdev);
+
+ if (input_dev->in_use) {
+ dev_err(input_dev->dev,
+ "Device is already open..only one instance is allowed\n");
+ return -EBUSY;
+ }
+ input_dev->in_use++;
+ file->private_data = input_dev;
+
+ return 0;
+}
+
+static int user_sp_input_release(struct inode *inode, struct file *file)
+{
+ struct user_sp_input_dev *input_dev = file->private_data;
+
+ input_dev->in_use--;
+
+ return 0;
+}
+
+static ssize_t user_sp_input_write(struct file *file,
+ const char __user *buffer, size_t count, loff_t *ppos)
+{
+ int ret = count;
+ struct user_sp_input_dev *input_dev = file->private_data;
+ unsigned char cmd = 0;
+ int scancode = 0;
+
+ if (copy_from_user(&cmd, buffer, 1)) {
+ dev_err(input_dev->dev, "Copy from user failed\n");
+ ret = -EFAULT;
+ goto out_free;
+ }
+
+ if (copy_from_user(&scancode, &buffer[1], 4)) {
+ dev_err(input_dev->dev, "Copy from user failed\n");
+ ret = -EFAULT;
+ goto out_free;
+ }
+
+ switch (cmd) {
+ case USER_CONTROL_PRESSED:
+ dev_dbg(input_dev->dev, "user controlled pressed 0x%x\n",
+ scancode);
+ rc_keydown(input_dev->spdev, scancode, 0);
+ break;
+ case USER_CONTROL_REPEATED:
+ dev_dbg(input_dev->dev, "user controlled repeated 0x%x\n",
+ scancode);
+ rc_repeat(input_dev->spdev);
+ break;
+ case USER_CONTROL_RELEASED:
+ dev_dbg(input_dev->dev, "user controlled released 0x%x\n",
+ scancode);
+ rc_keyup(input_dev->spdev);
+ break;
+ }
+
+out_free:
+ return ret;
+}
+
+const struct file_operations sp_fops = {
+ .owner = THIS_MODULE,
+ .open = user_sp_input_open,
+ .write = user_sp_input_write,
+ .release = user_sp_input_release,
+};
+
+static int __devinit user_sp_input_probe(struct platform_device *pdev)
+{
+ struct user_sp_input_dev *user_sp_dev;
+ struct rc_dev *spdev;
+ int retval;
+
+ user_sp_dev = kzalloc(sizeof(struct user_sp_input_dev), GFP_KERNEL);
+ if (!user_sp_dev)
+ return -ENOMEM;
+
+ user_sp_dev->sp_input_class = class_create(THIS_MODULE,
+ "user-sp-input-loopback");
+
+ if (IS_ERR(user_sp_dev->sp_input_class)) {
+ retval = PTR_ERR(user_sp_dev->sp_input_class);
+ goto err;
+ }
+
+ retval = alloc_chrdev_region(&user_sp_dev->sp_input_base_dev, 0,
+ MAX_SP_DEVICES, USER_SP_INPUT_DEV_NAME);
+
+ if (retval) {
+ dev_err(&pdev->dev,
+ "alloc_chrdev_region failed\n");
+ goto alloc_chrdev_err;
+ }
+
+ dev_info(&pdev->dev, "User space report standby key event input" \
+ " driver registered, major %d\n",
+ MAJOR(user_sp_dev->sp_input_base_dev));
+
+ cdev_init(&user_sp_dev->sp_input_cdev, &sp_fops);
+ retval = cdev_add(&user_sp_dev->sp_input_cdev,
+ user_sp_dev->sp_input_base_dev, MAX_SP_DEVICES);
+ if (retval) {
+ dev_err(&pdev->dev, "cdev_add failed\n");
+ goto cdev_add_err;
+ }
+ user_sp_dev->sp_input_dev = device_create(user_sp_dev->sp_input_class,
+ NULL, MKDEV(MAJOR(user_sp_dev->sp_input_base_dev), 0), NULL,
+ "user-sp-input-dev%d", 0);
+
+ if (IS_ERR(user_sp_dev->sp_input_dev)) {
+ retval = PTR_ERR(user_sp_dev->sp_input_dev);
+ dev_err(&pdev->dev, "device_create failed\n");
+ goto device_create_err;
+ }
+
+ spdev = rc_allocate_device();
+ if (!spdev) {
+ dev_err(&pdev->dev, "failed to allocate rc device");
+ retval = -ENOMEM;
+ goto err_allocate_device;
+ }
+
+ spdev->driver_type = RC_DRIVER_SCANCODE;
+ spdev->allowed_protos = RC_TYPE_OTHER;
+ spdev->input_name = USER_SP_INPUT_DEV_NAME;
+ spdev->input_id.bustype = BUS_HOST;
+ spdev->driver_name = USER_SP_INPUT_DRV_NAME;
+ spdev->map_name = RC_MAP_RC6_PHILIPS;
+
+ retval = rc_register_device(spdev);
+ if (retval < 0) {
+ dev_err(&pdev->dev, "failed to register rc device\n");
+ goto rc_register_err;
+ }
+ user_sp_dev->spdev = spdev;
+ user_sp_dev->dev = &pdev->dev;
+ platform_set_drvdata(pdev, user_sp_dev);
+ user_sp_dev->in_use = 0;
+
+ return 0;
+
+rc_register_err:
+ rc_free_device(spdev);
+err_allocate_device:
+ device_destroy(user_sp_dev->sp_input_class,
+ MKDEV(MAJOR(user_sp_dev->sp_input_base_dev), 0));
+cdev_add_err:
+ unregister_chrdev_region(user_sp_dev->sp_input_base_dev,
+ MAX_SP_DEVICES);
+device_create_err:
+ cdev_del(&user_sp_dev->sp_input_cdev);
+alloc_chrdev_err:
+ class_destroy(user_sp_dev->sp_input_class);
+err:
+ kfree(user_sp_dev);
+ return retval;
+}
+
+static int __devexit user_sp_input_remove(struct platform_device *pdev)
+{
+ struct user_sp_input_dev *user_sp_dev = platform_get_drvdata(pdev);
+
+ platform_set_drvdata(pdev, NULL);
+ rc_free_device(user_sp_dev->spdev);
+ device_destroy(user_sp_dev->sp_input_class,
+ MKDEV(MAJOR(user_sp_dev->sp_input_base_dev), 0));
+ unregister_chrdev_region(user_sp_dev->sp_input_base_dev,
+ MAX_SP_DEVICES);
+ cdev_del(&user_sp_dev->sp_input_cdev);
+ class_destroy(user_sp_dev->sp_input_class);
+ kfree(user_sp_dev);
+
+ return 0;
+}
+
+static struct platform_driver user_sp_input_driver = {
+ .probe = user_sp_input_probe,
+ .remove = __devexit_p(user_sp_input_remove),
+ .driver = {
+ .name = USER_SP_INPUT_DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init user_sp_input_init(void)
+{
+ return platform_driver_register(&user_sp_input_driver);
+}
+module_init(user_sp_input_init);
+
+static void __exit user_sp_input_exit(void)
+{
+ platform_driver_unregister(&user_sp_input_driver);
+}
+module_exit(user_sp_input_exit);
+
+MODULE_DESCRIPTION("User SP RC Input driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm_vidc/msm_vidc_common.c b/drivers/media/video/msm_vidc/msm_vidc_common.c
index d797ba7..fa056ca 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_common.c
+++ b/drivers/media/video/msm_vidc/msm_vidc_common.c
@@ -729,7 +729,7 @@
mutex_unlock(&bufq->lock);
if (!found) {
dprintk(VIDC_ERR,
- "Failed to find the buffer in queued list: %d, %d\n",
+ "Failed to find the buffer in queued list: 0x%x, %d\n",
dev_addr, q->type);
vb = NULL;
}
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 76e9b9c..0b5449e 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -136,6 +136,10 @@
module_param(perdev_minors, int, 0444);
MODULE_PARM_DESC(perdev_minors, "Minors numbers to allocate per device");
+static inline int mmc_blk_part_switch(struct mmc_card *card,
+ struct mmc_blk_data *md);
+static int get_card_status(struct mmc_card *card, u32 *status, int retries);
+
static inline void mmc_blk_clear_packed(struct mmc_queue_req *mqrq)
{
mqrq->packed_cmd = MMC_PACKED_NONE;
@@ -463,6 +467,38 @@
return ERR_PTR(err);
}
+static int ioctl_rpmb_card_status_poll(struct mmc_card *card, u32 *status,
+ u32 retries_max)
+{
+ int err;
+ u32 retry_count = 0;
+
+ if (!status || !retries_max)
+ return -EINVAL;
+
+ do {
+ err = get_card_status(card, status, 5);
+ if (err)
+ break;
+
+ if (!R1_STATUS(*status) &&
+ (R1_CURRENT_STATE(*status) != R1_STATE_PRG))
+ break; /* RPMB programming operation complete */
+
+ /*
+ * Rechedule to give the MMC device a chance to continue
+ * processing the previous command without being polled too
+ * frequently.
+ */
+ usleep_range(1000, 5000);
+ } while (++retry_count < retries_max);
+
+ if (retry_count == retries_max)
+ err = -EPERM;
+
+ return err;
+}
+
static int mmc_blk_ioctl_cmd(struct block_device *bdev,
struct mmc_ioc_cmd __user *ic_ptr)
{
@@ -474,6 +510,8 @@
struct mmc_request mrq = {NULL};
struct scatterlist sg;
int err;
+ int is_rpmb = false;
+ u32 status = 0;
/*
* The caller must have CAP_SYS_RAWIO, and must be calling this on the
@@ -493,6 +531,9 @@
goto cmd_done;
}
+ if (md->area_type & MMC_BLK_DATA_AREA_RPMB)
+ is_rpmb = true;
+
card = md->queue.card;
if (IS_ERR(card)) {
err = PTR_ERR(card);
@@ -543,12 +584,23 @@
mmc_claim_host(card->host);
+ err = mmc_blk_part_switch(card, md);
+ if (err)
+ goto cmd_rel_host;
+
if (idata->ic.is_acmd) {
err = mmc_app_cmd(card->host, card);
if (err)
goto cmd_rel_host;
}
+ if (is_rpmb) {
+ err = mmc_set_blockcount(card, data.blocks,
+ idata->ic.write_flag & (1 << 31));
+ if (err)
+ goto cmd_rel_host;
+ }
+
mmc_wait_for_req(card->host, &mrq);
if (cmd.error) {
@@ -584,6 +636,18 @@
}
}
+ if (is_rpmb) {
+ /*
+ * Ensure RPMB command has completed by polling CMD13
+ * "Send Status".
+ */
+ err = ioctl_rpmb_card_status_poll(card, &status, 5);
+ if (err)
+ dev_err(mmc_dev(card->host),
+ "%s: Card Status=0x%08X, error %d\n",
+ __func__, status, err);
+ }
+
cmd_rel_host:
mmc_release_host(card->host);
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index f91ba89..89f834a 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -2214,6 +2214,20 @@
}
EXPORT_SYMBOL(mmc_set_blocklen);
+int mmc_set_blockcount(struct mmc_card *card, unsigned int blockcount,
+ bool is_rel_write)
+{
+ struct mmc_command cmd = {0};
+
+ cmd.opcode = MMC_SET_BLOCK_COUNT;
+ cmd.arg = blockcount & 0x0000FFFF;
+ if (is_rel_write)
+ cmd.arg |= 1 << 31;
+ cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
+ return mmc_wait_for_cmd(card->host, &cmd, 5);
+}
+EXPORT_SYMBOL(mmc_set_blockcount);
+
static void mmc_hw_reset_for_init(struct mmc_host *host)
{
if (!(host->caps & MMC_CAP_HW_RESET) || !host->ops->hw_reset)
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index c8b47b9..00dc5bf 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -6536,19 +6536,19 @@
#if CONFIG_DEBUG_FS
static void msmsdcc_print_pm_stats(struct msmsdcc_host *host, ktime_t start,
- const char *func)
+ const char *func, int err)
{
ktime_t diff;
- if (host->print_pm_stats) {
+ if (host->print_pm_stats && !err) {
diff = ktime_sub(ktime_get(), start);
- pr_info("%s: %s: Completed in %llu usec\n", func,
- mmc_hostname(host->mmc), (u64)ktime_to_us(diff));
+ pr_info("%s: %s: Completed in %llu usec\n",
+ mmc_hostname(host->mmc), func, (u64)ktime_to_us(diff));
}
}
#else
static void msmsdcc_print_pm_stats(struct msmsdcc_host *host, ktime_t start,
- const char *func) {}
+ const char *func, int err) {}
#endif
static int
@@ -6615,7 +6615,7 @@
out:
/* set bus bandwidth to 0 immediately */
msmsdcc_msm_bus_cancel_work_and_set_vote(host, NULL);
- msmsdcc_print_pm_stats(host, start, __func__);
+ msmsdcc_print_pm_stats(host, start, __func__, rc);
return rc;
}
@@ -6664,7 +6664,7 @@
host->pending_resume = false;
pr_debug("%s: %s: end\n", mmc_hostname(mmc), __func__);
out:
- msmsdcc_print_pm_stats(host, start, __func__);
+ msmsdcc_print_pm_stats(host, start, __func__, 0);
return 0;
}
@@ -6701,7 +6701,7 @@
if (!pm_runtime_suspended(dev))
rc = msmsdcc_runtime_suspend(dev);
out:
- msmsdcc_print_pm_stats(host, start, __func__);
+ msmsdcc_print_pm_stats(host, start, __func__, rc);
return rc;
}
@@ -6757,7 +6757,7 @@
enable_irq(host->plat->status_irq);
}
out:
- msmsdcc_print_pm_stats(host, start, __func__);
+ msmsdcc_print_pm_stats(host, start, __func__, rc);
return rc;
}
diff --git a/drivers/platform/msm/sps/sps_bam.c b/drivers/platform/msm/sps/sps_bam.c
index a3bbb73..af421ac 100644
--- a/drivers/platform/msm/sps/sps_bam.c
+++ b/drivers/platform/msm/sps/sps_bam.c
@@ -1167,6 +1167,7 @@
struct sps_iovec *desc;
struct sps_iovec iovec;
u32 next_write;
+ static int show_recom;
/* Is this a BAM-to-BAM or satellite connection? */
if ((pipe->state & (BAM_STATE_BAM2BAM | BAM_STATE_REMOTE))) {
@@ -1199,12 +1200,24 @@
if (!pipe->sys.ack_xfers && pipe->polled) {
pipe_handler_eot(dev, pipe);
if (next_write == pipe->sys.acked_offset) {
+ if (!show_recom) {
+ show_recom = true;
+ SPS_ERR("sps:Client of BAM 0x%x pipe %d is recommended to have flow control",
+ BAM_ID(dev), pipe_index);
+ }
+
SPS_DBG2("sps:Descriptor FIFO is full for BAM "
"0x%x pipe %d after pipe_handler_eot",
BAM_ID(dev), pipe_index);
return SPS_ERROR;
}
} else {
+ if (!show_recom) {
+ show_recom = true;
+ SPS_ERR("sps:Client of BAM 0x%x pipe %d is recommended to have flow control.",
+ BAM_ID(dev), pipe_index);
+ }
+
SPS_DBG2("sps:Descriptor FIFO is full for "
"BAM 0x%x pipe %d", BAM_ID(dev), pipe_index);
return SPS_ERROR;
diff --git a/drivers/power/qpnp-bms.c b/drivers/power/qpnp-bms.c
index 12b186d..0a072b1 100644
--- a/drivers/power/qpnp-bms.c
+++ b/drivers/power/qpnp-bms.c
@@ -33,7 +33,7 @@
#define BMS1_MODE_CTL 0X40
/* Coulomb counter clear registers */
#define BMS1_CC_DATA_CTL 0x42
-#define BMS1_CC_CLEAR_CTRL 0x43
+#define BMS1_CC_CLEAR_CTL 0x43
/* OCV limit registers */
#define BMS1_OCV_USE_LOW_LIMIT_THR0 0x48
#define BMS1_OCV_USE_LOW_LIMIT_THR1 0x49
@@ -484,12 +484,49 @@
pr_debug("last_good_ocv_uv = %d\n", raw->last_good_ocv_uv);
}
+#define CLEAR_CC BIT(7)
+#define CLEAR_SW_CC BIT(6)
+/**
+ * reset both cc and sw-cc.
+ * note: this should only be ever called from one thread
+ * or there may be a race condition where CC is never enabled
+ * again
+ */
+static void reset_cc(struct qpnp_bms_chip *chip)
+{
+ int rc;
+
+ pr_debug("resetting cc manually\n");
+ rc = qpnp_masked_write(chip, BMS1_CC_CLEAR_CTL,
+ CLEAR_CC | CLEAR_SW_CC,
+ CLEAR_CC | CLEAR_SW_CC);
+ if (rc)
+ pr_err("cc reset failed: %d\n", rc);
+
+ /* wait for 100us for cc to reset */
+ udelay(100);
+
+ rc = qpnp_masked_write(chip, BMS1_CC_CLEAR_CTL,
+ CLEAR_CC | CLEAR_SW_CC, 0);
+ if (rc)
+ pr_err("cc reenable failed: %d\n", rc);
+}
+
static int read_soc_params_raw(struct qpnp_bms_chip *chip,
struct raw_soc_params *raw)
{
int rc;
mutex_lock(&chip->bms_output_lock);
+
+ if (chip->prev_last_good_ocv_raw == 0) {
+ /* software workaround for BMS 1.0
+ * The coulomb counter does not reset upon PON, so reset it
+ * manually upon probe. */
+ if (chip->revision1 == 0 && chip->revision2 == 0)
+ reset_cc(chip);
+ }
+
lock_output_data(chip);
rc = qpnp_read_wrapper(chip, (u8 *)&raw->last_good_ocv_raw,
@@ -1980,6 +2017,7 @@
pr_err("Error reading version register %d\n", rc);
goto error_read;
}
+ pr_debug("BMS version: %hhu.%hhu\n", chip->revision2, chip->revision1);
rc = qpnp_vadc_is_ready();
if (rc) {
diff --git a/drivers/tty/serial/msm_serial_hs_lite.c b/drivers/tty/serial/msm_serial_hs_lite.c
index 3de990c..0189a07 100644
--- a/drivers/tty/serial/msm_serial_hs_lite.c
+++ b/drivers/tty/serial/msm_serial_hs_lite.c
@@ -692,9 +692,9 @@
* Configure Rx Watermark as 3/4 size of Rx FIFO.
* RFWR register takes value in Words for UARTDM Core
* whereas it is consider to be in Bytes for UART Core.
- * Hence configuring Rx Watermark as 12 Words.
+ * Hence configuring Rx Watermark as 48 Words.
*/
- watermark = (port->fifosize * 3) / (4*4);
+ watermark = (port->fifosize * 3) / 4;
msm_hsl_write(port, watermark, regmap[vid][UARTDM_RFWR]);
/* set TX watermark */
@@ -775,18 +775,15 @@
#endif
pm_runtime_get_sync(port->dev);
- /* Set RFR Level as 3/4 of UARTDM FIFO Size */
+ /*
+ * Set RFR Level as 3/4 of UARTDM FIFO Size
+ * i.e. 48 Words = 192 bytes as Rx FIFO is 64 words ( 256 bytes).
+ */
if (likely(port->fifosize > 48))
rfr_level = port->fifosize - 16;
else
rfr_level = port->fifosize;
- /*
- * Use rfr_level value in Words to program
- * MR1 register for UARTDM Core.
- */
- rfr_level = (rfr_level / 4);
-
spin_lock_irqsave(&port->lock, flags);
vid = msm_hsl_port->ver_id;
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index d416904..2b0a79f 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -1248,6 +1248,10 @@
/* fall through */
case USB_CHG_STATE_DETECTED:
dwc3_chg_block_reset(mdwc);
+ /* Enable VDP_SRC */
+ if (mdwc->charger.chg_type == DWC3_DCP_CHARGER)
+ dwc3_msm_write_readback(mdwc->base,
+ CHARGING_DET_CTRL_REG, 0x1F, 0x10);
dev_dbg(mdwc->dev, "chg_type = %s\n",
chg_to_string(mdwc->charger.chg_type));
mdwc->charger.notify_detection_complete(mdwc->otg_xceiv->otg,
@@ -1279,6 +1283,7 @@
static int dwc3_msm_suspend(struct dwc3_msm *mdwc)
{
int ret;
+ bool dcp;
dev_dbg(mdwc->dev, "%s: entering lpm\n", __func__);
@@ -1287,23 +1292,29 @@
return 0;
}
+ if (mdwc->hs_phy_irq)
+ disable_irq(mdwc->hs_phy_irq);
+
if (cancel_delayed_work_sync(&mdwc->chg_work))
dev_dbg(mdwc->dev, "%s: chg_work was pending\n", __func__);
if (mdwc->chg_state != USB_CHG_STATE_DETECTED) {
/* charger detection wasn't complete; re-init flags */
mdwc->chg_state = USB_CHG_STATE_UNDEFINED;
mdwc->charger.chg_type = DWC3_INVALID_CHARGER;
+ dwc3_msm_write_readback(mdwc->base, CHARGING_DET_CTRL_REG,
+ 0x37, 0x0);
}
+ dcp = mdwc->charger.chg_type == DWC3_DCP_CHARGER;
+
/* Sequence to put hardware in low power state:
* 1. Set OTGDISABLE to disable OTG block in HSPHY (saves power)
- * 2. Clear charger detection control fields
+ * 2. Clear charger detection control fields (performed above)
* 3. SUSPEND PHY and turn OFF core clock after some delay
* 4. Clear interrupt latch register and enable BSV, ID HV interrupts
* 5. Enable PHY retention
*/
dwc3_msm_write_readback(mdwc->base, HS_PHY_CTRL_REG, 0x1000, 0x1000);
- dwc3_msm_write_readback(mdwc->base, CHARGING_DET_CTRL_REG, 0x37, 0x0);
dwc3_msm_write_readback(mdwc->base, HS_PHY_CTRL_REG,
0xC00000, 0x800000);
@@ -1323,7 +1334,8 @@
dwc3_msm_write_reg(mdwc->base, HS_PHY_IRQ_STAT_REG, 0xFFF);
dwc3_msm_write_readback(mdwc->base, HS_PHY_CTRL_REG, 0x18000, 0x18000);
- dwc3_msm_write_readback(mdwc->base, HS_PHY_CTRL_REG, 0x2, 0x0);
+ if (!dcp)
+ dwc3_msm_write_readback(mdwc->base, HS_PHY_CTRL_REG, 0x2, 0x0);
/* make sure above writes are completed before turning off clocks */
wmb();
@@ -1343,7 +1355,7 @@
dev_err(mdwc->dev, "Failed to reset bus bw vote\n");
}
- if (mdwc->otg_xceiv && mdwc->ext_xceiv.otg_capability)
+ if (mdwc->otg_xceiv && mdwc->ext_xceiv.otg_capability && !dcp)
dwc3_hsusb_ldo_enable(0);
dwc3_ssusb_ldo_enable(0);
@@ -1354,12 +1366,16 @@
dev_info(mdwc->dev, "DWC3 in low power mode\n");
+ if (mdwc->hs_phy_irq)
+ enable_irq(mdwc->hs_phy_irq);
+
return 0;
}
static int dwc3_msm_resume(struct dwc3_msm *mdwc)
{
int ret;
+ bool dcp;
dev_dbg(mdwc->dev, "%s: exiting lpm\n", __func__);
@@ -1383,7 +1399,8 @@
dev_err(mdwc->dev, "%s failed to vote for TCXO buffer%d\n",
__func__, ret);
- if (mdwc->otg_xceiv && mdwc->ext_xceiv.otg_capability)
+ dcp = mdwc->charger.chg_type == DWC3_DCP_CHARGER;
+ if (mdwc->otg_xceiv && mdwc->ext_xceiv.otg_capability && !dcp)
dwc3_hsusb_ldo_enable(1);
dwc3_ssusb_ldo_enable(1);
diff --git a/drivers/video/msm/mipi_dsi_host.c b/drivers/video/msm/mipi_dsi_host.c
index 96bfb9f..ee4a578 100644
--- a/drivers/video/msm/mipi_dsi_host.c
+++ b/drivers/video/msm/mipi_dsi_host.c
@@ -1249,7 +1249,6 @@
/* transmit read comamnd to client */
mipi_dsi_cmd_dma_tx(tp);
- mipi_dsi_disable_irq(DSI_CMD_TERM);
/*
* once cmd_dma_done interrupt received,
* return data from client is ready and stored
@@ -1359,7 +1358,6 @@
/* transmit read comamnd to client */
mipi_dsi_cmd_dma_tx(tp);
- mipi_dsi_disable_irq(DSI_CMD_TERM);
/*
* once cmd_dma_done interrupt received,
* return data from client is ready and stored
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index e76b0ae..6502841 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -282,6 +282,7 @@
struct request_list rq;
request_fn_proc *request_fn;
+ request_fn_proc *urgent_request_fn;
make_request_fn *make_request_fn;
prep_rq_fn *prep_rq_fn;
unprep_rq_fn *unprep_rq_fn;
@@ -365,6 +366,8 @@
struct list_head icq_list;
struct queue_limits limits;
+ bool notified_urgent;
+ bool dispatched_urgent;
/*
* sg stuff
@@ -673,6 +676,8 @@
extern struct request *blk_make_request(struct request_queue *, struct bio *,
gfp_t);
extern void blk_requeue_request(struct request_queue *, struct request *);
+extern int blk_reinsert_request(struct request_queue *q, struct request *rq);
+extern bool blk_reinsert_req_sup(struct request_queue *q);
extern void blk_add_request_payload(struct request *rq, struct page *page,
unsigned int len);
extern int blk_rq_check_limits(struct request_queue *q, struct request *rq);
@@ -822,6 +827,7 @@
extern struct request_queue *blk_init_queue(request_fn_proc *, spinlock_t *);
extern struct request_queue *blk_init_allocated_queue(struct request_queue *,
request_fn_proc *, spinlock_t *);
+extern void blk_urgent_request(struct request_queue *q, request_fn_proc *fn);
extern void blk_cleanup_queue(struct request_queue *);
extern void blk_queue_make_request(struct request_queue *, make_request_fn *);
extern void blk_queue_bounce_limit(struct request_queue *, u64);
diff --git a/include/linux/elevator.h b/include/linux/elevator.h
index 7d4e035..b36b28f 100644
--- a/include/linux/elevator.h
+++ b/include/linux/elevator.h
@@ -22,6 +22,9 @@
typedef int (elevator_dispatch_fn) (struct request_queue *, int);
typedef void (elevator_add_req_fn) (struct request_queue *, struct request *);
+typedef int (elevator_reinsert_req_fn) (struct request_queue *,
+ struct request *);
+typedef bool (elevator_is_urgent_fn) (struct request_queue *);
typedef struct request *(elevator_request_list_fn) (struct request_queue *, struct request *);
typedef void (elevator_completed_req_fn) (struct request_queue *, struct request *);
typedef int (elevator_may_queue_fn) (struct request_queue *, int);
@@ -46,6 +49,9 @@
elevator_dispatch_fn *elevator_dispatch_fn;
elevator_add_req_fn *elevator_add_req_fn;
+ elevator_reinsert_req_fn *elevator_reinsert_req_fn;
+ elevator_is_urgent_fn *elevator_is_urgent_fn;
+
elevator_activate_req_fn *elevator_activate_req_fn;
elevator_deactivate_req_fn *elevator_deactivate_req_fn;
@@ -122,6 +128,7 @@
extern void elv_bio_merged(struct request_queue *q, struct request *,
struct bio *);
extern void elv_requeue_request(struct request_queue *, struct request *);
+extern int elv_reinsert_request(struct request_queue *, struct request *);
extern struct request *elv_former_request(struct request_queue *, struct request *);
extern struct request *elv_latter_request(struct request_queue *, struct request *);
extern int elv_register_queue(struct request_queue *q);
diff --git a/include/linux/epm_adc.h b/include/linux/epm_adc.h
index ca1a425..14cb148 100644
--- a/include/linux/epm_adc.h
+++ b/include/linux/epm_adc.h
@@ -13,55 +13,54 @@
int32_t physical;
};
-#ifdef __KERNEL__
struct epm_psoc_init_resp {
- u8 cmd;
- u8 version;
- u8 compatible_ver;
- u8 firm_ver[3];
- u8 num_dev;
- u8 num_channel;
+ uint8_t cmd;
+ uint8_t version;
+ uint8_t compatible_ver;
+ uint8_t firm_ver[3];
+ uint8_t num_dev;
+ uint8_t num_channel;
};
struct epm_psoc_channel_configure {
- u8 cmd;
- u8 device_num;
+ uint8_t cmd;
+ uint8_t device_num;
uint32_t channel_num;
};
struct epm_psoc_set_avg {
- u8 cmd;
- u8 avg_period;
- u8 return_code;
+ uint8_t cmd;
+ uint8_t avg_period;
+ uint8_t return_code;
};
struct epm_psoc_get_data {
- u8 cmd;
- u8 dev_num;
- u8 chan_num;
+ uint8_t cmd;
+ uint8_t dev_num;
+ uint8_t chan_num;
uint32_t timestamp_resp_value;
uint32_t reading_value;
};
struct epm_psoc_get_buffered_data {
- u8 cmd;
- u8 dev_num;
- u8 status_mask;
- u8 chan_idx;
+ uint8_t cmd;
+ uint8_t dev_num;
+ uint8_t status_mask;
+ uint8_t chan_idx;
uint32_t chan_mask;
uint32_t timestamp_start;
uint32_t timestamp_end;
- u8 buff_data[48];
+ uint8_t buff_data[48];
};
struct epm_psoc_system_time_stamp {
- u8 cmd;
+ uint8_t cmd;
uint32_t timestamp;
};
struct epm_psoc_set_channel {
- u8 cmd;
- u8 dev_num;
+ uint8_t cmd;
+ uint8_t dev_num;
uint32_t channel_mask;
};
@@ -72,23 +71,23 @@
};
struct epm_psoc_get_avg_buffered_switch_data {
- u8 cmd;
- u8 status;
+ uint8_t cmd;
+ uint8_t status;
uint32_t timestamp_start;
uint32_t channel_mask;
- u8 avg_data[54];
+ uint8_t avg_data[54];
struct result_buffer data[54];
};
struct epm_psoc_set_channel_switch {
- u8 cmd;
- u8 dev;
+ uint8_t cmd;
+ uint8_t dev;
uint32_t delay;
};
struct epm_psoc_set_vadc {
- u8 cmd;
- u8 vadc_dev;
+ uint8_t cmd;
+ uint8_t vadc_dev;
uint32_t vadc_voltage;
};
@@ -97,6 +96,7 @@
uint32_t gain;
};
+#ifdef __KERNEL__
struct epm_adc_platform_data {
struct epm_chan_properties *channel;
uint32_t num_channels;
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
index 7247696..24b9790 100644
--- a/include/linux/mmc/core.h
+++ b/include/linux/mmc/core.h
@@ -178,6 +178,8 @@
extern unsigned int mmc_calc_max_discard(struct mmc_card *card);
extern int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen);
+extern int mmc_set_blockcount(struct mmc_card *card, unsigned int blockcount,
+ bool is_rel_write);
extern int mmc_hw_reset(struct mmc_host *host);
extern int mmc_hw_reset_check(struct mmc_host *host);
extern int mmc_can_reset(struct mmc_card *card);
diff --git a/sound/soc/msm/Kconfig b/sound/soc/msm/Kconfig
index d5cada7..04ca56a 100644
--- a/sound/soc/msm/Kconfig
+++ b/sound/soc/msm/Kconfig
@@ -107,7 +107,7 @@
config SND_SOC_MSM_QDSP6V2_INTF
bool "SoC Q6 audio driver for MSM8974"
- depends on MSM_QDSP6_APR
+ depends on MSM_QDSP6_APRV2
help
To add support for SoC audio on MSM8974.
This will enable all the platform specific