blob: e1137670d4d27e846e4ecaecb020275205977230 [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
Alexandre Belloni22652ba2018-02-19 16:23:56 +0100139 return 0;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700140}
141
142
143static int fm3130_set_time(struct device *dev, struct rtc_time *t)
144{
145 struct fm3130 *fm3130 = dev_get_drvdata(dev);
146 int tmp, i;
147 u8 *buf = fm3130->regs;
148
149 dev_dbg(dev, "%s secs=%d, mins=%d, "
150 "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
151 "write", t->tm_sec, t->tm_min,
152 t->tm_hour, t->tm_mday,
153 t->tm_mon, t->tm_year, t->tm_wday);
154
155 /* first register addr */
Adrian Bunkfe20ba72008-10-18 20:28:41 -0700156 buf[FM3130_RTC_SECONDS] = bin2bcd(t->tm_sec);
157 buf[FM3130_RTC_MINUTES] = bin2bcd(t->tm_min);
158 buf[FM3130_RTC_HOURS] = bin2bcd(t->tm_hour);
159 buf[FM3130_RTC_DAY] = bin2bcd(t->tm_wday + 1);
160 buf[FM3130_RTC_DATE] = bin2bcd(t->tm_mday);
161 buf[FM3130_RTC_MONTHS] = bin2bcd(t->tm_mon + 1);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700162
163 /* assume 20YY not 19YY */
164 tmp = t->tm_year - 100;
Adrian Bunkfe20ba72008-10-18 20:28:41 -0700165 buf[FM3130_RTC_YEARS] = bin2bcd(tmp);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700166
Andy Shevchenko01a4ca12013-02-21 16:44:22 -0800167 dev_dbg(dev, "%s: %15ph\n", "write", buf);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700168
169 fm3130_rtc_mode(dev, FM3130_MODE_WRITE);
170
171 /* Writing time registers, we don't support multibyte transfers */
172 for (i = 0; i < FM3130_CLOCK_REGS; i++) {
173 i2c_smbus_write_byte_data(fm3130->client,
174 FM3130_RTC_SECONDS + i,
175 fm3130->regs[FM3130_RTC_SECONDS + i]);
176 }
177
178 fm3130_rtc_mode(dev, FM3130_MODE_NORMAL);
179
180 /* We assume here that data are valid once written */
181 if (!fm3130->data_valid)
182 fm3130->data_valid = 1;
183 return 0;
184}
185
186static int fm3130_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
187{
188 struct fm3130 *fm3130 = dev_get_drvdata(dev);
189 int tmp;
190 struct rtc_time *tm = &alrm->time;
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700191
192 if (!fm3130->alarm_valid) {
193 /*
194 * We have invalid alarm in RTC, probably due to battery faults
195 * or other problems. Return EIO for now, it will allow us to
196 * set alarm value later instead of error during probing which
197 * disables device
198 */
199 return -EIO;
200 }
201
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700202 /* read the RTC alarm registers all at once */
203 tmp = i2c_transfer(to_i2c_adapter(fm3130->client->dev.parent),
204 &fm3130->msg[2], 2);
205 if (tmp != 2) {
206 dev_err(dev, "%s error %d\n", "read", tmp);
207 return -EIO;
208 }
209 dev_dbg(dev, "alarm read %02x %02x %02x %02x %02x\n",
210 fm3130->regs[FM3130_ALARM_SECONDS],
211 fm3130->regs[FM3130_ALARM_MINUTES],
212 fm3130->regs[FM3130_ALARM_HOURS],
213 fm3130->regs[FM3130_ALARM_DATE],
214 fm3130->regs[FM3130_ALARM_MONTHS]);
215
Adrian Bunkfe20ba72008-10-18 20:28:41 -0700216 tm->tm_sec = bcd2bin(fm3130->regs[FM3130_ALARM_SECONDS] & 0x7F);
217 tm->tm_min = bcd2bin(fm3130->regs[FM3130_ALARM_MINUTES] & 0x7F);
218 tm->tm_hour = bcd2bin(fm3130->regs[FM3130_ALARM_HOURS] & 0x3F);
219 tm->tm_mday = bcd2bin(fm3130->regs[FM3130_ALARM_DATE] & 0x3F);
220 tm->tm_mon = bcd2bin(fm3130->regs[FM3130_ALARM_MONTHS] & 0x1F);
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700221
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700222 if (tm->tm_mon > 0)
223 tm->tm_mon -= 1; /* RTC is 1-12, tm_mon is 0-11 */
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700224
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700225 dev_dbg(dev, "%s secs=%d, mins=%d, "
226 "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
227 "read alarm", tm->tm_sec, tm->tm_min,
228 tm->tm_hour, tm->tm_mday,
229 tm->tm_mon, tm->tm_year, tm->tm_wday);
230
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700231 /* check if alarm enabled */
232 fm3130->regs[FM3130_RTC_CONTROL] =
233 i2c_smbus_read_byte_data(fm3130->client, FM3130_RTC_CONTROL);
234
235 if ((fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_AEN) &&
236 (~fm3130->regs[FM3130_RTC_CONTROL] &
237 FM3130_RTC_CONTROL_BIT_CAL)) {
238 alrm->enabled = 1;
239 }
240
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700241 return 0;
242}
243
244static int fm3130_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
245{
246 struct fm3130 *fm3130 = dev_get_drvdata(dev);
247 struct rtc_time *tm = &alrm->time;
248 int i;
249
250 dev_dbg(dev, "%s secs=%d, mins=%d, "
251 "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
252 "write alarm", tm->tm_sec, tm->tm_min,
253 tm->tm_hour, tm->tm_mday,
254 tm->tm_mon, tm->tm_year, tm->tm_wday);
255
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700256 fm3130->regs[FM3130_ALARM_SECONDS] =
257 (tm->tm_sec != -1) ? bin2bcd(tm->tm_sec) : 0x80;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700258
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700259 fm3130->regs[FM3130_ALARM_MINUTES] =
260 (tm->tm_min != -1) ? bin2bcd(tm->tm_min) : 0x80;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700261
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700262 fm3130->regs[FM3130_ALARM_HOURS] =
263 (tm->tm_hour != -1) ? bin2bcd(tm->tm_hour) : 0x80;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700264
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700265 fm3130->regs[FM3130_ALARM_DATE] =
266 (tm->tm_mday != -1) ? bin2bcd(tm->tm_mday) : 0x80;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700267
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700268 fm3130->regs[FM3130_ALARM_MONTHS] =
269 (tm->tm_mon != -1) ? bin2bcd(tm->tm_mon + 1) : 0x80;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700270
271 dev_dbg(dev, "alarm write %02x %02x %02x %02x %02x\n",
272 fm3130->regs[FM3130_ALARM_SECONDS],
273 fm3130->regs[FM3130_ALARM_MINUTES],
274 fm3130->regs[FM3130_ALARM_HOURS],
275 fm3130->regs[FM3130_ALARM_DATE],
276 fm3130->regs[FM3130_ALARM_MONTHS]);
277 /* Writing time registers, we don't support multibyte transfers */
278 for (i = 0; i < FM3130_ALARM_REGS; i++) {
279 i2c_smbus_write_byte_data(fm3130->client,
280 FM3130_ALARM_SECONDS + i,
281 fm3130->regs[FM3130_ALARM_SECONDS + i]);
282 }
283 fm3130->regs[FM3130_RTC_CONTROL] =
284 i2c_smbus_read_byte_data(fm3130->client, FM3130_RTC_CONTROL);
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700285
286 /* enable or disable alarm */
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700287 if (alrm->enabled) {
288 i2c_smbus_write_byte_data(fm3130->client, FM3130_RTC_CONTROL,
289 (fm3130->regs[FM3130_RTC_CONTROL] &
290 ~(FM3130_RTC_CONTROL_BIT_CAL)) |
291 FM3130_RTC_CONTROL_BIT_AEN);
292 } else {
293 i2c_smbus_write_byte_data(fm3130->client, FM3130_RTC_CONTROL,
294 fm3130->regs[FM3130_RTC_CONTROL] &
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700295 ~(FM3130_RTC_CONTROL_BIT_CAL) &
296 ~(FM3130_RTC_CONTROL_BIT_AEN));
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700297 }
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700298
299 /* We assume here that data is valid once written */
300 if (!fm3130->alarm_valid)
301 fm3130->alarm_valid = 1;
302
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700303 return 0;
304}
305
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700306static int fm3130_alarm_irq_enable(struct device *dev, unsigned int enabled)
307{
308 struct fm3130 *fm3130 = dev_get_drvdata(dev);
309 int ret = 0;
310
311 fm3130->regs[FM3130_RTC_CONTROL] =
312 i2c_smbus_read_byte_data(fm3130->client, FM3130_RTC_CONTROL);
313
314 dev_dbg(dev, "alarm_irq_enable: enable=%d, FM3130_RTC_CONTROL=%02x\n",
315 enabled, fm3130->regs[FM3130_RTC_CONTROL]);
316
317 switch (enabled) {
318 case 0: /* alarm off */
319 ret = i2c_smbus_write_byte_data(fm3130->client,
320 FM3130_RTC_CONTROL, fm3130->regs[FM3130_RTC_CONTROL] &
321 ~(FM3130_RTC_CONTROL_BIT_CAL) &
322 ~(FM3130_RTC_CONTROL_BIT_AEN));
323 break;
324 case 1: /* alarm on */
325 ret = i2c_smbus_write_byte_data(fm3130->client,
326 FM3130_RTC_CONTROL, (fm3130->regs[FM3130_RTC_CONTROL] &
327 ~(FM3130_RTC_CONTROL_BIT_CAL)) |
328 FM3130_RTC_CONTROL_BIT_AEN);
329 break;
330 default:
331 ret = -EINVAL;
332 break;
333 }
334
335 return ret;
336}
337
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700338static const struct rtc_class_ops fm3130_rtc_ops = {
339 .read_time = fm3130_get_time,
340 .set_time = fm3130_set_time,
341 .read_alarm = fm3130_read_alarm,
342 .set_alarm = fm3130_set_alarm,
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700343 .alarm_irq_enable = fm3130_alarm_irq_enable,
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700344};
345
346static struct i2c_driver fm3130_driver;
347
Greg Kroah-Hartman5a167f42012-12-21 13:09:38 -0800348static int fm3130_probe(struct i2c_client *client,
349 const struct i2c_device_id *id)
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700350{
351 struct fm3130 *fm3130;
352 int err = -ENODEV;
353 int tmp;
354 struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
355
356 if (!i2c_check_functionality(adapter,
357 I2C_FUNC_I2C | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
358 return -EIO;
359
Jingoo Hanc54a52e2013-04-29 16:20:41 -0700360 fm3130 = devm_kzalloc(&client->dev, sizeof(struct fm3130), GFP_KERNEL);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700361
362 if (!fm3130)
363 return -ENOMEM;
364
365 fm3130->client = client;
366 i2c_set_clientdata(client, fm3130);
367 fm3130->reg_addr_time = FM3130_RTC_SECONDS;
368 fm3130->reg_addr_alarm = FM3130_ALARM_SECONDS;
369
370 /* Messages to read time */
371 fm3130->msg[0].addr = client->addr;
372 fm3130->msg[0].flags = 0;
373 fm3130->msg[0].len = 1;
374 fm3130->msg[0].buf = &fm3130->reg_addr_time;
375
376 fm3130->msg[1].addr = client->addr;
377 fm3130->msg[1].flags = I2C_M_RD;
378 fm3130->msg[1].len = FM3130_CLOCK_REGS;
379 fm3130->msg[1].buf = &fm3130->regs[FM3130_RTC_SECONDS];
380
381 /* Messages to read alarm */
382 fm3130->msg[2].addr = client->addr;
383 fm3130->msg[2].flags = 0;
384 fm3130->msg[2].len = 1;
385 fm3130->msg[2].buf = &fm3130->reg_addr_alarm;
386
387 fm3130->msg[3].addr = client->addr;
388 fm3130->msg[3].flags = I2C_M_RD;
389 fm3130->msg[3].len = FM3130_ALARM_REGS;
390 fm3130->msg[3].buf = &fm3130->regs[FM3130_ALARM_SECONDS];
391
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700392 fm3130->alarm_valid = 0;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700393 fm3130->data_valid = 0;
394
395 tmp = i2c_transfer(adapter, fm3130->msg, 4);
396 if (tmp != 4) {
Jingoo Han198b8ec2013-04-29 16:19:29 -0700397 dev_dbg(&client->dev, "read error %d\n", tmp);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700398 err = -EIO;
399 goto exit_free;
400 }
401
402 fm3130->regs[FM3130_RTC_CONTROL] =
403 i2c_smbus_read_byte_data(client, FM3130_RTC_CONTROL);
404 fm3130->regs[FM3130_CAL_CONTROL] =
405 i2c_smbus_read_byte_data(client, FM3130_CAL_CONTROL);
406
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700407 /* Disabling calibration mode */
Sergey Matyukevichf4b51622010-02-02 13:43:59 -0800408 if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_CAL) {
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700409 i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL,
410 fm3130->regs[FM3130_RTC_CONTROL] &
411 ~(FM3130_RTC_CONTROL_BIT_CAL));
412 dev_warn(&client->dev, "Disabling calibration mode!\n");
Sergey Matyukevichf4b51622010-02-02 13:43:59 -0800413 }
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700414
415 /* Disabling read and write modes */
416 if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_WRITE ||
Sergey Matyukevichf4b51622010-02-02 13:43:59 -0800417 fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_READ) {
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700418 i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL,
419 fm3130->regs[FM3130_RTC_CONTROL] &
420 ~(FM3130_RTC_CONTROL_BIT_READ |
421 FM3130_RTC_CONTROL_BIT_WRITE));
422 dev_warn(&client->dev, "Disabling READ or WRITE mode!\n");
Sergey Matyukevichf4b51622010-02-02 13:43:59 -0800423 }
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700424
425 /* oscillator off? turn it on, so clock can tick. */
426 if (fm3130->regs[FM3130_CAL_CONTROL] & FM3130_CAL_CONTROL_BIT_nOSCEN)
427 i2c_smbus_write_byte_data(client, FM3130_CAL_CONTROL,
428 fm3130->regs[FM3130_CAL_CONTROL] &
429 ~(FM3130_CAL_CONTROL_BIT_nOSCEN));
430
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700431 /* low battery? clear flag, and warn */
432 if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_LB) {
433 i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL,
434 fm3130->regs[FM3130_RTC_CONTROL] &
435 ~(FM3130_RTC_CONTROL_BIT_LB));
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700436 dev_warn(&client->dev, "Low battery!\n");
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700437 }
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700438
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700439 /* check if Power On Reset bit is set */
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700440 if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_POR) {
441 i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL,
442 fm3130->regs[FM3130_RTC_CONTROL] &
443 ~FM3130_RTC_CONTROL_BIT_POR);
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700444 dev_dbg(&client->dev, "POR bit is set\n");
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700445 }
446 /* ACS is controlled by alarm */
447 i2c_smbus_write_byte_data(client, FM3130_ALARM_WP_CONTROL, 0x80);
448
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700449 /* alarm registers sanity check */
450 tmp = bcd2bin(fm3130->regs[FM3130_RTC_SECONDS] & 0x7f);
451 if (tmp > 59)
452 goto bad_alarm;
453
Adrian Bunkfe20ba72008-10-18 20:28:41 -0700454 tmp = bcd2bin(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f);
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700455 if (tmp > 59)
456 goto bad_alarm;
457
458 tmp = bcd2bin(fm3130->regs[FM3130_RTC_HOURS] & 0x3f);
459 if (tmp > 23)
460 goto bad_alarm;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700461
Adrian Bunkfe20ba72008-10-18 20:28:41 -0700462 tmp = bcd2bin(fm3130->regs[FM3130_RTC_DATE] & 0x3f);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700463 if (tmp == 0 || tmp > 31)
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700464 goto bad_alarm;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700465
Adrian Bunkfe20ba72008-10-18 20:28:41 -0700466 tmp = bcd2bin(fm3130->regs[FM3130_RTC_MONTHS] & 0x1f);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700467 if (tmp == 0 || tmp > 12)
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700468 goto bad_alarm;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700469
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700470 fm3130->alarm_valid = 1;
471
472bad_alarm:
473
474 /* clock registers sanity chek */
475 tmp = bcd2bin(fm3130->regs[FM3130_RTC_SECONDS] & 0x7f);
476 if (tmp > 59)
477 goto bad_clock;
478
479 tmp = bcd2bin(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f);
480 if (tmp > 59)
481 goto bad_clock;
482
483 tmp = bcd2bin(fm3130->regs[FM3130_RTC_HOURS] & 0x3f);
484 if (tmp > 23)
485 goto bad_clock;
486
487 tmp = bcd2bin(fm3130->regs[FM3130_RTC_DAY] & 0x7);
488 if (tmp == 0 || tmp > 7)
489 goto bad_clock;
490
491 tmp = bcd2bin(fm3130->regs[FM3130_RTC_DATE] & 0x3f);
492 if (tmp == 0 || tmp > 31)
493 goto bad_clock;
494
495 tmp = bcd2bin(fm3130->regs[FM3130_RTC_MONTHS] & 0x1f);
496 if (tmp == 0 || tmp > 12)
497 goto bad_clock;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700498
499 fm3130->data_valid = 1;
500
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700501bad_clock:
502
503 if (!fm3130->data_valid || !fm3130->alarm_valid)
Andy Shevchenko01a4ca12013-02-21 16:44:22 -0800504 dev_dbg(&client->dev, "%s: %15ph\n", "bogus registers",
505 fm3130->regs);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700506
507 /* We won't bail out here because we just got invalid data.
508 Time setting from u-boot doesn't work anyway */
Jingoo Hanc54a52e2013-04-29 16:20:41 -0700509 fm3130->rtc = devm_rtc_device_register(&client->dev, client->name,
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700510 &fm3130_rtc_ops, THIS_MODULE);
511 if (IS_ERR(fm3130->rtc)) {
512 err = PTR_ERR(fm3130->rtc);
513 dev_err(&client->dev,
514 "unable to register the class device\n");
515 goto exit_free;
516 }
517 return 0;
518exit_free:
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700519 return err;
520}
521
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700522static struct i2c_driver fm3130_driver = {
523 .driver = {
524 .name = "rtc-fm3130",
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700525 },
526 .probe = fm3130_probe,
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700527 .id_table = fm3130_id,
528};
529
Axel Lin0abc9202012-03-23 15:02:31 -0700530module_i2c_driver(fm3130_driver);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700531
532MODULE_DESCRIPTION("RTC driver for FM3130");
533MODULE_AUTHOR("Sergey Lapin <slapin@ossfans.org>");
534MODULE_LICENSE("GPL");
535