2019-05-29 17:17:58 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2023-02-02 18:54:43 +03:00
/*
* pm8xxx RTC driver
*
* Copyright ( c ) 2010 - 2011 , Code Aurora Forum . All rights reserved .
* Copyright ( c ) 2023 , Linaro Limited
2011-07-26 04:13:33 +04:00
*/
2014-04-04 01:50:13 +04:00
# include <linux/of.h>
2011-07-26 04:13:33 +04:00
# include <linux/module.h>
2023-02-02 18:54:43 +03:00
# include <linux/nvmem-consumer.h>
2011-07-26 04:13:33 +04:00
# include <linux/init.h>
# include <linux/rtc.h>
2014-04-04 01:50:11 +04:00
# include <linux/platform_device.h>
2011-07-26 04:13:33 +04:00
# include <linux/pm.h>
2022-02-16 18:24:42 +03:00
# include <linux/pm_wakeirq.h>
2014-04-04 01:50:11 +04:00
# include <linux/regmap.h>
2011-07-26 04:13:33 +04:00
# include <linux/slab.h>
# include <linux/spinlock.h>
2023-02-02 18:54:33 +03:00
# include <asm/unaligned.h>
2011-07-26 04:13:33 +04:00
/* RTC_CTRL register bit fields */
# define PM8xxx_RTC_ENABLE BIT(7)
# define PM8xxx_RTC_ALARM_CLEAR BIT(0)
2020-12-24 14:28:57 +03:00
# define PM8xxx_RTC_ALARM_ENABLE BIT(7)
2011-07-26 04:13:33 +04:00
# define NUM_8_BIT_RTC_REGS 0x4
2014-10-30 00:50:33 +03:00
/**
* struct pm8xxx_rtc_regs - describe RTC registers per PMIC versions
2023-02-02 18:54:37 +03:00
* @ ctrl : address of control register
* @ write : base address of write registers
* @ read : base address of read registers
* @ alarm_ctrl : address of alarm control register
* @ alarm_ctrl2 : address of alarm control2 register
* @ alarm_rw : base address of alarm read - write registers
* @ alarm_en : alarm enable mask
2014-10-30 00:50:33 +03:00
*/
struct pm8xxx_rtc_regs {
unsigned int ctrl ;
unsigned int write ;
unsigned int read ;
unsigned int alarm_ctrl ;
unsigned int alarm_ctrl2 ;
unsigned int alarm_rw ;
unsigned int alarm_en ;
} ;
2011-07-26 04:13:33 +04:00
/**
2023-02-02 18:54:37 +03:00
* struct pm8xxx_rtc - RTC driver internal structure
* @ rtc : RTC device
* @ regmap : regmap used to access registers
* @ allow_set_time : whether the time can be set
2023-02-02 18:54:36 +03:00
* @ alarm_irq : alarm irq number
2023-02-02 18:54:37 +03:00
* @ regs : register description
2023-02-02 18:54:35 +03:00
* @ dev : device structure
2023-02-02 18:54:43 +03:00
* @ nvmem_cell : nvmem cell for offset
* @ offset : offset from epoch in seconds
2011-07-26 04:13:33 +04:00
*/
struct pm8xxx_rtc {
struct rtc_device * rtc ;
2014-04-04 01:50:11 +04:00
struct regmap * regmap ;
2014-04-04 01:50:13 +04:00
bool allow_set_time ;
2023-02-02 18:54:36 +03:00
int alarm_irq ;
2014-10-30 00:50:33 +03:00
const struct pm8xxx_rtc_regs * regs ;
2023-02-02 18:54:35 +03:00
struct device * dev ;
2023-02-02 18:54:43 +03:00
struct nvmem_cell * nvmem_cell ;
u32 offset ;
2011-07-26 04:13:33 +04:00
} ;
2023-02-02 18:54:43 +03:00
static int pm8xxx_rtc_read_nvmem_offset ( struct pm8xxx_rtc * rtc_dd )
{
size_t len ;
void * buf ;
int rc ;
buf = nvmem_cell_read ( rtc_dd - > nvmem_cell , & len ) ;
if ( IS_ERR ( buf ) ) {
rc = PTR_ERR ( buf ) ;
dev_dbg ( rtc_dd - > dev , " failed to read nvmem offset: %d \n " , rc ) ;
return rc ;
}
if ( len ! = sizeof ( u32 ) ) {
dev_dbg ( rtc_dd - > dev , " unexpected nvmem cell size %zu \n " , len ) ;
kfree ( buf ) ;
return - EINVAL ;
}
rtc_dd - > offset = get_unaligned_le32 ( buf ) ;
kfree ( buf ) ;
return 0 ;
}
static int pm8xxx_rtc_write_nvmem_offset ( struct pm8xxx_rtc * rtc_dd , u32 offset )
{
u8 buf [ sizeof ( u32 ) ] ;
int rc ;
put_unaligned_le32 ( offset , buf ) ;
rc = nvmem_cell_write ( rtc_dd - > nvmem_cell , buf , sizeof ( buf ) ) ;
if ( rc < 0 ) {
dev_dbg ( rtc_dd - > dev , " failed to write nvmem offset: %d \n " , rc ) ;
return rc ;
}
return 0 ;
}
static int pm8xxx_rtc_read_offset ( struct pm8xxx_rtc * rtc_dd )
{
if ( ! rtc_dd - > nvmem_cell )
return 0 ;
return pm8xxx_rtc_read_nvmem_offset ( rtc_dd ) ;
}
2023-02-02 18:54:39 +03:00
static int pm8xxx_rtc_read_raw ( struct pm8xxx_rtc * rtc_dd , u32 * secs )
{
const struct pm8xxx_rtc_regs * regs = rtc_dd - > regs ;
u8 value [ NUM_8_BIT_RTC_REGS ] ;
unsigned int reg ;
int rc ;
rc = regmap_bulk_read ( rtc_dd - > regmap , regs - > read , value , sizeof ( value ) ) ;
if ( rc )
return rc ;
/*
* Read the LSB again and check if there has been a carry over .
* If there has , redo the read operation .
*/
rc = regmap_read ( rtc_dd - > regmap , regs - > read , & reg ) ;
if ( rc < 0 )
return rc ;
if ( reg < value [ 0 ] ) {
rc = regmap_bulk_read ( rtc_dd - > regmap , regs - > read , value ,
sizeof ( value ) ) ;
if ( rc )
return rc ;
}
* secs = get_unaligned_le32 ( value ) ;
return 0 ;
}
2023-02-02 18:54:43 +03:00
static int pm8xxx_rtc_update_offset ( struct pm8xxx_rtc * rtc_dd , u32 secs )
{
u32 raw_secs ;
u32 offset ;
int rc ;
if ( ! rtc_dd - > nvmem_cell )
return - ENODEV ;
rc = pm8xxx_rtc_read_raw ( rtc_dd , & raw_secs ) ;
if ( rc )
return rc ;
offset = secs - raw_secs ;
if ( offset = = rtc_dd - > offset )
return 0 ;
rc = pm8xxx_rtc_write_nvmem_offset ( rtc_dd , offset ) ;
if ( rc )
return rc ;
rtc_dd - > offset = offset ;
return 0 ;
}
2011-07-26 04:13:33 +04:00
/*
* Steps to write the RTC registers .
* 1. Disable alarm if enabled .
2018-03-05 12:05:58 +03:00
* 2. Disable rtc if enabled .
* 3. Write 0x00 to LSB .
* 4. Write Byte [ 1 ] , Byte [ 2 ] , Byte [ 3 ] then Byte [ 0 ] .
* 5. Enable rtc if disabled in step 2.
* 6. Enable alarm if disabled in step 1.
2011-07-26 04:13:33 +04:00
*/
2023-02-02 18:54:43 +03:00
static int __pm8xxx_rtc_set_time ( struct pm8xxx_rtc * rtc_dd , u32 secs )
2011-07-26 04:13:33 +04:00
{
2014-10-30 00:50:33 +03:00
const struct pm8xxx_rtc_regs * regs = rtc_dd - > regs ;
2023-02-02 18:54:29 +03:00
u8 value [ NUM_8_BIT_RTC_REGS ] ;
bool alarm_enabled ;
2023-02-02 18:54:33 +03:00
int rc ;
2011-07-26 04:13:33 +04:00
2023-02-02 18:54:33 +03:00
put_unaligned_le32 ( secs , value ) ;
2011-07-26 04:13:33 +04:00
2023-02-02 18:54:29 +03:00
rc = regmap_update_bits_check ( rtc_dd - > regmap , regs - > alarm_ctrl ,
regs - > alarm_en , 0 , & alarm_enabled ) ;
2014-10-30 00:50:33 +03:00
if ( rc )
2023-02-02 18:54:30 +03:00
return rc ;
2014-10-30 00:50:33 +03:00
2023-02-02 18:54:37 +03:00
/* Disable RTC */
2023-02-02 18:54:29 +03:00
rc = regmap_update_bits ( rtc_dd - > regmap , regs - > ctrl , PM8xxx_RTC_ENABLE , 0 ) ;
2018-03-05 12:05:58 +03:00
if ( rc )
2023-02-02 18:54:30 +03:00
return rc ;
2018-03-05 12:05:58 +03:00
2011-07-26 04:13:33 +04:00
/* Write 0 to Byte[0] */
2014-10-30 00:50:33 +03:00
rc = regmap_write ( rtc_dd - > regmap , regs - > write , 0 ) ;
2023-02-02 18:54:28 +03:00
if ( rc )
2023-02-02 18:54:30 +03:00
return rc ;
2011-07-26 04:13:33 +04:00
/* Write Byte[1], Byte[2], Byte[3] */
2014-10-30 00:50:33 +03:00
rc = regmap_bulk_write ( rtc_dd - > regmap , regs - > write + 1 ,
2014-04-04 01:50:11 +04:00
& value [ 1 ] , sizeof ( value ) - 1 ) ;
2023-02-02 18:54:28 +03:00
if ( rc )
2023-02-02 18:54:30 +03:00
return rc ;
2011-07-26 04:13:33 +04:00
/* Write Byte[0] */
2014-10-30 00:50:33 +03:00
rc = regmap_write ( rtc_dd - > regmap , regs - > write , value [ 0 ] ) ;
2023-02-02 18:54:28 +03:00
if ( rc )
2023-02-02 18:54:30 +03:00
return rc ;
2011-07-26 04:13:33 +04:00
2023-02-02 18:54:37 +03:00
/* Enable RTC */
2023-02-02 18:54:29 +03:00
rc = regmap_update_bits ( rtc_dd - > regmap , regs - > ctrl , PM8xxx_RTC_ENABLE ,
PM8xxx_RTC_ENABLE ) ;
if ( rc )
2023-02-02 18:54:30 +03:00
return rc ;
2018-03-05 12:05:58 +03:00
2011-07-26 04:13:33 +04:00
if ( alarm_enabled ) {
2023-02-02 18:54:29 +03:00
rc = regmap_update_bits ( rtc_dd - > regmap , regs - > alarm_ctrl ,
regs - > alarm_en , regs - > alarm_en ) ;
2023-02-02 18:54:28 +03:00
if ( rc )
2023-02-02 18:54:30 +03:00
return rc ;
2011-07-26 04:13:33 +04:00
}
2023-02-02 18:54:30 +03:00
return 0 ;
2011-07-26 04:13:33 +04:00
}
2023-02-02 18:54:43 +03:00
static int pm8xxx_rtc_set_time ( struct device * dev , struct rtc_time * tm )
{
struct pm8xxx_rtc * rtc_dd = dev_get_drvdata ( dev ) ;
u32 secs ;
int rc ;
secs = rtc_tm_to_time64 ( tm ) ;
if ( rtc_dd - > allow_set_time )
rc = __pm8xxx_rtc_set_time ( rtc_dd , secs ) ;
else
rc = pm8xxx_rtc_update_offset ( rtc_dd , secs ) ;
if ( rc )
return rc ;
dev_dbg ( dev , " set time: %ptRd %ptRt (%u + %u) \n " , tm , tm ,
secs - rtc_dd - > offset , rtc_dd - > offset ) ;
return 0 ;
}
2011-07-26 04:13:33 +04:00
static int pm8xxx_rtc_read_time ( struct device * dev , struct rtc_time * tm )
{
struct pm8xxx_rtc * rtc_dd = dev_get_drvdata ( dev ) ;
2023-02-02 18:54:38 +03:00
u32 secs ;
2023-02-02 18:54:39 +03:00
int rc ;
2011-07-26 04:13:33 +04:00
2023-02-02 18:54:39 +03:00
rc = pm8xxx_rtc_read_raw ( rtc_dd , & secs ) ;
2023-02-02 18:54:28 +03:00
if ( rc )
2011-07-26 04:13:33 +04:00
return rc ;
2023-02-02 18:54:43 +03:00
secs + = rtc_dd - > offset ;
2020-03-06 10:37:57 +03:00
rtc_time64_to_tm ( secs , tm ) ;
2011-07-26 04:13:33 +04:00
2023-02-02 18:54:43 +03:00
dev_dbg ( dev , " read time: %ptRd %ptRt (%u + %u) \n " , tm , tm ,
secs - rtc_dd - > offset , rtc_dd - > offset ) ;
2011-07-26 04:13:33 +04:00
return 0 ;
}
static int pm8xxx_rtc_set_alarm ( struct device * dev , struct rtc_wkalrm * alarm )
{
struct pm8xxx_rtc * rtc_dd = dev_get_drvdata ( dev ) ;
2014-10-30 00:50:33 +03:00
const struct pm8xxx_rtc_regs * regs = rtc_dd - > regs ;
2023-02-02 18:54:40 +03:00
u8 value [ NUM_8_BIT_RTC_REGS ] ;
2023-02-02 18:54:38 +03:00
u32 secs ;
2023-02-02 18:54:33 +03:00
int rc ;
2011-07-26 04:13:33 +04:00
2020-03-06 10:37:57 +03:00
secs = rtc_tm_to_time64 ( & alarm - > time ) ;
2023-02-02 18:54:43 +03:00
secs - = rtc_dd - > offset ;
2023-02-02 18:54:33 +03:00
put_unaligned_le32 ( secs , value ) ;
2011-07-26 04:13:33 +04:00
2023-02-02 18:54:27 +03:00
rc = regmap_update_bits ( rtc_dd - > regmap , regs - > alarm_ctrl ,
regs - > alarm_en , 0 ) ;
if ( rc )
return rc ;
2014-10-30 00:50:33 +03:00
rc = regmap_bulk_write ( rtc_dd - > regmap , regs - > alarm_rw , value ,
2014-04-04 01:50:11 +04:00
sizeof ( value ) ) ;
2023-02-02 18:54:28 +03:00
if ( rc )
2023-02-02 18:54:30 +03:00
return rc ;
2011-07-26 04:13:33 +04:00
2023-02-02 18:54:27 +03:00
if ( alarm - > enabled ) {
rc = regmap_update_bits ( rtc_dd - > regmap , regs - > alarm_ctrl ,
regs - > alarm_en , regs - > alarm_en ) ;
if ( rc )
2023-02-02 18:54:30 +03:00
return rc ;
2011-07-26 04:13:33 +04:00
}
2023-02-02 18:54:34 +03:00
dev_dbg ( dev , " set alarm: %ptRd %ptRt \n " , & alarm - > time , & alarm - > time ) ;
2023-02-02 18:54:30 +03:00
return 0 ;
2011-07-26 04:13:33 +04:00
}
static int pm8xxx_rtc_read_alarm ( struct device * dev , struct rtc_wkalrm * alarm )
{
struct pm8xxx_rtc * rtc_dd = dev_get_drvdata ( dev ) ;
2014-10-30 00:50:33 +03:00
const struct pm8xxx_rtc_regs * regs = rtc_dd - > regs ;
2023-02-02 18:54:40 +03:00
u8 value [ NUM_8_BIT_RTC_REGS ] ;
unsigned int ctrl_reg ;
2023-02-02 18:54:38 +03:00
u32 secs ;
2023-02-02 18:54:40 +03:00
int rc ;
2011-07-26 04:13:33 +04:00
2014-10-30 00:50:33 +03:00
rc = regmap_bulk_read ( rtc_dd - > regmap , regs - > alarm_rw , value ,
2014-04-04 01:50:11 +04:00
sizeof ( value ) ) ;
2023-02-02 18:54:28 +03:00
if ( rc )
2011-07-26 04:13:33 +04:00
return rc ;
2023-02-02 18:54:33 +03:00
secs = get_unaligned_le32 ( value ) ;
2023-02-02 18:54:43 +03:00
secs + = rtc_dd - > offset ;
2020-03-06 10:37:57 +03:00
rtc_time64_to_tm ( secs , & alarm - > time ) ;
2011-07-26 04:13:33 +04:00
2020-12-24 14:28:57 +03:00
rc = regmap_read ( rtc_dd - > regmap , regs - > alarm_ctrl , & ctrl_reg ) ;
2023-02-02 18:54:28 +03:00
if ( rc )
2020-12-24 14:28:57 +03:00
return rc ;
2023-02-02 18:54:28 +03:00
2020-12-24 14:28:57 +03:00
alarm - > enabled = ! ! ( ctrl_reg & PM8xxx_RTC_ALARM_ENABLE ) ;
2023-02-02 18:54:34 +03:00
dev_dbg ( dev , " read alarm: %ptRd %ptRt \n " , & alarm - > time , & alarm - > time ) ;
2011-07-26 04:13:33 +04:00
return 0 ;
}
static int pm8xxx_rtc_alarm_irq_enable ( struct device * dev , unsigned int enable )
{
struct pm8xxx_rtc * rtc_dd = dev_get_drvdata ( dev ) ;
2014-10-30 00:50:33 +03:00
const struct pm8xxx_rtc_regs * regs = rtc_dd - > regs ;
2020-03-21 14:50:17 +03:00
u8 value [ NUM_8_BIT_RTC_REGS ] = { 0 } ;
2023-02-02 18:54:29 +03:00
unsigned int val ;
2023-02-02 18:54:40 +03:00
int rc ;
2011-07-26 04:13:33 +04:00
2014-04-04 01:50:10 +04:00
if ( enable )
2023-02-02 18:54:29 +03:00
val = regs - > alarm_en ;
2014-04-04 01:50:10 +04:00
else
2023-02-02 18:54:29 +03:00
val = 0 ;
2011-07-26 04:13:33 +04:00
2023-02-02 18:54:29 +03:00
rc = regmap_update_bits ( rtc_dd - > regmap , regs - > alarm_ctrl ,
regs - > alarm_en , val ) ;
2023-02-02 18:54:28 +03:00
if ( rc )
2023-02-02 18:54:30 +03:00
return rc ;
2011-07-26 04:13:33 +04:00
2023-02-02 18:54:37 +03:00
/* Clear alarm register */
2020-03-21 14:50:17 +03:00
if ( ! enable ) {
rc = regmap_bulk_write ( rtc_dd - > regmap , regs - > alarm_rw , value ,
sizeof ( value ) ) ;
2023-02-02 18:54:28 +03:00
if ( rc )
2023-02-02 18:54:30 +03:00
return rc ;
2020-03-21 14:50:17 +03:00
}
2023-02-02 18:54:30 +03:00
return 0 ;
2011-07-26 04:13:33 +04:00
}
2014-04-04 01:50:13 +04:00
static const struct rtc_class_ops pm8xxx_rtc_ops = {
2011-07-26 04:13:33 +04:00
. read_time = pm8xxx_rtc_read_time ,
2014-04-04 01:50:13 +04:00
. set_time = pm8xxx_rtc_set_time ,
2011-07-26 04:13:33 +04:00
. set_alarm = pm8xxx_rtc_set_alarm ,
. read_alarm = pm8xxx_rtc_read_alarm ,
. alarm_irq_enable = pm8xxx_rtc_alarm_irq_enable ,
} ;
static irqreturn_t pm8xxx_alarm_trigger ( int irq , void * dev_id )
{
struct pm8xxx_rtc * rtc_dd = dev_id ;
2014-10-30 00:50:33 +03:00
const struct pm8xxx_rtc_regs * regs = rtc_dd - > regs ;
2011-07-26 04:13:33 +04:00
int rc ;
rtc_update_irq ( rtc_dd - > rtc , 1 , RTC_IRQF | RTC_AF ) ;
2023-02-02 18:54:37 +03:00
/* Disable alarm */
2023-02-02 18:54:29 +03:00
rc = regmap_update_bits ( rtc_dd - > regmap , regs - > alarm_ctrl ,
regs - > alarm_en , 0 ) ;
2023-02-02 18:54:30 +03:00
if ( rc )
2023-02-02 18:54:31 +03:00
return IRQ_NONE ;
2011-07-26 04:13:33 +04:00
2023-02-02 18:54:37 +03:00
/* Clear alarm status */
2023-02-02 18:54:29 +03:00
rc = regmap_update_bits ( rtc_dd - > regmap , regs - > alarm_ctrl2 ,
PM8xxx_RTC_ALARM_CLEAR , 0 ) ;
2023-02-02 18:54:28 +03:00
if ( rc )
2023-02-02 18:54:31 +03:00
return IRQ_NONE ;
2011-07-26 04:13:33 +04:00
return IRQ_HANDLED ;
}
2014-10-30 00:50:33 +03:00
static int pm8xxx_rtc_enable ( struct pm8xxx_rtc * rtc_dd )
{
const struct pm8xxx_rtc_regs * regs = rtc_dd - > regs ;
2023-02-02 18:54:29 +03:00
return regmap_update_bits ( rtc_dd - > regmap , regs - > ctrl , PM8xxx_RTC_ENABLE ,
PM8xxx_RTC_ENABLE ) ;
2014-10-30 00:50:33 +03:00
}
static const struct pm8xxx_rtc_regs pm8921_regs = {
. ctrl = 0x11d ,
. write = 0x11f ,
. read = 0x123 ,
. alarm_rw = 0x127 ,
. alarm_ctrl = 0x11d ,
. alarm_ctrl2 = 0x11e ,
. alarm_en = BIT ( 1 ) ,
} ;
static const struct pm8xxx_rtc_regs pm8058_regs = {
. ctrl = 0x1e8 ,
. write = 0x1ea ,
. read = 0x1ee ,
. alarm_rw = 0x1f2 ,
. alarm_ctrl = 0x1e8 ,
. alarm_ctrl2 = 0x1e9 ,
. alarm_en = BIT ( 1 ) ,
} ;
static const struct pm8xxx_rtc_regs pm8941_regs = {
. ctrl = 0x6046 ,
. write = 0x6040 ,
. read = 0x6048 ,
. alarm_rw = 0x6140 ,
. alarm_ctrl = 0x6146 ,
. alarm_ctrl2 = 0x6148 ,
. alarm_en = BIT ( 7 ) ,
} ;
2021-04-09 16:59:23 +03:00
static const struct pm8xxx_rtc_regs pmk8350_regs = {
. ctrl = 0x6146 ,
. write = 0x6140 ,
. read = 0x6148 ,
. alarm_rw = 0x6240 ,
. alarm_ctrl = 0x6246 ,
. alarm_ctrl2 = 0x6248 ,
. alarm_en = BIT ( 7 ) ,
} ;
2014-04-04 01:50:13 +04:00
static const struct of_device_id pm8xxx_id_table [ ] = {
2014-10-30 00:50:33 +03:00
{ . compatible = " qcom,pm8921-rtc " , . data = & pm8921_regs } ,
{ . compatible = " qcom,pm8058-rtc " , . data = & pm8058_regs } ,
{ . compatible = " qcom,pm8941-rtc " , . data = & pm8941_regs } ,
2021-04-09 16:59:23 +03:00
{ . compatible = " qcom,pmk8350-rtc " , . data = & pmk8350_regs } ,
2014-04-04 01:50:13 +04:00
{ } ,
} ;
MODULE_DEVICE_TABLE ( of , pm8xxx_id_table ) ;
2012-12-22 01:09:38 +04:00
static int pm8xxx_rtc_probe ( struct platform_device * pdev )
2011-07-26 04:13:33 +04:00
{
2014-04-04 01:50:13 +04:00
const struct of_device_id * match ;
2023-02-02 18:54:40 +03:00
struct pm8xxx_rtc * rtc_dd ;
int rc ;
2011-07-26 04:13:33 +04:00
2014-04-04 01:50:13 +04:00
match = of_match_node ( pm8xxx_id_table , pdev - > dev . of_node ) ;
if ( ! match )
return - ENXIO ;
2011-07-26 04:13:33 +04:00
2013-07-04 02:07:09 +04:00
rtc_dd = devm_kzalloc ( & pdev - > dev , sizeof ( * rtc_dd ) , GFP_KERNEL ) ;
2014-04-04 01:49:43 +04:00
if ( rtc_dd = = NULL )
2011-07-26 04:13:33 +04:00
return - ENOMEM ;
2014-04-04 01:50:11 +04:00
rtc_dd - > regmap = dev_get_regmap ( pdev - > dev . parent , NULL ) ;
2023-02-02 18:54:41 +03:00
if ( ! rtc_dd - > regmap )
2014-04-04 01:50:11 +04:00
return - ENXIO ;
2023-02-02 18:54:36 +03:00
rtc_dd - > alarm_irq = platform_get_irq ( pdev , 0 ) ;
if ( rtc_dd - > alarm_irq < 0 )
2013-07-04 02:07:09 +04:00
return - ENXIO ;
2011-07-26 04:13:33 +04:00
2014-04-04 01:50:13 +04:00
rtc_dd - > allow_set_time = of_property_read_bool ( pdev - > dev . of_node ,
" allow-set-time " ) ;
2011-07-26 04:13:33 +04:00
2023-02-02 18:54:43 +03:00
rtc_dd - > nvmem_cell = devm_nvmem_cell_get ( & pdev - > dev , " offset " ) ;
if ( IS_ERR ( rtc_dd - > nvmem_cell ) ) {
rc = PTR_ERR ( rtc_dd - > nvmem_cell ) ;
if ( rc ! = - ENOENT )
return rc ;
rtc_dd - > nvmem_cell = NULL ;
}
2014-10-30 00:50:33 +03:00
rtc_dd - > regs = match - > data ;
2023-02-02 18:54:35 +03:00
rtc_dd - > dev = & pdev - > dev ;
2011-07-26 04:13:33 +04:00
2023-02-02 18:54:43 +03:00
if ( ! rtc_dd - > allow_set_time ) {
rc = pm8xxx_rtc_read_offset ( rtc_dd ) ;
if ( rc )
return rc ;
}
2014-10-30 00:50:33 +03:00
rc = pm8xxx_rtc_enable ( rtc_dd ) ;
if ( rc )
2013-07-04 02:07:09 +04:00
return rc ;
2011-07-26 04:13:33 +04:00
platform_set_drvdata ( pdev , rtc_dd ) ;
2014-04-04 01:50:14 +04:00
device_init_wakeup ( & pdev - > dev , 1 ) ;
2020-03-06 10:37:55 +03:00
rtc_dd - > rtc = devm_rtc_allocate_device ( & pdev - > dev ) ;
if ( IS_ERR ( rtc_dd - > rtc ) )
2013-07-04 02:07:09 +04:00
return PTR_ERR ( rtc_dd - > rtc ) ;
2020-03-06 10:37:55 +03:00
rtc_dd - > rtc - > ops = & pm8xxx_rtc_ops ;
2020-03-06 10:37:56 +03:00
rtc_dd - > rtc - > range_max = U32_MAX ;
2011-07-26 04:13:33 +04:00
2023-02-02 18:54:36 +03:00
rc = devm_request_any_context_irq ( & pdev - > dev , rtc_dd - > alarm_irq ,
2014-04-04 01:50:12 +04:00
pm8xxx_alarm_trigger ,
IRQF_TRIGGER_RISING ,
" pm8xxx_rtc_alarm " , rtc_dd ) ;
2023-02-02 18:54:41 +03:00
if ( rc < 0 )
2013-07-04 02:07:09 +04:00
return rc ;
2011-07-26 04:13:33 +04:00
2022-02-16 18:24:42 +03:00
rc = devm_rtc_register_device ( rtc_dd - > rtc ) ;
if ( rc )
return rc ;
2011-07-26 04:13:33 +04:00
2023-02-02 18:54:36 +03:00
rc = dev_pm_set_wake_irq ( & pdev - > dev , rtc_dd - > alarm_irq ) ;
2022-02-16 18:24:42 +03:00
if ( rc )
return rc ;
2011-07-26 04:13:33 +04:00
return 0 ;
}
2022-02-16 18:24:42 +03:00
static int pm8xxx_remove ( struct platform_device * pdev )
2011-07-26 04:13:33 +04:00
{
2022-02-16 18:24:42 +03:00
dev_pm_clear_wake_irq ( & pdev - > dev ) ;
2011-07-26 04:13:33 +04:00
return 0 ;
}
static struct platform_driver pm8xxx_rtc_driver = {
. probe = pm8xxx_rtc_probe ,
2022-02-16 18:24:42 +03:00
. remove = pm8xxx_remove ,
2011-07-26 04:13:33 +04:00
. driver = {
2014-04-04 01:50:13 +04:00
. name = " rtc-pm8xxx " ,
. of_match_table = pm8xxx_id_table ,
2011-07-26 04:13:33 +04:00
} ,
} ;
2012-01-11 03:10:48 +04:00
module_platform_driver ( pm8xxx_rtc_driver ) ;
2011-07-26 04:13:33 +04:00
MODULE_ALIAS ( " platform:rtc-pm8xxx " ) ;
MODULE_DESCRIPTION ( " PMIC8xxx RTC driver " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;
MODULE_AUTHOR ( " Anirudh Ghayal <aghayal@codeaurora.org> " ) ;
2023-02-02 18:54:43 +03:00
MODULE_AUTHOR ( " Johan Hovold <johan@kernel.org> " ) ;