2014-09-05 16:21:34 +04:00
/*
* Copyright ( C ) 2013 - 2014 Texas Instruments Incorporated - http : //www.ti.com
2015-06-28 17:24:55 +03:00
*
* Authors :
* Jyri Sarha < jsarha @ ti . com >
* Sergej Sawazki < ce3a @ gmx . de >
2014-09-05 16:21:34 +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 .
*
2015-06-28 17:24:55 +03:00
* Gpio controlled clock implementation
2014-09-05 16:21:34 +04:00
*/
# include <linux/clk-provider.h>
2015-06-28 17:24:53 +03:00
# include <linux/export.h>
2014-09-05 16:21:34 +04:00
# include <linux/slab.h>
# include <linux/gpio.h>
2014-09-30 21:16:22 +04:00
# include <linux/gpio/consumer.h>
2014-09-05 16:21:34 +04:00
# include <linux/of_gpio.h>
# include <linux/err.h>
# include <linux/device.h>
/**
* DOC : basic gpio gated clock which can be enabled and disabled
* with gpio output
* Traits of this clock :
* prepare - clk_ ( un ) prepare only ensures parent is ( un ) prepared
* enable - clk_enable and clk_disable are functional & control gpio
* rate - inherits rate from parent . No clk_set_rate support
* parent - fixed parent . No clk_set_parent support
*/
# define to_clk_gpio(_hw) container_of(_hw, struct clk_gpio, hw)
static int clk_gpio_gate_enable ( struct clk_hw * hw )
{
struct clk_gpio * clk = to_clk_gpio ( hw ) ;
gpiod_set_value ( clk - > gpiod , 1 ) ;
return 0 ;
}
static void clk_gpio_gate_disable ( struct clk_hw * hw )
{
struct clk_gpio * clk = to_clk_gpio ( hw ) ;
gpiod_set_value ( clk - > gpiod , 0 ) ;
}
static int clk_gpio_gate_is_enabled ( struct clk_hw * hw )
{
struct clk_gpio * clk = to_clk_gpio ( hw ) ;
return gpiod_get_value ( clk - > gpiod ) ;
}
const struct clk_ops clk_gpio_gate_ops = {
. enable = clk_gpio_gate_enable ,
. disable = clk_gpio_gate_disable ,
. is_enabled = clk_gpio_gate_is_enabled ,
} ;
EXPORT_SYMBOL_GPL ( clk_gpio_gate_ops ) ;
/**
2015-06-28 17:24:55 +03:00
* DOC : basic clock multiplexer which can be controlled with a gpio output
* Traits of this clock :
* prepare - clk_prepare only ensures that parents are prepared
* rate - rate is only affected by parent switching . No clk_set_rate support
* parent - parent is adjustable through clk_set_parent
2014-09-05 16:21:34 +04:00
*/
2015-06-28 17:24:55 +03:00
static u8 clk_gpio_mux_get_parent ( struct clk_hw * hw )
2014-09-05 16:21:34 +04:00
{
2015-06-28 17:24:55 +03:00
struct clk_gpio * clk = to_clk_gpio ( hw ) ;
return gpiod_get_value ( clk - > gpiod ) ;
}
static int clk_gpio_mux_set_parent ( struct clk_hw * hw , u8 index )
{
struct clk_gpio * clk = to_clk_gpio ( hw ) ;
gpiod_set_value ( clk - > gpiod , index ) ;
return 0 ;
}
const struct clk_ops clk_gpio_mux_ops = {
. get_parent = clk_gpio_mux_get_parent ,
. set_parent = clk_gpio_mux_set_parent ,
. determine_rate = __clk_mux_determine_rate ,
} ;
EXPORT_SYMBOL_GPL ( clk_gpio_mux_ops ) ;
static struct clk * clk_register_gpio ( struct device * dev , const char * name ,
const char * * parent_names , u8 num_parents , unsigned gpio ,
bool active_low , unsigned long flags ,
const struct clk_ops * clk_gpio_ops )
{
struct clk_gpio * clk_gpio ;
struct clk * clk ;
struct clk_init_data init = { } ;
2014-09-05 16:21:34 +04:00
unsigned long gpio_flags ;
int err ;
2015-06-28 17:24:55 +03:00
if ( dev )
clk_gpio = devm_kzalloc ( dev , sizeof ( * clk_gpio ) , GFP_KERNEL ) ;
else
clk_gpio = kzalloc ( sizeof ( * clk_gpio ) , GFP_KERNEL ) ;
if ( ! clk_gpio )
return ERR_PTR ( - ENOMEM ) ;
2015-03-18 16:53:17 +03:00
if ( active_low )
gpio_flags = GPIOF_ACTIVE_LOW | GPIOF_OUT_INIT_HIGH ;
2014-09-05 16:21:34 +04:00
else
gpio_flags = GPIOF_OUT_INIT_LOW ;
if ( dev )
2015-03-18 16:53:17 +03:00
err = devm_gpio_request_one ( dev , gpio , gpio_flags , name ) ;
2014-09-05 16:21:34 +04:00
else
2015-03-18 16:53:17 +03:00
err = gpio_request_one ( gpio , gpio_flags , name ) ;
2014-09-05 16:21:34 +04:00
if ( err ) {
2015-06-28 17:24:54 +03:00
if ( err ! = - EPROBE_DEFER )
pr_err ( " %s: %s: Error requesting clock control gpio %u \n " ,
__func__ , name , gpio ) ;
2015-06-28 17:24:55 +03:00
if ( ! dev )
kfree ( clk_gpio ) ;
2014-09-05 16:21:34 +04:00
2015-06-28 17:24:55 +03:00
return ERR_PTR ( err ) ;
2014-09-05 16:21:34 +04:00
}
init . name = name ;
2015-06-28 17:24:55 +03:00
init . ops = clk_gpio_ops ;
2014-09-05 16:21:34 +04:00
init . flags = flags | CLK_IS_BASIC ;
2015-06-28 17:24:55 +03:00
init . parent_names = parent_names ;
init . num_parents = num_parents ;
2014-09-05 16:21:34 +04:00
2015-03-18 16:53:17 +03:00
clk_gpio - > gpiod = gpio_to_desc ( gpio ) ;
2014-09-05 16:21:34 +04:00
clk_gpio - > hw . init = & init ;
2015-06-28 17:24:55 +03:00
if ( dev )
clk = devm_clk_register ( dev , & clk_gpio - > hw ) ;
else
clk = clk_register ( NULL , & clk_gpio - > hw ) ;
2014-09-05 16:21:34 +04:00
if ( ! IS_ERR ( clk ) )
return clk ;
2015-06-28 17:24:55 +03:00
if ( ! dev ) {
gpiod_put ( clk_gpio - > gpiod ) ;
2014-09-05 16:21:34 +04:00
kfree ( clk_gpio ) ;
2015-06-28 17:24:55 +03:00
}
2014-09-05 16:21:34 +04:00
return clk ;
}
2015-06-28 17:24:55 +03:00
/**
* clk_register_gpio_gate - register a gpio clock gate with the clock framework
* @ dev : device that is registering this clock
* @ name : name of this clock
* @ parent_name : name of this clock ' s parent
* @ gpio : gpio number to gate this clock
* @ active_low : true if gpio should be set to 0 to enable clock
* @ flags : clock flags
*/
struct clk * clk_register_gpio_gate ( struct device * dev , const char * name ,
const char * parent_name , unsigned gpio , bool active_low ,
unsigned long flags )
{
return clk_register_gpio ( dev , name ,
( parent_name ? & parent_name : NULL ) ,
( parent_name ? 1 : 0 ) , gpio , active_low , flags ,
& clk_gpio_gate_ops ) ;
}
2014-09-05 16:21:34 +04:00
EXPORT_SYMBOL_GPL ( clk_register_gpio_gate ) ;
2015-06-28 17:24:55 +03:00
/**
* clk_register_gpio_mux - register a gpio clock mux with the clock framework
* @ dev : device that is registering this clock
* @ name : name of this clock
* @ parent_names : names of this clock ' s parents
* @ num_parents : number of parents listed in @ parent_names
* @ gpio : gpio number to gate this clock
* @ active_low : true if gpio should be set to 0 to enable clock
* @ flags : clock flags
*/
struct clk * clk_register_gpio_mux ( struct device * dev , const char * name ,
const char * * parent_names , u8 num_parents , unsigned gpio ,
bool active_low , unsigned long flags )
{
if ( num_parents ! = 2 ) {
pr_err ( " mux-clock %s must have 2 parents \n " , name ) ;
return ERR_PTR ( - EINVAL ) ;
}
return clk_register_gpio ( dev , name , parent_names , num_parents ,
gpio , active_low , flags , & clk_gpio_mux_ops ) ;
}
EXPORT_SYMBOL_GPL ( clk_register_gpio_mux ) ;
2014-09-05 16:21:34 +04:00
# ifdef CONFIG_OF
/**
2015-06-28 17:24:55 +03:00
* clk_register_get ( ) has to be delayed , because - EPROBE_DEFER
2014-09-05 16:21:34 +04:00
* can not be handled properly at of_clk_init ( ) call time .
*/
2015-06-28 17:24:55 +03:00
struct clk_gpio_delayed_register_data {
const char * gpio_name ;
2014-09-05 16:21:34 +04:00
struct device_node * node ;
struct mutex lock ;
struct clk * clk ;
2015-06-28 17:24:55 +03:00
struct clk * ( * clk_register_get ) ( const char * name ,
const char * * parent_names , u8 num_parents ,
unsigned gpio , bool active_low ) ;
2014-09-05 16:21:34 +04:00
} ;
2015-06-28 17:24:55 +03:00
static struct clk * of_clk_gpio_delayed_register_get (
struct of_phandle_args * clkspec , void * _data )
2014-09-05 16:21:34 +04:00
{
2015-06-28 17:24:55 +03:00
struct clk_gpio_delayed_register_data * data = _data ;
2014-09-05 16:21:34 +04:00
struct clk * clk ;
2015-06-28 17:24:55 +03:00
const char * * parent_names ;
int i , num_parents ;
2014-09-05 16:21:34 +04:00
int gpio ;
2015-03-18 16:53:17 +03:00
enum of_gpio_flags of_flags ;
2014-09-05 16:21:34 +04:00
mutex_lock ( & data - > lock ) ;
if ( data - > clk ) {
mutex_unlock ( & data - > lock ) ;
return data - > clk ;
}
2015-06-28 17:24:55 +03:00
gpio = of_get_named_gpio_flags ( data - > node , data - > gpio_name , 0 ,
& of_flags ) ;
2014-09-05 16:21:34 +04:00
if ( gpio < 0 ) {
mutex_unlock ( & data - > lock ) ;
2015-06-28 17:24:55 +03:00
if ( gpio = = - EPROBE_DEFER )
pr_debug ( " %s: %s: GPIOs not yet available, retry later \n " ,
data - > node - > name , __func__ ) ;
else
pr_err ( " %s: %s: Can't get '%s' DT property \n " ,
data - > node - > name , __func__ ,
data - > gpio_name ) ;
2014-09-05 16:21:34 +04:00
return ERR_PTR ( gpio ) ;
}
2015-06-28 17:24:55 +03:00
num_parents = of_clk_get_parent_count ( data - > node ) ;
2014-09-05 16:21:34 +04:00
2015-06-28 17:24:55 +03:00
parent_names = kcalloc ( num_parents , sizeof ( char * ) , GFP_KERNEL ) ;
2015-07-14 22:45:19 +03:00
if ( ! parent_names ) {
clk = ERR_PTR ( - ENOMEM ) ;
goto out ;
}
2015-06-28 17:24:55 +03:00
for ( i = 0 ; i < num_parents ; i + + )
parent_names [ i ] = of_clk_get_parent_name ( data - > node , i ) ;
clk = data - > clk_register_get ( data - > node - > name , parent_names ,
num_parents , gpio , of_flags & OF_GPIO_ACTIVE_LOW ) ;
if ( IS_ERR ( clk ) )
goto out ;
2014-09-05 16:21:34 +04:00
data - > clk = clk ;
2015-06-28 17:24:55 +03:00
out :
2014-09-05 16:21:34 +04:00
mutex_unlock ( & data - > lock ) ;
2015-06-28 17:24:55 +03:00
kfree ( parent_names ) ;
2014-09-05 16:21:34 +04:00
return clk ;
}
2015-06-28 17:24:55 +03:00
static struct clk * of_clk_gpio_gate_delayed_register_get ( const char * name ,
const char * * parent_names , u8 num_parents ,
unsigned gpio , bool active_low )
{
return clk_register_gpio_gate ( NULL , name , parent_names [ 0 ] ,
gpio , active_low , 0 ) ;
}
static struct clk * of_clk_gpio_mux_delayed_register_get ( const char * name ,
const char * * parent_names , u8 num_parents , unsigned gpio ,
bool active_low )
{
return clk_register_gpio_mux ( NULL , name , parent_names , num_parents ,
gpio , active_low , 0 ) ;
}
static void __init of_gpio_clk_setup ( struct device_node * node ,
const char * gpio_name ,
struct clk * ( * clk_register_get ) ( const char * name ,
const char * * parent_names , u8 num_parents ,
unsigned gpio , bool active_low ) )
2014-09-05 16:21:34 +04:00
{
2015-06-28 17:24:55 +03:00
struct clk_gpio_delayed_register_data * data ;
2014-09-05 16:21:34 +04:00
2015-06-28 17:24:55 +03:00
data = kzalloc ( sizeof ( * data ) , GFP_KERNEL ) ;
2014-09-05 16:21:34 +04:00
if ( ! data )
return ;
data - > node = node ;
2015-06-28 17:24:55 +03:00
data - > gpio_name = gpio_name ;
data - > clk_register_get = clk_register_get ;
2014-09-05 16:21:34 +04:00
mutex_init ( & data - > lock ) ;
2015-06-28 17:24:55 +03:00
of_clk_add_provider ( node , of_clk_gpio_delayed_register_get , data ) ;
}
static void __init of_gpio_gate_clk_setup ( struct device_node * node )
{
of_gpio_clk_setup ( node , " enable-gpios " ,
of_clk_gpio_gate_delayed_register_get ) ;
2014-09-05 16:21:34 +04:00
}
CLK_OF_DECLARE ( gpio_gate_clk , " gpio-gate-clock " , of_gpio_gate_clk_setup ) ;
2015-06-28 17:24:55 +03:00
void __init of_gpio_mux_clk_setup ( struct device_node * node )
{
of_gpio_clk_setup ( node , " select-gpios " ,
of_clk_gpio_mux_delayed_register_get ) ;
}
CLK_OF_DECLARE ( gpio_mux_clk , " gpio-mux-clock " , of_gpio_mux_clk_setup ) ;
2014-09-05 16:21:34 +04:00
# endif