2014-01-28 15:09:11 +04:00
/*
* MOXA ART SoCs clock driver .
*
* Copyright ( C ) 2013 Jonas Jensen
*
* Jonas Jensen < jonas . jensen @ gmail . com >
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed " as is " without any
* warranty of any kind , whether express or implied .
*/
2015-05-02 02:09:33 +03:00
# include <linux/clk.h>
2014-01-28 15:09:11 +04:00
# include <linux/clk-provider.h>
# include <linux/io.h>
# include <linux/of_address.h>
# include <linux/clkdev.h>
2015-05-02 02:09:33 +03:00
static void __init moxart_of_pll_clk_init ( struct device_node * node )
2014-01-28 15:09:11 +04:00
{
2017-07-05 01:36:50 +03:00
void __iomem * base ;
2016-06-02 02:15:18 +03:00
struct clk_hw * hw ;
struct clk * ref_clk ;
2014-01-28 15:09:11 +04:00
unsigned int mul ;
const char * name = node - > name ;
const char * parent_name ;
of_property_read_string ( node , " clock-output-names " , & name ) ;
parent_name = of_clk_get_parent_name ( node , 0 ) ;
base = of_iomap ( node , 0 ) ;
if ( ! base ) {
2017-07-19 00:42:52 +03:00
pr_err ( " %pOF: of_iomap failed \n " , node ) ;
2014-01-28 15:09:11 +04:00
return ;
}
mul = readl ( base + 0x30 ) > > 3 & 0x3f ;
iounmap ( base ) ;
ref_clk = of_clk_get ( node , 0 ) ;
if ( IS_ERR ( ref_clk ) ) {
2017-07-19 00:42:52 +03:00
pr_err ( " %pOF: of_clk_get failed \n " , node ) ;
2014-01-28 15:09:11 +04:00
return ;
}
2016-06-02 02:15:18 +03:00
hw = clk_hw_register_fixed_factor ( NULL , name , parent_name , 0 , mul , 1 ) ;
if ( IS_ERR ( hw ) ) {
2017-07-19 00:42:52 +03:00
pr_err ( " %pOF: failed to register clock \n " , node ) ;
2014-01-28 15:09:11 +04:00
return ;
}
2016-06-02 02:15:18 +03:00
clk_hw_register_clkdev ( hw , NULL , name ) ;
of_clk_add_hw_provider ( node , of_clk_hw_simple_get , hw ) ;
2014-01-28 15:09:11 +04:00
}
CLK_OF_DECLARE ( moxart_pll_clock , " moxa,moxart-pll-clock " ,
moxart_of_pll_clk_init ) ;
2015-05-02 02:09:33 +03:00
static void __init moxart_of_apb_clk_init ( struct device_node * node )
2014-01-28 15:09:11 +04:00
{
2017-07-05 01:36:50 +03:00
void __iomem * base ;
2016-06-02 02:15:18 +03:00
struct clk_hw * hw ;
struct clk * pll_clk ;
2014-01-28 15:09:11 +04:00
unsigned int div , val ;
unsigned int div_idx [ ] = { 2 , 3 , 4 , 6 , 8 } ;
const char * name = node - > name ;
const char * parent_name ;
of_property_read_string ( node , " clock-output-names " , & name ) ;
parent_name = of_clk_get_parent_name ( node , 0 ) ;
base = of_iomap ( node , 0 ) ;
if ( ! base ) {
2017-07-19 00:42:52 +03:00
pr_err ( " %pOF: of_iomap failed \n " , node ) ;
2014-01-28 15:09:11 +04:00
return ;
}
val = readl ( base + 0xc ) > > 4 & 0x7 ;
iounmap ( base ) ;
if ( val > 4 )
val = 0 ;
div = div_idx [ val ] * 2 ;
pll_clk = of_clk_get ( node , 0 ) ;
if ( IS_ERR ( pll_clk ) ) {
2017-07-19 00:42:52 +03:00
pr_err ( " %pOF: of_clk_get failed \n " , node ) ;
2014-01-28 15:09:11 +04:00
return ;
}
2016-06-02 02:15:18 +03:00
hw = clk_hw_register_fixed_factor ( NULL , name , parent_name , 0 , 1 , div ) ;
if ( IS_ERR ( hw ) ) {
2017-07-19 00:42:52 +03:00
pr_err ( " %pOF: failed to register clock \n " , node ) ;
2014-01-28 15:09:11 +04:00
return ;
}
2016-06-02 02:15:18 +03:00
clk_hw_register_clkdev ( hw , NULL , name ) ;
of_clk_add_hw_provider ( node , of_clk_hw_simple_get , hw ) ;
2014-01-28 15:09:11 +04:00
}
CLK_OF_DECLARE ( moxart_apb_clock , " moxa,moxart-apb-clock " ,
moxart_of_apb_clk_init ) ;