2014-09-03 17:51:44 +04:00
/*
2016-08-29 14:07:58 +03:00
* MFD core driver for Rockchip RK808 / RK818
2014-09-03 17:51:44 +04:00
*
* Copyright ( c ) 2014 , Fuzhou Rockchip Electronics Co . , Ltd
*
* Author : Chris Zhong < zyw @ rock - chips . com >
* Author : Zhang Qing < zhangqing @ rock - chips . com >
*
2016-08-29 14:07:58 +03:00
* Copyright ( C ) 2016 PHYTEC Messtechnik GmbH
*
* Author : Wadim Egorov < w . egorov @ phytec . de >
*
2014-09-03 17:51:44 +04:00
* 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 .
*/
# include <linux/i2c.h>
# include <linux/interrupt.h>
# include <linux/mfd/rk808.h>
# include <linux/mfd/core.h>
# include <linux/module.h>
2016-08-29 14:07:58 +03:00
# include <linux/of_device.h>
2014-09-03 17:51:44 +04:00
# include <linux/regmap.h>
struct rk808_reg_data {
int addr ;
int mask ;
int value ;
} ;
2014-09-10 03:06:04 +04:00
static bool rk808_is_volatile_reg ( struct device * dev , unsigned int reg )
{
/*
* Notes :
* - Technically the ROUND_30s bit makes RTC_CTRL_REG volatile , but
* we don ' t use that feature . It ' s better to cache .
* - It ' s unlikely we care that RK808_DEVCTRL_REG is volatile since
* bits are cleared in case when we shutoff anyway , but better safe .
*/
switch ( reg ) {
case RK808_SECONDS_REG . . . RK808_WEEKS_REG :
case RK808_RTC_STATUS_REG :
case RK808_VB_MON_REG :
case RK808_THERMAL_REG :
case RK808_DCDC_UV_STS_REG :
case RK808_LDO_UV_STS_REG :
case RK808_DCDC_PG_REG :
case RK808_LDO_PG_REG :
case RK808_DEVCTRL_REG :
case RK808_INT_STS_REG1 :
case RK808_INT_STS_REG2 :
return true ;
}
return false ;
}
2016-08-29 14:07:58 +03:00
static const struct regmap_config rk818_regmap_config = {
. reg_bits = 8 ,
. val_bits = 8 ,
. max_register = RK818_USB_CTRL_REG ,
. cache_type = REGCACHE_RBTREE ,
. volatile_reg = rk808_is_volatile_reg ,
} ;
2017-08-21 04:28:38 +03:00
static const struct regmap_config rk805_regmap_config = {
. reg_bits = 8 ,
. val_bits = 8 ,
. max_register = RK805_OFF_SOURCE_REG ,
. cache_type = REGCACHE_RBTREE ,
. volatile_reg = rk808_is_volatile_reg ,
} ;
2014-09-03 17:51:44 +04:00
static const struct regmap_config rk808_regmap_config = {
. reg_bits = 8 ,
. val_bits = 8 ,
. max_register = RK808_IO_POL_REG ,
2014-09-10 03:06:04 +04:00
. cache_type = REGCACHE_RBTREE ,
. volatile_reg = rk808_is_volatile_reg ,
2014-09-03 17:51:44 +04:00
} ;
static struct resource rtc_resources [ ] = {
{
. start = RK808_IRQ_RTC_ALARM ,
. end = RK808_IRQ_RTC_ALARM ,
. flags = IORESOURCE_IRQ ,
}
} ;
2017-08-21 04:28:42 +03:00
static struct resource rk805_key_resources [ ] = {
{
. start = RK805_IRQ_PWRON_FALL ,
. end = RK805_IRQ_PWRON_FALL ,
. flags = IORESOURCE_IRQ ,
} ,
{
. start = RK805_IRQ_PWRON_RISE ,
. end = RK805_IRQ_PWRON_RISE ,
. flags = IORESOURCE_IRQ ,
}
} ;
2017-08-21 04:28:38 +03:00
static const struct mfd_cell rk805s [ ] = {
{ . name = " rk808-clkout " , } ,
{ . name = " rk808-regulator " , } ,
2017-08-21 04:28:41 +03:00
{ . name = " rk805-pinctrl " , } ,
2017-08-21 04:28:38 +03:00
{
. name = " rk808-rtc " ,
. num_resources = ARRAY_SIZE ( rtc_resources ) ,
. resources = & rtc_resources [ 0 ] ,
} ,
2017-08-21 04:28:42 +03:00
{ . name = " rk805-pwrkey " ,
. num_resources = ARRAY_SIZE ( rk805_key_resources ) ,
. resources = & rk805_key_resources [ 0 ] ,
} ,
2017-08-21 04:28:38 +03:00
} ;
2014-09-03 17:51:44 +04:00
static const struct mfd_cell rk808s [ ] = {
{ . name = " rk808-clkout " , } ,
{ . name = " rk808-regulator " , } ,
{
. name = " rk808-rtc " ,
. num_resources = ARRAY_SIZE ( rtc_resources ) ,
2016-08-29 14:07:58 +03:00
. resources = rtc_resources ,
2014-09-03 17:51:44 +04:00
} ,
} ;
2016-08-29 14:07:58 +03:00
static const struct mfd_cell rk818s [ ] = {
{ . name = " rk808-clkout " , } ,
{ . name = " rk808-regulator " , } ,
{
. name = " rk808-rtc " ,
. num_resources = ARRAY_SIZE ( rtc_resources ) ,
. resources = rtc_resources ,
} ,
} ;
2017-08-21 04:28:38 +03:00
static const struct rk808_reg_data rk805_pre_init_reg [ ] = {
{ RK805_BUCK1_CONFIG_REG , RK805_BUCK1_2_ILMAX_MASK ,
RK805_BUCK1_2_ILMAX_4000MA } ,
{ RK805_BUCK2_CONFIG_REG , RK805_BUCK1_2_ILMAX_MASK ,
RK805_BUCK1_2_ILMAX_4000MA } ,
{ RK805_BUCK3_CONFIG_REG , RK805_BUCK3_4_ILMAX_MASK ,
RK805_BUCK3_ILMAX_3000MA } ,
{ RK805_BUCK4_CONFIG_REG , RK805_BUCK3_4_ILMAX_MASK ,
RK805_BUCK4_ILMAX_3500MA } ,
{ RK805_BUCK4_CONFIG_REG , BUCK_ILMIN_MASK , BUCK_ILMIN_400MA } ,
{ RK805_GPIO_IO_POL_REG , SLP_SD_MSK , SLEEP_FUN } ,
{ RK805_THERMAL_REG , TEMP_HOTDIE_MSK , TEMP115C } ,
} ;
2016-08-29 14:07:58 +03:00
static const struct rk808_reg_data rk808_pre_init_reg [ ] = {
2014-09-03 17:51:44 +04:00
{ RK808_BUCK3_CONFIG_REG , BUCK_ILMIN_MASK , BUCK_ILMIN_150MA } ,
{ RK808_BUCK4_CONFIG_REG , BUCK_ILMIN_MASK , BUCK_ILMIN_200MA } ,
{ RK808_BOOST_CONFIG_REG , BOOST_ILMIN_MASK , BOOST_ILMIN_100MA } ,
{ RK808_BUCK1_CONFIG_REG , BUCK1_RATE_MASK , BUCK_ILMIN_200MA } ,
{ RK808_BUCK2_CONFIG_REG , BUCK2_RATE_MASK , BUCK_ILMIN_200MA } ,
2015-02-28 13:09:06 +03:00
{ RK808_DCDC_UV_ACT_REG , BUCK_UV_ACT_MASK , BUCK_UV_ACT_DISABLE } ,
2014-09-03 17:51:44 +04:00
{ RK808_VB_MON_REG , MASK_ALL , VB_LO_ACT |
VB_LO_SEL_3500MV } ,
} ;
2016-08-29 14:07:58 +03:00
static const struct rk808_reg_data rk818_pre_init_reg [ ] = {
/* improve efficiency */
{ RK818_BUCK2_CONFIG_REG , BUCK2_RATE_MASK , BUCK_ILMIN_250MA } ,
{ RK818_BUCK4_CONFIG_REG , BUCK_ILMIN_MASK , BUCK_ILMIN_250MA } ,
{ RK818_BOOST_CONFIG_REG , BOOST_ILMIN_MASK , BOOST_ILMIN_100MA } ,
{ RK818_USB_CTRL_REG , RK818_USB_ILIM_SEL_MASK ,
RK818_USB_ILMIN_2000MA } ,
/* close charger when usb lower then 3.4V */
{ RK818_USB_CTRL_REG , RK818_USB_CHG_SD_VSEL_MASK ,
( 0x7 < < 4 ) } ,
/* no action when vref */
{ RK818_H5V_EN_REG , BIT ( 1 ) , RK818_REF_RDY_CTRL } ,
/* enable HDMI 5V */
{ RK818_H5V_EN_REG , BIT ( 0 ) , RK818_H5V_EN } ,
{ RK808_VB_MON_REG , MASK_ALL , VB_LO_ACT |
VB_LO_SEL_3500MV } ,
} ;
2017-08-21 04:28:38 +03:00
static const struct regmap_irq rk805_irqs [ ] = {
[ RK805_IRQ_PWRON_RISE ] = {
. mask = RK805_IRQ_PWRON_RISE_MSK ,
. reg_offset = 0 ,
} ,
[ RK805_IRQ_VB_LOW ] = {
. mask = RK805_IRQ_VB_LOW_MSK ,
. reg_offset = 0 ,
} ,
[ RK805_IRQ_PWRON ] = {
. mask = RK805_IRQ_PWRON_MSK ,
. reg_offset = 0 ,
} ,
[ RK805_IRQ_PWRON_LP ] = {
. mask = RK805_IRQ_PWRON_LP_MSK ,
. reg_offset = 0 ,
} ,
[ RK805_IRQ_HOTDIE ] = {
. mask = RK805_IRQ_HOTDIE_MSK ,
. reg_offset = 0 ,
} ,
[ RK805_IRQ_RTC_ALARM ] = {
. mask = RK805_IRQ_RTC_ALARM_MSK ,
. reg_offset = 0 ,
} ,
[ RK805_IRQ_RTC_PERIOD ] = {
. mask = RK805_IRQ_RTC_PERIOD_MSK ,
. reg_offset = 0 ,
} ,
[ RK805_IRQ_PWRON_FALL ] = {
. mask = RK805_IRQ_PWRON_FALL_MSK ,
. reg_offset = 0 ,
} ,
} ;
2014-09-03 17:51:44 +04:00
static const struct regmap_irq rk808_irqs [ ] = {
/* INT_STS */
[ RK808_IRQ_VOUT_LO ] = {
. mask = RK808_IRQ_VOUT_LO_MSK ,
. reg_offset = 0 ,
} ,
[ RK808_IRQ_VB_LO ] = {
. mask = RK808_IRQ_VB_LO_MSK ,
. reg_offset = 0 ,
} ,
[ RK808_IRQ_PWRON ] = {
. mask = RK808_IRQ_PWRON_MSK ,
. reg_offset = 0 ,
} ,
[ RK808_IRQ_PWRON_LP ] = {
. mask = RK808_IRQ_PWRON_LP_MSK ,
. reg_offset = 0 ,
} ,
[ RK808_IRQ_HOTDIE ] = {
. mask = RK808_IRQ_HOTDIE_MSK ,
. reg_offset = 0 ,
} ,
[ RK808_IRQ_RTC_ALARM ] = {
. mask = RK808_IRQ_RTC_ALARM_MSK ,
. reg_offset = 0 ,
} ,
[ RK808_IRQ_RTC_PERIOD ] = {
. mask = RK808_IRQ_RTC_PERIOD_MSK ,
. reg_offset = 0 ,
} ,
/* INT_STS2 */
[ RK808_IRQ_PLUG_IN_INT ] = {
. mask = RK808_IRQ_PLUG_IN_INT_MSK ,
. reg_offset = 1 ,
} ,
[ RK808_IRQ_PLUG_OUT_INT ] = {
. mask = RK808_IRQ_PLUG_OUT_INT_MSK ,
. reg_offset = 1 ,
} ,
} ;
2016-08-29 14:07:58 +03:00
static const struct regmap_irq rk818_irqs [ ] = {
/* INT_STS */
[ RK818_IRQ_VOUT_LO ] = {
. mask = RK818_IRQ_VOUT_LO_MSK ,
. reg_offset = 0 ,
} ,
[ RK818_IRQ_VB_LO ] = {
. mask = RK818_IRQ_VB_LO_MSK ,
. reg_offset = 0 ,
} ,
[ RK818_IRQ_PWRON ] = {
. mask = RK818_IRQ_PWRON_MSK ,
. reg_offset = 0 ,
} ,
[ RK818_IRQ_PWRON_LP ] = {
. mask = RK818_IRQ_PWRON_LP_MSK ,
. reg_offset = 0 ,
} ,
[ RK818_IRQ_HOTDIE ] = {
. mask = RK818_IRQ_HOTDIE_MSK ,
. reg_offset = 0 ,
} ,
[ RK818_IRQ_RTC_ALARM ] = {
. mask = RK818_IRQ_RTC_ALARM_MSK ,
. reg_offset = 0 ,
} ,
[ RK818_IRQ_RTC_PERIOD ] = {
. mask = RK818_IRQ_RTC_PERIOD_MSK ,
. reg_offset = 0 ,
} ,
[ RK818_IRQ_USB_OV ] = {
. mask = RK818_IRQ_USB_OV_MSK ,
. reg_offset = 0 ,
} ,
/* INT_STS2 */
[ RK818_IRQ_PLUG_IN ] = {
. mask = RK818_IRQ_PLUG_IN_MSK ,
. reg_offset = 1 ,
} ,
[ RK818_IRQ_PLUG_OUT ] = {
. mask = RK818_IRQ_PLUG_OUT_MSK ,
. reg_offset = 1 ,
} ,
[ RK818_IRQ_CHG_OK ] = {
. mask = RK818_IRQ_CHG_OK_MSK ,
. reg_offset = 1 ,
} ,
[ RK818_IRQ_CHG_TE ] = {
. mask = RK818_IRQ_CHG_TE_MSK ,
. reg_offset = 1 ,
} ,
[ RK818_IRQ_CHG_TS1 ] = {
. mask = RK818_IRQ_CHG_TS1_MSK ,
. reg_offset = 1 ,
} ,
[ RK818_IRQ_TS2 ] = {
. mask = RK818_IRQ_TS2_MSK ,
. reg_offset = 1 ,
} ,
[ RK818_IRQ_CHG_CVTLIM ] = {
. mask = RK818_IRQ_CHG_CVTLIM_MSK ,
. reg_offset = 1 ,
} ,
[ RK818_IRQ_DISCHG_ILIM ] = {
. mask = RK818_IRQ_DISCHG_ILIM_MSK ,
. reg_offset = 1 ,
} ,
} ;
2017-08-21 04:28:38 +03:00
static struct regmap_irq_chip rk805_irq_chip = {
. name = " rk805 " ,
. irqs = rk805_irqs ,
. num_irqs = ARRAY_SIZE ( rk805_irqs ) ,
. num_regs = 1 ,
. status_base = RK805_INT_STS_REG ,
. mask_base = RK805_INT_STS_MSK_REG ,
. ack_base = RK805_INT_STS_REG ,
. init_ack_masked = true ,
} ;
2017-01-24 22:25:24 +03:00
static const struct regmap_irq_chip rk808_irq_chip = {
2014-09-03 17:51:44 +04:00
. name = " rk808 " ,
. irqs = rk808_irqs ,
. num_irqs = ARRAY_SIZE ( rk808_irqs ) ,
. num_regs = 2 ,
. irq_reg_stride = 2 ,
. status_base = RK808_INT_STS_REG1 ,
. mask_base = RK808_INT_STS_MSK_REG1 ,
. ack_base = RK808_INT_STS_REG1 ,
. init_ack_masked = true ,
} ;
2017-01-24 22:25:24 +03:00
static const struct regmap_irq_chip rk818_irq_chip = {
2016-08-29 14:07:58 +03:00
. name = " rk818 " ,
. irqs = rk818_irqs ,
. num_irqs = ARRAY_SIZE ( rk818_irqs ) ,
. num_regs = 2 ,
. irq_reg_stride = 2 ,
. status_base = RK818_INT_STS_REG1 ,
. mask_base = RK818_INT_STS_MSK_REG1 ,
. ack_base = RK818_INT_STS_REG1 ,
. init_ack_masked = true ,
} ;
2014-09-03 17:51:44 +04:00
static struct i2c_client * rk808_i2c_client ;
2017-08-21 04:28:38 +03:00
static void rk805_device_shutdown ( void )
{
int ret ;
struct rk808 * rk808 = i2c_get_clientdata ( rk808_i2c_client ) ;
if ( ! rk808 ) {
dev_warn ( & rk808_i2c_client - > dev ,
" have no rk805, so do nothing here \n " ) ;
return ;
}
ret = regmap_update_bits ( rk808 - > regmap ,
RK805_DEV_CTRL_REG ,
DEV_OFF , DEV_OFF ) ;
if ( ret )
dev_err ( & rk808_i2c_client - > dev , " power off error! \n " ) ;
}
2014-09-03 17:51:44 +04:00
static void rk808_device_shutdown ( void )
{
int ret ;
struct rk808 * rk808 = i2c_get_clientdata ( rk808_i2c_client ) ;
if ( ! rk808 ) {
dev_warn ( & rk808_i2c_client - > dev ,
" have no rk808, so do nothing here \n " ) ;
return ;
}
ret = regmap_update_bits ( rk808 - > regmap ,
RK808_DEVCTRL_REG ,
DEV_OFF_RST , DEV_OFF_RST ) ;
if ( ret )
dev_err ( & rk808_i2c_client - > dev , " power off error! \n " ) ;
}
2016-10-17 12:03:10 +03:00
static void rk818_device_shutdown ( void )
{
int ret ;
struct rk808 * rk808 = i2c_get_clientdata ( rk808_i2c_client ) ;
if ( ! rk808 ) {
dev_warn ( & rk808_i2c_client - > dev ,
" have no rk818, so do nothing here \n " ) ;
return ;
}
ret = regmap_update_bits ( rk808 - > regmap ,
RK818_DEVCTRL_REG ,
DEV_OFF , DEV_OFF ) ;
if ( ret )
dev_err ( & rk808_i2c_client - > dev , " power off error! \n " ) ;
}
2016-08-29 14:07:58 +03:00
static const struct of_device_id rk808_of_match [ ] = {
2017-08-21 04:28:38 +03:00
{ . compatible = " rockchip,rk805 " } ,
2016-08-29 14:07:58 +03:00
{ . compatible = " rockchip,rk808 " } ,
{ . compatible = " rockchip,rk818 " } ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( of , rk808_of_match ) ;
2014-09-03 17:51:44 +04:00
static int rk808_probe ( struct i2c_client * client ,
const struct i2c_device_id * id )
{
struct device_node * np = client - > dev . of_node ;
struct rk808 * rk808 ;
2016-08-29 14:07:58 +03:00
const struct rk808_reg_data * pre_init_reg ;
const struct mfd_cell * cells ;
2016-10-17 12:03:10 +03:00
void ( * pm_pwroff_fn ) ( void ) ;
2016-08-29 14:07:58 +03:00
int nr_pre_init_regs ;
int nr_cells ;
2017-08-21 04:28:34 +03:00
int pm_off = 0 , msb , lsb ;
2014-09-03 17:51:44 +04:00
int ret ;
int i ;
rk808 = devm_kzalloc ( & client - > dev , sizeof ( * rk808 ) , GFP_KERNEL ) ;
if ( ! rk808 )
return - ENOMEM ;
2017-08-21 04:28:34 +03:00
/* Read chip variant */
msb = i2c_smbus_read_byte_data ( client , RK808_ID_MSB ) ;
if ( msb < 0 ) {
dev_err ( & client - > dev , " failed to read the chip id at 0x%x \n " ,
2016-08-29 14:07:58 +03:00
RK808_ID_MSB ) ;
2017-08-21 04:28:34 +03:00
return msb ;
2016-08-29 14:07:58 +03:00
}
2017-08-21 04:28:34 +03:00
lsb = i2c_smbus_read_byte_data ( client , RK808_ID_LSB ) ;
if ( lsb < 0 ) {
dev_err ( & client - > dev , " failed to read the chip id at 0x%x \n " ,
RK808_ID_LSB ) ;
return lsb ;
}
rk808 - > variant = ( ( msb < < 8 ) | lsb ) & RK8XX_ID_MSK ;
dev_info ( & client - > dev , " chip id: 0x%x \n " , ( unsigned int ) rk808 - > variant ) ;
2016-08-29 14:07:58 +03:00
switch ( rk808 - > variant ) {
2017-08-21 04:28:38 +03:00
case RK805_ID :
rk808 - > regmap_cfg = & rk805_regmap_config ;
rk808 - > regmap_irq_chip = & rk805_irq_chip ;
pre_init_reg = rk805_pre_init_reg ;
nr_pre_init_regs = ARRAY_SIZE ( rk805_pre_init_reg ) ;
cells = rk805s ;
nr_cells = ARRAY_SIZE ( rk805s ) ;
pm_pwroff_fn = rk805_device_shutdown ;
break ;
2016-08-29 14:07:58 +03:00
case RK808_ID :
rk808 - > regmap_cfg = & rk808_regmap_config ;
rk808 - > regmap_irq_chip = & rk808_irq_chip ;
pre_init_reg = rk808_pre_init_reg ;
nr_pre_init_regs = ARRAY_SIZE ( rk808_pre_init_reg ) ;
cells = rk808s ;
nr_cells = ARRAY_SIZE ( rk808s ) ;
2016-10-17 12:03:10 +03:00
pm_pwroff_fn = rk808_device_shutdown ;
2016-08-29 14:07:58 +03:00
break ;
case RK818_ID :
rk808 - > regmap_cfg = & rk818_regmap_config ;
rk808 - > regmap_irq_chip = & rk818_irq_chip ;
pre_init_reg = rk818_pre_init_reg ;
nr_pre_init_regs = ARRAY_SIZE ( rk818_pre_init_reg ) ;
cells = rk818s ;
nr_cells = ARRAY_SIZE ( rk818s ) ;
2016-10-17 12:03:10 +03:00
pm_pwroff_fn = rk818_device_shutdown ;
2016-08-29 14:07:58 +03:00
break ;
default :
dev_err ( & client - > dev , " Unsupported RK8XX ID %lu \n " ,
rk808 - > variant ) ;
return - EINVAL ;
}
rk808 - > i2c = client ;
i2c_set_clientdata ( client , rk808 ) ;
rk808 - > regmap = devm_regmap_init_i2c ( client , rk808 - > regmap_cfg ) ;
2014-09-03 17:51:44 +04:00
if ( IS_ERR ( rk808 - > regmap ) ) {
dev_err ( & client - > dev , " regmap initialization failed \n " ) ;
return PTR_ERR ( rk808 - > regmap ) ;
}
2016-08-29 14:07:58 +03:00
if ( ! client - > irq ) {
dev_err ( & client - > dev , " No interrupt support, no core IRQ \n " ) ;
return - EINVAL ;
2014-09-03 17:51:44 +04:00
}
ret = regmap_add_irq_chip ( rk808 - > regmap , client - > irq ,
IRQF_ONESHOT , - 1 ,
2016-08-29 14:07:58 +03:00
rk808 - > regmap_irq_chip , & rk808 - > irq_data ) ;
2014-09-03 17:51:44 +04:00
if ( ret ) {
dev_err ( & client - > dev , " Failed to add irq_chip %d \n " , ret ) ;
return ret ;
}
2016-08-29 14:07:58 +03:00
for ( i = 0 ; i < nr_pre_init_regs ; i + + ) {
ret = regmap_update_bits ( rk808 - > regmap ,
pre_init_reg [ i ] . addr ,
pre_init_reg [ i ] . mask ,
pre_init_reg [ i ] . value ) ;
if ( ret ) {
dev_err ( & client - > dev ,
" 0x%x write err \n " ,
pre_init_reg [ i ] . addr ) ;
return ret ;
}
}
2014-09-03 17:51:44 +04:00
2016-08-29 14:07:58 +03:00
ret = devm_mfd_add_devices ( & client - > dev , PLATFORM_DEVID_NONE ,
cells , nr_cells , NULL , 0 ,
regmap_irq_get_domain ( rk808 - > irq_data ) ) ;
2014-09-03 17:51:44 +04:00
if ( ret ) {
dev_err ( & client - > dev , " failed to add MFD devices %d \n " , ret ) ;
goto err_irq ;
}
pm_off = of_property_read_bool ( np ,
" rockchip,system-power-controller " ) ;
if ( pm_off & & ! pm_power_off ) {
rk808_i2c_client = client ;
2016-10-17 12:03:10 +03:00
pm_power_off = pm_pwroff_fn ;
2014-09-03 17:51:44 +04:00
}
return 0 ;
err_irq :
regmap_del_irq_chip ( client - > irq , rk808 - > irq_data ) ;
return ret ;
}
static int rk808_remove ( struct i2c_client * client )
{
struct rk808 * rk808 = i2c_get_clientdata ( client ) ;
regmap_del_irq_chip ( client - > irq , rk808 - > irq_data ) ;
pm_power_off = NULL ;
return 0 ;
}
static const struct i2c_device_id rk808_ids [ ] = {
2017-08-21 04:28:38 +03:00
{ " rk805 " } ,
2014-09-03 17:51:44 +04:00
{ " rk808 " } ,
2016-08-29 14:07:58 +03:00
{ " rk818 " } ,
2014-09-03 17:51:44 +04:00
{ } ,
} ;
MODULE_DEVICE_TABLE ( i2c , rk808_ids ) ;
static struct i2c_driver rk808_i2c_driver = {
. driver = {
. name = " rk808 " ,
. of_match_table = rk808_of_match ,
} ,
. probe = rk808_probe ,
. remove = rk808_remove ,
. id_table = rk808_ids ,
} ;
module_i2c_driver ( rk808_i2c_driver ) ;
MODULE_LICENSE ( " GPL " ) ;
MODULE_AUTHOR ( " Chris Zhong <zyw@rock-chips.com> " ) ;
MODULE_AUTHOR ( " Zhang Qing <zhangqing@rock-chips.com> " ) ;
2016-08-29 14:07:58 +03:00
MODULE_AUTHOR ( " Wadim Egorov <w.egorov@phytec.de> " ) ;
MODULE_DESCRIPTION ( " RK808/RK818 PMIC driver " ) ;