Merge "msm-fb: display: lm2 writeback support on mpq platfroms" into msm-3.0
diff --git a/Documentation/devicetree/bindings/prng/msm-rng.txt b/Documentation/devicetree/bindings/prng/msm-rng.txt
new file mode 100644
index 0000000..3d55808
--- /dev/null
+++ b/Documentation/devicetree/bindings/prng/msm-rng.txt
@@ -0,0 +1,12 @@
+* RNG (Random Number Generator)
+
+Required properties:
+- compatible : Should be "qcom,msm-rng"
+- reg : Offset and length of the register set for the device
+
+Example:
+
+ qcom,msm-rng@f9bff000 {
+ compatible = "qcom,msm-rng";
+ reg = <0xf9bff000 0x200>;
+ };
diff --git a/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt b/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt
new file mode 100644
index 0000000..cd7bdce
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt
@@ -0,0 +1,21 @@
+Qualcomm Global Distributed Switch Controller (GDSC) Regulator Driver
+
+The GDSC driver, implemented under the regulator framework, is responsible for
+safely collapsing and restoring power to peripheral cores on chipsets like
+msm-copper for power savings.
+
+Required properties:
+ - compatible: Must be "qcom,gdsc"
+ - regulator-name: A string used as a descriptive name for regulator outputs
+ - reg: The address of the GDSCR register
+
+Optional properties:
+ - parent-supply: phandle to the parent supply/regulator node
+
+Example:
+ gdsc_oxili_gx: qcom,gdsc@fd8c4024 {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_oxili_gx";
+ parent-supply = <&pm8841_s4>;
+ reg = <0xfd8c4024 0x4>;
+ };
diff --git a/arch/arm/boot/dts/msm-gdsc.dtsi b/arch/arm/boot/dts/msm-gdsc.dtsi
new file mode 100644
index 0000000..f83fe76
--- /dev/null
+++ b/arch/arm/boot/dts/msm-gdsc.dtsi
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+ gdsc_venus: qcom,gdsc@fd8c1024 {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_venus";
+ reg = <0xfd8c1024 0x4>;
+ };
+
+ gdsc_mdss: qcom,gdsc@fd8c2304 {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_mdss";
+ reg = <0xfd8c2304 0x4>;
+ };
+
+ gdsc_jpeg: qcom,gdsc@fd8c35a4 {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_jpeg";
+ reg = <0xfd8c35a4 0x4>;
+ };
+
+ gdsc_vfe: qcom,gdsc@fd8c36a4 {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_vfe";
+ reg = <0xfd8c36a4 0x4>;
+ };
+
+ gdsc_oxili_gx: qcom,gdsc@fd8c4024 {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_oxili_gx";
+ reg = <0xfd8c4024 0x4>;
+ };
+
+ gdsc_oxili_cx: qcom,gdsc@fd8c4034 {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_oxili_cx";
+ reg = <0xfd8c4034 0x4>;
+ };
+
+ gdsc_usb_hsic: qcom,gdsc@fc400404 {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_usb_hsic";
+ reg = <0xfc400404 0x4>;
+ };
+};
diff --git a/arch/arm/boot/dts/msmcopper.dtsi b/arch/arm/boot/dts/msmcopper.dtsi
index e807680..60f59d3 100644
--- a/arch/arm/boot/dts/msmcopper.dtsi
+++ b/arch/arm/boot/dts/msmcopper.dtsi
@@ -18,6 +18,7 @@
/include/ "msmcopper-regulator.dtsi"
/include/ "msmcopper-gpio.dtsi"
/include/ "msmcopper-iommu.dtsi"
+/include/ "msm-gdsc.dtsi"
/ {
model = "Qualcomm MSM Copper";
@@ -132,6 +133,7 @@
qcom,bam-dma-res-pipes = <6>;
};
+
spi@f9924000 {
compatible = "qcom,spi-qup-v2";
reg = <0xf9924000 0x1000>;
@@ -275,6 +277,10 @@
qcom,dwc-usb3-msm-dbm-eps = <4>;
};
+ gdsc_oxili_gx: qcom,gdsc@fd8c4024 {
+ parent-supply = <&pm8841_s4>;
+ };
+
qcom,lpass@fe200000 {
compatible = "qcom,pil-q6v5-lpass";
reg = <0xfe200000 0x00100>,
@@ -302,4 +308,9 @@
rpm-channel-name = "rpm_requests";
rpm-channel-type = <15>; /* SMD_APPS_RPM */
};
+
+ qcom,msm-rng@f9bff000 {
+ compatible = "qcom,msm-rng";
+ reg = <0xf9bff000 0x200>;
+ };
};
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 289b28c..a24498c 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -994,7 +994,6 @@
config DEBUG_MSM8960_UART
bool "Kernel low-level debugging messages via MSM 8960 UART"
depends on ARCH_MSM8960 && DEBUG_LL
- select DEBUG_MSM8930_UART
select MSM_HAS_DEBUG_UART_HS
help
Say Y here if you want the debug print routines to direct
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index dba3367..3659055 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -285,6 +285,7 @@
obj-$(CONFIG_ARCH_MSMCOPPER) += board-copper.o board-dt.o board-copper-regulator.o board-copper-gpiomux.o
obj-$(CONFIG_ARCH_MSMCOPPER) += acpuclock-krait.o acpuclock-copper.o
obj-$(CONFIG_ARCH_MSMCOPPER) += clock-local2.o clock-pll.o clock-copper.o
+obj-$(CONFIG_ARCH_MSMCOPPER) += gdsc.o
obj-$(CONFIG_ARCH_MSM9625) += board-9625.o board-9625-gpiomux.o
obj-$(CONFIG_MACH_SAPPHIRE) += board-sapphire.o board-sapphire-gpio.o
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 835b8b9..0234de6 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -91,6 +91,7 @@
#endif
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+#define HOLE_SIZE 0x20000
#define MSM_PMEM_KERNEL_EBI1_SIZE 0x65000
#ifdef CONFIG_MSM_IOMMU
#define MSM_ION_MM_SIZE 0x3800000
@@ -103,7 +104,7 @@
#define MSM_ION_QSECOM_SIZE 0x600000 /* (6MB) */
#define MSM_ION_HEAP_NUM 8
#endif
-#define MSM_ION_MM_FW_SIZE 0x200000 /* (2MB) */
+#define MSM_ION_MM_FW_SIZE (0x200000 - HOLE_SIZE) /* (2MB - 128KB) */
#define MSM_ION_MFC_SIZE SZ_8K
#define MSM_ION_AUDIO_SIZE MSM_PMEM_AUDIO_SIZE
#else
@@ -111,10 +112,11 @@
#define MSM_ION_HEAP_NUM 1
#endif
-#define APQ8064_FIXED_AREA_START 0xa0000000
+#define APQ8064_FIXED_AREA_START (0xa0000000 - (MSM_ION_MM_FW_SIZE + \
+ HOLE_SIZE))
#define MAX_FIXED_AREA_SIZE 0x10000000
-#define MSM_MM_FW_SIZE 0x200000
-#define APQ8064_FW_START (APQ8064_FIXED_AREA_START - MSM_MM_FW_SIZE)
+#define MSM_MM_FW_SIZE (0x200000 - HOLE_SIZE)
+#define APQ8064_FW_START APQ8064_FIXED_AREA_START
/* PCIe power enable pmic gpio */
#define PCIE_PWR_EN_PMIC_GPIO 13
@@ -505,19 +507,20 @@
return;
if (apq8064_fmem_pdata.size) {
- apq8064_fmem_pdata.reserved_size_low = fixed_low_size;
+ apq8064_fmem_pdata.reserved_size_low = fixed_low_size +
+ HOLE_SIZE;
apq8064_fmem_pdata.reserved_size_high = fixed_high_size;
}
/* Since the fixed area may be carved out of lowmem,
* make sure the length is a multiple of 1M.
*/
- fixed_size = (fixed_size + MSM_MM_FW_SIZE + SECTION_SIZE - 1)
+ fixed_size = (fixed_size + HOLE_SIZE + SECTION_SIZE - 1)
& SECTION_MASK;
apq8064_reserve_fixed_area(fixed_size);
fixed_low_start = APQ8064_FIXED_AREA_START;
- fixed_middle_start = fixed_low_start + fixed_low_size;
+ fixed_middle_start = fixed_low_start + fixed_low_size + HOLE_SIZE;
fixed_high_start = fixed_middle_start + fixed_middle_size;
for (i = 0; i < apq8064_ion_pdata.nr; ++i) {
@@ -525,11 +528,13 @@
if (heap->extra_data) {
int fixed_position = NOT_FIXED;
+ struct ion_cp_heap_pdata *pdata;
switch (heap->type) {
case ION_HEAP_TYPE_CP:
- fixed_position = ((struct ion_cp_heap_pdata *)
- heap->extra_data)->fixed_position;
+ pdata =
+ (struct ion_cp_heap_pdata *)heap->extra_data;
+ fixed_position = pdata->fixed_position;
break;
case ION_HEAP_TYPE_CARVEOUT:
fixed_position = ((struct ion_co_heap_pdata *)
@@ -545,6 +550,9 @@
break;
case FIXED_MIDDLE:
heap->base = fixed_middle_start;
+ pdata->secure_base = fixed_middle_start
+ - HOLE_SIZE;
+ pdata->secure_size = HOLE_SIZE + heap->size;
break;
case FIXED_HIGH:
heap->base = fixed_high_start;
diff --git a/arch/arm/mach-msm/board-copper.c b/arch/arm/mach-msm/board-copper.c
index 90cfee4..62bab86 100644
--- a/arch/arm/mach-msm/board-copper.c
+++ b/arch/arm/mach-msm/board-copper.c
@@ -408,23 +408,6 @@
.resource = copper_tzlog_resources,
};
-#ifdef CONFIG_HW_RANDOM_MSM
-/* PRNG device */
-#define MSM_PRNG_PHYS 0xF9BFF000
-static struct resource rng_resources = {
- .flags = IORESOURCE_MEM,
- .start = MSM_PRNG_PHYS,
- .end = MSM_PRNG_PHYS + SZ_512 - 1,
-};
-
-struct platform_device msm8974_device_rng = {
- .name = "msm_rng",
- .id = 0,
- .num_resources = 1,
- .resource = &rng_resources,
-};
-#endif
-
void __init msm_copper_add_devices(void)
{
@@ -436,9 +419,6 @@
platform_add_devices(msm_copper_stub_regulator_devices,
msm_copper_stub_regulator_devices_len);
platform_device_register(&copper_device_tz_log);
-#ifdef CONFIG_HW_RANDOM_MSM
- platform_device_register(&msm8974_device_rng);
-#endif
}
/*
@@ -517,6 +497,8 @@
"pil-q6v5-lpass", NULL),
OF_DEV_AUXDATA("qcom,pil-pronto", 0xFB21B000, \
"pil_pronto", NULL),
+ OF_DEV_AUXDATA("qcom,msm-rng", 0xF9BFF000, \
+ "msm_rng", NULL),
{}
};
diff --git a/arch/arm/mach-msm/clock-7x30.c b/arch/arm/mach-msm/clock-7x30.c
index fcd6386..cc48fe7 100644
--- a/arch/arm/mach-msm/clock-7x30.c
+++ b/arch/arm/mach-msm/clock-7x30.c
@@ -221,9 +221,15 @@
pcom_xo_enable(PCOM_XO_TCXO, PCOM_XO_DISABLE);
}
+static enum handoff xo_clk_handoff(struct clk *clk)
+{
+ return HANDOFF_ENABLED_CLK;
+}
+
static struct clk_ops clk_ops_tcxo = {
.enable = tcxo_clk_enable,
.disable = tcxo_clk_disable,
+ .handoff = xo_clk_handoff,
.is_local = pcom_is_local,
};
@@ -250,6 +256,7 @@
static struct clk_ops clk_ops_lpxo = {
.enable = lpxo_clk_enable,
.disable = lpxo_clk_disable,
+ .handoff = xo_clk_handoff,
.is_local = pcom_is_local,
};
diff --git a/arch/arm/mach-msm/clock-copper.c b/arch/arm/mach-msm/clock-copper.c
index d0054b5..4d5f773 100644
--- a/arch/arm/mach-msm/clock-copper.c
+++ b/arch/arm/mach-msm/clock-copper.c
@@ -598,9 +598,16 @@
return;
}
+static enum handoff cxo_clk_handoff(struct clk *clk)
+{
+ /* TODO: Remove from here once the rpm xo clock is ready. */
+ return HANDOFF_ENABLED_CLK;
+}
+
static struct clk_ops clk_ops_cxo = {
.enable = cxo_clk_enable,
.disable = cxo_clk_disable,
+ .handoff = cxo_clk_handoff,
};
static struct fixed_clk cxo_clk_src = {
@@ -4918,7 +4925,7 @@
CLK_LOOKUP("bus_clk", q6ss_ahb_lfabif_clk.c, "pil-q6v5-lpass"),
CLK_LOOKUP("mem_clk", gcc_boot_rom_ahb_clk.c, ""),
CLK_LOOKUP("bus_clk", gcc_mss_cfg_ahb_clk.c, ""),
- CLK_LOOKUP("core_clk", gcc_prng_ahb_clk.c, "msm_rng.0"),
+ CLK_LOOKUP("core_clk", gcc_prng_ahb_clk.c, "msm_rng"),
/* TODO: Remove dummy clocks as soon as they become unnecessary */
CLK_DUMMY("phy_clk", NULL, "msm_otg", OFF),
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 08211a2..f8ab18a 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -400,6 +400,4 @@
extern struct platform_device copper_device_tz_log;
-extern struct platform_device msm8974_device_rng;
-
extern struct platform_device mdm_sglte_device;
diff --git a/arch/arm/mach-msm/gdsc.c b/arch/arm/mach-msm/gdsc.c
new file mode 100644
index 0000000..a77ac24
--- /dev/null
+++ b/arch/arm/mach-msm/gdsc.c
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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/io.h>
+#include <linux/iopoll.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+
+#define PWR_ON_MASK BIT(31)
+#define EN_REST_WAIT_MASK (0xF << 20)
+#define EN_FEW_WAIT_MASK (0xF << 16)
+#define CLK_DIS_WAIT_MASK (0xF << 12)
+#define SW_OVERRIDE_MASK BIT(2)
+#define HW_CONTROL_MASK BIT(1)
+#define SW_COLLAPSE_MASK BIT(0)
+
+/* Wait 2^n CXO cycles between all states. Here, n=2 (4 cycles). */
+#define EN_REST_WAIT_VAL (0x2 << 20)
+#define EN_FEW_WAIT_VAL (0x2 << 16)
+#define CLK_DIS_WAIT_VAL (0x2 << 12)
+
+#define TIMEOUT_US 10
+
+struct gdsc {
+ struct regulator_dev *rdev;
+ struct regulator_desc rdesc;
+ void __iomem *gdscr;
+};
+
+static int gdsc_is_enabled(struct regulator_dev *rdev)
+{
+ struct gdsc *sc = rdev_get_drvdata(rdev);
+
+ return !!(readl_relaxed(sc->gdscr) & PWR_ON_MASK);
+}
+
+static int gdsc_enable(struct regulator_dev *rdev)
+{
+ struct gdsc *sc = rdev_get_drvdata(rdev);
+ uint32_t regval;
+ int ret;
+
+ regval = readl_relaxed(sc->gdscr);
+ regval &= ~SW_COLLAPSE_MASK;
+ writel_relaxed(regval, sc->gdscr);
+
+ ret = readl_tight_poll_timeout(sc->gdscr, regval, regval & PWR_ON_MASK,
+ TIMEOUT_US);
+ if (ret)
+ dev_err(&rdev->dev, "%s enable timed out\n", sc->rdesc.name);
+
+ return ret;
+}
+
+static int gdsc_disable(struct regulator_dev *rdev)
+{
+ struct gdsc *sc = rdev_get_drvdata(rdev);
+ uint32_t regval;
+ int ret;
+
+ regval = readl_relaxed(sc->gdscr);
+ regval |= SW_COLLAPSE_MASK;
+ writel_relaxed(regval, sc->gdscr);
+
+ ret = readl_tight_poll_timeout(sc->gdscr, regval,
+ !(regval & PWR_ON_MASK), TIMEOUT_US);
+ if (ret)
+ dev_err(&rdev->dev, "%s disable timed out\n", sc->rdesc.name);
+
+ return ret;
+}
+
+static struct regulator_ops gdsc_ops = {
+ .is_enabled = gdsc_is_enabled,
+ .enable = gdsc_enable,
+ .disable = gdsc_disable,
+};
+
+static int __devinit gdsc_probe(struct platform_device *pdev)
+{
+ static atomic_t gdsc_count = ATOMIC_INIT(-1);
+ struct regulator_init_data *init_data;
+ struct resource *res;
+ struct gdsc *sc;
+ uint32_t regval;
+ int ret;
+
+ sc = devm_kzalloc(&pdev->dev, sizeof(struct gdsc), GFP_KERNEL);
+ if (sc == NULL)
+ return -ENOMEM;
+
+ init_data = of_get_regulator_init_data(&pdev->dev);
+ if (init_data == NULL)
+ return -ENOMEM;
+
+ if (of_get_property(pdev->dev.of_node, "parent-supply", NULL))
+ init_data->supply_regulator = "parent";
+
+ ret = of_property_read_string(pdev->dev.of_node, "regulator-name",
+ &sc->rdesc.name);
+ if (ret)
+ return ret;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res == NULL)
+ return -EINVAL;
+ sc->gdscr = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+ if (sc->gdscr == NULL)
+ return -ENOMEM;
+
+ sc->rdesc.id = atomic_inc_return(&gdsc_count);
+ sc->rdesc.ops = &gdsc_ops;
+ sc->rdesc.type = REGULATOR_VOLTAGE;
+ sc->rdesc.owner = THIS_MODULE;
+ platform_set_drvdata(pdev, sc);
+
+ /*
+ * Disable HW trigger: collapse/restore occur based on registers writes.
+ * Disable SW override: Use hardware state-machine for sequencing.
+ */
+ regval = readl_relaxed(sc->gdscr);
+ regval &= ~(HW_CONTROL_MASK | SW_OVERRIDE_MASK);
+
+ /* Configure wait time between states. */
+ regval &= ~(EN_REST_WAIT_MASK | EN_FEW_WAIT_MASK | CLK_DIS_WAIT_MASK);
+ regval |= EN_REST_WAIT_VAL | EN_FEW_WAIT_VAL | CLK_DIS_WAIT_VAL;
+ writel_relaxed(regval, sc->gdscr);
+
+ sc->rdev = regulator_register(&sc->rdesc, &pdev->dev, init_data, sc,
+ pdev->dev.of_node);
+ if (IS_ERR(sc->rdev)) {
+ dev_err(&pdev->dev, "regulator_register(\"%s\") failed.\n",
+ sc->rdesc.name);
+ return PTR_ERR(sc->rdev);
+ }
+
+ return 0;
+}
+
+static int __devexit gdsc_remove(struct platform_device *pdev)
+{
+ struct gdsc *sc = platform_get_drvdata(pdev);
+ regulator_unregister(sc->rdev);
+ return 0;
+}
+
+static struct of_device_id gdsc_match_table[] = {
+ { .compatible = "qcom,gdsc" },
+ {}
+};
+
+static struct platform_driver gdsc_driver = {
+ .probe = gdsc_probe,
+ .remove = __devexit_p(gdsc_remove),
+ .driver = {
+ .name = "gdsc",
+ .of_match_table = gdsc_match_table,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init gdsc_init(void)
+{
+ return platform_driver_register(&gdsc_driver);
+}
+subsys_initcall(gdsc_init);
+
+static void __exit gdsc_exit(void)
+{
+ platform_driver_unregister(&gdsc_driver);
+}
+module_exit(gdsc_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Copper GDSC power rail regulator driver");
diff --git a/arch/arm/mach-msm/gss-8064.c b/arch/arm/mach-msm/gss-8064.c
index 3c475d6..126f8e0 100644
--- a/arch/arm/mach-msm/gss-8064.c
+++ b/arch/arm/mach-msm/gss-8064.c
@@ -23,6 +23,7 @@
#include <linux/fs.h>
#include <mach/irqs.h>
+#include <mach/msm_smsm.h>
#include <mach/scm.h>
#include <mach/peripheral-loader.h>
#include <mach/subsystem_restart.h>
@@ -42,6 +43,32 @@
static int crash_shutdown;
+#define MAX_SSR_REASON_LEN 81U
+
+static void log_gss_sfr(void)
+{
+ u32 size;
+ char *smem_reason, reason[MAX_SSR_REASON_LEN];
+
+ smem_reason = smem_get_entry(SMEM_SSR_REASON_MSS0, &size);
+ if (!smem_reason || !size) {
+ pr_err("GSS subsystem failure reason: (unknown, smem_get_entry failed).\n");
+ return;
+ }
+ if (!smem_reason[0]) {
+ pr_err("GSS subsystem failure reason: (unknown, init string found).\n");
+ return;
+ }
+
+ size = min(size, MAX_SSR_REASON_LEN-1);
+ memcpy(reason, smem_reason, size);
+ reason[size] = '\0';
+ pr_err("GSS subsystem failure reason: %s.\n", reason);
+
+ smem_reason[0] = '\0';
+ wmb();
+}
+
static void gss_fatal_fn(struct work_struct *work)
{
uint32_t panic_smsm_states = SMSM_RESET | SMSM_SYSTEM_DOWNLOAD;
@@ -58,6 +85,7 @@
pr_err("GSS SMSM state changed to SMSM_RESET.\n"
"Probable err_fatal on the GSS. "
"Calling subsystem restart...\n");
+ log_gss_sfr();
subsystem_restart("gss");
} else if (gss_state & reset_smsm_states) {
@@ -68,6 +96,7 @@
kernel_restart(NULL);
} else {
/* TODO: Bus unlock code/sequence goes _here_ */
+ log_gss_sfr();
subsystem_restart("gss");
}
}
@@ -84,6 +113,7 @@
pr_err("GSS SMSM state changed to SMSM_RESET.\n"
"Probable err_fatal on the GSS. "
"Calling subsystem restart...\n");
+ log_gss_sfr();
subsystem_restart("gss");
}
}
diff --git a/arch/arm/mach-msm/peripheral-loader.c b/arch/arm/mach-msm/peripheral-loader.c
index 9d0ce0d..bfbf4bc 100644
--- a/arch/arm/mach-msm/peripheral-loader.c
+++ b/arch/arm/mach-msm/peripheral-loader.c
@@ -138,8 +138,8 @@
const u8 *data;
if (memblock_overlaps_memory(phdr->p_paddr, phdr->p_memsz)) {
- dev_err(&pil->dev,
- "kernel memory would be overwritten [%#08lx, %#08lx)\n",
+ dev_err(&pil->dev, "%s: kernel memory would be overwritten "
+ "[%#08lx, %#08lx)\n", pil->desc->name,
(unsigned long)phdr->p_paddr,
(unsigned long)(phdr->p_paddr + phdr->p_memsz));
return -EPERM;
@@ -150,14 +150,15 @@
pil->desc->name, num);
ret = request_firmware(&fw, fw_name, &pil->dev);
if (ret) {
- dev_err(&pil->dev, "Failed to locate blob %s\n",
- fw_name);
+ dev_err(&pil->dev, "%s: Failed to locate blob %s\n",
+ pil->desc->name, fw_name);
return ret;
}
if (fw->size != phdr->p_filesz) {
- dev_err(&pil->dev, "Blob size %u doesn't match %u\n",
- fw->size, phdr->p_filesz);
+ dev_err(&pil->dev, "%s: Blob size %u doesn't match "
+ "%u\n", pil->desc->name, fw->size,
+ phdr->p_filesz);
ret = -EPERM;
goto release_fw;
}
@@ -174,7 +175,8 @@
size = min_t(size_t, IOMAP_SIZE, count);
buf = ioremap(paddr, size);
if (!buf) {
- dev_err(&pil->dev, "Failed to map memory\n");
+ dev_err(&pil->dev, "%s: Failed to map memory\n",
+ pil->desc->name);
ret = -ENOMEM;
goto release_fw;
}
@@ -195,7 +197,8 @@
size = min_t(size_t, IOMAP_SIZE, count);
buf = ioremap(paddr, size);
if (!buf) {
- dev_err(&pil->dev, "Failed to map memory\n");
+ dev_err(&pil->dev, "%s: Failed to map memory\n",
+ pil->desc->name);
ret = -ENOMEM;
goto release_fw;
}
@@ -210,7 +213,8 @@
ret = pil->desc->ops->verify_blob(pil->desc, phdr->p_paddr,
phdr->p_memsz);
if (ret)
- dev_err(&pil->dev, "Blob%u failed verification\n", num);
+ dev_err(&pil->dev, "%s: Blob%u failed verification\n",
+ pil->desc->name, num);
}
release_fw:
@@ -241,38 +245,43 @@
snprintf(fw_name, sizeof(fw_name), "%s.mdt", pil->desc->name);
ret = request_firmware(&fw, fw_name, &pil->dev);
if (ret) {
- dev_err(&pil->dev, "Failed to locate %s\n", fw_name);
+ dev_err(&pil->dev, "%s: Failed to locate %s\n",
+ pil->desc->name, fw_name);
goto out;
}
if (fw->size < sizeof(*ehdr)) {
- dev_err(&pil->dev, "Not big enough to be an elf header\n");
+ dev_err(&pil->dev, "%s: Not big enough to be an elf header\n",
+ pil->desc->name);
ret = -EIO;
goto release_fw;
}
ehdr = (struct elf32_hdr *)fw->data;
if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) {
- dev_err(&pil->dev, "Not an elf header\n");
+ dev_err(&pil->dev, "%s: Not an elf header\n", pil->desc->name);
ret = -EIO;
goto release_fw;
}
if (ehdr->e_phnum == 0) {
- dev_err(&pil->dev, "No loadable segments\n");
+ dev_err(&pil->dev, "%s: No loadable segments\n",
+ pil->desc->name);
ret = -EIO;
goto release_fw;
}
if (sizeof(struct elf32_phdr) * ehdr->e_phnum +
sizeof(struct elf32_hdr) > fw->size) {
- dev_err(&pil->dev, "Program headers not within mdt\n");
+ dev_err(&pil->dev, "%s: Program headers not within mdt\n",
+ pil->desc->name);
ret = -EIO;
goto release_fw;
}
ret = pil->desc->ops->init_image(pil->desc, fw->data, fw->size);
if (ret) {
- dev_err(&pil->dev, "Invalid firmware metadata\n");
+ dev_err(&pil->dev, "%s: Invalid firmware metadata\n",
+ pil->desc->name);
goto release_fw;
}
@@ -283,25 +292,27 @@
ret = load_segment(phdr, i, pil);
if (ret) {
- dev_err(&pil->dev, "Failed to load segment %d\n",
- i);
+ dev_err(&pil->dev, "%s: Failed to load segment %d\n",
+ pil->desc->name, i);
goto release_fw;
}
}
ret = pil_proxy_vote(pil);
if (ret) {
- dev_err(&pil->dev, "Failed to proxy vote\n");
+ dev_err(&pil->dev, "%s: Failed to proxy vote\n",
+ pil->desc->name);
goto release_fw;
}
ret = pil->desc->ops->auth_and_reset(pil->desc);
if (ret) {
- dev_err(&pil->dev, "Failed to bring out of reset\n");
+ dev_err(&pil->dev, "%s: Failed to bring out of reset\n",
+ pil->desc->name);
proxy_timeout = 0; /* Remove proxy vote immediately on error */
goto err_boot;
}
- dev_info(&pil->dev, "brought %s out of reset\n", pil->desc->name);
+ dev_info(&pil->dev, "%s: Brought out of reset\n", pil->desc->name);
err_boot:
pil_proxy_unvote(pil, proxy_timeout);
release_fw:
@@ -397,7 +408,8 @@
return;
mutex_lock(&pil->lock);
- if (WARN(!pil->count, "%s: Reference count mismatch\n", __func__))
+ if (WARN(!pil->count, "%s: %s: Reference count mismatch\n",
+ pil->desc->name, __func__))
goto err_out;
if (!--pil->count)
pil_shutdown(pil);
@@ -428,7 +440,8 @@
}
mutex_lock(&pil->lock);
- if (!WARN(!pil->count, "%s: Reference count mismatch\n", __func__))
+ if (!WARN(!pil->count, "%s: %s: Reference count mismatch\n",
+ pil->desc->name, __func__))
pil_shutdown(pil);
mutex_unlock(&pil->lock);
@@ -448,7 +461,8 @@
}
mutex_lock(&pil->lock);
- if (!WARN(!pil->count, "%s: Reference count mismatch\n", __func__))
+ if (!WARN(!pil->count, "%s: %s: Reference count mismatch\n",
+ pil->desc->name, __func__))
ret = load_image(pil);
if (!ret)
pil_set_state(pil, PIL_ONLINE);
diff --git a/drivers/char/hw_random/msm_rng.c b/drivers/char/hw_random/msm_rng.c
index 974b77e..7e6670d 100644
--- a/drivers/char/hw_random/msm_rng.c
+++ b/drivers/char/hw_random/msm_rng.c
@@ -231,12 +231,19 @@
return 0;
}
+static struct of_device_id qrng_match[] = {
+ { .compatible = "qcom,msm-rng",
+ },
+ {}
+};
+
static struct platform_driver rng_driver = {
.probe = msm_rng_probe,
.remove = __devexit_p(msm_rng_remove),
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
+ .of_match_table = qrng_match,
}
};
diff --git a/drivers/gpu/ion/msm/msm_ion.c b/drivers/gpu/ion/msm/msm_ion.c
index c239910..83afb25 100644
--- a/drivers/gpu/ion/msm/msm_ion.c
+++ b/drivers/gpu/ion/msm/msm_ion.c
@@ -136,9 +136,11 @@
}
cp_data->virt_addr = fmem_info->virt;
- cp_data->secure_base = heap->base;
- cp_data->secure_size =
+ if (!cp_data->secure_base) {
+ cp_data->secure_base = heap->base;
+ cp_data->secure_size =
heap->size + shared_heap->size;
+ }
} else if (!heap->base) {
ion_set_base_address(heap, shared_heap,
co_heap_data, cp_data);
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index e1c87e3..e4935ae 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -65,6 +65,11 @@
(rq_data_dir(req) == WRITE))
#define PACKED_CMD_VER 0x01
#define PACKED_CMD_WR 0x02
+#define MMC_BLK_UPDATE_STOP_REASON(stats, reason) \
+ do { \
+ if (stats->enabled) \
+ stats->pack_stop_reason[reason]++; \
+ } while (0)
static DEFINE_MUTEX(block_mutex);
@@ -1311,6 +1316,35 @@
}
+struct mmc_wr_pack_stats *mmc_blk_get_packed_statistics(struct mmc_card *card)
+{
+ if (!card)
+ return NULL;
+
+ return &card->wr_pack_stats;
+}
+EXPORT_SYMBOL(mmc_blk_get_packed_statistics);
+
+void mmc_blk_init_packed_statistics(struct mmc_card *card)
+{
+ int max_num_of_packed_reqs = 0;
+
+ if (!card || !card->wr_pack_stats.packing_events)
+ return;
+
+ max_num_of_packed_reqs = card->ext_csd.max_packed_writes;
+
+ spin_lock(&card->wr_pack_stats.lock);
+ memset(card->wr_pack_stats.packing_events, 0,
+ (max_num_of_packed_reqs + 1) *
+ sizeof(*card->wr_pack_stats.packing_events));
+ memset(&card->wr_pack_stats.pack_stop_reason, 0,
+ sizeof(card->wr_pack_stats.pack_stop_reason));
+ card->wr_pack_stats.enabled = true;
+ spin_unlock(&card->wr_pack_stats.lock);
+}
+EXPORT_SYMBOL(mmc_blk_init_packed_statistics);
+
static u8 mmc_blk_prep_packed_list(struct mmc_queue *mq, struct request *req)
{
struct request_queue *q = mq->queue;
@@ -1323,6 +1357,7 @@
u8 put_back = 0;
u8 max_packed_rw = 0;
u8 reqs = 0;
+ struct mmc_wr_pack_stats *stats = &card->wr_pack_stats;
mmc_blk_clear_packed(mq->mqrq_cur);
@@ -1360,20 +1395,26 @@
phys_segments++;
}
+ spin_lock(&stats->lock);
+
while (reqs < max_packed_rw - 1) {
spin_lock_irq(q->queue_lock);
next = blk_fetch_request(q);
spin_unlock_irq(q->queue_lock);
- if (!next)
+ if (!next) {
+ MMC_BLK_UPDATE_STOP_REASON(stats, EMPTY_QUEUE);
break;
+ }
if (next->cmd_flags & REQ_DISCARD ||
next->cmd_flags & REQ_FLUSH) {
+ MMC_BLK_UPDATE_STOP_REASON(stats, FLUSH_OR_DISCARD);
put_back = 1;
break;
}
if (rq_data_dir(cur) != rq_data_dir(next)) {
+ MMC_BLK_UPDATE_STOP_REASON(stats, WRONG_DATA_DIR);
put_back = 1;
break;
}
@@ -1381,18 +1422,22 @@
if (mmc_req_rel_wr(next) &&
(md->flags & MMC_BLK_REL_WR) &&
!en_rel_wr) {
+ MMC_BLK_UPDATE_STOP_REASON(stats, REL_WRITE);
put_back = 1;
break;
}
req_sectors += blk_rq_sectors(next);
if (req_sectors > max_blk_count) {
+ if (stats->enabled)
+ stats->pack_stop_reason[EXCEEDS_SECTORS]++;
put_back = 1;
break;
}
phys_segments += next->nr_phys_segments;
if (phys_segments > max_phys_segs) {
+ MMC_BLK_UPDATE_STOP_REASON(stats, EXCEEDS_SEGMENTS);
put_back = 1;
break;
}
@@ -1410,6 +1455,15 @@
spin_unlock_irq(q->queue_lock);
}
+ if (stats->enabled) {
+ if (reqs + 1 <= card->ext_csd.max_packed_writes)
+ stats->packing_events[reqs + 1]++;
+ if (reqs + 1 == max_packed_rw)
+ MMC_BLK_UPDATE_STOP_REASON(stats, THRESHOLD);
+ }
+
+ spin_unlock(&stats->lock);
+
if (reqs > 0) {
list_add(&req->queuelist, &mq->mqrq_cur->packed_list);
mq->mqrq_cur->packed_num = ++reqs;
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
index 84983e0..bca06a5 100644
--- a/drivers/mmc/core/bus.c
+++ b/drivers/mmc/core/bus.c
@@ -246,6 +246,8 @@
card->dev.release = mmc_release_card;
card->dev.type = type;
+ spin_lock_init(&card->wr_pack_stats.lock);
+
return card;
}
@@ -359,6 +361,8 @@
device_del(&card->dev);
}
+ kfree(card->wr_pack_stats.packing_events);
+
put_device(&card->dev);
}
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c
index c1b0405..0efcf9d 100644
--- a/drivers/mmc/core/debugfs.c
+++ b/drivers/mmc/core/debugfs.c
@@ -287,6 +287,164 @@
.llseek = default_llseek,
};
+static int mmc_wr_pack_stats_open(struct inode *inode, struct file *filp)
+{
+ struct mmc_card *card = inode->i_private;
+
+ filp->private_data = card;
+ card->wr_pack_stats.print_in_read = 1;
+ return 0;
+}
+
+#define TEMP_BUF_SIZE 256
+static ssize_t mmc_wr_pack_stats_read(struct file *filp, char __user *ubuf,
+ size_t cnt, loff_t *ppos)
+{
+ struct mmc_card *card = filp->private_data;
+ struct mmc_wr_pack_stats *pack_stats;
+ int i;
+ int max_num_of_packed_reqs = 0;
+ char *temp_buf;
+
+ if (!card)
+ return cnt;
+
+ if (!card->wr_pack_stats.print_in_read)
+ return 0;
+
+ if (!card->wr_pack_stats.enabled) {
+ pr_info("%s: write packing statistics are disabled\n",
+ mmc_hostname(card->host));
+ goto exit;
+ }
+
+ pack_stats = &card->wr_pack_stats;
+
+ if (!pack_stats->packing_events) {
+ pr_info("%s: NULL packing_events\n", mmc_hostname(card->host));
+ goto exit;
+ }
+
+ max_num_of_packed_reqs = card->ext_csd.max_packed_writes;
+
+ temp_buf = kmalloc(TEMP_BUF_SIZE, GFP_KERNEL);
+ if (!temp_buf)
+ goto exit;
+
+ spin_lock(&pack_stats->lock);
+
+ snprintf(temp_buf, TEMP_BUF_SIZE, "%s: write packing statistics:\n",
+ mmc_hostname(card->host));
+ strlcat(ubuf, temp_buf, cnt);
+
+ for (i = 1 ; i <= max_num_of_packed_reqs ; ++i) {
+ if (pack_stats->packing_events[i]) {
+ snprintf(temp_buf, TEMP_BUF_SIZE,
+ "%s: Packed %d reqs - %d times\n",
+ mmc_hostname(card->host), i,
+ pack_stats->packing_events[i]);
+ strlcat(ubuf, temp_buf, cnt);
+ }
+ }
+
+ snprintf(temp_buf, TEMP_BUF_SIZE,
+ "%s: stopped packing due to the following reasons:\n",
+ mmc_hostname(card->host));
+ strlcat(ubuf, temp_buf, cnt);
+
+ if (pack_stats->pack_stop_reason[EXCEEDS_SEGMENTS]) {
+ snprintf(temp_buf, TEMP_BUF_SIZE,
+ "%s: %d times: exceed max num of segments\n",
+ mmc_hostname(card->host),
+ pack_stats->pack_stop_reason[EXCEEDS_SEGMENTS]);
+ strlcat(ubuf, temp_buf, cnt);
+ }
+ if (pack_stats->pack_stop_reason[EXCEEDS_SECTORS]) {
+ snprintf(temp_buf, TEMP_BUF_SIZE,
+ "%s: %d times: exceed max num of sectors\n",
+ mmc_hostname(card->host),
+ pack_stats->pack_stop_reason[EXCEEDS_SECTORS]);
+ strlcat(ubuf, temp_buf, cnt);
+ }
+ if (pack_stats->pack_stop_reason[WRONG_DATA_DIR]) {
+ snprintf(temp_buf, TEMP_BUF_SIZE,
+ "%s: %d times: wrong data direction\n",
+ mmc_hostname(card->host),
+ pack_stats->pack_stop_reason[WRONG_DATA_DIR]);
+ strlcat(ubuf, temp_buf, cnt);
+ }
+ if (pack_stats->pack_stop_reason[FLUSH_OR_DISCARD]) {
+ snprintf(temp_buf, TEMP_BUF_SIZE,
+ "%s: %d times: flush or discard\n",
+ mmc_hostname(card->host),
+ pack_stats->pack_stop_reason[FLUSH_OR_DISCARD]);
+ strlcat(ubuf, temp_buf, cnt);
+ }
+ if (pack_stats->pack_stop_reason[EMPTY_QUEUE]) {
+ snprintf(temp_buf, TEMP_BUF_SIZE,
+ "%s: %d times: empty queue\n",
+ mmc_hostname(card->host),
+ pack_stats->pack_stop_reason[EMPTY_QUEUE]);
+ strlcat(ubuf, temp_buf, cnt);
+ }
+ if (pack_stats->pack_stop_reason[REL_WRITE]) {
+ snprintf(temp_buf, TEMP_BUF_SIZE,
+ "%s: %d times: rel write\n",
+ mmc_hostname(card->host),
+ pack_stats->pack_stop_reason[REL_WRITE]);
+ strlcat(ubuf, temp_buf, cnt);
+ }
+ if (pack_stats->pack_stop_reason[THRESHOLD]) {
+ snprintf(temp_buf, TEMP_BUF_SIZE,
+ "%s: %d times: Threshold\n",
+ mmc_hostname(card->host),
+ pack_stats->pack_stop_reason[THRESHOLD]);
+ strlcat(ubuf, temp_buf, cnt);
+ }
+
+ spin_unlock(&pack_stats->lock);
+
+ kfree(temp_buf);
+
+ pr_info("%s", ubuf);
+
+exit:
+ if (card->wr_pack_stats.print_in_read == 1) {
+ card->wr_pack_stats.print_in_read = 0;
+ return strnlen(ubuf, cnt);
+ }
+
+ return 0;
+}
+
+static ssize_t mmc_wr_pack_stats_write(struct file *filp,
+ const char __user *ubuf, size_t cnt,
+ loff_t *ppos)
+{
+ struct mmc_card *card = filp->private_data;
+ int value;
+
+ if (!card)
+ return cnt;
+
+ sscanf(ubuf, "%d", &value);
+ if (value) {
+ mmc_blk_init_packed_statistics(card);
+ } else {
+ spin_lock(&card->wr_pack_stats.lock);
+ card->wr_pack_stats.enabled = false;
+ spin_unlock(&card->wr_pack_stats.lock);
+ }
+
+ return cnt;
+}
+
+static const struct file_operations mmc_dbg_wr_pack_stats_fops = {
+ .open = mmc_wr_pack_stats_open,
+ .read = mmc_wr_pack_stats_read,
+ .write = mmc_wr_pack_stats_write,
+};
+
void mmc_add_card_debugfs(struct mmc_card *card)
{
struct mmc_host *host = card->host;
@@ -319,6 +477,12 @@
&mmc_dbg_ext_csd_fops))
goto err;
+ if (mmc_card_mmc(card) && (card->ext_csd.rev >= 6) &&
+ (card->host->caps2 & MMC_CAP2_PACKED_WR))
+ if (!debugfs_create_file("wr_pack_stats", S_IRUSR, root, card,
+ &mmc_dbg_wr_pack_stats_fops))
+ goto err;
+
return;
err:
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 6178097..169fe68 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -1223,6 +1223,24 @@
} else {
card->ext_csd.packed_event_en = 1;
}
+
+ }
+
+ if (!oldcard) {
+ if ((host->caps2 & MMC_CAP2_PACKED_CMD) &&
+ (card->ext_csd.max_packed_writes > 0)) {
+ /*
+ * We would like to keep the statistics in an index
+ * that equals the num of packed requests
+ * (1 to max_packed_writes)
+ */
+ card->wr_pack_stats.packing_events = kzalloc(
+ (card->ext_csd.max_packed_writes + 1) *
+ sizeof(*card->wr_pack_stats.packing_events),
+ GFP_KERNEL);
+ if (!card->wr_pack_stats.packing_events)
+ goto free_card;
+ }
}
if (!oldcard)
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 927efdd..40f0f33 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -5022,6 +5022,8 @@
mmc->caps2 |= MMC_CAP2_PACKED_WR;
mmc->caps2 |= MMC_CAP2_PACKED_WR_CONTROL;
mmc->caps2 |= (MMC_CAP2_BOOTPART_NOACC | MMC_CAP2_DETECT_ON_ERR);
+ mmc->caps2 |= MMC_CAP2_SANITIZE;
+
if (pdev->dev.of_node) {
if (of_get_property((&pdev->dev)->of_node,
"qcom,sdcc-hs200", NULL))
diff --git a/drivers/platform/msm/sps/bam.c b/drivers/platform/msm/sps/bam.c
index d7edb82..cf98f68 100644
--- a/drivers/platform/msm/sps/bam.c
+++ b/drivers/platform/msm/sps/bam.c
@@ -649,6 +649,8 @@
u32 cfg_bits = 0xffffffff & ~(1 << 11);
u32 ver = 0;
+ SPS_DBG2("sps:%s:bam=0x%x(va).ee=%d.", __func__, (u32) base, ee);
+
ver = bam_read_reg_field(base, REVISION, BAM_REVISION);
if ((ver < BAM_MIN_VERSION) || (ver > BAM_MAX_VERSION)) {
@@ -743,6 +745,8 @@
u32 mask;
u32 pipe;
+ SPS_DBG2("sps:%s:bam=0x%x(va).", __func__, (u32) base);
+
/*
* Discover the hardware version number and the number of pipes
* supported by this BAM
@@ -782,6 +786,8 @@
{
u32 ver = 0;
+ SPS_DBG2("sps:%s:bam=0x%x(va).", __func__, (u32) base);
+
if (!bam_read_reg_field(base, CTRL, BAM_EN)) {
SPS_ERR("sps:%s:bam 0x%x(va) is not enabled.\n",
__func__, (u32) base);
@@ -813,6 +819,8 @@
*/
void bam_exit(void *base, u32 ee)
{
+ SPS_DBG2("sps:%s:bam=0x%x(va).ee=%d.", __func__, (u32) base, ee);
+
bam_write_reg_field(base, IRQ_SRCS_MSK_EE(ee), BAM_IRQ, 0);
bam_write_reg(base, IRQ_EN, 0);
@@ -899,6 +907,8 @@
int bam_pipe_init(void *base, u32 pipe, struct bam_pipe_parameters *param,
u32 ee)
{
+ SPS_DBG2("sps:%s:bam=0x%x(va).pipe=%d.", __func__, (u32) base, pipe);
+
/* Reset the BAM pipe */
bam_write_reg(base, P_RST(pipe), 1);
/* No delay needed */
@@ -967,6 +977,8 @@
*/
void bam_pipe_exit(void *base, u32 pipe, u32 ee)
{
+ SPS_DBG2("sps:%s:bam=0x%x(va).pipe=%d.", __func__, (u32) base, pipe);
+
bam_write_reg(base, P_IRQ_EN(pipe), 0);
/* Disable the Pipe Interrupt at the BAM level */
@@ -982,6 +994,8 @@
*/
void bam_pipe_enable(void *base, u32 pipe)
{
+ SPS_DBG2("sps:%s:bam=0x%x(va).pipe=%d.", __func__, (u32) base, pipe);
+
bam_write_reg_field(base, P_CTRL(pipe), P_EN, 1);
}
@@ -991,6 +1005,8 @@
*/
void bam_pipe_disable(void *base, u32 pipe)
{
+ SPS_DBG2("sps:%s:bam=0x%x(va).pipe=%d.", __func__, (u32) base, pipe);
+
bam_write_reg_field(base, P_CTRL(pipe), P_EN, 0);
}
@@ -1010,6 +1026,8 @@
void bam_pipe_set_irq(void *base, u32 pipe, enum bam_enable irq_en,
u32 src_mask, u32 ee)
{
+ SPS_DBG2("sps:%s:bam=0x%x(va).pipe=%d.", __func__, (u32) base, pipe);
+
bam_write_reg(base, P_IRQ_EN(pipe), src_mask);
bam_write_reg_field(base, IRQ_SRCS_MSK_EE(ee), (1 << pipe), irq_en);
}
@@ -1287,7 +1305,7 @@
"BAM_P_IRQ_STTS: 0x%x\n"
"BAM_P_IRQ_STTS_P_TRNSFR_END_IRQ: 0x%x\n"
"BAM_P_IRQ_STTS_P_PRCSD_DESC_IRQ: 0x%x\n"
- "BAM_P_IRQ_EN: %d\n"
+ "BAM_P_IRQ_EN: 0x%x\n"
"BAM_P_PRDCR_SDBNDn_BAM_P_BYTES_FREE: 0x%x (%d)\n"
"BAM_P_CNSMR_SDBNDn_BAM_P_BYTES_AVAIL: 0x%x (%d)\n"
"BAM_P_SW_DESC_OFST: 0x%x\n"
@@ -1335,4 +1353,50 @@
bam_read_reg_field(base, P_EVNT_GEN_TRSHLD(pipe),
P_EVNT_GEN_TRSHLD_P_TRSHLD));
}
+
+/* output descriptor FIFO of a pipe */
+void print_bam_pipe_desc_fifo(void *virt_addr, u32 pipe_index)
+{
+ void *base = virt_addr;
+ u32 pipe = pipe_index;
+ u32 desc_fifo_addr;
+ u32 desc_fifo_size;
+ u32 *desc_fifo;
+ int i;
+
+ if (base == NULL)
+ return;
+
+ desc_fifo_addr = bam_read_reg(base, P_DESC_FIFO_ADDR(pipe));
+ desc_fifo_size = bam_read_reg_field(base, P_FIFO_SIZES(pipe),
+ P_DESC_FIFO_SIZE);
+
+ if (desc_fifo_addr == 0) {
+ SPS_ERR("sps:%s:desc FIFO address of Pipe %d is NULL.\n",
+ __func__, pipe);
+ return;
+ } else if (desc_fifo_size == 0) {
+ SPS_ERR("sps:%s:desc FIFO size of Pipe %d is 0.\n",
+ __func__, pipe);
+ return;
+ }
+
+ SPS_INFO("\nsps:----- descriptor FIFO of Pipe %d -----\n", pipe);
+
+ SPS_INFO("BAM_P_DESC_FIFO_ADDR: 0x%x\n"
+ "BAM_P_DESC_FIFO_SIZE: 0x%x (%d)\n\n",
+ desc_fifo_addr, desc_fifo_size, desc_fifo_size);
+
+ desc_fifo = (u32 *) phys_to_virt(desc_fifo_addr);
+
+ SPS_INFO("-------------------- begin of FIFO --------------------\n");
+
+ for (i = 0; i < desc_fifo_size; i += 0x10)
+ SPS_INFO("addr 0x%x: 0x%x, 0x%x, 0x%x, 0x%x.\n",
+ desc_fifo_addr + i,
+ desc_fifo[i / 4], desc_fifo[(i / 4) + 1],
+ desc_fifo[(i / 4) + 2], desc_fifo[(i / 4) + 3]);
+
+ SPS_INFO("-------------------- end of FIFO --------------------\n");
+}
#endif
diff --git a/drivers/platform/msm/sps/sps.c b/drivers/platform/msm/sps/sps.c
index 6d61bb6..fbaea09 100644
--- a/drivers/platform/msm/sps/sps.c
+++ b/drivers/platform/msm/sps/sps.c
@@ -327,6 +327,26 @@
print_bam_pipe_selected_reg(vir_addr, 4);
print_bam_pipe_selected_reg(vir_addr, 5);
break;
+ case 6: /* output desc FIFO of all active pipes */
+ for (i = 0; i < num_pipes; i++)
+ print_bam_pipe_desc_fifo(vir_addr, i);
+ break;
+ case 7: /* output desc FIFO of some pipes */
+ print_bam_pipe_desc_fifo(vir_addr, 4);
+ print_bam_pipe_desc_fifo(vir_addr, 5);
+ break;
+ case 8: /* output selected registers and valid desc FIFO of all pipes */
+ for (i = 0; i < num_pipes; i++) {
+ print_bam_pipe_selected_reg(vir_addr, i);
+ print_bam_pipe_desc_fifo(vir_addr, i);
+ }
+ break;
+ case 9: /* output selected registers and desc FIFO of some pipes */
+ print_bam_pipe_selected_reg(vir_addr, 4);
+ print_bam_pipe_desc_fifo(vir_addr, 4);
+ print_bam_pipe_selected_reg(vir_addr, 5);
+ print_bam_pipe_desc_fifo(vir_addr, 5);
+ break;
default:
pr_info("sps:no dump option is chosen yet.");
}
@@ -455,7 +475,7 @@
struct sps_bam_props bamdma_props = {0};
#endif
- SPS_DBG("sps:sps_device_init");
+ SPS_DBG2("sps:%s.", __func__);
success = false;
@@ -581,6 +601,8 @@
*/
static int sps_client_init(struct sps_pipe *client)
{
+ SPS_DBG("sps:%s.", __func__);
+
if (client == NULL)
return -EINVAL;
@@ -609,6 +631,8 @@
*/
static int sps_client_de_init(struct sps_pipe *client)
{
+ SPS_DBG("sps:%s.", __func__);
+
if (client->client_state != SPS_STATE_DISCONNECT) {
SPS_ERR("sps:De-init client in connected state: 0x%x",
client->client_state);
@@ -637,6 +661,8 @@
{
struct sps_bam *bam;
+ SPS_DBG("sps:%s.", __func__);
+
list_for_each_entry(bam, &sps->bams_q, list) {
if (bam->props.phys_addr == phys_addr)
return bam;
@@ -662,6 +688,8 @@
{
struct sps_bam *bam;
+ SPS_DBG("sps:%s.", __func__);
+
if (handle == NULL) {
SPS_ERR("sps:%s:handle is NULL.\n", __func__);
return SPS_ERROR;
@@ -697,6 +725,8 @@
int sps_setup_bam2bam_fifo(struct sps_mem_buffer *mem_buffer,
u32 addr, u32 size, int use_offset)
{
+ SPS_DBG("sps:%s.", __func__);
+
if ((mem_buffer == NULL) || (size == 0)) {
SPS_ERR("sps:invalid buffer address or size.");
return SPS_ERROR;
@@ -746,6 +776,8 @@
{
struct sps_bam *bam;
+ SPS_DBG("sps:%s.", __func__);
+
if (h == SPS_DEV_HANDLE_MEM || h == SPS_DEV_HANDLE_INVALID)
return NULL;
@@ -821,6 +853,8 @@
struct sps_bam *bam;
int result;
+ SPS_DBG2("sps:%s.", __func__);
+
if (h == NULL) {
SPS_ERR("sps:%s:pipe is NULL.\n", __func__);
return SPS_ERROR;
@@ -915,6 +949,8 @@
struct sps_bam *bam;
int result;
+ SPS_DBG2("sps:%s.", __func__);
+
if (pipe == NULL) {
SPS_ERR("sps:Invalid pipe.");
return SPS_ERROR;
@@ -1292,6 +1328,8 @@
{
struct sps_pipe *pipe = h;
+ SPS_DBG("sps:%s.", __func__);
+
if (h == NULL) {
SPS_ERR("sps:%s:pipe is NULL.\n", __func__);
return SPS_ERROR;
@@ -1352,6 +1390,8 @@
struct sps_bam *bam;
int result;
+ SPS_DBG("sps:%s.", __func__);
+
if (h == NULL) {
SPS_ERR("sps:%s:pipe is NULL.\n", __func__);
return SPS_ERROR;
@@ -1401,6 +1441,8 @@
int sps_alloc_mem(struct sps_pipe *h, enum sps_mem mem,
struct sps_mem_buffer *mem_buffer)
{
+ SPS_DBG("sps:%s.", __func__);
+
if (h == NULL) {
SPS_ERR("sps:%s:pipe is NULL.\n", __func__);
return SPS_ERROR;
@@ -1437,6 +1479,8 @@
*/
int sps_free_mem(struct sps_pipe *h, struct sps_mem_buffer *mem_buffer)
{
+ SPS_DBG("sps:%s.", __func__);
+
if (h == NULL) {
SPS_ERR("sps:%s:pipe is NULL.\n", __func__);
return SPS_ERROR;
@@ -1500,6 +1544,8 @@
int ok;
int result;
+ SPS_DBG2("sps:%s.", __func__);
+
if (bam_props == NULL) {
SPS_ERR("sps:%s:bam_props is NULL.\n", __func__);
return SPS_ERROR;
@@ -1647,6 +1693,8 @@
{
struct sps_bam *bam;
+ SPS_DBG2("sps:%s.", __func__);
+
if (dev_handle == 0) {
SPS_ERR("sps:%s:device handle should not be 0.\n", __func__);
return SPS_ERROR;
@@ -1766,6 +1814,8 @@
{
struct sps_pipe *ctx = NULL;
+ SPS_DBG("sps:%s.", __func__);
+
ctx = kzalloc(sizeof(struct sps_pipe), GFP_KERNEL);
if (ctx == NULL) {
SPS_ERR("sps:Fail to allocate pipe context.");
@@ -1786,6 +1836,8 @@
{
int res;
+ SPS_DBG("sps:%s.", __func__);
+
if (ctx == NULL) {
SPS_ERR("sps:%s:pipe is NULL.\n", __func__);
return SPS_ERROR;
@@ -1808,6 +1860,8 @@
struct resource *resource;
struct msm_sps_platform_data *pdata;
+ SPS_DBG("sps:%s.", __func__);
+
pdata = pdev->dev.platform_data;
if (pdata == NULL) {
@@ -1870,6 +1924,8 @@
#ifdef CONFIG_SPS_SUPPORT_BAMDMA
struct resource *resource;
+ SPS_DBG("sps:%s.", __func__);
+
if (of_property_read_u32((&pdev->dev)->of_node,
"qcom,bam-dma-res-pipes",
&sps->bamdma_restricted_pipes)) {
@@ -1920,7 +1976,7 @@
{
int ret;
- SPS_DBG("sps:msm_sps_probe.");
+ SPS_DBG2("sps:%s.", __func__);
if (pdev->dev.of_node) {
if (get_device_tree_data(pdev)) {
diff --git a/drivers/platform/msm/sps/sps_bam.c b/drivers/platform/msm/sps/sps_bam.c
index e0289ad..245ccd2 100644
--- a/drivers/platform/msm/sps/sps_bam.c
+++ b/drivers/platform/msm/sps/sps_bam.c
@@ -221,7 +221,7 @@
IRQF_TRIGGER_HIGH, "sps", dev);
if (result) {
- SPS_ERR("sps:Failed to register BAM 0x%x IRQ %d",
+ SPS_ERR("sps:Failed to enable BAM 0x%x IRQ %d",
BAM_ID(dev), dev->props.irq);
return SPS_ERROR;
}
diff --git a/drivers/platform/msm/sps/spsi.h b/drivers/platform/msm/sps/spsi.h
index 8e4907b..e8ab832 100644
--- a/drivers/platform/msm/sps/spsi.h
+++ b/drivers/platform/msm/sps/spsi.h
@@ -193,6 +193,9 @@
/* output the content of selected BAM pipe registers */
void print_bam_pipe_selected_reg(void *, u32);
+
+/* output descriptor FIFO of a pipe */
+void print_bam_pipe_desc_fifo(void *, u32);
#endif
/**
diff --git a/drivers/video/msm/lvds.c b/drivers/video/msm/lvds.c
index 18225fb..88c24b9 100644
--- a/drivers/video/msm/lvds.c
+++ b/drivers/video/msm/lvds.c
@@ -65,28 +65,14 @@
usleep(1000);
/* LVDS PHY PLL configuration */
- MDP_OUTP(MDP_BASE + 0xc3000, 0x08);
- MDP_OUTP(MDP_BASE + 0xc3004, 0x87);
+ MDP_OUTP(MDP_BASE + 0xc3004, 0x62);
MDP_OUTP(MDP_BASE + 0xc3008, 0x30);
- MDP_OUTP(MDP_BASE + 0xc300c, 0x06);
- MDP_OUTP(MDP_BASE + 0xc3014, 0x20);
- MDP_OUTP(MDP_BASE + 0xc3018, 0x0F);
- MDP_OUTP(MDP_BASE + 0xc301c, 0x01);
+ MDP_OUTP(MDP_BASE + 0xc300c, 0xc4);
+ MDP_OUTP(MDP_BASE + 0xc3014, 0x10);
+ MDP_OUTP(MDP_BASE + 0xc3018, 0x05);
+ MDP_OUTP(MDP_BASE + 0xc301c, 0x62);
MDP_OUTP(MDP_BASE + 0xc3020, 0x41);
MDP_OUTP(MDP_BASE + 0xc3024, 0x0d);
- MDP_OUTP(MDP_BASE + 0xc3028, 0x07);
- MDP_OUTP(MDP_BASE + 0xc302c, 0x00);
- MDP_OUTP(MDP_BASE + 0xc3030, 0x1c);
- MDP_OUTP(MDP_BASE + 0xc3034, 0x01);
- MDP_OUTP(MDP_BASE + 0xc3038, 0x00);
- MDP_OUTP(MDP_BASE + 0xc3040, 0xC0);
- MDP_OUTP(MDP_BASE + 0xc3044, 0x00);
- MDP_OUTP(MDP_BASE + 0xc3048, 0x30);
- MDP_OUTP(MDP_BASE + 0xc304c, 0x00);
-
- MDP_OUTP(MDP_BASE + 0xc3000, 0x11);
- MDP_OUTP(MDP_BASE + 0xc3064, 0x05);
- MDP_OUTP(MDP_BASE + 0xc3050, 0x20);
MDP_OUTP(MDP_BASE + 0xc3000, 0x01);
/* Wait until LVDS PLL is locked and ready */
@@ -210,6 +196,10 @@
if (lvds_clk)
clk_disable_unprepare(lvds_clk);
+ MDP_OUTP(MDP_BASE + 0xc3100, 0x0);
+ MDP_OUTP(MDP_BASE + 0xc3000, 0x0);
+ usleep(10);
+
if (lvds_pdata && lvds_pdata->lcdc_power_save)
lvds_pdata->lcdc_power_save(0);
diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h
index e6dc795..a7161fe 100644
--- a/drivers/video/msm/mdp4.h
+++ b/drivers/video/msm/mdp4.h
@@ -48,12 +48,6 @@
OVERLAY_PERF_LEVEL4
};
-enum mdp4_overlay_status {
- MDP4_OVERLAY_TYPE_UNSET,
- MDP4_OVERLAY_TYPE_SET,
- MDP4_OVERLAY_TYPE_MAX
-};
-
typedef int (*cmd_fxn_t)(struct platform_device *pdev);
enum { /* display */
@@ -727,8 +721,6 @@
void mdp4_overlay_dsi_video_wait4vsync(struct msm_fb_data_type *mfd);
void mdp4_primary_vsync_dsi_video(void);
uint32_t mdp4_ss_table_value(int8_t param, int8_t index);
-void mdp4_overlay_status_write(enum mdp4_overlay_status type, bool val);
-bool mdp4_overlay_status_read(enum mdp4_overlay_status type);
void mdp4_overlay_ctrl_db_reset(void);
int mdp4_overlay_writeback_on(struct platform_device *pdev);
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index c46c683..6d4e44b 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -198,19 +198,6 @@
}
}
-/* static array with index 0 for unset status and 1 for set status */
-static bool overlay_status[MDP4_OVERLAY_TYPE_MAX];
-
-void mdp4_overlay_status_write(enum mdp4_overlay_status type, bool val)
-{
- overlay_status[type] = val;
-}
-
-bool mdp4_overlay_status_read(enum mdp4_overlay_status type)
-{
- return overlay_status[type];
-}
-
void mdp4_overlay_ctrl_db_reset(void)
{
int i;
@@ -2517,12 +2504,6 @@
mdp4_stat.overlay_set[pipe->mixer_num]++;
- if (ctrl->panel_mode & MDP4_PANEL_MDDI) {
- if (mdp_hw_revision == MDP4_REVISION_V2_1 &&
- pipe->mixer_num == MDP4_MIXER0)
- mdp4_overlay_status_write(MDP4_OVERLAY_TYPE_SET, true);
- }
-
if (ctrl->panel_mode & MDP4_PANEL_DTV &&
pipe->mixer_num == MDP4_MIXER1) {
u32 use_blt = mdp4_overlay_blt_enable(req, mfd, perf_level);
@@ -2640,9 +2621,6 @@
}
#else
if (ctrl->panel_mode & MDP4_PANEL_MDDI) {
- if (mdp_hw_revision == MDP4_REVISION_V2_1)
- mdp4_overlay_status_write(
- MDP4_OVERLAY_TYPE_UNSET, true);
if (mfd->panel_power_on)
mdp4_mddi_overlay_restore();
}
@@ -2749,7 +2727,7 @@
if (mfd->use_ov1_blt)
mdp4_overlay1_update_blt_mode(mfd);
- mdp4_overlay_dtv_wait_for_ov(mfd, pipe);
+ mdp4_overlay_dtv_wait4vsync();
mdp4_iommu_unmap(pipe);
mutex_unlock(&mfd->dma->ov_mutex);
diff --git a/drivers/video/msm/mdp4_overlay_mddi.c b/drivers/video/msm/mdp4_overlay_mddi.c
index 83959df..5aa5965 100644
--- a/drivers/video/msm/mdp4_overlay_mddi.c
+++ b/drivers/video/msm/mdp4_overlay_mddi.c
@@ -450,27 +450,6 @@
/* change mdp clk while mdp is idle` */
mdp4_set_perf_level();
- if (mdp_hw_revision == MDP4_REVISION_V2_1) {
- if (mdp4_overlay_status_read(MDP4_OVERLAY_TYPE_UNSET)) {
- uint32 data;
- data = inpdw(MDP_BASE + 0x0028);
- data &= ~0x0300; /* bit 8, 9, MASTER4 */
- if (mfd->fbi->var.xres == 540) /* qHD, 540x960 */
- data |= 0x0200;
- else
- data |= 0x0100;
- MDP_OUTP(MDP_BASE + 0x00028, data);
- mdp4_overlay_status_write(MDP4_OVERLAY_TYPE_UNSET,
- false);
- }
- if (mdp4_overlay_status_read(MDP4_OVERLAY_TYPE_SET)) {
- uint32 data;
- data = inpdw(MDP_BASE + 0x0028);
- data &= ~0x0300; /* bit 8, 9, MASTER4 */
- MDP_OUTP(MDP_BASE + 0x00028, data);
- mdp4_overlay_status_write(MDP4_OVERLAY_TYPE_SET, false);
- }
- }
mdp_enable_irq(MDP_OVERLAY0_TERM);
mfd->dma->busy = TRUE;
/* start OVERLAY pipe */
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
index b480b42..64d2976 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
@@ -1064,20 +1064,10 @@
void ddl_set_vidc_timeout(struct ddl_client_context *ddl)
{
- unsigned long core_clk_rate;
u32 vidc_time_out = 0;
- if (ddl->codec_data.decoder.idr_only_decoding) {
+ if (ddl->codec_data.decoder.idr_only_decoding)
vidc_time_out = 2 * DDL_VIDC_1080P_200MHZ_TIMEOUT_VALUE;
- } else {
- res_trk_get_clk_rate(&core_clk_rate);
- if (core_clk_rate == DDL_VIDC_1080P_48MHZ)
- vidc_time_out = DDL_VIDC_1080P_48MHZ_TIMEOUT_VALUE;
- else if (core_clk_rate == DDL_VIDC_1080P_133MHZ)
- vidc_time_out = DDL_VIDC_1080P_133MHZ_TIMEOUT_VALUE;
- else
- vidc_time_out = DDL_VIDC_1080P_200MHZ_TIMEOUT_VALUE;
- }
- DDL_MSG_HIGH("%s Video core time out value = 0x%x"
+ DDL_MSG_HIGH("%s Video core time out value = 0x%x",
__func__, vidc_time_out);
vidc_sm_set_video_core_timeout_value(
&ddl->shared_mem[ddl->command_channel], vidc_time_out);
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index c05134c..beb5470 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -176,6 +176,25 @@
#define SDIO_MAX_FUNCS 7
+enum mmc_packed_stop_reasons {
+ EXCEEDS_SEGMENTS = 0,
+ EXCEEDS_SECTORS,
+ WRONG_DATA_DIR,
+ FLUSH_OR_DISCARD,
+ EMPTY_QUEUE,
+ REL_WRITE,
+ THRESHOLD,
+ MAX_REASONS,
+};
+
+struct mmc_wr_pack_stats {
+ u32 *packing_events;
+ u32 pack_stop_reason[MAX_REASONS];
+ spinlock_t lock;
+ bool enabled;
+ bool print_in_read;
+};
+
/*
* MMC device
*/
@@ -246,6 +265,8 @@
unsigned int sd_bus_speed; /* Bus Speed Mode set for the card */
struct dentry *debugfs_root;
+
+ struct mmc_wr_pack_stats wr_pack_stats; /* packed commands stats*/
};
/*
@@ -448,4 +469,8 @@
extern void mmc_fixup_device(struct mmc_card *card,
const struct mmc_fixup *table);
+extern struct mmc_wr_pack_stats *mmc_blk_get_packed_statistics(
+ struct mmc_card *card);
+extern void mmc_blk_init_packed_statistics(struct mmc_card *card);
+
#endif
diff --git a/scripts/gcc-wrapper.py b/scripts/gcc-wrapper.py
index f7cb424..16c623c 100755
--- a/scripts/gcc-wrapper.py
+++ b/scripts/gcc-wrapper.py
@@ -44,8 +44,8 @@
"alignment.c:720",
"async.c:122",
"async.c:270",
- "block.c:880",
- "block.c:881",
+ "block.c:885",
+ "block.c:886",
"dir.c:43",
"dm.c:1053",
"dm.c:1080",