2013-07-15 13:14:20 +03: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 18:20:49 +02:00
# include "clock.h"
2013-07-15 13:14:20 +03: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 18:20:49 +02:00
static struct clk * _register_interface ( struct device * dev , const char * name ,
const char * parent_name ,
2017-02-09 11:24:37 +02:00
struct clk_omap_reg * reg , u8 bit_idx ,
2014-12-16 18:20:49 +02:00
const struct clk_hw_omap_ops * ops )
2013-07-15 13:14:20 +03:00
{
struct clk_init_data init = { NULL } ;
struct clk_hw_omap * clk_hw ;
2014-12-16 18:20:49 +02:00
struct clk * clk ;
2013-07-15 13:14:20 +03:00
clk_hw = kzalloc ( sizeof ( * clk_hw ) , GFP_KERNEL ) ;
if ( ! clk_hw )
2014-12-16 18:20:49 +02:00
return ERR_PTR ( - ENOMEM ) ;
2013-07-15 13:14:20 +03:00
clk_hw - > hw . init = & init ;
clk_hw - > ops = ops ;
2017-02-09 11:24:37 +02:00
memcpy ( & clk_hw - > enable_reg , reg , sizeof ( * reg ) ) ;
2014-12-16 18:20:49 +02:00
clk_hw - > enable_bit = bit_idx ;
2013-07-15 13:14:20 +03:00
2014-12-16 18:20:49 +02:00
init . name = name ;
2013-07-15 13:14:20 +03:00
init . ops = & ti_interface_clk_ops ;
init . flags = 0 ;
init . num_parents = 1 ;
init . parent_names = & parent_name ;
2016-09-29 12:06:40 +03:00
clk = ti_clk_register ( NULL , & clk_hw - > hw , name ) ;
2013-07-15 13:14:20 +03:00
2014-12-16 18:20:49 +02:00
if ( IS_ERR ( clk ) )
kfree ( clk_hw ) ;
else
2015-06-29 16:56:30 -07:00
omap2_init_clk_hw_omap_clocks ( & clk_hw - > hw ) ;
2014-12-16 18:20:49 +02:00
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 11:24:37 +02:00
struct clk_omap_reg reg ;
2014-12-16 18:20:49 +02:00
u8 enable_bit = 0 ;
u32 val ;
2017-02-09 11:24:37 +02:00
if ( ti_clk_get_reg_addr ( node , 0 , & reg ) )
2014-12-16 18:20:49 +02: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 ) {
pr_err ( " %s must have a parent \n " , node - > name ) ;
2013-07-15 13:14:20 +03:00
return ;
}
2017-02-09 11:24:37 +02:00
clk = _register_interface ( NULL , node - > name , parent_name , & reg ,
2014-12-16 18:20:49 +02:00
enable_bit , ops ) ;
if ( ! IS_ERR ( clk ) )
of_clk_add_provider ( node , of_clk_src_simple_get , clk ) ;
2013-07-15 13:14:20 +03: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 19:16:07 +02:00
# ifdef CONFIG_ARCH_OMAP3
2013-07-15 13:14:20 +03: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 19:16:07 +02: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