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/slab.h>
15 #include <linux/rtc.h>
16 #include <linux/platform_device.h>
17 #include <linux/mfd/max8925.h>
30 #define MAX8925_RTC_SEC 0x00
31 #define MAX8925_RTC_MIN 0x01
32 #define MAX8925_RTC_HOUR 0x02
33 #define MAX8925_RTC_WEEKDAY 0x03
34 #define MAX8925_RTC_DATE 0x04
35 #define MAX8925_RTC_MONTH 0x05
36 #define MAX8925_RTC_YEAR1 0x06
37 #define MAX8925_RTC_YEAR2 0x07
38 #define MAX8925_ALARM0_SEC 0x08
39 #define MAX8925_ALARM0_MIN 0x09
40 #define MAX8925_ALARM0_HOUR 0x0a
41 #define MAX8925_ALARM0_WEEKDAY 0x0b
42 #define MAX8925_ALARM0_DATE 0x0c
43 #define MAX8925_ALARM0_MON 0x0d
44 #define MAX8925_ALARM0_YEAR1 0x0e
45 #define MAX8925_ALARM0_YEAR2 0x0f
46 #define MAX8925_ALARM1_SEC 0x10
47 #define MAX8925_ALARM1_MIN 0x11
48 #define MAX8925_ALARM1_HOUR 0x12
49 #define MAX8925_ALARM1_WEEKDAY 0x13
50 #define MAX8925_ALARM1_DATE 0x14
51 #define MAX8925_ALARM1_MON 0x15
52 #define MAX8925_ALARM1_YEAR1 0x16
53 #define MAX8925_ALARM1_YEAR2 0x17
54 #define MAX8925_RTC_CNTL 0x1b
55 #define MAX8925_RTC_STATUS 0x20
58 #define ALARM_1SEC (1 << 7)
59 #define HOUR_12 (1 << 7)
60 #define HOUR_AM_PM (1 << 5)
61 #define ALARM0_IRQ (1 << 3)
62 #define ALARM1_IRQ (1 << 2)
63 #define ALARM0_STATUS (1 << 2)
64 #define ALARM1_STATUS (1 << 1)
67 struct max8925_rtc_info
{
68 struct rtc_device
*rtc_dev
;
69 struct max8925_chip
*chip
;
70 struct i2c_client
*rtc
;
74 static irqreturn_t
rtc_update_handler(int irq
, void *data
)
76 struct max8925_rtc_info
*info
= (struct max8925_rtc_info
*)data
;
78 /* disable ALARM0 except for 1SEC alarm */
79 max8925_set_bits(info
->rtc
, MAX8925_ALARM0_CNTL
, 0x7f, 0);
80 rtc_update_irq(info
->rtc_dev
, 1, RTC_IRQF
| RTC_AF
);
84 static int tm_calc(struct rtc_time
*tm
, unsigned char *buf
, int len
)
88 tm
->tm_year
= (buf
[RTC_YEAR2
] >> 4) * 1000
89 + (buf
[RTC_YEAR2
] & 0xf) * 100
90 + (buf
[RTC_YEAR1
] >> 4) * 10
91 + (buf
[RTC_YEAR1
] & 0xf);
93 tm
->tm_mon
= ((buf
[RTC_MONTH
] >> 4) & 0x01) * 10
94 + (buf
[RTC_MONTH
] & 0x0f);
95 tm
->tm_mday
= ((buf
[RTC_DATE
] >> 4) & 0x03) * 10
96 + (buf
[RTC_DATE
] & 0x0f);
97 tm
->tm_wday
= buf
[RTC_WEEKDAY
] & 0x07;
98 if (buf
[RTC_HOUR
] & HOUR_12
) {
99 tm
->tm_hour
= ((buf
[RTC_HOUR
] >> 4) & 0x1) * 10
100 + (buf
[RTC_HOUR
] & 0x0f);
101 if (buf
[RTC_HOUR
] & HOUR_AM_PM
)
104 tm
->tm_hour
= ((buf
[RTC_HOUR
] >> 4) & 0x03) * 10
105 + (buf
[RTC_HOUR
] & 0x0f);
106 tm
->tm_min
= ((buf
[RTC_MIN
] >> 4) & 0x7) * 10
107 + (buf
[RTC_MIN
] & 0x0f);
108 tm
->tm_sec
= ((buf
[RTC_SEC
] >> 4) & 0x7) * 10
109 + (buf
[RTC_SEC
] & 0x0f);
113 static int data_calc(unsigned char *buf
, struct rtc_time
*tm
, int len
)
115 unsigned char high
, low
;
120 high
= (tm
->tm_year
+ 1900) / 1000;
121 low
= (tm
->tm_year
+ 1900) / 100;
122 low
= low
- high
* 10;
123 buf
[RTC_YEAR2
] = (high
<< 4) + low
;
124 high
= (tm
->tm_year
+ 1900) / 10;
125 low
= tm
->tm_year
+ 1900;
126 low
= low
- high
* 10;
127 high
= high
- (high
/ 10) * 10;
128 buf
[RTC_YEAR1
] = (high
<< 4) + low
;
129 high
= tm
->tm_mon
/ 10;
131 low
= low
- high
* 10;
132 buf
[RTC_MONTH
] = (high
<< 4) + low
;
133 high
= tm
->tm_mday
/ 10;
135 low
= low
- high
* 10;
136 buf
[RTC_DATE
] = (high
<< 4) + low
;
137 buf
[RTC_WEEKDAY
] = tm
->tm_wday
;
138 high
= tm
->tm_hour
/ 10;
140 low
= low
- high
* 10;
141 buf
[RTC_HOUR
] = (high
<< 4) + low
;
142 high
= tm
->tm_min
/ 10;
144 low
= low
- high
* 10;
145 buf
[RTC_MIN
] = (high
<< 4) + low
;
146 high
= tm
->tm_sec
/ 10;
148 low
= low
- high
* 10;
149 buf
[RTC_SEC
] = (high
<< 4) + low
;
153 static int max8925_rtc_read_time(struct device
*dev
, struct rtc_time
*tm
)
155 struct max8925_rtc_info
*info
= dev_get_drvdata(dev
);
156 unsigned char buf
[TIME_NUM
];
159 ret
= max8925_bulk_read(info
->rtc
, MAX8925_RTC_SEC
, TIME_NUM
, buf
);
162 ret
= tm_calc(tm
, buf
, TIME_NUM
);
167 static int max8925_rtc_set_time(struct device
*dev
, struct rtc_time
*tm
)
169 struct max8925_rtc_info
*info
= dev_get_drvdata(dev
);
170 unsigned char buf
[TIME_NUM
];
173 ret
= data_calc(buf
, tm
, TIME_NUM
);
176 ret
= max8925_bulk_write(info
->rtc
, MAX8925_RTC_SEC
, TIME_NUM
, buf
);
181 static int max8925_rtc_read_alarm(struct device
*dev
, struct rtc_wkalrm
*alrm
)
183 struct max8925_rtc_info
*info
= dev_get_drvdata(dev
);
184 unsigned char buf
[TIME_NUM
];
187 ret
= max8925_bulk_read(info
->rtc
, MAX8925_ALARM0_SEC
, TIME_NUM
, buf
);
190 ret
= tm_calc(&alrm
->time
, buf
, TIME_NUM
);
193 ret
= max8925_reg_read(info
->rtc
, MAX8925_RTC_IRQ_MASK
);
196 if ((ret
& ALARM0_IRQ
) == 0)
200 ret
= max8925_reg_read(info
->rtc
, MAX8925_RTC_STATUS
);
203 if (ret
& ALARM0_STATUS
)
211 static int max8925_rtc_set_alarm(struct device
*dev
, struct rtc_wkalrm
*alrm
)
213 struct max8925_rtc_info
*info
= dev_get_drvdata(dev
);
214 unsigned char buf
[TIME_NUM
];
217 ret
= data_calc(buf
, &alrm
->time
, TIME_NUM
);
220 ret
= max8925_bulk_write(info
->rtc
, MAX8925_ALARM0_SEC
, TIME_NUM
, buf
);
223 /* only enable alarm on year/month/day/hour/min/sec */
224 ret
= max8925_reg_write(info
->rtc
, MAX8925_ALARM0_CNTL
, 0x77);
231 static const struct rtc_class_ops max8925_rtc_ops
= {
232 .read_time
= max8925_rtc_read_time
,
233 .set_time
= max8925_rtc_set_time
,
234 .read_alarm
= max8925_rtc_read_alarm
,
235 .set_alarm
= max8925_rtc_set_alarm
,
238 static int __devinit
max8925_rtc_probe(struct platform_device
*pdev
)
240 struct max8925_chip
*chip
= dev_get_drvdata(pdev
->dev
.parent
);
241 struct max8925_rtc_info
*info
;
244 info
= kzalloc(sizeof(struct max8925_rtc_info
), GFP_KERNEL
);
248 info
->rtc
= chip
->rtc
;
249 info
->dev
= &pdev
->dev
;
250 irq
= chip
->irq_base
+ MAX8925_IRQ_RTC_ALARM0
;
252 ret
= request_threaded_irq(irq
, NULL
, rtc_update_handler
,
253 IRQF_ONESHOT
, "rtc-alarm0", info
);
255 dev_err(chip
->dev
, "Failed to request IRQ: #%d: %d\n",
260 dev_set_drvdata(&pdev
->dev
, info
);
261 /* XXX - isn't this redundant? */
262 platform_set_drvdata(pdev
, info
);
264 info
->rtc_dev
= rtc_device_register("max8925-rtc", &pdev
->dev
,
265 &max8925_rtc_ops
, THIS_MODULE
);
266 ret
= PTR_ERR(info
->rtc_dev
);
267 if (IS_ERR(info
->rtc_dev
)) {
268 dev_err(&pdev
->dev
, "Failed to register RTC device: %d\n", ret
);
274 platform_set_drvdata(pdev
, NULL
);
275 free_irq(chip
->irq_base
+ MAX8925_IRQ_RTC_ALARM0
, info
);
281 static int __devexit
max8925_rtc_remove(struct platform_device
*pdev
)
283 struct max8925_rtc_info
*info
= platform_get_drvdata(pdev
);
286 free_irq(info
->chip
->irq_base
+ MAX8925_IRQ_RTC_ALARM0
, info
);
287 rtc_device_unregister(info
->rtc_dev
);
293 static struct platform_driver max8925_rtc_driver
= {
295 .name
= "max8925-rtc",
296 .owner
= THIS_MODULE
,
298 .probe
= max8925_rtc_probe
,
299 .remove
= __devexit_p(max8925_rtc_remove
),
302 static int __init
max8925_rtc_init(void)
304 return platform_driver_register(&max8925_rtc_driver
);
306 module_init(max8925_rtc_init
);
308 static void __exit
max8925_rtc_exit(void)
310 platform_driver_unregister(&max8925_rtc_driver
);
312 module_exit(max8925_rtc_exit
);
314 MODULE_DESCRIPTION("Maxim MAX8925 RTC driver");
315 MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
316 MODULE_LICENSE("GPL");