drivers/rtc/rtc-m41t80.c: remove disabled alarm functionality
[deliverable/linux.git] / drivers / rtc / rtc-s35390a.c
CommitLineData
c46288b0
BB
1/*
2 * Seiko Instruments S-35390A RTC Driver
3 *
4 * Copyright (c) 2007 Byron Bradley
5 *
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.
10 */
11
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>
18
19#define S35390A_CMD_STATUS1 0
20#define S35390A_CMD_STATUS2 1
21#define S35390A_CMD_TIME1 2
22
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
30
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
36
3760f736
JD
37static const struct i2c_device_id s35390a_id[] = {
38 { "s35390a", 0 },
39 { }
40};
41MODULE_DEVICE_TABLE(i2c, s35390a_id);
42
c46288b0
BB
43struct s35390a {
44 struct i2c_client *client[8];
45 struct rtc_device *rtc;
46 int twentyfourhour;
47};
48
49static int s35390a_set_reg(struct s35390a *s35390a, int reg, char *buf, int len)
50{
51 struct i2c_client *client = s35390a->client[reg];
52 struct i2c_msg msg[] = {
65659f63
S
53 {
54 .addr = client->addr,
55 .len = len,
56 .buf = buf
57 },
c46288b0
BB
58 };
59
60 if ((i2c_transfer(client->adapter, msg, 1)) != 1)
61 return -EIO;
62
63 return 0;
64}
65
66static int s35390a_get_reg(struct s35390a *s35390a, int reg, char *buf, int len)
67{
68 struct i2c_client *client = s35390a->client[reg];
69 struct i2c_msg msg[] = {
65659f63
S
70 {
71 .addr = client->addr,
72 .flags = I2C_M_RD,
73 .len = len,
74 .buf = buf
75 },
c46288b0
BB
76 };
77
78 if ((i2c_transfer(client->adapter, msg, 1)) != 1)
79 return -EIO;
80
81 return 0;
82}
83
84static int s35390a_reset(struct s35390a *s35390a)
85{
86 char buf[1];
87
88 if (s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, buf, sizeof(buf)) < 0)
89 return -EIO;
90
91 if (!(buf[0] & (S35390A_FLAG_POC | S35390A_FLAG_BLD)))
92 return 0;
93
94 buf[0] |= (S35390A_FLAG_RESET | S35390A_FLAG_24H);
95 buf[0] &= 0xf0;
96 return s35390a_set_reg(s35390a, S35390A_CMD_STATUS1, buf, sizeof(buf));
97}
98
99static int s35390a_disable_test_mode(struct s35390a *s35390a)
100{
101 char buf[1];
102
103 if (s35390a_get_reg(s35390a, S35390A_CMD_STATUS2, buf, sizeof(buf)) < 0)
104 return -EIO;
105
106 if (!(buf[0] & S35390A_FLAG_TEST))
107 return 0;
108
109 buf[0] &= ~S35390A_FLAG_TEST;
110 return s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, buf, sizeof(buf));
111}
112
113static char s35390a_hr2reg(struct s35390a *s35390a, int hour)
114{
115 if (s35390a->twentyfourhour)
fe20ba70 116 return bin2bcd(hour);
c46288b0
BB
117
118 if (hour < 12)
fe20ba70 119 return bin2bcd(hour);
c46288b0 120
fe20ba70 121 return 0x40 | bin2bcd(hour - 12);
c46288b0
BB
122}
123
124static int s35390a_reg2hr(struct s35390a *s35390a, char reg)
125{
126 unsigned hour;
127
128 if (s35390a->twentyfourhour)
fe20ba70 129 return bcd2bin(reg & 0x3f);
c46288b0 130
fe20ba70 131 hour = bcd2bin(reg & 0x3f);
c46288b0
BB
132 if (reg & 0x40)
133 hour += 12;
134
135 return hour;
136}
137
138static int s35390a_set_datetime(struct i2c_client *client, struct rtc_time *tm)
139{
140 struct s35390a *s35390a = i2c_get_clientdata(client);
141 int i, err;
142 char buf[7];
143
144 dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d mday=%d, "
145 "mon=%d, year=%d, wday=%d\n", __func__, tm->tm_sec,
146 tm->tm_min, tm->tm_hour, tm->tm_mday, tm->tm_mon, tm->tm_year,
147 tm->tm_wday);
148
fe20ba70
AB
149 buf[S35390A_BYTE_YEAR] = bin2bcd(tm->tm_year - 100);
150 buf[S35390A_BYTE_MONTH] = bin2bcd(tm->tm_mon + 1);
151 buf[S35390A_BYTE_DAY] = bin2bcd(tm->tm_mday);
152 buf[S35390A_BYTE_WDAY] = bin2bcd(tm->tm_wday);
c46288b0 153 buf[S35390A_BYTE_HOURS] = s35390a_hr2reg(s35390a, tm->tm_hour);
fe20ba70
AB
154 buf[S35390A_BYTE_MINS] = bin2bcd(tm->tm_min);
155 buf[S35390A_BYTE_SECS] = bin2bcd(tm->tm_sec);
c46288b0
BB
156
157 /* This chip expects the bits of each byte to be in reverse order */
158 for (i = 0; i < 7; ++i)
159 buf[i] = bitrev8(buf[i]);
160
161 err = s35390a_set_reg(s35390a, S35390A_CMD_TIME1, buf, sizeof(buf));
162
163 return err;
164}
165
166static int s35390a_get_datetime(struct i2c_client *client, struct rtc_time *tm)
167{
168 struct s35390a *s35390a = i2c_get_clientdata(client);
169 char buf[7];
170 int i, err;
171
172 err = s35390a_get_reg(s35390a, S35390A_CMD_TIME1, buf, sizeof(buf));
173 if (err < 0)
174 return err;
175
176 /* This chip returns the bits of each byte in reverse order */
177 for (i = 0; i < 7; ++i)
178 buf[i] = bitrev8(buf[i]);
179
fe20ba70
AB
180 tm->tm_sec = bcd2bin(buf[S35390A_BYTE_SECS]);
181 tm->tm_min = bcd2bin(buf[S35390A_BYTE_MINS]);
c46288b0 182 tm->tm_hour = s35390a_reg2hr(s35390a, buf[S35390A_BYTE_HOURS]);
fe20ba70
AB
183 tm->tm_wday = bcd2bin(buf[S35390A_BYTE_WDAY]);
184 tm->tm_mday = bcd2bin(buf[S35390A_BYTE_DAY]);
185 tm->tm_mon = bcd2bin(buf[S35390A_BYTE_MONTH]) - 1;
186 tm->tm_year = bcd2bin(buf[S35390A_BYTE_YEAR]) + 100;
c46288b0
BB
187
188 dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, mday=%d, "
189 "mon=%d, year=%d, wday=%d\n", __func__, tm->tm_sec,
190 tm->tm_min, tm->tm_hour, tm->tm_mday, tm->tm_mon, tm->tm_year,
191 tm->tm_wday);
192
193 return rtc_valid_tm(tm);
194}
195
196static int s35390a_rtc_read_time(struct device *dev, struct rtc_time *tm)
197{
198 return s35390a_get_datetime(to_i2c_client(dev), tm);
199}
200
201static int s35390a_rtc_set_time(struct device *dev, struct rtc_time *tm)
202{
203 return s35390a_set_datetime(to_i2c_client(dev), tm);
204}
205
206static const struct rtc_class_ops s35390a_rtc_ops = {
207 .read_time = s35390a_rtc_read_time,
208 .set_time = s35390a_rtc_set_time,
209};
210
211static struct i2c_driver s35390a_driver;
212
d2653e92
JD
213static int s35390a_probe(struct i2c_client *client,
214 const struct i2c_device_id *id)
c46288b0
BB
215{
216 int err;
217 unsigned int i;
218 struct s35390a *s35390a;
219 struct rtc_time tm;
220 char buf[1];
221
222 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
223 err = -ENODEV;
224 goto exit;
225 }
226
227 s35390a = kzalloc(sizeof(struct s35390a), GFP_KERNEL);
228 if (!s35390a) {
229 err = -ENOMEM;
230 goto exit;
231 }
232
233 s35390a->client[0] = client;
234 i2c_set_clientdata(client, s35390a);
235
236 /* This chip uses multiple addresses, use dummy devices for them */
237 for (i = 1; i < 8; ++i) {
238 s35390a->client[i] = i2c_new_dummy(client->adapter,
60b129d7 239 client->addr + i);
c46288b0
BB
240 if (!s35390a->client[i]) {
241 dev_err(&client->dev, "Address %02x unavailable\n",
242 client->addr + i);
243 err = -EBUSY;
244 goto exit_dummy;
245 }
246 }
247
248 err = s35390a_reset(s35390a);
249 if (err < 0) {
250 dev_err(&client->dev, "error resetting chip\n");
251 goto exit_dummy;
252 }
253
254 err = s35390a_disable_test_mode(s35390a);
255 if (err < 0) {
256 dev_err(&client->dev, "error disabling test mode\n");
257 goto exit_dummy;
258 }
259
260 err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, buf, sizeof(buf));
261 if (err < 0) {
262 dev_err(&client->dev, "error checking 12/24 hour mode\n");
263 goto exit_dummy;
264 }
265 if (buf[0] & S35390A_FLAG_24H)
266 s35390a->twentyfourhour = 1;
267 else
268 s35390a->twentyfourhour = 0;
269
270 if (s35390a_get_datetime(client, &tm) < 0)
271 dev_warn(&client->dev, "clock needs to be set\n");
272
273 s35390a->rtc = rtc_device_register(s35390a_driver.driver.name,
274 &client->dev, &s35390a_rtc_ops, THIS_MODULE);
275
276 if (IS_ERR(s35390a->rtc)) {
277 err = PTR_ERR(s35390a->rtc);
278 goto exit_dummy;
279 }
280 return 0;
281
282exit_dummy:
283 for (i = 1; i < 8; ++i)
284 if (s35390a->client[i])
285 i2c_unregister_device(s35390a->client[i]);
286 kfree(s35390a);
c46288b0
BB
287
288exit:
289 return err;
290}
291
292static int s35390a_remove(struct i2c_client *client)
293{
294 unsigned int i;
295
296 struct s35390a *s35390a = i2c_get_clientdata(client);
297 for (i = 1; i < 8; ++i)
298 if (s35390a->client[i])
299 i2c_unregister_device(s35390a->client[i]);
300
301 rtc_device_unregister(s35390a->rtc);
302 kfree(s35390a);
c46288b0
BB
303
304 return 0;
305}
306
307static struct i2c_driver s35390a_driver = {
308 .driver = {
309 .name = "rtc-s35390a",
310 },
311 .probe = s35390a_probe,
312 .remove = s35390a_remove,
3760f736 313 .id_table = s35390a_id,
c46288b0
BB
314};
315
0abc9201 316module_i2c_driver(s35390a_driver);
c46288b0
BB
317
318MODULE_AUTHOR("Byron Bradley <byron.bbradley@gmail.com>");
319MODULE_DESCRIPTION("S35390A RTC driver");
320MODULE_LICENSE("GPL");
This page took 0.378528 seconds and 5 git commands to generate.