2019-05-28 20:10:04 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2012-03-23 20:29:46 +04:00
/*
* Device tree integration for the pin control subsystem
*
* Copyright ( C ) 2012 NVIDIA CORPORATION . All rights reserved .
*/
# include <linux/device.h>
# include <linux/of.h>
# include <linux/pinctrl/pinctrl.h>
# include <linux/slab.h>
# include "core.h"
# include "devicetree.h"
/**
* struct pinctrl_dt_map - mapping table chunk parsed from device tree
* @ node : list node for struct pinctrl ' s @ dt_maps field
* @ pctldev : the pin controller that allocated this struct , and will free it
2020-07-13 17:49:18 +03:00
* @ map : the mapping table entries
* @ num_maps : number of mapping table entries
2012-03-23 20:29:46 +04:00
*/
struct pinctrl_dt_map {
struct list_head node ;
struct pinctrl_dev * pctldev ;
struct pinctrl_map * map ;
2023-11-29 19:06:46 +03:00
unsigned int num_maps ;
2012-03-23 20:29:46 +04:00
} ;
static void dt_free_map ( struct pinctrl_dev * pctldev ,
2023-11-29 19:06:46 +03:00
struct pinctrl_map * map , unsigned int num_maps )
2012-03-23 20:29:46 +04:00
{
2019-10-02 15:42:06 +03:00
int i ;
for ( i = 0 ; i < num_maps ; + + i ) {
kfree_const ( map [ i ] . dev_name ) ;
map [ i ] . dev_name = NULL ;
}
2012-03-23 20:29:46 +04:00
if ( pctldev ) {
2013-02-16 13:25:07 +04:00
const struct pinctrl_ops * ops = pctldev - > desc - > pctlops ;
2016-12-30 21:37:31 +03:00
if ( ops - > dt_free_map )
ops - > dt_free_map ( pctldev , map , num_maps ) ;
2012-03-23 20:29:46 +04:00
} else {
/* There is no pctldev for PIN_MAP_TYPE_DUMMY_STATE */
kfree ( map ) ;
}
}
void pinctrl_dt_free_maps ( struct pinctrl * p )
{
struct pinctrl_dt_map * dt_map , * n1 ;
list_for_each_entry_safe ( dt_map , n1 , & p - > dt_maps , node ) {
2019-12-16 23:51:18 +03:00
pinctrl_unregister_mappings ( dt_map - > map ) ;
2012-03-23 20:29:46 +04:00
list_del ( & dt_map - > node ) ;
dt_free_map ( dt_map - > pctldev , dt_map - > map ,
dt_map - > num_maps ) ;
kfree ( dt_map ) ;
}
of_node_put ( p - > dev - > of_node ) ;
}
static int dt_remember_or_free_map ( struct pinctrl * p , const char * statename ,
struct pinctrl_dev * pctldev ,
2023-11-29 19:06:46 +03:00
struct pinctrl_map * map , unsigned int num_maps )
2012-03-23 20:29:46 +04:00
{
int i ;
struct pinctrl_dt_map * dt_map ;
/* Initialize common mapping table entry fields */
for ( i = 0 ; i < num_maps ; i + + ) {
2019-10-02 15:42:06 +03:00
const char * devname ;
devname = kstrdup_const ( dev_name ( p - > dev ) , GFP_KERNEL ) ;
if ( ! devname )
goto err_free_map ;
map [ i ] . dev_name = devname ;
2012-03-23 20:29:46 +04:00
map [ i ] . name = statename ;
if ( pctldev )
map [ i ] . ctrl_dev_name = dev_name ( pctldev - > dev ) ;
}
/* Remember the converted mapping table entries */
dt_map = kzalloc ( sizeof ( * dt_map ) , GFP_KERNEL ) ;
2019-10-02 15:42:06 +03:00
if ( ! dt_map )
goto err_free_map ;
2012-03-23 20:29:46 +04:00
dt_map - > pctldev = pctldev ;
dt_map - > map = map ;
dt_map - > num_maps = num_maps ;
list_add_tail ( & dt_map - > node , & p - > dt_maps ) ;
2019-12-16 23:51:18 +03:00
return pinctrl_register_mappings ( map , num_maps ) ;
2019-10-02 15:42:06 +03:00
err_free_map :
dt_free_map ( pctldev , map , num_maps ) ;
return - ENOMEM ;
2012-03-23 20:29:46 +04:00
}
2012-11-06 19:03:35 +04:00
struct pinctrl_dev * of_pinctrl_get ( struct device_node * np )
2012-10-27 13:51:36 +04:00
{
2015-06-18 08:42:45 +03:00
return get_pinctrl_dev_from_of_node ( np ) ;
2012-10-27 13:51:36 +04:00
}
2020-04-01 07:19:04 +03:00
EXPORT_SYMBOL_GPL ( of_pinctrl_get ) ;
2012-10-27 13:51:36 +04:00
2016-12-27 20:19:59 +03:00
static int dt_to_map_one_config ( struct pinctrl * p ,
2018-06-07 19:51:33 +03:00
struct pinctrl_dev * hog_pctldev ,
2016-12-27 20:19:59 +03:00
const char * statename ,
2012-03-23 20:29:46 +04:00
struct device_node * np_config )
{
2018-06-07 19:51:33 +03:00
struct pinctrl_dev * pctldev = NULL ;
2012-03-23 20:29:46 +04:00
struct device_node * np_pctldev ;
2013-02-16 13:25:07 +04:00
const struct pinctrl_ops * ops ;
2012-03-23 20:29:46 +04:00
int ret ;
struct pinctrl_map * map ;
2023-11-29 19:06:46 +03:00
unsigned int num_maps ;
2018-07-09 18:41:50 +03:00
bool allow_default = false ;
2012-03-23 20:29:46 +04:00
/* Find the pin controller containing np_config */
np_pctldev = of_node_get ( np_config ) ;
for ( ; ; ) {
2018-07-09 18:41:50 +03:00
if ( ! allow_default )
allow_default = of_property_read_bool ( np_pctldev ,
" pinctrl-use-default " ) ;
2012-03-23 20:29:46 +04:00
np_pctldev = of_get_next_parent ( np_pctldev ) ;
if ( ! np_pctldev | | of_node_is_root ( np_pctldev ) ) {
of_node_put ( np_pctldev ) ;
2022-06-01 10:06:58 +03:00
ret = - ENODEV ;
2020-08-25 17:33:48 +03:00
/* keep deferring if modules are enabled */
if ( IS_ENABLED ( CONFIG_MODULES ) & & ! allow_default & & ret < 0 )
2020-02-25 08:08:25 +03:00
ret = - EPROBE_DEFER ;
return ret ;
2012-03-23 20:29:46 +04:00
}
2018-02-28 18:53:06 +03:00
/* If we're creating a hog we can use the passed pctldev */
2018-06-07 19:51:33 +03:00
if ( hog_pctldev & & ( np_pctldev = = p - > dev - > of_node ) ) {
pctldev = hog_pctldev ;
2018-02-28 18:53:06 +03:00
break ;
2018-06-07 19:51:33 +03:00
}
2018-02-28 18:53:06 +03:00
pctldev = get_pinctrl_dev_from_of_node ( np_pctldev ) ;
2012-03-23 20:29:46 +04:00
if ( pctldev )
break ;
2013-01-12 00:22:36 +04:00
/* Do not defer probing of hogs (circular loop) */
if ( np_pctldev = = p - > dev - > of_node ) {
of_node_put ( np_pctldev ) ;
return - ENODEV ;
}
2012-03-23 20:29:46 +04:00
}
of_node_put ( np_pctldev ) ;
/*
* Call pinctrl driver to parse device tree node , and
* generate mapping table entries
*/
ops = pctldev - > desc - > pctlops ;
if ( ! ops - > dt_node_to_map ) {
dev_err ( p - > dev , " pctldev %s doesn't support DT \n " ,
dev_name ( pctldev - > dev ) ) ;
return - ENODEV ;
}
ret = ops - > dt_node_to_map ( pctldev , np_config , & map , & num_maps ) ;
if ( ret < 0 )
return ret ;
2019-11-01 14:43:52 +03:00
else if ( num_maps = = 0 ) {
/*
* If we have no valid maps ( maybe caused by empty pinctrl node
* or typing error ) ther is no need remember this , so just
* return .
*/
dev_info ( p - > dev ,
" there is not valid maps for state %s \n " , statename ) ;
return 0 ;
}
2012-03-23 20:29:46 +04:00
/* Stash the mapping table chunk away for later use */
return dt_remember_or_free_map ( p , statename , pctldev , map , num_maps ) ;
}
static int dt_remember_dummy_state ( struct pinctrl * p , const char * statename )
{
struct pinctrl_map * map ;
map = kzalloc ( sizeof ( * map ) , GFP_KERNEL ) ;
2017-08-26 21:30:04 +03:00
if ( ! map )
2012-03-23 20:29:46 +04:00
return - ENOMEM ;
/* There is no pctldev for PIN_MAP_TYPE_DUMMY_STATE */
map - > type = PIN_MAP_TYPE_DUMMY_STATE ;
return dt_remember_or_free_map ( p , statename , NULL , map , 1 ) ;
}
2016-12-27 20:19:59 +03:00
int pinctrl_dt_to_map ( struct pinctrl * p , struct pinctrl_dev * pctldev )
2012-03-23 20:29:46 +04:00
{
struct device_node * np = p - > dev - > of_node ;
int state , ret ;
char * propname ;
struct property * prop ;
const char * statename ;
const __be32 * list ;
int size , config ;
phandle phandle ;
struct device_node * np_config ;
/* CONFIG_OF enabled, p->dev not instantiated from DT */
if ( ! np ) {
2014-01-30 22:57:20 +04:00
if ( of_have_populated_dt ( ) )
dev_dbg ( p - > dev ,
" no of_node; not parsing pinctrl DT \n " ) ;
2012-03-23 20:29:46 +04:00
return 0 ;
}
/* We may store pointers to property names within the node */
of_node_get ( np ) ;
/* For each defined state ID */
for ( state = 0 ; ; state + + ) {
/* Retrieve the pinctrl-* property */
propname = kasprintf ( GFP_KERNEL , " pinctrl-%d " , state ) ;
2022-11-10 11:20:56 +03:00
if ( ! propname )
return - ENOMEM ;
2012-03-23 20:29:46 +04:00
prop = of_find_property ( np , propname , & size ) ;
kfree ( propname ) ;
2016-06-16 18:27:41 +03:00
if ( ! prop ) {
if ( state = = 0 ) {
of_node_put ( np ) ;
return - ENODEV ;
}
2012-03-23 20:29:46 +04:00
break ;
2016-06-16 18:27:41 +03:00
}
2012-03-23 20:29:46 +04:00
list = prop - > value ;
size / = sizeof ( * list ) ;
/* Determine whether pinctrl-names property names the state */
ret = of_property_read_string_index ( np , " pinctrl-names " ,
state , & statename ) ;
/*
* If not , statename is just the integer state ID . But rather
* than dynamically allocate it and have to free it later ,
* just point part way into the property name for the string .
*/
2019-07-31 16:29:15 +03:00
if ( ret < 0 )
statename = prop - > name + strlen ( " pinctrl- " ) ;
2012-03-23 20:29:46 +04:00
/* For every referenced pin configuration node in it */
for ( config = 0 ; config < size ; config + + ) {
phandle = be32_to_cpup ( list + + ) ;
/* Look up the pin configuration node */
np_config = of_find_node_by_phandle ( phandle ) ;
if ( ! np_config ) {
dev_err ( p - > dev ,
" prop %s index %i invalid phandle \n " ,
prop - > name , config ) ;
ret = - EINVAL ;
goto err ;
}
/* Parse the node */
2016-12-27 20:19:59 +03:00
ret = dt_to_map_one_config ( p , pctldev , statename ,
np_config ) ;
2012-03-23 20:29:46 +04:00
of_node_put ( np_config ) ;
if ( ret < 0 )
goto err ;
}
/* No entries in DT? Generate a dummy state table entry */
if ( ! size ) {
ret = dt_remember_dummy_state ( p , statename ) ;
if ( ret < 0 )
goto err ;
}
}
return 0 ;
err :
pinctrl_dt_free_maps ( p ) ;
return ret ;
}
2016-11-03 19:35:47 +03:00
/*
* For pinctrl binding , typically # pinctrl - cells is for the pin controller
* device , so either parent or grandparent . See pinctrl - bindings . txt .
*/
static int pinctrl_find_cells_size ( const struct device_node * np )
{
const char * cells_name = " #pinctrl-cells " ;
int cells_size , error ;
error = of_property_read_u32 ( np - > parent , cells_name , & cells_size ) ;
if ( error ) {
error = of_property_read_u32 ( np - > parent - > parent ,
cells_name , & cells_size ) ;
if ( error )
return - ENOENT ;
}
return cells_size ;
}
/**
* pinctrl_get_list_and_count - Gets the list and it ' s cell size and number
* @ np : pointer to device node with the property
* @ list_name : property that contains the list
* @ list : pointer for the list found
* @ cells_size : pointer for the cell size found
* @ nr_elements : pointer for the number of elements found
*
* Typically np is a single pinctrl entry containing the list .
*/
static int pinctrl_get_list_and_count ( const struct device_node * np ,
const char * list_name ,
const __be32 * * list ,
int * cells_size ,
int * nr_elements )
{
int size ;
* cells_size = 0 ;
* nr_elements = 0 ;
* list = of_get_property ( np , list_name , & size ) ;
if ( ! * list )
return - ENOENT ;
* cells_size = pinctrl_find_cells_size ( np ) ;
if ( * cells_size < 0 )
return - ENOENT ;
/* First element is always the index within the pinctrl device */
* nr_elements = ( size / sizeof ( * * list ) ) / ( * cells_size + 1 ) ;
return 0 ;
}
/**
* pinctrl_count_index_with_args - Count number of elements in a pinctrl entry
* @ np : pointer to device node with the property
* @ list_name : property that contains the list
*
* Counts the number of elements in a pinctrl array consisting of an index
* within the controller and a number of u32 entries specified for each
* entry . Note that device_node is always for the parent pin controller device .
*/
int pinctrl_count_index_with_args ( const struct device_node * np ,
const char * list_name )
{
const __be32 * list ;
int size , nr_cells , error ;
error = pinctrl_get_list_and_count ( np , list_name , & list ,
& nr_cells , & size ) ;
if ( error )
return error ;
return size ;
}
EXPORT_SYMBOL_GPL ( pinctrl_count_index_with_args ) ;
/**
* pinctrl_copy_args - Populates of_phandle_args based on index
* @ np : pointer to device node with the property
* @ list : pointer to a list with the elements
* @ index : entry within the list of elements
* @ nr_cells : number of cells in the list
* @ nr_elem : number of elements for each entry in the list
* @ out_args : returned values
*
* Populates the of_phandle_args based on the index in the list .
*/
static int pinctrl_copy_args ( const struct device_node * np ,
const __be32 * list ,
int index , int nr_cells , int nr_elem ,
struct of_phandle_args * out_args )
{
int i ;
memset ( out_args , 0 , sizeof ( * out_args ) ) ;
out_args - > np = ( struct device_node * ) np ;
out_args - > args_count = nr_cells + 1 ;
if ( index > = nr_elem )
return - EINVAL ;
list + = index * ( nr_cells + 1 ) ;
for ( i = 0 ; i < nr_cells + 1 ; i + + )
out_args - > args [ i ] = be32_to_cpup ( list + + ) ;
return 0 ;
}
/**
* pinctrl_parse_index_with_args - Find a node pointed by index in a list
* @ np : pointer to device node with the property
* @ list_name : property that contains the list
* @ index : index within the list
2020-07-13 17:49:18 +03:00
* @ out_args : entries in the list pointed by index
2016-11-03 19:35:47 +03:00
*
* Finds the selected element in a pinctrl array consisting of an index
* within the controller and a number of u32 entries specified for each
* entry . Note that device_node is always for the parent pin controller device .
*/
int pinctrl_parse_index_with_args ( const struct device_node * np ,
const char * list_name , int index ,
struct of_phandle_args * out_args )
{
const __be32 * list ;
int nr_elem , nr_cells , error ;
error = pinctrl_get_list_and_count ( np , list_name , & list ,
& nr_cells , & nr_elem ) ;
if ( error | | ! nr_cells )
return error ;
error = pinctrl_copy_args ( np , list , index , nr_cells , nr_elem ,
out_args ) ;
if ( error )
return error ;
return 0 ;
}
EXPORT_SYMBOL_GPL ( pinctrl_parse_index_with_args ) ;