2019-05-27 08:55:01 +02:00
// SPDX-License-Identifier: GPL-2.0-or-later
2014-02-27 16:24:14 +01: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-18 15:20:22 -07:00
# include <linux/io.h>
2014-02-27 16:24:14 +01:00
# include <linux/of_address.h>
2015-06-19 15:00:46 -07:00
# include <linux/clk.h>
2014-02-27 16:24:14 +01:00
# include <linux/clk-provider.h>
2015-10-07 11:08:57 +02:00
# include "clkgen.h"
2014-02-27 16:24:14 +01:00
static const char * * __init clkgen_mux_get_parents ( struct device_node * np ,
int * num_parents )
{
const char * * parents ;
2016-02-19 17:43:30 -08:00
unsigned int nparents ;
2014-02-27 16:24:14 +01:00
2015-05-29 11:25:46 +02:00
nparents = of_clk_get_parent_count ( np ) ;
2016-02-19 17:43:30 -08:00
if ( WARN_ON ( ! nparents ) )
2014-02-27 16:24:14 +01:00
return ERR_PTR ( - EINVAL ) ;
2015-07-07 18:30:05 -07:00
parents = kcalloc ( nparents , sizeof ( const char * ) , GFP_KERNEL ) ;
2014-02-27 16:24:14 +01:00
if ( ! parents )
return ERR_PTR ( - ENOMEM ) ;
2015-07-06 22:59:04 -05:00
* num_parents = of_clk_parent_fill ( np , parents , nparents ) ;
2014-02-27 16:24:14 +01:00
return parents ;
}
2014-02-27 16:24:16 +01:00
struct clkgen_mux_data {
u32 offset ;
u8 shift ;
u8 width ;
spinlock_t * lock ;
unsigned long clk_flags ;
u8 mux_flags ;
} ;
2014-07-15 17:20:23 +02:00
static struct clkgen_mux_data stih407_a9_mux_data = {
. offset = 0x1a4 ,
2015-06-23 16:09:25 +02:00
. shift = 0 ,
2014-07-15 17:20:23 +02:00
. width = 2 ,
2015-10-07 11:08:57 +02:00
. lock = & clkgen_a9_lock ,
2014-07-15 17:20:23 +02:00
} ;
2014-02-27 16:24:19 +01:00
2016-08-29 14:26:54 +02:00
static void __init st_of_clkgen_mux_setup ( struct device_node * np ,
struct clkgen_mux_data * data )
2014-02-27 16:24:16 +01:00
{
struct clk * clk ;
void __iomem * reg ;
const char * * parents ;
2016-08-29 14:26:53 +02:00
int num_parents = 0 ;
2014-02-27 16:24:16 +01:00
reg = of_iomap ( np , 0 ) ;
if ( ! reg ) {
pr_err ( " %s: Failed to get base address \n " , __func__ ) ;
return ;
}
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-07 18:30:05 -07:00
goto err_parents ;
2014-02-27 16:24:16 +01: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-07 18:30:05 -07:00
kfree ( parents ) ;
2014-02-27 16:24:16 +01:00
of_clk_add_provider ( np , of_clk_src_simple_get , clk ) ;
2015-07-07 18:30:05 -07:00
return ;
2014-02-27 16:24:16 +01:00
err :
kfree ( parents ) ;
2015-07-07 18:30:05 -07:00
err_parents :
iounmap ( reg ) ;
2014-02-27 16:24:16 +01:00
}
2016-08-29 14:26:54 +02: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 ) ;