2019-06-03 10:27:14 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
//
// Copyright (C) 2018 ROHM Semiconductors
//
// RTC driver for ROHM BD70528 PMIC
# include <linux/bcd.h>
# include <linux/mfd/rohm-bd70528.h>
2020-01-20 15:45:36 +02:00
# include <linux/mfd/rohm-bd71828.h>
2019-06-03 10:27:14 +03:00
# include <linux/module.h>
# include <linux/of.h>
# include <linux/platform_device.h>
# include <linux/regmap.h>
# include <linux/rtc.h>
/*
* We read regs RTC_SEC = > RTC_YEAR
* this struct is ordered according to chip registers .
2020-01-20 15:45:36 +02:00
* Keep it u8 only ( or packed ) to avoid padding issues .
2019-06-03 10:27:14 +03:00
*/
struct bd70528_rtc_day {
u8 sec ;
u8 min ;
u8 hour ;
} __packed ;
struct bd70528_rtc_data {
struct bd70528_rtc_day time ;
u8 week ;
u8 day ;
u8 month ;
u8 year ;
} __packed ;
struct bd70528_rtc_wake {
struct bd70528_rtc_day time ;
u8 ctrl ;
} __packed ;
2020-01-20 15:45:36 +02:00
struct bd71828_rtc_alm {
struct bd70528_rtc_data alm0 ;
struct bd70528_rtc_data alm1 ;
u8 alm_mask ;
u8 alm1_mask ;
} __packed ;
2019-06-03 10:27:14 +03:00
struct bd70528_rtc_alm {
struct bd70528_rtc_data data ;
u8 alm_mask ;
u8 alm_repeat ;
} __packed ;
struct bd70528_rtc {
2020-01-20 15:45:36 +02:00
struct rohm_regmap_dev * parent ;
2019-06-03 10:27:14 +03:00
struct device * dev ;
2020-01-20 15:45:36 +02:00
u8 reg_time_start ;
bool has_rtc_timers ;
2019-06-03 10:27:14 +03:00
} ;
static int bd70528_set_wake ( struct rohm_regmap_dev * bd70528 ,
int enable , int * old_state )
{
int ret ;
unsigned int ctrl_reg ;
ret = regmap_read ( bd70528 - > regmap , BD70528_REG_WAKE_EN , & ctrl_reg ) ;
if ( ret )
return ret ;
if ( old_state ) {
if ( ctrl_reg & BD70528_MASK_WAKE_EN )
* old_state | = BD70528_WAKE_STATE_BIT ;
else
* old_state & = ~ BD70528_WAKE_STATE_BIT ;
if ( ! enable = = ! ( * old_state & BD70528_WAKE_STATE_BIT ) )
return 0 ;
}
if ( enable )
ctrl_reg | = BD70528_MASK_WAKE_EN ;
else
ctrl_reg & = ~ BD70528_MASK_WAKE_EN ;
return regmap_write ( bd70528 - > regmap , BD70528_REG_WAKE_EN ,
ctrl_reg ) ;
}
static int bd70528_set_elapsed_tmr ( struct rohm_regmap_dev * bd70528 ,
int enable , int * old_state )
{
int ret ;
unsigned int ctrl_reg ;
/*
* TBD
* What is the purpose of elapsed timer ?
* Is the timeout registers counting down , or is the disable - re - enable
* going to restart the elapsed - time counting ? If counting is restarted
* the timeout should be decreased by the amount of time that has
* elapsed since starting the timer . Maybe we should store the monotonic
* clock value when timer is started so that if RTC is set while timer
* is armed we could do the compensation . This is a hack if RTC / system
* clk are drifting . OTOH , RTC controlled via I2C is in any case
* inaccurate . . .
*/
ret = regmap_read ( bd70528 - > regmap , BD70528_REG_ELAPSED_TIMER_EN ,
& ctrl_reg ) ;
if ( ret )
return ret ;
if ( old_state ) {
if ( ctrl_reg & BD70528_MASK_ELAPSED_TIMER_EN )
* old_state | = BD70528_ELAPSED_STATE_BIT ;
else
* old_state & = ~ BD70528_ELAPSED_STATE_BIT ;
if ( ( ! enable ) = = ( ! ( * old_state & BD70528_ELAPSED_STATE_BIT ) ) )
return 0 ;
}
if ( enable )
ctrl_reg | = BD70528_MASK_ELAPSED_TIMER_EN ;
else
ctrl_reg & = ~ BD70528_MASK_ELAPSED_TIMER_EN ;
return regmap_write ( bd70528 - > regmap , BD70528_REG_ELAPSED_TIMER_EN ,
ctrl_reg ) ;
}
static int bd70528_set_rtc_based_timers ( struct bd70528_rtc * r , int new_state ,
int * old_state )
{
int ret ;
2020-01-20 15:45:36 +02:00
ret = bd70528_wdt_set ( r - > parent , new_state & BD70528_WDT_STATE_BIT ,
2019-06-03 10:27:14 +03:00
old_state ) ;
if ( ret ) {
dev_err ( r - > dev ,
" Failed to disable WDG for RTC setting (%d) \n " , ret ) ;
return ret ;
}
2020-01-20 15:45:36 +02:00
ret = bd70528_set_elapsed_tmr ( r - > parent ,
2019-06-03 10:27:14 +03:00
new_state & BD70528_ELAPSED_STATE_BIT ,
old_state ) ;
if ( ret ) {
dev_err ( r - > dev ,
" Failed to disable 'elapsed timer' for RTC setting \n " ) ;
return ret ;
}
2020-01-20 15:45:36 +02:00
ret = bd70528_set_wake ( r - > parent , new_state & BD70528_WAKE_STATE_BIT ,
2019-06-03 10:27:14 +03:00
old_state ) ;
if ( ret ) {
dev_err ( r - > dev ,
" Failed to disable 'wake timer' for RTC setting \n " ) ;
return ret ;
}
return ret ;
}
static int bd70528_re_enable_rtc_based_timers ( struct bd70528_rtc * r ,
int old_state )
{
2020-01-20 15:45:36 +02:00
if ( ! r - > has_rtc_timers )
return 0 ;
2019-06-03 10:27:14 +03:00
return bd70528_set_rtc_based_timers ( r , old_state , NULL ) ;
}
static int bd70528_disable_rtc_based_timers ( struct bd70528_rtc * r ,
int * old_state )
{
2020-01-20 15:45:36 +02:00
if ( ! r - > has_rtc_timers )
return 0 ;
2019-06-03 10:27:14 +03:00
return bd70528_set_rtc_based_timers ( r , 0 , old_state ) ;
}
static inline void tmday2rtc ( struct rtc_time * t , struct bd70528_rtc_day * d )
{
d - > sec & = ~ BD70528_MASK_RTC_SEC ;
d - > min & = ~ BD70528_MASK_RTC_MINUTE ;
d - > hour & = ~ BD70528_MASK_RTC_HOUR ;
d - > sec | = bin2bcd ( t - > tm_sec ) ;
d - > min | = bin2bcd ( t - > tm_min ) ;
d - > hour | = bin2bcd ( t - > tm_hour ) ;
}
static inline void tm2rtc ( struct rtc_time * t , struct bd70528_rtc_data * r )
{
r - > day & = ~ BD70528_MASK_RTC_DAY ;
r - > week & = ~ BD70528_MASK_RTC_WEEK ;
r - > month & = ~ BD70528_MASK_RTC_MONTH ;
/*
* PM and 24 H bits are not used by Wake - thus we clear them
* here and not in tmday2rtc ( ) which is also used by wake .
*/
r - > time . hour & = ~ ( BD70528_MASK_RTC_HOUR_PM | BD70528_MASK_RTC_HOUR_24H ) ;
tmday2rtc ( t , & r - > time ) ;
/*
* We do always set time in 24 H mode .
*/
r - > time . hour | = BD70528_MASK_RTC_HOUR_24H ;
r - > day | = bin2bcd ( t - > tm_mday ) ;
r - > week | = bin2bcd ( t - > tm_wday ) ;
r - > month | = bin2bcd ( t - > tm_mon + 1 ) ;
r - > year = bin2bcd ( t - > tm_year - 100 ) ;
}
static inline void rtc2tm ( struct bd70528_rtc_data * r , struct rtc_time * t )
{
t - > tm_sec = bcd2bin ( r - > time . sec & BD70528_MASK_RTC_SEC ) ;
t - > tm_min = bcd2bin ( r - > time . min & BD70528_MASK_RTC_MINUTE ) ;
t - > tm_hour = bcd2bin ( r - > time . hour & BD70528_MASK_RTC_HOUR ) ;
/*
* If RTC is in 12 H mode , then bit BD70528_MASK_RTC_HOUR_PM
* is not BCD value but tells whether it is AM or PM
*/
if ( ! ( r - > time . hour & BD70528_MASK_RTC_HOUR_24H ) ) {
t - > tm_hour % = 12 ;
if ( r - > time . hour & BD70528_MASK_RTC_HOUR_PM )
t - > tm_hour + = 12 ;
}
t - > tm_mday = bcd2bin ( r - > day & BD70528_MASK_RTC_DAY ) ;
t - > tm_mon = bcd2bin ( r - > month & BD70528_MASK_RTC_MONTH ) - 1 ;
t - > tm_year = 100 + bcd2bin ( r - > year & BD70528_MASK_RTC_YEAR ) ;
t - > tm_wday = bcd2bin ( r - > week & BD70528_MASK_RTC_WEEK ) ;
}
2020-01-20 15:45:36 +02:00
static int bd71828_set_alarm ( struct device * dev , struct rtc_wkalrm * a )
{
int ret ;
struct bd71828_rtc_alm alm ;
struct bd70528_rtc * r = dev_get_drvdata ( dev ) ;
struct rohm_regmap_dev * parent = r - > parent ;
ret = regmap_bulk_read ( parent - > regmap , BD71828_REG_RTC_ALM_START ,
& alm , sizeof ( alm ) ) ;
if ( ret ) {
dev_err ( dev , " Failed to read alarm regs \n " ) ;
return ret ;
}
tm2rtc ( & a - > time , & alm . alm0 ) ;
if ( ! a - > enabled )
alm . alm_mask & = ~ BD70528_MASK_ALM_EN ;
else
alm . alm_mask | = BD70528_MASK_ALM_EN ;
ret = regmap_bulk_write ( parent - > regmap , BD71828_REG_RTC_ALM_START ,
& alm , sizeof ( alm ) ) ;
if ( ret )
dev_err ( dev , " Failed to set alarm time \n " ) ;
return ret ;
}
2019-06-03 10:27:14 +03:00
static int bd70528_set_alarm ( struct device * dev , struct rtc_wkalrm * a )
{
struct bd70528_rtc_wake wake ;
struct bd70528_rtc_alm alm ;
int ret ;
struct bd70528_rtc * r = dev_get_drvdata ( dev ) ;
2020-01-20 15:45:36 +02:00
struct rohm_regmap_dev * parent = r - > parent ;
2019-06-03 10:27:14 +03:00
2020-01-20 15:45:36 +02:00
ret = regmap_bulk_read ( parent - > regmap , BD70528_REG_RTC_WAKE_START ,
2019-06-03 10:27:14 +03:00
& wake , sizeof ( wake ) ) ;
if ( ret ) {
dev_err ( dev , " Failed to read wake regs \n " ) ;
return ret ;
}
2020-01-20 15:45:36 +02:00
ret = regmap_bulk_read ( parent - > regmap , BD70528_REG_RTC_ALM_START ,
2019-06-03 10:27:14 +03:00
& alm , sizeof ( alm ) ) ;
if ( ret ) {
dev_err ( dev , " Failed to read alarm regs \n " ) ;
return ret ;
}
tm2rtc ( & a - > time , & alm . data ) ;
tmday2rtc ( & a - > time , & wake . time ) ;
if ( a - > enabled ) {
alm . alm_mask & = ~ BD70528_MASK_ALM_EN ;
wake . ctrl | = BD70528_MASK_WAKE_EN ;
} else {
alm . alm_mask | = BD70528_MASK_ALM_EN ;
wake . ctrl & = ~ BD70528_MASK_WAKE_EN ;
}
2020-01-20 15:45:36 +02:00
ret = regmap_bulk_write ( parent - > regmap ,
2019-06-03 10:27:14 +03:00
BD70528_REG_RTC_WAKE_START , & wake ,
sizeof ( wake ) ) ;
if ( ret ) {
dev_err ( dev , " Failed to set wake time \n " ) ;
return ret ;
}
2020-01-20 15:45:36 +02:00
ret = regmap_bulk_write ( parent - > regmap , BD70528_REG_RTC_ALM_START ,
2019-06-03 10:27:14 +03:00
& alm , sizeof ( alm ) ) ;
if ( ret )
dev_err ( dev , " Failed to set alarm time \n " ) ;
return ret ;
}
2020-01-20 15:45:36 +02:00
static int bd71828_read_alarm ( struct device * dev , struct rtc_wkalrm * a )
{
int ret ;
struct bd71828_rtc_alm alm ;
struct bd70528_rtc * r = dev_get_drvdata ( dev ) ;
struct rohm_regmap_dev * parent = r - > parent ;
ret = regmap_bulk_read ( parent - > regmap , BD71828_REG_RTC_ALM_START ,
& alm , sizeof ( alm ) ) ;
if ( ret ) {
dev_err ( dev , " Failed to read alarm regs \n " ) ;
return ret ;
}
rtc2tm ( & alm . alm0 , & a - > time ) ;
a - > time . tm_mday = - 1 ;
a - > time . tm_mon = - 1 ;
a - > time . tm_year = - 1 ;
a - > enabled = ! ! ( alm . alm_mask & BD70528_MASK_ALM_EN ) ;
a - > pending = 0 ;
return 0 ;
}
2019-06-03 10:27:14 +03:00
static int bd70528_read_alarm ( struct device * dev , struct rtc_wkalrm * a )
{
struct bd70528_rtc_alm alm ;
int ret ;
struct bd70528_rtc * r = dev_get_drvdata ( dev ) ;
2020-01-20 15:45:36 +02:00
struct rohm_regmap_dev * parent = r - > parent ;
2019-06-03 10:27:14 +03:00
2020-01-20 15:45:36 +02:00
ret = regmap_bulk_read ( parent - > regmap , BD70528_REG_RTC_ALM_START ,
2019-06-03 10:27:14 +03:00
& alm , sizeof ( alm ) ) ;
if ( ret ) {
dev_err ( dev , " Failed to read alarm regs \n " ) ;
return ret ;
}
rtc2tm ( & alm . data , & a - > time ) ;
a - > time . tm_mday = - 1 ;
a - > time . tm_mon = - 1 ;
a - > time . tm_year = - 1 ;
a - > enabled = ! ( alm . alm_mask & BD70528_MASK_ALM_EN ) ;
a - > pending = 0 ;
return 0 ;
}
static int bd70528_set_time_locked ( struct device * dev , struct rtc_time * t )
{
int ret , tmpret , old_states ;
struct bd70528_rtc_data rtc_data ;
struct bd70528_rtc * r = dev_get_drvdata ( dev ) ;
2020-01-20 15:45:36 +02:00
struct rohm_regmap_dev * parent = r - > parent ;
2019-06-03 10:27:14 +03:00
ret = bd70528_disable_rtc_based_timers ( r , & old_states ) ;
if ( ret )
return ret ;
2020-01-20 15:45:36 +02:00
tmpret = regmap_bulk_read ( parent - > regmap ,
r - > reg_time_start , & rtc_data ,
2019-06-03 10:27:14 +03:00
sizeof ( rtc_data ) ) ;
if ( tmpret ) {
dev_err ( dev , " Failed to read RTC time registers \n " ) ;
goto renable_out ;
}
tm2rtc ( t , & rtc_data ) ;
2020-01-20 15:45:36 +02:00
tmpret = regmap_bulk_write ( parent - > regmap ,
r - > reg_time_start , & rtc_data ,
2019-06-03 10:27:14 +03:00
sizeof ( rtc_data ) ) ;
if ( tmpret ) {
dev_err ( dev , " Failed to set RTC time \n " ) ;
goto renable_out ;
}
renable_out :
ret = bd70528_re_enable_rtc_based_timers ( r , old_states ) ;
if ( tmpret )
ret = tmpret ;
return ret ;
}
2020-01-20 15:45:36 +02:00
static int bd71828_set_time ( struct device * dev , struct rtc_time * t )
{
return bd70528_set_time_locked ( dev , t ) ;
}
2019-06-03 10:27:14 +03:00
static int bd70528_set_time ( struct device * dev , struct rtc_time * t )
{
int ret ;
struct bd70528_rtc * r = dev_get_drvdata ( dev ) ;
2020-01-20 15:45:36 +02:00
bd70528_wdt_lock ( r - > parent ) ;
2019-06-03 10:27:14 +03:00
ret = bd70528_set_time_locked ( dev , t ) ;
2020-01-20 15:45:36 +02:00
bd70528_wdt_unlock ( r - > parent ) ;
2019-06-03 10:27:14 +03:00
return ret ;
}
static int bd70528_get_time ( struct device * dev , struct rtc_time * t )
{
struct bd70528_rtc * r = dev_get_drvdata ( dev ) ;
2020-01-20 15:45:36 +02:00
struct rohm_regmap_dev * parent = r - > parent ;
2019-06-03 10:27:14 +03:00
struct bd70528_rtc_data rtc_data ;
int ret ;
/* read the RTC date and time registers all at once */
2020-01-20 15:45:36 +02:00
ret = regmap_bulk_read ( parent - > regmap ,
r - > reg_time_start , & rtc_data ,
2019-06-03 10:27:14 +03:00
sizeof ( rtc_data ) ) ;
if ( ret ) {
dev_err ( dev , " Failed to read RTC time (err %d) \n " , ret ) ;
return ret ;
}
rtc2tm ( & rtc_data , t ) ;
return 0 ;
}
static int bd70528_alm_enable ( struct device * dev , unsigned int enabled )
{
int ret ;
unsigned int enableval = BD70528_MASK_ALM_EN ;
struct bd70528_rtc * r = dev_get_drvdata ( dev ) ;
if ( enabled )
enableval = 0 ;
2020-01-20 15:45:36 +02:00
bd70528_wdt_lock ( r - > parent ) ;
ret = bd70528_set_wake ( r - > parent , enabled , NULL ) ;
2019-06-03 10:27:14 +03:00
if ( ret ) {
dev_err ( dev , " Failed to change wake state \n " ) ;
goto out_unlock ;
}
2020-01-20 15:45:36 +02:00
ret = regmap_update_bits ( r - > parent - > regmap , BD70528_REG_RTC_ALM_MASK ,
2019-06-03 10:27:14 +03:00
BD70528_MASK_ALM_EN , enableval ) ;
if ( ret )
dev_err ( dev , " Failed to change alarm state \n " ) ;
out_unlock :
2020-01-20 15:45:36 +02:00
bd70528_wdt_unlock ( r - > parent ) ;
return ret ;
}
static int bd71828_alm_enable ( struct device * dev , unsigned int enabled )
{
int ret ;
struct bd70528_rtc * r = dev_get_drvdata ( dev ) ;
unsigned int enableval = BD70528_MASK_ALM_EN ;
if ( ! enabled )
enableval = 0 ;
ret = regmap_update_bits ( r - > parent - > regmap , BD71828_REG_RTC_ALM0_MASK ,
BD70528_MASK_ALM_EN , enableval ) ;
if ( ret )
dev_err ( dev , " Failed to change alarm state \n " ) ;
2019-06-03 10:27:14 +03:00
return ret ;
}
static const struct rtc_class_ops bd70528_rtc_ops = {
. read_time = bd70528_get_time ,
. set_time = bd70528_set_time ,
. read_alarm = bd70528_read_alarm ,
. set_alarm = bd70528_set_alarm ,
. alarm_irq_enable = bd70528_alm_enable ,
} ;
2020-01-20 15:45:36 +02:00
static const struct rtc_class_ops bd71828_rtc_ops = {
. read_time = bd70528_get_time ,
. set_time = bd71828_set_time ,
. read_alarm = bd71828_read_alarm ,
. set_alarm = bd71828_set_alarm ,
. alarm_irq_enable = bd71828_alm_enable ,
} ;
2019-06-03 10:27:14 +03:00
static irqreturn_t alm_hndlr ( int irq , void * data )
{
struct rtc_device * rtc = data ;
rtc_update_irq ( rtc , 1 , RTC_IRQF | RTC_AF | RTC_PF ) ;
return IRQ_HANDLED ;
}
static int bd70528_probe ( struct platform_device * pdev )
{
struct bd70528_rtc * bd_rtc ;
2020-01-20 15:45:36 +02:00
const struct rtc_class_ops * rtc_ops ;
struct rohm_regmap_dev * parent ;
const char * irq_name ;
2019-06-03 10:27:14 +03:00
int ret ;
struct rtc_device * rtc ;
int irq ;
unsigned int hr ;
2020-01-20 15:45:36 +02:00
bool enable_main_irq = false ;
u8 hour_reg ;
enum rohm_chip_type chip = platform_get_device_id ( pdev ) - > driver_data ;
2019-06-03 10:27:14 +03:00
2020-01-20 15:45:36 +02:00
parent = dev_get_drvdata ( pdev - > dev . parent ) ;
if ( ! parent ) {
2019-06-03 10:27:14 +03:00
dev_err ( & pdev - > dev , " No MFD driver data \n " ) ;
return - EINVAL ;
}
bd_rtc = devm_kzalloc ( & pdev - > dev , sizeof ( * bd_rtc ) , GFP_KERNEL ) ;
if ( ! bd_rtc )
return - ENOMEM ;
2020-01-20 15:45:36 +02:00
bd_rtc - > parent = parent ;
2019-06-03 10:27:14 +03:00
bd_rtc - > dev = & pdev - > dev ;
2020-01-20 15:45:36 +02:00
switch ( chip ) {
case ROHM_CHIP_TYPE_BD70528 :
irq_name = " bd70528-rtc-alm " ;
bd_rtc - > has_rtc_timers = true ;
bd_rtc - > reg_time_start = BD70528_REG_RTC_START ;
hour_reg = BD70528_REG_RTC_HOUR ;
enable_main_irq = true ;
rtc_ops = & bd70528_rtc_ops ;
break ;
case ROHM_CHIP_TYPE_BD71828 :
irq_name = " bd71828-rtc-alm-0 " ;
bd_rtc - > reg_time_start = BD71828_REG_RTC_START ;
hour_reg = BD71828_REG_RTC_HOUR ;
rtc_ops = & bd71828_rtc_ops ;
break ;
default :
dev_err ( & pdev - > dev , " Unknown chip \n " ) ;
return - ENOENT ;
}
irq = platform_get_irq_byname ( pdev , irq_name ) ;
2020-03-21 14:08:37 -04:00
if ( irq < 0 )
2019-06-03 10:27:14 +03:00
return irq ;
platform_set_drvdata ( pdev , bd_rtc ) ;
2020-01-20 15:45:36 +02:00
ret = regmap_read ( parent - > regmap , hour_reg , & hr ) ;
2019-06-03 10:27:14 +03:00
if ( ret ) {
dev_err ( & pdev - > dev , " Failed to reag RTC clock \n " ) ;
return ret ;
}
if ( ! ( hr & BD70528_MASK_RTC_HOUR_24H ) ) {
struct rtc_time t ;
2020-01-20 15:45:36 +02:00
ret = rtc_ops - > read_time ( & pdev - > dev , & t ) ;
2019-06-03 10:27:14 +03:00
if ( ! ret )
2020-01-20 15:45:36 +02:00
ret = rtc_ops - > set_time ( & pdev - > dev , & t ) ;
2019-06-03 10:27:14 +03:00
if ( ret ) {
dev_err ( & pdev - > dev ,
" Setting 24H clock for RTC failed \n " ) ;
return ret ;
}
}
device_set_wakeup_capable ( & pdev - > dev , true ) ;
device_wakeup_enable ( & pdev - > dev ) ;
rtc = devm_rtc_allocate_device ( & pdev - > dev ) ;
if ( IS_ERR ( rtc ) ) {
dev_err ( & pdev - > dev , " RTC device creation failed \n " ) ;
return PTR_ERR ( rtc ) ;
}
rtc - > range_min = RTC_TIMESTAMP_BEGIN_2000 ;
rtc - > range_max = RTC_TIMESTAMP_END_2099 ;
2020-01-20 15:45:36 +02:00
rtc - > ops = rtc_ops ;
2019-06-03 10:27:14 +03:00
/* Request alarm IRQ prior to registerig the RTC */
ret = devm_request_threaded_irq ( & pdev - > dev , irq , NULL , & alm_hndlr ,
IRQF_ONESHOT , " bd70528-rtc " , rtc ) ;
if ( ret )
return ret ;
/*
* BD70528 irq controller is not touching the main mask register .
* So enable the RTC block interrupts at main level . We can just
* leave them enabled as irq - controller should disable irqs
* from sub - registers when IRQ is disabled or freed .
*/
2020-01-20 15:45:36 +02:00
if ( enable_main_irq ) {
ret = regmap_update_bits ( parent - > regmap ,
2019-06-03 10:27:14 +03:00
BD70528_REG_INT_MAIN_MASK ,
BD70528_INT_RTC_MASK , 0 ) ;
2020-01-20 15:45:36 +02:00
if ( ret ) {
dev_err ( & pdev - > dev , " Failed to enable RTC interrupts \n " ) ;
return ret ;
}
2019-06-03 10:27:14 +03:00
}
2019-08-19 00:00:41 +02:00
return rtc_register_device ( rtc ) ;
2019-06-03 10:27:14 +03:00
}
2020-01-20 15:45:36 +02:00
static const struct platform_device_id bd718x7_rtc_id [ ] = {
{ " bd70528-rtc " , ROHM_CHIP_TYPE_BD70528 } ,
{ " bd71828-rtc " , ROHM_CHIP_TYPE_BD71828 } ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( platform , bd718x7_rtc_id ) ;
2019-06-03 10:27:14 +03:00
static struct platform_driver bd70528_rtc = {
. driver = {
. name = " bd70528-rtc "
} ,
. probe = bd70528_probe ,
2020-01-20 15:45:36 +02:00
. id_table = bd718x7_rtc_id ,
2019-06-03 10:27:14 +03:00
} ;
module_platform_driver ( bd70528_rtc ) ;
MODULE_AUTHOR ( " Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com> " ) ;
2020-01-20 15:45:36 +02:00
MODULE_DESCRIPTION ( " ROHM BD70528 and BD71828 PMIC RTC driver " ) ;
2019-06-03 10:27:14 +03:00
MODULE_LICENSE ( " GPL " ) ;
2019-11-06 08:34:18 +00:00
MODULE_ALIAS ( " platform:bd70528-rtc " ) ;