2012-09-14 17:24:50 +04:00
/*
* Device access for Dialog DA9055 PMICs .
*
* Copyright ( c ) 2012 Dialog Semiconductor Ltd .
*
* Author : David Dajun Chen < dchen @ diasemi . com >
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation ; either version 2 of the License , or ( at your
* option ) any later version .
*/
# include <linux/module.h>
# include <linux/device.h>
# include <linux/input.h>
# include <linux/irq.h>
# include <linux/mutex.h>
# include <linux/mfd/core.h>
# include <linux/mfd/da9055/core.h>
# include <linux/mfd/da9055/pdata.h>
# include <linux/mfd/da9055/reg.h>
# define DA9055_IRQ_NONKEY_MASK 0x01
# define DA9055_IRQ_ALM_MASK 0x02
# define DA9055_IRQ_TICK_MASK 0x04
# define DA9055_IRQ_ADC_MASK 0x08
# define DA9055_IRQ_BUCK_ILIM_MASK 0x08
static bool da9055_register_readable ( struct device * dev , unsigned int reg )
{
switch ( reg ) {
case DA9055_REG_STATUS_A :
case DA9055_REG_STATUS_B :
case DA9055_REG_EVENT_A :
case DA9055_REG_EVENT_B :
case DA9055_REG_EVENT_C :
case DA9055_REG_IRQ_MASK_A :
case DA9055_REG_IRQ_MASK_B :
case DA9055_REG_IRQ_MASK_C :
case DA9055_REG_CONTROL_A :
case DA9055_REG_CONTROL_B :
case DA9055_REG_CONTROL_C :
case DA9055_REG_CONTROL_D :
case DA9055_REG_CONTROL_E :
case DA9055_REG_ADC_MAN :
case DA9055_REG_ADC_CONT :
case DA9055_REG_VSYS_MON :
case DA9055_REG_ADC_RES_L :
case DA9055_REG_ADC_RES_H :
case DA9055_REG_VSYS_RES :
case DA9055_REG_ADCIN1_RES :
case DA9055_REG_ADCIN2_RES :
case DA9055_REG_ADCIN3_RES :
case DA9055_REG_COUNT_S :
case DA9055_REG_COUNT_MI :
case DA9055_REG_COUNT_H :
case DA9055_REG_COUNT_D :
case DA9055_REG_COUNT_MO :
case DA9055_REG_COUNT_Y :
case DA9055_REG_ALARM_H :
case DA9055_REG_ALARM_D :
case DA9055_REG_ALARM_MI :
case DA9055_REG_ALARM_MO :
case DA9055_REG_ALARM_Y :
case DA9055_REG_GPIO0_1 :
case DA9055_REG_GPIO2 :
case DA9055_REG_GPIO_MODE0_2 :
case DA9055_REG_BCORE_CONT :
case DA9055_REG_BMEM_CONT :
case DA9055_REG_LDO1_CONT :
case DA9055_REG_LDO2_CONT :
case DA9055_REG_LDO3_CONT :
case DA9055_REG_LDO4_CONT :
case DA9055_REG_LDO5_CONT :
case DA9055_REG_LDO6_CONT :
case DA9055_REG_BUCK_LIM :
case DA9055_REG_BCORE_MODE :
case DA9055_REG_VBCORE_A :
case DA9055_REG_VBMEM_A :
case DA9055_REG_VLDO1_A :
case DA9055_REG_VLDO2_A :
case DA9055_REG_VLDO3_A :
case DA9055_REG_VLDO4_A :
case DA9055_REG_VLDO5_A :
case DA9055_REG_VLDO6_A :
case DA9055_REG_VBCORE_B :
case DA9055_REG_VBMEM_B :
case DA9055_REG_VLDO1_B :
case DA9055_REG_VLDO2_B :
case DA9055_REG_VLDO3_B :
case DA9055_REG_VLDO4_B :
case DA9055_REG_VLDO5_B :
case DA9055_REG_VLDO6_B :
return true ;
default :
return false ;
}
}
static bool da9055_register_writeable ( struct device * dev , unsigned int reg )
{
switch ( reg ) {
case DA9055_REG_STATUS_A :
case DA9055_REG_STATUS_B :
case DA9055_REG_EVENT_A :
case DA9055_REG_EVENT_B :
case DA9055_REG_EVENT_C :
case DA9055_REG_IRQ_MASK_A :
case DA9055_REG_IRQ_MASK_B :
case DA9055_REG_IRQ_MASK_C :
case DA9055_REG_CONTROL_A :
case DA9055_REG_CONTROL_B :
case DA9055_REG_CONTROL_C :
case DA9055_REG_CONTROL_D :
case DA9055_REG_CONTROL_E :
case DA9055_REG_ADC_MAN :
case DA9055_REG_ADC_CONT :
case DA9055_REG_VSYS_MON :
case DA9055_REG_ADC_RES_L :
case DA9055_REG_ADC_RES_H :
case DA9055_REG_VSYS_RES :
case DA9055_REG_ADCIN1_RES :
case DA9055_REG_ADCIN2_RES :
case DA9055_REG_ADCIN3_RES :
case DA9055_REG_COUNT_S :
case DA9055_REG_COUNT_MI :
case DA9055_REG_COUNT_H :
case DA9055_REG_COUNT_D :
case DA9055_REG_COUNT_MO :
case DA9055_REG_COUNT_Y :
case DA9055_REG_ALARM_H :
case DA9055_REG_ALARM_D :
case DA9055_REG_ALARM_MI :
case DA9055_REG_ALARM_MO :
case DA9055_REG_ALARM_Y :
case DA9055_REG_GPIO0_1 :
case DA9055_REG_GPIO2 :
case DA9055_REG_GPIO_MODE0_2 :
case DA9055_REG_BCORE_CONT :
case DA9055_REG_BMEM_CONT :
case DA9055_REG_LDO1_CONT :
case DA9055_REG_LDO2_CONT :
case DA9055_REG_LDO3_CONT :
case DA9055_REG_LDO4_CONT :
case DA9055_REG_LDO5_CONT :
case DA9055_REG_LDO6_CONT :
case DA9055_REG_BUCK_LIM :
case DA9055_REG_BCORE_MODE :
case DA9055_REG_VBCORE_A :
case DA9055_REG_VBMEM_A :
case DA9055_REG_VLDO1_A :
case DA9055_REG_VLDO2_A :
case DA9055_REG_VLDO3_A :
case DA9055_REG_VLDO4_A :
case DA9055_REG_VLDO5_A :
case DA9055_REG_VLDO6_A :
case DA9055_REG_VBCORE_B :
case DA9055_REG_VBMEM_B :
case DA9055_REG_VLDO1_B :
case DA9055_REG_VLDO2_B :
case DA9055_REG_VLDO3_B :
case DA9055_REG_VLDO4_B :
case DA9055_REG_VLDO5_B :
case DA9055_REG_VLDO6_B :
return true ;
default :
return false ;
}
}
static bool da9055_register_volatile ( struct device * dev , unsigned int reg )
{
switch ( reg ) {
case DA9055_REG_STATUS_A :
case DA9055_REG_STATUS_B :
case DA9055_REG_EVENT_A :
case DA9055_REG_EVENT_B :
case DA9055_REG_EVENT_C :
case DA9055_REG_CONTROL_A :
case DA9055_REG_CONTROL_E :
case DA9055_REG_ADC_MAN :
case DA9055_REG_ADC_RES_L :
case DA9055_REG_ADC_RES_H :
case DA9055_REG_VSYS_RES :
case DA9055_REG_ADCIN1_RES :
case DA9055_REG_ADCIN2_RES :
case DA9055_REG_ADCIN3_RES :
case DA9055_REG_COUNT_S :
case DA9055_REG_COUNT_MI :
case DA9055_REG_COUNT_H :
case DA9055_REG_COUNT_D :
case DA9055_REG_COUNT_MO :
case DA9055_REG_COUNT_Y :
case DA9055_REG_ALARM_MI :
case DA9055_REG_BCORE_CONT :
case DA9055_REG_BMEM_CONT :
case DA9055_REG_LDO1_CONT :
case DA9055_REG_LDO2_CONT :
case DA9055_REG_LDO3_CONT :
case DA9055_REG_LDO4_CONT :
case DA9055_REG_LDO5_CONT :
case DA9055_REG_LDO6_CONT :
return true ;
default :
return false ;
}
}
2015-04-27 15:54:13 +03:00
static const struct regmap_irq da9055_irqs [ ] = {
2012-09-14 17:24:50 +04:00
[ DA9055_IRQ_NONKEY ] = {
. reg_offset = 0 ,
. mask = DA9055_IRQ_NONKEY_MASK ,
} ,
[ DA9055_IRQ_ALARM ] = {
. reg_offset = 0 ,
. mask = DA9055_IRQ_ALM_MASK ,
} ,
[ DA9055_IRQ_TICK ] = {
. reg_offset = 0 ,
. mask = DA9055_IRQ_TICK_MASK ,
} ,
[ DA9055_IRQ_HWMON ] = {
. reg_offset = 0 ,
. mask = DA9055_IRQ_ADC_MASK ,
} ,
[ DA9055_IRQ_REGULATOR ] = {
. reg_offset = 1 ,
. mask = DA9055_IRQ_BUCK_ILIM_MASK ,
} ,
} ;
2015-04-27 15:54:13 +03:00
const struct regmap_config da9055_regmap_config = {
2012-09-14 17:24:50 +04:00
. reg_bits = 8 ,
. val_bits = 8 ,
. cache_type = REGCACHE_RBTREE ,
. max_register = DA9055_MAX_REGISTER_CNT ,
. readable_reg = da9055_register_readable ,
. writeable_reg = da9055_register_writeable ,
. volatile_reg = da9055_register_volatile ,
} ;
EXPORT_SYMBOL_GPL ( da9055_regmap_config ) ;
static struct resource da9055_onkey_resource = {
. name = " ONKEY " ,
. start = DA9055_IRQ_NONKEY ,
. end = DA9055_IRQ_NONKEY ,
. flags = IORESOURCE_IRQ ,
} ;
static struct resource da9055_rtc_resource [ ] = {
{
. name = " ALM " ,
. start = DA9055_IRQ_ALARM ,
. end = DA9055_IRQ_ALARM ,
. flags = IORESOURCE_IRQ ,
} ,
{
. name = " TICK " ,
. start = DA9055_IRQ_TICK ,
. end = DA9055_IRQ_TICK ,
. flags = IORESOURCE_IRQ ,
} ,
} ;
static struct resource da9055_hwmon_resource = {
. name = " HWMON " ,
. start = DA9055_IRQ_HWMON ,
. end = DA9055_IRQ_HWMON ,
. flags = IORESOURCE_IRQ ,
} ;
static struct resource da9055_ld05_6_resource = {
. name = " REGULATOR " ,
. start = DA9055_IRQ_REGULATOR ,
. end = DA9055_IRQ_REGULATOR ,
. flags = IORESOURCE_IRQ ,
} ;
2013-11-18 17:32:57 +04:00
static const struct mfd_cell da9055_devs [ ] = {
2012-09-14 17:24:50 +04:00
{
2014-08-22 18:26:55 +04:00
. of_compatible = " dlg,da9055-gpio " ,
2012-09-14 17:24:50 +04:00
. name = " da9055-gpio " ,
} ,
{
2014-08-22 18:26:55 +04:00
. of_compatible = " dlg,da9055-regulator " ,
2012-09-14 17:24:50 +04:00
. name = " da9055-regulator " ,
. id = 1 ,
} ,
{
2014-08-22 18:26:55 +04:00
. of_compatible = " dlg,da9055-regulator " ,
2012-09-14 17:24:50 +04:00
. name = " da9055-regulator " ,
. id = 2 ,
} ,
{
2014-08-22 18:26:55 +04:00
. of_compatible = " dlg,da9055-regulator " ,
2012-09-14 17:24:50 +04:00
. name = " da9055-regulator " ,
. id = 3 ,
} ,
{
2014-08-22 18:26:55 +04:00
. of_compatible = " dlg,da9055-regulator " ,
2012-09-14 17:24:50 +04:00
. name = " da9055-regulator " ,
. id = 4 ,
} ,
{
2014-08-22 18:26:55 +04:00
. of_compatible = " dlg,da9055-regulator " ,
2012-09-14 17:24:50 +04:00
. name = " da9055-regulator " ,
. id = 5 ,
} ,
{
2014-08-22 18:26:55 +04:00
. of_compatible = " dlg,da9055-regulator " ,
2012-09-14 17:24:50 +04:00
. name = " da9055-regulator " ,
. id = 6 ,
} ,
{
2014-08-22 18:26:55 +04:00
. of_compatible = " dlg,da9055-regulator " ,
2012-09-14 17:24:50 +04:00
. name = " da9055-regulator " ,
. id = 7 ,
. resources = & da9055_ld05_6_resource ,
. num_resources = 1 ,
} ,
{
2014-08-22 18:26:55 +04:00
. of_compatible = " dlg,da9055-regulator " ,
2012-09-14 17:24:50 +04:00
. name = " da9055-regulator " ,
. resources = & da9055_ld05_6_resource ,
. num_resources = 1 ,
. id = 8 ,
} ,
{
2014-08-22 18:26:55 +04:00
. of_compatible = " dlg,da9055-onkey " ,
2012-09-14 17:24:50 +04:00
. name = " da9055-onkey " ,
. resources = & da9055_onkey_resource ,
. num_resources = 1 ,
} ,
{
2014-08-22 18:26:55 +04:00
. of_compatible = " dlg,da9055-rtc " ,
2012-09-14 17:24:50 +04:00
. name = " da9055-rtc " ,
. resources = da9055_rtc_resource ,
. num_resources = ARRAY_SIZE ( da9055_rtc_resource ) ,
} ,
{
2014-08-22 18:26:55 +04:00
. of_compatible = " dlg,da9055-hwmon " ,
2012-09-14 17:24:50 +04:00
. name = " da9055-hwmon " ,
. resources = & da9055_hwmon_resource ,
. num_resources = 1 ,
} ,
{
2014-08-22 18:26:55 +04:00
. of_compatible = " dlg,da9055-watchdog " ,
2012-09-14 17:24:50 +04:00
. name = " da9055-watchdog " ,
} ,
} ;
2015-04-27 15:54:13 +03:00
static const struct regmap_irq_chip da9055_regmap_irq_chip = {
2012-09-14 17:24:50 +04:00
. name = " da9055_irq " ,
. status_base = DA9055_REG_EVENT_A ,
. mask_base = DA9055_REG_IRQ_MASK_A ,
. ack_base = DA9055_REG_EVENT_A ,
. num_regs = 3 ,
. irqs = da9055_irqs ,
. num_irqs = ARRAY_SIZE ( da9055_irqs ) ,
} ;
2012-11-19 22:23:04 +04:00
int da9055_device_init ( struct da9055 * da9055 )
2012-09-14 17:24:50 +04:00
{
2013-07-30 12:10:05 +04:00
struct da9055_pdata * pdata = dev_get_platdata ( da9055 - > dev ) ;
2012-09-14 17:24:50 +04:00
int ret ;
2013-07-05 17:18:30 +04:00
uint8_t clear_events [ 3 ] = { 0xFF , 0xFF , 0xFF } ;
2012-09-14 17:24:50 +04:00
if ( pdata & & pdata - > init ! = NULL )
pdata - > init ( da9055 ) ;
if ( ! pdata | | ! pdata - > irq_base )
da9055 - > irq_base = - 1 ;
else
da9055 - > irq_base = pdata - > irq_base ;
2013-07-05 17:18:30 +04:00
ret = da9055_group_write ( da9055 , DA9055_REG_EVENT_A , 3 , clear_events ) ;
if ( ret < 0 )
return ret ;
2012-09-14 17:24:50 +04:00
ret = regmap_add_irq_chip ( da9055 - > regmap , da9055 - > chip_irq ,
2013-03-18 13:12:38 +04:00
IRQF_TRIGGER_LOW | IRQF_ONESHOT ,
2012-09-14 17:24:50 +04:00
da9055 - > irq_base , & da9055_regmap_irq_chip ,
& da9055 - > irq_data ) ;
if ( ret < 0 )
return ret ;
da9055 - > irq_base = regmap_irq_chip_get_base ( da9055 - > irq_data ) ;
ret = mfd_add_devices ( da9055 - > dev , - 1 ,
da9055_devs , ARRAY_SIZE ( da9055_devs ) ,
NULL , da9055 - > irq_base , NULL ) ;
if ( ret )
goto err ;
return 0 ;
err :
mfd_remove_devices ( da9055 - > dev ) ;
return ret ;
}
2012-11-19 22:26:01 +04:00
void da9055_device_exit ( struct da9055 * da9055 )
2012-09-14 17:24:50 +04:00
{
regmap_del_irq_chip ( da9055 - > chip_irq , da9055 - > irq_data ) ;
mfd_remove_devices ( da9055 - > dev ) ;
}
MODULE_DESCRIPTION ( " Core support for the DA9055 PMIC " ) ;
MODULE_LICENSE ( " GPL " ) ;
MODULE_AUTHOR ( " David Dajun Chen <dchen@diasemi.com> " ) ;