diff options
author | Alex Frid <afrid@nvidia.com> | 2013-12-02 19:31:08 -0800 |
---|---|---|
committer | Yu-Huan Hsu <yhsu@nvidia.com> | 2013-12-04 14:47:39 -0800 |
commit | 9eec03df07d6a143ab05d236c15b51ae9925cb9a (patch) | |
tree | 3a64973e950c2ea9d5f8cf63632d63f07fc5822d /arch/arm/mach-tegra/tegra_cl_dvfs.c | |
parent | c442029f6f583ae0ece957c759e89fde63852a96 (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.c | 20 |
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); |