2013-01-08 10:41:02 +01:00
/*
* Copyright ( C ) ST - Ericsson SA 2013
*
* Author : Patrice Chotard < patrice . chotard @ st . com >
* License terms : GNU General Public License ( GPL ) version 2
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*/
# include <linux/kernel.h>
# include <linux/types.h>
# include <linux/slab.h>
# include <linux/init.h>
# include <linux/module.h>
# include <linux/err.h>
2013-01-31 11:07:40 +00:00
# include <linux/of.h>
# include <linux/of_device.h>
2013-01-08 10:41:02 +01:00
# include <linux/platform_device.h>
# include <linux/gpio.h>
# include <linux/irq.h>
2013-01-31 10:43:00 +00:00
# include <linux/irqdomain.h>
2013-01-08 10:41:02 +01:00
# include <linux/interrupt.h>
# include <linux/bitops.h>
# include <linux/mfd/abx500.h>
# include <linux/mfd/abx500/ab8500.h>
# include <linux/mfd/abx500/ab8500-gpio.h>
# include <linux/pinctrl/pinctrl.h>
# include <linux/pinctrl/consumer.h>
# include <linux/pinctrl/pinmux.h>
# include <linux/pinctrl/pinconf.h>
# include <linux/pinctrl/pinconf-generic.h>
# include "pinctrl-abx500.h"
/*
* The AB9540 and AB8540 GPIO support are extended versions
* of the AB8500 GPIO support .
* The AB9540 supports an additional ( 7 th ) register so that
* more GPIO may be configured and used .
* The AB8540 supports 4 new gpios ( GPIOx_VBAT ) that have
* internal pull - up and pull - down capabilities .
*/
/*
* GPIO registers offset
* Bank : 0x10
*/
# define AB8500_GPIO_SEL1_REG 0x00
# define AB8500_GPIO_SEL2_REG 0x01
# define AB8500_GPIO_SEL3_REG 0x02
# define AB8500_GPIO_SEL4_REG 0x03
# define AB8500_GPIO_SEL5_REG 0x04
# define AB8500_GPIO_SEL6_REG 0x05
# define AB9540_GPIO_SEL7_REG 0x06
# define AB8500_GPIO_DIR1_REG 0x10
# define AB8500_GPIO_DIR2_REG 0x11
# define AB8500_GPIO_DIR3_REG 0x12
# define AB8500_GPIO_DIR4_REG 0x13
# define AB8500_GPIO_DIR5_REG 0x14
# define AB8500_GPIO_DIR6_REG 0x15
# define AB9540_GPIO_DIR7_REG 0x16
# define AB8500_GPIO_OUT1_REG 0x20
# define AB8500_GPIO_OUT2_REG 0x21
# define AB8500_GPIO_OUT3_REG 0x22
# define AB8500_GPIO_OUT4_REG 0x23
# define AB8500_GPIO_OUT5_REG 0x24
# define AB8500_GPIO_OUT6_REG 0x25
# define AB9540_GPIO_OUT7_REG 0x26
# define AB8500_GPIO_PUD1_REG 0x30
# define AB8500_GPIO_PUD2_REG 0x31
# define AB8500_GPIO_PUD3_REG 0x32
# define AB8500_GPIO_PUD4_REG 0x33
# define AB8500_GPIO_PUD5_REG 0x34
# define AB8500_GPIO_PUD6_REG 0x35
# define AB9540_GPIO_PUD7_REG 0x36
# define AB8500_GPIO_IN1_REG 0x40
# define AB8500_GPIO_IN2_REG 0x41
# define AB8500_GPIO_IN3_REG 0x42
# define AB8500_GPIO_IN4_REG 0x43
# define AB8500_GPIO_IN5_REG 0x44
# define AB8500_GPIO_IN6_REG 0x45
# define AB9540_GPIO_IN7_REG 0x46
# define AB8540_GPIO_VINSEL_REG 0x47
# define AB8540_GPIO_PULL_UPDOWN_REG 0x48
# define AB8500_GPIO_ALTFUN_REG 0x50
# define AB8540_GPIO_PULL_UPDOWN_MASK 0x03
# define AB8540_GPIO_VINSEL_MASK 0x03
# define AB8540_GPIOX_VBAT_START 51
# define AB8540_GPIOX_VBAT_END 54
struct abx500_pinctrl {
struct device * dev ;
struct pinctrl_dev * pctldev ;
struct abx500_pinctrl_soc_data * soc ;
struct gpio_chip chip ;
struct ab8500 * parent ;
struct mutex lock ;
u32 irq_base ;
struct abx500_gpio_irq_cluster * irq_cluster ;
int irq_cluster_size ;
} ;
/**
* to_abx500_pinctrl ( ) - get the pointer to abx500_pinctrl
* @ chip : Member of the structure abx500_pinctrl
*/
static inline struct abx500_pinctrl * to_abx500_pinctrl ( struct gpio_chip * chip )
{
return container_of ( chip , struct abx500_pinctrl , chip ) ;
}
static int abx500_gpio_get_bit ( struct gpio_chip * chip , u8 reg ,
2013-01-23 13:24:08 +00:00
unsigned offset , bool * bit )
2013-01-08 10:41:02 +01:00
{
struct abx500_pinctrl * pct = to_abx500_pinctrl ( chip ) ;
u8 pos = offset % 8 ;
u8 val ;
int ret ;
reg + = offset / 8 ;
ret = abx500_get_register_interruptible ( pct - > dev ,
AB8500_MISC , reg , & val ) ;
* bit = ! ! ( val & BIT ( pos ) ) ;
if ( ret < 0 )
dev_err ( pct - > dev ,
" %s read reg =%x, offset=%x failed \n " ,
__func__ , reg , offset ) ;
return ret ;
}
static int abx500_gpio_set_bits ( struct gpio_chip * chip , u8 reg ,
2013-01-23 13:24:08 +00:00
unsigned offset , int val )
2013-01-08 10:41:02 +01:00
{
struct abx500_pinctrl * pct = to_abx500_pinctrl ( chip ) ;
u8 pos = offset % 8 ;
int ret ;
reg + = offset / 8 ;
ret = abx500_mask_and_set_register_interruptible ( pct - > dev ,
2013-01-23 13:26:02 +00:00
AB8500_MISC , reg , BIT ( pos ) , val < < pos ) ;
2013-01-08 10:41:02 +01:00
if ( ret < 0 )
dev_err ( pct - > dev , " %s write failed \n " , __func__ ) ;
2013-01-23 13:24:08 +00:00
2013-01-08 10:41:02 +01:00
return ret ;
}
2013-01-23 13:24:08 +00:00
2013-01-08 10:41:02 +01:00
/**
* abx500_gpio_get ( ) - Get the particular GPIO value
2013-01-23 13:24:08 +00:00
* @ chip : Gpio device
* @ offset : GPIO number to read
2013-01-08 10:41:02 +01:00
*/
static int abx500_gpio_get ( struct gpio_chip * chip , unsigned offset )
{
struct abx500_pinctrl * pct = to_abx500_pinctrl ( chip ) ;
bool bit ;
int ret ;
ret = abx500_gpio_get_bit ( chip , AB8500_GPIO_IN1_REG ,
offset , & bit ) ;
if ( ret < 0 ) {
dev_err ( pct - > dev , " %s failed \n " , __func__ ) ;
return ret ;
}
2013-01-23 13:24:08 +00:00
2013-01-08 10:41:02 +01:00
return bit ;
}
static void abx500_gpio_set ( struct gpio_chip * chip , unsigned offset , int val )
{
struct abx500_pinctrl * pct = to_abx500_pinctrl ( chip ) ;
int ret ;
ret = abx500_gpio_set_bits ( chip , AB8500_GPIO_OUT1_REG , offset , val ) ;
if ( ret < 0 )
dev_err ( pct - > dev , " %s write failed \n " , __func__ ) ;
}
static int abx500_config_pull_updown ( struct abx500_pinctrl * pct ,
2013-01-23 13:24:08 +00:00
int offset , enum abx500_gpio_pull_updown val )
2013-01-08 10:41:02 +01:00
{
u8 pos ;
int ret ;
struct pullud * pullud ;
if ( ! pct - > soc - > pullud ) {
dev_err ( pct - > dev , " %s AB chip doesn't support pull up/down feature " ,
__func__ ) ;
ret = - EPERM ;
goto out ;
}
pullud = pct - > soc - > pullud ;
if ( ( offset < pullud - > first_pin )
| | ( offset > pullud - > last_pin ) ) {
ret = - EINVAL ;
goto out ;
}
pos = offset < < 1 ;
ret = abx500_mask_and_set_register_interruptible ( pct - > dev ,
AB8500_MISC , AB8540_GPIO_PULL_UPDOWN_REG ,
AB8540_GPIO_PULL_UPDOWN_MASK < < pos , val < < pos ) ;
out :
if ( ret < 0 )
dev_err ( pct - > dev , " %s failed (%d) \n " , __func__ , ret ) ;
2013-01-23 13:24:08 +00:00
2013-01-08 10:41:02 +01:00
return ret ;
}
static int abx500_gpio_direction_output ( struct gpio_chip * chip ,
unsigned offset ,
int val )
{
struct abx500_pinctrl * pct = to_abx500_pinctrl ( chip ) ;
struct pullud * pullud = pct - > soc - > pullud ;
unsigned gpio ;
int ret ;
2013-01-23 13:24:08 +00:00
2013-01-08 10:41:02 +01:00
/* set direction as output */
ret = abx500_gpio_set_bits ( chip , AB8500_GPIO_DIR1_REG , offset , 1 ) ;
if ( ret < 0 )
return ret ;
/* disable pull down */
ret = abx500_gpio_set_bits ( chip , AB8500_GPIO_PUD1_REG , offset , 1 ) ;
if ( ret < 0 )
return ret ;
/* if supported, disable both pull down and pull up */
gpio = offset + 1 ;
if ( pullud & & gpio > = pullud - > first_pin & & gpio < = pullud - > last_pin ) {
ret = abx500_config_pull_updown ( pct ,
gpio ,
ABX500_GPIO_PULL_NONE ) ;
if ( ret < 0 )
return ret ;
}
2013-01-23 13:24:08 +00:00
2013-01-08 10:41:02 +01:00
/* set the output as 1 or 0 */
return abx500_gpio_set_bits ( chip , AB8500_GPIO_OUT1_REG , offset , val ) ;
}
static int abx500_gpio_direction_input ( struct gpio_chip * chip , unsigned offset )
{
/* set the register as input */
return abx500_gpio_set_bits ( chip , AB8500_GPIO_DIR1_REG , offset , 0 ) ;
}
static int abx500_gpio_to_irq ( struct gpio_chip * chip , unsigned offset )
{
struct abx500_pinctrl * pct = to_abx500_pinctrl ( chip ) ;
2013-01-31 09:45:17 +00:00
/* The AB8500 GPIO numbers are off by one */
int gpio = offset + 1 ;
2013-01-08 10:41:02 +01:00
int base = pct - > irq_base ;
int i ;
for ( i = 0 ; i < pct - > irq_cluster_size ; i + + ) {
struct abx500_gpio_irq_cluster * cluster =
& pct - > irq_cluster [ i ] ;
2013-01-31 09:45:17 +00:00
if ( gpio > = cluster - > start & & gpio < = cluster - > end )
return base + gpio - cluster - > start ;
2013-01-08 10:41:02 +01:00
/* Advance by the number of gpios in this cluster */
base + = cluster - > end + cluster - > offset - cluster - > start + 1 ;
}
return - EINVAL ;
}
static int abx500_set_mode ( struct pinctrl_dev * pctldev , struct gpio_chip * chip ,
2013-01-23 13:24:08 +00:00
unsigned gpio , int alt_setting )
2013-01-08 10:41:02 +01:00
{
struct abx500_pinctrl * pct = pinctrl_dev_get_drvdata ( pctldev ) ;
struct alternate_functions af = pct - > soc - > alternate_functions [ gpio ] ;
int ret ;
int val ;
unsigned offset ;
2013-01-23 13:24:08 +00:00
2013-01-08 10:41:02 +01:00
const char * modes [ ] = {
[ ABX500_DEFAULT ] = " default " ,
[ ABX500_ALT_A ] = " altA " ,
[ ABX500_ALT_B ] = " altB " ,
[ ABX500_ALT_C ] = " altC " ,
} ;
/* sanity check */
if ( ( ( alt_setting = = ABX500_ALT_A ) & & ( af . gpiosel_bit = = UNUSED ) ) | |
( ( alt_setting = = ABX500_ALT_B ) & & ( af . alt_bit1 = = UNUSED ) ) | |
( ( alt_setting = = ABX500_ALT_C ) & & ( af . alt_bit2 = = UNUSED ) ) ) {
dev_dbg ( pct - > dev , " pin %d doesn't support %s mode \n " , gpio ,
modes [ alt_setting ] ) ;
return - EINVAL ;
}
/* on ABx5xx, there is no GPIO0, so adjust the offset */
offset = gpio - 1 ;
2013-01-23 13:24:08 +00:00
2013-01-08 10:41:02 +01:00
switch ( alt_setting ) {
case ABX500_DEFAULT :
/*
* for ABx5xx family , default mode is always selected by
* writing 0 to GPIOSELx register , except for pins which
* support at least ALT_B mode , default mode is selected
* by writing 1 to GPIOSELx register
*/
val = 0 ;
if ( af . alt_bit1 ! = UNUSED )
val + + ;
ret = abx500_gpio_set_bits ( chip , AB8500_GPIO_SEL1_REG ,
offset , val ) ;
break ;
2013-01-23 13:24:08 +00:00
2013-01-08 10:41:02 +01:00
case ABX500_ALT_A :
/*
* for ABx5xx family , alt_a mode is always selected by
* writing 1 to GPIOSELx register , except for pins which
* support at least ALT_B mode , alt_a mode is selected
* by writing 0 to GPIOSELx register and 0 in ALTFUNC
* register
*/
if ( af . alt_bit1 ! = UNUSED ) {
ret = abx500_gpio_set_bits ( chip , AB8500_GPIO_SEL1_REG ,
offset , 0 ) ;
ret = abx500_gpio_set_bits ( chip ,
AB8500_GPIO_ALTFUN_REG ,
af . alt_bit1 ,
! ! ( af . alta_val & & BIT ( 0 ) ) ) ;
if ( af . alt_bit2 ! = UNUSED )
ret = abx500_gpio_set_bits ( chip ,
AB8500_GPIO_ALTFUN_REG ,
af . alt_bit2 ,
! ! ( af . alta_val & & BIT ( 1 ) ) ) ;
} else
ret = abx500_gpio_set_bits ( chip , AB8500_GPIO_SEL1_REG ,
offset , 1 ) ;
break ;
2013-01-23 13:24:08 +00:00
2013-01-08 10:41:02 +01:00
case ABX500_ALT_B :
ret = abx500_gpio_set_bits ( chip , AB8500_GPIO_SEL1_REG ,
offset , 0 ) ;
ret = abx500_gpio_set_bits ( chip , AB8500_GPIO_ALTFUN_REG ,
af . alt_bit1 , ! ! ( af . altb_val & & BIT ( 0 ) ) ) ;
if ( af . alt_bit2 ! = UNUSED )
ret = abx500_gpio_set_bits ( chip ,
AB8500_GPIO_ALTFUN_REG ,
af . alt_bit2 ,
! ! ( af . altb_val & & BIT ( 1 ) ) ) ;
break ;
2013-01-23 13:24:08 +00:00
2013-01-08 10:41:02 +01:00
case ABX500_ALT_C :
ret = abx500_gpio_set_bits ( chip , AB8500_GPIO_SEL1_REG ,
offset , 0 ) ;
ret = abx500_gpio_set_bits ( chip , AB8500_GPIO_ALTFUN_REG ,
af . alt_bit2 , ! ! ( af . altc_val & & BIT ( 0 ) ) ) ;
ret = abx500_gpio_set_bits ( chip , AB8500_GPIO_ALTFUN_REG ,
af . alt_bit2 , ! ! ( af . altc_val & & BIT ( 1 ) ) ) ;
break ;
default :
dev_dbg ( pct - > dev , " unknow alt_setting %d \n " , alt_setting ) ;
2013-01-23 13:24:08 +00:00
2013-01-08 10:41:02 +01:00
return - EINVAL ;
}
2013-01-23 13:24:08 +00:00
2013-01-08 10:41:02 +01:00
return ret ;
}
static u8 abx500_get_mode ( struct pinctrl_dev * pctldev , struct gpio_chip * chip ,
2013-01-23 13:24:08 +00:00
unsigned gpio )
2013-01-08 10:41:02 +01:00
{
u8 mode ;
bool bit_mode ;
bool alt_bit1 ;
bool alt_bit2 ;
struct abx500_pinctrl * pct = pinctrl_dev_get_drvdata ( pctldev ) ;
struct alternate_functions af = pct - > soc - > alternate_functions [ gpio ] ;
2013-02-05 20:10:57 +01:00
/* on ABx5xx, there is no GPIO0, so adjust the offset */
unsigned offset = gpio - 1 ;
2013-01-08 10:41:02 +01:00
/*
* if gpiosel_bit is set to unused ,
* it means no GPIO or special case
*/
if ( af . gpiosel_bit = = UNUSED )
return ABX500_DEFAULT ;
/* read GpioSelx register */
2013-02-05 20:10:57 +01:00
abx500_gpio_get_bit ( chip , AB8500_GPIO_SEL1_REG + ( offset / 8 ) ,
2013-01-08 10:41:02 +01:00
af . gpiosel_bit , & bit_mode ) ;
mode = bit_mode ;
/* sanity check */
if ( ( af . alt_bit1 < UNUSED ) | | ( af . alt_bit1 > 7 ) | |
( af . alt_bit2 < UNUSED ) | | ( af . alt_bit2 > 7 ) ) {
dev_err ( pct - > dev ,
" alt_bitX value not in correct range (-1 to 7) \n " ) ;
return - EINVAL ;
}
2013-01-23 13:24:08 +00:00
2013-01-08 10:41:02 +01:00
/* if alt_bit2 is used, alt_bit1 must be used too */
if ( ( af . alt_bit2 ! = UNUSED ) & & ( af . alt_bit1 = = UNUSED ) ) {
dev_err ( pct - > dev ,
" if alt_bit2 is used, alt_bit1 can't be unused \n " ) ;
return - EINVAL ;
}
/* check if pin use AlternateFunction register */
if ( ( af . alt_bit1 = = UNUSED ) & & ( af . alt_bit1 = = UNUSED ) )
return mode ;
/*
* if pin GPIOSEL bit is set and pin supports alternate function ,
* it means DEFAULT mode
*/
if ( mode )
return ABX500_DEFAULT ;
2013-01-23 13:24:08 +00:00
2013-01-08 10:41:02 +01:00
/*
* pin use the AlternatFunction register
* read alt_bit1 value
*/
abx500_gpio_get_bit ( chip , AB8500_GPIO_ALTFUN_REG ,
af . alt_bit1 , & alt_bit1 ) ;
if ( af . alt_bit2 ! = UNUSED )
/* read alt_bit2 value */
abx500_gpio_get_bit ( chip , AB8500_GPIO_ALTFUN_REG , af . alt_bit2 ,
& alt_bit2 ) ;
else
alt_bit2 = 0 ;
mode = ( alt_bit2 < < 1 ) + alt_bit1 ;
if ( mode = = af . alta_val )
return ABX500_ALT_A ;
else if ( mode = = af . altb_val )
return ABX500_ALT_B ;
else
return ABX500_ALT_C ;
}
# ifdef CONFIG_DEBUG_FS
# include <linux/seq_file.h>
static void abx500_gpio_dbg_show_one ( struct seq_file * s ,
2013-01-23 13:24:08 +00:00
struct pinctrl_dev * pctldev ,
struct gpio_chip * chip ,
unsigned offset , unsigned gpio )
2013-01-08 10:41:02 +01:00
{
const char * label = gpiochip_is_requested ( chip , offset - 1 ) ;
u8 gpio_offset = offset - 1 ;
int mode = - 1 ;
bool is_out ;
bool pull ;
2013-01-23 13:24:08 +00:00
2013-01-08 10:41:02 +01:00
const char * modes [ ] = {
[ ABX500_DEFAULT ] = " default " ,
[ ABX500_ALT_A ] = " altA " ,
[ ABX500_ALT_B ] = " altB " ,
[ ABX500_ALT_C ] = " altC " ,
} ;
abx500_gpio_get_bit ( chip , AB8500_GPIO_DIR1_REG , gpio_offset , & is_out ) ;
abx500_gpio_get_bit ( chip , AB8500_GPIO_PUD1_REG , gpio_offset , & pull ) ;
if ( pctldev )
mode = abx500_get_mode ( pctldev , chip , offset ) ;
seq_printf ( s , " gpio-%-3d (%-20.20s) %-3s %-9s %s " ,
gpio , label ? : " (none) " ,
is_out ? " out " : " in " ,
is_out ?
( chip - > get
? ( chip - > get ( chip , offset ) ? " hi " : " lo " )
: " ? " )
: ( pull ? " pull up " : " pull down " ) ,
( mode < 0 ) ? " unknown " : modes [ mode ] ) ;
}
static void abx500_gpio_dbg_show ( struct seq_file * s , struct gpio_chip * chip )
{
unsigned i ;
unsigned gpio = chip - > base ;
struct abx500_pinctrl * pct = to_abx500_pinctrl ( chip ) ;
struct pinctrl_dev * pctldev = pct - > pctldev ;
for ( i = 0 ; i < chip - > ngpio ; i + + , gpio + + ) {
/* On AB8500, there is no GPIO0, the first is the GPIO 1 */
abx500_gpio_dbg_show_one ( s , pctldev , chip , i + 1 , gpio ) ;
seq_printf ( s , " \n " ) ;
}
}
# else
static inline void abx500_gpio_dbg_show_one ( struct seq_file * s ,
2013-01-23 13:24:08 +00:00
struct pinctrl_dev * pctldev ,
struct gpio_chip * chip ,
unsigned offset , unsigned gpio )
2013-01-08 10:41:02 +01:00
{
}
# define abx500_gpio_dbg_show NULL
# endif
int abx500_gpio_request ( struct gpio_chip * chip , unsigned offset )
{
int gpio = chip - > base + offset ;
return pinctrl_request_gpio ( gpio ) ;
}
void abx500_gpio_free ( struct gpio_chip * chip , unsigned offset )
{
int gpio = chip - > base + offset ;
pinctrl_free_gpio ( gpio ) ;
}
static struct gpio_chip abx500gpio_chip = {
. label = " abx500-gpio " ,
. owner = THIS_MODULE ,
. request = abx500_gpio_request ,
. free = abx500_gpio_free ,
. direction_input = abx500_gpio_direction_input ,
. get = abx500_gpio_get ,
. direction_output = abx500_gpio_direction_output ,
. set = abx500_gpio_set ,
. to_irq = abx500_gpio_to_irq ,
. dbg_show = abx500_gpio_dbg_show ,
} ;
static int abx500_pmx_get_funcs_cnt ( struct pinctrl_dev * pctldev )
{
struct abx500_pinctrl * pct = pinctrl_dev_get_drvdata ( pctldev ) ;
return pct - > soc - > nfunctions ;
}
static const char * abx500_pmx_get_func_name ( struct pinctrl_dev * pctldev ,
unsigned function )
{
struct abx500_pinctrl * pct = pinctrl_dev_get_drvdata ( pctldev ) ;
return pct - > soc - > functions [ function ] . name ;
}
static int abx500_pmx_get_func_groups ( struct pinctrl_dev * pctldev ,
2013-01-23 13:24:08 +00:00
unsigned function ,
const char * const * * groups ,
unsigned * const num_groups )
2013-01-08 10:41:02 +01:00
{
struct abx500_pinctrl * pct = pinctrl_dev_get_drvdata ( pctldev ) ;
* groups = pct - > soc - > functions [ function ] . groups ;
* num_groups = pct - > soc - > functions [ function ] . ngroups ;
return 0 ;
}
static int abx500_pmx_enable ( struct pinctrl_dev * pctldev , unsigned function ,
2013-01-23 13:24:08 +00:00
unsigned group )
2013-01-08 10:41:02 +01:00
{
struct abx500_pinctrl * pct = pinctrl_dev_get_drvdata ( pctldev ) ;
struct gpio_chip * chip = & pct - > chip ;
const struct abx500_pingroup * g ;
int i ;
int ret = 0 ;
g = & pct - > soc - > groups [ group ] ;
if ( g - > altsetting < 0 )
return - EINVAL ;
dev_dbg ( pct - > dev , " enable group %s, %u pins \n " , g - > name , g - > npins ) ;
for ( i = 0 ; i < g - > npins ; i + + ) {
dev_dbg ( pct - > dev , " setting pin %d to altsetting %d \n " ,
g - > pins [ i ] , g - > altsetting ) ;
ret = abx500_set_mode ( pctldev , chip , g - > pins [ i ] , g - > altsetting ) ;
}
2013-01-23 13:24:08 +00:00
2013-01-08 10:41:02 +01:00
return ret ;
}
static void abx500_pmx_disable ( struct pinctrl_dev * pctldev ,
2013-01-23 13:24:08 +00:00
unsigned function , unsigned group )
2013-01-08 10:41:02 +01:00
{
struct abx500_pinctrl * pct = pinctrl_dev_get_drvdata ( pctldev ) ;
const struct abx500_pingroup * g ;
g = & pct - > soc - > groups [ group ] ;
if ( g - > altsetting < 0 )
return ;
/* FIXME: poke out the mux, set the pin to some default state? */
dev_dbg ( pct - > dev , " disable group %s, %u pins \n " , g - > name , g - > npins ) ;
}
int abx500_gpio_request_enable ( struct pinctrl_dev * pctldev ,
2013-01-23 13:24:08 +00:00
struct pinctrl_gpio_range * range ,
unsigned offset )
2013-01-08 10:41:02 +01:00
{
struct abx500_pinctrl * pct = pinctrl_dev_get_drvdata ( pctldev ) ;
const struct abx500_pinrange * p ;
int ret ;
int i ;
/*
* Different ranges have different ways to enable GPIO function on a
* pin , so refer back to our local range type , where we handily define
* what altfunc enables GPIO for a certain pin .
*/
for ( i = 0 ; i < pct - > soc - > gpio_num_ranges ; i + + ) {
p = & pct - > soc - > gpio_ranges [ i ] ;
if ( ( offset > = p - > offset ) & &
( offset < ( p - > offset + p - > npins ) ) )
break ;
}
if ( i = = pct - > soc - > gpio_num_ranges ) {
dev_err ( pct - > dev , " %s failed to locate range \n " , __func__ ) ;
return - ENODEV ;
}
dev_dbg ( pct - > dev , " enable GPIO by altfunc %d at gpio %d \n " ,
p - > altfunc , offset ) ;
ret = abx500_set_mode ( pct - > pctldev , & pct - > chip ,
offset , p - > altfunc ) ;
if ( ret < 0 ) {
dev_err ( pct - > dev , " %s setting altfunc failed \n " , __func__ ) ;
return ret ;
}
return ret ;
}
static void abx500_gpio_disable_free ( struct pinctrl_dev * pctldev ,
2013-01-23 13:24:08 +00:00
struct pinctrl_gpio_range * range ,
unsigned offset )
2013-01-08 10:41:02 +01:00
{
}
static struct pinmux_ops abx500_pinmux_ops = {
. get_functions_count = abx500_pmx_get_funcs_cnt ,
. get_function_name = abx500_pmx_get_func_name ,
. get_function_groups = abx500_pmx_get_func_groups ,
. enable = abx500_pmx_enable ,
. disable = abx500_pmx_disable ,
. gpio_request_enable = abx500_gpio_request_enable ,
. gpio_disable_free = abx500_gpio_disable_free ,
} ;
static int abx500_get_groups_cnt ( struct pinctrl_dev * pctldev )
{
struct abx500_pinctrl * pct = pinctrl_dev_get_drvdata ( pctldev ) ;
return pct - > soc - > ngroups ;
}
static const char * abx500_get_group_name ( struct pinctrl_dev * pctldev ,
2013-01-23 13:24:08 +00:00
unsigned selector )
2013-01-08 10:41:02 +01:00
{
struct abx500_pinctrl * pct = pinctrl_dev_get_drvdata ( pctldev ) ;
return pct - > soc - > groups [ selector ] . name ;
}
static int abx500_get_group_pins ( struct pinctrl_dev * pctldev ,
2013-01-23 13:24:08 +00:00
unsigned selector ,
const unsigned * * pins ,
unsigned * num_pins )
2013-01-08 10:41:02 +01:00
{
struct abx500_pinctrl * pct = pinctrl_dev_get_drvdata ( pctldev ) ;
* pins = pct - > soc - > groups [ selector ] . pins ;
* num_pins = pct - > soc - > groups [ selector ] . npins ;
2013-01-23 13:24:08 +00:00
2013-01-08 10:41:02 +01:00
return 0 ;
}
static void abx500_pin_dbg_show ( struct pinctrl_dev * pctldev ,
2013-01-23 13:24:08 +00:00
struct seq_file * s , unsigned offset )
2013-01-08 10:41:02 +01:00
{
struct abx500_pinctrl * pct = pinctrl_dev_get_drvdata ( pctldev ) ;
struct gpio_chip * chip = & pct - > chip ;
abx500_gpio_dbg_show_one ( s , pctldev , chip , offset ,
chip - > base + offset - 1 ) ;
}
static struct pinctrl_ops abx500_pinctrl_ops = {
. get_groups_count = abx500_get_groups_cnt ,
. get_group_name = abx500_get_group_name ,
. get_group_pins = abx500_get_group_pins ,
. pin_dbg_show = abx500_pin_dbg_show ,
} ;
int abx500_pin_config_get ( struct pinctrl_dev * pctldev ,
2013-01-23 13:24:08 +00:00
unsigned pin ,
unsigned long * config )
2013-01-08 10:41:02 +01:00
{
2012-12-20 11:11:19 +00:00
return - ENOSYS ;
2013-01-08 10:41:02 +01:00
}
int abx500_pin_config_set ( struct pinctrl_dev * pctldev ,
2013-01-23 13:24:08 +00:00
unsigned pin ,
unsigned long config )
2013-01-08 10:41:02 +01:00
{
struct abx500_pinctrl * pct = pinctrl_dev_get_drvdata ( pctldev ) ;
struct pullud * pullud = pct - > soc - > pullud ;
struct gpio_chip * chip = & pct - > chip ;
unsigned offset ;
int ret ;
enum pin_config_param param = pinconf_to_config_param ( config ) ;
enum pin_config_param argument = pinconf_to_config_argument ( config ) ;
dev_dbg ( chip - > dev , " pin %d [%#lx]: %s %s \n " ,
pin , config , ( param = = PIN_CONFIG_OUTPUT ) ? " output " : " input " ,
( param = = PIN_CONFIG_OUTPUT ) ? ( argument ? " high " : " low " ) :
( argument ? " pull up " : " pull down " ) ) ;
2013-01-23 13:24:08 +00:00
2013-01-08 10:41:02 +01:00
/* on ABx500, there is no GPIO0, so adjust the offset */
offset = pin - 1 ;
switch ( param ) {
case PIN_CONFIG_BIAS_PULL_DOWN :
/*
* if argument = 1 set the pull down
* else clear the pull down
*/
ret = abx500_gpio_direction_input ( chip , offset ) ;
/*
* Some chips only support pull down , while some actually
* support both pull up and pull down . Such chips have
* a " pullud " range specified for the pins that support
* both features . If the pin is not within that range , we
* fall back to the old bit set that only support pull down .
*/
if ( pullud & &
pin > = pullud - > first_pin & &
pin < = pullud - > last_pin )
ret = abx500_config_pull_updown ( pct ,
pin ,
argument ? ABX500_GPIO_PULL_DOWN : ABX500_GPIO_PULL_NONE ) ;
else
/* Chip only supports pull down */
ret = abx500_gpio_set_bits ( chip , AB8500_GPIO_PUD1_REG ,
offset , argument ? 0 : 1 ) ;
break ;
2013-01-23 13:24:08 +00:00
2013-01-08 10:41:02 +01:00
case PIN_CONFIG_OUTPUT :
ret = abx500_gpio_direction_output ( chip , offset , argument ) ;
2013-01-23 13:24:08 +00:00
2013-01-08 10:41:02 +01:00
break ;
2013-01-23 13:24:08 +00:00
2013-01-08 10:41:02 +01:00
default :
dev_err ( chip - > dev , " illegal configuration requested \n " ) ;
2013-01-23 13:24:08 +00:00
2013-01-08 10:41:02 +01:00
return - EINVAL ;
}
2013-01-23 13:24:08 +00:00
2013-01-08 10:41:02 +01:00
return ret ;
}
static struct pinconf_ops abx500_pinconf_ops = {
. pin_config_get = abx500_pin_config_get ,
. pin_config_set = abx500_pin_config_set ,
} ;
static struct pinctrl_desc abx500_pinctrl_desc = {
. name = " pinctrl-abx500 " ,
. pctlops = & abx500_pinctrl_ops ,
. pmxops = & abx500_pinmux_ops ,
. confops = & abx500_pinconf_ops ,
. owner = THIS_MODULE ,
} ;
static int abx500_get_gpio_num ( struct abx500_pinctrl_soc_data * soc )
{
unsigned int lowest = 0 ;
unsigned int highest = 0 ;
unsigned int npins = 0 ;
int i ;
/*
* Compute number of GPIOs from the last SoC gpio range descriptors
* These ranges may include " holes " but the GPIO number space shall
* still be homogeneous , so we need to detect and account for any
* such holes so that these are included in the number of GPIO pins .
*/
for ( i = 0 ; i < soc - > gpio_num_ranges ; i + + ) {
unsigned gstart ;
unsigned gend ;
const struct abx500_pinrange * p ;
p = & soc - > gpio_ranges [ i ] ;
gstart = p - > offset ;
gend = p - > offset + p - > npins - 1 ;
if ( i = = 0 ) {
/* First iteration, set start values */
lowest = gstart ;
highest = gend ;
} else {
if ( gstart < lowest )
lowest = gstart ;
if ( gend > highest )
highest = gend ;
}
}
/* this gives the absolute number of pins */
npins = highest - lowest + 1 ;
return npins ;
}
2013-01-31 11:07:40 +00:00
static const struct of_device_id abx500_gpio_match [ ] = {
{ . compatible = " stericsson,ab8500-gpio " , . data = ( void * ) PINCTRL_AB8500 , } ,
{ . compatible = " stericsson,ab8505-gpio " , . data = ( void * ) PINCTRL_AB8505 , } ,
{ . compatible = " stericsson,ab8540-gpio " , . data = ( void * ) PINCTRL_AB8540 , } ,
{ . compatible = " stericsson,ab9540-gpio " , . data = ( void * ) PINCTRL_AB9540 , } ,
} ;
2013-01-08 10:41:02 +01:00
static int abx500_gpio_probe ( struct platform_device * pdev )
{
struct ab8500_platform_data * abx500_pdata =
dev_get_platdata ( pdev - > dev . parent ) ;
2013-01-31 11:07:40 +00:00
struct abx500_gpio_platform_data * pdata = NULL ;
struct device_node * np = pdev - > dev . of_node ;
2013-01-08 10:41:02 +01:00
struct abx500_pinctrl * pct ;
const struct platform_device_id * platid = platform_get_device_id ( pdev ) ;
2013-01-31 11:07:40 +00:00
unsigned int id = - 1 ;
2013-01-31 11:06:33 +00:00
int ret , err ;
2013-01-08 10:41:02 +01:00
int i ;
2013-01-31 11:07:40 +00:00
if ( abx500_pdata )
pdata = abx500_pdata - > gpio ;
2013-01-23 13:24:08 +00:00
if ( ! pdata ) {
2013-01-31 11:07:40 +00:00
if ( np ) {
const struct of_device_id * match ;
match = of_match_device ( abx500_gpio_match , & pdev - > dev ) ;
if ( ! match )
return - ENODEV ;
id = ( unsigned long ) match - > data ;
} else {
dev_err ( & pdev - > dev , " gpio dt and platform data missing \n " ) ;
return - ENODEV ;
}
2013-01-08 10:41:02 +01:00
}
2013-01-31 11:07:40 +00:00
if ( platid )
id = platid - > driver_data ;
2013-01-08 10:41:02 +01:00
pct = devm_kzalloc ( & pdev - > dev , sizeof ( struct abx500_pinctrl ) ,
GFP_KERNEL ) ;
if ( pct = = NULL ) {
dev_err ( & pdev - > dev ,
" failed to allocate memory for pct \n " ) ;
return - ENOMEM ;
}
pct - > dev = & pdev - > dev ;
pct - > parent = dev_get_drvdata ( pdev - > dev . parent ) ;
pct - > chip = abx500gpio_chip ;
pct - > chip . dev = & pdev - > dev ;
pct - > chip . base = pdata - > gpio_base ;
pct - > irq_base = pdata - > irq_base ;
2013-01-31 11:07:40 +00:00
pct - > chip . base = ( np ) ? - 1 : pdata - > gpio_base ;
2013-01-08 10:41:02 +01:00
/* initialize the lock */
mutex_init ( & pct - > lock ) ;
/* Poke in other ASIC variants here */
2013-01-31 11:07:40 +00:00
switch ( id ) {
2013-01-08 10:59:53 +01:00
case PINCTRL_AB8500 :
abx500_pinctrl_ab8500_init ( & pct - > soc ) ;
break ;
2013-01-28 14:35:19 +01:00
case PINCTRL_AB8540 :
abx500_pinctrl_ab8540_init ( & pct - > soc ) ;
break ;
2013-01-28 14:29:35 +01:00
case PINCTRL_AB9540 :
abx500_pinctrl_ab9540_init ( & pct - > soc ) ;
break ;
2013-01-28 14:23:45 +01:00
case PINCTRL_AB8505 :
abx500_pinctrl_ab8505_init ( & pct - > soc ) ;
break ;
2013-01-08 10:41:02 +01:00
default :
dev_err ( & pdev - > dev , " Unsupported pinctrl sub driver (%d) \n " ,
( int ) platid - > driver_data ) ;
2013-01-16 09:17:13 +00:00
mutex_destroy ( & pct - > lock ) ;
2013-01-08 10:41:02 +01:00
return - EINVAL ;
}
if ( ! pct - > soc ) {
dev_err ( & pdev - > dev , " Invalid SOC data \n " ) ;
2013-01-16 09:17:13 +00:00
mutex_destroy ( & pct - > lock ) ;
2013-01-08 10:41:02 +01:00
return - EINVAL ;
}
pct - > chip . ngpio = abx500_get_gpio_num ( pct - > soc ) ;
pct - > irq_cluster = pct - > soc - > gpio_irq_cluster ;
pct - > irq_cluster_size = pct - > soc - > ngpio_irq_cluster ;
ret = gpiochip_add ( & pct - > chip ) ;
if ( ret ) {
2013-01-23 13:24:08 +00:00
dev_err ( & pdev - > dev , " unable to add gpiochip: %d \n " , ret ) ;
2013-01-16 09:17:13 +00:00
mutex_destroy ( & pct - > lock ) ;
2013-01-31 10:43:00 +00:00
return ret ;
2013-01-08 10:41:02 +01:00
}
dev_info ( & pdev - > dev , " added gpiochip \n " ) ;
abx500_pinctrl_desc . pins = pct - > soc - > pins ;
abx500_pinctrl_desc . npins = pct - > soc - > npins ;
pct - > pctldev = pinctrl_register ( & abx500_pinctrl_desc , & pdev - > dev , pct ) ;
if ( ! pct - > pctldev ) {
dev_err ( & pdev - > dev ,
" could not register abx500 pinctrl driver \n " ) ;
2013-01-31 11:06:33 +00:00
ret = - EINVAL ;
2013-01-08 10:41:02 +01:00
goto out_rem_chip ;
}
dev_info ( & pdev - > dev , " registered pin controller \n " ) ;
/* We will handle a range of GPIO pins */
for ( i = 0 ; i < pct - > soc - > gpio_num_ranges ; i + + ) {
const struct abx500_pinrange * p = & pct - > soc - > gpio_ranges [ i ] ;
ret = gpiochip_add_pin_range ( & pct - > chip ,
dev_name ( & pdev - > dev ) ,
p - > offset - 1 , p - > offset , p - > npins ) ;
if ( ret < 0 )
2013-01-31 11:06:33 +00:00
goto out_rem_chip ;
2013-01-08 10:41:02 +01:00
}
platform_set_drvdata ( pdev , pct ) ;
dev_info ( & pdev - > dev , " initialized abx500 pinctrl driver \n " ) ;
return 0 ;
out_rem_chip :
2013-01-31 11:06:33 +00:00
err = gpiochip_remove ( & pct - > chip ) ;
if ( err )
2013-01-08 10:41:02 +01:00
dev_info ( & pdev - > dev , " failed to remove gpiochip \n " ) ;
2013-01-31 10:43:00 +00:00
2013-01-08 10:41:02 +01:00
mutex_destroy ( & pct - > lock ) ;
return ret ;
}
2013-01-23 13:24:08 +00:00
/**
2013-01-08 10:41:02 +01:00
* abx500_gpio_remove ( ) - remove Ab8500 - gpio driver
2013-01-23 13:24:08 +00:00
* @ pdev : Platform device registered
2013-01-08 10:41:02 +01:00
*/
static int abx500_gpio_remove ( struct platform_device * pdev )
{
struct abx500_pinctrl * pct = platform_get_drvdata ( pdev ) ;
int ret ;
ret = gpiochip_remove ( & pct - > chip ) ;
if ( ret < 0 ) {
dev_err ( pct - > dev , " unable to remove gpiochip: %d \n " ,
ret ) ;
return ret ;
}
mutex_destroy ( & pct - > lock ) ;
return 0 ;
}
static const struct platform_device_id abx500_pinctrl_id [ ] = {
{ " pinctrl-ab8500 " , PINCTRL_AB8500 } ,
{ " pinctrl-ab8540 " , PINCTRL_AB8540 } ,
{ " pinctrl-ab9540 " , PINCTRL_AB9540 } ,
{ " pinctrl-ab8505 " , PINCTRL_AB8505 } ,
{ } ,
} ;
static struct platform_driver abx500_gpio_driver = {
. driver = {
. name = " abx500-gpio " ,
. owner = THIS_MODULE ,
2013-01-31 11:07:40 +00:00
. of_match_table = abx500_gpio_match ,
2013-01-08 10:41:02 +01:00
} ,
. probe = abx500_gpio_probe ,
. remove = abx500_gpio_remove ,
. id_table = abx500_pinctrl_id ,
} ;
static int __init abx500_gpio_init ( void )
{
return platform_driver_register ( & abx500_gpio_driver ) ;
}
core_initcall ( abx500_gpio_init ) ;
MODULE_AUTHOR ( " Patrice Chotard <patrice.chotard@st.com> " ) ;
MODULE_DESCRIPTION ( " Driver allows to use AxB5xx unused pins to be used as GPIO " ) ;
MODULE_ALIAS ( " platform:abx500-gpio " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;