2013-06-18 15:33:02 +04:00
/*
* Pinctrl GPIO driver for Intel Baytrail
* Copyright ( c ) 2012 - 2013 , Intel Corporation .
*
* Author : Mathias Nyman < mathias . nyman @ linux . intel . com >
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms and conditions of the GNU General Public License ,
* version 2 , as published by the Free Software Foundation .
*
* This program is distributed in the hope it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License for
* more details .
*
* You should have received a copy of the GNU General Public License along with
* this program ; if not , write to the Free Software Foundation , Inc . ,
* 51 Franklin St - Fifth Floor , Boston , MA 02110 - 1301 USA .
*
*/
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/init.h>
# include <linux/types.h>
# include <linux/bitops.h>
# include <linux/interrupt.h>
# include <linux/gpio.h>
# include <linux/acpi.h>
# include <linux/platform_device.h>
# include <linux/seq_file.h>
# include <linux/io.h>
# include <linux/pm_runtime.h>
# include <linux/pinctrl/pinctrl.h>
/* memory mapped register offsets */
# define BYT_CONF0_REG 0x000
# define BYT_CONF1_REG 0x004
# define BYT_VAL_REG 0x008
# define BYT_DFT_REG 0x00c
# define BYT_INT_STAT_REG 0x800
/* BYT_CONF0_REG register bits */
2014-05-16 13:18:29 +04:00
# define BYT_IODEN BIT(31)
2014-06-12 22:06:20 +04:00
# define BYT_DIRECT_IRQ_EN BIT(27)
2013-06-18 15:33:02 +04:00
# define BYT_TRIG_NEG BIT(26)
# define BYT_TRIG_POS BIT(25)
# define BYT_TRIG_LVL BIT(24)
2014-05-16 13:18:29 +04:00
# define BYT_PULL_STR_SHIFT 9
# define BYT_PULL_STR_MASK (3 << BYT_PULL_STR_SHIFT)
# define BYT_PULL_STR_2K (0 << BYT_PULL_STR_SHIFT)
# define BYT_PULL_STR_10K (1 << BYT_PULL_STR_SHIFT)
# define BYT_PULL_STR_20K (2 << BYT_PULL_STR_SHIFT)
# define BYT_PULL_STR_40K (3 << BYT_PULL_STR_SHIFT)
# define BYT_PULL_ASSIGN_SHIFT 7
# define BYT_PULL_ASSIGN_MASK (3 << BYT_PULL_ASSIGN_SHIFT)
# define BYT_PULL_ASSIGN_UP (1 << BYT_PULL_ASSIGN_SHIFT)
# define BYT_PULL_ASSIGN_DOWN (2 << BYT_PULL_ASSIGN_SHIFT)
2013-06-18 15:33:02 +04:00
# define BYT_PIN_MUX 0x07
/* BYT_VAL_REG register bits */
# define BYT_INPUT_EN BIT(2) /* 0: input enabled (active low)*/
# define BYT_OUTPUT_EN BIT(1) /* 0: output enabled (active low)*/
# define BYT_LEVEL BIT(0)
# define BYT_DIR_MASK (BIT(1) | BIT(2))
# define BYT_TRIG_MASK (BIT(26) | BIT(25) | BIT(24))
# define BYT_NGPIO_SCORE 102
# define BYT_NGPIO_NCORE 28
# define BYT_NGPIO_SUS 44
2014-03-06 17:59:49 +04:00
# define BYT_SCORE_ACPI_UID "1"
# define BYT_NCORE_ACPI_UID "2"
# define BYT_SUS_ACPI_UID "3"
2013-06-18 15:33:02 +04:00
/*
* Baytrail gpio controller consist of three separate sub - controllers called
* SCORE , NCORE and SUS . The sub - controllers are identified by their acpi UID .
*
* GPIO numbering is _not_ ordered meaning that gpio # 0 in ACPI namespace does
* _not_ correspond to the first gpio register at controller ' s gpio base .
* There is no logic or pattern in mapping gpio numbers to registers ( pads ) so
* each sub - controller needs to have its own mapping table
*/
/* score_pins[gpio_nr] = pad_nr */
static unsigned const score_pins [ BYT_NGPIO_SCORE ] = {
85 , 89 , 93 , 96 , 99 , 102 , 98 , 101 , 34 , 37 ,
36 , 38 , 39 , 35 , 40 , 84 , 62 , 61 , 64 , 59 ,
54 , 56 , 60 , 55 , 63 , 57 , 51 , 50 , 53 , 47 ,
52 , 49 , 48 , 43 , 46 , 41 , 45 , 42 , 58 , 44 ,
95 , 105 , 70 , 68 , 67 , 66 , 69 , 71 , 65 , 72 ,
86 , 90 , 88 , 92 , 103 , 77 , 79 , 83 , 78 , 81 ,
80 , 82 , 13 , 12 , 15 , 14 , 17 , 18 , 19 , 16 ,
2 , 1 , 0 , 4 , 6 , 7 , 9 , 8 , 33 , 32 ,
31 , 30 , 29 , 27 , 25 , 28 , 26 , 23 , 21 , 20 ,
24 , 22 , 5 , 3 , 10 , 11 , 106 , 87 , 91 , 104 ,
97 , 100 ,
} ;
static unsigned const ncore_pins [ BYT_NGPIO_NCORE ] = {
19 , 18 , 17 , 20 , 21 , 22 , 24 , 25 , 23 , 16 ,
14 , 15 , 12 , 26 , 27 , 1 , 4 , 8 , 11 , 0 ,
3 , 6 , 10 , 13 , 2 , 5 , 9 , 7 ,
} ;
static unsigned const sus_pins [ BYT_NGPIO_SUS ] = {
29 , 33 , 30 , 31 , 32 , 34 , 36 , 35 , 38 , 37 ,
18 , 7 , 11 , 20 , 17 , 1 , 8 , 10 , 19 , 12 ,
0 , 2 , 23 , 39 , 28 , 27 , 22 , 21 , 24 , 25 ,
26 , 51 , 56 , 54 , 49 , 55 , 48 , 57 , 50 , 58 ,
52 , 53 , 59 , 40 ,
} ;
static struct pinctrl_gpio_range byt_ranges [ ] = {
{
2014-03-06 17:59:49 +04:00
. name = BYT_SCORE_ACPI_UID , /* match with acpi _UID in probe */
2013-06-18 15:33:02 +04:00
. npins = BYT_NGPIO_SCORE ,
. pins = score_pins ,
} ,
{
2014-03-06 17:59:49 +04:00
. name = BYT_NCORE_ACPI_UID ,
2013-06-18 15:33:02 +04:00
. npins = BYT_NGPIO_NCORE ,
. pins = ncore_pins ,
} ,
{
2014-03-06 17:59:49 +04:00
. name = BYT_SUS_ACPI_UID ,
2013-06-18 15:33:02 +04:00
. npins = BYT_NGPIO_SUS ,
. pins = sus_pins ,
} ,
{
} ,
} ;
struct byt_gpio {
struct gpio_chip chip ;
struct platform_device * pdev ;
spinlock_t lock ;
void __iomem * reg_base ;
struct pinctrl_gpio_range * range ;
} ;
2013-07-10 15:55:39 +04:00
# define to_byt_gpio(c) container_of(c, struct byt_gpio, chip)
2013-06-18 15:33:02 +04:00
static void __iomem * byt_gpio_reg ( struct gpio_chip * chip , unsigned offset ,
int reg )
{
2013-07-10 15:55:39 +04:00
struct byt_gpio * vg = to_byt_gpio ( chip ) ;
2013-06-18 15:33:02 +04:00
u32 reg_offset ;
if ( reg = = BYT_INT_STAT_REG )
reg_offset = ( offset / 32 ) * 4 ;
else
reg_offset = vg - > range - > pins [ offset ] * 16 ;
2013-07-10 15:55:38 +04:00
return vg - > reg_base + reg_offset + reg ;
2013-06-18 15:33:02 +04:00
}
2015-02-23 15:53:11 +03:00
static void byt_gpio_clear_triggering ( struct byt_gpio * vg , unsigned offset )
{
void __iomem * reg = byt_gpio_reg ( & vg - > chip , offset , BYT_CONF0_REG ) ;
unsigned long flags ;
u32 value ;
spin_lock_irqsave ( & vg - > lock , flags ) ;
value = readl ( reg ) ;
value & = ~ ( BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL ) ;
writel ( value , reg ) ;
spin_unlock_irqrestore ( & vg - > lock , flags ) ;
}
2015-02-23 15:53:10 +03:00
static u32 byt_get_gpio_mux ( struct byt_gpio * vg , unsigned offset )
2014-03-06 17:59:49 +04:00
{
/* SCORE pin 92-93 */
if ( ! strcmp ( vg - > range - > name , BYT_SCORE_ACPI_UID ) & &
offset > = 92 & & offset < = 93 )
2015-02-23 15:53:10 +03:00
return 1 ;
2014-03-06 17:59:49 +04:00
/* SUS pin 11-21 */
if ( ! strcmp ( vg - > range - > name , BYT_SUS_ACPI_UID ) & &
offset > = 11 & & offset < = 21 )
2015-02-23 15:53:10 +03:00
return 1 ;
2014-03-06 17:59:49 +04:00
2015-02-23 15:53:10 +03:00
return 0 ;
2014-03-06 17:59:49 +04:00
}
2013-06-18 15:33:02 +04:00
static int byt_gpio_request ( struct gpio_chip * chip , unsigned offset )
{
2013-07-10 15:55:39 +04:00
struct byt_gpio * vg = to_byt_gpio ( chip ) ;
2014-03-06 17:59:49 +04:00
void __iomem * reg = byt_gpio_reg ( chip , offset , BYT_CONF0_REG ) ;
2015-02-23 15:53:10 +03:00
u32 value , gpio_mux ;
2014-03-06 17:59:49 +04:00
/*
* In most cases , func pin mux 000 means GPIO function .
* But , some pins may have func pin mux 001 represents
2015-02-23 15:53:10 +03:00
* GPIO function .
*
* Because there are devices out there where some pins were not
* configured correctly we allow changing the mux value from
* request ( but print out warning about that ) .
2014-03-06 17:59:49 +04:00
*/
value = readl ( reg ) & BYT_PIN_MUX ;
2015-02-23 15:53:10 +03:00
gpio_mux = byt_get_gpio_mux ( vg , offset ) ;
if ( WARN_ON ( gpio_mux ! = value ) ) {
unsigned long flags ;
spin_lock_irqsave ( & vg - > lock , flags ) ;
value = readl ( reg ) & ~ BYT_PIN_MUX ;
value | = gpio_mux ;
writel ( value , reg ) ;
spin_unlock_irqrestore ( & vg - > lock , flags ) ;
dev_warn ( & vg - > pdev - > dev ,
" pin %u forcibly re-configured as GPIO \n " , offset ) ;
2014-03-06 17:59:49 +04:00
}
2013-06-18 15:33:02 +04:00
pm_runtime_get ( & vg - > pdev - > dev ) ;
return 0 ;
}
static void byt_gpio_free ( struct gpio_chip * chip , unsigned offset )
{
2013-07-10 15:55:39 +04:00
struct byt_gpio * vg = to_byt_gpio ( chip ) ;
2013-06-18 15:33:02 +04:00
2015-02-23 15:53:11 +03:00
byt_gpio_clear_triggering ( vg , offset ) ;
2013-06-18 15:33:02 +04:00
pm_runtime_put ( & vg - > pdev - > dev ) ;
}
static int byt_irq_type ( struct irq_data * d , unsigned type )
{
2014-07-25 10:54:47 +04:00
struct byt_gpio * vg = to_byt_gpio ( irq_data_get_irq_chip_data ( d ) ) ;
2013-06-18 15:33:02 +04:00
u32 offset = irqd_to_hwirq ( d ) ;
u32 value ;
unsigned long flags ;
void __iomem * reg = byt_gpio_reg ( & vg - > chip , offset , BYT_CONF0_REG ) ;
if ( offset > = vg - > chip . ngpio )
return - EINVAL ;
spin_lock_irqsave ( & vg - > lock , flags ) ;
value = readl ( reg ) ;
2014-09-26 18:14:51 +04:00
WARN ( value & BYT_DIRECT_IRQ_EN ,
" Bad pad config for io mode, force direct_irq_en bit clearing " ) ;
2013-06-18 15:33:02 +04:00
/* For level trigges the BYT_TRIG_POS and BYT_TRIG_NEG bits
* are used to indicate high and low level triggering
*/
2014-09-26 18:14:51 +04:00
value & = ~ ( BYT_DIRECT_IRQ_EN | BYT_TRIG_POS | BYT_TRIG_NEG |
BYT_TRIG_LVL ) ;
2013-06-18 15:33:02 +04:00
switch ( type ) {
case IRQ_TYPE_LEVEL_HIGH :
value | = BYT_TRIG_LVL ;
case IRQ_TYPE_EDGE_RISING :
value | = BYT_TRIG_POS ;
break ;
case IRQ_TYPE_LEVEL_LOW :
value | = BYT_TRIG_LVL ;
case IRQ_TYPE_EDGE_FALLING :
value | = BYT_TRIG_NEG ;
break ;
case IRQ_TYPE_EDGE_BOTH :
value | = ( BYT_TRIG_NEG | BYT_TRIG_POS ) ;
break ;
}
writel ( value , reg ) ;
spin_unlock_irqrestore ( & vg - > lock , flags ) ;
return 0 ;
}
static int byt_gpio_get ( struct gpio_chip * chip , unsigned offset )
{
void __iomem * reg = byt_gpio_reg ( chip , offset , BYT_VAL_REG ) ;
return readl ( reg ) & BYT_LEVEL ;
}
static void byt_gpio_set ( struct gpio_chip * chip , unsigned offset , int value )
{
2013-07-10 15:55:39 +04:00
struct byt_gpio * vg = to_byt_gpio ( chip ) ;
2013-06-18 15:33:02 +04:00
void __iomem * reg = byt_gpio_reg ( chip , offset , BYT_VAL_REG ) ;
unsigned long flags ;
u32 old_val ;
spin_lock_irqsave ( & vg - > lock , flags ) ;
old_val = readl ( reg ) ;
if ( value )
writel ( old_val | BYT_LEVEL , reg ) ;
else
writel ( old_val & ~ BYT_LEVEL , reg ) ;
spin_unlock_irqrestore ( & vg - > lock , flags ) ;
}
static int byt_gpio_direction_input ( struct gpio_chip * chip , unsigned offset )
{
2013-07-10 15:55:39 +04:00
struct byt_gpio * vg = to_byt_gpio ( chip ) ;
2013-06-18 15:33:02 +04:00
void __iomem * reg = byt_gpio_reg ( chip , offset , BYT_VAL_REG ) ;
unsigned long flags ;
u32 value ;
spin_lock_irqsave ( & vg - > lock , flags ) ;
value = readl ( reg ) | BYT_DIR_MASK ;
2013-07-10 15:55:40 +04:00
value & = ~ BYT_INPUT_EN ; /* active low */
2013-06-18 15:33:02 +04:00
writel ( value , reg ) ;
spin_unlock_irqrestore ( & vg - > lock , flags ) ;
return 0 ;
}
static int byt_gpio_direction_output ( struct gpio_chip * chip ,
unsigned gpio , int value )
{
2013-07-10 15:55:39 +04:00
struct byt_gpio * vg = to_byt_gpio ( chip ) ;
2014-06-12 22:06:20 +04:00
void __iomem * conf_reg = byt_gpio_reg ( chip , gpio , BYT_CONF0_REG ) ;
2013-06-18 15:33:02 +04:00
void __iomem * reg = byt_gpio_reg ( chip , gpio , BYT_VAL_REG ) ;
unsigned long flags ;
u32 reg_val ;
spin_lock_irqsave ( & vg - > lock , flags ) ;
2014-06-12 22:06:20 +04:00
/*
* Before making any direction modifications , do a check if gpio
* is set for direct IRQ . On baytrail , setting GPIO to output does
* not make sense , so let ' s at least warn the caller before they shoot
* themselves in the foot .
*/
WARN ( readl ( conf_reg ) & BYT_DIRECT_IRQ_EN ,
" Potential Error: Setting GPIO with direct_irq_en to output " ) ;
2013-07-10 15:55:40 +04:00
reg_val = readl ( reg ) | BYT_DIR_MASK ;
2014-10-14 21:54:37 +04:00
reg_val & = ~ ( BYT_OUTPUT_EN | BYT_INPUT_EN ) ;
2013-07-10 15:55:40 +04:00
if ( value )
writel ( reg_val | BYT_LEVEL , reg ) ;
else
writel ( reg_val & ~ BYT_LEVEL , reg ) ;
2013-06-18 15:33:02 +04:00
spin_unlock_irqrestore ( & vg - > lock , flags ) ;
return 0 ;
}
static void byt_gpio_dbg_show ( struct seq_file * s , struct gpio_chip * chip )
{
2013-07-10 15:55:39 +04:00
struct byt_gpio * vg = to_byt_gpio ( chip ) ;
2013-06-18 15:33:02 +04:00
int i ;
unsigned long flags ;
u32 conf0 , val , offs ;
spin_lock_irqsave ( & vg - > lock , flags ) ;
for ( i = 0 ; i < vg - > chip . ngpio ; i + + ) {
2014-05-16 13:18:29 +04:00
const char * pull_str = NULL ;
const char * pull = NULL ;
2013-11-22 16:01:23 +04:00
const char * label ;
2013-06-18 15:33:02 +04:00
offs = vg - > range - > pins [ i ] * 16 ;
conf0 = readl ( vg - > reg_base + offs + BYT_CONF0_REG ) ;
val = readl ( vg - > reg_base + offs + BYT_VAL_REG ) ;
2013-11-22 16:01:23 +04:00
label = gpiochip_is_requested ( chip , i ) ;
if ( ! label )
label = " Unrequested " ;
2014-05-16 13:18:29 +04:00
switch ( conf0 & BYT_PULL_ASSIGN_MASK ) {
case BYT_PULL_ASSIGN_UP :
pull = " up " ;
break ;
case BYT_PULL_ASSIGN_DOWN :
pull = " down " ;
break ;
}
switch ( conf0 & BYT_PULL_STR_MASK ) {
case BYT_PULL_STR_2K :
pull_str = " 2k " ;
break ;
case BYT_PULL_STR_10K :
pull_str = " 10k " ;
break ;
case BYT_PULL_STR_20K :
pull_str = " 20k " ;
break ;
case BYT_PULL_STR_40K :
pull_str = " 40k " ;
break ;
}
2013-06-18 15:33:02 +04:00
seq_printf ( s ,
2014-05-16 13:18:29 +04:00
" gpio-%-3d (%-20.20s) %s %s %s pad-%-3d offset:0x%03x mux:%d %s%s%s " ,
2013-06-18 15:33:02 +04:00
i ,
2013-11-22 16:01:23 +04:00
label ,
2013-06-18 15:33:02 +04:00
val & BYT_INPUT_EN ? " " : " in " ,
val & BYT_OUTPUT_EN ? " " : " out " ,
val & BYT_LEVEL ? " hi " : " lo " ,
vg - > range - > pins [ i ] , offs ,
conf0 & 0x7 ,
2014-05-16 13:18:29 +04:00
conf0 & BYT_TRIG_NEG ? " fall " : " " ,
conf0 & BYT_TRIG_POS ? " rise " : " " ,
conf0 & BYT_TRIG_LVL ? " level " : " " ) ;
if ( pull & & pull_str )
seq_printf ( s , " %-4s %-3s " , pull , pull_str ) ;
else
seq_puts ( s , " " ) ;
if ( conf0 & BYT_IODEN )
seq_puts ( s , " open-drain " ) ;
seq_puts ( s , " \n " ) ;
2013-06-18 15:33:02 +04:00
}
spin_unlock_irqrestore ( & vg - > lock , flags ) ;
}
static void byt_gpio_irq_handler ( unsigned irq , struct irq_desc * desc )
{
struct irq_data * data = irq_desc_get_irq_data ( desc ) ;
2014-07-25 10:54:47 +04:00
struct byt_gpio * vg = to_byt_gpio ( irq_desc_get_handler_data ( desc ) ) ;
2013-06-18 15:33:02 +04:00
struct irq_chip * chip = irq_data_get_irq_chip ( data ) ;
u32 base , pin , mask ;
void __iomem * reg ;
u32 pending ;
unsigned virq ;
int looplimit = 0 ;
/* check from GPIO controller which pin triggered the interrupt */
for ( base = 0 ; base < vg - > chip . ngpio ; base + = 32 ) {
reg = byt_gpio_reg ( & vg - > chip , base , BYT_INT_STAT_REG ) ;
while ( ( pending = readl ( reg ) ) ) {
pin = __ffs ( pending ) ;
mask = BIT ( pin ) ;
/* Clear before handling so we can't lose an edge */
writel ( mask , reg ) ;
2014-07-25 10:54:47 +04:00
virq = irq_find_mapping ( vg - > chip . irqdomain , base + pin ) ;
2013-06-18 15:33:02 +04:00
generic_handle_irq ( virq ) ;
/* In case bios or user sets triggering incorretly a pin
* might remain in " interrupt triggered " state .
*/
if ( looplimit + + > 32 ) {
dev_err ( & vg - > pdev - > dev ,
" Gpio %d interrupt flood, disabling \n " ,
base + pin ) ;
reg = byt_gpio_reg ( & vg - > chip , base + pin ,
BYT_CONF0_REG ) ;
mask = readl ( reg ) ;
mask & = ~ ( BYT_TRIG_NEG | BYT_TRIG_POS |
BYT_TRIG_LVL ) ;
writel ( mask , reg ) ;
mask = readl ( reg ) ; /* flush */
break ;
}
}
}
chip - > irq_eoi ( data ) ;
}
static void byt_irq_unmask ( struct irq_data * d )
{
}
static void byt_irq_mask ( struct irq_data * d )
{
}
static struct irq_chip byt_irqchip = {
. name = " BYT-GPIO " ,
. irq_mask = byt_irq_mask ,
. irq_unmask = byt_irq_unmask ,
. irq_set_type = byt_irq_type ,
2014-08-11 17:51:55 +04:00
. flags = IRQCHIP_SKIP_SET_WAKE ,
2013-06-18 15:33:02 +04:00
} ;
static void byt_gpio_irq_init_hw ( struct byt_gpio * vg )
{
void __iomem * reg ;
u32 base , value ;
2015-02-23 15:53:11 +03:00
int i ;
/*
* Clear interrupt triggers for all pins that are GPIOs and
* do not use direct IRQ mode . This will prevent spurious
* interrupts from misconfigured pins .
*/
for ( i = 0 ; i < vg - > chip . ngpio ; i + + ) {
value = readl ( byt_gpio_reg ( & vg - > chip , i , BYT_CONF0_REG ) ) ;
if ( ( value & BYT_PIN_MUX ) = = byt_get_gpio_mux ( vg , i ) & &
! ( value & BYT_DIRECT_IRQ_EN ) ) {
byt_gpio_clear_triggering ( vg , i ) ;
dev_dbg ( & vg - > pdev - > dev , " disabling GPIO %d \n " , i ) ;
}
}
2013-06-18 15:33:02 +04:00
/* clear interrupt status trigger registers */
for ( base = 0 ; base < vg - > chip . ngpio ; base + = 32 ) {
reg = byt_gpio_reg ( & vg - > chip , base , BYT_INT_STAT_REG ) ;
writel ( 0xffffffff , reg ) ;
/* make sure trigger bits are cleared, if not then a pin
might be misconfigured in bios */
value = readl ( reg ) ;
if ( value )
dev_err ( & vg - > pdev - > dev ,
" GPIO interrupt error, pins misconfigured \n " ) ;
}
}
static int byt_gpio_probe ( struct platform_device * pdev )
{
struct byt_gpio * vg ;
struct gpio_chip * gc ;
struct resource * mem_rc , * irq_rc ;
struct device * dev = & pdev - > dev ;
struct acpi_device * acpi_dev ;
struct pinctrl_gpio_range * range ;
acpi_handle handle = ACPI_HANDLE ( dev ) ;
int ret ;
if ( acpi_bus_get_device ( handle , & acpi_dev ) )
return - ENODEV ;
vg = devm_kzalloc ( dev , sizeof ( struct byt_gpio ) , GFP_KERNEL ) ;
if ( ! vg ) {
dev_err ( & pdev - > dev , " can't allocate byt_gpio chip data \n " ) ;
return - ENOMEM ;
}
for ( range = byt_ranges ; range - > name ; range + + ) {
if ( ! strcmp ( acpi_dev - > pnp . unique_id , range - > name ) ) {
vg - > chip . ngpio = range - > npins ;
vg - > range = range ;
break ;
}
}
if ( ! vg - > chip . ngpio | | ! vg - > range )
return - ENODEV ;
vg - > pdev = pdev ;
platform_set_drvdata ( pdev , vg ) ;
mem_rc = platform_get_resource ( pdev , IORESOURCE_MEM , 0 ) ;
vg - > reg_base = devm_ioremap_resource ( dev , mem_rc ) ;
if ( IS_ERR ( vg - > reg_base ) )
return PTR_ERR ( vg - > reg_base ) ;
spin_lock_init ( & vg - > lock ) ;
gc = & vg - > chip ;
gc - > label = dev_name ( & pdev - > dev ) ;
gc - > owner = THIS_MODULE ;
gc - > request = byt_gpio_request ;
gc - > free = byt_gpio_free ;
gc - > direction_input = byt_gpio_direction_input ;
gc - > direction_output = byt_gpio_direction_output ;
gc - > get = byt_gpio_get ;
gc - > set = byt_gpio_set ;
gc - > dbg_show = byt_gpio_dbg_show ;
gc - > base = - 1 ;
2013-12-04 17:42:46 +04:00
gc - > can_sleep = false ;
2013-06-18 15:33:02 +04:00
gc - > dev = dev ;
2014-07-25 10:54:47 +04:00
ret = gpiochip_add ( gc ) ;
if ( ret ) {
dev_err ( & pdev - > dev , " failed adding byt-gpio chip \n " ) ;
return ret ;
}
2013-06-18 15:33:02 +04:00
/* set up interrupts */
irq_rc = platform_get_resource ( pdev , IORESOURCE_IRQ , 0 ) ;
if ( irq_rc & & irq_rc - > start ) {
byt_gpio_irq_init_hw ( vg ) ;
2014-07-25 10:54:47 +04:00
ret = gpiochip_irqchip_add ( gc , & byt_irqchip , 0 ,
handle_simple_irq , IRQ_TYPE_NONE ) ;
if ( ret ) {
dev_err ( dev , " failed to add irqchip \n " ) ;
gpiochip_remove ( gc ) ;
return ret ;
}
2013-06-18 15:33:02 +04:00
2014-07-25 10:54:47 +04:00
gpiochip_set_chained_irqchip ( gc , & byt_irqchip ,
( unsigned ) irq_rc - > start ,
byt_gpio_irq_handler ) ;
2014-05-15 19:28:47 +04:00
}
2013-06-18 15:33:02 +04:00
pm_runtime_enable ( dev ) ;
return 0 ;
}
static int byt_gpio_runtime_suspend ( struct device * dev )
{
return 0 ;
}
static int byt_gpio_runtime_resume ( struct device * dev )
{
return 0 ;
}
static const struct dev_pm_ops byt_gpio_pm_ops = {
. runtime_suspend = byt_gpio_runtime_suspend ,
. runtime_resume = byt_gpio_runtime_resume ,
} ;
static const struct acpi_device_id byt_gpio_acpi_match [ ] = {
{ " INT33B2 " , 0 } ,
2014-05-15 19:28:46 +04:00
{ " INT33FC " , 0 } ,
2013-06-18 15:33:02 +04:00
{ }
} ;
MODULE_DEVICE_TABLE ( acpi , byt_gpio_acpi_match ) ;
static int byt_gpio_remove ( struct platform_device * pdev )
{
struct byt_gpio * vg = platform_get_drvdata ( pdev ) ;
2013-07-10 15:55:36 +04:00
2013-06-18 15:33:02 +04:00
pm_runtime_disable ( & pdev - > dev ) ;
2014-07-13 00:30:13 +04:00
gpiochip_remove ( & vg - > chip ) ;
2013-06-18 15:33:02 +04:00
return 0 ;
}
static struct platform_driver byt_gpio_driver = {
. probe = byt_gpio_probe ,
. remove = byt_gpio_remove ,
. driver = {
. name = " byt_gpio " ,
. pm = & byt_gpio_pm_ops ,
. acpi_match_table = ACPI_PTR ( byt_gpio_acpi_match ) ,
} ,
} ;
static int __init byt_gpio_init ( void )
{
return platform_driver_register ( & byt_gpio_driver ) ;
}
subsys_initcall ( byt_gpio_init ) ;
2014-10-14 00:50:08 +04:00
static void __exit byt_gpio_exit ( void )
{
platform_driver_unregister ( & byt_gpio_driver ) ;
}
module_exit ( byt_gpio_exit ) ;