summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/tegra_cl_dvfs.c
diff options
context:
space:
mode:
authorAlex Frid <afrid@nvidia.com>2013-12-02 19:31:08 -0800
committerYu-Huan Hsu <yhsu@nvidia.com>2013-12-04 14:47:39 -0800
commit9eec03df07d6a143ab05d236c15b51ae9925cb9a (patch)
tree3a64973e950c2ea9d5f8cf63632d63f07fc5822d /arch/arm/mach-tegra/tegra_cl_dvfs.c
parentc442029f6f583ae0ece957c759e89fde63852a96 (diff)
ARM: tegra: dvfs: Support non-sync DFLL monitor
Added platform flag to indicate DFLL monitor h/w that do not allow synchronization because DATA_NEW status bit can not be used. For any monitor read just skipped synchronization, and rely only on already implemented check for consistency of consecutive reads. In addition, replaced wait for data in calibration procedure with explicit delay to make sure data has been monitored at least one full sample period. Bug 1401470 Change-Id: Ia3b21ff3db8c46f1fc3167634e337888201eb4e2 Signed-off-by: Alex Frid <afrid@nvidia.com> Reviewed-on: http://git-master/r/337555 GVS: Gerrit_Virtual_Submit 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.c20
1 files changed, 15 insertions, 5 deletions
diff --git a/arch/arm/mach-tegra/tegra_cl_dvfs.c b/arch/arm/mach-tegra/tegra_cl_dvfs.c
index 9dec660a966d..5fad2694e413 100644
--- a/arch/arm/mach-tegra/tegra_cl_dvfs.c
+++ b/arch/arm/mach-tegra/tegra_cl_dvfs.c
@@ -320,7 +320,8 @@ static inline void disable_forced_output(struct tegra_cl_dvfs *cld)
* (neither "old" nor "new") values. Synchronization with the "rising edge"
* of DATA_NEW makes it very unlikely, but still possible. Use simple filter:
* compare 2 consecutive readings for data consistency within 2 LSb range.
- * Return error otherwise.
+ * Return error otherwise. On the platform that does not allow to use DATA_NEW
+ * at all check for consistency of consecutive reads is the only protection.
*/
static int filter_monitor_data(struct tegra_cl_dvfs *cld, u32 *data)
{
@@ -341,10 +342,12 @@ static int filter_monitor_data(struct tegra_cl_dvfs *cld, u32 *data)
static inline void wait_data_new(struct tegra_cl_dvfs *cld, u32 *data)
{
cl_dvfs_readl(cld, CL_DVFS_MONITOR_DATA); /* clear data new */
- do {
- *data = cl_dvfs_readl(cld, CL_DVFS_MONITOR_DATA);
- } while (!(*data & CL_DVFS_MONITOR_DATA_NEW) &&
- (cld->mode > TEGRA_CL_DVFS_DISABLED));
+ if (!(cld->p_data->flags & TEGRA_CL_DVFS_DATA_NEW_NO_USE)) {
+ do {
+ *data = cl_dvfs_readl(cld, CL_DVFS_MONITOR_DATA);
+ } while (!(*data & CL_DVFS_MONITOR_DATA_NEW) &&
+ (cld->mode > TEGRA_CL_DVFS_DISABLED));
+ }
}
static inline u32 get_last_output(struct tegra_cl_dvfs *cld)
@@ -791,6 +794,13 @@ static void cl_dvfs_calibrate(struct tegra_cl_dvfs *cld)
/* Synchronize with sample period, and get rate measurements */
switch_monitor(cld, CL_DVFS_MONITOR_CTRL_FREQ);
+
+ if (cld->p_data->flags & TEGRA_CL_DVFS_DATA_NEW_NO_USE) {
+ /* Cannot use DATA_NEW synch - get data after one full sample
+ period (with 10us margin) */
+ int delay = 1000000 / cld->p_data->cfg_param->sample_rate + 10;
+ udelay(delay);
+ }
wait_data_new(cld, &data);
wait_data_new(cld, &data);