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
23 #define S35390A_BYTE_YEAR 0
24 #define S35390A_BYTE_MONTH 1
25 #define S35390A_BYTE_DAY 2
26 #define S35390A_BYTE_WDAY 3
27 #define S35390A_BYTE_HOURS 4
28 #define S35390A_BYTE_MINS 5
29 #define S35390A_BYTE_SECS 6
31 #define S35390A_FLAG_POC 0x01
32 #define S35390A_FLAG_BLD 0x02
33 #define S35390A_FLAG_24H 0x40
34 #define S35390A_FLAG_RESET 0x80
35 #define S35390A_FLAG_TEST 0x01
37 static const struct i2c_device_id s35390a_id
[] = {
41 MODULE_DEVICE_TABLE(i2c
, s35390a_id
);
44 struct i2c_client
*client
[8];
45 struct rtc_device
*rtc
;
49 static int s35390a_set_reg(struct s35390a
*s35390a
, int reg
, char *buf
, int len
)
51 struct i2c_client
*client
= s35390a
->client
[reg
];
52 struct i2c_msg msg
[] = {
53 { client
->addr
, 0, len
, buf
},
56 if ((i2c_transfer(client
->adapter
, msg
, 1)) != 1)
62 static int s35390a_get_reg(struct s35390a
*s35390a
, int reg
, char *buf
, int len
)
64 struct i2c_client
*client
= s35390a
->client
[reg
];
65 struct i2c_msg msg
[] = {
66 { client
->addr
, I2C_M_RD
, len
, buf
},
69 if ((i2c_transfer(client
->adapter
, msg
, 1)) != 1)
75 static int s35390a_reset(struct s35390a
*s35390a
)
79 if (s35390a_get_reg(s35390a
, S35390A_CMD_STATUS1
, buf
, sizeof(buf
)) < 0)
82 if (!(buf
[0] & (S35390A_FLAG_POC
| S35390A_FLAG_BLD
)))
85 buf
[0] |= (S35390A_FLAG_RESET
| S35390A_FLAG_24H
);
87 return s35390a_set_reg(s35390a
, S35390A_CMD_STATUS1
, buf
, sizeof(buf
));
90 static int s35390a_disable_test_mode(struct s35390a
*s35390a
)
94 if (s35390a_get_reg(s35390a
, S35390A_CMD_STATUS2
, buf
, sizeof(buf
)) < 0)
97 if (!(buf
[0] & S35390A_FLAG_TEST
))
100 buf
[0] &= ~S35390A_FLAG_TEST
;
101 return s35390a_set_reg(s35390a
, S35390A_CMD_STATUS2
, buf
, sizeof(buf
));
104 static char s35390a_hr2reg(struct s35390a
*s35390a
, int hour
)
106 if (s35390a
->twentyfourhour
)
107 return bin2bcd(hour
);
110 return bin2bcd(hour
);
112 return 0x40 | bin2bcd(hour
- 12);
115 static int s35390a_reg2hr(struct s35390a
*s35390a
, char reg
)
119 if (s35390a
->twentyfourhour
)
120 return bcd2bin(reg
& 0x3f);
122 hour
= bcd2bin(reg
& 0x3f);
129 static int s35390a_set_datetime(struct i2c_client
*client
, struct rtc_time
*tm
)
131 struct s35390a
*s35390a
= i2c_get_clientdata(client
);
135 dev_dbg(&client
->dev
, "%s: tm is secs=%d, mins=%d, hours=%d mday=%d, "
136 "mon=%d, year=%d, wday=%d\n", __func__
, tm
->tm_sec
,
137 tm
->tm_min
, tm
->tm_hour
, tm
->tm_mday
, tm
->tm_mon
, tm
->tm_year
,
140 buf
[S35390A_BYTE_YEAR
] = bin2bcd(tm
->tm_year
- 100);
141 buf
[S35390A_BYTE_MONTH
] = bin2bcd(tm
->tm_mon
+ 1);
142 buf
[S35390A_BYTE_DAY
] = bin2bcd(tm
->tm_mday
);
143 buf
[S35390A_BYTE_WDAY
] = bin2bcd(tm
->tm_wday
);
144 buf
[S35390A_BYTE_HOURS
] = s35390a_hr2reg(s35390a
, tm
->tm_hour
);
145 buf
[S35390A_BYTE_MINS
] = bin2bcd(tm
->tm_min
);
146 buf
[S35390A_BYTE_SECS
] = bin2bcd(tm
->tm_sec
);
148 /* This chip expects the bits of each byte to be in reverse order */
149 for (i
= 0; i
< 7; ++i
)
150 buf
[i
] = bitrev8(buf
[i
]);
152 err
= s35390a_set_reg(s35390a
, S35390A_CMD_TIME1
, buf
, sizeof(buf
));
157 static int s35390a_get_datetime(struct i2c_client
*client
, struct rtc_time
*tm
)
159 struct s35390a
*s35390a
= i2c_get_clientdata(client
);
163 err
= s35390a_get_reg(s35390a
, S35390A_CMD_TIME1
, buf
, sizeof(buf
));
167 /* This chip returns the bits of each byte in reverse order */
168 for (i
= 0; i
< 7; ++i
)
169 buf
[i
] = bitrev8(buf
[i
]);
171 tm
->tm_sec
= bcd2bin(buf
[S35390A_BYTE_SECS
]);
172 tm
->tm_min
= bcd2bin(buf
[S35390A_BYTE_MINS
]);
173 tm
->tm_hour
= s35390a_reg2hr(s35390a
, buf
[S35390A_BYTE_HOURS
]);
174 tm
->tm_wday
= bcd2bin(buf
[S35390A_BYTE_WDAY
]);
175 tm
->tm_mday
= bcd2bin(buf
[S35390A_BYTE_DAY
]);
176 tm
->tm_mon
= bcd2bin(buf
[S35390A_BYTE_MONTH
]) - 1;
177 tm
->tm_year
= bcd2bin(buf
[S35390A_BYTE_YEAR
]) + 100;
179 dev_dbg(&client
->dev
, "%s: tm is secs=%d, mins=%d, hours=%d, mday=%d, "
180 "mon=%d, year=%d, wday=%d\n", __func__
, tm
->tm_sec
,
181 tm
->tm_min
, tm
->tm_hour
, tm
->tm_mday
, tm
->tm_mon
, tm
->tm_year
,
184 return rtc_valid_tm(tm
);
187 static int s35390a_rtc_read_time(struct device
*dev
, struct rtc_time
*tm
)
189 return s35390a_get_datetime(to_i2c_client(dev
), tm
);
192 static int s35390a_rtc_set_time(struct device
*dev
, struct rtc_time
*tm
)
194 return s35390a_set_datetime(to_i2c_client(dev
), tm
);
197 static const struct rtc_class_ops s35390a_rtc_ops
= {
198 .read_time
= s35390a_rtc_read_time
,
199 .set_time
= s35390a_rtc_set_time
,
202 static struct i2c_driver s35390a_driver
;
204 static int s35390a_probe(struct i2c_client
*client
,
205 const struct i2c_device_id
*id
)
209 struct s35390a
*s35390a
;
213 if (!i2c_check_functionality(client
->adapter
, I2C_FUNC_I2C
)) {
218 s35390a
= kzalloc(sizeof(struct s35390a
), GFP_KERNEL
);
224 s35390a
->client
[0] = client
;
225 i2c_set_clientdata(client
, s35390a
);
227 /* This chip uses multiple addresses, use dummy devices for them */
228 for (i
= 1; i
< 8; ++i
) {
229 s35390a
->client
[i
] = i2c_new_dummy(client
->adapter
,
231 if (!s35390a
->client
[i
]) {
232 dev_err(&client
->dev
, "Address %02x unavailable\n",
239 err
= s35390a_reset(s35390a
);
241 dev_err(&client
->dev
, "error resetting chip\n");
245 err
= s35390a_disable_test_mode(s35390a
);
247 dev_err(&client
->dev
, "error disabling test mode\n");
251 err
= s35390a_get_reg(s35390a
, S35390A_CMD_STATUS1
, buf
, sizeof(buf
));
253 dev_err(&client
->dev
, "error checking 12/24 hour mode\n");
256 if (buf
[0] & S35390A_FLAG_24H
)
257 s35390a
->twentyfourhour
= 1;
259 s35390a
->twentyfourhour
= 0;
261 if (s35390a_get_datetime(client
, &tm
) < 0)
262 dev_warn(&client
->dev
, "clock needs to be set\n");
264 s35390a
->rtc
= rtc_device_register(s35390a_driver
.driver
.name
,
265 &client
->dev
, &s35390a_rtc_ops
, THIS_MODULE
);
267 if (IS_ERR(s35390a
->rtc
)) {
268 err
= PTR_ERR(s35390a
->rtc
);
274 for (i
= 1; i
< 8; ++i
)
275 if (s35390a
->client
[i
])
276 i2c_unregister_device(s35390a
->client
[i
]);
283 static int s35390a_remove(struct i2c_client
*client
)
287 struct s35390a
*s35390a
= i2c_get_clientdata(client
);
288 for (i
= 1; i
< 8; ++i
)
289 if (s35390a
->client
[i
])
290 i2c_unregister_device(s35390a
->client
[i
]);
292 rtc_device_unregister(s35390a
->rtc
);
298 static struct i2c_driver s35390a_driver
= {
300 .name
= "rtc-s35390a",
302 .probe
= s35390a_probe
,
303 .remove
= s35390a_remove
,
304 .id_table
= s35390a_id
,
307 static int __init
s35390a_rtc_init(void)
309 return i2c_add_driver(&s35390a_driver
);
312 static void __exit
s35390a_rtc_exit(void)
314 i2c_del_driver(&s35390a_driver
);
317 MODULE_AUTHOR("Byron Bradley <byron.bbradley@gmail.com>");
318 MODULE_DESCRIPTION("S35390A RTC driver");
319 MODULE_LICENSE("GPL");
321 module_init(s35390a_rtc_init
);
322 module_exit(s35390a_rtc_exit
);