2013-04-23 20:16:59 +08:00
# include <linux/clk.h>
# include <linux/err.h>
# include <linux/of.h>
# include <linux/slab.h>
2012-09-11 08:50:00 +02:00
# include <linux/spinlock.h>
2013-03-25 09:20:38 -03:00
# include "clk.h"
2012-09-11 08:50:00 +02:00
DEFINE_SPINLOCK ( imx_ccm_lock ) ;
2013-04-23 20:16:59 +08:00
2014-06-10 19:40:26 +04:00
void __init imx_check_clocks ( struct clk * clks [ ] , unsigned int count )
{
unsigned i ;
for ( i = 0 ; i < count ; i + + )
if ( IS_ERR ( clks [ i ] ) )
pr_err ( " i.MX clk %u: register failed with %ld \n " ,
i , PTR_ERR ( clks [ i ] ) ) ;
}
2013-04-23 20:16:59 +08:00
static struct clk * __init imx_obtain_fixed_clock_from_dt ( const char * name )
{
2013-05-24 16:55:42 -03:00
struct of_phandle_args phandle ;
2013-04-23 20:16:59 +08:00
struct clk * clk = ERR_PTR ( - ENODEV ) ;
char * path ;
path = kasprintf ( GFP_KERNEL , " /clocks/%s " , name ) ;
if ( ! path )
return ERR_PTR ( - ENOMEM ) ;
phandle . np = of_find_node_by_path ( path ) ;
kfree ( path ) ;
if ( phandle . np ) {
clk = of_clk_get_from_provider ( & phandle ) ;
of_node_put ( phandle . np ) ;
}
return clk ;
}
struct clk * __init imx_obtain_fixed_clock (
const char * name , unsigned long rate )
{
struct clk * clk ;
clk = imx_obtain_fixed_clock_from_dt ( name ) ;
if ( IS_ERR ( clk ) )
clk = imx_clk_fixed ( name , rate ) ;
return clk ;
}
2013-07-04 17:57:17 +08:00
/*
* This fixups the register CCM_CSCMR1 write value .
* The write / read / divider values of the aclk_podf field
* of that register have the relationship described by
* the following table :
*
* write value read value divider
* 3 b ' 000 3 b ' 110 7
* 3 b ' 001 3 b ' 111 8
* 3 b ' 010 3 b ' 100 5
* 3 b ' 011 3 b ' 101 6
* 3 b ' 100 3 b ' 010 3
* 3 b ' 101 3 b ' 011 4
* 3 b ' 110 3 b ' 000 1
* 3 b ' 111 3 b ' 001 2 ( default )
*
* That ' s why we do the xor operation below .
*/
# define CSCMR1_FIXUP 0x00600000
void imx_cscmr1_fixup ( u32 * val )
{
* val ^ = CSCMR1_FIXUP ;
return ;
}
2015-09-21 18:53:57 +02:00
static int imx_keep_uart_clocks __initdata ;
static struct clk * * const * imx_uart_clocks __initdata ;
static int __init imx_keep_uart_clocks_param ( char * str )
{
imx_keep_uart_clocks = 1 ;
return 0 ;
}
__setup_param ( " earlycon " , imx_keep_uart_earlycon ,
imx_keep_uart_clocks_param , 0 ) ;
__setup_param ( " earlyprintk " , imx_keep_uart_earlyprintk ,
imx_keep_uart_clocks_param , 0 ) ;
void __init imx_register_uart_clocks ( struct clk * * const clks [ ] )
{
if ( imx_keep_uart_clocks ) {
int i ;
imx_uart_clocks = clks ;
for ( i = 0 ; imx_uart_clocks [ i ] ; i + + )
clk_prepare_enable ( * imx_uart_clocks [ i ] ) ;
}
}
static int __init imx_clk_disable_uart ( void )
{
if ( imx_keep_uart_clocks & & imx_uart_clocks ) {
int i ;
for ( i = 0 ; imx_uart_clocks [ i ] ; i + + )
clk_disable_unprepare ( * imx_uart_clocks [ i ] ) ;
}
return 0 ;
}
late_initcall_sync ( imx_clk_disable_uart ) ;