blob: 1caa21b82c7d1fdfcf35474e90771d4c41bc07a4 [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 */
107 tmp = i2c_transfer(to_i2c_adapter(fm3130->client->dev.parent),
108 fm3130->msg, 2);
109 if (tmp != 2) {
110 dev_err(dev, "%s error %d\n", "read", tmp);
111 return -EIO;
112 }
113
114 fm3130_rtc_mode(dev, FM3130_MODE_NORMAL);
115
Andy Shevchenko01a4ca12013-02-21 16:44:22 -0800116 dev_dbg(dev, "%s: %15ph\n", "read", fm3130->regs);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700117
Adrian Bunkfe20ba72008-10-18 20:28:41 -0700118 t->tm_sec = bcd2bin(fm3130->regs[FM3130_RTC_SECONDS] & 0x7f);
119 t->tm_min = bcd2bin(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700120 tmp = fm3130->regs[FM3130_RTC_HOURS] & 0x3f;
Adrian Bunkfe20ba72008-10-18 20:28:41 -0700121 t->tm_hour = bcd2bin(tmp);
122 t->tm_wday = bcd2bin(fm3130->regs[FM3130_RTC_DAY] & 0x07) - 1;
123 t->tm_mday = bcd2bin(fm3130->regs[FM3130_RTC_DATE] & 0x3f);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700124 tmp = fm3130->regs[FM3130_RTC_MONTHS] & 0x1f;
Adrian Bunkfe20ba72008-10-18 20:28:41 -0700125 t->tm_mon = bcd2bin(tmp) - 1;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700126
127 /* assume 20YY not 19YY, and ignore CF bit */
Adrian Bunkfe20ba72008-10-18 20:28:41 -0700128 t->tm_year = bcd2bin(fm3130->regs[FM3130_RTC_YEARS]) + 100;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700129
130 dev_dbg(dev, "%s secs=%d, mins=%d, "
131 "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
132 "read", t->tm_sec, t->tm_min,
133 t->tm_hour, t->tm_mday,
134 t->tm_mon, t->tm_year, t->tm_wday);
135
Alexandre Belloni22652ba2018-02-19 16:23:56 +0100136 return 0;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700137}
138
139
140static int fm3130_set_time(struct device *dev, struct rtc_time *t)
141{
142 struct fm3130 *fm3130 = dev_get_drvdata(dev);
143 int tmp, i;
144 u8 *buf = fm3130->regs;
145
146 dev_dbg(dev, "%s secs=%d, mins=%d, "
147 "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
148 "write", t->tm_sec, t->tm_min,
149 t->tm_hour, t->tm_mday,
150 t->tm_mon, t->tm_year, t->tm_wday);
151
152 /* first register addr */
Adrian Bunkfe20ba72008-10-18 20:28:41 -0700153 buf[FM3130_RTC_SECONDS] = bin2bcd(t->tm_sec);
154 buf[FM3130_RTC_MINUTES] = bin2bcd(t->tm_min);
155 buf[FM3130_RTC_HOURS] = bin2bcd(t->tm_hour);
156 buf[FM3130_RTC_DAY] = bin2bcd(t->tm_wday + 1);
157 buf[FM3130_RTC_DATE] = bin2bcd(t->tm_mday);
158 buf[FM3130_RTC_MONTHS] = bin2bcd(t->tm_mon + 1);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700159
160 /* assume 20YY not 19YY */
161 tmp = t->tm_year - 100;
Adrian Bunkfe20ba72008-10-18 20:28:41 -0700162 buf[FM3130_RTC_YEARS] = bin2bcd(tmp);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700163
Andy Shevchenko01a4ca12013-02-21 16:44:22 -0800164 dev_dbg(dev, "%s: %15ph\n", "write", buf);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700165
166 fm3130_rtc_mode(dev, FM3130_MODE_WRITE);
167
168 /* Writing time registers, we don't support multibyte transfers */
169 for (i = 0; i < FM3130_CLOCK_REGS; i++) {
170 i2c_smbus_write_byte_data(fm3130->client,
171 FM3130_RTC_SECONDS + i,
172 fm3130->regs[FM3130_RTC_SECONDS + i]);
173 }
174
175 fm3130_rtc_mode(dev, FM3130_MODE_NORMAL);
176
177 /* We assume here that data are valid once written */
178 if (!fm3130->data_valid)
179 fm3130->data_valid = 1;
180 return 0;
181}
182
183static int fm3130_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
184{
185 struct fm3130 *fm3130 = dev_get_drvdata(dev);
186 int tmp;
187 struct rtc_time *tm = &alrm->time;
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700188
189 if (!fm3130->alarm_valid) {
190 /*
191 * We have invalid alarm in RTC, probably due to battery faults
192 * or other problems. Return EIO for now, it will allow us to
193 * set alarm value later instead of error during probing which
194 * disables device
195 */
196 return -EIO;
197 }
198
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700199 /* read the RTC alarm registers all at once */
200 tmp = i2c_transfer(to_i2c_adapter(fm3130->client->dev.parent),
201 &fm3130->msg[2], 2);
202 if (tmp != 2) {
203 dev_err(dev, "%s error %d\n", "read", tmp);
204 return -EIO;
205 }
206 dev_dbg(dev, "alarm read %02x %02x %02x %02x %02x\n",
207 fm3130->regs[FM3130_ALARM_SECONDS],
208 fm3130->regs[FM3130_ALARM_MINUTES],
209 fm3130->regs[FM3130_ALARM_HOURS],
210 fm3130->regs[FM3130_ALARM_DATE],
211 fm3130->regs[FM3130_ALARM_MONTHS]);
212
Adrian Bunkfe20ba72008-10-18 20:28:41 -0700213 tm->tm_sec = bcd2bin(fm3130->regs[FM3130_ALARM_SECONDS] & 0x7F);
214 tm->tm_min = bcd2bin(fm3130->regs[FM3130_ALARM_MINUTES] & 0x7F);
215 tm->tm_hour = bcd2bin(fm3130->regs[FM3130_ALARM_HOURS] & 0x3F);
216 tm->tm_mday = bcd2bin(fm3130->regs[FM3130_ALARM_DATE] & 0x3F);
217 tm->tm_mon = bcd2bin(fm3130->regs[FM3130_ALARM_MONTHS] & 0x1F);
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700218
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700219 if (tm->tm_mon > 0)
220 tm->tm_mon -= 1; /* RTC is 1-12, tm_mon is 0-11 */
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700221
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700222 dev_dbg(dev, "%s secs=%d, mins=%d, "
223 "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
224 "read alarm", tm->tm_sec, tm->tm_min,
225 tm->tm_hour, tm->tm_mday,
226 tm->tm_mon, tm->tm_year, tm->tm_wday);
227
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700228 /* check if alarm enabled */
229 fm3130->regs[FM3130_RTC_CONTROL] =
230 i2c_smbus_read_byte_data(fm3130->client, FM3130_RTC_CONTROL);
231
232 if ((fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_AEN) &&
233 (~fm3130->regs[FM3130_RTC_CONTROL] &
234 FM3130_RTC_CONTROL_BIT_CAL)) {
235 alrm->enabled = 1;
236 }
237
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700238 return 0;
239}
240
241static int fm3130_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
242{
243 struct fm3130 *fm3130 = dev_get_drvdata(dev);
244 struct rtc_time *tm = &alrm->time;
245 int i;
246
247 dev_dbg(dev, "%s secs=%d, mins=%d, "
248 "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
249 "write alarm", tm->tm_sec, tm->tm_min,
250 tm->tm_hour, tm->tm_mday,
251 tm->tm_mon, tm->tm_year, tm->tm_wday);
252
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700253 fm3130->regs[FM3130_ALARM_SECONDS] =
254 (tm->tm_sec != -1) ? bin2bcd(tm->tm_sec) : 0x80;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700255
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700256 fm3130->regs[FM3130_ALARM_MINUTES] =
257 (tm->tm_min != -1) ? bin2bcd(tm->tm_min) : 0x80;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700258
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700259 fm3130->regs[FM3130_ALARM_HOURS] =
260 (tm->tm_hour != -1) ? bin2bcd(tm->tm_hour) : 0x80;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700261
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700262 fm3130->regs[FM3130_ALARM_DATE] =
263 (tm->tm_mday != -1) ? bin2bcd(tm->tm_mday) : 0x80;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700264
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700265 fm3130->regs[FM3130_ALARM_MONTHS] =
266 (tm->tm_mon != -1) ? bin2bcd(tm->tm_mon + 1) : 0x80;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700267
268 dev_dbg(dev, "alarm write %02x %02x %02x %02x %02x\n",
269 fm3130->regs[FM3130_ALARM_SECONDS],
270 fm3130->regs[FM3130_ALARM_MINUTES],
271 fm3130->regs[FM3130_ALARM_HOURS],
272 fm3130->regs[FM3130_ALARM_DATE],
273 fm3130->regs[FM3130_ALARM_MONTHS]);
274 /* Writing time registers, we don't support multibyte transfers */
275 for (i = 0; i < FM3130_ALARM_REGS; i++) {
276 i2c_smbus_write_byte_data(fm3130->client,
277 FM3130_ALARM_SECONDS + i,
278 fm3130->regs[FM3130_ALARM_SECONDS + i]);
279 }
280 fm3130->regs[FM3130_RTC_CONTROL] =
281 i2c_smbus_read_byte_data(fm3130->client, FM3130_RTC_CONTROL);
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700282
283 /* enable or disable alarm */
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700284 if (alrm->enabled) {
285 i2c_smbus_write_byte_data(fm3130->client, FM3130_RTC_CONTROL,
286 (fm3130->regs[FM3130_RTC_CONTROL] &
287 ~(FM3130_RTC_CONTROL_BIT_CAL)) |
288 FM3130_RTC_CONTROL_BIT_AEN);
289 } else {
290 i2c_smbus_write_byte_data(fm3130->client, FM3130_RTC_CONTROL,
291 fm3130->regs[FM3130_RTC_CONTROL] &
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700292 ~(FM3130_RTC_CONTROL_BIT_CAL) &
293 ~(FM3130_RTC_CONTROL_BIT_AEN));
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700294 }
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700295
296 /* We assume here that data is valid once written */
297 if (!fm3130->alarm_valid)
298 fm3130->alarm_valid = 1;
299
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700300 return 0;
301}
302
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700303static int fm3130_alarm_irq_enable(struct device *dev, unsigned int enabled)
304{
305 struct fm3130 *fm3130 = dev_get_drvdata(dev);
306 int ret = 0;
307
308 fm3130->regs[FM3130_RTC_CONTROL] =
309 i2c_smbus_read_byte_data(fm3130->client, FM3130_RTC_CONTROL);
310
311 dev_dbg(dev, "alarm_irq_enable: enable=%d, FM3130_RTC_CONTROL=%02x\n",
312 enabled, fm3130->regs[FM3130_RTC_CONTROL]);
313
314 switch (enabled) {
315 case 0: /* alarm off */
316 ret = i2c_smbus_write_byte_data(fm3130->client,
317 FM3130_RTC_CONTROL, fm3130->regs[FM3130_RTC_CONTROL] &
318 ~(FM3130_RTC_CONTROL_BIT_CAL) &
319 ~(FM3130_RTC_CONTROL_BIT_AEN));
320 break;
321 case 1: /* alarm on */
322 ret = i2c_smbus_write_byte_data(fm3130->client,
323 FM3130_RTC_CONTROL, (fm3130->regs[FM3130_RTC_CONTROL] &
324 ~(FM3130_RTC_CONTROL_BIT_CAL)) |
325 FM3130_RTC_CONTROL_BIT_AEN);
326 break;
327 default:
328 ret = -EINVAL;
329 break;
330 }
331
332 return ret;
333}
334
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700335static const struct rtc_class_ops fm3130_rtc_ops = {
336 .read_time = fm3130_get_time,
337 .set_time = fm3130_set_time,
338 .read_alarm = fm3130_read_alarm,
339 .set_alarm = fm3130_set_alarm,
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700340 .alarm_irq_enable = fm3130_alarm_irq_enable,
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700341};
342
343static struct i2c_driver fm3130_driver;
344
Greg Kroah-Hartman5a167f42012-12-21 13:09:38 -0800345static int fm3130_probe(struct i2c_client *client,
346 const struct i2c_device_id *id)
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700347{
348 struct fm3130 *fm3130;
349 int err = -ENODEV;
350 int tmp;
351 struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
352
353 if (!i2c_check_functionality(adapter,
354 I2C_FUNC_I2C | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
355 return -EIO;
356
Jingoo Hanc54a52e2013-04-29 16:20:41 -0700357 fm3130 = devm_kzalloc(&client->dev, sizeof(struct fm3130), GFP_KERNEL);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700358
359 if (!fm3130)
360 return -ENOMEM;
361
362 fm3130->client = client;
363 i2c_set_clientdata(client, fm3130);
364 fm3130->reg_addr_time = FM3130_RTC_SECONDS;
365 fm3130->reg_addr_alarm = FM3130_ALARM_SECONDS;
366
367 /* Messages to read time */
368 fm3130->msg[0].addr = client->addr;
369 fm3130->msg[0].flags = 0;
370 fm3130->msg[0].len = 1;
371 fm3130->msg[0].buf = &fm3130->reg_addr_time;
372
373 fm3130->msg[1].addr = client->addr;
374 fm3130->msg[1].flags = I2C_M_RD;
375 fm3130->msg[1].len = FM3130_CLOCK_REGS;
376 fm3130->msg[1].buf = &fm3130->regs[FM3130_RTC_SECONDS];
377
378 /* Messages to read alarm */
379 fm3130->msg[2].addr = client->addr;
380 fm3130->msg[2].flags = 0;
381 fm3130->msg[2].len = 1;
382 fm3130->msg[2].buf = &fm3130->reg_addr_alarm;
383
384 fm3130->msg[3].addr = client->addr;
385 fm3130->msg[3].flags = I2C_M_RD;
386 fm3130->msg[3].len = FM3130_ALARM_REGS;
387 fm3130->msg[3].buf = &fm3130->regs[FM3130_ALARM_SECONDS];
388
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700389 fm3130->alarm_valid = 0;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700390 fm3130->data_valid = 0;
391
392 tmp = i2c_transfer(adapter, fm3130->msg, 4);
393 if (tmp != 4) {
Jingoo Han198b8ec2013-04-29 16:19:29 -0700394 dev_dbg(&client->dev, "read error %d\n", tmp);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700395 err = -EIO;
396 goto exit_free;
397 }
398
399 fm3130->regs[FM3130_RTC_CONTROL] =
400 i2c_smbus_read_byte_data(client, FM3130_RTC_CONTROL);
401 fm3130->regs[FM3130_CAL_CONTROL] =
402 i2c_smbus_read_byte_data(client, FM3130_CAL_CONTROL);
403
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700404 /* Disabling calibration mode */
Sergey Matyukevichf4b51622010-02-02 13:43:59 -0800405 if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_CAL) {
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700406 i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL,
407 fm3130->regs[FM3130_RTC_CONTROL] &
408 ~(FM3130_RTC_CONTROL_BIT_CAL));
409 dev_warn(&client->dev, "Disabling calibration mode!\n");
Sergey Matyukevichf4b51622010-02-02 13:43:59 -0800410 }
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700411
412 /* Disabling read and write modes */
413 if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_WRITE ||
Sergey Matyukevichf4b51622010-02-02 13:43:59 -0800414 fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_READ) {
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700415 i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL,
416 fm3130->regs[FM3130_RTC_CONTROL] &
417 ~(FM3130_RTC_CONTROL_BIT_READ |
418 FM3130_RTC_CONTROL_BIT_WRITE));
419 dev_warn(&client->dev, "Disabling READ or WRITE mode!\n");
Sergey Matyukevichf4b51622010-02-02 13:43:59 -0800420 }
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700421
422 /* oscillator off? turn it on, so clock can tick. */
423 if (fm3130->regs[FM3130_CAL_CONTROL] & FM3130_CAL_CONTROL_BIT_nOSCEN)
424 i2c_smbus_write_byte_data(client, FM3130_CAL_CONTROL,
425 fm3130->regs[FM3130_CAL_CONTROL] &
426 ~(FM3130_CAL_CONTROL_BIT_nOSCEN));
427
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700428 /* low battery? clear flag, and warn */
429 if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_LB) {
430 i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL,
431 fm3130->regs[FM3130_RTC_CONTROL] &
432 ~(FM3130_RTC_CONTROL_BIT_LB));
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700433 dev_warn(&client->dev, "Low battery!\n");
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700434 }
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700435
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700436 /* check if Power On Reset bit is set */
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700437 if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_POR) {
438 i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL,
439 fm3130->regs[FM3130_RTC_CONTROL] &
440 ~FM3130_RTC_CONTROL_BIT_POR);
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700441 dev_dbg(&client->dev, "POR bit is set\n");
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700442 }
443 /* ACS is controlled by alarm */
444 i2c_smbus_write_byte_data(client, FM3130_ALARM_WP_CONTROL, 0x80);
445
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700446 /* alarm registers sanity check */
447 tmp = bcd2bin(fm3130->regs[FM3130_RTC_SECONDS] & 0x7f);
448 if (tmp > 59)
449 goto bad_alarm;
450
Adrian Bunkfe20ba72008-10-18 20:28:41 -0700451 tmp = bcd2bin(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f);
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700452 if (tmp > 59)
453 goto bad_alarm;
454
455 tmp = bcd2bin(fm3130->regs[FM3130_RTC_HOURS] & 0x3f);
456 if (tmp > 23)
457 goto bad_alarm;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700458
Adrian Bunkfe20ba72008-10-18 20:28:41 -0700459 tmp = bcd2bin(fm3130->regs[FM3130_RTC_DATE] & 0x3f);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700460 if (tmp == 0 || tmp > 31)
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700461 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_MONTHS] & 0x1f);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700464 if (tmp == 0 || tmp > 12)
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700465 goto bad_alarm;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700466
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700467 fm3130->alarm_valid = 1;
468
469bad_alarm:
470
471 /* clock registers sanity chek */
472 tmp = bcd2bin(fm3130->regs[FM3130_RTC_SECONDS] & 0x7f);
473 if (tmp > 59)
474 goto bad_clock;
475
476 tmp = bcd2bin(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f);
477 if (tmp > 59)
478 goto bad_clock;
479
480 tmp = bcd2bin(fm3130->regs[FM3130_RTC_HOURS] & 0x3f);
481 if (tmp > 23)
482 goto bad_clock;
483
484 tmp = bcd2bin(fm3130->regs[FM3130_RTC_DAY] & 0x7);
485 if (tmp == 0 || tmp > 7)
486 goto bad_clock;
487
488 tmp = bcd2bin(fm3130->regs[FM3130_RTC_DATE] & 0x3f);
489 if (tmp == 0 || tmp > 31)
490 goto bad_clock;
491
492 tmp = bcd2bin(fm3130->regs[FM3130_RTC_MONTHS] & 0x1f);
493 if (tmp == 0 || tmp > 12)
494 goto bad_clock;
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700495
496 fm3130->data_valid = 1;
497
Sergey Matyukevichf3f99cf2010-08-10 18:02:10 -0700498bad_clock:
499
500 if (!fm3130->data_valid || !fm3130->alarm_valid)
Andy Shevchenko01a4ca12013-02-21 16:44:22 -0800501 dev_dbg(&client->dev, "%s: %15ph\n", "bogus registers",
502 fm3130->regs);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700503
504 /* We won't bail out here because we just got invalid data.
505 Time setting from u-boot doesn't work anyway */
Jingoo Hanc54a52e2013-04-29 16:20:41 -0700506 fm3130->rtc = devm_rtc_device_register(&client->dev, client->name,
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700507 &fm3130_rtc_ops, THIS_MODULE);
508 if (IS_ERR(fm3130->rtc)) {
509 err = PTR_ERR(fm3130->rtc);
510 dev_err(&client->dev,
511 "unable to register the class device\n");
512 goto exit_free;
513 }
514 return 0;
515exit_free:
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700516 return err;
517}
518
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700519static struct i2c_driver fm3130_driver = {
520 .driver = {
521 .name = "rtc-fm3130",
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700522 },
523 .probe = fm3130_probe,
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700524 .id_table = fm3130_id,
525};
526
Axel Lin0abc9202012-03-23 15:02:31 -0700527module_i2c_driver(fm3130_driver);
Sergey Lapinc6d8f402008-06-12 15:21:55 -0700528
529MODULE_DESCRIPTION("RTC driver for FM3130");
530MODULE_AUTHOR("Sergey Lapin <slapin@ossfans.org>");
531MODULE_LICENSE("GPL");
532