2 * Seiko Instruments S-35390A RTC Driver
4 * Copyright (c) 2007 Byron Bradley
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
12 #include <linux/module.h>
13 #include <linux/rtc.h>
14 #include <linux/i2c.h>
15 #include <linux/bitrev.h>
16 #include <linux/bcd.h>
17 #include <linux/slab.h>
19 #define S35390A_CMD_STATUS1 0
20 #define S35390A_CMD_STATUS2 1
21 #define S35390A_CMD_TIME1 2
22 #define S35390A_CMD_TIME2 3
23 #define S35390A_CMD_INT2_REG1 5
25 #define S35390A_BYTE_YEAR 0
26 #define S35390A_BYTE_MONTH 1
27 #define S35390A_BYTE_DAY 2
28 #define S35390A_BYTE_WDAY 3
29 #define S35390A_BYTE_HOURS 4
30 #define S35390A_BYTE_MINS 5
31 #define S35390A_BYTE_SECS 6
33 #define S35390A_ALRM_BYTE_WDAY 0
34 #define S35390A_ALRM_BYTE_HOURS 1
35 #define S35390A_ALRM_BYTE_MINS 2
37 #define S35390A_FLAG_POC 0x01
38 #define S35390A_FLAG_BLD 0x02
39 #define S35390A_FLAG_24H 0x40
40 #define S35390A_FLAG_RESET 0x80
41 #define S35390A_FLAG_TEST 0x01
43 #define S35390A_INT2_MODE_MASK 0xF0
45 #define S35390A_INT2_MODE_NOINTR 0x00
46 #define S35390A_INT2_MODE_FREQ 0x10
47 #define S35390A_INT2_MODE_ALARM 0x40
48 #define S35390A_INT2_MODE_PMIN_EDG 0x20
50 static const struct i2c_device_id s35390a_id
[] = {
54 MODULE_DEVICE_TABLE(i2c
, s35390a_id
);
57 struct i2c_client
*client
[8];
58 struct rtc_device
*rtc
;
62 static int s35390a_set_reg(struct s35390a
*s35390a
, int reg
, char *buf
, int len
)
64 struct i2c_client
*client
= s35390a
->client
[reg
];
65 struct i2c_msg msg
[] = {
73 if ((i2c_transfer(client
->adapter
, msg
, 1)) != 1)
79 static int s35390a_get_reg(struct s35390a
*s35390a
, int reg
, char *buf
, int len
)
81 struct i2c_client
*client
= s35390a
->client
[reg
];
82 struct i2c_msg msg
[] = {
91 if ((i2c_transfer(client
->adapter
, msg
, 1)) != 1)
97 static int s35390a_reset(struct s35390a
*s35390a
)
101 if (s35390a_get_reg(s35390a
, S35390A_CMD_STATUS1
, buf
, sizeof(buf
)) < 0)
104 if (!(buf
[0] & (S35390A_FLAG_POC
| S35390A_FLAG_BLD
)))
107 buf
[0] |= (S35390A_FLAG_RESET
| S35390A_FLAG_24H
);
109 return s35390a_set_reg(s35390a
, S35390A_CMD_STATUS1
, buf
, sizeof(buf
));
112 static int s35390a_disable_test_mode(struct s35390a
*s35390a
)
116 if (s35390a_get_reg(s35390a
, S35390A_CMD_STATUS2
, buf
, sizeof(buf
)) < 0)
119 if (!(buf
[0] & S35390A_FLAG_TEST
))
122 buf
[0] &= ~S35390A_FLAG_TEST
;
123 return s35390a_set_reg(s35390a
, S35390A_CMD_STATUS2
, buf
, sizeof(buf
));
126 static char s35390a_hr2reg(struct s35390a
*s35390a
, int hour
)
128 if (s35390a
->twentyfourhour
)
129 return bin2bcd(hour
);
132 return bin2bcd(hour
);
134 return 0x40 | bin2bcd(hour
- 12);
137 static int s35390a_reg2hr(struct s35390a
*s35390a
, char reg
)
141 if (s35390a
->twentyfourhour
)
142 return bcd2bin(reg
& 0x3f);
144 hour
= bcd2bin(reg
& 0x3f);
151 static int s35390a_set_datetime(struct i2c_client
*client
, struct rtc_time
*tm
)
153 struct s35390a
*s35390a
= i2c_get_clientdata(client
);
157 dev_dbg(&client
->dev
, "%s: tm is secs=%d, mins=%d, hours=%d mday=%d, "
158 "mon=%d, year=%d, wday=%d\n", __func__
, tm
->tm_sec
,
159 tm
->tm_min
, tm
->tm_hour
, tm
->tm_mday
, tm
->tm_mon
, tm
->tm_year
,
162 buf
[S35390A_BYTE_YEAR
] = bin2bcd(tm
->tm_year
- 100);
163 buf
[S35390A_BYTE_MONTH
] = bin2bcd(tm
->tm_mon
+ 1);
164 buf
[S35390A_BYTE_DAY
] = bin2bcd(tm
->tm_mday
);
165 buf
[S35390A_BYTE_WDAY
] = bin2bcd(tm
->tm_wday
);
166 buf
[S35390A_BYTE_HOURS
] = s35390a_hr2reg(s35390a
, tm
->tm_hour
);
167 buf
[S35390A_BYTE_MINS
] = bin2bcd(tm
->tm_min
);
168 buf
[S35390A_BYTE_SECS
] = bin2bcd(tm
->tm_sec
);
170 /* This chip expects the bits of each byte to be in reverse order */
171 for (i
= 0; i
< 7; ++i
)
172 buf
[i
] = bitrev8(buf
[i
]);
174 err
= s35390a_set_reg(s35390a
, S35390A_CMD_TIME1
, buf
, sizeof(buf
));
179 static int s35390a_get_datetime(struct i2c_client
*client
, struct rtc_time
*tm
)
181 struct s35390a
*s35390a
= i2c_get_clientdata(client
);
185 err
= s35390a_get_reg(s35390a
, S35390A_CMD_TIME1
, buf
, sizeof(buf
));
189 /* This chip returns the bits of each byte in reverse order */
190 for (i
= 0; i
< 7; ++i
)
191 buf
[i
] = bitrev8(buf
[i
]);
193 tm
->tm_sec
= bcd2bin(buf
[S35390A_BYTE_SECS
]);
194 tm
->tm_min
= bcd2bin(buf
[S35390A_BYTE_MINS
]);
195 tm
->tm_hour
= s35390a_reg2hr(s35390a
, buf
[S35390A_BYTE_HOURS
]);
196 tm
->tm_wday
= bcd2bin(buf
[S35390A_BYTE_WDAY
]);
197 tm
->tm_mday
= bcd2bin(buf
[S35390A_BYTE_DAY
]);
198 tm
->tm_mon
= bcd2bin(buf
[S35390A_BYTE_MONTH
]) - 1;
199 tm
->tm_year
= bcd2bin(buf
[S35390A_BYTE_YEAR
]) + 100;
201 dev_dbg(&client
->dev
, "%s: tm is secs=%d, mins=%d, hours=%d, mday=%d, "
202 "mon=%d, year=%d, wday=%d\n", __func__
, tm
->tm_sec
,
203 tm
->tm_min
, tm
->tm_hour
, tm
->tm_mday
, tm
->tm_mon
, tm
->tm_year
,
206 return rtc_valid_tm(tm
);
209 static int s35390a_set_alarm(struct i2c_client
*client
, struct rtc_wkalrm
*alm
)
211 struct s35390a
*s35390a
= i2c_get_clientdata(client
);
212 char buf
[3], sts
= 0;
215 dev_dbg(&client
->dev
, "%s: alm is secs=%d, mins=%d, hours=%d mday=%d, "\
216 "mon=%d, year=%d, wday=%d\n", __func__
, alm
->time
.tm_sec
,
217 alm
->time
.tm_min
, alm
->time
.tm_hour
, alm
->time
.tm_mday
,
218 alm
->time
.tm_mon
, alm
->time
.tm_year
, alm
->time
.tm_wday
);
220 /* disable interrupt */
221 err
= s35390a_set_reg(s35390a
, S35390A_CMD_STATUS2
, &sts
, sizeof(sts
));
225 /* clear pending interrupt, if any */
226 err
= s35390a_get_reg(s35390a
, S35390A_CMD_STATUS1
, &sts
, sizeof(sts
));
231 sts
= S35390A_INT2_MODE_ALARM
;
233 sts
= S35390A_INT2_MODE_NOINTR
;
235 /* This chip expects the bits of each byte to be in reverse order */
238 /* set interupt mode*/
239 err
= s35390a_set_reg(s35390a
, S35390A_CMD_STATUS2
, &sts
, sizeof(sts
));
243 if (alm
->time
.tm_wday
!= -1)
244 buf
[S35390A_ALRM_BYTE_WDAY
] = bin2bcd(alm
->time
.tm_wday
) | 0x80;
246 buf
[S35390A_ALRM_BYTE_HOURS
] = s35390a_hr2reg(s35390a
,
247 alm
->time
.tm_hour
) | 0x80;
248 buf
[S35390A_ALRM_BYTE_MINS
] = bin2bcd(alm
->time
.tm_min
) | 0x80;
250 if (alm
->time
.tm_hour
>= 12)
251 buf
[S35390A_ALRM_BYTE_HOURS
] |= 0x40;
253 for (i
= 0; i
< 3; ++i
)
254 buf
[i
] = bitrev8(buf
[i
]);
256 err
= s35390a_set_reg(s35390a
, S35390A_CMD_INT2_REG1
, buf
,
262 static int s35390a_read_alarm(struct i2c_client
*client
, struct rtc_wkalrm
*alm
)
264 struct s35390a
*s35390a
= i2c_get_clientdata(client
);
269 * initialize all members to -1 to signal the core that they are not
270 * defined by the hardware.
272 alm
->time
.tm_sec
= -1;
273 alm
->time
.tm_min
= -1;
274 alm
->time
.tm_hour
= -1;
275 alm
->time
.tm_mday
= -1;
276 alm
->time
.tm_mon
= -1;
277 alm
->time
.tm_year
= -1;
278 alm
->time
.tm_wday
= -1;
279 alm
->time
.tm_yday
= -1;
280 alm
->time
.tm_isdst
= -1;
282 err
= s35390a_get_reg(s35390a
, S35390A_CMD_STATUS2
, &sts
, sizeof(sts
));
286 if (bitrev8(sts
) != S35390A_INT2_MODE_ALARM
)
289 err
= s35390a_get_reg(s35390a
, S35390A_CMD_INT2_REG1
, buf
, sizeof(buf
));
293 /* This chip returns the bits of each byte in reverse order */
294 for (i
= 0; i
< 3; ++i
) {
295 buf
[i
] = bitrev8(buf
[i
]);
299 alm
->time
.tm_wday
= bcd2bin(buf
[S35390A_ALRM_BYTE_WDAY
]);
300 alm
->time
.tm_hour
= s35390a_reg2hr(s35390a
,
301 buf
[S35390A_ALRM_BYTE_HOURS
]);
302 alm
->time
.tm_min
= bcd2bin(buf
[S35390A_ALRM_BYTE_MINS
]);
304 dev_dbg(&client
->dev
, "%s: alm is mins=%d, hours=%d, wday=%d\n",
305 __func__
, alm
->time
.tm_min
, alm
->time
.tm_hour
,
311 static int s35390a_rtc_read_alarm(struct device
*dev
, struct rtc_wkalrm
*alm
)
313 return s35390a_read_alarm(to_i2c_client(dev
), alm
);
316 static int s35390a_rtc_set_alarm(struct device
*dev
, struct rtc_wkalrm
*alm
)
318 return s35390a_set_alarm(to_i2c_client(dev
), alm
);
321 static int s35390a_rtc_read_time(struct device
*dev
, struct rtc_time
*tm
)
323 return s35390a_get_datetime(to_i2c_client(dev
), tm
);
326 static int s35390a_rtc_set_time(struct device
*dev
, struct rtc_time
*tm
)
328 return s35390a_set_datetime(to_i2c_client(dev
), tm
);
331 static const struct rtc_class_ops s35390a_rtc_ops
= {
332 .read_time
= s35390a_rtc_read_time
,
333 .set_time
= s35390a_rtc_set_time
,
334 .set_alarm
= s35390a_rtc_set_alarm
,
335 .read_alarm
= s35390a_rtc_read_alarm
,
339 static struct i2c_driver s35390a_driver
;
341 static int s35390a_probe(struct i2c_client
*client
,
342 const struct i2c_device_id
*id
)
346 struct s35390a
*s35390a
;
350 if (!i2c_check_functionality(client
->adapter
, I2C_FUNC_I2C
)) {
355 s35390a
= devm_kzalloc(&client
->dev
, sizeof(struct s35390a
),
362 s35390a
->client
[0] = client
;
363 i2c_set_clientdata(client
, s35390a
);
365 /* This chip uses multiple addresses, use dummy devices for them */
366 for (i
= 1; i
< 8; ++i
) {
367 s35390a
->client
[i
] = i2c_new_dummy(client
->adapter
,
369 if (!s35390a
->client
[i
]) {
370 dev_err(&client
->dev
, "Address %02x unavailable\n",
377 err
= s35390a_reset(s35390a
);
379 dev_err(&client
->dev
, "error resetting chip\n");
383 err
= s35390a_disable_test_mode(s35390a
);
385 dev_err(&client
->dev
, "error disabling test mode\n");
389 err
= s35390a_get_reg(s35390a
, S35390A_CMD_STATUS1
, buf
, sizeof(buf
));
391 dev_err(&client
->dev
, "error checking 12/24 hour mode\n");
394 if (buf
[0] & S35390A_FLAG_24H
)
395 s35390a
->twentyfourhour
= 1;
397 s35390a
->twentyfourhour
= 0;
399 if (s35390a_get_datetime(client
, &tm
) < 0)
400 dev_warn(&client
->dev
, "clock needs to be set\n");
402 device_set_wakeup_capable(&client
->dev
, 1);
404 s35390a
->rtc
= devm_rtc_device_register(&client
->dev
,
405 s35390a_driver
.driver
.name
,
406 &s35390a_rtc_ops
, THIS_MODULE
);
408 if (IS_ERR(s35390a
->rtc
)) {
409 err
= PTR_ERR(s35390a
->rtc
);
415 for (i
= 1; i
< 8; ++i
)
416 if (s35390a
->client
[i
])
417 i2c_unregister_device(s35390a
->client
[i
]);
423 static int s35390a_remove(struct i2c_client
*client
)
426 struct s35390a
*s35390a
= i2c_get_clientdata(client
);
428 for (i
= 1; i
< 8; ++i
)
429 if (s35390a
->client
[i
])
430 i2c_unregister_device(s35390a
->client
[i
]);
435 static struct i2c_driver s35390a_driver
= {
437 .name
= "rtc-s35390a",
439 .probe
= s35390a_probe
,
440 .remove
= s35390a_remove
,
441 .id_table
= s35390a_id
,
444 module_i2c_driver(s35390a_driver
);
446 MODULE_AUTHOR("Byron Bradley <byron.bbradley@gmail.com>");
447 MODULE_DESCRIPTION("S35390A RTC driver");
448 MODULE_LICENSE("GPL");