2012-07-10 13:05:46 +04:00
/*
* Generic device tree based pinctrl driver for one register per pin
* type pinmux controllers
*
* Copyright ( C ) 2012 Texas Instruments , Inc .
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed " as is " without any
* warranty of any kind , whether express or implied .
*/
# include <linux/init.h>
# include <linux/module.h>
# include <linux/io.h>
# include <linux/slab.h>
# include <linux/err.h>
# include <linux/list.h>
2013-10-03 08:39:40 +04:00
# include <linux/interrupt.h>
# include <linux/irqchip/chained_irq.h>
2012-07-10 13:05:46 +04:00
# include <linux/of.h>
# include <linux/of_device.h>
# include <linux/of_address.h>
2013-10-03 08:39:40 +04:00
# include <linux/of_irq.h>
2012-07-10 13:05:46 +04:00
# include <linux/pinctrl/pinctrl.h>
# include <linux/pinctrl/pinmux.h>
2013-02-17 15:42:55 +04:00
# include <linux/pinctrl/pinconf-generic.h>
2012-07-10 13:05:46 +04:00
2013-10-03 08:39:40 +04:00
# include <linux/platform_data/pinctrl-single.h>
2012-07-10 13:05:46 +04:00
# include "core.h"
2016-11-03 19:35:48 +03:00
# include "devicetree.h"
2013-02-17 15:42:55 +04:00
# include "pinconf.h"
2016-12-27 20:20:03 +03:00
# include "pinmux.h"
2012-07-10 13:05:46 +04:00
# define DRIVER_NAME "pinctrl-single"
# define PCS_OFF_DISABLED ~0U
/**
* struct pcs_func_vals - mux function register offset and value pair
* @ reg : register virtual address
* @ val : register value
*/
struct pcs_func_vals {
void __iomem * reg ;
unsigned val ;
2012-09-11 12:54:24 +04:00
unsigned mask ;
2012-07-10 13:05:46 +04:00
} ;
2013-02-17 15:42:55 +04:00
/**
* struct pcs_conf_vals - pinconf parameter , pinconf register offset
* and value , enable , disable , mask
* @ param : config parameter
* @ val : user input bits in the pinconf register
* @ enable : enable bits in the pinconf register
* @ disable : disable bits in the pinconf register
* @ mask : mask bits in the register value
*/
struct pcs_conf_vals {
enum pin_config_param param ;
unsigned val ;
unsigned enable ;
unsigned disable ;
unsigned mask ;
} ;
/**
* struct pcs_conf_type - pinconf property name , pinconf param pair
* @ name : property name in DTS file
* @ param : config parameter
*/
struct pcs_conf_type {
const char * name ;
enum pin_config_param param ;
} ;
2012-07-10 13:05:46 +04:00
/**
* struct pcs_function - pinctrl function
* @ name : pinctrl function name
* @ vals : register and vals array
* @ nvals : number of entries in vals array
* @ pgnames : array of pingroup names the function uses
* @ npgnames : number of pingroup names the function uses
* @ node : list node
*/
struct pcs_function {
const char * name ;
struct pcs_func_vals * vals ;
unsigned nvals ;
const char * * pgnames ;
int npgnames ;
2013-02-17 15:42:55 +04:00
struct pcs_conf_vals * conf ;
int nconfs ;
2012-07-10 13:05:46 +04:00
struct list_head node ;
} ;
2013-02-17 15:42:52 +04:00
/**
* struct pcs_gpiofunc_range - pin ranges with same mux value of gpio function
* @ offset : offset base of pins
* @ npins : number pins with the same mux value of gpio function
* @ gpiofunc : mux value of gpio function
* @ node : list node
*/
struct pcs_gpiofunc_range {
unsigned offset ;
unsigned npins ;
unsigned gpiofunc ;
struct list_head node ;
} ;
2012-07-10 13:05:46 +04:00
/**
* struct pcs_data - wrapper for data needed by pinctrl framework
* @ pa : pindesc array
* @ cur : index to current element
*
* REVISIT : We should be able to drop this eventually by adding
* support for registering pins individually in the pinctrl
* framework for those drivers that don ' t need a static array .
*/
struct pcs_data {
struct pinctrl_pin_desc * pa ;
int cur ;
} ;
2013-10-03 08:39:39 +04:00
/**
* struct pcs_soc_data - SoC specific settings
* @ flags : initial SoC specific PCS_FEAT_xxx values
2013-10-03 08:39:40 +04:00
* @ irq : optional interrupt for the controller
* @ irq_enable_mask : optional SoC specific interrupt enable mask
* @ irq_status_mask : optional SoC specific interrupt status mask
2013-10-03 08:39:40 +04:00
* @ rearm : optional SoC specific wake - up rearm function
2013-10-03 08:39:39 +04:00
*/
struct pcs_soc_data {
unsigned flags ;
2013-10-03 08:39:40 +04:00
int irq ;
unsigned irq_enable_mask ;
unsigned irq_status_mask ;
2013-10-03 08:39:40 +04:00
void ( * rearm ) ( void ) ;
2013-10-03 08:39:39 +04:00
} ;
2012-07-10 13:05:46 +04:00
/**
* struct pcs_device - pinctrl device instance
* @ res : resources
* @ base : virtual address of the controller
* @ size : size of the ioremapped area
* @ dev : device entry
2016-11-03 19:35:48 +03:00
* @ np : device tree node
2012-07-10 13:05:46 +04:00
* @ pctl : pin controller device
2013-10-03 08:39:39 +04:00
* @ flags : mask of PCS_FEAT_xxx values
2016-11-03 19:35:48 +03:00
* @ missing_nr_pinctrl_cells : for legacy binding , may go away
* @ socdata : soc specific data
2013-10-03 08:39:40 +04:00
* @ lock : spinlock for register access
2012-07-10 13:05:46 +04:00
* @ mutex : mutex protecting the lists
* @ width : bits per mux register
* @ fmask : function register mask
* @ fshift : function register shift
* @ foff : value to turn mux off
* @ fmax : max number of functions in fmask
2016-11-03 19:35:48 +03:00
* @ bits_per_mux : number of bits per mux
* @ bits_per_pin : number of bits per pin
2012-07-10 13:05:46 +04:00
* @ pins : physical pins on the SoC
2013-02-17 15:42:52 +04:00
* @ gpiofuncs : list of gpio functions
2013-10-03 08:39:40 +04:00
* @ irqs : list of interrupt registers
* @ chip : chip container for this instance
* @ domain : IRQ domain for this instance
2012-07-10 13:05:46 +04:00
* @ desc : pin controller descriptor
* @ read : register read function to use
* @ write : register write function to use
*/
struct pcs_device {
struct resource * res ;
void __iomem * base ;
unsigned size ;
struct device * dev ;
2016-11-03 19:35:48 +03:00
struct device_node * np ;
2012-07-10 13:05:46 +04:00
struct pinctrl_dev * pctl ;
2013-10-03 08:39:39 +04:00
unsigned flags ;
2013-10-03 08:39:40 +04:00
# define PCS_QUIRK_SHARED_IRQ (1 << 2)
# define PCS_FEAT_IRQ (1 << 1)
2013-10-03 08:39:39 +04:00
# define PCS_FEAT_PINCONF (1 << 0)
2016-11-03 19:35:48 +03:00
struct property * missing_nr_pinctrl_cells ;
2013-10-03 08:39:40 +04:00
struct pcs_soc_data socdata ;
raw_spinlock_t lock ;
2012-07-10 13:05:46 +04:00
struct mutex mutex ;
unsigned width ;
unsigned fmask ;
unsigned fshift ;
unsigned foff ;
unsigned fmax ;
2012-09-11 12:54:24 +04:00
bool bits_per_mux ;
2013-05-21 18:08:00 +04:00
unsigned bits_per_pin ;
2012-07-10 13:05:46 +04:00
struct pcs_data pins ;
2013-02-17 15:42:52 +04:00
struct list_head gpiofuncs ;
2013-10-03 08:39:40 +04:00
struct list_head irqs ;
struct irq_chip chip ;
struct irq_domain * domain ;
2012-07-10 13:05:46 +04:00
struct pinctrl_desc desc ;
unsigned ( * read ) ( void __iomem * reg ) ;
void ( * write ) ( unsigned val , void __iomem * reg ) ;
} ;
2013-10-03 08:39:40 +04:00
# define PCS_QUIRK_HAS_SHARED_IRQ (pcs->flags & PCS_QUIRK_SHARED_IRQ)
# define PCS_HAS_IRQ (pcs->flags & PCS_FEAT_IRQ)
2013-10-03 08:39:39 +04:00
# define PCS_HAS_PINCONF (pcs->flags & PCS_FEAT_PINCONF)
2013-02-17 15:42:55 +04:00
static int pcs_pinconf_get ( struct pinctrl_dev * pctldev , unsigned pin ,
unsigned long * config ) ;
static int pcs_pinconf_set ( struct pinctrl_dev * pctldev , unsigned pin ,
2013-08-27 22:32:12 +04:00
unsigned long * configs , unsigned num_configs ) ;
2013-02-17 15:42:55 +04:00
static enum pin_config_param pcs_bias [ ] = {
PIN_CONFIG_BIAS_PULL_DOWN ,
PIN_CONFIG_BIAS_PULL_UP ,
} ;
2016-02-01 21:28:17 +03:00
/*
* This lock class tells lockdep that irqchip core that this single
* pinctrl can be in a different category than its parents , so it won ' t
* report false recursion .
*/
static struct lock_class_key pcs_lock_class ;
2012-07-10 13:05:46 +04:00
/*
* REVISIT : Reads and writes could eventually use regmap or something
* generic . But at least on omaps , some mux registers are performance
* critical as they may need to be remuxed every time before and after
* idle . Adding tests for register access width for every read and
* write like regmap is doing is not desired , and caching the registers
* does not help in this case .
*/
static unsigned __maybe_unused pcs_readb ( void __iomem * reg )
{
return readb ( reg ) ;
}
static unsigned __maybe_unused pcs_readw ( void __iomem * reg )
{
return readw ( reg ) ;
}
static unsigned __maybe_unused pcs_readl ( void __iomem * reg )
{
return readl ( reg ) ;
}
static void __maybe_unused pcs_writeb ( unsigned val , void __iomem * reg )
{
writeb ( val , reg ) ;
}
static void __maybe_unused pcs_writew ( unsigned val , void __iomem * reg )
{
writew ( val , reg ) ;
}
static void __maybe_unused pcs_writel ( unsigned val , void __iomem * reg )
{
writel ( val , reg ) ;
}
static void pcs_pin_dbg_show ( struct pinctrl_dev * pctldev ,
struct seq_file * s ,
2012-11-07 19:19:42 +04:00
unsigned pin )
2012-07-10 13:05:46 +04:00
{
2012-09-26 23:07:43 +04:00
struct pcs_device * pcs ;
2012-11-07 19:19:42 +04:00
unsigned val , mux_bytes ;
2016-10-27 17:59:52 +03:00
unsigned long offset ;
size_t pa ;
2012-09-26 23:07:43 +04:00
pcs = pinctrl_dev_get_drvdata ( pctldev ) ;
2012-11-07 19:19:42 +04:00
mux_bytes = pcs - > width / BITS_PER_BYTE ;
2016-10-27 17:59:52 +03:00
offset = pin * mux_bytes ;
val = pcs - > read ( pcs - > base + offset ) ;
pa = pcs - > res - > start + offset ;
2012-09-26 23:07:43 +04:00
2016-10-27 17:59:52 +03:00
seq_printf ( s , " %zx %08x %s " , pa , val , DRIVER_NAME ) ;
2012-07-10 13:05:46 +04:00
}
static void pcs_dt_free_map ( struct pinctrl_dev * pctldev ,
struct pinctrl_map * map , unsigned num_maps )
{
struct pcs_device * pcs ;
pcs = pinctrl_dev_get_drvdata ( pctldev ) ;
devm_kfree ( pcs - > dev , map ) ;
}
static int pcs_dt_node_to_map ( struct pinctrl_dev * pctldev ,
struct device_node * np_config ,
struct pinctrl_map * * map , unsigned * num_maps ) ;
2013-02-16 13:25:07 +04:00
static const struct pinctrl_ops pcs_pinctrl_ops = {
2016-12-27 20:20:02 +03:00
. get_groups_count = pinctrl_generic_get_group_count ,
. get_group_name = pinctrl_generic_get_group_name ,
. get_group_pins = pinctrl_generic_get_group_pins ,
2012-07-10 13:05:46 +04:00
. pin_dbg_show = pcs_pin_dbg_show ,
. dt_node_to_map = pcs_dt_node_to_map ,
. dt_free_map = pcs_dt_free_map ,
} ;
2013-02-17 15:42:55 +04:00
static int pcs_get_function ( struct pinctrl_dev * pctldev , unsigned pin ,
struct pcs_function * * func )
{
struct pcs_device * pcs = pinctrl_dev_get_drvdata ( pctldev ) ;
struct pin_desc * pdesc = pin_desc_get ( pctldev , pin ) ;
const struct pinctrl_setting_mux * setting ;
2016-12-27 20:20:03 +03:00
struct function_desc * function ;
2013-02-17 15:42:55 +04:00
unsigned fselector ;
/* If pin is not described in DTS & enabled, mux_setting is NULL. */
setting = pdesc - > mux_setting ;
if ( ! setting )
return - ENOTSUPP ;
fselector = setting - > func ;
2016-12-27 20:20:03 +03:00
function = pinmux_generic_get_function ( pctldev , fselector ) ;
* func = function - > data ;
2013-02-17 15:42:55 +04:00
if ( ! ( * func ) ) {
dev_err ( pcs - > dev , " %s could not find function%i \n " ,
__func__ , fselector ) ;
return - ENOTSUPP ;
}
return 0 ;
}
2014-09-03 15:02:56 +04:00
static int pcs_set_mux ( struct pinctrl_dev * pctldev , unsigned fselector ,
2012-07-10 13:05:46 +04:00
unsigned group )
{
struct pcs_device * pcs ;
2016-12-27 20:20:03 +03:00
struct function_desc * function ;
2012-07-10 13:05:46 +04:00
struct pcs_function * func ;
int i ;
pcs = pinctrl_dev_get_drvdata ( pctldev ) ;
2013-02-17 15:42:54 +04:00
/* If function mask is null, needn't enable it. */
if ( ! pcs - > fmask )
return 0 ;
2016-12-27 20:20:03 +03:00
function = pinmux_generic_get_function ( pctldev , fselector ) ;
func = function - > data ;
2012-07-10 13:05:46 +04:00
if ( ! func )
return - EINVAL ;
dev_dbg ( pcs - > dev , " enabling %s function%i \n " ,
func - > name , fselector ) ;
for ( i = 0 ; i < func - > nvals ; i + + ) {
struct pcs_func_vals * vals ;
2013-10-03 08:39:40 +04:00
unsigned long flags ;
2012-09-11 12:54:24 +04:00
unsigned val , mask ;
2012-07-10 13:05:46 +04:00
vals = & func - > vals [ i ] ;
2013-10-03 08:39:40 +04:00
raw_spin_lock_irqsave ( & pcs - > lock , flags ) ;
2012-07-10 13:05:46 +04:00
val = pcs - > read ( vals - > reg ) ;
2013-05-21 18:08:00 +04:00
if ( pcs - > bits_per_mux )
mask = vals - > mask ;
2012-09-11 12:54:24 +04:00
else
2013-05-21 18:08:00 +04:00
mask = pcs - > fmask ;
2012-09-11 12:54:24 +04:00
val & = ~ mask ;
val | = ( vals - > val & mask ) ;
2012-07-10 13:05:46 +04:00
pcs - > write ( val , vals - > reg ) ;
2013-10-03 08:39:40 +04:00
raw_spin_unlock_irqrestore ( & pcs - > lock , flags ) ;
2012-07-10 13:05:46 +04:00
}
return 0 ;
}
static int pcs_request_gpio ( struct pinctrl_dev * pctldev ,
2013-02-17 15:42:52 +04:00
struct pinctrl_gpio_range * range , unsigned pin )
2012-07-10 13:05:46 +04:00
{
2013-02-17 15:42:52 +04:00
struct pcs_device * pcs = pinctrl_dev_get_drvdata ( pctldev ) ;
struct pcs_gpiofunc_range * frange = NULL ;
struct list_head * pos , * tmp ;
int mux_bytes = 0 ;
unsigned data ;
2013-02-17 15:42:54 +04:00
/* If function mask is null, return directly. */
if ( ! pcs - > fmask )
return - ENOTSUPP ;
2013-02-17 15:42:52 +04:00
list_for_each_safe ( pos , tmp , & pcs - > gpiofuncs ) {
frange = list_entry ( pos , struct pcs_gpiofunc_range , node ) ;
if ( pin > = frange - > offset + frange - > npins
| | pin < frange - > offset )
continue ;
mux_bytes = pcs - > width / BITS_PER_BYTE ;
data = pcs - > read ( pcs - > base + pin * mux_bytes ) & ~ pcs - > fmask ;
data | = frange - > gpiofunc ;
pcs - > write ( data , pcs - > base + pin * mux_bytes ) ;
break ;
}
return 0 ;
2012-07-10 13:05:46 +04:00
}
2013-02-16 13:25:07 +04:00
static const struct pinmux_ops pcs_pinmux_ops = {
2016-12-27 20:20:03 +03:00
. get_functions_count = pinmux_generic_get_function_count ,
. get_function_name = pinmux_generic_get_function_name ,
. get_function_groups = pinmux_generic_get_function_groups ,
2014-09-05 11:53:23 +04:00
. set_mux = pcs_set_mux ,
2012-07-10 13:05:46 +04:00
. gpio_request_enable = pcs_request_gpio ,
} ;
2013-02-17 15:42:55 +04:00
/* Clear BIAS value */
static void pcs_pinconf_clear_bias ( struct pinctrl_dev * pctldev , unsigned pin )
{
unsigned long config ;
int i ;
for ( i = 0 ; i < ARRAY_SIZE ( pcs_bias ) ; i + + ) {
config = pinconf_to_config_packed ( pcs_bias [ i ] , 0 ) ;
2013-08-27 22:32:12 +04:00
pcs_pinconf_set ( pctldev , pin , & config , 1 ) ;
2013-02-17 15:42:55 +04:00
}
}
/*
* Check whether PIN_CONFIG_BIAS_DISABLE is valid .
* It ' s depend on that PULL_DOWN & PULL_UP configs are all invalid .
*/
static bool pcs_pinconf_bias_disable ( struct pinctrl_dev * pctldev , unsigned pin )
{
unsigned long config ;
int i ;
for ( i = 0 ; i < ARRAY_SIZE ( pcs_bias ) ; i + + ) {
config = pinconf_to_config_packed ( pcs_bias [ i ] , 0 ) ;
if ( ! pcs_pinconf_get ( pctldev , pin , & config ) )
goto out ;
}
return true ;
out :
return false ;
}
2012-07-10 13:05:46 +04:00
static int pcs_pinconf_get ( struct pinctrl_dev * pctldev ,
unsigned pin , unsigned long * config )
{
2013-02-17 15:42:55 +04:00
struct pcs_device * pcs = pinctrl_dev_get_drvdata ( pctldev ) ;
struct pcs_function * func ;
enum pin_config_param param ;
unsigned offset = 0 , data = 0 , i , j , ret ;
ret = pcs_get_function ( pctldev , pin , & func ) ;
if ( ret )
return ret ;
for ( i = 0 ; i < func - > nconfs ; i + + ) {
param = pinconf_to_config_param ( * config ) ;
if ( param = = PIN_CONFIG_BIAS_DISABLE ) {
if ( pcs_pinconf_bias_disable ( pctldev , pin ) ) {
* config = 0 ;
return 0 ;
} else {
return - ENOTSUPP ;
}
} else if ( param ! = func - > conf [ i ] . param ) {
continue ;
}
offset = pin * ( pcs - > width / BITS_PER_BYTE ) ;
data = pcs - > read ( pcs - > base + offset ) & func - > conf [ i ] . mask ;
switch ( func - > conf [ i ] . param ) {
/* 4 parameters */
case PIN_CONFIG_BIAS_PULL_DOWN :
case PIN_CONFIG_BIAS_PULL_UP :
case PIN_CONFIG_INPUT_SCHMITT_ENABLE :
if ( ( data ! = func - > conf [ i ] . enable ) | |
( data = = func - > conf [ i ] . disable ) )
return - ENOTSUPP ;
* config = 0 ;
break ;
/* 2 parameters */
case PIN_CONFIG_INPUT_SCHMITT :
for ( j = 0 ; j < func - > nconfs ; j + + ) {
switch ( func - > conf [ j ] . param ) {
case PIN_CONFIG_INPUT_SCHMITT_ENABLE :
if ( data ! = func - > conf [ j ] . enable )
return - ENOTSUPP ;
break ;
default :
break ;
}
}
* config = data ;
break ;
case PIN_CONFIG_DRIVE_STRENGTH :
case PIN_CONFIG_SLEW_RATE :
2014-01-28 11:20:44 +04:00
case PIN_CONFIG_LOW_POWER_MODE :
2013-02-17 15:42:55 +04:00
default :
* config = data ;
break ;
}
return 0 ;
}
2012-07-10 13:05:46 +04:00
return - ENOTSUPP ;
}
static int pcs_pinconf_set ( struct pinctrl_dev * pctldev ,
2013-08-27 22:32:12 +04:00
unsigned pin , unsigned long * configs ,
unsigned num_configs )
2012-07-10 13:05:46 +04:00
{
2013-02-17 15:42:55 +04:00
struct pcs_device * pcs = pinctrl_dev_get_drvdata ( pctldev ) ;
struct pcs_function * func ;
2013-03-13 12:01:26 +04:00
unsigned offset = 0 , shift = 0 , i , data , ret ;
u16 arg ;
2013-08-27 22:32:12 +04:00
int j ;
2013-02-17 15:42:55 +04:00
ret = pcs_get_function ( pctldev , pin , & func ) ;
if ( ret )
return ret ;
2013-08-27 22:32:12 +04:00
for ( j = 0 ; j < num_configs ; j + + ) {
for ( i = 0 ; i < func - > nconfs ; i + + ) {
if ( pinconf_to_config_param ( configs [ j ] )
! = func - > conf [ i ] . param )
continue ;
2013-02-17 15:42:55 +04:00
offset = pin * ( pcs - > width / BITS_PER_BYTE ) ;
data = pcs - > read ( pcs - > base + offset ) ;
2013-08-27 22:32:12 +04:00
arg = pinconf_to_config_argument ( configs [ j ] ) ;
2013-02-17 15:42:55 +04:00
switch ( func - > conf [ i ] . param ) {
/* 2 parameters */
case PIN_CONFIG_INPUT_SCHMITT :
case PIN_CONFIG_DRIVE_STRENGTH :
case PIN_CONFIG_SLEW_RATE :
2014-01-28 11:20:44 +04:00
case PIN_CONFIG_LOW_POWER_MODE :
2013-02-17 15:42:55 +04:00
shift = ffs ( func - > conf [ i ] . mask ) - 1 ;
data & = ~ func - > conf [ i ] . mask ;
data | = ( arg < < shift ) & func - > conf [ i ] . mask ;
break ;
/* 4 parameters */
case PIN_CONFIG_BIAS_DISABLE :
pcs_pinconf_clear_bias ( pctldev , pin ) ;
break ;
case PIN_CONFIG_BIAS_PULL_DOWN :
case PIN_CONFIG_BIAS_PULL_UP :
2013-03-13 12:01:26 +04:00
if ( arg )
2013-02-17 15:42:55 +04:00
pcs_pinconf_clear_bias ( pctldev , pin ) ;
/* fall through */
case PIN_CONFIG_INPUT_SCHMITT_ENABLE :
data & = ~ func - > conf [ i ] . mask ;
2013-03-13 12:01:26 +04:00
if ( arg )
2013-02-17 15:42:55 +04:00
data | = func - > conf [ i ] . enable ;
else
data | = func - > conf [ i ] . disable ;
break ;
default :
return - ENOTSUPP ;
}
pcs - > write ( data , pcs - > base + offset ) ;
2013-08-27 22:32:12 +04:00
break ;
2013-02-17 15:42:55 +04:00
}
2013-08-27 22:32:12 +04:00
if ( i > = func - > nconfs )
return - ENOTSUPP ;
} /* for each config */
return 0 ;
2012-07-10 13:05:46 +04:00
}
static int pcs_pinconf_group_get ( struct pinctrl_dev * pctldev ,
unsigned group , unsigned long * config )
{
2013-02-17 15:42:55 +04:00
const unsigned * pins ;
unsigned npins , old = 0 ;
int i , ret ;
2016-12-27 20:20:02 +03:00
ret = pinctrl_generic_get_group_pins ( pctldev , group , & pins , & npins ) ;
2013-02-17 15:42:55 +04:00
if ( ret )
return ret ;
for ( i = 0 ; i < npins ; i + + ) {
if ( pcs_pinconf_get ( pctldev , pins [ i ] , config ) )
return - ENOTSUPP ;
/* configs do not match between two pins */
if ( i & & ( old ! = * config ) )
return - ENOTSUPP ;
old = * config ;
}
return 0 ;
2012-07-10 13:05:46 +04:00
}
static int pcs_pinconf_group_set ( struct pinctrl_dev * pctldev ,
2013-08-27 22:32:12 +04:00
unsigned group , unsigned long * configs ,
unsigned num_configs )
2012-07-10 13:05:46 +04:00
{
2013-02-17 15:42:55 +04:00
const unsigned * pins ;
unsigned npins ;
int i , ret ;
2016-12-27 20:20:02 +03:00
ret = pinctrl_generic_get_group_pins ( pctldev , group , & pins , & npins ) ;
2013-02-17 15:42:55 +04:00
if ( ret )
return ret ;
for ( i = 0 ; i < npins ; i + + ) {
2013-08-27 22:32:12 +04:00
if ( pcs_pinconf_set ( pctldev , pins [ i ] , configs , num_configs ) )
2013-02-17 15:42:55 +04:00
return - ENOTSUPP ;
}
return 0 ;
2012-07-10 13:05:46 +04:00
}
static void pcs_pinconf_dbg_show ( struct pinctrl_dev * pctldev ,
2013-02-17 15:42:55 +04:00
struct seq_file * s , unsigned pin )
2012-07-10 13:05:46 +04:00
{
}
static void pcs_pinconf_group_dbg_show ( struct pinctrl_dev * pctldev ,
struct seq_file * s , unsigned selector )
{
}
2013-02-17 15:42:55 +04:00
static void pcs_pinconf_config_dbg_show ( struct pinctrl_dev * pctldev ,
struct seq_file * s ,
unsigned long config )
{
pinconf_generic_dump_config ( pctldev , s , config ) ;
}
2013-02-16 13:25:07 +04:00
static const struct pinconf_ops pcs_pinconf_ops = {
2012-07-10 13:05:46 +04:00
. pin_config_get = pcs_pinconf_get ,
. pin_config_set = pcs_pinconf_set ,
. pin_config_group_get = pcs_pinconf_group_get ,
. pin_config_group_set = pcs_pinconf_group_set ,
. pin_config_dbg_show = pcs_pinconf_dbg_show ,
. pin_config_group_dbg_show = pcs_pinconf_group_dbg_show ,
2013-02-17 15:42:55 +04:00
. pin_config_config_dbg_show = pcs_pinconf_config_dbg_show ,
2013-03-04 09:47:39 +04:00
. is_generic = true ,
2012-07-10 13:05:46 +04:00
} ;
/**
* pcs_add_pin ( ) - add a pin to the static per controller pin array
* @ pcs : pcs driver instance
* @ offset : register offset from base
*/
2013-05-21 18:08:01 +04:00
static int pcs_add_pin ( struct pcs_device * pcs , unsigned offset ,
unsigned pin_pos )
2012-07-10 13:05:46 +04:00
{
2014-04-11 03:47:19 +04:00
struct pcs_soc_data * pcs_soc = & pcs - > socdata ;
2012-07-10 13:05:46 +04:00
struct pinctrl_pin_desc * pin ;
int i ;
i = pcs - > pins . cur ;
if ( i > = pcs - > desc . npins ) {
dev_err ( pcs - > dev , " too many pins, max %i \n " ,
pcs - > desc . npins ) ;
return - ENOMEM ;
}
2014-04-11 03:47:19 +04:00
if ( pcs_soc - > irq_enable_mask ) {
unsigned val ;
val = pcs - > read ( pcs - > base + offset ) ;
if ( val & pcs_soc - > irq_enable_mask ) {
dev_dbg ( pcs - > dev , " irq enabled at boot for pin at %lx (%x), clearing \n " ,
( unsigned long ) pcs - > res - > start + offset , val ) ;
val & = ~ pcs_soc - > irq_enable_mask ;
pcs - > write ( val , pcs - > base + offset ) ;
}
}
2012-07-10 13:05:46 +04:00
pin = & pcs - > pins . pa [ i ] ;
pin - > number = i ;
pcs - > pins . cur + + ;
return i ;
}
/**
* pcs_allocate_pin_table ( ) - adds all the pins for the pinctrl driver
* @ pcs : pcs driver instance
*
* In case of errors , resources are freed in pcs_free_resources .
*
* If your hardware needs holes in the address space , then just set
* up multiple driver instances .
*/
2012-12-22 01:10:23 +04:00
static int pcs_allocate_pin_table ( struct pcs_device * pcs )
2012-07-10 13:05:46 +04:00
{
int mux_bytes , nr_pins , i ;
2013-05-21 18:08:01 +04:00
int num_pins_in_register = 0 ;
2012-07-10 13:05:46 +04:00
mux_bytes = pcs - > width / BITS_PER_BYTE ;
2013-05-21 18:08:00 +04:00
if ( pcs - > bits_per_mux ) {
pcs - > bits_per_pin = fls ( pcs - > fmask ) ;
nr_pins = ( pcs - > size * BITS_PER_BYTE ) / pcs - > bits_per_pin ;
2013-05-21 18:08:01 +04:00
num_pins_in_register = pcs - > width / pcs - > bits_per_pin ;
2013-05-21 18:08:00 +04:00
} else {
nr_pins = pcs - > size / mux_bytes ;
}
2012-07-10 13:05:46 +04:00
dev_dbg ( pcs - > dev , " allocating %i pins \n " , nr_pins ) ;
pcs - > pins . pa = devm_kzalloc ( pcs - > dev ,
sizeof ( * pcs - > pins . pa ) * nr_pins ,
GFP_KERNEL ) ;
if ( ! pcs - > pins . pa )
return - ENOMEM ;
pcs - > desc . pins = pcs - > pins . pa ;
pcs - > desc . npins = nr_pins ;
for ( i = 0 ; i < pcs - > desc . npins ; i + + ) {
unsigned offset ;
int res ;
2013-05-21 18:08:00 +04:00
int byte_num ;
2013-05-21 18:08:01 +04:00
int pin_pos = 0 ;
2012-07-10 13:05:46 +04:00
2013-05-21 18:08:00 +04:00
if ( pcs - > bits_per_mux ) {
byte_num = ( pcs - > bits_per_pin * i ) / BITS_PER_BYTE ;
offset = ( byte_num / mux_bytes ) * mux_bytes ;
2013-05-21 18:08:01 +04:00
pin_pos = i % num_pins_in_register ;
2013-05-21 18:08:00 +04:00
} else {
offset = i * mux_bytes ;
}
2013-05-21 18:08:01 +04:00
res = pcs_add_pin ( pcs , offset , pin_pos ) ;
2012-07-10 13:05:46 +04:00
if ( res < 0 ) {
dev_err ( pcs - > dev , " error adding pins: %i \n " , res ) ;
return res ;
}
}
return 0 ;
}
/**
* pcs_add_function ( ) - adds a new function to the function list
* @ pcs : pcs driver instance
* @ np : device node of the mux entry
* @ name : name of the function
* @ vals : array of mux register value pairs used by the function
* @ nvals : number of mux register value pairs
* @ pgnames : array of pingroup names for the function
* @ npgnames : number of pingroup names
*/
static struct pcs_function * pcs_add_function ( struct pcs_device * pcs ,
struct device_node * np ,
const char * name ,
struct pcs_func_vals * vals ,
unsigned nvals ,
const char * * pgnames ,
unsigned npgnames )
{
struct pcs_function * function ;
2016-12-27 20:20:03 +03:00
int res ;
2012-07-10 13:05:46 +04:00
function = devm_kzalloc ( pcs - > dev , sizeof ( * function ) , GFP_KERNEL ) ;
if ( ! function )
return NULL ;
function - > vals = vals ;
function - > nvals = nvals ;
2016-12-27 20:20:03 +03:00
res = pinmux_generic_add_function ( pcs - > pctl , name ,
pgnames , npgnames ,
function ) ;
if ( res )
return NULL ;
2012-07-10 13:05:46 +04:00
return function ;
}
/**
* pcs_get_pin_by_offset ( ) - get a pin index based on the register offset
* @ pcs : pcs driver instance
* @ offset : register offset from the base
*
* Note that this is OK as long as the pins are in a static array .
*/
static int pcs_get_pin_by_offset ( struct pcs_device * pcs , unsigned offset )
{
unsigned index ;
if ( offset > = pcs - > size ) {
dev_err ( pcs - > dev , " mux offset out of range: 0x%x (0x%x) \n " ,
offset , pcs - > size ) ;
return - EINVAL ;
}
2013-05-21 18:08:00 +04:00
if ( pcs - > bits_per_mux )
index = ( offset * BITS_PER_BYTE ) / pcs - > bits_per_pin ;
else
index = offset / ( pcs - > width / BITS_PER_BYTE ) ;
2012-07-10 13:05:46 +04:00
return index ;
}
2013-02-17 15:42:55 +04:00
/*
* check whether data matches enable bits or disable bits
* Return value : 1 for matching enable bits , 0 for matching disable bits ,
* and negative value for matching failure .
*/
static int pcs_config_match ( unsigned data , unsigned enable , unsigned disable )
{
int ret = - EINVAL ;
if ( data = = enable )
ret = 1 ;
else if ( data = = disable )
ret = 0 ;
return ret ;
}
static void add_config ( struct pcs_conf_vals * * conf , enum pin_config_param param ,
unsigned value , unsigned enable , unsigned disable ,
unsigned mask )
{
( * conf ) - > param = param ;
( * conf ) - > val = value ;
( * conf ) - > enable = enable ;
( * conf ) - > disable = disable ;
( * conf ) - > mask = mask ;
( * conf ) + + ;
}
static void add_setting ( unsigned long * * setting , enum pin_config_param param ,
unsigned arg )
{
* * setting = pinconf_to_config_packed ( param , arg ) ;
( * setting ) + + ;
}
/* add pinconf setting with 2 parameters */
static void pcs_add_conf2 ( struct pcs_device * pcs , struct device_node * np ,
const char * name , enum pin_config_param param ,
struct pcs_conf_vals * * conf , unsigned long * * settings )
{
2013-03-13 12:01:26 +04:00
unsigned value [ 2 ] , shift ;
2013-02-17 15:42:55 +04:00
int ret ;
ret = of_property_read_u32_array ( np , name , value , 2 ) ;
if ( ret )
return ;
/* set value & mask */
value [ 0 ] & = value [ 1 ] ;
2013-03-13 12:01:26 +04:00
shift = ffs ( value [ 1 ] ) - 1 ;
2013-02-17 15:42:55 +04:00
/* skip enable & disable */
add_config ( conf , param , value [ 0 ] , 0 , 0 , value [ 1 ] ) ;
2013-03-13 12:01:26 +04:00
add_setting ( settings , param , value [ 0 ] > > shift ) ;
2013-02-17 15:42:55 +04:00
}
/* add pinconf setting with 4 parameters */
static void pcs_add_conf4 ( struct pcs_device * pcs , struct device_node * np ,
const char * name , enum pin_config_param param ,
struct pcs_conf_vals * * conf , unsigned long * * settings )
{
unsigned value [ 4 ] ;
int ret ;
/* value to set, enable, disable, mask */
ret = of_property_read_u32_array ( np , name , value , 4 ) ;
if ( ret )
return ;
if ( ! value [ 3 ] ) {
dev_err ( pcs - > dev , " mask field of the property can't be 0 \n " ) ;
return ;
}
value [ 0 ] & = value [ 3 ] ;
value [ 1 ] & = value [ 3 ] ;
value [ 2 ] & = value [ 3 ] ;
ret = pcs_config_match ( value [ 0 ] , value [ 1 ] , value [ 2 ] ) ;
if ( ret < 0 )
dev_dbg ( pcs - > dev , " failed to match enable or disable bits \n " ) ;
add_config ( conf , param , value [ 0 ] , value [ 1 ] , value [ 2 ] , value [ 3 ] ) ;
add_setting ( settings , param , ret ) ;
}
static int pcs_parse_pinconf ( struct pcs_device * pcs , struct device_node * np ,
struct pcs_function * func ,
struct pinctrl_map * * map )
{
struct pinctrl_map * m = * map ;
int i = 0 , nconfs = 0 ;
unsigned long * settings = NULL , * s = NULL ;
struct pcs_conf_vals * conf = NULL ;
struct pcs_conf_type prop2 [ ] = {
{ " pinctrl-single,drive-strength " , PIN_CONFIG_DRIVE_STRENGTH , } ,
{ " pinctrl-single,slew-rate " , PIN_CONFIG_SLEW_RATE , } ,
{ " pinctrl-single,input-schmitt " , PIN_CONFIG_INPUT_SCHMITT , } ,
2014-01-28 11:20:44 +04:00
{ " pinctrl-single,low-power-mode " , PIN_CONFIG_LOW_POWER_MODE , } ,
2013-02-17 15:42:55 +04:00
} ;
struct pcs_conf_type prop4 [ ] = {
{ " pinctrl-single,bias-pullup " , PIN_CONFIG_BIAS_PULL_UP , } ,
{ " pinctrl-single,bias-pulldown " , PIN_CONFIG_BIAS_PULL_DOWN , } ,
{ " pinctrl-single,input-schmitt-enable " ,
PIN_CONFIG_INPUT_SCHMITT_ENABLE , } ,
} ;
/* If pinconf isn't supported, don't parse properties in below. */
2013-10-03 08:39:39 +04:00
if ( ! PCS_HAS_PINCONF )
2013-02-17 15:42:55 +04:00
return 0 ;
/* cacluate how much properties are supported in current node */
for ( i = 0 ; i < ARRAY_SIZE ( prop2 ) ; i + + ) {
if ( of_find_property ( np , prop2 [ i ] . name , NULL ) )
nconfs + + ;
}
for ( i = 0 ; i < ARRAY_SIZE ( prop4 ) ; i + + ) {
if ( of_find_property ( np , prop4 [ i ] . name , NULL ) )
nconfs + + ;
}
if ( ! nconfs )
return 0 ;
func - > conf = devm_kzalloc ( pcs - > dev ,
sizeof ( struct pcs_conf_vals ) * nconfs ,
GFP_KERNEL ) ;
if ( ! func - > conf )
return - ENOMEM ;
func - > nconfs = nconfs ;
conf = & ( func - > conf [ 0 ] ) ;
m + + ;
settings = devm_kzalloc ( pcs - > dev , sizeof ( unsigned long ) * nconfs ,
GFP_KERNEL ) ;
if ( ! settings )
return - ENOMEM ;
s = & settings [ 0 ] ;
for ( i = 0 ; i < ARRAY_SIZE ( prop2 ) ; i + + )
pcs_add_conf2 ( pcs , np , prop2 [ i ] . name , prop2 [ i ] . param ,
& conf , & s ) ;
for ( i = 0 ; i < ARRAY_SIZE ( prop4 ) ; i + + )
pcs_add_conf4 ( pcs , np , prop4 [ i ] . name , prop4 [ i ] . param ,
& conf , & s ) ;
m - > type = PIN_MAP_TYPE_CONFIGS_GROUP ;
m - > data . configs . group_or_pin = np - > name ;
m - > data . configs . configs = settings ;
m - > data . configs . num_configs = nconfs ;
return 0 ;
}
2012-07-10 13:05:46 +04:00
/**
* smux_parse_one_pinctrl_entry ( ) - parses a device tree mux entry
2016-12-27 20:20:02 +03:00
* @ pctldev : pin controller device
2012-07-10 13:05:46 +04:00
* @ pcs : pinctrl driver instance
* @ np : device node of the mux entry
* @ map : map entry
2013-02-17 15:42:55 +04:00
* @ num_maps : number of map
2012-07-10 13:05:46 +04:00
* @ pgnames : pingroup names
*
* Note that this binding currently supports only sets of one register + value .
*
* Also note that this driver tries to avoid understanding pin and function
* names because of the extra bloat they would cause especially in the case of
* a large number of pins . This driver just sets what is specified for the board
* in the . dts file . Further user space debugging tools can be developed to
* decipher the pin and function names using debugfs .
*
* If you are concerned about the boot time , set up the static pins in
* the bootloader , and only set up selected pins as device tree entries .
*/
static int pcs_parse_one_pinctrl_entry ( struct pcs_device * pcs ,
struct device_node * np ,
struct pinctrl_map * * map ,
2013-02-17 15:42:55 +04:00
unsigned * num_maps ,
2012-07-10 13:05:46 +04:00
const char * * pgnames )
{
2016-11-03 19:35:48 +03:00
const char * name = " pinctrl-single,pins " ;
2012-07-10 13:05:46 +04:00
struct pcs_func_vals * vals ;
2016-11-03 19:35:48 +03:00
int rows , * pins , found = 0 , res = - ENOMEM , i ;
2012-07-10 13:05:46 +04:00
struct pcs_function * function ;
2016-11-03 19:35:48 +03:00
rows = pinctrl_count_index_with_args ( np , name ) ;
2016-11-09 17:54:00 +03:00
if ( rows < = 0 ) {
2016-12-23 03:47:14 +03:00
dev_err ( pcs - > dev , " Invalid number of rows: %d \n " , rows ) ;
2016-11-09 17:54:00 +03:00
return - EINVAL ;
}
2012-07-10 13:05:46 +04:00
vals = devm_kzalloc ( pcs - > dev , sizeof ( * vals ) * rows , GFP_KERNEL ) ;
if ( ! vals )
return - ENOMEM ;
pins = devm_kzalloc ( pcs - > dev , sizeof ( * pins ) * rows , GFP_KERNEL ) ;
if ( ! pins )
goto free_vals ;
2016-11-03 19:35:48 +03:00
for ( i = 0 ; i < rows ; i + + ) {
struct of_phandle_args pinctrl_spec ;
unsigned int offset ;
2012-07-10 13:05:46 +04:00
int pin ;
2016-11-03 19:35:48 +03:00
res = pinctrl_parse_index_with_args ( np , name , i , & pinctrl_spec ) ;
if ( res )
return res ;
if ( pinctrl_spec . args_count < 2 ) {
dev_err ( pcs - > dev , " invalid args_count for spec: %i \n " ,
pinctrl_spec . args_count ) ;
break ;
}
/* Index plus one value cell */
offset = pinctrl_spec . args [ 0 ] ;
2012-07-10 13:05:46 +04:00
vals [ found ] . reg = pcs - > base + offset ;
2016-11-03 19:35:48 +03:00
vals [ found ] . val = pinctrl_spec . args [ 1 ] ;
dev_dbg ( pcs - > dev , " %s index: 0x%x value: 0x%x \n " ,
pinctrl_spec . np - > name , offset , pinctrl_spec . args [ 1 ] ) ;
2012-07-10 13:05:46 +04:00
pin = pcs_get_pin_by_offset ( pcs , offset ) ;
if ( pin < 0 ) {
dev_err ( pcs - > dev ,
" could not add functions for %s %ux \n " ,
np - > name , offset ) ;
break ;
}
pins [ found + + ] = pin ;
}
pgnames [ 0 ] = np - > name ;
function = pcs_add_function ( pcs , np , np - > name , vals , found , pgnames , 1 ) ;
2016-11-16 14:41:51 +03:00
if ( ! function ) {
res = - ENOMEM ;
2012-07-10 13:05:46 +04:00
goto free_pins ;
2016-11-16 14:41:51 +03:00
}
2012-07-10 13:05:46 +04:00
2016-12-27 20:20:02 +03:00
res = pinctrl_generic_add_group ( pcs - > pctl , np - > name , pins , found , pcs ) ;
2012-07-10 13:05:46 +04:00
if ( res < 0 )
goto free_function ;
( * map ) - > type = PIN_MAP_TYPE_MUX_GROUP ;
( * map ) - > data . mux . group = np - > name ;
( * map ) - > data . mux . function = np - > name ;
2013-10-03 08:39:39 +04:00
if ( PCS_HAS_PINCONF ) {
2013-05-07 16:06:19 +04:00
res = pcs_parse_pinconf ( pcs , np , function , map ) ;
if ( res )
2013-02-17 15:42:55 +04:00
goto free_pingroups ;
* num_maps = 2 ;
} else {
* num_maps = 1 ;
}
2012-07-10 13:05:46 +04:00
return 0 ;
2013-02-17 15:42:55 +04:00
free_pingroups :
2016-12-27 20:20:02 +03:00
pinctrl_generic_remove_last_group ( pcs - > pctl ) ;
2013-02-17 15:42:55 +04:00
* num_maps = 1 ;
2012-07-10 13:05:46 +04:00
free_function :
2016-12-27 20:20:03 +03:00
pinmux_generic_remove_last_function ( pcs - > pctl ) ;
2012-07-10 13:05:46 +04:00
free_pins :
devm_kfree ( pcs - > dev , pins ) ;
2013-05-21 18:08:00 +04:00
free_vals :
devm_kfree ( pcs - > dev , vals ) ;
return res ;
}
static int pcs_parse_bits_in_pinctrl_entry ( struct pcs_device * pcs ,
struct device_node * np ,
struct pinctrl_map * * map ,
unsigned * num_maps ,
const char * * pgnames )
{
2016-11-09 17:54:01 +03:00
const char * name = " pinctrl-single,bits " ;
2013-05-21 18:08:00 +04:00
struct pcs_func_vals * vals ;
2016-11-03 19:35:49 +03:00
int rows , * pins , found = 0 , res = - ENOMEM , i ;
2013-05-21 18:08:00 +04:00
int npins_in_row ;
struct pcs_function * function ;
2016-11-03 19:35:49 +03:00
rows = pinctrl_count_index_with_args ( np , name ) ;
2016-11-09 17:54:00 +03:00
if ( rows < = 0 ) {
dev_err ( pcs - > dev , " Invalid number of rows: %d \n " , rows ) ;
return - EINVAL ;
}
2013-05-21 18:08:00 +04:00
npins_in_row = pcs - > width / pcs - > bits_per_pin ;
vals = devm_kzalloc ( pcs - > dev , sizeof ( * vals ) * rows * npins_in_row ,
GFP_KERNEL ) ;
if ( ! vals )
return - ENOMEM ;
pins = devm_kzalloc ( pcs - > dev , sizeof ( * pins ) * rows * npins_in_row ,
GFP_KERNEL ) ;
if ( ! pins )
goto free_vals ;
2016-11-03 19:35:49 +03:00
for ( i = 0 ; i < rows ; i + + ) {
struct of_phandle_args pinctrl_spec ;
2013-05-21 18:08:00 +04:00
unsigned offset , val ;
unsigned mask , bit_pos , val_pos , mask_pos , submask ;
unsigned pin_num_from_lsb ;
int pin ;
2016-11-03 19:35:49 +03:00
res = pinctrl_parse_index_with_args ( np , name , i , & pinctrl_spec ) ;
if ( res )
return res ;
if ( pinctrl_spec . args_count < 3 ) {
dev_err ( pcs - > dev , " invalid args_count for spec: %i \n " ,
pinctrl_spec . args_count ) ;
break ;
}
/* Index plus two value cells */
offset = pinctrl_spec . args [ 0 ] ;
val = pinctrl_spec . args [ 1 ] ;
mask = pinctrl_spec . args [ 2 ] ;
dev_dbg ( pcs - > dev , " %s index: 0x%x value: 0x%x mask: 0x%x \n " ,
pinctrl_spec . np - > name , offset , val , mask ) ;
2013-05-21 18:08:00 +04:00
/* Parse pins in each row from LSB */
while ( mask ) {
2016-04-14 07:59:16 +03:00
bit_pos = __ffs ( mask ) ;
2013-05-21 18:08:00 +04:00
pin_num_from_lsb = bit_pos / pcs - > bits_per_pin ;
2016-04-14 07:59:16 +03:00
mask_pos = ( ( pcs - > fmask ) < < bit_pos ) ;
2013-05-21 18:08:00 +04:00
val_pos = val & mask_pos ;
submask = mask & mask_pos ;
2014-01-09 16:50:29 +04:00
if ( ( mask & mask_pos ) = = 0 ) {
dev_err ( pcs - > dev ,
" Invalid mask for %s at 0x%x \n " ,
np - > name , offset ) ;
break ;
}
2013-05-21 18:08:00 +04:00
mask & = ~ mask_pos ;
if ( submask ! = mask_pos ) {
dev_warn ( pcs - > dev ,
" Invalid submask 0x%x for %s at 0x%x \n " ,
submask , np - > name , offset ) ;
continue ;
}
vals [ found ] . mask = submask ;
vals [ found ] . reg = pcs - > base + offset ;
vals [ found ] . val = val_pos ;
pin = pcs_get_pin_by_offset ( pcs , offset ) ;
if ( pin < 0 ) {
dev_err ( pcs - > dev ,
" could not add functions for %s %ux \n " ,
np - > name , offset ) ;
break ;
}
pins [ found + + ] = pin + pin_num_from_lsb ;
}
}
pgnames [ 0 ] = np - > name ;
function = pcs_add_function ( pcs , np , np - > name , vals , found , pgnames , 1 ) ;
2016-11-16 14:41:51 +03:00
if ( ! function ) {
res = - ENOMEM ;
2013-05-21 18:08:00 +04:00
goto free_pins ;
2016-11-16 14:41:51 +03:00
}
2013-05-21 18:08:00 +04:00
2016-12-27 20:20:02 +03:00
res = pinctrl_generic_add_group ( pcs - > pctl , np - > name , pins , found , pcs ) ;
2013-05-21 18:08:00 +04:00
if ( res < 0 )
goto free_function ;
( * map ) - > type = PIN_MAP_TYPE_MUX_GROUP ;
( * map ) - > data . mux . group = np - > name ;
( * map ) - > data . mux . function = np - > name ;
2013-10-03 08:39:39 +04:00
if ( PCS_HAS_PINCONF ) {
2013-05-21 18:08:00 +04:00
dev_err ( pcs - > dev , " pinconf not supported \n " ) ;
goto free_pingroups ;
}
* num_maps = 1 ;
return 0 ;
free_pingroups :
2016-12-27 20:20:02 +03:00
pinctrl_generic_remove_last_group ( pcs - > pctl ) ;
2013-05-21 18:08:00 +04:00
* num_maps = 1 ;
free_function :
2016-12-27 20:20:03 +03:00
pinmux_generic_remove_last_function ( pcs - > pctl ) ;
2013-05-21 18:08:00 +04:00
free_pins :
devm_kfree ( pcs - > dev , pins ) ;
2012-07-10 13:05:46 +04:00
free_vals :
devm_kfree ( pcs - > dev , vals ) ;
return res ;
}
/**
* pcs_dt_node_to_map ( ) - allocates and parses pinctrl maps
* @ pctldev : pinctrl instance
* @ np_config : device tree pinmux entry
* @ map : array of map entries
* @ num_maps : number of maps
*/
static int pcs_dt_node_to_map ( struct pinctrl_dev * pctldev ,
struct device_node * np_config ,
struct pinctrl_map * * map , unsigned * num_maps )
{
struct pcs_device * pcs ;
const char * * pgnames ;
int ret ;
pcs = pinctrl_dev_get_drvdata ( pctldev ) ;
2013-02-17 15:42:55 +04:00
/* create 2 maps. One is for pinmux, and the other is for pinconf. */
* map = devm_kzalloc ( pcs - > dev , sizeof ( * * map ) * 2 , GFP_KERNEL ) ;
2012-11-20 15:04:39 +04:00
if ( ! * map )
2012-07-10 13:05:46 +04:00
return - ENOMEM ;
* num_maps = 0 ;
pgnames = devm_kzalloc ( pcs - > dev , sizeof ( * pgnames ) , GFP_KERNEL ) ;
if ( ! pgnames ) {
ret = - ENOMEM ;
goto free_map ;
}
2013-05-21 18:08:00 +04:00
if ( pcs - > bits_per_mux ) {
ret = pcs_parse_bits_in_pinctrl_entry ( pcs , np_config , map ,
num_maps , pgnames ) ;
if ( ret < 0 ) {
dev_err ( pcs - > dev , " no pins entries for %s \n " ,
np_config - > name ) ;
goto free_pgnames ;
}
} else {
ret = pcs_parse_one_pinctrl_entry ( pcs , np_config , map ,
num_maps , pgnames ) ;
if ( ret < 0 ) {
dev_err ( pcs - > dev , " no pins entries for %s \n " ,
np_config - > name ) ;
goto free_pgnames ;
}
2012-07-10 13:05:46 +04:00
}
return 0 ;
free_pgnames :
devm_kfree ( pcs - > dev , pgnames ) ;
free_map :
devm_kfree ( pcs - > dev , * map ) ;
return ret ;
}
2013-10-03 08:39:40 +04:00
/**
* pcs_irq_free ( ) - free interrupt
* @ pcs : pcs driver instance
*/
static void pcs_irq_free ( struct pcs_device * pcs )
{
struct pcs_soc_data * pcs_soc = & pcs - > socdata ;
if ( pcs_soc - > irq < 0 )
return ;
if ( pcs - > domain )
irq_domain_remove ( pcs - > domain ) ;
if ( PCS_QUIRK_HAS_SHARED_IRQ )
free_irq ( pcs_soc - > irq , pcs_soc ) ;
else
irq_set_chained_handler ( pcs_soc - > irq , NULL ) ;
}
2012-07-10 13:05:46 +04:00
/**
* pcs_free_resources ( ) - free memory used by this driver
* @ pcs : pcs driver instance
*/
static void pcs_free_resources ( struct pcs_device * pcs )
{
2013-10-03 08:39:40 +04:00
pcs_irq_free ( pcs ) ;
2015-11-05 19:10:22 +03:00
pinctrl_unregister ( pcs - > pctl ) ;
2016-12-27 20:20:02 +03:00
2016-11-03 19:35:48 +03:00
# if IS_BUILTIN(CONFIG_PINCTRL_SINGLE)
if ( pcs - > missing_nr_pinctrl_cells )
of_remove_property ( pcs - > np , pcs - > missing_nr_pinctrl_cells ) ;
# endif
2012-07-10 13:05:46 +04:00
}
2015-03-16 22:59:09 +03:00
static const struct of_device_id pcs_of_match [ ] ;
2012-07-10 13:05:46 +04:00
2013-02-17 15:42:52 +04:00
static int pcs_add_gpio_func ( struct device_node * node , struct pcs_device * pcs )
{
const char * propname = " pinctrl-single,gpio-range " ;
const char * cellname = " #pinctrl-single,gpio-range-cells " ;
struct of_phandle_args gpiospec ;
struct pcs_gpiofunc_range * range ;
int ret , i ;
for ( i = 0 ; ; i + + ) {
ret = of_parse_phandle_with_args ( node , propname , cellname ,
i , & gpiospec ) ;
/* Do not treat it as error. Only treat it as end condition. */
if ( ret ) {
ret = 0 ;
break ;
}
range = devm_kzalloc ( pcs - > dev , sizeof ( * range ) , GFP_KERNEL ) ;
if ( ! range ) {
ret = - ENOMEM ;
break ;
}
range - > offset = gpiospec . args [ 0 ] ;
range - > npins = gpiospec . args [ 1 ] ;
range - > gpiofunc = gpiospec . args [ 2 ] ;
mutex_lock ( & pcs - > mutex ) ;
list_add_tail ( & range - > node , & pcs - > gpiofuncs ) ;
mutex_unlock ( & pcs - > mutex ) ;
}
return ret ;
}
2013-10-03 08:39:40 +04:00
/**
* @ reg : virtual address of interrupt register
* @ hwirq : hardware irq number
* @ irq : virtual irq number
* @ node : list node
*/
struct pcs_interrupt {
void __iomem * reg ;
irq_hw_number_t hwirq ;
unsigned int irq ;
struct list_head node ;
} ;
/**
* pcs_irq_set ( ) - enables or disables an interrupt
*
* Note that this currently assumes one interrupt per pinctrl
* register that is typically used for wake - up events .
*/
static inline void pcs_irq_set ( struct pcs_soc_data * pcs_soc ,
int irq , const bool enable )
{
struct pcs_device * pcs ;
struct list_head * pos ;
unsigned mask ;
pcs = container_of ( pcs_soc , struct pcs_device , socdata ) ;
list_for_each ( pos , & pcs - > irqs ) {
struct pcs_interrupt * pcswi ;
unsigned soc_mask ;
pcswi = list_entry ( pos , struct pcs_interrupt , node ) ;
if ( irq ! = pcswi - > irq )
continue ;
soc_mask = pcs_soc - > irq_enable_mask ;
raw_spin_lock ( & pcs - > lock ) ;
mask = pcs - > read ( pcswi - > reg ) ;
if ( enable )
mask | = soc_mask ;
else
mask & = ~ soc_mask ;
pcs - > write ( mask , pcswi - > reg ) ;
2016-06-01 00:17:06 +03:00
/* flush posted write */
mask = pcs - > read ( pcswi - > reg ) ;
2013-10-03 08:39:40 +04:00
raw_spin_unlock ( & pcs - > lock ) ;
}
2013-10-11 20:13:16 +04:00
if ( pcs_soc - > rearm )
pcs_soc - > rearm ( ) ;
2013-10-03 08:39:40 +04:00
}
/**
* pcs_irq_mask ( ) - mask pinctrl interrupt
* @ d : interrupt data
*/
static void pcs_irq_mask ( struct irq_data * d )
{
struct pcs_soc_data * pcs_soc = irq_data_get_irq_chip_data ( d ) ;
pcs_irq_set ( pcs_soc , d - > irq , false ) ;
}
/**
* pcs_irq_unmask ( ) - unmask pinctrl interrupt
* @ d : interrupt data
*/
static void pcs_irq_unmask ( struct irq_data * d )
{
struct pcs_soc_data * pcs_soc = irq_data_get_irq_chip_data ( d ) ;
pcs_irq_set ( pcs_soc , d - > irq , true ) ;
}
/**
* pcs_irq_set_wake ( ) - toggle the suspend and resume wake up
* @ d : interrupt data
* @ state : wake - up state
*
* Note that this should be called only for suspend and resume .
* For runtime PM , the wake - up events should be enabled by default .
*/
static int pcs_irq_set_wake ( struct irq_data * d , unsigned int state )
{
if ( state )
pcs_irq_unmask ( d ) ;
else
pcs_irq_mask ( d ) ;
return 0 ;
}
/**
* pcs_irq_handle ( ) - common interrupt handler
* @ pcs_irq : interrupt data
*
* Note that this currently assumes we have one interrupt bit per
* mux register . This interrupt is typically used for wake - up events .
* For more complex interrupts different handlers can be specified .
*/
static int pcs_irq_handle ( struct pcs_soc_data * pcs_soc )
{
struct pcs_device * pcs ;
struct list_head * pos ;
int count = 0 ;
pcs = container_of ( pcs_soc , struct pcs_device , socdata ) ;
list_for_each ( pos , & pcs - > irqs ) {
struct pcs_interrupt * pcswi ;
unsigned mask ;
pcswi = list_entry ( pos , struct pcs_interrupt , node ) ;
raw_spin_lock ( & pcs - > lock ) ;
mask = pcs - > read ( pcswi - > reg ) ;
raw_spin_unlock ( & pcs - > lock ) ;
if ( mask & pcs_soc - > irq_status_mask ) {
generic_handle_irq ( irq_find_mapping ( pcs - > domain ,
pcswi - > hwirq ) ) ;
count + + ;
}
}
return count ;
}
/**
* pcs_irq_handler ( ) - handler for the shared interrupt case
* @ irq : interrupt
* @ d : data
*
* Use this for cases where multiple instances of
* pinctrl - single share a single interrupt like on omaps .
*/
static irqreturn_t pcs_irq_handler ( int irq , void * d )
{
struct pcs_soc_data * pcs_soc = d ;
return pcs_irq_handle ( pcs_soc ) ? IRQ_HANDLED : IRQ_NONE ;
}
/**
* pcs_irq_handle ( ) - handler for the dedicated chained interrupt case
* @ irq : interrupt
* @ desc : interrupt descriptor
*
* Use this if you have a separate interrupt for each
* pinctrl - single instance .
*/
2015-09-14 11:42:37 +03:00
static void pcs_irq_chain_handler ( struct irq_desc * desc )
2013-10-03 08:39:40 +04:00
{
struct pcs_soc_data * pcs_soc = irq_desc_get_handler_data ( desc ) ;
struct irq_chip * chip ;
2015-06-04 07:13:16 +03:00
chip = irq_desc_get_chip ( desc ) ;
2013-10-03 08:39:40 +04:00
chained_irq_enter ( chip , desc ) ;
2014-06-26 17:43:01 +04:00
pcs_irq_handle ( pcs_soc ) ;
2013-10-03 08:39:40 +04:00
/* REVISIT: export and add handle_bad_irq(irq, desc)? */
chained_irq_exit ( chip , desc ) ;
return ;
}
static int pcs_irqdomain_map ( struct irq_domain * d , unsigned int irq ,
irq_hw_number_t hwirq )
{
struct pcs_soc_data * pcs_soc = d - > host_data ;
struct pcs_device * pcs ;
struct pcs_interrupt * pcswi ;
pcs = container_of ( pcs_soc , struct pcs_device , socdata ) ;
pcswi = devm_kzalloc ( pcs - > dev , sizeof ( * pcswi ) , GFP_KERNEL ) ;
if ( ! pcswi )
return - ENOMEM ;
pcswi - > reg = pcs - > base + hwirq ;
pcswi - > hwirq = hwirq ;
pcswi - > irq = irq ;
mutex_lock ( & pcs - > mutex ) ;
list_add_tail ( & pcswi - > node , & pcs - > irqs ) ;
mutex_unlock ( & pcs - > mutex ) ;
irq_set_chip_data ( irq , pcs_soc ) ;
irq_set_chip_and_handler ( irq , & pcs - > chip ,
handle_level_irq ) ;
2016-02-01 21:28:17 +03:00
irq_set_lockdep_class ( irq , & pcs_lock_class ) ;
2013-10-19 03:20:05 +04:00
irq_set_noprobe ( irq ) ;
2013-10-03 08:39:40 +04:00
return 0 ;
}
2015-04-27 15:54:06 +03:00
static const struct irq_domain_ops pcs_irqdomain_ops = {
2013-10-03 08:39:40 +04:00
. map = pcs_irqdomain_map ,
. xlate = irq_domain_xlate_onecell ,
} ;
/**
* pcs_irq_init_chained_handler ( ) - set up a chained interrupt handler
* @ pcs : pcs driver instance
* @ np : device node pointer
*/
static int pcs_irq_init_chained_handler ( struct pcs_device * pcs ,
struct device_node * np )
{
struct pcs_soc_data * pcs_soc = & pcs - > socdata ;
const char * name = " pinctrl " ;
int num_irqs ;
if ( ! pcs_soc - > irq_enable_mask | |
! pcs_soc - > irq_status_mask ) {
pcs_soc - > irq = - 1 ;
return - EINVAL ;
}
INIT_LIST_HEAD ( & pcs - > irqs ) ;
pcs - > chip . name = name ;
pcs - > chip . irq_ack = pcs_irq_mask ;
pcs - > chip . irq_mask = pcs_irq_mask ;
pcs - > chip . irq_unmask = pcs_irq_unmask ;
pcs - > chip . irq_set_wake = pcs_irq_set_wake ;
if ( PCS_QUIRK_HAS_SHARED_IRQ ) {
int res ;
res = request_irq ( pcs_soc - > irq , pcs_irq_handler ,
2015-07-06 18:13:37 +03:00
IRQF_SHARED | IRQF_NO_SUSPEND |
IRQF_NO_THREAD ,
2013-10-03 08:39:40 +04:00
name , pcs_soc ) ;
if ( res ) {
pcs_soc - > irq = - 1 ;
return res ;
}
} else {
2015-06-21 22:11:06 +03:00
irq_set_chained_handler_and_data ( pcs_soc - > irq ,
pcs_irq_chain_handler ,
pcs_soc ) ;
2013-10-03 08:39:40 +04:00
}
/*
* We can use the register offset as the hardirq
* number as irq_domain_add_simple maps them lazily .
* This way we can easily support more than one
* interrupt per function if needed .
*/
num_irqs = pcs - > size ;
pcs - > domain = irq_domain_add_simple ( np , num_irqs , 0 ,
& pcs_irqdomain_ops ,
pcs_soc ) ;
if ( ! pcs - > domain ) {
irq_set_chained_handler ( pcs_soc - > irq , NULL ) ;
return - EINVAL ;
}
return 0 ;
}
2013-02-17 15:42:52 +04:00
2013-07-15 12:14:26 +04:00
# ifdef CONFIG_PM
2013-05-31 14:13:01 +04:00
static int pinctrl_single_suspend ( struct platform_device * pdev ,
pm_message_t state )
{
struct pcs_device * pcs ;
pcs = platform_get_drvdata ( pdev ) ;
if ( ! pcs )
return - EINVAL ;
return pinctrl_force_sleep ( pcs - > pctl ) ;
}
static int pinctrl_single_resume ( struct platform_device * pdev )
{
struct pcs_device * pcs ;
pcs = platform_get_drvdata ( pdev ) ;
if ( ! pcs )
return - EINVAL ;
return pinctrl_force_default ( pcs - > pctl ) ;
}
2013-07-15 12:14:26 +04:00
# endif
2013-05-31 14:13:01 +04:00
2016-11-03 19:35:48 +03:00
/**
* pcs_quirk_missing_pinctrl_cells - handle legacy binding
* @ pcs : pinctrl driver instance
* @ np : device tree node
* @ cells : number of cells
*
* Handle legacy binding with no # pinctrl - cells . This should be
* always two pinctrl - single , bit - per - mux and one for others .
* At some point we may want to consider removing this .
*/
static int pcs_quirk_missing_pinctrl_cells ( struct pcs_device * pcs ,
struct device_node * np ,
int cells )
{
struct property * p ;
const char * name = " #pinctrl-cells " ;
int error ;
u32 val ;
error = of_property_read_u32 ( np , name , & val ) ;
if ( ! error )
return 0 ;
dev_warn ( pcs - > dev , " please update dts to use %s = <%i> \n " ,
name , cells ) ;
p = devm_kzalloc ( pcs - > dev , sizeof ( * p ) , GFP_KERNEL ) ;
if ( ! p )
return - ENOMEM ;
p - > length = sizeof ( __be32 ) ;
p - > value = devm_kzalloc ( pcs - > dev , sizeof ( __be32 ) , GFP_KERNEL ) ;
if ( ! p - > value )
return - ENOMEM ;
* ( __be32 * ) p - > value = cpu_to_be32 ( cells ) ;
p - > name = devm_kstrdup ( pcs - > dev , name , GFP_KERNEL ) ;
if ( ! p - > name )
return - ENOMEM ;
pcs - > missing_nr_pinctrl_cells = p ;
# if IS_BUILTIN(CONFIG_PINCTRL_SINGLE)
error = of_add_property ( np , pcs - > missing_nr_pinctrl_cells ) ;
# endif
return error ;
}
2012-12-22 01:10:23 +04:00
static int pcs_probe ( struct platform_device * pdev )
2012-07-10 13:05:46 +04:00
{
struct device_node * np = pdev - > dev . of_node ;
const struct of_device_id * match ;
2013-10-03 08:39:40 +04:00
struct pcs_pdata * pdata ;
2012-07-10 13:05:46 +04:00
struct resource * res ;
struct pcs_device * pcs ;
2013-10-03 08:39:39 +04:00
const struct pcs_soc_data * soc ;
2012-07-10 13:05:46 +04:00
int ret ;
match = of_match_device ( pcs_of_match , & pdev - > dev ) ;
if ( ! match )
return - EINVAL ;
pcs = devm_kzalloc ( & pdev - > dev , sizeof ( * pcs ) , GFP_KERNEL ) ;
if ( ! pcs ) {
dev_err ( & pdev - > dev , " could not allocate \n " ) ;
return - ENOMEM ;
}
pcs - > dev = & pdev - > dev ;
2016-11-03 19:35:48 +03:00
pcs - > np = np ;
2013-10-03 08:39:40 +04:00
raw_spin_lock_init ( & pcs - > lock ) ;
2012-07-10 13:05:46 +04:00
mutex_init ( & pcs - > mutex ) ;
2013-02-17 15:42:52 +04:00
INIT_LIST_HEAD ( & pcs - > gpiofuncs ) ;
2013-10-03 08:39:39 +04:00
soc = match - > data ;
pcs - > flags = soc - > flags ;
2013-10-03 08:39:40 +04:00
memcpy ( & pcs - > socdata , soc , sizeof ( * soc ) ) ;
2012-07-10 13:05:46 +04:00
2016-10-25 19:09:00 +03:00
ret = of_property_read_u32 ( np , " pinctrl-single,register-width " ,
& pcs - > width ) ;
if ( ret ) {
dev_err ( pcs - > dev , " register width not specified \n " ) ;
return ret ;
}
2012-07-10 13:05:46 +04:00
2013-02-17 15:42:54 +04:00
ret = of_property_read_u32 ( np , " pinctrl-single,function-mask " ,
& pcs - > fmask ) ;
if ( ! ret ) {
2016-04-14 07:59:16 +03:00
pcs - > fshift = __ffs ( pcs - > fmask ) ;
2013-02-17 15:42:54 +04:00
pcs - > fmax = pcs - > fmask > > pcs - > fshift ;
} else {
/* If mask property doesn't exist, function mux is invalid. */
pcs - > fmask = 0 ;
pcs - > fshift = 0 ;
pcs - > fmax = 0 ;
}
2012-07-10 13:05:46 +04:00
ret = of_property_read_u32 ( np , " pinctrl-single,function-off " ,
& pcs - > foff ) ;
if ( ret )
pcs - > foff = PCS_OFF_DISABLED ;
2012-09-11 12:54:24 +04:00
pcs - > bits_per_mux = of_property_read_bool ( np ,
" pinctrl-single,bit-per-mux " ) ;
2016-11-03 19:35:48 +03:00
ret = pcs_quirk_missing_pinctrl_cells ( pcs , np ,
pcs - > bits_per_mux ? 2 : 1 ) ;
if ( ret ) {
dev_err ( & pdev - > dev , " unable to patch #pinctrl-cells \n " ) ;
return ret ;
}
2012-09-11 12:54:24 +04:00
2012-07-10 13:05:46 +04:00
res = platform_get_resource ( pdev , IORESOURCE_MEM , 0 ) ;
if ( ! res ) {
dev_err ( pcs - > dev , " could not get resource \n " ) ;
return - ENODEV ;
}
pcs - > res = devm_request_mem_region ( pcs - > dev , res - > start ,
resource_size ( res ) , DRIVER_NAME ) ;
if ( ! pcs - > res ) {
dev_err ( pcs - > dev , " could not get mem_region \n " ) ;
return - EBUSY ;
}
pcs - > size = resource_size ( pcs - > res ) ;
pcs - > base = devm_ioremap ( pcs - > dev , pcs - > res - > start , pcs - > size ) ;
if ( ! pcs - > base ) {
dev_err ( pcs - > dev , " could not ioremap \n " ) ;
return - ENODEV ;
}
platform_set_drvdata ( pdev , pcs ) ;
switch ( pcs - > width ) {
case 8 :
pcs - > read = pcs_readb ;
pcs - > write = pcs_writeb ;
break ;
case 16 :
pcs - > read = pcs_readw ;
pcs - > write = pcs_writew ;
break ;
case 32 :
pcs - > read = pcs_readl ;
pcs - > write = pcs_writel ;
break ;
default :
break ;
}
pcs - > desc . name = DRIVER_NAME ;
pcs - > desc . pctlops = & pcs_pinctrl_ops ;
pcs - > desc . pmxops = & pcs_pinmux_ops ;
2013-10-03 08:39:39 +04:00
if ( PCS_HAS_PINCONF )
2013-03-04 09:47:39 +04:00
pcs - > desc . confops = & pcs_pinconf_ops ;
2012-07-10 13:05:46 +04:00
pcs - > desc . owner = THIS_MODULE ;
ret = pcs_allocate_pin_table ( pcs ) ;
if ( ret < 0 )
goto free ;
pcs - > pctl = pinctrl_register ( & pcs - > desc , pcs - > dev , pcs ) ;
2015-06-09 07:01:16 +03:00
if ( IS_ERR ( pcs - > pctl ) ) {
2012-07-10 13:05:46 +04:00
dev_err ( pcs - > dev , " could not register single pinctrl driver \n " ) ;
2015-06-09 07:01:16 +03:00
ret = PTR_ERR ( pcs - > pctl ) ;
2012-07-10 13:05:46 +04:00
goto free ;
}
2013-02-17 15:42:52 +04:00
ret = pcs_add_gpio_func ( np , pcs ) ;
if ( ret < 0 )
goto free ;
2013-10-03 08:39:40 +04:00
pcs - > socdata . irq = irq_of_parse_and_map ( np , 0 ) ;
if ( pcs - > socdata . irq )
pcs - > flags | = PCS_FEAT_IRQ ;
2013-10-03 08:39:40 +04:00
/* We still need auxdata for some omaps for PRM interrupts */
pdata = dev_get_platdata ( & pdev - > dev ) ;
if ( pdata ) {
if ( pdata - > rearm )
pcs - > socdata . rearm = pdata - > rearm ;
if ( pdata - > irq ) {
pcs - > socdata . irq = pdata - > irq ;
pcs - > flags | = PCS_FEAT_IRQ ;
}
}
2013-10-03 08:39:40 +04:00
if ( PCS_HAS_IRQ ) {
ret = pcs_irq_init_chained_handler ( pcs , np ) ;
if ( ret < 0 )
dev_warn ( pcs - > dev , " initialized with no interrupts \n " ) ;
}
2012-07-10 13:05:46 +04:00
dev_info ( pcs - > dev , " %i pins at pa %p size %u \n " ,
pcs - > desc . npins , pcs - > base , pcs - > size ) ;
return 0 ;
free :
pcs_free_resources ( pcs ) ;
return ret ;
}
2012-11-19 22:26:06 +04:00
static int pcs_remove ( struct platform_device * pdev )
2012-07-10 13:05:46 +04:00
{
struct pcs_device * pcs = platform_get_drvdata ( pdev ) ;
if ( ! pcs )
return 0 ;
pcs_free_resources ( pcs ) ;
return 0 ;
}
2013-10-03 08:39:40 +04:00
static const struct pcs_soc_data pinctrl_single_omap_wkup = {
. flags = PCS_QUIRK_SHARED_IRQ ,
. irq_enable_mask = ( 1 < < 14 ) , /* OMAP_WAKEUP_EN */
. irq_status_mask = ( 1 < < 15 ) , /* OMAP_WAKEUP_EVENT */
} ;
2014-08-22 18:01:01 +04:00
static const struct pcs_soc_data pinctrl_single_dra7 = {
. irq_enable_mask = ( 1 < < 24 ) , /* WAKEUPENABLE */
. irq_status_mask = ( 1 < < 25 ) , /* WAKEUPEVENT */
} ;
2014-08-22 18:01:02 +04:00
static const struct pcs_soc_data pinctrl_single_am437x = {
. flags = PCS_QUIRK_SHARED_IRQ ,
. irq_enable_mask = ( 1 < < 29 ) , /* OMAP_WAKEUP_EN */
. irq_status_mask = ( 1 < < 30 ) , /* OMAP_WAKEUP_EVENT */
} ;
2013-10-03 08:39:39 +04:00
static const struct pcs_soc_data pinctrl_single = {
} ;
static const struct pcs_soc_data pinconf_single = {
. flags = PCS_FEAT_PINCONF ,
} ;
2015-03-16 22:59:09 +03:00
static const struct of_device_id pcs_of_match [ ] = {
2013-10-03 08:39:40 +04:00
{ . compatible = " ti,omap3-padconf " , . data = & pinctrl_single_omap_wkup } ,
{ . compatible = " ti,omap4-padconf " , . data = & pinctrl_single_omap_wkup } ,
{ . compatible = " ti,omap5-padconf " , . data = & pinctrl_single_omap_wkup } ,
2014-08-22 18:01:01 +04:00
{ . compatible = " ti,dra7-padconf " , . data = & pinctrl_single_dra7 } ,
2014-08-22 18:01:02 +04:00
{ . compatible = " ti,am437-padconf " , . data = & pinctrl_single_am437x } ,
2013-10-03 08:39:39 +04:00
{ . compatible = " pinctrl-single " , . data = & pinctrl_single } ,
{ . compatible = " pinconf-single " , . data = & pinconf_single } ,
2012-07-10 13:05:46 +04:00
{ } ,
} ;
MODULE_DEVICE_TABLE ( of , pcs_of_match ) ;
static struct platform_driver pcs_driver = {
. probe = pcs_probe ,
2012-11-19 22:21:27 +04:00
. remove = pcs_remove ,
2012-07-10 13:05:46 +04:00
. driver = {
. name = DRIVER_NAME ,
. of_match_table = pcs_of_match ,
} ,
2013-05-31 14:13:01 +04:00
# ifdef CONFIG_PM
. suspend = pinctrl_single_suspend ,
. resume = pinctrl_single_resume ,
# endif
2012-07-10 13:05:46 +04:00
} ;
module_platform_driver ( pcs_driver ) ;
MODULE_AUTHOR ( " Tony Lindgren <tony@atomide.com> " ) ;
MODULE_DESCRIPTION ( " One-register-per-pin type device tree based pinctrl driver " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;