2008-11-09 19:32:46 +03:00
/*
2010-11-17 12:04:33 +03:00
* drivers / clk / clkdev . c
2008-11-09 19:32:46 +03:00
*
* Copyright ( C ) 2008 Russell King .
*
* 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 .
*
* Helper for the clk API to assist looking up a struct clk .
*/
# include <linux/module.h>
# include <linux/kernel.h>
# include <linux/device.h>
# include <linux/list.h>
# include <linux/errno.h>
# include <linux/err.h>
# include <linux/string.h>
# include <linux/mutex.h>
2009-08-05 02:38:06 +04:00
# include <linux/clk.h>
2010-11-17 12:04:33 +03:00
# include <linux/clkdev.h>
2015-01-23 14:03:30 +03:00
# include <linux/clk-provider.h>
2012-04-09 23:50:06 +04:00
# include <linux/of.h>
2008-11-09 19:32:46 +03:00
2013-08-23 19:03:44 +04:00
# include "clk.h"
2008-11-09 19:32:46 +03:00
static LIST_HEAD ( clocks ) ;
static DEFINE_MUTEX ( clocks_mutex ) ;
2012-07-18 07:52:23 +04:00
# if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK)
2015-02-06 22:42:43 +03:00
static struct clk * __of_clk_get ( struct device_node * np , int index ,
const char * dev_id , const char * con_id )
2012-04-09 23:50:06 +04:00
{
struct of_phandle_args clkspec ;
struct clk * clk ;
int rc ;
if ( index < 0 )
return ERR_PTR ( - EINVAL ) ;
rc = of_parse_phandle_with_args ( np , " clocks " , " #clock-cells " , index ,
& clkspec ) ;
if ( rc )
return ERR_PTR ( rc ) ;
2015-02-06 02:39:11 +03:00
clk = __of_clk_get_from_provider ( & clkspec , dev_id , con_id ) ;
2012-04-09 23:50:06 +04:00
of_node_put ( clkspec . np ) ;
2015-01-23 14:03:30 +03:00
return clk ;
}
struct clk * of_clk_get ( struct device_node * np , int index )
{
2015-02-06 22:42:43 +03:00
return __of_clk_get ( np , index , np - > full_name , NULL ) ;
2012-04-09 23:50:06 +04:00
}
EXPORT_SYMBOL ( of_clk_get ) ;
2015-01-23 14:03:30 +03:00
static struct clk * __of_clk_get_by_name ( struct device_node * np ,
const char * dev_id ,
const char * name )
2012-04-09 23:50:06 +04:00
{
struct clk * clk = ERR_PTR ( - ENOENT ) ;
/* Walk up the tree of devices looking for a clock that matches */
while ( np ) {
int index = 0 ;
/*
* For named clocks , first look up the name in the
* " clock-names " property . If it cannot be found , then
* index will be an error code , and of_clk_get ( ) will fail .
*/
if ( name )
index = of_property_match_string ( np , " clock-names " , name ) ;
2015-02-06 22:42:43 +03:00
clk = __of_clk_get ( np , index , dev_id , name ) ;
2015-01-23 14:03:30 +03:00
if ( ! IS_ERR ( clk ) ) {
2012-04-09 23:50:06 +04:00
break ;
2015-02-06 22:42:43 +03:00
} else if ( name & & index > = 0 ) {
2014-06-14 03:36:31 +04:00
if ( PTR_ERR ( clk ) ! = - EPROBE_DEFER )
pr_err ( " ERROR: could not get clock %s:%s(%i) \n " ,
np - > full_name , name ? name : " " , index ) ;
2012-04-09 23:50:06 +04:00
return clk ;
}
/*
* No matching clock found on this node . If the parent node
* has a " clock-ranges " property , then we can try one of its
* clocks .
*/
np = np - > parent ;
if ( np & & ! of_get_property ( np , " clock-ranges " , NULL ) )
break ;
}
return clk ;
}
2015-01-23 14:03:30 +03:00
/**
* of_clk_get_by_name ( ) - Parse and lookup a clock referenced by a device node
* @ np : pointer to clock consumer node
* @ name : name of consumer ' s clock input , or NULL for the first clock reference
*
* This function parses the clocks and clock - names properties ,
* and uses them to look up the struct clk from the registered list of clock
* providers .
*/
struct clk * of_clk_get_by_name ( struct device_node * np , const char * name )
{
if ( ! np )
return ERR_PTR ( - ENOENT ) ;
return __of_clk_get_by_name ( np , np - > full_name , name ) ;
}
2012-04-09 23:50:06 +04:00
EXPORT_SYMBOL ( of_clk_get_by_name ) ;
2015-01-23 14:03:30 +03:00
# else /* defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) */
static struct clk * __of_clk_get_by_name ( struct device_node * np ,
const char * dev_id ,
const char * name )
{
return ERR_PTR ( - ENOENT ) ;
}
2012-04-09 23:50:06 +04:00
# endif
2009-01-24 13:14:37 +03:00
/*
* Find the correct struct clk for the device and connection ID .
* We do slightly fuzzy matching here :
* An entry with a NULL ID is assumed to be a wildcard .
* If an entry has a device ID , it must match
* If an entry has a connection ID , it must match
* Then we take the most specific entry - with the following
2010-01-18 18:02:48 +03:00
* order of precedence : dev + con > dev only > con only .
2009-01-24 13:14:37 +03:00
*/
2011-04-30 13:14:08 +04:00
static struct clk_lookup * clk_find ( const char * dev_id , const char * con_id )
2008-11-09 19:32:46 +03:00
{
2011-04-30 13:14:08 +04:00
struct clk_lookup * p , * cl = NULL ;
2012-04-19 07:23:25 +04:00
int match , best_found = 0 , best_possible = 0 ;
if ( dev_id )
best_possible + = 2 ;
if ( con_id )
best_possible + = 1 ;
2008-11-09 19:32:46 +03:00
list_for_each_entry ( p , & clocks , node ) {
match = 0 ;
2009-01-24 13:14:37 +03:00
if ( p - > dev_id ) {
if ( ! dev_id | | strcmp ( p - > dev_id , dev_id ) )
continue ;
match + = 2 ;
}
if ( p - > con_id ) {
if ( ! con_id | | strcmp ( p - > con_id , con_id ) )
continue ;
match + = 1 ;
}
2008-11-09 19:32:46 +03:00
2012-04-19 07:23:25 +04:00
if ( match > best_found ) {
2011-04-30 13:14:08 +04:00
cl = p ;
2012-04-19 07:23:25 +04:00
if ( match ! = best_possible )
best_found = match ;
2010-03-09 13:54:30 +03:00
else
break ;
2008-11-09 19:32:46 +03:00
}
}
2011-04-30 13:14:08 +04:00
return cl ;
2008-11-09 19:32:46 +03:00
}
2009-03-07 14:55:49 +03:00
struct clk * clk_get_sys ( const char * dev_id , const char * con_id )
2008-11-09 19:32:46 +03:00
{
2011-04-30 13:14:08 +04:00
struct clk_lookup * cl ;
2015-01-23 14:03:30 +03:00
struct clk * clk = NULL ;
2008-11-09 19:32:46 +03:00
mutex_lock ( & clocks_mutex ) ;
2015-01-23 14:03:30 +03:00
2011-04-30 13:14:08 +04:00
cl = clk_find ( dev_id , con_id ) ;
2015-01-23 14:03:30 +03:00
if ( ! cl )
goto out ;
2015-03-02 18:45:41 +03:00
clk = __clk_create_clk ( cl - > clk_hw , dev_id , con_id ) ;
2015-02-06 22:42:43 +03:00
if ( IS_ERR ( clk ) )
goto out ;
if ( ! __clk_get ( clk ) ) {
__clk_free_clk ( clk ) ;
2011-04-30 13:14:08 +04:00
cl = NULL ;
2015-01-23 14:03:30 +03:00
goto out ;
}
out :
2008-11-09 19:32:46 +03:00
mutex_unlock ( & clocks_mutex ) ;
2015-01-23 14:03:30 +03:00
return cl ? clk : ERR_PTR ( - ENOENT ) ;
2008-11-09 19:32:46 +03:00
}
2009-03-07 14:55:49 +03:00
EXPORT_SYMBOL ( clk_get_sys ) ;
struct clk * clk_get ( struct device * dev , const char * con_id )
{
const char * dev_id = dev ? dev_name ( dev ) : NULL ;
2012-04-09 23:50:06 +04:00
struct clk * clk ;
if ( dev ) {
2015-01-23 14:03:30 +03:00
clk = __of_clk_get_by_name ( dev - > of_node , dev_id , con_id ) ;
if ( ! IS_ERR ( clk ) | | PTR_ERR ( clk ) = = - EPROBE_DEFER )
2013-11-25 22:47:04 +04:00
return clk ;
2012-04-09 23:50:06 +04:00
}
2009-03-07 14:55:49 +03:00
return clk_get_sys ( dev_id , con_id ) ;
}
2008-11-09 19:32:46 +03:00
EXPORT_SYMBOL ( clk_get ) ;
void clk_put ( struct clk * clk )
{
__clk_put ( clk ) ;
}
EXPORT_SYMBOL ( clk_put ) ;
2015-03-02 18:45:41 +03:00
static void __clkdev_add ( struct clk_lookup * cl )
2008-11-09 19:32:46 +03:00
{
mutex_lock ( & clocks_mutex ) ;
list_add_tail ( & cl - > node , & clocks ) ;
mutex_unlock ( & clocks_mutex ) ;
}
2015-03-02 18:45:41 +03:00
void clkdev_add ( struct clk_lookup * cl )
{
if ( ! cl - > clk_hw )
cl - > clk_hw = __clk_get_hw ( cl - > clk ) ;
__clkdev_add ( cl ) ;
}
2008-11-09 19:32:46 +03:00
EXPORT_SYMBOL ( clkdev_add ) ;
2015-03-10 17:34:00 +03:00
void clkdev_add_table ( struct clk_lookup * cl , size_t num )
2010-01-12 15:28:00 +03:00
{
mutex_lock ( & clocks_mutex ) ;
while ( num - - ) {
2015-03-02 18:45:41 +03:00
cl - > clk_hw = __clk_get_hw ( cl - > clk ) ;
2010-01-12 15:28:00 +03:00
list_add_tail ( & cl - > node , & clocks ) ;
cl + + ;
}
mutex_unlock ( & clocks_mutex ) ;
}
2008-11-09 19:32:46 +03:00
# define MAX_DEV_ID 20
# define MAX_CON_ID 16
struct clk_lookup_alloc {
struct clk_lookup cl ;
char dev_id [ MAX_DEV_ID ] ;
char con_id [ MAX_CON_ID ] ;
} ;
2012-05-02 12:30:32 +04:00
static struct clk_lookup * __init_refok
2015-03-02 18:45:41 +03:00
vclkdev_alloc ( struct clk_hw * hw , const char * con_id , const char * dev_fmt ,
2012-05-02 12:30:32 +04:00
va_list ap )
2008-11-09 19:32:46 +03:00
{
struct clk_lookup_alloc * cla ;
2010-11-17 12:04:33 +03:00
cla = __clkdev_alloc ( sizeof ( * cla ) ) ;
2008-11-09 19:32:46 +03:00
if ( ! cla )
return NULL ;
2015-03-02 18:45:41 +03:00
cla - > cl . clk_hw = hw ;
2008-11-09 19:32:46 +03:00
if ( con_id ) {
strlcpy ( cla - > con_id , con_id , sizeof ( cla - > con_id ) ) ;
cla - > cl . con_id = cla - > con_id ;
}
if ( dev_fmt ) {
vscnprintf ( cla - > dev_id , sizeof ( cla - > dev_id ) , dev_fmt , ap ) ;
cla - > cl . dev_id = cla - > dev_id ;
}
return & cla - > cl ;
}
2012-05-02 12:30:32 +04:00
2015-03-02 18:40:29 +03:00
static struct clk_lookup *
vclkdev_create ( struct clk_hw * hw , const char * con_id , const char * dev_fmt ,
va_list ap )
{
struct clk_lookup * cl ;
cl = vclkdev_alloc ( hw , con_id , dev_fmt , ap ) ;
if ( cl )
__clkdev_add ( cl ) ;
return cl ;
}
2012-05-02 12:30:32 +04:00
struct clk_lookup * __init_refok
clkdev_alloc ( struct clk * clk , const char * con_id , const char * dev_fmt , . . . )
{
struct clk_lookup * cl ;
va_list ap ;
va_start ( ap , dev_fmt ) ;
2015-03-02 18:45:41 +03:00
cl = vclkdev_alloc ( __clk_get_hw ( clk ) , con_id , dev_fmt , ap ) ;
2012-05-02 12:30:32 +04:00
va_end ( ap ) ;
return cl ;
}
2008-11-09 19:32:46 +03:00
EXPORT_SYMBOL ( clkdev_alloc ) ;
2015-03-02 18:40:29 +03:00
/**
* clkdev_create - allocate and add a clkdev lookup structure
* @ clk : struct clk to associate with all clk_lookups
* @ con_id : connection ID string on device
* @ dev_fmt : format string describing device name
*
* Returns a clk_lookup structure , which can be later unregistered and
* freed .
*/
struct clk_lookup * clkdev_create ( struct clk * clk , const char * con_id ,
const char * dev_fmt , . . . )
{
struct clk_lookup * cl ;
va_list ap ;
va_start ( ap , dev_fmt ) ;
cl = vclkdev_create ( __clk_get_hw ( clk ) , con_id , dev_fmt , ap ) ;
va_end ( ap ) ;
return cl ;
}
EXPORT_SYMBOL_GPL ( clkdev_create ) ;
2015-03-09 13:43:04 +03:00
int clk_add_alias ( const char * alias , const char * alias_dev_name ,
const char * con_id , struct device * dev )
2009-06-03 20:43:14 +04:00
{
2015-03-09 13:43:04 +03:00
struct clk * r = clk_get ( dev , con_id ) ;
2009-06-03 20:43:14 +04:00
struct clk_lookup * l ;
if ( IS_ERR ( r ) )
return PTR_ERR ( r ) ;
2015-10-20 13:49:44 +03:00
l = clkdev_create ( r , alias , alias_dev_name ? " %s " : NULL ,
alias_dev_name ) ;
2009-06-03 20:43:14 +04:00
clk_put ( r ) ;
2015-03-02 18:40:29 +03:00
return l ? 0 : - ENODEV ;
2009-06-03 20:43:14 +04:00
}
EXPORT_SYMBOL ( clk_add_alias ) ;
2008-11-09 19:32:46 +03:00
/*
* clkdev_drop - remove a clock dynamically allocated
*/
void clkdev_drop ( struct clk_lookup * cl )
{
mutex_lock ( & clocks_mutex ) ;
list_del ( & cl - > node ) ;
mutex_unlock ( & clocks_mutex ) ;
kfree ( cl ) ;
}
EXPORT_SYMBOL ( clkdev_drop ) ;
2012-05-02 12:30:32 +04:00
/**
* clk_register_clkdev - register one clock lookup for a struct clk
* @ clk : struct clk to associate with all clk_lookups
* @ con_id : connection ID string on device
* @ dev_id : format string describing device name
*
* con_id or dev_id may be NULL as a wildcard , just as in the rest of
* clkdev .
*
* To make things easier for mass registration , we detect error clks
* from a previous clk_register ( ) call , and return the error code for
* those . This is to permit this function to be called immediately
* after clk_register ( ) .
*/
int clk_register_clkdev ( struct clk * clk , const char * con_id ,
const char * dev_fmt , . . . )
{
struct clk_lookup * cl ;
va_list ap ;
if ( IS_ERR ( clk ) )
return PTR_ERR ( clk ) ;
va_start ( ap , dev_fmt ) ;
2015-03-02 18:40:29 +03:00
cl = vclkdev_create ( __clk_get_hw ( clk ) , con_id , dev_fmt , ap ) ;
2012-05-02 12:30:32 +04:00
va_end ( ap ) ;
2015-03-02 18:40:29 +03:00
return cl ? 0 : - ENOMEM ;
2012-05-02 12:30:32 +04:00
}
2015-01-23 14:03:32 +03:00
EXPORT_SYMBOL ( clk_register_clkdev ) ;
2012-05-02 12:30:32 +04:00
/**
* clk_register_clkdevs - register a set of clk_lookup for a struct clk
* @ clk : struct clk to associate with all clk_lookups
* @ cl : array of clk_lookup structures with con_id and dev_id pre - initialized
* @ num : number of clk_lookup structures to register
*
* To make things easier for mass registration , we detect error clks
* from a previous clk_register ( ) call , and return the error code for
* those . This is to permit this function to be called immediately
* after clk_register ( ) .
*/
int clk_register_clkdevs ( struct clk * clk , struct clk_lookup * cl , size_t num )
{
unsigned i ;
if ( IS_ERR ( clk ) )
return PTR_ERR ( clk ) ;
for ( i = 0 ; i < num ; i + + , cl + + ) {
2015-03-02 18:45:41 +03:00
cl - > clk_hw = __clk_get_hw ( clk ) ;
__clkdev_add ( cl ) ;
2012-05-02 12:30:32 +04:00
}
return 0 ;
}
EXPORT_SYMBOL ( clk_register_clkdevs ) ;