From: hgchu Date: Fri, 12 Jan 2018 01:32:29 +0000 (+0900) Subject: scsi: ufs: adjusted UFS power management for exynos specific X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=8214b37753fc9bdbc0adc6514cfda71cd6beaeb1;p=GitHub%2FLineageOS%2Fandroid_kernel_motorola_exynos9610.git scsi: ufs: adjusted UFS power management for exynos specific Change-Id: I151e77eb1f5f2703e33cd4e9834204a9fa66f88c Signed-off-by: hgchu --- diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c index f33a3797ef7b..713570e17b84 100644 --- a/drivers/scsi/ufs/ufshcd-pltfrm.c +++ b/drivers/scsi/ufs/ufshcd-pltfrm.c @@ -221,6 +221,34 @@ out: return err; } +static int ufshcd_parse_pm_lvl_policy(struct ufs_hba *hba) +{ + struct device *dev = hba->dev; + struct device_node *np = dev->of_node; + u32 lvl_def[] = {UFS_PM_LVL_2, UFS_PM_LVL_5}; + u32 lvl[2] = {0,}, i; + + for (i = 0; i < ARRAY_SIZE(lvl); i++) { + if (of_property_read_u32_index(np, "pm_lvl_states", i, lvl +i)) { + dev_info(hba->dev, + "UFS power management: set default level%d index %d\n", + lvl_def[i], i); + lvl[i] = lvl_def[i]; + } + + if (lvl[i] < UFS_PM_LVL_0 || lvl[i] >= UFS_PM_LVL_MAX) { + dev_warn(hba->dev, + "UFS power management: out of range level%d index %d\n", + lvl[i], i); + lvl[i] = lvl_def[i]; + } + } + + hba->rpm_lvl = lvl[0]; + hba->spm_lvl = lvl[1]; + + return 0; +} #ifdef CONFIG_PM /** * ufshcd_pltfrm_suspend - suspend power management function @@ -340,6 +368,7 @@ int ufshcd_pltfrm_init(struct platform_device *pdev, goto dealloc_host; } + ufshcd_parse_pm_lvl_policy(hba); pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 28f3b8582eae..193f67f5424b 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -3969,8 +3969,10 @@ static int ufshcd_change_power_mode(struct ufs_hba *hba, dev_err(hba->dev, "%s: power mode change failed %d\n", __func__, ret); } else { - ufshcd_vops_pwr_change_notify(hba, POST_CHANGE, NULL, + ret = ufshcd_vops_pwr_change_notify(hba, POST_CHANGE, NULL, pwr_mode); + if (ret) + goto out; memcpy(&hba->pwr_info, pwr_mode, sizeof(struct ufs_pa_layer_attr)); @@ -3993,13 +3995,17 @@ int ufshcd_config_pwr_mode(struct ufs_hba *hba, ret = ufshcd_vops_pwr_change_notify(hba, PRE_CHANGE, desired_pwr_mode, &final_params); - if (ret) - memcpy(&final_params, desired_pwr_mode, sizeof(final_params)); + if (ret) { + if (ret == -ENOTSUPP) + memcpy(&final_params, desired_pwr_mode, sizeof(final_params)); + else + goto out; + } ret = ufshcd_change_power_mode(hba, &final_params); if (!ret) ufshcd_print_pwr_info(hba); - +out: return ret; } EXPORT_SYMBOL_GPL(ufshcd_config_pwr_mode); @@ -6899,6 +6905,7 @@ static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool on, int ret = 0; struct ufs_clk_info *clki; struct list_head *head = &hba->clk_list_head; + const char *ref_clk = "ref_clk"; unsigned long flags; ktime_t start = ktime_get(); bool clk_state_changed = false; @@ -6912,7 +6919,8 @@ static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool on, list_for_each_entry(clki, head, list) { if (!IS_ERR_OR_NULL(clki->clk)) { - if (skip_ref_clk && !strcmp(clki->name, "ref_clk")) + if (skip_ref_clk && + !strncmp(clki->name, ref_clk, strlen(ref_clk))) continue; clk_state_changed = on ^ clki->enabled; @@ -7426,17 +7434,13 @@ static int ufshcd_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) if (ret) goto set_dev_active; - ufshcd_vreg_set_lpm(hba); - disable_clks: /* - * Call vendor specific suspend callback. As these callbacks may access - * vendor specific host controller register space call them before the - * host clocks are ON. + * Disable the host irq as host controller as there won't be any + * host controller trasanction expected till resume. */ - ret = ufshcd_vops_suspend(hba, pm_op); - if (ret) - goto set_link_active; + ufshcd_disable_irq(hba); + if (!ufshcd_is_link_active(hba)) ufshcd_setup_clocks(hba, false); @@ -7447,10 +7451,15 @@ disable_clks: hba->clk_gating.state = CLKS_OFF; trace_ufshcd_clk_gating(dev_name(hba->dev), hba->clk_gating.state); /* - * Disable the host irq as host controller as there won't be any - * host controller transaction expected till resume. + * Call vendor specific suspend callback. As these callbacks may access + * vendor specific host controller register space call them before the + * host clocks are ON. */ - ufshcd_disable_irq(hba); + ret = ufshcd_vops_suspend(hba, pm_op); + if (ret) + goto set_link_active; + + /* Put the host controller in low power mode if possible */ ufshcd_hba_vreg_set_lpm(hba); goto out;