blob: 83c3b3029fa774321332961b7abad8796088686b [file] [log] [blame]
Sergey Lapinc6d8f402008-06-12 15:21:55 -07001/*
2 * rtc-fm3130.c - RTC driver for Ramtron FM3130 I2C chip.
3 *
4 * Copyright (C) 2008 Sergey Lapin
5 * Based on ds1307 driver by James Chapman and David Brownell
6 *
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.
10 */
11
12#include <linux/module.h>
13#include <linux/i2c.h>
14#include <linux/rtc.h>
15#include <linux/bcd.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090016#include <linux/slab.h>
Sergey Lapinc6d8f402008-06-12 15:21:55 -070017
18#define FM3130_RTC_CONTROL (0x0)
19#define FM3130_CAL_CONTROL (0x1)
20#define FM3130_RTC_SECONDS (0x2)
21#define FM3130_RTC_MINUTES (0x3)
22#define FM3130_RTC_HOURS (0x4)
23#define FM3130_RTC_DAY (0x5)
24#define FM3130_RTC_DATE (0x6)
25#define FM3130_RTC_MONTHS (0x7)
26#define FM3130_RTC_YEARS (0x8)
27
28#define FM3130_ALARM_SECONDS (0x9)
29#define FM3130_ALARM_MINUTES (0xa)
30#define FM3130_ALARM_HOURS (0xb)
31#define FM3130_ALARM_DATE (0xc)
32#define FM3130_ALARM_MONTHS (0xd)
33#define FM3130_ALARM_WP_CONTROL (0xe)
34
35#define FM3130_CAL_CONTROL_BIT_nOSCEN (1 << 7) /* Osciallator enabled */
36#define FM3130_RTC_CONTROL_BIT_LB (1 << 7) /* Low battery */
37#define FM3130_RTC_CONTROL_BIT_AF (1 << 6) /* Alarm flag */
38#define FM3130_RTC_CONTROL_BIT_CF (1 << 5) /* Century overflow */
39#define FM3130_RTC_CONTROL_BIT_POR (1 << 4) /* Power on reset */
40#define FM3130_RTC_CONTROL_BIT_AEN (1 << 3) /* Alarm enable */
41#define FM3130_RTC_CONTROL_BIT_CAL (1 << 2) /* Calibration mode */
42#define FM3130_RTC_CONTROL_BIT_WRITE (1 << 1) /* W=1 -> write mode W=0 normal */
43#define FM3130_RTC_CONTROL_BIT_READ (1 << 0) /* R=1 -> read mode R=0 normal */
44
45#define FM3130_CLOCK_REGS 7
46#define FM3130_ALARM_REGS 5
47
48struct fm3130 {
49 u8 reg_addr_time;
Sachin Kamatc865e922013-07-03 15:05:51 -070050 u8 reg_addr_alarm;
Sergey Lapinc6d8f402008-06-12 15:21:55 -070051 u8 regs[15];
52 struct i2c_msg msg[4];
53 struct i2c_client *client;
54 struct rtc_device *rtc;
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -070055 int alarm_valid;
Sergey Lapinc6d8f402008-06-12 15:21:55 -070056 int data_valid;
Sergey Lapinc6d8f402008-06-12 15:21:55 -070057};
58static const struct i2c_device_id fm3130_id[] = {
Alessandro Zummo876550a2008-07-12 13:47:55 -070059 { "fm3130", 0 },
Sergey Lapinc6d8f402008-06-12 15:21:55 -070060 { }
61};
62MODULE_DEVICE_TABLE(i2c, fm3130_id);
63
64#define FM3130_MODE_NORMAL 0
65#define FM3130_MODE_WRITE 1
66#define FM3130_MODE_READ 2
67
68static void fm3130_rtc_mode(struct device *dev, int mode)
69{
70 struct fm3130 *fm3130 = dev_get_drvdata(dev);
71
72 fm3130->regs[FM3130_RTC_CONTROL] =
73 i2c_smbus_read_byte_data(fm3130->client, FM3130_RTC_CONTROL);
74 switch (mode) {
75 case FM3130_MODE_NORMAL:
76 fm3130->regs[FM3130_RTC_CONTROL] &=
77 ~(FM3130_RTC_CONTROL_BIT_WRITE |
78 FM3130_RTC_CONTROL_BIT_READ);
79 break;
80 case FM3130_MODE_WRITE:
81 fm3130->regs[FM3130_RTC_CONTROL] |= FM3130_RTC_CONTROL_BIT_WRITE;
82 break;
83 case FM3130_MODE_READ:
84 fm3130->regs[FM3130_RTC_CONTROL] |= FM3130_RTC_CONTROL_BIT_READ;
85 break;
86 default:
87 dev_dbg(dev, "invalid mode %d\n", mode);
88 break;
89 }
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -070090
Sergey Lapinc6d8f402008-06-12 15:21:55 -070091 i2c_smbus_write_byte_data(fm3130->client,
92 FM3130_RTC_CONTROL, fm3130->regs[FM3130_RTC_CONTROL]);
93}
94
95static int fm3130_get_time(struct device *dev, struct rtc_time *t)
96{
97 struct fm3130 *fm3130 = dev_get_drvdata(dev);
98 int tmp;
99
100 if (!fm3130->data_valid) {
101 /* We have invalid data in RTC, probably due
102 to battery faults or other problems. Return EIO
Uwe Kleine-Königfd0961f2010-06-11 12:16:56 +0200103 for now, it will allow us to set data later instead
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700104 of error during probing which disables device */
105 return -EIO;
106 }
107 fm3130_rtc_mode(dev, FM3130_MODE_READ);
108
109 /* read the RTC date and time registers all at once */
110 tmp = i2c_transfer(to_i2c_adapter(fm3130->client->dev.parent),
111 fm3130->msg, 2);
112 if (tmp != 2) {
113 dev_err(dev, "%s error %d\n", "read", tmp);
114 return -EIO;
115 }
116
117 fm3130_rtc_mode(dev, FM3130_MODE_NORMAL);
118
Andy Shevchenko01a4ca12013-02-21 16:44:22 -0800119 dev_dbg(dev, "%s: %15ph\n", "read", fm3130->regs);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700120
Adrian Bunkfe20ba72008-10-18 20:28:41 -0700121 t->tm_sec = bcd2bin(fm3130->regs[FM3130_RTC_SECONDS] & 0x7f);
122 t->tm_min = bcd2bin(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700123 tmp = fm3130->regs[FM3130_RTC_HOURS] & 0x3f;
Adrian Bunkfe20ba72008-10-18 20:28:41 -0700124 t->tm_hour = bcd2bin(tmp);
125 t->tm_wday = bcd2bin(fm3130->regs[FM3130_RTC_DAY] & 0x07) - 1;
126 t->tm_mday = bcd2bin(fm3130->regs[FM3130_RTC_DATE] & 0x3f);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700127 tmp = fm3130->regs[FM3130_RTC_MONTHS] & 0x1f;
Adrian Bunkfe20ba72008-10-18 20:28:41 -0700128 t->tm_mon = bcd2bin(tmp) - 1;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700129
130 /* assume 20YY not 19YY, and ignore CF bit */
Adrian Bunkfe20ba72008-10-18 20:28:41 -0700131 t->tm_year = bcd2bin(fm3130->regs[FM3130_RTC_YEARS]) + 100;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700132
133 dev_dbg(dev, "%s secs=%d, mins=%d, "
134 "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
135 "read", t->tm_sec, t->tm_min,
136 t->tm_hour, t->tm_mday,
137 t->tm_mon, t->tm_year, t->tm_wday);
138
139 /* initial clock setting can be undefined */
140 return rtc_valid_tm(t);
141}
142
143
144static int fm3130_set_time(struct device *dev, struct rtc_time *t)
145{
146 struct fm3130 *fm3130 = dev_get_drvdata(dev);
147 int tmp, i;
148 u8 *buf = fm3130->regs;
149
150 dev_dbg(dev, "%s secs=%d, mins=%d, "
151 "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
152 "write", t->tm_sec, t->tm_min,
153 t->tm_hour, t->tm_mday,
154 t->tm_mon, t->tm_year, t->tm_wday);
155
156 /* first register addr */
Adrian Bunkfe20ba72008-10-18 20:28:41 -0700157 buf[FM3130_RTC_SECONDS] = bin2bcd(t->tm_sec);
158 buf[FM3130_RTC_MINUTES] = bin2bcd(t->tm_min);
159 buf[FM3130_RTC_HOURS] = bin2bcd(t->tm_hour);
160 buf[FM3130_RTC_DAY] = bin2bcd(t->tm_wday + 1);
161 buf[FM3130_RTC_DATE] = bin2bcd(t->tm_mday);
162 buf[FM3130_RTC_MONTHS] = bin2bcd(t->tm_mon + 1);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700163
164 /* assume 20YY not 19YY */
165 tmp = t->tm_year - 100;
Adrian Bunkfe20ba72008-10-18 20:28:41 -0700166 buf[FM3130_RTC_YEARS] = bin2bcd(tmp);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700167
Andy Shevchenko01a4ca12013-02-21 16:44:22 -0800168 dev_dbg(dev, "%s: %15ph\n", "write", buf);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700169
170 fm3130_rtc_mode(dev, FM3130_MODE_WRITE);
171
172 /* Writing time registers, we don't support multibyte transfers */
173 for (i = 0; i < FM3130_CLOCK_REGS; i++) {
174 i2c_smbus_write_byte_data(fm3130->client,
175 FM3130_RTC_SECONDS + i,
176 fm3130->regs[FM3130_RTC_SECONDS + i]);
177 }
178
179 fm3130_rtc_mode(dev, FM3130_MODE_NORMAL);
180
181 /* We assume here that data are valid once written */
182 if (!fm3130->data_valid)
183 fm3130->data_valid = 1;
184 return 0;
185}
186
187static int fm3130_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
188{
189 struct fm3130 *fm3130 = dev_get_drvdata(dev);
190 int tmp;
191 struct rtc_time *tm = &alrm->time;
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700192
193 if (!fm3130->alarm_valid) {
194 /*
195 * We have invalid alarm in RTC, probably due to battery faults
196 * or other problems. Return EIO for now, it will allow us to
197 * set alarm value later instead of error during probing which
198 * disables device
199 */
200 return -EIO;
201 }
202
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700203 /* read the RTC alarm registers all at once */
204 tmp = i2c_transfer(to_i2c_adapter(fm3130->client->dev.parent),
205 &fm3130->msg[2], 2);
206 if (tmp != 2) {
207 dev_err(dev, "%s error %d\n", "read", tmp);
208 return -EIO;
209 }
210 dev_dbg(dev, "alarm read %02x %02x %02x %02x %02x\n",
211 fm3130->regs[FM3130_ALARM_SECONDS],
212 fm3130->regs[FM3130_ALARM_MINUTES],
213 fm3130->regs[FM3130_ALARM_HOURS],
214 fm3130->regs[FM3130_ALARM_DATE],
215 fm3130->regs[FM3130_ALARM_MONTHS]);
216
Adrian Bunkfe20ba72008-10-18 20:28:41 -0700217 tm->tm_sec = bcd2bin(fm3130->regs[FM3130_ALARM_SECONDS] & 0x7F);
218 tm->tm_min = bcd2bin(fm3130->regs[FM3130_ALARM_MINUTES] & 0x7F);
219 tm->tm_hour = bcd2bin(fm3130->regs[FM3130_ALARM_HOURS] & 0x3F);
220 tm->tm_mday = bcd2bin(fm3130->regs[FM3130_ALARM_DATE] & 0x3F);
221 tm->tm_mon = bcd2bin(fm3130->regs[FM3130_ALARM_MONTHS] & 0x1F);
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700222
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700223 if (tm->tm_mon > 0)
224 tm->tm_mon -= 1; /* RTC is 1-12, tm_mon is 0-11 */
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700225
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700226 dev_dbg(dev, "%s secs=%d, mins=%d, "
227 "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
228 "read alarm", tm->tm_sec, tm->tm_min,
229 tm->tm_hour, tm->tm_mday,
230 tm->tm_mon, tm->tm_year, tm->tm_wday);
231
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700232 /* check if alarm enabled */
233 fm3130->regs[FM3130_RTC_CONTROL] =
234 i2c_smbus_read_byte_data(fm3130->client, FM3130_RTC_CONTROL);
235
236 if ((fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_AEN) &&
237 (~fm3130->regs[FM3130_RTC_CONTROL] &
238 FM3130_RTC_CONTROL_BIT_CAL)) {
239 alrm->enabled = 1;
240 }
241
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700242 return 0;
243}
244
245static int fm3130_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
246{
247 struct fm3130 *fm3130 = dev_get_drvdata(dev);
248 struct rtc_time *tm = &alrm->time;
249 int i;
250
251 dev_dbg(dev, "%s secs=%d, mins=%d, "
252 "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
253 "write alarm", tm->tm_sec, tm->tm_min,
254 tm->tm_hour, tm->tm_mday,
255 tm->tm_mon, tm->tm_year, tm->tm_wday);
256
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700257 fm3130->regs[FM3130_ALARM_SECONDS] =
258 (tm->tm_sec != -1) ? bin2bcd(tm->tm_sec) : 0x80;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700259
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700260 fm3130->regs[FM3130_ALARM_MINUTES] =
261 (tm->tm_min != -1) ? bin2bcd(tm->tm_min) : 0x80;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700262
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700263 fm3130->regs[FM3130_ALARM_HOURS] =
264 (tm->tm_hour != -1) ? bin2bcd(tm->tm_hour) : 0x80;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700265
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700266 fm3130->regs[FM3130_ALARM_DATE] =
267 (tm->tm_mday != -1) ? bin2bcd(tm->tm_mday) : 0x80;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700268
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700269 fm3130->regs[FM3130_ALARM_MONTHS] =
270 (tm->tm_mon != -1) ? bin2bcd(tm->tm_mon + 1) : 0x80;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700271
272 dev_dbg(dev, "alarm write %02x %02x %02x %02x %02x\n",
273 fm3130->regs[FM3130_ALARM_SECONDS],
274 fm3130->regs[FM3130_ALARM_MINUTES],
275 fm3130->regs[FM3130_ALARM_HOURS],
276 fm3130->regs[FM3130_ALARM_DATE],
277 fm3130->regs[FM3130_ALARM_MONTHS]);
278 /* Writing time registers, we don't support multibyte transfers */
279 for (i = 0; i < FM3130_ALARM_REGS; i++) {
280 i2c_smbus_write_byte_data(fm3130->client,
281 FM3130_ALARM_SECONDS + i,
282 fm3130->regs[FM3130_ALARM_SECONDS + i]);
283 }
284 fm3130->regs[FM3130_RTC_CONTROL] =
285 i2c_smbus_read_byte_data(fm3130->client, FM3130_RTC_CONTROL);
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700286
287 /* enable or disable alarm */
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700288 if (alrm->enabled) {
289 i2c_smbus_write_byte_data(fm3130->client, FM3130_RTC_CONTROL,
290 (fm3130->regs[FM3130_RTC_CONTROL] &
291 ~(FM3130_RTC_CONTROL_BIT_CAL)) |
292 FM3130_RTC_CONTROL_BIT_AEN);
293 } else {
294 i2c_smbus_write_byte_data(fm3130->client, FM3130_RTC_CONTROL,
295 fm3130->regs[FM3130_RTC_CONTROL] &
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700296 ~(FM3130_RTC_CONTROL_BIT_CAL) &
297 ~(FM3130_RTC_CONTROL_BIT_AEN));
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700298 }
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700299
300 /* We assume here that data is valid once written */
301 if (!fm3130->alarm_valid)
302 fm3130->alarm_valid = 1;
303
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700304 return 0;
305}
306
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700307static int fm3130_alarm_irq_enable(struct device *dev, unsigned int enabled)
308{
309 struct fm3130 *fm3130 = dev_get_drvdata(dev);
310 int ret = 0;
311
312 fm3130->regs[FM3130_RTC_CONTROL] =
313 i2c_smbus_read_byte_data(fm3130->client, FM3130_RTC_CONTROL);
314
315 dev_dbg(dev, "alarm_irq_enable: enable=%d, FM3130_RTC_CONTROL=%02x\n",
316 enabled, fm3130->regs[FM3130_RTC_CONTROL]);
317
318 switch (enabled) {
319 case 0: /* alarm off */
320 ret = i2c_smbus_write_byte_data(fm3130->client,
321 FM3130_RTC_CONTROL, fm3130->regs[FM3130_RTC_CONTROL] &
322 ~(FM3130_RTC_CONTROL_BIT_CAL) &
323 ~(FM3130_RTC_CONTROL_BIT_AEN));
324 break;
325 case 1: /* alarm on */
326 ret = i2c_smbus_write_byte_data(fm3130->client,
327 FM3130_RTC_CONTROL, (fm3130->regs[FM3130_RTC_CONTROL] &
328 ~(FM3130_RTC_CONTROL_BIT_CAL)) |
329 FM3130_RTC_CONTROL_BIT_AEN);
330 break;
331 default:
332 ret = -EINVAL;
333 break;
334 }
335
336 return ret;
337}
338
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700339static const struct rtc_class_ops fm3130_rtc_ops = {
340 .read_time = fm3130_get_time,
341 .set_time = fm3130_set_time,
342 .read_alarm = fm3130_read_alarm,
343 .set_alarm = fm3130_set_alarm,
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700344 .alarm_irq_enable = fm3130_alarm_irq_enable,
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700345};
346
347static struct i2c_driver fm3130_driver;
348
Greg Kroah-Hartman5a167f42012-12-21 13:09:38 -0800349static int fm3130_probe(struct i2c_client *client,
350 const struct i2c_device_id *id)
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700351{
352 struct fm3130 *fm3130;
353 int err = -ENODEV;
354 int tmp;
355 struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
356
357 if (!i2c_check_functionality(adapter,
358 I2C_FUNC_I2C | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
359 return -EIO;
360
Jingoo Hanc54a52e2013-04-29 16:20:41 -0700361 fm3130 = devm_kzalloc(&client->dev, sizeof(struct fm3130), GFP_KERNEL);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700362
363 if (!fm3130)
364 return -ENOMEM;
365
366 fm3130->client = client;
367 i2c_set_clientdata(client, fm3130);
368 fm3130->reg_addr_time = FM3130_RTC_SECONDS;
369 fm3130->reg_addr_alarm = FM3130_ALARM_SECONDS;
370
371 /* Messages to read time */
372 fm3130->msg[0].addr = client->addr;
373 fm3130->msg[0].flags = 0;
374 fm3130->msg[0].len = 1;
375 fm3130->msg[0].buf = &fm3130->reg_addr_time;
376
377 fm3130->msg[1].addr = client->addr;
378 fm3130->msg[1].flags = I2C_M_RD;
379 fm3130->msg[1].len = FM3130_CLOCK_REGS;
380 fm3130->msg[1].buf = &fm3130->regs[FM3130_RTC_SECONDS];
381
382 /* Messages to read alarm */
383 fm3130->msg[2].addr = client->addr;
384 fm3130->msg[2].flags = 0;
385 fm3130->msg[2].len = 1;
386 fm3130->msg[2].buf = &fm3130->reg_addr_alarm;
387
388 fm3130->msg[3].addr = client->addr;
389 fm3130->msg[3].flags = I2C_M_RD;
390 fm3130->msg[3].len = FM3130_ALARM_REGS;
391 fm3130->msg[3].buf = &fm3130->regs[FM3130_ALARM_SECONDS];
392
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700393 fm3130->alarm_valid = 0;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700394 fm3130->data_valid = 0;
395
396 tmp = i2c_transfer(adapter, fm3130->msg, 4);
397 if (tmp != 4) {
Jingoo Han198b8ec2013-04-29 16:19:29 -0700398 dev_dbg(&client->dev, "read error %d\n", tmp);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700399 err = -EIO;
400 goto exit_free;
401 }
402
403 fm3130->regs[FM3130_RTC_CONTROL] =
404 i2c_smbus_read_byte_data(client, FM3130_RTC_CONTROL);
405 fm3130->regs[FM3130_CAL_CONTROL] =
406 i2c_smbus_read_byte_data(client, FM3130_CAL_CONTROL);
407
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700408 /* Disabling calibration mode */
Sergey Matyukevichf4b51622010-02-02 13:43:59 -0800409 if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_CAL) {
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700410 i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL,
411 fm3130->regs[FM3130_RTC_CONTROL] &
412 ~(FM3130_RTC_CONTROL_BIT_CAL));
413 dev_warn(&client->dev, "Disabling calibration mode!\n");
Sergey Matyukevichf4b51622010-02-02 13:43:59 -0800414 }
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700415
416 /* Disabling read and write modes */
417 if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_WRITE ||
Sergey Matyukevichf4b51622010-02-02 13:43:59 -0800418 fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_READ) {
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700419 i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL,
420 fm3130->regs[FM3130_RTC_CONTROL] &
421 ~(FM3130_RTC_CONTROL_BIT_READ |
422 FM3130_RTC_CONTROL_BIT_WRITE));
423 dev_warn(&client->dev, "Disabling READ or WRITE mode!\n");
Sergey Matyukevichf4b51622010-02-02 13:43:59 -0800424 }
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700425
426 /* oscillator off? turn it on, so clock can tick. */
427 if (fm3130->regs[FM3130_CAL_CONTROL] & FM3130_CAL_CONTROL_BIT_nOSCEN)
428 i2c_smbus_write_byte_data(client, FM3130_CAL_CONTROL,
429 fm3130->regs[FM3130_CAL_CONTROL] &
430 ~(FM3130_CAL_CONTROL_BIT_nOSCEN));
431
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700432 /* low battery? clear flag, and warn */
433 if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_LB) {
434 i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL,
435 fm3130->regs[FM3130_RTC_CONTROL] &
436 ~(FM3130_RTC_CONTROL_BIT_LB));
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700437 dev_warn(&client->dev, "Low battery!\n");
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700438 }
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700439
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700440 /* check if Power On Reset bit is set */
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700441 if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_POR) {
442 i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL,
443 fm3130->regs[FM3130_RTC_CONTROL] &
444 ~FM3130_RTC_CONTROL_BIT_POR);
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700445 dev_dbg(&client->dev, "POR bit is set\n");
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700446 }
447 /* ACS is controlled by alarm */
448 i2c_smbus_write_byte_data(client, FM3130_ALARM_WP_CONTROL, 0x80);
449
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700450 /* alarm registers sanity check */
451 tmp = bcd2bin(fm3130->regs[FM3130_RTC_SECONDS] & 0x7f);
452 if (tmp > 59)
453 goto bad_alarm;
454
Adrian Bunkfe20ba72008-10-18 20:28:41 -0700455 tmp = bcd2bin(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f);
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700456 if (tmp > 59)
457 goto bad_alarm;
458
459 tmp = bcd2bin(fm3130->regs[FM3130_RTC_HOURS] & 0x3f);
460 if (tmp > 23)
461 goto bad_alarm;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700462
Adrian Bunkfe20ba72008-10-18 20:28:41 -0700463 tmp = bcd2bin(fm3130->regs[FM3130_RTC_DATE] & 0x3f);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700464 if (tmp == 0 || tmp > 31)
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700465 goto bad_alarm;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700466
Adrian Bunkfe20ba72008-10-18 20:28:41 -0700467 tmp = bcd2bin(fm3130->regs[FM3130_RTC_MONTHS] & 0x1f);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700468 if (tmp == 0 || tmp > 12)
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700469 goto bad_alarm;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700470
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700471 fm3130->alarm_valid = 1;
472
473bad_alarm:
474
475 /* clock registers sanity chek */
476 tmp = bcd2bin(fm3130->regs[FM3130_RTC_SECONDS] & 0x7f);
477 if (tmp > 59)
478 goto bad_clock;
479
480 tmp = bcd2bin(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f);
481 if (tmp > 59)
482 goto bad_clock;
483
484 tmp = bcd2bin(fm3130->regs[FM3130_RTC_HOURS] & 0x3f);
485 if (tmp > 23)
486 goto bad_clock;
487
488 tmp = bcd2bin(fm3130->regs[FM3130_RTC_DAY] & 0x7);
489 if (tmp == 0 || tmp > 7)
490 goto bad_clock;
491
492 tmp = bcd2bin(fm3130->regs[FM3130_RTC_DATE] & 0x3f);
493 if (tmp == 0 || tmp > 31)
494 goto bad_clock;
495
496 tmp = bcd2bin(fm3130->regs[FM3130_RTC_MONTHS] & 0x1f);
497 if (tmp == 0 || tmp > 12)
498 goto bad_clock;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700499
500 fm3130->data_valid = 1;
501
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700502bad_clock:
503
504 if (!fm3130->data_valid || !fm3130->alarm_valid)
Andy Shevchenko01a4ca12013-02-21 16:44:22 -0800505 dev_dbg(&client->dev, "%s: %15ph\n", "bogus registers",
506 fm3130->regs);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700507
508 /* We won't bail out here because we just got invalid data.
509 Time setting from u-boot doesn't work anyway */
Jingoo Hanc54a52e2013-04-29 16:20:41 -0700510 fm3130->rtc = devm_rtc_device_register(&client->dev, client->name,
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700511 &fm3130_rtc_ops, THIS_MODULE);
512 if (IS_ERR(fm3130->rtc)) {
513 err = PTR_ERR(fm3130->rtc);
514 dev_err(&client->dev,
515 "unable to register the class device\n");
516 goto exit_free;
517 }
518 return 0;
519exit_free:
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700520 return err;
521}
522
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700523static struct i2c_driver fm3130_driver = {
524 .driver = {
525 .name = "rtc-fm3130",
526 .owner = THIS_MODULE,
527 },
528 .probe = fm3130_probe,
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700529 .id_table = fm3130_id,
530};
531
Axel Lin0abc9202012-03-23 15:02:31 -0700532module_i2c_driver(fm3130_driver);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700533
534MODULE_DESCRIPTION("RTC driver for FM3130");
535MODULE_AUTHOR("Sergey Lapin <slapin@ossfans.org>");
536MODULE_LICENSE("GPL");
537