diff options
author | Alex Frid <afrid@nvidia.com> | 2013-07-09 18:53:06 -0700 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2013-09-14 13:32:54 -0700 |
commit | 824999ffa32a8aee3301cf78ac411ff07e351d2b (patch) | |
tree | 61bd6395f644566acf09d6b826936af9527dcf42 /arch/arm/mach-tegra/tegra_cl_dvfs.c | |
parent | 4a5d228ee980592dd9a0b70cafd8c1a9847c45e9 (diff) |
ARM: tegra: dvfs: Modify cl-dvfs monitor control
- Dropped concept of "default monitor selection" (was - frequency).
Explicitly select monitor mux each time data is read.
- Restricted monitor debugfs node to frequency only (removed the
option to read other possible outputs - this is still available via
debugfs access to CL-DVFS registers)
- Added output_mv debugfs node to read last output value
Change-Id: Idca7500279d8c035e1f38ff99dd486ca79a3419d
Signed-off-by: Alex Frid <afrid@nvidia.com>
Reviewed-on: http://git-master/r/251605
Reviewed-by: Yu-Huan Hsu <yhsu@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra/tegra_cl_dvfs.c')
-rw-r--r-- | arch/arm/mach-tegra/tegra_cl_dvfs.c | 69 |
1 files changed, 44 insertions, 25 deletions
diff --git a/arch/arm/mach-tegra/tegra_cl_dvfs.c b/arch/arm/mach-tegra/tegra_cl_dvfs.c index 00d35a915416..e04c2c1cef4b 100644 --- a/arch/arm/mach-tegra/tegra_cl_dvfs.c +++ b/arch/arm/mach-tegra/tegra_cl_dvfs.c @@ -256,6 +256,14 @@ static inline void cl_dvfs_wmb(struct tegra_cl_dvfs *cld) cl_dvfs_readl(cld, CL_DVFS_CTRL); } +static inline void switch_monitor(struct tegra_cl_dvfs *cld, u32 selector) +{ + /* delay to make sure selector has switched */ + cl_dvfs_writel(cld, selector, CL_DVFS_MONITOR_CTRL); + cl_dvfs_wmb(cld); + udelay(1); +} + static inline void invalidate_request(struct tegra_cl_dvfs *cld) { u32 val = cl_dvfs_readl(cld, CL_DVFS_FREQ_REQ); @@ -662,12 +670,8 @@ static void cl_dvfs_calibrate(struct tegra_cl_dvfs *cld) return; cld->last_calibration = now; - if (cl_dvfs_readl(cld, CL_DVFS_MONITOR_CTRL) != - CL_DVFS_MONITOR_CTRL_FREQ) - cl_dvfs_writel(cld, CL_DVFS_MONITOR_CTRL_FREQ, - CL_DVFS_MONITOR_CTRL); - /* Synchronize with sample period, and get rate measurements */ + switch_monitor(cld, CL_DVFS_MONITOR_CTRL_FREQ); data = cl_dvfs_readl(cld, CL_DVFS_MONITOR_DATA); do { data = cl_dvfs_readl(cld, CL_DVFS_MONITOR_DATA); @@ -684,14 +688,10 @@ static void cl_dvfs_calibrate(struct tegra_cl_dvfs *cld) return; } } else { - /* Get last output, then restore default frequency monitoring */ - cl_dvfs_writel(cld, CL_DVFS_MONITOR_CTRL_OUT, - CL_DVFS_MONITOR_CTRL); - cl_dvfs_wmb(cld); + /* Get last output (there is no such thing as pending PWM) */ + switch_monitor(cld, CL_DVFS_MONITOR_CTRL_OUT); val = cl_dvfs_readl(cld, CL_DVFS_MONITOR_DATA) & CL_DVFS_MONITOR_DATA_MASK; - cl_dvfs_writel(cld, CL_DVFS_MONITOR_CTRL_FREQ, - CL_DVFS_MONITOR_CTRL); } /* Adjust minimum rate */ @@ -1778,30 +1778,45 @@ static int monitor_get(void *data, u64 *val) struct tegra_cl_dvfs *cld = ((struct clk *)data)->u.dfll.cl_dvfs; clk_enable(cld->soc_clk); - clk_lock_save(c, &flags); + + switch_monitor(cld, CL_DVFS_MONITOR_CTRL_FREQ); + v = cl_dvfs_readl(cld, CL_DVFS_MONITOR_DATA) & CL_DVFS_MONITOR_DATA_MASK; + v = GET_MONITORED_RATE(v, cld->ref_rate); + s = cl_dvfs_readl(cld, CL_DVFS_FREQ_REQ); + s = (s & CL_DVFS_FREQ_REQ_SCALE_MASK) >> CL_DVFS_FREQ_REQ_SCALE_SHIFT; + *val = (u64)v * (s + 1) / 256; - if (cl_dvfs_readl(cld, CL_DVFS_MONITOR_CTRL) == - CL_DVFS_MONITOR_CTRL_FREQ) { - v = GET_MONITORED_RATE(v, cld->ref_rate); - s = cl_dvfs_readl(cld, CL_DVFS_FREQ_REQ); - s = (s & CL_DVFS_FREQ_REQ_SCALE_MASK) >> - CL_DVFS_FREQ_REQ_SCALE_SHIFT; - *val = (u64)v * (s + 1) / 256; + clk_unlock_restore(c, &flags); + clk_disable(cld->soc_clk); + return 0; +} +DEFINE_SIMPLE_ATTRIBUTE(monitor_fops, monitor_get, NULL, "%llu\n"); - clk_unlock_restore(c, &flags); - clk_disable(cld->soc_clk); - return 0; - } - *val = v; +static int output_get(void *data, u64 *val) +{ + u32 v; + unsigned long flags; + struct clk *c = (struct clk *)data; + struct tegra_cl_dvfs *cld = ((struct clk *)data)->u.dfll.cl_dvfs; + + clk_enable(cld->soc_clk); + clk_lock_save(c, &flags); + + switch_monitor(cld, CL_DVFS_MONITOR_CTRL_OUT); + + v = cl_dvfs_readl(cld, CL_DVFS_MONITOR_DATA) & + CL_DVFS_MONITOR_DATA_MASK; + *val = is_i2c(cld) ? cld->out_map[v]->reg_uV / 1000 : + cld->p_data->vdd_map[v].reg_uV / 1000; clk_unlock_restore(c, &flags); clk_disable(cld->soc_clk); return 0; } -DEFINE_SIMPLE_ATTRIBUTE(monitor_fops, monitor_get, NULL, "%llu\n"); +DEFINE_SIMPLE_ATTRIBUTE(output_fops, output_get, NULL, "%llu\n"); static int vmax_get(void *data, u64 *val) { @@ -2042,6 +2057,10 @@ int __init tegra_cl_dvfs_debug_init(struct clk *dfll_clk) cl_dvfs_dentry, dfll_clk, &monitor_fops)) goto err_out; + if (!debugfs_create_file("output_mv", S_IRUGO, + cl_dvfs_dentry, dfll_clk, &output_fops)) + goto err_out; + if (!debugfs_create_file("vmax_mv", S_IRUGO, cl_dvfs_dentry, dfll_clk, &vmax_fops)) goto err_out; |