2012-09-11 22:56:23 +04:00
/*
* 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 .
*/
# include <linux/clk.h>
# include <linux/device.h>
# include <linux/export.h>
# include <linux/gfp.h>
static void devm_clk_release ( struct device * dev , void * res )
{
clk_put ( * ( struct clk * * ) res ) ;
}
struct clk * devm_clk_get ( struct device * dev , const char * id )
{
struct clk * * ptr , * clk ;
ptr = devres_alloc ( devm_clk_release , sizeof ( * ptr ) , GFP_KERNEL ) ;
if ( ! ptr )
return ERR_PTR ( - ENOMEM ) ;
clk = clk_get ( dev , id ) ;
if ( ! IS_ERR ( clk ) ) {
* ptr = clk ;
devres_add ( dev , ptr ) ;
} else {
devres_free ( ptr ) ;
}
return clk ;
}
EXPORT_SYMBOL ( devm_clk_get ) ;
2017-05-19 16:49:05 +03:00
struct clk_bulk_devres {
struct clk_bulk_data * clks ;
int num_clks ;
} ;
static void devm_clk_bulk_release ( struct device * dev , void * res )
{
struct clk_bulk_devres * devres = res ;
clk_bulk_put ( devres - > num_clks , devres - > clks ) ;
}
int __must_check devm_clk_bulk_get ( struct device * dev , int num_clks ,
struct clk_bulk_data * clks )
{
struct clk_bulk_devres * devres ;
int ret ;
devres = devres_alloc ( devm_clk_bulk_release ,
sizeof ( * devres ) , GFP_KERNEL ) ;
if ( ! devres )
return - ENOMEM ;
ret = clk_bulk_get ( dev , num_clks , clks ) ;
if ( ! ret ) {
devres - > clks = clks ;
devres - > num_clks = num_clks ;
devres_add ( dev , devres ) ;
} else {
devres_free ( devres ) ;
}
return ret ;
}
EXPORT_SYMBOL_GPL ( devm_clk_bulk_get ) ;
2012-09-11 22:56:23 +04:00
static int devm_clk_match ( struct device * dev , void * res , void * data )
{
struct clk * * c = res ;
if ( ! c | | ! * c ) {
WARN_ON ( ! c | | ! * c ) ;
return 0 ;
}
return * c = = data ;
}
void devm_clk_put ( struct device * dev , struct clk * clk )
{
int ret ;
2012-09-19 15:43:21 +04:00
ret = devres_release ( dev , devm_clk_release , devm_clk_match , clk ) ;
2012-09-11 22:56:23 +04:00
WARN_ON ( ret ) ;
}
EXPORT_SYMBOL ( devm_clk_put ) ;
2016-12-05 08:23:20 +03:00
struct clk * devm_get_clk_from_child ( struct device * dev ,
struct device_node * np , const char * con_id )
{
struct clk * * ptr , * clk ;
ptr = devres_alloc ( devm_clk_release , sizeof ( * ptr ) , GFP_KERNEL ) ;
if ( ! ptr )
return ERR_PTR ( - ENOMEM ) ;
clk = of_clk_get_by_name ( np , con_id ) ;
if ( ! IS_ERR ( clk ) ) {
* ptr = clk ;
devres_add ( dev , ptr ) ;
} else {
devres_free ( ptr ) ;
}
return clk ;
}
EXPORT_SYMBOL ( devm_get_clk_from_child ) ;