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