2012-03-23 20:29:46 +04:00
/*
* Device tree integration for the pin control subsystem
*
* Copyright ( C ) 2012 NVIDIA CORPORATION . All rights reserved .
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms and conditions of the GNU General Public License ,
* version 2 , as published by the Free Software Foundation .
*
* This program is distributed in the hope it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License for
* more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
# 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
* @ maps : the mapping table entries
*/
struct pinctrl_dt_map {
struct list_head node ;
struct pinctrl_dev * pctldev ;
struct pinctrl_map * map ;
unsigned num_maps ;
} ;
static void dt_free_map ( struct pinctrl_dev * pctldev ,
struct pinctrl_map * map , unsigned num_maps )
{
if ( pctldev ) {
2013-02-16 13:25:07 +04:00
const struct pinctrl_ops * ops = pctldev - > desc - > pctlops ;
2012-03-23 20:29:46 +04:00
ops - > dt_free_map ( pctldev , map , num_maps ) ;
} 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 ) {
pinctrl_unregister_map ( dt_map - > map ) ;
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 ,
struct pinctrl_map * map , unsigned num_maps )
{
int i ;
struct pinctrl_dt_map * dt_map ;
/* Initialize common mapping table entry fields */
for ( i = 0 ; i < num_maps ; i + + ) {
map [ i ] . dev_name = dev_name ( p - > dev ) ;
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 ) ;
if ( ! dt_map ) {
dev_err ( p - > dev , " failed to alloc struct pinctrl_dt_map \n " ) ;
dt_free_map ( pctldev , map , num_maps ) ;
return - ENOMEM ;
}
dt_map - > pctldev = pctldev ;
dt_map - > map = map ;
dt_map - > num_maps = num_maps ;
list_add_tail ( & dt_map - > node , & p - > dt_maps ) ;
return pinctrl_register_map ( map , num_maps , false , true ) ;
}
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
{
struct pinctrl_dev * pctldev ;
pinctrl: move subsystem mutex to pinctrl_dev struct
This mutex avoids deadlock in case of use of multiple pin
controllers. Before this modification, by using a global
mutex, deadlock appeared when, for example, a call to
pinctrl_pins_show() locked the pinctrl_mutex, called the
ops->pin_dbg_show of a particular pin controller. If this
pin controller needs I2C access to retrieve configuration
information and I2C driver is using pinctrl to drive its
pins, a call to pinctrl_select_state() try to lock again
pinctrl_mutex which leads to a deadlock.
Notice that the mutex grab from the two direction functions
was moved into pinctrl_gpio_direction().
For several cases, we can't replace pinctrl_mutex by
pctldev->mutex, because at this stage, pctldev is
not accessible :
- pinctrl_get()/pinctrl_put()
- pinctrl_register_maps()
So add respectively pinctrl_list_mutex and
pinctrl_maps_mutex in order to protect
pinctrl_list and pinctrl_maps list instead.
Reintroduce pinctrldev_list_mutex in
find_pinctrl_by_of_node(),
pinctrl_find_and_add_gpio_range()
pinctrl_request_gpio(), pinctrl_free_gpio(),
pinctrl_gpio_direction(), pinctrl_devices_show(),
pinctrl_register() and pinctrl_unregister() to
protect pinctrldev_list.
Changes v2->v3:
- Fix a missing EXPORT_SYMBOL_GPL() for pinctrl_select_state().
Changes v1->v2:
- pinctrl_select_state_locked() is removed, all lock mechanism
is located inside pinctrl_select_state(). When parsing
the state->setting list, take the per-pin-controller driver
lock. (Patrice).
- Introduce pinctrldev_list_mutex to protect pinctrldev_list
in all functions which parse or modify pictrldev_list.
(Patrice).
- move find_pinctrl_by_of_node() from pinctrl/devicetree.c to
pinctrl/core.c in order to protect pinctrldev_list.
(Patrice).
- Sink mutex:es into some functions and remove some _locked
variants down to where the lists are actually accessed to
make things simpler. (Linus)
- Drop *all* mutexes completely from pinctrl_lookup_state()
and pinctrl_select_state() - no relevant mutex was taken
and it was unclear what this was protecting against. (Linus)
Reported by : Seraphin Bonnaffe <seraphin.bonnaffe@stericsson.com>
Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2013-04-11 13:01:27 +04:00
pctldev = get_pinctrl_dev_from_of_node ( np ) ;
2012-10-27 13:51:36 +04:00
if ( ! pctldev )
return NULL ;
return pctldev ;
}
2012-03-23 20:29:46 +04:00
static int dt_to_map_one_config ( struct pinctrl * p , const char * statename ,
struct device_node * np_config )
{
struct device_node * np_pctldev ;
struct pinctrl_dev * 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 ;
unsigned num_maps ;
/* Find the pin controller containing np_config */
np_pctldev = of_node_get ( np_config ) ;
for ( ; ; ) {
np_pctldev = of_get_next_parent ( np_pctldev ) ;
if ( ! np_pctldev | | of_node_is_root ( np_pctldev ) ) {
2012-04-10 12:00:38 +04:00
dev_info ( p - > dev , " could not find pctldev for node %s, deferring probe \n " ,
2012-03-23 20:29:46 +04:00
np_config - > full_name ) ;
of_node_put ( np_pctldev ) ;
2012-04-10 12:00:38 +04:00
/* OK let's just assume this will appear later then */
return - EPROBE_DEFER ;
2012-03-23 20:29:46 +04:00
}
pinctrl: move subsystem mutex to pinctrl_dev struct
This mutex avoids deadlock in case of use of multiple pin
controllers. Before this modification, by using a global
mutex, deadlock appeared when, for example, a call to
pinctrl_pins_show() locked the pinctrl_mutex, called the
ops->pin_dbg_show of a particular pin controller. If this
pin controller needs I2C access to retrieve configuration
information and I2C driver is using pinctrl to drive its
pins, a call to pinctrl_select_state() try to lock again
pinctrl_mutex which leads to a deadlock.
Notice that the mutex grab from the two direction functions
was moved into pinctrl_gpio_direction().
For several cases, we can't replace pinctrl_mutex by
pctldev->mutex, because at this stage, pctldev is
not accessible :
- pinctrl_get()/pinctrl_put()
- pinctrl_register_maps()
So add respectively pinctrl_list_mutex and
pinctrl_maps_mutex in order to protect
pinctrl_list and pinctrl_maps list instead.
Reintroduce pinctrldev_list_mutex in
find_pinctrl_by_of_node(),
pinctrl_find_and_add_gpio_range()
pinctrl_request_gpio(), pinctrl_free_gpio(),
pinctrl_gpio_direction(), pinctrl_devices_show(),
pinctrl_register() and pinctrl_unregister() to
protect pinctrldev_list.
Changes v2->v3:
- Fix a missing EXPORT_SYMBOL_GPL() for pinctrl_select_state().
Changes v1->v2:
- pinctrl_select_state_locked() is removed, all lock mechanism
is located inside pinctrl_select_state(). When parsing
the state->setting list, take the per-pin-controller driver
lock. (Patrice).
- Introduce pinctrldev_list_mutex to protect pinctrldev_list
in all functions which parse or modify pictrldev_list.
(Patrice).
- move find_pinctrl_by_of_node() from pinctrl/devicetree.c to
pinctrl/core.c in order to protect pinctrldev_list.
(Patrice).
- Sink mutex:es into some functions and remove some _locked
variants down to where the lists are actually accessed to
make things simpler. (Linus)
- Drop *all* mutexes completely from pinctrl_lookup_state()
and pinctrl_select_state() - no relevant mutex was taken
and it was unclear what this was protecting against. (Linus)
Reported by : Seraphin Bonnaffe <seraphin.bonnaffe@stericsson.com>
Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2013-04-11 13:01:27 +04: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 ;
/* 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 ) ;
if ( ! map ) {
dev_err ( p - > dev , " failed to alloc struct pinctrl_map \n " ) ;
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 ) ;
}
int pinctrl_dt_to_map ( struct pinctrl * p )
{
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 ) ;
prop = of_find_property ( np , propname , & size ) ;
kfree ( propname ) ;
if ( ! prop )
break ;
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 .
*/
if ( ret < 0 ) {
/* strlen("pinctrl-") == 8 */
statename = prop - > name + 8 ;
}
/* 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 */
ret = dt_to_map_one_config ( p , statename , np_config ) ;
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 ;
}