2019-05-29 17:17:58 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2011-07-26 04:13:33 +04:00
/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
*/
2014-04-04 01:50:13 +04:00
# include <linux/of.h>
2011-07-26 04:13:33 +04:00
# include <linux/module.h>
# 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>
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>
/* RTC Register offsets from RTC CTRL REG */
# define PM8XXX_ALARM_CTRL_OFFSET 0x01
# define PM8XXX_RTC_WRITE_OFFSET 0x02
# define PM8XXX_RTC_READ_OFFSET 0x06
# define PM8XXX_ALARM_RW_OFFSET 0x0A
/* 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
* @ ctrl : base address of control register
* @ write : base address of write register
* @ read : base address of read register
* @ alarm_ctrl : base address of alarm control register
* @ alarm_ctrl2 : base address of alarm control2 register
* @ alarm_rw : base address of alarm read - write register
* @ alarm_en : alarm enable mask
*/
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
/**
* struct pm8xxx_rtc - rtc driver internal structure
* @ rtc : rtc device for this driver .
2014-04-04 01:50:11 +04:00
* @ regmap : regmap used to access RTC registers
2014-04-04 01:50:13 +04:00
* @ allow_set_time : indicates whether writing to the RTC is allowed
2011-07-26 04:13:33 +04:00
* @ rtc_alarm_irq : rtc alarm irq number .
2019-11-22 13:22:10 +03:00
* @ regs : rtc registers description .
2011-07-26 04:13:33 +04:00
* @ rtc_dev : device structure .
* @ ctrl_reg_lock : spinlock protecting access to ctrl_reg .
*/
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 ;
2011-07-26 04:13:33 +04:00
int rtc_alarm_irq ;
2014-10-30 00:50:33 +03:00
const struct pm8xxx_rtc_regs * regs ;
2011-07-26 04:13:33 +04:00
struct device * rtc_dev ;
spinlock_t ctrl_reg_lock ;
} ;
/*
* 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
*/
static int pm8xxx_rtc_set_time ( struct device * dev , struct rtc_time * tm )
{
int rc , i ;
unsigned long secs , irq_flags ;
2018-03-05 12:05:58 +03:00
u8 value [ NUM_8_BIT_RTC_REGS ] , alarm_enabled = 0 , rtc_disabled = 0 ;
unsigned int ctrl_reg , rtc_ctrl_reg ;
2011-07-26 04:13:33 +04:00
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 ;
2011-07-26 04:13:33 +04:00
2014-04-04 01:50:13 +04:00
if ( ! rtc_dd - > allow_set_time )
return - EACCES ;
2020-03-06 10:37:57 +03:00
secs = rtc_tm_to_time64 ( tm ) ;
2011-07-26 04:13:33 +04:00
2018-03-05 12:05:58 +03:00
dev_dbg ( dev , " Seconds value to be written to RTC = %lu \n " , secs ) ;
2011-07-26 04:13:33 +04:00
for ( i = 0 ; i < NUM_8_BIT_RTC_REGS ; i + + ) {
value [ i ] = secs & 0xFF ;
secs > > = 8 ;
}
spin_lock_irqsave ( & rtc_dd - > ctrl_reg_lock , irq_flags ) ;
2018-03-05 12:05:58 +03:00
rc = regmap_read ( rtc_dd - > regmap , regs - > alarm_ctrl , & ctrl_reg ) ;
2014-10-30 00:50:33 +03:00
if ( rc )
goto rtc_rw_fail ;
if ( ctrl_reg & regs - > alarm_en ) {
2011-07-26 04:13:33 +04:00
alarm_enabled = 1 ;
2014-10-30 00:50:33 +03:00
ctrl_reg & = ~ regs - > alarm_en ;
2018-03-05 12:05:58 +03:00
rc = regmap_write ( rtc_dd - > regmap , regs - > alarm_ctrl , ctrl_reg ) ;
if ( rc ) {
dev_err ( dev , " Write to RTC Alarm control register failed \n " ) ;
goto rtc_rw_fail ;
}
}
/* Disable RTC H/w before writing on RTC register */
rc = regmap_read ( rtc_dd - > regmap , regs - > ctrl , & rtc_ctrl_reg ) ;
if ( rc )
goto rtc_rw_fail ;
if ( rtc_ctrl_reg & PM8xxx_RTC_ENABLE ) {
rtc_disabled = 1 ;
rtc_ctrl_reg & = ~ PM8xxx_RTC_ENABLE ;
rc = regmap_write ( rtc_dd - > regmap , regs - > ctrl , rtc_ctrl_reg ) ;
2014-04-04 01:50:11 +04:00
if ( rc ) {
2014-04-04 01:50:10 +04:00
dev_err ( dev , " Write to RTC control register failed \n " ) ;
2011-07-26 04:13:33 +04:00
goto rtc_rw_fail ;
}
2014-04-04 01:50:10 +04: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 ) ;
2014-04-04 01:50:11 +04:00
if ( rc ) {
2011-07-26 04:13:33 +04:00
dev_err ( dev , " Write to RTC write data register failed \n " ) ;
goto rtc_rw_fail ;
}
/* 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 ) ;
if ( rc ) {
2011-07-26 04:13:33 +04:00
dev_err ( dev , " Write to RTC write data register failed \n " ) ;
goto rtc_rw_fail ;
}
/* Write Byte[0] */
2014-10-30 00:50:33 +03:00
rc = regmap_write ( rtc_dd - > regmap , regs - > write , value [ 0 ] ) ;
2014-04-04 01:50:11 +04:00
if ( rc ) {
2011-07-26 04:13:33 +04:00
dev_err ( dev , " Write to RTC write data register failed \n " ) ;
goto rtc_rw_fail ;
}
2018-03-05 12:05:58 +03:00
/* Enable RTC H/w after writing on RTC register */
if ( rtc_disabled ) {
rtc_ctrl_reg | = PM8xxx_RTC_ENABLE ;
rc = regmap_write ( rtc_dd - > regmap , regs - > ctrl , rtc_ctrl_reg ) ;
if ( rc ) {
dev_err ( dev , " Write to RTC control register failed \n " ) ;
goto rtc_rw_fail ;
}
}
2011-07-26 04:13:33 +04:00
if ( alarm_enabled ) {
2014-10-30 00:50:33 +03:00
ctrl_reg | = regs - > alarm_en ;
2018-03-05 12:05:58 +03:00
rc = regmap_write ( rtc_dd - > regmap , regs - > alarm_ctrl , ctrl_reg ) ;
2014-04-04 01:50:11 +04:00
if ( rc ) {
2018-03-05 12:05:58 +03:00
dev_err ( dev , " Write to RTC Alarm control register failed \n " ) ;
2011-07-26 04:13:33 +04:00
goto rtc_rw_fail ;
}
}
rtc_rw_fail :
2014-10-30 00:50:33 +03:00
spin_unlock_irqrestore ( & rtc_dd - > ctrl_reg_lock , irq_flags ) ;
2011-07-26 04:13:33 +04:00
return rc ;
}
static int pm8xxx_rtc_read_time ( struct device * dev , struct rtc_time * tm )
{
int rc ;
2014-04-04 01:50:11 +04:00
u8 value [ NUM_8_BIT_RTC_REGS ] ;
2011-07-26 04:13:33 +04:00
unsigned long secs ;
2014-04-04 01:50:11 +04:00
unsigned int reg ;
2011-07-26 04:13:33 +04:00
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 ;
2011-07-26 04:13:33 +04:00
2014-10-30 00:50:33 +03:00
rc = regmap_bulk_read ( rtc_dd - > regmap , regs - > read , value , sizeof ( value ) ) ;
2014-04-04 01:50:11 +04:00
if ( rc ) {
2011-07-26 04:13:33 +04:00
dev_err ( dev , " RTC read data register failed \n " ) ;
return rc ;
}
/*
* Read the LSB again and check if there has been a carry over .
* If there is , redo the read operation .
*/
2014-10-30 00:50:33 +03:00
rc = regmap_read ( rtc_dd - > regmap , regs - > read , & reg ) ;
2011-07-26 04:13:33 +04:00
if ( rc < 0 ) {
dev_err ( dev , " RTC read data register failed \n " ) ;
return rc ;
}
if ( unlikely ( reg < value [ 0 ] ) ) {
2014-10-30 00:50:33 +03:00
rc = regmap_bulk_read ( rtc_dd - > regmap , regs - > read ,
2014-04-04 01:50:11 +04:00
value , sizeof ( value ) ) ;
if ( rc ) {
2011-07-26 04:13:33 +04:00
dev_err ( dev , " RTC read data register failed \n " ) ;
return rc ;
}
}
2019-02-06 13:31:02 +03:00
secs = value [ 0 ] | ( value [ 1 ] < < 8 ) | ( value [ 2 ] < < 16 ) |
( ( unsigned long ) value [ 3 ] < < 24 ) ;
2011-07-26 04:13:33 +04:00
2020-03-06 10:37:57 +03:00
rtc_time64_to_tm ( secs , tm ) ;
2011-07-26 04:13:33 +04:00
2018-12-05 00:23:20 +03:00
dev_dbg ( dev , " secs = %lu, h:m:s == %ptRt, y-m-d = %ptRdr \n " , secs , tm , tm ) ;
2011-07-26 04:13:33 +04:00
return 0 ;
}
static int pm8xxx_rtc_set_alarm ( struct device * dev , struct rtc_wkalrm * alarm )
{
int rc , i ;
2014-10-30 00:50:33 +03:00
u8 value [ NUM_8_BIT_RTC_REGS ] ;
unsigned int ctrl_reg ;
2011-07-26 04:13:33 +04:00
unsigned long secs , irq_flags ;
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 ;
2011-07-26 04:13:33 +04:00
2020-03-06 10:37:57 +03:00
secs = rtc_tm_to_time64 ( & alarm - > time ) ;
2011-07-26 04:13:33 +04:00
for ( i = 0 ; i < NUM_8_BIT_RTC_REGS ; i + + ) {
value [ i ] = secs & 0xFF ;
secs > > = 8 ;
}
spin_lock_irqsave ( & rtc_dd - > ctrl_reg_lock , irq_flags ) ;
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 ) ) ;
if ( rc ) {
2011-07-26 04:13:33 +04:00
dev_err ( dev , " Write to RTC ALARM register failed \n " ) ;
goto rtc_rw_fail ;
}
2014-10-30 00:50:33 +03:00
rc = regmap_read ( rtc_dd - > regmap , regs - > alarm_ctrl , & ctrl_reg ) ;
if ( rc )
goto rtc_rw_fail ;
2014-04-04 01:50:10 +04:00
if ( alarm - > enabled )
2014-10-30 00:50:33 +03:00
ctrl_reg | = regs - > alarm_en ;
2014-04-04 01:50:10 +04:00
else
2014-10-30 00:50:33 +03:00
ctrl_reg & = ~ regs - > alarm_en ;
2011-07-26 04:13:33 +04:00
2014-10-30 00:50:33 +03:00
rc = regmap_write ( rtc_dd - > regmap , regs - > alarm_ctrl , ctrl_reg ) ;
2014-04-04 01:50:11 +04:00
if ( rc ) {
2014-10-30 00:50:33 +03:00
dev_err ( dev , " Write to RTC alarm control register failed \n " ) ;
2011-07-26 04:13:33 +04:00
goto rtc_rw_fail ;
}
2018-12-05 00:23:20 +03:00
dev_dbg ( dev , " Alarm Set for h:m:s=%ptRt, y-m-d=%ptRdr \n " ,
& alarm - > time , & alarm - > time ) ;
2011-07-26 04:13:33 +04:00
rtc_rw_fail :
spin_unlock_irqrestore ( & rtc_dd - > ctrl_reg_lock , irq_flags ) ;
return rc ;
}
static int pm8xxx_rtc_read_alarm ( struct device * dev , struct rtc_wkalrm * alarm )
{
int rc ;
2020-12-24 14:28:57 +03:00
unsigned int ctrl_reg ;
2011-07-26 04:13:33 +04:00
u8 value [ NUM_8_BIT_RTC_REGS ] ;
unsigned long secs ;
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 ;
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 ) ) ;
if ( rc ) {
2011-07-26 04:13:33 +04:00
dev_err ( dev , " RTC alarm time read failed \n " ) ;
return rc ;
}
2019-02-06 13:31:02 +03:00
secs = value [ 0 ] | ( value [ 1 ] < < 8 ) | ( value [ 2 ] < < 16 ) |
( ( unsigned long ) value [ 3 ] < < 24 ) ;
2011-07-26 04:13:33 +04:00
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 ) ;
if ( rc ) {
dev_err ( dev , " Read from RTC alarm control register failed \n " ) ;
return rc ;
}
alarm - > enabled = ! ! ( ctrl_reg & PM8xxx_RTC_ALARM_ENABLE ) ;
2018-12-05 00:23:20 +03:00
dev_dbg ( dev , " Alarm set for - h:m:s=%ptRt, y-m-d=%ptRdr \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 )
{
int rc ;
unsigned long irq_flags ;
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 ;
unsigned int ctrl_reg ;
2020-03-21 14:50:17 +03:00
u8 value [ NUM_8_BIT_RTC_REGS ] = { 0 } ;
2011-07-26 04:13:33 +04:00
spin_lock_irqsave ( & rtc_dd - > ctrl_reg_lock , irq_flags ) ;
2014-04-04 01:50:10 +04:00
2014-10-30 00:50:33 +03:00
rc = regmap_read ( rtc_dd - > regmap , regs - > alarm_ctrl , & ctrl_reg ) ;
if ( rc )
goto rtc_rw_fail ;
2014-04-04 01:50:10 +04:00
if ( enable )
2014-10-30 00:50:33 +03:00
ctrl_reg | = regs - > alarm_en ;
2014-04-04 01:50:10 +04:00
else
2014-10-30 00:50:33 +03:00
ctrl_reg & = ~ regs - > alarm_en ;
2011-07-26 04:13:33 +04:00
2014-10-30 00:50:33 +03:00
rc = regmap_write ( rtc_dd - > regmap , regs - > alarm_ctrl , ctrl_reg ) ;
2014-04-04 01:50:11 +04:00
if ( rc ) {
2011-07-26 04:13:33 +04:00
dev_err ( dev , " Write to RTC control register failed \n " ) ;
goto rtc_rw_fail ;
}
2020-03-21 14:50:17 +03:00
/* Clear Alarm register */
if ( ! enable ) {
rc = regmap_bulk_write ( rtc_dd - > regmap , regs - > alarm_rw , value ,
sizeof ( value ) ) ;
if ( rc ) {
dev_err ( dev , " Clear RTC ALARM register failed \n " ) ;
goto rtc_rw_fail ;
}
}
2011-07-26 04:13:33 +04:00
rtc_rw_fail :
spin_unlock_irqrestore ( & rtc_dd - > ctrl_reg_lock , irq_flags ) ;
return rc ;
}
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 ;
2014-04-04 01:50:11 +04:00
unsigned int ctrl_reg ;
2011-07-26 04:13:33 +04:00
int rc ;
rtc_update_irq ( rtc_dd - > rtc , 1 , RTC_IRQF | RTC_AF ) ;
2021-02-03 15:39:37 +03:00
spin_lock ( & rtc_dd - > ctrl_reg_lock ) ;
2011-07-26 04:13:33 +04:00
/* Clear the alarm enable bit */
2014-10-30 00:50:33 +03:00
rc = regmap_read ( rtc_dd - > regmap , regs - > alarm_ctrl , & ctrl_reg ) ;
if ( rc ) {
2021-02-03 15:39:37 +03:00
spin_unlock ( & rtc_dd - > ctrl_reg_lock ) ;
2014-10-30 00:50:33 +03:00
goto rtc_alarm_handled ;
}
ctrl_reg & = ~ regs - > alarm_en ;
2011-07-26 04:13:33 +04:00
2014-10-30 00:50:33 +03:00
rc = regmap_write ( rtc_dd - > regmap , regs - > alarm_ctrl , ctrl_reg ) ;
2014-04-04 01:50:11 +04:00
if ( rc ) {
2021-02-03 15:39:37 +03:00
spin_unlock ( & rtc_dd - > ctrl_reg_lock ) ;
2014-04-04 01:50:10 +04:00
dev_err ( rtc_dd - > rtc_dev ,
2014-10-30 00:50:33 +03:00
" Write to alarm control register failed \n " ) ;
2011-07-26 04:13:33 +04:00
goto rtc_alarm_handled ;
}
2021-02-03 15:39:37 +03:00
spin_unlock ( & rtc_dd - > ctrl_reg_lock ) ;
2011-07-26 04:13:33 +04:00
/* Clear RTC alarm register */
2014-10-30 00:50:33 +03:00
rc = regmap_read ( rtc_dd - > regmap , regs - > alarm_ctrl2 , & ctrl_reg ) ;
2014-04-04 01:50:11 +04:00
if ( rc ) {
2014-04-04 01:50:10 +04:00
dev_err ( rtc_dd - > rtc_dev ,
2014-10-30 00:50:33 +03:00
" RTC Alarm control2 register read failed \n " ) ;
2011-07-26 04:13:33 +04:00
goto rtc_alarm_handled ;
}
2014-10-30 00:50:33 +03:00
ctrl_reg | = PM8xxx_RTC_ALARM_CLEAR ;
rc = regmap_write ( rtc_dd - > regmap , regs - > alarm_ctrl2 , ctrl_reg ) ;
2014-04-04 01:50:11 +04:00
if ( rc )
2014-04-04 01:50:10 +04:00
dev_err ( rtc_dd - > rtc_dev ,
2014-10-30 00:50:33 +03:00
" Write to RTC Alarm control2 register failed \n " ) ;
2011-07-26 04:13:33 +04:00
rtc_alarm_handled :
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 ;
unsigned int ctrl_reg ;
int rc ;
/* Check if the RTC is on, else turn it on */
rc = regmap_read ( rtc_dd - > regmap , regs - > ctrl , & ctrl_reg ) ;
if ( rc )
return rc ;
if ( ! ( ctrl_reg & PM8xxx_RTC_ENABLE ) ) {
ctrl_reg | = PM8xxx_RTC_ENABLE ;
rc = regmap_write ( rtc_dd - > regmap , regs - > ctrl , ctrl_reg ) ;
if ( rc )
return rc ;
}
return 0 ;
}
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
/*
* Hardcoded RTC bases until IORESOURCE_REG mapping is figured out
*/
static const struct of_device_id pm8xxx_id_table [ ] = {
2014-10-30 00:50:33 +03:00
{ . compatible = " qcom,pm8921-rtc " , . data = & pm8921_regs } ,
2016-08-11 16:16:44 +03:00
{ . compatible = " qcom,pm8018-rtc " , . data = & pm8921_regs } ,
2014-10-30 00:50:33 +03:00
{ . 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
{
int rc ;
struct pm8xxx_rtc * rtc_dd ;
2014-04-04 01:50:13 +04:00
const struct of_device_id * match ;
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 ;
/* Initialise spinlock to protect RTC control register */
spin_lock_init ( & rtc_dd - > ctrl_reg_lock ) ;
2014-04-04 01:50:11 +04:00
rtc_dd - > regmap = dev_get_regmap ( pdev - > dev . parent , NULL ) ;
if ( ! rtc_dd - > regmap ) {
dev_err ( & pdev - > dev , " Parent regmap unavailable. \n " ) ;
return - ENXIO ;
}
2011-07-26 04:13:33 +04:00
rtc_dd - > rtc_alarm_irq = platform_get_irq ( pdev , 0 ) ;
2019-07-30 21:15:39 +03:00
if ( rtc_dd - > rtc_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
2014-10-30 00:50:33 +03:00
rtc_dd - > regs = match - > data ;
2011-07-26 04:13:33 +04:00
rtc_dd - > rtc_dev = & pdev - > dev ;
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 ) ;
2011-07-26 04:13:33 +04:00
/* Register the RTC device */
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
/* Request the alarm IRQ */
2014-04-04 01:50:12 +04:00
rc = devm_request_any_context_irq ( & pdev - > dev , rtc_dd - > rtc_alarm_irq ,
pm8xxx_alarm_trigger ,
IRQF_TRIGGER_RISING ,
" pm8xxx_rtc_alarm " , rtc_dd ) ;
2011-07-26 04:13:33 +04:00
if ( rc < 0 ) {
dev_err ( & pdev - > dev , " Request IRQ failed (%d) \n " , rc ) ;
2013-07-04 02:07:09 +04:00
return rc ;
2011-07-26 04:13:33 +04:00
}
2020-11-09 19:34:08 +03:00
return devm_rtc_register_device ( rtc_dd - > rtc ) ;
2011-07-26 04:13:33 +04:00
}
# ifdef CONFIG_PM_SLEEP
static int pm8xxx_rtc_resume ( struct device * dev )
{
struct pm8xxx_rtc * rtc_dd = dev_get_drvdata ( dev ) ;
if ( device_may_wakeup ( dev ) )
disable_irq_wake ( rtc_dd - > rtc_alarm_irq ) ;
return 0 ;
}
static int pm8xxx_rtc_suspend ( struct device * dev )
{
struct pm8xxx_rtc * rtc_dd = dev_get_drvdata ( dev ) ;
if ( device_may_wakeup ( dev ) )
enable_irq_wake ( rtc_dd - > rtc_alarm_irq ) ;
return 0 ;
}
# endif
2014-04-04 01:50:10 +04:00
static SIMPLE_DEV_PM_OPS ( pm8xxx_rtc_pm_ops ,
pm8xxx_rtc_suspend ,
pm8xxx_rtc_resume ) ;
2011-07-26 04:13:33 +04:00
static struct platform_driver pm8xxx_rtc_driver = {
. probe = pm8xxx_rtc_probe ,
. driver = {
2014-04-04 01:50:13 +04:00
. name = " rtc-pm8xxx " ,
. pm = & pm8xxx_rtc_pm_ops ,
. 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> " ) ;