xref: /OK3568_Linux_fs/kernel/drivers/rtc/rtc-ab8500.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (C) ST-Ericsson SA 2010
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Author: Virupax Sadashivpetimath <virupax.sadashivpetimath@stericsson.com>
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * RTC clock driver for the RTC part of the AB8500 Power management chip.
8*4882a593Smuzhiyun  * Based on RTC clock driver for the AB3100 Analog Baseband Chip by
9*4882a593Smuzhiyun  * Linus Walleij <linus.walleij@stericsson.com>
10*4882a593Smuzhiyun  */
11*4882a593Smuzhiyun 
12*4882a593Smuzhiyun #include <linux/module.h>
13*4882a593Smuzhiyun #include <linux/kernel.h>
14*4882a593Smuzhiyun #include <linux/init.h>
15*4882a593Smuzhiyun #include <linux/platform_device.h>
16*4882a593Smuzhiyun #include <linux/rtc.h>
17*4882a593Smuzhiyun #include <linux/mfd/abx500.h>
18*4882a593Smuzhiyun #include <linux/mfd/abx500/ab8500.h>
19*4882a593Smuzhiyun #include <linux/delay.h>
20*4882a593Smuzhiyun #include <linux/of.h>
21*4882a593Smuzhiyun #include <linux/pm_wakeirq.h>
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun #define AB8500_RTC_SOFF_STAT_REG	0x00
24*4882a593Smuzhiyun #define AB8500_RTC_CC_CONF_REG		0x01
25*4882a593Smuzhiyun #define AB8500_RTC_READ_REQ_REG		0x02
26*4882a593Smuzhiyun #define AB8500_RTC_WATCH_TSECMID_REG	0x03
27*4882a593Smuzhiyun #define AB8500_RTC_WATCH_TSECHI_REG	0x04
28*4882a593Smuzhiyun #define AB8500_RTC_WATCH_TMIN_LOW_REG	0x05
29*4882a593Smuzhiyun #define AB8500_RTC_WATCH_TMIN_MID_REG	0x06
30*4882a593Smuzhiyun #define AB8500_RTC_WATCH_TMIN_HI_REG	0x07
31*4882a593Smuzhiyun #define AB8500_RTC_ALRM_MIN_LOW_REG	0x08
32*4882a593Smuzhiyun #define AB8500_RTC_ALRM_MIN_MID_REG	0x09
33*4882a593Smuzhiyun #define AB8500_RTC_ALRM_MIN_HI_REG	0x0A
34*4882a593Smuzhiyun #define AB8500_RTC_STAT_REG		0x0B
35*4882a593Smuzhiyun #define AB8500_RTC_BKUP_CHG_REG		0x0C
36*4882a593Smuzhiyun #define AB8500_RTC_FORCE_BKUP_REG	0x0D
37*4882a593Smuzhiyun #define AB8500_RTC_CALIB_REG		0x0E
38*4882a593Smuzhiyun #define AB8500_RTC_SWITCH_STAT_REG	0x0F
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun /* RtcReadRequest bits */
41*4882a593Smuzhiyun #define RTC_READ_REQUEST		0x01
42*4882a593Smuzhiyun #define RTC_WRITE_REQUEST		0x02
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun /* RtcCtrl bits */
45*4882a593Smuzhiyun #define RTC_ALARM_ENA			0x04
46*4882a593Smuzhiyun #define RTC_STATUS_DATA			0x01
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun #define COUNTS_PER_SEC			(0xF000 / 60)
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun static const u8 ab8500_rtc_time_regs[] = {
51*4882a593Smuzhiyun 	AB8500_RTC_WATCH_TMIN_HI_REG, AB8500_RTC_WATCH_TMIN_MID_REG,
52*4882a593Smuzhiyun 	AB8500_RTC_WATCH_TMIN_LOW_REG, AB8500_RTC_WATCH_TSECHI_REG,
53*4882a593Smuzhiyun 	AB8500_RTC_WATCH_TSECMID_REG
54*4882a593Smuzhiyun };
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun static const u8 ab8500_rtc_alarm_regs[] = {
57*4882a593Smuzhiyun 	AB8500_RTC_ALRM_MIN_HI_REG, AB8500_RTC_ALRM_MIN_MID_REG,
58*4882a593Smuzhiyun 	AB8500_RTC_ALRM_MIN_LOW_REG
59*4882a593Smuzhiyun };
60*4882a593Smuzhiyun 
ab8500_rtc_read_time(struct device * dev,struct rtc_time * tm)61*4882a593Smuzhiyun static int ab8500_rtc_read_time(struct device *dev, struct rtc_time *tm)
62*4882a593Smuzhiyun {
63*4882a593Smuzhiyun 	unsigned long timeout = jiffies + HZ;
64*4882a593Smuzhiyun 	int retval, i;
65*4882a593Smuzhiyun 	unsigned long mins, secs;
66*4882a593Smuzhiyun 	unsigned char buf[ARRAY_SIZE(ab8500_rtc_time_regs)];
67*4882a593Smuzhiyun 	u8 value;
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun 	/* Request a data read */
70*4882a593Smuzhiyun 	retval = abx500_set_register_interruptible(dev,
71*4882a593Smuzhiyun 		AB8500_RTC, AB8500_RTC_READ_REQ_REG, RTC_READ_REQUEST);
72*4882a593Smuzhiyun 	if (retval < 0)
73*4882a593Smuzhiyun 		return retval;
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun 	/* Wait for some cycles after enabling the rtc read in ab8500 */
76*4882a593Smuzhiyun 	while (time_before(jiffies, timeout)) {
77*4882a593Smuzhiyun 		retval = abx500_get_register_interruptible(dev,
78*4882a593Smuzhiyun 			AB8500_RTC, AB8500_RTC_READ_REQ_REG, &value);
79*4882a593Smuzhiyun 		if (retval < 0)
80*4882a593Smuzhiyun 			return retval;
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun 		if (!(value & RTC_READ_REQUEST))
83*4882a593Smuzhiyun 			break;
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun 		usleep_range(1000, 5000);
86*4882a593Smuzhiyun 	}
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun 	/* Read the Watchtime registers */
89*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(ab8500_rtc_time_regs); i++) {
90*4882a593Smuzhiyun 		retval = abx500_get_register_interruptible(dev,
91*4882a593Smuzhiyun 			AB8500_RTC, ab8500_rtc_time_regs[i], &value);
92*4882a593Smuzhiyun 		if (retval < 0)
93*4882a593Smuzhiyun 			return retval;
94*4882a593Smuzhiyun 		buf[i] = value;
95*4882a593Smuzhiyun 	}
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun 	mins = (buf[0] << 16) | (buf[1] << 8) | buf[2];
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun 	secs =	(buf[3] << 8) | buf[4];
100*4882a593Smuzhiyun 	secs =	secs / COUNTS_PER_SEC;
101*4882a593Smuzhiyun 	secs =	secs + (mins * 60);
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun 	rtc_time64_to_tm(secs, tm);
104*4882a593Smuzhiyun 	return 0;
105*4882a593Smuzhiyun }
106*4882a593Smuzhiyun 
ab8500_rtc_set_time(struct device * dev,struct rtc_time * tm)107*4882a593Smuzhiyun static int ab8500_rtc_set_time(struct device *dev, struct rtc_time *tm)
108*4882a593Smuzhiyun {
109*4882a593Smuzhiyun 	int retval, i;
110*4882a593Smuzhiyun 	unsigned char buf[ARRAY_SIZE(ab8500_rtc_time_regs)];
111*4882a593Smuzhiyun 	unsigned long no_secs, no_mins, secs = 0;
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun 	secs = rtc_tm_to_time64(tm);
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun 	no_mins = secs / 60;
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun 	no_secs = secs % 60;
118*4882a593Smuzhiyun 	/* Make the seconds count as per the RTC resolution */
119*4882a593Smuzhiyun 	no_secs = no_secs * COUNTS_PER_SEC;
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun 	buf[4] = no_secs & 0xFF;
122*4882a593Smuzhiyun 	buf[3] = (no_secs >> 8) & 0xFF;
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun 	buf[2] = no_mins & 0xFF;
125*4882a593Smuzhiyun 	buf[1] = (no_mins >> 8) & 0xFF;
126*4882a593Smuzhiyun 	buf[0] = (no_mins >> 16) & 0xFF;
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(ab8500_rtc_time_regs); i++) {
129*4882a593Smuzhiyun 		retval = abx500_set_register_interruptible(dev, AB8500_RTC,
130*4882a593Smuzhiyun 			ab8500_rtc_time_regs[i], buf[i]);
131*4882a593Smuzhiyun 		if (retval < 0)
132*4882a593Smuzhiyun 			return retval;
133*4882a593Smuzhiyun 	}
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun 	/* Request a data write */
136*4882a593Smuzhiyun 	return abx500_set_register_interruptible(dev, AB8500_RTC,
137*4882a593Smuzhiyun 		AB8500_RTC_READ_REQ_REG, RTC_WRITE_REQUEST);
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun 
ab8500_rtc_read_alarm(struct device * dev,struct rtc_wkalrm * alarm)140*4882a593Smuzhiyun static int ab8500_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
141*4882a593Smuzhiyun {
142*4882a593Smuzhiyun 	int retval, i;
143*4882a593Smuzhiyun 	u8 rtc_ctrl, value;
144*4882a593Smuzhiyun 	unsigned char buf[ARRAY_SIZE(ab8500_rtc_alarm_regs)];
145*4882a593Smuzhiyun 	unsigned long secs, mins;
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun 	/* Check if the alarm is enabled or not */
148*4882a593Smuzhiyun 	retval = abx500_get_register_interruptible(dev, AB8500_RTC,
149*4882a593Smuzhiyun 		AB8500_RTC_STAT_REG, &rtc_ctrl);
150*4882a593Smuzhiyun 	if (retval < 0)
151*4882a593Smuzhiyun 		return retval;
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 	if (rtc_ctrl & RTC_ALARM_ENA)
154*4882a593Smuzhiyun 		alarm->enabled = 1;
155*4882a593Smuzhiyun 	else
156*4882a593Smuzhiyun 		alarm->enabled = 0;
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun 	alarm->pending = 0;
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(ab8500_rtc_alarm_regs); i++) {
161*4882a593Smuzhiyun 		retval = abx500_get_register_interruptible(dev, AB8500_RTC,
162*4882a593Smuzhiyun 			ab8500_rtc_alarm_regs[i], &value);
163*4882a593Smuzhiyun 		if (retval < 0)
164*4882a593Smuzhiyun 			return retval;
165*4882a593Smuzhiyun 		buf[i] = value;
166*4882a593Smuzhiyun 	}
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun 	mins = (buf[0] << 16) | (buf[1] << 8) | (buf[2]);
169*4882a593Smuzhiyun 	secs = mins * 60;
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun 	rtc_time64_to_tm(secs, &alarm->time);
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun 	return 0;
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun 
ab8500_rtc_irq_enable(struct device * dev,unsigned int enabled)176*4882a593Smuzhiyun static int ab8500_rtc_irq_enable(struct device *dev, unsigned int enabled)
177*4882a593Smuzhiyun {
178*4882a593Smuzhiyun 	return abx500_mask_and_set_register_interruptible(dev, AB8500_RTC,
179*4882a593Smuzhiyun 		AB8500_RTC_STAT_REG, RTC_ALARM_ENA,
180*4882a593Smuzhiyun 		enabled ? RTC_ALARM_ENA : 0);
181*4882a593Smuzhiyun }
182*4882a593Smuzhiyun 
ab8500_rtc_set_alarm(struct device * dev,struct rtc_wkalrm * alarm)183*4882a593Smuzhiyun static int ab8500_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
184*4882a593Smuzhiyun {
185*4882a593Smuzhiyun 	int retval, i;
186*4882a593Smuzhiyun 	unsigned char buf[ARRAY_SIZE(ab8500_rtc_alarm_regs)];
187*4882a593Smuzhiyun 	unsigned long mins, secs = 0, cursec = 0;
188*4882a593Smuzhiyun 	struct rtc_time curtm;
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun 	/* Get the number of seconds since 1970 */
191*4882a593Smuzhiyun 	secs = rtc_tm_to_time64(&alarm->time);
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun 	/*
194*4882a593Smuzhiyun 	 * Check whether alarm is set less than 1min.
195*4882a593Smuzhiyun 	 * Since our RTC doesn't support alarm resolution less than 1min,
196*4882a593Smuzhiyun 	 * return -EINVAL, so UIE EMUL can take it up, incase of UIE_ON
197*4882a593Smuzhiyun 	 */
198*4882a593Smuzhiyun 	ab8500_rtc_read_time(dev, &curtm); /* Read current time */
199*4882a593Smuzhiyun 	cursec = rtc_tm_to_time64(&curtm);
200*4882a593Smuzhiyun 	if ((secs - cursec) < 59) {
201*4882a593Smuzhiyun 		dev_dbg(dev, "Alarm less than 1 minute not supported\r\n");
202*4882a593Smuzhiyun 		return -EINVAL;
203*4882a593Smuzhiyun 	}
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun 	mins = secs / 60;
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun 	buf[2] = mins & 0xFF;
208*4882a593Smuzhiyun 	buf[1] = (mins >> 8) & 0xFF;
209*4882a593Smuzhiyun 	buf[0] = (mins >> 16) & 0xFF;
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun 	/* Set the alarm time */
212*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(ab8500_rtc_alarm_regs); i++) {
213*4882a593Smuzhiyun 		retval = abx500_set_register_interruptible(dev, AB8500_RTC,
214*4882a593Smuzhiyun 			ab8500_rtc_alarm_regs[i], buf[i]);
215*4882a593Smuzhiyun 		if (retval < 0)
216*4882a593Smuzhiyun 			return retval;
217*4882a593Smuzhiyun 	}
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun 	return ab8500_rtc_irq_enable(dev, alarm->enabled);
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun 
ab8500_rtc_set_calibration(struct device * dev,int calibration)222*4882a593Smuzhiyun static int ab8500_rtc_set_calibration(struct device *dev, int calibration)
223*4882a593Smuzhiyun {
224*4882a593Smuzhiyun 	int retval;
225*4882a593Smuzhiyun 	u8  rtccal = 0;
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun 	/*
228*4882a593Smuzhiyun 	 * Check that the calibration value (which is in units of 0.5
229*4882a593Smuzhiyun 	 * parts-per-million) is in the AB8500's range for RtcCalibration
230*4882a593Smuzhiyun 	 * register. -128 (0x80) is not permitted because the AB8500 uses
231*4882a593Smuzhiyun 	 * a sign-bit rather than two's complement, so 0x80 is just another
232*4882a593Smuzhiyun 	 * representation of zero.
233*4882a593Smuzhiyun 	 */
234*4882a593Smuzhiyun 	if ((calibration < -127) || (calibration > 127)) {
235*4882a593Smuzhiyun 		dev_err(dev, "RtcCalibration value outside permitted range\n");
236*4882a593Smuzhiyun 		return -EINVAL;
237*4882a593Smuzhiyun 	}
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun 	/*
240*4882a593Smuzhiyun 	 * The AB8500 uses sign (in bit7) and magnitude (in bits0-7)
241*4882a593Smuzhiyun 	 * so need to convert to this sort of representation before writing
242*4882a593Smuzhiyun 	 * into RtcCalibration register...
243*4882a593Smuzhiyun 	 */
244*4882a593Smuzhiyun 	if (calibration >= 0)
245*4882a593Smuzhiyun 		rtccal = 0x7F & calibration;
246*4882a593Smuzhiyun 	else
247*4882a593Smuzhiyun 		rtccal = ~(calibration - 1) | 0x80;
248*4882a593Smuzhiyun 
249*4882a593Smuzhiyun 	retval = abx500_set_register_interruptible(dev, AB8500_RTC,
250*4882a593Smuzhiyun 			AB8500_RTC_CALIB_REG, rtccal);
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun 	return retval;
253*4882a593Smuzhiyun }
254*4882a593Smuzhiyun 
ab8500_rtc_get_calibration(struct device * dev,int * calibration)255*4882a593Smuzhiyun static int ab8500_rtc_get_calibration(struct device *dev, int *calibration)
256*4882a593Smuzhiyun {
257*4882a593Smuzhiyun 	int retval;
258*4882a593Smuzhiyun 	u8  rtccal = 0;
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun 	retval =  abx500_get_register_interruptible(dev, AB8500_RTC,
261*4882a593Smuzhiyun 			AB8500_RTC_CALIB_REG, &rtccal);
262*4882a593Smuzhiyun 	if (retval >= 0) {
263*4882a593Smuzhiyun 		/*
264*4882a593Smuzhiyun 		 * The AB8500 uses sign (in bit7) and magnitude (in bits0-7)
265*4882a593Smuzhiyun 		 * so need to convert value from RtcCalibration register into
266*4882a593Smuzhiyun 		 * a two's complement signed value...
267*4882a593Smuzhiyun 		 */
268*4882a593Smuzhiyun 		if (rtccal & 0x80)
269*4882a593Smuzhiyun 			*calibration = 0 - (rtccal & 0x7F);
270*4882a593Smuzhiyun 		else
271*4882a593Smuzhiyun 			*calibration = 0x7F & rtccal;
272*4882a593Smuzhiyun 	}
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun 	return retval;
275*4882a593Smuzhiyun }
276*4882a593Smuzhiyun 
ab8500_sysfs_store_rtc_calibration(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)277*4882a593Smuzhiyun static ssize_t ab8500_sysfs_store_rtc_calibration(struct device *dev,
278*4882a593Smuzhiyun 				struct device_attribute *attr,
279*4882a593Smuzhiyun 				const char *buf, size_t count)
280*4882a593Smuzhiyun {
281*4882a593Smuzhiyun 	int retval;
282*4882a593Smuzhiyun 	int calibration = 0;
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun 	if (sscanf(buf, " %i ", &calibration) != 1) {
285*4882a593Smuzhiyun 		dev_err(dev, "Failed to store RTC calibration attribute\n");
286*4882a593Smuzhiyun 		return -EINVAL;
287*4882a593Smuzhiyun 	}
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun 	retval = ab8500_rtc_set_calibration(dev, calibration);
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun 	return retval ? retval : count;
292*4882a593Smuzhiyun }
293*4882a593Smuzhiyun 
ab8500_sysfs_show_rtc_calibration(struct device * dev,struct device_attribute * attr,char * buf)294*4882a593Smuzhiyun static ssize_t ab8500_sysfs_show_rtc_calibration(struct device *dev,
295*4882a593Smuzhiyun 				struct device_attribute *attr, char *buf)
296*4882a593Smuzhiyun {
297*4882a593Smuzhiyun 	int  retval = 0;
298*4882a593Smuzhiyun 	int  calibration = 0;
299*4882a593Smuzhiyun 
300*4882a593Smuzhiyun 	retval = ab8500_rtc_get_calibration(dev, &calibration);
301*4882a593Smuzhiyun 	if (retval < 0) {
302*4882a593Smuzhiyun 		dev_err(dev, "Failed to read RTC calibration attribute\n");
303*4882a593Smuzhiyun 		sprintf(buf, "0\n");
304*4882a593Smuzhiyun 		return retval;
305*4882a593Smuzhiyun 	}
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun 	return sprintf(buf, "%d\n", calibration);
308*4882a593Smuzhiyun }
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun static DEVICE_ATTR(rtc_calibration, S_IRUGO | S_IWUSR,
311*4882a593Smuzhiyun 		   ab8500_sysfs_show_rtc_calibration,
312*4882a593Smuzhiyun 		   ab8500_sysfs_store_rtc_calibration);
313*4882a593Smuzhiyun 
314*4882a593Smuzhiyun static struct attribute *ab8500_rtc_attrs[] = {
315*4882a593Smuzhiyun 	&dev_attr_rtc_calibration.attr,
316*4882a593Smuzhiyun 	NULL
317*4882a593Smuzhiyun };
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun static const struct attribute_group ab8500_rtc_sysfs_files = {
320*4882a593Smuzhiyun 	.attrs	= ab8500_rtc_attrs,
321*4882a593Smuzhiyun };
322*4882a593Smuzhiyun 
rtc_alarm_handler(int irq,void * data)323*4882a593Smuzhiyun static irqreturn_t rtc_alarm_handler(int irq, void *data)
324*4882a593Smuzhiyun {
325*4882a593Smuzhiyun 	struct rtc_device *rtc = data;
326*4882a593Smuzhiyun 	unsigned long events = RTC_IRQF | RTC_AF;
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun 	dev_dbg(&rtc->dev, "%s\n", __func__);
329*4882a593Smuzhiyun 	rtc_update_irq(rtc, 1, events);
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun 	return IRQ_HANDLED;
332*4882a593Smuzhiyun }
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun static const struct rtc_class_ops ab8500_rtc_ops = {
335*4882a593Smuzhiyun 	.read_time		= ab8500_rtc_read_time,
336*4882a593Smuzhiyun 	.set_time		= ab8500_rtc_set_time,
337*4882a593Smuzhiyun 	.read_alarm		= ab8500_rtc_read_alarm,
338*4882a593Smuzhiyun 	.set_alarm		= ab8500_rtc_set_alarm,
339*4882a593Smuzhiyun 	.alarm_irq_enable	= ab8500_rtc_irq_enable,
340*4882a593Smuzhiyun };
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun static const struct platform_device_id ab85xx_rtc_ids[] = {
343*4882a593Smuzhiyun 	{ "ab8500-rtc", (kernel_ulong_t)&ab8500_rtc_ops, },
344*4882a593Smuzhiyun 	{ /* sentinel */ }
345*4882a593Smuzhiyun };
346*4882a593Smuzhiyun MODULE_DEVICE_TABLE(platform, ab85xx_rtc_ids);
347*4882a593Smuzhiyun 
ab8500_rtc_probe(struct platform_device * pdev)348*4882a593Smuzhiyun static int ab8500_rtc_probe(struct platform_device *pdev)
349*4882a593Smuzhiyun {
350*4882a593Smuzhiyun 	const struct platform_device_id *platid = platform_get_device_id(pdev);
351*4882a593Smuzhiyun 	int err;
352*4882a593Smuzhiyun 	struct rtc_device *rtc;
353*4882a593Smuzhiyun 	u8 rtc_ctrl;
354*4882a593Smuzhiyun 	int irq;
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun 	irq = platform_get_irq_byname(pdev, "ALARM");
357*4882a593Smuzhiyun 	if (irq < 0)
358*4882a593Smuzhiyun 		return irq;
359*4882a593Smuzhiyun 
360*4882a593Smuzhiyun 	/* For RTC supply test */
361*4882a593Smuzhiyun 	err = abx500_mask_and_set_register_interruptible(&pdev->dev, AB8500_RTC,
362*4882a593Smuzhiyun 		AB8500_RTC_STAT_REG, RTC_STATUS_DATA, RTC_STATUS_DATA);
363*4882a593Smuzhiyun 	if (err < 0)
364*4882a593Smuzhiyun 		return err;
365*4882a593Smuzhiyun 
366*4882a593Smuzhiyun 	/* Wait for reset by the PorRtc */
367*4882a593Smuzhiyun 	usleep_range(1000, 5000);
368*4882a593Smuzhiyun 
369*4882a593Smuzhiyun 	err = abx500_get_register_interruptible(&pdev->dev, AB8500_RTC,
370*4882a593Smuzhiyun 		AB8500_RTC_STAT_REG, &rtc_ctrl);
371*4882a593Smuzhiyun 	if (err < 0)
372*4882a593Smuzhiyun 		return err;
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun 	/* Check if the RTC Supply fails */
375*4882a593Smuzhiyun 	if (!(rtc_ctrl & RTC_STATUS_DATA)) {
376*4882a593Smuzhiyun 		dev_err(&pdev->dev, "RTC supply failure\n");
377*4882a593Smuzhiyun 		return -ENODEV;
378*4882a593Smuzhiyun 	}
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun 	device_init_wakeup(&pdev->dev, true);
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun 	rtc = devm_rtc_allocate_device(&pdev->dev);
383*4882a593Smuzhiyun 	if (IS_ERR(rtc))
384*4882a593Smuzhiyun 		return PTR_ERR(rtc);
385*4882a593Smuzhiyun 
386*4882a593Smuzhiyun 	rtc->ops = (struct rtc_class_ops *)platid->driver_data;
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun 	err = devm_request_threaded_irq(&pdev->dev, irq, NULL,
389*4882a593Smuzhiyun 			rtc_alarm_handler, IRQF_ONESHOT,
390*4882a593Smuzhiyun 			"ab8500-rtc", rtc);
391*4882a593Smuzhiyun 	if (err < 0)
392*4882a593Smuzhiyun 		return err;
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun 	dev_pm_set_wake_irq(&pdev->dev, irq);
395*4882a593Smuzhiyun 	platform_set_drvdata(pdev, rtc);
396*4882a593Smuzhiyun 
397*4882a593Smuzhiyun 	rtc->uie_unsupported = 1;
398*4882a593Smuzhiyun 
399*4882a593Smuzhiyun 	rtc->range_max = (1ULL << 24) * 60 - 1; // 24-bit minutes + 59 secs
400*4882a593Smuzhiyun 	rtc->start_secs = RTC_TIMESTAMP_BEGIN_2000;
401*4882a593Smuzhiyun 	rtc->set_start_time = true;
402*4882a593Smuzhiyun 
403*4882a593Smuzhiyun 	err = rtc_add_group(rtc, &ab8500_rtc_sysfs_files);
404*4882a593Smuzhiyun 	if (err)
405*4882a593Smuzhiyun 		return err;
406*4882a593Smuzhiyun 
407*4882a593Smuzhiyun 	return rtc_register_device(rtc);
408*4882a593Smuzhiyun }
409*4882a593Smuzhiyun 
ab8500_rtc_remove(struct platform_device * pdev)410*4882a593Smuzhiyun static int ab8500_rtc_remove(struct platform_device *pdev)
411*4882a593Smuzhiyun {
412*4882a593Smuzhiyun 	dev_pm_clear_wake_irq(&pdev->dev);
413*4882a593Smuzhiyun 	device_init_wakeup(&pdev->dev, false);
414*4882a593Smuzhiyun 
415*4882a593Smuzhiyun 	return 0;
416*4882a593Smuzhiyun }
417*4882a593Smuzhiyun 
418*4882a593Smuzhiyun static struct platform_driver ab8500_rtc_driver = {
419*4882a593Smuzhiyun 	.driver = {
420*4882a593Smuzhiyun 		.name = "ab8500-rtc",
421*4882a593Smuzhiyun 	},
422*4882a593Smuzhiyun 	.probe	= ab8500_rtc_probe,
423*4882a593Smuzhiyun 	.remove = ab8500_rtc_remove,
424*4882a593Smuzhiyun 	.id_table = ab85xx_rtc_ids,
425*4882a593Smuzhiyun };
426*4882a593Smuzhiyun 
427*4882a593Smuzhiyun module_platform_driver(ab8500_rtc_driver);
428*4882a593Smuzhiyun 
429*4882a593Smuzhiyun MODULE_AUTHOR("Virupax Sadashivpetimath <virupax.sadashivpetimath@stericsson.com>");
430*4882a593Smuzhiyun MODULE_DESCRIPTION("AB8500 RTC Driver");
431*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
432