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>
# include <linux/interrupt.h>
# include <linux/delay.h>
# include <linux/errno.h>
# include <linux/io.h>
# 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/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>
# 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 */
2013-05-23 22:09:43 +04:00
# define U300_GPIO_NUM_PORTS 7
2011-09-08 12:04:51 +04:00
# define U300_GPIO_PINS_PER_PORT 8
2013-05-23 22:09:43 +04:00
# define U300_GPIO_MAX (U300_GPIO_PINS_PER_PORT * U300_GPIO_NUM_PORTS)
2011-09-08 12:04:51 +04:00
2014-03-25 16:37:17 +04:00
struct u300_gpio_port {
struct u300_gpio * gpio ;
char name [ 8 ] ;
int irq ;
int number ;
u8 toggle_edge_mode ;
} ;
2011-09-08 12:04:51 +04:00
struct u300_gpio {
struct gpio_chip chip ;
2014-03-25 16:37:17 +04:00
struct u300_gpio_port ports [ U300_GPIO_NUM_PORTS ] ;
2011-09-08 12:04:51 +04:00
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
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
# 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 */
2016-02-08 17:29:49 +03:00
static const struct u300_gpio_confdata __initconst
2013-05-23 22:09:43 +04:00
bs335_gpio_config [ U300_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
static int u300_gpio_get ( struct gpio_chip * chip , unsigned offset )
2009-04-24 00:15:04 +04:00
{
2015-12-08 11:33:30 +03:00
struct u300_gpio * gpio = gpiochip_get_data ( chip ) ;
2009-04-24 00:15:04 +04:00
2015-12-21 18:25:11 +03: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
{
2015-12-08 11:33:30 +03:00
struct u300_gpio * gpio = gpiochip_get_data ( chip ) ;
2011-09-08 12:04:51 +04:00
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
{
2015-12-08 11:33:30 +03:00
struct u300_gpio * gpio = gpiochip_get_data ( chip ) ;
2011-09-08 12:04:51 +04:00
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
{
2015-12-08 11:33:30 +03:00
struct u300_gpio * gpio = gpiochip_get_data ( 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-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 )
{
2015-12-08 11:33:30 +03:00
struct u300_gpio * gpio = gpiochip_get_data ( chip ) ;
2011-11-17 00:58:10 +04:00
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 ) ;
2013-03-15 09:09:52 +04:00
switch ( param ) {
2011-11-17 00:58:10 +04:00
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
{
2015-12-08 11:33:30 +03:00
struct u300_gpio * gpio = gpiochip_get_data ( 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 ;
}
2017-07-12 00:35:19 +03:00
static const struct gpio_chip u300_gpio_chip = {
2011-09-08 12:04:51 +04:00
. label = " u300-gpio-chip " ,
. owner = THIS_MODULE ,
2015-10-11 18:34:19 +03:00
. request = gpiochip_generic_request ,
. free = gpiochip_generic_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 ,
} ;
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
{
2014-03-25 16:37:17 +04:00
struct gpio_chip * chip = irq_data_get_irq_chip_data ( d ) ;
2015-12-08 11:33:30 +03:00
struct u300_gpio * gpio = gpiochip_get_data ( chip ) ;
2014-03-25 16:37:17 +04:00
struct u300_gpio_port * port = & gpio - > ports [ d - > hwirq > > 3 ] ;
int offset = 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
{
2014-03-25 16:37:17 +04:00
struct gpio_chip * chip = irq_data_get_irq_chip_data ( d ) ;
2015-12-08 11:33:30 +03:00
struct u300_gpio * gpio = gpiochip_get_data ( chip ) ;
2014-03-25 16:37:17 +04:00
struct u300_gpio_port * port = & gpio - > ports [ d - > hwirq > > 3 ] ;
int offset = 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
{
2014-03-25 16:37:17 +04:00
struct gpio_chip * chip = irq_data_get_irq_chip_data ( d ) ;
2015-12-08 11:33:30 +03:00
struct u300_gpio * gpio = gpiochip_get_data ( chip ) ;
2014-03-25 16:37:17 +04:00
int offset = 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 ) ;
2014-03-14 21:24:30 +04:00
}
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 ,
} ;
2015-09-14 11:42:37 +03:00
static void u300_gpio_irq_handler ( struct irq_desc * desc )
2009-04-24 00:15:04 +04:00
{
2015-07-13 02:50:02 +03:00
unsigned int irq = irq_desc_get_irq ( desc ) ;
2015-06-04 07:13:16 +03:00
struct irq_chip * parent_chip = irq_desc_get_chip ( desc ) ;
struct gpio_chip * chip = irq_desc_get_handler_data ( desc ) ;
2015-12-08 11:33:30 +03:00
struct u300_gpio * gpio = gpiochip_get_data ( chip ) ;
2014-03-25 16:37:17 +04:00
struct u300_gpio_port * port = & gpio - > ports [ irq - chip - > base ] ;
2011-09-08 12:04:51 +04:00
int pinoffset = port - > number < < 3 ; /* get the right stride */
unsigned long val ;
2009-04-24 00:15:04 +04:00
2014-03-25 16:37:17 +04:00
chained_irq_enter ( parent_chip , desc ) ;
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 ) {
int offset = pinoffset + irqoffset ;
2017-11-07 21:15:47 +03:00
int pin_irq = irq_find_mapping ( chip - > irq . domain , offset ) ;
2011-09-08 12:04:51 +04:00
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
2014-03-25 16:37:17 +04:00
chained_irq_exit ( parent_chip , desc ) ;
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
2013-05-23 22:09:43 +04:00
static void __init u300_gpio_init_coh901571 ( struct u300_gpio * gpio )
2011-09-08 12:04:51 +04:00
{
int i , j ;
/* Write default config and values to all pins */
2013-05-23 22:09:43 +04:00
for ( i = 0 ; i < U300_GPIO_NUM_PORTS ; i + + ) {
2011-09-08 12:04:51 +04:00
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
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 * 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 ;
2013-05-23 22:09:43 +04:00
gpio - > chip . ngpio = U300_GPIO_NUM_PORTS * U300_GPIO_PINS_PER_PORT ;
2015-11-04 11:56:26 +03:00
gpio - > chip . parent = & pdev - > dev ;
2013-05-23 22:09:43 +04:00
gpio - > chip . base = 0 ;
2011-09-08 12:04:51 +04:00
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 ) ;
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 ) ;
2013-05-23 22:09:43 +04:00
u300_gpio_init_coh901571 ( gpio ) ;
2011-09-08 12:04:51 +04:00
2014-03-25 16:37:17 +04:00
# ifdef CONFIG_OF_GPIO
gpio - > chip . of_node = pdev - > dev . of_node ;
# endif
2015-12-08 11:33:30 +03:00
err = gpiochip_add_data ( & gpio - > chip , gpio ) ;
2014-03-25 16:37:17 +04:00
if ( err ) {
dev_err ( gpio - > dev , " unable to add gpiochip: %d \n " , err ) ;
goto err_no_chip ;
}
err = gpiochip_irqchip_add ( & gpio - > chip ,
& u300_gpio_irqchip ,
0 ,
handle_simple_irq ,
IRQ_TYPE_EDGE_FALLING ) ;
if ( err ) {
dev_err ( gpio - > dev , " no GPIO irqchip \n " ) ;
goto err_no_irqchip ;
}
2011-09-08 12:04:51 +04:00
/* Add each port with its IRQ separately */
2013-05-23 22:09:43 +04:00
for ( portno = 0 ; portno < U300_GPIO_NUM_PORTS ; portno + + ) {
2014-03-25 16:37:17 +04:00
struct u300_gpio_port * port = & gpio - > ports [ portno ] ;
2011-09-08 12:04:51 +04:00
snprintf ( port - > name , 8 , " gpio%d " , portno ) ;
port - > number = portno ;
port - > gpio = gpio ;
2013-04-10 12:49:31 +04:00
port - > irq = platform_get_irq ( pdev , portno ) ;
2011-09-08 12:04:51 +04:00
2014-03-25 16:37:17 +04:00
gpiochip_set_chained_irqchip ( & gpio - > chip ,
& u300_gpio_irqchip ,
port - > irq ,
u300_gpio_irq_handler ) ;
2011-09-08 12:04:51 +04:00
/* Turns off irq force (test register) for this port */
writel ( 0x0 , gpio - > base + portno * gpio - > stride + ifr ) ;
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 ) ;
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 :
2014-03-25 16:37:17 +04:00
err_no_irqchip :
2014-07-13 00:30:13 +04:00
gpiochip_remove ( & gpio - > chip ) ;
2011-09-08 12:04:51 +04:00
err_no_chip :
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 ) ;
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
2014-07-13 00:30:13 +04:00
gpiochip_remove ( & gpio - > chip ) ;
2012-06-20 01:36:15 +04:00
clk_disable_unprepare ( gpio - > clk ) ;
2009-04-24 00:15:04 +04:00
return 0 ;
}
2013-04-10 12:49:31 +04:00
static const struct of_device_id u300_gpio_match [ ] = {
{ . compatible = " stericsson,gpio-coh901 " } ,
{ } ,
} ;
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 " ,
2013-04-10 12:49:31 +04:00
. of_match_table = u300_gpio_match ,
2009-04-24 00:15:04 +04:00
} ,
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 " ) ;