2013-07-15 14:14:20 +04:00
/*
* OMAP interface clock support
*
* Copyright ( C ) 2013 Texas Instruments , Inc .
*
* Tero Kristo < t - kristo @ ti . com >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*
* This program is distributed " as is " WITHOUT ANY WARRANTY of any
* kind , whether express or implied ; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*/
# include <linux/clk-provider.h>
# include <linux/slab.h>
# include <linux/of.h>
# include <linux/of_address.h>
# include <linux/clk/ti.h>
2014-12-16 19:20:49 +03:00
# include "clock.h"
2013-07-15 14:14:20 +04:00
# undef pr_fmt
# define pr_fmt(fmt) "%s: " fmt, __func__
static const struct clk_ops ti_interface_clk_ops = {
. init = & omap2_init_clk_clkdm ,
. enable = & omap2_dflt_clk_enable ,
. disable = & omap2_dflt_clk_disable ,
. is_enabled = & omap2_dflt_clk_is_enabled ,
} ;
2014-12-16 19:20:49 +03:00
static struct clk * _register_interface ( struct device * dev , const char * name ,
const char * parent_name ,
2017-02-09 12:24:37 +03:00
struct clk_omap_reg * reg , u8 bit_idx ,
2014-12-16 19:20:49 +03:00
const struct clk_hw_omap_ops * ops )
2013-07-15 14:14:20 +04:00
{
struct clk_init_data init = { NULL } ;
struct clk_hw_omap * clk_hw ;
2014-12-16 19:20:49 +03:00
struct clk * clk ;
2013-07-15 14:14:20 +04:00
clk_hw = kzalloc ( sizeof ( * clk_hw ) , GFP_KERNEL ) ;
if ( ! clk_hw )
2014-12-16 19:20:49 +03:00
return ERR_PTR ( - ENOMEM ) ;
2013-07-15 14:14:20 +04:00
clk_hw - > hw . init = & init ;
clk_hw - > ops = ops ;
2017-02-09 12:24:37 +03:00
memcpy ( & clk_hw - > enable_reg , reg , sizeof ( * reg ) ) ;
2014-12-16 19:20:49 +03:00
clk_hw - > enable_bit = bit_idx ;
2013-07-15 14:14:20 +04:00
2014-12-16 19:20:49 +03:00
init . name = name ;
2013-07-15 14:14:20 +04:00
init . ops = & ti_interface_clk_ops ;
init . flags = 0 ;
init . num_parents = 1 ;
init . parent_names = & parent_name ;
2019-01-15 12:15:15 +03:00
clk = ti_clk_register_omap_hw ( NULL , & clk_hw - > hw , name ) ;
2013-07-15 14:14:20 +04:00
2014-12-16 19:20:49 +03:00
if ( IS_ERR ( clk ) )
kfree ( clk_hw ) ;
return clk ;
}
static void __init _of_ti_interface_clk_setup ( struct device_node * node ,
const struct clk_hw_omap_ops * ops )
{
struct clk * clk ;
const char * parent_name ;
2017-02-09 12:24:37 +03:00
struct clk_omap_reg reg ;
2014-12-16 19:20:49 +03:00
u8 enable_bit = 0 ;
u32 val ;
2017-02-09 12:24:37 +03:00
if ( ti_clk_get_reg_addr ( node , 0 , & reg ) )
2014-12-16 19:20:49 +03:00
return ;
if ( ! of_property_read_u32 ( node , " ti,bit-shift " , & val ) )
enable_bit = val ;
parent_name = of_clk_get_parent_name ( node , 0 ) ;
if ( ! parent_name ) {
2018-08-28 18:44:29 +03:00
pr_err ( " %pOFn must have a parent \n " , node ) ;
2013-07-15 14:14:20 +04:00
return ;
}
2017-02-09 12:24:37 +03:00
clk = _register_interface ( NULL , node - > name , parent_name , & reg ,
2014-12-16 19:20:49 +03:00
enable_bit , ops ) ;
if ( ! IS_ERR ( clk ) )
of_clk_add_provider ( node , of_clk_src_simple_get , clk ) ;
2013-07-15 14:14:20 +04:00
}
static void __init of_ti_interface_clk_setup ( struct device_node * node )
{
_of_ti_interface_clk_setup ( node , & clkhwops_iclk_wait ) ;
}
CLK_OF_DECLARE ( ti_interface_clk , " ti,omap3-interface-clock " ,
of_ti_interface_clk_setup ) ;
static void __init of_ti_no_wait_interface_clk_setup ( struct device_node * node )
{
_of_ti_interface_clk_setup ( node , & clkhwops_iclk ) ;
}
CLK_OF_DECLARE ( ti_no_wait_interface_clk , " ti,omap3-no-wait-interface-clock " ,
of_ti_no_wait_interface_clk_setup ) ;
2014-02-25 21:16:07 +04:00
# ifdef CONFIG_ARCH_OMAP3
2013-07-15 14:14:20 +04:00
static void __init of_ti_hsotgusb_interface_clk_setup ( struct device_node * node )
{
_of_ti_interface_clk_setup ( node ,
& clkhwops_omap3430es2_iclk_hsotgusb_wait ) ;
}
CLK_OF_DECLARE ( ti_hsotgusb_interface_clk , " ti,omap3-hsotgusb-interface-clock " ,
of_ti_hsotgusb_interface_clk_setup ) ;
static void __init of_ti_dss_interface_clk_setup ( struct device_node * node )
{
_of_ti_interface_clk_setup ( node ,
& clkhwops_omap3430es2_iclk_dss_usbhost_wait ) ;
}
CLK_OF_DECLARE ( ti_dss_interface_clk , " ti,omap3-dss-interface-clock " ,
of_ti_dss_interface_clk_setup ) ;
static void __init of_ti_ssi_interface_clk_setup ( struct device_node * node )
{
_of_ti_interface_clk_setup ( node , & clkhwops_omap3430es2_iclk_ssi_wait ) ;
}
CLK_OF_DECLARE ( ti_ssi_interface_clk , " ti,omap3-ssi-interface-clock " ,
of_ti_ssi_interface_clk_setup ) ;
static void __init of_ti_am35xx_interface_clk_setup ( struct device_node * node )
{
_of_ti_interface_clk_setup ( node , & clkhwops_am35xx_ipss_wait ) ;
}
CLK_OF_DECLARE ( ti_am35xx_interface_clk , " ti,am35xx-interface-clock " ,
of_ti_am35xx_interface_clk_setup ) ;
2014-02-25 21:16:07 +04:00
# endif
# ifdef CONFIG_SOC_OMAP2430
static void __init of_ti_omap2430_interface_clk_setup ( struct device_node * node )
{
_of_ti_interface_clk_setup ( node , & clkhwops_omap2430_i2chs_wait ) ;
}
CLK_OF_DECLARE ( ti_omap2430_interface_clk , " ti,omap2430-interface-clock " ,
of_ti_omap2430_interface_clk_setup ) ;
# endif