2019-05-27 09:55:01 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2014-02-27 19:24:14 +04:00
/*
* clkgen - mux . c : ST GEN - MUX Clock driver
*
* Copyright ( C ) 2014 STMicroelectronics ( R & D ) Limited
*
* Authors : Stephen Gallimore < stephen . gallimore @ st . com >
* Pankaj Dev < pankaj . dev @ st . com >
*/
# include <linux/slab.h>
2019-04-19 01:20:22 +03:00
# include <linux/io.h>
2014-02-27 19:24:14 +04:00
# include <linux/of_address.h>
2015-06-20 01:00:46 +03:00
# include <linux/clk.h>
2014-02-27 19:24:14 +04:00
# include <linux/clk-provider.h>
2015-10-07 12:08:57 +03:00
# include "clkgen.h"
2014-02-27 19:24:14 +04:00
static const char * * __init clkgen_mux_get_parents ( struct device_node * np ,
int * num_parents )
{
const char * * parents ;
2016-02-20 04:43:30 +03:00
unsigned int nparents ;
2014-02-27 19:24:14 +04:00
2015-05-29 12:25:46 +03:00
nparents = of_clk_get_parent_count ( np ) ;
2016-02-20 04:43:30 +03:00
if ( WARN_ON ( ! nparents ) )
2014-02-27 19:24:14 +04:00
return ERR_PTR ( - EINVAL ) ;
2015-07-08 04:30:05 +03:00
parents = kcalloc ( nparents , sizeof ( const char * ) , GFP_KERNEL ) ;
2014-02-27 19:24:14 +04:00
if ( ! parents )
return ERR_PTR ( - ENOMEM ) ;
2015-07-07 06:59:04 +03:00
* num_parents = of_clk_parent_fill ( np , parents , nparents ) ;
2014-02-27 19:24:14 +04:00
return parents ;
}
2014-02-27 19:24:16 +04:00
struct clkgen_mux_data {
u32 offset ;
u8 shift ;
u8 width ;
spinlock_t * lock ;
unsigned long clk_flags ;
u8 mux_flags ;
} ;
2014-07-15 19:20:23 +04:00
static struct clkgen_mux_data stih407_a9_mux_data = {
. offset = 0x1a4 ,
2015-06-23 17:09:25 +03:00
. shift = 0 ,
2014-07-15 19:20:23 +04:00
. width = 2 ,
2015-10-07 12:08:57 +03:00
. lock = & clkgen_a9_lock ,
2014-07-15 19:20:23 +04:00
} ;
2014-02-27 19:24:19 +04:00
2016-08-29 15:26:54 +03:00
static void __init st_of_clkgen_mux_setup ( struct device_node * np ,
struct clkgen_mux_data * data )
2014-02-27 19:24:16 +04:00
{
struct clk * clk ;
void __iomem * reg ;
const char * * parents ;
2016-08-29 15:26:53 +03:00
int num_parents = 0 ;
2014-02-27 19:24:16 +04:00
2021-12-19 00:11:57 +03:00
/*
* First check for reg property within the node to keep backward
* compatibility , then if reg doesn ' t exist look at the parent node
*/
2014-02-27 19:24:16 +04:00
reg = of_iomap ( np , 0 ) ;
if ( ! reg ) {
2021-12-19 00:11:57 +03:00
reg = of_iomap ( of_get_parent ( np ) , 0 ) ;
if ( ! reg ) {
pr_err ( " %s: Failed to get base address \n " , __func__ ) ;
return ;
}
2014-02-27 19:24:16 +04:00
}
parents = clkgen_mux_get_parents ( np , & num_parents ) ;
if ( IS_ERR ( parents ) ) {
pr_err ( " %s: Failed to get parents (%ld) \n " ,
__func__ , PTR_ERR ( parents ) ) ;
2015-07-08 04:30:05 +03:00
goto err_parents ;
2014-02-27 19:24:16 +04:00
}
clk = clk_register_mux ( NULL , np - > name , parents , num_parents ,
data - > clk_flags | CLK_SET_RATE_PARENT ,
reg + data - > offset ,
data - > shift , data - > width , data - > mux_flags ,
data - > lock ) ;
if ( IS_ERR ( clk ) )
goto err ;
pr_debug ( " %s: parent %s rate %u \n " ,
__clk_get_name ( clk ) ,
__clk_get_name ( clk_get_parent ( clk ) ) ,
( unsigned int ) clk_get_rate ( clk ) ) ;
2015-07-08 04:30:05 +03:00
kfree ( parents ) ;
2014-02-27 19:24:16 +04:00
of_clk_add_provider ( np , of_clk_src_simple_get , clk ) ;
2015-07-08 04:30:05 +03:00
return ;
2014-02-27 19:24:16 +04:00
err :
kfree ( parents ) ;
2015-07-08 04:30:05 +03:00
err_parents :
iounmap ( reg ) ;
2014-02-27 19:24:16 +04:00
}
2016-08-29 15:26:54 +03:00
static void __init st_of_clkgen_a9_mux_setup ( struct device_node * np )
{
st_of_clkgen_mux_setup ( np , & stih407_a9_mux_data ) ;
}
CLK_OF_DECLARE ( clkgen_a9mux , " st,stih407-clkgen-a9-mux " ,
st_of_clkgen_a9_mux_setup ) ;