2012-10-04 07:15:05 +04:00
/*
* DA9052 interrupt support
*
* Author : Fabio Estevam < fabio . estevam @ freescale . com >
* Based on arizona - irq . c , which is :
*
* Copyright 2012 Wolfson Microelectronics plc
*
* Author : Mark Brown < broonie @ opensource . wolfsonmicro . com >
*
* 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/device.h>
# include <linux/delay.h>
# include <linux/input.h>
# include <linux/interrupt.h>
# include <linux/irq.h>
# include <linux/irqdomain.h>
# include <linux/slab.h>
# include <linux/module.h>
# include <linux/mfd/da9052/da9052.h>
# include <linux/mfd/da9052/reg.h>
# define DA9052_NUM_IRQ_REGS 4
# define DA9052_IRQ_MASK_POS_1 0x01
# define DA9052_IRQ_MASK_POS_2 0x02
# define DA9052_IRQ_MASK_POS_3 0x04
# define DA9052_IRQ_MASK_POS_4 0x08
# define DA9052_IRQ_MASK_POS_5 0x10
# define DA9052_IRQ_MASK_POS_6 0x20
# define DA9052_IRQ_MASK_POS_7 0x40
# define DA9052_IRQ_MASK_POS_8 0x80
2015-04-27 15:54:13 +03:00
static const struct regmap_irq da9052_irqs [ ] = {
2012-10-04 07:15:05 +04:00
[ DA9052_IRQ_DCIN ] = {
. reg_offset = 0 ,
. mask = DA9052_IRQ_MASK_POS_1 ,
} ,
[ DA9052_IRQ_VBUS ] = {
. reg_offset = 0 ,
. mask = DA9052_IRQ_MASK_POS_2 ,
} ,
[ DA9052_IRQ_DCINREM ] = {
. reg_offset = 0 ,
. mask = DA9052_IRQ_MASK_POS_3 ,
} ,
[ DA9052_IRQ_VBUSREM ] = {
. reg_offset = 0 ,
. mask = DA9052_IRQ_MASK_POS_4 ,
} ,
[ DA9052_IRQ_VDDLOW ] = {
. reg_offset = 0 ,
. mask = DA9052_IRQ_MASK_POS_5 ,
} ,
[ DA9052_IRQ_ALARM ] = {
. reg_offset = 0 ,
. mask = DA9052_IRQ_MASK_POS_6 ,
} ,
[ DA9052_IRQ_SEQRDY ] = {
. reg_offset = 0 ,
. mask = DA9052_IRQ_MASK_POS_7 ,
} ,
[ DA9052_IRQ_COMP1V2 ] = {
. reg_offset = 0 ,
. mask = DA9052_IRQ_MASK_POS_8 ,
} ,
[ DA9052_IRQ_NONKEY ] = {
. reg_offset = 1 ,
. mask = DA9052_IRQ_MASK_POS_1 ,
} ,
[ DA9052_IRQ_IDFLOAT ] = {
. reg_offset = 1 ,
. mask = DA9052_IRQ_MASK_POS_2 ,
} ,
[ DA9052_IRQ_IDGND ] = {
. reg_offset = 1 ,
. mask = DA9052_IRQ_MASK_POS_3 ,
} ,
[ DA9052_IRQ_CHGEND ] = {
. reg_offset = 1 ,
. mask = DA9052_IRQ_MASK_POS_4 ,
} ,
[ DA9052_IRQ_TBAT ] = {
. reg_offset = 1 ,
. mask = DA9052_IRQ_MASK_POS_5 ,
} ,
[ DA9052_IRQ_ADC_EOM ] = {
. reg_offset = 1 ,
. mask = DA9052_IRQ_MASK_POS_6 ,
} ,
[ DA9052_IRQ_PENDOWN ] = {
. reg_offset = 1 ,
. mask = DA9052_IRQ_MASK_POS_7 ,
} ,
[ DA9052_IRQ_TSIREADY ] = {
. reg_offset = 1 ,
. mask = DA9052_IRQ_MASK_POS_8 ,
} ,
[ DA9052_IRQ_GPI0 ] = {
. reg_offset = 2 ,
. mask = DA9052_IRQ_MASK_POS_1 ,
} ,
[ DA9052_IRQ_GPI1 ] = {
. reg_offset = 2 ,
. mask = DA9052_IRQ_MASK_POS_2 ,
} ,
[ DA9052_IRQ_GPI2 ] = {
. reg_offset = 2 ,
. mask = DA9052_IRQ_MASK_POS_3 ,
} ,
[ DA9052_IRQ_GPI3 ] = {
. reg_offset = 2 ,
. mask = DA9052_IRQ_MASK_POS_4 ,
} ,
[ DA9052_IRQ_GPI4 ] = {
. reg_offset = 2 ,
. mask = DA9052_IRQ_MASK_POS_5 ,
} ,
[ DA9052_IRQ_GPI5 ] = {
. reg_offset = 2 ,
. mask = DA9052_IRQ_MASK_POS_6 ,
} ,
[ DA9052_IRQ_GPI6 ] = {
. reg_offset = 2 ,
. mask = DA9052_IRQ_MASK_POS_7 ,
} ,
[ DA9052_IRQ_GPI7 ] = {
. reg_offset = 2 ,
. mask = DA9052_IRQ_MASK_POS_8 ,
} ,
[ DA9052_IRQ_GPI8 ] = {
. reg_offset = 3 ,
. mask = DA9052_IRQ_MASK_POS_1 ,
} ,
[ DA9052_IRQ_GPI9 ] = {
. reg_offset = 3 ,
. mask = DA9052_IRQ_MASK_POS_2 ,
} ,
[ DA9052_IRQ_GPI10 ] = {
. reg_offset = 3 ,
. mask = DA9052_IRQ_MASK_POS_3 ,
} ,
[ DA9052_IRQ_GPI11 ] = {
. reg_offset = 3 ,
. mask = DA9052_IRQ_MASK_POS_4 ,
} ,
[ DA9052_IRQ_GPI12 ] = {
. reg_offset = 3 ,
. mask = DA9052_IRQ_MASK_POS_5 ,
} ,
[ DA9052_IRQ_GPI13 ] = {
. reg_offset = 3 ,
. mask = DA9052_IRQ_MASK_POS_6 ,
} ,
[ DA9052_IRQ_GPI14 ] = {
. reg_offset = 3 ,
. mask = DA9052_IRQ_MASK_POS_7 ,
} ,
[ DA9052_IRQ_GPI15 ] = {
. reg_offset = 3 ,
. mask = DA9052_IRQ_MASK_POS_8 ,
} ,
} ;
2015-04-27 15:54:13 +03:00
static const struct regmap_irq_chip da9052_regmap_irq_chip = {
2012-10-04 07:15:05 +04:00
. name = " da9052_irq " ,
. status_base = DA9052_EVENT_A_REG ,
. mask_base = DA9052_IRQ_MASK_A_REG ,
. ack_base = DA9052_EVENT_A_REG ,
. num_regs = DA9052_NUM_IRQ_REGS ,
. irqs = da9052_irqs ,
. num_irqs = ARRAY_SIZE ( da9052_irqs ) ,
} ;
static int da9052_map_irq ( struct da9052 * da9052 , int irq )
{
return regmap_irq_get_virq ( da9052 - > irq_data , irq ) ;
}
int da9052_enable_irq ( struct da9052 * da9052 , int irq )
{
irq = da9052_map_irq ( da9052 , irq ) ;
if ( irq < 0 )
return irq ;
enable_irq ( irq ) ;
return 0 ;
}
EXPORT_SYMBOL_GPL ( da9052_enable_irq ) ;
int da9052_disable_irq ( struct da9052 * da9052 , int irq )
{
irq = da9052_map_irq ( da9052 , irq ) ;
if ( irq < 0 )
return irq ;
disable_irq ( irq ) ;
return 0 ;
}
EXPORT_SYMBOL_GPL ( da9052_disable_irq ) ;
int da9052_disable_irq_nosync ( struct da9052 * da9052 , int irq )
{
irq = da9052_map_irq ( da9052 , irq ) ;
if ( irq < 0 )
return irq ;
disable_irq_nosync ( irq ) ;
return 0 ;
}
EXPORT_SYMBOL_GPL ( da9052_disable_irq_nosync ) ;
int da9052_request_irq ( struct da9052 * da9052 , int irq , char * name ,
irq_handler_t handler , void * data )
{
irq = da9052_map_irq ( da9052 , irq ) ;
if ( irq < 0 )
return irq ;
return request_threaded_irq ( irq , NULL , handler ,
IRQF_TRIGGER_LOW | IRQF_ONESHOT ,
name , data ) ;
}
EXPORT_SYMBOL_GPL ( da9052_request_irq ) ;
void da9052_free_irq ( struct da9052 * da9052 , int irq , void * data )
{
irq = da9052_map_irq ( da9052 , irq ) ;
if ( irq < 0 )
return ;
free_irq ( irq , data ) ;
}
EXPORT_SYMBOL_GPL ( da9052_free_irq ) ;
static irqreturn_t da9052_auxadc_irq ( int irq , void * irq_data )
{
struct da9052 * da9052 = irq_data ;
complete ( & da9052 - > done ) ;
return IRQ_HANDLED ;
}
int da9052_irq_init ( struct da9052 * da9052 )
{
int ret ;
ret = regmap_add_irq_chip ( da9052 - > regmap , da9052 - > chip_irq ,
IRQF_TRIGGER_LOW | IRQF_ONESHOT ,
- 1 , & da9052_regmap_irq_chip ,
& da9052 - > irq_data ) ;
if ( ret < 0 ) {
dev_err ( da9052 - > dev , " regmap_add_irq_chip failed: %d \n " , ret ) ;
goto regmap_err ;
}
2015-03-04 19:13:12 +03:00
enable_irq_wake ( da9052 - > chip_irq ) ;
2012-10-04 07:15:05 +04:00
ret = da9052_request_irq ( da9052 , DA9052_IRQ_ADC_EOM , " adc-irq " ,
da9052_auxadc_irq , da9052 ) ;
if ( ret ! = 0 ) {
dev_err ( da9052 - > dev , " DA9052_IRQ_ADC_EOM failed: %d \n " , ret ) ;
goto request_irq_err ;
}
return 0 ;
request_irq_err :
regmap_del_irq_chip ( da9052 - > chip_irq , da9052 - > irq_data ) ;
regmap_err :
return ret ;
}
int da9052_irq_exit ( struct da9052 * da9052 )
{
2015-10-28 19:53:04 +03:00
da9052_free_irq ( da9052 , DA9052_IRQ_ADC_EOM , da9052 ) ;
2012-10-04 07:15:05 +04:00
regmap_del_irq_chip ( da9052 - > chip_irq , da9052 - > irq_data ) ;
return 0 ;
}