2019-06-04 11:11:33 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2009-06-18 03:26:11 +04:00
/*
* Driver for Epson ' s RTC module RX - 8025 SA / NB
*
* Copyright ( C ) 2009 Wolfgang Grandegger < wg @ grandegger . com >
*
* Copyright ( C ) 2005 by Digi International Inc .
* All rights reserved .
*
* Modified by fengjh at rising . com . cn
2016-01-29 08:17:22 +03:00
* < lm - sensors @ lm - sensors . org >
2009-06-18 03:26:11 +04:00
* 2006.11
*
* Code cleanup by Sergei Poselenov , < sposelenov @ emcraft . com >
* Converted to new style by Wolfgang Grandegger < wg @ grandegger . com >
* Alarm and periodic interrupt added by Dmitry Rakhchev < rda @ emcraft . com >
*/
# include <linux/bcd.h>
2015-07-25 12:50:22 +03:00
# include <linux/bitops.h>
2009-06-18 03:26:11 +04:00
# include <linux/i2c.h>
2015-07-24 16:50:23 +03:00
# include <linux/kernel.h>
# include <linux/module.h>
2009-06-18 03:26:11 +04:00
# include <linux/rtc.h>
/* Register definitions */
# define RX8025_REG_SEC 0x00
# define RX8025_REG_MIN 0x01
# define RX8025_REG_HOUR 0x02
# define RX8025_REG_WDAY 0x03
# define RX8025_REG_MDAY 0x04
# define RX8025_REG_MONTH 0x05
# define RX8025_REG_YEAR 0x06
# define RX8025_REG_DIGOFF 0x07
# define RX8025_REG_ALWMIN 0x08
# define RX8025_REG_ALWHOUR 0x09
# define RX8025_REG_ALWWDAY 0x0a
# define RX8025_REG_ALDMIN 0x0b
# define RX8025_REG_ALDHOUR 0x0c
/* 0x0d is reserved */
# define RX8025_REG_CTRL1 0x0e
# define RX8025_REG_CTRL2 0x0f
# define RX8025_BIT_CTRL1_CT (7 << 0)
/* 1 Hz periodic level irq */
# define RX8025_BIT_CTRL1_CT_1HZ 4
2015-07-25 12:50:22 +03:00
# define RX8025_BIT_CTRL1_TEST BIT(3)
# define RX8025_BIT_CTRL1_1224 BIT(5)
# define RX8025_BIT_CTRL1_DALE BIT(6)
# define RX8025_BIT_CTRL1_WALE BIT(7)
2009-06-18 03:26:11 +04:00
2015-07-25 12:50:22 +03:00
# define RX8025_BIT_CTRL2_DAFG BIT(0)
# define RX8025_BIT_CTRL2_WAFG BIT(1)
# define RX8025_BIT_CTRL2_CTFG BIT(2)
# define RX8025_BIT_CTRL2_PON BIT(4)
# define RX8025_BIT_CTRL2_XST BIT(5)
# define RX8025_BIT_CTRL2_VDET BIT(6)
2009-06-18 03:26:11 +04:00
2022-07-06 10:42:36 +03:00
# define RX8035_BIT_HOUR_1224 BIT(7)
2009-06-18 03:26:11 +04:00
/* Clock precision adjustment */
# define RX8025_ADJ_RESOLUTION 3050 /* in ppb */
# define RX8025_ADJ_DATA_MAX 62
# define RX8025_ADJ_DATA_MIN -62
2021-07-09 07:45:17 +03:00
enum rx_model {
model_rx_unknown ,
model_rx_8025 ,
model_rx_8035 ,
model_last
} ;
2009-06-18 03:26:11 +04:00
static const struct i2c_device_id rx8025_id [ ] = {
2021-07-09 07:45:17 +03:00
{ " rx8025 " , model_rx_8025 } ,
{ " rx8035 " , model_rx_8035 } ,
2009-06-18 03:26:11 +04:00
{ }
} ;
MODULE_DEVICE_TABLE ( i2c , rx8025_id ) ;
struct rx8025_data {
struct rtc_device * rtc ;
2021-07-09 07:45:17 +03:00
enum rx_model model ;
2009-06-18 03:26:11 +04:00
u8 ctrl1 ;
2022-07-06 10:42:36 +03:00
int is_24 ;
2009-06-18 03:26:11 +04:00
} ;
2015-08-04 01:40:25 +03:00
static s32 rx8025_read_reg ( const struct i2c_client * client , u8 number )
2009-06-18 03:26:11 +04:00
{
2015-08-04 01:40:25 +03:00
return i2c_smbus_read_byte_data ( client , number < < 4 ) ;
2009-06-18 03:26:11 +04:00
}
2015-08-04 01:40:25 +03:00
static int rx8025_read_regs ( const struct i2c_client * client ,
u8 number , u8 length , u8 * values )
2009-06-18 03:26:11 +04:00
{
2015-08-04 01:40:25 +03:00
int ret = i2c_smbus_read_i2c_block_data ( client , number < < 4 , length ,
values ) ;
if ( ret ! = length )
2009-06-18 03:26:11 +04:00
return ret < 0 ? ret : - EIO ;
return 0 ;
}
2015-08-04 01:40:25 +03:00
static s32 rx8025_write_reg ( const struct i2c_client * client , u8 number ,
u8 value )
2009-06-18 03:26:11 +04:00
{
2015-08-04 01:40:25 +03:00
return i2c_smbus_write_byte_data ( client , number < < 4 , value ) ;
2009-06-18 03:26:11 +04:00
}
2015-08-04 01:40:25 +03:00
static s32 rx8025_write_regs ( const struct i2c_client * client ,
u8 number , u8 length , const u8 * values )
2009-06-18 03:26:11 +04:00
{
2015-08-04 01:40:25 +03:00
return i2c_smbus_write_i2c_block_data ( client , number < < 4 ,
length , values ) ;
2009-06-18 03:26:11 +04:00
}
2021-07-09 07:45:17 +03:00
static int rx8025_is_osc_stopped ( enum rx_model model , int ctrl2 )
{
int xstp = ctrl2 & RX8025_BIT_CTRL2_XST ;
/* XSTP bit has different polarity on RX-8025 vs RX-8035.
* RX - 8025 : 0 = = oscillator stopped
* RX - 8035 : 1 = = oscillator stopped
*/
if ( model = = model_rx_8025 )
xstp = ! xstp ;
return xstp ;
}
2015-08-04 12:33:59 +03:00
static int rx8025_check_validity ( struct device * dev )
{
2019-12-18 11:16:24 +03:00
struct i2c_client * client = to_i2c_client ( dev ) ;
2021-07-09 07:45:17 +03:00
struct rx8025_data * drvdata = dev_get_drvdata ( dev ) ;
2015-08-04 12:33:59 +03:00
int ctrl2 ;
2021-07-09 07:45:17 +03:00
int xstp ;
2015-08-04 12:33:59 +03:00
2019-12-18 11:16:24 +03:00
ctrl2 = rx8025_read_reg ( client , RX8025_REG_CTRL2 ) ;
2015-08-04 12:33:59 +03:00
if ( ctrl2 < 0 )
return ctrl2 ;
if ( ctrl2 & RX8025_BIT_CTRL2_VDET )
dev_warn ( dev , " power voltage drop detected \n " ) ;
if ( ctrl2 & RX8025_BIT_CTRL2_PON ) {
dev_warn ( dev , " power-on reset detected, date is invalid \n " ) ;
return - EINVAL ;
}
2021-07-09 07:45:17 +03:00
xstp = rx8025_is_osc_stopped ( drvdata - > model , ctrl2 ) ;
if ( xstp ) {
2015-08-04 12:33:59 +03:00
dev_warn ( dev , " crystal stopped, date is invalid \n " ) ;
return - EINVAL ;
}
return 0 ;
}
2015-08-04 11:48:20 +03:00
static int rx8025_reset_validity ( struct i2c_client * client )
{
2021-07-09 07:45:17 +03:00
struct rx8025_data * drvdata = i2c_get_clientdata ( client ) ;
2015-08-04 11:48:20 +03:00
int ctrl2 = rx8025_read_reg ( client , RX8025_REG_CTRL2 ) ;
if ( ctrl2 < 0 )
return ctrl2 ;
ctrl2 & = ~ ( RX8025_BIT_CTRL2_PON | RX8025_BIT_CTRL2_VDET ) ;
2021-07-09 07:45:17 +03:00
if ( drvdata - > model = = model_rx_8025 )
ctrl2 | = RX8025_BIT_CTRL2_XST ;
else
ctrl2 & = ~ ( RX8025_BIT_CTRL2_XST ) ;
2015-08-04 11:48:20 +03:00
return rx8025_write_reg ( client , RX8025_REG_CTRL2 ,
2021-07-09 07:45:17 +03:00
ctrl2 ) ;
2015-08-04 11:48:20 +03:00
}
2015-07-24 16:59:43 +03:00
static irqreturn_t rx8025_handle_irq ( int irq , void * dev_id )
2009-06-18 03:26:11 +04:00
{
struct i2c_client * client = dev_id ;
struct rx8025_data * rx8025 = i2c_get_clientdata ( client ) ;
2021-07-09 07:45:17 +03:00
int status , xstp ;
2009-06-18 03:26:11 +04:00
2021-01-20 01:06:51 +03:00
rtc_lock ( rx8025 - > rtc ) ;
2015-08-04 01:40:25 +03:00
status = rx8025_read_reg ( client , RX8025_REG_CTRL2 ) ;
if ( status < 0 )
2009-06-18 03:26:11 +04:00
goto out ;
2021-07-09 07:45:17 +03:00
xstp = rx8025_is_osc_stopped ( rx8025 - > model , status ) ;
if ( xstp )
2009-06-18 03:26:11 +04:00
dev_warn ( & client - > dev , " Oscillation stop was detected, "
" you may have to readjust the clock \n " ) ;
if ( status & RX8025_BIT_CTRL2_CTFG ) {
/* periodic */
status & = ~ RX8025_BIT_CTRL2_CTFG ;
rtc_update_irq ( rx8025 - > rtc , 1 , RTC_PF | RTC_IRQF ) ;
}
if ( status & RX8025_BIT_CTRL2_DAFG ) {
/* alarm */
status & = RX8025_BIT_CTRL2_DAFG ;
if ( rx8025_write_reg ( client , RX8025_REG_CTRL1 ,
rx8025 - > ctrl1 & ~ RX8025_BIT_CTRL1_DALE ) )
goto out ;
rtc_update_irq ( rx8025 - > rtc , 1 , RTC_AF | RTC_IRQF ) ;
}
out :
2021-01-20 01:06:51 +03:00
rtc_unlock ( rx8025 - > rtc ) ;
2016-02-15 17:49:07 +03:00
2015-07-24 16:59:43 +03:00
return IRQ_HANDLED ;
2009-06-18 03:26:11 +04:00
}
static int rx8025_get_time ( struct device * dev , struct rtc_time * dt )
{
2019-12-18 11:16:24 +03:00
struct i2c_client * client = to_i2c_client ( dev ) ;
2009-06-18 03:26:11 +04:00
struct rx8025_data * rx8025 = dev_get_drvdata ( dev ) ;
2015-08-04 01:40:25 +03:00
u8 date [ 7 ] ;
2015-08-04 12:33:59 +03:00
int err ;
2015-07-26 11:13:31 +03:00
2015-08-04 12:33:59 +03:00
err = rx8025_check_validity ( dev ) ;
if ( err )
return err ;
2015-07-26 11:13:31 +03:00
2019-12-18 11:16:24 +03:00
err = rx8025_read_regs ( client , RX8025_REG_SEC , 7 , date ) ;
2009-06-18 03:26:11 +04:00
if ( err )
return err ;
2018-12-05 00:23:24 +03:00
dev_dbg ( dev , " %s: read %7ph \n " , __func__ , date ) ;
2009-06-18 03:26:11 +04:00
dt - > tm_sec = bcd2bin ( date [ RX8025_REG_SEC ] & 0x7f ) ;
dt - > tm_min = bcd2bin ( date [ RX8025_REG_MIN ] & 0x7f ) ;
2022-07-06 10:42:36 +03:00
if ( rx8025 - > is_24 )
2009-06-18 03:26:11 +04:00
dt - > tm_hour = bcd2bin ( date [ RX8025_REG_HOUR ] & 0x3f ) ;
else
dt - > tm_hour = bcd2bin ( date [ RX8025_REG_HOUR ] & 0x1f ) % 12
+ ( date [ RX8025_REG_HOUR ] & 0x20 ? 12 : 0 ) ;
dt - > tm_mday = bcd2bin ( date [ RX8025_REG_MDAY ] & 0x3f ) ;
dt - > tm_mon = bcd2bin ( date [ RX8025_REG_MONTH ] & 0x1f ) - 1 ;
2015-07-25 13:07:37 +03:00
dt - > tm_year = bcd2bin ( date [ RX8025_REG_YEAR ] ) + 100 ;
2009-06-18 03:26:11 +04:00
2018-12-05 00:23:24 +03:00
dev_dbg ( dev , " %s: date %ptRr \n " , __func__ , dt ) ;
2009-06-18 03:26:11 +04:00
2018-02-19 18:23:56 +03:00
return 0 ;
2009-06-18 03:26:11 +04:00
}
static int rx8025_set_time ( struct device * dev , struct rtc_time * dt )
{
2019-12-18 11:16:24 +03:00
struct i2c_client * client = to_i2c_client ( dev ) ;
2009-06-18 03:26:11 +04:00
struct rx8025_data * rx8025 = dev_get_drvdata ( dev ) ;
u8 date [ 7 ] ;
2015-08-04 11:48:20 +03:00
int ret ;
2009-06-18 03:26:11 +04:00
/*
* Here the read - only bits are written as " 0 " . I ' m not sure if that
* is sound .
*/
date [ RX8025_REG_SEC ] = bin2bcd ( dt - > tm_sec ) ;
date [ RX8025_REG_MIN ] = bin2bcd ( dt - > tm_min ) ;
2022-07-06 10:42:36 +03:00
if ( rx8025 - > is_24 )
2009-06-18 03:26:11 +04:00
date [ RX8025_REG_HOUR ] = bin2bcd ( dt - > tm_hour ) ;
else
date [ RX8025_REG_HOUR ] = ( dt - > tm_hour > = 12 ? 0x20 : 0 )
| bin2bcd ( ( dt - > tm_hour + 11 ) % 12 + 1 ) ;
date [ RX8025_REG_WDAY ] = bin2bcd ( dt - > tm_wday ) ;
date [ RX8025_REG_MDAY ] = bin2bcd ( dt - > tm_mday ) ;
date [ RX8025_REG_MONTH ] = bin2bcd ( dt - > tm_mon + 1 ) ;
2015-07-25 13:07:37 +03:00
date [ RX8025_REG_YEAR ] = bin2bcd ( dt - > tm_year - 100 ) ;
2009-06-18 03:26:11 +04:00
2018-12-05 00:23:24 +03:00
dev_dbg ( dev , " %s: write %7ph \n " , __func__ , date ) ;
2009-06-18 03:26:11 +04:00
2019-12-18 11:16:24 +03:00
ret = rx8025_write_regs ( client , RX8025_REG_SEC , 7 , date ) ;
2015-08-04 11:48:20 +03:00
if ( ret < 0 )
return ret ;
2019-12-18 11:16:24 +03:00
return rx8025_reset_validity ( client ) ;
2009-06-18 03:26:11 +04:00
}
2015-07-26 11:13:31 +03:00
static int rx8025_init_client ( struct i2c_client * client )
2009-06-18 03:26:11 +04:00
{
struct rx8025_data * rx8025 = i2c_get_clientdata ( client ) ;
u8 ctrl [ 2 ] , ctrl2 ;
int need_clear = 0 ;
2022-07-06 10:42:36 +03:00
int hour_reg ;
2009-06-18 03:26:11 +04:00
int err ;
2019-12-18 11:16:24 +03:00
err = rx8025_read_regs ( client , RX8025_REG_CTRL1 , 2 , ctrl ) ;
2009-06-18 03:26:11 +04:00
if ( err )
goto out ;
/* Keep test bit zero ! */
rx8025 - > ctrl1 = ctrl [ 0 ] & ~ RX8025_BIT_CTRL1_TEST ;
if ( ctrl [ 1 ] & ( RX8025_BIT_CTRL2_DAFG | RX8025_BIT_CTRL2_WAFG ) ) {
dev_warn ( & client - > dev , " Alarm was detected \n " ) ;
need_clear = 1 ;
}
2015-08-04 12:24:33 +03:00
if ( ctrl [ 1 ] & RX8025_BIT_CTRL2_CTFG )
2009-06-18 03:26:11 +04:00
need_clear = 1 ;
2015-07-26 11:13:31 +03:00
if ( need_clear ) {
2015-08-04 11:46:22 +03:00
ctrl2 = ctrl [ 1 ] ;
2015-08-04 11:48:20 +03:00
ctrl2 & = ~ ( RX8025_BIT_CTRL2_CTFG | RX8025_BIT_CTRL2_WAFG |
2009-06-18 03:26:11 +04:00
RX8025_BIT_CTRL2_DAFG ) ;
err = rx8025_write_reg ( client , RX8025_REG_CTRL2 , ctrl2 ) ;
}
2022-07-06 10:42:36 +03:00
if ( rx8025 - > model = = model_rx_8035 ) {
/* In RX-8035, 12/24 flag is in the hour register */
hour_reg = rx8025_read_reg ( client , RX8025_REG_HOUR ) ;
if ( hour_reg < 0 )
return hour_reg ;
rx8025 - > is_24 = ( hour_reg & RX8035_BIT_HOUR_1224 ) ;
} else {
rx8025 - > is_24 = ( ctrl [ 1 ] & RX8025_BIT_CTRL1_1224 ) ;
}
2009-06-18 03:26:11 +04:00
out :
return err ;
}
/* Alarm support */
static int rx8025_read_alarm ( struct device * dev , struct rtc_wkalrm * t )
{
2019-12-18 11:16:24 +03:00
struct i2c_client * client = to_i2c_client ( dev ) ;
2009-06-18 03:26:11 +04:00
struct rx8025_data * rx8025 = dev_get_drvdata ( dev ) ;
2015-08-04 01:40:25 +03:00
u8 ald [ 2 ] ;
int ctrl2 , err ;
2009-06-18 03:26:11 +04:00
err = rx8025_read_regs ( client , RX8025_REG_ALDMIN , 2 , ald ) ;
if ( err )
return err ;
2015-08-04 01:40:25 +03:00
ctrl2 = rx8025_read_reg ( client , RX8025_REG_CTRL2 ) ;
if ( ctrl2 < 0 )
return ctrl2 ;
2009-06-18 03:26:11 +04:00
dev_dbg ( dev , " %s: read alarm 0x%02x 0x%02x ctrl2 %02x \n " ,
__func__ , ald [ 0 ] , ald [ 1 ] , ctrl2 ) ;
/* Hardware alarms precision is 1 minute! */
t - > time . tm_sec = 0 ;
t - > time . tm_min = bcd2bin ( ald [ 0 ] & 0x7f ) ;
2022-07-06 10:42:36 +03:00
if ( rx8025 - > is_24 )
2009-06-18 03:26:11 +04:00
t - > time . tm_hour = bcd2bin ( ald [ 1 ] & 0x3f ) ;
else
t - > time . tm_hour = bcd2bin ( ald [ 1 ] & 0x1f ) % 12
+ ( ald [ 1 ] & 0x20 ? 12 : 0 ) ;
2019-04-10 17:05:59 +03:00
dev_dbg ( dev , " %s: date: %ptRr \n " , __func__ , & t - > time ) ;
2009-06-18 03:26:11 +04:00
t - > enabled = ! ! ( rx8025 - > ctrl1 & RX8025_BIT_CTRL1_DALE ) ;
t - > pending = ( ctrl2 & RX8025_BIT_CTRL2_DAFG ) & & t - > enabled ;
return err ;
}
static int rx8025_set_alarm ( struct device * dev , struct rtc_wkalrm * t )
{
struct i2c_client * client = to_i2c_client ( dev ) ;
struct rx8025_data * rx8025 = dev_get_drvdata ( dev ) ;
u8 ald [ 2 ] ;
int err ;
ald [ 0 ] = bin2bcd ( t - > time . tm_min ) ;
2022-07-06 10:42:36 +03:00
if ( rx8025 - > is_24 )
2009-06-18 03:26:11 +04:00
ald [ 1 ] = bin2bcd ( t - > time . tm_hour ) ;
else
ald [ 1 ] = ( t - > time . tm_hour > = 12 ? 0x20 : 0 )
| bin2bcd ( ( t - > time . tm_hour + 11 ) % 12 + 1 ) ;
dev_dbg ( dev , " %s: write 0x%02x 0x%02x \n " , __func__ , ald [ 0 ] , ald [ 1 ] ) ;
if ( rx8025 - > ctrl1 & RX8025_BIT_CTRL1_DALE ) {
rx8025 - > ctrl1 & = ~ RX8025_BIT_CTRL1_DALE ;
2019-12-18 11:16:24 +03:00
err = rx8025_write_reg ( client , RX8025_REG_CTRL1 ,
2009-06-18 03:26:11 +04:00
rx8025 - > ctrl1 ) ;
if ( err )
return err ;
}
2019-12-18 11:16:24 +03:00
err = rx8025_write_regs ( client , RX8025_REG_ALDMIN , 2 , ald ) ;
2009-06-18 03:26:11 +04:00
if ( err )
return err ;
if ( t - > enabled ) {
rx8025 - > ctrl1 | = RX8025_BIT_CTRL1_DALE ;
2019-12-18 11:16:24 +03:00
err = rx8025_write_reg ( client , RX8025_REG_CTRL1 ,
2009-06-18 03:26:11 +04:00
rx8025 - > ctrl1 ) ;
if ( err )
return err ;
}
return 0 ;
}
static int rx8025_alarm_irq_enable ( struct device * dev , unsigned int enabled )
{
2019-12-18 11:16:24 +03:00
struct i2c_client * client = to_i2c_client ( dev ) ;
2009-06-18 03:26:11 +04:00
struct rx8025_data * rx8025 = dev_get_drvdata ( dev ) ;
u8 ctrl1 ;
int err ;
ctrl1 = rx8025 - > ctrl1 ;
if ( enabled )
ctrl1 | = RX8025_BIT_CTRL1_DALE ;
else
ctrl1 & = ~ RX8025_BIT_CTRL1_DALE ;
if ( ctrl1 ! = rx8025 - > ctrl1 ) {
rx8025 - > ctrl1 = ctrl1 ;
2019-12-18 11:16:24 +03:00
err = rx8025_write_reg ( client , RX8025_REG_CTRL1 ,
2009-06-18 03:26:11 +04:00
rx8025 - > ctrl1 ) ;
if ( err )
return err ;
}
return 0 ;
}
/*
* According to the RX8025 SA / NB application manual the frequency and
2010-07-19 10:22:43 +04:00
* temperature characteristics can be approximated using the following
2009-06-18 03:26:11 +04:00
* equation :
*
* df = a * ( ut - t ) * * 2
*
* df : Frequency deviation in any temperature
* a : Coefficient = ( - 35 + - 5 ) * 10 * * - 9
* ut : Ultimate temperature in degree = + 25 + - 5 degree
* t : Any temperature in degree
*/
2021-11-08 01:54:57 +03:00
static int rx8025_read_offset ( struct device * dev , long * offset )
2009-06-18 03:26:11 +04:00
{
struct i2c_client * client = to_i2c_client ( dev ) ;
2015-08-04 01:40:25 +03:00
int digoff ;
2009-06-18 03:26:11 +04:00
2015-08-04 01:40:25 +03:00
digoff = rx8025_read_reg ( client , RX8025_REG_DIGOFF ) ;
if ( digoff < 0 )
return digoff ;
2009-06-18 03:26:11 +04:00
2021-11-08 01:54:57 +03:00
* offset = digoff > = 64 ? digoff - 128 : digoff ;
if ( * offset > 0 )
( * offset ) - - ;
* offset * = RX8025_ADJ_RESOLUTION ;
2009-06-18 03:26:11 +04:00
return 0 ;
}
2021-11-08 01:54:57 +03:00
static int rx8025_set_offset ( struct device * dev , long offset )
2009-06-18 03:26:11 +04:00
{
struct i2c_client * client = to_i2c_client ( dev ) ;
u8 digoff ;
2021-11-08 01:54:57 +03:00
offset / = RX8025_ADJ_RESOLUTION ;
if ( offset > RX8025_ADJ_DATA_MAX )
offset = RX8025_ADJ_DATA_MAX ;
else if ( offset < RX8025_ADJ_DATA_MIN )
offset = RX8025_ADJ_DATA_MIN ;
else if ( offset > 0 )
offset + + ;
else if ( offset < 0 )
offset + = 128 ;
digoff = offset ;
2009-06-18 03:26:11 +04:00
2022-05-05 05:23:14 +03:00
return rx8025_write_reg ( client , RX8025_REG_DIGOFF , digoff ) ;
2009-06-18 03:26:11 +04:00
}
2021-11-08 01:54:57 +03:00
static const struct rtc_class_ops rx8025_rtc_ops = {
. read_time = rx8025_get_time ,
. set_time = rx8025_set_time ,
. read_alarm = rx8025_read_alarm ,
. set_alarm = rx8025_set_alarm ,
. alarm_irq_enable = rx8025_alarm_irq_enable ,
. read_offset = rx8025_read_offset ,
. set_offset = rx8025_set_offset ,
} ;
2009-06-18 03:26:11 +04:00
static ssize_t rx8025_sysfs_show_clock_adjust ( struct device * dev ,
struct device_attribute * attr ,
char * buf )
{
2021-11-08 01:54:57 +03:00
long adj ;
int err ;
2009-06-18 03:26:11 +04:00
2021-11-08 01:54:57 +03:00
dev_warn_once ( dev , " clock_adjust_ppb is deprecated, use offset \n " ) ;
err = rx8025_read_offset ( dev , & adj ) ;
2009-06-18 03:26:11 +04:00
if ( err )
return err ;
2021-11-08 01:54:57 +03:00
return sprintf ( buf , " %ld \n " , - adj ) ;
2009-06-18 03:26:11 +04:00
}
static ssize_t rx8025_sysfs_store_clock_adjust ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t count )
{
2021-11-08 01:54:57 +03:00
long adj ;
int err ;
2009-06-18 03:26:11 +04:00
2021-11-08 01:54:57 +03:00
dev_warn_once ( dev , " clock_adjust_ppb is deprecated, use offset \n " ) ;
if ( kstrtol ( buf , 10 , & adj ) ! = 0 )
2009-06-18 03:26:11 +04:00
return - EINVAL ;
2021-11-08 01:54:57 +03:00
err = rx8025_set_offset ( dev , - adj ) ;
2009-06-18 03:26:11 +04:00
return err ? err : count ;
}
static DEVICE_ATTR ( clock_adjust_ppb , S_IRUGO | S_IWUSR ,
rx8025_sysfs_show_clock_adjust ,
rx8025_sysfs_store_clock_adjust ) ;
2021-11-08 01:54:56 +03:00
static struct attribute * rx8025_attrs [ ] = {
& dev_attr_clock_adjust_ppb . attr ,
NULL
} ;
2009-06-18 03:26:11 +04:00
2021-11-08 01:54:56 +03:00
static const struct attribute_group rx8025_attr_group = {
. attrs = rx8025_attrs ,
} ;
2009-06-18 03:26:11 +04:00
2012-12-22 01:09:38 +04:00
static int rx8025_probe ( struct i2c_client * client ,
const struct i2c_device_id * id )
2009-06-18 03:26:11 +04:00
{
2019-06-08 13:56:09 +03:00
struct i2c_adapter * adapter = client - > adapter ;
2009-06-18 03:26:11 +04:00
struct rx8025_data * rx8025 ;
2015-07-26 11:13:31 +03:00
int err = 0 ;
2009-06-18 03:26:11 +04:00
if ( ! i2c_check_functionality ( adapter , I2C_FUNC_SMBUS_BYTE_DATA
| I2C_FUNC_SMBUS_I2C_BLOCK ) ) {
dev_err ( & adapter - > dev ,
" doesn't support required functionality \n " ) ;
2015-07-24 17:12:10 +03:00
return - EIO ;
2009-06-18 03:26:11 +04:00
}
2013-07-04 02:07:10 +04:00
rx8025 = devm_kzalloc ( & client - > dev , sizeof ( * rx8025 ) , GFP_KERNEL ) ;
2015-09-26 17:25:28 +03:00
if ( ! rx8025 )
2015-07-24 17:12:10 +03:00
return - ENOMEM ;
2009-06-18 03:26:11 +04:00
i2c_set_clientdata ( client , rx8025 ) ;
2021-07-09 07:45:17 +03:00
if ( id )
rx8025 - > model = id - > driver_data ;
2015-07-26 11:13:31 +03:00
err = rx8025_init_client ( client ) ;
2009-06-18 03:26:11 +04:00
if ( err )
2015-07-24 17:12:10 +03:00
return err ;
2009-06-18 03:26:11 +04:00
2021-11-08 01:54:52 +03:00
rx8025 - > rtc = devm_rtc_allocate_device ( & client - > dev ) ;
if ( IS_ERR ( rx8025 - > rtc ) )
2015-07-24 17:12:10 +03:00
return PTR_ERR ( rx8025 - > rtc ) ;
2021-11-08 01:54:52 +03:00
rx8025 - > rtc - > ops = & rx8025_rtc_ops ;
2021-11-08 01:54:54 +03:00
rx8025 - > rtc - > range_min = RTC_TIMESTAMP_BEGIN_1900 ;
rx8025 - > rtc - > range_max = RTC_TIMESTAMP_END_2099 ;
2009-06-18 03:26:11 +04:00
if ( client - > irq > 0 ) {
dev_info ( & client - > dev , " IRQ %d supplied \n " , client - > irq ) ;
2015-07-24 17:07:30 +03:00
err = devm_request_threaded_irq ( & client - > dev , client - > irq , NULL ,
2016-02-15 17:49:06 +03:00
rx8025_handle_irq ,
IRQF_ONESHOT ,
" rx8025 " , client ) ;
2021-11-08 01:54:55 +03:00
if ( err )
clear_bit ( RTC_FEATURE_ALARM , rx8025 - > rtc - > features ) ;
2009-06-18 03:26:11 +04:00
}
rx8025 - > rtc - > max_user_freq = 1 ;
2021-11-08 01:54:53 +03:00
set_bit ( RTC_FEATURE_ALARM_RES_MINUTE , rx8025 - > rtc - > features ) ;
clear_bit ( RTC_FEATURE_UPDATE_INTERRUPT , rx8025 - > rtc - > features ) ;
2016-02-15 17:49:09 +03:00
2021-11-08 01:54:56 +03:00
err = rtc_add_group ( rx8025 - > rtc , & rx8025_attr_group ) ;
2021-11-08 01:54:52 +03:00
if ( err )
return err ;
2021-11-08 01:54:56 +03:00
return devm_rtc_register_device ( rx8025 - > rtc ) ;
2009-06-18 03:26:11 +04:00
}
static struct i2c_driver rx8025_driver = {
. driver = {
. name = " rtc-rx8025 " ,
} ,
. probe = rx8025_probe ,
. id_table = rx8025_id ,
} ;
2012-03-24 02:02:31 +04:00
module_i2c_driver ( rx8025_driver ) ;
2009-06-18 03:26:11 +04:00
MODULE_AUTHOR ( " Wolfgang Grandegger <wg@grandegger.com> " ) ;
MODULE_DESCRIPTION ( " RX-8025 SA/NB RTC driver " ) ;
MODULE_LICENSE ( " GPL " ) ;