2009-04-24 00:15:04 +04:00
/*
2011-06-05 04:38:28 +04:00
* U300 GPIO module .
2009-04-24 00:15:04 +04:00
*
2012-08-13 12:36:55 +04:00
* Copyright ( C ) 2007 - 2012 ST - Ericsson AB
2009-04-24 00:15:04 +04:00
* License terms : GNU General Public License ( GPL ) version 2
* COH 901 571 / 3 - Used in DB3210 ( U365 2.0 ) and DB3350 ( U335 1.0 )
2011-09-08 12:04:51 +04:00
* Author : Linus Walleij < linus . walleij @ linaro . org >
2009-04-24 00:15:04 +04:00
* Author : Jonas Aaberg < jonas . aberg @ stericsson . com >
*/
# include <linux/module.h>
2011-09-08 12:04:51 +04:00
# include <linux/irq.h>
2009-04-24 00:15:04 +04:00
# include <linux/interrupt.h>
# include <linux/delay.h>
# include <linux/errno.h>
# include <linux/io.h>
2012-10-17 20:31:20 +04:00
# include <linux/irqdomain.h>
2009-04-24 00:15:04 +04:00
# include <linux/clk.h>
# include <linux/err.h>
# include <linux/platform_device.h>
# include <linux/gpio.h>
2011-09-08 12:04:51 +04:00
# include <linux/list.h>
# include <linux/slab.h>
2012-02-09 04:52:22 +04:00
# include <linux/pinctrl/consumer.h>
2011-11-17 00:58:10 +04:00
# include <linux/pinctrl/pinconf-generic.h>
2012-08-13 12:56:43 +04:00
# include <linux/platform_data/pinctrl-coh901.h>
2011-11-17 00:58:10 +04:00
# include "pinctrl-coh901.h"
2009-04-24 00:15:04 +04:00
2012-08-13 12:36:55 +04:00
# define U300_GPIO_PORT_STRIDE (0x30)
2011-09-08 12:04:51 +04:00
/*
2012-08-13 12:36:55 +04:00
* Control Register 32 bit ( R / W )
* bit 15 - 9 ( mask 0x0000FE00 ) contains the number of cores . 8 * cores
* gives the number of GPIO pins .
* bit 8 - 2 ( mask 0x000001FC ) contains the core version ID .
2011-09-08 12:04:51 +04:00
*/
2012-08-13 12:36:55 +04:00
# define U300_GPIO_CR (0x00)
# define U300_GPIO_CR_SYNC_SEL_ENABLE (0x00000002UL)
# define U300_GPIO_CR_BLOCK_CLKRQ_ENABLE (0x00000001UL)
# define U300_GPIO_PXPDIR (0x04)
# define U300_GPIO_PXPDOR (0x08)
# define U300_GPIO_PXPCR (0x0C)
2011-09-08 12:04:51 +04:00
# define U300_GPIO_PXPCR_ALL_PINS_MODE_MASK (0x0000FFFFUL)
# define U300_GPIO_PXPCR_PIN_MODE_MASK (0x00000003UL)
# define U300_GPIO_PXPCR_PIN_MODE_SHIFT (0x00000002UL)
# define U300_GPIO_PXPCR_PIN_MODE_INPUT (0x00000000UL)
# define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL (0x00000001UL)
# define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_DRAIN (0x00000002UL)
# define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_SOURCE (0x00000003UL)
2012-08-13 12:36:55 +04:00
# define U300_GPIO_PXPER (0x10)
# define U300_GPIO_PXPER_ALL_PULL_UP_DISABLE_MASK (0x000000FFUL)
# define U300_GPIO_PXPER_PULL_UP_DISABLE (0x00000001UL)
# define U300_GPIO_PXIEV (0x14)
# define U300_GPIO_PXIEN (0x18)
# define U300_GPIO_PXIFR (0x1C)
# define U300_GPIO_PXICR (0x20)
2011-09-08 12:04:51 +04:00
# define U300_GPIO_PXICR_ALL_IRQ_CONFIG_MASK (0x000000FFUL)
# define U300_GPIO_PXICR_IRQ_CONFIG_MASK (0x00000001UL)
# define U300_GPIO_PXICR_IRQ_CONFIG_FALLING_EDGE (0x00000000UL)
# define U300_GPIO_PXICR_IRQ_CONFIG_RISING_EDGE (0x00000001UL)
/* 8 bits per port, no version has more than 7 ports */
# define U300_GPIO_PINS_PER_PORT 8
# define U300_GPIO_MAX (U300_GPIO_PINS_PER_PORT * 7)
struct u300_gpio {
struct gpio_chip chip ;
struct list_head port_list ;
struct clk * clk ;
void __iomem * base ;
struct device * dev ;
u32 stride ;
/* Register offsets */
u32 pcr ;
u32 dor ;
u32 dir ;
u32 per ;
u32 icr ;
u32 ien ;
u32 iev ;
} ;
2009-04-24 00:15:04 +04:00
struct u300_gpio_port {
2011-09-08 12:04:51 +04:00
struct list_head node ;
struct u300_gpio * gpio ;
char name [ 8 ] ;
2012-10-17 20:31:20 +04:00
struct irq_domain * domain ;
2009-04-24 00:15:04 +04:00
int irq ;
int number ;
2011-09-08 12:04:51 +04:00
u8 toggle_edge_mode ;
2009-04-24 00:15:04 +04:00
} ;
2011-09-08 12:04:51 +04:00
/*
* Macro to expand to read a specific register found in the " gpio "
* struct . It requires the struct u300_gpio * gpio variable to exist in
* its context . It calculates the port offset from the given pin
* offset , muliplies by the port stride and adds the register offset
* so it provides a pointer to the desired register .
*/
# define U300_PIN_REG(pin, reg) \
( gpio - > base + ( pin > > 3 ) * gpio - > stride + gpio - > reg )
2009-04-24 00:15:04 +04:00
2011-09-08 12:04:51 +04:00
/*
* Provides a bitmask for a specific gpio pin inside an 8 - bit GPIO
* register .
*/
# define U300_PIN_BIT(pin) \
( 1 < < ( pin & 0x07 ) )
2009-04-24 00:15:04 +04:00
2011-09-08 12:04:51 +04:00
struct u300_gpio_confdata {
u16 bias_mode ;
bool output ;
int outval ;
2009-04-24 00:15:04 +04:00
} ;
2011-09-08 12:04:51 +04:00
/* BS335 has seven ports of 8 bits each = GPIO pins 0..55 */
# define BS335_GPIO_NUM_PORTS 7
2009-04-24 00:15:04 +04:00
2011-09-08 12:04:51 +04:00
# define U300_FLOATING_INPUT { \
2011-11-16 23:10:09 +04:00
. bias_mode = PIN_CONFIG_BIAS_HIGH_IMPEDANCE , \
2011-09-08 12:04:51 +04:00
. output = false , \
}
2009-04-24 00:15:04 +04:00
2011-09-08 12:04:51 +04:00
# define U300_PULL_UP_INPUT { \
2011-11-16 23:10:09 +04:00
. bias_mode = PIN_CONFIG_BIAS_PULL_UP , \
2011-09-08 12:04:51 +04:00
. output = false , \
}
2009-04-24 00:15:04 +04:00
2011-09-08 12:04:51 +04:00
# define U300_OUTPUT_LOW { \
. output = true , \
. outval = 0 , \
}
2009-04-24 00:15:04 +04:00
2011-09-08 12:04:51 +04:00
# define U300_OUTPUT_HIGH { \
. output = true , \
. outval = 1 , \
}
2009-04-24 00:15:04 +04:00
/* Initial configuration */
2012-03-31 00:04:51 +04:00
static const struct __initconst u300_gpio_confdata
2011-09-08 12:04:51 +04:00
bs335_gpio_config [ BS335_GPIO_NUM_PORTS ] [ U300_GPIO_PINS_PER_PORT ] = {
2009-04-24 00:15:04 +04:00
/* Port 0, pins 0-7 */
{
2011-09-08 12:04:51 +04:00
U300_FLOATING_INPUT ,
U300_OUTPUT_HIGH ,
U300_FLOATING_INPUT ,
U300_OUTPUT_LOW ,
U300_OUTPUT_LOW ,
U300_OUTPUT_LOW ,
U300_OUTPUT_LOW ,
U300_OUTPUT_LOW ,
2009-04-24 00:15:04 +04:00
} ,
/* Port 1, pins 0-7 */
{
2011-09-08 12:04:51 +04:00
U300_OUTPUT_LOW ,
U300_OUTPUT_LOW ,
U300_OUTPUT_LOW ,
U300_PULL_UP_INPUT ,
U300_FLOATING_INPUT ,
U300_OUTPUT_HIGH ,
U300_OUTPUT_LOW ,
U300_OUTPUT_LOW ,
2009-04-24 00:15:04 +04:00
} ,
/* Port 2, pins 0-7 */
{
2011-09-08 12:04:51 +04:00
U300_FLOATING_INPUT ,
U300_FLOATING_INPUT ,
U300_FLOATING_INPUT ,
U300_FLOATING_INPUT ,
U300_OUTPUT_LOW ,
U300_PULL_UP_INPUT ,
U300_OUTPUT_LOW ,
U300_PULL_UP_INPUT ,
2009-04-24 00:15:04 +04:00
} ,
/* Port 3, pins 0-7 */
{
2011-09-08 12:04:51 +04:00
U300_PULL_UP_INPUT ,
U300_OUTPUT_LOW ,
U300_FLOATING_INPUT ,
U300_FLOATING_INPUT ,
U300_FLOATING_INPUT ,
U300_FLOATING_INPUT ,
U300_FLOATING_INPUT ,
U300_FLOATING_INPUT ,
2009-04-24 00:15:04 +04:00
} ,
/* Port 4, pins 0-7 */
{
2011-09-08 12:04:51 +04:00
U300_FLOATING_INPUT ,
U300_FLOATING_INPUT ,
U300_FLOATING_INPUT ,
U300_FLOATING_INPUT ,
U300_FLOATING_INPUT ,
U300_FLOATING_INPUT ,
U300_FLOATING_INPUT ,
U300_FLOATING_INPUT ,
2009-04-24 00:15:04 +04:00
} ,
/* Port 5, pins 0-7 */
{
2011-09-08 12:04:51 +04:00
U300_FLOATING_INPUT ,
U300_FLOATING_INPUT ,
U300_FLOATING_INPUT ,
U300_FLOATING_INPUT ,
U300_FLOATING_INPUT ,
U300_FLOATING_INPUT ,
U300_FLOATING_INPUT ,
U300_FLOATING_INPUT ,
2009-04-24 00:15:04 +04:00
} ,
/* Port 6, pind 0-7 */
{
2011-09-08 12:04:51 +04:00
U300_FLOATING_INPUT ,
U300_FLOATING_INPUT ,
U300_FLOATING_INPUT ,
U300_FLOATING_INPUT ,
U300_FLOATING_INPUT ,
U300_FLOATING_INPUT ,
U300_FLOATING_INPUT ,
U300_FLOATING_INPUT ,
2009-04-24 00:15:04 +04:00
}
2011-09-08 12:04:51 +04:00
} ;
2009-04-24 00:15:04 +04:00
2011-09-08 12:04:51 +04:00
/**
* to_u300_gpio ( ) - get the pointer to u300_gpio
* @ chip : the gpio chip member of the structure u300_gpio
2009-04-24 00:15:04 +04:00
*/
2011-09-08 12:04:51 +04:00
static inline struct u300_gpio * to_u300_gpio ( struct gpio_chip * chip )
2009-04-24 00:15:04 +04:00
{
2011-09-08 12:04:51 +04:00
return container_of ( chip , struct u300_gpio , chip ) ;
2009-04-24 00:15:04 +04:00
}
2011-11-16 13:24:39 +04:00
static int u300_gpio_request ( struct gpio_chip * chip , unsigned offset )
{
/*
* Map back to global GPIO space and request muxing , the direction
* parameter does not matter for this controller .
*/
int gpio = chip - > base + offset ;
2012-02-09 10:23:28 +04:00
return pinctrl_request_gpio ( gpio ) ;
2011-11-16 13:24:39 +04:00
}
static void u300_gpio_free ( struct gpio_chip * chip , unsigned offset )
{
int gpio = chip - > base + offset ;
2012-02-09 10:23:28 +04:00
pinctrl_free_gpio ( gpio ) ;
2011-11-16 13:24:39 +04:00
}
2011-09-08 12:04:51 +04:00
static int u300_gpio_get ( struct gpio_chip * chip , unsigned offset )
2009-04-24 00:15:04 +04:00
{
2011-09-08 12:04:51 +04:00
struct u300_gpio * gpio = to_u300_gpio ( chip ) ;
2009-04-24 00:15:04 +04:00
2011-09-08 12:04:51 +04:00
return readl ( U300_PIN_REG ( offset , dir ) ) & U300_PIN_BIT ( offset ) ;
2009-04-24 00:15:04 +04:00
}
2011-09-08 12:04:51 +04:00
static void u300_gpio_set ( struct gpio_chip * chip , unsigned offset , int value )
2009-09-28 15:36:18 +04:00
{
2011-09-08 12:04:51 +04:00
struct u300_gpio * gpio = to_u300_gpio ( chip ) ;
unsigned long flags ;
u32 val ;
2009-09-28 15:36:18 +04:00
2011-09-08 12:04:51 +04:00
local_irq_save ( flags ) ;
2009-04-24 00:15:04 +04:00
2011-09-08 12:04:51 +04:00
val = readl ( U300_PIN_REG ( offset , dor ) ) ;
if ( value )
writel ( val | U300_PIN_BIT ( offset ) , U300_PIN_REG ( offset , dor ) ) ;
else
writel ( val & ~ U300_PIN_BIT ( offset ) , U300_PIN_REG ( offset , dor ) ) ;
2009-04-24 00:15:04 +04:00
2011-09-08 12:04:51 +04:00
local_irq_restore ( flags ) ;
2009-04-24 00:15:04 +04:00
}
2011-09-08 12:04:51 +04:00
static int u300_gpio_direction_input ( struct gpio_chip * chip , unsigned offset )
2009-04-24 00:15:04 +04:00
{
2011-09-08 12:04:51 +04:00
struct u300_gpio * gpio = to_u300_gpio ( chip ) ;
unsigned long flags ;
u32 val ;
2009-04-24 00:15:04 +04:00
2011-09-08 12:04:51 +04:00
local_irq_save ( flags ) ;
val = readl ( U300_PIN_REG ( offset , pcr ) ) ;
/* Mask out this pin, note 2 bits per setting */
val & = ~ ( U300_GPIO_PXPCR_PIN_MODE_MASK < < ( ( offset & 0x07 ) < < 1 ) ) ;
writel ( val , U300_PIN_REG ( offset , pcr ) ) ;
local_irq_restore ( flags ) ;
return 0 ;
2009-04-24 00:15:04 +04:00
}
2011-09-08 12:04:51 +04:00
static int u300_gpio_direction_output ( struct gpio_chip * chip , unsigned offset ,
int value )
2009-04-24 00:15:04 +04:00
{
2011-09-08 12:04:51 +04:00
struct u300_gpio * gpio = to_u300_gpio ( chip ) ;
2009-04-24 00:15:04 +04:00
unsigned long flags ;
2011-09-08 12:04:51 +04:00
u32 oldmode ;
u32 val ;
2009-04-24 00:15:04 +04:00
local_irq_save ( flags ) ;
2011-09-08 12:04:51 +04:00
val = readl ( U300_PIN_REG ( offset , pcr ) ) ;
/*
* Drive mode must be set by the special mode set function , set
* push / pull mode by default if no mode has been selected .
*/
oldmode = val & ( U300_GPIO_PXPCR_PIN_MODE_MASK < <
( ( offset & 0x07 ) < < 1 ) ) ;
/* mode = 0 means input, else some mode is already set */
if ( oldmode = = 0 ) {
val & = ~ ( U300_GPIO_PXPCR_PIN_MODE_MASK < <
( ( offset & 0x07 ) < < 1 ) ) ;
val | = ( U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL
< < ( ( offset & 0x07 ) < < 1 ) ) ;
writel ( val , U300_PIN_REG ( offset , pcr ) ) ;
2009-04-24 00:15:04 +04:00
}
2011-09-08 12:04:51 +04:00
u300_gpio_set ( chip , offset , value ) ;
2009-04-24 00:15:04 +04:00
local_irq_restore ( flags ) ;
2011-09-08 12:04:51 +04:00
return 0 ;
2009-04-24 00:15:04 +04:00
}
2011-09-08 12:04:51 +04:00
static int u300_gpio_to_irq ( struct gpio_chip * chip , unsigned offset )
2009-04-24 00:15:04 +04:00
{
2011-09-08 12:04:51 +04:00
struct u300_gpio * gpio = to_u300_gpio ( chip ) ;
2012-10-17 20:31:20 +04:00
int portno = offset > > 3 ;
struct u300_gpio_port * port = NULL ;
struct list_head * p ;
int retirq ;
2011-09-08 12:04:51 +04:00
2012-10-17 20:31:20 +04:00
list_for_each ( p , & gpio - > port_list ) {
port = list_entry ( p , struct u300_gpio_port , node ) ;
if ( port - > number = = portno )
break ;
}
if ( port = = NULL ) {
dev_err ( gpio - > dev , " could not locate port for GPIO %d IRQ \n " ,
offset ) ;
return - EINVAL ;
}
/*
* The local hwirqs on the port are the lower three bits , there
* are exactly 8 IRQs per port since they are 8 - bit
*/
retirq = irq_find_mapping ( port - > domain , ( offset & 0x7 ) ) ;
dev_dbg ( gpio - > dev , " request IRQ for GPIO %d, return %d from port %d \n " ,
offset , retirq , port - > number ) ;
2011-09-08 12:04:51 +04:00
return retirq ;
}
2011-11-17 00:58:10 +04:00
/* Returning -EINVAL means "supported but not available" */
int u300_gpio_config_get ( struct gpio_chip * chip ,
unsigned offset ,
unsigned long * config )
{
struct u300_gpio * gpio = to_u300_gpio ( chip ) ;
enum pin_config_param param = ( enum pin_config_param ) * config ;
bool biasmode ;
u32 drmode ;
/* One bit per pin, clamp to bool range */
biasmode = ! ! ( readl ( U300_PIN_REG ( offset , per ) ) & U300_PIN_BIT ( offset ) ) ;
/* Mask out the two bits for this pin and shift to bits 0,1 */
drmode = readl ( U300_PIN_REG ( offset , pcr ) ) ;
drmode & = ( U300_GPIO_PXPCR_PIN_MODE_MASK < < ( ( offset & 0x07 ) < < 1 ) ) ;
drmode > > = ( ( offset & 0x07 ) < < 1 ) ;
switch ( param ) {
case PIN_CONFIG_BIAS_HIGH_IMPEDANCE :
* config = 0 ;
if ( biasmode )
return 0 ;
else
return - EINVAL ;
break ;
case PIN_CONFIG_BIAS_PULL_UP :
* config = 0 ;
if ( ! biasmode )
return 0 ;
else
return - EINVAL ;
break ;
case PIN_CONFIG_DRIVE_PUSH_PULL :
* config = 0 ;
if ( drmode = = U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL )
return 0 ;
else
return - EINVAL ;
break ;
case PIN_CONFIG_DRIVE_OPEN_DRAIN :
* config = 0 ;
if ( drmode = = U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_DRAIN )
return 0 ;
else
return - EINVAL ;
break ;
case PIN_CONFIG_DRIVE_OPEN_SOURCE :
* config = 0 ;
if ( drmode = = U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_SOURCE )
return 0 ;
else
return - EINVAL ;
break ;
default :
break ;
}
return - ENOTSUPP ;
}
int u300_gpio_config_set ( struct gpio_chip * chip , unsigned offset ,
enum pin_config_param param )
2011-09-08 12:04:51 +04:00
{
struct u300_gpio * gpio = to_u300_gpio ( chip ) ;
2009-04-24 00:15:04 +04:00
unsigned long flags ;
u32 val ;
local_irq_save ( flags ) ;
2011-09-08 12:04:51 +04:00
switch ( param ) {
2011-11-16 23:10:09 +04:00
case PIN_CONFIG_BIAS_DISABLE :
case PIN_CONFIG_BIAS_HIGH_IMPEDANCE :
2011-09-08 12:04:51 +04:00
val = readl ( U300_PIN_REG ( offset , per ) ) ;
writel ( val | U300_PIN_BIT ( offset ) , U300_PIN_REG ( offset , per ) ) ;
break ;
2011-11-16 23:10:09 +04:00
case PIN_CONFIG_BIAS_PULL_UP :
2011-09-08 12:04:51 +04:00
val = readl ( U300_PIN_REG ( offset , per ) ) ;
writel ( val & ~ U300_PIN_BIT ( offset ) , U300_PIN_REG ( offset , per ) ) ;
break ;
2011-11-16 23:10:09 +04:00
case PIN_CONFIG_DRIVE_PUSH_PULL :
2011-09-08 12:04:51 +04:00
val = readl ( U300_PIN_REG ( offset , pcr ) ) ;
val & = ~ ( U300_GPIO_PXPCR_PIN_MODE_MASK
< < ( ( offset & 0x07 ) < < 1 ) ) ;
val | = ( U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL
< < ( ( offset & 0x07 ) < < 1 ) ) ;
writel ( val , U300_PIN_REG ( offset , pcr ) ) ;
break ;
2011-11-16 23:10:09 +04:00
case PIN_CONFIG_DRIVE_OPEN_DRAIN :
2011-09-08 12:04:51 +04:00
val = readl ( U300_PIN_REG ( offset , pcr ) ) ;
val & = ~ ( U300_GPIO_PXPCR_PIN_MODE_MASK
< < ( ( offset & 0x07 ) < < 1 ) ) ;
val | = ( U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_DRAIN
< < ( ( offset & 0x07 ) < < 1 ) ) ;
writel ( val , U300_PIN_REG ( offset , pcr ) ) ;
break ;
2011-11-16 23:10:09 +04:00
case PIN_CONFIG_DRIVE_OPEN_SOURCE :
2011-09-08 12:04:51 +04:00
val = readl ( U300_PIN_REG ( offset , pcr ) ) ;
val & = ~ ( U300_GPIO_PXPCR_PIN_MODE_MASK
< < ( ( offset & 0x07 ) < < 1 ) ) ;
val | = ( U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_SOURCE
< < ( ( offset & 0x07 ) < < 1 ) ) ;
writel ( val , U300_PIN_REG ( offset , pcr ) ) ;
break ;
default :
local_irq_restore ( flags ) ;
dev_err ( gpio - > dev , " illegal configuration requested \n " ) ;
return - EINVAL ;
}
2009-04-24 00:15:04 +04:00
local_irq_restore ( flags ) ;
return 0 ;
}
2011-09-08 12:04:51 +04:00
static struct gpio_chip u300_gpio_chip = {
. label = " u300-gpio-chip " ,
. owner = THIS_MODULE ,
2011-11-16 13:24:39 +04:00
. request = u300_gpio_request ,
. free = u300_gpio_free ,
2011-09-08 12:04:51 +04:00
. get = u300_gpio_get ,
. set = u300_gpio_set ,
. direction_input = u300_gpio_direction_input ,
. direction_output = u300_gpio_direction_output ,
. to_irq = u300_gpio_to_irq ,
} ;
static void u300_toggle_trigger ( struct u300_gpio * gpio , unsigned offset )
2009-04-24 00:15:04 +04:00
{
u32 val ;
2011-09-08 12:04:51 +04:00
val = readl ( U300_PIN_REG ( offset , icr ) ) ;
/* Set mode depending on state */
if ( u300_gpio_get ( & gpio - > chip , offset ) ) {
/* High now, let's trigger on falling edge next then */
writel ( val & ~ U300_PIN_BIT ( offset ) , U300_PIN_REG ( offset , icr ) ) ;
dev_dbg ( gpio - > dev , " next IRQ on falling edge on pin %d \n " ,
offset ) ;
} else {
/* Low now, let's trigger on rising edge next then */
writel ( val | U300_PIN_BIT ( offset ) , U300_PIN_REG ( offset , icr ) ) ;
dev_dbg ( gpio - > dev , " next IRQ on rising edge on pin %d \n " ,
offset ) ;
}
2009-04-24 00:15:04 +04:00
}
2011-09-08 12:04:51 +04:00
static int u300_gpio_irq_type ( struct irq_data * d , unsigned trigger )
2009-04-24 00:15:04 +04:00
{
2011-09-08 12:04:51 +04:00
struct u300_gpio_port * port = irq_data_get_irq_chip_data ( d ) ;
struct u300_gpio * gpio = port - > gpio ;
2012-10-17 20:31:20 +04:00
int offset = ( port - > number < < 3 ) + d - > hwirq ;
2009-04-24 00:15:04 +04:00
u32 val ;
2011-09-08 12:04:51 +04:00
if ( ( trigger & IRQF_TRIGGER_RISING ) & &
( trigger & IRQF_TRIGGER_FALLING ) ) {
/*
* The GPIO block can only trigger on falling OR rising edges ,
* not both . So we need to toggle the mode whenever the pin
* goes from one state to the other with a special state flag
*/
dev_dbg ( gpio - > dev ,
" trigger on both rising and falling edge on pin %d \n " ,
offset ) ;
port - > toggle_edge_mode | = U300_PIN_BIT ( offset ) ;
u300_toggle_trigger ( gpio , offset ) ;
} else if ( trigger & IRQF_TRIGGER_RISING ) {
dev_dbg ( gpio - > dev , " trigger on rising edge on pin %d \n " ,
offset ) ;
val = readl ( U300_PIN_REG ( offset , icr ) ) ;
writel ( val | U300_PIN_BIT ( offset ) , U300_PIN_REG ( offset , icr ) ) ;
port - > toggle_edge_mode & = ~ U300_PIN_BIT ( offset ) ;
} else if ( trigger & IRQF_TRIGGER_FALLING ) {
dev_dbg ( gpio - > dev , " trigger on falling edge on pin %d \n " ,
offset ) ;
val = readl ( U300_PIN_REG ( offset , icr ) ) ;
writel ( val & ~ U300_PIN_BIT ( offset ) , U300_PIN_REG ( offset , icr ) ) ;
port - > toggle_edge_mode & = ~ U300_PIN_BIT ( offset ) ;
}
return 0 ;
2009-04-24 00:15:04 +04:00
}
2011-09-08 12:04:51 +04:00
static void u300_gpio_irq_enable ( struct irq_data * d )
2009-04-24 00:15:04 +04:00
{
2011-09-08 12:04:51 +04:00
struct u300_gpio_port * port = irq_data_get_irq_chip_data ( d ) ;
struct u300_gpio * gpio = port - > gpio ;
2012-10-17 20:31:20 +04:00
int offset = ( port - > number < < 3 ) + d - > hwirq ;
2009-04-24 00:15:04 +04:00
u32 val ;
unsigned long flags ;
2012-10-17 20:31:20 +04:00
dev_dbg ( gpio - > dev , " enable IRQ for hwirq %lu on port %s, offset %d \n " ,
d - > hwirq , port - > name , offset ) ;
2009-04-24 00:15:04 +04:00
local_irq_save ( flags ) ;
2011-09-08 12:04:51 +04:00
val = readl ( U300_PIN_REG ( offset , ien ) ) ;
writel ( val | U300_PIN_BIT ( offset ) , U300_PIN_REG ( offset , ien ) ) ;
2009-04-24 00:15:04 +04:00
local_irq_restore ( flags ) ;
}
2011-09-08 12:04:51 +04:00
static void u300_gpio_irq_disable ( struct irq_data * d )
2009-04-24 00:15:04 +04:00
{
2011-09-08 12:04:51 +04:00
struct u300_gpio_port * port = irq_data_get_irq_chip_data ( d ) ;
struct u300_gpio * gpio = port - > gpio ;
2012-10-17 20:31:20 +04:00
int offset = ( port - > number < < 3 ) + d - > hwirq ;
2009-04-24 00:15:04 +04:00
u32 val ;
unsigned long flags ;
local_irq_save ( flags ) ;
2011-09-08 12:04:51 +04:00
val = readl ( U300_PIN_REG ( offset , ien ) ) ;
writel ( val & ~ U300_PIN_BIT ( offset ) , U300_PIN_REG ( offset , ien ) ) ;
2009-04-24 00:15:04 +04:00
local_irq_restore ( flags ) ;
}
2011-09-08 12:04:51 +04:00
static struct irq_chip u300_gpio_irqchip = {
. name = " u300-gpio-irqchip " ,
. irq_enable = u300_gpio_irq_enable ,
. irq_disable = u300_gpio_irq_disable ,
. irq_set_type = u300_gpio_irq_type ,
} ;
static void u300_gpio_irq_handler ( unsigned irq , struct irq_desc * desc )
2009-04-24 00:15:04 +04:00
{
2011-09-08 12:04:51 +04:00
struct u300_gpio_port * port = irq_get_handler_data ( irq ) ;
struct u300_gpio * gpio = port - > gpio ;
int pinoffset = port - > number < < 3 ; /* get the right stride */
unsigned long val ;
2009-04-24 00:15:04 +04:00
2011-09-08 12:04:51 +04:00
desc - > irq_data . chip - > irq_ack ( & desc - > irq_data ) ;
2009-04-24 00:15:04 +04:00
/* Read event register */
2011-09-08 12:04:51 +04:00
val = readl ( U300_PIN_REG ( pinoffset , iev ) ) ;
2009-04-24 00:15:04 +04:00
/* Mask relevant bits */
2011-09-08 12:04:51 +04:00
val & = 0xFFU ; /* 8 bits per port */
2009-04-24 00:15:04 +04:00
/* ACK IRQ (clear event) */
2011-09-08 12:04:51 +04:00
writel ( val , U300_PIN_REG ( pinoffset , iev ) ) ;
/* Call IRQ handler */
if ( val ! = 0 ) {
int irqoffset ;
for_each_set_bit ( irqoffset , & val , U300_GPIO_PINS_PER_PORT ) {
2012-10-17 20:31:20 +04:00
int pin_irq = irq_find_mapping ( port - > domain , irqoffset ) ;
2011-09-08 12:04:51 +04:00
int offset = pinoffset + irqoffset ;
dev_dbg ( gpio - > dev , " GPIO IRQ %d on pin %d \n " ,
pin_irq , offset ) ;
generic_handle_irq ( pin_irq ) ;
/*
* Triggering IRQ on both rising and falling edge
* needs mockery
*/
if ( port - > toggle_edge_mode & U300_PIN_BIT ( offset ) )
u300_toggle_trigger ( gpio , offset ) ;
}
2009-04-24 00:15:04 +04:00
}
2011-09-08 12:04:51 +04:00
desc - > irq_data . chip - > irq_unmask ( & desc - > irq_data ) ;
2009-04-24 00:15:04 +04:00
}
2011-09-08 12:04:51 +04:00
static void __init u300_gpio_init_pin ( struct u300_gpio * gpio ,
int offset ,
const struct u300_gpio_confdata * conf )
2009-04-24 00:15:04 +04:00
{
2011-09-08 12:04:51 +04:00
/* Set mode: input or output */
if ( conf - > output ) {
u300_gpio_direction_output ( & gpio - > chip , offset , conf - > outval ) ;
2009-04-24 00:15:04 +04:00
2011-09-08 12:04:51 +04:00
/* Deactivate bias mode for output */
2011-11-17 00:58:10 +04:00
u300_gpio_config_set ( & gpio - > chip , offset ,
PIN_CONFIG_BIAS_HIGH_IMPEDANCE ) ;
2011-09-08 12:04:51 +04:00
/* Set drive mode for output */
2011-11-17 00:58:10 +04:00
u300_gpio_config_set ( & gpio - > chip , offset ,
PIN_CONFIG_DRIVE_PUSH_PULL ) ;
2011-09-08 12:04:51 +04:00
dev_dbg ( gpio - > dev , " set up pin %d as output, value: %d \n " ,
offset , conf - > outval ) ;
} else {
u300_gpio_direction_input ( & gpio - > chip , offset ) ;
/* Always set output low on input pins */
u300_gpio_set ( & gpio - > chip , offset , 0 ) ;
/* Set bias mode for input */
2011-11-17 00:58:10 +04:00
u300_gpio_config_set ( & gpio - > chip , offset , conf - > bias_mode ) ;
2011-09-08 12:04:51 +04:00
dev_dbg ( gpio - > dev , " set up pin %d as input, bias: %04x \n " ,
offset , conf - > bias_mode ) ;
2009-04-24 00:15:04 +04:00
}
2011-09-08 12:04:51 +04:00
}
2009-04-24 00:15:04 +04:00
2011-09-08 12:04:51 +04:00
static void __init u300_gpio_init_coh901571 ( struct u300_gpio * gpio ,
struct u300_gpio_platform * plat )
{
int i , j ;
/* Write default config and values to all pins */
for ( i = 0 ; i < plat - > ports ; i + + ) {
for ( j = 0 ; j < 8 ; j + + ) {
const struct u300_gpio_confdata * conf ;
int offset = ( i * 8 ) + j ;
2012-08-13 12:36:55 +04:00
conf = & bs335_gpio_config [ i ] [ j ] ;
2011-09-08 12:04:51 +04:00
u300_gpio_init_pin ( gpio , offset , conf ) ;
2009-04-24 00:15:04 +04:00
}
}
2011-09-08 12:04:51 +04:00
}
2009-04-24 00:15:04 +04:00
2011-09-08 12:04:51 +04:00
static inline void u300_gpio_free_ports ( struct u300_gpio * gpio )
{
struct u300_gpio_port * port ;
struct list_head * p , * n ;
list_for_each_safe ( p , n , & gpio - > port_list ) {
port = list_entry ( p , struct u300_gpio_port , node ) ;
list_del ( & port - > node ) ;
2012-10-17 20:31:20 +04:00
if ( port - > domain )
irq_domain_remove ( port - > domain ) ;
2011-09-08 12:04:51 +04:00
kfree ( port ) ;
2009-04-24 00:15:04 +04:00
}
}
2012-11-20 17:28:07 +04:00
/*
* Here we map a GPIO in the local gpio_chip pin space to a pin in
* the local pinctrl pin space . The pin controller used is
* pinctrl - u300 .
*/
struct coh901_pinpair {
unsigned int offset ;
unsigned int pin_base ;
} ;
# define COH901_PINRANGE(a, b) { .offset = a, .pin_base = b }
static struct coh901_pinpair coh901_pintable [ ] = {
COH901_PINRANGE ( 10 , 426 ) ,
COH901_PINRANGE ( 11 , 180 ) ,
COH901_PINRANGE ( 12 , 165 ) , /* MS/MMC card insertion */
COH901_PINRANGE ( 13 , 179 ) ,
COH901_PINRANGE ( 14 , 178 ) ,
COH901_PINRANGE ( 16 , 194 ) ,
COH901_PINRANGE ( 17 , 193 ) ,
COH901_PINRANGE ( 18 , 192 ) ,
COH901_PINRANGE ( 19 , 191 ) ,
COH901_PINRANGE ( 20 , 186 ) ,
COH901_PINRANGE ( 21 , 185 ) ,
COH901_PINRANGE ( 22 , 184 ) ,
COH901_PINRANGE ( 23 , 183 ) ,
COH901_PINRANGE ( 24 , 182 ) ,
COH901_PINRANGE ( 25 , 181 ) ,
} ;
2011-09-08 12:04:51 +04:00
static int __init u300_gpio_probe ( struct platform_device * pdev )
2009-04-24 00:15:04 +04:00
{
2011-09-08 12:04:51 +04:00
struct u300_gpio_platform * plat = dev_get_platdata ( & pdev - > dev ) ;
struct u300_gpio * gpio ;
2012-10-17 20:49:05 +04:00
struct resource * memres ;
2009-04-24 00:15:04 +04:00
int err = 0 ;
2011-09-08 12:04:51 +04:00
int portno ;
u32 val ;
u32 ifr ;
2009-04-24 00:15:04 +04:00
int i ;
2012-10-17 20:49:05 +04:00
gpio = devm_kzalloc ( & pdev - > dev , sizeof ( struct u300_gpio ) , GFP_KERNEL ) ;
if ( gpio = = NULL )
2011-09-08 12:04:51 +04:00
return - ENOMEM ;
gpio - > chip = u300_gpio_chip ;
gpio - > chip . ngpio = plat - > ports * U300_GPIO_PINS_PER_PORT ;
gpio - > chip . dev = & pdev - > dev ;
gpio - > chip . base = plat - > gpio_base ;
gpio - > dev = & pdev - > dev ;
2009-04-24 00:15:04 +04:00
2012-10-17 20:49:05 +04:00
memres = platform_get_resource ( pdev , IORESOURCE_MEM , 0 ) ;
if ( ! memres ) {
dev_err ( gpio - > dev , " could not get GPIO memory resource \n " ) ;
return - ENODEV ;
}
2013-01-21 14:09:14 +04:00
gpio - > base = devm_ioremap_resource ( & pdev - > dev , memres ) ;
if ( IS_ERR ( gpio - > base ) )
return PTR_ERR ( gpio - > base ) ;
2012-10-17 20:49:05 +04:00
gpio - > clk = devm_clk_get ( gpio - > dev , NULL ) ;
2011-09-08 12:04:51 +04:00
if ( IS_ERR ( gpio - > clk ) ) {
err = PTR_ERR ( gpio - > clk ) ;
dev_err ( gpio - > dev , " could not get GPIO clock \n " ) ;
2012-10-17 20:49:05 +04:00
return err ;
2009-04-24 00:15:04 +04:00
}
2012-10-17 20:49:05 +04:00
2012-06-20 01:36:15 +04:00
err = clk_prepare_enable ( gpio - > clk ) ;
2009-04-24 00:15:04 +04:00
if ( err ) {
2011-09-08 12:04:51 +04:00
dev_err ( gpio - > dev , " could not enable GPIO clock \n " ) ;
2012-10-17 20:49:05 +04:00
return err ;
2009-04-24 00:15:04 +04:00
}
2011-09-08 12:04:51 +04:00
2012-08-13 12:36:55 +04:00
dev_info ( gpio - > dev ,
" initializing GPIO Controller COH 901 571/3 \n " ) ;
gpio - > stride = U300_GPIO_PORT_STRIDE ;
gpio - > pcr = U300_GPIO_PXPCR ;
gpio - > dor = U300_GPIO_PXPDOR ;
gpio - > dir = U300_GPIO_PXPDIR ;
gpio - > per = U300_GPIO_PXPER ;
gpio - > icr = U300_GPIO_PXICR ;
gpio - > ien = U300_GPIO_PXIEN ;
gpio - > iev = U300_GPIO_PXIEV ;
ifr = U300_GPIO_PXIFR ;
val = readl ( gpio - > base + U300_GPIO_CR ) ;
dev_info ( gpio - > dev , " COH901571/3 block version: %d, " \
" number of cores: %d totalling %d pins \n " ,
( ( val & 0x000001FC ) > > 2 ) ,
( ( val & 0x0000FE00 ) > > 9 ) ,
( ( val & 0x0000FE00 ) > > 9 ) * 8 ) ;
writel ( U300_GPIO_CR_BLOCK_CLKRQ_ENABLE ,
gpio - > base + U300_GPIO_CR ) ;
u300_gpio_init_coh901571 ( gpio , plat ) ;
2011-09-08 12:04:51 +04:00
/* Add each port with its IRQ separately */
INIT_LIST_HEAD ( & gpio - > port_list ) ;
for ( portno = 0 ; portno < plat - > ports ; portno + + ) {
struct u300_gpio_port * port =
kmalloc ( sizeof ( struct u300_gpio_port ) , GFP_KERNEL ) ;
if ( ! port ) {
dev_err ( gpio - > dev , " out of memory \n " ) ;
err = - ENOMEM ;
goto err_no_port ;
2009-04-24 00:15:04 +04:00
}
2011-09-08 12:04:51 +04:00
snprintf ( port - > name , 8 , " gpio%d " , portno ) ;
port - > number = portno ;
port - > gpio = gpio ;
port - > irq = platform_get_irq_byname ( pdev ,
port - > name ) ;
2012-10-17 20:31:20 +04:00
dev_dbg ( gpio - > dev , " register IRQ %d for port %s \n " , port - > irq ,
2011-09-08 12:04:51 +04:00
port - > name ) ;
2012-10-17 20:31:20 +04:00
port - > domain = irq_domain_add_linear ( pdev - > dev . of_node ,
U300_GPIO_PINS_PER_PORT ,
& irq_domain_simple_ops ,
port ) ;
2012-11-13 20:16:14 +04:00
if ( ! port - > domain ) {
err = - ENOMEM ;
2012-10-17 20:31:20 +04:00
goto err_no_domain ;
2012-11-13 20:16:14 +04:00
}
2012-10-17 20:31:20 +04:00
2011-09-08 12:04:51 +04:00
irq_set_chained_handler ( port - > irq , u300_gpio_irq_handler ) ;
irq_set_handler_data ( port - > irq , port ) ;
/* For each GPIO pin set the unique IRQ handler */
for ( i = 0 ; i < U300_GPIO_PINS_PER_PORT ; i + + ) {
2012-10-17 20:31:20 +04:00
int irqno = irq_create_mapping ( port - > domain , i ) ;
2011-09-08 12:04:51 +04:00
2012-10-17 20:31:20 +04:00
dev_dbg ( gpio - > dev , " GPIO%d on port %s gets IRQ %d \n " ,
gpio - > chip . base + ( port - > number < < 3 ) + i ,
port - > name , irqno ) ;
2011-09-08 12:04:51 +04:00
irq_set_chip_and_handler ( irqno , & u300_gpio_irqchip ,
handle_simple_irq ) ;
set_irq_flags ( irqno , IRQF_VALID ) ;
irq_set_chip_data ( irqno , port ) ;
}
/* Turns off irq force (test register) for this port */
writel ( 0x0 , gpio - > base + portno * gpio - > stride + ifr ) ;
list_add_tail ( & port - > node , & gpio - > port_list ) ;
2009-04-24 00:15:04 +04:00
}
2011-09-08 12:04:51 +04:00
dev_dbg ( gpio - > dev , " initialized %d GPIO ports \n " , portno ) ;
err = gpiochip_add ( & gpio - > chip ) ;
if ( err ) {
dev_err ( gpio - > dev , " unable to add gpiochip: %d \n " , err ) ;
goto err_no_chip ;
}
2012-11-20 17:28:07 +04:00
/*
* Add pinctrl pin ranges , the pin controller must be registered
* at this point
*/
for ( i = 0 ; i < ARRAY_SIZE ( coh901_pintable ) ; i + + ) {
struct coh901_pinpair * p = & coh901_pintable [ i ] ;
err = gpiochip_add_pin_range ( & gpio - > chip , " pinctrl-u300 " ,
p - > offset , p - > pin_base , 1 ) ;
if ( err )
goto err_no_range ;
}
2011-09-08 12:04:51 +04:00
platform_set_drvdata ( pdev , gpio ) ;
2009-04-24 00:15:04 +04:00
return 0 ;
2012-11-20 17:28:07 +04:00
err_no_range :
2012-02-21 17:31:45 +04:00
err = gpiochip_remove ( & gpio - > chip ) ;
2011-09-08 12:04:51 +04:00
err_no_chip :
2012-10-17 20:31:20 +04:00
err_no_domain :
2011-09-08 12:04:51 +04:00
err_no_port :
u300_gpio_free_ports ( gpio ) ;
2012-06-20 01:36:15 +04:00
clk_disable_unprepare ( gpio - > clk ) ;
2012-11-13 20:16:14 +04:00
dev_err ( & pdev - > dev , " module ERROR:%d \n " , err ) ;
2009-04-24 00:15:04 +04:00
return err ;
}
2011-09-08 12:04:51 +04:00
static int __exit u300_gpio_remove ( struct platform_device * pdev )
2009-04-24 00:15:04 +04:00
{
2011-09-08 12:04:51 +04:00
struct u300_gpio * gpio = platform_get_drvdata ( pdev ) ;
int err ;
2009-04-24 00:15:04 +04:00
/* Turn off the GPIO block */
2012-08-13 12:36:55 +04:00
writel ( 0x00000000U , gpio - > base + U300_GPIO_CR ) ;
2011-09-08 12:04:51 +04:00
err = gpiochip_remove ( & gpio - > chip ) ;
if ( err < 0 ) {
dev_err ( gpio - > dev , " unable to remove gpiochip: %d \n " , err ) ;
return err ;
}
u300_gpio_free_ports ( gpio ) ;
2012-06-20 01:36:15 +04:00
clk_disable_unprepare ( gpio - > clk ) ;
2011-09-08 12:04:51 +04:00
platform_set_drvdata ( pdev , NULL ) ;
2009-04-24 00:15:04 +04:00
return 0 ;
}
2011-09-08 12:04:51 +04:00
static struct platform_driver u300_gpio_driver = {
2009-04-24 00:15:04 +04:00
. driver = {
. name = " u300-gpio " ,
} ,
2011-09-08 12:04:51 +04:00
. remove = __exit_p ( u300_gpio_remove ) ,
2009-04-24 00:15:04 +04:00
} ;
static int __init u300_gpio_init ( void )
{
2011-09-08 12:04:51 +04:00
return platform_driver_probe ( & u300_gpio_driver , u300_gpio_probe ) ;
2009-04-24 00:15:04 +04:00
}
static void __exit u300_gpio_exit ( void )
{
2011-09-08 12:04:51 +04:00
platform_driver_unregister ( & u300_gpio_driver ) ;
2009-04-24 00:15:04 +04:00
}
arch_initcall ( u300_gpio_init ) ;
module_exit ( u300_gpio_exit ) ;
MODULE_AUTHOR ( " Linus Walleij <linus.walleij@stericsson.com> " ) ;
2011-09-08 12:04:51 +04:00
MODULE_DESCRIPTION ( " ST-Ericsson AB COH 901 335/COH 901 571/3 GPIO driver " ) ;
2009-04-24 00:15:04 +04:00
MODULE_LICENSE ( " GPL " ) ;