2018-12-11 09:57:48 -08:00
// SPDX-License-Identifier: GPL-2.0
2014-09-05 15:21:34 +03:00
/*
2020-07-03 19:51:14 +02:00
* Copyright ( C ) 2013 - 2014 Texas Instruments Incorporated - https : //www.ti.com
2015-06-28 16:24:55 +02:00
*
* Authors :
* Jyri Sarha < jsarha @ ti . com >
* Sergej Sawazki < ce3a @ gmx . de >
2014-09-05 15:21:34 +03:00
*
2015-06-28 16:24:55 +02:00
* Gpio controlled clock implementation
2014-09-05 15:21:34 +03:00
*/
# include <linux/clk-provider.h>
2015-06-28 16:24:53 +02:00
# include <linux/export.h>
2014-09-05 15:21:34 +03:00
# include <linux/slab.h>
2014-09-30 18:16:22 +01:00
# include <linux/gpio/consumer.h>
2014-09-05 15:21:34 +03:00
# include <linux/err.h>
# include <linux/device.h>
2016-02-02 17:09:26 -08:00
# include <linux/platform_device.h>
# include <linux/of_device.h>
2014-09-05 15:21:34 +03:00
/**
* 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
*/
2019-08-30 08:09:12 -07:00
/**
* struct clk_gpio - gpio gated clock
*
* @ hw : handle between common and hardware - specific interfaces
* @ gpiod : gpio descriptor
*
* Clock with a gpio control for enabling and disabling the parent clock
* or switching between two parents by asserting or deasserting the gpio .
*
* Implements . enable , . disable and . is_enabled or
* . get_parent , . set_parent and . determine_rate depending on which clk_ops
* is used .
*/
struct clk_gpio {
struct clk_hw hw ;
struct gpio_desc * gpiod ;
} ;
# define to_clk_gpio(_hw) container_of(_hw, struct clk_gpio, hw)
2014-09-05 15:21:34 +03:00
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 ) ;
}
2019-08-30 08:09:12 -07:00
static const struct clk_ops clk_gpio_gate_ops = {
2014-09-05 15:21:34 +03:00
. enable = clk_gpio_gate_enable ,
. disable = clk_gpio_gate_disable ,
. is_enabled = clk_gpio_gate_is_enabled ,
} ;
2019-02-11 14:58:18 +01:00
static int clk_sleeping_gpio_gate_prepare ( struct clk_hw * hw )
{
struct clk_gpio * clk = to_clk_gpio ( hw ) ;
gpiod_set_value_cansleep ( clk - > gpiod , 1 ) ;
return 0 ;
}
static void clk_sleeping_gpio_gate_unprepare ( struct clk_hw * hw )
{
struct clk_gpio * clk = to_clk_gpio ( hw ) ;
gpiod_set_value_cansleep ( clk - > gpiod , 0 ) ;
}
static int clk_sleeping_gpio_gate_is_prepared ( struct clk_hw * hw )
{
struct clk_gpio * clk = to_clk_gpio ( hw ) ;
return gpiod_get_value_cansleep ( clk - > gpiod ) ;
}
static const struct clk_ops clk_sleeping_gpio_gate_ops = {
. prepare = clk_sleeping_gpio_gate_prepare ,
. unprepare = clk_sleeping_gpio_gate_unprepare ,
. is_prepared = clk_sleeping_gpio_gate_is_prepared ,
} ;
2014-09-05 15:21:34 +03:00
/**
2015-06-28 16:24:55 +02: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 15:21:34 +03:00
*/
2015-06-28 16:24:55 +02:00
static u8 clk_gpio_mux_get_parent ( struct clk_hw * hw )
2014-09-05 15:21:34 +03:00
{
2015-06-28 16:24:55 +02:00
struct clk_gpio * clk = to_clk_gpio ( hw ) ;
2018-03-13 09:54:03 +01:00
return gpiod_get_value_cansleep ( clk - > gpiod ) ;
2015-06-28 16:24:55 +02:00
}
static int clk_gpio_mux_set_parent ( struct clk_hw * hw , u8 index )
{
struct clk_gpio * clk = to_clk_gpio ( hw ) ;
2018-03-13 09:54:03 +01:00
gpiod_set_value_cansleep ( clk - > gpiod , index ) ;
2015-06-28 16:24:55 +02:00
return 0 ;
}
2019-08-30 08:09:12 -07:00
static const struct clk_ops clk_gpio_mux_ops = {
2015-06-28 16:24:55 +02:00
. get_parent = clk_gpio_mux_get_parent ,
. set_parent = clk_gpio_mux_set_parent ,
. determine_rate = __clk_mux_determine_rate ,
} ;
2019-08-30 08:09:12 -07:00
static struct clk_hw * clk_register_gpio ( struct device * dev , u8 num_parents ,
struct gpio_desc * gpiod ,
const struct clk_ops * clk_gpio_ops )
2015-06-28 16:24:55 +02:00
{
struct clk_gpio * clk_gpio ;
2016-02-07 00:27:55 -08:00
struct clk_hw * hw ;
2015-06-28 16:24:55 +02:00
struct clk_init_data init = { } ;
2014-09-05 15:21:34 +03:00
int err ;
2019-08-30 08:09:12 -07:00
const struct clk_parent_data gpio_parent_data [ ] = {
{ . index = 0 } ,
{ . index = 1 } ,
} ;
2014-09-05 15:21:34 +03:00
2019-08-30 08:09:12 -07:00
clk_gpio = devm_kzalloc ( dev , sizeof ( * clk_gpio ) , GFP_KERNEL ) ;
2015-06-28 16:24:55 +02:00
if ( ! clk_gpio )
return ERR_PTR ( - ENOMEM ) ;
2019-08-30 08:09:12 -07:00
init . name = dev - > of_node - > name ;
2015-06-28 16:24:55 +02:00
init . ops = clk_gpio_ops ;
2019-08-30 08:09:12 -07:00
init . parent_data = gpio_parent_data ;
2015-06-28 16:24:55 +02:00
init . num_parents = num_parents ;
2019-08-30 08:09:12 -07:00
init . flags = CLK_SET_RATE_PARENT ;
2014-09-05 15:21:34 +03:00
2017-09-24 18:19:18 +02:00
clk_gpio - > gpiod = gpiod ;
2014-09-05 15:21:34 +03:00
clk_gpio - > hw . init = & init ;
2016-02-07 00:27:55 -08:00
hw = & clk_gpio - > hw ;
2019-08-30 08:09:12 -07:00
err = devm_clk_hw_register ( dev , hw ) ;
if ( err )
return ERR_PTR ( err ) ;
2014-09-05 15:21:34 +03:00
2019-08-30 08:09:12 -07:00
return hw ;
2014-09-05 15:21:34 +03:00
}
2015-06-28 16:24:55 +02:00
2019-08-30 08:09:12 -07:00
static struct clk_hw * clk_hw_register_gpio_gate ( struct device * dev ,
int num_parents ,
struct gpio_desc * gpiod )
2015-06-28 16:24:55 +02:00
{
2019-02-11 14:58:18 +01:00
const struct clk_ops * ops ;
if ( gpiod_cansleep ( gpiod ) )
ops = & clk_sleeping_gpio_gate_ops ;
else
ops = & clk_gpio_gate_ops ;
2019-08-30 08:09:12 -07:00
return clk_register_gpio ( dev , num_parents , gpiod , ops ) ;
2015-06-28 16:24:55 +02:00
}
2016-02-07 00:27:55 -08:00
2019-08-30 08:09:12 -07:00
static struct clk_hw * clk_hw_register_gpio_mux ( struct device * dev ,
struct gpio_desc * gpiod )
2016-02-07 00:27:55 -08:00
{
2019-08-30 08:09:12 -07:00
return clk_register_gpio ( dev , 2 , gpiod , & clk_gpio_mux_ops ) ;
2016-02-07 00:27:55 -08:00
}
2015-06-28 16:24:55 +02:00
2016-02-02 17:09:26 -08:00
static int gpio_clk_driver_probe ( struct platform_device * pdev )
2014-09-05 15:21:34 +03:00
{
2019-08-30 08:09:12 -07:00
struct device * dev = & pdev - > dev ;
struct device_node * node = dev - > of_node ;
const char * gpio_name ;
2016-02-19 17:31:52 -08:00
unsigned int num_parents ;
2017-09-24 18:19:18 +02:00
struct gpio_desc * gpiod ;
2019-08-30 08:09:12 -07:00
struct clk_hw * hw ;
2017-09-24 18:19:18 +02:00
bool is_mux ;
int ret ;
2016-02-02 17:09:26 -08:00
2019-08-30 08:09:12 -07:00
is_mux = of_device_is_compatible ( node , " gpio-mux-clock " ) ;
2016-02-02 17:09:26 -08:00
num_parents = of_clk_get_parent_count ( node ) ;
2019-08-30 08:09:12 -07:00
if ( is_mux & & num_parents ! = 2 ) {
dev_err ( dev , " mux-clock must have 2 parents \n " ) ;
return - EINVAL ;
2014-09-05 15:21:34 +03:00
}
2017-09-24 18:19:18 +02:00
gpio_name = is_mux ? " select " : " enable " ;
2019-08-30 08:09:12 -07:00
gpiod = devm_gpiod_get ( dev , gpio_name , GPIOD_OUT_LOW ) ;
2017-09-24 18:19:18 +02:00
if ( IS_ERR ( gpiod ) ) {
ret = PTR_ERR ( gpiod ) ;
if ( ret = = - EPROBE_DEFER )
2018-08-28 10:44:29 -05:00
pr_debug ( " %pOFn: %s: GPIOs not yet available, retry later \n " ,
node , __func__ ) ;
2015-06-28 16:24:55 +02:00
else
2018-08-28 10:44:29 -05:00
pr_err ( " %pOFn: %s: Can't get '%s' named GPIO property \n " ,
node , __func__ ,
2016-02-02 17:09:26 -08:00
gpio_name ) ;
2017-09-24 18:19:18 +02:00
return ret ;
2014-09-05 15:21:34 +03:00
}
2016-02-02 17:09:26 -08:00
if ( is_mux )
2019-08-30 08:09:12 -07:00
hw = clk_hw_register_gpio_mux ( dev , gpiod ) ;
2016-02-02 17:09:26 -08:00
else
2019-08-30 08:09:12 -07:00
hw = clk_hw_register_gpio_gate ( dev , num_parents , gpiod ) ;
if ( IS_ERR ( hw ) )
return PTR_ERR ( hw ) ;
2014-09-05 15:21:34 +03:00
2019-08-30 08:09:12 -07:00
return devm_of_clk_add_hw_provider ( dev , of_clk_hw_simple_get , hw ) ;
2015-06-28 16:24:55 +02:00
}
2016-02-02 17:09:26 -08:00
static const struct of_device_id gpio_clk_match_table [ ] = {
{ . compatible = " gpio-mux-clock " } ,
{ . compatible = " gpio-gate-clock " } ,
{ }
} ;
2015-06-28 16:24:55 +02:00
2016-02-02 17:09:26 -08:00
static struct platform_driver gpio_clk_driver = {
. probe = gpio_clk_driver_probe ,
. driver = {
. name = " gpio-clk " ,
. of_match_table = gpio_clk_match_table ,
} ,
} ;
builtin_platform_driver ( gpio_clk_driver ) ;