1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
20565fb16STero Kristo /*
30565fb16STero Kristo * OMAP3/4 - specific DPLL control functions
40565fb16STero Kristo *
50565fb16STero Kristo * Copyright (C) 2009-2010 Texas Instruments, Inc.
60565fb16STero Kristo * Copyright (C) 2009-2010 Nokia Corporation
70565fb16STero Kristo *
80565fb16STero Kristo * Written by Paul Walmsley
90565fb16STero Kristo * Testing and integration fixes by Jouni Högander
100565fb16STero Kristo *
110565fb16STero Kristo * 36xx support added by Vishwanath BS, Richard Woodruff, and Nishanth
120565fb16STero Kristo * Menon
130565fb16STero Kristo *
140565fb16STero Kristo * Parts of this code are based on code written by
150565fb16STero Kristo * Richard Woodruff, Tony Lindgren, Tuukka Tikkanen, Karthik Dasu
160565fb16STero Kristo */
170565fb16STero Kristo
180565fb16STero Kristo #include <linux/kernel.h>
190565fb16STero Kristo #include <linux/device.h>
200565fb16STero Kristo #include <linux/list.h>
210565fb16STero Kristo #include <linux/errno.h>
220565fb16STero Kristo #include <linux/delay.h>
230565fb16STero Kristo #include <linux/clk.h>
240565fb16STero Kristo #include <linux/io.h>
250565fb16STero Kristo #include <linux/bitops.h>
260565fb16STero Kristo #include <linux/clkdev.h>
270565fb16STero Kristo #include <linux/clk/ti.h>
280565fb16STero Kristo
290565fb16STero Kristo #include "clock.h"
300565fb16STero Kristo
310565fb16STero Kristo /* CM_AUTOIDLE_PLL*.AUTO_* bit values */
320565fb16STero Kristo #define DPLL_AUTOIDLE_DISABLE 0x0
330565fb16STero Kristo #define DPLL_AUTOIDLE_LOW_POWER_STOP 0x1
340565fb16STero Kristo
350565fb16STero Kristo #define MAX_DPLL_WAIT_TRIES 1000000
360565fb16STero Kristo
370565fb16STero Kristo #define OMAP3XXX_EN_DPLL_LOCKED 0x7
380565fb16STero Kristo
390565fb16STero Kristo /* Forward declarations */
400565fb16STero Kristo static u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk);
410565fb16STero Kristo static void omap3_dpll_deny_idle(struct clk_hw_omap *clk);
420565fb16STero Kristo static void omap3_dpll_allow_idle(struct clk_hw_omap *clk);
430565fb16STero Kristo
440565fb16STero Kristo /* Private functions */
450565fb16STero Kristo
460565fb16STero Kristo /* _omap3_dpll_write_clken - write clken_bits arg to a DPLL's enable bits */
_omap3_dpll_write_clken(struct clk_hw_omap * clk,u8 clken_bits)470565fb16STero Kristo static void _omap3_dpll_write_clken(struct clk_hw_omap *clk, u8 clken_bits)
480565fb16STero Kristo {
490565fb16STero Kristo const struct dpll_data *dd;
500565fb16STero Kristo u32 v;
510565fb16STero Kristo
520565fb16STero Kristo dd = clk->dpll_data;
530565fb16STero Kristo
546c0afb50STero Kristo v = ti_clk_ll_ops->clk_readl(&dd->control_reg);
550565fb16STero Kristo v &= ~dd->enable_mask;
560565fb16STero Kristo v |= clken_bits << __ffs(dd->enable_mask);
576c0afb50STero Kristo ti_clk_ll_ops->clk_writel(v, &dd->control_reg);
580565fb16STero Kristo }
590565fb16STero Kristo
600565fb16STero Kristo /* _omap3_wait_dpll_status: wait for a DPLL to enter a specific state */
_omap3_wait_dpll_status(struct clk_hw_omap * clk,u8 state)610565fb16STero Kristo static int _omap3_wait_dpll_status(struct clk_hw_omap *clk, u8 state)
620565fb16STero Kristo {
630565fb16STero Kristo const struct dpll_data *dd;
640565fb16STero Kristo int i = 0;
650565fb16STero Kristo int ret = -EINVAL;
660565fb16STero Kristo const char *clk_name;
670565fb16STero Kristo
680565fb16STero Kristo dd = clk->dpll_data;
69a53ad8efSStephen Boyd clk_name = clk_hw_get_name(&clk->hw);
700565fb16STero Kristo
710565fb16STero Kristo state <<= __ffs(dd->idlest_mask);
720565fb16STero Kristo
736c0afb50STero Kristo while (((ti_clk_ll_ops->clk_readl(&dd->idlest_reg) & dd->idlest_mask)
740565fb16STero Kristo != state) && i < MAX_DPLL_WAIT_TRIES) {
750565fb16STero Kristo i++;
760565fb16STero Kristo udelay(1);
770565fb16STero Kristo }
780565fb16STero Kristo
790565fb16STero Kristo if (i == MAX_DPLL_WAIT_TRIES) {
800565fb16STero Kristo pr_err("clock: %s failed transition to '%s'\n",
810565fb16STero Kristo clk_name, (state) ? "locked" : "bypassed");
820565fb16STero Kristo } else {
830565fb16STero Kristo pr_debug("clock: %s transition to '%s' in %d loops\n",
840565fb16STero Kristo clk_name, (state) ? "locked" : "bypassed", i);
850565fb16STero Kristo
860565fb16STero Kristo ret = 0;
870565fb16STero Kristo }
880565fb16STero Kristo
890565fb16STero Kristo return ret;
900565fb16STero Kristo }
910565fb16STero Kristo
920565fb16STero Kristo /* From 3430 TRM ES2 4.7.6.2 */
_omap3_dpll_compute_freqsel(struct clk_hw_omap * clk,u8 n)930565fb16STero Kristo static u16 _omap3_dpll_compute_freqsel(struct clk_hw_omap *clk, u8 n)
940565fb16STero Kristo {
950565fb16STero Kristo unsigned long fint;
960565fb16STero Kristo u16 f = 0;
970565fb16STero Kristo
98b6f51284STero Kristo fint = clk_hw_get_rate(clk->dpll_data->clk_ref) / n;
990565fb16STero Kristo
1000565fb16STero Kristo pr_debug("clock: fint is %lu\n", fint);
1010565fb16STero Kristo
1020565fb16STero Kristo if (fint >= 750000 && fint <= 1000000)
1030565fb16STero Kristo f = 0x3;
1040565fb16STero Kristo else if (fint > 1000000 && fint <= 1250000)
1050565fb16STero Kristo f = 0x4;
1060565fb16STero Kristo else if (fint > 1250000 && fint <= 1500000)
1070565fb16STero Kristo f = 0x5;
1080565fb16STero Kristo else if (fint > 1500000 && fint <= 1750000)
1090565fb16STero Kristo f = 0x6;
1100565fb16STero Kristo else if (fint > 1750000 && fint <= 2100000)
1110565fb16STero Kristo f = 0x7;
1120565fb16STero Kristo else if (fint > 7500000 && fint <= 10000000)
1130565fb16STero Kristo f = 0xB;
1140565fb16STero Kristo else if (fint > 10000000 && fint <= 12500000)
1150565fb16STero Kristo f = 0xC;
1160565fb16STero Kristo else if (fint > 12500000 && fint <= 15000000)
1170565fb16STero Kristo f = 0xD;
1180565fb16STero Kristo else if (fint > 15000000 && fint <= 17500000)
1190565fb16STero Kristo f = 0xE;
1200565fb16STero Kristo else if (fint > 17500000 && fint <= 21000000)
1210565fb16STero Kristo f = 0xF;
1220565fb16STero Kristo else
1230565fb16STero Kristo pr_debug("clock: unknown freqsel setting for %d\n", n);
1240565fb16STero Kristo
1250565fb16STero Kristo return f;
1260565fb16STero Kristo }
1270565fb16STero Kristo
128539bf218SLee Jones /**
1290565fb16STero Kristo * _omap3_noncore_dpll_lock - instruct a DPLL to lock and wait for readiness
1300565fb16STero Kristo * @clk: pointer to a DPLL struct clk
1310565fb16STero Kristo *
1320565fb16STero Kristo * Instructs a non-CORE DPLL to lock. Waits for the DPLL to report
1330565fb16STero Kristo * readiness before returning. Will save and restore the DPLL's
1340565fb16STero Kristo * autoidle state across the enable, per the CDP code. If the DPLL
1350565fb16STero Kristo * locked successfully, return 0; if the DPLL did not lock in the time
1360565fb16STero Kristo * allotted, or DPLL3 was passed in, return -EINVAL.
1370565fb16STero Kristo */
_omap3_noncore_dpll_lock(struct clk_hw_omap * clk)1380565fb16STero Kristo static int _omap3_noncore_dpll_lock(struct clk_hw_omap *clk)
1390565fb16STero Kristo {
1400565fb16STero Kristo const struct dpll_data *dd;
1410565fb16STero Kristo u8 ai;
1420565fb16STero Kristo u8 state = 1;
1430565fb16STero Kristo int r = 0;
1440565fb16STero Kristo
145a53ad8efSStephen Boyd pr_debug("clock: locking DPLL %s\n", clk_hw_get_name(&clk->hw));
1460565fb16STero Kristo
1470565fb16STero Kristo dd = clk->dpll_data;
1480565fb16STero Kristo state <<= __ffs(dd->idlest_mask);
1490565fb16STero Kristo
1500565fb16STero Kristo /* Check if already locked */
1516c0afb50STero Kristo if ((ti_clk_ll_ops->clk_readl(&dd->idlest_reg) & dd->idlest_mask) ==
1520565fb16STero Kristo state)
1530565fb16STero Kristo goto done;
1540565fb16STero Kristo
1550565fb16STero Kristo ai = omap3_dpll_autoidle_read(clk);
1560565fb16STero Kristo
1570565fb16STero Kristo if (ai)
1580565fb16STero Kristo omap3_dpll_deny_idle(clk);
1590565fb16STero Kristo
1600565fb16STero Kristo _omap3_dpll_write_clken(clk, DPLL_LOCKED);
1610565fb16STero Kristo
1620565fb16STero Kristo r = _omap3_wait_dpll_status(clk, 1);
1630565fb16STero Kristo
1640565fb16STero Kristo if (ai)
1650565fb16STero Kristo omap3_dpll_allow_idle(clk);
1660565fb16STero Kristo
1670565fb16STero Kristo done:
1680565fb16STero Kristo return r;
1690565fb16STero Kristo }
1700565fb16STero Kristo
171539bf218SLee Jones /**
1720565fb16STero Kristo * _omap3_noncore_dpll_bypass - instruct a DPLL to bypass and wait for readiness
1730565fb16STero Kristo * @clk: pointer to a DPLL struct clk
1740565fb16STero Kristo *
1750565fb16STero Kristo * Instructs a non-CORE DPLL to enter low-power bypass mode. In
1760565fb16STero Kristo * bypass mode, the DPLL's rate is set equal to its parent clock's
1770565fb16STero Kristo * rate. Waits for the DPLL to report readiness before returning.
1780565fb16STero Kristo * Will save and restore the DPLL's autoidle state across the enable,
1790565fb16STero Kristo * per the CDP code. If the DPLL entered bypass mode successfully,
1800565fb16STero Kristo * return 0; if the DPLL did not enter bypass in the time allotted, or
1810565fb16STero Kristo * DPLL3 was passed in, or the DPLL does not support low-power bypass,
1820565fb16STero Kristo * return -EINVAL.
1830565fb16STero Kristo */
_omap3_noncore_dpll_bypass(struct clk_hw_omap * clk)1840565fb16STero Kristo static int _omap3_noncore_dpll_bypass(struct clk_hw_omap *clk)
1850565fb16STero Kristo {
1860565fb16STero Kristo int r;
1870565fb16STero Kristo u8 ai;
1880565fb16STero Kristo
1890565fb16STero Kristo if (!(clk->dpll_data->modes & (1 << DPLL_LOW_POWER_BYPASS)))
1900565fb16STero Kristo return -EINVAL;
1910565fb16STero Kristo
1920565fb16STero Kristo pr_debug("clock: configuring DPLL %s for low-power bypass\n",
193a53ad8efSStephen Boyd clk_hw_get_name(&clk->hw));
1940565fb16STero Kristo
1950565fb16STero Kristo ai = omap3_dpll_autoidle_read(clk);
1960565fb16STero Kristo
1970565fb16STero Kristo _omap3_dpll_write_clken(clk, DPLL_LOW_POWER_BYPASS);
1980565fb16STero Kristo
1990565fb16STero Kristo r = _omap3_wait_dpll_status(clk, 0);
2000565fb16STero Kristo
2010565fb16STero Kristo if (ai)
2020565fb16STero Kristo omap3_dpll_allow_idle(clk);
2030565fb16STero Kristo
2040565fb16STero Kristo return r;
2050565fb16STero Kristo }
2060565fb16STero Kristo
207539bf218SLee Jones /**
2080565fb16STero Kristo * _omap3_noncore_dpll_stop - instruct a DPLL to stop
2090565fb16STero Kristo * @clk: pointer to a DPLL struct clk
2100565fb16STero Kristo *
2110565fb16STero Kristo * Instructs a non-CORE DPLL to enter low-power stop. Will save and
2120565fb16STero Kristo * restore the DPLL's autoidle state across the stop, per the CDP
2130565fb16STero Kristo * code. If DPLL3 was passed in, or the DPLL does not support
2140565fb16STero Kristo * low-power stop, return -EINVAL; otherwise, return 0.
2150565fb16STero Kristo */
_omap3_noncore_dpll_stop(struct clk_hw_omap * clk)2160565fb16STero Kristo static int _omap3_noncore_dpll_stop(struct clk_hw_omap *clk)
2170565fb16STero Kristo {
2180565fb16STero Kristo u8 ai;
2190565fb16STero Kristo
2200565fb16STero Kristo if (!(clk->dpll_data->modes & (1 << DPLL_LOW_POWER_STOP)))
2210565fb16STero Kristo return -EINVAL;
2220565fb16STero Kristo
223a53ad8efSStephen Boyd pr_debug("clock: stopping DPLL %s\n", clk_hw_get_name(&clk->hw));
2240565fb16STero Kristo
2250565fb16STero Kristo ai = omap3_dpll_autoidle_read(clk);
2260565fb16STero Kristo
2270565fb16STero Kristo _omap3_dpll_write_clken(clk, DPLL_LOW_POWER_STOP);
2280565fb16STero Kristo
2290565fb16STero Kristo if (ai)
2300565fb16STero Kristo omap3_dpll_allow_idle(clk);
2310565fb16STero Kristo
2320565fb16STero Kristo return 0;
2330565fb16STero Kristo }
2340565fb16STero Kristo
2350565fb16STero Kristo /**
2360565fb16STero Kristo * _lookup_dco - Lookup DCO used by j-type DPLL
2370565fb16STero Kristo * @clk: pointer to a DPLL struct clk
2380565fb16STero Kristo * @dco: digital control oscillator selector
2390565fb16STero Kristo * @m: DPLL multiplier to set
2400565fb16STero Kristo * @n: DPLL divider to set
2410565fb16STero Kristo *
2420565fb16STero Kristo * See 36xx TRM section 3.5.3.3.3.2 "Type B DPLL (Low-Jitter)"
2430565fb16STero Kristo *
2440565fb16STero Kristo * XXX This code is not needed for 3430/AM35xx; can it be optimized
2450565fb16STero Kristo * out in non-multi-OMAP builds for those chips?
2460565fb16STero Kristo */
_lookup_dco(struct clk_hw_omap * clk,u8 * dco,u16 m,u8 n)2470565fb16STero Kristo static void _lookup_dco(struct clk_hw_omap *clk, u8 *dco, u16 m, u8 n)
2480565fb16STero Kristo {
2490565fb16STero Kristo unsigned long fint, clkinp; /* watch out for overflow */
2500565fb16STero Kristo
251a53ad8efSStephen Boyd clkinp = clk_hw_get_rate(clk_hw_get_parent(&clk->hw));
2520565fb16STero Kristo fint = (clkinp / n) * m;
2530565fb16STero Kristo
2540565fb16STero Kristo if (fint < 1000000000)
2550565fb16STero Kristo *dco = 2;
2560565fb16STero Kristo else
2570565fb16STero Kristo *dco = 4;
2580565fb16STero Kristo }
2590565fb16STero Kristo
2600565fb16STero Kristo /**
2610565fb16STero Kristo * _lookup_sddiv - Calculate sigma delta divider for j-type DPLL
2620565fb16STero Kristo * @clk: pointer to a DPLL struct clk
2630565fb16STero Kristo * @sd_div: target sigma-delta divider
2640565fb16STero Kristo * @m: DPLL multiplier to set
2650565fb16STero Kristo * @n: DPLL divider to set
2660565fb16STero Kristo *
2670565fb16STero Kristo * See 36xx TRM section 3.5.3.3.3.2 "Type B DPLL (Low-Jitter)"
2680565fb16STero Kristo *
2690565fb16STero Kristo * XXX This code is not needed for 3430/AM35xx; can it be optimized
2700565fb16STero Kristo * out in non-multi-OMAP builds for those chips?
2710565fb16STero Kristo */
_lookup_sddiv(struct clk_hw_omap * clk,u8 * sd_div,u16 m,u8 n)2720565fb16STero Kristo static void _lookup_sddiv(struct clk_hw_omap *clk, u8 *sd_div, u16 m, u8 n)
2730565fb16STero Kristo {
2740565fb16STero Kristo unsigned long clkinp, sd; /* watch out for overflow */
2750565fb16STero Kristo int mod1, mod2;
2760565fb16STero Kristo
277a53ad8efSStephen Boyd clkinp = clk_hw_get_rate(clk_hw_get_parent(&clk->hw));
2780565fb16STero Kristo
2790565fb16STero Kristo /*
2800565fb16STero Kristo * target sigma-delta to near 250MHz
2810565fb16STero Kristo * sd = ceil[(m/(n+1)) * (clkinp_MHz / 250)]
2820565fb16STero Kristo */
2830565fb16STero Kristo clkinp /= 100000; /* shift from MHz to 10*Hz for 38.4 and 19.2 */
2840565fb16STero Kristo mod1 = (clkinp * m) % (250 * n);
2850565fb16STero Kristo sd = (clkinp * m) / (250 * n);
2860565fb16STero Kristo mod2 = sd % 10;
2870565fb16STero Kristo sd /= 10;
2880565fb16STero Kristo
2890565fb16STero Kristo if (mod1 || mod2)
2900565fb16STero Kristo sd++;
2910565fb16STero Kristo *sd_div = sd;
2920565fb16STero Kristo }
2930565fb16STero Kristo
294539bf218SLee Jones /**
295*0899431fSDario Binacchi * omap3_noncore_dpll_ssc_program - set spread-spectrum clocking registers
296*0899431fSDario Binacchi * @clk: struct clk * of DPLL to set
297*0899431fSDario Binacchi *
298*0899431fSDario Binacchi * Enable the DPLL spread spectrum clocking if frequency modulation and
299*0899431fSDario Binacchi * frequency spreading have been set, otherwise disable it.
300*0899431fSDario Binacchi */
omap3_noncore_dpll_ssc_program(struct clk_hw_omap * clk)301*0899431fSDario Binacchi static void omap3_noncore_dpll_ssc_program(struct clk_hw_omap *clk)
302*0899431fSDario Binacchi {
303*0899431fSDario Binacchi struct dpll_data *dd = clk->dpll_data;
304*0899431fSDario Binacchi unsigned long ref_rate;
305*0899431fSDario Binacchi u32 v, ctrl, mod_freq_divider, exponent, mantissa;
306*0899431fSDario Binacchi u32 deltam_step, deltam_ceil;
307*0899431fSDario Binacchi
308*0899431fSDario Binacchi ctrl = ti_clk_ll_ops->clk_readl(&dd->control_reg);
309*0899431fSDario Binacchi
310*0899431fSDario Binacchi if (dd->ssc_modfreq && dd->ssc_deltam) {
311*0899431fSDario Binacchi ctrl |= dd->ssc_enable_mask;
312*0899431fSDario Binacchi
313*0899431fSDario Binacchi if (dd->ssc_downspread)
314*0899431fSDario Binacchi ctrl |= dd->ssc_downspread_mask;
315*0899431fSDario Binacchi else
316*0899431fSDario Binacchi ctrl &= ~dd->ssc_downspread_mask;
317*0899431fSDario Binacchi
318*0899431fSDario Binacchi ref_rate = clk_hw_get_rate(dd->clk_ref);
319*0899431fSDario Binacchi mod_freq_divider =
320*0899431fSDario Binacchi (ref_rate / dd->last_rounded_n) / (4 * dd->ssc_modfreq);
321*0899431fSDario Binacchi if (dd->ssc_modfreq > (ref_rate / 70))
322*0899431fSDario Binacchi pr_warn("clock: SSC modulation frequency of DPLL %s greater than %ld\n",
323*0899431fSDario Binacchi __clk_get_name(clk->hw.clk), ref_rate / 70);
324*0899431fSDario Binacchi
325*0899431fSDario Binacchi exponent = 0;
326*0899431fSDario Binacchi mantissa = mod_freq_divider;
327*0899431fSDario Binacchi while ((mantissa > 127) && (exponent < 7)) {
328*0899431fSDario Binacchi exponent++;
329*0899431fSDario Binacchi mantissa /= 2;
330*0899431fSDario Binacchi }
331*0899431fSDario Binacchi if (mantissa > 127)
332*0899431fSDario Binacchi mantissa = 127;
333*0899431fSDario Binacchi
334*0899431fSDario Binacchi v = ti_clk_ll_ops->clk_readl(&dd->ssc_modfreq_reg);
335*0899431fSDario Binacchi v &= ~(dd->ssc_modfreq_mant_mask | dd->ssc_modfreq_exp_mask);
336*0899431fSDario Binacchi v |= mantissa << __ffs(dd->ssc_modfreq_mant_mask);
337*0899431fSDario Binacchi v |= exponent << __ffs(dd->ssc_modfreq_exp_mask);
338*0899431fSDario Binacchi ti_clk_ll_ops->clk_writel(v, &dd->ssc_modfreq_reg);
339*0899431fSDario Binacchi
340*0899431fSDario Binacchi deltam_step = dd->last_rounded_m * dd->ssc_deltam;
341*0899431fSDario Binacchi deltam_step /= 10;
342*0899431fSDario Binacchi if (dd->ssc_downspread)
343*0899431fSDario Binacchi deltam_step /= 2;
344*0899431fSDario Binacchi
345*0899431fSDario Binacchi deltam_step <<= __ffs(dd->ssc_deltam_int_mask);
346*0899431fSDario Binacchi deltam_step /= 100;
347*0899431fSDario Binacchi deltam_step /= mod_freq_divider;
348*0899431fSDario Binacchi if (deltam_step > 0xFFFFF)
349*0899431fSDario Binacchi deltam_step = 0xFFFFF;
350*0899431fSDario Binacchi
351*0899431fSDario Binacchi deltam_ceil = (deltam_step & dd->ssc_deltam_int_mask) >>
352*0899431fSDario Binacchi __ffs(dd->ssc_deltam_int_mask);
353*0899431fSDario Binacchi if (deltam_step & dd->ssc_deltam_frac_mask)
354*0899431fSDario Binacchi deltam_ceil++;
355*0899431fSDario Binacchi
356*0899431fSDario Binacchi if ((dd->ssc_downspread &&
357*0899431fSDario Binacchi ((dd->last_rounded_m - (2 * deltam_ceil)) < 20 ||
358*0899431fSDario Binacchi dd->last_rounded_m > 2045)) ||
359*0899431fSDario Binacchi ((dd->last_rounded_m - deltam_ceil) < 20 ||
360*0899431fSDario Binacchi (dd->last_rounded_m + deltam_ceil) > 2045))
361*0899431fSDario Binacchi pr_warn("clock: SSC multiplier of DPLL %s is out of range\n",
362*0899431fSDario Binacchi __clk_get_name(clk->hw.clk));
363*0899431fSDario Binacchi
364*0899431fSDario Binacchi v = ti_clk_ll_ops->clk_readl(&dd->ssc_deltam_reg);
365*0899431fSDario Binacchi v &= ~(dd->ssc_deltam_int_mask | dd->ssc_deltam_frac_mask);
366*0899431fSDario Binacchi v |= deltam_step << __ffs(dd->ssc_deltam_int_mask |
367*0899431fSDario Binacchi dd->ssc_deltam_frac_mask);
368*0899431fSDario Binacchi ti_clk_ll_ops->clk_writel(v, &dd->ssc_deltam_reg);
369*0899431fSDario Binacchi } else {
370*0899431fSDario Binacchi ctrl &= ~dd->ssc_enable_mask;
371*0899431fSDario Binacchi }
372*0899431fSDario Binacchi
373*0899431fSDario Binacchi ti_clk_ll_ops->clk_writel(ctrl, &dd->control_reg);
374*0899431fSDario Binacchi }
375*0899431fSDario Binacchi
376*0899431fSDario Binacchi /**
377c255f151SDario Binacchi * omap3_noncore_dpll_program - set non-core DPLL M,N values directly
3780565fb16STero Kristo * @clk: struct clk * of DPLL to set
3790565fb16STero Kristo * @freqsel: FREQSEL value to set
3800565fb16STero Kristo *
3810565fb16STero Kristo * Program the DPLL with the last M, N values calculated, and wait for
3820565fb16STero Kristo * the DPLL to lock. Returns -EINVAL upon error, or 0 upon success.
3830565fb16STero Kristo */
omap3_noncore_dpll_program(struct clk_hw_omap * clk,u16 freqsel)3840565fb16STero Kristo static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel)
3850565fb16STero Kristo {
3860565fb16STero Kristo struct dpll_data *dd = clk->dpll_data;
38707ff73a9STero Kristo u8 dco, sd_div, ai = 0;
3880565fb16STero Kristo u32 v;
38907ff73a9STero Kristo bool errata_i810;
3900565fb16STero Kristo
3910565fb16STero Kristo /* 3430 ES2 TRM: 4.7.6.9 DPLL Programming Sequence */
3920565fb16STero Kristo _omap3_noncore_dpll_bypass(clk);
3930565fb16STero Kristo
3940565fb16STero Kristo /*
3950565fb16STero Kristo * Set jitter correction. Jitter correction applicable for OMAP343X
3960565fb16STero Kristo * only since freqsel field is no longer present on other devices.
3970565fb16STero Kristo */
3980565fb16STero Kristo if (ti_clk_get_features()->flags & TI_CLK_DPLL_HAS_FREQSEL) {
3996c0afb50STero Kristo v = ti_clk_ll_ops->clk_readl(&dd->control_reg);
4000565fb16STero Kristo v &= ~dd->freqsel_mask;
4010565fb16STero Kristo v |= freqsel << __ffs(dd->freqsel_mask);
4026c0afb50STero Kristo ti_clk_ll_ops->clk_writel(v, &dd->control_reg);
4030565fb16STero Kristo }
4040565fb16STero Kristo
4050565fb16STero Kristo /* Set DPLL multiplier, divider */
4066c0afb50STero Kristo v = ti_clk_ll_ops->clk_readl(&dd->mult_div1_reg);
4070565fb16STero Kristo
4080565fb16STero Kristo /* Handle Duty Cycle Correction */
4090565fb16STero Kristo if (dd->dcc_mask) {
4100565fb16STero Kristo if (dd->last_rounded_rate >= dd->dcc_rate)
4110565fb16STero Kristo v |= dd->dcc_mask; /* Enable DCC */
4120565fb16STero Kristo else
4130565fb16STero Kristo v &= ~dd->dcc_mask; /* Disable DCC */
4140565fb16STero Kristo }
4150565fb16STero Kristo
4160565fb16STero Kristo v &= ~(dd->mult_mask | dd->div1_mask);
4170565fb16STero Kristo v |= dd->last_rounded_m << __ffs(dd->mult_mask);
4180565fb16STero Kristo v |= (dd->last_rounded_n - 1) << __ffs(dd->div1_mask);
4190565fb16STero Kristo
4200565fb16STero Kristo /* Configure dco and sd_div for dplls that have these fields */
4210565fb16STero Kristo if (dd->dco_mask) {
4220565fb16STero Kristo _lookup_dco(clk, &dco, dd->last_rounded_m, dd->last_rounded_n);
4230565fb16STero Kristo v &= ~(dd->dco_mask);
4240565fb16STero Kristo v |= dco << __ffs(dd->dco_mask);
4250565fb16STero Kristo }
4260565fb16STero Kristo if (dd->sddiv_mask) {
4270565fb16STero Kristo _lookup_sddiv(clk, &sd_div, dd->last_rounded_m,
4280565fb16STero Kristo dd->last_rounded_n);
4290565fb16STero Kristo v &= ~(dd->sddiv_mask);
4300565fb16STero Kristo v |= sd_div << __ffs(dd->sddiv_mask);
4310565fb16STero Kristo }
4320565fb16STero Kristo
43307ff73a9STero Kristo /*
43407ff73a9STero Kristo * Errata i810 - DPLL controller can get stuck while transitioning
43507ff73a9STero Kristo * to a power saving state. Software must ensure the DPLL can not
43607ff73a9STero Kristo * transition to a low power state while changing M/N values.
43707ff73a9STero Kristo * Easiest way to accomplish this is to prevent DPLL autoidle
43807ff73a9STero Kristo * before doing the M/N re-program.
43907ff73a9STero Kristo */
44007ff73a9STero Kristo errata_i810 = ti_clk_get_features()->flags & TI_CLK_ERRATA_I810;
44107ff73a9STero Kristo
44207ff73a9STero Kristo if (errata_i810) {
44307ff73a9STero Kristo ai = omap3_dpll_autoidle_read(clk);
44407ff73a9STero Kristo if (ai) {
44507ff73a9STero Kristo omap3_dpll_deny_idle(clk);
44607ff73a9STero Kristo
44707ff73a9STero Kristo /* OCP barrier */
44807ff73a9STero Kristo omap3_dpll_autoidle_read(clk);
44907ff73a9STero Kristo }
45007ff73a9STero Kristo }
45107ff73a9STero Kristo
4526c0afb50STero Kristo ti_clk_ll_ops->clk_writel(v, &dd->mult_div1_reg);
4530565fb16STero Kristo
4540565fb16STero Kristo /* Set 4X multiplier and low-power mode */
4550565fb16STero Kristo if (dd->m4xen_mask || dd->lpmode_mask) {
4566c0afb50STero Kristo v = ti_clk_ll_ops->clk_readl(&dd->control_reg);
4570565fb16STero Kristo
4580565fb16STero Kristo if (dd->m4xen_mask) {
4590565fb16STero Kristo if (dd->last_rounded_m4xen)
4600565fb16STero Kristo v |= dd->m4xen_mask;
4610565fb16STero Kristo else
4620565fb16STero Kristo v &= ~dd->m4xen_mask;
4630565fb16STero Kristo }
4640565fb16STero Kristo
4650565fb16STero Kristo if (dd->lpmode_mask) {
4660565fb16STero Kristo if (dd->last_rounded_lpmode)
4670565fb16STero Kristo v |= dd->lpmode_mask;
4680565fb16STero Kristo else
4690565fb16STero Kristo v &= ~dd->lpmode_mask;
4700565fb16STero Kristo }
4710565fb16STero Kristo
4726c0afb50STero Kristo ti_clk_ll_ops->clk_writel(v, &dd->control_reg);
4730565fb16STero Kristo }
4740565fb16STero Kristo
475*0899431fSDario Binacchi if (dd->ssc_enable_mask)
476*0899431fSDario Binacchi omap3_noncore_dpll_ssc_program(clk);
477*0899431fSDario Binacchi
4780565fb16STero Kristo /* We let the clock framework set the other output dividers later */
4790565fb16STero Kristo
4800565fb16STero Kristo /* REVISIT: Set ramp-up delay? */
4810565fb16STero Kristo
4820565fb16STero Kristo _omap3_noncore_dpll_lock(clk);
4830565fb16STero Kristo
48407ff73a9STero Kristo if (errata_i810 && ai)
48507ff73a9STero Kristo omap3_dpll_allow_idle(clk);
48607ff73a9STero Kristo
4870565fb16STero Kristo return 0;
4880565fb16STero Kristo }
4890565fb16STero Kristo
4900565fb16STero Kristo /* Public functions */
4910565fb16STero Kristo
4920565fb16STero Kristo /**
4930565fb16STero Kristo * omap3_dpll_recalc - recalculate DPLL rate
494539bf218SLee Jones * @hw: struct clk_hw containing the DPLL struct clk
495539bf218SLee Jones * @parent_rate: clock rate of the DPLL parent
4960565fb16STero Kristo *
4970565fb16STero Kristo * Recalculate and propagate the DPLL rate.
4980565fb16STero Kristo */
omap3_dpll_recalc(struct clk_hw * hw,unsigned long parent_rate)4990565fb16STero Kristo unsigned long omap3_dpll_recalc(struct clk_hw *hw, unsigned long parent_rate)
5000565fb16STero Kristo {
5010565fb16STero Kristo struct clk_hw_omap *clk = to_clk_hw_omap(hw);
5020565fb16STero Kristo
5030565fb16STero Kristo return omap2_get_dpll_rate(clk);
5040565fb16STero Kristo }
5050565fb16STero Kristo
5060565fb16STero Kristo /* Non-CORE DPLL (e.g., DPLLs that do not control SDRC) clock functions */
5070565fb16STero Kristo
5080565fb16STero Kristo /**
5090565fb16STero Kristo * omap3_noncore_dpll_enable - instruct a DPLL to enter bypass or lock mode
510539bf218SLee Jones * @hw: struct clk_hw containing then pointer to a DPLL struct clk
5110565fb16STero Kristo *
5120565fb16STero Kristo * Instructs a non-CORE DPLL to enable, e.g., to enter bypass or lock.
5130565fb16STero Kristo * The choice of modes depends on the DPLL's programmed rate: if it is
5140565fb16STero Kristo * the same as the DPLL's parent clock, it will enter bypass;
5150565fb16STero Kristo * otherwise, it will enter lock. This code will wait for the DPLL to
5160565fb16STero Kristo * indicate readiness before returning, unless the DPLL takes too long
5170565fb16STero Kristo * to enter the target state. Intended to be used as the struct clk's
5180565fb16STero Kristo * enable function. If DPLL3 was passed in, or the DPLL does not
5190565fb16STero Kristo * support low-power stop, or if the DPLL took too long to enter
5200565fb16STero Kristo * bypass or lock, return -EINVAL; otherwise, return 0.
5210565fb16STero Kristo */
omap3_noncore_dpll_enable(struct clk_hw * hw)5220565fb16STero Kristo int omap3_noncore_dpll_enable(struct clk_hw *hw)
5230565fb16STero Kristo {
5240565fb16STero Kristo struct clk_hw_omap *clk = to_clk_hw_omap(hw);
5250565fb16STero Kristo int r;
5260565fb16STero Kristo struct dpll_data *dd;
5270565fb16STero Kristo struct clk_hw *parent;
5280565fb16STero Kristo
5290565fb16STero Kristo dd = clk->dpll_data;
5300565fb16STero Kristo if (!dd)
5310565fb16STero Kristo return -EINVAL;
5320565fb16STero Kristo
5330565fb16STero Kristo if (clk->clkdm) {
5340565fb16STero Kristo r = ti_clk_ll_ops->clkdm_clk_enable(clk->clkdm, hw->clk);
5350565fb16STero Kristo if (r) {
5360565fb16STero Kristo WARN(1,
5370565fb16STero Kristo "%s: could not enable %s's clockdomain %s: %d\n",
538a53ad8efSStephen Boyd __func__, clk_hw_get_name(hw),
5390565fb16STero Kristo clk->clkdm_name, r);
5400565fb16STero Kristo return r;
5410565fb16STero Kristo }
5420565fb16STero Kristo }
5430565fb16STero Kristo
544a53ad8efSStephen Boyd parent = clk_hw_get_parent(hw);
5450565fb16STero Kristo
546b6f51284STero Kristo if (clk_hw_get_rate(hw) == clk_hw_get_rate(dd->clk_bypass)) {
547b6f51284STero Kristo WARN_ON(parent != dd->clk_bypass);
5480565fb16STero Kristo r = _omap3_noncore_dpll_bypass(clk);
5490565fb16STero Kristo } else {
550b6f51284STero Kristo WARN_ON(parent != dd->clk_ref);
5510565fb16STero Kristo r = _omap3_noncore_dpll_lock(clk);
5520565fb16STero Kristo }
5530565fb16STero Kristo
5540565fb16STero Kristo return r;
5550565fb16STero Kristo }
5560565fb16STero Kristo
5570565fb16STero Kristo /**
5580565fb16STero Kristo * omap3_noncore_dpll_disable - instruct a DPLL to enter low-power stop
559539bf218SLee Jones * @hw: struct clk_hw containing then pointer to a DPLL struct clk
5600565fb16STero Kristo *
5610565fb16STero Kristo * Instructs a non-CORE DPLL to enter low-power stop. This function is
5620565fb16STero Kristo * intended for use in struct clkops. No return value.
5630565fb16STero Kristo */
omap3_noncore_dpll_disable(struct clk_hw * hw)5640565fb16STero Kristo void omap3_noncore_dpll_disable(struct clk_hw *hw)
5650565fb16STero Kristo {
5660565fb16STero Kristo struct clk_hw_omap *clk = to_clk_hw_omap(hw);
5670565fb16STero Kristo
5680565fb16STero Kristo _omap3_noncore_dpll_stop(clk);
5690565fb16STero Kristo if (clk->clkdm)
5700565fb16STero Kristo ti_clk_ll_ops->clkdm_clk_disable(clk->clkdm, hw->clk);
5710565fb16STero Kristo }
5720565fb16STero Kristo
5730565fb16STero Kristo /* Non-CORE DPLL rate set code */
5740565fb16STero Kristo
5750565fb16STero Kristo /**
5760565fb16STero Kristo * omap3_noncore_dpll_determine_rate - determine rate for a DPLL
5770565fb16STero Kristo * @hw: pointer to the clock to determine rate for
5784d341056SStephen Boyd * @req: target rate request
5790565fb16STero Kristo *
5800565fb16STero Kristo * Determines which DPLL mode to use for reaching a desired target rate.
5810565fb16STero Kristo * Checks whether the DPLL shall be in bypass or locked mode, and if
5820565fb16STero Kristo * locked, calculates the M,N values for the DPLL via round-rate.
5834d341056SStephen Boyd * Returns a 0 on success, negative error value in failure.
5840565fb16STero Kristo */
omap3_noncore_dpll_determine_rate(struct clk_hw * hw,struct clk_rate_request * req)5854d341056SStephen Boyd int omap3_noncore_dpll_determine_rate(struct clk_hw *hw,
5864d341056SStephen Boyd struct clk_rate_request *req)
5870565fb16STero Kristo {
5880565fb16STero Kristo struct clk_hw_omap *clk = to_clk_hw_omap(hw);
5890565fb16STero Kristo struct dpll_data *dd;
5900565fb16STero Kristo
5914d341056SStephen Boyd if (!req->rate)
5920565fb16STero Kristo return -EINVAL;
5930565fb16STero Kristo
5940565fb16STero Kristo dd = clk->dpll_data;
5950565fb16STero Kristo if (!dd)
5960565fb16STero Kristo return -EINVAL;
5970565fb16STero Kristo
598b6f51284STero Kristo if (clk_hw_get_rate(dd->clk_bypass) == req->rate &&
5990565fb16STero Kristo (dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
600b6f51284STero Kristo req->best_parent_hw = dd->clk_bypass;
6010565fb16STero Kristo } else {
6024d341056SStephen Boyd req->rate = omap2_dpll_round_rate(hw, req->rate,
6034d341056SStephen Boyd &req->best_parent_rate);
604b6f51284STero Kristo req->best_parent_hw = dd->clk_ref;
6050565fb16STero Kristo }
6060565fb16STero Kristo
6074d341056SStephen Boyd req->best_parent_rate = req->rate;
6080565fb16STero Kristo
6094d341056SStephen Boyd return 0;
6100565fb16STero Kristo }
6110565fb16STero Kristo
6120565fb16STero Kristo /**
6130565fb16STero Kristo * omap3_noncore_dpll_set_parent - set parent for a DPLL clock
6140565fb16STero Kristo * @hw: pointer to the clock to set parent for
6150565fb16STero Kristo * @index: parent index to select
6160565fb16STero Kristo *
6170565fb16STero Kristo * Sets parent for a DPLL clock. This sets the DPLL into bypass or
6180565fb16STero Kristo * locked mode. Returns 0 with success, negative error value otherwise.
6190565fb16STero Kristo */
omap3_noncore_dpll_set_parent(struct clk_hw * hw,u8 index)6200565fb16STero Kristo int omap3_noncore_dpll_set_parent(struct clk_hw *hw, u8 index)
6210565fb16STero Kristo {
6220565fb16STero Kristo struct clk_hw_omap *clk = to_clk_hw_omap(hw);
6230565fb16STero Kristo int ret;
6240565fb16STero Kristo
6250565fb16STero Kristo if (!hw)
6260565fb16STero Kristo return -EINVAL;
6270565fb16STero Kristo
6280565fb16STero Kristo if (index)
6290565fb16STero Kristo ret = _omap3_noncore_dpll_bypass(clk);
6300565fb16STero Kristo else
6310565fb16STero Kristo ret = _omap3_noncore_dpll_lock(clk);
6320565fb16STero Kristo
6330565fb16STero Kristo return ret;
6340565fb16STero Kristo }
6350565fb16STero Kristo
6360565fb16STero Kristo /**
6370565fb16STero Kristo * omap3_noncore_dpll_set_rate - set rate for a DPLL clock
6380565fb16STero Kristo * @hw: pointer to the clock to set parent for
6390565fb16STero Kristo * @rate: target rate for the clock
6400565fb16STero Kristo * @parent_rate: rate of the parent clock
6410565fb16STero Kristo *
6420565fb16STero Kristo * Sets rate for a DPLL clock. First checks if the clock parent is
6430565fb16STero Kristo * reference clock (in bypass mode, the rate of the clock can't be
6440565fb16STero Kristo * changed) and proceeds with the rate change operation. Returns 0
6450565fb16STero Kristo * with success, negative error value otherwise.
6460565fb16STero Kristo */
omap3_noncore_dpll_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)6470565fb16STero Kristo int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
6480565fb16STero Kristo unsigned long parent_rate)
6490565fb16STero Kristo {
6500565fb16STero Kristo struct clk_hw_omap *clk = to_clk_hw_omap(hw);
6510565fb16STero Kristo struct dpll_data *dd;
6520565fb16STero Kristo u16 freqsel = 0;
6530565fb16STero Kristo int ret;
6540565fb16STero Kristo
6550565fb16STero Kristo if (!hw || !rate)
6560565fb16STero Kristo return -EINVAL;
6570565fb16STero Kristo
6580565fb16STero Kristo dd = clk->dpll_data;
6590565fb16STero Kristo if (!dd)
6600565fb16STero Kristo return -EINVAL;
6610565fb16STero Kristo
662b6f51284STero Kristo if (clk_hw_get_parent(hw) != dd->clk_ref)
6630565fb16STero Kristo return -EINVAL;
6640565fb16STero Kristo
6650565fb16STero Kristo if (dd->last_rounded_rate == 0)
6660565fb16STero Kristo return -EINVAL;
6670565fb16STero Kristo
6680565fb16STero Kristo /* Freqsel is available only on OMAP343X devices */
6690565fb16STero Kristo if (ti_clk_get_features()->flags & TI_CLK_DPLL_HAS_FREQSEL) {
6700565fb16STero Kristo freqsel = _omap3_dpll_compute_freqsel(clk, dd->last_rounded_n);
6710565fb16STero Kristo WARN_ON(!freqsel);
6720565fb16STero Kristo }
6730565fb16STero Kristo
6740565fb16STero Kristo pr_debug("%s: %s: set rate: locking rate to %lu.\n", __func__,
675a53ad8efSStephen Boyd clk_hw_get_name(hw), rate);
6760565fb16STero Kristo
6770565fb16STero Kristo ret = omap3_noncore_dpll_program(clk, freqsel);
6780565fb16STero Kristo
6790565fb16STero Kristo return ret;
6800565fb16STero Kristo }
6810565fb16STero Kristo
6820565fb16STero Kristo /**
6830565fb16STero Kristo * omap3_noncore_dpll_set_rate_and_parent - set rate and parent for a DPLL clock
6840565fb16STero Kristo * @hw: pointer to the clock to set rate and parent for
6850565fb16STero Kristo * @rate: target rate for the DPLL
6860565fb16STero Kristo * @parent_rate: clock rate of the DPLL parent
6870565fb16STero Kristo * @index: new parent index for the DPLL, 0 - reference, 1 - bypass
6880565fb16STero Kristo *
6890565fb16STero Kristo * Sets rate and parent for a DPLL clock. If new parent is the bypass
6900565fb16STero Kristo * clock, only selects the parent. Otherwise proceeds with a rate
6910565fb16STero Kristo * change, as this will effectively also change the parent as the
6920565fb16STero Kristo * DPLL is put into locked mode. Returns 0 with success, negative error
6930565fb16STero Kristo * value otherwise.
6940565fb16STero Kristo */
omap3_noncore_dpll_set_rate_and_parent(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate,u8 index)6950565fb16STero Kristo int omap3_noncore_dpll_set_rate_and_parent(struct clk_hw *hw,
6960565fb16STero Kristo unsigned long rate,
6970565fb16STero Kristo unsigned long parent_rate,
6980565fb16STero Kristo u8 index)
6990565fb16STero Kristo {
7000565fb16STero Kristo int ret;
7010565fb16STero Kristo
7020565fb16STero Kristo if (!hw || !rate)
7030565fb16STero Kristo return -EINVAL;
7040565fb16STero Kristo
7050565fb16STero Kristo /*
7060565fb16STero Kristo * clk-ref at index[0], in which case we only need to set rate,
7070565fb16STero Kristo * the parent will be changed automatically with the lock sequence.
7080565fb16STero Kristo * With clk-bypass case we only need to change parent.
7090565fb16STero Kristo */
7100565fb16STero Kristo if (index)
7110565fb16STero Kristo ret = omap3_noncore_dpll_set_parent(hw, index);
7120565fb16STero Kristo else
7130565fb16STero Kristo ret = omap3_noncore_dpll_set_rate(hw, rate, parent_rate);
7140565fb16STero Kristo
7150565fb16STero Kristo return ret;
7160565fb16STero Kristo }
7170565fb16STero Kristo
7180565fb16STero Kristo /* DPLL autoidle read/set code */
7190565fb16STero Kristo
7200565fb16STero Kristo /**
7210565fb16STero Kristo * omap3_dpll_autoidle_read - read a DPLL's autoidle bits
7220565fb16STero Kristo * @clk: struct clk * of the DPLL to read
7230565fb16STero Kristo *
7240565fb16STero Kristo * Return the DPLL's autoidle bits, shifted down to bit 0. Returns
7250565fb16STero Kristo * -EINVAL if passed a null pointer or if the struct clk does not
7260565fb16STero Kristo * appear to refer to a DPLL.
7270565fb16STero Kristo */
omap3_dpll_autoidle_read(struct clk_hw_omap * clk)7280565fb16STero Kristo static u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk)
7290565fb16STero Kristo {
7300565fb16STero Kristo const struct dpll_data *dd;
7310565fb16STero Kristo u32 v;
7320565fb16STero Kristo
7330565fb16STero Kristo if (!clk || !clk->dpll_data)
7340565fb16STero Kristo return -EINVAL;
7350565fb16STero Kristo
7360565fb16STero Kristo dd = clk->dpll_data;
7370565fb16STero Kristo
7386c0afb50STero Kristo if (!dd->autoidle_mask)
7390565fb16STero Kristo return -EINVAL;
7400565fb16STero Kristo
7416c0afb50STero Kristo v = ti_clk_ll_ops->clk_readl(&dd->autoidle_reg);
7420565fb16STero Kristo v &= dd->autoidle_mask;
7430565fb16STero Kristo v >>= __ffs(dd->autoidle_mask);
7440565fb16STero Kristo
7450565fb16STero Kristo return v;
7460565fb16STero Kristo }
7470565fb16STero Kristo
7480565fb16STero Kristo /**
7490565fb16STero Kristo * omap3_dpll_allow_idle - enable DPLL autoidle bits
7500565fb16STero Kristo * @clk: struct clk * of the DPLL to operate on
7510565fb16STero Kristo *
7520565fb16STero Kristo * Enable DPLL automatic idle control. This automatic idle mode
7530565fb16STero Kristo * switching takes effect only when the DPLL is locked, at least on
7540565fb16STero Kristo * OMAP3430. The DPLL will enter low-power stop when its downstream
7550565fb16STero Kristo * clocks are gated. No return value.
7560565fb16STero Kristo */
omap3_dpll_allow_idle(struct clk_hw_omap * clk)7570565fb16STero Kristo static void omap3_dpll_allow_idle(struct clk_hw_omap *clk)
7580565fb16STero Kristo {
7590565fb16STero Kristo const struct dpll_data *dd;
7600565fb16STero Kristo u32 v;
7610565fb16STero Kristo
7620565fb16STero Kristo if (!clk || !clk->dpll_data)
7630565fb16STero Kristo return;
7640565fb16STero Kristo
7650565fb16STero Kristo dd = clk->dpll_data;
7660565fb16STero Kristo
7676c0afb50STero Kristo if (!dd->autoidle_mask)
7680565fb16STero Kristo return;
7690565fb16STero Kristo
7700565fb16STero Kristo /*
7710565fb16STero Kristo * REVISIT: CORE DPLL can optionally enter low-power bypass
7720565fb16STero Kristo * by writing 0x5 instead of 0x1. Add some mechanism to
7730565fb16STero Kristo * optionally enter this mode.
7740565fb16STero Kristo */
7756c0afb50STero Kristo v = ti_clk_ll_ops->clk_readl(&dd->autoidle_reg);
7760565fb16STero Kristo v &= ~dd->autoidle_mask;
7770565fb16STero Kristo v |= DPLL_AUTOIDLE_LOW_POWER_STOP << __ffs(dd->autoidle_mask);
7786c0afb50STero Kristo ti_clk_ll_ops->clk_writel(v, &dd->autoidle_reg);
7790565fb16STero Kristo }
7800565fb16STero Kristo
7810565fb16STero Kristo /**
7820565fb16STero Kristo * omap3_dpll_deny_idle - prevent DPLL from automatically idling
7830565fb16STero Kristo * @clk: struct clk * of the DPLL to operate on
7840565fb16STero Kristo *
7850565fb16STero Kristo * Disable DPLL automatic idle control. No return value.
7860565fb16STero Kristo */
omap3_dpll_deny_idle(struct clk_hw_omap * clk)7870565fb16STero Kristo static void omap3_dpll_deny_idle(struct clk_hw_omap *clk)
7880565fb16STero Kristo {
7890565fb16STero Kristo const struct dpll_data *dd;
7900565fb16STero Kristo u32 v;
7910565fb16STero Kristo
7920565fb16STero Kristo if (!clk || !clk->dpll_data)
7930565fb16STero Kristo return;
7940565fb16STero Kristo
7950565fb16STero Kristo dd = clk->dpll_data;
7960565fb16STero Kristo
7976c0afb50STero Kristo if (!dd->autoidle_mask)
7980565fb16STero Kristo return;
7990565fb16STero Kristo
8006c0afb50STero Kristo v = ti_clk_ll_ops->clk_readl(&dd->autoidle_reg);
8010565fb16STero Kristo v &= ~dd->autoidle_mask;
8020565fb16STero Kristo v |= DPLL_AUTOIDLE_DISABLE << __ffs(dd->autoidle_mask);
8036c0afb50STero Kristo ti_clk_ll_ops->clk_writel(v, &dd->autoidle_reg);
8040565fb16STero Kristo }
8050565fb16STero Kristo
8060565fb16STero Kristo /* Clock control for DPLL outputs */
8070565fb16STero Kristo
8080565fb16STero Kristo /* Find the parent DPLL for the given clkoutx2 clock */
omap3_find_clkoutx2_dpll(struct clk_hw * hw)8090565fb16STero Kristo static struct clk_hw_omap *omap3_find_clkoutx2_dpll(struct clk_hw *hw)
8100565fb16STero Kristo {
8110565fb16STero Kristo struct clk_hw_omap *pclk = NULL;
8120565fb16STero Kristo
8130565fb16STero Kristo /* Walk up the parents of clk, looking for a DPLL */
8140565fb16STero Kristo do {
8150565fb16STero Kristo do {
816a53ad8efSStephen Boyd hw = clk_hw_get_parent(hw);
8178aa09cf3STero Kristo } while (hw && (!omap2_clk_is_hw_omap(hw)));
8180565fb16STero Kristo if (!hw)
8190565fb16STero Kristo break;
8200565fb16STero Kristo pclk = to_clk_hw_omap(hw);
8210565fb16STero Kristo } while (pclk && !pclk->dpll_data);
8220565fb16STero Kristo
8230565fb16STero Kristo /* clk does not have a DPLL as a parent? error in the clock data */
8240565fb16STero Kristo if (!pclk) {
8250565fb16STero Kristo WARN_ON(1);
8260565fb16STero Kristo return NULL;
8270565fb16STero Kristo }
8280565fb16STero Kristo
8290565fb16STero Kristo return pclk;
8300565fb16STero Kristo }
8310565fb16STero Kristo
8320565fb16STero Kristo /**
8330565fb16STero Kristo * omap3_clkoutx2_recalc - recalculate DPLL X2 output virtual clock rate
834539bf218SLee Jones * @hw: pointer struct clk_hw
835539bf218SLee Jones * @parent_rate: clock rate of the DPLL parent
8360565fb16STero Kristo *
8370565fb16STero Kristo * Using parent clock DPLL data, look up DPLL state. If locked, set our
8380565fb16STero Kristo * rate to the dpll_clk * 2; otherwise, just use dpll_clk.
8390565fb16STero Kristo */
omap3_clkoutx2_recalc(struct clk_hw * hw,unsigned long parent_rate)8400565fb16STero Kristo unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
8410565fb16STero Kristo unsigned long parent_rate)
8420565fb16STero Kristo {
8430565fb16STero Kristo const struct dpll_data *dd;
8440565fb16STero Kristo unsigned long rate;
8450565fb16STero Kristo u32 v;
8460565fb16STero Kristo struct clk_hw_omap *pclk = NULL;
8470565fb16STero Kristo
8480565fb16STero Kristo if (!parent_rate)
8490565fb16STero Kristo return 0;
8500565fb16STero Kristo
8510565fb16STero Kristo pclk = omap3_find_clkoutx2_dpll(hw);
8520565fb16STero Kristo
8530565fb16STero Kristo if (!pclk)
8540565fb16STero Kristo return 0;
8550565fb16STero Kristo
8560565fb16STero Kristo dd = pclk->dpll_data;
8570565fb16STero Kristo
8580565fb16STero Kristo WARN_ON(!dd->enable_mask);
8590565fb16STero Kristo
8606c0afb50STero Kristo v = ti_clk_ll_ops->clk_readl(&dd->control_reg) & dd->enable_mask;
8610565fb16STero Kristo v >>= __ffs(dd->enable_mask);
8620565fb16STero Kristo if ((v != OMAP3XXX_EN_DPLL_LOCKED) || (dd->flags & DPLL_J_TYPE))
8630565fb16STero Kristo rate = parent_rate;
8640565fb16STero Kristo else
8650565fb16STero Kristo rate = parent_rate * 2;
8660565fb16STero Kristo return rate;
8670565fb16STero Kristo }
8680565fb16STero Kristo
869d6e7bbc1SRuss Dill /**
870d6e7bbc1SRuss Dill * omap3_core_dpll_save_context - Save the m and n values of the divider
871d6e7bbc1SRuss Dill * @hw: pointer struct clk_hw
872d6e7bbc1SRuss Dill *
873d6e7bbc1SRuss Dill * Before the dpll registers are lost save the last rounded rate m and n
874d6e7bbc1SRuss Dill * and the enable mask.
875d6e7bbc1SRuss Dill */
omap3_core_dpll_save_context(struct clk_hw * hw)876d6e7bbc1SRuss Dill int omap3_core_dpll_save_context(struct clk_hw *hw)
877d6e7bbc1SRuss Dill {
878d6e7bbc1SRuss Dill struct clk_hw_omap *clk = to_clk_hw_omap(hw);
879d6e7bbc1SRuss Dill struct dpll_data *dd;
880d6e7bbc1SRuss Dill u32 v;
881d6e7bbc1SRuss Dill
882d6e7bbc1SRuss Dill dd = clk->dpll_data;
883d6e7bbc1SRuss Dill
884d6e7bbc1SRuss Dill v = ti_clk_ll_ops->clk_readl(&dd->control_reg);
885d6e7bbc1SRuss Dill clk->context = (v & dd->enable_mask) >> __ffs(dd->enable_mask);
886d6e7bbc1SRuss Dill
887d6e7bbc1SRuss Dill if (clk->context == DPLL_LOCKED) {
888d6e7bbc1SRuss Dill v = ti_clk_ll_ops->clk_readl(&dd->mult_div1_reg);
889d6e7bbc1SRuss Dill dd->last_rounded_m = (v & dd->mult_mask) >>
890d6e7bbc1SRuss Dill __ffs(dd->mult_mask);
891d6e7bbc1SRuss Dill dd->last_rounded_n = ((v & dd->div1_mask) >>
892d6e7bbc1SRuss Dill __ffs(dd->div1_mask)) + 1;
893d6e7bbc1SRuss Dill }
894d6e7bbc1SRuss Dill
895d6e7bbc1SRuss Dill return 0;
896d6e7bbc1SRuss Dill }
897d6e7bbc1SRuss Dill
898d6e7bbc1SRuss Dill /**
899d6e7bbc1SRuss Dill * omap3_core_dpll_restore_context - restore the m and n values of the divider
900d6e7bbc1SRuss Dill * @hw: pointer struct clk_hw
901d6e7bbc1SRuss Dill *
902d6e7bbc1SRuss Dill * Restore the last rounded rate m and n
903d6e7bbc1SRuss Dill * and the enable mask.
904d6e7bbc1SRuss Dill */
omap3_core_dpll_restore_context(struct clk_hw * hw)905d6e7bbc1SRuss Dill void omap3_core_dpll_restore_context(struct clk_hw *hw)
906d6e7bbc1SRuss Dill {
907d6e7bbc1SRuss Dill struct clk_hw_omap *clk = to_clk_hw_omap(hw);
908d6e7bbc1SRuss Dill const struct dpll_data *dd;
909d6e7bbc1SRuss Dill u32 v;
910d6e7bbc1SRuss Dill
911d6e7bbc1SRuss Dill dd = clk->dpll_data;
912d6e7bbc1SRuss Dill
913d6e7bbc1SRuss Dill if (clk->context == DPLL_LOCKED) {
914d6e7bbc1SRuss Dill _omap3_dpll_write_clken(clk, 0x4);
915d6e7bbc1SRuss Dill _omap3_wait_dpll_status(clk, 0);
916d6e7bbc1SRuss Dill
917d6e7bbc1SRuss Dill v = ti_clk_ll_ops->clk_readl(&dd->mult_div1_reg);
918d6e7bbc1SRuss Dill v &= ~(dd->mult_mask | dd->div1_mask);
919d6e7bbc1SRuss Dill v |= dd->last_rounded_m << __ffs(dd->mult_mask);
920d6e7bbc1SRuss Dill v |= (dd->last_rounded_n - 1) << __ffs(dd->div1_mask);
921d6e7bbc1SRuss Dill ti_clk_ll_ops->clk_writel(v, &dd->mult_div1_reg);
922d6e7bbc1SRuss Dill
923d6e7bbc1SRuss Dill _omap3_dpll_write_clken(clk, DPLL_LOCKED);
924d6e7bbc1SRuss Dill _omap3_wait_dpll_status(clk, 1);
925d6e7bbc1SRuss Dill } else {
926d6e7bbc1SRuss Dill _omap3_dpll_write_clken(clk, clk->context);
927d6e7bbc1SRuss Dill }
928d6e7bbc1SRuss Dill }
929d6e7bbc1SRuss Dill
930d6e7bbc1SRuss Dill /**
931d6e7bbc1SRuss Dill * omap3_non_core_dpll_save_context - Save the m and n values of the divider
932d6e7bbc1SRuss Dill * @hw: pointer struct clk_hw
933d6e7bbc1SRuss Dill *
934d6e7bbc1SRuss Dill * Before the dpll registers are lost save the last rounded rate m and n
935d6e7bbc1SRuss Dill * and the enable mask.
936d6e7bbc1SRuss Dill */
omap3_noncore_dpll_save_context(struct clk_hw * hw)937d6e7bbc1SRuss Dill int omap3_noncore_dpll_save_context(struct clk_hw *hw)
938d6e7bbc1SRuss Dill {
939d6e7bbc1SRuss Dill struct clk_hw_omap *clk = to_clk_hw_omap(hw);
940d6e7bbc1SRuss Dill struct dpll_data *dd;
941d6e7bbc1SRuss Dill u32 v;
942d6e7bbc1SRuss Dill
943d6e7bbc1SRuss Dill dd = clk->dpll_data;
944d6e7bbc1SRuss Dill
945d6e7bbc1SRuss Dill v = ti_clk_ll_ops->clk_readl(&dd->control_reg);
946d6e7bbc1SRuss Dill clk->context = (v & dd->enable_mask) >> __ffs(dd->enable_mask);
947d6e7bbc1SRuss Dill
948d6e7bbc1SRuss Dill if (clk->context == DPLL_LOCKED) {
949d6e7bbc1SRuss Dill v = ti_clk_ll_ops->clk_readl(&dd->mult_div1_reg);
950d6e7bbc1SRuss Dill dd->last_rounded_m = (v & dd->mult_mask) >>
951d6e7bbc1SRuss Dill __ffs(dd->mult_mask);
952d6e7bbc1SRuss Dill dd->last_rounded_n = ((v & dd->div1_mask) >>
953d6e7bbc1SRuss Dill __ffs(dd->div1_mask)) + 1;
954d6e7bbc1SRuss Dill }
955d6e7bbc1SRuss Dill
956d6e7bbc1SRuss Dill return 0;
957d6e7bbc1SRuss Dill }
958d6e7bbc1SRuss Dill
959d6e7bbc1SRuss Dill /**
960d6e7bbc1SRuss Dill * omap3_core_dpll_restore_context - restore the m and n values of the divider
961d6e7bbc1SRuss Dill * @hw: pointer struct clk_hw
962d6e7bbc1SRuss Dill *
963d6e7bbc1SRuss Dill * Restore the last rounded rate m and n
964d6e7bbc1SRuss Dill * and the enable mask.
965d6e7bbc1SRuss Dill */
omap3_noncore_dpll_restore_context(struct clk_hw * hw)966d6e7bbc1SRuss Dill void omap3_noncore_dpll_restore_context(struct clk_hw *hw)
967d6e7bbc1SRuss Dill {
968d6e7bbc1SRuss Dill struct clk_hw_omap *clk = to_clk_hw_omap(hw);
969d6e7bbc1SRuss Dill const struct dpll_data *dd;
970d6e7bbc1SRuss Dill u32 ctrl, mult_div1;
971d6e7bbc1SRuss Dill
972d6e7bbc1SRuss Dill dd = clk->dpll_data;
973d6e7bbc1SRuss Dill
974d6e7bbc1SRuss Dill ctrl = ti_clk_ll_ops->clk_readl(&dd->control_reg);
975d6e7bbc1SRuss Dill mult_div1 = ti_clk_ll_ops->clk_readl(&dd->mult_div1_reg);
976d6e7bbc1SRuss Dill
977d6e7bbc1SRuss Dill if (clk->context == ((ctrl & dd->enable_mask) >>
978d6e7bbc1SRuss Dill __ffs(dd->enable_mask)) &&
979d6e7bbc1SRuss Dill dd->last_rounded_m == ((mult_div1 & dd->mult_mask) >>
980d6e7bbc1SRuss Dill __ffs(dd->mult_mask)) &&
981d6e7bbc1SRuss Dill dd->last_rounded_n == ((mult_div1 & dd->div1_mask) >>
982d6e7bbc1SRuss Dill __ffs(dd->div1_mask)) + 1) {
983d6e7bbc1SRuss Dill /* nothing to be done */
984d6e7bbc1SRuss Dill return;
985d6e7bbc1SRuss Dill }
986d6e7bbc1SRuss Dill
987d6e7bbc1SRuss Dill if (clk->context == DPLL_LOCKED)
988d6e7bbc1SRuss Dill omap3_noncore_dpll_program(clk, 0);
989d6e7bbc1SRuss Dill else
990d6e7bbc1SRuss Dill _omap3_dpll_write_clken(clk, clk->context);
991d6e7bbc1SRuss Dill }
992d6e7bbc1SRuss Dill
9930565fb16STero Kristo /* OMAP3/4 non-CORE DPLL clkops */
9940565fb16STero Kristo const struct clk_hw_omap_ops clkhwops_omap3_dpll = {
9950565fb16STero Kristo .allow_idle = omap3_dpll_allow_idle,
9960565fb16STero Kristo .deny_idle = omap3_dpll_deny_idle,
9970565fb16STero Kristo };
9980565fb16STero Kristo
9990565fb16STero Kristo /**
10000565fb16STero Kristo * omap3_dpll4_set_rate - set rate for omap3 per-dpll
10010565fb16STero Kristo * @hw: clock to change
10020565fb16STero Kristo * @rate: target rate for clock
1003539bf218SLee Jones * @parent_rate: clock rate of the DPLL parent
10040565fb16STero Kristo *
10050565fb16STero Kristo * Check if the current SoC supports the per-dpll reprogram operation
10060565fb16STero Kristo * or not, and then do the rate change if supported. Returns -EINVAL
10070565fb16STero Kristo * if not supported, 0 for success, and potential error codes from the
10080565fb16STero Kristo * clock rate change.
10090565fb16STero Kristo */
omap3_dpll4_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)10100565fb16STero Kristo int omap3_dpll4_set_rate(struct clk_hw *hw, unsigned long rate,
10110565fb16STero Kristo unsigned long parent_rate)
10120565fb16STero Kristo {
10130565fb16STero Kristo /*
10140565fb16STero Kristo * According to the 12-5 CDP code from TI, "Limitation 2.5"
10150565fb16STero Kristo * on 3430ES1 prevents us from changing DPLL multipliers or dividers
10160565fb16STero Kristo * on DPLL4.
10170565fb16STero Kristo */
10180565fb16STero Kristo if (ti_clk_get_features()->flags & TI_CLK_DPLL4_DENY_REPROGRAM) {
10190565fb16STero Kristo pr_err("clock: DPLL4 cannot change rate due to silicon 'Limitation 2.5' on 3430ES1.\n");
10200565fb16STero Kristo return -EINVAL;
10210565fb16STero Kristo }
10220565fb16STero Kristo
10230565fb16STero Kristo return omap3_noncore_dpll_set_rate(hw, rate, parent_rate);
10240565fb16STero Kristo }
10250565fb16STero Kristo
10260565fb16STero Kristo /**
10270565fb16STero Kristo * omap3_dpll4_set_rate_and_parent - set rate and parent for omap3 per-dpll
10280565fb16STero Kristo * @hw: clock to change
10290565fb16STero Kristo * @rate: target rate for clock
10300565fb16STero Kristo * @parent_rate: rate of the parent clock
10310565fb16STero Kristo * @index: parent index, 0 - reference clock, 1 - bypass clock
10320565fb16STero Kristo *
10330565fb16STero Kristo * Check if the current SoC support the per-dpll reprogram operation
10340565fb16STero Kristo * or not, and then do the rate + parent change if supported. Returns
10350565fb16STero Kristo * -EINVAL if not supported, 0 for success, and potential error codes
10360565fb16STero Kristo * from the clock rate change.
10370565fb16STero Kristo */
omap3_dpll4_set_rate_and_parent(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate,u8 index)10380565fb16STero Kristo int omap3_dpll4_set_rate_and_parent(struct clk_hw *hw, unsigned long rate,
10390565fb16STero Kristo unsigned long parent_rate, u8 index)
10400565fb16STero Kristo {
10410565fb16STero Kristo if (ti_clk_get_features()->flags & TI_CLK_DPLL4_DENY_REPROGRAM) {
10420565fb16STero Kristo pr_err("clock: DPLL4 cannot change rate due to silicon 'Limitation 2.5' on 3430ES1.\n");
10430565fb16STero Kristo return -EINVAL;
10440565fb16STero Kristo }
10450565fb16STero Kristo
10460565fb16STero Kristo return omap3_noncore_dpll_set_rate_and_parent(hw, rate, parent_rate,
10470565fb16STero Kristo index);
10480565fb16STero Kristo }
1049035cd485SRichard Watts
1050035cd485SRichard Watts /* Apply DM3730 errata sprz319 advisory 2.1. */
omap3_dpll5_apply_errata(struct clk_hw * hw,unsigned long parent_rate)1051035cd485SRichard Watts static bool omap3_dpll5_apply_errata(struct clk_hw *hw,
1052035cd485SRichard Watts unsigned long parent_rate)
1053035cd485SRichard Watts {
1054035cd485SRichard Watts struct omap3_dpll5_settings {
1055035cd485SRichard Watts unsigned int rate, m, n;
1056035cd485SRichard Watts };
1057035cd485SRichard Watts
1058035cd485SRichard Watts static const struct omap3_dpll5_settings precomputed[] = {
1059035cd485SRichard Watts /*
1060035cd485SRichard Watts * From DM3730 errata advisory 2.1, table 35 and 36.
1061035cd485SRichard Watts * The N value is increased by 1 compared to the tables as the
1062035cd485SRichard Watts * errata lists register values while last_rounded_field is the
1063035cd485SRichard Watts * real divider value.
1064035cd485SRichard Watts */
1065035cd485SRichard Watts { 12000000, 80, 0 + 1 },
1066035cd485SRichard Watts { 13000000, 443, 5 + 1 },
1067035cd485SRichard Watts { 19200000, 50, 0 + 1 },
1068035cd485SRichard Watts { 26000000, 443, 11 + 1 },
1069035cd485SRichard Watts { 38400000, 25, 0 + 1 }
1070035cd485SRichard Watts };
1071035cd485SRichard Watts
1072035cd485SRichard Watts const struct omap3_dpll5_settings *d;
1073035cd485SRichard Watts struct clk_hw_omap *clk = to_clk_hw_omap(hw);
1074035cd485SRichard Watts struct dpll_data *dd;
1075035cd485SRichard Watts unsigned int i;
1076035cd485SRichard Watts
1077035cd485SRichard Watts for (i = 0; i < ARRAY_SIZE(precomputed); ++i) {
1078035cd485SRichard Watts if (parent_rate == precomputed[i].rate)
1079035cd485SRichard Watts break;
1080035cd485SRichard Watts }
1081035cd485SRichard Watts
1082035cd485SRichard Watts if (i == ARRAY_SIZE(precomputed))
1083035cd485SRichard Watts return false;
1084035cd485SRichard Watts
1085035cd485SRichard Watts d = &precomputed[i];
1086035cd485SRichard Watts
1087035cd485SRichard Watts /* Update the M, N and rounded rate values and program the DPLL. */
1088035cd485SRichard Watts dd = clk->dpll_data;
1089035cd485SRichard Watts dd->last_rounded_m = d->m;
1090035cd485SRichard Watts dd->last_rounded_n = d->n;
1091035cd485SRichard Watts dd->last_rounded_rate = div_u64((u64)parent_rate * d->m, d->n);
1092035cd485SRichard Watts omap3_noncore_dpll_program(clk, 0);
1093035cd485SRichard Watts
1094035cd485SRichard Watts return true;
1095035cd485SRichard Watts }
1096035cd485SRichard Watts
1097035cd485SRichard Watts /**
1098035cd485SRichard Watts * omap3_dpll5_set_rate - set rate for omap3 dpll5
1099035cd485SRichard Watts * @hw: clock to change
1100035cd485SRichard Watts * @rate: target rate for clock
1101035cd485SRichard Watts * @parent_rate: rate of the parent clock
1102035cd485SRichard Watts *
1103035cd485SRichard Watts * Set rate for the DPLL5 clock. Apply the sprz319 advisory 2.1 on OMAP36xx if
1104035cd485SRichard Watts * the DPLL is used for USB host (detected through the requested rate).
1105035cd485SRichard Watts */
omap3_dpll5_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)1106035cd485SRichard Watts int omap3_dpll5_set_rate(struct clk_hw *hw, unsigned long rate,
1107035cd485SRichard Watts unsigned long parent_rate)
1108035cd485SRichard Watts {
1109035cd485SRichard Watts if (rate == OMAP3_DPLL5_FREQ_FOR_USBHOST * 8) {
1110035cd485SRichard Watts if (omap3_dpll5_apply_errata(hw, parent_rate))
1111035cd485SRichard Watts return 0;
1112035cd485SRichard Watts }
1113035cd485SRichard Watts
1114035cd485SRichard Watts return omap3_noncore_dpll_set_rate(hw, rate, parent_rate);
1115035cd485SRichard Watts }
1116