1b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan/*
2b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan * rtc-as3722.c - Real Time Clock driver for ams AS3722 PMICs
3b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan *
4b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan * Copyright (C) 2013 ams AG
5b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan * Copyright (c) 2013, NVIDIA Corporation. All rights reserved.
6b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan *
7b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan * Author: Florian Lobmaier <florian.lobmaier@ams.com>
8b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan * Author: Laxman Dewangan <ldewangan@nvidia.com>
9b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan *
10b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan * This program is free software; you can redistribute it and/or modify
11b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan * it under the terms of the GNU General Public License as published by
12b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan * the Free Software Foundation; either version 2 of the License, or
13b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan * (at your option) any later version.
14b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan *
15b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan * This program is distributed in the hope that it will be useful,
16b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan * but WITHOUT ANY WARRANTY; without even the implied warranty of
17b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan * GNU General Public License for more details.
19b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan */
20b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan
21b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan#include <linux/bcd.h>
22b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan#include <linux/completion.h>
23b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan#include <linux/delay.h>
24b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan#include <linux/interrupt.h>
25b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan#include <linux/ioctl.h>
26b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan#include <linux/kernel.h>
27b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan#include <linux/module.h>
28b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan#include <linux/mfd/as3722.h>
29b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan#include <linux/platform_device.h>
30b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan#include <linux/rtc.h>
31b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan#include <linux/time.h>
32b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan
33b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan#define AS3722_RTC_START_YEAR	  2000
34b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewanganstruct as3722_rtc {
35b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	struct rtc_device	*rtc;
36b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	struct device		*dev;
37b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	struct as3722		*as3722;
38b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	int			alarm_irq;
39b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	bool			irq_enable;
40b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan};
41b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan
42b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewanganstatic void as3722_time_to_reg(u8 *rbuff, struct rtc_time *tm)
43b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan{
44b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	rbuff[0] = bin2bcd(tm->tm_sec);
45b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	rbuff[1] = bin2bcd(tm->tm_min);
46b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	rbuff[2] = bin2bcd(tm->tm_hour);
47b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	rbuff[3] = bin2bcd(tm->tm_mday);
48b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	rbuff[4] = bin2bcd(tm->tm_mon);
49b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	rbuff[5] = bin2bcd(tm->tm_year - (AS3722_RTC_START_YEAR - 1900));
50b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan}
51b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan
52b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewanganstatic void as3722_reg_to_time(u8 *rbuff, struct rtc_time *tm)
53b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan{
54b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	tm->tm_sec = bcd2bin(rbuff[0] & 0x7F);
55b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	tm->tm_min = bcd2bin(rbuff[1] & 0x7F);
56b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	tm->tm_hour = bcd2bin(rbuff[2] & 0x3F);
57b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	tm->tm_mday = bcd2bin(rbuff[3] & 0x3F);
58b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	tm->tm_mon = bcd2bin(rbuff[4] & 0x1F);
59b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	tm->tm_year = (AS3722_RTC_START_YEAR - 1900) + bcd2bin(rbuff[5] & 0x7F);
60b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	return;
61b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan}
62b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan
63b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewanganstatic int as3722_rtc_read_time(struct device *dev, struct rtc_time *tm)
64b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan{
65b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	struct as3722_rtc *as3722_rtc = dev_get_drvdata(dev);
66b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	struct as3722 *as3722 = as3722_rtc->as3722;
67b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	u8 as_time_array[6];
68b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	int ret;
69b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan
70b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	ret = as3722_block_read(as3722, AS3722_RTC_SECOND_REG,
71b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan			6, as_time_array);
72b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	if (ret < 0) {
73b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan		dev_err(dev, "RTC_SECOND reg block read failed %d\n", ret);
74b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan		return ret;
75b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	}
76b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	as3722_reg_to_time(as_time_array, tm);
77b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	return 0;
78b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan}
79b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan
80b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewanganstatic int as3722_rtc_set_time(struct device *dev, struct rtc_time *tm)
81b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan{
82b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	struct as3722_rtc *as3722_rtc = dev_get_drvdata(dev);
83b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	struct as3722 *as3722 = as3722_rtc->as3722;
84b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	u8 as_time_array[6];
85b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	int ret;
86b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan
87b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	if (tm->tm_year < (AS3722_RTC_START_YEAR - 1900))
88b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan		return -EINVAL;
89b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan
90b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	as3722_time_to_reg(as_time_array, tm);
91b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	ret = as3722_block_write(as3722, AS3722_RTC_SECOND_REG, 6,
92b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan			as_time_array);
93b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	if (ret < 0)
94b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan		dev_err(dev, "RTC_SECOND reg block write failed %d\n", ret);
95b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	return ret;
96b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan}
97b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan
98b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewanganstatic int as3722_rtc_alarm_irq_enable(struct device *dev,
99b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan		unsigned int enabled)
100b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan{
101b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	struct as3722_rtc *as3722_rtc = dev_get_drvdata(dev);
102b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan
103b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	if (enabled && !as3722_rtc->irq_enable) {
104b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan		enable_irq(as3722_rtc->alarm_irq);
105b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan		as3722_rtc->irq_enable = true;
106b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	} else if (!enabled && as3722_rtc->irq_enable)  {
107b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan		disable_irq(as3722_rtc->alarm_irq);
108b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan		as3722_rtc->irq_enable = false;
109b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	}
110b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	return 0;
111b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan}
112b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan
113b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewanganstatic int as3722_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
114b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan{
115b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	struct as3722_rtc *as3722_rtc = dev_get_drvdata(dev);
116b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	struct as3722 *as3722 = as3722_rtc->as3722;
117b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	u8 as_time_array[6];
118b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	int ret;
119b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan
120b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	ret = as3722_block_read(as3722, AS3722_RTC_ALARM_SECOND_REG, 6,
121b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan			as_time_array);
122b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	if (ret < 0) {
123b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan		dev_err(dev, "RTC_ALARM_SECOND block read failed %d\n", ret);
124b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan		return ret;
125b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	}
126b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan
127b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	as3722_reg_to_time(as_time_array, &alrm->time);
128b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	return 0;
129b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan}
130b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan
131b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewanganstatic int as3722_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
132b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan{
133b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	struct as3722_rtc *as3722_rtc = dev_get_drvdata(dev);
134b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	struct as3722 *as3722 = as3722_rtc->as3722;
135b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	u8 as_time_array[6];
136b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	int ret;
137b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan
138b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	if (alrm->time.tm_year < (AS3722_RTC_START_YEAR - 1900))
139b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan		return -EINVAL;
140b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan
141b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	ret = as3722_rtc_alarm_irq_enable(dev, 0);
142b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	if (ret < 0) {
143b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan		dev_err(dev, "Disable RTC alarm failed\n");
144b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan		return ret;
145b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	}
146b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan
147b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	as3722_time_to_reg(as_time_array, &alrm->time);
148b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	ret = as3722_block_write(as3722, AS3722_RTC_ALARM_SECOND_REG, 6,
149b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan			as_time_array);
150b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	if (ret < 0) {
151b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan		dev_err(dev, "RTC_ALARM_SECOND block write failed %d\n", ret);
152b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan		return ret;
153b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	}
154b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan
155b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	if (alrm->enabled)
156b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan		ret = as3722_rtc_alarm_irq_enable(dev, alrm->enabled);
157b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	return ret;
158b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan}
159b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan
160b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewanganstatic irqreturn_t as3722_alarm_irq(int irq, void *data)
161b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan{
162b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	struct as3722_rtc *as3722_rtc = data;
163b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan
164b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	rtc_update_irq(as3722_rtc->rtc, 1, RTC_IRQF | RTC_AF);
165b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	return IRQ_HANDLED;
166b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan}
167b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan
168b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewanganstatic const struct rtc_class_ops as3722_rtc_ops = {
169b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	.read_time = as3722_rtc_read_time,
170b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	.set_time = as3722_rtc_set_time,
171b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	.read_alarm = as3722_rtc_read_alarm,
172b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	.set_alarm = as3722_rtc_set_alarm,
173b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	.alarm_irq_enable = as3722_rtc_alarm_irq_enable,
174b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan};
175b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan
176b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewanganstatic int as3722_rtc_probe(struct platform_device *pdev)
177b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan{
178b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	struct as3722 *as3722 = dev_get_drvdata(pdev->dev.parent);
179b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	struct as3722_rtc *as3722_rtc;
180b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	int ret;
181b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan
182b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	as3722_rtc = devm_kzalloc(&pdev->dev, sizeof(*as3722_rtc), GFP_KERNEL);
183b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	if (!as3722_rtc)
184b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan		return -ENOMEM;
185b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan
186b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	as3722_rtc->as3722 = as3722;
187b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	as3722_rtc->dev = &pdev->dev;
188b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	platform_set_drvdata(pdev, as3722_rtc);
189b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan
190b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	/* Enable the RTC to make sure it is running. */
191b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	ret = as3722_update_bits(as3722, AS3722_RTC_CONTROL_REG,
192b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan			AS3722_RTC_ON | AS3722_RTC_ALARM_WAKEUP_EN,
193b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan			AS3722_RTC_ON | AS3722_RTC_ALARM_WAKEUP_EN);
194b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	if (ret < 0) {
195b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan		dev_err(&pdev->dev, "RTC_CONTROL reg write failed: %d\n", ret);
196b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan		return ret;
197b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	}
198b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan
199b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	device_init_wakeup(&pdev->dev, 1);
200b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan
20175465c49f092f24acc236b0f51e9b8bf8adc329eLaxman Dewangan	as3722_rtc->rtc = devm_rtc_device_register(&pdev->dev, "as3722-rtc",
202b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan				&as3722_rtc_ops, THIS_MODULE);
203b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	if (IS_ERR(as3722_rtc->rtc)) {
204b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan		ret = PTR_ERR(as3722_rtc->rtc);
205b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan		dev_err(&pdev->dev, "RTC register failed: %d\n", ret);
206b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan		return ret;
207b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	}
208b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan
209b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	as3722_rtc->alarm_irq = platform_get_irq(pdev, 0);
210b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	dev_info(&pdev->dev, "RTC interrupt %d\n", as3722_rtc->alarm_irq);
211b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan
21275465c49f092f24acc236b0f51e9b8bf8adc329eLaxman Dewangan	ret = devm_request_threaded_irq(&pdev->dev, as3722_rtc->alarm_irq, NULL,
213b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan			as3722_alarm_irq, IRQF_ONESHOT | IRQF_EARLY_RESUME,
214b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan			"rtc-alarm", as3722_rtc);
215b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	if (ret < 0) {
216b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan		dev_err(&pdev->dev, "Failed to request alarm IRQ %d: %d\n",
217b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan				as3722_rtc->alarm_irq, ret);
21875465c49f092f24acc236b0f51e9b8bf8adc329eLaxman Dewangan		return ret;
219b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	}
220b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	disable_irq(as3722_rtc->alarm_irq);
221b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	return 0;
222b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan}
223b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan
224b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan#ifdef CONFIG_PM_SLEEP
225b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewanganstatic int as3722_rtc_suspend(struct device *dev)
226b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan{
227b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	struct as3722_rtc *as3722_rtc = dev_get_drvdata(dev);
228b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan
229b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	if (device_may_wakeup(dev))
230b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan		enable_irq_wake(as3722_rtc->alarm_irq);
231b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan
232b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	return 0;
233b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan}
234b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan
235b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewanganstatic int as3722_rtc_resume(struct device *dev)
236b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan{
237b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	struct as3722_rtc *as3722_rtc = dev_get_drvdata(dev);
238b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan
239b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	if (device_may_wakeup(dev))
240b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan		disable_irq_wake(as3722_rtc->alarm_irq);
241b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	return 0;
242b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan}
243b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan#endif
244b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan
245d55255cb11ca2220d09c2a08adee7ca3e14e0ba1Jingoo Hanstatic SIMPLE_DEV_PM_OPS(as3722_rtc_pm_ops, as3722_rtc_suspend,
246d55255cb11ca2220d09c2a08adee7ca3e14e0ba1Jingoo Han			 as3722_rtc_resume);
247b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan
248b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewanganstatic struct platform_driver as3722_rtc_driver = {
249b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	.probe = as3722_rtc_probe,
250b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	.driver = {
251b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan		.name = "as3722-rtc",
252b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan		.pm = &as3722_rtc_pm_ops,
253b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan	},
254b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan};
255b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewanganmodule_platform_driver(as3722_rtc_driver);
256b45062619840a56c090bab57df7b0fb36a30c2afLaxman Dewangan
257b45062619840a56c090bab57df7b0fb36a30c2afLaxman DewanganMODULE_DESCRIPTION("RTC driver for AS3722 PMICs");
258b45062619840a56c090bab57df7b0fb36a30c2afLaxman DewanganMODULE_ALIAS("platform:as3722-rtc");
259b45062619840a56c090bab57df7b0fb36a30c2afLaxman DewanganMODULE_AUTHOR("Florian Lobmaier <florian.lobmaier@ams.com>");
260b45062619840a56c090bab57df7b0fb36a30c2afLaxman DewanganMODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
261b45062619840a56c090bab57df7b0fb36a30c2afLaxman DewanganMODULE_LICENSE("GPL");
262