Add shared code to support the Tegra DFLL clocksource in open-loop...
mode. This root clocksource is present on the Tegra124 SoCs. The
DFLL is the intended primary clock source for the fast CPU cluster.
This code is very closely based on a patch by Paul Walmsley from
December (http://comments.gmane.org/gmane.linux.ports.tegra/15273),
which in turn comes from the internal driver by originally created
by Aleksandr Frid <afrid@xxxxxxxxxx>.
Subsequent patches will add support for closed loop mode and drivers
for the Tegra124 fast CPU cluster DFLL devices, which rely on this
code.
Signed-off-by: Paul Walmsley <pwalmsley@xxxxxxxxxx>
Signed-off-by: Tuomas Tynkkynen <ttynkkynen@xxxxxxxxxx>
---
v2 changes:
- minor, moved the devm_regulator_get here
drivers/clk/tegra/Makefile | 1 +
drivers/clk/tegra/clk-dfll.c | 1085 ++++++++++++++++++++++++++++++++++++++++++
drivers/clk/tegra/clk-dfll.h | 55 +++
3 files changed, 1141 insertions(+)
create mode 100644 drivers/clk/tegra/clk-dfll.c
create mode 100644 drivers/clk/tegra/clk-dfll.h
--- /dev/null...
+++ b/drivers/clk/tegra/clk-dfll.c
+...
+/*
+ * Output clock scaler helpers
+ */
+
+/**
+ * dfll_scale_dvco_rate - calculate scaled rate from the DVCO rate
+ * @scale_bits: clock scaler value (bits in the DFLL_FREQ_REQ_SCALE field)
+ * @dvco_rate: the DVCO rate
+ *
+ * Apply the same scaling formula that the DFLL hardware uses to scale
+ * the DVCO rate.
+ */
+static unsigned long dfll_scale_dvco_rate(int scale_bits,
+ unsigned long dvco_rate)
+{
+ return (u64)dvco_rate * (scale_bits + 1) / DFLL_FREQ_REQ_SCALE_MAX;
+}
+static u64 dfll_read_monitor_rate(struct tegra_dfll *td)Should be dfll_scale_dvco_rate(s, pre_scaler_rate);
+{
+ u32 v, s;
+ u64 pre_scaler_rate, post_scaler_rate;
+
+ if (!dfll_is_running(td))
+ return 0;
+
+ v = dfll_readl(td, DFLL_MONITOR_DATA);
+ v = (v & DFLL_MONITOR_DATA_VAL_MASK) >> DFLL_MONITOR_DATA_VAL_SHIFT;
+ pre_scaler_rate = dfll_calc_monitored_rate(v, td->ref_rate);
+
+ s = dfll_readl(td, DFLL_FREQ_REQ);
+ s = (s & DFLL_FREQ_REQ_SCALE_MASK) >> DFLL_FREQ_REQ_SCALE_SHIFT;
+ post_scaler_rate = dfll_scale_dvco_rate(pre_scaler_rate, s);