2011-07-26 04:13:33 +04:00
/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*/
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)
# 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 .
* @ ctrl_reg : rtc control register .
* @ 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 ;
2011-07-26 04:13:33 +04:00
rtc_tm_to_time ( tm , & secs ) ;
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
rtc_time_to_tm ( secs , tm ) ;
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
rtc_tm_to_time ( & alarm - > time , & secs ) ;
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 ;
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
rtc_time_to_tm ( secs , & alarm - > time ) ;
rc = rtc_valid_tm ( & alarm - > time ) ;
if ( rc < 0 ) {
dev_err ( dev , " Invalid alarm time read from RTC \n " ) ;
return rc ;
}
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 ;
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 ;
}
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 ;
unsigned long irq_flags ;
rtc_update_irq ( rtc_dd - > rtc , 1 , RTC_IRQF | RTC_AF ) ;
spin_lock_irqsave ( & rtc_dd - > ctrl_reg_lock , irq_flags ) ;
/* 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 ) {
spin_unlock_irqrestore ( & rtc_dd - > ctrl_reg_lock , irq_flags ) ;
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 ) {
2011-07-26 04:13:33 +04:00
spin_unlock_irqrestore ( & rtc_dd - > ctrl_reg_lock , irq_flags ) ;
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 ;
}
spin_unlock_irqrestore ( & rtc_dd - > ctrl_reg_lock , irq_flags ) ;
/* 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 ) ,
} ;
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 } ,
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 ) ;
if ( rtc_dd - > rtc_alarm_irq < 0 ) {
dev_err ( & pdev - > dev , " Alarm IRQ resource absent! \n " ) ;
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 */
2013-07-04 02:07:09 +04:00
rtc_dd - > rtc = devm_rtc_device_register ( & pdev - > dev , " pm8xxx_rtc " ,
2014-04-04 01:50:10 +04:00
& pm8xxx_rtc_ops , THIS_MODULE ) ;
2011-07-26 04:13:33 +04:00
if ( IS_ERR ( rtc_dd - > rtc ) ) {
dev_err ( & pdev - > dev , " %s: RTC registration failed (%ld) \n " ,
2014-04-04 01:50:10 +04:00
__func__ , PTR_ERR ( rtc_dd - > rtc ) ) ;
2013-07-04 02:07:09 +04:00
return PTR_ERR ( rtc_dd - > rtc ) ;
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
}
dev_dbg ( & pdev - > dev , " Probe success !! \n " ) ;
return 0 ;
}
# 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> " ) ;