scsi: ufs: Add sysfs node to dynamically control clock gating
Provide an option to enable/disable clock gating during runtime. Write 1 or 0 to "clkgate_enable" sysfs node to enable/disable clock gating. Change-Id: I69a20e66cf91bb889ac3942eb2d20d5adc289d03 Signed-off-by: Sahitya Tummala <stummala@codeaurora.org> [subhashj@codeaurora.org: resolved trivial merge conflicts] Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
This commit is contained in:
parent
61df89e001
commit
36d8e79c02
2 changed files with 50 additions and 0 deletions
|
@ -939,6 +939,41 @@ static ssize_t ufshcd_clkgate_delay_store(struct device *dev,
|
|||
return count;
|
||||
}
|
||||
|
||||
static ssize_t ufshcd_clkgate_enable_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct ufs_hba *hba = dev_get_drvdata(dev);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", hba->clk_gating.is_enabled);
|
||||
}
|
||||
|
||||
static ssize_t ufshcd_clkgate_enable_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
struct ufs_hba *hba = dev_get_drvdata(dev);
|
||||
unsigned long flags;
|
||||
u32 value;
|
||||
|
||||
if (kstrtou32(buf, 0, &value))
|
||||
return -EINVAL;
|
||||
|
||||
value = !!value;
|
||||
if (value == hba->clk_gating.is_enabled)
|
||||
goto out;
|
||||
|
||||
if (value) {
|
||||
ufshcd_release(hba);
|
||||
} else {
|
||||
spin_lock_irqsave(hba->host->host_lock, flags);
|
||||
hba->clk_gating.active_reqs++;
|
||||
spin_unlock_irqrestore(hba->host->host_lock, flags);
|
||||
}
|
||||
|
||||
hba->clk_gating.is_enabled = value;
|
||||
out:
|
||||
return count;
|
||||
}
|
||||
|
||||
static void ufshcd_init_clk_gating(struct ufs_hba *hba)
|
||||
{
|
||||
if (!ufshcd_is_clkgating_allowed(hba))
|
||||
|
@ -948,6 +983,8 @@ static void ufshcd_init_clk_gating(struct ufs_hba *hba)
|
|||
INIT_DELAYED_WORK(&hba->clk_gating.gate_work, ufshcd_gate_work);
|
||||
INIT_WORK(&hba->clk_gating.ungate_work, ufshcd_ungate_work);
|
||||
|
||||
hba->clk_gating.is_enabled = true;
|
||||
|
||||
hba->clk_gating.delay_attr.show = ufshcd_clkgate_delay_show;
|
||||
hba->clk_gating.delay_attr.store = ufshcd_clkgate_delay_store;
|
||||
sysfs_attr_init(&hba->clk_gating.delay_attr.attr);
|
||||
|
@ -955,6 +992,14 @@ static void ufshcd_init_clk_gating(struct ufs_hba *hba)
|
|||
hba->clk_gating.delay_attr.attr.mode = S_IRUGO | S_IWUSR;
|
||||
if (device_create_file(hba->dev, &hba->clk_gating.delay_attr))
|
||||
dev_err(hba->dev, "Failed to create sysfs for clkgate_delay\n");
|
||||
|
||||
hba->clk_gating.enable_attr.show = ufshcd_clkgate_enable_show;
|
||||
hba->clk_gating.enable_attr.store = ufshcd_clkgate_enable_store;
|
||||
sysfs_attr_init(&hba->clk_gating.enable_attr.attr);
|
||||
hba->clk_gating.enable_attr.attr.name = "clkgate_enable";
|
||||
hba->clk_gating.enable_attr.attr.mode = S_IRUGO | S_IWUSR;
|
||||
if (device_create_file(hba->dev, &hba->clk_gating.enable_attr))
|
||||
dev_err(hba->dev, "Failed to create sysfs for clkgate_enable\n");
|
||||
}
|
||||
|
||||
static void ufshcd_exit_clk_gating(struct ufs_hba *hba)
|
||||
|
@ -962,6 +1007,7 @@ static void ufshcd_exit_clk_gating(struct ufs_hba *hba)
|
|||
if (!ufshcd_is_clkgating_allowed(hba))
|
||||
return;
|
||||
device_remove_file(hba->dev, &hba->clk_gating.delay_attr);
|
||||
device_remove_file(hba->dev, &hba->clk_gating.enable_attr);
|
||||
cancel_work_sync(&hba->clk_gating.ungate_work);
|
||||
cancel_delayed_work_sync(&hba->clk_gating.gate_work);
|
||||
}
|
||||
|
|
|
@ -308,6 +308,8 @@ enum clk_gating_state {
|
|||
* @is_suspended: clk gating is suspended when set to 1 which can be used
|
||||
* during suspend/resume
|
||||
* @delay_attr: sysfs attribute to control delay_attr
|
||||
* @enable_attr: sysfs attribute to enable/disable clock gating
|
||||
* @is_enabled: Indicates the current status of clock gating
|
||||
* @active_reqs: number of requests that are pending and should be waited for
|
||||
* completion before gating clocks.
|
||||
*/
|
||||
|
@ -318,6 +320,8 @@ struct ufs_clk_gating {
|
|||
unsigned long delay_ms;
|
||||
bool is_suspended;
|
||||
struct device_attribute delay_attr;
|
||||
struct device_attribute enable_attr;
|
||||
bool is_enabled;
|
||||
int active_reqs;
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue