blob: 9857287215a94d7795f8231c371df2443215122a [file] [log] [blame]
Roy Zangc03675f2010-08-10 18:02:20 -07001/*
Akinobu Mita080481f52016-03-07 00:27:48 +09002 * RTC client/driver for the Maxim/Dallas DS3232/DS3234 Real-Time Clock
Roy Zangc03675f2010-08-10 18:02:20 -07003 *
Lei Xua2d6d2f2011-02-25 14:44:23 -08004 * Copyright (C) 2009-2011 Freescale Semiconductor.
Lan Chunhe-B25806f46418c2010-10-27 15:33:12 -07005 * Author: Jack Lan <jack.lan@freescale.com>
Akinobu Mita080481f52016-03-07 00:27:48 +09006 * Copyright (C) 2008 MIMOMax Wireless Ltd.
Roy Zangc03675f2010-08-10 18:02:20 -07007 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 */
Roy Zangc03675f2010-08-10 18:02:20 -070013
Joe Perchesa737e8352015-04-16 12:46:14 -070014#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
15
Roy Zangc03675f2010-08-10 18:02:20 -070016#include <linux/kernel.h>
17#include <linux/module.h>
18#include <linux/interrupt.h>
19#include <linux/i2c.h>
Akinobu Mita080481f52016-03-07 00:27:48 +090020#include <linux/spi/spi.h>
Roy Zangc03675f2010-08-10 18:02:20 -070021#include <linux/rtc.h>
22#include <linux/bcd.h>
Roy Zangc03675f2010-08-10 18:02:20 -070023#include <linux/slab.h>
Akinobu Mita370927c2016-03-07 00:27:47 +090024#include <linux/regmap.h>
Roy Zangc03675f2010-08-10 18:02:20 -070025
26#define DS3232_REG_SECONDS 0x00
27#define DS3232_REG_MINUTES 0x01
28#define DS3232_REG_HOURS 0x02
29#define DS3232_REG_AMPM 0x02
30#define DS3232_REG_DAY 0x03
31#define DS3232_REG_DATE 0x04
32#define DS3232_REG_MONTH 0x05
33#define DS3232_REG_CENTURY 0x05
34#define DS3232_REG_YEAR 0x06
35#define DS3232_REG_ALARM1 0x07 /* Alarm 1 BASE */
36#define DS3232_REG_ALARM2 0x0B /* Alarm 2 BASE */
37#define DS3232_REG_CR 0x0E /* Control register */
38# define DS3232_REG_CR_nEOSC 0x80
39# define DS3232_REG_CR_INTCN 0x04
40# define DS3232_REG_CR_A2IE 0x02
41# define DS3232_REG_CR_A1IE 0x01
42
43#define DS3232_REG_SR 0x0F /* control/status register */
44# define DS3232_REG_SR_OSF 0x80
45# define DS3232_REG_SR_BSY 0x04
46# define DS3232_REG_SR_A2F 0x02
47# define DS3232_REG_SR_A1F 0x01
48
49struct ds3232 {
Akinobu Mita370927c2016-03-07 00:27:47 +090050 struct device *dev;
51 struct regmap *regmap;
52 int irq;
Roy Zangc03675f2010-08-10 18:02:20 -070053 struct rtc_device *rtc;
Roy Zangc03675f2010-08-10 18:02:20 -070054
55 /* The mutex protects alarm operations, and prevents a race
56 * between the enable_irq() in the workqueue and the free_irq()
57 * in the remove function.
58 */
59 struct mutex mutex;
Wang Dongshengc93a3ae22014-04-03 14:50:08 -070060 bool suspended;
Roy Zangc03675f2010-08-10 18:02:20 -070061};
62
Akinobu Mita370927c2016-03-07 00:27:47 +090063static int ds3232_check_rtc_status(struct device *dev)
Roy Zangc03675f2010-08-10 18:02:20 -070064{
Akinobu Mita370927c2016-03-07 00:27:47 +090065 struct ds3232 *ds3232 = dev_get_drvdata(dev);
Roy Zangc03675f2010-08-10 18:02:20 -070066 int ret = 0;
67 int control, stat;
68
Akinobu Mita370927c2016-03-07 00:27:47 +090069 ret = regmap_read(ds3232->regmap, DS3232_REG_SR, &stat);
70 if (ret)
71 return ret;
Roy Zangc03675f2010-08-10 18:02:20 -070072
73 if (stat & DS3232_REG_SR_OSF)
Akinobu Mita370927c2016-03-07 00:27:47 +090074 dev_warn(dev,
Roy Zangc03675f2010-08-10 18:02:20 -070075 "oscillator discontinuity flagged, "
76 "time unreliable\n");
77
78 stat &= ~(DS3232_REG_SR_OSF | DS3232_REG_SR_A1F | DS3232_REG_SR_A2F);
79
Akinobu Mita370927c2016-03-07 00:27:47 +090080 ret = regmap_write(ds3232->regmap, DS3232_REG_SR, stat);
81 if (ret)
Roy Zangc03675f2010-08-10 18:02:20 -070082 return ret;
83
84 /* If the alarm is pending, clear it before requesting
85 * the interrupt, so an interrupt event isn't reported
86 * before everything is initialized.
87 */
88
Akinobu Mita370927c2016-03-07 00:27:47 +090089 ret = regmap_read(ds3232->regmap, DS3232_REG_CR, &control);
90 if (ret)
91 return ret;
Roy Zangc03675f2010-08-10 18:02:20 -070092
93 control &= ~(DS3232_REG_CR_A1IE | DS3232_REG_CR_A2IE);
94 control |= DS3232_REG_CR_INTCN;
95
Akinobu Mita370927c2016-03-07 00:27:47 +090096 return regmap_write(ds3232->regmap, DS3232_REG_CR, control);
Roy Zangc03675f2010-08-10 18:02:20 -070097}
98
99static int ds3232_read_time(struct device *dev, struct rtc_time *time)
100{
Akinobu Mita370927c2016-03-07 00:27:47 +0900101 struct ds3232 *ds3232 = dev_get_drvdata(dev);
Roy Zangc03675f2010-08-10 18:02:20 -0700102 int ret;
103 u8 buf[7];
104 unsigned int year, month, day, hour, minute, second;
105 unsigned int week, twelve_hr, am_pm;
106 unsigned int century, add_century = 0;
107
Akinobu Mita370927c2016-03-07 00:27:47 +0900108 ret = regmap_bulk_read(ds3232->regmap, DS3232_REG_SECONDS, buf, 7);
109 if (ret)
Roy Zangc03675f2010-08-10 18:02:20 -0700110 return ret;
Roy Zangc03675f2010-08-10 18:02:20 -0700111
112 second = buf[0];
113 minute = buf[1];
114 hour = buf[2];
115 week = buf[3];
116 day = buf[4];
117 month = buf[5];
118 year = buf[6];
119
120 /* Extract additional information for AM/PM and century */
121
122 twelve_hr = hour & 0x40;
123 am_pm = hour & 0x20;
124 century = month & 0x80;
125
126 /* Write to rtc_time structure */
127
128 time->tm_sec = bcd2bin(second);
129 time->tm_min = bcd2bin(minute);
130 if (twelve_hr) {
131 /* Convert to 24 hr */
132 if (am_pm)
133 time->tm_hour = bcd2bin(hour & 0x1F) + 12;
134 else
135 time->tm_hour = bcd2bin(hour & 0x1F);
136 } else {
137 time->tm_hour = bcd2bin(hour);
138 }
139
Lei Xua2d6d2f2011-02-25 14:44:23 -0800140 /* Day of the week in linux range is 0~6 while 1~7 in RTC chip */
141 time->tm_wday = bcd2bin(week) - 1;
Roy Zangc03675f2010-08-10 18:02:20 -0700142 time->tm_mday = bcd2bin(day);
Lei Xua2d6d2f2011-02-25 14:44:23 -0800143 /* linux tm_mon range:0~11, while month range is 1~12 in RTC chip */
144 time->tm_mon = bcd2bin(month & 0x7F) - 1;
Roy Zangc03675f2010-08-10 18:02:20 -0700145 if (century)
146 add_century = 100;
147
148 time->tm_year = bcd2bin(year) + add_century;
149
150 return rtc_valid_tm(time);
151}
152
153static int ds3232_set_time(struct device *dev, struct rtc_time *time)
154{
Akinobu Mita370927c2016-03-07 00:27:47 +0900155 struct ds3232 *ds3232 = dev_get_drvdata(dev);
Roy Zangc03675f2010-08-10 18:02:20 -0700156 u8 buf[7];
157
158 /* Extract time from rtc_time and load into ds3232*/
159
160 buf[0] = bin2bcd(time->tm_sec);
161 buf[1] = bin2bcd(time->tm_min);
162 buf[2] = bin2bcd(time->tm_hour);
Lei Xua2d6d2f2011-02-25 14:44:23 -0800163 /* Day of the week in linux range is 0~6 while 1~7 in RTC chip */
164 buf[3] = bin2bcd(time->tm_wday + 1);
Roy Zangc03675f2010-08-10 18:02:20 -0700165 buf[4] = bin2bcd(time->tm_mday); /* Date */
Lei Xua2d6d2f2011-02-25 14:44:23 -0800166 /* linux tm_mon range:0~11, while month range is 1~12 in RTC chip */
167 buf[5] = bin2bcd(time->tm_mon + 1);
Roy Zangc03675f2010-08-10 18:02:20 -0700168 if (time->tm_year >= 100) {
169 buf[5] |= 0x80;
170 buf[6] = bin2bcd(time->tm_year - 100);
171 } else {
172 buf[6] = bin2bcd(time->tm_year);
173 }
174
Akinobu Mita370927c2016-03-07 00:27:47 +0900175 return regmap_bulk_write(ds3232->regmap, DS3232_REG_SECONDS, buf, 7);
Roy Zangc03675f2010-08-10 18:02:20 -0700176}
177
Lan Chunhe-B25806f46418c2010-10-27 15:33:12 -0700178/*
179 * DS3232 has two alarm, we only use alarm1
180 * According to linux specification, only support one-shot alarm
181 * no periodic alarm mode
182 */
183static int ds3232_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
184{
Akinobu Mita370927c2016-03-07 00:27:47 +0900185 struct ds3232 *ds3232 = dev_get_drvdata(dev);
Lan Chunhe-B25806f46418c2010-10-27 15:33:12 -0700186 int control, stat;
187 int ret;
188 u8 buf[4];
189
190 mutex_lock(&ds3232->mutex);
191
Akinobu Mita370927c2016-03-07 00:27:47 +0900192 ret = regmap_read(ds3232->regmap, DS3232_REG_SR, &stat);
193 if (ret)
Lan Chunhe-B25806f46418c2010-10-27 15:33:12 -0700194 goto out;
Akinobu Mita370927c2016-03-07 00:27:47 +0900195 ret = regmap_read(ds3232->regmap, DS3232_REG_CR, &control);
196 if (ret)
Lan Chunhe-B25806f46418c2010-10-27 15:33:12 -0700197 goto out;
Akinobu Mita370927c2016-03-07 00:27:47 +0900198 ret = regmap_bulk_read(ds3232->regmap, DS3232_REG_ALARM1, buf, 4);
199 if (ret)
Lan Chunhe-B25806f46418c2010-10-27 15:33:12 -0700200 goto out;
201
202 alarm->time.tm_sec = bcd2bin(buf[0] & 0x7F);
203 alarm->time.tm_min = bcd2bin(buf[1] & 0x7F);
204 alarm->time.tm_hour = bcd2bin(buf[2] & 0x7F);
205 alarm->time.tm_mday = bcd2bin(buf[3] & 0x7F);
206
207 alarm->time.tm_mon = -1;
208 alarm->time.tm_year = -1;
209 alarm->time.tm_wday = -1;
210 alarm->time.tm_yday = -1;
211 alarm->time.tm_isdst = -1;
212
213 alarm->enabled = !!(control & DS3232_REG_CR_A1IE);
214 alarm->pending = !!(stat & DS3232_REG_SR_A1F);
215
216 ret = 0;
217out:
218 mutex_unlock(&ds3232->mutex);
219 return ret;
220}
221
222/*
223 * linux rtc-module does not support wday alarm
224 * and only 24h time mode supported indeed
225 */
226static int ds3232_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
227{
Akinobu Mita370927c2016-03-07 00:27:47 +0900228 struct ds3232 *ds3232 = dev_get_drvdata(dev);
Lan Chunhe-B25806f46418c2010-10-27 15:33:12 -0700229 int control, stat;
230 int ret;
231 u8 buf[4];
232
Akinobu Mita370927c2016-03-07 00:27:47 +0900233 if (ds3232->irq <= 0)
Lan Chunhe-B25806f46418c2010-10-27 15:33:12 -0700234 return -EINVAL;
235
236 mutex_lock(&ds3232->mutex);
237
238 buf[0] = bin2bcd(alarm->time.tm_sec);
239 buf[1] = bin2bcd(alarm->time.tm_min);
240 buf[2] = bin2bcd(alarm->time.tm_hour);
241 buf[3] = bin2bcd(alarm->time.tm_mday);
242
243 /* clear alarm interrupt enable bit */
Akinobu Mita370927c2016-03-07 00:27:47 +0900244 ret = regmap_read(ds3232->regmap, DS3232_REG_CR, &control);
245 if (ret)
Lan Chunhe-B25806f46418c2010-10-27 15:33:12 -0700246 goto out;
Lan Chunhe-B25806f46418c2010-10-27 15:33:12 -0700247 control &= ~(DS3232_REG_CR_A1IE | DS3232_REG_CR_A2IE);
Akinobu Mita370927c2016-03-07 00:27:47 +0900248 ret = regmap_write(ds3232->regmap, DS3232_REG_CR, control);
249 if (ret)
Lan Chunhe-B25806f46418c2010-10-27 15:33:12 -0700250 goto out;
251
252 /* clear any pending alarm flag */
Akinobu Mita370927c2016-03-07 00:27:47 +0900253 ret = regmap_read(ds3232->regmap, DS3232_REG_SR, &stat);
254 if (ret)
Lan Chunhe-B25806f46418c2010-10-27 15:33:12 -0700255 goto out;
Lan Chunhe-B25806f46418c2010-10-27 15:33:12 -0700256 stat &= ~(DS3232_REG_SR_A1F | DS3232_REG_SR_A2F);
Akinobu Mita370927c2016-03-07 00:27:47 +0900257 ret = regmap_write(ds3232->regmap, DS3232_REG_SR, stat);
258 if (ret)
Lan Chunhe-B25806f46418c2010-10-27 15:33:12 -0700259 goto out;
260
Akinobu Mita370927c2016-03-07 00:27:47 +0900261 ret = regmap_bulk_write(ds3232->regmap, DS3232_REG_ALARM1, buf, 4);
Akinobu Mita7b4393a2016-03-07 00:27:50 +0900262 if (ret)
263 goto out;
Lan Chunhe-B25806f46418c2010-10-27 15:33:12 -0700264
265 if (alarm->enabled) {
266 control |= DS3232_REG_CR_A1IE;
Akinobu Mita370927c2016-03-07 00:27:47 +0900267 ret = regmap_write(ds3232->regmap, DS3232_REG_CR, control);
Lan Chunhe-B25806f46418c2010-10-27 15:33:12 -0700268 }
269out:
270 mutex_unlock(&ds3232->mutex);
271 return ret;
272}
273
Akinobu Mita7b4393a2016-03-07 00:27:50 +0900274static int ds3232_update_alarm(struct device *dev, unsigned int enabled)
Lan Chunhe-B25806f46418c2010-10-27 15:33:12 -0700275{
Akinobu Mita370927c2016-03-07 00:27:47 +0900276 struct ds3232 *ds3232 = dev_get_drvdata(dev);
Lan Chunhe-B25806f46418c2010-10-27 15:33:12 -0700277 int control;
278 int ret;
Lan Chunhe-B25806f46418c2010-10-27 15:33:12 -0700279
280 mutex_lock(&ds3232->mutex);
281
Akinobu Mita370927c2016-03-07 00:27:47 +0900282 ret = regmap_read(ds3232->regmap, DS3232_REG_CR, &control);
283 if (ret)
Lan Chunhe-B25806f46418c2010-10-27 15:33:12 -0700284 goto unlock;
285
Akinobu Mita75222972016-03-07 00:27:51 +0900286 if (enabled)
Lan Chunhe-B25806f46418c2010-10-27 15:33:12 -0700287 /* enable alarm1 interrupt */
288 control |= DS3232_REG_CR_A1IE;
289 else
290 /* disable alarm1 interrupt */
291 control &= ~(DS3232_REG_CR_A1IE);
Akinobu Mita7b4393a2016-03-07 00:27:50 +0900292 ret = regmap_write(ds3232->regmap, DS3232_REG_CR, control);
Lan Chunhe-B25806f46418c2010-10-27 15:33:12 -0700293
294unlock:
295 mutex_unlock(&ds3232->mutex);
Akinobu Mita7b4393a2016-03-07 00:27:50 +0900296
297 return ret;
Lan Chunhe-B25806f46418c2010-10-27 15:33:12 -0700298}
299
300static int ds3232_alarm_irq_enable(struct device *dev, unsigned int enabled)
301{
Akinobu Mita370927c2016-03-07 00:27:47 +0900302 struct ds3232 *ds3232 = dev_get_drvdata(dev);
Lan Chunhe-B25806f46418c2010-10-27 15:33:12 -0700303
Akinobu Mita370927c2016-03-07 00:27:47 +0900304 if (ds3232->irq <= 0)
Lan Chunhe-B25806f46418c2010-10-27 15:33:12 -0700305 return -EINVAL;
306
Akinobu Mita7b4393a2016-03-07 00:27:50 +0900307 return ds3232_update_alarm(dev, enabled);
Lan Chunhe-B25806f46418c2010-10-27 15:33:12 -0700308}
309
Roy Zangc03675f2010-08-10 18:02:20 -0700310static irqreturn_t ds3232_irq(int irq, void *dev_id)
311{
Akinobu Mita370927c2016-03-07 00:27:47 +0900312 struct device *dev = dev_id;
313 struct ds3232 *ds3232 = dev_get_drvdata(dev);
Akinobu Mita370927c2016-03-07 00:27:47 +0900314 int ret;
Roy Zangc03675f2010-08-10 18:02:20 -0700315 int stat, control;
316
317 mutex_lock(&ds3232->mutex);
318
Akinobu Mita370927c2016-03-07 00:27:47 +0900319 ret = regmap_read(ds3232->regmap, DS3232_REG_SR, &stat);
320 if (ret)
Roy Zangc03675f2010-08-10 18:02:20 -0700321 goto unlock;
322
323 if (stat & DS3232_REG_SR_A1F) {
Akinobu Mita370927c2016-03-07 00:27:47 +0900324 ret = regmap_read(ds3232->regmap, DS3232_REG_CR, &control);
325 if (ret) {
Akinobu Mita95c60c12016-03-07 00:27:52 +0900326 dev_warn(ds3232->dev,
327 "Read Control Register error %d\n", ret);
Wang Dongshengc93a3ae22014-04-03 14:50:08 -0700328 } else {
329 /* disable alarm1 interrupt */
330 control &= ~(DS3232_REG_CR_A1IE);
Akinobu Mita7b4393a2016-03-07 00:27:50 +0900331 ret = regmap_write(ds3232->regmap, DS3232_REG_CR,
332 control);
333 if (ret) {
334 dev_warn(ds3232->dev,
335 "Write Control Register error %d\n",
336 ret);
337 goto unlock;
338 }
Roy Zangc03675f2010-08-10 18:02:20 -0700339
Wang Dongshengc93a3ae22014-04-03 14:50:08 -0700340 /* clear the alarm pend flag */
341 stat &= ~DS3232_REG_SR_A1F;
Akinobu Mita7b4393a2016-03-07 00:27:50 +0900342 ret = regmap_write(ds3232->regmap, DS3232_REG_SR, stat);
343 if (ret) {
344 dev_warn(ds3232->dev,
345 "Write Status Register error %d\n",
346 ret);
347 goto unlock;
348 }
Roy Zangc03675f2010-08-10 18:02:20 -0700349
Wang Dongshengc93a3ae22014-04-03 14:50:08 -0700350 rtc_update_irq(ds3232->rtc, 1, RTC_AF | RTC_IRQF);
Wang Dongshengc93a3ae22014-04-03 14:50:08 -0700351 }
Roy Zangc03675f2010-08-10 18:02:20 -0700352 }
353
Roy Zangc03675f2010-08-10 18:02:20 -0700354unlock:
355 mutex_unlock(&ds3232->mutex);
Akinobu Mita95c60c12016-03-07 00:27:52 +0900356
357 return IRQ_HANDLED;
Roy Zangc03675f2010-08-10 18:02:20 -0700358}
359
360static const struct rtc_class_ops ds3232_rtc_ops = {
361 .read_time = ds3232_read_time,
362 .set_time = ds3232_set_time,
Lan Chunhe-B25806f46418c2010-10-27 15:33:12 -0700363 .read_alarm = ds3232_read_alarm,
364 .set_alarm = ds3232_set_alarm,
365 .alarm_irq_enable = ds3232_alarm_irq_enable,
Roy Zangc03675f2010-08-10 18:02:20 -0700366};
367
Akinobu Mita370927c2016-03-07 00:27:47 +0900368static int ds3232_probe(struct device *dev, struct regmap *regmap, int irq,
369 const char *name)
Roy Zangc03675f2010-08-10 18:02:20 -0700370{
371 struct ds3232 *ds3232;
372 int ret;
373
Akinobu Mita370927c2016-03-07 00:27:47 +0900374 ds3232 = devm_kzalloc(dev, sizeof(*ds3232), GFP_KERNEL);
Roy Zangc03675f2010-08-10 18:02:20 -0700375 if (!ds3232)
376 return -ENOMEM;
377
Akinobu Mita370927c2016-03-07 00:27:47 +0900378 ds3232->regmap = regmap;
379 ds3232->irq = irq;
380 ds3232->dev = dev;
381 dev_set_drvdata(dev, ds3232);
Roy Zangc03675f2010-08-10 18:02:20 -0700382
Roy Zangc03675f2010-08-10 18:02:20 -0700383 mutex_init(&ds3232->mutex);
384
Akinobu Mita370927c2016-03-07 00:27:47 +0900385 ret = ds3232_check_rtc_status(dev);
Roy Zangc03675f2010-08-10 18:02:20 -0700386 if (ret)
Sachin Kamat66714612013-04-29 16:20:31 -0700387 return ret;
Roy Zangc03675f2010-08-10 18:02:20 -0700388
Akinobu Mita370927c2016-03-07 00:27:47 +0900389 if (ds3232->irq > 0) {
Akinobu Mita95c60c12016-03-07 00:27:52 +0900390 ret = devm_request_threaded_irq(dev, ds3232->irq, NULL,
391 ds3232_irq,
392 IRQF_SHARED | IRQF_ONESHOT,
393 name, dev);
Roy Zangc03675f2010-08-10 18:02:20 -0700394 if (ret) {
Akinobu Mita370927c2016-03-07 00:27:47 +0900395 ds3232->irq = 0;
396 dev_err(dev, "unable to request IRQ\n");
397 } else
398 device_init_wakeup(dev, 1);
Roy Zangc03675f2010-08-10 18:02:20 -0700399 }
Akinobu Mita370927c2016-03-07 00:27:47 +0900400 ds3232->rtc = devm_rtc_device_register(dev, name, &ds3232_rtc_ops,
401 THIS_MODULE);
402
Wang Dongshengc93a3ae22014-04-03 14:50:08 -0700403 return PTR_ERR_OR_ZERO(ds3232->rtc);
Roy Zangc03675f2010-08-10 18:02:20 -0700404}
405
Wang Dongshengc93a3ae22014-04-03 14:50:08 -0700406#ifdef CONFIG_PM_SLEEP
407static int ds3232_suspend(struct device *dev)
408{
409 struct ds3232 *ds3232 = dev_get_drvdata(dev);
Wang Dongshengc93a3ae22014-04-03 14:50:08 -0700410
Akinobu Mita95c60c12016-03-07 00:27:52 +0900411 if (device_may_wakeup(dev)) {
412 if (enable_irq_wake(ds3232->irq))
Wang Dongshengdc2280e2015-08-12 17:14:13 +0800413 dev_warn_once(dev, "Cannot set wakeup source\n");
Wang Dongshengc93a3ae22014-04-03 14:50:08 -0700414 }
415
416 return 0;
417}
418
419static int ds3232_resume(struct device *dev)
420{
421 struct ds3232 *ds3232 = dev_get_drvdata(dev);
Wang Dongshengc93a3ae22014-04-03 14:50:08 -0700422
Akinobu Mita95c60c12016-03-07 00:27:52 +0900423 if (device_may_wakeup(dev))
424 disable_irq_wake(ds3232->irq);
Wang Dongshengc93a3ae22014-04-03 14:50:08 -0700425
426 return 0;
427}
428#endif
429
430static const struct dev_pm_ops ds3232_pm_ops = {
431 SET_SYSTEM_SLEEP_PM_OPS(ds3232_suspend, ds3232_resume)
432};
433
Akinobu Mita080481f52016-03-07 00:27:48 +0900434#if IS_ENABLED(CONFIG_I2C)
435
Akinobu Mita370927c2016-03-07 00:27:47 +0900436static int ds3232_i2c_probe(struct i2c_client *client,
437 const struct i2c_device_id *id)
438{
439 struct regmap *regmap;
440 static const struct regmap_config config = {
441 .reg_bits = 8,
442 .val_bits = 8,
443 };
444
445 regmap = devm_regmap_init_i2c(client, &config);
446 if (IS_ERR(regmap)) {
447 dev_err(&client->dev, "%s: regmap allocation failed: %ld\n",
448 __func__, PTR_ERR(regmap));
449 return PTR_ERR(regmap);
450 }
451
452 return ds3232_probe(&client->dev, regmap, client->irq, client->name);
453}
454
Roy Zangc03675f2010-08-10 18:02:20 -0700455static const struct i2c_device_id ds3232_id[] = {
456 { "ds3232", 0 },
457 { }
458};
459MODULE_DEVICE_TABLE(i2c, ds3232_id);
460
461static struct i2c_driver ds3232_driver = {
462 .driver = {
463 .name = "rtc-ds3232",
Wang Dongshengc93a3ae22014-04-03 14:50:08 -0700464 .pm = &ds3232_pm_ops,
Roy Zangc03675f2010-08-10 18:02:20 -0700465 },
Akinobu Mita370927c2016-03-07 00:27:47 +0900466 .probe = ds3232_i2c_probe,
Roy Zangc03675f2010-08-10 18:02:20 -0700467 .id_table = ds3232_id,
468};
Akinobu Mita080481f52016-03-07 00:27:48 +0900469
470static int ds3232_register_driver(void)
471{
472 return i2c_add_driver(&ds3232_driver);
473}
474
475static void ds3232_unregister_driver(void)
476{
477 i2c_del_driver(&ds3232_driver);
478}
479
480#else
481
482static int ds3232_register_driver(void)
483{
484 return 0;
485}
486
487static void ds3232_unregister_driver(void)
488{
489}
490
491#endif
492
493#if IS_ENABLED(CONFIG_SPI_MASTER)
494
495static int ds3234_probe(struct spi_device *spi)
496{
497 int res;
498 unsigned int tmp;
499 static const struct regmap_config config = {
500 .reg_bits = 8,
501 .val_bits = 8,
502 .write_flag_mask = 0x80,
503 };
504 struct regmap *regmap;
505
506 regmap = devm_regmap_init_spi(spi, &config);
507 if (IS_ERR(regmap)) {
508 dev_err(&spi->dev, "%s: regmap allocation failed: %ld\n",
509 __func__, PTR_ERR(regmap));
510 return PTR_ERR(regmap);
511 }
512
513 spi->mode = SPI_MODE_3;
514 spi->bits_per_word = 8;
515 spi_setup(spi);
516
517 res = regmap_read(regmap, DS3232_REG_SECONDS, &tmp);
518 if (res)
519 return res;
520
521 /* Control settings
522 *
523 * CONTROL_REG
524 * BIT 7 6 5 4 3 2 1 0
525 * EOSC BBSQW CONV RS2 RS1 INTCN A2IE A1IE
526 *
527 * 0 0 0 1 1 1 0 0
528 *
529 * CONTROL_STAT_REG
530 * BIT 7 6 5 4 3 2 1 0
531 * OSF BB32kHz CRATE1 CRATE0 EN32kHz BSY A2F A1F
532 *
533 * 1 0 0 0 1 0 0 0
534 */
535 res = regmap_read(regmap, DS3232_REG_CR, &tmp);
536 if (res)
537 return res;
538 res = regmap_write(regmap, DS3232_REG_CR, tmp & 0x1c);
539 if (res)
540 return res;
541
542 res = regmap_read(regmap, DS3232_REG_SR, &tmp);
543 if (res)
544 return res;
545 res = regmap_write(regmap, DS3232_REG_SR, tmp & 0x88);
546 if (res)
547 return res;
548
549 /* Print our settings */
550 res = regmap_read(regmap, DS3232_REG_CR, &tmp);
551 if (res)
552 return res;
553 dev_info(&spi->dev, "Control Reg: 0x%02x\n", tmp);
554
555 res = regmap_read(regmap, DS3232_REG_SR, &tmp);
556 if (res)
557 return res;
558 dev_info(&spi->dev, "Ctrl/Stat Reg: 0x%02x\n", tmp);
559
560 return ds3232_probe(&spi->dev, regmap, spi->irq, "ds3234");
561}
562
Akinobu Mita080481f52016-03-07 00:27:48 +0900563static struct spi_driver ds3234_driver = {
564 .driver = {
565 .name = "ds3234",
566 },
567 .probe = ds3234_probe,
Akinobu Mita080481f52016-03-07 00:27:48 +0900568};
569
570static int ds3234_register_driver(void)
571{
572 return spi_register_driver(&ds3234_driver);
573}
574
575static void ds3234_unregister_driver(void)
576{
577 spi_unregister_driver(&ds3234_driver);
578}
579
580#else
581
582static int ds3234_register_driver(void)
583{
584 return 0;
585}
586
587static void ds3234_unregister_driver(void)
588{
589}
590
591#endif
592
593static int __init ds323x_init(void)
594{
595 int ret;
596
597 ret = ds3232_register_driver();
598 if (ret) {
599 pr_err("Failed to register ds3232 driver: %d\n", ret);
600 return ret;
601 }
602
603 ret = ds3234_register_driver();
604 if (ret) {
605 pr_err("Failed to register ds3234 driver: %d\n", ret);
606 ds3232_unregister_driver();
607 }
608
609 return ret;
610}
611module_init(ds323x_init)
612
613static void __exit ds323x_exit(void)
614{
615 ds3234_unregister_driver();
616 ds3232_unregister_driver();
617}
618module_exit(ds323x_exit)
Roy Zangc03675f2010-08-10 18:02:20 -0700619
620MODULE_AUTHOR("Srikanth Srinivasan <srikanth.srinivasan@freescale.com>");
Akinobu Mita080481f52016-03-07 00:27:48 +0900621MODULE_AUTHOR("Dennis Aberilla <denzzzhome@yahoo.com>");
622MODULE_DESCRIPTION("Maxim/Dallas DS3232/DS3234 RTC Driver");
Roy Zangc03675f2010-08-10 18:02:20 -0700623MODULE_LICENSE("GPL");
Akinobu Mita080481f52016-03-07 00:27:48 +0900624MODULE_ALIAS("spi:ds3234");