2008-04-11 17:06:45 +04:00
/*
* OF helpers for the GPIO API
*
* Copyright ( c ) 2007 - 2008 MontaVista Software , Inc .
*
* Author : Anton Vorontsov < avorontsov @ ru . mvista . com >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*/
2010-07-06 02:11:55 +04:00
# include <linux/device.h>
2014-01-27 10:45:08 +04:00
# include <linux/err.h>
2008-04-11 17:06:45 +04:00
# include <linux/errno.h>
2010-07-06 02:11:55 +04:00
# include <linux/module.h>
2008-04-11 17:06:45 +04:00
# include <linux/io.h>
2013-10-17 21:21:37 +04:00
# include <linux/gpio/consumer.h>
2008-04-11 17:06:45 +04:00
# include <linux/of.h>
2010-07-06 02:11:55 +04:00
# include <linux/of_address.h>
2008-04-11 17:06:45 +04:00
# include <linux/of_gpio.h>
2012-10-27 13:51:36 +04:00
# include <linux/pinctrl/pinctrl.h>
2010-07-06 02:11:55 +04:00
# include <linux/slab.h>
2015-02-02 20:44:44 +03:00
# include <linux/gpio/machine.h>
2008-04-11 17:06:45 +04:00
2014-07-22 11:17:41 +04:00
# include "gpiolib.h"
2013-10-17 21:21:37 +04:00
2016-10-25 04:47:44 +03:00
static int of_gpiochip_match_node_and_xlate ( struct gpio_chip * chip , void * data )
2012-05-17 23:54:40 +04:00
{
2016-10-25 04:47:44 +03:00
struct of_phandle_args * gpiospec = data ;
return chip - > gpiodev - > dev . of_node = = gpiospec - > np & &
chip - > of_xlate ( chip , gpiospec , NULL ) > = 0 ;
gpio: of: remove of_gpiochip_and_xlate() and struct gg_data
The usage of gpiochip_find(&gg_data, of_gpiochip_and_xlate) is odd.
Usually gpiochip_find() is used to find a gpio_chip. Here, however,
the return value from gpiochip_find() is just discarded. Instead,
gpiochip_find(&gg_data, of_gpiochip_and_xlate) is called for the
side-effect of the match function.
The match function, of_gpiochip_find_and_xlate(), fills the given
struct gg_data, but a match function should be simply called to
judge the matching.
This commit fixes this distortion and makes the code more readable.
Remove of_gpiochip_find_and_xlate() and struct gg_data. Instead,
this adds a very simple helper function of_find_gpiochip_by_node().
Now, of_get_named_gpiod_flags() is implemented more straight-forward.
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2016-06-14 13:07:06 +03:00
}
2012-05-17 23:54:40 +04:00
2016-10-25 04:47:44 +03:00
static struct gpio_chip * of_find_gpiochip_by_xlate (
struct of_phandle_args * gpiospec )
gpio: of: remove of_gpiochip_and_xlate() and struct gg_data
The usage of gpiochip_find(&gg_data, of_gpiochip_and_xlate) is odd.
Usually gpiochip_find() is used to find a gpio_chip. Here, however,
the return value from gpiochip_find() is just discarded. Instead,
gpiochip_find(&gg_data, of_gpiochip_and_xlate) is called for the
side-effect of the match function.
The match function, of_gpiochip_find_and_xlate(), fills the given
struct gg_data, but a match function should be simply called to
judge the matching.
This commit fixes this distortion and makes the code more readable.
Remove of_gpiochip_find_and_xlate() and struct gg_data. Instead,
this adds a very simple helper function of_find_gpiochip_by_node().
Now, of_get_named_gpiod_flags() is implemented more straight-forward.
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2016-06-14 13:07:06 +03:00
{
2016-10-25 04:47:44 +03:00
return gpiochip_find ( gpiospec , of_gpiochip_match_node_and_xlate ) ;
2012-05-17 23:54:40 +04:00
}
2016-06-14 13:07:07 +03:00
static struct gpio_desc * of_xlate_and_get_gpiod_flags ( struct gpio_chip * chip ,
struct of_phandle_args * gpiospec ,
enum of_gpio_flags * flags )
2012-05-17 23:54:40 +04:00
{
int ret ;
2016-06-14 13:07:07 +03:00
if ( chip - > of_gpio_n_cells ! = gpiospec - > args_count )
return ERR_PTR ( - EINVAL ) ;
ret = chip - > of_xlate ( chip , gpiospec , flags ) ;
if ( ret < 0 )
return ERR_PTR ( ret ) ;
return gpiochip_get_desc ( chip , ret ) ;
2012-05-17 23:54:40 +04:00
}
2008-04-11 17:06:45 +04:00
/**
2013-10-17 21:21:37 +04:00
* of_get_named_gpiod_flags ( ) - Get a GPIO descriptor and flags for GPIO API
2008-04-11 17:06:45 +04:00
* @ np : device node to get GPIO from
2011-06-28 03:49:57 +04:00
* @ propname : property name containing gpio specifier ( s )
2008-04-11 17:06:45 +04:00
* @ index : index of the GPIO
2008-12-01 09:30:04 +03:00
* @ flags : a flags pointer to fill in
2008-04-11 17:06:45 +04:00
*
2013-10-17 21:21:37 +04:00
* Returns GPIO descriptor to use with Linux GPIO API , or one of the errno
2008-12-01 09:30:04 +03:00
* value on the error condition . If @ flags is not NULL the function also fills
* in flags for the GPIO .
2008-04-11 17:06:45 +04:00
*/
2013-10-17 21:21:37 +04:00
struct gpio_desc * of_get_named_gpiod_flags ( struct device_node * np ,
const char * propname , int index , enum of_gpio_flags * flags )
2008-04-11 17:06:45 +04:00
{
gpio: of: remove of_gpiochip_and_xlate() and struct gg_data
The usage of gpiochip_find(&gg_data, of_gpiochip_and_xlate) is odd.
Usually gpiochip_find() is used to find a gpio_chip. Here, however,
the return value from gpiochip_find() is just discarded. Instead,
gpiochip_find(&gg_data, of_gpiochip_and_xlate) is called for the
side-effect of the match function.
The match function, of_gpiochip_find_and_xlate(), fills the given
struct gg_data, but a match function should be simply called to
judge the matching.
This commit fixes this distortion and makes the code more readable.
Remove of_gpiochip_find_and_xlate() and struct gg_data. Instead,
this adds a very simple helper function of_find_gpiochip_by_node().
Now, of_get_named_gpiod_flags() is implemented more straight-forward.
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2016-06-14 13:07:06 +03:00
struct of_phandle_args gpiospec ;
struct gpio_chip * chip ;
struct gpio_desc * desc ;
2008-10-10 08:43:17 +04:00
int ret ;
2012-05-17 23:54:40 +04:00
2011-12-12 20:25:57 +04:00
ret = of_parse_phandle_with_args ( np , propname , " #gpio-cells " , index ,
gpio: of: remove of_gpiochip_and_xlate() and struct gg_data
The usage of gpiochip_find(&gg_data, of_gpiochip_and_xlate) is odd.
Usually gpiochip_find() is used to find a gpio_chip. Here, however,
the return value from gpiochip_find() is just discarded. Instead,
gpiochip_find(&gg_data, of_gpiochip_and_xlate) is called for the
side-effect of the match function.
The match function, of_gpiochip_find_and_xlate(), fills the given
struct gg_data, but a match function should be simply called to
judge the matching.
This commit fixes this distortion and makes the code more readable.
Remove of_gpiochip_find_and_xlate() and struct gg_data. Instead,
this adds a very simple helper function of_find_gpiochip_by_node().
Now, of_get_named_gpiod_flags() is implemented more straight-forward.
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2016-06-14 13:07:06 +03:00
& gpiospec ) ;
2008-10-10 08:43:17 +04:00
if ( ret ) {
2017-07-19 00:43:03 +03:00
pr_debug ( " %s: can't parse '%s' property of node '%pOF[%d]' \n " ,
__func__ , propname , np , index ) ;
2013-10-17 21:21:37 +04:00
return ERR_PTR ( ret ) ;
2008-04-11 17:06:45 +04:00
}
2016-10-25 04:47:44 +03:00
chip = of_find_gpiochip_by_xlate ( & gpiospec ) ;
gpio: of: remove of_gpiochip_and_xlate() and struct gg_data
The usage of gpiochip_find(&gg_data, of_gpiochip_and_xlate) is odd.
Usually gpiochip_find() is used to find a gpio_chip. Here, however,
the return value from gpiochip_find() is just discarded. Instead,
gpiochip_find(&gg_data, of_gpiochip_and_xlate) is called for the
side-effect of the match function.
The match function, of_gpiochip_find_and_xlate(), fills the given
struct gg_data, but a match function should be simply called to
judge the matching.
This commit fixes this distortion and makes the code more readable.
Remove of_gpiochip_find_and_xlate() and struct gg_data. Instead,
this adds a very simple helper function of_find_gpiochip_by_node().
Now, of_get_named_gpiod_flags() is implemented more straight-forward.
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2016-06-14 13:07:06 +03:00
if ( ! chip ) {
desc = ERR_PTR ( - EPROBE_DEFER ) ;
goto out ;
}
2016-06-14 13:07:07 +03:00
desc = of_xlate_and_get_gpiod_flags ( chip , & gpiospec , flags ) ;
gpio: of: remove of_gpiochip_and_xlate() and struct gg_data
The usage of gpiochip_find(&gg_data, of_gpiochip_and_xlate) is odd.
Usually gpiochip_find() is used to find a gpio_chip. Here, however,
the return value from gpiochip_find() is just discarded. Instead,
gpiochip_find(&gg_data, of_gpiochip_and_xlate) is called for the
side-effect of the match function.
The match function, of_gpiochip_find_and_xlate(), fills the given
struct gg_data, but a match function should be simply called to
judge the matching.
This commit fixes this distortion and makes the code more readable.
Remove of_gpiochip_find_and_xlate() and struct gg_data. Instead,
this adds a very simple helper function of_find_gpiochip_by_node().
Now, of_get_named_gpiod_flags() is implemented more straight-forward.
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2016-06-14 13:07:06 +03:00
if ( IS_ERR ( desc ) )
goto out ;
2008-04-11 17:06:45 +04:00
2017-07-19 00:43:03 +03:00
pr_debug ( " %s: parsed '%s' property of node '%pOF[%d]' - status (%d) \n " ,
__func__ , propname , np , index ,
gpio: of: remove of_gpiochip_and_xlate() and struct gg_data
The usage of gpiochip_find(&gg_data, of_gpiochip_and_xlate) is odd.
Usually gpiochip_find() is used to find a gpio_chip. Here, however,
the return value from gpiochip_find() is just discarded. Instead,
gpiochip_find(&gg_data, of_gpiochip_and_xlate) is called for the
side-effect of the match function.
The match function, of_gpiochip_find_and_xlate(), fills the given
struct gg_data, but a match function should be simply called to
judge the matching.
This commit fixes this distortion and makes the code more readable.
Remove of_gpiochip_find_and_xlate() and struct gg_data. Instead,
this adds a very simple helper function of_find_gpiochip_by_node().
Now, of_get_named_gpiod_flags() is implemented more straight-forward.
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2016-06-14 13:07:06 +03:00
PTR_ERR_OR_ZERO ( desc ) ) ;
out :
of_node_put ( gpiospec . np ) ;
return desc ;
2008-04-11 17:06:45 +04:00
}
2014-05-17 09:54:50 +04:00
int of_get_named_gpio_flags ( struct device_node * np , const char * list_name ,
int index , enum of_gpio_flags * flags )
{
struct gpio_desc * desc ;
desc = of_get_named_gpiod_flags ( np , list_name , index , flags ) ;
if ( IS_ERR ( desc ) )
return PTR_ERR ( desc ) ;
else
return desc_to_gpio ( desc ) ;
}
EXPORT_SYMBOL ( of_get_named_gpio_flags ) ;
2016-10-03 11:09:40 +03:00
struct gpio_desc * of_find_gpio ( struct device * dev , const char * con_id ,
unsigned int idx ,
enum gpio_lookup_flags * flags )
{
char prop_name [ 32 ] ; /* 32 is max size of property name */
enum of_gpio_flags of_flags ;
struct gpio_desc * desc ;
unsigned int i ;
for ( i = 0 ; i < ARRAY_SIZE ( gpio_suffixes ) ; i + + ) {
if ( con_id )
snprintf ( prop_name , sizeof ( prop_name ) , " %s-%s " , con_id ,
gpio_suffixes [ i ] ) ;
else
snprintf ( prop_name , sizeof ( prop_name ) , " %s " ,
gpio_suffixes [ i ] ) ;
desc = of_get_named_gpiod_flags ( dev - > of_node , prop_name , idx ,
& of_flags ) ;
if ( ! IS_ERR ( desc ) | | ( PTR_ERR ( desc ) ! = - ENOENT ) )
break ;
}
if ( IS_ERR ( desc ) )
return desc ;
if ( of_flags & OF_GPIO_ACTIVE_LOW )
* flags | = GPIO_ACTIVE_LOW ;
if ( of_flags & OF_GPIO_SINGLE_ENDED ) {
2017-04-06 16:35:52 +03:00
if ( of_flags & OF_GPIO_OPEN_DRAIN )
2016-10-03 11:09:40 +03:00
* flags | = GPIO_OPEN_DRAIN ;
else
* flags | = GPIO_OPEN_SOURCE ;
}
2017-10-20 05:57:58 +03:00
if ( of_flags & OF_GPIO_SLEEP_MAY_LOSE_VALUE )
* flags | = GPIO_SLEEP_MAY_LOSE_VALUE ;
2017-05-23 17:47:29 +03:00
2016-10-03 11:09:40 +03:00
return desc ;
}
2015-02-02 20:44:44 +03:00
/**
2015-08-14 17:10:58 +03:00
* of_parse_own_gpio ( ) - Get a GPIO hog descriptor , names and flags for GPIO API
2015-02-02 20:44:44 +03:00
* @ np : device node to get GPIO from
2016-06-14 13:07:04 +03:00
* @ chip : GPIO chip whose hog is parsed
2016-12-19 21:21:34 +03:00
* @ idx : Index of the GPIO to parse
2015-02-02 20:44:44 +03:00
* @ name : GPIO line name
* @ lflags : gpio_lookup_flags - returned from of_find_gpio ( ) or
2015-08-14 17:10:58 +03:00
* of_parse_own_gpio ( )
2015-02-02 20:44:44 +03:00
* @ dflags : gpiod_flags - optional GPIO initialization flags
*
* Returns GPIO descriptor to use with Linux GPIO API , or one of the errno
* value on the error condition .
*/
2015-08-14 17:10:58 +03:00
static struct gpio_desc * of_parse_own_gpio ( struct device_node * np ,
2016-06-14 13:07:04 +03:00
struct gpio_chip * chip ,
2016-12-19 21:21:34 +03:00
unsigned int idx , const char * * name ,
2015-08-14 17:10:58 +03:00
enum gpio_lookup_flags * lflags ,
enum gpiod_flags * dflags )
2015-02-02 20:44:44 +03:00
{
struct device_node * chip_np ;
enum of_gpio_flags xlate_flags ;
2016-06-14 13:07:04 +03:00
struct of_phandle_args gpiospec ;
struct gpio_desc * desc ;
2016-12-19 21:21:34 +03:00
unsigned int i ;
2015-02-02 20:44:44 +03:00
u32 tmp ;
2016-06-14 13:07:03 +03:00
int ret ;
2015-02-02 20:44:44 +03:00
2016-06-14 13:07:04 +03:00
chip_np = chip - > of_node ;
2015-02-02 20:44:44 +03:00
if ( ! chip_np )
return ERR_PTR ( - EINVAL ) ;
xlate_flags = 0 ;
* lflags = 0 ;
* dflags = 0 ;
ret = of_property_read_u32 ( chip_np , " #gpio-cells " , & tmp ) ;
if ( ret )
return ERR_PTR ( ret ) ;
2016-06-14 13:07:04 +03:00
gpiospec . np = chip_np ;
gpiospec . args_count = tmp ;
2015-02-02 20:44:44 +03:00
2016-12-19 21:21:34 +03:00
for ( i = 0 ; i < tmp ; i + + ) {
ret = of_property_read_u32_index ( np , " gpios " , idx * tmp + i ,
& gpiospec . args [ i ] ) ;
if ( ret )
return ERR_PTR ( ret ) ;
}
2015-02-02 20:44:44 +03:00
2016-06-14 13:07:07 +03:00
desc = of_xlate_and_get_gpiod_flags ( chip , & gpiospec , & xlate_flags ) ;
2016-06-14 13:07:04 +03:00
if ( IS_ERR ( desc ) )
return desc ;
2015-02-02 20:44:44 +03:00
if ( xlate_flags & OF_GPIO_ACTIVE_LOW )
* lflags | = GPIO_ACTIVE_LOW ;
if ( of_property_read_bool ( np , " input " ) )
* dflags | = GPIOD_IN ;
else if ( of_property_read_bool ( np , " output-low " ) )
* dflags | = GPIOD_OUT_LOW ;
else if ( of_property_read_bool ( np , " output-high " ) )
* dflags | = GPIOD_OUT_HIGH ;
else {
pr_warn ( " GPIO line %d (%s): no hogging state specified, bailing out \n " ,
2016-06-14 13:07:04 +03:00
desc_to_gpio ( desc ) , np - > name ) ;
2015-02-02 20:44:44 +03:00
return ERR_PTR ( - EINVAL ) ;
}
if ( name & & of_property_read_string ( np , " line-name " , name ) )
* name = np - > name ;
2016-06-14 13:07:04 +03:00
return desc ;
2015-02-02 20:44:44 +03:00
}
/**
2015-08-14 17:10:58 +03:00
* of_gpiochip_scan_gpios - Scan gpio - controller for gpio definitions
2015-02-02 20:44:44 +03:00
* @ chip : gpio chip to act on
*
* This is only used by of_gpiochip_add to request / set GPIO initial
* configuration .
2017-06-01 13:30:01 +03:00
* It returns error if it fails otherwise 0 on success .
2015-02-02 20:44:44 +03:00
*/
2016-03-11 16:43:22 +03:00
static int of_gpiochip_scan_gpios ( struct gpio_chip * chip )
2015-02-02 20:44:44 +03:00
{
struct gpio_desc * desc = NULL ;
struct device_node * np ;
const char * name ;
enum gpio_lookup_flags lflags ;
enum gpiod_flags dflags ;
2016-12-19 21:21:34 +03:00
unsigned int i ;
2016-03-11 16:43:22 +03:00
int ret ;
2015-02-02 20:44:44 +03:00
2016-03-11 16:43:20 +03:00
for_each_available_child_of_node ( chip - > of_node , np ) {
2015-02-02 20:44:44 +03:00
if ( ! of_property_read_bool ( np , " gpio-hog " ) )
continue ;
2016-12-19 21:21:34 +03:00
for ( i = 0 ; ; i + + ) {
desc = of_parse_own_gpio ( np , chip , i , & name , & lflags ,
& dflags ) ;
if ( IS_ERR ( desc ) )
break ;
ret = gpiod_hog ( desc , name , lflags , dflags ) ;
if ( ret < 0 ) {
of_node_put ( np ) ;
return ret ;
}
2016-10-29 19:13:52 +03:00
}
2015-02-02 20:44:44 +03:00
}
2016-03-11 16:43:22 +03:00
return 0 ;
2015-02-02 20:44:44 +03:00
}
2008-04-11 17:06:45 +04:00
/**
2017-07-24 17:57:23 +03:00
* of_gpio_simple_xlate - translate gpiospec to the GPIO number and flags
2010-06-08 17:48:16 +04:00
* @ gc : pointer to the gpio_chip structure
2017-07-24 17:57:23 +03:00
* @ gpiospec : GPIO specifier as found in the device tree
2008-12-01 09:30:04 +03:00
* @ flags : a flags pointer to fill in
2008-04-11 17:06:45 +04:00
*
* This is simple translation function , suitable for the most 1 : 1 mapped
2017-07-24 17:57:23 +03:00
* GPIO chips . This function performs only one sanity check : whether GPIO
2008-04-11 17:06:45 +04:00
* is less than ngpios ( that is specified in the gpio_chip ) .
*/
2011-12-12 20:25:57 +04:00
int of_gpio_simple_xlate ( struct gpio_chip * gc ,
const struct of_phandle_args * gpiospec , u32 * flags )
2008-04-11 17:06:45 +04:00
{
2008-12-01 09:30:04 +03:00
/*
* We ' re discouraging gpio_cells < 2 , since that way you ' ll have to
2015-05-18 21:41:43 +03:00
* write your own xlate function ( that will have to retrieve the GPIO
2008-12-01 09:30:04 +03:00
* number and the flags from a single gpio cell - - this is possible ,
* but not recommended ) .
*/
2010-06-08 17:48:16 +04:00
if ( gc - > of_gpio_n_cells < 2 ) {
2008-12-01 09:30:04 +03:00
WARN_ON ( 1 ) ;
return - EINVAL ;
}
2011-12-12 20:25:57 +04:00
if ( WARN_ON ( gpiospec - > args_count < gc - > of_gpio_n_cells ) )
return - EINVAL ;
2012-04-04 04:02:58 +04:00
if ( gpiospec - > args [ 0 ] > = gc - > ngpio )
2008-04-11 17:06:45 +04:00
return - EINVAL ;
2008-12-01 09:30:04 +03:00
if ( flags )
2011-12-12 20:25:57 +04:00
* flags = gpiospec - > args [ 1 ] ;
2008-12-01 09:30:04 +03:00
2011-12-12 20:25:57 +04:00
return gpiospec - > args [ 0 ] ;
2008-04-11 17:06:45 +04:00
}
2011-07-28 19:25:41 +04:00
EXPORT_SYMBOL ( of_gpio_simple_xlate ) ;
2008-04-11 17:06:45 +04:00
/**
2015-12-04 17:13:53 +03:00
* of_mm_gpiochip_add_data - Add memory mapped GPIO chip ( bank )
2008-04-11 17:06:45 +04:00
* @ np : device node of the GPIO chip
* @ mm_gc : pointer to the of_mm_gpio_chip allocated structure
2015-12-04 17:13:53 +03:00
* @ data : driver data to store in the struct gpio_chip
2008-04-11 17:06:45 +04:00
*
* To use this function you should allocate and fill mm_gc with :
*
* 1 ) In the gpio_chip structure :
* - all the callbacks
2010-06-08 17:48:16 +04:00
* - of_gpio_n_cells
* - of_xlate callback ( optional )
2008-04-11 17:06:45 +04:00
*
* 3 ) In the of_mm_gpio_chip structure :
* - save_regs callback ( optional )
*
* If succeeded , this function will map bank ' s memory and will
* do all necessary work for you . Then you ' ll able to use . regs
* to manage GPIOs from the callbacks .
*/
2015-12-04 17:13:53 +03:00
int of_mm_gpiochip_add_data ( struct device_node * np ,
struct of_mm_gpio_chip * mm_gc ,
void * data )
2008-04-11 17:06:45 +04:00
{
int ret = - ENOMEM ;
2010-06-08 17:48:16 +04:00
struct gpio_chip * gc = & mm_gc - > gc ;
2008-04-11 17:06:45 +04:00
2017-07-19 00:43:03 +03:00
gc - > label = kasprintf ( GFP_KERNEL , " %pOF " , np ) ;
2008-04-11 17:06:45 +04:00
if ( ! gc - > label )
goto err0 ;
mm_gc - > regs = of_iomap ( np , 0 ) ;
if ( ! mm_gc - > regs )
goto err1 ;
2008-04-29 18:05:24 +04:00
gc - > base = - 1 ;
2008-04-11 17:06:45 +04:00
if ( mm_gc - > save_regs )
mm_gc - > save_regs ( mm_gc ) ;
2010-06-08 17:48:16 +04:00
mm_gc - > gc . of_node = np ;
2008-04-11 17:06:45 +04:00
2015-12-04 17:13:53 +03:00
ret = gpiochip_add_data ( gc , data ) ;
2008-04-11 17:06:45 +04:00
if ( ret )
goto err2 ;
return 0 ;
err2 :
iounmap ( mm_gc - > regs ) ;
err1 :
kfree ( gc - > label ) ;
err0 :
2017-07-19 00:43:03 +03:00
pr_err ( " %pOF: GPIO chip registration failed with status %d \n " , np , ret ) ;
2008-04-11 17:06:45 +04:00
return ret ;
}
2015-12-04 17:13:53 +03:00
EXPORT_SYMBOL ( of_mm_gpiochip_add_data ) ;
2010-06-08 17:48:16 +04:00
2014-12-17 18:51:13 +03:00
/**
* of_mm_gpiochip_remove - Remove memory mapped GPIO chip ( bank )
* @ mm_gc : pointer to the of_mm_gpio_chip allocated structure
*/
void of_mm_gpiochip_remove ( struct of_mm_gpio_chip * mm_gc )
{
struct gpio_chip * gc = & mm_gc - > gc ;
if ( ! mm_gc )
return ;
gpiochip_remove ( gc ) ;
iounmap ( mm_gc - > regs ) ;
kfree ( gc - > label ) ;
}
EXPORT_SYMBOL ( of_mm_gpiochip_remove ) ;
2012-10-27 13:51:36 +04:00
# ifdef CONFIG_PINCTRL
2015-07-14 11:29:54 +03:00
static int of_gpiochip_add_pin_range ( struct gpio_chip * chip )
2012-10-27 13:51:36 +04:00
{
struct device_node * np = chip - > of_node ;
struct of_phandle_args pinspec ;
2012-11-06 19:03:35 +04:00
struct pinctrl_dev * pctldev ;
2012-10-27 13:51:36 +04:00
int index = 0 , ret ;
2013-10-15 17:37:54 +04:00
const char * name ;
static const char group_names_propname [ ] = " gpio-ranges-group-names " ;
struct property * group_names ;
2012-10-27 13:51:36 +04:00
if ( ! np )
2015-07-14 11:29:54 +03:00
return 0 ;
2012-10-27 13:51:36 +04:00
2013-10-15 17:37:54 +04:00
group_names = of_find_property ( np , group_names_propname , NULL ) ;
2013-02-17 15:42:48 +04:00
for ( ; ; index + + ) {
2013-08-15 01:27:12 +04:00
ret = of_parse_phandle_with_fixed_args ( np , " gpio-ranges " , 3 ,
index , & pinspec ) ;
2012-10-27 13:51:36 +04:00
if ( ret )
break ;
2012-11-06 19:03:35 +04:00
pctldev = of_pinctrl_get ( pinspec . np ) ;
2016-05-23 04:52:09 +03:00
of_node_put ( pinspec . np ) ;
2012-11-06 19:03:35 +04:00
if ( ! pctldev )
2015-07-14 11:29:54 +03:00
return - EPROBE_DEFER ;
2012-10-27 13:51:36 +04:00
2013-10-15 17:37:54 +04:00
if ( pinspec . args [ 2 ] ) {
if ( group_names ) {
2015-07-07 23:22:15 +03:00
of_property_read_string_index ( np ,
2013-10-15 17:37:54 +04:00
group_names_propname ,
index , & name ) ;
if ( strlen ( name ) ) {
2017-07-19 00:43:03 +03:00
pr_err ( " %pOF: Group name of numeric GPIO ranges must be the empty string. \n " ,
np ) ;
2013-10-15 17:37:54 +04:00
break ;
}
}
/* npins != 0: linear range */
ret = gpiochip_add_pin_range ( chip ,
pinctrl_dev_get_devname ( pctldev ) ,
pinspec . args [ 0 ] ,
pinspec . args [ 1 ] ,
pinspec . args [ 2 ] ) ;
if ( ret )
2015-07-14 11:29:54 +03:00
return ret ;
2013-10-15 17:37:54 +04:00
} else {
/* npins == 0: special range */
if ( pinspec . args [ 1 ] ) {
2017-07-19 00:43:03 +03:00
pr_err ( " %pOF: Illegal gpio-range format. \n " ,
np ) ;
2013-10-15 17:37:54 +04:00
break ;
}
if ( ! group_names ) {
2017-07-19 00:43:03 +03:00
pr_err ( " %pOF: GPIO group range requested but no %s property. \n " ,
np , group_names_propname ) ;
2013-10-15 17:37:54 +04:00
break ;
}
ret = of_property_read_string_index ( np ,
group_names_propname ,
index , & name ) ;
if ( ret )
break ;
if ( ! strlen ( name ) ) {
2017-07-19 00:43:03 +03:00
pr_err ( " %pOF: Group name of GPIO group range cannot be the empty string. \n " ,
np ) ;
2013-10-15 17:37:54 +04:00
break ;
}
ret = gpiochip_add_pingroup_range ( chip , pctldev ,
pinspec . args [ 0 ] , name ) ;
if ( ret )
2015-07-14 11:29:54 +03:00
return ret ;
2013-10-15 17:37:54 +04:00
}
2013-02-17 15:42:48 +04:00
}
2015-07-14 11:29:54 +03:00
return 0 ;
2012-10-27 13:51:36 +04:00
}
# else
2015-07-14 11:29:54 +03:00
static int of_gpiochip_add_pin_range ( struct gpio_chip * chip ) { return 0 ; }
2012-10-27 13:51:36 +04:00
# endif
2015-07-14 11:29:54 +03:00
int of_gpiochip_add ( struct gpio_chip * chip )
2010-06-08 17:48:17 +04:00
{
2015-07-14 11:29:54 +03:00
int status ;
2015-11-04 11:56:26 +03:00
if ( ( ! chip - > of_node ) & & ( chip - > parent ) )
chip - > of_node = chip - > parent - > of_node ;
2010-06-08 17:48:17 +04:00
if ( ! chip - > of_node )
2015-07-14 11:29:54 +03:00
return 0 ;
2010-06-08 17:48:17 +04:00
if ( ! chip - > of_xlate ) {
chip - > of_gpio_n_cells = 2 ;
chip - > of_xlate = of_gpio_simple_xlate ;
}
2016-06-14 13:07:05 +03:00
if ( chip - > of_gpio_n_cells > MAX_PHANDLE_ARGS )
return - EINVAL ;
2015-07-14 11:29:54 +03:00
status = of_gpiochip_add_pin_range ( chip ) ;
if ( status )
return status ;
2016-04-19 16:26:26 +03:00
/* If the chip defines names itself, these take precedence */
if ( ! chip - > names )
2016-10-21 17:21:31 +03:00
devprop_gpiochip_set_names ( chip ) ;
2016-04-19 16:26:26 +03:00
2010-06-08 17:48:17 +04:00
of_node_get ( chip - > of_node ) ;
2015-02-02 20:44:44 +03:00
2016-03-11 16:43:22 +03:00
return of_gpiochip_scan_gpios ( chip ) ;
2010-06-08 17:48:17 +04:00
}
void of_gpiochip_remove ( struct gpio_chip * chip )
{
2012-11-06 18:03:47 +04:00
gpiochip_remove_pin_ranges ( chip ) ;
2014-08-08 14:07:51 +04:00
of_node_put ( chip - > of_node ) ;
2010-06-08 17:48:17 +04:00
}