Merge branch 'bkl/procfs' of git://git.kernel.org/pub/scm/linux/kernel/git/frederic...
[linux-2.6-block.git] / drivers / rtc / rtc-fm3130.c
CommitLineData
c6d8f400
SL
1/*
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>
5a0e3ad6 16#include <linux/slab.h>
c6d8f400
SL
17
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;
50 u8 reg_addr_alarm;
51 u8 regs[15];
52 struct i2c_msg msg[4];
53 struct i2c_client *client;
54 struct rtc_device *rtc;
55 int data_valid;
56 int alarm;
57};
58static const struct i2c_device_id fm3130_id[] = {
876550aa 59 { "fm3130", 0 },
c6d8f400
SL
60 { }
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 }
90 /* Checking for alarm */
91 if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_AF) {
92 fm3130->alarm = 1;
93 fm3130->regs[FM3130_RTC_CONTROL] &= ~FM3130_RTC_CONTROL_BIT_AF;
94 }
95 i2c_smbus_write_byte_data(fm3130->client,
96 FM3130_RTC_CONTROL, fm3130->regs[FM3130_RTC_CONTROL]);
97}
98
99static int fm3130_get_time(struct device *dev, struct rtc_time *t)
100{
101 struct fm3130 *fm3130 = dev_get_drvdata(dev);
102 int tmp;
103
104 if (!fm3130->data_valid) {
105 /* We have invalid data in RTC, probably due
106 to battery faults or other problems. Return EIO
107 for now, it will allow us to set data later insted
108 of error during probing which disables device */
109 return -EIO;
110 }
111 fm3130_rtc_mode(dev, FM3130_MODE_READ);
112
113 /* read the RTC date and time registers all at once */
114 tmp = i2c_transfer(to_i2c_adapter(fm3130->client->dev.parent),
115 fm3130->msg, 2);
116 if (tmp != 2) {
117 dev_err(dev, "%s error %d\n", "read", tmp);
118 return -EIO;
119 }
120
121 fm3130_rtc_mode(dev, FM3130_MODE_NORMAL);
122
123 dev_dbg(dev, "%s: %02x %02x %02x %02x %02x %02x %02x %02x"
124 "%02x %02x %02x %02x %02x %02x %02x\n",
125 "read",
126 fm3130->regs[0], fm3130->regs[1],
127 fm3130->regs[2], fm3130->regs[3],
128 fm3130->regs[4], fm3130->regs[5],
129 fm3130->regs[6], fm3130->regs[7],
130 fm3130->regs[8], fm3130->regs[9],
131 fm3130->regs[0xa], fm3130->regs[0xb],
132 fm3130->regs[0xc], fm3130->regs[0xd],
133 fm3130->regs[0xe]);
134
fe20ba70
AB
135 t->tm_sec = bcd2bin(fm3130->regs[FM3130_RTC_SECONDS] & 0x7f);
136 t->tm_min = bcd2bin(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f);
c6d8f400 137 tmp = fm3130->regs[FM3130_RTC_HOURS] & 0x3f;
fe20ba70
AB
138 t->tm_hour = bcd2bin(tmp);
139 t->tm_wday = bcd2bin(fm3130->regs[FM3130_RTC_DAY] & 0x07) - 1;
140 t->tm_mday = bcd2bin(fm3130->regs[FM3130_RTC_DATE] & 0x3f);
c6d8f400 141 tmp = fm3130->regs[FM3130_RTC_MONTHS] & 0x1f;
fe20ba70 142 t->tm_mon = bcd2bin(tmp) - 1;
c6d8f400
SL
143
144 /* assume 20YY not 19YY, and ignore CF bit */
fe20ba70 145 t->tm_year = bcd2bin(fm3130->regs[FM3130_RTC_YEARS]) + 100;
c6d8f400
SL
146
147 dev_dbg(dev, "%s secs=%d, mins=%d, "
148 "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
149 "read", t->tm_sec, t->tm_min,
150 t->tm_hour, t->tm_mday,
151 t->tm_mon, t->tm_year, t->tm_wday);
152
153 /* initial clock setting can be undefined */
154 return rtc_valid_tm(t);
155}
156
157
158static int fm3130_set_time(struct device *dev, struct rtc_time *t)
159{
160 struct fm3130 *fm3130 = dev_get_drvdata(dev);
161 int tmp, i;
162 u8 *buf = fm3130->regs;
163
164 dev_dbg(dev, "%s secs=%d, mins=%d, "
165 "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
166 "write", t->tm_sec, t->tm_min,
167 t->tm_hour, t->tm_mday,
168 t->tm_mon, t->tm_year, t->tm_wday);
169
170 /* first register addr */
fe20ba70
AB
171 buf[FM3130_RTC_SECONDS] = bin2bcd(t->tm_sec);
172 buf[FM3130_RTC_MINUTES] = bin2bcd(t->tm_min);
173 buf[FM3130_RTC_HOURS] = bin2bcd(t->tm_hour);
174 buf[FM3130_RTC_DAY] = bin2bcd(t->tm_wday + 1);
175 buf[FM3130_RTC_DATE] = bin2bcd(t->tm_mday);
176 buf[FM3130_RTC_MONTHS] = bin2bcd(t->tm_mon + 1);
c6d8f400
SL
177
178 /* assume 20YY not 19YY */
179 tmp = t->tm_year - 100;
fe20ba70 180 buf[FM3130_RTC_YEARS] = bin2bcd(tmp);
c6d8f400
SL
181
182 dev_dbg(dev, "%s: %02x %02x %02x %02x %02x %02x %02x"
183 "%02x %02x %02x %02x %02x %02x %02x %02x\n",
184 "write", buf[0], buf[1], buf[2], buf[3],
185 buf[4], buf[5], buf[6], buf[7],
186 buf[8], buf[9], buf[0xa], buf[0xb],
187 buf[0xc], buf[0xd], buf[0xe]);
188
189 fm3130_rtc_mode(dev, FM3130_MODE_WRITE);
190
191 /* Writing time registers, we don't support multibyte transfers */
192 for (i = 0; i < FM3130_CLOCK_REGS; i++) {
193 i2c_smbus_write_byte_data(fm3130->client,
194 FM3130_RTC_SECONDS + i,
195 fm3130->regs[FM3130_RTC_SECONDS + i]);
196 }
197
198 fm3130_rtc_mode(dev, FM3130_MODE_NORMAL);
199
200 /* We assume here that data are valid once written */
201 if (!fm3130->data_valid)
202 fm3130->data_valid = 1;
203 return 0;
204}
205
206static int fm3130_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
207{
208 struct fm3130 *fm3130 = dev_get_drvdata(dev);
209 int tmp;
210 struct rtc_time *tm = &alrm->time;
211 /* read the RTC alarm registers all at once */
212 tmp = i2c_transfer(to_i2c_adapter(fm3130->client->dev.parent),
213 &fm3130->msg[2], 2);
214 if (tmp != 2) {
215 dev_err(dev, "%s error %d\n", "read", tmp);
216 return -EIO;
217 }
218 dev_dbg(dev, "alarm read %02x %02x %02x %02x %02x\n",
219 fm3130->regs[FM3130_ALARM_SECONDS],
220 fm3130->regs[FM3130_ALARM_MINUTES],
221 fm3130->regs[FM3130_ALARM_HOURS],
222 fm3130->regs[FM3130_ALARM_DATE],
223 fm3130->regs[FM3130_ALARM_MONTHS]);
224
225
fe20ba70
AB
226 tm->tm_sec = bcd2bin(fm3130->regs[FM3130_ALARM_SECONDS] & 0x7F);
227 tm->tm_min = bcd2bin(fm3130->regs[FM3130_ALARM_MINUTES] & 0x7F);
228 tm->tm_hour = bcd2bin(fm3130->regs[FM3130_ALARM_HOURS] & 0x3F);
229 tm->tm_mday = bcd2bin(fm3130->regs[FM3130_ALARM_DATE] & 0x3F);
230 tm->tm_mon = bcd2bin(fm3130->regs[FM3130_ALARM_MONTHS] & 0x1F);
c6d8f400
SL
231 if (tm->tm_mon > 0)
232 tm->tm_mon -= 1; /* RTC is 1-12, tm_mon is 0-11 */
233 dev_dbg(dev, "%s secs=%d, mins=%d, "
234 "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
235 "read alarm", tm->tm_sec, tm->tm_min,
236 tm->tm_hour, tm->tm_mday,
237 tm->tm_mon, tm->tm_year, tm->tm_wday);
238
239 return 0;
240}
241
242static int fm3130_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
243{
244 struct fm3130 *fm3130 = dev_get_drvdata(dev);
245 struct rtc_time *tm = &alrm->time;
246 int i;
247
248 dev_dbg(dev, "%s secs=%d, mins=%d, "
249 "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
250 "write alarm", tm->tm_sec, tm->tm_min,
251 tm->tm_hour, tm->tm_mday,
252 tm->tm_mon, tm->tm_year, tm->tm_wday);
253
254 if (tm->tm_sec != -1)
255 fm3130->regs[FM3130_ALARM_SECONDS] =
fe20ba70 256 bin2bcd(tm->tm_sec) | 0x80;
c6d8f400
SL
257
258 if (tm->tm_min != -1)
259 fm3130->regs[FM3130_ALARM_MINUTES] =
fe20ba70 260 bin2bcd(tm->tm_min) | 0x80;
c6d8f400
SL
261
262 if (tm->tm_hour != -1)
263 fm3130->regs[FM3130_ALARM_HOURS] =
fe20ba70 264 bin2bcd(tm->tm_hour) | 0x80;
c6d8f400
SL
265
266 if (tm->tm_mday != -1)
267 fm3130->regs[FM3130_ALARM_DATE] =
fe20ba70 268 bin2bcd(tm->tm_mday) | 0x80;
c6d8f400
SL
269
270 if (tm->tm_mon != -1)
271 fm3130->regs[FM3130_ALARM_MONTHS] =
fe20ba70 272 bin2bcd(tm->tm_mon + 1) | 0x80;
c6d8f400
SL
273
274 dev_dbg(dev, "alarm write %02x %02x %02x %02x %02x\n",
275 fm3130->regs[FM3130_ALARM_SECONDS],
276 fm3130->regs[FM3130_ALARM_MINUTES],
277 fm3130->regs[FM3130_ALARM_HOURS],
278 fm3130->regs[FM3130_ALARM_DATE],
279 fm3130->regs[FM3130_ALARM_MONTHS]);
280 /* Writing time registers, we don't support multibyte transfers */
281 for (i = 0; i < FM3130_ALARM_REGS; i++) {
282 i2c_smbus_write_byte_data(fm3130->client,
283 FM3130_ALARM_SECONDS + i,
284 fm3130->regs[FM3130_ALARM_SECONDS + i]);
285 }
286 fm3130->regs[FM3130_RTC_CONTROL] =
287 i2c_smbus_read_byte_data(fm3130->client, FM3130_RTC_CONTROL);
288 /* Checking for alarm */
289 if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_AF) {
290 fm3130->alarm = 1;
291 fm3130->regs[FM3130_RTC_CONTROL] &= ~FM3130_RTC_CONTROL_BIT_AF;
292 }
293 if (alrm->enabled) {
294 i2c_smbus_write_byte_data(fm3130->client, FM3130_RTC_CONTROL,
295 (fm3130->regs[FM3130_RTC_CONTROL] &
296 ~(FM3130_RTC_CONTROL_BIT_CAL)) |
297 FM3130_RTC_CONTROL_BIT_AEN);
298 } else {
299 i2c_smbus_write_byte_data(fm3130->client, FM3130_RTC_CONTROL,
300 fm3130->regs[FM3130_RTC_CONTROL] &
301 ~(FM3130_RTC_CONTROL_BIT_AEN));
302 }
303 return 0;
304}
305
306static const struct rtc_class_ops fm3130_rtc_ops = {
307 .read_time = fm3130_get_time,
308 .set_time = fm3130_set_time,
309 .read_alarm = fm3130_read_alarm,
310 .set_alarm = fm3130_set_alarm,
311};
312
313static struct i2c_driver fm3130_driver;
314
315static int __devinit fm3130_probe(struct i2c_client *client,
316 const struct i2c_device_id *id)
317{
318 struct fm3130 *fm3130;
319 int err = -ENODEV;
320 int tmp;
321 struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
322
323 if (!i2c_check_functionality(adapter,
324 I2C_FUNC_I2C | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
325 return -EIO;
326
327 fm3130 = kzalloc(sizeof(struct fm3130), GFP_KERNEL);
328
329 if (!fm3130)
330 return -ENOMEM;
331
332 fm3130->client = client;
333 i2c_set_clientdata(client, fm3130);
334 fm3130->reg_addr_time = FM3130_RTC_SECONDS;
335 fm3130->reg_addr_alarm = FM3130_ALARM_SECONDS;
336
337 /* Messages to read time */
338 fm3130->msg[0].addr = client->addr;
339 fm3130->msg[0].flags = 0;
340 fm3130->msg[0].len = 1;
341 fm3130->msg[0].buf = &fm3130->reg_addr_time;
342
343 fm3130->msg[1].addr = client->addr;
344 fm3130->msg[1].flags = I2C_M_RD;
345 fm3130->msg[1].len = FM3130_CLOCK_REGS;
346 fm3130->msg[1].buf = &fm3130->regs[FM3130_RTC_SECONDS];
347
348 /* Messages to read alarm */
349 fm3130->msg[2].addr = client->addr;
350 fm3130->msg[2].flags = 0;
351 fm3130->msg[2].len = 1;
352 fm3130->msg[2].buf = &fm3130->reg_addr_alarm;
353
354 fm3130->msg[3].addr = client->addr;
355 fm3130->msg[3].flags = I2C_M_RD;
356 fm3130->msg[3].len = FM3130_ALARM_REGS;
357 fm3130->msg[3].buf = &fm3130->regs[FM3130_ALARM_SECONDS];
358
359 fm3130->data_valid = 0;
360
361 tmp = i2c_transfer(adapter, fm3130->msg, 4);
362 if (tmp != 4) {
363 pr_debug("read error %d\n", tmp);
364 err = -EIO;
365 goto exit_free;
366 }
367
368 fm3130->regs[FM3130_RTC_CONTROL] =
369 i2c_smbus_read_byte_data(client, FM3130_RTC_CONTROL);
370 fm3130->regs[FM3130_CAL_CONTROL] =
371 i2c_smbus_read_byte_data(client, FM3130_CAL_CONTROL);
372
373 /* Checking for alarm */
374 if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_AF) {
375 fm3130->alarm = 1;
376 fm3130->regs[FM3130_RTC_CONTROL] &= ~FM3130_RTC_CONTROL_BIT_AF;
377 }
378
379 /* Disabling calibration mode */
f4b51628 380 if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_CAL) {
c6d8f400
SL
381 i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL,
382 fm3130->regs[FM3130_RTC_CONTROL] &
383 ~(FM3130_RTC_CONTROL_BIT_CAL));
384 dev_warn(&client->dev, "Disabling calibration mode!\n");
f4b51628 385 }
c6d8f400
SL
386
387 /* Disabling read and write modes */
388 if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_WRITE ||
f4b51628 389 fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_READ) {
c6d8f400
SL
390 i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL,
391 fm3130->regs[FM3130_RTC_CONTROL] &
392 ~(FM3130_RTC_CONTROL_BIT_READ |
393 FM3130_RTC_CONTROL_BIT_WRITE));
394 dev_warn(&client->dev, "Disabling READ or WRITE mode!\n");
f4b51628 395 }
c6d8f400
SL
396
397 /* oscillator off? turn it on, so clock can tick. */
398 if (fm3130->regs[FM3130_CAL_CONTROL] & FM3130_CAL_CONTROL_BIT_nOSCEN)
399 i2c_smbus_write_byte_data(client, FM3130_CAL_CONTROL,
400 fm3130->regs[FM3130_CAL_CONTROL] &
401 ~(FM3130_CAL_CONTROL_BIT_nOSCEN));
402
403 /* oscillator fault? clear flag, and warn */
404 if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_LB)
405 dev_warn(&client->dev, "Low battery!\n");
406
407 /* oscillator fault? clear flag, and warn */
408 if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_POR) {
409 i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL,
410 fm3130->regs[FM3130_RTC_CONTROL] &
411 ~FM3130_RTC_CONTROL_BIT_POR);
412 dev_warn(&client->dev, "SET TIME!\n");
413 }
414 /* ACS is controlled by alarm */
415 i2c_smbus_write_byte_data(client, FM3130_ALARM_WP_CONTROL, 0x80);
416
417 /* TODO */
418 /* TODO need to sanity check alarm */
419 tmp = fm3130->regs[FM3130_RTC_SECONDS];
fe20ba70 420 tmp = bcd2bin(tmp & 0x7f);
c6d8f400
SL
421 if (tmp > 60)
422 goto exit_bad;
fe20ba70 423 tmp = bcd2bin(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f);
c6d8f400
SL
424 if (tmp > 60)
425 goto exit_bad;
426
fe20ba70 427 tmp = bcd2bin(fm3130->regs[FM3130_RTC_DATE] & 0x3f);
c6d8f400
SL
428 if (tmp == 0 || tmp > 31)
429 goto exit_bad;
430
fe20ba70 431 tmp = bcd2bin(fm3130->regs[FM3130_RTC_MONTHS] & 0x1f);
c6d8f400
SL
432 if (tmp == 0 || tmp > 12)
433 goto exit_bad;
434
435 tmp = fm3130->regs[FM3130_RTC_HOURS];
436
437 fm3130->data_valid = 1;
438
439exit_bad:
440 if (!fm3130->data_valid)
441 dev_dbg(&client->dev,
442 "%s: %02x %02x %02x %02x %02x %02x %02x %02x"
443 "%02x %02x %02x %02x %02x %02x %02x\n",
444 "bogus registers",
445 fm3130->regs[0], fm3130->regs[1],
446 fm3130->regs[2], fm3130->regs[3],
447 fm3130->regs[4], fm3130->regs[5],
448 fm3130->regs[6], fm3130->regs[7],
449 fm3130->regs[8], fm3130->regs[9],
450 fm3130->regs[0xa], fm3130->regs[0xb],
451 fm3130->regs[0xc], fm3130->regs[0xd],
452 fm3130->regs[0xe]);
453
454 /* We won't bail out here because we just got invalid data.
455 Time setting from u-boot doesn't work anyway */
456 fm3130->rtc = rtc_device_register(client->name, &client->dev,
457 &fm3130_rtc_ops, THIS_MODULE);
458 if (IS_ERR(fm3130->rtc)) {
459 err = PTR_ERR(fm3130->rtc);
460 dev_err(&client->dev,
461 "unable to register the class device\n");
462 goto exit_free;
463 }
464 return 0;
465exit_free:
466 kfree(fm3130);
467 return err;
468}
469
470static int __devexit fm3130_remove(struct i2c_client *client)
471{
472 struct fm3130 *fm3130 = i2c_get_clientdata(client);
473
474 rtc_device_unregister(fm3130->rtc);
475 kfree(fm3130);
476 return 0;
477}
478
479static struct i2c_driver fm3130_driver = {
480 .driver = {
481 .name = "rtc-fm3130",
482 .owner = THIS_MODULE,
483 },
484 .probe = fm3130_probe,
485 .remove = __devexit_p(fm3130_remove),
486 .id_table = fm3130_id,
487};
488
489static int __init fm3130_init(void)
490{
491 return i2c_add_driver(&fm3130_driver);
492}
493module_init(fm3130_init);
494
495static void __exit fm3130_exit(void)
496{
497 i2c_del_driver(&fm3130_driver);
498}
499module_exit(fm3130_exit);
500
501MODULE_DESCRIPTION("RTC driver for FM3130");
502MODULE_AUTHOR("Sergey Lapin <slapin@ossfans.org>");
503MODULE_LICENSE("GPL");
504