2019-04-08 00:16:46 +03:00
// SPDX-License-Identifier: GPL-2.0+
2011-03-23 02:34:55 +03:00
/*
* An RTC driver for the NVIDIA Tegra 200 series internal RTC .
*
2019-05-27 13:13:59 +03:00
* Copyright ( c ) 2010 - 2019 , NVIDIA Corporation .
2011-03-23 02:34:55 +03:00
*/
2017-01-12 19:07:42 +03:00
2017-01-12 19:07:43 +03:00
# include <linux/clk.h>
2017-01-12 19:07:42 +03:00
# include <linux/delay.h>
2011-03-23 02:34:55 +03:00
# include <linux/init.h>
# include <linux/io.h>
2017-01-12 19:07:42 +03:00
# include <linux/irq.h>
# include <linux/kernel.h>
# include <linux/module.h>
2018-06-20 08:47:28 +03:00
# include <linux/mod_devicetable.h>
2011-03-23 02:34:55 +03:00
# include <linux/platform_device.h>
2013-04-30 03:19:23 +04:00
# include <linux/pm.h>
2017-01-12 19:07:42 +03:00
# include <linux/rtc.h>
# include <linux/slab.h>
2011-03-23 02:34:55 +03:00
2019-05-27 13:13:57 +03:00
/* Set to 1 = busy every eight 32 kHz clocks during copy of sec+msec to AHB. */
2011-03-23 02:34:55 +03:00
# define TEGRA_RTC_REG_BUSY 0x004
# define TEGRA_RTC_REG_SECONDS 0x008
2019-05-27 13:13:57 +03:00
/* When msec is read, the seconds are buffered into shadow seconds. */
2011-03-23 02:34:55 +03:00
# define TEGRA_RTC_REG_SHADOW_SECONDS 0x00c
# define TEGRA_RTC_REG_MILLI_SECONDS 0x010
# define TEGRA_RTC_REG_SECONDS_ALARM0 0x014
# define TEGRA_RTC_REG_SECONDS_ALARM1 0x018
# define TEGRA_RTC_REG_MILLI_SECONDS_ALARM0 0x01c
# define TEGRA_RTC_REG_INTR_MASK 0x028
/* write 1 bits to clear status bits */
# define TEGRA_RTC_REG_INTR_STATUS 0x02c
/* bits in INTR_MASK */
# define TEGRA_RTC_INTR_MASK_MSEC_CDN_ALARM (1<<4)
# define TEGRA_RTC_INTR_MASK_SEC_CDN_ALARM (1<<3)
# define TEGRA_RTC_INTR_MASK_MSEC_ALARM (1<<2)
# define TEGRA_RTC_INTR_MASK_SEC_ALARM1 (1<<1)
# define TEGRA_RTC_INTR_MASK_SEC_ALARM0 (1<<0)
/* bits in INTR_STATUS */
# define TEGRA_RTC_INTR_STATUS_MSEC_CDN_ALARM (1<<4)
# define TEGRA_RTC_INTR_STATUS_SEC_CDN_ALARM (1<<3)
# define TEGRA_RTC_INTR_STATUS_MSEC_ALARM (1<<2)
# define TEGRA_RTC_INTR_STATUS_SEC_ALARM1 (1<<1)
# define TEGRA_RTC_INTR_STATUS_SEC_ALARM0 (1<<0)
struct tegra_rtc_info {
2019-05-27 13:13:57 +03:00
struct platform_device * pdev ;
2019-05-27 13:13:58 +03:00
struct rtc_device * rtc ;
void __iomem * base ; /* NULL if not initialized */
2019-05-27 13:13:57 +03:00
struct clk * clk ;
2019-05-27 13:13:58 +03:00
int irq ; /* alarm and periodic IRQ */
spinlock_t lock ;
2011-03-23 02:34:55 +03:00
} ;
2019-05-27 13:13:57 +03:00
/*
* RTC hardware is busy when it is updating its values over AHB once every
* eight 32 kHz clocks ( ~ 250 us ) . Outside of these updates the CPU is free to
* write . CPU is always free to read .
2011-03-23 02:34:55 +03:00
*/
static inline u32 tegra_rtc_check_busy ( struct tegra_rtc_info * info )
{
2019-05-27 13:13:58 +03:00
return readl ( info - > base + TEGRA_RTC_REG_BUSY ) & 1 ;
2011-03-23 02:34:55 +03:00
}
2019-05-27 13:13:57 +03:00
/*
* Wait for hardware to be ready for writing . This function tries to maximize
* the amount of time before the next update . It does this by waiting for the
* RTC to become busy with its periodic update , then returning once the RTC
* first becomes not busy .
*
2011-03-23 02:34:55 +03:00
* This periodic update ( where the seconds and milliseconds are copied to the
2019-05-27 13:13:57 +03:00
* AHB side ) occurs every eight 32 kHz clocks ( ~ 250 us ) . The behavior of this
* function allows us to make some assumptions without introducing a race ,
* because 250 us is plenty of time to read / write a value .
2011-03-23 02:34:55 +03:00
*/
static int tegra_rtc_wait_while_busy ( struct device * dev )
{
struct tegra_rtc_info * info = dev_get_drvdata ( dev ) ;
2019-05-27 13:13:57 +03:00
int retries = 500 ; /* ~490 us is the worst case, ~250 us is best */
2011-03-23 02:34:55 +03:00
2019-05-27 13:13:57 +03:00
/*
* First wait for the RTC to become busy . This is when it posts its
* updated seconds + msec registers to AHB side .
*/
2011-03-23 02:34:55 +03:00
while ( tegra_rtc_check_busy ( info ) ) {
if ( ! retries - - )
goto retry_failed ;
2019-05-27 13:13:57 +03:00
2011-03-23 02:34:55 +03:00
udelay ( 1 ) ;
}
/* now we have about 250 us to manipulate registers */
return 0 ;
retry_failed :
2019-05-27 13:13:57 +03:00
dev_err ( dev , " write failed: retry count exceeded \n " ) ;
2011-03-23 02:34:55 +03:00
return - ETIMEDOUT ;
}
static int tegra_rtc_read_time ( struct device * dev , struct rtc_time * tm )
{
struct tegra_rtc_info * info = dev_get_drvdata ( dev ) ;
2019-05-27 13:13:58 +03:00
unsigned long flags ;
2019-11-22 13:22:11 +03:00
u32 sec ;
2011-03-23 02:34:55 +03:00
2019-05-27 13:13:57 +03:00
/*
* RTC hardware copies seconds to shadow seconds when a read of
* milliseconds occurs . use a lock to keep other threads out .
*/
2019-05-27 13:13:58 +03:00
spin_lock_irqsave ( & info - > lock , flags ) ;
2011-03-23 02:34:55 +03:00
2019-11-22 13:22:11 +03:00
readl ( info - > base + TEGRA_RTC_REG_MILLI_SECONDS ) ;
2019-05-27 13:13:58 +03:00
sec = readl ( info - > base + TEGRA_RTC_REG_SHADOW_SECONDS ) ;
2011-03-23 02:34:55 +03:00
2019-05-27 13:13:58 +03:00
spin_unlock_irqrestore ( & info - > lock , flags ) ;
2011-03-23 02:34:55 +03:00
2019-04-08 00:16:45 +03:00
rtc_time64_to_tm ( sec , tm ) ;
2011-03-23 02:34:55 +03:00
2019-05-27 13:13:57 +03:00
dev_vdbg ( dev , " time read as %u, %ptR \n " , sec , tm ) ;
2011-03-23 02:34:55 +03:00
return 0 ;
}
static int tegra_rtc_set_time ( struct device * dev , struct rtc_time * tm )
{
struct tegra_rtc_info * info = dev_get_drvdata ( dev ) ;
2019-05-27 13:13:58 +03:00
u32 sec ;
2011-03-23 02:34:55 +03:00
int ret ;
2019-05-27 13:13:57 +03:00
/* convert tm to seconds */
2019-04-08 00:16:45 +03:00
sec = rtc_tm_to_time64 ( tm ) ;
2011-03-23 02:34:55 +03:00
2019-05-27 13:13:57 +03:00
dev_vdbg ( dev , " time set to %u, %ptR \n " , sec , tm ) ;
2011-03-23 02:34:55 +03:00
2019-05-27 13:13:57 +03:00
/* seconds only written if wait succeeded */
2011-03-23 02:34:55 +03:00
ret = tegra_rtc_wait_while_busy ( dev ) ;
if ( ! ret )
2019-05-27 13:13:58 +03:00
writel ( sec , info - > base + TEGRA_RTC_REG_SECONDS ) ;
2011-03-23 02:34:55 +03:00
dev_vdbg ( dev , " time read back as %d \n " ,
2019-05-27 13:13:58 +03:00
readl ( info - > base + TEGRA_RTC_REG_SECONDS ) ) ;
2011-03-23 02:34:55 +03:00
return ret ;
}
static int tegra_rtc_read_alarm ( struct device * dev , struct rtc_wkalrm * alarm )
{
struct tegra_rtc_info * info = dev_get_drvdata ( dev ) ;
2019-05-27 13:13:58 +03:00
u32 sec , value ;
2011-03-23 02:34:55 +03:00
2019-05-27 13:13:58 +03:00
sec = readl ( info - > base + TEGRA_RTC_REG_SECONDS_ALARM0 ) ;
2011-03-23 02:34:55 +03:00
if ( sec = = 0 ) {
2019-05-27 13:13:57 +03:00
/* alarm is disabled */
2011-03-23 02:34:55 +03:00
alarm - > enabled = 0 ;
} else {
2019-05-27 13:13:57 +03:00
/* alarm is enabled */
2011-03-23 02:34:55 +03:00
alarm - > enabled = 1 ;
2019-04-08 00:16:45 +03:00
rtc_time64_to_tm ( sec , & alarm - > time ) ;
2011-03-23 02:34:55 +03:00
}
2019-05-27 13:13:58 +03:00
value = readl ( info - > base + TEGRA_RTC_REG_INTR_STATUS ) ;
alarm - > pending = ( value & TEGRA_RTC_INTR_STATUS_SEC_ALARM0 ) ! = 0 ;
2011-03-23 02:34:55 +03:00
return 0 ;
}
static int tegra_rtc_alarm_irq_enable ( struct device * dev , unsigned int enabled )
{
struct tegra_rtc_info * info = dev_get_drvdata ( dev ) ;
2019-05-27 13:13:58 +03:00
unsigned long flags ;
u32 status ;
2011-03-23 02:34:55 +03:00
tegra_rtc_wait_while_busy ( dev ) ;
2019-05-27 13:13:58 +03:00
spin_lock_irqsave ( & info - > lock , flags ) ;
2011-03-23 02:34:55 +03:00
2019-05-27 13:13:57 +03:00
/* read the original value, and OR in the flag */
2019-05-27 13:13:58 +03:00
status = readl ( info - > base + TEGRA_RTC_REG_INTR_MASK ) ;
2011-03-23 02:34:55 +03:00
if ( enabled )
status | = TEGRA_RTC_INTR_MASK_SEC_ALARM0 ; /* set it */
else
status & = ~ TEGRA_RTC_INTR_MASK_SEC_ALARM0 ; /* clear it */
2019-05-27 13:13:58 +03:00
writel ( status , info - > base + TEGRA_RTC_REG_INTR_MASK ) ;
2011-03-23 02:34:55 +03:00
2019-05-27 13:13:58 +03:00
spin_unlock_irqrestore ( & info - > lock , flags ) ;
2011-03-23 02:34:55 +03:00
return 0 ;
}
static int tegra_rtc_set_alarm ( struct device * dev , struct rtc_wkalrm * alarm )
{
struct tegra_rtc_info * info = dev_get_drvdata ( dev ) ;
2019-05-27 13:13:58 +03:00
u32 sec ;
2011-03-23 02:34:55 +03:00
if ( alarm - > enabled )
2019-04-08 00:16:45 +03:00
sec = rtc_tm_to_time64 ( & alarm - > time ) ;
2011-03-23 02:34:55 +03:00
else
sec = 0 ;
tegra_rtc_wait_while_busy ( dev ) ;
2019-05-27 13:13:58 +03:00
writel ( sec , info - > base + TEGRA_RTC_REG_SECONDS_ALARM0 ) ;
2011-03-23 02:34:55 +03:00
dev_vdbg ( dev , " alarm read back as %d \n " ,
2019-05-27 13:13:58 +03:00
readl ( info - > base + TEGRA_RTC_REG_SECONDS_ALARM0 ) ) ;
2011-03-23 02:34:55 +03:00
/* if successfully written and alarm is enabled ... */
if ( sec ) {
tegra_rtc_alarm_irq_enable ( dev , 1 ) ;
2019-05-27 13:13:57 +03:00
dev_vdbg ( dev , " alarm set as %u, %ptR \n " , sec , & alarm - > time ) ;
2011-03-23 02:34:55 +03:00
} else {
2019-05-27 13:13:57 +03:00
/* disable alarm if 0 or write error */
2011-03-23 02:34:55 +03:00
dev_vdbg ( dev , " alarm disabled \n " ) ;
tegra_rtc_alarm_irq_enable ( dev , 0 ) ;
}
return 0 ;
}
static int tegra_rtc_proc ( struct device * dev , struct seq_file * seq )
{
if ( ! dev | | ! dev - > driver )
return 0 ;
2015-04-16 02:17:51 +03:00
seq_printf ( seq , " name \t \t : %s \n " , dev_name ( dev ) ) ;
return 0 ;
2011-03-23 02:34:55 +03:00
}
static irqreturn_t tegra_rtc_irq_handler ( int irq , void * data )
{
struct device * dev = data ;
struct tegra_rtc_info * info = dev_get_drvdata ( dev ) ;
2021-02-03 15:39:39 +03:00
unsigned long events = 0 ;
2019-05-27 13:13:58 +03:00
u32 status ;
2011-03-23 02:34:55 +03:00
2019-05-27 13:13:58 +03:00
status = readl ( info - > base + TEGRA_RTC_REG_INTR_STATUS ) ;
2011-03-23 02:34:55 +03:00
if ( status ) {
2019-05-27 13:13:57 +03:00
/* clear the interrupt masks and status on any IRQ */
2011-03-23 02:34:55 +03:00
tegra_rtc_wait_while_busy ( dev ) ;
2019-05-27 13:13:57 +03:00
2021-02-03 15:39:39 +03:00
spin_lock ( & info - > lock ) ;
2019-05-27 13:13:58 +03:00
writel ( 0 , info - > base + TEGRA_RTC_REG_INTR_MASK ) ;
writel ( status , info - > base + TEGRA_RTC_REG_INTR_STATUS ) ;
2021-02-03 15:39:39 +03:00
spin_unlock ( & info - > lock ) ;
2011-03-23 02:34:55 +03:00
}
2019-05-27 13:13:57 +03:00
/* check if alarm */
if ( status & TEGRA_RTC_INTR_STATUS_SEC_ALARM0 )
2011-03-23 02:34:55 +03:00
events | = RTC_IRQF | RTC_AF ;
2019-05-27 13:13:57 +03:00
/* check if periodic */
if ( status & TEGRA_RTC_INTR_STATUS_SEC_CDN_ALARM )
2011-03-23 02:34:55 +03:00
events | = RTC_IRQF | RTC_PF ;
2019-05-27 13:13:58 +03:00
rtc_update_irq ( info - > rtc , 1 , events ) ;
2011-03-23 02:34:55 +03:00
return IRQ_HANDLED ;
}
rtc: constify rtc_class_ops structures
Check for rtc_class_ops structures that are only passed to
devm_rtc_device_register, rtc_device_register,
platform_device_register_data, all of which declare the corresponding
parameter as const. Declare rtc_class_ops structures that have these
properties as const.
The semantic patch that makes this change is as follows:
(http://coccinelle.lip6.fr/)
// <smpl>
@r disable optional_qualifier@
identifier i;
position p;
@@
static struct rtc_class_ops i@p = { ... };
@ok@
identifier r.i;
expression e1,e2,e3,e4;
position p;
@@
(
devm_rtc_device_register(e1,e2,&i@p,e3)
|
rtc_device_register(e1,e2,&i@p,e3)
|
platform_device_register_data(e1,e2,e3,&i@p,e4)
)
@bad@
position p != {r.p,ok.p};
identifier r.i;
@@
i@p
@depends on !bad disable optional_qualifier@
identifier r.i;
@@
static
+const
struct rtc_class_ops i = { ... };
// </smpl>
Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr>
Acked-by: Baruch Siach <baruch@tkos.co.il>
Acked-by: Hans Ulli Kroll <ulli.kroll@googlemail.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Acked-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
2016-08-31 11:05:25 +03:00
static const struct rtc_class_ops tegra_rtc_ops = {
2019-05-27 13:13:57 +03:00
. read_time = tegra_rtc_read_time ,
. set_time = tegra_rtc_set_time ,
. read_alarm = tegra_rtc_read_alarm ,
. set_alarm = tegra_rtc_set_alarm ,
. proc = tegra_rtc_proc ,
2011-03-23 02:34:55 +03:00
. alarm_irq_enable = tegra_rtc_alarm_irq_enable ,
} ;
2013-01-05 03:34:45 +04:00
static const struct of_device_id tegra_rtc_dt_match [ ] = {
{ . compatible = " nvidia,tegra20-rtc " , } ,
{ }
} ;
MODULE_DEVICE_TABLE ( of , tegra_rtc_dt_match ) ;
2019-05-27 13:13:59 +03:00
static int tegra_rtc_probe ( struct platform_device * pdev )
2011-03-23 02:34:55 +03:00
{
struct tegra_rtc_info * info ;
int ret ;
2019-05-27 13:13:57 +03:00
info = devm_kzalloc ( & pdev - > dev , sizeof ( * info ) , GFP_KERNEL ) ;
2011-03-23 02:34:55 +03:00
if ( ! info )
return - ENOMEM ;
2019-10-06 13:29:20 +03:00
info - > base = devm_platform_ioremap_resource ( pdev , 0 ) ;
2019-05-27 13:13:58 +03:00
if ( IS_ERR ( info - > base ) )
return PTR_ERR ( info - > base ) ;
2011-03-23 02:34:55 +03:00
2018-09-21 13:12:09 +03:00
ret = platform_get_irq ( pdev , 0 ) ;
2019-07-30 21:15:39 +03:00
if ( ret < = 0 )
2018-09-21 13:12:09 +03:00
return ret ;
2019-05-27 13:13:58 +03:00
info - > irq = ret ;
2011-03-23 02:34:55 +03:00
2019-05-27 13:13:58 +03:00
info - > rtc = devm_rtc_allocate_device ( & pdev - > dev ) ;
if ( IS_ERR ( info - > rtc ) )
return PTR_ERR ( info - > rtc ) ;
2019-04-08 00:16:44 +03:00
2019-05-27 13:13:58 +03:00
info - > rtc - > ops = & tegra_rtc_ops ;
info - > rtc - > range_max = U32_MAX ;
2019-04-08 00:16:44 +03:00
2017-01-12 19:07:43 +03:00
info - > clk = devm_clk_get ( & pdev - > dev , NULL ) ;
if ( IS_ERR ( info - > clk ) )
return PTR_ERR ( info - > clk ) ;
ret = clk_prepare_enable ( info - > clk ) ;
if ( ret < 0 )
return ret ;
2019-05-27 13:13:57 +03:00
/* set context info */
2011-03-23 02:34:55 +03:00
info - > pdev = pdev ;
2019-05-27 13:13:58 +03:00
spin_lock_init ( & info - > lock ) ;
2011-03-23 02:34:55 +03:00
platform_set_drvdata ( pdev , info ) ;
2019-05-27 13:13:57 +03:00
/* clear out the hardware */
2019-05-27 13:13:58 +03:00
writel ( 0 , info - > base + TEGRA_RTC_REG_SECONDS_ALARM0 ) ;
writel ( 0xffffffff , info - > base + TEGRA_RTC_REG_INTR_STATUS ) ;
writel ( 0 , info - > base + TEGRA_RTC_REG_INTR_MASK ) ;
2011-03-23 02:34:55 +03:00
device_init_wakeup ( & pdev - > dev , 1 ) ;
2019-05-27 13:13:58 +03:00
ret = devm_request_irq ( & pdev - > dev , info - > irq , tegra_rtc_irq_handler ,
IRQF_TRIGGER_HIGH , dev_name ( & pdev - > dev ) ,
& pdev - > dev ) ;
2011-03-23 02:34:55 +03:00
if ( ret ) {
2019-05-27 13:13:57 +03:00
dev_err ( & pdev - > dev , " failed to request interrupt: %d \n " , ret ) ;
2019-04-08 00:16:44 +03:00
goto disable_clk ;
}
2020-11-09 19:34:08 +03:00
ret = devm_rtc_register_device ( info - > rtc ) ;
2019-08-19 01:00:41 +03:00
if ( ret )
2017-01-12 19:07:43 +03:00
goto disable_clk ;
2011-03-23 02:34:55 +03:00
dev_notice ( & pdev - > dev , " Tegra internal Real Time Clock \n " ) ;
2017-01-12 19:07:43 +03:00
return 0 ;
disable_clk :
clk_disable_unprepare ( info - > clk ) ;
return ret ;
}
static int tegra_rtc_remove ( struct platform_device * pdev )
{
struct tegra_rtc_info * info = platform_get_drvdata ( pdev ) ;
clk_disable_unprepare ( info - > clk ) ;
2011-03-23 02:34:55 +03:00
return 0 ;
}
2013-04-30 03:19:21 +04:00
# ifdef CONFIG_PM_SLEEP
2013-04-30 03:19:23 +04:00
static int tegra_rtc_suspend ( struct device * dev )
2011-03-23 02:34:55 +03:00
{
2013-04-30 03:19:23 +04:00
struct tegra_rtc_info * info = dev_get_drvdata ( dev ) ;
2011-03-23 02:34:55 +03:00
tegra_rtc_wait_while_busy ( dev ) ;
2019-05-27 13:13:57 +03:00
/* only use ALARM0 as a wake source */
2019-05-27 13:13:58 +03:00
writel ( 0xffffffff , info - > base + TEGRA_RTC_REG_INTR_STATUS ) ;
2011-03-23 02:34:55 +03:00
writel ( TEGRA_RTC_INTR_STATUS_SEC_ALARM0 ,
2019-05-27 13:13:58 +03:00
info - > base + TEGRA_RTC_REG_INTR_MASK ) ;
2011-03-23 02:34:55 +03:00
dev_vdbg ( dev , " alarm sec = %d \n " ,
2019-05-27 13:13:58 +03:00
readl ( info - > base + TEGRA_RTC_REG_SECONDS_ALARM0 ) ) ;
2011-03-23 02:34:55 +03:00
2019-05-27 13:13:57 +03:00
dev_vdbg ( dev , " Suspend (device_may_wakeup=%d) IRQ:%d \n " ,
2019-05-27 13:13:58 +03:00
device_may_wakeup ( dev ) , info - > irq ) ;
2011-03-23 02:34:55 +03:00
2019-05-27 13:13:57 +03:00
/* leave the alarms on as a wake source */
2011-03-23 02:34:55 +03:00
if ( device_may_wakeup ( dev ) )
2019-05-27 13:13:58 +03:00
enable_irq_wake ( info - > irq ) ;
2011-03-23 02:34:55 +03:00
return 0 ;
}
2013-04-30 03:19:23 +04:00
static int tegra_rtc_resume ( struct device * dev )
2011-03-23 02:34:55 +03:00
{
2013-04-30 03:19:23 +04:00
struct tegra_rtc_info * info = dev_get_drvdata ( dev ) ;
2011-03-23 02:34:55 +03:00
dev_vdbg ( dev , " Resume (device_may_wakeup=%d) \n " ,
2019-05-27 13:13:57 +03:00
device_may_wakeup ( dev ) ) ;
/* alarms were left on as a wake source, turn them off */
2011-03-23 02:34:55 +03:00
if ( device_may_wakeup ( dev ) )
2019-05-27 13:13:58 +03:00
disable_irq_wake ( info - > irq ) ;
2011-03-23 02:34:55 +03:00
return 0 ;
}
# endif
2013-04-30 03:19:23 +04:00
static SIMPLE_DEV_PM_OPS ( tegra_rtc_pm_ops , tegra_rtc_suspend , tegra_rtc_resume ) ;
2011-03-23 02:34:55 +03:00
static void tegra_rtc_shutdown ( struct platform_device * pdev )
{
2019-05-27 13:13:57 +03:00
dev_vdbg ( & pdev - > dev , " disabling interrupts \n " ) ;
2011-03-23 02:34:55 +03:00
tegra_rtc_alarm_irq_enable ( & pdev - > dev , 0 ) ;
}
static struct platform_driver tegra_rtc_driver = {
2019-05-27 13:13:59 +03:00
. probe = tegra_rtc_probe ,
2019-05-27 13:13:57 +03:00
. remove = tegra_rtc_remove ,
. shutdown = tegra_rtc_shutdown ,
. driver = {
. name = " tegra_rtc " ,
2013-01-05 03:34:45 +04:00
. of_match_table = tegra_rtc_dt_match ,
2019-05-27 13:13:57 +03:00
. pm = & tegra_rtc_pm_ops ,
2011-03-23 02:34:55 +03:00
} ,
} ;
2019-05-27 13:13:59 +03:00
module_platform_driver ( tegra_rtc_driver ) ;
2011-03-23 02:34:55 +03:00
MODULE_AUTHOR ( " Jon Mayo <jmayo@nvidia.com> " ) ;
MODULE_DESCRIPTION ( " driver for Tegra internal RTC " ) ;
MODULE_LICENSE ( " GPL " ) ;