Merge "msm: bam_dmux: remove A2_DEFAULT_DESCRIPTORS"
diff --git a/arch/arm/boot/dts/msm8974-fluid.dts b/arch/arm/boot/dts/msm8974-fluid.dts
new file mode 100644
index 0000000..b1d467e
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974-fluid.dts
@@ -0,0 +1,366 @@
+/* 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.
+ */
+
+/dts-v1/;
+
+/include/ "msm8974.dtsi"
+/include/ "dsi-panel-toshiba-720p-video.dtsi"
+
+/ {
+ model = "Qualcomm MSM 8974 FLUID";
+ compatible = "qcom,msm8974-fluid", "qcom,msm8974";
+ qcom,msm-id = <126 3 0>;
+
+ serial@f991e000 {
+ status = "ok";
+ };
+
+ qcom,mdss_dsi@fd922800 {
+ qcom,mdss_dsi_toshiba_720p_video {
+ status = "ok";
+ };
+ };
+
+ i2c@f9924000 {
+ atmel_mxt_ts@4a {
+ compatible = "atmel,mxt-ts";
+ reg = <0x4a>;
+ interrupt-parent = <&msmgpio>;
+ interrupts = <61 0x2>;
+ vdd_ana-supply = <&pm8941_l18>;
+ vcc_i2c-supply = <&pm8941_lvs1>;
+ atmel,reset-gpio = <&msmgpio 60 0x00>;
+ atmel,irq-gpio = <&msmgpio 61 0x00>;
+ atmel,panel-coords = <0 0 760 1424>;
+ atmel,display-coords = <0 0 720 1280>;
+ atmel,i2c-pull-up = <1>;
+ atmel,cfg_1 {
+ atmel,family-id = <0x82>;
+ atmel,variant-id = <0x19>;
+ atmel,version = <0x10>;
+ atmel,build = <0xaa>;
+ atmel,config = [
+ /* Object 6, Instance = 0 */
+ 00 00 00 00 00 00
+ /* Object 38, Instance = 0 */
+ 15 00 02 10 08 0C 00 00
+ /* Object 7, Instance = 0 */
+ FF FF 32 03
+ /* Object 8, Instance = 0 */
+ 0F 00 0A 0A 00 00 0A 00 00 00
+ /* Object 9, Instance = 0 */
+ 83 00 00 18 0E 00 70 32 02 01
+ 00 03 01 01 05 0A 0A 0A 90 05
+ F8 02 00 00 0F 0F 00 00 48 2D
+ 07 0C 00 00 00 00
+ /* Object 15, Instance = 0 */
+ 00 00 00 00 00 00 00 00 00 00
+ 00
+ /* Object 18, Instance = 0 */
+ 00 00
+ /* Object 19, Instance = 0 */
+ 00 00 00 00 00 00
+ /* Object 23, Instance = 0 */
+ 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00
+ /* Object 25, Instance = 0 */
+ 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00
+ /* Object 40, Instance = 0 */
+ 00 00 00 00 00
+ /* Object 42, Instance = 0 */
+ 00 00 00 00 00 00 00 00 00 00
+ /* Object 46, Instance = 0 */
+ 00 00 10 10 00 00 03 00 00 01
+ /* Object 47, Instance = 0 */
+ 08 0A 28 0A 02 0A 00 8C 00 20
+ 00 00 00
+ /* Object 55, Instance = 0 */
+ 00 00 00 00 00 00
+ /* Object 56, Instance = 0 */
+ 03 00 01 18 05 05 05 05 05 05
+ 05 05 05 05 05 05 05 05 05 05
+ 05 05 05 05 05 05 05 05 00 00
+ 00 00 00 00 00 00 00 00 00 00
+ 00 00
+ /* Object 57, Instance = 0 */
+ 00 00 00
+ /* Object 61, Instance = 0 */
+ 00 00 00 00 00
+ /* Object 61, Instance = 1 */
+ 00 00 00 00 00
+ /* Object 62, Instance = 0 */
+ 7F 03 00 16 00 00 00 00 00 00
+ 04 08 10 18 05 00 0A 05 05 50
+ 14 19 34 1A 64 00 00 04 40 00
+ 00 00 00 00 30 32 02 00 01 00
+ 05 00 00 00 00 00 00 00 00 00
+ 00 00 0C 00
+ ];
+ };
+ };
+ };
+
+ gpio_keys {
+ compatible = "gpio-keys";
+
+ camera_snapshot {
+ label = "camera_snapshot";
+ gpios = <&pm8941_gpios 3 0x1>;
+ linux,input-type = <1>;
+ linux,code = <0x2fe>;
+ gpio-key,wakeup;
+ debounce-interval = <15>;
+ };
+
+ camera_focus {
+ label = "camera_focus";
+ gpios = <&pm8941_gpios 4 0x1>;
+ linux,input-type = <1>;
+ linux,code = <0x210>;
+ gpio-key,wakeup;
+ debounce-interval = <15>;
+ };
+
+ vol_up {
+ label = "volume_up";
+ gpios = <&pm8941_gpios 5 0x1>;
+ linux,input-type = <1>;
+ linux,code = <115>;
+ gpio-key,wakeup;
+ debounce-interval = <15>;
+ };
+ };
+
+ spi@f9923000 {
+ ethernet-switch@2 {
+ compatible = "micrel,ks8851";
+ reg = <2>;
+ interrupt-parent = <&msmgpio>;
+ interrupts = <94 0>;
+ spi-max-frequency = <4800000>;
+ rst-gpio = <&pm8941_mpps 6 0>;
+ vdd-io-supply = <&spi_eth_vreg>;
+ vdd-phy-supply = <&spi_eth_vreg>;
+ };
+ };
+};
+
+&sdcc1 {
+ qcom,sdcc-bus-width = <4>;
+};
+
+&sdcc2 {
+ #address-cells = <0>;
+ interrupt-parent = <&sdcc2>;
+ interrupts = <0 1 2>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0xffffffff>;
+ interrupt-map = <0 &intc 0 125 0
+ 1 &intc 0 220 0
+ 2 &msmgpio 62 0x3>;
+ interrupt-names = "core_irq", "bam_irq", "status_irq";
+ cd-gpios = <&msmgpio 62 0x1>;
+};
+
+&pm8941_gpios {
+ gpio@c000 { /* GPIO 1 */
+ };
+
+ gpio@c100 { /* GPIO 2 */
+ };
+
+ gpio@c200 { /* GPIO 3 */
+ qcom,mode = <0>;
+ qcom,pull = <0>;
+ qcom,vin-sel = <2>;
+ qcom,select = <0>;
+ };
+
+ gpio@c300 { /* GPIO 4 */
+ qcom,mode = <0>;
+ qcom,pull = <0>;
+ qcom,vin-sel = <2>;
+ qcom,select = <0>;
+ };
+
+ gpio@c400 { /* GPIO 5 */
+ qcom,mode = <0>;
+ qcom,pull = <0>;
+ qcom,vin-sel = <2>;
+ qcom,select = <0>;
+ };
+
+ gpio@c500 { /* GPIO 6 */
+ };
+
+ gpio@c600 { /* GPIO 7 */
+ };
+
+ gpio@c700 { /* GPIO 8 */
+ };
+
+ gpio@c800 { /* GPIO 9 */
+ };
+
+ gpio@c900 { /* GPIO 10 */
+ };
+
+ gpio@ca00 { /* GPIO 11 */
+ };
+
+ gpio@cb00 { /* GPIO 12 */
+ };
+
+ gpio@cc00 { /* GPIO 13 */
+ };
+
+ gpio@cd00 { /* GPIO 14 */
+ };
+
+ gpio@ce00 { /* GPIO 15 */
+ qcom,mode = <1>;
+ qcom,output-type = <0>;
+ qcom,pull = <5>;
+ qcom,vin-sel = <2>;
+ qcom,out-strength = <3>;
+ qcom,src-select = <2>;
+ qcom,master-en = <1>;
+ };
+
+ gpio@cf00 { /* GPIO 16 */
+ };
+
+ gpio@d000 { /* GPIO 17 */
+ };
+
+ gpio@d100 { /* GPIO 18 */
+ };
+
+ gpio@d200 { /* GPIO 19 */
+ qcom,mode = <1>; /* QPNP_PIN_MODE_DIG_OUT */
+ qcom,output-type = <0>; /* QPNP_PIN_OUT_BUF_CMOS */
+ qcom,pull = <5>; /* QPNP_PIN_PULL_NO */
+ qcom,vin-sel = <2>; /* QPNP_PIN_VIN2 */
+ qcom,out-strength = <2>; /* QPNP_PIN_OUT_STRENGTH_MED */
+ qcom,src-select = <0>; /* QPNP_PIN_SEL_FUNC_CONSTANT */
+ qcom,master-en = <1>;
+ };
+
+ gpio@d300 { /* GPIO 20 */
+ };
+
+ gpio@d400 { /* GPIO 21 */
+ };
+
+ gpio@d500 { /* GPIO 22 */
+ };
+
+ gpio@d600 { /* GPIO 23 */
+ };
+
+ gpio@d700 { /* GPIO 24 */
+ };
+
+ gpio@d800 { /* GPIO 25 */
+ };
+
+ gpio@d900 { /* GPIO 26 */
+ };
+
+ gpio@da00 { /* GPIO 27 */
+ };
+
+ gpio@db00 { /* GPIO 28 */
+ };
+
+ gpio@dc00 { /* GPIO 29 */
+ qcom,pull = <0>; /* set to default pull */
+ qcom,master-en = <1>;
+ qcom,vin-sel = <2>; /* select 1.8 V source */
+ };
+
+ gpio@dd00 { /* GPIO 30 */
+ };
+
+ gpio@de00 { /* GPIO 31 */
+ };
+
+ gpio@df00 { /* GPIO 32 */
+ };
+
+ gpio@e000 { /* GPIO 33 */
+ };
+
+ gpio@e100 { /* GPIO 34 */
+ };
+
+ gpio@e200 { /* GPIO 35 */
+ };
+
+ gpio@e300 { /* GPIO 36 */
+ };
+};
+
+&pm8941_mpps {
+
+ mpp@a000 { /* MPP 1 */
+ };
+
+ mpp@a100 { /* MPP 2 */
+ };
+
+ mpp@a200 { /* MPP 3 */
+ };
+
+ mpp@a300 { /* MPP 4 */
+ };
+
+ mpp@a400 { /* MPP 5 */
+ /* SPI_ETH config */
+ qcom,mode = <1>; /* DIG_OUT */
+ qcom,output-type = <0>; /* CMOS */
+ qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
+ qcom,src-select = <0>; /* CONSTANT */
+ qcom,master-en = <1>; /* ENABLE MPP */
+ };
+
+ mpp@a500 { /* MPP 6 */
+ /* SPI_ETH_RST config */
+ qcom,mode = <1>; /* DIG_OUT */
+ qcom,output-type = <0>; /* CMOS */
+ qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
+ qcom,src-select = <0>; /* CONSTANT */
+ qcom,master-en = <1>; /* ENABLE MPP */
+ };
+
+ mpp@a600 { /* MPP 7 */
+ };
+
+ mpp@a700 { /* MPP 8 */
+ };
+};
+
+&pm8841_mpps {
+
+ mpp@a000 { /* MPP 1 */
+ };
+
+ mpp@a100 { /* MPP 2 */
+ };
+
+ mpp@a200 { /* MPP 3 */
+ };
+
+ mpp@a300 { /* MPP 4 */
+ };
+};
diff --git a/arch/arm/boot/dts/msm8974-mdss.dtsi b/arch/arm/boot/dts/msm8974-mdss.dtsi
index ee5836c..ca98706 100644
--- a/arch/arm/boot/dts/msm8974-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8974-mdss.dtsi
@@ -18,6 +18,8 @@
reg-names = "mdp_phys", "vbif_phys";
interrupts = <0 72 0>;
vdd-supply = <&gdsc_mdss>;
+ qcom,memory-reservation-type = "EBI1"; /* reserve EBI memory */
+ qcom,memory-reservation-size = <0x800000>; /* size 8MB */
};
mdss_dsi: qcom,mdss_dsi@fd922800 {
diff --git a/arch/arm/boot/dts/msm8974-mtp.dts b/arch/arm/boot/dts/msm8974-mtp.dts
index e183d04..00aec9f 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dts
+++ b/arch/arm/boot/dts/msm8974-mtp.dts
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -18,7 +18,7 @@
/ {
model = "Qualcomm MSM 8974 MTP";
compatible = "qcom,msm8974-mtp", "qcom,msm8974";
- qcom,msm-id = <126 8 0>, <126 3 0>;
+ qcom,msm-id = <126 8 0>;
serial@f991e000 {
status = "ok";
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 157f159..2020422 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -1909,7 +1909,7 @@
config MSM_PIL_QDSP6V3
tristate "QDSP6v3 (Hexagon) Boot Support"
- depends on MSM_PIL
+ depends on MSM_PIL && MSM_SUBSYSTEM_RESTART
help
Support for booting and shutting down QDSP6v3 processors (hexagon).
The QDSP6 is a low power DSP used in audio software applications.
@@ -1945,7 +1945,7 @@
config MSM_PIL_RIVA
tristate "RIVA (WCNSS) Boot Support"
- depends on MSM_PIL
+ depends on MSM_PIL && MSM_SUBSYSTEM_RESTART
help
Support for booting and shutting down the RIVA processor (WCNSS).
Riva is the wireless subsystem processor used in bluetooth, wireless
@@ -1984,8 +1984,8 @@
Venus is the Video subsystem processor used for video codecs.
config MSM_PIL_GSS
- tristate "GSS (Coretx A5) Boot Support"
- depends on MSM_PIL
+ tristate "GSS (Cortex A5) Boot Support"
+ depends on MSM_PIL && MSM_SUBSYSTEM_RESTART
help
Support for booting and shutting down Cortex A5 processors which run
GPS subsystem firmware.
@@ -2018,22 +2018,6 @@
lpass hardware watchdog interrupt lines and plugs into the subsystem
restart and PIL drivers. For MSM9615, it only supports a full chip reset.
-config MSM_WCNSS_SSR_8960
- tristate "MSM 8960 WCNSS restart module"
- depends on (ARCH_MSM8960)
- help
- This option enables the WCNSS restart module for MSM8960, which
- monitors WCNSS hardware watchdog interrupt lines and plugs WCNSS
- into the subsystem restart framework.
-
-config MSM_GSS_SSR_8064
- bool "MSM 8064 GSS restart driver"
- depends on (ARCH_APQ8064)
- help
- This option enables the gps subsystem restart driver for APQ8064, which monitors
- gss hardware watchdog interrupt lines and plugs into the subsystem
- restart and PIL drivers.
-
config MSM_MODEM_SSR_8974
bool "MSM 8974 Modem restart driver"
depends on (ARCH_MSM8974)
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 1b42d2d..7dece76 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -195,15 +195,12 @@
obj-y += subsystem_notif.o
obj-y += subsystem_restart.o
obj-y += ramdump.o
- obj-$(CONFIG_ARCH_MSM8X60) += lpass-8660.o
endif
obj-$(CONFIG_MSM_SYSMON_COMM) += sysmon.o
obj-$(CONFIG_MSM_MODEM_8960) += modem-8960.o
obj-$(CONFIG_MSM_MODEM_SSR_8974) += modem-ssr-8974.o
obj-$(CONFIG_MSM_LPASS_8960) += lpass-8960.o
obj-$(CONFIG_MSM_ADSP_SSR_8974) += adsp-8974.o
-obj-$(CONFIG_MSM_WCNSS_SSR_8960) += wcnss-ssr-8960.o
-obj-$(CONFIG_MSM_GSS_SSR_8064) += gss-8064.o
ifdef CONFIG_CPU_IDLE
obj-$(CONFIG_ARCH_APQ8064) += cpuidle.o
@@ -351,7 +348,7 @@
obj-$(CONFIG_ARCH_MSM8226) += gpiomux-v2.o gpiomux.o
obj-$(CONFIG_MSM_SLEEP_STATS_DEVICE) += idle_stats_device.o
-obj-$(CONFIG_MSM_DCVS) += msm_dcvs_scm.o msm_dcvs.o msm_dcvs_idle.o
+obj-$(CONFIG_MSM_DCVS) += msm_dcvs_scm.o msm_dcvs.o msm_dcvs_idle.o msm_mpdecision.o
obj-$(CONFIG_MSM_RUN_QUEUE_STATS) += msm_rq_stats.o
obj-$(CONFIG_MSM_SHOW_RESUME_IRQ) += msm_show_resume_irq.o
obj-$(CONFIG_BT_MSM_PINTEST) += btpintest.o
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index 32ef39f..7ba22f4 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -222,6 +222,7 @@
static void rx_timer_work_func(struct work_struct *work);
static DECLARE_WORK(rx_timer_work, rx_timer_work_func);
+static struct delayed_work queue_rx_work;
static struct workqueue_struct *bam_mux_rx_workqueue;
static struct workqueue_struct *bam_mux_tx_workqueue;
@@ -429,21 +430,27 @@
rx_len_cached = bam_rx_pool_len;
mutex_unlock(&bam_rx_pool_mutexlock);
- while (rx_len_cached < NUM_BUFFERS) {
+ while (bam_connection_is_active && rx_len_cached < NUM_BUFFERS) {
if (in_global_reset)
goto fail;
- info = kmalloc(sizeof(struct rx_pkt_info), GFP_KERNEL);
+ info = kmalloc(sizeof(struct rx_pkt_info),
+ GFP_NOWAIT | __GFP_NOWARN);
if (!info) {
- pr_err("%s: unable to alloc rx_pkt_info\n", __func__);
+ DMUX_LOG_KERR(
+ "%s: unable to alloc rx_pkt_info, will retry later\n",
+ __func__);
goto fail;
}
INIT_WORK(&info->work, handle_bam_mux_cmd);
- info->skb = __dev_alloc_skb(BUFFER_SIZE, GFP_KERNEL);
+ info->skb = __dev_alloc_skb(BUFFER_SIZE,
+ GFP_NOWAIT | __GFP_NOWARN);
if (info->skb == NULL) {
- DMUX_LOG_KERR("%s: unable to alloc skb\n", __func__);
+ DMUX_LOG_KERR(
+ "%s: unable to alloc skb, will retry later\n",
+ __func__);
goto fail_info;
}
ptr = skb_put(info->skb, BUFFER_SIZE);
@@ -487,11 +494,16 @@
fail:
if (rx_len_cached == 0) {
- DMUX_LOG_KERR("%s: RX queue failure\n", __func__);
- in_global_reset = 1;
+ DMUX_LOG_KERR("%s: rescheduling\n", __func__);
+ schedule_delayed_work(&queue_rx_work, msecs_to_jiffies(100));
}
}
+static void queue_rx_work_func(struct work_struct *work)
+{
+ queue_rx();
+}
+
static void bam_mux_process_data(struct sk_buff *rx_skb)
{
unsigned long flags;
@@ -2421,6 +2433,7 @@
init_completion(&bam_connection_completion);
init_completion(&dfab_unvote_completion);
INIT_DELAYED_WORK(&ul_timeout_work, ul_timeout);
+ INIT_DELAYED_WORK(&queue_rx_work, queue_rx_work_func);
wake_lock_init(&bam_wakelock, WAKE_LOCK_SUSPEND, "bam_dmux_wakelock");
rc = smsm_state_cb_register(SMSM_MODEM_STATE, SMSM_A2_POWER_CONTROL,
diff --git a/arch/arm/mach-msm/board-8064-pmic.c b/arch/arm/mach-msm/board-8064-pmic.c
index 6eadc59..f6423c8 100644
--- a/arch/arm/mach-msm/board-8064-pmic.c
+++ b/arch/arm/mach-msm/board-8064-pmic.c
@@ -115,7 +115,6 @@
/* Initial PM8921 GPIO configurations */
static struct pm8xxx_gpio_init pm8921_gpios[] __initdata = {
PM8921_GPIO_OUTPUT(14, 1, HIGH), /* HDMI Mux Selector */
- PM8921_GPIO_OUTPUT(23, 0, HIGH), /* touchscreen power FET */
PM8921_GPIO_OUTPUT_BUFCONF(25, 0, LOW, CMOS), /* DISP_RESET_N */
PM8921_GPIO_OUTPUT_FUNC(26, 0, PM_GPIO_FUNC_2), /* Bl: Off, PWM mode */
PM8921_GPIO_OUTPUT_VIN(30, 1, PM_GPIO_VIN_VPH), /* SMB349 susp line */
@@ -146,10 +145,13 @@
PM8921_GPIO_OUTPUT(37, 0, LOW), /* MUX1_SEL */
};
+static struct pm8xxx_gpio_init touchscreen_gpios[] __initdata = {
+ PM8921_GPIO_OUTPUT(23, 0, HIGH), /* touchscreen power FET */
+};
+
/* Initial PM8917 GPIO configurations */
static struct pm8xxx_gpio_init pm8917_gpios[] __initdata = {
PM8921_GPIO_OUTPUT(14, 1, HIGH), /* HDMI Mux Selector */
- PM8921_GPIO_OUTPUT(23, 0, HIGH), /* touchscreen power FET */
PM8921_GPIO_OUTPUT_BUFCONF(25, 0, LOW, CMOS), /* DISP_RESET_N */
PM8921_GPIO_OUTPUT(26, 1, HIGH), /* Backlight: on */
PM8921_GPIO_OUTPUT_BUFCONF(36, 1, LOW, OPEN_DRAIN),
@@ -210,6 +212,8 @@
apq8064_configure_gpios(pm8917_gpios, ARRAY_SIZE(pm8917_gpios));
if (machine_is_apq8064_cdp() || machine_is_apq8064_liquid()) {
+ apq8064_configure_gpios(touchscreen_gpios,
+ ARRAY_SIZE(touchscreen_gpios));
if (socinfo_get_pmic_model() != PMIC_MODEL_PM8917)
apq8064_configure_gpios(pm8921_cdp_kp_gpios,
ARRAY_SIZE(pm8921_cdp_kp_gpios));
diff --git a/arch/arm/mach-msm/board-8064-regulator.c b/arch/arm/mach-msm/board-8064-regulator.c
index 6cdafbc..ef3c81d 100644
--- a/arch/arm/mach-msm/board-8064-regulator.c
+++ b/arch/arm/mach-msm/board-8064-regulator.c
@@ -771,4 +771,10 @@
= ARRAY_SIZE(vreg_consumers_8917_S1);
}
}
+
+ /*
+ * Switch to 8960_PM8917 rpm-regulator version so that TCXO workaround
+ * is applied to PM8917 regulators L25, L26, L27, and L28.
+ */
+ apq8064_rpm_regulator_pdata.version = RPM_VREG_VERSION_8960_PM8917;
}
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 2fd1a68..cc9dcbb 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-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
@@ -927,7 +927,8 @@
static void __init apq8064_ehci_host_init(void)
{
if (machine_is_apq8064_liquid() || machine_is_mpq8064_cdp() ||
- machine_is_mpq8064_hrd() || machine_is_mpq8064_dtv()) {
+ machine_is_mpq8064_hrd() || machine_is_mpq8064_dtv() ||
+ machine_is_apq8064_cdp()) {
if (machine_is_apq8064_liquid())
msm_ehci_host_pdata3.dock_connect_irq =
PM8921_MPP_IRQ(PM8921_IRQ_BASE, 9);
@@ -2467,7 +2468,6 @@
&apq8064_device_ext_3p3v_vreg,
&apq8064_device_ssbi_pmic1,
&apq8064_device_ssbi_pmic2,
- &apq8064_device_ext_ts_sw_vreg,
};
static struct platform_device *pm8917_common_devices[] __initdata = {
@@ -2475,7 +2475,6 @@
&apq8064_device_ext_3p3v_vreg,
&apq8064_device_ssbi_pmic1,
&apq8064_device_ssbi_pmic2,
- &apq8064_device_ext_ts_sw_vreg,
};
static struct platform_device *common_devices[] __initdata = {
@@ -2570,6 +2569,7 @@
&msm_gss,
&apq8064_rtb_device,
&apq8064_cpu_idle_device,
+ &apq8064_msm_gov_device,
&apq8064_device_cache_erp,
&msm8960_device_ebi1_ch0_erp,
&msm8960_device_ebi1_ch1_erp,
@@ -2593,6 +2593,7 @@
#ifdef CONFIG_BATTERY_BCL
&battery_bcl_device,
#endif
+ &apq8064_msm_mpd_device,
};
static struct platform_device *cdp_devices[] __initdata = {
@@ -3372,6 +3373,8 @@
else
platform_add_devices(pm8917_common_devices,
ARRAY_SIZE(pm8917_common_devices));
+ if (machine_is_apq8064_cdp() || machine_is_apq8064_liquid())
+ platform_device_register(&apq8064_device_ext_ts_sw_vreg);
platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
if (!(machine_is_mpq8064_cdp() || machine_is_mpq8064_hrd() ||
machine_is_mpq8064_dtv()))
diff --git a/arch/arm/mach-msm/board-9625.c b/arch/arm/mach-msm/board-9625.c
index 797f5f1..37e93b6 100644
--- a/arch/arm/mach-msm/board-9625.c
+++ b/arch/arm/mach-msm/board-9625.c
@@ -31,8 +31,39 @@
#include <mach/gpio.h>
#include <mach/clk-provider.h>
#include <mach/qpnp-int.h>
+#include <mach/msm_memtypes.h>
#include "clock.h"
+#define MSM_KERNEL_EBI_SIZE 0x51000
+
+static struct memtype_reserve msm9625_reserve_table[] __initdata = {
+ [MEMTYPE_SMI] = {
+ },
+ [MEMTYPE_EBI0] = {
+ .flags = MEMTYPE_FLAGS_1M_ALIGN,
+ },
+ [MEMTYPE_EBI1] = {
+ .flags = MEMTYPE_FLAGS_1M_ALIGN,
+ },
+};
+
+static int msm9625_paddr_to_memtype(unsigned int paddr)
+{
+ return MEMTYPE_EBI1;
+}
+
+static void __init msm9625_calculate_reserve_sizes(void)
+{
+ msm9625_reserve_table[MEMTYPE_EBI1].size += MSM_KERNEL_EBI_SIZE;
+}
+
+static struct reserve_info msm9625_reserve_info __initdata = {
+ .memtype_reserve_table = msm9625_reserve_table,
+ .calculate_reserve_sizes = msm9625_calculate_reserve_sizes,
+ .paddr_to_memtype = msm9625_paddr_to_memtype,
+};
+
+
#define L2CC_AUX_CTRL ((0x1 << L2X0_AUX_CTRL_SHARE_OVERRIDE_SHIFT) | \
(0x2 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT) | \
(0x1 << L2X0_AUX_CTRL_EVNT_MON_BUS_EN_SHIFT))
@@ -97,6 +128,13 @@
.init = msm_dt_timer_init
};
+static void __init msm9625_reserve(void)
+{
+ reserve_info = &msm9625_reserve_info;
+ msm_reserve();
+}
+
+
void __init msm9625_init(void)
{
if (socinfo_init() < 0)
@@ -115,4 +153,5 @@
.handle_irq = gic_handle_irq,
.timer = &msm_dt_timer,
.dt_compat = msm9625_dt_match,
+ .reserve = msm9625_reserve,
MACHINE_END
diff --git a/arch/arm/mach-msm/board-fsm9xxx.c b/arch/arm/mach-msm/board-fsm9xxx.c
index b4f6968..1d6eb01 100644
--- a/arch/arm/mach-msm/board-fsm9xxx.c
+++ b/arch/arm/mach-msm/board-fsm9xxx.c
@@ -941,6 +941,8 @@
static void __init fsm9xxx_init(void)
{
+ msm_clock_init(&fsm9xxx_clock_init_data);
+
regulator_has_full_constraints();
#if defined(CONFIG_I2C_SSBI) || defined(CONFIG_MSM_SSBI)
@@ -977,7 +979,6 @@
{
msm_shared_ram_phys = 0x00100000;
msm_map_fsm9xxx_io();
- msm_clock_init(&fsm9xxx_clock_init_data);
if (socinfo_init() < 0)
pr_err("%s: socinfo_init() failed!\n",
__func__);
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index c0461e1..6d964e2 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-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
@@ -1962,6 +1962,11 @@
.end = 0x10008000 + SZ_256 - 1,
.flags = IORESOURCE_MEM,
},
+ {
+ .start = GSS_A5_WDOG_EXPIRED,
+ .end = GSS_A5_WDOG_EXPIRED,
+ .flags = IORESOURCE_IRQ,
+ },
};
struct platform_device msm_gss = {
@@ -2691,6 +2696,23 @@
},
};
+static struct msm_mpd_algo_param apq8064_mpd_algo_param = {
+ .em_win_size_min_us = 10000,
+ .em_win_size_max_us = 100000,
+ .em_max_util_pct = 90,
+ .online_util_pct_min = 60,
+ .slack_time_min_us = 50000,
+ .slack_time_max_us = 100000,
+};
+
+struct platform_device apq8064_msm_mpd_device = {
+ .name = "msm_mpdecision",
+ .id = -1,
+ .dev = {
+ .platform_data = &apq8064_mpd_algo_param,
+ },
+};
+
#ifdef CONFIG_MSM_VCAP
#define VCAP_HW_BASE 0x05900000
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 5cbfb5b..2a641ba 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -1444,6 +1444,11 @@
.end = 0x03204000 + SZ_256 - 1,
.flags = IORESOURCE_MEM,
},
+ {
+ .start = RIVA_APSS_WDOG_BITE_RESET_RDY_IRQ,
+ .end = RIVA_APSS_WDOG_BITE_RESET_RDY_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
};
struct platform_device msm_8960_riva = {
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index 0a9bbf6..46853ac 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -1316,8 +1316,8 @@
};
static struct msm_rpmstats_platform_data msm_rpm_stat_pdata = {
- .phys_addr_base = 0x0010D204,
- .phys_size = SZ_8K,
+ .phys_addr_base = 0x0010DD04,
+ .phys_size = SZ_256,
};
struct platform_device msm9615_rpm_stat_device = {
diff --git a/arch/arm/mach-msm/devices-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c
index b88fb50..37cdc98 100644
--- a/arch/arm/mach-msm/devices-msm8x60.c
+++ b/arch/arm/mach-msm/devices-msm8x60.c
@@ -192,7 +192,9 @@
gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE, (void *)MSM_QGIC_CPU_BASE);
}
-#define MSM_LPASS_QDSP6SS_PHYS 0x28800000
+#define MSM_LPASS_QDSP6SS_PHYS 0x28800000
+#define MSM_LPASS_QDSP6SS_WDOG_PHYS 0x28882000
+#define MSM_LPASS_QDSP6SS_IM_PHYS 0x288A0000
static struct resource msm_8660_q6_resources[] = {
{
@@ -200,6 +202,21 @@
.end = MSM_LPASS_QDSP6SS_PHYS + SZ_256 - 1,
.flags = IORESOURCE_MEM,
},
+ {
+ .start = MSM_LPASS_QDSP6SS_IM_PHYS,
+ .end = MSM_LPASS_QDSP6SS_IM_PHYS + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MSM_LPASS_QDSP6SS_WDOG_PHYS,
+ .end = MSM_LPASS_QDSP6SS_WDOG_PHYS + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = LPASS_Q6SS_WDOG_EXPIRED,
+ .end = LPASS_Q6SS_WDOG_EXPIRED,
+ .flags = IORESOURCE_IRQ,
+ },
};
struct platform_device msm_pil_q6v3 = {
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 0506217..7e750f5 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -1,7 +1,7 @@
/* linux/arch/arm/mach-msm/devices.h
*
* Copyright (C) 2008 Google, Inc.
- * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, The 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
@@ -447,6 +447,8 @@
extern struct platform_device msm8960ab_device_acpuclk;
extern struct platform_device msm9615_device_acpuclk;
+extern struct platform_device apq8064_msm_mpd_device;
+
extern struct platform_device msm_gpio_device;
extern struct platform_device apq_cpudai_mi2s;
diff --git a/arch/arm/mach-msm/gss-8064.c b/arch/arm/mach-msm/gss-8064.c
deleted file mode 100644
index ba6af61..0000000
--- a/arch/arm/mach-msm/gss-8064.c
+++ /dev/null
@@ -1,265 +0,0 @@
-/* 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/interrupt.h>
-#include <linux/reboot.h>
-#include <linux/workqueue.h>
-#include <linux/io.h>
-#include <linux/jiffies.h>
-#include <linux/stringify.h>
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/miscdevice.h>
-#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>
-#include <mach/subsystem_notif.h>
-#include <mach/socinfo.h>
-
-#include "smd_private.h"
-#include "modem_notifier.h"
-#include "ramdump.h"
-
-static struct gss_8064_data {
- struct miscdevice gss_dev;
- void *pil_handle;
- void *gss_ramdump_dev;
- void *smem_ramdump_dev;
-} gss_data;
-
-static int crash_shutdown;
-
-static struct subsys_device *gss_8064_dev;
-
-#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 restart_gss(void)
-{
- log_gss_sfr();
- subsystem_restart_dev(gss_8064_dev);
-}
-
-static void smsm_state_cb(void *data, uint32_t old_state, uint32_t new_state)
-{
- /* Ignore if we're the one that set SMSM_RESET */
- if (crash_shutdown)
- return;
-
- if (new_state & SMSM_RESET) {
- pr_err("GSS SMSM state changed to SMSM_RESET.\n"
- "Probable err_fatal on the GSS. "
- "Calling subsystem restart...\n");
- restart_gss();
- }
-}
-
-#define Q6_FW_WDOG_ENABLE 0x08882024
-#define Q6_SW_WDOG_ENABLE 0x08982024
-static int gss_shutdown(const struct subsys_desc *desc)
-{
- pil_force_shutdown("gss");
- disable_irq_nosync(GSS_A5_WDOG_EXPIRED);
-
- return 0;
-}
-
-static int gss_powerup(const struct subsys_desc *desc)
-{
- pil_force_boot("gss");
- enable_irq(GSS_A5_WDOG_EXPIRED);
- return 0;
-}
-
-void gss_crash_shutdown(const struct subsys_desc *desc)
-{
- crash_shutdown = 1;
- 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},
-};
-
-static int gss_ramdump(int enable,
- const struct subsys_desc *crashed_subsys)
-{
- int ret = 0;
-
- if (enable) {
- ret = do_ramdump(gss_data.gss_ramdump_dev, gss_segments,
- ARRAY_SIZE(gss_segments));
-
- if (ret < 0) {
- pr_err("Unable to dump gss memory (rc = %d).\n",
- ret);
- goto out;
- }
-
- ret = do_ramdump(gss_data.smem_ramdump_dev, smem_segments,
- ARRAY_SIZE(smem_segments));
-
- if (ret < 0) {
- pr_err("Unable to dump smem memory (rc = %d).\n", ret);
- goto out;
- }
- }
-
-out:
- return ret;
-}
-
-static irqreturn_t gss_wdog_bite_irq(int irq, void *dev_id)
-{
- pr_err("Watchdog bite received from GSS!\n");
- restart_gss();
-
- return IRQ_HANDLED;
-}
-
-static struct subsys_desc gss_8064 = {
- .name = "gss",
- .shutdown = gss_shutdown,
- .powerup = gss_powerup,
- .ramdump = gss_ramdump,
- .crash_shutdown = gss_crash_shutdown
-};
-
-static int gss_subsystem_restart_init(void)
-{
- gss_8064_dev = subsys_register(&gss_8064);
- if (IS_ERR(gss_8064_dev))
- return PTR_ERR(gss_8064_dev);
- return 0;
-}
-
-static int gss_open(struct inode *inode, struct file *filep)
-{
- void *ret;
- gss_data.pil_handle = ret = pil_get("gss");
- if (!ret)
- pr_debug("%s - pil_get returned NULL\n", __func__);
- return 0;
-}
-
-static int gss_release(struct inode *inode, struct file *filep)
-{
- pil_put(gss_data.pil_handle);
- pr_debug("%s pil_put called on GSS\n", __func__);
- return 0;
-}
-
-const struct file_operations gss_file_ops = {
- .open = gss_open,
- .release = gss_release,
-};
-
-static int __init gss_8064_init(void)
-{
- int ret;
-
- if (!(cpu_is_apq8064() || cpu_is_apq8064ab()))
- return -ENODEV;
-
- ret = smsm_state_cb_register(SMSM_MODEM_STATE, SMSM_RESET,
- smsm_state_cb, 0);
-
- if (ret < 0)
- pr_err("%s: Unable to register SMSM callback! (%d)\n",
- __func__, ret);
-
- ret = request_irq(GSS_A5_WDOG_EXPIRED, gss_wdog_bite_irq,
- IRQF_TRIGGER_RISING, "gss_a5_wdog", NULL);
-
- if (ret < 0) {
- pr_err("%s: Unable to request gss watchdog IRQ. (%d)\n",
- __func__, ret);
- disable_irq_nosync(GSS_A5_WDOG_EXPIRED);
- goto out;
- }
-
- ret = gss_subsystem_restart_init();
-
- if (ret < 0) {
- pr_err("%s: Unable to reg with subsystem restart. (%d)\n",
- __func__, ret);
- goto out;
- }
-
- gss_data.gss_dev.minor = MISC_DYNAMIC_MINOR;
- gss_data.gss_dev.name = "gss";
- gss_data.gss_dev.fops = &gss_file_ops;
- ret = misc_register(&gss_data.gss_dev);
-
- if (ret) {
- pr_err("%s: misc_registers failed for %s (%d)", __func__,
- gss_data.gss_dev.name, ret);
- goto out;
- }
-
- gss_data.gss_ramdump_dev = create_ramdump_device("gss");
-
- if (!gss_data.gss_ramdump_dev) {
- pr_err("%s: Unable to create gss ramdump device. (%d)\n",
- __func__, -ENOMEM);
- ret = -ENOMEM;
- goto out;
- }
-
- gss_data.smem_ramdump_dev = create_ramdump_device("smem-gss");
-
- if (!gss_data.smem_ramdump_dev) {
- pr_err("%s: Unable to create smem ramdump device. (%d)\n",
- __func__, -ENOMEM);
- ret = -ENOMEM;
- goto out;
- }
-
- pr_info("%s: gss fatal driver init'ed.\n", __func__);
-out:
- return ret;
-}
-
-module_init(gss_8064_init);
diff --git a/arch/arm/mach-msm/include/mach/msm_dcvs.h b/arch/arm/mach-msm/include/mach/msm_dcvs.h
index fa7e6f0..78d0d4a 100644
--- a/arch/arm/mach-msm/include/mach/msm_dcvs.h
+++ b/arch/arm/mach-msm/include/mach/msm_dcvs.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -18,6 +18,8 @@
#define CORE_NAME_MAX (32)
#define CORES_MAX (10)
+#define CPU_OFFSET 1 /* used to notify TZ the core number */
+
enum msm_core_idle_state {
MSM_DCVS_IDLE_ENTER,
MSM_DCVS_IDLE_EXIT,
diff --git a/arch/arm/mach-msm/include/mach/msm_dcvs_scm.h b/arch/arm/mach-msm/include/mach/msm_dcvs_scm.h
index 3cc2595..d97cd32 100644
--- a/arch/arm/mach-msm/include/mach/msm_dcvs_scm.h
+++ b/arch/arm/mach-msm/include/mach/msm_dcvs_scm.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -13,13 +13,23 @@
#ifndef _ARCH_ARM_MACH_MSM_MSM_DCVS_SCM_H
#define _ARCH_ARM_MACH_MSM_MSM_DCVS_SCM_H
+enum msm_dcvs_algo_param_type {
+ MSM_DCVS_ALGO_DCVS_PARAM = 0,
+ MSM_DCVS_ALGO_MPD_PARAM = 1,
+};
+
enum msm_dcvs_scm_event {
- MSM_DCVS_SCM_IDLE_ENTER,
- MSM_DCVS_SCM_IDLE_EXIT,
- MSM_DCVS_SCM_QOS_TIMER_EXPIRED,
- MSM_DCVS_SCM_CLOCK_FREQ_UPDATE,
- MSM_DCVS_SCM_ENABLE_CORE,
- MSM_DCVS_SCM_RESET_CORE,
+ MSM_DCVS_SCM_IDLE_ENTER = 0, /* Core enters idle */
+ MSM_DCVS_SCM_IDLE_EXIT = 1, /* Core exits idle */
+ MSM_DCVS_SCM_QOS_TIMER_EXPIRED = 2, /* Core slack timer expired */
+ MSM_DCVS_SCM_CLOCK_FREQ_UPDATE = 3, /* Core freq change complete */
+ MSM_DCVS_SCM_CORE_ONLINE = 4, /* Core is online */
+ MSM_DCVS_SCM_CORE_OFFLINE = 5, /* Core is offline */
+ MSM_DCVS_SCM_CORE_UNAVAILABLE = 6, /* Core is offline + unavailable */
+ MSM_DCVS_SCM_DCVS_ENABLE = 7, /* DCVS is enabled/disabled for core */
+ MSM_DCVS_SCM_MPD_ENABLE = 8, /* Enable/disable MP Decision */
+ MSM_DCVS_SCM_RUNQ_UPDATE = 9, /* Update running threads */
+ MSM_DCVS_SCM_MPD_QOS_TIMER_EXPIRED = 10, /* MPDecision slack timer */
};
struct msm_dcvs_algo_param {
@@ -46,6 +56,18 @@
};
+struct msm_mpd_algo_param {
+ uint32_t em_win_size_min_us;
+ uint32_t em_win_size_max_us;
+ uint32_t em_max_util_pct;
+ uint32_t mp_em_rounding_point_min;
+ uint32_t mp_em_rounding_point_max;
+ uint32_t online_util_pct_min;
+ uint32_t online_util_pct_max;
+ uint32_t slack_time_min_us;
+ uint32_t slack_time_max_us;
+};
+
#ifdef CONFIG_MSM_DCVS
/**
* Initialize DCVS algorithm in TrustZone.
@@ -101,6 +123,15 @@
struct msm_dcvs_algo_param *param);
/**
+ * Set MPDecision algorithm parameters
+ *
+ * @param: The param data structure
+ * 0 on success.
+ * -EINVAL: Invalid args.
+ */
+extern int msm_mpd_scm_set_algo_params(struct msm_mpd_algo_param *param);
+
+/**
* Do an SCM call.
*
* @core_id: The core identifier.
@@ -158,6 +189,9 @@
static inline int msm_dcvs_scm_set_algo_params(uint32_t core_id,
struct msm_dcvs_algo_param *param)
{ return -ENOSYS; }
+static inline int msm_mpd_scm_set_algo_params(
+ struct msm_mpd_algo_param *param)
+{ return -ENOSYS; }
static inline int msm_dcvs_scm_event(uint32_t core_id,
enum msm_dcvs_scm_event event_id,
uint32_t param0, uint32_t param1,
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-9625.h b/arch/arm/mach-msm/include/mach/msm_iomap-9625.h
index eecdd67..765de13 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-9625.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-9625.h
@@ -34,9 +34,27 @@
#define MSM9625_TLMM_PHYS 0xFD510000
#define MSM9625_TLMM_SIZE SZ_16K
+/*
+ * TODO: Revert IMEM_PHYS back to actual
+ * address 0xfe807800
+ * after IMEM issues resolved.
+ *
+ */
+#define MSM9625_IMEM_PHYS 0xFC42B000
+#define MSM9625_IMEM_SIZE SZ_2K
+
#ifdef CONFIG_DEBUG_MSM9625_UART
#define MSM_DEBUG_UART_BASE IOMEM(0xFA71E000)
#define MSM_DEBUG_UART_PHYS 0xF991E000
#endif
+/*
+ * IMEM is retained for secure watchdog reset
+ * Debug Image looks at actual IMEM to
+ * do memory dumping.
+ */
+
+#define MSM9625_DBG_IMEM_PHYS 0xFE807800
+#define MSM9625_DBG_IMEM_SIZE SZ_4K
+
#endif
diff --git a/arch/arm/mach-msm/include/mach/rpm-regulator.h b/arch/arm/mach-msm/include/mach/rpm-regulator.h
index f6e082d..075d20f 100644
--- a/arch/arm/mach-msm/include/mach/rpm-regulator.h
+++ b/arch/arm/mach-msm/include/mach/rpm-regulator.h
@@ -32,7 +32,8 @@
RPM_VREG_VERSION_9615,
RPM_VREG_VERSION_8930,
RPM_VREG_VERSION_8930_PM8917,
- RPM_VREG_VERSION_MAX = RPM_VREG_VERSION_8930_PM8917,
+ RPM_VREG_VERSION_8960_PM8917,
+ RPM_VREG_VERSION_MAX = RPM_VREG_VERSION_8960_PM8917,
};
#define RPM_VREG_PIN_CTRL_NONE 0x00
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index 5ee7068..39ac253 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -462,6 +462,7 @@
MSM_CHIP_DEVICE(APCS_GCC, MSM9625),
MSM_CHIP_DEVICE(TLMM, MSM9625),
MSM_CHIP_DEVICE(TMR, MSM9625),
+ MSM_CHIP_DEVICE(IMEM, MSM9625),
{
.virtual = (unsigned long) MSM_SHARED_RAM_BASE,
.length = MSM_SHARED_RAM_SIZE,
@@ -470,6 +471,7 @@
#ifdef CONFIG_DEBUG_MSM9625_UART
MSM_DEVICE(DEBUG_UART),
#endif
+ MSM_CHIP_DEVICE(DBG_IMEM, MSM9625),
};
void __init msm_map_msm9625_io(void)
diff --git a/arch/arm/mach-msm/lpass-8660.c b/arch/arm/mach-msm/lpass-8660.c
deleted file mode 100644
index be18b68..0000000
--- a/arch/arm/mach-msm/lpass-8660.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/* Copyright (c) 2011-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/interrupt.h>
-#include <linux/reboot.h>
-#include <linux/workqueue.h>
-#include <linux/io.h>
-#include <linux/jiffies.h>
-#include <linux/stringify.h>
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/err.h>
-
-#include <mach/irqs.h>
-#include <mach/scm.h>
-#include <mach/peripheral-loader.h>
-#include <mach/subsystem_restart.h>
-#include <mach/subsystem_notif.h>
-
-#include "smd_private.h"
-#include "modem_notifier.h"
-#include "ramdump.h"
-
-#define Q6SS_WDOG_ENABLE 0x28882024
-#define Q6SS_SOFT_INTR_WAKEUP 0x288A001C
-#define MODULE_NAME "lpass_8x60"
-#define SCM_Q6_NMI_CMD 0x1
-
-static struct subsys_device *subsys_8x60_q6_dev;
-
-/* Subsystem restart: QDSP6 data, functions */
-static void *q6_ramdump_dev;
-static void q6_fatal_fn(struct work_struct *);
-static DECLARE_WORK(q6_fatal_work, q6_fatal_fn);
-static void __iomem *q6_wakeup_intr;
-
-static void q6_fatal_fn(struct work_struct *work)
-{
- pr_err("%s: Watchdog bite received from Q6!\n", MODULE_NAME);
- subsystem_restart_dev(subsys_8x60_q6_dev);
- enable_irq(LPASS_Q6SS_WDOG_EXPIRED);
-}
-
-static void send_q6_nmi(void)
-{
- /* Send NMI to QDSP6 via an SCM call. */
- scm_call_atomic1(SCM_SVC_UTIL, SCM_Q6_NMI_CMD, 0x1);
-
- /* Wakeup the Q6 */
- if (q6_wakeup_intr)
- writel_relaxed(0x2000, q6_wakeup_intr);
- else
- pr_warn("lpass-8660: Unable to send wakeup interrupt to Q6.\n");
-
- /* Q6 requires atleast 100ms to dump caches etc.*/
- mdelay(100);
-
- pr_info("subsystem-fatal-8x60: Q6 NMI was sent.\n");
-}
-
-int subsys_q6_shutdown(const struct subsys_desc *crashed_subsys)
-{
- void __iomem *q6_wdog_addr =
- ioremap_nocache(Q6SS_WDOG_ENABLE, 8);
-
- send_q6_nmi();
- writel_relaxed(0x0, q6_wdog_addr);
- /* The write needs to go through before the q6 is shutdown. */
- mb();
- iounmap(q6_wdog_addr);
-
- pil_force_shutdown("q6");
- disable_irq_nosync(LPASS_Q6SS_WDOG_EXPIRED);
-
- return 0;
-}
-
-int subsys_q6_powerup(const struct subsys_desc *crashed_subsys)
-{
- int ret = pil_force_boot("q6");
- enable_irq(LPASS_Q6SS_WDOG_EXPIRED);
- return ret;
-}
-
-/* FIXME: Get address, size from PIL */
-static struct ramdump_segment q6_segments[] = { {0x46700000, 0x47F00000 -
- 0x46700000}, {0x28400000, 0x12800} };
-static int subsys_q6_ramdump(int enable,
- const struct subsys_desc *crashed_subsys)
-{
- if (enable)
- return do_ramdump(q6_ramdump_dev, q6_segments,
- ARRAY_SIZE(q6_segments));
- else
- return 0;
-}
-
-void subsys_q6_crash_shutdown(const struct subsys_desc *crashed_subsys)
-{
- send_q6_nmi();
-}
-
-static irqreturn_t lpass_wdog_bite_irq(int irq, void *dev_id)
-{
- int ret;
-
- ret = schedule_work(&q6_fatal_work);
- disable_irq_nosync(LPASS_Q6SS_WDOG_EXPIRED);
-
- return IRQ_HANDLED;
-}
-
-static struct subsys_desc subsys_8x60_q6 = {
- .name = "lpass",
- .shutdown = subsys_q6_shutdown,
- .powerup = subsys_q6_powerup,
- .ramdump = subsys_q6_ramdump,
- .crash_shutdown = subsys_q6_crash_shutdown
-};
-
-static void __exit lpass_fatal_exit(void)
-{
- subsys_unregister(subsys_8x60_q6_dev);
- iounmap(q6_wakeup_intr);
- free_irq(LPASS_Q6SS_WDOG_EXPIRED, NULL);
-}
-
-static int __init lpass_fatal_init(void)
-{
- int ret;
-
- ret = request_irq(LPASS_Q6SS_WDOG_EXPIRED, lpass_wdog_bite_irq,
- IRQF_TRIGGER_RISING, "q6_wdog", NULL);
-
- if (ret < 0) {
- pr_err("%s: Unable to request LPASS_Q6SS_WDOG_EXPIRED irq.",
- __func__);
- goto out;
- }
-
- q6_ramdump_dev = create_ramdump_device("lpass");
-
- if (!q6_ramdump_dev) {
- ret = -ENOMEM;
- goto out;
- }
-
- q6_wakeup_intr = ioremap_nocache(Q6SS_SOFT_INTR_WAKEUP, 8);
-
- if (!q6_wakeup_intr)
- pr_warn("lpass-8660: Unable to ioremap q6 wakeup address.");
-
- subsys_8x60_q6_dev = subsys_register(&subsys_8x60_q6);
- if (IS_ERR(subsys_8x60_q6_dev))
- ret = PTR_ERR(subsys_8x60_q6_dev);
-out:
- return ret;
-}
-
-module_init(lpass_fatal_init);
-module_exit(lpass_fatal_exit);
-
diff --git a/arch/arm/mach-msm/msm_dcvs.c b/arch/arm/mach-msm/msm_dcvs.c
index 0c158de..890e450 100644
--- a/arch/arm/mach-msm/msm_dcvs.c
+++ b/arch/arm/mach-msm/msm_dcvs.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -582,7 +582,7 @@
if (core->idle_driver) {
core->actual_freq = core->freq_driver->get_frequency(drv);
/* Notify TZ to start receiving idle info for the core */
- ret = msm_dcvs_update_freq(core, MSM_DCVS_SCM_ENABLE_CORE, 1,
+ ret = msm_dcvs_update_freq(core, MSM_DCVS_SCM_DCVS_ENABLE, 1,
&ret1, &ret2);
core->idle_driver->enable(core->idle_driver,
MSM_DCVS_ENABLE_IDLE_PULSE);
@@ -615,7 +615,7 @@
core->idle_driver->enable(core->idle_driver,
MSM_DCVS_DISABLE_IDLE_PULSE);
/* Notify TZ to stop receiving idle info for the core */
- ret = msm_dcvs_update_freq(core, MSM_DCVS_SCM_ENABLE_CORE, 0,
+ ret = msm_dcvs_update_freq(core, MSM_DCVS_SCM_DCVS_ENABLE, 0,
&ret1, &ret2);
hrtimer_cancel(&core->timer);
core->idle_driver->enable(core->idle_driver,
diff --git a/arch/arm/mach-msm/msm_dcvs_scm.c b/arch/arm/mach-msm/msm_dcvs_scm.c
index 6095e0813..bf623df 100644
--- a/arch/arm/mach-msm/msm_dcvs_scm.c
+++ b/arch/arm/mach-msm/msm_dcvs_scm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -44,6 +44,14 @@
uint32_t size;
};
+struct msm_algo_param {
+ enum msm_dcvs_algo_param_type type;
+ union {
+ struct msm_dcvs_algo_param dcvs_param;
+ struct msm_mpd_algo_param mpd_param;
+ } u;
+};
+
int msm_dcvs_scm_init(size_t size)
{
int ret = 0;
@@ -123,13 +131,15 @@
{
int ret = 0;
struct scm_algo algo;
- struct msm_dcvs_algo_param *p = NULL;
+ struct msm_algo_param *p = NULL;
- p = kzalloc(PAGE_ALIGN(sizeof(struct msm_dcvs_algo_param)), GFP_KERNEL);
+ p = kzalloc(PAGE_ALIGN(sizeof(struct msm_algo_param)), GFP_KERNEL);
if (!p)
return -ENOMEM;
- memcpy(p, param, sizeof(struct msm_dcvs_algo_param));
+
+ p->type = MSM_DCVS_ALGO_DCVS_PARAM;
+ memcpy(&p->u.dcvs_param, param, sizeof(struct msm_dcvs_algo_param));
algo.core_id = core_id;
algo.algo_phy = virt_to_phys(p);
@@ -143,6 +153,31 @@
}
EXPORT_SYMBOL(msm_dcvs_scm_set_algo_params);
+int msm_mpd_scm_set_algo_params(struct msm_mpd_algo_param *param)
+{
+ int ret = 0;
+ struct scm_algo algo;
+ struct msm_algo_param *p = NULL;
+
+ p = kzalloc(PAGE_ALIGN(sizeof(struct msm_algo_param)), GFP_KERNEL);
+ if (!p)
+ return -ENOMEM;
+
+ p->type = MSM_DCVS_ALGO_MPD_PARAM;
+ memcpy(&p->u.mpd_param, param, sizeof(struct msm_mpd_algo_param));
+
+ algo.core_id = 0;
+ algo.algo_phy = virt_to_phys(p);
+
+ ret = scm_call(SCM_SVC_DCVS, DCVS_CMD_SET_ALGO_PARAM,
+ &algo, sizeof(algo), NULL, 0);
+
+ kfree(p);
+
+ return ret;
+}
+EXPORT_SYMBOL(msm_mpd_scm_set_algo_params);
+
int msm_dcvs_scm_event(uint32_t core_id,
enum msm_dcvs_scm_event event_id,
uint32_t param0, uint32_t param1,
diff --git a/arch/arm/mach-msm/msm_mpdecision.c b/arch/arm/mach-msm/msm_mpdecision.c
new file mode 100644
index 0000000..056e4eb
--- /dev/null
+++ b/arch/arm/mach-msm/msm_mpdecision.c
@@ -0,0 +1,707 @@
+ /* 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.
+ */
+
+#define pr_fmt(fmt) "mpd %s: " fmt, __func__
+
+#include <linux/cpumask.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/kthread.h>
+#include <linux/kobject.h>
+#include <linux/ktime.h>
+#include <linux/hrtimer.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/cpu.h>
+#include <linux/stringify.h>
+#include <linux/sched.h>
+#include <linux/platform_device.h>
+#include <linux/debugfs.h>
+#include <linux/cpu_pm.h>
+#include <linux/cpu.h>
+#include <linux/cpufreq.h>
+#include <linux/sched.h>
+#include <linux/rq_stats.h>
+#include <asm/atomic.h>
+#include <asm/page.h>
+#include <mach/msm_dcvs.h>
+#include <mach/msm_dcvs_scm.h>
+
+#define DEFAULT_RQ_AVG_POLL_MS (1)
+
+struct mpd_attrib {
+ struct kobj_attribute enabled;
+ struct kobj_attribute rq_avg_poll_ms;
+ struct kobj_attribute iowait_threshold_pct;
+
+ struct kobj_attribute em_win_size_min_us;
+ struct kobj_attribute em_win_size_max_us;
+ struct kobj_attribute em_max_util_pct;
+ struct kobj_attribute mp_em_rounding_point_min;
+ struct kobj_attribute mp_em_rounding_point_max;
+ struct kobj_attribute online_util_pct_min;
+ struct kobj_attribute online_util_pct_max;
+ struct kobj_attribute slack_time_min_us;
+ struct kobj_attribute slack_time_max_us;
+ struct kobj_attribute hp_up_max_ms;
+ struct kobj_attribute hp_up_ms;
+ struct kobj_attribute hp_up_count;
+ struct kobj_attribute hp_dw_max_ms;
+ struct kobj_attribute hp_dw_ms;
+ struct kobj_attribute hp_dw_count;
+ struct attribute_group attrib_group;
+};
+
+struct msm_mpd_scm_data {
+ enum msm_dcvs_scm_event event;
+ int nr;
+};
+
+struct mpdecision {
+ uint32_t enabled;
+ atomic_t algo_cpu_mask;
+ uint32_t rq_avg_poll_ms;
+ uint32_t iowait_threshold_pct;
+ ktime_t next_update;
+ uint32_t slack_us;
+ struct msm_mpd_algo_param mp_param;
+ struct mpd_attrib attrib;
+ struct mutex lock;
+ struct task_struct *task;
+ struct task_struct *hptask;
+ struct hrtimer slack_timer;
+ struct msm_mpd_scm_data data;
+ int hpupdate;
+ wait_queue_head_t wait_q;
+ wait_queue_head_t wait_hpq;
+};
+
+struct hp_latency {
+ int hp_up_max_ms;
+ int hp_up_ms;
+ int hp_up_count;
+ int hp_dw_max_ms;
+ int hp_dw_ms;
+ int hp_dw_count;
+};
+
+static DEFINE_PER_CPU(struct hrtimer, rq_avg_poll_timer);
+static DEFINE_SPINLOCK(rq_avg_lock);
+
+enum {
+ MSM_MPD_DEBUG_NOTIFIER = BIT(0),
+ MSM_MPD_CORE_STATUS = BIT(1),
+ MSM_MPD_SLACK_TIMER = BIT(2),
+};
+
+enum {
+ HPUPDATE_WAITING = 0, /* we are waiting for cpumask update */
+ HPUPDATE_SCHEDULED = 1, /* we are in the process of hotplugging */
+ HPUPDATE_IN_PROGRESS = 2, /* we are in the process of hotplugging */
+};
+
+static int msm_mpd_enabled = 1;
+module_param_named(enabled, msm_mpd_enabled, int, S_IRUGO | S_IWUSR | S_IWGRP);
+
+static struct dentry *debugfs_base;
+static struct mpdecision msm_mpd;
+
+static struct hp_latency hp_latencies;
+
+static unsigned long last_nr;
+static int num_present_hundreds;
+
+#define RQ_AVG_INSIGNIFICANT_BITS 3
+static bool ok_to_update_tz(int nr, int last_nr)
+{
+ /*
+ * Exclude unnecessary TZ reports if run queue haven't changed much from
+ * the last reported value. The left shift by INSIGNIFICANT_BITS is to
+ * filter out small changes in the run queue average which won't cause
+ * a online cpu mask change. Also if the cpu online count does not match
+ * the count requested by TZ and we are not in the process of bringing
+ * cpus online as indicated by a HPUPDATE_IN_PROGRESS in msm_mpd.hpdata
+ */
+ return
+ (((nr >> RQ_AVG_INSIGNIFICANT_BITS)
+ != (last_nr >> RQ_AVG_INSIGNIFICANT_BITS))
+ || ((hweight32(atomic_read(&msm_mpd.algo_cpu_mask))
+ != num_online_cpus())
+ && (msm_mpd.hpupdate != HPUPDATE_IN_PROGRESS)));
+}
+
+static enum hrtimer_restart msm_mpd_rq_avg_poll_timer(struct hrtimer *timer)
+{
+ int nr, nr_iowait;
+ ktime_t curr_time = ktime_get();
+ unsigned long flags;
+ int cpu = smp_processor_id();
+ enum hrtimer_restart restart = HRTIMER_RESTART;
+
+ spin_lock_irqsave(&rq_avg_lock, flags);
+ /* If running on the wrong cpu, don't restart */
+ if (&per_cpu(rq_avg_poll_timer, cpu) != timer)
+ restart = HRTIMER_NORESTART;
+
+ if (ktime_to_ns(ktime_sub(curr_time, msm_mpd.next_update)) < 0)
+ goto out;
+
+ msm_mpd.next_update = ktime_add_ns(curr_time,
+ (msm_mpd.rq_avg_poll_ms * NSEC_PER_MSEC));
+
+ sched_get_nr_running_avg(&nr, &nr_iowait);
+
+ if ((nr_iowait >= msm_mpd.iowait_threshold_pct) && (nr < last_nr))
+ nr = last_nr;
+
+ if (nr > num_present_hundreds)
+ nr = num_present_hundreds;
+
+ if (ok_to_update_tz(nr, last_nr)) {
+ hrtimer_try_to_cancel(&msm_mpd.slack_timer);
+ msm_mpd.data.nr = nr;
+ msm_mpd.data.event = MSM_DCVS_SCM_RUNQ_UPDATE;
+ wake_up(&msm_mpd.wait_q);
+ last_nr = nr;
+ }
+
+out:
+ hrtimer_set_expires(timer, msm_mpd.next_update);
+ spin_unlock_irqrestore(&rq_avg_lock, flags);
+ /* set next expiration */
+ return restart;
+}
+
+static void bring_up_cpu(int cpu)
+{
+ int cpu_action_time_ms;
+ int time_taken_ms;
+ int ret, ret1, ret2;
+
+ cpu_action_time_ms = ktime_to_ms(ktime_get());
+ ret = cpu_up(cpu);
+ if (ret) {
+ pr_debug("Error %d online core %d\n", ret, cpu);
+ } else {
+ time_taken_ms = ktime_to_ms(ktime_get()) - cpu_action_time_ms;
+ if (time_taken_ms > hp_latencies.hp_up_max_ms)
+ hp_latencies.hp_up_max_ms = time_taken_ms;
+ if (time_taken_ms > 5)
+ pr_warn("cpu_up for cpu%d exceeded 5ms (%d)\n",
+ cpu, time_taken_ms);
+ hp_latencies.hp_up_ms += time_taken_ms;
+ hp_latencies.hp_up_count++;
+ ret = msm_dcvs_scm_event(
+ CPU_OFFSET + cpu,
+ MSM_DCVS_SCM_CORE_ONLINE,
+ cpufreq_get(cpu),
+ (uint32_t) time_taken_ms * USEC_PER_MSEC,
+ &ret1, &ret2);
+ if (ret)
+ pr_err("Error sending hotplug scm event err=%d\n", ret);
+ }
+}
+
+static void bring_down_cpu(int cpu)
+{
+ int cpu_action_time_ms;
+ int time_taken_ms;
+ int ret, ret1, ret2;
+
+ BUG_ON(cpu == 0);
+ cpu_action_time_ms = ktime_to_ms(ktime_get());
+ ret = cpu_down(cpu);
+ if (ret) {
+ pr_debug("Error %d offline" "core %d\n", ret, cpu);
+ } else {
+ time_taken_ms = ktime_to_ms(ktime_get()) - cpu_action_time_ms;
+ if (time_taken_ms > hp_latencies.hp_dw_max_ms)
+ hp_latencies.hp_dw_max_ms = time_taken_ms;
+ if (time_taken_ms > 5)
+ pr_warn("cpu_down for cpu%d exceeded 5ms (%d)\n",
+ cpu, time_taken_ms);
+ hp_latencies.hp_dw_ms += time_taken_ms;
+ hp_latencies.hp_dw_count++;
+ ret = msm_dcvs_scm_event(
+ CPU_OFFSET + cpu,
+ MSM_DCVS_SCM_CORE_OFFLINE,
+ (uint32_t) time_taken_ms * USEC_PER_MSEC,
+ 0,
+ &ret1, &ret2);
+ if (ret)
+ pr_err("Error sending hotplug scm event err=%d\n", ret);
+ }
+}
+
+static int __ref msm_mpd_update_scm(enum msm_dcvs_scm_event event, int nr)
+{
+ int ret = 0;
+ uint32_t req_cpu_mask = 0;
+ uint32_t slack_us = 0;
+ uint32_t param0 = 0;
+
+ if (event == MSM_DCVS_SCM_RUNQ_UPDATE)
+ param0 = nr;
+
+ ret = msm_dcvs_scm_event(0, event, param0, 0,
+ &req_cpu_mask, &slack_us);
+
+ if (ret) {
+ pr_err("Error (%d) sending event %d, param %d\n", ret, event,
+ param0);
+ return ret;
+ }
+
+ msm_mpd.slack_us = slack_us;
+ atomic_set(&msm_mpd.algo_cpu_mask, req_cpu_mask);
+ msm_mpd.hpupdate = HPUPDATE_SCHEDULED;
+ wake_up(&msm_mpd.wait_hpq);
+
+ /* Start MP Decision slack timer */
+ if (slack_us) {
+ hrtimer_cancel(&msm_mpd.slack_timer);
+ ret = hrtimer_start(&msm_mpd.slack_timer,
+ ktime_set(0, slack_us * NSEC_PER_USEC),
+ HRTIMER_MODE_REL_PINNED);
+ if (ret)
+ pr_err("Failed to register slack timer (%d) %d\n",
+ slack_us, ret);
+ }
+
+ return ret;
+}
+
+static enum hrtimer_restart msm_mpd_slack_timer(struct hrtimer *timer)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&rq_avg_lock, flags);
+ if (msm_mpd.data.event == MSM_DCVS_SCM_RUNQ_UPDATE)
+ goto out;
+
+ msm_mpd.data.nr = 0;
+ msm_mpd.data.event = MSM_DCVS_SCM_MPD_QOS_TIMER_EXPIRED;
+ wake_up(&msm_mpd.wait_q);
+out:
+ spin_unlock_irqrestore(&rq_avg_lock, flags);
+ return HRTIMER_NORESTART;
+}
+
+static int msm_mpd_idle_notifier(struct notifier_block *self,
+ unsigned long cmd, void *v)
+{
+ int cpu = smp_processor_id();
+ unsigned long flags;
+
+ switch (cmd) {
+ case CPU_PM_EXIT:
+ spin_lock_irqsave(&rq_avg_lock, flags);
+ hrtimer_start(&per_cpu(rq_avg_poll_timer, cpu),
+ msm_mpd.next_update,
+ HRTIMER_MODE_ABS_PINNED);
+ spin_unlock_irqrestore(&rq_avg_lock, flags);
+ break;
+ case CPU_PM_ENTER:
+ hrtimer_cancel(&per_cpu(rq_avg_poll_timer, cpu));
+ break;
+ default:
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+static int msm_mpd_hotplug_notifier(struct notifier_block *self,
+ unsigned long action, void *hcpu)
+{
+ int cpu = (int)hcpu;
+ unsigned long flags;
+
+ switch (action & (~CPU_TASKS_FROZEN)) {
+ case CPU_STARTING:
+ spin_lock_irqsave(&rq_avg_lock, flags);
+ hrtimer_start(&per_cpu(rq_avg_poll_timer, cpu),
+ msm_mpd.next_update,
+ HRTIMER_MODE_ABS_PINNED);
+ spin_unlock_irqrestore(&rq_avg_lock, flags);
+ break;
+ default:
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block msm_mpd_idle_nb = {
+ .notifier_call = msm_mpd_idle_notifier,
+};
+
+static struct notifier_block msm_mpd_hotplug_nb = {
+ .notifier_call = msm_mpd_hotplug_notifier,
+};
+
+static int __cpuinit msm_mpd_do_hotplug(void *data)
+{
+ int *event = (int *)data;
+ static struct sched_param param = {.sched_priority = MAX_RT_PRIO - 1};
+ int cpu;
+
+ sched_setscheduler(current, SCHED_FIFO, ¶m);
+
+ while (1) {
+ wait_event(msm_mpd.wait_hpq, *event || kthread_should_stop());
+ if (kthread_should_stop())
+ break;
+
+ msm_mpd.hpupdate = HPUPDATE_IN_PROGRESS;
+ /*
+ * Bring online any offline cores, then offline any online
+ * cores. Whenever a core is off/onlined restart the procedure
+ * in case a new core is desired to be brought online in the
+ * mean time.
+ */
+restart:
+ for_each_possible_cpu(cpu) {
+ if ((atomic_read(&msm_mpd.algo_cpu_mask) & (1 << cpu))
+ && !cpu_online(cpu)) {
+ bring_up_cpu(cpu);
+ if (cpu_online(cpu))
+ goto restart;
+ }
+ }
+
+ for_each_possible_cpu(cpu) {
+ if (!(atomic_read(&msm_mpd.algo_cpu_mask) & (1 << cpu))
+ && cpu_online(cpu)) {
+ bring_down_cpu(cpu);
+ if (!cpu_online(cpu))
+ goto restart;
+ }
+ }
+ msm_mpd.hpupdate = HPUPDATE_WAITING;
+ }
+
+ return 0;
+}
+
+static int msm_mpd_do_update_scm(void *data)
+{
+ struct msm_mpd_scm_data *scm_data = (struct msm_mpd_scm_data *)data;
+ static struct sched_param param = {.sched_priority = MAX_RT_PRIO - 1};
+ unsigned long flags;
+ enum msm_dcvs_scm_event event;
+ int nr;
+
+ sched_setscheduler(current, SCHED_FIFO, ¶m);
+
+ while (1) {
+ wait_event(msm_mpd.wait_q,
+ msm_mpd.data.event == MSM_DCVS_SCM_MPD_QOS_TIMER_EXPIRED
+ || msm_mpd.data.event == MSM_DCVS_SCM_RUNQ_UPDATE
+ || kthread_should_stop());
+
+ if (kthread_should_stop())
+ break;
+
+ spin_lock_irqsave(&rq_avg_lock, flags);
+ event = scm_data->event;
+ nr = scm_data->nr;
+ scm_data->event = 0;
+ scm_data->nr = 0;
+ spin_unlock_irqrestore(&rq_avg_lock, flags);
+
+ msm_mpd_update_scm(event, nr);
+ }
+ return 0;
+}
+
+static int __ref msm_mpd_set_enabled(uint32_t enable)
+{
+ int ret = 0;
+ int ret0 = 0;
+ int ret1 = 0;
+ int cpu;
+ static uint32_t last_enable;
+
+ enable = (enable > 0) ? 1 : 0;
+ if (last_enable == enable)
+ return ret;
+
+ if (enable) {
+ ret = msm_mpd_scm_set_algo_params(&msm_mpd.mp_param);
+ if (ret) {
+ pr_err("Error(%d): msm_mpd_scm_set_algo_params failed\n",
+ ret);
+ return ret;
+ }
+ }
+
+ ret = msm_dcvs_scm_event(0, MSM_DCVS_SCM_MPD_ENABLE, enable, 0,
+ &ret0, &ret1);
+ if (ret) {
+ pr_err("Error(%d) %s MP Decision\n",
+ ret, (enable ? "enabling" : "disabling"));
+ } else {
+ last_enable = enable;
+ last_nr = 0;
+ }
+ if (enable) {
+ msm_mpd.next_update = ktime_add_ns(ktime_get(),
+ (msm_mpd.rq_avg_poll_ms * NSEC_PER_MSEC));
+ msm_mpd.task = kthread_run(msm_mpd_do_update_scm,
+ &msm_mpd.data, "msm_mpdecision");
+ if (IS_ERR(msm_mpd.task))
+ return -EFAULT;
+
+ msm_mpd.hptask = kthread_run(msm_mpd_do_hotplug,
+ &msm_mpd.hpupdate, "msm_hp");
+ if (IS_ERR(msm_mpd.hptask))
+ return -EFAULT;
+
+ for_each_online_cpu(cpu)
+ hrtimer_start(&per_cpu(rq_avg_poll_timer, cpu),
+ msm_mpd.next_update,
+ HRTIMER_MODE_ABS_PINNED);
+ cpu_pm_register_notifier(&msm_mpd_idle_nb);
+ register_cpu_notifier(&msm_mpd_hotplug_nb);
+ msm_mpd.enabled = 1;
+ } else {
+ for_each_online_cpu(cpu)
+ hrtimer_cancel(&per_cpu(rq_avg_poll_timer, cpu));
+ kthread_stop(msm_mpd.hptask);
+ kthread_stop(msm_mpd.task);
+ cpu_pm_unregister_notifier(&msm_mpd_idle_nb);
+ unregister_cpu_notifier(&msm_mpd_hotplug_nb);
+ msm_mpd.enabled = 0;
+ }
+
+ return ret;
+}
+
+static int msm_mpd_set_rq_avg_poll_ms(uint32_t val)
+{
+ /*
+ * No need to do anything. Just let the timer set its own next poll
+ * interval when it next fires.
+ */
+ msm_mpd.rq_avg_poll_ms = val;
+ return 0;
+}
+
+static int msm_mpd_set_iowait_threshold_pct(uint32_t val)
+{
+ /*
+ * No need to do anything. Just let the timer set its own next poll
+ * interval when it next fires.
+ */
+ msm_mpd.iowait_threshold_pct = val;
+ return 0;
+}
+
+#define MPD_ALGO_PARAM(_name, _param) \
+static ssize_t msm_mpd_attr_##_name##_show(struct kobject *kobj, \
+ struct kobj_attribute *attr, char *buf) \
+{ \
+ return snprintf(buf, PAGE_SIZE, "%d\n", _param); \
+} \
+static ssize_t msm_mpd_attr_##_name##_store(struct kobject *kobj, \
+ struct kobj_attribute *attr, const char *buf, size_t count) \
+{ \
+ int ret = 0; \
+ uint32_t val; \
+ uint32_t old_val; \
+ mutex_lock(&msm_mpd.lock); \
+ ret = kstrtouint(buf, 10, &val); \
+ if (ret) { \
+ pr_err("Invalid input %s for %s %d\n", \
+ buf, __stringify(_name), ret);\
+ return 0; \
+ } \
+ old_val = _param; \
+ _param = val; \
+ ret = msm_mpd_scm_set_algo_params(&msm_mpd.mp_param); \
+ if (ret) { \
+ pr_err("Error %d returned when setting algo param %s to %d\n",\
+ ret, __stringify(_name), val); \
+ _param = old_val; \
+ } \
+ mutex_unlock(&msm_mpd.lock); \
+ return count; \
+}
+
+#define MPD_PARAM(_name, _param) \
+static ssize_t msm_mpd_attr_##_name##_show(struct kobject *kobj, \
+ struct kobj_attribute *attr, char *buf) \
+{ \
+ return snprintf(buf, PAGE_SIZE, "%d\n", _param); \
+} \
+static ssize_t msm_mpd_attr_##_name##_store(struct kobject *kobj, \
+ struct kobj_attribute *attr, const char *buf, size_t count) \
+{ \
+ int ret = 0; \
+ uint32_t val; \
+ uint32_t old_val; \
+ mutex_lock(&msm_mpd.lock); \
+ ret = kstrtouint(buf, 10, &val); \
+ if (ret) { \
+ pr_err("Invalid input %s for %s %d\n", \
+ buf, __stringify(_name), ret);\
+ return 0; \
+ } \
+ old_val = _param; \
+ ret = msm_mpd_set_##_name(val); \
+ if (ret) { \
+ pr_err("Error %d returned when setting algo param %s to %d\n",\
+ ret, __stringify(_name), val); \
+ _param = old_val; \
+ } \
+ mutex_unlock(&msm_mpd.lock); \
+ return count; \
+}
+
+#define MPD_RW_ATTRIB(i, _name) \
+ msm_mpd.attrib._name.attr.name = __stringify(_name); \
+ msm_mpd.attrib._name.attr.mode = S_IRUGO | S_IWUSR; \
+ msm_mpd.attrib._name.show = msm_mpd_attr_##_name##_show; \
+ msm_mpd.attrib._name.store = msm_mpd_attr_##_name##_store; \
+ msm_mpd.attrib.attrib_group.attrs[i] = &msm_mpd.attrib._name.attr;
+
+MPD_PARAM(enabled, msm_mpd.enabled);
+MPD_PARAM(rq_avg_poll_ms, msm_mpd.rq_avg_poll_ms);
+MPD_PARAM(iowait_threshold_pct, msm_mpd.iowait_threshold_pct);
+MPD_ALGO_PARAM(em_win_size_min_us, msm_mpd.mp_param.em_win_size_min_us);
+MPD_ALGO_PARAM(em_win_size_max_us, msm_mpd.mp_param.em_win_size_max_us);
+MPD_ALGO_PARAM(em_max_util_pct, msm_mpd.mp_param.em_max_util_pct);
+MPD_ALGO_PARAM(mp_em_rounding_point_min,
+ msm_mpd.mp_param.mp_em_rounding_point_min);
+MPD_ALGO_PARAM(mp_em_rounding_point_max,
+ msm_mpd.mp_param.mp_em_rounding_point_max);
+MPD_ALGO_PARAM(online_util_pct_min, msm_mpd.mp_param.online_util_pct_min);
+MPD_ALGO_PARAM(online_util_pct_max, msm_mpd.mp_param.online_util_pct_max);
+MPD_ALGO_PARAM(slack_time_min_us, msm_mpd.mp_param.slack_time_min_us);
+MPD_ALGO_PARAM(slack_time_max_us, msm_mpd.mp_param.slack_time_max_us);
+MPD_ALGO_PARAM(hp_up_max_ms, hp_latencies.hp_up_max_ms);
+MPD_ALGO_PARAM(hp_up_ms, hp_latencies.hp_up_ms);
+MPD_ALGO_PARAM(hp_up_count, hp_latencies.hp_up_count);
+MPD_ALGO_PARAM(hp_dw_max_ms, hp_latencies.hp_dw_max_ms);
+MPD_ALGO_PARAM(hp_dw_ms, hp_latencies.hp_dw_ms);
+MPD_ALGO_PARAM(hp_dw_count, hp_latencies.hp_dw_count);
+
+static int __devinit msm_mpd_probe(struct platform_device *pdev)
+{
+ struct kobject *module_kobj = NULL;
+ int ret = 0;
+ const int attr_count = 19;
+ struct msm_mpd_algo_param *param = NULL;
+
+ param = pdev->dev.platform_data;
+
+ module_kobj = kset_find_obj(module_kset, KBUILD_MODNAME);
+ if (!module_kobj) {
+ pr_err("Cannot find kobject for module %s\n", KBUILD_MODNAME);
+ ret = -ENOENT;
+ goto done;
+ }
+
+ msm_mpd.attrib.attrib_group.attrs =
+ kzalloc(attr_count * sizeof(struct attribute *), GFP_KERNEL);
+ if (!msm_mpd.attrib.attrib_group.attrs) {
+ ret = -ENOMEM;
+ goto done;
+ }
+
+ MPD_RW_ATTRIB(0, enabled);
+ MPD_RW_ATTRIB(1, rq_avg_poll_ms);
+ MPD_RW_ATTRIB(2, iowait_threshold_pct);
+ MPD_RW_ATTRIB(3, em_win_size_min_us);
+ MPD_RW_ATTRIB(4, em_win_size_max_us);
+ MPD_RW_ATTRIB(5, em_max_util_pct);
+ MPD_RW_ATTRIB(6, mp_em_rounding_point_min);
+ MPD_RW_ATTRIB(7, mp_em_rounding_point_max);
+ MPD_RW_ATTRIB(8, online_util_pct_min);
+ MPD_RW_ATTRIB(9, online_util_pct_max);
+ MPD_RW_ATTRIB(10, slack_time_min_us);
+ MPD_RW_ATTRIB(11, slack_time_max_us);
+ MPD_RW_ATTRIB(12, hp_up_max_ms);
+ MPD_RW_ATTRIB(13, hp_up_ms);
+ MPD_RW_ATTRIB(14, hp_up_count);
+ MPD_RW_ATTRIB(15, hp_dw_max_ms);
+ MPD_RW_ATTRIB(16, hp_dw_ms);
+ MPD_RW_ATTRIB(17, hp_dw_count);
+
+ msm_mpd.attrib.attrib_group.attrs[18] = NULL;
+ ret = sysfs_create_group(module_kobj, &msm_mpd.attrib.attrib_group);
+ if (ret)
+ pr_err("Unable to create sysfs objects :%d\n", ret);
+
+ msm_mpd.rq_avg_poll_ms = DEFAULT_RQ_AVG_POLL_MS;
+
+ memcpy(&msm_mpd.mp_param, param, sizeof(struct msm_mpd_algo_param));
+
+ debugfs_base = debugfs_create_dir("msm_mpdecision", NULL);
+ if (!debugfs_base) {
+ pr_err("Cannot create debugfs base msm_mpdecision\n");
+ ret = -ENOENT;
+ goto done;
+ }
+
+done:
+ if (ret && debugfs_base)
+ debugfs_remove(debugfs_base);
+
+ return ret;
+}
+
+static int __devexit msm_mpd_remove(struct platform_device *pdev)
+{
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+static struct platform_driver msm_mpd_driver = {
+ .probe = msm_mpd_probe,
+ .remove = __devexit_p(msm_mpd_remove),
+ .driver = {
+ .name = "msm_mpdecision",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init msm_mpdecision_init(void)
+{
+ int cpu;
+ if (!msm_mpd_enabled) {
+ pr_info("Not enabled\n");
+ return 0;
+ }
+
+ num_present_hundreds = 100 * num_present_cpus();
+
+ hrtimer_init(&msm_mpd.slack_timer, CLOCK_MONOTONIC,
+ HRTIMER_MODE_REL_PINNED);
+ msm_mpd.slack_timer.function = msm_mpd_slack_timer;
+
+ for_each_possible_cpu(cpu) {
+ hrtimer_init(&per_cpu(rq_avg_poll_timer, cpu),
+ CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED);
+ per_cpu(rq_avg_poll_timer, cpu).function
+ = msm_mpd_rq_avg_poll_timer;
+ }
+ mutex_init(&msm_mpd.lock);
+ init_waitqueue_head(&msm_mpd.wait_q);
+ init_waitqueue_head(&msm_mpd.wait_hpq);
+ return platform_driver_register(&msm_mpd_driver);
+}
+late_initcall(msm_mpdecision_init);
diff --git a/arch/arm/mach-msm/peripheral-loader.h b/arch/arm/mach-msm/peripheral-loader.h
index e3b250b..405b73f 100644
--- a/arch/arm/mach-msm/peripheral-loader.h
+++ b/arch/arm/mach-msm/peripheral-loader.h
@@ -55,7 +55,15 @@
struct pil_device;
+#ifdef CONFIG_MSM_PIL
extern struct pil_device *msm_pil_register(struct pil_desc *desc);
extern void msm_pil_unregister(struct pil_device *pil);
+#else
+static inline struct pil_device *msm_pil_register(struct pil_desc *desc)
+{
+ return NULL;
+}
+static inline void msm_pil_unregister(struct pil_device *pil) { }
+#endif
#endif
diff --git a/arch/arm/mach-msm/pil-gss.c b/arch/arm/mach-msm/pil-gss.c
index 73248db..bccbce2 100644
--- a/arch/arm/mach-msm/pil-gss.c
+++ b/arch/arm/mach-msm/pil-gss.c
@@ -21,15 +21,22 @@
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/smp.h>
+#include <linux/miscdevice.h>
+#include <linux/reboot.h>
+#include <linux/interrupt.h>
#include <mach/msm_iomap.h>
#include <mach/msm_xo.h>
#include <mach/socinfo.h>
#include <mach/msm_bus_board.h>
#include <mach/msm_bus.h>
+#include <mach/subsystem_restart.h>
+#include <mach/peripheral-loader.h>
#include "peripheral-loader.h"
#include "scm-pas.h"
+#include "smd_private.h"
+#include "ramdump.h"
#define GSS_CSR_AHB_CLK_SEL 0x0
#define GSS_CSR_RESET 0x4
@@ -63,6 +70,14 @@
unsigned long start_addr;
struct clk *xo;
struct pil_device *pil;
+ struct miscdevice misc_dev;
+ struct subsys_device *subsys;
+ struct subsys_desc subsys_desc;
+ int crash_shutdown;
+ int irq;
+ void *pil_handle;
+ struct ramdump_device *ramdump_dev;
+ struct ramdump_device *smem_ramdump_dev;
};
static int pil_gss_init_image(struct pil_desc *pil, const u8 *metadata,
@@ -308,11 +323,160 @@
.proxy_unvote = remove_gss_proxy_votes,
};
+#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 restart_gss(struct gss_data *drv)
+{
+ log_gss_sfr();
+ subsystem_restart_dev(drv->subsys);
+}
+
+static void smsm_state_cb(void *data, uint32_t old_state, uint32_t new_state)
+{
+ struct gss_data *drv = data;
+
+ /* Ignore if we're the one that set SMSM_RESET */
+ if (drv->crash_shutdown)
+ return;
+
+ if (new_state & SMSM_RESET) {
+ pr_err("GSS SMSM state changed to SMSM_RESET.\n"
+ "Probable err_fatal on the GSS. "
+ "Calling subsystem restart...\n");
+ restart_gss(drv);
+ }
+}
+
+static int gss_shutdown(const struct subsys_desc *desc)
+{
+ struct gss_data *drv = container_of(desc, struct gss_data, subsys_desc);
+
+ pil_force_shutdown("gss");
+ disable_irq_nosync(drv->irq);
+
+ return 0;
+}
+
+static int gss_powerup(const struct subsys_desc *desc)
+{
+ struct gss_data *drv = container_of(desc, struct gss_data, subsys_desc);
+
+ pil_force_boot("gss");
+ enable_irq(drv->irq);
+ return 0;
+}
+
+void gss_crash_shutdown(const struct subsys_desc *desc)
+{
+ struct gss_data *drv = container_of(desc, struct gss_data, subsys_desc);
+
+ drv->crash_shutdown = 1;
+ 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},
+};
+
+static int gss_ramdump(int enable, const struct subsys_desc *desc)
+{
+ 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;
+ }
+
+ 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;
+ }
+ }
+
+ return 0;
+}
+
+static irqreturn_t gss_wdog_bite_irq(int irq, void *dev_id)
+{
+ struct gss_data *drv = dev_id;
+
+ pr_err("Watchdog bite received from GSS!\n");
+ restart_gss(drv);
+
+ return IRQ_HANDLED;
+}
+
+static int gss_open(struct inode *inode, struct file *filp)
+{
+ void *ret;
+ struct miscdevice *c = filp->private_data;
+ struct gss_data *drv = container_of(c, struct gss_data, misc_dev);
+
+ drv->pil_handle = ret = pil_get("gss");
+ if (!ret)
+ pr_debug("%s - pil_get returned NULL\n", __func__);
+
+ return 0;
+}
+
+static int gss_release(struct inode *inode, struct file *filp)
+{
+ struct miscdevice *c = filp->private_data;
+ struct gss_data *drv = container_of(c, struct gss_data, misc_dev);
+
+ pil_put(drv->pil_handle);
+ pr_debug("%s pil_put called on GSS\n", __func__);
+
+ return 0;
+}
+
+const struct file_operations gss_file_ops = {
+ .open = gss_open,
+ .release = gss_release,
+ .owner = THIS_MODULE,
+};
+
static int __devinit pil_gss_probe(struct platform_device *pdev)
{
struct gss_data *drv;
struct resource *res;
struct pil_desc *desc;
+ int ret;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
@@ -344,6 +508,10 @@
if (IS_ERR(drv->xo))
return PTR_ERR(drv->xo);
+ drv->irq = platform_get_irq(pdev, 0);
+ if (drv->irq < 0)
+ return drv->irq;
+
desc->name = "gss";
desc->dev = &pdev->dev;
desc->owner = THIS_MODULE;
@@ -363,13 +531,71 @@
if (IS_ERR(drv->pil)) {
return PTR_ERR(drv->pil);
}
+
+ ret = smsm_state_cb_register(SMSM_MODEM_STATE, SMSM_RESET,
+ smsm_state_cb, drv);
+ if (ret < 0)
+ dev_warn(&pdev->dev, "Unable to register SMSM callback\n");
+
+ drv->subsys_desc.name = "gss";
+ drv->subsys_desc.shutdown = gss_shutdown;
+ drv->subsys_desc.powerup = gss_powerup;
+ drv->subsys_desc.ramdump = gss_ramdump;
+ drv->subsys_desc.crash_shutdown = gss_crash_shutdown;
+
+ drv->subsys = subsys_register(&drv->subsys_desc);
+ if (IS_ERR(drv->subsys)) {
+ ret = PTR_ERR(drv->subsys);
+ goto err_subsys;
+ }
+
+ drv->misc_dev.minor = MISC_DYNAMIC_MINOR;
+ drv->misc_dev.name = "gss";
+ drv->misc_dev.fops = &gss_file_ops;
+ ret = misc_register(&drv->misc_dev);
+ if (ret)
+ goto err_misc;
+
+ drv->ramdump_dev = create_ramdump_device("gss");
+ if (!drv->ramdump_dev) {
+ ret = -ENOMEM;
+ goto err_ramdump;
+ }
+
+ drv->smem_ramdump_dev = create_ramdump_device("smem-gss");
+ if (!drv->smem_ramdump_dev) {
+ ret = -ENOMEM;
+ goto err_smem;
+ }
+
+ ret = devm_request_irq(&pdev->dev, drv->irq, gss_wdog_bite_irq,
+ IRQF_TRIGGER_RISING, "gss_a5_wdog", drv);
+ if (ret < 0)
+ goto err;
return 0;
+err:
+ destroy_ramdump_device(drv->smem_ramdump_dev);
+err_smem:
+ destroy_ramdump_device(drv->ramdump_dev);
+err_ramdump:
+ misc_deregister(&drv->misc_dev);
+err_misc:
+ subsys_unregister(drv->subsys);
+err_subsys:
+ msm_pil_unregister(drv->pil);
+ return ret;
}
static int __devexit pil_gss_remove(struct platform_device *pdev)
{
struct gss_data *drv = platform_get_drvdata(pdev);
+
+ destroy_ramdump_device(drv->smem_ramdump_dev);
+ destroy_ramdump_device(drv->ramdump_dev);
+ misc_deregister(&drv->misc_dev);
+ subsys_unregister(drv->subsys);
msm_pil_unregister(drv->pil);
+
return 0;
}
diff --git a/arch/arm/mach-msm/pil-q6v3.c b/arch/arm/mach-msm/pil-q6v3.c
index 28b9dee..1a226de 100644
--- a/arch/arm/mach-msm/pil-q6v3.c
+++ b/arch/arm/mach-msm/pil-q6v3.c
@@ -19,9 +19,15 @@
#include <linux/elf.h>
#include <linux/err.h>
#include <linux/clk.h>
+#include <linux/workqueue.h>
+#include <linux/interrupt.h>
#include <mach/msm_iomap.h>
+#include <mach/subsystem_restart.h>
+#include <mach/scm.h>
+#include <mach/peripheral-loader.h>
+#include "ramdump.h"
#include "peripheral-loader.h"
#include "scm-pas.h"
@@ -60,11 +66,34 @@
#define Q6_STRAP_TCM_BASE (0x28C << 15)
#define Q6_STRAP_TCM_CONFIG 0x28B
+#define SCM_Q6_NMI_CMD 0x1
+
+/**
+ * struct q6v3_data - LPASS driver data
+ * @base: register base
+ * @wk_base: wakeup register base
+ * @wd_base: watchdog register base
+ * @start_addr: address that processor starts running at
+ * @irq: watchdog irq
+ * @pil: peripheral handle
+ * @subsys: subsystem restart handle
+ * @subsys_desc: subsystem restart descriptor
+ * @fatal_wrk: fatal error workqueue
+ * @pll: pll clock handle
+ * @ramdump_dev: ramdump device
+ */
struct q6v3_data {
void __iomem *base;
+ void __iomem *wk_base;
+ void __iomem *wd_base;
unsigned long start_addr;
+ int irq;
struct pil_device *pil;
+ struct subsys_device *subsys;
+ struct subsys_desc subsys_desc;
+ struct work_struct fatal_wrk;
struct clk *pll;
+ struct ramdump_device *ramdump_dev;
};
static int pil_q6v3_init_image(struct pil_desc *pil, const u8 *metadata,
@@ -198,11 +227,96 @@
.proxy_unvote = pil_q6v3_remove_proxy_votes,
};
+static void q6_fatal_fn(struct work_struct *work)
+{
+ struct q6v3_data *drv = container_of(work, struct q6v3_data, fatal_wrk);
+
+ pr_err("Watchdog bite received from Q6!\n");
+ subsystem_restart_dev(drv->subsys);
+ enable_irq(drv->irq);
+}
+
+static void send_q6_nmi(struct q6v3_data *drv)
+{
+ /* Send NMI to QDSP6 via an SCM call. */
+ scm_call_atomic1(SCM_SVC_UTIL, SCM_Q6_NMI_CMD, 0x1);
+
+ /* Wakeup the Q6 */
+ writel_relaxed(0x2000, drv->wk_base + 0x1c);
+ /* Q6 requires atleast 100ms to dump caches etc.*/
+ mdelay(100);
+ pr_info("Q6 NMI was sent.\n");
+}
+
+static int lpass_q6_shutdown(const struct subsys_desc *subsys)
+{
+ struct q6v3_data *drv;
+
+ drv = container_of(subsys, struct q6v3_data, subsys_desc);
+ send_q6_nmi(drv);
+ writel_relaxed(0x0, drv->wd_base + 0x24);
+ mb();
+
+ pil_force_shutdown("q6");
+ disable_irq_nosync(drv->irq);
+
+ return 0;
+}
+
+static int lpass_q6_powerup(const struct subsys_desc *subsys)
+{
+ struct q6v3_data *drv;
+ int ret;
+
+ drv = container_of(subsys, struct q6v3_data, subsys_desc);
+ ret = pil_force_boot("q6");
+ enable_irq(drv->irq);
+ 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
+ return 0;
+}
+
+static void lpass_q6_crash_shutdown(const struct subsys_desc *subsys)
+{
+ struct q6v3_data *drv;
+
+ drv = container_of(subsys, struct q6v3_data, subsys_desc);
+ send_q6_nmi(drv);
+}
+
+static irqreturn_t lpass_wdog_bite_irq(int irq, void *dev_id)
+{
+ int ret;
+ struct q6v3_data *drv = dev_id;
+
+ ret = schedule_work(&drv->fatal_wrk);
+ disable_irq_nosync(drv->irq);
+
+ return IRQ_HANDLED;
+}
+
static int __devinit pil_q6v3_driver_probe(struct platform_device *pdev)
{
struct q6v3_data *drv;
struct resource *res;
struct pil_desc *desc;
+ int ret;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
@@ -217,14 +331,34 @@
if (!drv->base)
return -ENOMEM;
- desc = devm_kzalloc(&pdev->dev, sizeof(*desc), GFP_KERNEL);
- if (!drv)
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (!res)
+ return -EINVAL;
+
+ drv->wk_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+ if (!drv->wk_base)
return -ENOMEM;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+ if (!res)
+ return -EINVAL;
+
+ drv->wd_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+ if (!drv->wd_base)
+ return -ENOMEM;
+
+ drv->irq = platform_get_irq(pdev, 0);
+ if (drv->irq < 0)
+ return drv->irq;
+
drv->pll = devm_clk_get(&pdev->dev, "pll4");
if (IS_ERR(drv->pll))
return PTR_ERR(drv->pll);
+ desc = devm_kzalloc(&pdev->dev, sizeof(*desc), GFP_KERNEL);
+ if (!drv)
+ return -ENOMEM;
+
desc->name = "q6";
desc->dev = &pdev->dev;
desc->owner = THIS_MODULE;
@@ -239,15 +373,51 @@
}
drv->pil = msm_pil_register(desc);
- if (IS_ERR(drv->pil)) {
+ if (IS_ERR(drv->pil))
return PTR_ERR(drv->pil);
+
+ drv->subsys_desc.name = "lpass";
+ drv->subsys_desc.shutdown = lpass_q6_shutdown;
+ drv->subsys_desc.powerup = lpass_q6_powerup;
+ drv->subsys_desc.ramdump = lpass_q6_ramdump;
+ drv->subsys_desc.crash_shutdown = lpass_q6_crash_shutdown;
+
+ INIT_WORK(&drv->fatal_wrk, q6_fatal_fn);
+
+ drv->ramdump_dev = create_ramdump_device("lpass");
+ if (!drv->ramdump_dev) {
+ ret = -ENOMEM;
+ goto err_ramdump;
}
+
+ drv->subsys = subsys_register(&drv->subsys_desc);
+ if (IS_ERR(drv->subsys)) {
+ ret = PTR_ERR(drv->subsys);
+ goto err_subsys;
+ }
+
+ ret = devm_request_irq(&pdev->dev, drv->irq, lpass_wdog_bite_irq,
+ IRQF_TRIGGER_RISING, "lpass_wdog", drv);
+ if (ret) {
+ dev_err(&pdev->dev, "Unable to request wdog irq.\n");
+ goto err_irq;
+ }
+
return 0;
+err_irq:
+ subsys_unregister(drv->subsys);
+err_subsys:
+ destroy_ramdump_device(drv->ramdump_dev);
+err_ramdump:
+ msm_pil_unregister(drv->pil);
+ return ret;
}
static int __devexit pil_q6v3_driver_exit(struct platform_device *pdev)
{
struct q6v3_data *drv = platform_get_drvdata(pdev);
+ subsys_unregister(drv->subsys);
+ destroy_ramdump_device(drv->ramdump_dev);
msm_pil_unregister(drv->pil);
return 0;
}
diff --git a/arch/arm/mach-msm/pil-riva.c b/arch/arm/mach-msm/pil-riva.c
index 3040a31..dbb4408 100644
--- a/arch/arm/mach-msm/pil-riva.c
+++ b/arch/arm/mach-msm/pil-riva.c
@@ -20,11 +20,17 @@
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/wcnss_wlan.h>
#include <mach/msm_iomap.h>
+#include <mach/subsystem_restart.h>
+#include <mach/peripheral-loader.h>
#include "peripheral-loader.h"
#include "scm-pas.h"
+#include "ramdump.h"
+#include "smd_private.h"
#define RIVA_PMU_A2XB_CFG 0xB8
#define RIVA_PMU_A2XB_CFG_EN BIT(0)
@@ -82,6 +88,13 @@
struct clk *xo;
struct regulator *pll_supply;
struct pil_device *pil;
+ int irq;
+ int crash;
+ int rst_in_progress;
+ struct subsys_device *subsys;
+ struct subsys_desc subsys_desc;
+ struct delayed_work cancel_work;
+ struct ramdump_device *ramdump_dev;
};
static bool cxo_is_needed(struct riva_data *drv)
@@ -272,6 +285,160 @@
.proxy_unvote = pil_riva_remove_proxy_vote,
};
+static int enable_riva_ssr;
+
+static int enable_riva_ssr_set(const char *val, struct kernel_param *kp)
+{
+ int ret;
+
+ ret = param_set_int(val, kp);
+ if (ret)
+ return ret;
+
+ if (enable_riva_ssr)
+ pr_info("Subsystem restart activated for riva.\n");
+
+ return 0;
+}
+module_param_call(enable_riva_ssr, enable_riva_ssr_set, param_get_int,
+ &enable_riva_ssr, S_IRUGO | S_IWUSR);
+
+static void smsm_state_cb_hdlr(void *data, uint32_t old_state,
+ uint32_t new_state)
+{
+ struct riva_data *drv = data;
+ char *smem_reset_reason;
+ char buffer[81];
+ unsigned smem_reset_size;
+ unsigned size;
+
+ drv->crash = true;
+ if (!(new_state & SMSM_RESET))
+ return;
+
+ if (drv->rst_in_progress) {
+ pr_err("riva: Ignoring smsm reset req, restart in progress\n");
+ return;
+ }
+
+ pr_err("riva: smsm state changed to smsm reset\n");
+
+ smem_reset_reason = smem_get_entry(SMEM_SSR_REASON_WCNSS0,
+ &smem_reset_size);
+
+ if (!smem_reset_reason || !smem_reset_size) {
+ pr_err("wcnss subsystem failure reason:\n"
+ "(unknown, smem_get_entry failed)");
+ } else if (!smem_reset_reason[0]) {
+ pr_err("wcnss subsystem failure reason:\n"
+ "(unknown, init string found)");
+ } else {
+ size = smem_reset_size < sizeof(buffer) ? smem_reset_size :
+ (sizeof(buffer) - 1);
+ memcpy(buffer, smem_reset_reason, size);
+ buffer[size] = '\0';
+ pr_err("wcnss subsystem failure reason: %s\n", buffer);
+ memset(smem_reset_reason, 0, smem_reset_size);
+ wmb();
+ }
+
+ drv->rst_in_progress = 1;
+ subsystem_restart_dev(drv->subsys);
+}
+
+static irqreturn_t riva_wdog_bite_irq_hdlr(int irq, void *dev_id)
+{
+ struct riva_data *drv = dev_id;
+
+ drv->crash = true;
+ if (drv->rst_in_progress) {
+ pr_err("Ignoring riva bite irq, restart in progress\n");
+ return IRQ_HANDLED;
+ }
+ if (!enable_riva_ssr)
+ panic("Watchdog bite received from Riva");
+
+ drv->rst_in_progress = 1;
+ subsystem_restart_dev(drv->subsys);
+
+ return IRQ_HANDLED;
+}
+
+static void riva_post_bootup(struct work_struct *work)
+{
+ struct platform_device *pdev = wcnss_get_platform_device();
+ struct wcnss_wlan_config *pwlanconfig = wcnss_get_wlan_config();
+
+ wcnss_wlan_power(&pdev->dev, pwlanconfig, WCNSS_WLAN_SWITCH_OFF);
+}
+
+static int riva_shutdown(const struct subsys_desc *desc)
+{
+ struct riva_data *drv;
+
+ drv = container_of(desc, struct riva_data, subsys_desc);
+ pil_force_shutdown("wcnss");
+ flush_delayed_work(&drv->cancel_work);
+ wcnss_flush_delayed_boot_votes();
+ disable_irq_nosync(drv->irq);
+
+ return 0;
+}
+
+static int riva_powerup(const struct subsys_desc *desc)
+{
+ struct riva_data *drv;
+ struct platform_device *pdev = wcnss_get_platform_device();
+ struct wcnss_wlan_config *pwlanconfig = wcnss_get_wlan_config();
+ int ret = 0;
+
+ drv = container_of(desc, struct riva_data, subsys_desc);
+ if (pdev && pwlanconfig) {
+ ret = wcnss_wlan_power(&pdev->dev, pwlanconfig,
+ WCNSS_WLAN_SWITCH_ON);
+ if (!ret)
+ pil_force_boot("wcnss");
+ }
+ drv->rst_in_progress = 0;
+ enable_irq(drv->irq);
+ schedule_delayed_work(&drv->cancel_work, msecs_to_jiffies(5000));
+
+ 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
+ return 0;
+}
+
+/* Riva crash handler */
+static void riva_crash_shutdown(const struct subsys_desc *desc)
+{
+ struct riva_data *drv;
+
+ drv = container_of(desc, struct riva_data, subsys_desc);
+ pr_err("riva crash shutdown %d\n", drv->crash);
+ if (drv->crash != true)
+ smsm_change_state(SMSM_APPS_STATE, SMSM_RESET, SMSM_RESET);
+}
+
static int __devinit pil_riva_probe(struct platform_device *pdev)
{
struct riva_data *drv;
@@ -317,6 +484,10 @@
}
}
+ drv->irq = platform_get_irq(pdev, 0);
+ if (drv->irq < 0)
+ return drv->irq;
+
desc->name = "wcnss";
desc->dev = &pdev->dev;
desc->owner = THIS_MODULE;
@@ -337,13 +508,60 @@
drv->pil = msm_pil_register(desc);
if (IS_ERR(drv->pil))
return PTR_ERR(drv->pil);
+
+ ret = smsm_state_cb_register(SMSM_WCNSS_STATE, SMSM_RESET,
+ smsm_state_cb_hdlr, drv);
+ if (ret < 0)
+ goto err_smsm;
+
+ drv->subsys_desc.name = "wcnss";
+ drv->subsys_desc.shutdown = riva_shutdown;
+ drv->subsys_desc.powerup = riva_powerup;
+ drv->subsys_desc.ramdump = riva_ramdump;
+ drv->subsys_desc.crash_shutdown = riva_crash_shutdown;
+
+ INIT_DELAYED_WORK(&drv->cancel_work, riva_post_bootup);
+
+ drv->ramdump_dev = create_ramdump_device("riva");
+ if (!drv->ramdump_dev) {
+ ret = -ENOMEM;
+ goto err_ramdump;
+ }
+
+ drv->subsys = subsys_register(&drv->subsys_desc);
+ if (IS_ERR(drv->subsys)) {
+ ret = PTR_ERR(drv->subsys);
+ goto err_subsys;
+ }
+
+ ret = devm_request_irq(&pdev->dev, drv->irq, riva_wdog_bite_irq_hdlr,
+ IRQF_TRIGGER_HIGH, "riva_wdog", drv);
+ if (ret < 0)
+ goto err;
+
return 0;
+err:
+ subsys_unregister(drv->subsys);
+err_subsys:
+ destroy_ramdump_device(drv->ramdump_dev);
+err_ramdump:
+ smsm_state_cb_deregister(SMSM_WCNSS_STATE, SMSM_RESET,
+ smsm_state_cb_hdlr, drv);
+err_smsm:
+ msm_pil_unregister(drv->pil);
+ return ret;
}
static int __devexit pil_riva_remove(struct platform_device *pdev)
{
struct riva_data *drv = platform_get_drvdata(pdev);
+
+ subsys_unregister(drv->subsys);
+ destroy_ramdump_device(drv->ramdump_dev);
+ smsm_state_cb_deregister(SMSM_WCNSS_STATE, SMSM_RESET,
+ smsm_state_cb_hdlr, drv);
msm_pil_unregister(drv->pil);
+
return 0;
}
diff --git a/arch/arm/mach-msm/rpm-regulator-8960.c b/arch/arm/mach-msm/rpm-regulator-8960.c
index 8fe3571..c5c01c2 100644
--- a/arch/arm/mach-msm/rpm-regulator-8960.c
+++ b/arch/arm/mach-msm/rpm-regulator-8960.c
@@ -325,3 +325,32 @@
{
return &config;
}
+
+struct vreg_config *get_config_8960_pm8917(void)
+{
+ int i;
+
+ /*
+ * PM8917 regulators L24, L25, L26, L27, and L28 require CXO to be ON
+ * while they are enabled. These same regulators on PM8921 do not
+ * require CXO to be ON. Therefore, set the require_cxo flag for these
+ * regulators only when using PM8917.
+ *
+ * Do not apply the workaround to L24 (VDD_MX) because it is always on
+ * and using the TCXO workaround with it would result in additional
+ * latency during every Krait upscaling event.
+ */
+ for (i = 0; i < ARRAY_SIZE(vregs); i++) {
+ switch (vregs[i].id) {
+ case RPM_VREG_ID_PM8921_L25:
+ case RPM_VREG_ID_PM8921_L26:
+ case RPM_VREG_ID_PM8921_L27:
+ case RPM_VREG_ID_PM8921_L28:
+ vregs[i].requires_cxo = true;
+ default:
+ break;
+ }
+ }
+
+ return &config;
+}
diff --git a/arch/arm/mach-msm/rpm-regulator-private.h b/arch/arm/mach-msm/rpm-regulator-private.h
index d55bd73..703335f 100644
--- a/arch/arm/mach-msm/rpm-regulator-private.h
+++ b/arch/arm/mach-msm/rpm-regulator-private.h
@@ -158,11 +158,16 @@
#if defined(CONFIG_MSM_RPM_REGULATOR) && \
(defined(CONFIG_ARCH_MSM8960) || defined(CONFIG_ARCH_APQ8064))
struct vreg_config *get_config_8960(void);
+struct vreg_config *get_config_8960_pm8917(void);
#else
static inline struct vreg_config *get_config_8960(void)
{
return NULL;
}
+static inline struct vreg_config *get_config_8960_pm8917(void)
+{
+ return NULL;
+}
#endif
#if defined(CONFIG_MSM_RPM_REGULATOR) && defined(CONFIG_ARCH_MSM9615)
diff --git a/arch/arm/mach-msm/rpm-regulator-smd.c b/arch/arm/mach-msm/rpm-regulator-smd.c
index a8af9e7..9c621c4 100644
--- a/arch/arm/mach-msm/rpm-regulator-smd.c
+++ b/arch/arm/mach-msm/rpm-regulator-smd.c
@@ -1286,7 +1286,7 @@
}
}
- of_property_read_u32(node, "qcom,system_load", ®->system_load);
+ of_property_read_u32(node, "qcom,system-load", ®->system_load);
rpm_vreg_lock(rpm_vreg);
list_add(®->list, &rpm_vreg->reg_list);
diff --git a/arch/arm/mach-msm/rpm-regulator.c b/arch/arm/mach-msm/rpm-regulator.c
index 424a4fe..01543a2 100644
--- a/arch/arm/mach-msm/rpm-regulator.c
+++ b/arch/arm/mach-msm/rpm-regulator.c
@@ -63,6 +63,7 @@
[RPM_VREG_VERSION_9615] = get_config_9615,
[RPM_VREG_VERSION_8930] = get_config_8930,
[RPM_VREG_VERSION_8930_PM8917] = get_config_8930_pm8917,
+ [RPM_VREG_VERSION_8960_PM8917] = get_config_8960_pm8917,
};
static struct rpm_regulator_consumer_mapping *consumer_map;
diff --git a/arch/arm/mach-msm/scm-pas.h b/arch/arm/mach-msm/scm-pas.h
index dd24e20..8da1d75 100644
--- a/arch/arm/mach-msm/scm-pas.h
+++ b/arch/arm/mach-msm/scm-pas.h
@@ -25,8 +25,29 @@
PAS_VIDC,
};
+#ifdef CONFIG_MSM_PIL
extern int pas_init_image(enum pas_id id, const u8 *metadata, size_t size);
extern int pas_auth_and_reset(enum pas_id id);
extern int pas_shutdown(enum pas_id id);
extern int pas_supported(enum pas_id id);
+#else
+static inline int pas_init_image(enum pas_id id, const u8 *metadata,
+ size_t size)
+{
+ return 0;
+}
+static inline int pas_auth_and_reset(enum pas_id id)
+{
+ return 0;
+}
+static inline int pas_shutdown(enum pas_id id)
+{
+ return 0;
+}
+static inline int pas_supported(enum pas_id id)
+{
+ return 0;
+}
+#endif
+
#endif
diff --git a/arch/arm/mach-msm/wcnss-ssr-8960.c b/arch/arm/mach-msm/wcnss-ssr-8960.c
deleted file mode 100644
index 5516e30..0000000
--- a/arch/arm/mach-msm/wcnss-ssr-8960.c
+++ /dev/null
@@ -1,277 +0,0 @@
-/* Copyright (c) 2011-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/interrupt.h>
-#include <linux/reboot.h>
-#include <linux/workqueue.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/wcnss_wlan.h>
-#include <linux/err.h>
-#include <asm/mach-types.h>
-#include <mach/irqs.h>
-#include <mach/scm.h>
-#include <mach/subsystem_restart.h>
-#include <mach/subsystem_notif.h>
-#include <mach/peripheral-loader.h>
-#include "smd_private.h"
-#include "ramdump.h"
-
-#define MODULE_NAME "wcnss_8960"
-#define MAX_BUF_SIZE 0x51
-
-
-
-static struct delayed_work cancel_vote_work;
-static void *riva_ramdump_dev;
-static int riva_crash;
-static int ss_restart_inprogress;
-static int enable_riva_ssr;
-static struct subsys_device *riva_8960_dev;
-
-static void smsm_state_cb_hdlr(void *data, uint32_t old_state,
- uint32_t new_state)
-{
- char *smem_reset_reason;
- char buffer[MAX_BUF_SIZE];
- unsigned smem_reset_size;
- unsigned size;
-
- riva_crash = true;
-
- pr_err("%s: smsm state changed\n", MODULE_NAME);
-
- if (!(new_state & SMSM_RESET))
- return;
-
- if (ss_restart_inprogress) {
- pr_err("%s: Ignoring smsm reset req, restart in progress\n",
- MODULE_NAME);
- return;
- }
-
- if (!enable_riva_ssr)
- panic(MODULE_NAME ": SMSM reset request received from Riva");
-
- smem_reset_reason = smem_get_entry(SMEM_SSR_REASON_WCNSS0,
- &smem_reset_size);
-
- if (!smem_reset_reason || !smem_reset_size) {
- pr_err("%s: wcnss subsystem failure reason: %s\n",
- __func__, "(unknown, smem_get_entry failed)");
- } else if (!smem_reset_reason[0]) {
- pr_err("%s: wcnss subsystem failure reason: %s\n",
- __func__, "(unknown, init string found)");
- } else {
- size = smem_reset_size < MAX_BUF_SIZE ? smem_reset_size :
- (MAX_BUF_SIZE - 1);
- memcpy(buffer, smem_reset_reason, size);
- buffer[size] = '\0';
- pr_err("%s: wcnss subsystem failure reason: %s\n",
- __func__, buffer);
- memset(smem_reset_reason, 0, smem_reset_size);
- wmb();
- }
-
- ss_restart_inprogress = true;
- subsystem_restart_dev(riva_8960_dev);
-}
-
-static irqreturn_t riva_wdog_bite_irq_hdlr(int irq, void *dev_id)
-{
- riva_crash = true;
-
- if (ss_restart_inprogress) {
- pr_err("%s: Ignoring riva bite irq, restart in progress\n",
- MODULE_NAME);
- return IRQ_HANDLED;
- }
-
- if (!enable_riva_ssr)
- panic(MODULE_NAME ": Watchdog bite received from Riva");
-
- ss_restart_inprogress = true;
- subsystem_restart_dev(riva_8960_dev);
-
- return IRQ_HANDLED;
-}
-
-/* SMSM reset Riva */
-static void smsm_riva_reset(void)
-{
- /* per SS reset request bit is not available now,
- * all SS host modules are setting this bit
- * This is still under discussion*/
- smsm_change_state(SMSM_APPS_STATE, SMSM_RESET, SMSM_RESET);
-}
-
-static void riva_post_bootup(struct work_struct *work)
-{
- struct platform_device *pdev = wcnss_get_platform_device();
- struct wcnss_wlan_config *pwlanconfig = wcnss_get_wlan_config();
-
- pr_debug(MODULE_NAME ": Cancel APPS vote for Iris & Riva\n");
-
- wcnss_wlan_power(&pdev->dev, pwlanconfig,
- WCNSS_WLAN_SWITCH_OFF);
-}
-
-/* Subsystem handlers */
-static int riva_shutdown(const struct subsys_desc *subsys)
-{
- pil_force_shutdown("wcnss");
- flush_delayed_work(&cancel_vote_work);
- wcnss_flush_delayed_boot_votes();
- disable_irq_nosync(RIVA_APSS_WDOG_BITE_RESET_RDY_IRQ);
-
- return 0;
-}
-
-static int riva_powerup(const struct subsys_desc *subsys)
-{
- struct platform_device *pdev = wcnss_get_platform_device();
- struct wcnss_wlan_config *pwlanconfig = wcnss_get_wlan_config();
- int ret = -1;
-
- if (pdev && pwlanconfig)
- ret = wcnss_wlan_power(&pdev->dev, pwlanconfig,
- WCNSS_WLAN_SWITCH_ON);
- /* delay PIL operation, this SSR may be happening soon after kernel
- * resumes because of a SMSM RESET by Riva when APPS was suspended.
- * PIL fails to locate the images without this delay */
- if (!ret) {
- msleep(1000);
- pil_force_boot("wcnss");
- }
- ss_restart_inprogress = false;
- enable_irq(RIVA_APSS_WDOG_BITE_RESET_RDY_IRQ);
- schedule_delayed_work(&cancel_vote_work, msecs_to_jiffies(5000));
-
- return ret;
-}
-
-/* 5MB RAM segments for Riva SS */
-static struct ramdump_segment riva_segments[] = {{0x8f200000,
- 0x8f700000 - 0x8f200000} };
-
-static int riva_ramdump(int enable, const struct subsys_desc *subsys)
-{
- pr_debug("%s: enable[%d]\n", MODULE_NAME, enable);
- if (enable)
- return do_ramdump(riva_ramdump_dev,
- riva_segments,
- ARRAY_SIZE(riva_segments));
- else
- return 0;
-}
-
-/* Riva crash handler */
-static void riva_crash_shutdown(const struct subsys_desc *subsys)
-{
- pr_err("%s: crash shutdown : %d\n", MODULE_NAME, riva_crash);
- if (riva_crash != true)
- smsm_riva_reset();
-}
-
-static struct subsys_desc riva_8960 = {
- .name = "wcnss",
- .shutdown = riva_shutdown,
- .powerup = riva_powerup,
- .ramdump = riva_ramdump,
- .crash_shutdown = riva_crash_shutdown
-};
-
-static int enable_riva_ssr_set(const char *val, struct kernel_param *kp)
-{
- int ret;
-
- ret = param_set_int(val, kp);
- if (ret)
- return ret;
-
- if (enable_riva_ssr)
- pr_info(MODULE_NAME ": Subsystem restart activated for riva.\n");
-
- return 0;
-}
-
-module_param_call(enable_riva_ssr, enable_riva_ssr_set, param_get_int,
- &enable_riva_ssr, S_IRUGO | S_IWUSR);
-
-static int __init riva_restart_init(void)
-{
- riva_8960_dev = subsys_register(&riva_8960);
- if (IS_ERR(riva_8960_dev))
- return PTR_ERR(riva_8960_dev);
- return 0;
-}
-
-static int __init riva_ssr_module_init(void)
-{
- int ret;
-
- if (machine_is_mpq8064_hrd()) {
- pr_err("Riva not supported on this target\n");
- return 0;
- }
-
- ret = smsm_state_cb_register(SMSM_WCNSS_STATE, SMSM_RESET,
- smsm_state_cb_hdlr, 0);
- if (ret < 0) {
- pr_err("%s: Unable to register smsm callback for Riva Reset! %d\n",
- MODULE_NAME, ret);
- goto out;
- }
- ret = request_irq(RIVA_APSS_WDOG_BITE_RESET_RDY_IRQ,
- riva_wdog_bite_irq_hdlr, IRQF_TRIGGER_HIGH,
- "riva_wdog", NULL);
-
- if (ret < 0) {
- pr_err("%s: Unable to register for Riva bite interrupt (%d)\n",
- MODULE_NAME, ret);
- goto out;
- }
- ret = riva_restart_init();
- if (ret < 0) {
- pr_err("%s: Unable to register with ssr. (%d)\n",
- MODULE_NAME, ret);
- goto out;
- }
- riva_ramdump_dev = create_ramdump_device("riva");
- if (!riva_ramdump_dev) {
- pr_err("%s: Unable to create ramdump device.\n",
- MODULE_NAME);
- ret = -ENOMEM;
- goto out;
- }
- INIT_DELAYED_WORK(&cancel_vote_work, riva_post_bootup);
-
- pr_info("%s: module initialized\n", MODULE_NAME);
-out:
- return ret;
-}
-
-static void __exit riva_ssr_module_exit(void)
-{
- if (machine_is_mpq8064_hrd())
- return;
- subsys_unregister(riva_8960_dev);
- free_irq(RIVA_APSS_WDOG_BITE_RESET_RDY_IRQ, NULL);
-}
-
-module_init(riva_ssr_module_init);
-module_exit(riva_ssr_module_exit);
-
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/bluetooth/hci_ibs.c b/drivers/bluetooth/hci_ibs.c
index 6253605..acff5a5 100644
--- a/drivers/bluetooth/hci_ibs.c
+++ b/drivers/bluetooth/hci_ibs.c
@@ -254,13 +254,14 @@
struct ibs_struct *ibs = container_of(work, struct ibs_struct,
ws_awake_device);
struct hci_uart *hu = (struct hci_uart *)ibs->ibs_hu;
+ unsigned long flags;
BT_DBG(" %p ", hu);
/* Vote for serial clock */
ibs_msm_serial_clock_vote(HCI_IBS_TX_VOTE_CLOCK_ON, hu);
- spin_lock(&ibs->hci_ibs_lock);
+ spin_lock_irqsave(&ibs->hci_ibs_lock, flags);
/* send wake indication to device */
if (send_hci_ibs_cmd(HCI_IBS_WAKE_IND, hu) < 0)
@@ -271,7 +272,8 @@
/* start retransmit timer */
mod_timer(&ibs->wake_retrans_timer, jiffies + wake_retrans);
- spin_unlock(&ibs->hci_ibs_lock);
+ spin_unlock_irqrestore(&ibs->hci_ibs_lock, flags);
+
}
static void ibs_wq_awake_rx(struct work_struct *work)
@@ -279,12 +281,14 @@
struct ibs_struct *ibs = container_of(work, struct ibs_struct,
ws_awake_rx);
struct hci_uart *hu = (struct hci_uart *)ibs->ibs_hu;
+ unsigned long flags;
BT_DBG(" %p ", hu);
ibs_msm_serial_clock_vote(HCI_IBS_RX_VOTE_CLOCK_ON, hu);
- spin_lock(&ibs->hci_ibs_lock);
+ spin_lock_irqsave(&ibs->hci_ibs_lock, flags);
+
ibs->rx_ibs_state = HCI_IBS_RX_AWAKE;
/* Always acknowledge device wake up,
* sending IBS message doesn't count as TX ON
@@ -294,7 +298,8 @@
ibs->ibs_sent_wacks++; /* debug */
- spin_unlock(&ibs->hci_ibs_lock);
+ spin_unlock_irqrestore(&ibs->hci_ibs_lock, flags);
+
/* actually send the packets */
hci_uart_tx_wakeup(hu);
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 09da40c..5c6cdc6 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -1422,9 +1422,9 @@
INIT_WORK(&(driver->diag_clean_wcnss_reg_work),
diag_clean_wcnss_reg_fn);
diag_debugfs_init();
+ diag_masks_init();
diagfwd_init();
diagfwd_cntl_init();
- diag_masks_init();
driver->dci_state = diag_dci_init();
diag_sdio_fn(INIT);
diag_bridge_fn(INIT);
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index e0d40be..129ca7e 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -2163,6 +2163,9 @@
if (!adreno_dev->fast_hang_detect)
return 0;
+ if (device->ftbl->isidle(device))
+ return 0;
+
for (i = 0; i < hang_detect_regs_count; i++) {
if (hang_detect_regs[i] == 0)
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 664d519..5ba844a 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -1752,6 +1752,8 @@
if (result)
goto error;
+ entry->memdesc.priv |= param->flags & KGSL_MEMTYPE_MASK;
+
result = kgsl_mmu_map(private->pagetable,
&entry->memdesc,
GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index 0e1e100..54ba5ad 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -729,7 +729,8 @@
return 0;
gpuaddr = memdesc->gpuaddr;
- memdesc->priv |= KGSL_MEMFLAGS_GLOBAL;
+ memdesc->priv |= KGSL_MEMFLAGS_GLOBAL
+ | (KGSL_MEMTYPE_KERNEL << KGSL_MEMTYPE_SHIFT);
result = kgsl_mmu_map(pagetable, memdesc, protflags);
if (result)
diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c
index c2ce5c7..bdc5686 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.c
+++ b/drivers/gpu/msm/kgsl_sharedmem.c
@@ -540,7 +540,6 @@
memdesc->size = size;
memdesc->pagetable = pagetable;
- memdesc->priv = KGSL_MEMFLAGS_CACHED;
memdesc->ops = &kgsl_page_alloc_ops;
memdesc->sg = kgsl_sg_alloc(sglen);
diff --git a/drivers/gpu/msm/kgsl_sharedmem.h b/drivers/gpu/msm/kgsl_sharedmem.h
index de89ac1..5a6c4c2 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.h
+++ b/drivers/gpu/msm/kgsl_sharedmem.h
@@ -27,8 +27,6 @@
#define KGSL_CACHE_OP_FLUSH 0x02
#define KGSL_CACHE_OP_CLEAN 0x03
-/** Set if the memdesc describes cached memory */
-#define KGSL_MEMFLAGS_CACHED 0x00000001
/** Set if the memdesc is mapped into all pagetables */
#define KGSL_MEMFLAGS_GLOBAL 0x00000002
@@ -136,6 +134,7 @@
{
if (kgsl_mmu_get_mmutype() == KGSL_MMU_TYPE_NONE)
return kgsl_sharedmem_ebimem(memdesc, pagetable, size);
+ memdesc->priv |= (KGSL_MEMTYPE_KERNEL << KGSL_MEMTYPE_SHIFT);
return kgsl_sharedmem_page_alloc(memdesc, pagetable, size);
}
@@ -144,10 +143,17 @@
struct kgsl_pagetable *pagetable,
size_t size, unsigned int flags)
{
+ int ret;
+ unsigned int mask = (KGSL_MEMTYPE_MASK | KGSL_MEMFLAGS_GPUREADONLY);
if (kgsl_mmu_get_mmutype() == KGSL_MMU_TYPE_NONE)
- return kgsl_sharedmem_ebimem_user(memdesc, pagetable, size,
+ ret = kgsl_sharedmem_ebimem_user(memdesc, pagetable, size,
flags);
- return kgsl_sharedmem_page_alloc_user(memdesc, pagetable, size, flags);
+ else
+ ret = kgsl_sharedmem_page_alloc_user(memdesc, pagetable, size,
+ flags);
+ if (ret == 0)
+ memdesc->priv |= flags & mask;
+ return ret;
}
static inline int
diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c
index 2c95ef5..77922e2 100644
--- a/drivers/media/video/msm/msm_isp.c
+++ b/drivers/media/video/msm/msm_isp.c
@@ -711,8 +711,12 @@
int rc = -EINVAL;
void __user *argp = (void __user *)arg;
- struct v4l2_subdev *sd = pmctl->vfe_sdev;
-
+ struct v4l2_subdev *sd;
+ if (!pmctl->vfe_sdev) {
+ pr_err("%s vfe subdev is NULL\n", __func__);
+ return -ENXIO;
+ }
+ sd = pmctl->vfe_sdev;
D("%s: cmd %d\n", __func__, _IOC_NR(cmd));
switch (cmd) {
case MSM_CAM_IOCTL_CONFIG_VFE:
diff --git a/drivers/media/video/vcap_vp.c b/drivers/media/video/vcap_vp.c
index aa39aad..a017cf2 100644
--- a/drivers/media/video/vcap_vp.c
+++ b/drivers/media/video/vcap_vp.c
@@ -304,7 +304,7 @@
}
if (irq & 0x01000000) {
v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
- VCAP_VC_LINE_ERR_EVENT;
+ VCAP_VP_REG_W_ERR_EVENT;
v4l2_event_queue(dev->vfd, &v4l2_evt);
}
if (irq & 0x00020000) {
diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h
index b7d4c32..180a18a 100644
--- a/drivers/video/msm/mdp4.h
+++ b/drivers/video/msm/mdp4.h
@@ -306,10 +306,16 @@
uint32 is_fg; /* control alpha & color key */
uint32 srcp0_addr; /* interleave, luma */
uint32 srcp0_ystride;
+ struct file *srcp0_file;
+ int put0_need;
uint32 srcp1_addr; /* pseudoplanar, chroma plane */
uint32 srcp1_ystride;
+ struct file *srcp1_file;
+ int put1_need;
uint32 srcp2_addr; /* planar color 2*/
uint32 srcp2_ystride;
+ struct file *srcp2_file;
+ int put2_need;
uint32 srcp3_addr; /* alpha/color 3 */
uint32 srcp3_ystride;
uint32 fetch_plane;
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index 8f308c3..c7e811f 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -191,6 +191,19 @@
if (pipe == NULL)
return;
+ if (pipe->flags & MDP_MEMORY_ID_TYPE_FB) {
+ if (pipe->put0_need)
+ fput_light(pipe->srcp0_file, pipe->put0_need);
+ if (pipe->put1_need)
+ fput_light(pipe->srcp1_file, pipe->put1_need);
+ if (pipe->put2_need)
+ fput_light(pipe->srcp2_file, pipe->put2_need);
+
+ pr_debug("%s: ndx=%d flags=%x put=%d\n", __func__,
+ pipe->pipe_ndx, pipe->flags, pipe->put0_need);
+ return;
+ }
+
mutex_lock(&iommu_mutex);
mixer = pipe->mixer_num;
iom = &pipe->iommu;
@@ -2955,14 +2968,13 @@
if (file == NULL)
return -EINVAL;
+ pipe->flags |= MDP_MEMORY_ID_TYPE_FB;
if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
fb_num = MINOR(file->f_dentry->d_inode->i_rdev);
if (get_fb_phys_info(start, len, fb_num,
DISPLAY_SUBSYSTEM_ID)) {
ret = -1;
} else {
- pr_warn("%s: mdp4_overlay play with FB memory\n",
- __func__);
*srcp_file = file;
*p_need = put_needed;
}
@@ -3320,11 +3332,8 @@
struct mdp4_overlay_pipe *pipe;
ulong start, addr;
ulong len = 0;
- struct file *srcp0_file = NULL;
- struct file *srcp1_file = NULL, *srcp2_file = NULL;
struct ion_handle *srcp0_ihdl = NULL;
struct ion_handle *srcp1_ihdl = NULL, *srcp2_ihdl = NULL;
- int ps0_need, p_need;
uint32_t overlay_version = 0;
int ret = 0;
@@ -3349,8 +3358,8 @@
mutex_lock(&mfd->dma->ov_mutex);
img = &req->data;
- get_img(img, info, pipe, 0, &start, &len, &srcp0_file,
- &ps0_need, &srcp0_ihdl);
+ get_img(img, info, pipe, 0, &start, &len, &pipe->srcp0_file,
+ &pipe->put0_need, &srcp0_ihdl);
if (len == 0) {
pr_err("%s: pmem Error\n", __func__);
ret = -1;
@@ -3372,8 +3381,9 @@
if (pipe->fetch_plane == OVERLAY_PLANE_PSEUDO_PLANAR) {
if (overlay_version > 0) {
img = &req->plane1_data;
- get_img(img, info, pipe, 1, &start, &len, &srcp1_file,
- &p_need, &srcp1_ihdl);
+ get_img(img, info, pipe, 1, &start, &len,
+ &pipe->srcp1_file, &pipe->put1_need,
+ &srcp1_ihdl);
if (len == 0) {
pr_err("%s: Error to get plane1\n", __func__);
ret = -EINVAL;
@@ -3404,8 +3414,9 @@
} else if (pipe->fetch_plane == OVERLAY_PLANE_PLANAR) {
if (overlay_version > 0) {
img = &req->plane1_data;
- get_img(img, info, pipe, 1, &start, &len, &srcp1_file,
- &p_need, &srcp1_ihdl);
+ get_img(img, info, pipe, 1, &start, &len,
+ &pipe->srcp1_file, &pipe->put1_need,
+ &srcp1_ihdl);
if (len == 0) {
pr_err("%s: Error to get plane1\n", __func__);
ret = -EINVAL;
@@ -3414,8 +3425,9 @@
pipe->srcp1_addr = start + img->offset;
img = &req->plane2_data;
- get_img(img, info, pipe, 2, &start, &len, &srcp2_file,
- &p_need, &srcp2_ihdl);
+ get_img(img, info, pipe, 2, &start, &len,
+ &pipe->srcp2_file, &pipe->put2_need,
+ &srcp2_ihdl);
if (len == 0) {
pr_err("%s: Error to get plane2\n", __func__);
ret = -EINVAL;
@@ -3512,17 +3524,6 @@
end:
mutex_unlock(&mfd->dma->ov_mutex);
-#ifdef CONFIG_ANDROID_PMEM
- if (srcp0_file)
- put_pmem_file(srcp0_file);
- if (srcp1_file)
- put_pmem_file(srcp1_file);
- if (srcp2_file)
- put_pmem_file(srcp2_file);
-#endif
- /* only source may use frame buffer */
- if (img->flags & MDP_MEMORY_ID_TYPE_FB)
- fput_light(srcp0_file, ps0_need);
return ret;
}
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index efb4da6..9f29887 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -42,6 +42,9 @@
#include <linux/vmalloc.h>
#include <mach/board.h>
+#include <mach/memory.h>
+#include <mach/msm_memtypes.h>
+#include <mach/iommu_domains.h>
#include "mdss_fb.h"
#include "mdss_mdp.h"
@@ -596,37 +599,17 @@
size *= mfd->fb_page;
if (mfd->index == 0) {
- struct ion_client *iclient = mdss_get_ionclient();
-
- if (iclient) {
- mfd->ihdl = ion_alloc(iclient, size, SZ_4K,
- ION_HEAP(ION_CP_MM_HEAP_ID) |
- ION_HEAP(ION_SF_HEAP_ID), 0);
- if (IS_ERR_OR_NULL(mfd->ihdl)) {
- pr_err("unable to alloc fbmem from ion (%p)\n",
- mfd->ihdl);
- return -ENOMEM;
- }
-
- virt = ion_map_kernel(iclient, mfd->ihdl);
- ion_phys(iclient, mfd->ihdl, &phys, &size);
-
- if (is_mdss_iommu_attached()) {
- ion_map_iommu(iclient, mfd->ihdl,
- mdss_get_iommu_domain(),
- 0, SZ_4K, 0, &mfd->iova,
- (unsigned long *) &size,
- 0, 0);
- }
- } else {
- virt = dma_alloc_coherent(NULL, size,
- (dma_addr_t *) &phys, GFP_KERNEL);
- if (!virt) {
- pr_err("unable to alloc fbmem size=%u\n", size);
- return -ENOMEM;
- }
+ virt = allocate_contiguous_memory(size, MEMTYPE_EBI1, SZ_1M, 0);
+ if (!virt) {
+ pr_err("unable to alloc fbmem size=%u\n", size);
+ return -ENOMEM;
}
-
+ phys = memory_pool_node_paddr(virt);
+ if (is_mdss_iommu_attached()) {
+ msm_iommu_map_contig_buffer(phys,
+ mdss_get_iommu_domain(), 0, size, SZ_4K, 0,
+ &(mfd->iova));
+ }
pr_info("allocating %u bytes at %p (%lx phys) for fb %d\n",
size, virt, phys, mfd->index);
} else {
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index 4f641cc..0f6cfe9 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -1081,8 +1081,10 @@
static const struct of_device_id mdss_mdp_dt_match[] = {
{ .compatible = "qcom,mdss_mdp",},
+ {}
};
MODULE_DEVICE_TABLE(of, mdss_mdp_dt_match);
+EXPORT_COMPAT("qcom,mdss_mdp");
static struct platform_driver mdss_mdp_driver = {
.probe = mdss_mdp_probe,
diff --git a/include/linux/msm_kgsl.h b/include/linux/msm_kgsl.h
index 71ff639..5e1395e 100644
--- a/include/linux/msm_kgsl.h
+++ b/include/linux/msm_kgsl.h
@@ -2,7 +2,7 @@
#define _MSM_KGSL_H
#define KGSL_VERSION_MAJOR 3
-#define KGSL_VERSION_MINOR 12
+#define KGSL_VERSION_MINOR 13
/*context flags */
#define KGSL_CONTEXT_SAVE_GMEM 0x00000001
@@ -18,6 +18,33 @@
/* Memory allocayion flags */
#define KGSL_MEMFLAGS_GPUREADONLY 0x01000000
+#define KGSL_MEMTYPE_MASK 0x0000FF00
+#define KGSL_MEMTYPE_SHIFT 8
+
+/* Memory types for which allocations are made */
+#define KGSL_MEMTYPE_OBJECTANY 0
+#define KGSL_MEMTYPE_FRAMEBUFFER 1
+#define KGSL_MEMTYPE_RENDERBUFFER 2
+#define KGSL_MEMTYPE_ARRAYBUFFER 3
+#define KGSL_MEMTYPE_ELEMENTARRAYBUFFER 4
+#define KGSL_MEMTYPE_VERTEXARRAYBUFFER 5
+#define KGSL_MEMTYPE_TEXTURE 6
+#define KGSL_MEMTYPE_SURFACE 7
+#define KGSL_MEMTYPE_EGL_SURFACE 8
+#define KGSL_MEMTYPE_GL 9
+#define KGSL_MEMTYPE_CL 10
+#define KGSL_MEMTYPE_CL_BUFFER_MAP 11
+#define KGSL_MEMTYPE_CL_BUFFER_NOMAP 12
+#define KGSL_MEMTYPE_CL_IMAGE_MAP 13
+#define KGSL_MEMTYPE_CL_IMAGE_NOMAP 14
+#define KGSL_MEMTYPE_CL_KERNEL_STACK 15
+#define KGSL_MEMTYPE_COMMAND 16
+#define KGSL_MEMTYPE_2D 17
+#define KGSL_MEMTYPE_EGL_IMAGE 18
+#define KGSL_MEMTYPE_EGL_SHADOW 19
+#define KGSL_MEMTYPE_MULTISAMPLE 20
+#define KGSL_MEMTYPE_KERNEL 255
+
/* generic flag values */
#define KGSL_FLAGS_NORMALMODE 0x00000000
#define KGSL_FLAGS_SAFEMODE 0x00000001
@@ -278,8 +305,7 @@
unsigned int offset;
unsigned int hostptr; /*input param */
enum kgsl_user_mem_type memtype;
- unsigned int reserved; /* May be required to add
- params for another mem type */
+ unsigned int flags;
};
#define IOCTL_KGSL_MAP_USER_MEM \
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 2c9509d..1f13da3 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -142,6 +142,8 @@
extern unsigned long nr_iowait_cpu(int cpu);
extern unsigned long this_cpu_load(void);
+extern void sched_update_nr_prod(int cpu, unsigned long nr, bool inc);
+extern void sched_get_nr_running_avg(int *avg, int *iowait_avg);
extern void calc_global_load(unsigned long ticks);
diff --git a/kernel/sched/Makefile b/kernel/sched/Makefile
index 9a7dd35..3ede7d9 100644
--- a/kernel/sched/Makefile
+++ b/kernel/sched/Makefile
@@ -11,7 +11,7 @@
CFLAGS_core.o := $(PROFILING) -fno-omit-frame-pointer
endif
-obj-y += core.o clock.o idle_task.o fair.o rt.o stop_task.o
+obj-y += core.o clock.o idle_task.o fair.o rt.o stop_task.o sched_avg.o
obj-$(CONFIG_SMP) += cpupri.o
obj-$(CONFIG_SCHED_AUTOGROUP) += auto_group.o
obj-$(CONFIG_SCHEDSTATS) += stats.o
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index fb3acba..451bd4f 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -916,11 +916,13 @@
static inline void inc_nr_running(struct rq *rq)
{
+ sched_update_nr_prod(cpu_of(rq), rq->nr_running, true);
rq->nr_running++;
}
static inline void dec_nr_running(struct rq *rq)
{
+ sched_update_nr_prod(cpu_of(rq), rq->nr_running, false);
rq->nr_running--;
}
diff --git a/kernel/sched/sched_avg.c b/kernel/sched/sched_avg.c
new file mode 100644
index 0000000..8eaf2f7
--- /dev/null
+++ b/kernel/sched/sched_avg.c
@@ -0,0 +1,106 @@
+/* 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.
+ */
+
+/*
+ * Scheduler hook for average runqueue determination
+ */
+#include <linux/module.h>
+#include <linux/percpu.h>
+#include <linux/hrtimer.h>
+#include <linux/sched.h>
+#include <linux/math64.h>
+
+static DEFINE_PER_CPU(u64, nr_prod_sum);
+static DEFINE_PER_CPU(u64, last_time);
+static DEFINE_PER_CPU(u64, nr);
+static DEFINE_PER_CPU(unsigned long, iowait_prod_sum);
+static DEFINE_PER_CPU(spinlock_t, nr_lock) = __SPIN_LOCK_UNLOCKED(nr_lock);
+static s64 last_get_time;
+
+/**
+ * sched_get_nr_running_avg
+ * @return: Average nr_running and iowait value since last poll.
+ * Returns the avg * 100 to return up to two decimal points
+ * of accuracy.
+ *
+ * Obtains the average nr_running value since the last poll.
+ * This function may not be called concurrently with itself
+ */
+void sched_get_nr_running_avg(int *avg, int *iowait_avg)
+{
+ int cpu;
+ u64 curr_time = sched_clock();
+ u64 diff = curr_time - last_get_time;
+ u64 tmp_avg = 0, tmp_iowait = 0;
+
+ *avg = 0;
+ *iowait_avg = 0;
+
+ if (!diff)
+ return;
+
+ last_get_time = curr_time;
+ /* read and reset nr_running counts */
+ for_each_possible_cpu(cpu) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&per_cpu(nr_lock, cpu), flags);
+ tmp_avg += per_cpu(nr_prod_sum, cpu);
+ tmp_avg += per_cpu(nr, cpu) *
+ (curr_time - per_cpu(last_time, cpu));
+ tmp_iowait = per_cpu(iowait_prod_sum, cpu);
+ tmp_iowait += nr_iowait_cpu(cpu) *
+ (curr_time - per_cpu(last_time, cpu));
+ per_cpu(last_time, cpu) = curr_time;
+ per_cpu(nr_prod_sum, cpu) = 0;
+ per_cpu(iowait_prod_sum, cpu) = 0;
+ spin_unlock_irqrestore(&per_cpu(nr_lock, cpu), flags);
+ }
+
+ *avg = (int)div64_u64(tmp_avg * 100, diff);
+ *iowait_avg = (int)div64_u64(tmp_iowait * 100, diff);
+
+ BUG_ON(*avg < 0);
+ pr_debug("%s - avg:%d\n", __func__, *avg);
+ BUG_ON(*iowait_avg < 0);
+ pr_debug("%s - avg:%d\n", __func__, *iowait_avg);
+}
+EXPORT_SYMBOL(sched_get_nr_running_avg);
+
+/**
+ * sched_update_nr_prod
+ * @cpu: The core id of the nr running driver.
+ * @nr: Updated nr running value for cpu.
+ * @inc: Whether we are increasing or decreasing the count
+ * @return: N/A
+ *
+ * Update average with latest nr_running value for CPU
+ */
+void sched_update_nr_prod(int cpu, unsigned long nr_running, bool inc)
+{
+ int diff;
+ s64 curr_time;
+ unsigned long flags;
+
+ spin_lock_irqsave(&per_cpu(nr_lock, cpu), flags);
+ curr_time = sched_clock();
+ diff = curr_time - per_cpu(last_time, cpu);
+ per_cpu(last_time, cpu) = curr_time;
+ per_cpu(nr, cpu) = nr_running + (inc ? 1 : -1);
+
+ BUG_ON(per_cpu(nr, cpu) < 0);
+
+ per_cpu(nr_prod_sum, cpu) += nr_running * diff;
+ per_cpu(iowait_prod_sum, cpu) += nr_iowait_cpu(cpu) * diff;
+ spin_unlock_irqrestore(&per_cpu(nr_lock, cpu), flags);
+}
+EXPORT_SYMBOL(sched_update_nr_prod);
diff --git a/sound/soc/codecs/wcd9304.c b/sound/soc/codecs/wcd9304.c
index 9432a06..b303878 100644
--- a/sound/soc/codecs/wcd9304.c
+++ b/sound/soc/codecs/wcd9304.c
@@ -4976,6 +4976,7 @@
SITAR_REG_VAL(SITAR_A_CDC_RX1_B6_CTL, 0x80),
SITAR_REG_VAL(SITAR_A_CDC_CLSG_FREQ_THRESH_B3_CTL, 0x1B),
+ SITAR_REG_VAL(SITAR_A_CDC_CLSG_FREQ_THRESH_B4_CTL, 0x5B),
};