2013-10-11 12:44:49 +04:00
/*
* Copyright ( C ) 2013 Boris BREZILLON < b . brezillon @ overkiz . com >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
*/
# include <linux/clk-provider.h>
# include <linux/clkdev.h>
# include <linux/clk/at91_pmc.h>
# include <linux/delay.h>
2014-09-07 10:14:29 +04:00
# include <linux/mfd/syscon.h>
# include <linux/regmap.h>
2013-10-11 12:44:49 +04:00
# include "pmc.h"
# define SLOW_CLOCK_FREQ 32768
# define MAINF_DIV 16
# define MAINFRDY_TIMEOUT (((MAINF_DIV + 1) * USEC_PER_SEC) / \
SLOW_CLOCK_FREQ )
# define MAINF_LOOP_MIN_WAIT (USEC_PER_SEC / SLOW_CLOCK_FREQ)
# define MAINF_LOOP_MAX_WAIT MAINFRDY_TIMEOUT
2014-05-07 20:00:08 +04:00
# define MOR_KEY_MASK (0xff << 16)
struct clk_main_osc {
2013-10-11 12:44:49 +04:00
struct clk_hw hw ;
2014-09-07 10:14:29 +04:00
struct regmap * regmap ;
2013-10-11 12:44:49 +04:00
} ;
2014-05-07 20:00:08 +04:00
# define to_clk_main_osc(hw) container_of(hw, struct clk_main_osc, hw)
struct clk_main_rc_osc {
struct clk_hw hw ;
2014-09-07 10:14:29 +04:00
struct regmap * regmap ;
2014-05-07 20:00:08 +04:00
unsigned long frequency ;
unsigned long accuracy ;
} ;
# define to_clk_main_rc_osc(hw) container_of(hw, struct clk_main_rc_osc, hw)
struct clk_rm9200_main {
struct clk_hw hw ;
2014-09-07 10:14:29 +04:00
struct regmap * regmap ;
2014-05-07 20:00:08 +04:00
} ;
# define to_clk_rm9200_main(hw) container_of(hw, struct clk_rm9200_main, hw)
2013-10-11 12:44:49 +04:00
2014-05-07 20:00:08 +04:00
struct clk_sam9x5_main {
struct clk_hw hw ;
2014-09-07 10:14:29 +04:00
struct regmap * regmap ;
2014-05-07 20:00:08 +04:00
u8 parent ;
} ;
# define to_clk_sam9x5_main(hw) container_of(hw, struct clk_sam9x5_main, hw)
2014-09-07 10:14:29 +04:00
static inline bool clk_main_osc_ready ( struct regmap * regmap )
{
unsigned int status ;
regmap_read ( regmap , AT91_PMC_SR , & status ) ;
return status & AT91_PMC_MOSCS ;
}
2014-05-07 20:00:08 +04:00
static int clk_main_osc_prepare ( struct clk_hw * hw )
2013-10-11 12:44:49 +04:00
{
2014-05-07 20:00:08 +04:00
struct clk_main_osc * osc = to_clk_main_osc ( hw ) ;
2014-09-07 10:14:29 +04:00
struct regmap * regmap = osc - > regmap ;
2013-10-11 12:44:49 +04:00
u32 tmp ;
2014-09-07 10:14:29 +04:00
regmap_read ( regmap , AT91_CKGR_MOR , & tmp ) ;
tmp & = ~ MOR_KEY_MASK ;
2014-05-07 20:00:08 +04:00
if ( tmp & AT91_PMC_OSCBYPASS )
return 0 ;
if ( ! ( tmp & AT91_PMC_MOSCEN ) ) {
tmp | = AT91_PMC_MOSCEN | AT91_PMC_KEY ;
2014-09-07 10:14:29 +04:00
regmap_write ( regmap , AT91_CKGR_MOR , tmp ) ;
2014-05-07 20:00:08 +04:00
}
2015-09-17 00:47:39 +03:00
while ( ! clk_main_osc_ready ( regmap ) )
cpu_relax ( ) ;
2013-10-11 12:44:49 +04:00
2014-05-07 20:00:08 +04:00
return 0 ;
}
static void clk_main_osc_unprepare ( struct clk_hw * hw )
{
struct clk_main_osc * osc = to_clk_main_osc ( hw ) ;
2014-09-07 10:14:29 +04:00
struct regmap * regmap = osc - > regmap ;
u32 tmp ;
2014-05-07 20:00:08 +04:00
2014-09-07 10:14:29 +04:00
regmap_read ( regmap , AT91_CKGR_MOR , & tmp ) ;
2014-05-07 20:00:08 +04:00
if ( tmp & AT91_PMC_OSCBYPASS )
return ;
if ( ! ( tmp & AT91_PMC_MOSCEN ) )
return ;
tmp & = ~ ( AT91_PMC_KEY | AT91_PMC_MOSCEN ) ;
2014-09-07 10:14:29 +04:00
regmap_write ( regmap , AT91_CKGR_MOR , tmp | AT91_PMC_KEY ) ;
2014-05-07 20:00:08 +04:00
}
static int clk_main_osc_is_prepared ( struct clk_hw * hw )
{
struct clk_main_osc * osc = to_clk_main_osc ( hw ) ;
2014-09-07 10:14:29 +04:00
struct regmap * regmap = osc - > regmap ;
u32 tmp , status ;
2014-05-07 20:00:08 +04:00
2014-09-07 10:14:29 +04:00
regmap_read ( regmap , AT91_CKGR_MOR , & tmp ) ;
2014-05-07 20:00:08 +04:00
if ( tmp & AT91_PMC_OSCBYPASS )
return 1 ;
2014-09-07 10:14:29 +04:00
regmap_read ( regmap , AT91_PMC_SR , & status ) ;
return ( status & AT91_PMC_MOSCS ) & & ( tmp & AT91_PMC_MOSCEN ) ;
2014-05-07 20:00:08 +04:00
}
static const struct clk_ops main_osc_ops = {
. prepare = clk_main_osc_prepare ,
. unprepare = clk_main_osc_unprepare ,
. is_prepared = clk_main_osc_is_prepared ,
} ;
2018-10-16 17:21:44 +03:00
struct clk_hw * __init
2014-09-07 10:14:29 +04:00
at91_clk_register_main_osc ( struct regmap * regmap ,
2014-05-07 20:00:08 +04:00
const char * name ,
const char * parent_name ,
bool bypass )
{
struct clk_main_osc * osc ;
struct clk_init_data init ;
2016-06-02 00:31:22 +03:00
struct clk_hw * hw ;
int ret ;
2014-05-07 20:00:08 +04:00
2015-09-17 00:47:39 +03:00
if ( ! name | | ! parent_name )
2014-05-07 20:00:08 +04:00
return ERR_PTR ( - EINVAL ) ;
osc = kzalloc ( sizeof ( * osc ) , GFP_KERNEL ) ;
if ( ! osc )
return ERR_PTR ( - ENOMEM ) ;
init . name = name ;
init . ops = & main_osc_ops ;
init . parent_names = & parent_name ;
init . num_parents = 1 ;
init . flags = CLK_IGNORE_UNUSED ;
osc - > hw . init = & init ;
2014-09-07 10:14:29 +04:00
osc - > regmap = regmap ;
2014-05-07 20:00:08 +04:00
if ( bypass )
2014-09-07 10:14:29 +04:00
regmap_update_bits ( regmap ,
AT91_CKGR_MOR , MOR_KEY_MASK |
AT91_PMC_MOSCEN ,
AT91_PMC_OSCBYPASS | AT91_PMC_KEY ) ;
2014-05-07 20:00:08 +04:00
2016-06-02 00:31:22 +03:00
hw = & osc - > hw ;
ret = clk_hw_register ( NULL , & osc - > hw ) ;
if ( ret ) {
2014-05-07 20:00:08 +04:00
kfree ( osc ) ;
2016-06-02 00:31:22 +03:00
hw = ERR_PTR ( ret ) ;
}
2014-05-07 20:00:08 +04:00
2016-06-02 00:31:22 +03:00
return hw ;
2014-05-07 20:00:08 +04:00
}
2014-09-07 10:14:29 +04:00
static bool clk_main_rc_osc_ready ( struct regmap * regmap )
{
unsigned int status ;
regmap_read ( regmap , AT91_PMC_SR , & status ) ;
return status & AT91_PMC_MOSCRCS ;
}
2014-05-07 20:00:08 +04:00
static int clk_main_rc_osc_prepare ( struct clk_hw * hw )
{
struct clk_main_rc_osc * osc = to_clk_main_rc_osc ( hw ) ;
2014-09-07 10:14:29 +04:00
struct regmap * regmap = osc - > regmap ;
unsigned int mor ;
2014-05-07 20:00:08 +04:00
2014-09-07 10:14:29 +04:00
regmap_read ( regmap , AT91_CKGR_MOR , & mor ) ;
2014-05-07 20:00:08 +04:00
2014-09-07 10:14:29 +04:00
if ( ! ( mor & AT91_PMC_MOSCRCEN ) )
regmap_update_bits ( regmap , AT91_CKGR_MOR ,
MOR_KEY_MASK | AT91_PMC_MOSCRCEN ,
AT91_PMC_MOSCRCEN | AT91_PMC_KEY ) ;
2014-05-07 20:00:08 +04:00
2015-09-17 00:47:39 +03:00
while ( ! clk_main_rc_osc_ready ( regmap ) )
cpu_relax ( ) ;
2014-05-07 20:00:08 +04:00
return 0 ;
}
static void clk_main_rc_osc_unprepare ( struct clk_hw * hw )
{
struct clk_main_rc_osc * osc = to_clk_main_rc_osc ( hw ) ;
2014-09-07 10:14:29 +04:00
struct regmap * regmap = osc - > regmap ;
unsigned int mor ;
2014-05-07 20:00:08 +04:00
2014-09-07 10:14:29 +04:00
regmap_read ( regmap , AT91_CKGR_MOR , & mor ) ;
if ( ! ( mor & AT91_PMC_MOSCRCEN ) )
2014-05-07 20:00:08 +04:00
return ;
2014-09-07 10:14:29 +04:00
regmap_update_bits ( regmap , AT91_CKGR_MOR ,
MOR_KEY_MASK | AT91_PMC_MOSCRCEN , AT91_PMC_KEY ) ;
2014-05-07 20:00:08 +04:00
}
static int clk_main_rc_osc_is_prepared ( struct clk_hw * hw )
{
struct clk_main_rc_osc * osc = to_clk_main_rc_osc ( hw ) ;
2014-09-07 10:14:29 +04:00
struct regmap * regmap = osc - > regmap ;
unsigned int mor , status ;
regmap_read ( regmap , AT91_CKGR_MOR , & mor ) ;
regmap_read ( regmap , AT91_PMC_SR , & status ) ;
2014-05-07 20:00:08 +04:00
2014-09-07 10:14:29 +04:00
return ( mor & AT91_PMC_MOSCRCEN ) & & ( status & AT91_PMC_MOSCRCS ) ;
2014-05-07 20:00:08 +04:00
}
static unsigned long clk_main_rc_osc_recalc_rate ( struct clk_hw * hw ,
unsigned long parent_rate )
{
struct clk_main_rc_osc * osc = to_clk_main_rc_osc ( hw ) ;
return osc - > frequency ;
}
static unsigned long clk_main_rc_osc_recalc_accuracy ( struct clk_hw * hw ,
unsigned long parent_acc )
{
struct clk_main_rc_osc * osc = to_clk_main_rc_osc ( hw ) ;
return osc - > accuracy ;
}
static const struct clk_ops main_rc_osc_ops = {
. prepare = clk_main_rc_osc_prepare ,
. unprepare = clk_main_rc_osc_unprepare ,
. is_prepared = clk_main_rc_osc_is_prepared ,
. recalc_rate = clk_main_rc_osc_recalc_rate ,
. recalc_accuracy = clk_main_rc_osc_recalc_accuracy ,
} ;
2018-10-16 17:21:44 +03:00
struct clk_hw * __init
2014-09-07 10:14:29 +04:00
at91_clk_register_main_rc_osc ( struct regmap * regmap ,
2014-05-07 20:00:08 +04:00
const char * name ,
u32 frequency , u32 accuracy )
{
struct clk_main_rc_osc * osc ;
struct clk_init_data init ;
2016-06-02 00:31:22 +03:00
struct clk_hw * hw ;
int ret ;
2014-05-07 20:00:08 +04:00
2014-09-07 10:14:29 +04:00
if ( ! name | | ! frequency )
2014-05-07 20:00:08 +04:00
return ERR_PTR ( - EINVAL ) ;
osc = kzalloc ( sizeof ( * osc ) , GFP_KERNEL ) ;
if ( ! osc )
return ERR_PTR ( - ENOMEM ) ;
init . name = name ;
init . ops = & main_rc_osc_ops ;
init . parent_names = NULL ;
init . num_parents = 0 ;
2016-03-01 21:59:46 +03:00
init . flags = CLK_IGNORE_UNUSED ;
2014-05-07 20:00:08 +04:00
osc - > hw . init = & init ;
2014-09-07 10:14:29 +04:00
osc - > regmap = regmap ;
2014-05-07 20:00:08 +04:00
osc - > frequency = frequency ;
osc - > accuracy = accuracy ;
2016-06-02 00:31:22 +03:00
hw = & osc - > hw ;
ret = clk_hw_register ( NULL , hw ) ;
if ( ret ) {
2014-05-07 20:00:08 +04:00
kfree ( osc ) ;
2016-06-02 00:31:22 +03:00
hw = ERR_PTR ( ret ) ;
}
2014-05-07 20:00:08 +04:00
2016-06-02 00:31:22 +03:00
return hw ;
2014-05-07 20:00:08 +04:00
}
2014-09-07 10:14:29 +04:00
static int clk_main_probe_frequency ( struct regmap * regmap )
2014-05-07 20:00:08 +04:00
{
unsigned long prep_time , timeout ;
2014-09-07 10:14:29 +04:00
unsigned int mcfr ;
2013-10-11 12:44:49 +04:00
timeout = jiffies + usecs_to_jiffies ( MAINFRDY_TIMEOUT ) ;
do {
2014-05-07 20:00:08 +04:00
prep_time = jiffies ;
2014-09-07 10:14:29 +04:00
regmap_read ( regmap , AT91_CKGR_MCFR , & mcfr ) ;
if ( mcfr & AT91_PMC_MAINRDY )
2013-10-11 12:44:49 +04:00
return 0 ;
usleep_range ( MAINF_LOOP_MIN_WAIT , MAINF_LOOP_MAX_WAIT ) ;
2014-05-07 20:00:08 +04:00
} while ( time_before ( prep_time , timeout ) ) ;
2013-10-11 12:44:49 +04:00
2014-05-07 20:00:08 +04:00
return - ETIMEDOUT ;
2013-10-11 12:44:49 +04:00
}
2014-09-07 10:14:29 +04:00
static unsigned long clk_main_recalc_rate ( struct regmap * regmap ,
2014-05-07 20:00:08 +04:00
unsigned long parent_rate )
2013-10-11 12:44:49 +04:00
{
2014-09-07 10:14:29 +04:00
unsigned int mcfr ;
2014-05-07 20:00:08 +04:00
if ( parent_rate )
return parent_rate ;
2014-07-01 18:12:12 +04:00
pr_warn ( " Main crystal frequency not set, using approximate value \n " ) ;
2014-09-07 10:14:29 +04:00
regmap_read ( regmap , AT91_CKGR_MCFR , & mcfr ) ;
if ( ! ( mcfr & AT91_PMC_MAINRDY ) )
2014-05-07 20:00:08 +04:00
return 0 ;
2013-10-11 12:44:49 +04:00
2014-09-07 10:14:29 +04:00
return ( ( mcfr & AT91_PMC_MAINF ) * SLOW_CLOCK_FREQ ) / MAINF_DIV ;
2013-10-11 12:44:49 +04:00
}
2014-05-07 20:00:08 +04:00
static int clk_rm9200_main_prepare ( struct clk_hw * hw )
2013-10-11 12:44:49 +04:00
{
2014-05-07 20:00:08 +04:00
struct clk_rm9200_main * clkmain = to_clk_rm9200_main ( hw ) ;
2014-09-07 10:14:29 +04:00
return clk_main_probe_frequency ( clkmain - > regmap ) ;
2014-05-07 20:00:08 +04:00
}
static int clk_rm9200_main_is_prepared ( struct clk_hw * hw )
{
struct clk_rm9200_main * clkmain = to_clk_rm9200_main ( hw ) ;
2014-09-07 10:14:29 +04:00
unsigned int status ;
regmap_read ( clkmain - > regmap , AT91_CKGR_MCFR , & status ) ;
2014-05-07 20:00:08 +04:00
2014-09-07 10:14:29 +04:00
return status & AT91_PMC_MAINRDY ? 1 : 0 ;
2014-05-07 20:00:08 +04:00
}
static unsigned long clk_rm9200_main_recalc_rate ( struct clk_hw * hw ,
unsigned long parent_rate )
{
struct clk_rm9200_main * clkmain = to_clk_rm9200_main ( hw ) ;
2014-09-07 10:14:29 +04:00
return clk_main_recalc_rate ( clkmain - > regmap , parent_rate ) ;
2014-05-07 20:00:08 +04:00
}
static const struct clk_ops rm9200_main_ops = {
. prepare = clk_rm9200_main_prepare ,
. is_prepared = clk_rm9200_main_is_prepared ,
. recalc_rate = clk_rm9200_main_recalc_rate ,
} ;
2018-10-16 17:21:44 +03:00
struct clk_hw * __init
2014-09-07 10:14:29 +04:00
at91_clk_register_rm9200_main ( struct regmap * regmap ,
2014-05-07 20:00:08 +04:00
const char * name ,
const char * parent_name )
{
struct clk_rm9200_main * clkmain ;
struct clk_init_data init ;
2016-06-02 00:31:22 +03:00
struct clk_hw * hw ;
int ret ;
2014-05-07 20:00:08 +04:00
2014-09-07 10:14:29 +04:00
if ( ! name )
2014-05-07 20:00:08 +04:00
return ERR_PTR ( - EINVAL ) ;
if ( ! parent_name )
return ERR_PTR ( - EINVAL ) ;
clkmain = kzalloc ( sizeof ( * clkmain ) , GFP_KERNEL ) ;
if ( ! clkmain )
return ERR_PTR ( - ENOMEM ) ;
init . name = name ;
init . ops = & rm9200_main_ops ;
init . parent_names = & parent_name ;
init . num_parents = 1 ;
init . flags = 0 ;
clkmain - > hw . init = & init ;
2014-09-07 10:14:29 +04:00
clkmain - > regmap = regmap ;
2014-05-07 20:00:08 +04:00
2016-06-02 00:31:22 +03:00
hw = & clkmain - > hw ;
ret = clk_hw_register ( NULL , & clkmain - > hw ) ;
if ( ret ) {
2014-05-07 20:00:08 +04:00
kfree ( clkmain ) ;
2016-06-02 00:31:22 +03:00
hw = ERR_PTR ( ret ) ;
}
2014-05-07 20:00:08 +04:00
2016-06-02 00:31:22 +03:00
return hw ;
2014-05-07 20:00:08 +04:00
}
2014-09-07 10:14:29 +04:00
static inline bool clk_sam9x5_main_ready ( struct regmap * regmap )
{
unsigned int status ;
regmap_read ( regmap , AT91_PMC_SR , & status ) ;
return status & AT91_PMC_MOSCSELS ? 1 : 0 ;
}
2014-05-07 20:00:08 +04:00
static int clk_sam9x5_main_prepare ( struct clk_hw * hw )
{
struct clk_sam9x5_main * clkmain = to_clk_sam9x5_main ( hw ) ;
2014-09-07 10:14:29 +04:00
struct regmap * regmap = clkmain - > regmap ;
2013-10-11 12:44:49 +04:00
2015-09-17 00:47:39 +03:00
while ( ! clk_sam9x5_main_ready ( regmap ) )
cpu_relax ( ) ;
2014-05-07 20:00:08 +04:00
2014-09-07 10:14:29 +04:00
return clk_main_probe_frequency ( regmap ) ;
2014-05-07 20:00:08 +04:00
}
2013-10-11 12:44:49 +04:00
2014-05-07 20:00:08 +04:00
static int clk_sam9x5_main_is_prepared ( struct clk_hw * hw )
{
struct clk_sam9x5_main * clkmain = to_clk_sam9x5_main ( hw ) ;
2013-10-11 12:44:49 +04:00
2014-09-07 10:14:29 +04:00
return clk_sam9x5_main_ready ( clkmain - > regmap ) ;
2013-10-11 12:44:49 +04:00
}
2014-05-07 20:00:08 +04:00
static unsigned long clk_sam9x5_main_recalc_rate ( struct clk_hw * hw ,
unsigned long parent_rate )
{
struct clk_sam9x5_main * clkmain = to_clk_sam9x5_main ( hw ) ;
2014-09-07 10:14:29 +04:00
return clk_main_recalc_rate ( clkmain - > regmap , parent_rate ) ;
2014-05-07 20:00:08 +04:00
}
static int clk_sam9x5_main_set_parent ( struct clk_hw * hw , u8 index )
{
struct clk_sam9x5_main * clkmain = to_clk_sam9x5_main ( hw ) ;
2014-09-07 10:14:29 +04:00
struct regmap * regmap = clkmain - > regmap ;
unsigned int tmp ;
2014-05-07 20:00:08 +04:00
if ( index > 1 )
return - EINVAL ;
2014-09-07 10:14:29 +04:00
regmap_read ( regmap , AT91_CKGR_MOR , & tmp ) ;
tmp & = ~ MOR_KEY_MASK ;
2014-05-07 20:00:08 +04:00
if ( index & & ! ( tmp & AT91_PMC_MOSCSEL ) )
2014-09-07 10:14:29 +04:00
regmap_write ( regmap , AT91_CKGR_MOR , tmp | AT91_PMC_MOSCSEL ) ;
2014-05-07 20:00:08 +04:00
else if ( ! index & & ( tmp & AT91_PMC_MOSCSEL ) )
2014-09-07 10:14:29 +04:00
regmap_write ( regmap , AT91_CKGR_MOR , tmp & ~ AT91_PMC_MOSCSEL ) ;
2014-05-07 20:00:08 +04:00
2015-09-17 00:47:39 +03:00
while ( ! clk_sam9x5_main_ready ( regmap ) )
cpu_relax ( ) ;
2014-05-07 20:00:08 +04:00
return 0 ;
}
static u8 clk_sam9x5_main_get_parent ( struct clk_hw * hw )
{
struct clk_sam9x5_main * clkmain = to_clk_sam9x5_main ( hw ) ;
2014-09-07 10:14:29 +04:00
unsigned int status ;
2014-05-07 20:00:08 +04:00
2014-09-07 10:14:29 +04:00
regmap_read ( clkmain - > regmap , AT91_CKGR_MOR , & status ) ;
return status & AT91_PMC_MOSCEN ? 1 : 0 ;
2014-05-07 20:00:08 +04:00
}
static const struct clk_ops sam9x5_main_ops = {
. prepare = clk_sam9x5_main_prepare ,
. is_prepared = clk_sam9x5_main_is_prepared ,
. recalc_rate = clk_sam9x5_main_recalc_rate ,
. set_parent = clk_sam9x5_main_set_parent ,
. get_parent = clk_sam9x5_main_get_parent ,
2013-10-11 12:44:49 +04:00
} ;
2018-10-16 17:21:44 +03:00
struct clk_hw * __init
2014-09-07 10:14:29 +04:00
at91_clk_register_sam9x5_main ( struct regmap * regmap ,
2014-05-07 20:00:08 +04:00
const char * name ,
const char * * parent_names ,
int num_parents )
2013-10-11 12:44:49 +04:00
{
2014-05-07 20:00:08 +04:00
struct clk_sam9x5_main * clkmain ;
2013-10-11 12:44:49 +04:00
struct clk_init_data init ;
2014-09-07 10:14:29 +04:00
unsigned int status ;
2016-06-02 00:31:22 +03:00
struct clk_hw * hw ;
int ret ;
2013-10-11 12:44:49 +04:00
2014-09-07 10:14:29 +04:00
if ( ! name )
2013-10-11 12:44:49 +04:00
return ERR_PTR ( - EINVAL ) ;
2014-05-07 20:00:08 +04:00
if ( ! parent_names | | ! num_parents )
2013-10-11 12:44:49 +04:00
return ERR_PTR ( - EINVAL ) ;
clkmain = kzalloc ( sizeof ( * clkmain ) , GFP_KERNEL ) ;
if ( ! clkmain )
return ERR_PTR ( - ENOMEM ) ;
init . name = name ;
2014-05-07 20:00:08 +04:00
init . ops = & sam9x5_main_ops ;
init . parent_names = parent_names ;
init . num_parents = num_parents ;
init . flags = CLK_SET_PARENT_GATE ;
2013-10-11 12:44:49 +04:00
clkmain - > hw . init = & init ;
2014-09-07 10:14:29 +04:00
clkmain - > regmap = regmap ;
regmap_read ( clkmain - > regmap , AT91_CKGR_MOR , & status ) ;
clkmain - > parent = status & AT91_PMC_MOSCEN ? 1 : 0 ;
2013-10-11 12:44:49 +04:00
2016-06-02 00:31:22 +03:00
hw = & clkmain - > hw ;
ret = clk_hw_register ( NULL , & clkmain - > hw ) ;
if ( ret ) {
2013-10-11 12:44:49 +04:00
kfree ( clkmain ) ;
2016-06-02 00:31:22 +03:00
hw = ERR_PTR ( ret ) ;
}
2013-10-11 12:44:49 +04:00
2016-06-02 00:31:22 +03:00
return hw ;
2013-10-11 12:44:49 +04:00
}