diff options
author | Chen-Yu Tsai <wens@csie.org> | 2017-10-12 11:37:00 +0300 |
---|---|---|
committer | Maxime Ripard <maxime.ripard@free-electrons.com> | 2017-10-13 10:27:13 +0300 |
commit | 392ba5fafcdf1969d1abd9a637cc40c45f4781bc (patch) | |
tree | f624600dd29c6a4f8f09ea41b5ab18697496b2f9 /drivers/clk/sunxi-ng/ccu_nm.c | |
parent | 05d2eaac96d4284b0967cc522ad22f6f23fdf82a (diff) | |
download | linux-392ba5fafcdf1969d1abd9a637cc40c45f4781bc.tar.xz |
clk: sunxi-ng: nm: Add support for sigma-delta modulation
Some of the N-M-style clocks, namely the PLLs, support sigma-delta
modulation to do fractional-N frequency synthesis. This is used in
the audio PLL to generate the exact frequency the audio blocks need.
These frequencies can not be generated with integer N-M factors.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Diffstat (limited to 'drivers/clk/sunxi-ng/ccu_nm.c')
-rw-r--r-- | drivers/clk/sunxi-ng/ccu_nm.c | 22 |
1 files changed, 21 insertions, 1 deletions
diff --git a/drivers/clk/sunxi-ng/ccu_nm.c b/drivers/clk/sunxi-ng/ccu_nm.c index 84a5e7f17f6f..7620aa973a6e 100644 --- a/drivers/clk/sunxi-ng/ccu_nm.c +++ b/drivers/clk/sunxi-ng/ccu_nm.c @@ -90,6 +90,14 @@ static unsigned long ccu_nm_recalc_rate(struct clk_hw *hw, if (!m) m++; + if (ccu_sdm_helper_is_enabled(&nm->common, &nm->sdm)) { + unsigned long rate = + ccu_sdm_helper_read_rate(&nm->common, &nm->sdm, + m, n); + if (rate) + return rate; + } + return parent_rate * n / m; } @@ -102,6 +110,9 @@ static long ccu_nm_round_rate(struct clk_hw *hw, unsigned long rate, if (ccu_frac_helper_has_rate(&nm->common, &nm->frac, rate)) return rate; + if (ccu_sdm_helper_has_rate(&nm->common, &nm->sdm, rate)) + return rate; + _nm.min_n = nm->n.min ?: 1; _nm.max_n = nm->n.max ?: 1 << nm->n.width; _nm.min_m = 1; @@ -143,7 +154,16 @@ static int ccu_nm_set_rate(struct clk_hw *hw, unsigned long rate, _nm.min_m = 1; _nm.max_m = nm->m.max ?: 1 << nm->m.width; - ccu_nm_find_best(parent_rate, rate, &_nm); + if (ccu_sdm_helper_has_rate(&nm->common, &nm->sdm, rate)) { + ccu_sdm_helper_enable(&nm->common, &nm->sdm, rate); + + /* Sigma delta modulation requires specific N and M factors */ + ccu_sdm_helper_get_factors(&nm->common, &nm->sdm, rate, + &_nm.m, &_nm.n); + } else { + ccu_sdm_helper_disable(&nm->common, &nm->sdm); + ccu_nm_find_best(parent_rate, rate, &_nm); + } spin_lock_irqsave(nm->common.lock, flags); |