2019-06-04 11:11:33 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2010-09-28 18:37:20 +04:00
/*
* Copyright 2009 - 2010 Pengutronix
* Uwe Kleine - Koenig < u . kleine - koenig @ pengutronix . de >
*
* loosely based on an earlier driver that has
* Copyright 2009 Pengutronix , Sascha Hauer < s . hauer @ pengutronix . de >
*/
# include <linux/module.h>
2011-12-12 21:52:57 +04:00
# include <linux/of.h>
# include <linux/of_device.h>
2014-06-18 21:05:40 +04:00
# include <linux/platform_device.h>
# include <linux/mfd/core.h>
2010-09-28 18:37:20 +04:00
2012-04-01 10:41:38 +04:00
# include "mc13xxx.h"
2010-09-28 18:37:20 +04:00
# define MC13XXX_IRQSTAT0 0
# define MC13XXX_IRQMASK0 1
# define MC13XXX_IRQSTAT1 3
# define MC13XXX_IRQMASK1 4
# define MC13XXX_REVISION 7
# define MC13XXX_REVISION_REVMETAL (0x07 << 0)
# define MC13XXX_REVISION_REVFULL (0x03 << 3)
# define MC13XXX_REVISION_ICID (0x07 << 6)
# define MC13XXX_REVISION_FIN (0x03 << 9)
# define MC13XXX_REVISION_FAB (0x03 << 11)
# define MC13XXX_REVISION_ICIDCODE (0x3f << 13)
2012-07-12 13:57:53 +04:00
# define MC34708_REVISION_REVMETAL (0x07 << 0)
# define MC34708_REVISION_REVFULL (0x07 << 3)
# define MC34708_REVISION_FIN (0x07 << 6)
# define MC34708_REVISION_FAB (0x07 << 9)
2014-09-08 11:01:11 +04:00
# define MC13XXX_PWRCTRL 15
# define MC13XXX_PWRCTRL_WDIRESET (1 << 12)
2011-08-24 17:28:21 +04:00
# define MC13XXX_ADC1 44
# define MC13XXX_ADC1_ADEN (1 << 0)
# define MC13XXX_ADC1_RAND (1 << 1)
# define MC13XXX_ADC1_ADSEL (1 << 3)
# define MC13XXX_ADC1_ASC (1 << 20)
# define MC13XXX_ADC1_ADTRIGIGN (1 << 21)
2010-09-28 18:37:20 +04:00
2011-08-24 17:28:21 +04:00
# define MC13XXX_ADC2 45
2010-09-28 18:37:20 +04:00
void mc13xxx_lock ( struct mc13xxx * mc13xxx )
{
if ( ! mutex_trylock ( & mc13xxx - > lock ) ) {
2015-03-12 06:13:51 +03:00
dev_dbg ( mc13xxx - > dev , " wait for %s from %ps \n " ,
2010-09-28 18:37:20 +04:00
__func__ , __builtin_return_address ( 0 ) ) ;
mutex_lock ( & mc13xxx - > lock ) ;
}
2015-03-12 06:13:51 +03:00
dev_dbg ( mc13xxx - > dev , " %s from %ps \n " ,
2010-09-28 18:37:20 +04:00
__func__ , __builtin_return_address ( 0 ) ) ;
}
EXPORT_SYMBOL ( mc13xxx_lock ) ;
void mc13xxx_unlock ( struct mc13xxx * mc13xxx )
{
2015-03-12 06:13:51 +03:00
dev_dbg ( mc13xxx - > dev , " %s from %ps \n " ,
2010-09-28 18:37:20 +04:00
__func__ , __builtin_return_address ( 0 ) ) ;
mutex_unlock ( & mc13xxx - > lock ) ;
}
EXPORT_SYMBOL ( mc13xxx_unlock ) ;
int mc13xxx_reg_read ( struct mc13xxx * mc13xxx , unsigned int offset , u32 * val )
{
int ret ;
2012-04-01 10:41:37 +04:00
ret = regmap_read ( mc13xxx - > regmap , offset , val ) ;
2012-05-01 14:26:46 +04:00
dev_vdbg ( mc13xxx - > dev , " [0x%02x] -> 0x%06x \n " , offset , * val ) ;
2010-09-28 18:37:20 +04:00
2012-05-01 14:26:46 +04:00
return ret ;
2010-09-28 18:37:20 +04:00
}
EXPORT_SYMBOL ( mc13xxx_reg_read ) ;
int mc13xxx_reg_write ( struct mc13xxx * mc13xxx , unsigned int offset , u32 val )
{
2012-05-01 14:26:46 +04:00
dev_vdbg ( mc13xxx - > dev , " [0x%02x] <- 0x%06x \n " , offset , val ) ;
2010-09-28 18:37:20 +04:00
2013-12-07 13:00:43 +04:00
if ( val > = BIT ( 24 ) )
2010-09-28 18:37:20 +04:00
return - EINVAL ;
2012-04-01 10:41:37 +04:00
return regmap_write ( mc13xxx - > regmap , offset , val ) ;
2010-09-28 18:37:20 +04:00
}
EXPORT_SYMBOL ( mc13xxx_reg_write ) ;
int mc13xxx_reg_rmw ( struct mc13xxx * mc13xxx , unsigned int offset ,
u32 mask , u32 val )
{
BUG_ON ( val & ~ mask ) ;
2012-04-01 10:41:37 +04:00
dev_vdbg ( mc13xxx - > dev , " [0x%02x] <- 0x%06x (mask: 0x%06x) \n " ,
offset , val , mask ) ;
2010-09-28 18:37:20 +04:00
2012-04-01 10:41:37 +04:00
return regmap_update_bits ( mc13xxx - > regmap , offset , mask , val ) ;
2010-09-28 18:37:20 +04:00
}
EXPORT_SYMBOL ( mc13xxx_reg_rmw ) ;
int mc13xxx_irq_mask ( struct mc13xxx * mc13xxx , int irq )
{
2014-06-18 21:05:40 +04:00
int virq = regmap_irq_get_virq ( mc13xxx - > irq_data , irq ) ;
2010-09-28 18:37:20 +04:00
2014-06-18 21:05:40 +04:00
disable_irq_nosync ( virq ) ;
2010-09-28 18:37:20 +04:00
2014-06-18 21:05:40 +04:00
return 0 ;
2010-09-28 18:37:20 +04:00
}
EXPORT_SYMBOL ( mc13xxx_irq_mask ) ;
int mc13xxx_irq_unmask ( struct mc13xxx * mc13xxx , int irq )
{
2014-06-18 21:05:40 +04:00
int virq = regmap_irq_get_virq ( mc13xxx - > irq_data , irq ) ;
2010-09-28 18:37:20 +04:00
2014-06-18 21:05:40 +04:00
enable_irq ( virq ) ;
2010-09-28 18:37:20 +04:00
2014-06-18 21:05:40 +04:00
return 0 ;
2010-09-28 18:37:20 +04:00
}
EXPORT_SYMBOL ( mc13xxx_irq_unmask ) ;
int mc13xxx_irq_status ( struct mc13xxx * mc13xxx , int irq ,
int * enabled , int * pending )
{
int ret ;
unsigned int offmask = irq < 24 ? MC13XXX_IRQMASK0 : MC13XXX_IRQMASK1 ;
unsigned int offstat = irq < 24 ? MC13XXX_IRQSTAT0 : MC13XXX_IRQSTAT1 ;
u32 irqbit = 1 < < ( irq < 24 ? irq : irq - 24 ) ;
2014-06-18 21:05:40 +04:00
if ( irq < 0 | | irq > = ARRAY_SIZE ( mc13xxx - > irqs ) )
2010-09-28 18:37:20 +04:00
return - EINVAL ;
if ( enabled ) {
u32 mask ;
ret = mc13xxx_reg_read ( mc13xxx , offmask , & mask ) ;
if ( ret )
return ret ;
* enabled = mask & irqbit ;
}
if ( pending ) {
u32 stat ;
ret = mc13xxx_reg_read ( mc13xxx , offstat , & stat ) ;
if ( ret )
return ret ;
* pending = stat & irqbit ;
}
return 0 ;
}
EXPORT_SYMBOL ( mc13xxx_irq_status ) ;
int mc13xxx_irq_request ( struct mc13xxx * mc13xxx , int irq ,
irq_handler_t handler , const char * name , void * dev )
{
2014-06-18 21:05:40 +04:00
int virq = regmap_irq_get_virq ( mc13xxx - > irq_data , irq ) ;
2010-09-28 18:37:20 +04:00
2014-06-18 21:05:40 +04:00
return devm_request_threaded_irq ( mc13xxx - > dev , virq , NULL , handler ,
2015-05-16 21:42:11 +03:00
IRQF_ONESHOT , name , dev ) ;
2010-09-28 18:37:20 +04:00
}
EXPORT_SYMBOL ( mc13xxx_irq_request ) ;
int mc13xxx_irq_free ( struct mc13xxx * mc13xxx , int irq , void * dev )
{
2014-06-18 21:05:40 +04:00
int virq = regmap_irq_get_virq ( mc13xxx - > irq_data , irq ) ;
2010-09-28 18:37:20 +04:00
2014-06-18 21:05:40 +04:00
devm_free_irq ( mc13xxx - > dev , virq , dev ) ;
2010-09-28 18:37:20 +04:00
return 0 ;
}
EXPORT_SYMBOL ( mc13xxx_irq_free ) ;
# define maskval(reg, mask) (((reg) & (mask)) >> __ffs(mask))
2012-07-12 13:57:52 +04:00
static void mc13xxx_print_revision ( struct mc13xxx * mc13xxx , u32 revision )
2010-09-28 18:37:20 +04:00
{
2012-07-12 13:57:52 +04:00
dev_info ( mc13xxx - > dev , " %s: rev: %d.%d, "
" fin: %d, fab: %d, icid: %d/%d \n " ,
mc13xxx - > variant - > name ,
maskval ( revision , MC13XXX_REVISION_REVFULL ) ,
maskval ( revision , MC13XXX_REVISION_REVMETAL ) ,
maskval ( revision , MC13XXX_REVISION_FIN ) ,
maskval ( revision , MC13XXX_REVISION_FAB ) ,
maskval ( revision , MC13XXX_REVISION_ICID ) ,
maskval ( revision , MC13XXX_REVISION_ICIDCODE ) ) ;
}
2010-09-28 18:37:20 +04:00
2012-07-12 13:57:53 +04:00
static void mc34708_print_revision ( struct mc13xxx * mc13xxx , u32 revision )
{
dev_info ( mc13xxx - > dev , " %s: rev %d.%d, fin: %d, fab: %d \n " ,
mc13xxx - > variant - > name ,
maskval ( revision , MC34708_REVISION_REVFULL ) ,
maskval ( revision , MC34708_REVISION_REVMETAL ) ,
maskval ( revision , MC34708_REVISION_FIN ) ,
maskval ( revision , MC34708_REVISION_FAB ) ) ;
}
2012-07-12 13:57:52 +04:00
/* These are only exported for mc13xxx-i2c and mc13xxx-spi */
struct mc13xxx_variant mc13xxx_variant_mc13783 = {
. name = " mc13783 " ,
. print_revision = mc13xxx_print_revision ,
} ;
EXPORT_SYMBOL_GPL ( mc13xxx_variant_mc13783 ) ;
2010-09-28 18:37:20 +04:00
2012-07-12 13:57:52 +04:00
struct mc13xxx_variant mc13xxx_variant_mc13892 = {
. name = " mc13892 " ,
. print_revision = mc13xxx_print_revision ,
} ;
EXPORT_SYMBOL_GPL ( mc13xxx_variant_mc13892 ) ;
2010-09-28 18:37:20 +04:00
2012-07-12 13:57:53 +04:00
struct mc13xxx_variant mc13xxx_variant_mc34708 = {
. name = " mc34708 " ,
. print_revision = mc34708_print_revision ,
} ;
EXPORT_SYMBOL_GPL ( mc13xxx_variant_mc34708 ) ;
2010-09-28 18:37:20 +04:00
static const char * mc13xxx_get_chipname ( struct mc13xxx * mc13xxx )
{
2012-07-12 13:57:52 +04:00
return mc13xxx - > variant - > name ;
2010-09-28 18:37:20 +04:00
}
int mc13xxx_get_flags ( struct mc13xxx * mc13xxx )
{
2011-12-12 21:52:57 +04:00
return mc13xxx - > flags ;
2010-09-28 18:37:20 +04:00
}
EXPORT_SYMBOL ( mc13xxx_get_flags ) ;
2011-08-24 17:28:21 +04:00
# define MC13XXX_ADC1_CHAN0_SHIFT 5
# define MC13XXX_ADC1_CHAN1_SHIFT 8
2012-02-20 15:18:13 +04:00
# define MC13783_ADC1_ATO_SHIFT 11
# define MC13783_ADC1_ATOX (1 << 19)
2010-09-28 18:37:20 +04:00
struct mc13xxx_adcdone_data {
struct mc13xxx * mc13xxx ;
struct completion done ;
} ;
2011-08-24 17:28:21 +04:00
static irqreturn_t mc13xxx_handler_adcdone ( int irq , void * data )
2010-09-28 18:37:20 +04:00
{
struct mc13xxx_adcdone_data * adcdone_data = data ;
complete_all ( & adcdone_data - > done ) ;
return IRQ_HANDLED ;
}
2011-08-24 17:28:21 +04:00
# define MC13XXX_ADC_WORKING (1 << 0)
2010-09-28 18:37:20 +04:00
2011-08-24 17:28:21 +04:00
int mc13xxx_adc_do_conversion ( struct mc13xxx * mc13xxx , unsigned int mode ,
2012-02-20 15:18:13 +04:00
unsigned int channel , u8 ato , bool atox ,
unsigned int * sample )
2010-09-28 18:37:20 +04:00
{
u32 adc0 , adc1 , old_adc0 ;
int i , ret ;
struct mc13xxx_adcdone_data adcdone_data = {
. mc13xxx = mc13xxx ,
} ;
init_completion ( & adcdone_data . done ) ;
2012-05-01 14:26:46 +04:00
dev_dbg ( mc13xxx - > dev , " %s \n " , __func__ ) ;
2010-09-28 18:37:20 +04:00
mc13xxx_lock ( mc13xxx ) ;
2011-08-24 17:28:21 +04:00
if ( mc13xxx - > adcflags & MC13XXX_ADC_WORKING ) {
2010-09-28 18:37:20 +04:00
ret = - EBUSY ;
goto out ;
}
2011-08-24 17:28:21 +04:00
mc13xxx - > adcflags | = MC13XXX_ADC_WORKING ;
2010-09-28 18:37:20 +04:00
2018-12-21 00:12:11 +03:00
ret = mc13xxx_reg_read ( mc13xxx , MC13XXX_ADC0 , & old_adc0 ) ;
if ( ret )
goto out ;
2010-09-28 18:37:20 +04:00
2018-08-28 23:02:40 +03:00
adc0 = MC13XXX_ADC0_ADINC1 | MC13XXX_ADC0_ADINC2 |
MC13XXX_ADC0_CHRGRAWDIV ;
2011-08-24 17:28:21 +04:00
adc1 = MC13XXX_ADC1_ADEN | MC13XXX_ADC1_ADTRIGIGN | MC13XXX_ADC1_ASC ;
2010-09-28 18:37:20 +04:00
2018-03-27 17:19:49 +03:00
/*
* Channels mapped through ADIN7 :
* 7 - General purpose ADIN7
* 16 - UID
* 17 - Die temperature
*/
if ( channel > 7 & & channel < 16 ) {
2011-08-24 17:28:21 +04:00
adc1 | = MC13XXX_ADC1_ADSEL ;
2018-03-27 17:19:49 +03:00
} else if ( channel = = 16 ) {
adc0 | = MC13XXX_ADC0_ADIN7SEL_UID ;
channel = 7 ;
} else if ( channel = = 17 ) {
adc0 | = MC13XXX_ADC0_ADIN7SEL_DIE ;
channel = 7 ;
}
2010-09-28 18:37:20 +04:00
switch ( mode ) {
2011-08-24 17:28:21 +04:00
case MC13XXX_ADC_MODE_TS :
adc0 | = MC13XXX_ADC0_ADREFEN | MC13XXX_ADC0_TSMOD0 |
MC13XXX_ADC0_TSMOD1 ;
adc1 | = 4 < < MC13XXX_ADC1_CHAN1_SHIFT ;
2010-09-28 18:37:20 +04:00
break ;
2011-08-24 17:28:21 +04:00
case MC13XXX_ADC_MODE_SINGLE_CHAN :
2011-11-29 15:09:03 +04:00
adc0 | = old_adc0 & MC13XXX_ADC0_CONFIG_MASK ;
2011-08-24 17:28:21 +04:00
adc1 | = ( channel & 0x7 ) < < MC13XXX_ADC1_CHAN0_SHIFT ;
adc1 | = MC13XXX_ADC1_RAND ;
2010-09-28 18:37:20 +04:00
break ;
2011-08-24 17:28:21 +04:00
case MC13XXX_ADC_MODE_MULT_CHAN :
2011-11-29 15:09:03 +04:00
adc0 | = old_adc0 & MC13XXX_ADC0_CONFIG_MASK ;
2011-08-24 17:28:21 +04:00
adc1 | = 4 < < MC13XXX_ADC1_CHAN1_SHIFT ;
2010-09-28 18:37:20 +04:00
break ;
default :
2011-08-24 17:28:21 +04:00
mc13xxx_unlock ( mc13xxx ) ;
2010-09-28 18:37:20 +04:00
return - EINVAL ;
}
2012-02-20 15:18:13 +04:00
adc1 | = ato < < MC13783_ADC1_ATO_SHIFT ;
if ( atox )
adc1 | = MC13783_ADC1_ATOX ;
2012-05-01 14:26:46 +04:00
dev_dbg ( mc13xxx - > dev , " %s: request irq \n " , __func__ ) ;
2011-08-24 17:28:21 +04:00
mc13xxx_irq_request ( mc13xxx , MC13XXX_IRQ_ADCDONE ,
mc13xxx_handler_adcdone , __func__ , & adcdone_data ) ;
2010-09-28 18:37:20 +04:00
2011-08-24 17:28:21 +04:00
mc13xxx_reg_write ( mc13xxx , MC13XXX_ADC0 , adc0 ) ;
mc13xxx_reg_write ( mc13xxx , MC13XXX_ADC1 , adc1 ) ;
2010-09-28 18:37:20 +04:00
mc13xxx_unlock ( mc13xxx ) ;
ret = wait_for_completion_interruptible_timeout ( & adcdone_data . done , HZ ) ;
if ( ! ret )
ret = - ETIMEDOUT ;
mc13xxx_lock ( mc13xxx ) ;
2011-08-24 17:28:21 +04:00
mc13xxx_irq_free ( mc13xxx , MC13XXX_IRQ_ADCDONE , & adcdone_data ) ;
2010-09-28 18:37:20 +04:00
if ( ret > 0 )
for ( i = 0 ; i < 4 ; + + i ) {
ret = mc13xxx_reg_read ( mc13xxx ,
2011-08-24 17:28:21 +04:00
MC13XXX_ADC2 , & sample [ i ] ) ;
2010-09-28 18:37:20 +04:00
if ( ret )
break ;
}
2011-08-24 17:28:21 +04:00
if ( mode = = MC13XXX_ADC_MODE_TS )
2010-09-28 18:37:20 +04:00
/* restore TSMOD */
2011-08-24 17:28:21 +04:00
mc13xxx_reg_write ( mc13xxx , MC13XXX_ADC0 , old_adc0 ) ;
2010-09-28 18:37:20 +04:00
2011-08-24 17:28:21 +04:00
mc13xxx - > adcflags & = ~ MC13XXX_ADC_WORKING ;
2010-09-28 18:37:20 +04:00
out :
mc13xxx_unlock ( mc13xxx ) ;
return ret ;
}
2011-08-24 17:28:21 +04:00
EXPORT_SYMBOL_GPL ( mc13xxx_adc_do_conversion ) ;
2010-09-28 18:37:20 +04:00
static int mc13xxx_add_subdevice_pdata ( struct mc13xxx * mc13xxx ,
2011-04-08 03:55:01 +04:00
const char * format , void * pdata , size_t pdata_size )
2010-09-28 18:37:20 +04:00
{
char buf [ 30 ] ;
const char * name = mc13xxx_get_chipname ( mc13xxx ) ;
struct mfd_cell cell = {
2011-04-08 03:55:01 +04:00
. platform_data = pdata ,
. pdata_size = pdata_size ,
2010-09-28 18:37:20 +04:00
} ;
/* there is no asnprintf in the kernel :-( */
if ( snprintf ( buf , sizeof ( buf ) , format , name ) > sizeof ( buf ) )
return - E2BIG ;
cell . name = kmemdup ( buf , strlen ( buf ) + 1 , GFP_KERNEL ) ;
if ( ! cell . name )
return - ENOMEM ;
2014-06-18 21:05:40 +04:00
return mfd_add_devices ( mc13xxx - > dev , - 1 , & cell , 1 , NULL , 0 ,
regmap_irq_get_domain ( mc13xxx - > irq_data ) ) ;
2010-09-28 18:37:20 +04:00
}
static int mc13xxx_add_subdevice ( struct mc13xxx * mc13xxx , const char * format )
{
2011-04-08 03:55:01 +04:00
return mc13xxx_add_subdevice_pdata ( mc13xxx , format , NULL , 0 ) ;
2010-09-28 18:37:20 +04:00
}
2011-12-12 21:52:57 +04:00
# ifdef CONFIG_OF
static int mc13xxx_probe_flags_dt ( struct mc13xxx * mc13xxx )
{
2012-04-01 10:41:37 +04:00
struct device_node * np = mc13xxx - > dev - > of_node ;
2011-12-12 21:52:57 +04:00
if ( ! np )
return - ENODEV ;
2015-11-16 12:13:17 +03:00
if ( of_property_read_bool ( np , " fsl,mc13xxx-uses-adc " ) )
2011-12-12 21:52:57 +04:00
mc13xxx - > flags | = MC13XXX_USE_ADC ;
2015-11-16 12:13:17 +03:00
if ( of_property_read_bool ( np , " fsl,mc13xxx-uses-codec " ) )
2011-12-12 21:52:57 +04:00
mc13xxx - > flags | = MC13XXX_USE_CODEC ;
2015-11-16 12:13:17 +03:00
if ( of_property_read_bool ( np , " fsl,mc13xxx-uses-rtc " ) )
2011-12-12 21:52:57 +04:00
mc13xxx - > flags | = MC13XXX_USE_RTC ;
2015-11-16 12:13:17 +03:00
if ( of_property_read_bool ( np , " fsl,mc13xxx-uses-touch " ) )
2011-12-12 21:52:57 +04:00
mc13xxx - > flags | = MC13XXX_USE_TOUCHSCREEN ;
return 0 ;
}
# else
static inline int mc13xxx_probe_flags_dt ( struct mc13xxx * mc13xxx )
{
return - ENODEV ;
}
# endif
2013-12-14 17:03:12 +04:00
int mc13xxx_common_init ( struct device * dev )
2010-09-28 18:37:20 +04:00
{
2013-12-14 17:03:12 +04:00
struct mc13xxx_platform_data * pdata = dev_get_platdata ( dev ) ;
struct mc13xxx * mc13xxx = dev_get_drvdata ( dev ) ;
2012-07-12 13:57:52 +04:00
u32 revision ;
2014-06-18 21:05:40 +04:00
int i , ret ;
2010-09-28 18:37:20 +04:00
2013-12-14 17:03:12 +04:00
mc13xxx - > dev = dev ;
2010-09-28 18:37:20 +04:00
2012-07-12 13:57:52 +04:00
ret = mc13xxx_reg_read ( mc13xxx , MC13XXX_REVISION , & revision ) ;
2012-05-01 14:26:46 +04:00
if ( ret )
2013-12-14 17:03:12 +04:00
return ret ;
2010-09-28 18:37:20 +04:00
2012-07-12 13:57:52 +04:00
mc13xxx - > variant - > print_revision ( mc13xxx , revision ) ;
2014-09-08 11:01:11 +04:00
ret = mc13xxx_reg_rmw ( mc13xxx , MC13XXX_PWRCTRL ,
MC13XXX_PWRCTRL_WDIRESET , MC13XXX_PWRCTRL_WDIRESET ) ;
if ( ret )
return ret ;
2014-06-18 21:05:40 +04:00
for ( i = 0 ; i < ARRAY_SIZE ( mc13xxx - > irqs ) ; i + + ) {
mc13xxx - > irqs [ i ] . reg_offset = i / MC13XXX_IRQ_PER_REG ;
mc13xxx - > irqs [ i ] . mask = BIT ( i % MC13XXX_IRQ_PER_REG ) ;
}
2010-09-28 18:37:20 +04:00
2014-06-18 21:05:40 +04:00
mc13xxx - > irq_chip . name = dev_name ( dev ) ;
mc13xxx - > irq_chip . status_base = MC13XXX_IRQSTAT0 ;
mc13xxx - > irq_chip . mask_base = MC13XXX_IRQMASK0 ;
mc13xxx - > irq_chip . ack_base = MC13XXX_IRQSTAT0 ;
mc13xxx - > irq_chip . irq_reg_stride = MC13XXX_IRQSTAT1 - MC13XXX_IRQSTAT0 ;
mc13xxx - > irq_chip . init_ack_masked = true ;
mc13xxx - > irq_chip . use_ack = true ;
mc13xxx - > irq_chip . num_regs = MC13XXX_IRQ_REG_CNT ;
mc13xxx - > irq_chip . irqs = mc13xxx - > irqs ;
mc13xxx - > irq_chip . num_irqs = ARRAY_SIZE ( mc13xxx - > irqs ) ;
ret = regmap_add_irq_chip ( mc13xxx - > regmap , mc13xxx - > irq , IRQF_ONESHOT ,
0 , & mc13xxx - > irq_chip , & mc13xxx - > irq_data ) ;
2010-09-28 18:37:20 +04:00
if ( ret )
2013-12-14 17:03:12 +04:00
return ret ;
2010-09-28 18:37:20 +04:00
2014-04-16 02:56:14 +04:00
mutex_init ( & mc13xxx - > lock ) ;
2011-12-12 21:52:57 +04:00
if ( mc13xxx_probe_flags_dt ( mc13xxx ) < 0 & & pdata )
mc13xxx - > flags = pdata - > flags ;
if ( pdata ) {
mc13xxx_add_subdevice_pdata ( mc13xxx , " %s-regulator " ,
& pdata - > regulators , sizeof ( pdata - > regulators ) ) ;
2011-04-08 03:55:01 +04:00
mc13xxx_add_subdevice_pdata ( mc13xxx , " %s-led " ,
pdata - > leds , sizeof ( * pdata - > leds ) ) ;
2011-09-18 20:10:53 +04:00
mc13xxx_add_subdevice_pdata ( mc13xxx , " %s-pwrbutton " ,
pdata - > buttons , sizeof ( * pdata - > buttons ) ) ;
2014-05-01 10:48:03 +04:00
if ( mc13xxx - > flags & MC13XXX_USE_CODEC )
mc13xxx_add_subdevice_pdata ( mc13xxx , " %s-codec " ,
pdata - > codec , sizeof ( * pdata - > codec ) ) ;
if ( mc13xxx - > flags & MC13XXX_USE_TOUCHSCREEN )
mc13xxx_add_subdevice_pdata ( mc13xxx , " %s-ts " ,
& pdata - > touch , sizeof ( pdata - > touch ) ) ;
2011-12-12 21:52:57 +04:00
} else {
mc13xxx_add_subdevice ( mc13xxx , " %s-regulator " ) ;
mc13xxx_add_subdevice ( mc13xxx , " %s-led " ) ;
mc13xxx_add_subdevice ( mc13xxx , " %s-pwrbutton " ) ;
2014-05-01 10:48:03 +04:00
if ( mc13xxx - > flags & MC13XXX_USE_CODEC )
mc13xxx_add_subdevice ( mc13xxx , " %s-codec " ) ;
if ( mc13xxx - > flags & MC13XXX_USE_TOUCHSCREEN )
mc13xxx_add_subdevice ( mc13xxx , " %s-ts " ) ;
2011-12-12 21:52:57 +04:00
}
2011-09-18 20:10:53 +04:00
2014-06-18 21:05:40 +04:00
if ( mc13xxx - > flags & MC13XXX_USE_ADC )
mc13xxx_add_subdevice ( mc13xxx , " %s-adc " ) ;
if ( mc13xxx - > flags & MC13XXX_USE_RTC )
mc13xxx_add_subdevice ( mc13xxx , " %s-rtc " ) ;
2010-09-28 18:37:20 +04:00
return 0 ;
}
2012-04-01 10:41:38 +04:00
EXPORT_SYMBOL_GPL ( mc13xxx_common_init ) ;
2010-09-28 18:37:20 +04:00
2013-12-14 17:03:12 +04:00
int mc13xxx_common_exit ( struct device * dev )
2010-09-28 18:37:20 +04:00
{
2013-12-14 17:03:12 +04:00
struct mc13xxx * mc13xxx = dev_get_drvdata ( dev ) ;
mfd_remove_devices ( dev ) ;
2014-06-18 21:05:40 +04:00
regmap_del_irq_chip ( mc13xxx - > irq , mc13xxx - > irq_data ) ;
2013-12-14 17:03:12 +04:00
mutex_destroy ( & mc13xxx - > lock ) ;
2010-09-28 18:37:20 +04:00
2013-12-14 17:03:12 +04:00
return 0 ;
2010-09-28 18:37:20 +04:00
}
2013-12-14 17:03:12 +04:00
EXPORT_SYMBOL_GPL ( mc13xxx_common_exit ) ;
2010-09-28 18:37:20 +04:00
MODULE_DESCRIPTION ( " Core driver for Freescale MC13XXX PMIC " ) ;
MODULE_AUTHOR ( " Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de> " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;