2019-03-04 22:12:17 +03:00
// SPDX-License-Identifier: GPL-2.0
2015-11-03 01:48:32 +03:00
/*
* RTC driver for the Micro Crystal RV8803
*
* Copyright ( C ) 2015 Micro Crystal SA
2019-03-04 22:17:38 +03:00
* Alexandre Belloni < alexandre . belloni @ bootlin . com >
2015-11-03 01:48:32 +03:00
*
*/
# include <linux/bcd.h>
# include <linux/bitops.h>
2016-07-21 13:41:29 +03:00
# include <linux/log2.h>
2015-11-03 01:48:32 +03:00
# include <linux/i2c.h>
# include <linux/interrupt.h>
# include <linux/kernel.h>
# include <linux/module.h>
2017-03-03 17:29:12 +03:00
# include <linux/of_device.h>
2015-11-03 01:48:32 +03:00
# include <linux/rtc.h>
2016-07-21 13:41:30 +03:00
# define RV8803_I2C_TRY_COUNT 4
2015-11-03 01:48:32 +03:00
# define RV8803_SEC 0x00
# define RV8803_MIN 0x01
# define RV8803_HOUR 0x02
# define RV8803_WEEK 0x03
# define RV8803_DAY 0x04
# define RV8803_MONTH 0x05
# define RV8803_YEAR 0x06
# define RV8803_RAM 0x07
# define RV8803_ALARM_MIN 0x08
# define RV8803_ALARM_HOUR 0x09
# define RV8803_ALARM_WEEK_OR_DAY 0x0A
# define RV8803_EXT 0x0D
# define RV8803_FLAG 0x0E
# define RV8803_CTRL 0x0F
# define RV8803_EXT_WADA BIT(6)
# define RV8803_FLAG_V1F BIT(0)
# define RV8803_FLAG_V2F BIT(1)
# define RV8803_FLAG_AF BIT(3)
# define RV8803_FLAG_TF BIT(4)
# define RV8803_FLAG_UF BIT(5)
# define RV8803_CTRL_RESET BIT(0)
# define RV8803_CTRL_EIE BIT(2)
# define RV8803_CTRL_AIE BIT(3)
# define RV8803_CTRL_TIE BIT(4)
# define RV8803_CTRL_UIE BIT(5)
2016-06-29 17:40:01 +03:00
# define RX8900_BACKUP_CTRL 0x18
# define RX8900_FLAG_SWOFF BIT(2)
# define RX8900_FLAG_VDETOFF BIT(3)
enum rv8803_type {
rv_8803 ,
2021-11-30 15:58:30 +03:00
rx_8804 ,
2016-06-29 17:40:01 +03:00
rx_8900
} ;
2015-11-03 01:48:32 +03:00
struct rv8803_data {
struct i2c_client * client ;
struct rtc_device * rtc ;
2016-02-04 15:45:20 +03:00
struct mutex flags_lock ;
2015-11-03 01:48:32 +03:00
u8 ctrl ;
2016-06-29 17:40:01 +03:00
enum rv8803_type type ;
2015-11-03 01:48:32 +03:00
} ;
2016-07-21 13:41:30 +03:00
static int rv8803_read_reg ( const struct i2c_client * client , u8 reg )
{
int try = RV8803_I2C_TRY_COUNT ;
s32 ret ;
/*
* There is a 61 µ s window during which the RTC does not acknowledge I2C
* transfers . In that case , ensure that there are multiple attempts .
*/
do
ret = i2c_smbus_read_byte_data ( client , reg ) ;
while ( ( ret = = - ENXIO | | ret = = - EIO ) & & - - try ) ;
if ( ret < 0 )
dev_err ( & client - > dev , " Unable to read register 0x%02x \n " , reg ) ;
return ret ;
}
static int rv8803_read_regs ( const struct i2c_client * client ,
u8 reg , u8 count , u8 * values )
{
int try = RV8803_I2C_TRY_COUNT ;
s32 ret ;
do
ret = i2c_smbus_read_i2c_block_data ( client , reg , count , values ) ;
while ( ( ret = = - ENXIO | | ret = = - EIO ) & & - - try ) ;
if ( ret ! = count ) {
dev_err ( & client - > dev ,
" Unable to read registers 0x%02x..0x%02x \n " ,
reg , reg + count - 1 ) ;
return ret < 0 ? ret : - EIO ;
}
return 0 ;
}
static int rv8803_write_reg ( const struct i2c_client * client , u8 reg , u8 value )
{
int try = RV8803_I2C_TRY_COUNT ;
s32 ret ;
do
ret = i2c_smbus_write_byte_data ( client , reg , value ) ;
while ( ( ret = = - ENXIO | | ret = = - EIO ) & & - - try ) ;
if ( ret )
dev_err ( & client - > dev , " Unable to write register 0x%02x \n " , reg ) ;
return ret ;
}
static int rv8803_write_regs ( const struct i2c_client * client ,
u8 reg , u8 count , const u8 * values )
{
int try = RV8803_I2C_TRY_COUNT ;
s32 ret ;
do
ret = i2c_smbus_write_i2c_block_data ( client , reg , count ,
values ) ;
while ( ( ret = = - ENXIO | | ret = = - EIO ) & & - - try ) ;
if ( ret )
dev_err ( & client - > dev ,
" Unable to write registers 0x%02x..0x%02x \n " ,
reg , reg + count - 1 ) ;
return ret ;
}
2015-11-03 01:48:32 +03:00
static irqreturn_t rv8803_handle_irq ( int irq , void * dev_id )
{
struct i2c_client * client = dev_id ;
struct rv8803_data * rv8803 = i2c_get_clientdata ( client ) ;
unsigned long events = 0 ;
2016-07-21 13:41:30 +03:00
int flags ;
2015-11-03 01:48:32 +03:00
2016-02-04 15:45:20 +03:00
mutex_lock ( & rv8803 - > flags_lock ) ;
2015-11-03 01:48:32 +03:00
2016-07-21 13:41:30 +03:00
flags = rv8803_read_reg ( client , RV8803_FLAG ) ;
2015-11-03 01:48:32 +03:00
if ( flags < = 0 ) {
2016-02-04 15:45:20 +03:00
mutex_unlock ( & rv8803 - > flags_lock ) ;
2015-11-03 01:48:32 +03:00
return IRQ_NONE ;
}
if ( flags & RV8803_FLAG_V1F )
dev_warn ( & client - > dev , " Voltage low, temperature compensation stopped. \n " ) ;
if ( flags & RV8803_FLAG_V2F )
dev_warn ( & client - > dev , " Voltage low, data loss detected. \n " ) ;
if ( flags & RV8803_FLAG_TF ) {
flags & = ~ RV8803_FLAG_TF ;
rv8803 - > ctrl & = ~ RV8803_CTRL_TIE ;
events | = RTC_PF ;
}
if ( flags & RV8803_FLAG_AF ) {
flags & = ~ RV8803_FLAG_AF ;
rv8803 - > ctrl & = ~ RV8803_CTRL_AIE ;
events | = RTC_AF ;
}
if ( flags & RV8803_FLAG_UF ) {
flags & = ~ RV8803_FLAG_UF ;
rv8803 - > ctrl & = ~ RV8803_CTRL_UIE ;
events | = RTC_UF ;
}
if ( events ) {
rtc_update_irq ( rv8803 - > rtc , 1 , events ) ;
2016-07-21 13:41:30 +03:00
rv8803_write_reg ( client , RV8803_FLAG , flags ) ;
rv8803_write_reg ( rv8803 - > client , RV8803_CTRL , rv8803 - > ctrl ) ;
2015-11-03 01:48:32 +03:00
}
2016-02-04 15:45:20 +03:00
mutex_unlock ( & rv8803 - > flags_lock ) ;
2015-11-03 01:48:32 +03:00
return IRQ_HANDLED ;
}
static int rv8803_get_time ( struct device * dev , struct rtc_time * tm )
{
struct rv8803_data * rv8803 = dev_get_drvdata ( dev ) ;
u8 date1 [ 7 ] ;
u8 date2 [ 7 ] ;
u8 * date = date1 ;
int ret , flags ;
2016-07-21 13:41:30 +03:00
flags = rv8803_read_reg ( rv8803 - > client , RV8803_FLAG ) ;
2015-11-03 01:48:32 +03:00
if ( flags < 0 )
return flags ;
if ( flags & RV8803_FLAG_V2F ) {
dev_warn ( dev , " Voltage low, data is invalid. \n " ) ;
return - EINVAL ;
}
2016-07-21 13:41:30 +03:00
ret = rv8803_read_regs ( rv8803 - > client , RV8803_SEC , 7 , date ) ;
if ( ret )
return ret ;
2015-11-03 01:48:32 +03:00
if ( ( date1 [ RV8803_SEC ] & 0x7f ) = = bin2bcd ( 59 ) ) {
2016-07-21 13:41:30 +03:00
ret = rv8803_read_regs ( rv8803 - > client , RV8803_SEC , 7 , date2 ) ;
if ( ret )
return ret ;
2015-11-03 01:48:32 +03:00
if ( ( date2 [ RV8803_SEC ] & 0x7f ) ! = bin2bcd ( 59 ) )
date = date2 ;
}
tm - > tm_sec = bcd2bin ( date [ RV8803_SEC ] & 0x7f ) ;
tm - > tm_min = bcd2bin ( date [ RV8803_MIN ] & 0x7f ) ;
tm - > tm_hour = bcd2bin ( date [ RV8803_HOUR ] & 0x3f ) ;
2016-07-21 13:41:29 +03:00
tm - > tm_wday = ilog2 ( date [ RV8803_WEEK ] & 0x7f ) ;
2015-11-03 01:48:32 +03:00
tm - > tm_mday = bcd2bin ( date [ RV8803_DAY ] & 0x3f ) ;
tm - > tm_mon = bcd2bin ( date [ RV8803_MONTH ] & 0x1f ) - 1 ;
tm - > tm_year = bcd2bin ( date [ RV8803_YEAR ] ) + 100 ;
2016-07-21 13:41:28 +03:00
return 0 ;
2015-11-03 01:48:32 +03:00
}
static int rv8803_set_time ( struct device * dev , struct rtc_time * tm )
{
struct rv8803_data * rv8803 = dev_get_drvdata ( dev ) ;
u8 date [ 7 ] ;
2016-07-21 13:41:31 +03:00
int ctrl , flags , ret ;
2015-11-03 01:48:32 +03:00
2016-07-21 13:41:31 +03:00
ctrl = rv8803_read_reg ( rv8803 - > client , RV8803_CTRL ) ;
if ( ctrl < 0 )
return ctrl ;
/* Stop the clock */
ret = rv8803_write_reg ( rv8803 - > client , RV8803_CTRL ,
ctrl | RV8803_CTRL_RESET ) ;
if ( ret )
return ret ;
2015-11-03 01:48:32 +03:00
date [ RV8803_SEC ] = bin2bcd ( tm - > tm_sec ) ;
date [ RV8803_MIN ] = bin2bcd ( tm - > tm_min ) ;
date [ RV8803_HOUR ] = bin2bcd ( tm - > tm_hour ) ;
date [ RV8803_WEEK ] = 1 < < ( tm - > tm_wday ) ;
date [ RV8803_DAY ] = bin2bcd ( tm - > tm_mday ) ;
date [ RV8803_MONTH ] = bin2bcd ( tm - > tm_mon + 1 ) ;
date [ RV8803_YEAR ] = bin2bcd ( tm - > tm_year - 100 ) ;
2016-07-21 13:41:30 +03:00
ret = rv8803_write_regs ( rv8803 - > client , RV8803_SEC , 7 , date ) ;
if ( ret )
2015-11-03 01:48:32 +03:00
return ret ;
2016-07-21 13:41:31 +03:00
/* Restart the clock */
ret = rv8803_write_reg ( rv8803 - > client , RV8803_CTRL ,
ctrl & ~ RV8803_CTRL_RESET ) ;
if ( ret )
return ret ;
2016-02-04 15:45:20 +03:00
mutex_lock ( & rv8803 - > flags_lock ) ;
2015-11-03 01:48:32 +03:00
2016-07-21 13:41:30 +03:00
flags = rv8803_read_reg ( rv8803 - > client , RV8803_FLAG ) ;
2015-11-03 01:48:32 +03:00
if ( flags < 0 ) {
2016-02-04 15:45:20 +03:00
mutex_unlock ( & rv8803 - > flags_lock ) ;
2015-11-03 01:48:32 +03:00
return flags ;
}
2016-07-21 13:41:30 +03:00
ret = rv8803_write_reg ( rv8803 - > client , RV8803_FLAG ,
2016-07-21 13:41:32 +03:00
flags & ~ ( RV8803_FLAG_V1F | RV8803_FLAG_V2F ) ) ;
2015-11-03 01:48:32 +03:00
2016-02-04 15:45:20 +03:00
mutex_unlock ( & rv8803 - > flags_lock ) ;
2015-11-03 01:48:32 +03:00
return ret ;
}
static int rv8803_get_alarm ( struct device * dev , struct rtc_wkalrm * alrm )
{
struct rv8803_data * rv8803 = dev_get_drvdata ( dev ) ;
struct i2c_client * client = rv8803 - > client ;
u8 alarmvals [ 3 ] ;
int flags , ret ;
2016-07-21 13:41:30 +03:00
ret = rv8803_read_regs ( client , RV8803_ALARM_MIN , 3 , alarmvals ) ;
if ( ret )
return ret ;
2015-11-03 01:48:32 +03:00
2016-07-21 13:41:30 +03:00
flags = rv8803_read_reg ( client , RV8803_FLAG ) ;
2015-11-03 01:48:32 +03:00
if ( flags < 0 )
return flags ;
alrm - > time . tm_sec = 0 ;
alrm - > time . tm_min = bcd2bin ( alarmvals [ 0 ] & 0x7f ) ;
alrm - > time . tm_hour = bcd2bin ( alarmvals [ 1 ] & 0x3f ) ;
alrm - > time . tm_mday = bcd2bin ( alarmvals [ 2 ] & 0x3f ) ;
alrm - > enabled = ! ! ( rv8803 - > ctrl & RV8803_CTRL_AIE ) ;
alrm - > pending = ( flags & RV8803_FLAG_AF ) & & alrm - > enabled ;
return 0 ;
}
static int rv8803_set_alarm ( struct device * dev , struct rtc_wkalrm * alrm )
{
struct i2c_client * client = to_i2c_client ( dev ) ;
struct rv8803_data * rv8803 = dev_get_drvdata ( dev ) ;
u8 alarmvals [ 3 ] ;
u8 ctrl [ 2 ] ;
int ret , err ;
/* The alarm has no seconds, round up to nearest minute */
if ( alrm - > time . tm_sec ) {
time64_t alarm_time = rtc_tm_to_time64 ( & alrm - > time ) ;
alarm_time + = 60 - alrm - > time . tm_sec ;
rtc_time64_to_tm ( alarm_time , & alrm - > time ) ;
}
2016-02-04 15:45:20 +03:00
mutex_lock ( & rv8803 - > flags_lock ) ;
2015-11-03 01:48:32 +03:00
2016-07-21 13:41:30 +03:00
ret = rv8803_read_regs ( client , RV8803_FLAG , 2 , ctrl ) ;
if ( ret ) {
2016-02-04 15:45:20 +03:00
mutex_unlock ( & rv8803 - > flags_lock ) ;
2016-07-21 13:41:30 +03:00
return ret ;
2015-11-03 01:48:32 +03:00
}
alarmvals [ 0 ] = bin2bcd ( alrm - > time . tm_min ) ;
alarmvals [ 1 ] = bin2bcd ( alrm - > time . tm_hour ) ;
alarmvals [ 2 ] = bin2bcd ( alrm - > time . tm_mday ) ;
if ( rv8803 - > ctrl & ( RV8803_CTRL_AIE | RV8803_CTRL_UIE ) ) {
rv8803 - > ctrl & = ~ ( RV8803_CTRL_AIE | RV8803_CTRL_UIE ) ;
2016-07-21 13:41:30 +03:00
err = rv8803_write_reg ( rv8803 - > client , RV8803_CTRL ,
rv8803 - > ctrl ) ;
2015-11-03 01:48:32 +03:00
if ( err ) {
2016-02-04 15:45:20 +03:00
mutex_unlock ( & rv8803 - > flags_lock ) ;
2015-11-03 01:48:32 +03:00
return err ;
}
}
2021-11-01 04:33:59 +03:00
ctrl [ 0 ] & = ~ RV8803_FLAG_AF ;
err = rv8803_write_reg ( rv8803 - > client , RV8803_FLAG , ctrl [ 0 ] ) ;
2016-02-04 15:45:20 +03:00
mutex_unlock ( & rv8803 - > flags_lock ) ;
2015-11-03 01:48:32 +03:00
if ( err )
return err ;
2016-07-21 13:41:30 +03:00
err = rv8803_write_regs ( rv8803 - > client , RV8803_ALARM_MIN , 3 , alarmvals ) ;
2015-11-03 01:48:32 +03:00
if ( err )
return err ;
if ( alrm - > enabled ) {
if ( rv8803 - > rtc - > uie_rtctimer . enabled )
rv8803 - > ctrl | = RV8803_CTRL_UIE ;
if ( rv8803 - > rtc - > aie_timer . enabled )
rv8803 - > ctrl | = RV8803_CTRL_AIE ;
2016-07-21 13:41:30 +03:00
err = rv8803_write_reg ( rv8803 - > client , RV8803_CTRL ,
rv8803 - > ctrl ) ;
2015-11-03 01:48:32 +03:00
if ( err )
return err ;
}
return 0 ;
}
static int rv8803_alarm_irq_enable ( struct device * dev , unsigned int enabled )
{
struct i2c_client * client = to_i2c_client ( dev ) ;
struct rv8803_data * rv8803 = dev_get_drvdata ( dev ) ;
int ctrl , flags , err ;
ctrl = rv8803 - > ctrl ;
if ( enabled ) {
if ( rv8803 - > rtc - > uie_rtctimer . enabled )
ctrl | = RV8803_CTRL_UIE ;
if ( rv8803 - > rtc - > aie_timer . enabled )
ctrl | = RV8803_CTRL_AIE ;
} else {
if ( ! rv8803 - > rtc - > uie_rtctimer . enabled )
ctrl & = ~ RV8803_CTRL_UIE ;
if ( ! rv8803 - > rtc - > aie_timer . enabled )
ctrl & = ~ RV8803_CTRL_AIE ;
}
2016-02-04 15:45:20 +03:00
mutex_lock ( & rv8803 - > flags_lock ) ;
2016-07-21 13:41:30 +03:00
flags = rv8803_read_reg ( client , RV8803_FLAG ) ;
2015-11-03 01:48:32 +03:00
if ( flags < 0 ) {
2016-02-04 15:45:20 +03:00
mutex_unlock ( & rv8803 - > flags_lock ) ;
2015-11-03 01:48:32 +03:00
return flags ;
}
flags & = ~ ( RV8803_FLAG_AF | RV8803_FLAG_UF ) ;
2016-07-21 13:41:30 +03:00
err = rv8803_write_reg ( client , RV8803_FLAG , flags ) ;
2016-02-04 15:45:20 +03:00
mutex_unlock ( & rv8803 - > flags_lock ) ;
2015-11-03 01:48:32 +03:00
if ( err )
return err ;
if ( ctrl ! = rv8803 - > ctrl ) {
rv8803 - > ctrl = ctrl ;
2016-07-21 13:41:30 +03:00
err = rv8803_write_reg ( client , RV8803_CTRL , rv8803 - > ctrl ) ;
2015-11-03 01:48:32 +03:00
if ( err )
return err ;
}
return 0 ;
}
static int rv8803_ioctl ( struct device * dev , unsigned int cmd , unsigned long arg )
{
struct i2c_client * client = to_i2c_client ( dev ) ;
struct rv8803_data * rv8803 = dev_get_drvdata ( dev ) ;
2019-12-15 01:02:57 +03:00
unsigned int vl = 0 ;
2015-11-03 01:48:32 +03:00
int flags , ret = 0 ;
switch ( cmd ) {
case RTC_VL_READ :
2016-07-21 13:41:30 +03:00
flags = rv8803_read_reg ( client , RV8803_FLAG ) ;
2015-11-03 01:48:32 +03:00
if ( flags < 0 )
return flags ;
2019-12-15 01:02:57 +03:00
if ( flags & RV8803_FLAG_V1F ) {
2015-11-03 01:48:32 +03:00
dev_warn ( & client - > dev , " Voltage low, temperature compensation stopped. \n " ) ;
2019-12-15 01:02:57 +03:00
vl = RTC_VL_ACCURACY_LOW ;
}
2015-11-03 01:48:32 +03:00
if ( flags & RV8803_FLAG_V2F )
2019-12-15 01:02:57 +03:00
vl | = RTC_VL_DATA_INVALID ;
2015-11-03 01:48:32 +03:00
2019-12-15 01:02:57 +03:00
return put_user ( vl , ( unsigned int __user * ) arg ) ;
2015-11-03 01:48:32 +03:00
case RTC_VL_CLR :
2016-02-04 15:45:20 +03:00
mutex_lock ( & rv8803 - > flags_lock ) ;
2016-07-21 13:41:30 +03:00
flags = rv8803_read_reg ( client , RV8803_FLAG ) ;
2015-11-03 01:48:32 +03:00
if ( flags < 0 ) {
2016-02-04 15:45:20 +03:00
mutex_unlock ( & rv8803 - > flags_lock ) ;
2015-11-03 01:48:32 +03:00
return flags ;
}
2019-12-15 01:02:56 +03:00
flags & = ~ RV8803_FLAG_V1F ;
2016-07-21 13:41:30 +03:00
ret = rv8803_write_reg ( client , RV8803_FLAG , flags ) ;
2016-02-04 15:45:20 +03:00
mutex_unlock ( & rv8803 - > flags_lock ) ;
2016-07-21 13:41:30 +03:00
if ( ret )
2015-11-03 01:48:32 +03:00
return ret ;
return 0 ;
default :
return - ENOIOCTLCMD ;
}
}
2017-07-06 12:42:04 +03:00
static int rv8803_nvram_write ( void * priv , unsigned int offset , void * val ,
size_t bytes )
2015-11-03 01:48:32 +03:00
{
2020-09-21 11:24:49 +03:00
return rv8803_write_reg ( priv , RV8803_RAM , * ( u8 * ) val ) ;
2015-11-03 01:48:32 +03:00
}
2017-07-06 12:42:04 +03:00
static int rv8803_nvram_read ( void * priv , unsigned int offset ,
void * val , size_t bytes )
2015-11-03 01:48:32 +03:00
{
int ret ;
2017-07-06 12:42:04 +03:00
ret = rv8803_read_reg ( priv , RV8803_RAM ) ;
2015-11-03 01:48:32 +03:00
if ( ret < 0 )
return ret ;
2017-07-06 12:42:04 +03:00
* ( u8 * ) val = ret ;
2015-11-03 01:48:32 +03:00
2017-07-06 12:42:04 +03:00
return 0 ;
2015-11-03 01:48:32 +03:00
}
2021-01-11 02:17:51 +03:00
static const struct rtc_class_ops rv8803_rtc_ops = {
2015-11-03 01:48:32 +03:00
. read_time = rv8803_get_time ,
. set_time = rv8803_set_time ,
. ioctl = rv8803_ioctl ,
2021-01-11 02:17:51 +03:00
. read_alarm = rv8803_get_alarm ,
. set_alarm = rv8803_set_alarm ,
. alarm_irq_enable = rv8803_alarm_irq_enable ,
2015-11-03 01:48:32 +03:00
} ;
2016-06-29 17:40:01 +03:00
static int rx8900_trickle_charger_init ( struct rv8803_data * rv8803 )
{
struct i2c_client * client = rv8803 - > client ;
struct device_node * node = client - > dev . of_node ;
int err ;
u8 flags ;
if ( ! node )
return 0 ;
if ( rv8803 - > type ! = rx_8900 )
return 0 ;
err = i2c_smbus_read_byte_data ( rv8803 - > client , RX8900_BACKUP_CTRL ) ;
if ( err < 0 )
return err ;
flags = ~ ( RX8900_FLAG_VDETOFF | RX8900_FLAG_SWOFF ) & ( u8 ) err ;
if ( of_property_read_bool ( node , " epson,vdet-disable " ) )
flags | = RX8900_FLAG_VDETOFF ;
if ( of_property_read_bool ( node , " trickle-diode-disable " ) )
flags | = RX8900_FLAG_SWOFF ;
return i2c_smbus_write_byte_data ( rv8803 - > client , RX8900_BACKUP_CTRL ,
flags ) ;
}
2015-11-03 01:48:32 +03:00
static int rv8803_probe ( struct i2c_client * client ,
const struct i2c_device_id * id )
{
2019-06-08 13:56:07 +03:00
struct i2c_adapter * adapter = client - > adapter ;
2015-11-03 01:48:32 +03:00
struct rv8803_data * rv8803 ;
2016-07-21 13:41:30 +03:00
int err , flags ;
2018-02-13 01:47:32 +03:00
struct nvmem_config nvmem_cfg = {
. name = " rv8803_nvram " ,
. word_size = 1 ,
. stride = 1 ,
. size = 1 ,
. reg_read = rv8803_nvram_read ,
. reg_write = rv8803_nvram_write ,
. priv = client ,
} ;
2015-11-03 01:48:32 +03:00
if ( ! i2c_check_functionality ( adapter , I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_I2C_BLOCK ) ) {
dev_err ( & adapter - > dev , " doesn't support I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_I2C_BLOCK \n " ) ;
return - EIO ;
}
rv8803 = devm_kzalloc ( & client - > dev , sizeof ( struct rv8803_data ) ,
GFP_KERNEL ) ;
if ( ! rv8803 )
return - ENOMEM ;
2016-02-04 15:45:20 +03:00
mutex_init ( & rv8803 - > flags_lock ) ;
2015-11-03 01:48:32 +03:00
rv8803 - > client = client ;
2017-03-03 17:29:12 +03:00
if ( client - > dev . of_node )
rv8803 - > type = ( enum rv8803_type )
of_device_get_match_data ( & client - > dev ) ;
else
rv8803 - > type = id - > driver_data ;
2015-11-03 01:48:32 +03:00
i2c_set_clientdata ( client , rv8803 ) ;
2016-07-21 13:41:30 +03:00
flags = rv8803_read_reg ( client , RV8803_FLAG ) ;
2015-11-03 01:48:32 +03:00
if ( flags < 0 )
return flags ;
if ( flags & RV8803_FLAG_V1F )
dev_warn ( & client - > dev , " Voltage low, temperature compensation stopped. \n " ) ;
if ( flags & RV8803_FLAG_V2F )
dev_warn ( & client - > dev , " Voltage low, data loss detected. \n " ) ;
if ( flags & RV8803_FLAG_AF )
dev_warn ( & client - > dev , " An alarm maybe have been missed. \n " ) ;
2017-07-06 12:42:03 +03:00
rv8803 - > rtc = devm_rtc_allocate_device ( & client - > dev ) ;
2019-08-19 01:00:41 +03:00
if ( IS_ERR ( rv8803 - > rtc ) )
2017-07-06 12:42:03 +03:00
return PTR_ERR ( rv8803 - > rtc ) ;
2015-11-03 01:48:32 +03:00
if ( client - > irq > 0 ) {
err = devm_request_threaded_irq ( & client - > dev , client - > irq ,
NULL , rv8803_handle_irq ,
IRQF_TRIGGER_LOW | IRQF_ONESHOT ,
" rv8803 " , client ) ;
if ( err ) {
dev_warn ( & client - > dev , " unable to request IRQ, alarms disabled \n " ) ;
client - > irq = 0 ;
}
}
2021-01-11 02:17:51 +03:00
if ( ! client - > irq )
clear_bit ( RTC_FEATURE_ALARM , rv8803 - > rtc - > features ) ;
2015-11-03 01:48:32 +03:00
2016-07-21 13:41:30 +03:00
err = rv8803_write_reg ( rv8803 - > client , RV8803_EXT , RV8803_EXT_WADA ) ;
2015-11-03 01:48:32 +03:00
if ( err )
return err ;
2016-06-29 17:40:01 +03:00
err = rx8900_trickle_charger_init ( rv8803 ) ;
if ( err ) {
dev_err ( & client - > dev , " failed to init charger \n " ) ;
return err ;
}
2018-02-13 01:47:33 +03:00
rv8803 - > rtc - > ops = & rv8803_rtc_ops ;
2019-03-04 13:03:46 +03:00
rv8803 - > rtc - > range_min = RTC_TIMESTAMP_BEGIN_2000 ;
rv8803 - > rtc - > range_max = RTC_TIMESTAMP_END_2099 ;
2020-11-09 19:34:08 +03:00
err = devm_rtc_register_device ( rv8803 - > rtc ) ;
2018-02-13 01:47:33 +03:00
if ( err )
return err ;
2020-11-09 19:34:06 +03:00
devm_rtc_nvmem_register ( rv8803 - > rtc , & nvmem_cfg ) ;
2018-02-13 01:47:33 +03:00
2015-11-03 01:48:32 +03:00
rv8803 - > rtc - > max_user_freq = 1 ;
return 0 ;
}
static const struct i2c_device_id rv8803_id [ ] = {
2016-06-29 17:40:01 +03:00
{ " rv8803 " , rv_8803 } ,
2021-11-30 15:58:30 +03:00
{ " rv8804 " , rx_8804 } ,
2018-08-28 00:23:44 +03:00
{ " rx8803 " , rv_8803 } ,
2016-06-29 17:40:01 +03:00
{ " rx8900 " , rx_8900 } ,
2015-11-03 01:48:32 +03:00
{ }
} ;
MODULE_DEVICE_TABLE ( i2c , rv8803_id ) ;
2021-02-02 14:22:14 +03:00
static const __maybe_unused struct of_device_id rv8803_of_match [ ] = {
2017-03-03 17:29:12 +03:00
{
. compatible = " microcrystal,rv8803 " ,
2018-08-28 00:23:43 +03:00
. data = ( void * ) rv_8803
2017-03-03 17:29:12 +03:00
} ,
2018-08-28 00:23:44 +03:00
{
. compatible = " epson,rx8803 " ,
. data = ( void * ) rv_8803
} ,
2021-11-30 15:58:30 +03:00
{
. compatible = " epson,rx8804 " ,
. data = ( void * ) rx_8804
} ,
2017-03-03 17:29:12 +03:00
{
. compatible = " epson,rx8900 " ,
. data = ( void * ) rx_8900
} ,
{ }
} ;
MODULE_DEVICE_TABLE ( of , rv8803_of_match ) ;
2015-11-03 01:48:32 +03:00
static struct i2c_driver rv8803_driver = {
. driver = {
. name = " rtc-rv8803 " ,
2017-03-03 17:29:12 +03:00
. of_match_table = of_match_ptr ( rv8803_of_match ) ,
2015-11-03 01:48:32 +03:00
} ,
. probe = rv8803_probe ,
. id_table = rv8803_id ,
} ;
module_i2c_driver ( rv8803_driver ) ;
2019-03-04 22:17:38 +03:00
MODULE_AUTHOR ( " Alexandre Belloni <alexandre.belloni@bootlin.com> " ) ;
2015-11-03 01:48:32 +03:00
MODULE_DESCRIPTION ( " Micro Crystal RV8803 RTC driver " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;