aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/ufs
diff options
context:
space:
mode:
authorSahitya Tummala <stummala@codeaurora.org>2014-09-25 08:32:34 -0400
committerChristoph Hellwig <hch@lst.de>2014-10-01 07:11:25 -0400
commit856b348305c98d4e0c8e5eafa97c61443197f8d3 (patch)
treebbb29c8efc53c8b7b6e83f547e57a8007bc14b8c /drivers/scsi/ufs
parent4cff6d991e4a291cf50fe2659da2ea9ad46620bf (diff)
ufs: Add support for clock scaling using devfreq framework
The clocks for UFS device will be managed by generic DVFS (Dynamic Voltage and Frequency Scaling) framework within kernel. This devfreq framework works with different governors to scale the clocks. By default, UFS devices uses simple_ondemand governor which scales the clocks up if the load is more than upthreshold and scales down if the load is less than downthreshold. Signed-off-by: Sahitya Tummala <stummala@codeaurora.org> Signed-off-by: Dolev Raviv <draviv@codeaurora.org> Signed-off-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'drivers/scsi/ufs')
-rw-r--r--drivers/scsi/ufs/Kconfig2
-rw-r--r--drivers/scsi/ufs/ufshcd.c178
-rw-r--r--drivers/scsi/ufs/ufshcd.h20
3 files changed, 199 insertions, 1 deletions
diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
index f07f90179bbc..6e07b2afddeb 100644
--- a/drivers/scsi/ufs/Kconfig
+++ b/drivers/scsi/ufs/Kconfig
@@ -35,6 +35,8 @@
35config SCSI_UFSHCD 35config SCSI_UFSHCD
36 tristate "Universal Flash Storage Controller Driver Core" 36 tristate "Universal Flash Storage Controller Driver Core"
37 depends on SCSI && SCSI_DMA 37 depends on SCSI && SCSI_DMA
38 select PM_DEVFREQ
39 select DEVFREQ_GOV_SIMPLE_ONDEMAND
38 ---help--- 40 ---help---
39 This selects the support for UFS devices in Linux, say Y and make 41 This selects the support for UFS devices in Linux, say Y and make
40 sure that you know the name of your UFS host adapter (the card 42 sure that you know the name of your UFS host adapter (the card
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 6f1ea5192db6..df525e3b2c19 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -38,6 +38,7 @@
38 */ 38 */
39 39
40#include <linux/async.h> 40#include <linux/async.h>
41#include <linux/devfreq.h>
41 42
42#include "ufshcd.h" 43#include "ufshcd.h"
43#include "unipro.h" 44#include "unipro.h"
@@ -545,6 +546,8 @@ static void ufshcd_ungate_work(struct work_struct *work)
545 hba->clk_gating.is_suspended = false; 546 hba->clk_gating.is_suspended = false;
546 } 547 }
547unblock_reqs: 548unblock_reqs:
549 if (ufshcd_is_clkscaling_enabled(hba))
550 devfreq_resume_device(hba->devfreq);
548 scsi_unblock_requests(hba->host); 551 scsi_unblock_requests(hba->host);
549} 552}
550 553
@@ -561,10 +564,10 @@ int ufshcd_hold(struct ufs_hba *hba, bool async)
561 564
562 if (!ufshcd_is_clkgating_allowed(hba)) 565 if (!ufshcd_is_clkgating_allowed(hba))
563 goto out; 566 goto out;
564start:
565 spin_lock_irqsave(hba->host->host_lock, flags); 567 spin_lock_irqsave(hba->host->host_lock, flags);
566 hba->clk_gating.active_reqs++; 568 hba->clk_gating.active_reqs++;
567 569
570start:
568 switch (hba->clk_gating.state) { 571 switch (hba->clk_gating.state) {
569 case CLKS_ON: 572 case CLKS_ON:
570 break; 573 break;
@@ -596,6 +599,7 @@ start:
596 spin_unlock_irqrestore(hba->host->host_lock, flags); 599 spin_unlock_irqrestore(hba->host->host_lock, flags);
597 flush_work(&hba->clk_gating.ungate_work); 600 flush_work(&hba->clk_gating.ungate_work);
598 /* Make sure state is CLKS_ON before returning */ 601 /* Make sure state is CLKS_ON before returning */
602 spin_lock_irqsave(hba->host->host_lock, flags);
599 goto start; 603 goto start;
600 default: 604 default:
601 dev_err(hba->dev, "%s: clk gating is in invalid state %d\n", 605 dev_err(hba->dev, "%s: clk gating is in invalid state %d\n",
@@ -636,6 +640,11 @@ static void ufshcd_gate_work(struct work_struct *work)
636 ufshcd_set_link_hibern8(hba); 640 ufshcd_set_link_hibern8(hba);
637 } 641 }
638 642
643 if (ufshcd_is_clkscaling_enabled(hba)) {
644 devfreq_suspend_device(hba->devfreq);
645 hba->clk_scaling.window_start_t = 0;
646 }
647
639 if (!ufshcd_is_link_active(hba)) 648 if (!ufshcd_is_link_active(hba))
640 ufshcd_setup_clocks(hba, false); 649 ufshcd_setup_clocks(hba, false);
641 else 650 else
@@ -737,6 +746,32 @@ static void ufshcd_exit_clk_gating(struct ufs_hba *hba)
737 device_remove_file(hba->dev, &hba->clk_gating.delay_attr); 746 device_remove_file(hba->dev, &hba->clk_gating.delay_attr);
738} 747}
739 748
749/* Must be called with host lock acquired */
750static void ufshcd_clk_scaling_start_busy(struct ufs_hba *hba)
751{
752 if (!ufshcd_is_clkscaling_enabled(hba))
753 return;
754
755 if (!hba->clk_scaling.is_busy_started) {
756 hba->clk_scaling.busy_start_t = ktime_get();
757 hba->clk_scaling.is_busy_started = true;
758 }
759}
760
761static void ufshcd_clk_scaling_update_busy(struct ufs_hba *hba)
762{
763 struct ufs_clk_scaling *scaling = &hba->clk_scaling;
764
765 if (!ufshcd_is_clkscaling_enabled(hba))
766 return;
767
768 if (!hba->outstanding_reqs && scaling->is_busy_started) {
769 scaling->tot_busy_t += ktime_to_us(ktime_sub(ktime_get(),
770 scaling->busy_start_t));
771 scaling->busy_start_t = ktime_set(0, 0);
772 scaling->is_busy_started = false;
773 }
774}
740/** 775/**
741 * ufshcd_send_command - Send SCSI or device management commands 776 * ufshcd_send_command - Send SCSI or device management commands
742 * @hba: per adapter instance 777 * @hba: per adapter instance
@@ -745,6 +780,7 @@ static void ufshcd_exit_clk_gating(struct ufs_hba *hba)
745static inline 780static inline
746void ufshcd_send_command(struct ufs_hba *hba, unsigned int task_tag) 781void ufshcd_send_command(struct ufs_hba *hba, unsigned int task_tag)
747{ 782{
783 ufshcd_clk_scaling_start_busy(hba);
748 __set_bit(task_tag, &hba->outstanding_reqs); 784 __set_bit(task_tag, &hba->outstanding_reqs);
749 ufshcd_writel(hba, 1 << task_tag, REG_UTP_TRANSFER_REQ_DOOR_BELL); 785 ufshcd_writel(hba, 1 << task_tag, REG_UTP_TRANSFER_REQ_DOOR_BELL);
750} 786}
@@ -3027,6 +3063,8 @@ static void ufshcd_transfer_req_compl(struct ufs_hba *hba)
3027 /* clear corresponding bits of completed commands */ 3063 /* clear corresponding bits of completed commands */
3028 hba->outstanding_reqs ^= completed_reqs; 3064 hba->outstanding_reqs ^= completed_reqs;
3029 3065
3066 ufshcd_clk_scaling_update_busy(hba);
3067
3030 /* we might have free'd some tags above */ 3068 /* we might have free'd some tags above */
3031 wake_up(&hba->dev_cmd.tag_wq); 3069 wake_up(&hba->dev_cmd.tag_wq);
3032} 3070}
@@ -4151,6 +4189,10 @@ static int ufshcd_probe_hba(struct ufs_hba *hba)
4151 if (!hba->is_init_prefetch) 4189 if (!hba->is_init_prefetch)
4152 hba->is_init_prefetch = true; 4190 hba->is_init_prefetch = true;
4153 4191
4192 /* Resume devfreq after UFS device is detected */
4193 if (ufshcd_is_clkscaling_enabled(hba))
4194 devfreq_resume_device(hba->devfreq);
4195
4154out: 4196out:
4155 /* 4197 /*
4156 * If we failed to initialize the device or the device is not 4198 * If we failed to initialize the device or the device is not
@@ -4472,6 +4514,7 @@ static int ufshcd_init_clocks(struct ufs_hba *hba)
4472 clki->max_freq, ret); 4514 clki->max_freq, ret);
4473 goto out; 4515 goto out;
4474 } 4516 }
4517 clki->curr_freq = clki->max_freq;
4475 } 4518 }
4476 dev_dbg(dev, "%s: clk: %s, rate: %lu\n", __func__, 4519 dev_dbg(dev, "%s: clk: %s, rate: %lu\n", __func__,
4477 clki->name, clk_get_rate(clki->clk)); 4520 clki->name, clk_get_rate(clki->clk));
@@ -4868,6 +4911,15 @@ static int ufshcd_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
4868 4911
4869disable_clks: 4912disable_clks:
4870 /* 4913 /*
4914 * The clock scaling needs access to controller registers. Hence, Wait
4915 * for pending clock scaling work to be done before clocks are
4916 * turned off.
4917 */
4918 if (ufshcd_is_clkscaling_enabled(hba)) {
4919 devfreq_suspend_device(hba->devfreq);
4920 hba->clk_scaling.window_start_t = 0;
4921 }
4922 /*
4871 * Call vendor specific suspend callback. As these callbacks may access 4923 * Call vendor specific suspend callback. As these callbacks may access
4872 * vendor specific host controller register space call them before the 4924 * vendor specific host controller register space call them before the
4873 * host clocks are ON. 4925 * host clocks are ON.
@@ -4989,6 +5041,9 @@ static int ufshcd_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
4989 ufshcd_disable_auto_bkops(hba); 5041 ufshcd_disable_auto_bkops(hba);
4990 hba->clk_gating.is_suspended = false; 5042 hba->clk_gating.is_suspended = false;
4991 5043
5044 if (ufshcd_is_clkscaling_enabled(hba))
5045 devfreq_resume_device(hba->devfreq);
5046
4992 /* Schedule clock gating in case of no access to UFS device yet */ 5047 /* Schedule clock gating in case of no access to UFS device yet */
4993 ufshcd_release(hba); 5048 ufshcd_release(hba);
4994 goto out; 5049 goto out;
@@ -5172,6 +5227,8 @@ void ufshcd_remove(struct ufs_hba *hba)
5172 scsi_host_put(hba->host); 5227 scsi_host_put(hba->host);
5173 5228
5174 ufshcd_exit_clk_gating(hba); 5229 ufshcd_exit_clk_gating(hba);
5230 if (ufshcd_is_clkscaling_enabled(hba))
5231 devfreq_remove_device(hba->devfreq);
5175 ufshcd_hba_exit(hba); 5232 ufshcd_hba_exit(hba);
5176} 5233}
5177EXPORT_SYMBOL_GPL(ufshcd_remove); 5234EXPORT_SYMBOL_GPL(ufshcd_remove);
@@ -5228,6 +5285,112 @@ out_error:
5228} 5285}
5229EXPORT_SYMBOL(ufshcd_alloc_host); 5286EXPORT_SYMBOL(ufshcd_alloc_host);
5230 5287
5288static int ufshcd_scale_clks(struct ufs_hba *hba, bool scale_up)
5289{
5290 int ret = 0;
5291 struct ufs_clk_info *clki;
5292 struct list_head *head = &hba->clk_list_head;
5293
5294 if (!head || list_empty(head))
5295 goto out;
5296
5297 list_for_each_entry(clki, head, list) {
5298 if (!IS_ERR_OR_NULL(clki->clk)) {
5299 if (scale_up && clki->max_freq) {
5300 if (clki->curr_freq == clki->max_freq)
5301 continue;
5302 ret = clk_set_rate(clki->clk, clki->max_freq);
5303 if (ret) {
5304 dev_err(hba->dev, "%s: %s clk set rate(%dHz) failed, %d\n",
5305 __func__, clki->name,
5306 clki->max_freq, ret);
5307 break;
5308 }
5309 clki->curr_freq = clki->max_freq;
5310
5311 } else if (!scale_up && clki->min_freq) {
5312 if (clki->curr_freq == clki->min_freq)
5313 continue;
5314 ret = clk_set_rate(clki->clk, clki->min_freq);
5315 if (ret) {
5316 dev_err(hba->dev, "%s: %s clk set rate(%dHz) failed, %d\n",
5317 __func__, clki->name,
5318 clki->min_freq, ret);
5319 break;
5320 }
5321 clki->curr_freq = clki->min_freq;
5322 }
5323 }
5324 dev_dbg(hba->dev, "%s: clk: %s, rate: %lu\n", __func__,
5325 clki->name, clk_get_rate(clki->clk));
5326 }
5327 if (hba->vops->clk_scale_notify)
5328 hba->vops->clk_scale_notify(hba);
5329out:
5330 return ret;
5331}
5332
5333static int ufshcd_devfreq_target(struct device *dev,
5334 unsigned long *freq, u32 flags)
5335{
5336 int err = 0;
5337 struct ufs_hba *hba = dev_get_drvdata(dev);
5338
5339 if (!ufshcd_is_clkscaling_enabled(hba))
5340 return -EINVAL;
5341
5342 if (*freq == UINT_MAX)
5343 err = ufshcd_scale_clks(hba, true);
5344 else if (*freq == 0)
5345 err = ufshcd_scale_clks(hba, false);
5346
5347 return err;
5348}
5349
5350static int ufshcd_devfreq_get_dev_status(struct device *dev,
5351 struct devfreq_dev_status *stat)
5352{
5353 struct ufs_hba *hba = dev_get_drvdata(dev);
5354 struct ufs_clk_scaling *scaling = &hba->clk_scaling;
5355 unsigned long flags;
5356
5357 if (!ufshcd_is_clkscaling_enabled(hba))
5358 return -EINVAL;
5359
5360 memset(stat, 0, sizeof(*stat));
5361
5362 spin_lock_irqsave(hba->host->host_lock, flags);
5363 if (!scaling->window_start_t)
5364 goto start_window;
5365
5366 if (scaling->is_busy_started)
5367 scaling->tot_busy_t += ktime_to_us(ktime_sub(ktime_get(),
5368 scaling->busy_start_t));
5369
5370 stat->total_time = jiffies_to_usecs((long)jiffies -
5371 (long)scaling->window_start_t);
5372 stat->busy_time = scaling->tot_busy_t;
5373start_window:
5374 scaling->window_start_t = jiffies;
5375 scaling->tot_busy_t = 0;
5376
5377 if (hba->outstanding_reqs) {
5378 scaling->busy_start_t = ktime_get();
5379 scaling->is_busy_started = true;
5380 } else {
5381 scaling->busy_start_t = ktime_set(0, 0);
5382 scaling->is_busy_started = false;
5383 }
5384 spin_unlock_irqrestore(hba->host->host_lock, flags);
5385 return 0;
5386}
5387
5388static struct devfreq_dev_profile ufs_devfreq_profile = {
5389 .polling_ms = 100,
5390 .target = ufshcd_devfreq_target,
5391 .get_dev_status = ufshcd_devfreq_get_dev_status,
5392};
5393
5231/** 5394/**
5232 * ufshcd_init - Driver initialization routine 5395 * ufshcd_init - Driver initialization routine
5233 * @hba: per-adapter instance 5396 * @hba: per-adapter instance
@@ -5337,6 +5500,19 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
5337 goto out_remove_scsi_host; 5500 goto out_remove_scsi_host;
5338 } 5501 }
5339 5502
5503 if (ufshcd_is_clkscaling_enabled(hba)) {
5504 hba->devfreq = devfreq_add_device(dev, &ufs_devfreq_profile,
5505 "simple_ondemand", NULL);
5506 if (IS_ERR(hba->devfreq)) {
5507 dev_err(hba->dev, "Unable to register with devfreq %ld\n",
5508 PTR_ERR(hba->devfreq));
5509 goto out_remove_scsi_host;
5510 }
5511 /* Suspend devfreq until the UFS device is detected */
5512 devfreq_suspend_device(hba->devfreq);
5513 hba->clk_scaling.window_start_t = 0;
5514 }
5515
5340 /* Hold auto suspend until async scan completes */ 5516 /* Hold auto suspend until async scan completes */
5341 pm_runtime_get_sync(dev); 5517 pm_runtime_get_sync(dev);
5342 5518
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index ac72a6daf50e..908db3eb0609 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -210,6 +210,7 @@ struct ufs_dev_cmd {
210 * @name: clock name 210 * @name: clock name
211 * @max_freq: maximum frequency supported by the clock 211 * @max_freq: maximum frequency supported by the clock
212 * @min_freq: min frequency that can be used for clock scaling 212 * @min_freq: min frequency that can be used for clock scaling
213 * @curr_freq: indicates the current frequency that it is set to
213 * @enabled: variable to check against multiple enable/disable 214 * @enabled: variable to check against multiple enable/disable
214 */ 215 */
215struct ufs_clk_info { 216struct ufs_clk_info {
@@ -218,6 +219,7 @@ struct ufs_clk_info {
218 const char *name; 219 const char *name;
219 u32 max_freq; 220 u32 max_freq;
220 u32 min_freq; 221 u32 min_freq;
222 u32 curr_freq;
221 bool enabled; 223 bool enabled;
222}; 224};
223 225
@@ -244,6 +246,7 @@ struct ufs_pwr_mode_info {
244 * @name: variant name 246 * @name: variant name
245 * @init: called when the driver is initialized 247 * @init: called when the driver is initialized
246 * @exit: called to cleanup everything done in init 248 * @exit: called to cleanup everything done in init
249 * @clk_scale_notify: notifies that clks are scaled up/down
247 * @setup_clocks: called before touching any of the controller registers 250 * @setup_clocks: called before touching any of the controller registers
248 * @setup_regulators: called before accessing the host controller 251 * @setup_regulators: called before accessing the host controller
249 * @hce_enable_notify: called before and after HCE enable bit is set to allow 252 * @hce_enable_notify: called before and after HCE enable bit is set to allow
@@ -260,6 +263,7 @@ struct ufs_hba_variant_ops {
260 const char *name; 263 const char *name;
261 int (*init)(struct ufs_hba *); 264 int (*init)(struct ufs_hba *);
262 void (*exit)(struct ufs_hba *); 265 void (*exit)(struct ufs_hba *);
266 void (*clk_scale_notify)(struct ufs_hba *);
263 int (*setup_clocks)(struct ufs_hba *, bool); 267 int (*setup_clocks)(struct ufs_hba *, bool);
264 int (*setup_regulators)(struct ufs_hba *, bool); 268 int (*setup_regulators)(struct ufs_hba *, bool);
265 int (*hce_enable_notify)(struct ufs_hba *, bool); 269 int (*hce_enable_notify)(struct ufs_hba *, bool);
@@ -303,6 +307,13 @@ struct ufs_clk_gating {
303 int active_reqs; 307 int active_reqs;
304}; 308};
305 309
310struct ufs_clk_scaling {
311 ktime_t busy_start_t;
312 bool is_busy_started;
313 unsigned long tot_busy_t;
314 unsigned long window_start_t;
315};
316
306/** 317/**
307 * struct ufs_init_prefetch - contains data that is pre-fetched once during 318 * struct ufs_init_prefetch - contains data that is pre-fetched once during
308 * initialization 319 * initialization
@@ -456,6 +467,11 @@ struct ufs_hba {
456#define UFSHCD_CAP_CLK_GATING (1 << 0) 467#define UFSHCD_CAP_CLK_GATING (1 << 0)
457 /* Allow hiberb8 with clk gating */ 468 /* Allow hiberb8 with clk gating */
458#define UFSHCD_CAP_HIBERN8_WITH_CLK_GATING (1 << 1) 469#define UFSHCD_CAP_HIBERN8_WITH_CLK_GATING (1 << 1)
470 /* Allow dynamic clk scaling */
471#define UFSHCD_CAP_CLK_SCALING (1 << 2)
472
473 struct devfreq *devfreq;
474 struct ufs_clk_scaling clk_scaling;
459}; 475};
460 476
461/* Returns true if clocks can be gated. Otherwise false */ 477/* Returns true if clocks can be gated. Otherwise false */
@@ -467,6 +483,10 @@ static inline bool ufshcd_can_hibern8_during_gating(struct ufs_hba *hba)
467{ 483{
468 return hba->caps & UFSHCD_CAP_HIBERN8_WITH_CLK_GATING; 484 return hba->caps & UFSHCD_CAP_HIBERN8_WITH_CLK_GATING;
469} 485}
486static inline int ufshcd_is_clkscaling_enabled(struct ufs_hba *hba)
487{
488 return hba->caps & UFSHCD_CAP_CLK_SCALING;
489}
470#define ufshcd_writel(hba, val, reg) \ 490#define ufshcd_writel(hba, val, reg) \
471 writel((val), (hba)->mmio_base + (reg)) 491 writel((val), (hba)->mmio_base + (reg))
472#define ufshcd_readl(hba, reg) \ 492#define ufshcd_readl(hba, reg) \