1b6838275SAlexandre Belloni // SPDX-License-Identifier: GPL-2.0+
2ff859ba6SAndrew Chew /*
3ff859ba6SAndrew Chew * An RTC driver for the NVIDIA Tegra 200 series internal RTC.
4ff859ba6SAndrew Chew *
53e483e59SThierry Reding * Copyright (c) 2010-2019, NVIDIA Corporation.
6ff859ba6SAndrew Chew */
70ae20595SThierry Reding
85fa40869SThierry Reding #include <linux/clk.h>
9ff859ba6SAndrew Chew #include <linux/delay.h>
100ae20595SThierry Reding #include <linux/init.h>
110ae20595SThierry Reding #include <linux/io.h>
120ae20595SThierry Reding #include <linux/irq.h>
130ae20595SThierry Reding #include <linux/kernel.h>
140ae20595SThierry Reding #include <linux/module.h>
15ac316725SRandy Dunlap #include <linux/mod_devicetable.h>
16ff859ba6SAndrew Chew #include <linux/platform_device.h>
173443ad09SLaxman Dewangan #include <linux/pm.h>
180ae20595SThierry Reding #include <linux/rtc.h>
190ae20595SThierry Reding #include <linux/slab.h>
20ff859ba6SAndrew Chew
21a2d29238SThierry Reding /* Set to 1 = busy every eight 32 kHz clocks during copy of sec+msec to AHB. */
22ff859ba6SAndrew Chew #define TEGRA_RTC_REG_BUSY 0x004
23ff859ba6SAndrew Chew #define TEGRA_RTC_REG_SECONDS 0x008
24a2d29238SThierry Reding /* When msec is read, the seconds are buffered into shadow seconds. */
25ff859ba6SAndrew Chew #define TEGRA_RTC_REG_SHADOW_SECONDS 0x00c
26ff859ba6SAndrew Chew #define TEGRA_RTC_REG_MILLI_SECONDS 0x010
27ff859ba6SAndrew Chew #define TEGRA_RTC_REG_SECONDS_ALARM0 0x014
28ff859ba6SAndrew Chew #define TEGRA_RTC_REG_SECONDS_ALARM1 0x018
29ff859ba6SAndrew Chew #define TEGRA_RTC_REG_MILLI_SECONDS_ALARM0 0x01c
30ff859ba6SAndrew Chew #define TEGRA_RTC_REG_INTR_MASK 0x028
31ff859ba6SAndrew Chew /* write 1 bits to clear status bits */
32ff859ba6SAndrew Chew #define TEGRA_RTC_REG_INTR_STATUS 0x02c
33ff859ba6SAndrew Chew
34ff859ba6SAndrew Chew /* bits in INTR_MASK */
35ff859ba6SAndrew Chew #define TEGRA_RTC_INTR_MASK_MSEC_CDN_ALARM (1<<4)
36ff859ba6SAndrew Chew #define TEGRA_RTC_INTR_MASK_SEC_CDN_ALARM (1<<3)
37ff859ba6SAndrew Chew #define TEGRA_RTC_INTR_MASK_MSEC_ALARM (1<<2)
38ff859ba6SAndrew Chew #define TEGRA_RTC_INTR_MASK_SEC_ALARM1 (1<<1)
39ff859ba6SAndrew Chew #define TEGRA_RTC_INTR_MASK_SEC_ALARM0 (1<<0)
40ff859ba6SAndrew Chew
41ff859ba6SAndrew Chew /* bits in INTR_STATUS */
42ff859ba6SAndrew Chew #define TEGRA_RTC_INTR_STATUS_MSEC_CDN_ALARM (1<<4)
43ff859ba6SAndrew Chew #define TEGRA_RTC_INTR_STATUS_SEC_CDN_ALARM (1<<3)
44ff859ba6SAndrew Chew #define TEGRA_RTC_INTR_STATUS_MSEC_ALARM (1<<2)
45ff859ba6SAndrew Chew #define TEGRA_RTC_INTR_STATUS_SEC_ALARM1 (1<<1)
46ff859ba6SAndrew Chew #define TEGRA_RTC_INTR_STATUS_SEC_ALARM0 (1<<0)
47ff859ba6SAndrew Chew
48ff859ba6SAndrew Chew struct tegra_rtc_info {
49ff859ba6SAndrew Chew struct platform_device *pdev;
50c6af561aSThierry Reding struct rtc_device *rtc;
51c6af561aSThierry Reding void __iomem *base; /* NULL if not initialized */
525fa40869SThierry Reding struct clk *clk;
53c6af561aSThierry Reding int irq; /* alarm and periodic IRQ */
54c6af561aSThierry Reding spinlock_t lock;
55ff859ba6SAndrew Chew };
56ff859ba6SAndrew Chew
57a2d29238SThierry Reding /*
58a2d29238SThierry Reding * RTC hardware is busy when it is updating its values over AHB once every
59a2d29238SThierry Reding * eight 32 kHz clocks (~250 us). Outside of these updates the CPU is free to
60a2d29238SThierry Reding * write. CPU is always free to read.
61ff859ba6SAndrew Chew */
tegra_rtc_check_busy(struct tegra_rtc_info * info)62ff859ba6SAndrew Chew static inline u32 tegra_rtc_check_busy(struct tegra_rtc_info *info)
63ff859ba6SAndrew Chew {
64c6af561aSThierry Reding return readl(info->base + TEGRA_RTC_REG_BUSY) & 1;
65ff859ba6SAndrew Chew }
66ff859ba6SAndrew Chew
67a2d29238SThierry Reding /*
68a2d29238SThierry Reding * Wait for hardware to be ready for writing. This function tries to maximize
69a2d29238SThierry Reding * the amount of time before the next update. It does this by waiting for the
70a2d29238SThierry Reding * RTC to become busy with its periodic update, then returning once the RTC
71a2d29238SThierry Reding * first becomes not busy.
72a2d29238SThierry Reding *
73ff859ba6SAndrew Chew * This periodic update (where the seconds and milliseconds are copied to the
74a2d29238SThierry Reding * AHB side) occurs every eight 32 kHz clocks (~250 us). The behavior of this
75a2d29238SThierry Reding * function allows us to make some assumptions without introducing a race,
76a2d29238SThierry Reding * because 250 us is plenty of time to read/write a value.
77ff859ba6SAndrew Chew */
tegra_rtc_wait_while_busy(struct device * dev)78ff859ba6SAndrew Chew static int tegra_rtc_wait_while_busy(struct device *dev)
79ff859ba6SAndrew Chew {
80ff859ba6SAndrew Chew struct tegra_rtc_info *info = dev_get_drvdata(dev);
81a2d29238SThierry Reding int retries = 500; /* ~490 us is the worst case, ~250 us is best */
82ff859ba6SAndrew Chew
83a2d29238SThierry Reding /*
84a2d29238SThierry Reding * First wait for the RTC to become busy. This is when it posts its
85a2d29238SThierry Reding * updated seconds+msec registers to AHB side.
86a2d29238SThierry Reding */
87ff859ba6SAndrew Chew while (tegra_rtc_check_busy(info)) {
88ff859ba6SAndrew Chew if (!retries--)
89ff859ba6SAndrew Chew goto retry_failed;
90a2d29238SThierry Reding
91ff859ba6SAndrew Chew udelay(1);
92ff859ba6SAndrew Chew }
93ff859ba6SAndrew Chew
94ff859ba6SAndrew Chew /* now we have about 250 us to manipulate registers */
95ff859ba6SAndrew Chew return 0;
96ff859ba6SAndrew Chew
97ff859ba6SAndrew Chew retry_failed:
98a2d29238SThierry Reding dev_err(dev, "write failed: retry count exceeded\n");
99ff859ba6SAndrew Chew return -ETIMEDOUT;
100ff859ba6SAndrew Chew }
101ff859ba6SAndrew Chew
tegra_rtc_read_time(struct device * dev,struct rtc_time * tm)102ff859ba6SAndrew Chew static int tegra_rtc_read_time(struct device *dev, struct rtc_time *tm)
103ff859ba6SAndrew Chew {
104ff859ba6SAndrew Chew struct tegra_rtc_info *info = dev_get_drvdata(dev);
105c6af561aSThierry Reding unsigned long flags;
1068321c2ecSAlexandre Belloni u32 sec;
107ff859ba6SAndrew Chew
108a2d29238SThierry Reding /*
109a2d29238SThierry Reding * RTC hardware copies seconds to shadow seconds when a read of
110a2d29238SThierry Reding * milliseconds occurs. use a lock to keep other threads out.
111a2d29238SThierry Reding */
112c6af561aSThierry Reding spin_lock_irqsave(&info->lock, flags);
113ff859ba6SAndrew Chew
1148321c2ecSAlexandre Belloni readl(info->base + TEGRA_RTC_REG_MILLI_SECONDS);
115c6af561aSThierry Reding sec = readl(info->base + TEGRA_RTC_REG_SHADOW_SECONDS);
116ff859ba6SAndrew Chew
117c6af561aSThierry Reding spin_unlock_irqrestore(&info->lock, flags);
118ff859ba6SAndrew Chew
11934ea0ac3SAlexandre Belloni rtc_time64_to_tm(sec, tm);
120ff859ba6SAndrew Chew
121a2d29238SThierry Reding dev_vdbg(dev, "time read as %u, %ptR\n", sec, tm);
122ff859ba6SAndrew Chew
123ff859ba6SAndrew Chew return 0;
124ff859ba6SAndrew Chew }
125ff859ba6SAndrew Chew
tegra_rtc_set_time(struct device * dev,struct rtc_time * tm)126ff859ba6SAndrew Chew static int tegra_rtc_set_time(struct device *dev, struct rtc_time *tm)
127ff859ba6SAndrew Chew {
128ff859ba6SAndrew Chew struct tegra_rtc_info *info = dev_get_drvdata(dev);
129c6af561aSThierry Reding u32 sec;
130ff859ba6SAndrew Chew int ret;
131ff859ba6SAndrew Chew
132a2d29238SThierry Reding /* convert tm to seconds */
13334ea0ac3SAlexandre Belloni sec = rtc_tm_to_time64(tm);
134ff859ba6SAndrew Chew
135a2d29238SThierry Reding dev_vdbg(dev, "time set to %u, %ptR\n", sec, tm);
136ff859ba6SAndrew Chew
137a2d29238SThierry Reding /* seconds only written if wait succeeded */
138ff859ba6SAndrew Chew ret = tegra_rtc_wait_while_busy(dev);
139ff859ba6SAndrew Chew if (!ret)
140c6af561aSThierry Reding writel(sec, info->base + TEGRA_RTC_REG_SECONDS);
141ff859ba6SAndrew Chew
142ff859ba6SAndrew Chew dev_vdbg(dev, "time read back as %d\n",
143c6af561aSThierry Reding readl(info->base + TEGRA_RTC_REG_SECONDS));
144ff859ba6SAndrew Chew
145ff859ba6SAndrew Chew return ret;
146ff859ba6SAndrew Chew }
147ff859ba6SAndrew Chew
tegra_rtc_read_alarm(struct device * dev,struct rtc_wkalrm * alarm)148ff859ba6SAndrew Chew static int tegra_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
149ff859ba6SAndrew Chew {
150ff859ba6SAndrew Chew struct tegra_rtc_info *info = dev_get_drvdata(dev);
151c6af561aSThierry Reding u32 sec, value;
152ff859ba6SAndrew Chew
153c6af561aSThierry Reding sec = readl(info->base + TEGRA_RTC_REG_SECONDS_ALARM0);
154ff859ba6SAndrew Chew
155ff859ba6SAndrew Chew if (sec == 0) {
156a2d29238SThierry Reding /* alarm is disabled */
157ff859ba6SAndrew Chew alarm->enabled = 0;
158ff859ba6SAndrew Chew } else {
159a2d29238SThierry Reding /* alarm is enabled */
160ff859ba6SAndrew Chew alarm->enabled = 1;
16134ea0ac3SAlexandre Belloni rtc_time64_to_tm(sec, &alarm->time);
162ff859ba6SAndrew Chew }
163ff859ba6SAndrew Chew
164c6af561aSThierry Reding value = readl(info->base + TEGRA_RTC_REG_INTR_STATUS);
165c6af561aSThierry Reding alarm->pending = (value & TEGRA_RTC_INTR_STATUS_SEC_ALARM0) != 0;
166ff859ba6SAndrew Chew
167ff859ba6SAndrew Chew return 0;
168ff859ba6SAndrew Chew }
169ff859ba6SAndrew Chew
tegra_rtc_alarm_irq_enable(struct device * dev,unsigned int enabled)170ff859ba6SAndrew Chew static int tegra_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
171ff859ba6SAndrew Chew {
172ff859ba6SAndrew Chew struct tegra_rtc_info *info = dev_get_drvdata(dev);
173c6af561aSThierry Reding unsigned long flags;
174c6af561aSThierry Reding u32 status;
175ff859ba6SAndrew Chew
176ff859ba6SAndrew Chew tegra_rtc_wait_while_busy(dev);
177c6af561aSThierry Reding spin_lock_irqsave(&info->lock, flags);
178ff859ba6SAndrew Chew
179a2d29238SThierry Reding /* read the original value, and OR in the flag */
180c6af561aSThierry Reding status = readl(info->base + TEGRA_RTC_REG_INTR_MASK);
181ff859ba6SAndrew Chew if (enabled)
182ff859ba6SAndrew Chew status |= TEGRA_RTC_INTR_MASK_SEC_ALARM0; /* set it */
183ff859ba6SAndrew Chew else
184ff859ba6SAndrew Chew status &= ~TEGRA_RTC_INTR_MASK_SEC_ALARM0; /* clear it */
185ff859ba6SAndrew Chew
186c6af561aSThierry Reding writel(status, info->base + TEGRA_RTC_REG_INTR_MASK);
187ff859ba6SAndrew Chew
188c6af561aSThierry Reding spin_unlock_irqrestore(&info->lock, flags);
189ff859ba6SAndrew Chew
190ff859ba6SAndrew Chew return 0;
191ff859ba6SAndrew Chew }
192ff859ba6SAndrew Chew
tegra_rtc_set_alarm(struct device * dev,struct rtc_wkalrm * alarm)193ff859ba6SAndrew Chew static int tegra_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
194ff859ba6SAndrew Chew {
195ff859ba6SAndrew Chew struct tegra_rtc_info *info = dev_get_drvdata(dev);
196c6af561aSThierry Reding u32 sec;
197ff859ba6SAndrew Chew
198ff859ba6SAndrew Chew if (alarm->enabled)
19934ea0ac3SAlexandre Belloni sec = rtc_tm_to_time64(&alarm->time);
200ff859ba6SAndrew Chew else
201ff859ba6SAndrew Chew sec = 0;
202ff859ba6SAndrew Chew
203ff859ba6SAndrew Chew tegra_rtc_wait_while_busy(dev);
204c6af561aSThierry Reding writel(sec, info->base + TEGRA_RTC_REG_SECONDS_ALARM0);
205ff859ba6SAndrew Chew dev_vdbg(dev, "alarm read back as %d\n",
206c6af561aSThierry Reding readl(info->base + TEGRA_RTC_REG_SECONDS_ALARM0));
207ff859ba6SAndrew Chew
208ff859ba6SAndrew Chew /* if successfully written and alarm is enabled ... */
209ff859ba6SAndrew Chew if (sec) {
210ff859ba6SAndrew Chew tegra_rtc_alarm_irq_enable(dev, 1);
211a2d29238SThierry Reding dev_vdbg(dev, "alarm set as %u, %ptR\n", sec, &alarm->time);
212ff859ba6SAndrew Chew } else {
213a2d29238SThierry Reding /* disable alarm if 0 or write error */
214ff859ba6SAndrew Chew dev_vdbg(dev, "alarm disabled\n");
215ff859ba6SAndrew Chew tegra_rtc_alarm_irq_enable(dev, 0);
216ff859ba6SAndrew Chew }
217ff859ba6SAndrew Chew
218ff859ba6SAndrew Chew return 0;
219ff859ba6SAndrew Chew }
220ff859ba6SAndrew Chew
tegra_rtc_proc(struct device * dev,struct seq_file * seq)221ff859ba6SAndrew Chew static int tegra_rtc_proc(struct device *dev, struct seq_file *seq)
222ff859ba6SAndrew Chew {
223ff859ba6SAndrew Chew if (!dev || !dev->driver)
224ff859ba6SAndrew Chew return 0;
225ff859ba6SAndrew Chew
2264395eb1fSJoe Perches seq_printf(seq, "name\t\t: %s\n", dev_name(dev));
2274395eb1fSJoe Perches
2284395eb1fSJoe Perches return 0;
229ff859ba6SAndrew Chew }
230ff859ba6SAndrew Chew
tegra_rtc_irq_handler(int irq,void * data)231ff859ba6SAndrew Chew static irqreturn_t tegra_rtc_irq_handler(int irq, void *data)
232ff859ba6SAndrew Chew {
233ff859ba6SAndrew Chew struct device *dev = data;
234ff859ba6SAndrew Chew struct tegra_rtc_info *info = dev_get_drvdata(dev);
235669022c2SXiaofei Tan unsigned long events = 0;
236c6af561aSThierry Reding u32 status;
237ff859ba6SAndrew Chew
238c6af561aSThierry Reding status = readl(info->base + TEGRA_RTC_REG_INTR_STATUS);
239ff859ba6SAndrew Chew if (status) {
240a2d29238SThierry Reding /* clear the interrupt masks and status on any IRQ */
241ff859ba6SAndrew Chew tegra_rtc_wait_while_busy(dev);
242a2d29238SThierry Reding
243669022c2SXiaofei Tan spin_lock(&info->lock);
244c6af561aSThierry Reding writel(0, info->base + TEGRA_RTC_REG_INTR_MASK);
245c6af561aSThierry Reding writel(status, info->base + TEGRA_RTC_REG_INTR_STATUS);
246669022c2SXiaofei Tan spin_unlock(&info->lock);
247ff859ba6SAndrew Chew }
248ff859ba6SAndrew Chew
249a2d29238SThierry Reding /* check if alarm */
250a2d29238SThierry Reding if (status & TEGRA_RTC_INTR_STATUS_SEC_ALARM0)
251ff859ba6SAndrew Chew events |= RTC_IRQF | RTC_AF;
252ff859ba6SAndrew Chew
253a2d29238SThierry Reding /* check if periodic */
254a2d29238SThierry Reding if (status & TEGRA_RTC_INTR_STATUS_SEC_CDN_ALARM)
255ff859ba6SAndrew Chew events |= RTC_IRQF | RTC_PF;
256ff859ba6SAndrew Chew
257c6af561aSThierry Reding rtc_update_irq(info->rtc, 1, events);
258ff859ba6SAndrew Chew
259ff859ba6SAndrew Chew return IRQ_HANDLED;
260ff859ba6SAndrew Chew }
261ff859ba6SAndrew Chew
26234c7b3acSJulia Lawall static const struct rtc_class_ops tegra_rtc_ops = {
263ff859ba6SAndrew Chew .read_time = tegra_rtc_read_time,
264ff859ba6SAndrew Chew .set_time = tegra_rtc_set_time,
265ff859ba6SAndrew Chew .read_alarm = tegra_rtc_read_alarm,
266ff859ba6SAndrew Chew .set_alarm = tegra_rtc_set_alarm,
267ff859ba6SAndrew Chew .proc = tegra_rtc_proc,
268ff859ba6SAndrew Chew .alarm_irq_enable = tegra_rtc_alarm_irq_enable,
269ff859ba6SAndrew Chew };
270ff859ba6SAndrew Chew
2712d79cf8aSJoseph Lo static const struct of_device_id tegra_rtc_dt_match[] = {
2722d79cf8aSJoseph Lo { .compatible = "nvidia,tegra20-rtc", },
2732d79cf8aSJoseph Lo {}
2742d79cf8aSJoseph Lo };
2752d79cf8aSJoseph Lo MODULE_DEVICE_TABLE(of, tegra_rtc_dt_match);
2762d79cf8aSJoseph Lo
tegra_rtc_probe(struct platform_device * pdev)2773e483e59SThierry Reding static int tegra_rtc_probe(struct platform_device *pdev)
278ff859ba6SAndrew Chew {
279ff859ba6SAndrew Chew struct tegra_rtc_info *info;
280ff859ba6SAndrew Chew int ret;
281ff859ba6SAndrew Chew
282a2d29238SThierry Reding info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
283ff859ba6SAndrew Chew if (!info)
284ff859ba6SAndrew Chew return -ENOMEM;
285ff859ba6SAndrew Chew
28609ef18bcSYueHaibing info->base = devm_platform_ioremap_resource(pdev, 0);
287c6af561aSThierry Reding if (IS_ERR(info->base))
288c6af561aSThierry Reding return PTR_ERR(info->base);
289ff859ba6SAndrew Chew
290fe0b5cedSThierry Reding ret = platform_get_irq(pdev, 0);
291faac9102SStephen Boyd if (ret <= 0)
292fe0b5cedSThierry Reding return ret;
293fe0b5cedSThierry Reding
294c6af561aSThierry Reding info->irq = ret;
295ff859ba6SAndrew Chew
296c6af561aSThierry Reding info->rtc = devm_rtc_allocate_device(&pdev->dev);
297c6af561aSThierry Reding if (IS_ERR(info->rtc))
298c6af561aSThierry Reding return PTR_ERR(info->rtc);
299e1089802SAlexandre Belloni
300c6af561aSThierry Reding info->rtc->ops = &tegra_rtc_ops;
301c6af561aSThierry Reding info->rtc->range_max = U32_MAX;
302e1089802SAlexandre Belloni
3035fa40869SThierry Reding info->clk = devm_clk_get(&pdev->dev, NULL);
3045fa40869SThierry Reding if (IS_ERR(info->clk))
3055fa40869SThierry Reding return PTR_ERR(info->clk);
3065fa40869SThierry Reding
3075fa40869SThierry Reding ret = clk_prepare_enable(info->clk);
3085fa40869SThierry Reding if (ret < 0)
3095fa40869SThierry Reding return ret;
3105fa40869SThierry Reding
311a2d29238SThierry Reding /* set context info */
312ff859ba6SAndrew Chew info->pdev = pdev;
313c6af561aSThierry Reding spin_lock_init(&info->lock);
314ff859ba6SAndrew Chew
315ff859ba6SAndrew Chew platform_set_drvdata(pdev, info);
316ff859ba6SAndrew Chew
317a2d29238SThierry Reding /* clear out the hardware */
318c6af561aSThierry Reding writel(0, info->base + TEGRA_RTC_REG_SECONDS_ALARM0);
319c6af561aSThierry Reding writel(0xffffffff, info->base + TEGRA_RTC_REG_INTR_STATUS);
320c6af561aSThierry Reding writel(0, info->base + TEGRA_RTC_REG_INTR_MASK);
321ff859ba6SAndrew Chew
322ff859ba6SAndrew Chew device_init_wakeup(&pdev->dev, 1);
323ff859ba6SAndrew Chew
324c6af561aSThierry Reding ret = devm_request_irq(&pdev->dev, info->irq, tegra_rtc_irq_handler,
325c6af561aSThierry Reding IRQF_TRIGGER_HIGH, dev_name(&pdev->dev),
326c6af561aSThierry Reding &pdev->dev);
327ff859ba6SAndrew Chew if (ret) {
328a2d29238SThierry Reding dev_err(&pdev->dev, "failed to request interrupt: %d\n", ret);
3295fa40869SThierry Reding goto disable_clk;
330ff859ba6SAndrew Chew }
331ff859ba6SAndrew Chew
332fdcfd854SBartosz Golaszewski ret = devm_rtc_register_device(info->rtc);
33344c638ceSAlexandre Belloni if (ret)
334e1089802SAlexandre Belloni goto disable_clk;
335e1089802SAlexandre Belloni
33668567112SLaxman Dewangan dev_notice(&pdev->dev, "Tegra internal Real Time Clock\n");
337ff859ba6SAndrew Chew
338ff859ba6SAndrew Chew return 0;
3395fa40869SThierry Reding
3405fa40869SThierry Reding disable_clk:
3415fa40869SThierry Reding clk_disable_unprepare(info->clk);
3425fa40869SThierry Reding return ret;
3435fa40869SThierry Reding }
3445fa40869SThierry Reding
tegra_rtc_remove(struct platform_device * pdev)345*31c94505SUwe Kleine-König static void tegra_rtc_remove(struct platform_device *pdev)
3465fa40869SThierry Reding {
3475fa40869SThierry Reding struct tegra_rtc_info *info = platform_get_drvdata(pdev);
3485fa40869SThierry Reding
3495fa40869SThierry Reding clk_disable_unprepare(info->clk);
350ff859ba6SAndrew Chew }
351ff859ba6SAndrew Chew
35238a6276eSLaxman Dewangan #ifdef CONFIG_PM_SLEEP
tegra_rtc_suspend(struct device * dev)3533443ad09SLaxman Dewangan static int tegra_rtc_suspend(struct device *dev)
354ff859ba6SAndrew Chew {
3553443ad09SLaxman Dewangan struct tegra_rtc_info *info = dev_get_drvdata(dev);
356ff859ba6SAndrew Chew
357ff859ba6SAndrew Chew tegra_rtc_wait_while_busy(dev);
358ff859ba6SAndrew Chew
359a2d29238SThierry Reding /* only use ALARM0 as a wake source */
360c6af561aSThierry Reding writel(0xffffffff, info->base + TEGRA_RTC_REG_INTR_STATUS);
361ff859ba6SAndrew Chew writel(TEGRA_RTC_INTR_STATUS_SEC_ALARM0,
362c6af561aSThierry Reding info->base + TEGRA_RTC_REG_INTR_MASK);
363ff859ba6SAndrew Chew
364ff859ba6SAndrew Chew dev_vdbg(dev, "alarm sec = %d\n",
365c6af561aSThierry Reding readl(info->base + TEGRA_RTC_REG_SECONDS_ALARM0));
366ff859ba6SAndrew Chew
367a2d29238SThierry Reding dev_vdbg(dev, "Suspend (device_may_wakeup=%d) IRQ:%d\n",
368c6af561aSThierry Reding device_may_wakeup(dev), info->irq);
369ff859ba6SAndrew Chew
370a2d29238SThierry Reding /* leave the alarms on as a wake source */
371ff859ba6SAndrew Chew if (device_may_wakeup(dev))
372c6af561aSThierry Reding enable_irq_wake(info->irq);
373ff859ba6SAndrew Chew
374ff859ba6SAndrew Chew return 0;
375ff859ba6SAndrew Chew }
376ff859ba6SAndrew Chew
tegra_rtc_resume(struct device * dev)3773443ad09SLaxman Dewangan static int tegra_rtc_resume(struct device *dev)
378ff859ba6SAndrew Chew {
3793443ad09SLaxman Dewangan struct tegra_rtc_info *info = dev_get_drvdata(dev);
380ff859ba6SAndrew Chew
381ff859ba6SAndrew Chew dev_vdbg(dev, "Resume (device_may_wakeup=%d)\n",
382ff859ba6SAndrew Chew device_may_wakeup(dev));
383a2d29238SThierry Reding
384a2d29238SThierry Reding /* alarms were left on as a wake source, turn them off */
385ff859ba6SAndrew Chew if (device_may_wakeup(dev))
386c6af561aSThierry Reding disable_irq_wake(info->irq);
387ff859ba6SAndrew Chew
388ff859ba6SAndrew Chew return 0;
389ff859ba6SAndrew Chew }
390ff859ba6SAndrew Chew #endif
391ff859ba6SAndrew Chew
3923443ad09SLaxman Dewangan static SIMPLE_DEV_PM_OPS(tegra_rtc_pm_ops, tegra_rtc_suspend, tegra_rtc_resume);
3933443ad09SLaxman Dewangan
tegra_rtc_shutdown(struct platform_device * pdev)394ff859ba6SAndrew Chew static void tegra_rtc_shutdown(struct platform_device *pdev)
395ff859ba6SAndrew Chew {
396a2d29238SThierry Reding dev_vdbg(&pdev->dev, "disabling interrupts\n");
397ff859ba6SAndrew Chew tegra_rtc_alarm_irq_enable(&pdev->dev, 0);
398ff859ba6SAndrew Chew }
399ff859ba6SAndrew Chew
400ff859ba6SAndrew Chew static struct platform_driver tegra_rtc_driver = {
4013e483e59SThierry Reding .probe = tegra_rtc_probe,
402*31c94505SUwe Kleine-König .remove_new = tegra_rtc_remove,
403ff859ba6SAndrew Chew .shutdown = tegra_rtc_shutdown,
404ff859ba6SAndrew Chew .driver = {
405ff859ba6SAndrew Chew .name = "tegra_rtc",
4062d79cf8aSJoseph Lo .of_match_table = tegra_rtc_dt_match,
4073443ad09SLaxman Dewangan .pm = &tegra_rtc_pm_ops,
408ff859ba6SAndrew Chew },
409ff859ba6SAndrew Chew };
4103e483e59SThierry Reding module_platform_driver(tegra_rtc_driver);
411ff859ba6SAndrew Chew
412ff859ba6SAndrew Chew MODULE_AUTHOR("Jon Mayo <jmayo@nvidia.com>");
413ff859ba6SAndrew Chew MODULE_DESCRIPTION("driver for Tegra internal RTC");
414ff859ba6SAndrew Chew MODULE_LICENSE("GPL");
415