blob: 677ec2da13d8385516b9636acefae61bb99bbcf4 [file] [log] [blame]
Thomas Gleixnerd2912cb2019-06-04 10:11:33 +02001// SPDX-License-Identifier: GPL-2.0-only
Sergey Lapinc6d8f402008-06-12 15:21:55 -07002/*
3 * rtc-fm3130.c - RTC driver for Ramtron FM3130 I2C chip.
4 *
5 * Copyright (C) 2008 Sergey Lapin
6 * Based on ds1307 driver by James Chapman and David Brownell
Sergey Lapinc6d8f402008-06-12 15:21:55 -07007 */
8
9#include <linux/module.h>
10#include <linux/i2c.h>
11#include <linux/rtc.h>
12#include <linux/bcd.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090013#include <linux/slab.h>
Sergey Lapinc6d8f402008-06-12 15:21:55 -070014
15#define FM3130_RTC_CONTROL (0x0)
16#define FM3130_CAL_CONTROL (0x1)
17#define FM3130_RTC_SECONDS (0x2)
18#define FM3130_RTC_MINUTES (0x3)
19#define FM3130_RTC_HOURS (0x4)
20#define FM3130_RTC_DAY (0x5)
21#define FM3130_RTC_DATE (0x6)
22#define FM3130_RTC_MONTHS (0x7)
23#define FM3130_RTC_YEARS (0x8)
24
25#define FM3130_ALARM_SECONDS (0x9)
26#define FM3130_ALARM_MINUTES (0xa)
27#define FM3130_ALARM_HOURS (0xb)
28#define FM3130_ALARM_DATE (0xc)
29#define FM3130_ALARM_MONTHS (0xd)
30#define FM3130_ALARM_WP_CONTROL (0xe)
31
32#define FM3130_CAL_CONTROL_BIT_nOSCEN (1 << 7) /* Osciallator enabled */
33#define FM3130_RTC_CONTROL_BIT_LB (1 << 7) /* Low battery */
34#define FM3130_RTC_CONTROL_BIT_AF (1 << 6) /* Alarm flag */
35#define FM3130_RTC_CONTROL_BIT_CF (1 << 5) /* Century overflow */
36#define FM3130_RTC_CONTROL_BIT_POR (1 << 4) /* Power on reset */
37#define FM3130_RTC_CONTROL_BIT_AEN (1 << 3) /* Alarm enable */
38#define FM3130_RTC_CONTROL_BIT_CAL (1 << 2) /* Calibration mode */
39#define FM3130_RTC_CONTROL_BIT_WRITE (1 << 1) /* W=1 -> write mode W=0 normal */
40#define FM3130_RTC_CONTROL_BIT_READ (1 << 0) /* R=1 -> read mode R=0 normal */
41
42#define FM3130_CLOCK_REGS 7
43#define FM3130_ALARM_REGS 5
44
45struct fm3130 {
46 u8 reg_addr_time;
Sachin Kamatc865e922013-07-03 15:05:51 -070047 u8 reg_addr_alarm;
Sergey Lapinc6d8f402008-06-12 15:21:55 -070048 u8 regs[15];
49 struct i2c_msg msg[4];
50 struct i2c_client *client;
51 struct rtc_device *rtc;
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -070052 int alarm_valid;
Sergey Lapinc6d8f402008-06-12 15:21:55 -070053 int data_valid;
Sergey Lapinc6d8f402008-06-12 15:21:55 -070054};
55static const struct i2c_device_id fm3130_id[] = {
Alessandro Zummo876550a2008-07-12 13:47:55 -070056 { "fm3130", 0 },
Sergey Lapinc6d8f402008-06-12 15:21:55 -070057 { }
58};
59MODULE_DEVICE_TABLE(i2c, fm3130_id);
60
61#define FM3130_MODE_NORMAL 0
62#define FM3130_MODE_WRITE 1
63#define FM3130_MODE_READ 2
64
65static void fm3130_rtc_mode(struct device *dev, int mode)
66{
67 struct fm3130 *fm3130 = dev_get_drvdata(dev);
68
69 fm3130->regs[FM3130_RTC_CONTROL] =
70 i2c_smbus_read_byte_data(fm3130->client, FM3130_RTC_CONTROL);
71 switch (mode) {
72 case FM3130_MODE_NORMAL:
73 fm3130->regs[FM3130_RTC_CONTROL] &=
74 ~(FM3130_RTC_CONTROL_BIT_WRITE |
75 FM3130_RTC_CONTROL_BIT_READ);
76 break;
77 case FM3130_MODE_WRITE:
78 fm3130->regs[FM3130_RTC_CONTROL] |= FM3130_RTC_CONTROL_BIT_WRITE;
79 break;
80 case FM3130_MODE_READ:
81 fm3130->regs[FM3130_RTC_CONTROL] |= FM3130_RTC_CONTROL_BIT_READ;
82 break;
83 default:
84 dev_dbg(dev, "invalid mode %d\n", mode);
85 break;
86 }
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -070087
Sergey Lapinc6d8f402008-06-12 15:21:55 -070088 i2c_smbus_write_byte_data(fm3130->client,
89 FM3130_RTC_CONTROL, fm3130->regs[FM3130_RTC_CONTROL]);
90}
91
92static int fm3130_get_time(struct device *dev, struct rtc_time *t)
93{
94 struct fm3130 *fm3130 = dev_get_drvdata(dev);
95 int tmp;
96
97 if (!fm3130->data_valid) {
98 /* We have invalid data in RTC, probably due
99 to battery faults or other problems. Return EIO
Uwe Kleine-Königfd0961f2010-06-11 12:16:56 +0200100 for now, it will allow us to set data later instead
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700101 of error during probing which disables device */
102 return -EIO;
103 }
104 fm3130_rtc_mode(dev, FM3130_MODE_READ);
105
106 /* read the RTC date and time registers all at once */
Wolfram Sang55c24312019-06-08 12:56:05 +0200107 tmp = i2c_transfer(fm3130->client->adapter, fm3130->msg, 2);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700108 if (tmp != 2) {
109 dev_err(dev, "%s error %d\n", "read", tmp);
110 return -EIO;
111 }
112
113 fm3130_rtc_mode(dev, FM3130_MODE_NORMAL);
114
Andy Shevchenko01a4ca12013-02-21 16:44:22 -0800115 dev_dbg(dev, "%s: %15ph\n", "read", fm3130->regs);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700116
Adrian Bunkfe20ba72008-10-18 20:28:41 -0700117 t->tm_sec = bcd2bin(fm3130->regs[FM3130_RTC_SECONDS] & 0x7f);
118 t->tm_min = bcd2bin(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700119 tmp = fm3130->regs[FM3130_RTC_HOURS] & 0x3f;
Adrian Bunkfe20ba72008-10-18 20:28:41 -0700120 t->tm_hour = bcd2bin(tmp);
121 t->tm_wday = bcd2bin(fm3130->regs[FM3130_RTC_DAY] & 0x07) - 1;
122 t->tm_mday = bcd2bin(fm3130->regs[FM3130_RTC_DATE] & 0x3f);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700123 tmp = fm3130->regs[FM3130_RTC_MONTHS] & 0x1f;
Adrian Bunkfe20ba72008-10-18 20:28:41 -0700124 t->tm_mon = bcd2bin(tmp) - 1;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700125
126 /* assume 20YY not 19YY, and ignore CF bit */
Adrian Bunkfe20ba72008-10-18 20:28:41 -0700127 t->tm_year = bcd2bin(fm3130->regs[FM3130_RTC_YEARS]) + 100;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700128
129 dev_dbg(dev, "%s secs=%d, mins=%d, "
130 "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
131 "read", t->tm_sec, t->tm_min,
132 t->tm_hour, t->tm_mday,
133 t->tm_mon, t->tm_year, t->tm_wday);
134
Alexandre Belloni22652ba2018-02-19 16:23:56 +0100135 return 0;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700136}
137
138
139static int fm3130_set_time(struct device *dev, struct rtc_time *t)
140{
141 struct fm3130 *fm3130 = dev_get_drvdata(dev);
142 int tmp, i;
143 u8 *buf = fm3130->regs;
144
145 dev_dbg(dev, "%s secs=%d, mins=%d, "
146 "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
147 "write", t->tm_sec, t->tm_min,
148 t->tm_hour, t->tm_mday,
149 t->tm_mon, t->tm_year, t->tm_wday);
150
151 /* first register addr */
Adrian Bunkfe20ba72008-10-18 20:28:41 -0700152 buf[FM3130_RTC_SECONDS] = bin2bcd(t->tm_sec);
153 buf[FM3130_RTC_MINUTES] = bin2bcd(t->tm_min);
154 buf[FM3130_RTC_HOURS] = bin2bcd(t->tm_hour);
155 buf[FM3130_RTC_DAY] = bin2bcd(t->tm_wday + 1);
156 buf[FM3130_RTC_DATE] = bin2bcd(t->tm_mday);
157 buf[FM3130_RTC_MONTHS] = bin2bcd(t->tm_mon + 1);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700158
159 /* assume 20YY not 19YY */
160 tmp = t->tm_year - 100;
Adrian Bunkfe20ba72008-10-18 20:28:41 -0700161 buf[FM3130_RTC_YEARS] = bin2bcd(tmp);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700162
Andy Shevchenko01a4ca12013-02-21 16:44:22 -0800163 dev_dbg(dev, "%s: %15ph\n", "write", buf);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700164
165 fm3130_rtc_mode(dev, FM3130_MODE_WRITE);
166
167 /* Writing time registers, we don't support multibyte transfers */
168 for (i = 0; i < FM3130_CLOCK_REGS; i++) {
169 i2c_smbus_write_byte_data(fm3130->client,
170 FM3130_RTC_SECONDS + i,
171 fm3130->regs[FM3130_RTC_SECONDS + i]);
172 }
173
174 fm3130_rtc_mode(dev, FM3130_MODE_NORMAL);
175
176 /* We assume here that data are valid once written */
177 if (!fm3130->data_valid)
178 fm3130->data_valid = 1;
179 return 0;
180}
181
182static int fm3130_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
183{
184 struct fm3130 *fm3130 = dev_get_drvdata(dev);
185 int tmp;
186 struct rtc_time *tm = &alrm->time;
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700187
188 if (!fm3130->alarm_valid) {
189 /*
190 * We have invalid alarm in RTC, probably due to battery faults
191 * or other problems. Return EIO for now, it will allow us to
192 * set alarm value later instead of error during probing which
193 * disables device
194 */
195 return -EIO;
196 }
197
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700198 /* read the RTC alarm registers all at once */
Wolfram Sang55c24312019-06-08 12:56:05 +0200199 tmp = i2c_transfer(fm3130->client->adapter, &fm3130->msg[2], 2);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700200 if (tmp != 2) {
201 dev_err(dev, "%s error %d\n", "read", tmp);
202 return -EIO;
203 }
204 dev_dbg(dev, "alarm read %02x %02x %02x %02x %02x\n",
205 fm3130->regs[FM3130_ALARM_SECONDS],
206 fm3130->regs[FM3130_ALARM_MINUTES],
207 fm3130->regs[FM3130_ALARM_HOURS],
208 fm3130->regs[FM3130_ALARM_DATE],
209 fm3130->regs[FM3130_ALARM_MONTHS]);
210
Adrian Bunkfe20ba72008-10-18 20:28:41 -0700211 tm->tm_sec = bcd2bin(fm3130->regs[FM3130_ALARM_SECONDS] & 0x7F);
212 tm->tm_min = bcd2bin(fm3130->regs[FM3130_ALARM_MINUTES] & 0x7F);
213 tm->tm_hour = bcd2bin(fm3130->regs[FM3130_ALARM_HOURS] & 0x3F);
214 tm->tm_mday = bcd2bin(fm3130->regs[FM3130_ALARM_DATE] & 0x3F);
215 tm->tm_mon = bcd2bin(fm3130->regs[FM3130_ALARM_MONTHS] & 0x1F);
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700216
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700217 if (tm->tm_mon > 0)
218 tm->tm_mon -= 1; /* RTC is 1-12, tm_mon is 0-11 */
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700219
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700220 dev_dbg(dev, "%s secs=%d, mins=%d, "
221 "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
222 "read alarm", tm->tm_sec, tm->tm_min,
223 tm->tm_hour, tm->tm_mday,
224 tm->tm_mon, tm->tm_year, tm->tm_wday);
225
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700226 /* check if alarm enabled */
227 fm3130->regs[FM3130_RTC_CONTROL] =
228 i2c_smbus_read_byte_data(fm3130->client, FM3130_RTC_CONTROL);
229
230 if ((fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_AEN) &&
231 (~fm3130->regs[FM3130_RTC_CONTROL] &
232 FM3130_RTC_CONTROL_BIT_CAL)) {
233 alrm->enabled = 1;
234 }
235
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700236 return 0;
237}
238
239static int fm3130_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
240{
241 struct fm3130 *fm3130 = dev_get_drvdata(dev);
242 struct rtc_time *tm = &alrm->time;
243 int i;
244
245 dev_dbg(dev, "%s secs=%d, mins=%d, "
246 "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
247 "write alarm", tm->tm_sec, tm->tm_min,
248 tm->tm_hour, tm->tm_mday,
249 tm->tm_mon, tm->tm_year, tm->tm_wday);
250
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700251 fm3130->regs[FM3130_ALARM_SECONDS] =
252 (tm->tm_sec != -1) ? bin2bcd(tm->tm_sec) : 0x80;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700253
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700254 fm3130->regs[FM3130_ALARM_MINUTES] =
255 (tm->tm_min != -1) ? bin2bcd(tm->tm_min) : 0x80;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700256
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700257 fm3130->regs[FM3130_ALARM_HOURS] =
258 (tm->tm_hour != -1) ? bin2bcd(tm->tm_hour) : 0x80;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700259
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700260 fm3130->regs[FM3130_ALARM_DATE] =
261 (tm->tm_mday != -1) ? bin2bcd(tm->tm_mday) : 0x80;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700262
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700263 fm3130->regs[FM3130_ALARM_MONTHS] =
264 (tm->tm_mon != -1) ? bin2bcd(tm->tm_mon + 1) : 0x80;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700265
266 dev_dbg(dev, "alarm write %02x %02x %02x %02x %02x\n",
267 fm3130->regs[FM3130_ALARM_SECONDS],
268 fm3130->regs[FM3130_ALARM_MINUTES],
269 fm3130->regs[FM3130_ALARM_HOURS],
270 fm3130->regs[FM3130_ALARM_DATE],
271 fm3130->regs[FM3130_ALARM_MONTHS]);
272 /* Writing time registers, we don't support multibyte transfers */
273 for (i = 0; i < FM3130_ALARM_REGS; i++) {
274 i2c_smbus_write_byte_data(fm3130->client,
275 FM3130_ALARM_SECONDS + i,
276 fm3130->regs[FM3130_ALARM_SECONDS + i]);
277 }
278 fm3130->regs[FM3130_RTC_CONTROL] =
279 i2c_smbus_read_byte_data(fm3130->client, FM3130_RTC_CONTROL);
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700280
281 /* enable or disable alarm */
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700282 if (alrm->enabled) {
283 i2c_smbus_write_byte_data(fm3130->client, FM3130_RTC_CONTROL,
284 (fm3130->regs[FM3130_RTC_CONTROL] &
285 ~(FM3130_RTC_CONTROL_BIT_CAL)) |
286 FM3130_RTC_CONTROL_BIT_AEN);
287 } else {
288 i2c_smbus_write_byte_data(fm3130->client, FM3130_RTC_CONTROL,
289 fm3130->regs[FM3130_RTC_CONTROL] &
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700290 ~(FM3130_RTC_CONTROL_BIT_CAL) &
291 ~(FM3130_RTC_CONTROL_BIT_AEN));
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700292 }
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700293
294 /* We assume here that data is valid once written */
295 if (!fm3130->alarm_valid)
296 fm3130->alarm_valid = 1;
297
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700298 return 0;
299}
300
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700301static int fm3130_alarm_irq_enable(struct device *dev, unsigned int enabled)
302{
303 struct fm3130 *fm3130 = dev_get_drvdata(dev);
304 int ret = 0;
305
306 fm3130->regs[FM3130_RTC_CONTROL] =
307 i2c_smbus_read_byte_data(fm3130->client, FM3130_RTC_CONTROL);
308
309 dev_dbg(dev, "alarm_irq_enable: enable=%d, FM3130_RTC_CONTROL=%02x\n",
310 enabled, fm3130->regs[FM3130_RTC_CONTROL]);
311
312 switch (enabled) {
313 case 0: /* alarm off */
314 ret = i2c_smbus_write_byte_data(fm3130->client,
315 FM3130_RTC_CONTROL, fm3130->regs[FM3130_RTC_CONTROL] &
316 ~(FM3130_RTC_CONTROL_BIT_CAL) &
317 ~(FM3130_RTC_CONTROL_BIT_AEN));
318 break;
319 case 1: /* alarm on */
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 default:
326 ret = -EINVAL;
327 break;
328 }
329
330 return ret;
331}
332
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700333static const struct rtc_class_ops fm3130_rtc_ops = {
334 .read_time = fm3130_get_time,
335 .set_time = fm3130_set_time,
336 .read_alarm = fm3130_read_alarm,
337 .set_alarm = fm3130_set_alarm,
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700338 .alarm_irq_enable = fm3130_alarm_irq_enable,
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700339};
340
341static struct i2c_driver fm3130_driver;
342
Greg Kroah-Hartman5a167f42012-12-21 13:09:38 -0800343static int fm3130_probe(struct i2c_client *client,
344 const struct i2c_device_id *id)
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700345{
346 struct fm3130 *fm3130;
347 int err = -ENODEV;
348 int tmp;
Wolfram Sang55c24312019-06-08 12:56:05 +0200349 struct i2c_adapter *adapter = client->adapter;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700350
351 if (!i2c_check_functionality(adapter,
352 I2C_FUNC_I2C | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
353 return -EIO;
354
Jingoo Hanc54a52e2013-04-29 16:20:41 -0700355 fm3130 = devm_kzalloc(&client->dev, sizeof(struct fm3130), GFP_KERNEL);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700356
357 if (!fm3130)
358 return -ENOMEM;
359
360 fm3130->client = client;
361 i2c_set_clientdata(client, fm3130);
362 fm3130->reg_addr_time = FM3130_RTC_SECONDS;
363 fm3130->reg_addr_alarm = FM3130_ALARM_SECONDS;
364
365 /* Messages to read time */
366 fm3130->msg[0].addr = client->addr;
367 fm3130->msg[0].flags = 0;
368 fm3130->msg[0].len = 1;
369 fm3130->msg[0].buf = &fm3130->reg_addr_time;
370
371 fm3130->msg[1].addr = client->addr;
372 fm3130->msg[1].flags = I2C_M_RD;
373 fm3130->msg[1].len = FM3130_CLOCK_REGS;
374 fm3130->msg[1].buf = &fm3130->regs[FM3130_RTC_SECONDS];
375
376 /* Messages to read alarm */
377 fm3130->msg[2].addr = client->addr;
378 fm3130->msg[2].flags = 0;
379 fm3130->msg[2].len = 1;
380 fm3130->msg[2].buf = &fm3130->reg_addr_alarm;
381
382 fm3130->msg[3].addr = client->addr;
383 fm3130->msg[3].flags = I2C_M_RD;
384 fm3130->msg[3].len = FM3130_ALARM_REGS;
385 fm3130->msg[3].buf = &fm3130->regs[FM3130_ALARM_SECONDS];
386
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700387 fm3130->alarm_valid = 0;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700388 fm3130->data_valid = 0;
389
390 tmp = i2c_transfer(adapter, fm3130->msg, 4);
391 if (tmp != 4) {
Jingoo Han198b8ec82013-04-29 16:19:29 -0700392 dev_dbg(&client->dev, "read error %d\n", tmp);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700393 err = -EIO;
394 goto exit_free;
395 }
396
397 fm3130->regs[FM3130_RTC_CONTROL] =
398 i2c_smbus_read_byte_data(client, FM3130_RTC_CONTROL);
399 fm3130->regs[FM3130_CAL_CONTROL] =
400 i2c_smbus_read_byte_data(client, FM3130_CAL_CONTROL);
401
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700402 /* Disabling calibration mode */
Sergey Matyukevichf4b51622010-02-02 13:43:59 -0800403 if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_CAL) {
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700404 i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL,
405 fm3130->regs[FM3130_RTC_CONTROL] &
406 ~(FM3130_RTC_CONTROL_BIT_CAL));
407 dev_warn(&client->dev, "Disabling calibration mode!\n");
Sergey Matyukevichf4b51622010-02-02 13:43:59 -0800408 }
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700409
410 /* Disabling read and write modes */
411 if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_WRITE ||
Sergey Matyukevichf4b51622010-02-02 13:43:59 -0800412 fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_READ) {
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700413 i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL,
414 fm3130->regs[FM3130_RTC_CONTROL] &
415 ~(FM3130_RTC_CONTROL_BIT_READ |
416 FM3130_RTC_CONTROL_BIT_WRITE));
417 dev_warn(&client->dev, "Disabling READ or WRITE mode!\n");
Sergey Matyukevichf4b51622010-02-02 13:43:59 -0800418 }
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700419
420 /* oscillator off? turn it on, so clock can tick. */
421 if (fm3130->regs[FM3130_CAL_CONTROL] & FM3130_CAL_CONTROL_BIT_nOSCEN)
422 i2c_smbus_write_byte_data(client, FM3130_CAL_CONTROL,
423 fm3130->regs[FM3130_CAL_CONTROL] &
424 ~(FM3130_CAL_CONTROL_BIT_nOSCEN));
425
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700426 /* low battery? clear flag, and warn */
427 if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_LB) {
428 i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL,
429 fm3130->regs[FM3130_RTC_CONTROL] &
430 ~(FM3130_RTC_CONTROL_BIT_LB));
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700431 dev_warn(&client->dev, "Low battery!\n");
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700432 }
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700433
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700434 /* check if Power On Reset bit is set */
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700435 if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_POR) {
436 i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL,
437 fm3130->regs[FM3130_RTC_CONTROL] &
438 ~FM3130_RTC_CONTROL_BIT_POR);
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700439 dev_dbg(&client->dev, "POR bit is set\n");
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700440 }
441 /* ACS is controlled by alarm */
442 i2c_smbus_write_byte_data(client, FM3130_ALARM_WP_CONTROL, 0x80);
443
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700444 /* alarm registers sanity check */
445 tmp = bcd2bin(fm3130->regs[FM3130_RTC_SECONDS] & 0x7f);
446 if (tmp > 59)
447 goto bad_alarm;
448
Adrian Bunkfe20ba72008-10-18 20:28:41 -0700449 tmp = bcd2bin(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f);
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700450 if (tmp > 59)
451 goto bad_alarm;
452
453 tmp = bcd2bin(fm3130->regs[FM3130_RTC_HOURS] & 0x3f);
454 if (tmp > 23)
455 goto bad_alarm;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700456
Adrian Bunkfe20ba72008-10-18 20:28:41 -0700457 tmp = bcd2bin(fm3130->regs[FM3130_RTC_DATE] & 0x3f);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700458 if (tmp == 0 || tmp > 31)
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700459 goto bad_alarm;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700460
Adrian Bunkfe20ba72008-10-18 20:28:41 -0700461 tmp = bcd2bin(fm3130->regs[FM3130_RTC_MONTHS] & 0x1f);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700462 if (tmp == 0 || tmp > 12)
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700463 goto bad_alarm;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700464
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700465 fm3130->alarm_valid = 1;
466
467bad_alarm:
468
469 /* clock registers sanity chek */
470 tmp = bcd2bin(fm3130->regs[FM3130_RTC_SECONDS] & 0x7f);
471 if (tmp > 59)
472 goto bad_clock;
473
474 tmp = bcd2bin(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f);
475 if (tmp > 59)
476 goto bad_clock;
477
478 tmp = bcd2bin(fm3130->regs[FM3130_RTC_HOURS] & 0x3f);
479 if (tmp > 23)
480 goto bad_clock;
481
482 tmp = bcd2bin(fm3130->regs[FM3130_RTC_DAY] & 0x7);
483 if (tmp == 0 || tmp > 7)
484 goto bad_clock;
485
486 tmp = bcd2bin(fm3130->regs[FM3130_RTC_DATE] & 0x3f);
487 if (tmp == 0 || tmp > 31)
488 goto bad_clock;
489
490 tmp = bcd2bin(fm3130->regs[FM3130_RTC_MONTHS] & 0x1f);
491 if (tmp == 0 || tmp > 12)
492 goto bad_clock;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700493
494 fm3130->data_valid = 1;
495
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700496bad_clock:
497
498 if (!fm3130->data_valid || !fm3130->alarm_valid)
Andy Shevchenko01a4ca12013-02-21 16:44:22 -0800499 dev_dbg(&client->dev, "%s: %15ph\n", "bogus registers",
500 fm3130->regs);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700501
502 /* We won't bail out here because we just got invalid data.
503 Time setting from u-boot doesn't work anyway */
Jingoo Hanc54a52e2013-04-29 16:20:41 -0700504 fm3130->rtc = devm_rtc_device_register(&client->dev, client->name,
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700505 &fm3130_rtc_ops, THIS_MODULE);
506 if (IS_ERR(fm3130->rtc)) {
507 err = PTR_ERR(fm3130->rtc);
508 dev_err(&client->dev,
509 "unable to register the class device\n");
510 goto exit_free;
511 }
512 return 0;
513exit_free:
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700514 return err;
515}
516
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700517static struct i2c_driver fm3130_driver = {
518 .driver = {
519 .name = "rtc-fm3130",
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700520 },
521 .probe = fm3130_probe,
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700522 .id_table = fm3130_id,
523};
524
Axel Lin0abc9202012-03-23 15:02:31 -0700525module_i2c_driver(fm3130_driver);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700526
527MODULE_DESCRIPTION("RTC driver for FM3130");
528MODULE_AUTHOR("Sergey Lapin <slapin@ossfans.org>");
529MODULE_LICENSE("GPL");
530