2019-06-04 10:11:33 +02:00
// SPDX-License-Identifier: GPL-2.0-only
2008-03-18 10:22:06 +02:00
/*
* linux / arch / arm / mach - omap2 / clock . c
*
2008-03-18 11:56:39 +02:00
* Copyright ( C ) 2005 - 2008 Texas Instruments , Inc .
2010-02-22 22:09:24 -07:00
* Copyright ( C ) 2004 - 2010 Nokia Corporation
2008-03-18 10:22:06 +02:00
*
2008-03-18 11:56:39 +02:00
* Contacts :
* Richard Woodruff < r - woodruff2 @ ti . com >
2008-03-18 10:22:06 +02:00
* Paul Walmsley
*/
# undef DEBUG
# include <linux/kernel.h>
2012-09-27 10:33:33 -06:00
# include <linux/export.h>
2008-03-18 10:22:06 +02:00
# include <linux/list.h>
# include <linux/errno.h>
2010-02-22 22:09:36 -07:00
# include <linux/err.h>
# include <linux/delay.h>
2015-06-22 17:05:21 -07:00
# include <linux/clk.h>
2012-11-10 16:58:41 -07:00
# include <linux/clk-provider.h>
2008-09-06 12:10:45 +01:00
# include <linux/io.h>
2008-09-06 12:13:59 +01:00
# include <linux/bitops.h>
2014-10-22 15:15:36 +03:00
# include <linux/of_address.h>
2011-03-03 11:25:43 +01:00
# include <asm/cpu.h>
2012-08-31 10:59:07 -07:00
# include <trace/events/power.h>
# include "soc.h"
# include "clockdomain.h"
2008-03-18 10:22:06 +02:00
# include "clock.h"
2012-10-29 20:56:29 -06:00
# include "cm.h"
2012-10-21 01:01:11 -06:00
# include "cm2xxx.h"
# include "cm3xxx.h"
2008-03-18 10:22:06 +02:00
# include "cm-regbits-24xx.h"
# include "cm-regbits-34xx.h"
2012-10-29 20:56:29 -06:00
# include "common.h"
2011-12-13 10:46:43 -08:00
u16 cpu_mask ;
2008-03-18 10:22:06 +02:00
2014-07-02 11:47:40 +03:00
/* DPLL valid Fint frequency band limits - from 34xx TRM Section 4.7.6.2 */
# define OMAP3430_DPLL_FINT_BAND1_MIN 750000
# define OMAP3430_DPLL_FINT_BAND1_MAX 2100000
# define OMAP3430_DPLL_FINT_BAND2_MIN 7500000
# define OMAP3430_DPLL_FINT_BAND2_MAX 21000000
/*
* DPLL valid Fint frequency range for OMAP36xx and OMAP4xxx .
* From device data manual section 4.3 " DPLL and DLL Specifications " .
*/
# define OMAP3PLUS_DPLL_FINT_MIN 32000
# define OMAP3PLUS_DPLL_FINT_MAX 52000000
2017-02-09 11:24:37 +02:00
struct ti_clk_ll_ops omap_clk_ll_ops = {
2015-03-03 11:14:31 +02:00
. clkdm_clk_enable = clkdm_clk_enable ,
. clkdm_clk_disable = clkdm_clk_disable ,
2016-09-30 14:10:11 +03:00
. clkdm_lookup = clkdm_lookup ,
2015-03-03 13:47:08 +02:00
. cm_wait_module_ready = omap_cm_wait_module_ready ,
. cm_split_idlest_reg = cm_split_idlest_reg ,
2014-10-22 15:15:36 +03:00
} ;
2015-04-27 21:55:42 +03:00
/**
* omap2_clk_setup_ll_ops - setup clock driver low - level ops
*
* Sets up clock driver low - level platform ops . These are needed
* for register accesses and various other misc platform operations .
* Returns 0 on success , - EBUSY if low level ops have been registered
* already .
*/
int __init omap2_clk_setup_ll_ops ( void )
{
return ti_clk_setup_ll_ops ( & omap_clk_ll_ops ) ;
}
OMAP2+ clock: revise omap2_clk_{disable,enable}()
Simplify the code in the omap2_clk_disable() and omap2_clk_enable()
functions, reducing levels of indentation. This makes the code easier
to read. Add some additional debugging pr_debug()s here also to help
others understand what is going on.
Revise the omap2_clk_disable() logic so that it now attempts to
disable the clock's clockdomain before recursing up the clock tree.
Simultaneously, ensure that omap2_clk_enable() is called on parent
clocks first, before enabling the clockdomain. This ensures that a
parent clock's clockdomain is enabled before the child clock's
clockdomain. These sequences should be the inverse of each other.
Revise the omap2_clk_enable() logic so that it now cleans up after
itself upon encountering an error. Previously, an error enabling a
parent clock could have resulted in inconsistent usecounts on the
enclosing clockdomain.
Remove the trivial _omap2_clk_disable() and _omap2_clk_enable() static
functions, and replace it with the clkops calls that they were
executing.
For all this to work, the clockdomain omap2_clkdm_clk_enable() and
omap2_clkdm_clk_disable() code must not return an error on clockdomains
without CLKSTCTRL registers; so modify those functions to simply return 0
in that case.
While here, add some basic kerneldoc documentation on both functions,
and get rid of some old non-CodingStyle-compliant comments that have
existed since the dawn of time (at least, the OMAP clock framework's
time).
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Cc: Richard Woodruff <r-woodruff2@ti.com>
Cc: Rajendra Nayak <rnayak@ti.com>
2010-02-22 22:09:38 -07:00
/*
* OMAP2 + specific clock functions
*/
2008-03-18 10:22:06 +02:00
2014-07-02 11:47:39 +03:00
/**
* ti_clk_init_features - init clock features struct for the SoC
*
* Initializes the clock features struct based on the SoC type .
*/
void __init ti_clk_init_features ( void )
{
2015-02-27 17:54:14 +02:00
struct ti_clk_features features = { 0 } ;
2014-07-02 11:47:40 +03:00
/* Fint setup for DPLLs */
if ( cpu_is_omap3430 ( ) ) {
2015-02-27 17:54:14 +02:00
features . fint_min = OMAP3430_DPLL_FINT_BAND1_MIN ;
features . fint_max = OMAP3430_DPLL_FINT_BAND2_MAX ;
features . fint_band1_max = OMAP3430_DPLL_FINT_BAND1_MAX ;
features . fint_band2_min = OMAP3430_DPLL_FINT_BAND2_MIN ;
2014-07-02 11:47:40 +03:00
} else {
2015-02-27 17:54:14 +02:00
features . fint_min = OMAP3PLUS_DPLL_FINT_MIN ;
features . fint_max = OMAP3PLUS_DPLL_FINT_MAX ;
2014-07-02 11:47:40 +03:00
}
2014-07-02 11:47:42 +03:00
/* Bypass value setup for DPLLs */
if ( cpu_is_omap24xx ( ) ) {
2015-02-27 17:54:14 +02:00
features . dpll_bypass_vals | =
2014-07-02 11:47:42 +03:00
( 1 < < OMAP2XXX_EN_DPLL_LPBYPASS ) |
( 1 < < OMAP2XXX_EN_DPLL_FRBYPASS ) ;
} else if ( cpu_is_omap34xx ( ) ) {
2015-02-27 17:54:14 +02:00
features . dpll_bypass_vals | =
2014-07-02 11:47:42 +03:00
( 1 < < OMAP3XXX_EN_DPLL_LPBYPASS ) |
( 1 < < OMAP3XXX_EN_DPLL_FRBYPASS ) ;
} else if ( soc_is_am33xx ( ) | | cpu_is_omap44xx ( ) | | soc_is_am43xx ( ) | |
soc_is_omap54xx ( ) | | soc_is_dra7xx ( ) ) {
2015-02-27 17:54:14 +02:00
features . dpll_bypass_vals | =
2014-07-02 11:47:42 +03:00
( 1 < < OMAP4XXX_EN_DPLL_LPBYPASS ) |
( 1 < < OMAP4XXX_EN_DPLL_FRBYPASS ) |
( 1 < < OMAP4XXX_EN_DPLL_MNBYPASS ) ;
}
2014-07-02 11:47:43 +03:00
/* Jitter correction only available on OMAP343X */
if ( cpu_is_omap343x ( ) )
2015-02-27 17:54:14 +02:00
features . flags | = TI_CLK_DPLL_HAS_FREQSEL ;
2014-07-02 11:47:44 +03:00
2019-04-04 11:11:05 +03:00
if ( omap_type ( ) = = OMAP2_DEVICE_TYPE_GP )
features . flags | = TI_CLK_DEVICE_TYPE_GP ;
2014-07-02 11:47:44 +03:00
/* Idlest value for interface clocks.
* 24 xx uses 0 to indicate not ready , and 1 to indicate ready .
* 34 xx reverses this , just to keep us on our toes
* AM35xx uses both , depending on the module .
*/
if ( cpu_is_omap24xx ( ) )
2015-02-27 17:54:14 +02:00
features . cm_idlest_val = OMAP24XX_CM_IDLEST_VAL ;
2014-07-02 11:47:44 +03:00
else if ( cpu_is_omap34xx ( ) )
2015-02-27 17:54:14 +02:00
features . cm_idlest_val = OMAP34XX_CM_IDLEST_VAL ;
2014-10-03 16:57:10 +03:00
/* On OMAP3430 ES1.0, DPLL4 can't be re-programmed */
if ( omap_rev ( ) = = OMAP3430_REV_ES1_0 )
2015-02-27 17:54:14 +02:00
features . flags | = TI_CLK_DPLL4_DENY_REPROGRAM ;
2015-11-30 16:43:25 +02:00
/* Errata I810 for omap5 / dra7 */
if ( soc_is_omap54xx ( ) | | soc_is_dra7xx ( ) )
features . flags | = TI_CLK_ERRATA_I810 ;
2015-02-27 17:54:14 +02:00
ti_clk_setup_features ( & features ) ;
2014-07-02 11:47:39 +03:00
}