2019-05-28 10:10:04 -07:00
// SPDX-License-Identifier: GPL-2.0-only
2012-03-16 11:10:19 +05:30
/*
* Core driver for TI TPS65090 PMIC family
*
* Copyright ( c ) 2012 , NVIDIA CORPORATION . All rights reserved .
2019-01-13 13:36:41 -05:00
*
* Author : Venu Byravarasu < vbyravarasu @ nvidia . com >
2012-03-16 11:10:19 +05:30
*/
# include <linux/interrupt.h>
# include <linux/irq.h>
# include <linux/kernel.h>
2019-01-13 13:36:41 -05:00
# include <linux/init.h>
2012-03-16 11:10:19 +05:30
# include <linux/mutex.h>
# include <linux/slab.h>
# include <linux/i2c.h>
# include <linux/mfd/core.h>
# include <linux/mfd/tps65090.h>
2013-01-29 14:35:15 +05:30
# include <linux/of.h>
# include <linux/of_device.h>
2012-03-16 11:10:19 +05:30
# include <linux/err.h>
# define NUM_INT_REG 2
2012-11-20 08:44:49 +05:30
# define TPS65090_INT1_MASK_VAC_STATUS_CHANGE 1
# define TPS65090_INT1_MASK_VSYS_STATUS_CHANGE 2
# define TPS65090_INT1_MASK_BAT_STATUS_CHANGE 3
# define TPS65090_INT1_MASK_CHARGING_STATUS_CHANGE 4
# define TPS65090_INT1_MASK_CHARGING_COMPLETE 5
# define TPS65090_INT1_MASK_OVERLOAD_DCDC1 6
# define TPS65090_INT1_MASK_OVERLOAD_DCDC2 7
# define TPS65090_INT2_MASK_OVERLOAD_DCDC3 0
# define TPS65090_INT2_MASK_OVERLOAD_FET1 1
# define TPS65090_INT2_MASK_OVERLOAD_FET2 2
# define TPS65090_INT2_MASK_OVERLOAD_FET3 3
# define TPS65090_INT2_MASK_OVERLOAD_FET4 4
# define TPS65090_INT2_MASK_OVERLOAD_FET5 5
# define TPS65090_INT2_MASK_OVERLOAD_FET6 6
# define TPS65090_INT2_MASK_OVERLOAD_FET7 7
2012-03-16 11:10:19 +05:30
2020-09-22 21:26:59 +02:00
static const struct resource charger_resources [ ] = {
2013-03-12 18:08:07 -04:00
{
. start = TPS65090_IRQ_VAC_STATUS_CHANGE ,
. end = TPS65090_IRQ_VAC_STATUS_CHANGE ,
. flags = IORESOURCE_IRQ ,
}
} ;
2014-04-16 16:12:25 -07:00
enum tps65090_cells {
PMIC = 0 ,
CHARGER = 1 ,
} ;
static struct mfd_cell tps65090s [ ] = {
[ PMIC ] = {
2012-07-18 18:33:42 +05:30
. name = " tps65090-pmic " ,
2012-03-16 11:10:19 +05:30
} ,
2014-04-16 16:12:25 -07:00
[ CHARGER ] = {
2012-11-20 08:44:45 +05:30
. name = " tps65090-charger " ,
2013-03-12 18:08:07 -04:00
. num_resources = ARRAY_SIZE ( charger_resources ) ,
. resources = & charger_resources [ 0 ] ,
2013-04-10 13:14:55 -04:00
. of_compatible = " ti,tps65090-charger " ,
2012-03-16 11:10:19 +05:30
} ,
} ;
2012-11-20 08:44:49 +05:30
static const struct regmap_irq tps65090_irqs [ ] = {
/* INT1 IRQs*/
[ TPS65090_IRQ_VAC_STATUS_CHANGE ] = {
2014-11-10 12:28:36 +00:00
. mask = TPS65090_INT1_MASK_VAC_STATUS_CHANGE ,
2012-11-20 08:44:49 +05:30
} ,
[ TPS65090_IRQ_VSYS_STATUS_CHANGE ] = {
2014-11-10 12:28:36 +00:00
. mask = TPS65090_INT1_MASK_VSYS_STATUS_CHANGE ,
2012-11-20 08:44:49 +05:30
} ,
[ TPS65090_IRQ_BAT_STATUS_CHANGE ] = {
2014-11-10 12:28:36 +00:00
. mask = TPS65090_INT1_MASK_BAT_STATUS_CHANGE ,
2012-11-20 08:44:49 +05:30
} ,
[ TPS65090_IRQ_CHARGING_STATUS_CHANGE ] = {
2014-11-10 12:28:36 +00:00
. mask = TPS65090_INT1_MASK_CHARGING_STATUS_CHANGE ,
2012-11-20 08:44:49 +05:30
} ,
[ TPS65090_IRQ_CHARGING_COMPLETE ] = {
2014-11-10 12:28:36 +00:00
. mask = TPS65090_INT1_MASK_CHARGING_COMPLETE ,
2012-11-20 08:44:49 +05:30
} ,
[ TPS65090_IRQ_OVERLOAD_DCDC1 ] = {
2014-11-10 12:28:36 +00:00
. mask = TPS65090_INT1_MASK_OVERLOAD_DCDC1 ,
2012-11-20 08:44:49 +05:30
} ,
[ TPS65090_IRQ_OVERLOAD_DCDC2 ] = {
2014-11-10 12:28:36 +00:00
. mask = TPS65090_INT1_MASK_OVERLOAD_DCDC2 ,
2012-11-20 08:44:49 +05:30
} ,
/* INT2 IRQs*/
[ TPS65090_IRQ_OVERLOAD_DCDC3 ] = {
2014-11-10 12:28:36 +00:00
. reg_offset = 1 ,
. mask = TPS65090_INT2_MASK_OVERLOAD_DCDC3 ,
2012-11-20 08:44:49 +05:30
} ,
[ TPS65090_IRQ_OVERLOAD_FET1 ] = {
2014-11-10 12:28:36 +00:00
. reg_offset = 1 ,
. mask = TPS65090_INT2_MASK_OVERLOAD_FET1 ,
2012-11-20 08:44:49 +05:30
} ,
[ TPS65090_IRQ_OVERLOAD_FET2 ] = {
2014-11-10 12:28:36 +00:00
. reg_offset = 1 ,
. mask = TPS65090_INT2_MASK_OVERLOAD_FET2 ,
2012-11-20 08:44:49 +05:30
} ,
[ TPS65090_IRQ_OVERLOAD_FET3 ] = {
2014-11-10 12:28:36 +00:00
. reg_offset = 1 ,
. mask = TPS65090_INT2_MASK_OVERLOAD_FET3 ,
2012-11-20 08:44:49 +05:30
} ,
[ TPS65090_IRQ_OVERLOAD_FET4 ] = {
2014-11-10 12:28:36 +00:00
. reg_offset = 1 ,
. mask = TPS65090_INT2_MASK_OVERLOAD_FET4 ,
2012-11-20 08:44:49 +05:30
} ,
[ TPS65090_IRQ_OVERLOAD_FET5 ] = {
2014-11-10 12:28:36 +00:00
. reg_offset = 1 ,
. mask = TPS65090_INT2_MASK_OVERLOAD_FET5 ,
2012-11-20 08:44:49 +05:30
} ,
[ TPS65090_IRQ_OVERLOAD_FET6 ] = {
2014-11-10 12:28:36 +00:00
. reg_offset = 1 ,
. mask = TPS65090_INT2_MASK_OVERLOAD_FET6 ,
2012-11-20 08:44:49 +05:30
} ,
[ TPS65090_IRQ_OVERLOAD_FET7 ] = {
2014-11-10 12:28:36 +00:00
. reg_offset = 1 ,
. mask = TPS65090_INT2_MASK_OVERLOAD_FET7 ,
2012-11-20 08:44:49 +05:30
} ,
} ;
2012-03-16 11:10:19 +05:30
2012-11-20 08:44:49 +05:30
static struct regmap_irq_chip tps65090_irq_chip = {
. name = " tps65090 " ,
. irqs = tps65090_irqs ,
. num_irqs = ARRAY_SIZE ( tps65090_irqs ) ,
. num_regs = NUM_INT_REG ,
2014-04-16 16:12:27 -07:00
. status_base = TPS65090_REG_INTR_STS ,
. mask_base = TPS65090_REG_INTR_MASK ,
2012-11-20 08:44:49 +05:30
. mask_invert = true ,
} ;
2012-03-16 11:10:19 +05:30
static bool is_volatile_reg ( struct device * dev , unsigned int reg )
{
2014-04-16 16:12:27 -07:00
/* Nearly all registers have status bits mixed in, except a few */
switch ( reg ) {
case TPS65090_REG_INTR_MASK :
case TPS65090_REG_INTR_MASK2 :
case TPS65090_REG_CG_CTRL0 :
case TPS65090_REG_CG_CTRL1 :
case TPS65090_REG_CG_CTRL2 :
case TPS65090_REG_CG_CTRL3 :
case TPS65090_REG_CG_CTRL4 :
case TPS65090_REG_CG_CTRL5 :
2012-03-16 11:10:19 +05:30
return false ;
2014-04-16 16:12:27 -07:00
}
return true ;
2012-03-16 11:10:19 +05:30
}
static const struct regmap_config tps65090_regmap_config = {
. reg_bits = 8 ,
. val_bits = 8 ,
2016-01-31 23:00:06 +01:00
. max_register = TPS65090_MAX_REG ,
. num_reg_defaults_raw = TPS65090_NUM_REGS ,
2012-03-16 11:10:19 +05:30
. cache_type = REGCACHE_RBTREE ,
. volatile_reg = is_volatile_reg ,
} ;
2013-01-29 14:35:15 +05:30
# ifdef CONFIG_OF
static const struct of_device_id tps65090_of_match [ ] = {
{ . compatible = " ti,tps65090 " , } ,
{ } ,
} ;
# endif
2012-11-19 13:23:04 -05:00
static int tps65090_i2c_probe ( struct i2c_client * client ,
2014-11-10 12:28:36 +00:00
const struct i2c_device_id * id )
2012-03-16 11:10:19 +05:30
{
2013-07-30 17:10:05 +09:00
struct tps65090_platform_data * pdata = dev_get_platdata ( & client - > dev ) ;
2013-01-29 14:35:15 +05:30
int irq_base = 0 ;
2012-03-16 11:10:19 +05:30
struct tps65090 * tps65090 ;
int ret ;
2013-01-29 14:35:15 +05:30
if ( ! pdata & & ! client - > dev . of_node ) {
dev_err ( & client - > dev ,
" tps65090 requires platform data or of_node \n " ) ;
2012-03-16 11:10:19 +05:30
return - EINVAL ;
}
2013-01-29 14:35:15 +05:30
if ( pdata )
irq_base = pdata - > irq_base ;
2012-11-20 08:44:46 +05:30
tps65090 = devm_kzalloc ( & client - > dev , sizeof ( * tps65090 ) , GFP_KERNEL ) ;
2018-03-08 15:25:58 +01:00
if ( ! tps65090 )
2012-03-16 11:10:19 +05:30
return - ENOMEM ;
tps65090 - > dev = & client - > dev ;
i2c_set_clientdata ( client , tps65090 ) ;
2012-11-20 08:44:47 +05:30
tps65090 - > rmap = devm_regmap_init_i2c ( client , & tps65090_regmap_config ) ;
2012-03-16 11:10:19 +05:30
if ( IS_ERR ( tps65090 - > rmap ) ) {
2012-04-25 09:30:36 +08:00
ret = PTR_ERR ( tps65090 - > rmap ) ;
dev_err ( & client - > dev , " regmap_init failed with err: %d \n " , ret ) ;
2012-11-20 08:44:49 +05:30
return ret ;
}
if ( client - > irq ) {
ret = regmap_add_irq_chip ( tps65090 - > rmap , client - > irq ,
2014-11-10 12:28:36 +00:00
IRQF_ONESHOT | IRQF_TRIGGER_LOW , irq_base ,
& tps65090_irq_chip , & tps65090 - > irq_data ) ;
if ( ret ) {
dev_err ( & client - > dev ,
" IRQ init failed with err: %d \n " , ret ) ;
2012-11-20 08:44:49 +05:30
return ret ;
}
2014-04-16 16:12:25 -07:00
} else {
/* Don't tell children they have an IRQ that'll never fire */
tps65090s [ CHARGER ] . num_resources = 0 ;
2012-04-25 09:30:36 +08:00
}
2012-03-16 11:10:19 +05:30
ret = mfd_add_devices ( tps65090 - > dev , - 1 , tps65090s ,
2014-11-10 12:28:36 +00:00
ARRAY_SIZE ( tps65090s ) , NULL ,
0 , regmap_irq_get_domain ( tps65090 - > irq_data ) ) ;
2012-03-16 11:10:19 +05:30
if ( ret ) {
dev_err ( & client - > dev , " add mfd devices failed with err: %d \n " ,
ret ) ;
2012-04-25 10:04:58 +08:00
goto err_irq_exit ;
2012-03-16 11:10:19 +05:30
}
return 0 ;
err_irq_exit :
if ( client - > irq )
2012-11-20 08:44:49 +05:30
regmap_del_irq_chip ( client - > irq , tps65090 - > irq_data ) ;
2012-03-16 11:10:19 +05:30
return ret ;
}
static const struct i2c_device_id tps65090_id_table [ ] = {
{ " tps65090 " , 0 } ,
{ } ,
} ;
static struct i2c_driver tps65090_driver = {
. driver = {
. name = " tps65090 " ,
2019-01-13 13:36:41 -05:00
. suppress_bind_attrs = true ,
2013-01-29 14:35:15 +05:30
. of_match_table = of_match_ptr ( tps65090_of_match ) ,
2012-03-16 11:10:19 +05:30
} ,
. probe = tps65090_i2c_probe ,
. id_table = tps65090_id_table ,
} ;
static int __init tps65090_init ( void )
{
return i2c_add_driver ( & tps65090_driver ) ;
}
subsys_initcall ( tps65090_init ) ;