summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-mdss-panels.dtsi62
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-mdss.dtsi1
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-pm660a-qrd.dts32
-rw-r--r--drivers/char/diag/diagchar.h1
-rw-r--r--drivers/char/diag/diagchar_core.c20
-rw-r--r--drivers/char/diag/diagfwd_cntl.c6
-rw-r--r--drivers/iio/adc/qcom-rradc.c13
-rw-r--r--drivers/input/touchscreen/Kconfig10
-rw-r--r--drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c16
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c22
-rw-r--r--drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c2
-rw-r--r--drivers/mmc/host/sdhci-msm.c4
-rw-r--r--drivers/net/wireless/ath/wil6210/main.c20
-rw-r--r--drivers/pci/host/pci-msm.c50
-rw-r--r--drivers/power/supply/qcom/fg-core.h14
-rw-r--r--drivers/power/supply/qcom/fg-memif.c78
-rw-r--r--drivers/power/supply/qcom/qpnp-fg-gen3.c64
-rw-r--r--drivers/power/supply/qcom/qpnp-qnovo.c143
-rw-r--r--drivers/power/supply/qcom/qpnp-smb2.c2
-rw-r--r--drivers/power/supply/qcom/smb-lib.h1
-rw-r--r--drivers/soc/qcom/glink_private.h5
-rw-r--r--drivers/soc/qcom/glink_ssr.c84
-rw-r--r--drivers/usb/phy/phy-msm-ssusb-qmp.c8
-rw-r--r--fs/fat/fatent.c7
-rw-r--r--fs/fat/inode.c5
-rw-r--r--include/linux/qpnp/qpnp-revid.h23
-rw-r--r--sound/soc/codecs/sdm660_cdc/msm-digital-cdc.c2
27 files changed, 564 insertions, 131 deletions
diff --git a/arch/arm/boot/dts/qcom/sdm630-mdss-panels.dtsi b/arch/arm/boot/dts/qcom/sdm630-mdss-panels.dtsi
index 43a01094662a..77e99ef7f103 100644
--- a/arch/arm/boot/dts/qcom/sdm630-mdss-panels.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm630-mdss-panels.dtsi
@@ -15,6 +15,7 @@
#include "dsi-panel-nt35695b-truly-fhd-cmd.dtsi"
#include "dsi-panel-truly-1080p-cmd.dtsi"
#include "dsi-panel-truly-1080p-video.dtsi"
+#include "dsi-panel-rm67195-amoled-fhd-cmd.dtsi"
&soc {
dsi_panel_pwr_supply: dsi_panel_pwr_supply {
@@ -49,6 +50,57 @@
qcom,supply-post-on-sleep = <10>;
};
};
+
+ dsi_panel_pwr_supply_labibb_amoled:
+ dsi_panel_pwr_supply_labibb_amoled {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ qcom,panel-supply-entry@0 {
+ reg = <0>;
+ qcom,supply-name = "wqhd-vddio";
+ qcom,supply-min-voltage = <1880000>;
+ qcom,supply-max-voltage = <1950000>;
+ qcom,supply-enable-load = <32000>;
+ qcom,supply-disable-load = <80>;
+ };
+
+ qcom,panel-supply-entry@1 {
+ reg = <1>;
+ qcom,supply-name = "vdda-3p3";
+ qcom,supply-min-voltage = <3300000>;
+ qcom,supply-max-voltage = <3300000>;
+ qcom,supply-enable-load = <13200>;
+ qcom,supply-disable-load = <80>;
+ };
+
+ qcom,panel-supply-entry@2 {
+ reg = <2>;
+ qcom,supply-name = "lab";
+ qcom,supply-min-voltage = <4600000>;
+ qcom,supply-max-voltage = <6100000>;
+ qcom,supply-enable-load = <100000>;
+ qcom,supply-disable-load = <100>;
+ };
+
+ qcom,panel-supply-entry@3 {
+ reg = <3>;
+ qcom,supply-name = "ibb";
+ qcom,supply-min-voltage = <4000000>;
+ qcom,supply-max-voltage = <6300000>;
+ qcom,supply-enable-load = <100000>;
+ qcom,supply-disable-load = <100>;
+ };
+
+ qcom,panel-supply-entry@4 {
+ reg = <4>;
+ qcom,supply-name = "oledb";
+ qcom,supply-min-voltage = <5000000>;
+ qcom,supply-max-voltage = <8100000>;
+ qcom,supply-enable-load = <100000>;
+ qcom,supply-disable-load = <100>;
+ };
+ };
};
&dsi_nt35695b_truly_fhd_video {
@@ -98,3 +150,13 @@
qcom,esd-check-enabled;
qcom,mdss-dsi-panel-status-check-mode = "bta_check";
};
+
+&dsi_rm67195_amoled_fhd_cmd {
+ qcom,mdss-dsi-panel-timings-phy-v2 = [23 1e 07 08 05 03 04 a0
+ 23 1e 07 08 05 03 04 a0
+ 23 1e 07 08 05 03 04 a0
+ 23 1e 07 08 05 03 04 a0
+ 23 19 07 08 05 03 04 a0];
+ qcom,mdss-dsi-t-clk-post = <0x0d>;
+ qcom,mdss-dsi-t-clk-pre = <0x2d>;
+};
diff --git a/arch/arm/boot/dts/qcom/sdm630-mdss.dtsi b/arch/arm/boot/dts/qcom/sdm630-mdss.dtsi
index 9c34a60e7aaa..f12e18fbdfd6 100644
--- a/arch/arm/boot/dts/qcom/sdm630-mdss.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm630-mdss.dtsi
@@ -347,6 +347,7 @@
qcom,timing-db-mode;
wqhd-vddio-supply = <&pm660_l11>;
+ vdda-3p3-supply = <&pm660l_l6>;
lab-supply = <&lcdb_ldo_vreg>;
ibb-supply = <&lcdb_ncp_vreg>;
qcom,mdss-mdp = <&mdss_mdp>;
diff --git a/arch/arm/boot/dts/qcom/sdm630-pm660a-qrd.dts b/arch/arm/boot/dts/qcom/sdm630-pm660a-qrd.dts
index c2408ba7bf76..deb10b591444 100644
--- a/arch/arm/boot/dts/qcom/sdm630-pm660a-qrd.dts
+++ b/arch/arm/boot/dts/qcom/sdm630-pm660a-qrd.dts
@@ -51,3 +51,35 @@
qcom,wsa-devs = <&wsa881x_211_en>, <&wsa881x_213_en>;
qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrLeft";
};
+
+&pm660a_oledb {
+ status = "okay";
+ qcom,oledb-default-voltage-mv = <6400>;
+};
+
+&mdss_mdp {
+ qcom,mdss-pref-prim-intf = "dsi";
+};
+
+&mdss_dsi {
+ hw-config = "single_dsi";
+};
+
+&mdss_dsi0 {
+ qcom,dsi-pref-prim-pan = <&dsi_rm67195_amoled_fhd_cmd>;
+ pinctrl-names = "mdss_default", "mdss_sleep";
+ pinctrl-0 = <&mdss_dsi_active &mdss_te_active>;
+ pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>;
+ oledb-supply = <&pm660a_oledb>;
+ lab-supply = <&lab_regulator>;
+ ibb-supply = <&ibb_regulator>;
+ qcom,platform-reset-gpio = <&tlmm 53 0>;
+ qcom,platform-te-gpio = <&tlmm 59 0>;
+};
+
+&dsi_rm67195_amoled_fhd_cmd {
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_dcs";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <255>;
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply_labibb_amoled>;
+};
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 9d235b7abc58..dbbd5514cdcc 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -418,6 +418,7 @@ struct diag_md_session_t {
struct diag_mask_info *msg_mask;
struct diag_mask_info *log_mask;
struct diag_mask_info *event_mask;
+ struct thread_info *md_client_thread_info;
struct task_struct *task;
};
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 335064352789..009a2a4f90a2 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -1237,11 +1237,10 @@ int diag_md_session_create(int mode, int peripheral_mask, int proc)
mutex_unlock(&driver->md_session_lock);
return -ENOMEM;
}
-
new_session->peripheral_mask = 0;
new_session->pid = current->tgid;
new_session->task = current;
-
+ new_session->md_client_thread_info = current_thread_info();
new_session->log_mask = kzalloc(sizeof(struct diag_mask_info),
GFP_KERNEL);
if (!new_session->log_mask) {
@@ -1359,7 +1358,6 @@ static void diag_md_session_close(struct diag_md_session_t *session_info)
struct diag_md_session_t *diag_md_session_get_pid(int pid)
{
int i;
-
for (i = 0; i < NUM_MD_SESSIONS; i++) {
if (driver->md_session_map[i] &&
driver->md_session_map[i]->pid == pid)
@@ -1475,7 +1473,10 @@ static int diag_md_session_check(int curr_mode, int req_mode,
* If this session owns all the requested peripherals, then
* call function to switch the modes/masks for the md_session
*/
+ mutex_lock(&driver->md_session_lock);
session_info = diag_md_session_get_pid(current->tgid);
+ mutex_unlock(&driver->md_session_lock);
+
if (!session_info) {
*change_mode = 1;
return 0;
@@ -1504,7 +1505,9 @@ static int diag_md_session_check(int curr_mode, int req_mode,
* owned by this md session
*/
change_mask = driver->md_session_mask & param->peripheral_mask;
+ mutex_lock(&driver->md_session_lock);
session_info = diag_md_session_get_pid(current->tgid);
+ mutex_unlock(&driver->md_session_lock);
if (session_info) {
if ((session_info->peripheral_mask & change_mask)
@@ -1892,8 +1895,9 @@ static int diag_ioctl_hdlc_toggle(unsigned long ioarg)
{
uint8_t hdlc_support;
struct diag_md_session_t *session_info = NULL;
-
+ mutex_lock(&driver->md_session_lock);
session_info = diag_md_session_get_pid(current->tgid);
+ mutex_unlock(&driver->md_session_lock);
if (copy_from_user(&hdlc_support, (void __user *)ioarg,
sizeof(uint8_t)))
return -EFAULT;
@@ -2603,7 +2607,9 @@ static int diag_user_process_raw_data(const char __user *buf, int len)
} else {
wait_event_interruptible(driver->wait_q,
(driver->in_busy_pktdata == 0));
+ mutex_lock(&driver->md_session_lock);
info = diag_md_session_get_pid(current->tgid);
+ mutex_unlock(&driver->md_session_lock);
ret = diag_process_apps_pkt(user_space_data, len, info);
if (ret == 1)
diag_send_error_rsp((void *)(user_space_data), len,
@@ -2671,7 +2677,9 @@ static int diag_user_process_userspace_data(const char __user *buf, int len)
/* send masks to local processor now */
if (!remote_proc) {
+ mutex_lock(&driver->md_session_lock);
session_info = diag_md_session_get_pid(current->tgid);
+ mutex_unlock(&driver->md_session_lock);
if (!session_info) {
pr_err("diag:In %s request came from invalid md session pid:%d",
__func__, current->tgid);
@@ -2832,7 +2840,9 @@ static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count,
COPY_USER_SPACE_OR_EXIT(buf, data_type, sizeof(int));
/* place holder for number of data field */
ret += sizeof(int);
+ mutex_lock(&driver->md_session_lock);
session_info = diag_md_session_get_pid(current->tgid);
+ mutex_unlock(&driver->md_session_lock);
exit_stat = diag_md_copy_to_user(buf, &ret, count,
session_info);
goto exit;
@@ -2846,7 +2856,9 @@ static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count,
data_type = driver->data_ready[index] & HDLC_SUPPORT_TYPE;
driver->data_ready[index] ^= HDLC_SUPPORT_TYPE;
COPY_USER_SPACE_OR_EXIT(buf, data_type, sizeof(int));
+ mutex_lock(&driver->md_session_lock);
session_info = diag_md_session_get_pid(current->tgid);
+ mutex_unlock(&driver->md_session_lock);
if (session_info)
COPY_USER_SPACE_OR_EXIT(buf+4,
session_info->hdlc_disabled,
diff --git a/drivers/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c
index 62c8d0028af9..96f4a15a5d67 100644
--- a/drivers/char/diag/diagfwd_cntl.c
+++ b/drivers/char/diag/diagfwd_cntl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2017, 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
@@ -124,7 +124,9 @@ void diag_notify_md_client(uint8_t peripheral, int data)
info.si_signo = SIGCONT;
if (driver->md_session_map[peripheral] &&
driver->md_session_map[peripheral]->task) {
- if (driver->md_session_map[peripheral]->pid ==
+ if (driver->md_session_map[peripheral]->
+ md_client_thread_info->task != NULL
+ && driver->md_session_map[peripheral]->pid ==
driver->md_session_map[peripheral]->task->tgid) {
DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
"md_session %d pid = %d, md_session %d task tgid = %d\n",
diff --git a/drivers/iio/adc/qcom-rradc.c b/drivers/iio/adc/qcom-rradc.c
index 202fee4711c1..537cca877f66 100644
--- a/drivers/iio/adc/qcom-rradc.c
+++ b/drivers/iio/adc/qcom-rradc.c
@@ -164,11 +164,6 @@
#define FG_ADC_RR_DIE_TEMP_SLOPE 2
#define FG_ADC_RR_DIE_TEMP_OFFSET_MILLI_DEGC 25000
-#define FAB_ID_GF 0x30
-#define FAB_ID_SMIC 0x11
-#define FAB_ID_660_GF 0x0
-#define FAB_ID_660_TSMC 0x2
-#define FAB_ID_660_MX 0x3
#define FG_ADC_RR_CHG_TEMP_GF_OFFSET_UV 1303168
#define FG_ADC_RR_CHG_TEMP_GF_SLOPE_UV_PER_C 3784
#define FG_ADC_RR_CHG_TEMP_SMIC_OFFSET_UV 1338433
@@ -402,11 +397,11 @@ static int rradc_get_660_fab_coeff(struct rradc_chip *chip,
int64_t *offset, int64_t *slope)
{
switch (chip->pmic_fab_id->fab_id) {
- case FAB_ID_660_GF:
+ case PM660_FAB_ID_GF:
*offset = FG_ADC_RR_CHG_TEMP_660_GF_OFFSET_UV;
*slope = FG_RR_CHG_TEMP_660_GF_SLOPE_UV_PER_C;
break;
- case FAB_ID_660_TSMC:
+ case PM660_FAB_ID_TSMC:
*offset = FG_ADC_RR_CHG_TEMP_660_SMIC_OFFSET_UV;
*slope = FG_RR_CHG_TEMP_660_SMIC_SLOPE_UV_PER_C;
break;
@@ -422,11 +417,11 @@ static int rradc_get_8998_fab_coeff(struct rradc_chip *chip,
int64_t *offset, int64_t *slope)
{
switch (chip->pmic_fab_id->fab_id) {
- case FAB_ID_GF:
+ case PMI8998_FAB_ID_GF:
*offset = FG_ADC_RR_CHG_TEMP_GF_OFFSET_UV;
*slope = FG_ADC_RR_CHG_TEMP_GF_SLOPE_UV_PER_C;
break;
- case FAB_ID_SMIC:
+ case PMI8998_FAB_ID_SMIC:
*offset = FG_ADC_RR_CHG_TEMP_SMIC_OFFSET_UV;
*slope = FG_ADC_RR_CHG_TEMP_SMIC_SLOPE_UV_PER_C;
break;
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 075c18e0e4ae..1d4e8a4ce206 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -1128,6 +1128,16 @@ config TOUCHSCREEN_FT5X06_GESTURE
If unsure, say N.
+config TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
+ bool "Synaptics DSX firmware update extra sysfs attributes"
+ depends on TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE
+ help
+ Say Y here to enable support for extra sysfs attributes
+ supporting firmware update in a development environment.
+ This does not affect the core or other subsystem attributes.
+
+ If unsure, say N.
+
config TOUCHSCREEN_ROHM_BU21023
tristate "ROHM BU21023/24 Dual touch support resistive touchscreens"
depends on I2C
diff --git a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c
index 0ec16e606545..4787f2bcd768 100644
--- a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c
+++ b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c
@@ -102,6 +102,7 @@
(fwu->config_data[2] == config_id[2]) && \
(fwu->config_data[3] == config_id[3]))
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
static ssize_t fwu_sysfs_show_image(struct file *data_file,
struct kobject *kobj, struct bin_attribute *attributes,
char *buf, loff_t pos, size_t count);
@@ -157,6 +158,7 @@ static ssize_t fwu_sysfs_config_id_show(struct device *dev,
static ssize_t fwu_sysfs_package_id_show(struct device *dev,
struct device_attribute *attr, char *buf);
+#endif
enum bl_version {
V5 = 5,
@@ -296,6 +298,7 @@ struct synaptics_rmi4_fwu_handle {
struct synaptics_rmi4_data *rmi4_data;
};
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
static struct bin_attribute dev_attr_data = {
.attr = {
.name = "data",
@@ -305,9 +308,11 @@ static struct bin_attribute dev_attr_data = {
.read = fwu_sysfs_show_image,
.write = fwu_sysfs_store_image,
};
+#endif
static struct device_attribute attrs[] = {
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
__ATTR(force_update_fw, S_IWUSR | S_IWGRP,
NULL,
fwu_sysfs_force_reflash_store),
@@ -353,6 +358,7 @@ static struct device_attribute attrs[] = {
__ATTR(package_id, S_IRUGO,
fwu_sysfs_package_id_show,
synaptics_rmi4_store_error),
+#endif
};
static struct synaptics_rmi4_fwu_handle *fwu;
@@ -1220,6 +1226,7 @@ write_config:
return retval;
}
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
static int fwu_start_write_config(void)
{
int retval;
@@ -1395,6 +1402,7 @@ exit:
return retval;
}
+#endif
static int fwu_do_lockdown(void)
{
@@ -1585,6 +1593,7 @@ int synaptics_dsx_fw_updater(unsigned char *fw_data)
}
EXPORT_SYMBOL(synaptics_dsx_fw_updater);
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
static ssize_t fwu_sysfs_show_image(struct file *data_file,
struct kobject *kobj, struct bin_attribute *attributes,
char *buf, loff_t pos, size_t count)
@@ -1972,6 +1981,7 @@ static ssize_t fwu_sysfs_package_id_show(struct device *dev,
(package_id[1] << 8) | package_id[0],
(package_id[3] << 8) | package_id[2]);
}
+#endif
static void synaptics_rmi4_fwu_attn(struct synaptics_rmi4_data *rmi4_data,
unsigned char intr_mask)
@@ -2045,6 +2055,7 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data)
fwu->do_lockdown = DO_LOCKDOWN;
fwu->initialized = true;
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
retval = sysfs_create_bin_file(&rmi4_data->input_dev->dev.kobj,
&dev_attr_data);
if (retval < 0) {
@@ -2053,6 +2064,7 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data)
__func__);
goto exit_free_fwu;
}
+#endif
for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
retval = sysfs_create_file(&rmi4_data->input_dev->dev.kobj,
@@ -2074,7 +2086,9 @@ exit_remove_attrs:
&attrs[attr_count].attr);
}
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data);
+#endif
exit_free_fwu:
kfree(fwu);
@@ -2096,7 +2110,9 @@ static void synaptics_rmi4_fwu_remove(struct synaptics_rmi4_data *rmi4_data)
&attrs[attr_count].attr);
}
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data);
+#endif
kfree(fwu->read_config_buf);
kfree(fwu);
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
index 54b237a9fc05..b44b7573e0e6 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
@@ -2441,7 +2441,7 @@ int msm_isp_ab_ib_update_lpm_mode(struct vfe_device *vfe_dev, void *arg)
total_bandwidth +=
stream_info->bandwidth[
vfe_idx];
- stream_info->state = PAUSING;
+ stream_info->state = PAUSED;
}
spin_unlock_irqrestore(&stream_info->lock, flags);
}
@@ -2455,7 +2455,7 @@ int msm_isp_ab_ib_update_lpm_mode(struct vfe_device *vfe_dev, void *arg)
msm_isp_get_stream_common_data(vfe_dev,
ab_ib_vote->stream_src[i]);
spin_lock_irqsave(&stream_info->lock, flags);
- if (stream_info->state == PAUSING) {
+ if (stream_info->state == PAUSED) {
vfe_idx =
msm_isp_get_vfe_idx_for_stream(vfe_dev,
stream_info);
@@ -2813,6 +2813,7 @@ static int __msm_isp_check_stream_state(struct msm_vfe_axi_stream *stream_info,
case RESUMING:
case RESUME_PENDING:
case ACTIVE:
+ case PAUSED:
if (cmd != 0)
return -EALREADY;
break;
@@ -2879,9 +2880,11 @@ static void __msm_isp_stop_axi_streams(struct vfe_device *vfe_dev,
* those state transitions instead of directly forcing stream to
* be INACTIVE
*/
- while (stream_info->state != ACTIVE)
- __msm_isp_axi_stream_update(stream_info,
+ if (stream_info->state != PAUSED) {
+ while (stream_info->state != ACTIVE)
+ __msm_isp_axi_stream_update(stream_info,
&timestamp);
+ }
msm_isp_cfg_stream_scratch(stream_info, VFE_PING_FLAG);
msm_isp_cfg_stream_scratch(stream_info, VFE_PONG_FLAG);
stream_info->undelivered_request_cnt = 0;
@@ -2894,8 +2897,15 @@ static void __msm_isp_stop_axi_streams(struct vfe_device *vfe_dev,
vfe_dev->hw_info->vfe_ops.axi_ops.
clear_wm_irq_mask(vfe_dev, stream_info);
}
- init_completion(&stream_info->inactive_comp);
- stream_info->state = STOP_PENDING;
+ if (stream_info->state == ACTIVE) {
+ init_completion(&stream_info->inactive_comp);
+ stream_info->state = STOP_PENDING;
+ } else if (stream_info->state == PAUSED) {
+ /* don't wait for reg update */
+ stream_info->state = STOP_PENDING;
+ msm_isp_axi_stream_enable_cfg(stream_info);
+ stream_info->state = INACTIVE;
+ }
spin_unlock_irqrestore(&stream_info->lock, flags);
}
diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
index 9d52107c9993..41d8ef577a27 100644
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
@@ -73,7 +73,7 @@ static void msm_ispif_io_dump_reg(struct ispif_device *ispif)
static inline int msm_ispif_is_intf_valid(uint32_t csid_version,
- uint8_t intf_type)
+ enum msm_ispif_vfe_intf intf_type)
{
return ((csid_version <= CSID_VERSION_V22 && intf_type != VFE0) ||
(intf_type >= VFE_MAX)) ? false : true;
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 16d1341e7cd0..2eaac11ec8ba 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -3914,8 +3914,8 @@ void sdhci_msm_pm_qos_cpu_init(struct sdhci_host *host,
group->req.type = PM_QOS_REQ_AFFINE_CORES;
cpumask_copy(&group->req.cpus_affine,
&msm_host->pdata->pm_qos_data.cpu_group_map.mask[i]);
- /* For initialization phase, set the performance mode latency */
- group->latency = latency[i].latency[SDHCI_PERFORMANCE_MODE];
+ /* We set default latency here for all pm_qos cpu groups. */
+ group->latency = PM_QOS_DEFAULT_VALUE;
pm_qos_add_request(&group->req, PM_QOS_CPU_DMA_LATENCY,
group->latency);
pr_info("%s (): voted for group #%d (mask=0x%lx) latency=%d (0x%p)\n",
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c
index 958c96b75fbb..01a27335ec34 100644
--- a/drivers/net/wireless/ath/wil6210/main.c
+++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -130,9 +130,15 @@ void wil_memcpy_fromio_32(void *dst, const volatile void __iomem *src,
u32 *d = dst;
const volatile u32 __iomem *s = src;
- /* size_t is unsigned, if (count%4 != 0) it will wrap */
- for (count += 4; count > 4; count -= 4)
+ for (; count >= 4; count -= 4)
*d++ = __raw_readl(s++);
+
+ if (unlikely(count)) {
+ /* count can be 1..3 */
+ u32 tmp = __raw_readl(s);
+
+ memcpy(d, &tmp, count);
+ }
}
void wil_memcpy_fromio_halp_vote(struct wil6210_priv *wil, void *dst,
@@ -149,8 +155,16 @@ void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src,
volatile u32 __iomem *d = dst;
const u32 *s = src;
- for (count += 4; count > 4; count -= 4)
+ for (; count >= 4; count -= 4)
__raw_writel(*s++, d++);
+
+ if (unlikely(count)) {
+ /* count can be 1..3 */
+ u32 tmp = 0;
+
+ memcpy(&tmp, s, count);
+ __raw_writel(tmp, d);
+ }
}
void wil_memcpy_toio_halp_vote(struct wil6210_priv *wil,
diff --git a/drivers/pci/host/pci-msm.c b/drivers/pci/host/pci-msm.c
index 584ad96c703f..6e9a8649ee2f 100644
--- a/drivers/pci/host/pci-msm.c
+++ b/drivers/pci/host/pci-msm.c
@@ -2511,6 +2511,48 @@ int msm_pcie_debug_info(struct pci_dev *dev, u32 option, u32 base,
}
EXPORT_SYMBOL(msm_pcie_debug_info);
+#ifdef CONFIG_SYSFS
+static ssize_t msm_pcie_enumerate_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct msm_pcie_dev_t *pcie_dev = (struct msm_pcie_dev_t *)
+ dev_get_drvdata(dev);
+
+ if (pcie_dev)
+ msm_pcie_enumerate(pcie_dev->rc_idx);
+
+ return count;
+}
+
+static DEVICE_ATTR(enumerate, S_IWUSR, NULL, msm_pcie_enumerate_store);
+
+static void msm_pcie_sysfs_init(struct msm_pcie_dev_t *dev)
+{
+ int ret;
+
+ ret = device_create_file(&dev->pdev->dev, &dev_attr_enumerate);
+ if (ret)
+ PCIE_DBG_FS(dev,
+ "RC%d: failed to create sysfs enumerate node\n",
+ dev->rc_idx);
+}
+
+static void msm_pcie_sysfs_exit(struct msm_pcie_dev_t *dev)
+{
+ if (dev->pdev)
+ device_remove_file(&dev->pdev->dev, &dev_attr_enumerate);
+}
+#else
+static void msm_pcie_sysfs_init(struct msm_pcie_dev_t *dev)
+{
+}
+
+static void msm_pcie_sysfs_exit(struct msm_pcie_dev_t *dev)
+{
+}
+#endif
+
#ifdef CONFIG_DEBUG_FS
static struct dentry *dent_msm_pcie;
static struct dentry *dfile_rc_sel;
@@ -6277,6 +6319,9 @@ static int msm_pcie_probe(struct platform_device *pdev)
msm_pcie_dev[rc_idx].pcidev_table[i].registered = true;
}
+ dev_set_drvdata(&msm_pcie_dev[rc_idx].pdev->dev, &msm_pcie_dev[rc_idx]);
+ msm_pcie_sysfs_init(&msm_pcie_dev[rc_idx]);
+
ret = msm_pcie_get_resources(&msm_pcie_dev[rc_idx],
msm_pcie_dev[rc_idx].pdev);
@@ -6490,11 +6535,16 @@ int __init pcie_init(void)
static void __exit pcie_exit(void)
{
+ int i;
+
PCIE_GEN_DBG("pcie:%s.\n", __func__);
platform_driver_unregister(&msm_pcie_driver);
msm_pcie_debugfs_exit();
+
+ for (i = 0; i < MAX_RC_NUM; i++)
+ msm_pcie_sysfs_exit(&msm_pcie_dev[i]);
}
subsys_initcall_sync(pcie_init);
diff --git a/drivers/power/supply/qcom/fg-core.h b/drivers/power/supply/qcom/fg-core.h
index 1c0eecdf162c..f2047592a94b 100644
--- a/drivers/power/supply/qcom/fg-core.h
+++ b/drivers/power/supply/qcom/fg-core.h
@@ -46,10 +46,13 @@
&& (value) <= (right)))
/* Awake votable reasons */
-#define SRAM_READ "fg_sram_read"
-#define SRAM_WRITE "fg_sram_write"
-#define PROFILE_LOAD "fg_profile_load"
-#define DELTA_SOC "fg_delta_soc"
+#define SRAM_READ "fg_sram_read"
+#define SRAM_WRITE "fg_sram_write"
+#define PROFILE_LOAD "fg_profile_load"
+#define DELTA_SOC "fg_delta_soc"
+
+/* Delta BSOC votable reasons */
+#define DELTA_BSOC_IRQ_VOTER "fg_delta_bsoc_irq"
#define DEBUG_PRINT_BUFFER_SIZE 64
/* 3 byte address + 1 space character */
@@ -330,6 +333,7 @@ struct fg_chip {
struct fg_memif *sram;
struct fg_irq_info *irqs;
struct votable *awake_votable;
+ struct votable *delta_bsoc_irq_en_votable;
struct fg_sram_param *sp;
struct fg_alg_flag *alg_flags;
int *debug_mask;
@@ -370,8 +374,8 @@ struct fg_chip {
bool esr_fcc_ctrl_en;
bool soc_reporting_ready;
bool esr_flt_cold_temp_en;
- bool bsoc_delta_irq_en;
bool slope_limit_en;
+ bool use_ima_single_mode;
struct completion soc_update;
struct completion soc_ready;
struct delayed_work profile_load_work;
diff --git a/drivers/power/supply/qcom/fg-memif.c b/drivers/power/supply/qcom/fg-memif.c
index c00c72c5884c..8a949bfe61d0 100644
--- a/drivers/power/supply/qcom/fg-memif.c
+++ b/drivers/power/supply/qcom/fg-memif.c
@@ -48,6 +48,10 @@ static int fg_config_access_mode(struct fg_chip *chip, bool access, bool burst)
int rc;
u8 intf_ctl = 0;
+ fg_dbg(chip, FG_SRAM_READ | FG_SRAM_WRITE, "access: %d burst: %d\n",
+ access, burst);
+
+ WARN_ON(burst && chip->use_ima_single_mode);
intf_ctl = ((access == FG_WRITE) ? IMA_WR_EN_BIT : 0) |
(burst ? MEM_ACS_BURST_BIT : 0);
@@ -293,7 +297,9 @@ static int fg_check_iacs_ready(struct fg_chip *chip)
/* check for error condition */
rc = fg_clear_ima_errors_if_any(chip, false);
if (rc < 0) {
- pr_err("Failed to check for ima errors rc=%d\n", rc);
+ if (rc != -EAGAIN)
+ pr_err("Failed to check for ima errors rc=%d\n",
+ rc);
return rc;
}
@@ -357,7 +363,12 @@ static int __fg_interleaved_mem_write(struct fg_chip *chip, u16 address,
/* check for error condition */
rc = fg_clear_ima_errors_if_any(chip, false);
if (rc < 0) {
- pr_err("Failed to check for ima errors rc=%d\n", rc);
+ if (rc == -EAGAIN)
+ pr_err("IMA error cleared, address [%d %d] len %d\n",
+ address, offset, len);
+ else
+ pr_err("Failed to check for ima errors rc=%d\n",
+ rc);
return rc;
}
@@ -365,6 +376,15 @@ static int __fg_interleaved_mem_write(struct fg_chip *chip, u16 address,
len -= num_bytes;
offset = byte_enable = 0;
+ if (chip->use_ima_single_mode && len) {
+ address++;
+ rc = fg_set_address(chip, address);
+ if (rc < 0) {
+ pr_err("failed to set address rc = %d\n", rc);
+ return rc;
+ }
+ }
+
rc = fg_check_iacs_ready(chip);
if (rc < 0) {
pr_debug("IACS_RDY failed rc=%d\n", rc);
@@ -403,22 +423,40 @@ static int __fg_interleaved_mem_read(struct fg_chip *chip, u16 address,
/* check for error condition */
rc = fg_clear_ima_errors_if_any(chip, false);
if (rc < 0) {
- pr_err("Failed to check for ima errors rc=%d\n", rc);
+ if (rc == -EAGAIN)
+ pr_err("IMA error cleared, address [%d %d] len %d\n",
+ address, offset, len);
+ else
+ pr_err("Failed to check for ima errors rc=%d\n",
+ rc);
return rc;
}
- if (len && len < BYTES_PER_SRAM_WORD) {
- /*
- * Move to single mode. Changing address is not
- * required here as it must be in burst mode. Address
- * will get incremented internally by FG HW once the MSB
- * of RD_DATA is read.
- */
- rc = fg_config_access_mode(chip, FG_READ, 0);
- if (rc < 0) {
- pr_err("failed to move to single mode rc=%d\n",
- rc);
- return -EIO;
+ if (chip->use_ima_single_mode) {
+ if (len) {
+ address++;
+ rc = fg_set_address(chip, address);
+ if (rc < 0) {
+ pr_err("failed to set address rc = %d\n",
+ rc);
+ return rc;
+ }
+ }
+ } else {
+ if (len && len < BYTES_PER_SRAM_WORD) {
+ /*
+ * Move to single mode. Changing address is not
+ * required here as it must be in burst mode.
+ * Address will get incremented internally by FG
+ * HW once the MSB of RD_DATA is read.
+ */
+ rc = fg_config_access_mode(chip, FG_READ,
+ false);
+ if (rc < 0) {
+ pr_err("failed to move to single mode rc=%d\n",
+ rc);
+ return -EIO;
+ }
}
}
@@ -489,6 +527,7 @@ static int fg_interleaved_mem_config(struct fg_chip *chip, u8 *val,
u16 address, int offset, int len, bool access)
{
int rc = 0;
+ bool burst_mode = false;
if (!is_mem_access_available(chip, access))
return -EBUSY;
@@ -503,7 +542,8 @@ static int fg_interleaved_mem_config(struct fg_chip *chip, u8 *val,
}
/* configure for the read/write, single/burst mode */
- rc = fg_config_access_mode(chip, access, (offset + len) > 4);
+ burst_mode = chip->use_ima_single_mode ? false : ((offset + len) > 4);
+ rc = fg_config_access_mode(chip, access, burst_mode);
if (rc < 0) {
pr_err("failed to set memory access rc = %d\n", rc);
return rc;
@@ -583,7 +623,7 @@ retry:
if (rc < 0) {
count++;
if (rc == -EAGAIN) {
- pr_err("IMA access failed retry_count = %d\n", count);
+ pr_err("IMA read failed retry_count = %d\n", count);
goto retry;
}
pr_err("failed to read SRAM address rc = %d\n", rc);
@@ -667,8 +707,8 @@ retry:
rc = __fg_interleaved_mem_write(chip, address, offset, val, len);
if (rc < 0) {
count++;
- if ((rc == -EAGAIN) && (count < RETRY_COUNT)) {
- pr_err("IMA access failed retry_count = %d\n", count);
+ if (rc == -EAGAIN) {
+ pr_err("IMA write failed retry_count = %d\n", count);
goto retry;
}
pr_err("failed to write SRAM address rc = %d\n", rc);
diff --git a/drivers/power/supply/qcom/qpnp-fg-gen3.c b/drivers/power/supply/qcom/qpnp-fg-gen3.c
index 5ce74dab9aab..59216a567662 100644
--- a/drivers/power/supply/qcom/qpnp-fg-gen3.c
+++ b/drivers/power/supply/qcom/qpnp-fg-gen3.c
@@ -1054,6 +1054,25 @@ static void fg_notify_charger(struct fg_chip *chip)
fg_dbg(chip, FG_STATUS, "Notified charger on float voltage and FCC\n");
}
+static int fg_delta_bsoc_irq_en_cb(struct votable *votable, void *data,
+ int enable, const char *client)
+{
+ struct fg_chip *chip = data;
+
+ if (!chip->irqs[BSOC_DELTA_IRQ].irq)
+ return 0;
+
+ if (enable) {
+ enable_irq(chip->irqs[BSOC_DELTA_IRQ].irq);
+ enable_irq_wake(chip->irqs[BSOC_DELTA_IRQ].irq);
+ } else {
+ disable_irq_wake(chip->irqs[BSOC_DELTA_IRQ].irq);
+ disable_irq(chip->irqs[BSOC_DELTA_IRQ].irq);
+ }
+
+ return 0;
+}
+
static int fg_awake_cb(struct votable *votable, void *data, int awake,
const char *client)
{
@@ -1477,16 +1496,8 @@ static int fg_charge_full_update(struct fg_chip *chip)
return 0;
mutex_lock(&chip->charge_full_lock);
- if (!chip->charge_done && chip->bsoc_delta_irq_en) {
- disable_irq_wake(fg_irqs[BSOC_DELTA_IRQ].irq);
- disable_irq_nosync(fg_irqs[BSOC_DELTA_IRQ].irq);
- chip->bsoc_delta_irq_en = false;
- } else if (chip->charge_done && !chip->bsoc_delta_irq_en) {
- enable_irq(fg_irqs[BSOC_DELTA_IRQ].irq);
- enable_irq_wake(fg_irqs[BSOC_DELTA_IRQ].irq);
- chip->bsoc_delta_irq_en = true;
- }
-
+ vote(chip->delta_bsoc_irq_en_votable, DELTA_BSOC_IRQ_VOTER,
+ chip->charge_done, 0);
rc = power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_HEALTH,
&prop);
if (rc < 0) {
@@ -2198,6 +2209,17 @@ static bool is_profile_load_required(struct fg_chip *chip)
/* Check if integrity bit is set */
if (val & PROFILE_LOAD_BIT) {
fg_dbg(chip, FG_STATUS, "Battery profile integrity bit is set\n");
+
+ /* Whitelist the values */
+ val &= ~PROFILE_LOAD_BIT;
+ if (val != HLOS_RESTART_BIT && val != BOOTLOADER_LOAD_BIT &&
+ val != (BOOTLOADER_LOAD_BIT | BOOTLOADER_RESTART_BIT)) {
+ val |= PROFILE_LOAD_BIT;
+ pr_warn("Garbage value in profile integrity word: 0x%x\n",
+ val);
+ return true;
+ }
+
rc = fg_sram_read(chip, PROFILE_LOAD_WORD, PROFILE_LOAD_OFFSET,
buf, PROFILE_COMP_LEN, FG_IMA_DEFAULT);
if (rc < 0) {
@@ -3744,6 +3766,7 @@ static int fg_parse_dt(struct fg_chip *chip)
case PM660_SUBTYPE:
chip->sp = pmi8998_v2_sram_params;
chip->alg_flags = pmi8998_v2_alg_flags;
+ chip->use_ima_single_mode = true;
break;
default:
return -EINVAL;
@@ -4022,6 +4045,9 @@ static void fg_cleanup(struct fg_chip *chip)
if (chip->awake_votable)
destroy_votable(chip->awake_votable);
+ if (chip->delta_bsoc_irq_en_votable)
+ destroy_votable(chip->delta_bsoc_irq_en_votable);
+
if (chip->batt_id_chan)
iio_channel_release(chip->batt_id_chan);
@@ -4063,7 +4089,15 @@ static int fg_gen3_probe(struct platform_device *pdev)
chip);
if (IS_ERR(chip->awake_votable)) {
rc = PTR_ERR(chip->awake_votable);
- return rc;
+ goto exit;
+ }
+
+ chip->delta_bsoc_irq_en_votable = create_votable("FG_DELTA_BSOC_IRQ",
+ VOTE_SET_ANY,
+ fg_delta_bsoc_irq_en_cb, chip);
+ if (IS_ERR(chip->delta_bsoc_irq_en_votable)) {
+ rc = PTR_ERR(chip->delta_bsoc_irq_en_votable);
+ goto exit;
}
rc = fg_parse_dt(chip);
@@ -4090,7 +4124,7 @@ static int fg_gen3_probe(struct platform_device *pdev)
rc = fg_get_batt_id(chip);
if (rc < 0) {
pr_err("Error in getting battery id, rc:%d\n", rc);
- return rc;
+ goto exit;
}
rc = fg_get_batt_profile(chip);
@@ -4148,11 +4182,7 @@ static int fg_gen3_probe(struct platform_device *pdev)
disable_irq_nosync(fg_irqs[SOC_UPDATE_IRQ].irq);
/* Keep BSOC_DELTA_IRQ irq disabled until we require it */
- if (fg_irqs[BSOC_DELTA_IRQ].irq) {
- disable_irq_wake(fg_irqs[BSOC_DELTA_IRQ].irq);
- disable_irq_nosync(fg_irqs[BSOC_DELTA_IRQ].irq);
- chip->bsoc_delta_irq_en = false;
- }
+ rerun_election(chip->delta_bsoc_irq_en_votable);
rc = fg_debugfs_create(chip);
if (rc < 0) {
diff --git a/drivers/power/supply/qcom/qpnp-qnovo.c b/drivers/power/supply/qcom/qpnp-qnovo.c
index ada231905df9..8f9514a25f63 100644
--- a/drivers/power/supply/qcom/qpnp-qnovo.c
+++ b/drivers/power/supply/qcom/qpnp-qnovo.c
@@ -29,6 +29,7 @@
#define QNOVO_PTRAIN_STS 0x08
#define QNOVO_ERROR_STS 0x09
#define QNOVO_ERROR_BIT BIT(0)
+#define QNOVO_ERROR_STS2 0x0A
#define QNOVO_INT_RT_STS 0x10
#define QNOVO_INT_SET_TYPE 0x11
#define QNOVO_INT_POLARITY_HIGH 0x12
@@ -272,28 +273,22 @@ static int qnovo_disable_cb(struct votable *votable, void *data, int disable,
const char *client)
{
struct qnovo *chip = data;
- int rc = 0;
+ union power_supply_propval pval = {0};
+ int rc;
- if (disable) {
- rc = qnovo_batt_psy_update(chip, true);
- if (rc < 0)
- return rc;
- }
+ if (!is_batt_available(chip))
+ return -EINVAL;
- rc = qnovo_masked_write(chip, QNOVO_PTRAIN_EN, QNOVO_PTRAIN_EN_BIT,
- disable ? 0 : QNOVO_PTRAIN_EN_BIT);
+ pval.intval = !disable;
+ rc = power_supply_set_property(chip->batt_psy,
+ POWER_SUPPLY_PROP_CHARGE_QNOVO_ENABLE,
+ &pval);
if (rc < 0) {
- dev_err(chip->dev, "Couldn't %s pulse train rc=%d\n",
- disable ? "disable" : "enable", rc);
- return rc;
- }
-
- if (!disable) {
- rc = qnovo_batt_psy_update(chip, false);
- if (rc < 0)
- return rc;
+ pr_err("Couldn't set prop qnovo_enable rc = %d\n", rc);
+ return -EINVAL;
}
+ rc = qnovo_batt_psy_update(chip, disable);
return rc;
}
@@ -348,13 +343,15 @@ static int qnovo_check_chg_version(struct qnovo *chip)
enum {
VER = 0,
OK_TO_QNOVO,
- ENABLE,
+ QNOVO_ENABLE,
+ PT_ENABLE,
FV_REQUEST,
FCC_REQUEST,
PE_CTRL_REG,
PE_CTRL2_REG,
PTRAIN_STS_REG,
INT_RT_STS_REG,
+ ERR_STS2_REG,
PREST1,
PPULS1,
NREST1,
@@ -394,6 +391,12 @@ struct param_info {
};
static struct param_info params[] = {
+ [PT_ENABLE] = {
+ .name = "PT_ENABLE",
+ .start_addr = QNOVO_PTRAIN_EN,
+ .num_regs = 1,
+ .units_str = "",
+ },
[FV_REQUEST] = {
.units_str = "uV",
},
@@ -424,6 +427,12 @@ static struct param_info params[] = {
.num_regs = 1,
.units_str = "",
},
+ [ERR_STS2_REG] = {
+ .name = "RAW_CHGR_ERR",
+ .start_addr = QNOVO_ERROR_STS2,
+ .num_regs = 1,
+ .units_str = "",
+ },
[PREST1] = {
.name = "PREST1",
.start_addr = QNOVO_PREST1_CTRL,
@@ -648,30 +657,70 @@ static ssize_t ok_to_qnovo_show(struct class *c, struct class_attribute *attr,
return snprintf(buf, PAGE_SIZE, "%d\n", chip->cs.ok_to_qnovo);
}
-static ssize_t enable_show(struct class *c, struct class_attribute *attr,
+static ssize_t qnovo_enable_show(struct class *c, struct class_attribute *attr,
char *ubuf)
{
struct qnovo *chip = container_of(c, struct qnovo, qnovo_class);
- int val;
+ int val = get_effective_result(chip->disable_votable);
- val = get_client_vote(chip->disable_votable, USER_VOTER);
- val = !val;
- return snprintf(ubuf, PAGE_SIZE, "%d\n", val);
+ return snprintf(ubuf, PAGE_SIZE, "%d\n", !val);
+}
+
+static ssize_t qnovo_enable_store(struct class *c, struct class_attribute *attr,
+ const char *ubuf, size_t count)
+{
+ struct qnovo *chip = container_of(c, struct qnovo, qnovo_class);
+ unsigned long val;
+
+ if (kstrtoul(ubuf, 0, &val))
+ return -EINVAL;
+
+ vote(chip->disable_votable, USER_VOTER, !val, 0);
+
+ return count;
}
-static ssize_t enable_store(struct class *c, struct class_attribute *attr,
+static ssize_t pt_enable_show(struct class *c, struct class_attribute *attr,
+ char *ubuf)
+{
+ int i = attr - qnovo_attributes;
+ struct qnovo *chip = container_of(c, struct qnovo, qnovo_class);
+ u8 buf[2] = {0, 0};
+ u16 regval;
+ int rc;
+
+ rc = qnovo_read(chip, params[i].start_addr, buf, params[i].num_regs);
+ if (rc < 0) {
+ pr_err("Couldn't read %s rc = %d\n", params[i].name, rc);
+ return -EINVAL;
+ }
+ regval = buf[1] << 8 | buf[0];
+
+ return snprintf(ubuf, PAGE_SIZE, "%d\n",
+ (int)(regval & QNOVO_PTRAIN_EN_BIT));
+}
+
+static ssize_t pt_enable_store(struct class *c, struct class_attribute *attr,
const char *ubuf, size_t count)
{
struct qnovo *chip = container_of(c, struct qnovo, qnovo_class);
unsigned long val;
- bool disable;
+ int rc = 0;
+
+ if (get_effective_result(chip->disable_votable))
+ return -EINVAL;
if (kstrtoul(ubuf, 0, &val))
return -EINVAL;
- disable = !val;
+ rc = qnovo_masked_write(chip, QNOVO_PTRAIN_EN, QNOVO_PTRAIN_EN_BIT,
+ (bool)val ? QNOVO_PTRAIN_EN_BIT : 0);
+ if (rc < 0) {
+ dev_err(chip->dev, "Couldn't %s pulse train rc=%d\n",
+ (bool)val ? "enable" : "disable", rc);
+ return rc;
+ }
- vote(chip->disable_votable, USER_VOTER, disable, 0);
return count;
}
@@ -698,6 +747,9 @@ static ssize_t val_store(struct class *c, struct class_attribute *attr,
int i = attr - qnovo_attributes;
unsigned long val;
+ if (get_effective_result(chip->disable_votable))
+ return -EINVAL;
+
if (kstrtoul(ubuf, 0, &val))
return -EINVAL;
@@ -707,6 +759,8 @@ static ssize_t val_store(struct class *c, struct class_attribute *attr,
if (i == FCC_REQUEST)
chip->fcc_uA_request = val;
+ qnovo_batt_psy_update(chip, false);
+
return count;
}
@@ -1016,8 +1070,8 @@ static ssize_t batt_prop_show(struct class *c, struct class_attribute *attr,
static struct class_attribute qnovo_attributes[] = {
[VER] = __ATTR_RO(version),
[OK_TO_QNOVO] = __ATTR_RO(ok_to_qnovo),
- [ENABLE] = __ATTR(enable, 0644,
- enable_show, enable_store),
+ [QNOVO_ENABLE] = __ATTR_RW(qnovo_enable),
+ [PT_ENABLE] = __ATTR_RW(pt_enable),
[FV_REQUEST] = __ATTR(fv_uV_request, 0644,
val_show, val_store),
[FCC_REQUEST] = __ATTR(fcc_uA_request, 0644,
@@ -1030,6 +1084,8 @@ static struct class_attribute qnovo_attributes[] = {
reg_show, NULL),
[INT_RT_STS_REG] = __ATTR(INT_RT_STS_REG, 0444,
reg_show, NULL),
+ [ERR_STS2_REG] = __ATTR(ERR_STS2_REG, 0444,
+ reg_show, NULL),
[PREST1] = __ATTR(PREST1_mS, 0644,
time_show, time_store),
[PPULS1] = __ATTR(PPULS1_uC, 0644,
@@ -1050,7 +1106,7 @@ static struct class_attribute qnovo_attributes[] = {
time_show, NULL),
[PREST2] = __ATTR(PREST2_mS, 0644,
time_show, time_store),
- [PPULS2] = __ATTR(PPULS2_mS, 0644,
+ [PPULS2] = __ATTR(PPULS2_uC, 0644,
coulomb_show, coulomb_store),
[NREST2] = __ATTR(NREST2_mS, 0644,
time_show, time_store),
@@ -1135,8 +1191,7 @@ static void get_chg_status(struct qnovo *chip, const struct chg_props *cp,
{
cs->ok_to_qnovo = false;
- if (cp->charging &&
- (cp->usb_online || cp->dc_online))
+ if (cp->charging && (cp->usb_online || cp->dc_online))
cs->ok_to_qnovo = true;
}
@@ -1152,17 +1207,10 @@ static void status_change_work(struct work_struct *work)
get_chg_status(chip, &cp, &cs);
if (cs.ok_to_qnovo ^ chip->cs.ok_to_qnovo) {
- /*
- * when it is not okay to Qnovo charge, disable both voters,
- * so that when it becomes okay to Qnovo charge the user voter
- * has to specifically enable its vote to being Qnovo charging
- */
- if (!cs.ok_to_qnovo) {
- vote(chip->disable_votable, OK_TO_QNOVO_VOTER, 1, 0);
- vote(chip->disable_votable, USER_VOTER, 1, 0);
- } else {
- vote(chip->disable_votable, OK_TO_QNOVO_VOTER, 0, 0);
- }
+ vote(chip->disable_votable, OK_TO_QNOVO_VOTER,
+ !cs.ok_to_qnovo, 0);
+ if (!cs.ok_to_qnovo)
+ vote(chip->disable_votable, USER_VOTER, true, 0);
notify_uevent = true;
}
@@ -1192,8 +1240,6 @@ static irqreturn_t handle_ptrain_done(int irq, void *data)
{
struct qnovo *chip = data;
- /* disable user voter here */
- vote(chip->disable_votable, USER_VOTER, 0, 0);
kobject_uevent(&chip->dev->kobj, KOBJ_CHANGE);
return IRQ_HANDLED;
}
@@ -1206,7 +1252,7 @@ static int qnovo_hw_init(struct qnovo *chip)
u8 vadc_offset, vadc_gain;
u8 val;
- vote(chip->disable_votable, USER_VOTER, 1, 0);
+ vote(chip->disable_votable, USER_VOTER, true, 0);
val = 0;
rc = qnovo_write(chip, QNOVO_STRM_CTRL, &val, 1);
@@ -1318,6 +1364,9 @@ static int qnovo_request_interrupts(struct qnovo *chip)
irq_ptrain_done, rc);
return rc;
}
+
+ enable_irq_wake(irq_ptrain_done);
+
return rc;
}
@@ -1399,6 +1448,8 @@ static int qnovo_probe(struct platform_device *pdev)
goto unreg_notifier;
}
+ device_init_wakeup(chip->dev, true);
+
return rc;
unreg_notifier:
diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c
index ee4b78181ade..e8249163e948 100644
--- a/drivers/power/supply/qcom/qpnp-smb2.c
+++ b/drivers/power/supply/qcom/qpnp-smb2.c
@@ -999,6 +999,8 @@ static int smb2_batt_set_prop(struct power_supply *psy,
break;
case POWER_SUPPLY_PROP_CURRENT_QNOVO:
chg->qnovo_fcc_ua = val->intval;
+ vote(chg->pl_disable_votable, PL_QNOVO_VOTER,
+ val->intval != -EINVAL && val->intval < 2000000, 0);
rc = rerun_election(chg->fcc_votable);
break;
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h
index 0645b60310b3..32a1c29bb376 100644
--- a/drivers/power/supply/qcom/smb-lib.h
+++ b/drivers/power/supply/qcom/smb-lib.h
@@ -37,6 +37,7 @@ enum print_reason {
#define USB_PSY_VOTER "USB_PSY_VOTER"
#define PL_TAPER_WORK_RUNNING_VOTER "PL_TAPER_WORK_RUNNING_VOTER"
#define PL_INDIRECT_VOTER "PL_INDIRECT_VOTER"
+#define PL_QNOVO_VOTER "PL_QNOVO_VOTER"
#define USBIN_I_VOTER "USBIN_I_VOTER"
#define USBIN_V_VOTER "USBIN_V_VOTER"
#define CHG_STATE_VOTER "CHG_STATE_VOTER"
diff --git a/drivers/soc/qcom/glink_private.h b/drivers/soc/qcom/glink_private.h
index cdd6988418f7..24053c853a83 100644
--- a/drivers/soc/qcom/glink_private.h
+++ b/drivers/soc/qcom/glink_private.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2017, 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
@@ -693,6 +693,7 @@ enum ssr_command {
* edge: The G-Link edge name for the channel associated with
* this callback data
* do_cleanup_data: Structure containing the G-Link SSR do_cleanup message.
+ * cb_kref: Kref object to maintain cb_data reference.
*/
struct ssr_notify_data {
bool tx_done;
@@ -700,6 +701,7 @@ struct ssr_notify_data {
bool responded;
const char *edge;
struct do_cleanup_msg *do_cleanup_data;
+ struct kref cb_kref;
};
/**
@@ -734,6 +736,7 @@ struct subsys_info {
int notify_list_len;
bool link_up;
spinlock_t link_up_lock;
+ spinlock_t cb_lock;
};
/**
diff --git a/drivers/soc/qcom/glink_ssr.c b/drivers/soc/qcom/glink_ssr.c
index 5e2dbc8b1d20..7e23b0bc3852 100644
--- a/drivers/soc/qcom/glink_ssr.c
+++ b/drivers/soc/qcom/glink_ssr.c
@@ -115,6 +115,44 @@ static LIST_HEAD(subsystem_list);
static atomic_t responses_remaining = ATOMIC_INIT(0);
static wait_queue_head_t waitqueue;
+/**
+ * cb_data_release() - Free cb_data and set to NULL
+ * @kref_ptr: pointer to kref.
+ *
+ * This function releses cb_data.
+ */
+static inline void cb_data_release(struct kref *kref_ptr)
+{
+ struct ssr_notify_data *cb_data;
+
+ cb_data = container_of(kref_ptr, struct ssr_notify_data, cb_kref);
+ kfree(cb_data);
+}
+
+/**
+ * check_and_get_cb_data() - Try to get reference to kref of cb_data
+ * @ss_info: pointer to subsystem info structure.
+ *
+ * Return: NULL is cb_data is NULL, pointer to cb_data otherwise
+ */
+static struct ssr_notify_data *check_and_get_cb_data(
+ struct subsys_info *ss_info)
+{
+ struct ssr_notify_data *cb_data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ss_info->cb_lock, flags);
+ if (ss_info->cb_data == NULL) {
+ GLINK_SSR_LOG("<SSR> %s: cb_data is NULL\n", __func__);
+ spin_unlock_irqrestore(&ss_info->cb_lock, flags);
+ return 0;
+ }
+ kref_get(&ss_info->cb_data->cb_kref);
+ cb_data = ss_info->cb_data;
+ spin_unlock_irqrestore(&ss_info->cb_lock, flags);
+ return cb_data;
+}
+
static void rx_done_cb_worker(struct work_struct *work)
{
struct rx_done_ch_work *rx_done_work =
@@ -338,8 +376,10 @@ void close_ch_worker(struct work_struct *work)
ss_info->link_state_handle = link_state_handle;
BUG_ON(!ss_info->cb_data);
- kfree(ss_info->cb_data);
+ spin_lock_irqsave(&ss_info->cb_lock, flags);
+ kref_put(&ss_info->cb_data->cb_kref, cb_data_release);
ss_info->cb_data = NULL;
+ spin_unlock_irqrestore(&ss_info->cb_lock, flags);
kfree(close_work);
}
@@ -507,13 +547,18 @@ int notify_for_subsystem(struct subsys_info *ss_info)
return -ENODEV;
}
handle = ss_info_channel->handle;
- ss_leaf_entry->cb_data = ss_info_channel->cb_data;
+ ss_leaf_entry->cb_data = check_and_get_cb_data(
+ ss_info_channel);
+ if (!ss_leaf_entry->cb_data) {
+ GLINK_SSR_LOG("<SSR> %s: CB data is NULL\n", __func__);
+ atomic_dec(&responses_remaining);
+ continue;
+ }
spin_lock_irqsave(&ss_info->link_up_lock, flags);
if (IS_ERR_OR_NULL(ss_info_channel->handle) ||
- !ss_info_channel->cb_data ||
!ss_info_channel->link_up ||
- ss_info_channel->cb_data->event
+ ss_leaf_entry->cb_data->event
!= GLINK_CONNECTED) {
GLINK_SSR_LOG(
@@ -526,6 +571,8 @@ int notify_for_subsystem(struct subsys_info *ss_info)
spin_unlock_irqrestore(&ss_info->link_up_lock, flags);
atomic_dec(&responses_remaining);
+ kref_put(&ss_leaf_entry->cb_data->cb_kref,
+ cb_data_release);
continue;
}
spin_unlock_irqrestore(&ss_info->link_up_lock, flags);
@@ -536,6 +583,8 @@ int notify_for_subsystem(struct subsys_info *ss_info)
GLINK_SSR_ERR(
"%s %s: Could not allocate do_cleanup_msg\n",
"<SSR>", __func__);
+ kref_put(&ss_leaf_entry->cb_data->cb_kref,
+ cb_data_release);
return -ENOMEM;
}
@@ -567,6 +616,8 @@ int notify_for_subsystem(struct subsys_info *ss_info)
__func__);
}
atomic_dec(&responses_remaining);
+ kref_put(&ss_leaf_entry->cb_data->cb_kref,
+ cb_data_release);
continue;
}
@@ -596,10 +647,12 @@ int notify_for_subsystem(struct subsys_info *ss_info)
__func__);
}
atomic_dec(&responses_remaining);
+ kref_put(&ss_leaf_entry->cb_data->cb_kref,
+ cb_data_release);
continue;
}
-
sequence_number++;
+ kref_put(&ss_leaf_entry->cb_data->cb_kref, cb_data_release);
}
wait_ret = wait_event_timeout(waitqueue,
@@ -608,6 +661,21 @@ int notify_for_subsystem(struct subsys_info *ss_info)
list_for_each_entry(ss_leaf_entry, &ss_info->notify_list,
notify_list_node) {
+ ss_info_channel =
+ get_info_for_subsystem(ss_leaf_entry->ssr_name);
+ if (ss_info_channel == NULL) {
+ GLINK_SSR_ERR(
+ "<SSR> %s: unable to find subsystem name\n",
+ __func__);
+ continue;
+ }
+
+ ss_leaf_entry->cb_data = check_and_get_cb_data(
+ ss_info_channel);
+ if (!ss_leaf_entry->cb_data) {
+ GLINK_SSR_LOG("<SSR> %s: CB data is NULL\n", __func__);
+ continue;
+ }
if (!wait_ret && !IS_ERR_OR_NULL(ss_leaf_entry->cb_data)
&& !ss_leaf_entry->cb_data->responded) {
GLINK_SSR_ERR("%s %s: Subsystem %s %s\n",
@@ -626,6 +694,7 @@ int notify_for_subsystem(struct subsys_info *ss_info)
if (!IS_ERR_OR_NULL(ss_leaf_entry->cb_data))
ss_leaf_entry->cb_data->responded = false;
+ kref_put(&ss_leaf_entry->cb_data->cb_kref, cb_data_release);
}
complete(&notifications_successful_complete);
return 0;
@@ -644,6 +713,7 @@ static int configure_and_open_channel(struct subsys_info *ss_info)
struct glink_open_config open_cfg;
struct ssr_notify_data *cb_data = NULL;
void *handle = NULL;
+ unsigned long flags;
if (!ss_info) {
GLINK_SSR_ERR("<SSR> %s: ss_info structure invalid\n",
@@ -660,7 +730,10 @@ static int configure_and_open_channel(struct subsys_info *ss_info)
cb_data->responded = false;
cb_data->event = GLINK_SSR_EVENT_INIT;
cb_data->edge = ss_info->edge;
+ spin_lock_irqsave(&ss_info->cb_lock, flags);
ss_info->cb_data = cb_data;
+ kref_init(&cb_data->cb_kref);
+ spin_unlock_irqrestore(&ss_info->cb_lock, flags);
memset(&open_cfg, 0, sizeof(struct glink_open_config));
@@ -876,6 +949,7 @@ static int glink_ssr_probe(struct platform_device *pdev)
ss_info->link_state_handle = NULL;
ss_info->cb_data = NULL;
spin_lock_init(&ss_info->link_up_lock);
+ spin_lock_init(&ss_info->cb_lock);
nb = kmalloc(sizeof(struct restart_notifier_block), GFP_KERNEL);
if (!nb) {
diff --git a/drivers/usb/phy/phy-msm-ssusb-qmp.c b/drivers/usb/phy/phy-msm-ssusb-qmp.c
index c9df25286342..aa11cf2f7417 100644
--- a/drivers/usb/phy/phy-msm-ssusb-qmp.c
+++ b/drivers/usb/phy/phy-msm-ssusb-qmp.c
@@ -330,10 +330,6 @@ static int msm_ssphy_qmp_init(struct usb_phy *uphy)
phy->clk_enabled = true;
}
- /* select usb3 phy mode */
- if (phy->tcsr_usb3_dp_phymode)
- writel_relaxed(0x0, phy->tcsr_usb3_dp_phymode);
-
writel_relaxed(0x01,
phy->base + phy->phy_reg[USB3_PHY_POWER_DOWN_CONTROL]);
@@ -409,6 +405,10 @@ static int msm_ssphy_qmp_reset(struct usb_phy *uphy)
goto deassert_phy_phy_reset;
}
+ /* select usb3 phy mode */
+ if (phy->tcsr_usb3_dp_phymode)
+ writel_relaxed(0x0, phy->tcsr_usb3_dp_phymode);
+
/* Deassert USB3 PHY CSR reset */
ret = reset_control_deassert(phy->phy_reset);
if (ret) {
diff --git a/fs/fat/fatent.c b/fs/fat/fatent.c
index 8226557130a2..6abd78629140 100644
--- a/fs/fat/fatent.c
+++ b/fs/fat/fatent.c
@@ -92,7 +92,8 @@ static int fat12_ent_bread(struct super_block *sb, struct fat_entry *fatent,
err_brelse:
brelse(bhs[0]);
err:
- fat_msg(sb, KERN_ERR, "FAT read failed (blocknr %llu)", (llu)blocknr);
+ fat_msg_ratelimit(sb, KERN_ERR,
+ "FAT read failed (blocknr %llu)", (llu)blocknr);
return -EIO;
}
@@ -105,8 +106,8 @@ static int fat_ent_bread(struct super_block *sb, struct fat_entry *fatent,
fatent->fat_inode = MSDOS_SB(sb)->fat_inode;
fatent->bhs[0] = sb_bread(sb, blocknr);
if (!fatent->bhs[0]) {
- fat_msg(sb, KERN_ERR, "FAT read failed (blocknr %llu)",
- (llu)blocknr);
+ fat_msg_ratelimit(sb, KERN_ERR,
+ "FAT read failed (blocknr %llu)", (llu)blocknr);
return -EIO;
}
fatent->nr_bhs = 1;
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index cf644d52c0cf..a6c21fba6e9f 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -760,8 +760,9 @@ retry:
fat_get_blknr_offset(sbi, i_pos, &blocknr, &offset);
bh = sb_bread(sb, blocknr);
if (!bh) {
- fat_msg(sb, KERN_ERR, "unable to read inode block "
- "for updating (i_pos %lld)", i_pos);
+ fat_msg_ratelimit(sb, KERN_ERR,
+ "unable to read inode block for updating (i_pos %lld)",
+ i_pos);
return -EIO;
}
spin_lock(&sbi->inode_hash_lock);
diff --git a/include/linux/qpnp/qpnp-revid.h b/include/linux/qpnp/qpnp-revid.h
index 4023e3a683d3..a0e2283ef4c9 100644
--- a/include/linux/qpnp/qpnp-revid.h
+++ b/include/linux/qpnp/qpnp-revid.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2017, 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
@@ -181,6 +181,7 @@
#define PM660L_SUBTYPE 0x1A
#define PM660_SUBTYPE 0x1B
+/* PMI8998 REV_ID */
#define PMI8998_V1P0_REV1 0x00
#define PMI8998_V1P0_REV2 0x00
#define PMI8998_V1P0_REV3 0x00
@@ -196,6 +197,26 @@
#define PMI8998_V2P0_REV3 0x00
#define PMI8998_V2P0_REV4 0x02
+/* PM660 REV_ID */
+#define PM660_V1P0_REV1 0x00
+#define PM660_V1P0_REV2 0x00
+#define PM660_V1P0_REV3 0x00
+#define PM660_V1P0_REV4 0x01
+
+#define PM660_V1P1_REV1 0x00
+#define PM660_V1P1_REV2 0x00
+#define PM660_V1P1_REV3 0x01
+#define PM660_V1P1_REV4 0x01
+
+/* PMI8998 FAB_ID */
+#define PMI8998_FAB_ID_SMIC 0x11
+#define PMI8998_FAB_ID_GF 0x30
+
+/* PM660 FAB_ID */
+#define PM660_FAB_ID_GF 0x0
+#define PM660_FAB_ID_TSMC 0x2
+#define PM660_FAB_ID_MX 0x3
+
/* PM8005 */
#define PM8005_SUBTYPE 0x18
diff --git a/sound/soc/codecs/sdm660_cdc/msm-digital-cdc.c b/sound/soc/codecs/sdm660_cdc/msm-digital-cdc.c
index 3aa502ba065f..2f8c8d6b8a7a 100644
--- a/sound/soc/codecs/sdm660_cdc/msm-digital-cdc.c
+++ b/sound/soc/codecs/sdm660_cdc/msm-digital-cdc.c
@@ -2016,7 +2016,7 @@ static struct snd_soc_codec_driver soc_msm_dig_codec = {
const struct regmap_config msm_digital_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
- .val_bits = 32,
+ .val_bits = 8,
.lock = enable_digital_callback,
.unlock = disable_digital_callback,
.cache_type = REGCACHE_FLAT,