summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/input/touchscreen/gt9xx/gt9xx.txt2
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-blsp.dtsi6
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-pinctrl.dtsi88
-rw-r--r--arch/arm/configs/msmfalcon_defconfig1
-rw-r--r--arch/arm64/configs/msmcortex-perf_defconfig1
-rw-r--r--arch/arm64/configs/msmcortex_defconfig1
-rw-r--r--drivers/devfreq/governor_bw_vbif.c12
-rw-r--r--drivers/gpu/msm/adreno.c2
-rw-r--r--drivers/gpu/msm/kgsl_pwrctrl.c45
-rw-r--r--drivers/gpu/msm/kgsl_pwrscale.c6
-rw-r--r--drivers/gpu/msm/kgsl_pwrscale.h4
-rw-r--r--drivers/input/misc/ots_pat9125/pat9125_linux_driver.c29
-rw-r--r--drivers/input/touchscreen/gt9xx/gt9xx.c236
-rw-r--r--drivers/input/touchscreen/gt9xx/gt9xx.h11
-rw-r--r--drivers/input/touchscreen/gt9xx/gt9xx_update.c13
-rw-r--r--drivers/iommu/arm-smmu.c2
-rw-r--r--drivers/platform/msm/gsi/gsi.c17
-rw-r--r--drivers/platform/msm/gsi/gsi.h11
-rw-r--r--drivers/power/qcom-charger/fg-util.c11
-rw-r--r--drivers/power/qcom-charger/qpnp-fg-gen3.c2
-rw-r--r--drivers/thermal/cpu_cooling.c56
-rw-r--r--drivers/thermal/msm_lmh_dcvs.c74
-rw-r--r--include/linux/cpu_cooling.h16
-rw-r--r--include/linux/sched/core_ctl.h (renamed from kernel/sched/core_ctl.h)7
-rw-r--r--include/trace/events/sched.h15
-rw-r--r--kernel/sched/core.c2
-rw-r--r--kernel/sched/core_ctl.c33
-rw-r--r--kernel/sched/fair.c3
-rw-r--r--kernel/sched/hmp.c2
-rw-r--r--sound/soc/codecs/wcd934x/wcd934x.c39
30 files changed, 661 insertions, 86 deletions
diff --git a/Documentation/devicetree/bindings/input/touchscreen/gt9xx/gt9xx.txt b/Documentation/devicetree/bindings/input/touchscreen/gt9xx/gt9xx.txt
index 4c676fa66e62..ff8fb76166a3 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/gt9xx/gt9xx.txt
+++ b/Documentation/devicetree/bindings/input/touchscreen/gt9xx/gt9xx.txt
@@ -34,7 +34,7 @@ Optional properties:
It is a four tuple consisting of min x,
min y, max x and max y values.
- goodix,i2c-pull-up : To specify pull up is required.
- - goodix,no-force-update : To specify force update is allowed.
+ - goodix,force-update : To specify force update is allowed.
- goodix,enable-power-off : Power off touchscreen during suspend.
- goodix,button-map : Button map of key codes. The number of key codes
depend on panel.
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-blsp.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-blsp.dtsi
index 929a079c64c3..a660ea06795e 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-blsp.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-blsp.dtsi
@@ -736,8 +736,10 @@
clocks = <&clock_gcc clk_gcc_blsp1_uart3_apps_clk>,
<&clock_gcc clk_gcc_blsp1_ahb_clk>;
pinctrl-names = "sleep", "default";
- pinctrl-0 = <&blsp1_uart3_sleep>;
- pinctrl-1 = <&blsp1_uart3_active>;
+ pinctrl-0 = <&blsp1_uart3_tx_sleep>, <&blsp1_uart3_rxcts_sleep>,
+ <&blsp1_uart3_rfr_sleep>;
+ pinctrl-1 = <&blsp1_uart3_tx_active>,
+ <&blsp1_uart3_rxcts_active>, <&blsp1_uart3_rfr_active>;
qcom,msm-bus,name = "buart3";
qcom,msm-bus,num-cases = <2>;
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-pinctrl.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-pinctrl.dtsi
index 3975bc5d16f5..e5fd988dccce 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-pinctrl.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-pinctrl.dtsi
@@ -1223,29 +1223,83 @@
};
};
- blsp1_uart3_active: blsp1_uart3_active {
- mux {
- pins = "gpio45", "gpio46", "gpio47", "gpio48";
- function = "blsp_uart3_a";
+ blsp1_uart3: blsp1_uart3 {
+ blsp1_uart3_tx_active: blsp1_uart3_tx_active {
+ mux {
+ pins = "gpio45";
+ function = "blsp_uart3_a";
+ };
+
+ config {
+ pins = "gpio45";
+ drive-strength = <2>;
+ bias-disable;
+ };
};
- config {
- pins = "gpio45", "gpio46", "gpio47", "gpio48";
- drive-strength = <2>;
- bias-disable;
+ blsp1_uart3_tx_sleep: blsp1_uart3_tx_sleep {
+ mux {
+ pins = "gpio45";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio45";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
};
- };
- blsp1_uart3_sleep: blsp1_uart3_sleep {
- mux {
- pins = "gpio45", "gpio46", "gpio47", "gpio48";
- function = "gpio";
+ blsp1_uart3_rxcts_active: blsp1_uart3_rxcts_active {
+ mux {
+ pins = "gpio46", "gpio47";
+ function = "blsp_uart3_a";
+ };
+
+ config {
+ pins = "gpio46", "gpio47";
+ drive-strength = <2>;
+ bias-disable;
+ };
};
- config {
- pins = "gpio45", "gpio46", "gpio47", "gpio48";
- drive-strength = <2>;
- bias-pull-up;
+ blsp1_uart3_rxcts_sleep: blsp1_uart3_rxcts_sleep {
+ mux {
+ pins = "gpio46", "gpio47";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio46", "gpio47";
+ drive-strength = <2>;
+ bias-no-pull;
+ };
+ };
+
+ blsp1_uart3_rfr_active: blsp1_uart3_rfr_active {
+ mux {
+ pins = "gpio48";
+ function = "blsp_uart3_a";
+ };
+
+ config {
+ pins = "gpio48";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ blsp1_uart3_rfr_sleep: blsp1_uart3_rfr_sleep {
+ mux {
+ pins = "gpio48";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio48";
+ drive-strength = <2>;
+ bias-no-pull;
+ };
};
};
diff --git a/arch/arm/configs/msmfalcon_defconfig b/arch/arm/configs/msmfalcon_defconfig
index 41572d54afcb..069603eefe48 100644
--- a/arch/arm/configs/msmfalcon_defconfig
+++ b/arch/arm/configs/msmfalcon_defconfig
@@ -336,7 +336,6 @@ CONFIG_FB_MSM=y
CONFIG_FB_MSM_MDSS=y
CONFIG_FB_MSM_MDSS_WRITEBACK=y
CONFIG_FB_MSM_MDSS_HDMI_PANEL=y
-CONFIG_FB_MSM_MDSS_DP_PANEL=y
CONFIG_FB_MSM_MDSS_XLOG_DEBUG=y
CONFIG_LOGO=y
# CONFIG_LOGO_LINUX_MONO is not set
diff --git a/arch/arm64/configs/msmcortex-perf_defconfig b/arch/arm64/configs/msmcortex-perf_defconfig
index 5d2f29b053c4..0bda100dfb5a 100644
--- a/arch/arm64/configs/msmcortex-perf_defconfig
+++ b/arch/arm64/configs/msmcortex-perf_defconfig
@@ -321,6 +321,7 @@ CONFIG_QPNP_SMB2=y
CONFIG_SMB138X_CHARGER=y
CONFIG_QPNP_QNOVO=y
CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
+CONFIG_CPU_THERMAL=y
CONFIG_LIMITS_MONITOR=y
CONFIG_LIMITS_LITE_HW=y
CONFIG_THERMAL_MONITOR=y
diff --git a/arch/arm64/configs/msmcortex_defconfig b/arch/arm64/configs/msmcortex_defconfig
index 741f2e5bc8f6..3568fe4ed29f 100644
--- a/arch/arm64/configs/msmcortex_defconfig
+++ b/arch/arm64/configs/msmcortex_defconfig
@@ -324,6 +324,7 @@ CONFIG_QPNP_SMB2=y
CONFIG_SMB138X_CHARGER=y
CONFIG_QPNP_QNOVO=y
CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
+CONFIG_CPU_THERMAL=y
CONFIG_LIMITS_MONITOR=y
CONFIG_LIMITS_LITE_HW=y
CONFIG_THERMAL_MONITOR=y
diff --git a/drivers/devfreq/governor_bw_vbif.c b/drivers/devfreq/governor_bw_vbif.c
index da1eefb8c94e..33e144b653d0 100644
--- a/drivers/devfreq/governor_bw_vbif.c
+++ b/drivers/devfreq/governor_bw_vbif.c
@@ -78,15 +78,13 @@ static int devfreq_vbif_ev_handler(struct devfreq *devfreq,
case DEVFREQ_GOV_START:
mutex_lock(&df_lock);
df = devfreq;
- if (df->profile->get_dev_status)
- ret = df->profile->get_dev_status(df->dev.parent,
- &stat);
+ if (df->profile->get_dev_status &&
+ !df->profile->get_dev_status(df->dev.parent, &stat) &&
+ stat.private_data)
+ dev_ab = stat.private_data;
else
- ret = 0;
- if (ret || !stat.private_data)
pr_warn("Device doesn't take AB votes!\n");
- else
- dev_ab = stat.private_data;
+
mutex_unlock(&df_lock);
ret = devfreq_vbif_update_bw(0, 0);
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 94d828027f20..9940f7a7c2b7 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -1961,7 +1961,7 @@ static int adreno_setproperty(struct kgsl_device_private *dev_priv,
KGSL_STATE_ACTIVE);
device->pwrctrl.ctrl_flags = KGSL_PWR_ON;
adreno_fault_detect_stop(adreno_dev);
- kgsl_pwrscale_disable(device);
+ kgsl_pwrscale_disable(device, true);
}
mutex_unlock(&device->mutex);
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index d71c6a63f2d3..172de7406c26 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -1387,6 +1387,47 @@ done:
return 0;
}
+static ssize_t kgsl_pwrctrl_pwrscale_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct kgsl_device *device = kgsl_device_from_dev(dev);
+ int ret;
+ unsigned int enable = 0;
+
+ if (device == NULL)
+ return 0;
+
+ ret = kgsl_sysfs_store(buf, &enable);
+ if (ret)
+ return ret;
+
+ mutex_lock(&device->mutex);
+
+ if (enable)
+ kgsl_pwrscale_enable(device);
+ else
+ kgsl_pwrscale_disable(device, false);
+
+ mutex_unlock(&device->mutex);
+
+ return count;
+}
+
+static ssize_t kgsl_pwrctrl_pwrscale_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct kgsl_device *device = kgsl_device_from_dev(dev);
+ struct kgsl_pwrscale *psc;
+
+ if (device == NULL)
+ return 0;
+ psc = &device->pwrscale;
+
+ return snprintf(buf, PAGE_SIZE, "%u\n", psc->enabled);
+}
+
static DEVICE_ATTR(gpuclk, 0644, kgsl_pwrctrl_gpuclk_show,
kgsl_pwrctrl_gpuclk_store);
static DEVICE_ATTR(max_gpuclk, 0644, kgsl_pwrctrl_max_gpuclk_show,
@@ -1449,6 +1490,9 @@ static DEVICE_ATTR(clock_mhz, 0444, kgsl_pwrctrl_clock_mhz_show, NULL);
static DEVICE_ATTR(freq_table_mhz, 0444,
kgsl_pwrctrl_freq_table_mhz_show, NULL);
static DEVICE_ATTR(temp, 0444, kgsl_pwrctrl_temp_show, NULL);
+static DEVICE_ATTR(pwrscale, 0644,
+ kgsl_pwrctrl_pwrscale_show,
+ kgsl_pwrctrl_pwrscale_store);
static const struct device_attribute *pwrctrl_attr_list[] = {
&dev_attr_gpuclk,
@@ -1477,6 +1521,7 @@ static const struct device_attribute *pwrctrl_attr_list[] = {
&dev_attr_clock_mhz,
&dev_attr_freq_table_mhz,
&dev_attr_temp,
+ &dev_attr_pwrscale,
NULL
};
diff --git a/drivers/gpu/msm/kgsl_pwrscale.c b/drivers/gpu/msm/kgsl_pwrscale.c
index 01d3b74c16fd..85cd29b5364e 100644
--- a/drivers/gpu/msm/kgsl_pwrscale.c
+++ b/drivers/gpu/msm/kgsl_pwrscale.c
@@ -189,19 +189,21 @@ EXPORT_SYMBOL(kgsl_pwrscale_update);
/*
* kgsl_pwrscale_disable - temporarily disable the governor
* @device: The device
+ * @turbo: Indicates if pwrlevel should be forced to turbo
*
* Temporarily disable the governor, to prevent interference
* with profiling tools that expect a fixed clock frequency.
* This function must be called with the device mutex locked.
*/
-void kgsl_pwrscale_disable(struct kgsl_device *device)
+void kgsl_pwrscale_disable(struct kgsl_device *device, bool turbo)
{
BUG_ON(!mutex_is_locked(&device->mutex));
if (device->pwrscale.devfreqptr)
queue_work(device->pwrscale.devfreq_wq,
&device->pwrscale.devfreq_suspend_ws);
device->pwrscale.enabled = false;
- kgsl_pwrctrl_pwrlevel_change(device, KGSL_PWRLEVEL_TURBO);
+ if (turbo)
+ kgsl_pwrctrl_pwrlevel_change(device, KGSL_PWRLEVEL_TURBO);
}
EXPORT_SYMBOL(kgsl_pwrscale_disable);
diff --git a/drivers/gpu/msm/kgsl_pwrscale.h b/drivers/gpu/msm/kgsl_pwrscale.h
index c85317869f1d..0756a4490f22 100644
--- a/drivers/gpu/msm/kgsl_pwrscale.h
+++ b/drivers/gpu/msm/kgsl_pwrscale.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2016, 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
@@ -123,7 +123,7 @@ void kgsl_pwrscale_sleep(struct kgsl_device *device);
void kgsl_pwrscale_wake(struct kgsl_device *device);
void kgsl_pwrscale_enable(struct kgsl_device *device);
-void kgsl_pwrscale_disable(struct kgsl_device *device);
+void kgsl_pwrscale_disable(struct kgsl_device *device, bool turbo);
int kgsl_devfreq_target(struct device *dev, unsigned long *freq, u32 flags);
int kgsl_devfreq_get_dev_status(struct device *, struct devfreq_dev_status *);
diff --git a/drivers/input/misc/ots_pat9125/pat9125_linux_driver.c b/drivers/input/misc/ots_pat9125/pat9125_linux_driver.c
index ca5a9ec2f7f9..fa5e4cca129d 100644
--- a/drivers/input/misc/ots_pat9125/pat9125_linux_driver.c
+++ b/drivers/input/misc/ots_pat9125/pat9125_linux_driver.c
@@ -31,6 +31,10 @@ struct pixart_pat9125_data {
struct pinctrl_state *pinctrl_state_release;
};
+/* Declaration of suspend and resume functions */
+static int pat9125_suspend(struct device *dev);
+static int pat9125_resume(struct device *dev);
+
static int pat9125_i2c_write(struct i2c_client *client, u8 reg, u8 *data,
int len)
{
@@ -146,6 +150,27 @@ static irqreturn_t pat9125_irq(int irq, void *dev_data)
return IRQ_HANDLED;
}
+static ssize_t pat9125_suspend_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct pixart_pat9125_data *data =
+ (struct pixart_pat9125_data *) dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
+ int mode;
+
+ if (kstrtoint(buf, 10, &mode)) {
+ dev_err(dev, "failed to read input for sysfs\n");
+ return -EINVAL;
+ }
+
+ if (mode == 1)
+ pat9125_suspend(&client->dev);
+ else if (mode == 0)
+ pat9125_resume(&client->dev);
+
+ return count;
+}
+
static ssize_t pat9125_test_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
@@ -191,11 +216,15 @@ static ssize_t pat9125_test_show(struct device *dev,
{
return 0;
}
+
+static DEVICE_ATTR(suspend, S_IRUGO | S_IWUSR | S_IWGRP,
+ NULL, pat9125_suspend_store);
static DEVICE_ATTR(test, S_IRUGO | S_IWUSR | S_IWGRP,
pat9125_test_show, pat9125_test_store);
static struct attribute *pat9125_attr_list[] = {
&dev_attr_test.attr,
+ &dev_attr_suspend.attr,
NULL,
};
diff --git a/drivers/input/touchscreen/gt9xx/gt9xx.c b/drivers/input/touchscreen/gt9xx/gt9xx.c
index a9d7666a6d6f..3b19a45922c4 100644
--- a/drivers/input/touchscreen/gt9xx/gt9xx.c
+++ b/drivers/input/touchscreen/gt9xx/gt9xx.c
@@ -115,6 +115,8 @@ struct i2c_client *i2c_connect_client;
#define GTP_DEBUGFS_DIR "ts_debug"
#define GTP_DEBUGFS_FILE_SUSPEND "suspend"
+#define GTP_DEBUGFS_FILE_DATA "data"
+#define GTP_DEBUGFS_FILE_ADDR "addr"
/*******************************************************
Function:
@@ -1521,12 +1523,108 @@ static ssize_t gtp_fw_name_store(struct device *dev,
return size;
}
+static ssize_t gtp_fw_upgrade_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct goodix_ts_data *ts = dev_get_drvdata(dev);
+
+ return snprintf(buf, 2, "%d\n", ts->fw_loading);
+}
+
+static ssize_t gtp_fw_upgrade_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct goodix_ts_data *ts = dev_get_drvdata(dev);
+ unsigned int val;
+ int ret;
+
+ if (size > 2)
+ return -EINVAL;
+
+ ret = kstrtouint(buf, 10, &val);
+ if (ret)
+ return ret;
+
+ if (ts->gtp_is_suspend) {
+ dev_err(&ts->client->dev,
+ "Can't start fw upgrade. Device is in suspend state");
+ return -EBUSY;
+ }
+
+ mutex_lock(&ts->input_dev->mutex);
+ if (!ts->fw_loading && val) {
+ disable_irq(ts->client->irq);
+ ts->fw_loading = true;
+ if (config_enabled(CONFIG_GT9XX_TOUCHPANEL_UPDATE)) {
+ ret = gup_update_proc(NULL);
+ if (ret == FAIL)
+ dev_err(&ts->client->dev,
+ "Fail to update GTP firmware\n");
+ }
+ ts->fw_loading = false;
+ enable_irq(ts->client->irq);
+ }
+ mutex_unlock(&ts->input_dev->mutex);
+
+ return size;
+}
+
+static ssize_t gtp_force_fw_upgrade_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct goodix_ts_data *ts = dev_get_drvdata(dev);
+ unsigned int val;
+ int ret;
+
+ if (size > 2)
+ return -EINVAL;
+
+ ret = kstrtouint(buf, 10, &val);
+ if (ret)
+ return ret;
+
+ if (ts->gtp_is_suspend) {
+ dev_err(&ts->client->dev,
+ "Can't start fw upgrade. Device is in suspend state.");
+ return -EBUSY;
+ }
+
+ mutex_lock(&ts->input_dev->mutex);
+ if (!ts->fw_loading && val) {
+ disable_irq(ts->client->irq);
+ ts->fw_loading = true;
+ ts->force_update = true;
+ if (config_enabled(CONFIG_GT9XX_TOUCHPANEL_UPDATE)) {
+ ret = gup_update_proc(NULL);
+ if (ret == FAIL)
+ dev_err(&ts->client->dev,
+ "Fail to force update GTP firmware.\n");
+ }
+ ts->force_update = false;
+ ts->fw_loading = false;
+ enable_irq(ts->client->irq);
+ }
+ mutex_unlock(&ts->input_dev->mutex);
+
+ return size;
+}
+
static DEVICE_ATTR(fw_name, (S_IRUGO | S_IWUSR | S_IWGRP),
gtp_fw_name_show,
gtp_fw_name_store);
+static DEVICE_ATTR(fw_upgrade, (S_IRUGO | S_IWUSR | S_IWGRP),
+ gtp_fw_upgrade_show,
+ gtp_fw_upgrade_store);
+static DEVICE_ATTR(force_fw_upgrade, (S_IRUGO | S_IWUSR | S_IWGRP),
+ gtp_fw_upgrade_show,
+ gtp_force_fw_upgrade_store);
static struct attribute *gtp_attrs[] = {
&dev_attr_fw_name.attr,
+ &dev_attr_fw_upgrade.attr,
+ &dev_attr_force_fw_upgrade.attr,
NULL
};
@@ -1534,6 +1632,84 @@ static const struct attribute_group gtp_attr_grp = {
.attrs = gtp_attrs,
};
+static int gtp_debug_addr_is_valid(u16 addr)
+{
+ if (addr < GTP_VALID_ADDR_START || addr > GTP_VALID_ADDR_END) {
+ pr_err("GTP reg address is invalid: 0x%x\n", addr);
+ return false;
+ }
+
+ return true;
+}
+
+static int gtp_debug_data_set(void *_data, u64 val)
+{
+ struct goodix_ts_data *ts = _data;
+
+ mutex_lock(&ts->input_dev->mutex);
+ if (gtp_debug_addr_is_valid(ts->addr))
+ dev_err(&ts->client->dev,
+ "Writing to GTP registers not supported\n");
+ mutex_unlock(&ts->input_dev->mutex);
+
+ return 0;
+}
+
+static int gtp_debug_data_get(void *_data, u64 *val)
+{
+ struct goodix_ts_data *ts = _data;
+ int ret;
+ u8 buf[3] = {0};
+
+ mutex_lock(&ts->input_dev->mutex);
+ buf[0] = ts->addr >> 8;
+ buf[1] = ts->addr & 0x00ff;
+
+ if (gtp_debug_addr_is_valid(ts->addr)) {
+ ret = gtp_i2c_read(ts->client, buf, 3);
+ if (ret < 0)
+ dev_err(&ts->client->dev,
+ "GTP read register 0x%x failed (%d)\n",
+ ts->addr, ret);
+ else
+ *val = buf[2];
+ }
+ mutex_unlock(&ts->input_dev->mutex);
+
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(debug_data_fops, gtp_debug_data_get,
+ gtp_debug_data_set, "%llx\n");
+
+static int gtp_debug_addr_set(void *_data, u64 val)
+{
+ struct goodix_ts_data *ts = _data;
+
+ if (gtp_debug_addr_is_valid(val)) {
+ mutex_lock(&ts->input_dev->mutex);
+ ts->addr = val;
+ mutex_unlock(&ts->input_dev->mutex);
+ }
+
+ return 0;
+}
+
+static int gtp_debug_addr_get(void *_data, u64 *val)
+{
+ struct goodix_ts_data *ts = _data;
+
+ mutex_lock(&ts->input_dev->mutex);
+ if (gtp_debug_addr_is_valid(ts->addr))
+ *val = ts->addr;
+ mutex_unlock(&ts->input_dev->mutex);
+
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(debug_addr_fops, gtp_debug_addr_get,
+ gtp_debug_addr_set, "%llx\n");
+
static int gtp_debug_suspend_set(void *_data, u64 val)
{
struct goodix_ts_data *ts = _data;
@@ -1567,7 +1743,7 @@ static int gtp_debugfs_init(struct goodix_ts_data *data)
data->debug_base = debugfs_create_dir(GTP_DEBUGFS_DIR, NULL);
if (IS_ERR_OR_NULL(data->debug_base)) {
- pr_err("Failed to create debugfs dir\n");
+ dev_err(&data->client->dev, "Failed to create debugfs dir\n");
return -EINVAL;
}
@@ -1576,7 +1752,27 @@ static int gtp_debugfs_init(struct goodix_ts_data *data)
data->debug_base,
data,
&debug_suspend_fops)))) {
- pr_err("Failed to create suspend file\n");
+ dev_err(&data->client->dev, "Failed to create suspend file\n");
+ debugfs_remove_recursive(data->debug_base);
+ return -EINVAL;
+ }
+
+ if ((IS_ERR_OR_NULL(debugfs_create_file(GTP_DEBUGFS_FILE_DATA,
+ S_IWUSR | S_IWGRP | S_IRUSR | S_IRGRP,
+ data->debug_base,
+ data,
+ &debug_data_fops)))) {
+ dev_err(&data->client->dev, "Failed to create data file\n");
+ debugfs_remove_recursive(data->debug_base);
+ return -EINVAL;
+ }
+
+ if ((IS_ERR_OR_NULL(debugfs_create_file(GTP_DEBUGFS_FILE_ADDR,
+ S_IWUSR | S_IWGRP | S_IRUSR | S_IRGRP,
+ data->debug_base,
+ data,
+ &debug_addr_fops)))) {
+ dev_err(&data->client->dev, "Failed to create addr file\n");
debugfs_remove_recursive(data->debug_base);
return -EINVAL;
}
@@ -1645,8 +1841,8 @@ static int goodix_parse_dt(struct device *dev,
pdata->i2c_pull_up = of_property_read_bool(np,
"goodix,i2c-pull-up");
- pdata->no_force_update = of_property_read_bool(np,
- "goodix,no-force-update");
+ pdata->force_update = of_property_read_bool(np,
+ "goodix,force-update");
pdata->enable_power_off = of_property_read_bool(np,
"goodix,enable-power-off");
@@ -1761,9 +1957,7 @@ static int goodix_ts_probe(struct i2c_client *client,
return -EINVAL;
}
-#if GTP_ESD_PROTECT
i2c_connect_client = client;
-#endif
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
dev_err(&client->dev, "GTP I2C not supported\n");
@@ -1811,22 +2005,24 @@ static int goodix_ts_probe(struct i2c_client *client,
goto exit_power_off;
}
+ if (pdata->force_update)
+ ts->force_update = true;
+
if (pdata->fw_name)
strlcpy(ts->fw_name, pdata->fw_name,
strlen(pdata->fw_name) + 1);
-#ifdef CONFIG_GT9XX_TOUCHPANEL_UPDATE
- ret = gup_init_update_proc(ts);
- if (ret < 0) {
- dev_err(&client->dev,
- "GTP Create firmware update thread error.\n");
- goto exit_power_off;
+ if (config_enabled(CONFIG_GT9XX_TOUCHPANEL_UPDATE)) {
+ ret = gup_init_update_proc(ts);
+ if (ret < 0) {
+ dev_err(&client->dev,
+ "GTP Create firmware update thread error\n");
+ goto exit_power_off;
+ }
}
-#endif
-
ret = gtp_init_panel(ts);
if (ret < 0) {
- dev_err(&client->dev, "GTP init panel failed.\n");
+ dev_err(&client->dev, "GTP init panel failed\n");
ts->abs_x_max = GTP_MAX_WIDTH;
ts->abs_y_max = GTP_MAX_HEIGHT;
ts->int_trigger_type = GTP_INT_TRIGGER;
@@ -1834,7 +2030,7 @@ static int goodix_ts_probe(struct i2c_client *client,
ret = gtp_request_input_dev(ts);
if (ret) {
- dev_err(&client->dev, "GTP request input dev failed.\n");
+ dev_err(&client->dev, "GTP request input dev failed\n");
goto exit_free_inputdev;
}
input_set_drvdata(ts->input_dev, ts);
@@ -2017,6 +2213,14 @@ static int goodix_ts_suspend(struct device *dev)
}
mutex_lock(&ts->lock);
+
+ if (ts->fw_loading) {
+ dev_info(&ts->client->dev,
+ "Fw upgrade in progress, can't go to suspend.");
+ mutex_unlock(&ts->lock);
+ return 0;
+ }
+
#if GTP_ESD_PROTECT
gtp_esd_switch(ts->client, SWITCH_OFF);
#endif
diff --git a/drivers/input/touchscreen/gt9xx/gt9xx.h b/drivers/input/touchscreen/gt9xx/gt9xx.h
index 38487eea7b10..779a0ddd93f8 100644
--- a/drivers/input/touchscreen/gt9xx/gt9xx.h
+++ b/drivers/input/touchscreen/gt9xx/gt9xx.h
@@ -53,7 +53,7 @@ struct goodix_ts_platform_data {
u32 panel_miny;
u32 panel_maxx;
u32 panel_maxy;
- bool no_force_update;
+ bool force_update;
bool i2c_pull_up;
bool enable_power_off;
size_t config_data_len[GOODIX_MAX_CFG_GROUP];
@@ -74,6 +74,7 @@ struct goodix_ts_data {
s32 use_irq;
u16 abs_x_max;
u16 abs_y_max;
+ u16 addr;
u8 max_touch_num;
u8 int_trigger_type;
u8 green_wake_mode;
@@ -88,6 +89,8 @@ struct goodix_ts_data {
u8 fw_error;
bool power_on;
struct mutex lock;
+ bool fw_loading;
+ bool force_update;
struct regulator *avdd;
struct regulator *vdd;
struct regulator *vcc_i2c;
@@ -172,6 +175,8 @@ extern u16 total_len;
/* HIGH: 0x28/0x29, LOW: 0xBA/0xBB */
#define GTP_I2C_ADDRESS_HIGH 0x14
#define GTP_I2C_ADDRESS_LOW 0x5D
+#define GTP_VALID_ADDR_START 0x8040
+#define GTP_VALID_ADDR_END 0x8177
/* GTP CM_HEAD RW flags */
#define GTP_RW_READ 0
@@ -210,11 +215,9 @@ s32 init_wr_node(struct i2c_client *client);
void uninit_wr_node(void);
#endif
-#ifdef CONFIG_GT9XX_TOUCHPANEL_UPDATE
-extern u8 gup_init_update_proc(struct goodix_ts_data *ts);
+u8 gup_init_update_proc(struct goodix_ts_data *ts);
s32 gup_enter_update_mode(struct i2c_client *client);
void gup_leave_update_mode(struct i2c_client *client);
s32 gup_update_proc(void *dir);
extern struct i2c_client *i2c_connect_client;
-#endif
#endif /* _GOODIX_GT9XX_H_ */
diff --git a/drivers/input/touchscreen/gt9xx/gt9xx_update.c b/drivers/input/touchscreen/gt9xx/gt9xx_update.c
index 4660b27d156c..a91256c576e3 100644
--- a/drivers/input/touchscreen/gt9xx/gt9xx_update.c
+++ b/drivers/input/touchscreen/gt9xx/gt9xx_update.c
@@ -1408,10 +1408,15 @@ s32 gup_update_proc(void *dir)
goto file_fail;
}
- ret = gup_enter_update_judge(ts->client, &fw_head);
- if (ret == FAIL) {
- pr_err("Check *.bin file fail");
- goto file_fail;
+ if (ts->force_update) {
+ dev_dbg(&ts->client->dev, "Enter force update.");
+ } else {
+ ret = gup_enter_update_judge(ts->client, &fw_head);
+ if (ret == FAIL) {
+ dev_err(&ts->client->dev,
+ "Check *.bin file fail.");
+ goto file_fail;
+ }
}
ts->enter_update = 1;
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index afa519aa8203..702706ae60f7 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -2938,7 +2938,7 @@ static struct iommu_group *arm_smmu_device_group(struct device *dev)
*/
group = generic_device_group(dev);
- if (IS_ERR(group))
+ if (IS_ERR_OR_NULL(group))
return group;
if (dev_is_pci(dev))
diff --git a/drivers/platform/msm/gsi/gsi.c b/drivers/platform/msm/gsi/gsi.c
index bd2132d77360..df3901093006 100644
--- a/drivers/platform/msm/gsi/gsi.c
+++ b/drivers/platform/msm/gsi/gsi.c
@@ -108,6 +108,11 @@ static void gsi_handle_ch_ctrl(int ee)
GSIDBG("ch %x\n", ch);
for (i = 0; i < 32; i++) {
if ((1 << i) & ch) {
+ if (i >= gsi_ctx->max_ch || i >= GSI_CHAN_MAX) {
+ GSIERR("invalid channel %d\n", i);
+ break;
+ }
+
ctx = &gsi_ctx->chan[i];
val = gsi_readl(gsi_ctx->base +
GSI_EE_n_GSI_CH_k_CNTXT_0_OFFS(i, ee));
@@ -116,6 +121,7 @@ static void gsi_handle_ch_ctrl(int ee)
GSI_EE_n_GSI_CH_k_CNTXT_0_CHSTATE_SHFT;
GSIDBG("ch %u state updated to %u\n", i, ctx->state);
complete(&ctx->compl);
+ gsi_ctx->ch_dbg[i].cmd_completed++;
}
}
@@ -135,6 +141,11 @@ static void gsi_handle_ev_ctrl(int ee)
GSIDBG("ev %x\n", ch);
for (i = 0; i < 32; i++) {
if ((1 << i) & ch) {
+ if (i >= gsi_ctx->max_ev || i >= GSI_EVT_RING_MAX) {
+ GSIERR("invalid event %d\n", i);
+ break;
+ }
+
ctx = &gsi_ctx->evtr[i];
val = gsi_readl(gsi_ctx->base +
GSI_EE_n_EV_CH_k_CNTXT_0_OFFS(i, ee));
@@ -1605,6 +1616,7 @@ int gsi_alloc_channel(struct gsi_chan_props *props, unsigned long dev_hdl,
ctx->props = *props;
mutex_lock(&gsi_ctx->mlock);
+ gsi_ctx->ch_dbg[props->ch_id].ch_allocate++;
val = (((props->ch_id << GSI_EE_n_GSI_CH_CMD_CHID_SHFT) &
GSI_EE_n_GSI_CH_CMD_CHID_BMSK) |
((op << GSI_EE_n_GSI_CH_CMD_OPCODE_SHFT) &
@@ -1775,6 +1787,7 @@ int gsi_start_channel(unsigned long chan_hdl)
mutex_lock(&gsi_ctx->mlock);
init_completion(&ctx->compl);
+ gsi_ctx->ch_dbg[chan_hdl].ch_start++;
val = (((chan_hdl << GSI_EE_n_GSI_CH_CMD_CHID_SHFT) &
GSI_EE_n_GSI_CH_CMD_CHID_BMSK) |
((op << GSI_EE_n_GSI_CH_CMD_OPCODE_SHFT) &
@@ -1832,6 +1845,7 @@ int gsi_stop_channel(unsigned long chan_hdl)
mutex_lock(&gsi_ctx->mlock);
init_completion(&ctx->compl);
+ gsi_ctx->ch_dbg[chan_hdl].ch_stop++;
val = (((chan_hdl << GSI_EE_n_GSI_CH_CMD_CHID_SHFT) &
GSI_EE_n_GSI_CH_CMD_CHID_BMSK) |
((op << GSI_EE_n_GSI_CH_CMD_OPCODE_SHFT) &
@@ -1900,6 +1914,7 @@ int gsi_stop_db_channel(unsigned long chan_hdl)
mutex_lock(&gsi_ctx->mlock);
init_completion(&ctx->compl);
+ gsi_ctx->ch_dbg[chan_hdl].ch_db_stop++;
val = (((chan_hdl << GSI_EE_n_GSI_CH_CMD_CHID_SHFT) &
GSI_EE_n_GSI_CH_CMD_CHID_BMSK) |
((op << GSI_EE_n_GSI_CH_CMD_OPCODE_SHFT) &
@@ -1964,6 +1979,7 @@ int gsi_reset_channel(unsigned long chan_hdl)
reset:
init_completion(&ctx->compl);
+ gsi_ctx->ch_dbg[chan_hdl].ch_reset++;
val = (((chan_hdl << GSI_EE_n_GSI_CH_CMD_CHID_SHFT) &
GSI_EE_n_GSI_CH_CMD_CHID_BMSK) |
((op << GSI_EE_n_GSI_CH_CMD_OPCODE_SHFT) &
@@ -2030,6 +2046,7 @@ int gsi_dealloc_channel(unsigned long chan_hdl)
mutex_lock(&gsi_ctx->mlock);
init_completion(&ctx->compl);
+ gsi_ctx->ch_dbg[chan_hdl].ch_de_alloc++;
val = (((chan_hdl << GSI_EE_n_GSI_CH_CMD_CHID_SHFT) &
GSI_EE_n_GSI_CH_CMD_CHID_BMSK) |
((op << GSI_EE_n_GSI_CH_CMD_OPCODE_SHFT) &
diff --git a/drivers/platform/msm/gsi/gsi.h b/drivers/platform/msm/gsi/gsi.h
index 0b94ed2d3a92..750ae2b329d3 100644
--- a/drivers/platform/msm/gsi/gsi.h
+++ b/drivers/platform/msm/gsi/gsi.h
@@ -125,12 +125,23 @@ struct gsi_ee_scratch {
uint32_t word1;
};
+struct ch_debug_stats {
+ unsigned long ch_allocate;
+ unsigned long ch_start;
+ unsigned long ch_stop;
+ unsigned long ch_reset;
+ unsigned long ch_de_alloc;
+ unsigned long ch_db_stop;
+ unsigned long cmd_completed;
+};
+
struct gsi_ctx {
void __iomem *base;
struct device *dev;
struct gsi_per_props per;
bool per_registered;
struct gsi_chan_ctx chan[GSI_CHAN_MAX];
+ struct ch_debug_stats ch_dbg[GSI_CHAN_MAX];
struct gsi_evt_ctx evtr[GSI_EVT_RING_MAX];
struct mutex mlock;
spinlock_t slock;
diff --git a/drivers/power/qcom-charger/fg-util.c b/drivers/power/qcom-charger/fg-util.c
index bbdbe48896d7..0e3c7dbb5731 100644
--- a/drivers/power/qcom-charger/fg-util.c
+++ b/drivers/power/qcom-charger/fg-util.c
@@ -621,6 +621,17 @@ static ssize_t fg_sram_dfs_reg_write(struct file *file, const char __user *buf,
/* Parse the data in the buffer. It should be a string of numbers */
while ((pos < count) &&
sscanf(kbuf + pos, "%i%n", &data, &bytes_read) == 1) {
+ /*
+ * We shouldn't be receiving a string of characters that
+ * exceeds a size of 5 to keep this functionally correct.
+ * Also, we should make sure that pos never gets overflowed
+ * beyond the limit.
+ */
+ if (bytes_read > 5 || bytes_read > INT_MAX - pos) {
+ cnt = 0;
+ ret = -EINVAL;
+ break;
+ }
pos += bytes_read;
values[cnt++] = data & 0xff;
}
diff --git a/drivers/power/qcom-charger/qpnp-fg-gen3.c b/drivers/power/qcom-charger/qpnp-fg-gen3.c
index c0a19ae115d0..c0e4e533cab9 100644
--- a/drivers/power/qcom-charger/qpnp-fg-gen3.c
+++ b/drivers/power/qcom-charger/qpnp-fg-gen3.c
@@ -1663,7 +1663,7 @@ static void fg_notify_charger(struct fg_chip *chip)
return;
}
- prop.intval = chip->bp.fastchg_curr_ma;
+ prop.intval = chip->bp.fastchg_curr_ma * 1000;
rc = power_supply_set_property(chip->batt_psy,
POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, &prop);
if (rc < 0) {
diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 6ceac4f2d4b2..560c5c72daeb 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -103,6 +103,7 @@ struct cpufreq_cooling_device {
int dyn_power_table_entries;
struct device *cpu_dev;
get_static_t plat_get_static_power;
+ struct cpu_cooling_ops *plat_ops;
};
static DEFINE_IDR(cpufreq_idr);
static DEFINE_MUTEX(cooling_cpufreq_lock);
@@ -504,8 +505,13 @@ static int cpufreq_get_cur_state(struct thermal_cooling_device *cdev,
unsigned long *state)
{
struct cpufreq_cooling_device *cpufreq_device = cdev->devdata;
+ unsigned int cpu = cpumask_any(&cpufreq_device->allowed_cpus);
- *state = cpufreq_device->cpufreq_state;
+ if (cpufreq_device->plat_ops
+ && cpufreq_device->plat_ops->get_cur_state)
+ cpufreq_device->plat_ops->get_cur_state(cpu, state);
+ else
+ *state = cpufreq_device->cpufreq_state;
return 0;
}
@@ -539,7 +545,17 @@ static int cpufreq_set_cur_state(struct thermal_cooling_device *cdev,
cpufreq_device->cpufreq_state = state;
cpufreq_device->clipped_freq = clip_freq;
- cpufreq_update_policy(cpu);
+ /* Check if the device has a platform mitigation function that
+ * can handle the CPU freq mitigation, if not, notify cpufreq
+ * framework.
+ */
+ if (cpufreq_device->plat_ops) {
+ if (cpufreq_device->plat_ops->ceil_limit)
+ cpufreq_device->plat_ops->ceil_limit(cpu,
+ clip_freq);
+ } else {
+ cpufreq_update_policy(cpu);
+ }
return 0;
}
@@ -773,6 +789,9 @@ static unsigned int find_next_max(struct cpufreq_frequency_table *table,
* @capacitance: dynamic power coefficient for these cpus
* @plat_static_func: function to calculate the static power consumed by these
* cpus (optional)
+ * @plat_mitig_func: function that does the mitigation by changing the
+ * frequencies (Optional). By default, cpufreq framweork will
+ * be notified of the new limits.
*
* This interface function registers the cpufreq cooling device with the name
* "thermal-cpufreq-%x". This api can support multiple instances of cpufreq
@@ -785,7 +804,8 @@ static unsigned int find_next_max(struct cpufreq_frequency_table *table,
static struct thermal_cooling_device *
__cpufreq_cooling_register(struct device_node *np,
const struct cpumask *clip_cpus, u32 capacitance,
- get_static_t plat_static_func)
+ get_static_t plat_static_func,
+ struct cpu_cooling_ops *plat_ops)
{
struct thermal_cooling_device *cool_dev;
struct cpufreq_cooling_device *cpufreq_dev;
@@ -851,6 +871,8 @@ __cpufreq_cooling_register(struct device_node *np,
}
}
+ cpufreq_dev->plat_ops = plat_ops;
+
ret = get_idr(&cpufreq_idr, &cpufreq_dev->id);
if (ret) {
cool_dev = ERR_PTR(ret);
@@ -924,7 +946,7 @@ free_cdev:
struct thermal_cooling_device *
cpufreq_cooling_register(const struct cpumask *clip_cpus)
{
- return __cpufreq_cooling_register(NULL, clip_cpus, 0, NULL);
+ return __cpufreq_cooling_register(NULL, clip_cpus, 0, NULL, NULL);
}
EXPORT_SYMBOL_GPL(cpufreq_cooling_register);
@@ -948,7 +970,7 @@ of_cpufreq_cooling_register(struct device_node *np,
if (!np)
return ERR_PTR(-EINVAL);
- return __cpufreq_cooling_register(np, clip_cpus, 0, NULL);
+ return __cpufreq_cooling_register(np, clip_cpus, 0, NULL, NULL);
}
EXPORT_SYMBOL_GPL(of_cpufreq_cooling_register);
@@ -978,11 +1000,31 @@ cpufreq_power_cooling_register(const struct cpumask *clip_cpus, u32 capacitance,
get_static_t plat_static_func)
{
return __cpufreq_cooling_register(NULL, clip_cpus, capacitance,
- plat_static_func);
+ plat_static_func, NULL);
}
EXPORT_SYMBOL(cpufreq_power_cooling_register);
/**
+ * cpufreq_platform_cooling_register() - create cpufreq cooling device with
+ * additional platform specific mitigation function.
+ *
+ * @clip_cpus: cpumask of cpus where the frequency constraints will happen
+ * @plat_ops: the platform mitigation functions that will be called insted of
+ * cpufreq, if provided.
+ *
+ * Return: a valid struct thermal_cooling_device pointer on success,
+ * on failure, it returns a corresponding ERR_PTR().
+ */
+struct thermal_cooling_device *
+cpufreq_platform_cooling_register(const struct cpumask *clip_cpus,
+ struct cpu_cooling_ops *plat_ops)
+{
+ return __cpufreq_cooling_register(NULL, clip_cpus, 0, NULL,
+ plat_ops);
+}
+EXPORT_SYMBOL(cpufreq_platform_cooling_register);
+
+/**
* of_cpufreq_power_cooling_register() - create cpufreq cooling device with power extensions
* @np: a valid struct device_node to the cooling device device tree node
* @clip_cpus: cpumask of cpus where the frequency constraints will happen
@@ -1015,7 +1057,7 @@ of_cpufreq_power_cooling_register(struct device_node *np,
return ERR_PTR(-EINVAL);
return __cpufreq_cooling_register(np, clip_cpus, capacitance,
- plat_static_func);
+ plat_static_func, NULL);
}
EXPORT_SYMBOL(of_cpufreq_power_cooling_register);
diff --git a/drivers/thermal/msm_lmh_dcvs.c b/drivers/thermal/msm_lmh_dcvs.c
index fbe76eaa3867..3758e39a1c02 100644
--- a/drivers/thermal/msm_lmh_dcvs.c
+++ b/drivers/thermal/msm_lmh_dcvs.c
@@ -24,6 +24,7 @@
#include <linux/interrupt.h>
#include <linux/timer.h>
#include <linux/pm_opp.h>
+#include <linux/cpu_cooling.h>
#include <asm/smp_plat.h>
#include <asm/cacheflush.h>
@@ -40,6 +41,7 @@
#define MSM_LIMITS_NODE_DCVS 0x44435653
#define MSM_LIMITS_SUB_FN_THERMAL 0x54484D4C
+#define MSM_LIMITS_SUB_FN_GENERAL 0x47454E00
#define MSM_LIMITS_ALGO_MODE_ENABLE 0x454E424C
@@ -49,6 +51,8 @@
#define MSM_LIMITS_CLUSTER_0 0x6370302D
#define MSM_LIMITS_CLUSTER_1 0x6370312D
+#define MSM_LIMITS_DOMAIN_MAX 0x444D4158
+
#define MSM_LIMITS_HIGH_THRESHOLD_VAL 95000
#define MSM_LIMITS_ARM_THRESHOLD_VAL 65000
#define MSM_LIMITS_POLLING_DELAY_MS 10
@@ -77,8 +81,12 @@ struct msm_lmh_dcvs_hw {
cpumask_t core_map;
struct timer_list poll_timer;
uint32_t max_freq;
+ uint32_t hw_freq_limit;
+ struct list_head list;
};
+LIST_HEAD(lmh_dcvs_hw_list);
+
static void msm_lmh_dcvs_get_max_freq(uint32_t cpu, uint32_t *max_freq)
{
unsigned long freq_ceil = UINT_MAX;
@@ -99,12 +107,29 @@ static void msm_lmh_dcvs_get_max_freq(uint32_t cpu, uint32_t *max_freq)
static uint32_t msm_lmh_mitigation_notify(struct msm_lmh_dcvs_hw *hw)
{
uint32_t max_limit = 0, val = 0;
+ struct device *cpu_dev = NULL;
+ unsigned long freq_val;
val = readl_relaxed(hw->osm_hw_reg);
dcvsh_get_frequency(val, max_limit);
+ cpu_dev = get_cpu_device(cpumask_first(&hw->core_map));
+ if (!cpu_dev) {
+ pr_err("Error in get CPU%d device\n",
+ cpumask_first(&hw->core_map));
+ goto notify_exit;
+ }
+
+ freq_val = max_limit;
+ rcu_read_lock();
+ dev_pm_opp_find_freq_floor(cpu_dev, &freq_val);
+ rcu_read_unlock();
+ max_limit = freq_val;
+
sched_update_cpu_freq_min_max(&hw->core_map, 0, max_limit);
trace_lmh_dcvs_freq(cpumask_first(&hw->core_map), max_limit);
+notify_exit:
+ hw->hw_freq_limit = max_limit;
return max_limit;
}
@@ -250,6 +275,45 @@ static int trip_notify(enum thermal_trip_type type, int temp, void *data)
return 0;
}
+static struct msm_lmh_dcvs_hw *get_dcvsh_hw_from_cpu(int cpu)
+{
+ struct msm_lmh_dcvs_hw *hw;
+
+ list_for_each_entry(hw, &lmh_dcvs_hw_list, list) {
+ if (cpumask_test_cpu(cpu, &hw->core_map))
+ return hw;
+ }
+
+ return NULL;
+}
+
+static int lmh_set_max_limit(int cpu, u32 freq)
+{
+ struct msm_lmh_dcvs_hw *hw = get_dcvsh_hw_from_cpu(cpu);
+
+ if (!hw)
+ return -EINVAL;
+
+ return msm_lmh_dcvs_write(hw->affinity, MSM_LIMITS_SUB_FN_GENERAL,
+ MSM_LIMITS_DOMAIN_MAX, freq);
+}
+
+static int lmh_get_cur_limit(int cpu, unsigned long *freq)
+{
+ struct msm_lmh_dcvs_hw *hw = get_dcvsh_hw_from_cpu(cpu);
+
+ if (!hw)
+ return -EINVAL;
+ *freq = hw->hw_freq_limit;
+
+ return 0;
+}
+
+static struct cpu_cooling_ops cd_ops = {
+ .get_cur_state = lmh_get_cur_limit,
+ .ceil_limit = lmh_set_max_limit,
+};
+
static int msm_lmh_dcvs_probe(struct platform_device *pdev)
{
int ret;
@@ -257,6 +321,7 @@ static int msm_lmh_dcvs_probe(struct platform_device *pdev)
struct msm_lmh_dcvs_hw *hw;
char sensor_name[] = "limits_sensor-00";
struct thermal_zone_device *tzdev;
+ struct thermal_cooling_device *cdev;
struct device_node *dn = pdev->dev.of_node;
struct device_node *cpu_node, *lmh_node;
uint32_t id, max_freq, request_reg, clear_reg;
@@ -331,6 +396,10 @@ static int msm_lmh_dcvs_probe(struct platform_device *pdev)
if (IS_ERR_OR_NULL(tzdev))
return PTR_ERR(tzdev);
+ /* Setup cooling devices to request mitigation states */
+ cdev = cpufreq_platform_cooling_register(&hw->core_map, &cd_ops);
+ if (IS_ERR_OR_NULL(cdev))
+ return PTR_ERR(cdev);
/*
* Driver defaults to for low and hi thresholds.
* Since we make a check for hi > lo value, set the hi threshold
@@ -356,7 +425,7 @@ static int msm_lmh_dcvs_probe(struct platform_device *pdev)
return ret;
}
- hw->max_freq = max_freq;
+ hw->hw_freq_limit = hw->max_freq = max_freq;
switch (affinity) {
case 0:
@@ -399,6 +468,9 @@ static int msm_lmh_dcvs_probe(struct platform_device *pdev)
return ret;
}
+ INIT_LIST_HEAD(&hw->list);
+ list_add(&hw->list, &lmh_dcvs_hw_list);
+
return ret;
}
diff --git a/include/linux/cpu_cooling.h b/include/linux/cpu_cooling.h
index c156f5082758..e221494fb7a0 100644
--- a/include/linux/cpu_cooling.h
+++ b/include/linux/cpu_cooling.h
@@ -31,6 +31,11 @@
typedef int (*get_static_t)(cpumask_t *cpumask, int interval,
unsigned long voltage, u32 *power);
+struct cpu_cooling_ops {
+ int (*ceil_limit)(int, u32);
+ int (*get_cur_state)(int, unsigned long *);
+};
+
#ifdef CONFIG_CPU_THERMAL
/**
* cpufreq_cooling_register - function to create cpufreq cooling device.
@@ -43,6 +48,10 @@ struct thermal_cooling_device *
cpufreq_power_cooling_register(const struct cpumask *clip_cpus,
u32 capacitance, get_static_t plat_static_func);
+struct thermal_cooling_device *
+cpufreq_platform_cooling_register(const struct cpumask *clip_cpus,
+ struct cpu_cooling_ops *ops);
+
/**
* of_cpufreq_cooling_register - create cpufreq cooling device based on DT.
* @np: a valid struct device_node to the cooling device device tree node.
@@ -112,6 +121,13 @@ of_cpufreq_power_cooling_register(struct device_node *np,
return NULL;
}
+static inline struct thermal_cooling_device *
+cpufreq_platform_cooling_register(const struct cpumask *clip_cpus,
+ struct cpu_cooling_ops *ops)
+{
+ return NULL;
+}
+
static inline
void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
{
diff --git a/kernel/sched/core_ctl.h b/include/linux/sched/core_ctl.h
index 3b0c12acb9c0..98d7cb3e899b 100644
--- a/kernel/sched/core_ctl.h
+++ b/include/linux/sched/core_ctl.h
@@ -16,9 +16,12 @@
#ifdef CONFIG_SCHED_CORE_CTL
void core_ctl_check(u64 wallclock);
-void core_ctl_set_boost(bool boost);
+int core_ctl_set_boost(bool boost);
#else
static inline void core_ctl_check(u64 wallclock) {}
-static inline void core_ctl_set_boost(bool boost) {}
+static inline int core_ctl_set_boost(bool boost)
+{
+ return 0;
+}
#endif
#endif
diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h
index cd15ae7b8b0c..7778ff3947de 100644
--- a/include/trace/events/sched.h
+++ b/include/trace/events/sched.h
@@ -1323,6 +1323,21 @@ TRACE_EVENT(core_ctl_set_busy,
__entry->is_busy)
);
+TRACE_EVENT(core_ctl_set_boost,
+
+ TP_PROTO(u32 refcount, s32 ret),
+ TP_ARGS(refcount, ret),
+ TP_STRUCT__entry(
+ __field(u32, refcount)
+ __field(s32, ret)
+ ),
+ TP_fast_assign(
+ __entry->refcount = refcount;
+ __entry->ret = ret;
+ ),
+ TP_printk("refcount=%u, ret=%d", __entry->refcount, __entry->ret)
+);
+
/**
* sched_isolate - called when cores are isolated/unisolated
*
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 7e7e19ed53c6..53f7b50b7541 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -75,6 +75,7 @@
#include <linux/context_tracking.h>
#include <linux/compiler.h>
#include <linux/irq.h>
+#include <linux/sched/core_ctl.h>
#include <asm/switch_to.h>
#include <asm/tlb.h>
@@ -85,7 +86,6 @@
#endif
#include "sched.h"
-#include "core_ctl.h"
#include "../workqueue_internal.h"
#include "../smpboot.h"
diff --git a/kernel/sched/core_ctl.c b/kernel/sched/core_ctl.c
index d81886da7ca2..0db85a4fa9c8 100644
--- a/kernel/sched/core_ctl.c
+++ b/kernel/sched/core_ctl.c
@@ -45,7 +45,7 @@ struct cluster_data {
bool nrrun_changed;
struct task_struct *core_ctl_thread;
unsigned int first_cpu;
- bool boost;
+ unsigned int boost;
struct kobject kobj;
};
@@ -652,17 +652,40 @@ static bool do_check(u64 wallclock)
return do_check;
}
-void core_ctl_set_boost(bool boost)
+int core_ctl_set_boost(bool boost)
{
unsigned int index = 0;
struct cluster_data *cluster;
+ unsigned long flags;
+ int ret = 0;
+ bool boost_state_changed = false;
+ spin_lock_irqsave(&state_lock, flags);
for_each_cluster(cluster, index) {
- if (cluster->is_big_cluster && cluster->boost != boost) {
- cluster->boost = boost;
- apply_need(cluster);
+ if (cluster->is_big_cluster) {
+ if (boost) {
+ boost_state_changed = !cluster->boost;
+ ++cluster->boost;
+ } else {
+ if (!cluster->boost) {
+ pr_err("Error turning off boost. Boost already turned off\n");
+ ret = -EINVAL;
+ } else {
+ --cluster->boost;
+ boost_state_changed = !cluster->boost;
+ }
+ }
+ break;
}
}
+ spin_unlock_irqrestore(&state_lock, flags);
+
+ if (boost_state_changed)
+ apply_need(cluster);
+
+ trace_core_ctl_set_boost(cluster->boost, ret);
+
+ return ret;
}
void core_ctl_check(u64 wallclock)
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 98ae45174a40..e32d4d7903b0 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -3056,7 +3056,8 @@ bias_to_prev_cpu(struct cpu_select_env *env, struct cluster_cpu_stats *stats)
static inline bool
wake_to_waker_cluster(struct cpu_select_env *env)
{
- return !env->need_idle && !env->reason && env->sync &&
+ return env->boost_type == SCHED_BOOST_NONE &&
+ !env->need_idle && !env->reason && env->sync &&
task_load(current) > sched_big_waker_task_load &&
task_load(env->p) < sched_small_wakee_task_load;
}
diff --git a/kernel/sched/hmp.c b/kernel/sched/hmp.c
index 7039eb8f1e63..d220482f4dbc 100644
--- a/kernel/sched/hmp.c
+++ b/kernel/sched/hmp.c
@@ -18,9 +18,9 @@
#include <linux/list_sort.h>
#include <linux/syscore_ops.h>
#include <linux/of.h>
+#include <linux/sched/core_ctl.h>
#include "sched.h"
-#include "core_ctl.h"
#include <trace/events/sched.h>
diff --git a/sound/soc/codecs/wcd934x/wcd934x.c b/sound/soc/codecs/wcd934x/wcd934x.c
index 30c23df444d6..a526e1afdd28 100644
--- a/sound/soc/codecs/wcd934x/wcd934x.c
+++ b/sound/soc/codecs/wcd934x/wcd934x.c
@@ -3602,7 +3602,7 @@ static void tavil_tx_hpf_corner_freq_callback(struct work_struct *work)
struct hpf_work *hpf_work;
struct tavil_priv *tavil;
struct snd_soc_codec *codec;
- u16 dec_cfg_reg, amic_reg;
+ u16 dec_cfg_reg, amic_reg, go_bit_reg;
u8 hpf_cut_off_freq;
int amic_n;
@@ -3613,6 +3613,7 @@ static void tavil_tx_hpf_corner_freq_callback(struct work_struct *work)
hpf_cut_off_freq = hpf_work->hpf_cut_off_freq;
dec_cfg_reg = WCD934X_CDC_TX0_TX_PATH_CFG0 + 16 * hpf_work->decimator;
+ go_bit_reg = dec_cfg_reg + 7;
dev_dbg(codec->dev, "%s: decimator %u hpf_cut_of_freq 0x%x\n",
__func__, hpf_work->decimator, hpf_cut_off_freq);
@@ -3624,6 +3625,10 @@ static void tavil_tx_hpf_corner_freq_callback(struct work_struct *work)
}
snd_soc_update_bits(codec, dec_cfg_reg, TX_HPF_CUT_OFF_FREQ_MASK,
hpf_cut_off_freq << 5);
+ snd_soc_update_bits(codec, go_bit_reg, 0x02, 0x02);
+ /* Minimum 1 clk cycle delay is required as per HW spec */
+ usleep_range(1000, 1010);
+ snd_soc_update_bits(codec, go_bit_reg, 0x02, 0x00);
}
static void tavil_tx_mute_update_callback(struct work_struct *work)
@@ -3643,7 +3648,6 @@ static void tavil_tx_mute_update_callback(struct work_struct *work)
16 * tx_mute_dwork->decimator;
hpf_gate_reg = WCD934X_CDC_TX0_TX_PATH_SEC2 +
16 * tx_mute_dwork->decimator;
- snd_soc_update_bits(codec, hpf_gate_reg, 0x01, 0x01);
snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x10, 0x00);
}
@@ -3730,20 +3734,27 @@ static int tavil_codec_enable_dec(struct snd_soc_dapm_widget *w,
break;
}
}
+ /* Enable TX PGA Mute */
+ snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x10, 0x10);
+ break;
+ case SND_SOC_DAPM_POST_PMU:
hpf_cut_off_freq = (snd_soc_read(codec, dec_cfg_reg) &
TX_HPF_CUT_OFF_FREQ_MASK) >> 5;
tavil->tx_hpf_work[decimator].hpf_cut_off_freq =
hpf_cut_off_freq;
- if (hpf_cut_off_freq != CF_MIN_3DB_150HZ)
+ if (hpf_cut_off_freq != CF_MIN_3DB_150HZ) {
snd_soc_update_bits(codec, dec_cfg_reg,
TX_HPF_CUT_OFF_FREQ_MASK,
CF_MIN_3DB_150HZ << 5);
- /* Enable TX PGA Mute */
- snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x10, 0x10);
- break;
- case SND_SOC_DAPM_POST_PMU:
- snd_soc_update_bits(codec, hpf_gate_reg, 0x01, 0x00);
+ snd_soc_update_bits(codec, hpf_gate_reg, 0x02, 0x02);
+ /*
+ * Minimum 1 clk cycle delay is required as per
+ * HW spec.
+ */
+ usleep_range(1000, 1010);
+ snd_soc_update_bits(codec, hpf_gate_reg, 0x02, 0x00);
+ }
/* schedule work queue to Remove Mute */
schedule_delayed_work(&tavil->tx_mute_dwork[decimator].dwork,
msecs_to_jiffies(tx_unmute_delay));
@@ -3760,10 +3771,20 @@ static int tavil_codec_enable_dec(struct snd_soc_dapm_widget *w,
snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x10, 0x10);
if (cancel_delayed_work_sync(
&tavil->tx_hpf_work[decimator].dwork)) {
- if (hpf_cut_off_freq != CF_MIN_3DB_150HZ)
+ if (hpf_cut_off_freq != CF_MIN_3DB_150HZ) {
snd_soc_update_bits(codec, dec_cfg_reg,
TX_HPF_CUT_OFF_FREQ_MASK,
hpf_cut_off_freq << 5);
+ snd_soc_update_bits(codec, hpf_gate_reg,
+ 0x02, 0x02);
+ /*
+ * Minimum 1 clk cycle delay is required as per
+ * HW spec.
+ */
+ usleep_range(1000, 1010);
+ snd_soc_update_bits(codec, hpf_gate_reg,
+ 0x02, 0x00);
+ }
}
cancel_delayed_work_sync(
&tavil->tx_mute_dwork[decimator].dwork);