xref: /openbmc/linux/drivers/rtc/rtc-ds3232.c (revision 2612e3bbc0386368a850140a6c9b990cd496a5ec)
12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2c03675f0SRoy Zang /*
3080481f5SAkinobu Mita  * RTC client/driver for the Maxim/Dallas DS3232/DS3234 Real-Time Clock
4c03675f0SRoy Zang  *
5a2d6d2faSLei Xu  * Copyright (C) 2009-2011 Freescale Semiconductor.
6f46418c5SLan Chunhe-B25806  * Author: Jack Lan <jack.lan@freescale.com>
7080481f5SAkinobu Mita  * Copyright (C) 2008 MIMOMax Wireless Ltd.
8c03675f0SRoy Zang  */
9c03675f0SRoy Zang 
10a737e835SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
11a737e835SJoe Perches 
12c03675f0SRoy Zang #include <linux/kernel.h>
13c03675f0SRoy Zang #include <linux/module.h>
14c03675f0SRoy Zang #include <linux/interrupt.h>
15c03675f0SRoy Zang #include <linux/i2c.h>
16080481f5SAkinobu Mita #include <linux/spi/spi.h>
17c03675f0SRoy Zang #include <linux/rtc.h>
18c03675f0SRoy Zang #include <linux/bcd.h>
19c03675f0SRoy Zang #include <linux/slab.h>
20370927c4SAkinobu Mita #include <linux/regmap.h>
21c35c4195SKirill Esipov #include <linux/hwmon.h>
22c03675f0SRoy Zang 
23c03675f0SRoy Zang #define DS3232_REG_SECONDS      0x00
24c03675f0SRoy Zang #define DS3232_REG_MINUTES      0x01
25c03675f0SRoy Zang #define DS3232_REG_HOURS        0x02
26c03675f0SRoy Zang #define DS3232_REG_AMPM         0x02
27c03675f0SRoy Zang #define DS3232_REG_DAY          0x03
28c03675f0SRoy Zang #define DS3232_REG_DATE         0x04
29c03675f0SRoy Zang #define DS3232_REG_MONTH        0x05
30c03675f0SRoy Zang #define DS3232_REG_CENTURY      0x05
31c03675f0SRoy Zang #define DS3232_REG_YEAR         0x06
32c03675f0SRoy Zang #define DS3232_REG_ALARM1       0x07       /* Alarm 1 BASE */
33c03675f0SRoy Zang #define DS3232_REG_ALARM2       0x0B       /* Alarm 2 BASE */
34c03675f0SRoy Zang #define DS3232_REG_CR           0x0E       /* Control register */
35c03675f0SRoy Zang #       define DS3232_REG_CR_nEOSC   0x80
36c03675f0SRoy Zang #       define DS3232_REG_CR_INTCN   0x04
37c03675f0SRoy Zang #       define DS3232_REG_CR_A2IE    0x02
38c03675f0SRoy Zang #       define DS3232_REG_CR_A1IE    0x01
39c03675f0SRoy Zang 
40c03675f0SRoy Zang #define DS3232_REG_SR           0x0F       /* control/status register */
41c03675f0SRoy Zang #       define DS3232_REG_SR_OSF     0x80
42c03675f0SRoy Zang #       define DS3232_REG_SR_BSY     0x04
43c03675f0SRoy Zang #       define DS3232_REG_SR_A2F     0x02
44c03675f0SRoy Zang #       define DS3232_REG_SR_A1F     0x01
45c03675f0SRoy Zang 
46c35c4195SKirill Esipov #define DS3232_REG_TEMPERATURE	0x11
479eec31f3SHan Nandor #define DS3232_REG_SRAM_START   0x14
489eec31f3SHan Nandor #define DS3232_REG_SRAM_END     0xFF
499eec31f3SHan Nandor 
509eec31f3SHan Nandor #define DS3232_REG_SRAM_SIZE    236
51c35c4195SKirill Esipov 
52c03675f0SRoy Zang struct ds3232 {
53370927c4SAkinobu Mita 	struct device *dev;
54370927c4SAkinobu Mita 	struct regmap *regmap;
55370927c4SAkinobu Mita 	int irq;
56c03675f0SRoy Zang 	struct rtc_device *rtc;
57c03675f0SRoy Zang 
58c93a3ae2SWang Dongsheng 	bool suspended;
59c03675f0SRoy Zang };
60c03675f0SRoy Zang 
ds3232_check_rtc_status(struct device * dev)61370927c4SAkinobu Mita static int ds3232_check_rtc_status(struct device *dev)
62c03675f0SRoy Zang {
63370927c4SAkinobu Mita 	struct ds3232 *ds3232 = dev_get_drvdata(dev);
64c03675f0SRoy Zang 	int ret = 0;
65c03675f0SRoy Zang 	int control, stat;
66c03675f0SRoy Zang 
67370927c4SAkinobu Mita 	ret = regmap_read(ds3232->regmap, DS3232_REG_SR, &stat);
68370927c4SAkinobu Mita 	if (ret)
69370927c4SAkinobu Mita 		return ret;
70c03675f0SRoy Zang 
71c03675f0SRoy Zang 	if (stat & DS3232_REG_SR_OSF)
72370927c4SAkinobu Mita 		dev_warn(dev,
73c03675f0SRoy Zang 				"oscillator discontinuity flagged, "
74c03675f0SRoy Zang 				"time unreliable\n");
75c03675f0SRoy Zang 
76c03675f0SRoy Zang 	stat &= ~(DS3232_REG_SR_OSF | DS3232_REG_SR_A1F | DS3232_REG_SR_A2F);
77c03675f0SRoy Zang 
78370927c4SAkinobu Mita 	ret = regmap_write(ds3232->regmap, DS3232_REG_SR, stat);
79370927c4SAkinobu Mita 	if (ret)
80c03675f0SRoy Zang 		return ret;
81c03675f0SRoy Zang 
82c03675f0SRoy Zang 	/* If the alarm is pending, clear it before requesting
83c03675f0SRoy Zang 	 * the interrupt, so an interrupt event isn't reported
84c03675f0SRoy Zang 	 * before everything is initialized.
85c03675f0SRoy Zang 	 */
86c03675f0SRoy Zang 
87370927c4SAkinobu Mita 	ret = regmap_read(ds3232->regmap, DS3232_REG_CR, &control);
88370927c4SAkinobu Mita 	if (ret)
89370927c4SAkinobu Mita 		return ret;
90c03675f0SRoy Zang 
91c03675f0SRoy Zang 	control &= ~(DS3232_REG_CR_A1IE | DS3232_REG_CR_A2IE);
92c03675f0SRoy Zang 	control |= DS3232_REG_CR_INTCN;
93c03675f0SRoy Zang 
94370927c4SAkinobu Mita 	return regmap_write(ds3232->regmap, DS3232_REG_CR, control);
95c03675f0SRoy Zang }
96c03675f0SRoy Zang 
ds3232_read_time(struct device * dev,struct rtc_time * time)97c03675f0SRoy Zang static int ds3232_read_time(struct device *dev, struct rtc_time *time)
98c03675f0SRoy Zang {
99370927c4SAkinobu Mita 	struct ds3232 *ds3232 = dev_get_drvdata(dev);
100c03675f0SRoy Zang 	int ret;
101c03675f0SRoy Zang 	u8 buf[7];
102c03675f0SRoy Zang 	unsigned int year, month, day, hour, minute, second;
103c03675f0SRoy Zang 	unsigned int week, twelve_hr, am_pm;
104c03675f0SRoy Zang 	unsigned int century, add_century = 0;
105c03675f0SRoy Zang 
106370927c4SAkinobu Mita 	ret = regmap_bulk_read(ds3232->regmap, DS3232_REG_SECONDS, buf, 7);
107370927c4SAkinobu Mita 	if (ret)
108c03675f0SRoy Zang 		return ret;
109c03675f0SRoy Zang 
110c03675f0SRoy Zang 	second = buf[0];
111c03675f0SRoy Zang 	minute = buf[1];
112c03675f0SRoy Zang 	hour = buf[2];
113c03675f0SRoy Zang 	week = buf[3];
114c03675f0SRoy Zang 	day = buf[4];
115c03675f0SRoy Zang 	month = buf[5];
116c03675f0SRoy Zang 	year = buf[6];
117c03675f0SRoy Zang 
118c03675f0SRoy Zang 	/* Extract additional information for AM/PM and century */
119c03675f0SRoy Zang 
120c03675f0SRoy Zang 	twelve_hr = hour & 0x40;
121c03675f0SRoy Zang 	am_pm = hour & 0x20;
122c03675f0SRoy Zang 	century = month & 0x80;
123c03675f0SRoy Zang 
124c03675f0SRoy Zang 	/* Write to rtc_time structure */
125c03675f0SRoy Zang 
126c03675f0SRoy Zang 	time->tm_sec = bcd2bin(second);
127c03675f0SRoy Zang 	time->tm_min = bcd2bin(minute);
128c03675f0SRoy Zang 	if (twelve_hr) {
129c03675f0SRoy Zang 		/* Convert to 24 hr */
130c03675f0SRoy Zang 		if (am_pm)
131c03675f0SRoy Zang 			time->tm_hour = bcd2bin(hour & 0x1F) + 12;
132c03675f0SRoy Zang 		else
133c03675f0SRoy Zang 			time->tm_hour = bcd2bin(hour & 0x1F);
134c03675f0SRoy Zang 	} else {
135c03675f0SRoy Zang 		time->tm_hour = bcd2bin(hour);
136c03675f0SRoy Zang 	}
137c03675f0SRoy Zang 
138a2d6d2faSLei Xu 	/* Day of the week in linux range is 0~6 while 1~7 in RTC chip */
139a2d6d2faSLei Xu 	time->tm_wday = bcd2bin(week) - 1;
140c03675f0SRoy Zang 	time->tm_mday = bcd2bin(day);
141a2d6d2faSLei Xu 	/* linux tm_mon range:0~11, while month range is 1~12 in RTC chip */
142a2d6d2faSLei Xu 	time->tm_mon = bcd2bin(month & 0x7F) - 1;
143c03675f0SRoy Zang 	if (century)
144c03675f0SRoy Zang 		add_century = 100;
145c03675f0SRoy Zang 
146c03675f0SRoy Zang 	time->tm_year = bcd2bin(year) + add_century;
147c03675f0SRoy Zang 
14822652ba7SAlexandre Belloni 	return 0;
149c03675f0SRoy Zang }
150c03675f0SRoy Zang 
ds3232_set_time(struct device * dev,struct rtc_time * time)151c03675f0SRoy Zang static int ds3232_set_time(struct device *dev, struct rtc_time *time)
152c03675f0SRoy Zang {
153370927c4SAkinobu Mita 	struct ds3232 *ds3232 = dev_get_drvdata(dev);
154c03675f0SRoy Zang 	u8 buf[7];
155c03675f0SRoy Zang 
156c03675f0SRoy Zang 	/* Extract time from rtc_time and load into ds3232*/
157c03675f0SRoy Zang 
158c03675f0SRoy Zang 	buf[0] = bin2bcd(time->tm_sec);
159c03675f0SRoy Zang 	buf[1] = bin2bcd(time->tm_min);
160c03675f0SRoy Zang 	buf[2] = bin2bcd(time->tm_hour);
161a2d6d2faSLei Xu 	/* Day of the week in linux range is 0~6 while 1~7 in RTC chip */
162a2d6d2faSLei Xu 	buf[3] = bin2bcd(time->tm_wday + 1);
163c03675f0SRoy Zang 	buf[4] = bin2bcd(time->tm_mday); /* Date */
164a2d6d2faSLei Xu 	/* linux tm_mon range:0~11, while month range is 1~12 in RTC chip */
165a2d6d2faSLei Xu 	buf[5] = bin2bcd(time->tm_mon + 1);
166c03675f0SRoy Zang 	if (time->tm_year >= 100) {
167c03675f0SRoy Zang 		buf[5] |= 0x80;
168c03675f0SRoy Zang 		buf[6] = bin2bcd(time->tm_year - 100);
169c03675f0SRoy Zang 	} else {
170c03675f0SRoy Zang 		buf[6] = bin2bcd(time->tm_year);
171c03675f0SRoy Zang 	}
172c03675f0SRoy Zang 
173370927c4SAkinobu Mita 	return regmap_bulk_write(ds3232->regmap, DS3232_REG_SECONDS, buf, 7);
174c03675f0SRoy Zang }
175c03675f0SRoy Zang 
176f46418c5SLan Chunhe-B25806 /*
177f46418c5SLan Chunhe-B25806  * DS3232 has two alarm, we only use alarm1
178f46418c5SLan Chunhe-B25806  * According to linux specification, only support one-shot alarm
179f46418c5SLan Chunhe-B25806  * no periodic alarm mode
180f46418c5SLan Chunhe-B25806  */
ds3232_read_alarm(struct device * dev,struct rtc_wkalrm * alarm)181f46418c5SLan Chunhe-B25806 static int ds3232_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
182f46418c5SLan Chunhe-B25806 {
183370927c4SAkinobu Mita 	struct ds3232 *ds3232 = dev_get_drvdata(dev);
184f46418c5SLan Chunhe-B25806 	int control, stat;
185f46418c5SLan Chunhe-B25806 	int ret;
186f46418c5SLan Chunhe-B25806 	u8 buf[4];
187f46418c5SLan Chunhe-B25806 
188370927c4SAkinobu Mita 	ret = regmap_read(ds3232->regmap, DS3232_REG_SR, &stat);
189370927c4SAkinobu Mita 	if (ret)
190f46418c5SLan Chunhe-B25806 		goto out;
191370927c4SAkinobu Mita 	ret = regmap_read(ds3232->regmap, DS3232_REG_CR, &control);
192370927c4SAkinobu Mita 	if (ret)
193f46418c5SLan Chunhe-B25806 		goto out;
194370927c4SAkinobu Mita 	ret = regmap_bulk_read(ds3232->regmap, DS3232_REG_ALARM1, buf, 4);
195370927c4SAkinobu Mita 	if (ret)
196f46418c5SLan Chunhe-B25806 		goto out;
197f46418c5SLan Chunhe-B25806 
198f46418c5SLan Chunhe-B25806 	alarm->time.tm_sec = bcd2bin(buf[0] & 0x7F);
199f46418c5SLan Chunhe-B25806 	alarm->time.tm_min = bcd2bin(buf[1] & 0x7F);
200f46418c5SLan Chunhe-B25806 	alarm->time.tm_hour = bcd2bin(buf[2] & 0x7F);
201f46418c5SLan Chunhe-B25806 	alarm->time.tm_mday = bcd2bin(buf[3] & 0x7F);
202f46418c5SLan Chunhe-B25806 
203f46418c5SLan Chunhe-B25806 	alarm->enabled = !!(control & DS3232_REG_CR_A1IE);
204f46418c5SLan Chunhe-B25806 	alarm->pending = !!(stat & DS3232_REG_SR_A1F);
205f46418c5SLan Chunhe-B25806 
206f46418c5SLan Chunhe-B25806 	ret = 0;
207f46418c5SLan Chunhe-B25806 out:
208f46418c5SLan Chunhe-B25806 	return ret;
209f46418c5SLan Chunhe-B25806 }
210f46418c5SLan Chunhe-B25806 
211f46418c5SLan Chunhe-B25806 /*
212f46418c5SLan Chunhe-B25806  * linux rtc-module does not support wday alarm
213f46418c5SLan Chunhe-B25806  * and only 24h time mode supported indeed
214f46418c5SLan Chunhe-B25806  */
ds3232_set_alarm(struct device * dev,struct rtc_wkalrm * alarm)215f46418c5SLan Chunhe-B25806 static int ds3232_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
216f46418c5SLan Chunhe-B25806 {
217370927c4SAkinobu Mita 	struct ds3232 *ds3232 = dev_get_drvdata(dev);
218f46418c5SLan Chunhe-B25806 	int control, stat;
219f46418c5SLan Chunhe-B25806 	int ret;
220f46418c5SLan Chunhe-B25806 	u8 buf[4];
221f46418c5SLan Chunhe-B25806 
222370927c4SAkinobu Mita 	if (ds3232->irq <= 0)
223f46418c5SLan Chunhe-B25806 		return -EINVAL;
224f46418c5SLan Chunhe-B25806 
225f46418c5SLan Chunhe-B25806 	buf[0] = bin2bcd(alarm->time.tm_sec);
226f46418c5SLan Chunhe-B25806 	buf[1] = bin2bcd(alarm->time.tm_min);
227f46418c5SLan Chunhe-B25806 	buf[2] = bin2bcd(alarm->time.tm_hour);
228f46418c5SLan Chunhe-B25806 	buf[3] = bin2bcd(alarm->time.tm_mday);
229f46418c5SLan Chunhe-B25806 
230f46418c5SLan Chunhe-B25806 	/* clear alarm interrupt enable bit */
231370927c4SAkinobu Mita 	ret = regmap_read(ds3232->regmap, DS3232_REG_CR, &control);
232370927c4SAkinobu Mita 	if (ret)
233f46418c5SLan Chunhe-B25806 		goto out;
234f46418c5SLan Chunhe-B25806 	control &= ~(DS3232_REG_CR_A1IE | DS3232_REG_CR_A2IE);
235370927c4SAkinobu Mita 	ret = regmap_write(ds3232->regmap, DS3232_REG_CR, control);
236370927c4SAkinobu Mita 	if (ret)
237f46418c5SLan Chunhe-B25806 		goto out;
238f46418c5SLan Chunhe-B25806 
239f46418c5SLan Chunhe-B25806 	/* clear any pending alarm flag */
240370927c4SAkinobu Mita 	ret = regmap_read(ds3232->regmap, DS3232_REG_SR, &stat);
241370927c4SAkinobu Mita 	if (ret)
242f46418c5SLan Chunhe-B25806 		goto out;
243f46418c5SLan Chunhe-B25806 	stat &= ~(DS3232_REG_SR_A1F | DS3232_REG_SR_A2F);
244370927c4SAkinobu Mita 	ret = regmap_write(ds3232->regmap, DS3232_REG_SR, stat);
245370927c4SAkinobu Mita 	if (ret)
246f46418c5SLan Chunhe-B25806 		goto out;
247f46418c5SLan Chunhe-B25806 
248370927c4SAkinobu Mita 	ret = regmap_bulk_write(ds3232->regmap, DS3232_REG_ALARM1, buf, 4);
2497b4393a6SAkinobu Mita 	if (ret)
2507b4393a6SAkinobu Mita 		goto out;
251f46418c5SLan Chunhe-B25806 
252f46418c5SLan Chunhe-B25806 	if (alarm->enabled) {
253f46418c5SLan Chunhe-B25806 		control |= DS3232_REG_CR_A1IE;
254370927c4SAkinobu Mita 		ret = regmap_write(ds3232->regmap, DS3232_REG_CR, control);
255f46418c5SLan Chunhe-B25806 	}
256f46418c5SLan Chunhe-B25806 out:
257f46418c5SLan Chunhe-B25806 	return ret;
258f46418c5SLan Chunhe-B25806 }
259f46418c5SLan Chunhe-B25806 
ds3232_update_alarm(struct device * dev,unsigned int enabled)2607b4393a6SAkinobu Mita static int ds3232_update_alarm(struct device *dev, unsigned int enabled)
261f46418c5SLan Chunhe-B25806 {
262370927c4SAkinobu Mita 	struct ds3232 *ds3232 = dev_get_drvdata(dev);
263f46418c5SLan Chunhe-B25806 	int control;
264f46418c5SLan Chunhe-B25806 	int ret;
265f46418c5SLan Chunhe-B25806 
266370927c4SAkinobu Mita 	ret = regmap_read(ds3232->regmap, DS3232_REG_CR, &control);
267370927c4SAkinobu Mita 	if (ret)
268fc1dcb0bSAkinobu Mita 		return ret;
269f46418c5SLan Chunhe-B25806 
2707522297eSAkinobu Mita 	if (enabled)
271f46418c5SLan Chunhe-B25806 		/* enable alarm1 interrupt */
272f46418c5SLan Chunhe-B25806 		control |= DS3232_REG_CR_A1IE;
273f46418c5SLan Chunhe-B25806 	else
274f46418c5SLan Chunhe-B25806 		/* disable alarm1 interrupt */
275f46418c5SLan Chunhe-B25806 		control &= ~(DS3232_REG_CR_A1IE);
2767b4393a6SAkinobu Mita 	ret = regmap_write(ds3232->regmap, DS3232_REG_CR, control);
277f46418c5SLan Chunhe-B25806 
2787b4393a6SAkinobu Mita 	return ret;
279f46418c5SLan Chunhe-B25806 }
280f46418c5SLan Chunhe-B25806 
281c35c4195SKirill Esipov /*
282c35c4195SKirill Esipov  * Temperature sensor support for ds3232/ds3234 devices.
283c35c4195SKirill Esipov  * A user-initiated temperature conversion is not started by this function,
284c35c4195SKirill Esipov  * so the temperature is updated once every 64 seconds.
285c35c4195SKirill Esipov  */
ds3232_hwmon_read_temp(struct device * dev,long int * mC)286c35c4195SKirill Esipov static int ds3232_hwmon_read_temp(struct device *dev, long int *mC)
287c35c4195SKirill Esipov {
288c35c4195SKirill Esipov 	struct ds3232 *ds3232 = dev_get_drvdata(dev);
289c35c4195SKirill Esipov 	u8 temp_buf[2];
290c35c4195SKirill Esipov 	s16 temp;
291c35c4195SKirill Esipov 	int ret;
292c35c4195SKirill Esipov 
293c35c4195SKirill Esipov 	ret = regmap_bulk_read(ds3232->regmap, DS3232_REG_TEMPERATURE, temp_buf,
294c35c4195SKirill Esipov 			       sizeof(temp_buf));
295c35c4195SKirill Esipov 	if (ret < 0)
296c35c4195SKirill Esipov 		return ret;
297c35c4195SKirill Esipov 
298c35c4195SKirill Esipov 	/*
299c35c4195SKirill Esipov 	 * Temperature is represented as a 10-bit code with a resolution of
300c35c4195SKirill Esipov 	 * 0.25 degree celsius and encoded in two's complement format.
301c35c4195SKirill Esipov 	 */
302c35c4195SKirill Esipov 	temp = (temp_buf[0] << 8) | temp_buf[1];
303c35c4195SKirill Esipov 	temp >>= 6;
304c35c4195SKirill Esipov 	*mC = temp * 250;
305c35c4195SKirill Esipov 
306c35c4195SKirill Esipov 	return 0;
307c35c4195SKirill Esipov }
308c35c4195SKirill Esipov 
ds3232_hwmon_is_visible(const void * data,enum hwmon_sensor_types type,u32 attr,int channel)309c35c4195SKirill Esipov static umode_t ds3232_hwmon_is_visible(const void *data,
310c35c4195SKirill Esipov 				       enum hwmon_sensor_types type,
311c35c4195SKirill Esipov 				       u32 attr, int channel)
312c35c4195SKirill Esipov {
313c35c4195SKirill Esipov 	if (type != hwmon_temp)
314c35c4195SKirill Esipov 		return 0;
315c35c4195SKirill Esipov 
316c35c4195SKirill Esipov 	switch (attr) {
317c35c4195SKirill Esipov 	case hwmon_temp_input:
318c35c4195SKirill Esipov 		return 0444;
319c35c4195SKirill Esipov 	default:
320c35c4195SKirill Esipov 		return 0;
321c35c4195SKirill Esipov 	}
322c35c4195SKirill Esipov }
323c35c4195SKirill Esipov 
ds3232_hwmon_read(struct device * dev,enum hwmon_sensor_types type,u32 attr,int channel,long * temp)324c35c4195SKirill Esipov static int ds3232_hwmon_read(struct device *dev,
325c35c4195SKirill Esipov 			     enum hwmon_sensor_types type,
326c35c4195SKirill Esipov 			     u32 attr, int channel, long *temp)
327c35c4195SKirill Esipov {
328c35c4195SKirill Esipov 	int err;
329c35c4195SKirill Esipov 
330c35c4195SKirill Esipov 	switch (attr) {
331c35c4195SKirill Esipov 	case hwmon_temp_input:
332c35c4195SKirill Esipov 		err = ds3232_hwmon_read_temp(dev, temp);
333c35c4195SKirill Esipov 		break;
334c35c4195SKirill Esipov 	default:
335c35c4195SKirill Esipov 		err = -EOPNOTSUPP;
336c35c4195SKirill Esipov 		break;
337c35c4195SKirill Esipov 	}
338c35c4195SKirill Esipov 
339c35c4195SKirill Esipov 	return err;
340c35c4195SKirill Esipov }
341c35c4195SKirill Esipov 
342c35c4195SKirill Esipov static u32 ds3232_hwmon_chip_config[] = {
343c35c4195SKirill Esipov 	HWMON_C_REGISTER_TZ,
344c35c4195SKirill Esipov 	0
345c35c4195SKirill Esipov };
346c35c4195SKirill Esipov 
347c35c4195SKirill Esipov static const struct hwmon_channel_info ds3232_hwmon_chip = {
348c35c4195SKirill Esipov 	.type = hwmon_chip,
349c35c4195SKirill Esipov 	.config = ds3232_hwmon_chip_config,
350c35c4195SKirill Esipov };
351c35c4195SKirill Esipov 
352c35c4195SKirill Esipov static u32 ds3232_hwmon_temp_config[] = {
353c35c4195SKirill Esipov 	HWMON_T_INPUT,
354c35c4195SKirill Esipov 	0
355c35c4195SKirill Esipov };
356c35c4195SKirill Esipov 
357c35c4195SKirill Esipov static const struct hwmon_channel_info ds3232_hwmon_temp = {
358c35c4195SKirill Esipov 	.type = hwmon_temp,
359c35c4195SKirill Esipov 	.config = ds3232_hwmon_temp_config,
360c35c4195SKirill Esipov };
361c35c4195SKirill Esipov 
362d00caa55SKrzysztof Kozlowski static const struct hwmon_channel_info * const ds3232_hwmon_info[] = {
363c35c4195SKirill Esipov 	&ds3232_hwmon_chip,
364c35c4195SKirill Esipov 	&ds3232_hwmon_temp,
365c35c4195SKirill Esipov 	NULL
366c35c4195SKirill Esipov };
367c35c4195SKirill Esipov 
368c35c4195SKirill Esipov static const struct hwmon_ops ds3232_hwmon_hwmon_ops = {
369c35c4195SKirill Esipov 	.is_visible = ds3232_hwmon_is_visible,
370c35c4195SKirill Esipov 	.read = ds3232_hwmon_read,
371c35c4195SKirill Esipov };
372c35c4195SKirill Esipov 
373c35c4195SKirill Esipov static const struct hwmon_chip_info ds3232_hwmon_chip_info = {
374c35c4195SKirill Esipov 	.ops = &ds3232_hwmon_hwmon_ops,
375c35c4195SKirill Esipov 	.info = ds3232_hwmon_info,
376c35c4195SKirill Esipov };
377c35c4195SKirill Esipov 
ds3232_hwmon_register(struct device * dev,const char * name)378c35c4195SKirill Esipov static void ds3232_hwmon_register(struct device *dev, const char *name)
379c35c4195SKirill Esipov {
380c35c4195SKirill Esipov 	struct ds3232 *ds3232 = dev_get_drvdata(dev);
381c35c4195SKirill Esipov 	struct device *hwmon_dev;
382c35c4195SKirill Esipov 
383c35c4195SKirill Esipov 	if (!IS_ENABLED(CONFIG_RTC_DRV_DS3232_HWMON))
384c35c4195SKirill Esipov 		return;
385c35c4195SKirill Esipov 
386c35c4195SKirill Esipov 	hwmon_dev = devm_hwmon_device_register_with_info(dev, name, ds3232,
387c35c4195SKirill Esipov 							&ds3232_hwmon_chip_info,
388c35c4195SKirill Esipov 							NULL);
389c35c4195SKirill Esipov 	if (IS_ERR(hwmon_dev)) {
390c35c4195SKirill Esipov 		dev_err(dev, "unable to register hwmon device %ld\n",
391c35c4195SKirill Esipov 			PTR_ERR(hwmon_dev));
392c35c4195SKirill Esipov 	}
393c35c4195SKirill Esipov }
394c35c4195SKirill Esipov 
ds3232_alarm_irq_enable(struct device * dev,unsigned int enabled)395f46418c5SLan Chunhe-B25806 static int ds3232_alarm_irq_enable(struct device *dev, unsigned int enabled)
396f46418c5SLan Chunhe-B25806 {
397370927c4SAkinobu Mita 	struct ds3232 *ds3232 = dev_get_drvdata(dev);
398f46418c5SLan Chunhe-B25806 
399370927c4SAkinobu Mita 	if (ds3232->irq <= 0)
400f46418c5SLan Chunhe-B25806 		return -EINVAL;
401f46418c5SLan Chunhe-B25806 
4027b4393a6SAkinobu Mita 	return ds3232_update_alarm(dev, enabled);
403f46418c5SLan Chunhe-B25806 }
404f46418c5SLan Chunhe-B25806 
ds3232_irq(int irq,void * dev_id)405c03675f0SRoy Zang static irqreturn_t ds3232_irq(int irq, void *dev_id)
406c03675f0SRoy Zang {
407370927c4SAkinobu Mita 	struct device *dev = dev_id;
408370927c4SAkinobu Mita 	struct ds3232 *ds3232 = dev_get_drvdata(dev);
409370927c4SAkinobu Mita 	int ret;
410c03675f0SRoy Zang 	int stat, control;
411c03675f0SRoy Zang 
4123aa7eaf2SAlexandre Belloni 	rtc_lock(ds3232->rtc);
413c03675f0SRoy Zang 
414370927c4SAkinobu Mita 	ret = regmap_read(ds3232->regmap, DS3232_REG_SR, &stat);
415370927c4SAkinobu Mita 	if (ret)
416c03675f0SRoy Zang 		goto unlock;
417c03675f0SRoy Zang 
418c03675f0SRoy Zang 	if (stat & DS3232_REG_SR_A1F) {
419370927c4SAkinobu Mita 		ret = regmap_read(ds3232->regmap, DS3232_REG_CR, &control);
420370927c4SAkinobu Mita 		if (ret) {
42195c60c1cSAkinobu Mita 			dev_warn(ds3232->dev,
42295c60c1cSAkinobu Mita 				 "Read Control Register error %d\n", ret);
423c93a3ae2SWang Dongsheng 		} else {
424c03675f0SRoy Zang 			/* disable alarm1 interrupt */
425c03675f0SRoy Zang 			control &= ~(DS3232_REG_CR_A1IE);
4267b4393a6SAkinobu Mita 			ret = regmap_write(ds3232->regmap, DS3232_REG_CR,
4277b4393a6SAkinobu Mita 					   control);
4287b4393a6SAkinobu Mita 			if (ret) {
4297b4393a6SAkinobu Mita 				dev_warn(ds3232->dev,
4307b4393a6SAkinobu Mita 					 "Write Control Register error %d\n",
4317b4393a6SAkinobu Mita 					 ret);
4327b4393a6SAkinobu Mita 				goto unlock;
4337b4393a6SAkinobu Mita 			}
434c03675f0SRoy Zang 
435c03675f0SRoy Zang 			/* clear the alarm pend flag */
436c03675f0SRoy Zang 			stat &= ~DS3232_REG_SR_A1F;
4377b4393a6SAkinobu Mita 			ret = regmap_write(ds3232->regmap, DS3232_REG_SR, stat);
4387b4393a6SAkinobu Mita 			if (ret) {
4397b4393a6SAkinobu Mita 				dev_warn(ds3232->dev,
4407b4393a6SAkinobu Mita 					 "Write Status Register error %d\n",
4417b4393a6SAkinobu Mita 					 ret);
4427b4393a6SAkinobu Mita 				goto unlock;
4437b4393a6SAkinobu Mita 			}
444c03675f0SRoy Zang 
445c03675f0SRoy Zang 			rtc_update_irq(ds3232->rtc, 1, RTC_AF | RTC_IRQF);
446c93a3ae2SWang Dongsheng 		}
447c93a3ae2SWang Dongsheng 	}
448c93a3ae2SWang Dongsheng 
449c03675f0SRoy Zang unlock:
4503aa7eaf2SAlexandre Belloni 	rtc_unlock(ds3232->rtc);
45195c60c1cSAkinobu Mita 
45295c60c1cSAkinobu Mita 	return IRQ_HANDLED;
453c03675f0SRoy Zang }
454c03675f0SRoy Zang 
455c03675f0SRoy Zang static const struct rtc_class_ops ds3232_rtc_ops = {
456c03675f0SRoy Zang 	.read_time = ds3232_read_time,
457c03675f0SRoy Zang 	.set_time = ds3232_set_time,
458f46418c5SLan Chunhe-B25806 	.read_alarm = ds3232_read_alarm,
459f46418c5SLan Chunhe-B25806 	.set_alarm = ds3232_set_alarm,
460f46418c5SLan Chunhe-B25806 	.alarm_irq_enable = ds3232_alarm_irq_enable,
461c03675f0SRoy Zang };
462c03675f0SRoy Zang 
ds3232_nvmem_read(void * priv,unsigned int offset,void * val,size_t bytes)4639eec31f3SHan Nandor static int ds3232_nvmem_read(void *priv, unsigned int offset, void *val,
4649eec31f3SHan Nandor 			     size_t bytes)
4659eec31f3SHan Nandor {
4669eec31f3SHan Nandor 	struct regmap *ds3232_regmap = (struct regmap *)priv;
4679eec31f3SHan Nandor 
4689eec31f3SHan Nandor 	return regmap_bulk_read(ds3232_regmap, DS3232_REG_SRAM_START + offset,
4699eec31f3SHan Nandor 				val, bytes);
4709eec31f3SHan Nandor }
4719eec31f3SHan Nandor 
ds3232_nvmem_write(void * priv,unsigned int offset,void * val,size_t bytes)4729eec31f3SHan Nandor static int ds3232_nvmem_write(void *priv, unsigned int offset, void *val,
4739eec31f3SHan Nandor 			      size_t bytes)
4749eec31f3SHan Nandor {
4759eec31f3SHan Nandor 	struct regmap *ds3232_regmap = (struct regmap *)priv;
4769eec31f3SHan Nandor 
4779eec31f3SHan Nandor 	return regmap_bulk_write(ds3232_regmap, DS3232_REG_SRAM_START + offset,
4789eec31f3SHan Nandor 				 val, bytes);
4799eec31f3SHan Nandor }
4809eec31f3SHan Nandor 
ds3232_probe(struct device * dev,struct regmap * regmap,int irq,const char * name)481370927c4SAkinobu Mita static int ds3232_probe(struct device *dev, struct regmap *regmap, int irq,
482370927c4SAkinobu Mita 			const char *name)
483c03675f0SRoy Zang {
484c03675f0SRoy Zang 	struct ds3232 *ds3232;
485c03675f0SRoy Zang 	int ret;
4869eec31f3SHan Nandor 	struct nvmem_config nvmem_cfg = {
4879eec31f3SHan Nandor 		.name = "ds3232_sram",
4889eec31f3SHan Nandor 		.stride = 1,
4899eec31f3SHan Nandor 		.size = DS3232_REG_SRAM_SIZE,
4909eec31f3SHan Nandor 		.word_size = 1,
4919eec31f3SHan Nandor 		.reg_read = ds3232_nvmem_read,
4929eec31f3SHan Nandor 		.reg_write = ds3232_nvmem_write,
4939eec31f3SHan Nandor 		.priv = regmap,
4949eec31f3SHan Nandor 		.type = NVMEM_TYPE_BATTERY_BACKED
4959eec31f3SHan Nandor 	};
496c03675f0SRoy Zang 
497370927c4SAkinobu Mita 	ds3232 = devm_kzalloc(dev, sizeof(*ds3232), GFP_KERNEL);
498c03675f0SRoy Zang 	if (!ds3232)
499c03675f0SRoy Zang 		return -ENOMEM;
500c03675f0SRoy Zang 
501370927c4SAkinobu Mita 	ds3232->regmap = regmap;
502370927c4SAkinobu Mita 	ds3232->irq = irq;
503370927c4SAkinobu Mita 	ds3232->dev = dev;
504370927c4SAkinobu Mita 	dev_set_drvdata(dev, ds3232);
505c03675f0SRoy Zang 
506370927c4SAkinobu Mita 	ret = ds3232_check_rtc_status(dev);
507c03675f0SRoy Zang 	if (ret)
50866714612SSachin Kamat 		return ret;
509c03675f0SRoy Zang 
510d4f6c6f1SPhil Reid 	if (ds3232->irq > 0)
511d4f6c6f1SPhil Reid 		device_init_wakeup(dev, 1);
512d4f6c6f1SPhil Reid 
513c35c4195SKirill Esipov 	ds3232_hwmon_register(dev, name);
514c35c4195SKirill Esipov 
515b4b77f3cSQianyu Gong 	ds3232->rtc = devm_rtc_device_register(dev, name, &ds3232_rtc_ops,
516b4b77f3cSQianyu Gong 						THIS_MODULE);
517b4b77f3cSQianyu Gong 	if (IS_ERR(ds3232->rtc))
518b4b77f3cSQianyu Gong 		return PTR_ERR(ds3232->rtc);
519b4b77f3cSQianyu Gong 
5203a905c2dSBartosz Golaszewski 	ret = devm_rtc_nvmem_register(ds3232->rtc, &nvmem_cfg);
5219eec31f3SHan Nandor 	if(ret)
5229eec31f3SHan Nandor 		return ret;
5239eec31f3SHan Nandor 
524370927c4SAkinobu Mita 	if (ds3232->irq > 0) {
52595c60c1cSAkinobu Mita 		ret = devm_request_threaded_irq(dev, ds3232->irq, NULL,
52695c60c1cSAkinobu Mita 						ds3232_irq,
52795c60c1cSAkinobu Mita 						IRQF_SHARED | IRQF_ONESHOT,
52895c60c1cSAkinobu Mita 						name, dev);
529c03675f0SRoy Zang 		if (ret) {
530d4f6c6f1SPhil Reid 			device_set_wakeup_capable(dev, 0);
531370927c4SAkinobu Mita 			ds3232->irq = 0;
532370927c4SAkinobu Mita 			dev_err(dev, "unable to request IRQ\n");
533d4f6c6f1SPhil Reid 		}
534c03675f0SRoy Zang 	}
535370927c4SAkinobu Mita 
536b4b77f3cSQianyu Gong 	return 0;
537c03675f0SRoy Zang }
538c03675f0SRoy Zang 
539c93a3ae2SWang Dongsheng #ifdef CONFIG_PM_SLEEP
ds3232_suspend(struct device * dev)540c93a3ae2SWang Dongsheng static int ds3232_suspend(struct device *dev)
541c93a3ae2SWang Dongsheng {
542c93a3ae2SWang Dongsheng 	struct ds3232 *ds3232 = dev_get_drvdata(dev);
543c93a3ae2SWang Dongsheng 
54495c60c1cSAkinobu Mita 	if (device_may_wakeup(dev)) {
54595c60c1cSAkinobu Mita 		if (enable_irq_wake(ds3232->irq))
546dc2280ebSWang Dongsheng 			dev_warn_once(dev, "Cannot set wakeup source\n");
547c93a3ae2SWang Dongsheng 	}
548c93a3ae2SWang Dongsheng 
549c93a3ae2SWang Dongsheng 	return 0;
550c93a3ae2SWang Dongsheng }
551c93a3ae2SWang Dongsheng 
ds3232_resume(struct device * dev)552c93a3ae2SWang Dongsheng static int ds3232_resume(struct device *dev)
553c93a3ae2SWang Dongsheng {
554c93a3ae2SWang Dongsheng 	struct ds3232 *ds3232 = dev_get_drvdata(dev);
555c93a3ae2SWang Dongsheng 
55695c60c1cSAkinobu Mita 	if (device_may_wakeup(dev))
55795c60c1cSAkinobu Mita 		disable_irq_wake(ds3232->irq);
558c93a3ae2SWang Dongsheng 
559c93a3ae2SWang Dongsheng 	return 0;
560c93a3ae2SWang Dongsheng }
561c93a3ae2SWang Dongsheng #endif
562c93a3ae2SWang Dongsheng 
563c93a3ae2SWang Dongsheng static const struct dev_pm_ops ds3232_pm_ops = {
564c93a3ae2SWang Dongsheng 	SET_SYSTEM_SLEEP_PM_OPS(ds3232_suspend, ds3232_resume)
565c93a3ae2SWang Dongsheng };
566c93a3ae2SWang Dongsheng 
567080481f5SAkinobu Mita #if IS_ENABLED(CONFIG_I2C)
568080481f5SAkinobu Mita 
ds3232_i2c_probe(struct i2c_client * client)5693f4a3322SStephen Kitt static int ds3232_i2c_probe(struct i2c_client *client)
570370927c4SAkinobu Mita {
571370927c4SAkinobu Mita 	struct regmap *regmap;
572370927c4SAkinobu Mita 	static const struct regmap_config config = {
573370927c4SAkinobu Mita 		.reg_bits = 8,
574370927c4SAkinobu Mita 		.val_bits = 8,
5759eec31f3SHan Nandor 		.max_register = DS3232_REG_SRAM_END,
576370927c4SAkinobu Mita 	};
577370927c4SAkinobu Mita 
578370927c4SAkinobu Mita 	regmap = devm_regmap_init_i2c(client, &config);
579370927c4SAkinobu Mita 	if (IS_ERR(regmap)) {
580370927c4SAkinobu Mita 		dev_err(&client->dev, "%s: regmap allocation failed: %ld\n",
581370927c4SAkinobu Mita 			__func__, PTR_ERR(regmap));
582370927c4SAkinobu Mita 		return PTR_ERR(regmap);
583370927c4SAkinobu Mita 	}
584370927c4SAkinobu Mita 
585370927c4SAkinobu Mita 	return ds3232_probe(&client->dev, regmap, client->irq, client->name);
586370927c4SAkinobu Mita }
587370927c4SAkinobu Mita 
588c03675f0SRoy Zang static const struct i2c_device_id ds3232_id[] = {
589c03675f0SRoy Zang 	{ "ds3232", 0 },
590c03675f0SRoy Zang 	{ }
591c03675f0SRoy Zang };
592c03675f0SRoy Zang MODULE_DEVICE_TABLE(i2c, ds3232_id);
593c03675f0SRoy Zang 
5942c1dc25fSAlexandre Belloni static const  __maybe_unused struct of_device_id ds3232_of_match[] = {
5954dfbd137SJavier Martinez Canillas 	{ .compatible = "dallas,ds3232" },
5964dfbd137SJavier Martinez Canillas 	{ }
5974dfbd137SJavier Martinez Canillas };
5984dfbd137SJavier Martinez Canillas MODULE_DEVICE_TABLE(of, ds3232_of_match);
5994dfbd137SJavier Martinez Canillas 
600c03675f0SRoy Zang static struct i2c_driver ds3232_driver = {
601c03675f0SRoy Zang 	.driver = {
602c03675f0SRoy Zang 		.name = "rtc-ds3232",
6034dfbd137SJavier Martinez Canillas 		.of_match_table = of_match_ptr(ds3232_of_match),
604c93a3ae2SWang Dongsheng 		.pm	= &ds3232_pm_ops,
605c03675f0SRoy Zang 	},
606*31b0cecbSUwe Kleine-König 	.probe = ds3232_i2c_probe,
607c03675f0SRoy Zang 	.id_table = ds3232_id,
608c03675f0SRoy Zang };
609080481f5SAkinobu Mita 
ds3232_register_driver(void)610080481f5SAkinobu Mita static int ds3232_register_driver(void)
611080481f5SAkinobu Mita {
612080481f5SAkinobu Mita 	return i2c_add_driver(&ds3232_driver);
613080481f5SAkinobu Mita }
614080481f5SAkinobu Mita 
ds3232_unregister_driver(void)615080481f5SAkinobu Mita static void ds3232_unregister_driver(void)
616080481f5SAkinobu Mita {
617080481f5SAkinobu Mita 	i2c_del_driver(&ds3232_driver);
618080481f5SAkinobu Mita }
619080481f5SAkinobu Mita 
620080481f5SAkinobu Mita #else
621080481f5SAkinobu Mita 
ds3232_register_driver(void)622080481f5SAkinobu Mita static int ds3232_register_driver(void)
623080481f5SAkinobu Mita {
624080481f5SAkinobu Mita 	return 0;
625080481f5SAkinobu Mita }
626080481f5SAkinobu Mita 
ds3232_unregister_driver(void)627080481f5SAkinobu Mita static void ds3232_unregister_driver(void)
628080481f5SAkinobu Mita {
629080481f5SAkinobu Mita }
630080481f5SAkinobu Mita 
631080481f5SAkinobu Mita #endif
632080481f5SAkinobu Mita 
633080481f5SAkinobu Mita #if IS_ENABLED(CONFIG_SPI_MASTER)
634080481f5SAkinobu Mita 
ds3234_probe(struct spi_device * spi)635080481f5SAkinobu Mita static int ds3234_probe(struct spi_device *spi)
636080481f5SAkinobu Mita {
637080481f5SAkinobu Mita 	int res;
638080481f5SAkinobu Mita 	unsigned int tmp;
639080481f5SAkinobu Mita 	static const struct regmap_config config = {
640080481f5SAkinobu Mita 		.reg_bits = 8,
641080481f5SAkinobu Mita 		.val_bits = 8,
6429eec31f3SHan Nandor 		.max_register = DS3232_REG_SRAM_END,
643080481f5SAkinobu Mita 		.write_flag_mask = 0x80,
644080481f5SAkinobu Mita 	};
645080481f5SAkinobu Mita 	struct regmap *regmap;
646080481f5SAkinobu Mita 
647080481f5SAkinobu Mita 	regmap = devm_regmap_init_spi(spi, &config);
648080481f5SAkinobu Mita 	if (IS_ERR(regmap)) {
649080481f5SAkinobu Mita 		dev_err(&spi->dev, "%s: regmap allocation failed: %ld\n",
650080481f5SAkinobu Mita 			__func__, PTR_ERR(regmap));
651080481f5SAkinobu Mita 		return PTR_ERR(regmap);
652080481f5SAkinobu Mita 	}
653080481f5SAkinobu Mita 
654080481f5SAkinobu Mita 	spi->mode = SPI_MODE_3;
655080481f5SAkinobu Mita 	spi->bits_per_word = 8;
656080481f5SAkinobu Mita 	spi_setup(spi);
657080481f5SAkinobu Mita 
658080481f5SAkinobu Mita 	res = regmap_read(regmap, DS3232_REG_SECONDS, &tmp);
659080481f5SAkinobu Mita 	if (res)
660080481f5SAkinobu Mita 		return res;
661080481f5SAkinobu Mita 
662080481f5SAkinobu Mita 	/* Control settings
663080481f5SAkinobu Mita 	 *
664080481f5SAkinobu Mita 	 * CONTROL_REG
665080481f5SAkinobu Mita 	 * BIT 7	6	5	4	3	2	1	0
666080481f5SAkinobu Mita 	 *     EOSC	BBSQW	CONV	RS2	RS1	INTCN	A2IE	A1IE
667080481f5SAkinobu Mita 	 *
668080481f5SAkinobu Mita 	 *     0	0	0	1	1	1	0	0
669080481f5SAkinobu Mita 	 *
670080481f5SAkinobu Mita 	 * CONTROL_STAT_REG
671080481f5SAkinobu Mita 	 * BIT 7	6	5	4	3	2	1	0
672080481f5SAkinobu Mita 	 *     OSF	BB32kHz	CRATE1	CRATE0	EN32kHz	BSY	A2F	A1F
673080481f5SAkinobu Mita 	 *
674080481f5SAkinobu Mita 	 *     1	0	0	0	1	0	0	0
675080481f5SAkinobu Mita 	 */
676080481f5SAkinobu Mita 	res = regmap_read(regmap, DS3232_REG_CR, &tmp);
677080481f5SAkinobu Mita 	if (res)
678080481f5SAkinobu Mita 		return res;
679080481f5SAkinobu Mita 	res = regmap_write(regmap, DS3232_REG_CR, tmp & 0x1c);
680080481f5SAkinobu Mita 	if (res)
681080481f5SAkinobu Mita 		return res;
682080481f5SAkinobu Mita 
683080481f5SAkinobu Mita 	res = regmap_read(regmap, DS3232_REG_SR, &tmp);
684080481f5SAkinobu Mita 	if (res)
685080481f5SAkinobu Mita 		return res;
686080481f5SAkinobu Mita 	res = regmap_write(regmap, DS3232_REG_SR, tmp & 0x88);
687080481f5SAkinobu Mita 	if (res)
688080481f5SAkinobu Mita 		return res;
689080481f5SAkinobu Mita 
690080481f5SAkinobu Mita 	/* Print our settings */
691080481f5SAkinobu Mita 	res = regmap_read(regmap, DS3232_REG_CR, &tmp);
692080481f5SAkinobu Mita 	if (res)
693080481f5SAkinobu Mita 		return res;
694080481f5SAkinobu Mita 	dev_info(&spi->dev, "Control Reg: 0x%02x\n", tmp);
695080481f5SAkinobu Mita 
696080481f5SAkinobu Mita 	res = regmap_read(regmap, DS3232_REG_SR, &tmp);
697080481f5SAkinobu Mita 	if (res)
698080481f5SAkinobu Mita 		return res;
699080481f5SAkinobu Mita 	dev_info(&spi->dev, "Ctrl/Stat Reg: 0x%02x\n", tmp);
700080481f5SAkinobu Mita 
701080481f5SAkinobu Mita 	return ds3232_probe(&spi->dev, regmap, spi->irq, "ds3234");
702080481f5SAkinobu Mita }
703080481f5SAkinobu Mita 
704080481f5SAkinobu Mita static struct spi_driver ds3234_driver = {
705080481f5SAkinobu Mita 	.driver = {
706080481f5SAkinobu Mita 		.name	 = "ds3234",
707080481f5SAkinobu Mita 	},
708080481f5SAkinobu Mita 	.probe	 = ds3234_probe,
709080481f5SAkinobu Mita };
710080481f5SAkinobu Mita 
ds3234_register_driver(void)711080481f5SAkinobu Mita static int ds3234_register_driver(void)
712080481f5SAkinobu Mita {
713080481f5SAkinobu Mita 	return spi_register_driver(&ds3234_driver);
714080481f5SAkinobu Mita }
715080481f5SAkinobu Mita 
ds3234_unregister_driver(void)716080481f5SAkinobu Mita static void ds3234_unregister_driver(void)
717080481f5SAkinobu Mita {
718080481f5SAkinobu Mita 	spi_unregister_driver(&ds3234_driver);
719080481f5SAkinobu Mita }
720080481f5SAkinobu Mita 
721080481f5SAkinobu Mita #else
722080481f5SAkinobu Mita 
ds3234_register_driver(void)723080481f5SAkinobu Mita static int ds3234_register_driver(void)
724080481f5SAkinobu Mita {
725080481f5SAkinobu Mita 	return 0;
726080481f5SAkinobu Mita }
727080481f5SAkinobu Mita 
ds3234_unregister_driver(void)728080481f5SAkinobu Mita static void ds3234_unregister_driver(void)
729080481f5SAkinobu Mita {
730080481f5SAkinobu Mita }
731080481f5SAkinobu Mita 
732080481f5SAkinobu Mita #endif
733080481f5SAkinobu Mita 
ds323x_init(void)734080481f5SAkinobu Mita static int __init ds323x_init(void)
735080481f5SAkinobu Mita {
736080481f5SAkinobu Mita 	int ret;
737080481f5SAkinobu Mita 
738080481f5SAkinobu Mita 	ret = ds3232_register_driver();
739080481f5SAkinobu Mita 	if (ret) {
740080481f5SAkinobu Mita 		pr_err("Failed to register ds3232 driver: %d\n", ret);
741080481f5SAkinobu Mita 		return ret;
742080481f5SAkinobu Mita 	}
743080481f5SAkinobu Mita 
744080481f5SAkinobu Mita 	ret = ds3234_register_driver();
745080481f5SAkinobu Mita 	if (ret) {
746080481f5SAkinobu Mita 		pr_err("Failed to register ds3234 driver: %d\n", ret);
747080481f5SAkinobu Mita 		ds3232_unregister_driver();
748080481f5SAkinobu Mita 	}
749080481f5SAkinobu Mita 
750080481f5SAkinobu Mita 	return ret;
751080481f5SAkinobu Mita }
module_init(ds323x_init)752080481f5SAkinobu Mita module_init(ds323x_init)
753080481f5SAkinobu Mita 
754080481f5SAkinobu Mita static void __exit ds323x_exit(void)
755080481f5SAkinobu Mita {
756080481f5SAkinobu Mita 	ds3234_unregister_driver();
757080481f5SAkinobu Mita 	ds3232_unregister_driver();
758080481f5SAkinobu Mita }
759080481f5SAkinobu Mita module_exit(ds323x_exit)
760c03675f0SRoy Zang 
761c03675f0SRoy Zang MODULE_AUTHOR("Srikanth Srinivasan <srikanth.srinivasan@freescale.com>");
762080481f5SAkinobu Mita MODULE_AUTHOR("Dennis Aberilla <denzzzhome@yahoo.com>");
763080481f5SAkinobu Mita MODULE_DESCRIPTION("Maxim/Dallas DS3232/DS3234 RTC Driver");
764c03675f0SRoy Zang MODULE_LICENSE("GPL");
765080481f5SAkinobu Mita MODULE_ALIAS("spi:ds3234");
766