summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt4
-rw-r--r--arch/arm/boot/dts/qcom/msm8998-pinctrl.dtsi46
-rw-r--r--arch/arm/boot/dts/qcom/msm8998.dtsi4
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm8998.c28
-rw-r--r--drivers/power/qcom-charger/qpnp-smb2.c10
-rw-r--r--drivers/power/qcom-charger/smb-lib.c22
-rw-r--r--drivers/scsi/ufs/ufshcd-pltfrm.c21
-rw-r--r--drivers/scsi/ufs/ufshcd.c68
-rw-r--r--drivers/scsi/ufs/ufshcd.h1
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi.c4
-rw-r--r--kernel/sched/core.c10
-rw-r--r--kernel/sched/core_ctl.c10
12 files changed, 200 insertions, 28 deletions
diff --git a/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt b/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt
index bceee5e1747d..a25961c6e7de 100644
--- a/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt
+++ b/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt
@@ -55,6 +55,10 @@ Optional properties:
- lanes-per-direction: number of lanes available per direction - either 1 or 2.
Note that it is assume same number of lanes is used both directions at once.
If not specified, default is 2 lanes per direction.
+- pinctrl-names, pinctrl-0, pinctrl-1,.. pinctrl-n: Refer to "Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt"
+ for these optional properties
+
+
Note: If above properties are not defined it can be assumed that the supply
regulators or clocks are always on.
diff --git a/arch/arm/boot/dts/qcom/msm8998-pinctrl.dtsi b/arch/arm/boot/dts/qcom/msm8998-pinctrl.dtsi
index 1f5facd5cde5..5685e9041fe4 100644
--- a/arch/arm/boot/dts/qcom/msm8998-pinctrl.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8998-pinctrl.dtsi
@@ -1624,6 +1624,52 @@
};
};
+ ufs_dev_reset_assert: ufs_dev_reset_assert {
+ config {
+ pins = "ufs_reset";
+ bias-pull-down; /* default: pull down */
+ /*
+ * UFS_RESET driver strengths are having
+ * different values/steps compared to typical
+ * GPIO drive strengths.
+ *
+ * Following table clarifies:
+ *
+ * HDRV value | UFS_RESET | Typical GPIO
+ * (dec) | (mA) | (mA)
+ * 0 | 0.8 | 2
+ * 1 | 1.55 | 4
+ * 2 | 2.35 | 6
+ * 3 | 3.1 | 8
+ * 4 | 3.9 | 10
+ * 5 | 4.65 | 12
+ * 6 | 5.4 | 14
+ * 7 | 6.15 | 16
+ *
+ * POR value for UFS_RESET HDRV is 3 which means
+ * 3.1mA and we want to use that. Hence just
+ * specify 8mA to "drive-strength" binding and
+ * that should result into writing 3 to HDRV
+ * field.
+ */
+ drive-strength = <8>; /* default: 3.1 mA */
+ output-low; /* active low reset */
+ };
+ };
+
+ ufs_dev_reset_deassert: ufs_dev_reset_deassert {
+ config {
+ pins = "ufs_reset";
+ bias-pull-down; /* default: pull down */
+ /*
+ * default: 3.1 mA
+ * check comments under ufs_dev_reset_assert
+ */
+ drive-strength = <8>;
+ output-high; /* active low reset */
+ };
+ };
+
sdc2_clk_on: sdc2_clk_on {
config {
pins = "sdc2_clk";
diff --git a/arch/arm/boot/dts/qcom/msm8998.dtsi b/arch/arm/boot/dts/qcom/msm8998.dtsi
index 7f7f2f65deee..e95bc8597043 100644
--- a/arch/arm/boot/dts/qcom/msm8998.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8998.dtsi
@@ -1660,6 +1660,10 @@
qcom,pm-qos-cpu-group-latency-us = <70 70>;
qcom,pm-qos-default-cpu = <0>;
+ pinctrl-names = "dev-reset-assert", "dev-reset-deassert";
+ pinctrl-0 = <&ufs_dev_reset_assert>;
+ pinctrl-1 = <&ufs_dev_reset_deassert>;
+
resets = <&clock_gcc UFS_BCR>;
reset-names = "core_reset";
diff --git a/drivers/pinctrl/qcom/pinctrl-msm8998.c b/drivers/pinctrl/qcom/pinctrl-msm8998.c
index e983bcc8e47d..c4882f244d3f 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm8998.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm8998.c
@@ -92,6 +92,31 @@
.intr_detection_bit = -1, \
.intr_detection_width = -1, \
}
+
+#define UFS_RESET(pg_name, offset) \
+ { \
+ .name = #pg_name, \
+ .pins = pg_name##_pins, \
+ .npins = (unsigned)ARRAY_SIZE(pg_name##_pins), \
+ .ctl_reg = offset, \
+ .io_reg = offset + 0x4, \
+ .intr_cfg_reg = 0, \
+ .intr_status_reg = 0, \
+ .intr_target_reg = 0, \
+ .mux_bit = -1, \
+ .pull_bit = 3, \
+ .drv_bit = 0, \
+ .oe_bit = -1, \
+ .in_bit = -1, \
+ .out_bit = 0, \
+ .intr_enable_bit = -1, \
+ .intr_status_bit = -1, \
+ .intr_target_bit = -1, \
+ .intr_raw_status_bit = -1, \
+ .intr_polarity_bit = -1, \
+ .intr_detection_bit = -1, \
+ .intr_detection_width = -1, \
+ }
static const struct pinctrl_pin_desc msm8998_pins[] = {
PINCTRL_PIN(0, "GPIO_0"),
PINCTRL_PIN(1, "GPIO_1"),
@@ -246,6 +271,7 @@ static const struct pinctrl_pin_desc msm8998_pins[] = {
PINCTRL_PIN(150, "SDC2_CLK"),
PINCTRL_PIN(151, "SDC2_CMD"),
PINCTRL_PIN(152, "SDC2_DATA"),
+ PINCTRL_PIN(153, "UFS_RESET"),
};
#define DECLARE_MSM_GPIO_PINS(pin) \
@@ -404,6 +430,7 @@ DECLARE_MSM_GPIO_PINS(149);
static const unsigned int sdc2_clk_pins[] = { 150 };
static const unsigned int sdc2_cmd_pins[] = { 151 };
static const unsigned int sdc2_data_pins[] = { 152 };
+static const unsigned int ufs_reset_pins[] = { 153 };
enum msm8998_functions {
msm_mux_blsp_spi1,
@@ -1856,6 +1883,7 @@ static const struct msm_pingroup msm8998_groups[] = {
SDC_QDSD_PINGROUP(sdc2_clk, 0x999000, 14, 6),
SDC_QDSD_PINGROUP(sdc2_cmd, 0x999000, 11, 3),
SDC_QDSD_PINGROUP(sdc2_data, 0x999000, 9, 0),
+ UFS_RESET(ufs_reset, 0x19d000),
};
static const struct msm_pinctrl_soc_data msm8998_pinctrl = {
diff --git a/drivers/power/qcom-charger/qpnp-smb2.c b/drivers/power/qcom-charger/qpnp-smb2.c
index 039ffcc24c23..f7a54f71a28a 100644
--- a/drivers/power/qcom-charger/qpnp-smb2.c
+++ b/drivers/power/qcom-charger/qpnp-smb2.c
@@ -1172,12 +1172,14 @@ static int smb2_init_hw(struct smb2 *chip)
return rc;
}
- /* disable Type-C factory mode */
+ /*
+ * disable Type-C factory mode and stay in Attached.SRC state when VCONN
+ * over-current happens
+ */
rc = smblib_masked_write(chg, TYPE_C_CFG_REG,
- FACTORY_MODE_DETECTION_EN_BIT, 0);
+ FACTORY_MODE_DETECTION_EN_BIT | VCONN_OC_CFG_BIT, 0);
if (rc < 0) {
- dev_err(chg->dev,
- "Couldn't disable Type-C factory mode rc=%d\n", rc);
+ dev_err(chg->dev, "Couldn't configure Type-C rc=%d\n", rc);
return rc;
}
diff --git a/drivers/power/qcom-charger/smb-lib.c b/drivers/power/qcom-charger/smb-lib.c
index 52805357ef92..0faf8aee8aa0 100644
--- a/drivers/power/qcom-charger/smb-lib.c
+++ b/drivers/power/qcom-charger/smb-lib.c
@@ -2865,39 +2865,39 @@ irqreturn_t smblib_handle_usb_typec_change(int irq, void *data)
struct smb_irq_data *irq_data = data;
struct smb_charger *chg = irq_data->parent_data;
int rc;
- u8 stat;
+ u8 stat4, stat5;
bool debounce_done, sink_attached, legacy_cable;
/* WA - not when PD hard_reset WIP on cc2 in sink mode */
if (chg->cc2_sink_detach_flag == CC2_SINK_STD)
return IRQ_HANDLED;
- rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat);
+ rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat4);
if (rc < 0) {
smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc);
return IRQ_HANDLED;
}
- smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_4 = 0x%02x\n", stat);
- debounce_done = (bool)(stat & TYPEC_DEBOUNCE_DONE_STATUS_BIT);
- sink_attached = (bool)(stat & UFP_DFP_MODE_STATUS_BIT);
- rc = smblib_read(chg, TYPE_C_STATUS_5_REG, &stat);
+ rc = smblib_read(chg, TYPE_C_STATUS_5_REG, &stat5);
if (rc < 0) {
smblib_err(chg, "Couldn't read TYPE_C_STATUS_5 rc=%d\n", rc);
return IRQ_HANDLED;
}
- smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_5 = 0x%02x\n", stat);
- legacy_cable = (bool)(stat & TYPEC_LEGACY_CABLE_STATUS_BIT);
+
+ debounce_done = (bool)(stat4 & TYPEC_DEBOUNCE_DONE_STATUS_BIT);
+ sink_attached = (bool)(stat4 & UFP_DFP_MODE_STATUS_BIT);
+ legacy_cable = (bool)(stat5 & TYPEC_LEGACY_CABLE_STATUS_BIT);
smblib_handle_typec_debounce_done(chg,
debounce_done, sink_attached, legacy_cable);
- power_supply_changed(chg->usb_psy);
-
- if (stat & TYPEC_VBUS_ERROR_STATUS_BIT)
+ if (stat4 & TYPEC_VBUS_ERROR_STATUS_BIT)
smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s vbus-error\n",
irq_data->name);
+ power_supply_changed(chg->usb_psy);
+ smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_4 = 0x%02x\n", stat4);
+ smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_5 = 0x%02x\n", stat5);
return IRQ_HANDLED;
}
diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c
index 5a9564326099..41684dca6baa 100644
--- a/drivers/scsi/ufs/ufshcd-pltfrm.c
+++ b/drivers/scsi/ufs/ufshcd-pltfrm.c
@@ -250,6 +250,20 @@ static void ufshcd_parse_pm_levels(struct ufs_hba *hba)
}
}
+static int ufshcd_parse_pinctrl_info(struct ufs_hba *hba)
+{
+ int ret = 0;
+
+ /* Try to obtain pinctrl handle */
+ hba->pctrl = devm_pinctrl_get(hba->dev);
+ if (IS_ERR(hba->pctrl)) {
+ ret = PTR_ERR(hba->pctrl);
+ hba->pctrl = NULL;
+ }
+
+ return ret;
+}
+
#ifdef CONFIG_SMP
/**
* ufshcd_pltfrm_suspend - suspend power management function
@@ -361,6 +375,13 @@ int ufshcd_pltfrm_init(struct platform_device *pdev,
goto dealloc_host;
}
+ err = ufshcd_parse_pinctrl_info(hba);
+ if (err) {
+ dev_dbg(&pdev->dev, "%s: unable to parse pinctrl data %d\n",
+ __func__, err);
+ /* let's not fail the probe */
+ }
+
ufshcd_parse_pm_levels(hba);
if (!dev->dma_mask)
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index e52aed51f67d..6a5c9ca74818 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -446,6 +446,63 @@ void ufshcd_scsi_block_requests(struct ufs_hba *hba)
}
EXPORT_SYMBOL(ufshcd_scsi_block_requests);
+static int ufshcd_device_reset_ctrl(struct ufs_hba *hba, bool ctrl)
+{
+ int ret = 0;
+
+ if (!hba->pctrl)
+ return 0;
+
+ /* Assert reset if ctrl == true */
+ if (ctrl)
+ ret = pinctrl_select_state(hba->pctrl,
+ pinctrl_lookup_state(hba->pctrl, "dev-reset-assert"));
+ else
+ ret = pinctrl_select_state(hba->pctrl,
+ pinctrl_lookup_state(hba->pctrl, "dev-reset-deassert"));
+
+ if (ret < 0)
+ dev_err(hba->dev, "%s: %s failed with err %d\n",
+ __func__, ctrl ? "Assert" : "Deassert", ret);
+
+ return ret;
+}
+
+static inline int ufshcd_assert_device_reset(struct ufs_hba *hba)
+{
+ return ufshcd_device_reset_ctrl(hba, true);
+}
+
+static inline int ufshcd_deassert_device_reset(struct ufs_hba *hba)
+{
+ return ufshcd_device_reset_ctrl(hba, false);
+}
+
+static int ufshcd_reset_device(struct ufs_hba *hba)
+{
+ int ret;
+
+ /* reset the connected UFS device */
+ ret = ufshcd_assert_device_reset(hba);
+ if (ret)
+ goto out;
+ /*
+ * The reset signal is active low.
+ * The UFS device shall detect more than or equal to 1us of positive
+ * or negative RST_n pulse width.
+ * To be on safe side, keep the reset low for atleast 10us.
+ */
+ usleep_range(10, 15);
+
+ ret = ufshcd_deassert_device_reset(hba);
+ if (ret)
+ goto out;
+ /* same as assert, wait for atleast 10us after deassert */
+ usleep_range(10, 15);
+out:
+ return ret;
+}
+
/* replace non-printable or non-ASCII characters with spaces */
static inline void ufshcd_remove_non_printable(char *val)
{
@@ -6520,6 +6577,11 @@ static int ufshcd_reset_and_restore(struct ufs_hba *hba)
dev_warn(hba->dev, "%s: full reset returned %d\n",
__func__, err);
+ err = ufshcd_reset_device(hba);
+ if (err)
+ dev_warn(hba->dev, "%s: device reset failed. err %d\n",
+ __func__, err);
+
err = ufshcd_host_reset_and_restore(hba);
} while (err && --retries);
@@ -9422,6 +9484,12 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
/* Reset controller to power on reset (POR) state */
ufshcd_vops_full_reset(hba);
+ /* reset connected UFS device */
+ err = ufshcd_reset_device(hba);
+ if (err)
+ dev_warn(hba->dev, "%s: device reset failed. err %d\n",
+ __func__, err);
+
/* Host controller enable */
err = ufshcd_hba_enable(hba);
if (err) {
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 9f2b04c8ff82..c5eb21d8a0fe 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -907,6 +907,7 @@ struct ufs_hba {
int scsi_block_reqs_cnt;
bool full_init_linereset;
+ struct pinctrl *pctrl;
};
static inline void ufshcd_mark_shutdown_ongoing(struct ufs_hba *hba)
diff --git a/drivers/video/fbdev/msm/mdss_dsi.c b/drivers/video/fbdev/msm/mdss_dsi.c
index 8dccab8a81be..9ed34bc55773 100644
--- a/drivers/video/fbdev/msm/mdss_dsi.c
+++ b/drivers/video/fbdev/msm/mdss_dsi.c
@@ -1283,7 +1283,11 @@ int mdss_dsi_switch_mode(struct mdss_panel_data *pdata, int mode)
MDSS_DSI_ALL_CLKS, MDSS_DSI_CLK_ON);
if (dsi_ctrl_setup_needed)
mdss_dsi_ctrl_setup(ctrl_pdata);
+
+ ATRACE_BEGIN("switch_cmds");
ctrl_pdata->switch_mode(pdata, mode);
+ ATRACE_END("switch_cmds");
+
mdss_dsi_clk_ctrl(ctrl_pdata, ctrl_pdata->dsi_clk_handle,
MDSS_DSI_ALL_CLKS, MDSS_DSI_CLK_OFF);
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index a5d101e8a5f2..f60117eb60fa 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -5682,7 +5682,7 @@ int sched_isolate_cpu(int cpu)
if (trace_sched_isolate_enabled())
start_time = sched_clock();
- lock_device_hotplug();
+ cpu_maps_update_begin();
cpumask_andnot(&avail_cpus, cpu_online_mask, cpu_isolated_mask);
@@ -5731,7 +5731,7 @@ int sched_isolate_cpu(int cpu)
sched_update_group_capacities(cpu);
out:
- unlock_device_hotplug();
+ cpu_maps_update_done();
trace_sched_isolate(cpu, cpumask_bits(cpu_isolated_mask)[0],
start_time, 1);
return ret_code;
@@ -5752,8 +5752,6 @@ int sched_unisolate_cpu_unlocked(int cpu)
if (trace_sched_isolate_enabled())
start_time = sched_clock();
- lock_device_hotplug_assert();
-
if (!cpu_isolation_vote[cpu]) {
ret_code = -EINVAL;
goto out;
@@ -5792,9 +5790,9 @@ int sched_unisolate_cpu(int cpu)
{
int ret_code;
- lock_device_hotplug();
+ cpu_maps_update_begin();
ret_code = sched_unisolate_cpu_unlocked(cpu);
- unlock_device_hotplug();
+ cpu_maps_update_done();
return ret_code;
}
diff --git a/kernel/sched/core_ctl.c b/kernel/sched/core_ctl.c
index 9b21a09ec4ba..aac12bfc2ae6 100644
--- a/kernel/sched/core_ctl.c
+++ b/kernel/sched/core_ctl.c
@@ -893,14 +893,10 @@ static int __ref cpu_callback(struct notifier_block *nfb,
unsigned int need;
int ret = NOTIFY_OK;
- /* Don't affect suspend resume */
- if (action & CPU_TASKS_FROZEN)
- return NOTIFY_OK;
-
if (unlikely(!cluster || !cluster->inited))
return NOTIFY_OK;
- switch (action) {
+ switch (action & ~CPU_TASKS_FROZEN) {
case CPU_UP_PREPARE:
/* If online state of CPU somehow got out of sync, fix it. */
@@ -1095,7 +1091,7 @@ static int __init core_ctl_init(void)
cpufreq_register_notifier(&cpufreq_pol_nb, CPUFREQ_POLICY_NOTIFIER);
cpufreq_register_notifier(&cpufreq_gov_nb, CPUFREQ_GOVINFO_NOTIFIER);
- lock_device_hotplug();
+ cpu_maps_update_begin();
for_each_online_cpu(cpu) {
struct cpufreq_policy *policy;
int ret;
@@ -1109,7 +1105,7 @@ static int __init core_ctl_init(void)
cpufreq_cpu_put(policy);
}
}
- unlock_device_hotplug();
+ cpu_maps_update_done();
initialized = true;
return 0;
}