2 * RTC client/driver for the Maxim/Dallas DS3232 Real-Time Clock over I2C
4 * Copyright (C) 2009-2011 Freescale Semiconductor.
5 * Author: Jack Lan <jack.lan@freescale.com>
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
13 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
15 #include <linux/kernel.h>
16 #include <linux/module.h>
17 #include <linux/interrupt.h>
18 #include <linux/i2c.h>
19 #include <linux/rtc.h>
20 #include <linux/bcd.h>
21 #include <linux/workqueue.h>
22 #include <linux/slab.h>
23 #include <linux/regmap.h>
25 #define DS3232_REG_SECONDS 0x00
26 #define DS3232_REG_MINUTES 0x01
27 #define DS3232_REG_HOURS 0x02
28 #define DS3232_REG_AMPM 0x02
29 #define DS3232_REG_DAY 0x03
30 #define DS3232_REG_DATE 0x04
31 #define DS3232_REG_MONTH 0x05
32 #define DS3232_REG_CENTURY 0x05
33 #define DS3232_REG_YEAR 0x06
34 #define DS3232_REG_ALARM1 0x07 /* Alarm 1 BASE */
35 #define DS3232_REG_ALARM2 0x0B /* Alarm 2 BASE */
36 #define DS3232_REG_CR 0x0E /* Control register */
37 # define DS3232_REG_CR_nEOSC 0x80
38 # define DS3232_REG_CR_INTCN 0x04
39 # define DS3232_REG_CR_A2IE 0x02
40 # define DS3232_REG_CR_A1IE 0x01
42 #define DS3232_REG_SR 0x0F /* control/status register */
43 # define DS3232_REG_SR_OSF 0x80
44 # define DS3232_REG_SR_BSY 0x04
45 # define DS3232_REG_SR_A2F 0x02
46 # define DS3232_REG_SR_A1F 0x01
50 struct regmap
*regmap
;
52 struct rtc_device
*rtc
;
53 struct work_struct work
;
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.
64 static int ds3232_check_rtc_status(struct device
*dev
)
66 struct ds3232
*ds3232
= dev_get_drvdata(dev
);
70 ret
= regmap_read(ds3232
->regmap
, DS3232_REG_SR
, &stat
);
74 if (stat
& DS3232_REG_SR_OSF
)
76 "oscillator discontinuity flagged, "
79 stat
&= ~(DS3232_REG_SR_OSF
| DS3232_REG_SR_A1F
| DS3232_REG_SR_A2F
);
81 ret
= regmap_write(ds3232
->regmap
, DS3232_REG_SR
, stat
);
85 /* If the alarm is pending, clear it before requesting
86 * the interrupt, so an interrupt event isn't reported
87 * before everything is initialized.
90 ret
= regmap_read(ds3232
->regmap
, DS3232_REG_CR
, &control
);
94 control
&= ~(DS3232_REG_CR_A1IE
| DS3232_REG_CR_A2IE
);
95 control
|= DS3232_REG_CR_INTCN
;
97 return regmap_write(ds3232
->regmap
, DS3232_REG_CR
, control
);
100 static int ds3232_read_time(struct device
*dev
, struct rtc_time
*time
)
102 struct ds3232
*ds3232
= dev_get_drvdata(dev
);
105 unsigned int year
, month
, day
, hour
, minute
, second
;
106 unsigned int week
, twelve_hr
, am_pm
;
107 unsigned int century
, add_century
= 0;
109 ret
= regmap_bulk_read(ds3232
->regmap
, DS3232_REG_SECONDS
, buf
, 7);
121 /* Extract additional information for AM/PM and century */
123 twelve_hr
= hour
& 0x40;
125 century
= month
& 0x80;
127 /* Write to rtc_time structure */
129 time
->tm_sec
= bcd2bin(second
);
130 time
->tm_min
= bcd2bin(minute
);
132 /* Convert to 24 hr */
134 time
->tm_hour
= bcd2bin(hour
& 0x1F) + 12;
136 time
->tm_hour
= bcd2bin(hour
& 0x1F);
138 time
->tm_hour
= bcd2bin(hour
);
141 /* Day of the week in linux range is 0~6 while 1~7 in RTC chip */
142 time
->tm_wday
= bcd2bin(week
) - 1;
143 time
->tm_mday
= bcd2bin(day
);
144 /* linux tm_mon range:0~11, while month range is 1~12 in RTC chip */
145 time
->tm_mon
= bcd2bin(month
& 0x7F) - 1;
149 time
->tm_year
= bcd2bin(year
) + add_century
;
151 return rtc_valid_tm(time
);
154 static int ds3232_set_time(struct device
*dev
, struct rtc_time
*time
)
156 struct ds3232
*ds3232
= dev_get_drvdata(dev
);
159 /* Extract time from rtc_time and load into ds3232*/
161 buf
[0] = bin2bcd(time
->tm_sec
);
162 buf
[1] = bin2bcd(time
->tm_min
);
163 buf
[2] = bin2bcd(time
->tm_hour
);
164 /* Day of the week in linux range is 0~6 while 1~7 in RTC chip */
165 buf
[3] = bin2bcd(time
->tm_wday
+ 1);
166 buf
[4] = bin2bcd(time
->tm_mday
); /* Date */
167 /* linux tm_mon range:0~11, while month range is 1~12 in RTC chip */
168 buf
[5] = bin2bcd(time
->tm_mon
+ 1);
169 if (time
->tm_year
>= 100) {
171 buf
[6] = bin2bcd(time
->tm_year
- 100);
173 buf
[6] = bin2bcd(time
->tm_year
);
176 return regmap_bulk_write(ds3232
->regmap
, DS3232_REG_SECONDS
, buf
, 7);
180 * DS3232 has two alarm, we only use alarm1
181 * According to linux specification, only support one-shot alarm
182 * no periodic alarm mode
184 static int ds3232_read_alarm(struct device
*dev
, struct rtc_wkalrm
*alarm
)
186 struct ds3232
*ds3232
= dev_get_drvdata(dev
);
191 mutex_lock(&ds3232
->mutex
);
193 ret
= regmap_read(ds3232
->regmap
, DS3232_REG_SR
, &stat
);
196 ret
= regmap_read(ds3232
->regmap
, DS3232_REG_CR
, &control
);
199 ret
= regmap_bulk_read(ds3232
->regmap
, DS3232_REG_ALARM1
, buf
, 4);
203 alarm
->time
.tm_sec
= bcd2bin(buf
[0] & 0x7F);
204 alarm
->time
.tm_min
= bcd2bin(buf
[1] & 0x7F);
205 alarm
->time
.tm_hour
= bcd2bin(buf
[2] & 0x7F);
206 alarm
->time
.tm_mday
= bcd2bin(buf
[3] & 0x7F);
208 alarm
->time
.tm_mon
= -1;
209 alarm
->time
.tm_year
= -1;
210 alarm
->time
.tm_wday
= -1;
211 alarm
->time
.tm_yday
= -1;
212 alarm
->time
.tm_isdst
= -1;
214 alarm
->enabled
= !!(control
& DS3232_REG_CR_A1IE
);
215 alarm
->pending
= !!(stat
& DS3232_REG_SR_A1F
);
219 mutex_unlock(&ds3232
->mutex
);
224 * linux rtc-module does not support wday alarm
225 * and only 24h time mode supported indeed
227 static int ds3232_set_alarm(struct device
*dev
, struct rtc_wkalrm
*alarm
)
229 struct ds3232
*ds3232
= dev_get_drvdata(dev
);
234 if (ds3232
->irq
<= 0)
237 mutex_lock(&ds3232
->mutex
);
239 buf
[0] = bin2bcd(alarm
->time
.tm_sec
);
240 buf
[1] = bin2bcd(alarm
->time
.tm_min
);
241 buf
[2] = bin2bcd(alarm
->time
.tm_hour
);
242 buf
[3] = bin2bcd(alarm
->time
.tm_mday
);
244 /* clear alarm interrupt enable bit */
245 ret
= regmap_read(ds3232
->regmap
, DS3232_REG_CR
, &control
);
248 control
&= ~(DS3232_REG_CR_A1IE
| DS3232_REG_CR_A2IE
);
249 ret
= regmap_write(ds3232
->regmap
, DS3232_REG_CR
, control
);
253 /* clear any pending alarm flag */
254 ret
= regmap_read(ds3232
->regmap
, DS3232_REG_SR
, &stat
);
257 stat
&= ~(DS3232_REG_SR_A1F
| DS3232_REG_SR_A2F
);
258 ret
= regmap_write(ds3232
->regmap
, DS3232_REG_SR
, stat
);
262 ret
= regmap_bulk_write(ds3232
->regmap
, DS3232_REG_ALARM1
, buf
, 4);
264 if (alarm
->enabled
) {
265 control
|= DS3232_REG_CR_A1IE
;
266 ret
= regmap_write(ds3232
->regmap
, DS3232_REG_CR
, control
);
269 mutex_unlock(&ds3232
->mutex
);
273 static void ds3232_update_alarm(struct device
*dev
)
275 struct ds3232
*ds3232
= dev_get_drvdata(dev
);
280 mutex_lock(&ds3232
->mutex
);
282 ret
= regmap_bulk_read(ds3232
->regmap
, DS3232_REG_ALARM1
, buf
, 4);
286 buf
[0] = bcd2bin(buf
[0]) < 0 || (ds3232
->rtc
->irq_data
& RTC_UF
) ?
288 buf
[1] = bcd2bin(buf
[1]) < 0 || (ds3232
->rtc
->irq_data
& RTC_UF
) ?
290 buf
[2] = bcd2bin(buf
[2]) < 0 || (ds3232
->rtc
->irq_data
& RTC_UF
) ?
292 buf
[3] = bcd2bin(buf
[3]) < 0 || (ds3232
->rtc
->irq_data
& RTC_UF
) ?
295 ret
= regmap_bulk_write(ds3232
->regmap
, DS3232_REG_ALARM1
, buf
, 4);
299 ret
= regmap_read(ds3232
->regmap
, DS3232_REG_CR
, &control
);
303 if (ds3232
->rtc
->irq_data
& (RTC_AF
| RTC_UF
))
304 /* enable alarm1 interrupt */
305 control
|= DS3232_REG_CR_A1IE
;
307 /* disable alarm1 interrupt */
308 control
&= ~(DS3232_REG_CR_A1IE
);
309 regmap_write(ds3232
->regmap
, DS3232_REG_CR
, control
);
312 mutex_unlock(&ds3232
->mutex
);
315 static int ds3232_alarm_irq_enable(struct device
*dev
, unsigned int enabled
)
317 struct ds3232
*ds3232
= dev_get_drvdata(dev
);
319 if (ds3232
->irq
<= 0)
323 ds3232
->rtc
->irq_data
|= RTC_AF
;
325 ds3232
->rtc
->irq_data
&= ~RTC_AF
;
327 ds3232_update_alarm(dev
);
331 static irqreturn_t
ds3232_irq(int irq
, void *dev_id
)
333 struct device
*dev
= dev_id
;
334 struct ds3232
*ds3232
= dev_get_drvdata(dev
);
336 disable_irq_nosync(irq
);
339 * If rtc as a wakeup source, can't schedule the work
340 * at system resume flow, because at this time the i2c bus
341 * has not been resumed.
343 if (!ds3232
->suspended
)
344 schedule_work(&ds3232
->work
);
349 static void ds3232_work(struct work_struct
*work
)
351 struct ds3232
*ds3232
= container_of(work
, struct ds3232
, work
);
355 mutex_lock(&ds3232
->mutex
);
357 ret
= regmap_read(ds3232
->regmap
, DS3232_REG_SR
, &stat
);
361 if (stat
& DS3232_REG_SR_A1F
) {
362 ret
= regmap_read(ds3232
->regmap
, DS3232_REG_CR
, &control
);
364 pr_warn("Read Control Register error - Disable IRQ%d\n",
367 /* disable alarm1 interrupt */
368 control
&= ~(DS3232_REG_CR_A1IE
);
369 regmap_write(ds3232
->regmap
, DS3232_REG_CR
, control
);
371 /* clear the alarm pend flag */
372 stat
&= ~DS3232_REG_SR_A1F
;
373 regmap_write(ds3232
->regmap
, DS3232_REG_SR
, stat
);
375 rtc_update_irq(ds3232
->rtc
, 1, RTC_AF
| RTC_IRQF
);
377 if (!ds3232
->exiting
)
378 enable_irq(ds3232
->irq
);
383 mutex_unlock(&ds3232
->mutex
);
386 static const struct rtc_class_ops ds3232_rtc_ops
= {
387 .read_time
= ds3232_read_time
,
388 .set_time
= ds3232_set_time
,
389 .read_alarm
= ds3232_read_alarm
,
390 .set_alarm
= ds3232_set_alarm
,
391 .alarm_irq_enable
= ds3232_alarm_irq_enable
,
394 static int ds3232_probe(struct device
*dev
, struct regmap
*regmap
, int irq
,
397 struct ds3232
*ds3232
;
400 ds3232
= devm_kzalloc(dev
, sizeof(*ds3232
), GFP_KERNEL
);
404 ds3232
->regmap
= regmap
;
407 dev_set_drvdata(dev
, ds3232
);
409 INIT_WORK(&ds3232
->work
, ds3232_work
);
410 mutex_init(&ds3232
->mutex
);
412 ret
= ds3232_check_rtc_status(dev
);
416 if (ds3232
->irq
> 0) {
417 ret
= devm_request_irq(dev
, ds3232
->irq
, ds3232_irq
,
418 IRQF_SHARED
, name
, dev
);
421 dev_err(dev
, "unable to request IRQ\n");
423 device_init_wakeup(dev
, 1);
425 ds3232
->rtc
= devm_rtc_device_register(dev
, name
, &ds3232_rtc_ops
,
428 return PTR_ERR_OR_ZERO(ds3232
->rtc
);
431 static int ds3232_remove(struct device
*dev
)
433 struct ds3232
*ds3232
= dev_get_drvdata(dev
);
435 if (ds3232
->irq
> 0) {
436 mutex_lock(&ds3232
->mutex
);
438 mutex_unlock(&ds3232
->mutex
);
440 devm_free_irq(dev
, ds3232
->irq
, dev
);
441 cancel_work_sync(&ds3232
->work
);
447 #ifdef CONFIG_PM_SLEEP
448 static int ds3232_suspend(struct device
*dev
)
450 struct ds3232
*ds3232
= dev_get_drvdata(dev
);
452 if (device_can_wakeup(dev
)) {
453 ds3232
->suspended
= true;
454 if (irq_set_irq_wake(ds3232
->irq
, 1)) {
455 dev_warn_once(dev
, "Cannot set wakeup source\n");
456 ds3232
->suspended
= false;
463 static int ds3232_resume(struct device
*dev
)
465 struct ds3232
*ds3232
= dev_get_drvdata(dev
);
467 if (ds3232
->suspended
) {
468 ds3232
->suspended
= false;
470 /* Clear the hardware alarm pend flag */
471 schedule_work(&ds3232
->work
);
473 irq_set_irq_wake(ds3232
->irq
, 0);
480 static const struct dev_pm_ops ds3232_pm_ops
= {
481 SET_SYSTEM_SLEEP_PM_OPS(ds3232_suspend
, ds3232_resume
)
484 static int ds3232_i2c_probe(struct i2c_client
*client
,
485 const struct i2c_device_id
*id
)
487 struct regmap
*regmap
;
488 static const struct regmap_config config
= {
493 regmap
= devm_regmap_init_i2c(client
, &config
);
494 if (IS_ERR(regmap
)) {
495 dev_err(&client
->dev
, "%s: regmap allocation failed: %ld\n",
496 __func__
, PTR_ERR(regmap
));
497 return PTR_ERR(regmap
);
500 return ds3232_probe(&client
->dev
, regmap
, client
->irq
, client
->name
);
503 static int ds3232_i2c_remove(struct i2c_client
*client
)
505 return ds3232_remove(&client
->dev
);
508 static const struct i2c_device_id ds3232_id
[] = {
512 MODULE_DEVICE_TABLE(i2c
, ds3232_id
);
514 static struct i2c_driver ds3232_driver
= {
516 .name
= "rtc-ds3232",
517 .pm
= &ds3232_pm_ops
,
519 .probe
= ds3232_i2c_probe
,
520 .remove
= ds3232_i2c_remove
,
521 .id_table
= ds3232_id
,
523 module_i2c_driver(ds3232_driver
);
525 MODULE_AUTHOR("Srikanth Srinivasan <srikanth.srinivasan@freescale.com>");
526 MODULE_DESCRIPTION("Maxim/Dallas DS3232 RTC Driver");
527 MODULE_LICENSE("GPL");