2 * RTC driver for Maxim MAX8925
4 * Copyright (C) 2009-2010 Marvell International Ltd.
5 * Haojian Zhuang <haojian.zhuang@marvell.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
12 #include <linux/module.h>
13 #include <linux/i2c.h>
14 #include <linux/rtc.h>
15 #include <linux/platform_device.h>
16 #include <linux/mfd/max8925.h>
29 #define MAX8925_RTC_SEC 0x00
30 #define MAX8925_RTC_MIN 0x01
31 #define MAX8925_RTC_HOUR 0x02
32 #define MAX8925_RTC_WEEKDAY 0x03
33 #define MAX8925_RTC_DATE 0x04
34 #define MAX8925_RTC_MONTH 0x05
35 #define MAX8925_RTC_YEAR1 0x06
36 #define MAX8925_RTC_YEAR2 0x07
37 #define MAX8925_ALARM0_SEC 0x08
38 #define MAX8925_ALARM0_MIN 0x09
39 #define MAX8925_ALARM0_HOUR 0x0a
40 #define MAX8925_ALARM0_WEEKDAY 0x0b
41 #define MAX8925_ALARM0_DATE 0x0c
42 #define MAX8925_ALARM0_MON 0x0d
43 #define MAX8925_ALARM0_YEAR1 0x0e
44 #define MAX8925_ALARM0_YEAR2 0x0f
45 #define MAX8925_ALARM1_SEC 0x10
46 #define MAX8925_ALARM1_MIN 0x11
47 #define MAX8925_ALARM1_HOUR 0x12
48 #define MAX8925_ALARM1_WEEKDAY 0x13
49 #define MAX8925_ALARM1_DATE 0x14
50 #define MAX8925_ALARM1_MON 0x15
51 #define MAX8925_ALARM1_YEAR1 0x16
52 #define MAX8925_ALARM1_YEAR2 0x17
53 #define MAX8925_RTC_CNTL 0x1b
54 #define MAX8925_RTC_STATUS 0x20
57 #define ALARM_1SEC (1 << 7)
58 #define HOUR_12 (1 << 7)
59 #define HOUR_AM_PM (1 << 5)
60 #define ALARM0_IRQ (1 << 3)
61 #define ALARM1_IRQ (1 << 2)
62 #define ALARM0_STATUS (1 << 2)
63 #define ALARM1_STATUS (1 << 1)
66 struct max8925_rtc_info
{
67 struct rtc_device
*rtc_dev
;
68 struct max8925_chip
*chip
;
69 struct i2c_client
*rtc
;
73 static irqreturn_t
rtc_update_handler(int irq
, void *data
)
75 struct max8925_rtc_info
*info
= (struct max8925_rtc_info
*)data
;
77 /* disable ALARM0 except for 1SEC alarm */
78 max8925_set_bits(info
->rtc
, MAX8925_ALARM0_CNTL
, 0x7f, 0);
79 rtc_update_irq(info
->rtc_dev
, 1, RTC_IRQF
| RTC_AF
);
83 static int tm_calc(struct rtc_time
*tm
, unsigned char *buf
, int len
)
87 tm
->tm_year
= (buf
[RTC_YEAR2
] >> 4) * 1000
88 + (buf
[RTC_YEAR2
] & 0xf) * 100
89 + (buf
[RTC_YEAR1
] >> 4) * 10
90 + (buf
[RTC_YEAR1
] & 0xf);
92 tm
->tm_mon
= ((buf
[RTC_MONTH
] >> 4) & 0x01) * 10
93 + (buf
[RTC_MONTH
] & 0x0f);
94 tm
->tm_mday
= ((buf
[RTC_DATE
] >> 4) & 0x03) * 10
95 + (buf
[RTC_DATE
] & 0x0f);
96 tm
->tm_wday
= buf
[RTC_WEEKDAY
] & 0x07;
97 if (buf
[RTC_HOUR
] & HOUR_12
) {
98 tm
->tm_hour
= ((buf
[RTC_HOUR
] >> 4) & 0x1) * 10
99 + (buf
[RTC_HOUR
] & 0x0f);
100 if (buf
[RTC_HOUR
] & HOUR_AM_PM
)
103 tm
->tm_hour
= ((buf
[RTC_HOUR
] >> 4) & 0x03) * 10
104 + (buf
[RTC_HOUR
] & 0x0f);
105 tm
->tm_min
= ((buf
[RTC_MIN
] >> 4) & 0x7) * 10
106 + (buf
[RTC_MIN
] & 0x0f);
107 tm
->tm_sec
= ((buf
[RTC_SEC
] >> 4) & 0x7) * 10
108 + (buf
[RTC_SEC
] & 0x0f);
112 static int data_calc(unsigned char *buf
, struct rtc_time
*tm
, int len
)
114 unsigned char high
, low
;
119 high
= (tm
->tm_year
+ 1900) / 1000;
120 low
= (tm
->tm_year
+ 1900) / 100;
121 low
= low
- high
* 10;
122 buf
[RTC_YEAR2
] = (high
<< 4) + low
;
123 high
= (tm
->tm_year
+ 1900) / 10;
124 low
= tm
->tm_year
+ 1900;
125 low
= low
- high
* 10;
126 high
= high
- (high
/ 10) * 10;
127 buf
[RTC_YEAR1
] = (high
<< 4) + low
;
128 high
= tm
->tm_mon
/ 10;
130 low
= low
- high
* 10;
131 buf
[RTC_MONTH
] = (high
<< 4) + low
;
132 high
= tm
->tm_mday
/ 10;
134 low
= low
- high
* 10;
135 buf
[RTC_DATE
] = (high
<< 4) + low
;
136 buf
[RTC_WEEKDAY
] = tm
->tm_wday
;
137 high
= tm
->tm_hour
/ 10;
139 low
= low
- high
* 10;
140 buf
[RTC_HOUR
] = (high
<< 4) + low
;
141 high
= tm
->tm_min
/ 10;
143 low
= low
- high
* 10;
144 buf
[RTC_MIN
] = (high
<< 4) + low
;
145 high
= tm
->tm_sec
/ 10;
147 low
= low
- high
* 10;
148 buf
[RTC_SEC
] = (high
<< 4) + low
;
152 static int max8925_rtc_read_time(struct device
*dev
, struct rtc_time
*tm
)
154 struct max8925_rtc_info
*info
= dev_get_drvdata(dev
);
155 unsigned char buf
[TIME_NUM
];
158 ret
= max8925_bulk_read(info
->rtc
, MAX8925_RTC_SEC
, TIME_NUM
, buf
);
161 ret
= tm_calc(tm
, buf
, TIME_NUM
);
166 static int max8925_rtc_set_time(struct device
*dev
, struct rtc_time
*tm
)
168 struct max8925_rtc_info
*info
= dev_get_drvdata(dev
);
169 unsigned char buf
[TIME_NUM
];
172 ret
= data_calc(buf
, tm
, TIME_NUM
);
175 ret
= max8925_bulk_write(info
->rtc
, MAX8925_RTC_SEC
, TIME_NUM
, buf
);
180 static int max8925_rtc_read_alarm(struct device
*dev
, struct rtc_wkalrm
*alrm
)
182 struct max8925_rtc_info
*info
= dev_get_drvdata(dev
);
183 unsigned char buf
[TIME_NUM
];
186 ret
= max8925_bulk_read(info
->rtc
, MAX8925_ALARM0_SEC
, TIME_NUM
, buf
);
189 ret
= tm_calc(&alrm
->time
, buf
, TIME_NUM
);
192 ret
= max8925_reg_read(info
->rtc
, MAX8925_RTC_IRQ_MASK
);
195 if ((ret
& ALARM0_IRQ
) == 0)
199 ret
= max8925_reg_read(info
->rtc
, MAX8925_RTC_STATUS
);
202 if (ret
& ALARM0_STATUS
)
210 static int max8925_rtc_set_alarm(struct device
*dev
, struct rtc_wkalrm
*alrm
)
212 struct max8925_rtc_info
*info
= dev_get_drvdata(dev
);
213 unsigned char buf
[TIME_NUM
];
216 ret
= data_calc(buf
, &alrm
->time
, TIME_NUM
);
219 ret
= max8925_bulk_write(info
->rtc
, MAX8925_ALARM0_SEC
, TIME_NUM
, buf
);
222 /* only enable alarm on year/month/day/hour/min/sec */
223 ret
= max8925_reg_write(info
->rtc
, MAX8925_ALARM0_CNTL
, 0x77);
230 static const struct rtc_class_ops max8925_rtc_ops
= {
231 .read_time
= max8925_rtc_read_time
,
232 .set_time
= max8925_rtc_set_time
,
233 .read_alarm
= max8925_rtc_read_alarm
,
234 .set_alarm
= max8925_rtc_set_alarm
,
237 static int __devinit
max8925_rtc_probe(struct platform_device
*pdev
)
239 struct max8925_chip
*chip
= dev_get_drvdata(pdev
->dev
.parent
);
240 struct max8925_rtc_info
*info
;
243 info
= kzalloc(sizeof(struct max8925_rtc_info
), GFP_KERNEL
);
247 info
->rtc
= chip
->rtc
;
248 info
->dev
= &pdev
->dev
;
249 irq
= chip
->irq_base
+ MAX8925_IRQ_RTC_ALARM0
;
251 ret
= request_threaded_irq(irq
, NULL
, rtc_update_handler
,
252 IRQF_ONESHOT
, "rtc-alarm0", info
);
254 dev_err(chip
->dev
, "Failed to request IRQ: #%d: %d\n",
259 info
->rtc_dev
= rtc_device_register("max8925-rtc", &pdev
->dev
,
260 &max8925_rtc_ops
, THIS_MODULE
);
261 ret
= PTR_ERR(info
->rtc_dev
);
262 if (IS_ERR(info
->rtc_dev
)) {
263 dev_err(&pdev
->dev
, "Failed to register RTC device: %d\n", ret
);
267 dev_set_drvdata(&pdev
->dev
, info
);
268 platform_set_drvdata(pdev
, info
);
272 free_irq(chip
->irq_base
+ MAX8925_IRQ_RTC_ALARM0
, info
);
278 static int __devexit
max8925_rtc_remove(struct platform_device
*pdev
)
280 struct max8925_rtc_info
*info
= platform_get_drvdata(pdev
);
283 free_irq(info
->chip
->irq_base
+ MAX8925_IRQ_RTC_ALARM0
, info
);
284 rtc_device_unregister(info
->rtc_dev
);
290 static struct platform_driver max8925_rtc_driver
= {
292 .name
= "max8925-rtc",
293 .owner
= THIS_MODULE
,
295 .probe
= max8925_rtc_probe
,
296 .remove
= __devexit_p(max8925_rtc_remove
),
299 static int __init
max8925_rtc_init(void)
301 return platform_driver_register(&max8925_rtc_driver
);
303 module_init(max8925_rtc_init
);
305 static void __exit
max8925_rtc_exit(void)
307 platform_driver_unregister(&max8925_rtc_driver
);
309 module_exit(max8925_rtc_exit
);
311 MODULE_DESCRIPTION("Maxim MAX8925 RTC driver");
312 MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
313 MODULE_LICENSE("GPL");