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>
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>
2012-05-17 23:54:40 +04:00
# include <linux/gpio.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>
2010-07-06 02:11:55 +04:00
# include <linux/slab.h>
2008-04-11 17:06:45 +04:00
2012-05-17 23:54:40 +04:00
/* Private data structure for of_gpiochip_is_match */
struct gg_data {
enum of_gpio_flags * flags ;
struct of_phandle_args gpiospec ;
int out_gpio ;
} ;
/* Private function for resolving node pointer to gpio_chip */
static int of_gpiochip_find_and_xlate ( struct gpio_chip * gc , void * data )
{
struct gg_data * gg_data = data ;
int ret ;
if ( ( gc - > of_node ! = gg_data - > gpiospec . np ) | |
( gc - > of_gpio_n_cells ! = gg_data - > gpiospec . args_count ) | |
( ! gc - > of_xlate ) )
return false ;
ret = gc - > of_xlate ( gc , & gg_data - > gpiospec , gg_data - > flags ) ;
if ( ret < 0 )
return false ;
gg_data - > out_gpio = ret + gc - > base ;
return true ;
}
2008-04-11 17:06:45 +04:00
/**
2011-06-28 03:49:57 +04:00
* of_get_named_gpio_flags ( ) - Get a GPIO number and flags to use with 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
*
* Returns GPIO number to use with Linux generic 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
*/
2011-06-28 03:49:57 +04:00
int of_get_named_gpio_flags ( struct device_node * np , const char * propname ,
int index , enum of_gpio_flags * flags )
2008-04-11 17:06:45 +04:00
{
2012-05-17 23:54:40 +04:00
struct gg_data gg_data = { . flags = flags , . out_gpio = - ENODEV } ;
2008-10-10 08:43:17 +04:00
int ret ;
2012-05-17 23:54:40 +04:00
/* .of_xlate might decide to not fill in the flags, so clear it. */
if ( flags )
* flags = 0 ;
2008-04-11 17:06:45 +04:00
2011-12-12 20:25:57 +04:00
ret = of_parse_phandle_with_args ( np , propname , " #gpio-cells " , index ,
2012-05-17 23:54:40 +04:00
& gg_data . gpiospec ) ;
2008-10-10 08:43:17 +04:00
if ( ret ) {
pr_debug ( " %s: can't parse gpios property \n " , __func__ ) ;
2012-05-17 23:54:40 +04:00
return - EINVAL ;
2008-04-11 17:06:45 +04:00
}
2012-05-17 23:54:40 +04:00
gpiochip_find ( & gg_data , of_gpiochip_find_and_xlate ) ;
2008-04-11 17:06:45 +04:00
2012-05-17 23:54:40 +04:00
of_node_put ( gg_data . gpiospec . np ) ;
2008-04-11 17:06:45 +04:00
pr_debug ( " %s exited with status %d \n " , __func__ , ret ) ;
2012-05-17 23:54:40 +04:00
return gg_data . out_gpio ;
2008-04-11 17:06:45 +04:00
}
2011-06-28 03:49:57 +04:00
EXPORT_SYMBOL ( of_get_named_gpio_flags ) ;
2008-04-11 17:06:45 +04:00
2008-12-05 11:15:54 +03:00
/**
2012-02-02 19:20:01 +04:00
* of_gpio_named_count - Count GPIOs for a device
2008-12-05 11:15:54 +03:00
* @ np : device node to count GPIOs for
2012-02-02 19:20:01 +04:00
* @ propname : property name containing gpio specifier ( s )
2008-12-05 11:15:54 +03:00
*
* The function returns the count of GPIOs specified for a node .
*
* Note that the empty GPIO specifiers counts too . For example ,
*
* gpios = < 0
* & pio1 1 2
* 0
* & pio2 3 4 > ;
*
* defines four GPIOs ( so this function will return 4 ) , two of which
* are not specified .
*/
2012-02-02 19:20:01 +04:00
unsigned int of_gpio_named_count ( struct device_node * np , const char * propname )
2008-12-05 11:15:54 +03:00
{
unsigned int cnt = 0 ;
do {
int ret ;
2012-02-02 19:20:01 +04:00
ret = of_parse_phandle_with_args ( np , propname , " #gpio-cells " ,
2011-12-12 20:25:57 +04:00
cnt , NULL ) ;
2008-12-05 11:15:54 +03:00
/* A hole in the gpios = <> counts anyway. */
if ( ret < 0 & & ret ! = - EEXIST )
break ;
} while ( + + cnt ) ;
return cnt ;
}
2012-02-02 19:20:01 +04:00
EXPORT_SYMBOL ( of_gpio_named_count ) ;
2008-12-05 11:15:54 +03:00
2008-04-11 17:06:45 +04:00
/**
2008-12-01 09:30:04 +03:00
* of_gpio_simple_xlate - translate gpio_spec to the GPIO number and flags
2010-06-08 17:48:16 +04:00
* @ gc : pointer to the gpio_chip structure
2008-04-11 17:06:45 +04:00
* @ np : device node of the GPIO chip
* @ gpio_spec : 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
* gpio chips . This function performs only one sanity check : whether gpio
* 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
* write your own xlate function ( that will have to retrive the GPIO
* 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
/**
* of_mm_gpiochip_add - Add memory mapped GPIO chip ( bank )
* @ np : device node of the GPIO chip
* @ mm_gc : pointer to the of_mm_gpio_chip allocated structure
*
* 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 .
*/
int of_mm_gpiochip_add ( struct device_node * np ,
struct of_mm_gpio_chip * mm_gc )
{
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
gc - > label = kstrdup ( np - > full_name , GFP_KERNEL ) ;
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
ret = gpiochip_add ( gc ) ;
if ( ret )
goto err2 ;
return 0 ;
err2 :
iounmap ( mm_gc - > regs ) ;
err1 :
kfree ( gc - > label ) ;
err0 :
pr_err ( " %s: GPIO chip registration failed with status %d \n " ,
np - > full_name , ret ) ;
return ret ;
}
EXPORT_SYMBOL ( of_mm_gpiochip_add ) ;
2010-06-08 17:48:16 +04:00
2010-06-08 17:48:17 +04:00
void of_gpiochip_add ( struct gpio_chip * chip )
{
if ( ( ! chip - > of_node ) & & ( chip - > dev ) )
chip - > of_node = chip - > dev - > of_node ;
if ( ! chip - > of_node )
return ;
if ( ! chip - > of_xlate ) {
chip - > of_gpio_n_cells = 2 ;
chip - > of_xlate = of_gpio_simple_xlate ;
}
of_node_get ( chip - > of_node ) ;
}
void of_gpiochip_remove ( struct gpio_chip * chip )
{
if ( chip - > of_node )
of_node_put ( chip - > of_node ) ;
}