2 * Copyright (c) 2013 Samsung Electronics Co., Ltd
3 * http://www.samsung.com
5 * Copyright (C) 2013 Google, Inc
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
18 #include <linux/module.h>
19 #include <linux/i2c.h>
20 #include <linux/slab.h>
21 #include <linux/bcd.h>
22 #include <linux/bitops.h>
23 #include <linux/regmap.h>
24 #include <linux/rtc.h>
25 #include <linux/delay.h>
26 #include <linux/platform_device.h>
27 #include <linux/mfd/samsung/core.h>
28 #include <linux/mfd/samsung/irq.h>
29 #include <linux/mfd/samsung/rtc.h>
33 struct sec_pmic_dev
*s5m87xx
;
35 struct rtc_device
*rtc_dev
;
42 static void s5m8767_data_to_tm(u8
*data
, struct rtc_time
*tm
,
45 tm
->tm_sec
= data
[RTC_SEC
] & 0x7f;
46 tm
->tm_min
= data
[RTC_MIN
] & 0x7f;
48 tm
->tm_hour
= data
[RTC_HOUR
] & 0x1f;
50 tm
->tm_hour
= data
[RTC_HOUR
] & 0x0f;
51 if (data
[RTC_HOUR
] & HOUR_PM_MASK
)
55 tm
->tm_wday
= ffs(data
[RTC_WEEKDAY
] & 0x7f);
56 tm
->tm_mday
= data
[RTC_DATE
] & 0x1f;
57 tm
->tm_mon
= (data
[RTC_MONTH
] & 0x0f) - 1;
58 tm
->tm_year
= (data
[RTC_YEAR1
] & 0x7f) + 100;
63 static int s5m8767_tm_to_data(struct rtc_time
*tm
, u8
*data
)
65 data
[RTC_SEC
] = tm
->tm_sec
;
66 data
[RTC_MIN
] = tm
->tm_min
;
68 if (tm
->tm_hour
>= 12)
69 data
[RTC_HOUR
] = tm
->tm_hour
| HOUR_PM_MASK
;
71 data
[RTC_HOUR
] = tm
->tm_hour
& ~HOUR_PM_MASK
;
73 data
[RTC_WEEKDAY
] = 1 << tm
->tm_wday
;
74 data
[RTC_DATE
] = tm
->tm_mday
;
75 data
[RTC_MONTH
] = tm
->tm_mon
+ 1;
76 data
[RTC_YEAR1
] = tm
->tm_year
> 100 ? (tm
->tm_year
- 100) : 0;
78 if (tm
->tm_year
< 100) {
79 pr_err("s5m8767 RTC cannot handle the year %d.\n",
87 static inline int s5m8767_rtc_set_time_reg(struct s5m_rtc_info
*info
)
92 ret
= regmap_read(info
->rtc
, SEC_RTC_UDR_CON
, &data
);
94 dev_err(info
->dev
, "failed to read update reg(%d)\n", ret
);
98 data
|= RTC_TIME_EN_MASK
;
101 ret
= regmap_write(info
->rtc
, SEC_RTC_UDR_CON
, data
);
103 dev_err(info
->dev
, "failed to write update reg(%d)\n", ret
);
108 ret
= regmap_read(info
->rtc
, SEC_RTC_UDR_CON
, &data
);
109 } while ((data
& RTC_UDR_MASK
) && !ret
);
114 static inline int s5m8767_rtc_set_alarm_reg(struct s5m_rtc_info
*info
)
119 ret
= regmap_read(info
->rtc
, SEC_RTC_UDR_CON
, &data
);
121 dev_err(info
->dev
, "%s: fail to read update reg(%d)\n",
126 data
&= ~RTC_TIME_EN_MASK
;
127 data
|= RTC_UDR_MASK
;
129 ret
= regmap_write(info
->rtc
, SEC_RTC_UDR_CON
, data
);
131 dev_err(info
->dev
, "%s: fail to write update reg(%d)\n",
137 ret
= regmap_read(info
->rtc
, SEC_RTC_UDR_CON
, &data
);
138 } while ((data
& RTC_UDR_MASK
) && !ret
);
143 static void s5m8763_data_to_tm(u8
*data
, struct rtc_time
*tm
)
145 tm
->tm_sec
= bcd2bin(data
[RTC_SEC
]);
146 tm
->tm_min
= bcd2bin(data
[RTC_MIN
]);
148 if (data
[RTC_HOUR
] & HOUR_12
) {
149 tm
->tm_hour
= bcd2bin(data
[RTC_HOUR
] & 0x1f);
150 if (data
[RTC_HOUR
] & HOUR_PM
)
153 tm
->tm_hour
= bcd2bin(data
[RTC_HOUR
] & 0x3f);
156 tm
->tm_wday
= data
[RTC_WEEKDAY
] & 0x07;
157 tm
->tm_mday
= bcd2bin(data
[RTC_DATE
]);
158 tm
->tm_mon
= bcd2bin(data
[RTC_MONTH
]);
159 tm
->tm_year
= bcd2bin(data
[RTC_YEAR1
]) + bcd2bin(data
[RTC_YEAR2
]) * 100;
163 static void s5m8763_tm_to_data(struct rtc_time
*tm
, u8
*data
)
165 data
[RTC_SEC
] = bin2bcd(tm
->tm_sec
);
166 data
[RTC_MIN
] = bin2bcd(tm
->tm_min
);
167 data
[RTC_HOUR
] = bin2bcd(tm
->tm_hour
);
168 data
[RTC_WEEKDAY
] = tm
->tm_wday
;
169 data
[RTC_DATE
] = bin2bcd(tm
->tm_mday
);
170 data
[RTC_MONTH
] = bin2bcd(tm
->tm_mon
);
171 data
[RTC_YEAR1
] = bin2bcd(tm
->tm_year
% 100);
172 data
[RTC_YEAR2
] = bin2bcd((tm
->tm_year
+ 1900) / 100);
175 static int s5m_rtc_read_time(struct device
*dev
, struct rtc_time
*tm
)
177 struct s5m_rtc_info
*info
= dev_get_drvdata(dev
);
181 ret
= regmap_bulk_read(info
->rtc
, SEC_RTC_SEC
, data
, 8);
185 switch (info
->device_type
) {
187 s5m8763_data_to_tm(data
, tm
);
191 s5m8767_data_to_tm(data
, tm
, info
->rtc_24hr_mode
);
198 dev_dbg(dev
, "%s: %d/%d/%d %d:%d:%d(%d)\n", __func__
,
199 1900 + tm
->tm_year
, 1 + tm
->tm_mon
, tm
->tm_mday
,
200 tm
->tm_hour
, tm
->tm_min
, tm
->tm_sec
, tm
->tm_wday
);
202 return rtc_valid_tm(tm
);
205 static int s5m_rtc_set_time(struct device
*dev
, struct rtc_time
*tm
)
207 struct s5m_rtc_info
*info
= dev_get_drvdata(dev
);
211 switch (info
->device_type
) {
213 s5m8763_tm_to_data(tm
, data
);
216 ret
= s5m8767_tm_to_data(tm
, data
);
225 dev_dbg(dev
, "%s: %d/%d/%d %d:%d:%d(%d)\n", __func__
,
226 1900 + tm
->tm_year
, 1 + tm
->tm_mon
, tm
->tm_mday
,
227 tm
->tm_hour
, tm
->tm_min
, tm
->tm_sec
, tm
->tm_wday
);
229 ret
= regmap_raw_write(info
->rtc
, SEC_RTC_SEC
, data
, 8);
233 ret
= s5m8767_rtc_set_time_reg(info
);
238 static int s5m_rtc_read_alarm(struct device
*dev
, struct rtc_wkalrm
*alrm
)
240 struct s5m_rtc_info
*info
= dev_get_drvdata(dev
);
245 ret
= regmap_bulk_read(info
->rtc
, SEC_ALARM0_SEC
, data
, 8);
249 switch (info
->device_type
) {
251 s5m8763_data_to_tm(data
, &alrm
->time
);
252 ret
= regmap_read(info
->rtc
, SEC_ALARM0_CONF
, &val
);
256 alrm
->enabled
= !!val
;
258 ret
= regmap_read(info
->rtc
, SEC_RTC_STATUS
, &val
);
265 s5m8767_data_to_tm(data
, &alrm
->time
, info
->rtc_24hr_mode
);
266 dev_dbg(dev
, "%s: %d/%d/%d %d:%d:%d(%d)\n", __func__
,
267 1900 + alrm
->time
.tm_year
, 1 + alrm
->time
.tm_mon
,
268 alrm
->time
.tm_mday
, alrm
->time
.tm_hour
,
269 alrm
->time
.tm_min
, alrm
->time
.tm_sec
,
273 for (i
= 0; i
< 7; i
++) {
274 if (data
[i
] & ALARM_ENABLE_MASK
) {
281 ret
= regmap_read(info
->rtc
, SEC_RTC_STATUS
, &val
);
290 if (val
& ALARM0_STATUS
)
298 static int s5m_rtc_stop_alarm(struct s5m_rtc_info
*info
)
304 ret
= regmap_bulk_read(info
->rtc
, SEC_ALARM0_SEC
, data
, 8);
308 s5m8767_data_to_tm(data
, &tm
, info
->rtc_24hr_mode
);
309 dev_dbg(info
->dev
, "%s: %d/%d/%d %d:%d:%d(%d)\n", __func__
,
310 1900 + tm
.tm_year
, 1 + tm
.tm_mon
, tm
.tm_mday
,
311 tm
.tm_hour
, tm
.tm_min
, tm
.tm_sec
, tm
.tm_wday
);
313 switch (info
->device_type
) {
315 ret
= regmap_write(info
->rtc
, SEC_ALARM0_CONF
, 0);
319 for (i
= 0; i
< 7; i
++)
320 data
[i
] &= ~ALARM_ENABLE_MASK
;
322 ret
= regmap_raw_write(info
->rtc
, SEC_ALARM0_SEC
, data
, 8);
326 ret
= s5m8767_rtc_set_alarm_reg(info
);
337 static int s5m_rtc_start_alarm(struct s5m_rtc_info
*info
)
344 ret
= regmap_bulk_read(info
->rtc
, SEC_ALARM0_SEC
, data
, 8);
348 s5m8767_data_to_tm(data
, &tm
, info
->rtc_24hr_mode
);
349 dev_dbg(info
->dev
, "%s: %d/%d/%d %d:%d:%d(%d)\n", __func__
,
350 1900 + tm
.tm_year
, 1 + tm
.tm_mon
, tm
.tm_mday
,
351 tm
.tm_hour
, tm
.tm_min
, tm
.tm_sec
, tm
.tm_wday
);
353 switch (info
->device_type
) {
356 ret
= regmap_write(info
->rtc
, SEC_ALARM0_CONF
, alarm0_conf
);
360 data
[RTC_SEC
] |= ALARM_ENABLE_MASK
;
361 data
[RTC_MIN
] |= ALARM_ENABLE_MASK
;
362 data
[RTC_HOUR
] |= ALARM_ENABLE_MASK
;
363 data
[RTC_WEEKDAY
] &= ~ALARM_ENABLE_MASK
;
364 if (data
[RTC_DATE
] & 0x1f)
365 data
[RTC_DATE
] |= ALARM_ENABLE_MASK
;
366 if (data
[RTC_MONTH
] & 0xf)
367 data
[RTC_MONTH
] |= ALARM_ENABLE_MASK
;
368 if (data
[RTC_YEAR1
] & 0x7f)
369 data
[RTC_YEAR1
] |= ALARM_ENABLE_MASK
;
371 ret
= regmap_raw_write(info
->rtc
, SEC_ALARM0_SEC
, data
, 8);
374 ret
= s5m8767_rtc_set_alarm_reg(info
);
385 static int s5m_rtc_set_alarm(struct device
*dev
, struct rtc_wkalrm
*alrm
)
387 struct s5m_rtc_info
*info
= dev_get_drvdata(dev
);
391 switch (info
->device_type
) {
393 s5m8763_tm_to_data(&alrm
->time
, data
);
397 s5m8767_tm_to_data(&alrm
->time
, data
);
404 dev_dbg(dev
, "%s: %d/%d/%d %d:%d:%d(%d)\n", __func__
,
405 1900 + alrm
->time
.tm_year
, 1 + alrm
->time
.tm_mon
,
406 alrm
->time
.tm_mday
, alrm
->time
.tm_hour
, alrm
->time
.tm_min
,
407 alrm
->time
.tm_sec
, alrm
->time
.tm_wday
);
409 ret
= s5m_rtc_stop_alarm(info
);
413 ret
= regmap_raw_write(info
->rtc
, SEC_ALARM0_SEC
, data
, 8);
417 ret
= s5m8767_rtc_set_alarm_reg(info
);
422 ret
= s5m_rtc_start_alarm(info
);
427 static int s5m_rtc_alarm_irq_enable(struct device
*dev
,
428 unsigned int enabled
)
430 struct s5m_rtc_info
*info
= dev_get_drvdata(dev
);
433 return s5m_rtc_start_alarm(info
);
435 return s5m_rtc_stop_alarm(info
);
438 static irqreturn_t
s5m_rtc_alarm_irq(int irq
, void *data
)
440 struct s5m_rtc_info
*info
= data
;
442 rtc_update_irq(info
->rtc_dev
, 1, RTC_IRQF
| RTC_AF
);
447 static const struct rtc_class_ops s5m_rtc_ops
= {
448 .read_time
= s5m_rtc_read_time
,
449 .set_time
= s5m_rtc_set_time
,
450 .read_alarm
= s5m_rtc_read_alarm
,
451 .set_alarm
= s5m_rtc_set_alarm
,
452 .alarm_irq_enable
= s5m_rtc_alarm_irq_enable
,
455 static void s5m_rtc_enable_wtsr(struct s5m_rtc_info
*info
, bool enable
)
458 ret
= regmap_update_bits(info
->rtc
, SEC_WTSR_SMPL_CNTL
,
460 enable
? WTSR_ENABLE_MASK
: 0);
462 dev_err(info
->dev
, "%s: fail to update WTSR reg(%d)\n",
466 static void s5m_rtc_enable_smpl(struct s5m_rtc_info
*info
, bool enable
)
469 ret
= regmap_update_bits(info
->rtc
, SEC_WTSR_SMPL_CNTL
,
471 enable
? SMPL_ENABLE_MASK
: 0);
473 dev_err(info
->dev
, "%s: fail to update SMPL reg(%d)\n",
477 static int s5m8767_rtc_init_reg(struct s5m_rtc_info
*info
)
480 unsigned int tp_read
;
484 ret
= regmap_read(info
->rtc
, SEC_RTC_UDR_CON
, &tp_read
);
486 dev_err(info
->dev
, "%s: fail to read control reg(%d)\n",
491 /* Set RTC control register : Binary mode, 24hour mode */
492 data
[0] = (1 << BCD_EN_SHIFT
) | (1 << MODEL24_SHIFT
);
493 data
[1] = (0 << BCD_EN_SHIFT
) | (1 << MODEL24_SHIFT
);
495 info
->rtc_24hr_mode
= 1;
496 ret
= regmap_raw_write(info
->rtc
, SEC_ALARM0_CONF
, data
, 2);
498 dev_err(info
->dev
, "%s: fail to write controlm reg(%d)\n",
503 /* In first boot time, Set rtc time to 1/1/2012 00:00:00(SUN) */
504 if ((tp_read
& RTC_TCON_MASK
) == 0) {
505 dev_dbg(info
->dev
, "rtc init\n");
515 ret
= s5m_rtc_set_time(info
->dev
, &tm
);
518 ret
= regmap_update_bits(info
->rtc
, SEC_RTC_UDR_CON
,
519 RTC_TCON_MASK
, tp_read
| RTC_TCON_MASK
);
521 dev_err(info
->dev
, "%s: fail to update TCON reg(%d)\n",
527 static int s5m_rtc_probe(struct platform_device
*pdev
)
529 struct sec_pmic_dev
*s5m87xx
= dev_get_drvdata(pdev
->dev
.parent
);
530 struct sec_platform_data
*pdata
= s5m87xx
->pdata
;
531 struct s5m_rtc_info
*info
;
535 dev_err(pdev
->dev
.parent
, "Platform data not supplied\n");
539 info
= devm_kzalloc(&pdev
->dev
, sizeof(*info
), GFP_KERNEL
);
543 info
->dev
= &pdev
->dev
;
544 info
->s5m87xx
= s5m87xx
;
545 info
->rtc
= s5m87xx
->rtc
;
546 info
->device_type
= s5m87xx
->device_type
;
547 info
->wtsr_smpl
= s5m87xx
->wtsr_smpl
;
549 switch (pdata
->device_type
) {
551 info
->irq
= s5m87xx
->irq_base
+ S5M8763_IRQ_ALARM0
;
555 info
->irq
= s5m87xx
->irq_base
+ S5M8767_IRQ_RTCA1
;
560 dev_err(&pdev
->dev
, "Unsupported device type: %d\n", ret
);
564 platform_set_drvdata(pdev
, info
);
566 ret
= s5m8767_rtc_init_reg(info
);
568 if (info
->wtsr_smpl
) {
569 s5m_rtc_enable_wtsr(info
, true);
570 s5m_rtc_enable_smpl(info
, true);
573 device_init_wakeup(&pdev
->dev
, 1);
575 info
->rtc_dev
= devm_rtc_device_register(&pdev
->dev
, "s5m-rtc",
576 &s5m_rtc_ops
, THIS_MODULE
);
578 if (IS_ERR(info
->rtc_dev
))
579 return PTR_ERR(info
->rtc_dev
);
581 ret
= devm_request_threaded_irq(&pdev
->dev
, info
->irq
, NULL
,
582 s5m_rtc_alarm_irq
, 0, "rtc-alarm0",
585 dev_err(&pdev
->dev
, "Failed to request alarm IRQ: %d: %d\n",
591 static void s5m_rtc_shutdown(struct platform_device
*pdev
)
593 struct s5m_rtc_info
*info
= platform_get_drvdata(pdev
);
595 unsigned int val
= 0;
596 if (info
->wtsr_smpl
) {
597 for (i
= 0; i
< 3; i
++) {
598 s5m_rtc_enable_wtsr(info
, false);
599 regmap_read(info
->rtc
, SEC_WTSR_SMPL_CNTL
, &val
);
600 pr_debug("%s: WTSR_SMPL reg(0x%02x)\n", __func__
, val
);
601 if (val
& WTSR_ENABLE_MASK
)
602 pr_emerg("%s: fail to disable WTSR\n",
605 pr_info("%s: success to disable WTSR\n",
611 /* Disable SMPL when power off */
612 s5m_rtc_enable_smpl(info
, false);
615 static const struct platform_device_id s5m_rtc_id
[] = {
619 static struct platform_driver s5m_rtc_driver
= {
622 .owner
= THIS_MODULE
,
624 .probe
= s5m_rtc_probe
,
625 .shutdown
= s5m_rtc_shutdown
,
626 .id_table
= s5m_rtc_id
,
629 module_platform_driver(s5m_rtc_driver
);
631 /* Module information */
632 MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>");
633 MODULE_DESCRIPTION("Samsung S5M RTC driver");
634 MODULE_LICENSE("GPL");
635 MODULE_ALIAS("platform:s5m-rtc");