diff options
Diffstat (limited to 'drivers/rtc/rtc-rs5c372.c')
-rw-r--r-- | drivers/rtc/rtc-rs5c372.c | 228 |
1 files changed, 148 insertions, 80 deletions
diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c index 56caf6b2c3e5..8b561958fb1e 100644 --- a/drivers/rtc/rtc-rs5c372.c +++ b/drivers/rtc/rtc-rs5c372.c | |||
@@ -1,8 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * An I2C driver for Ricoh RS5C372 and RV5C38[67] RTCs | 2 | * An I2C driver for Ricoh RS5C372, R2025S/D and RV5C38[67] RTCs |
3 | * | 3 | * |
4 | * Copyright (C) 2005 Pavel Mironchik <pmironchik@optifacio.net> | 4 | * Copyright (C) 2005 Pavel Mironchik <pmironchik@optifacio.net> |
5 | * Copyright (C) 2006 Tower Technologies | 5 | * Copyright (C) 2006 Tower Technologies |
6 | * Copyright (C) 2008 Paul Mundt | ||
6 | * | 7 | * |
7 | * This program is free software; you can redistribute it and/or modify | 8 | * 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 | * it under the terms of the GNU General Public License version 2 as |
@@ -13,7 +14,7 @@ | |||
13 | #include <linux/rtc.h> | 14 | #include <linux/rtc.h> |
14 | #include <linux/bcd.h> | 15 | #include <linux/bcd.h> |
15 | 16 | ||
16 | #define DRV_VERSION "0.5" | 17 | #define DRV_VERSION "0.6" |
17 | 18 | ||
18 | 19 | ||
19 | /* | 20 | /* |
@@ -51,7 +52,8 @@ | |||
51 | # define RS5C_CTRL1_CT4 (4 << 0) /* 1 Hz level irq */ | 52 | # define RS5C_CTRL1_CT4 (4 << 0) /* 1 Hz level irq */ |
52 | #define RS5C_REG_CTRL2 15 | 53 | #define RS5C_REG_CTRL2 15 |
53 | # define RS5C372_CTRL2_24 (1 << 5) | 54 | # define RS5C372_CTRL2_24 (1 << 5) |
54 | # define RS5C_CTRL2_XSTP (1 << 4) | 55 | # define R2025_CTRL2_XST (1 << 5) |
56 | # define RS5C_CTRL2_XSTP (1 << 4) /* only if !R2025S/D */ | ||
55 | # define RS5C_CTRL2_CTFG (1 << 2) | 57 | # define RS5C_CTRL2_CTFG (1 << 2) |
56 | # define RS5C_CTRL2_AAFG (1 << 1) /* or WAFG */ | 58 | # define RS5C_CTRL2_AAFG (1 << 1) /* or WAFG */ |
57 | # define RS5C_CTRL2_BAFG (1 << 0) /* or DAFG */ | 59 | # define RS5C_CTRL2_BAFG (1 << 0) /* or DAFG */ |
@@ -63,6 +65,7 @@ | |||
63 | 65 | ||
64 | enum rtc_type { | 66 | enum rtc_type { |
65 | rtc_undef = 0, | 67 | rtc_undef = 0, |
68 | rtc_r2025sd, | ||
66 | rtc_rs5c372a, | 69 | rtc_rs5c372a, |
67 | rtc_rs5c372b, | 70 | rtc_rs5c372b, |
68 | rtc_rv5c386, | 71 | rtc_rv5c386, |
@@ -70,6 +73,7 @@ enum rtc_type { | |||
70 | }; | 73 | }; |
71 | 74 | ||
72 | static const struct i2c_device_id rs5c372_id[] = { | 75 | static const struct i2c_device_id rs5c372_id[] = { |
76 | { "r2025sd", rtc_r2025sd }, | ||
73 | { "rs5c372a", rtc_rs5c372a }, | 77 | { "rs5c372a", rtc_rs5c372a }, |
74 | { "rs5c372b", rtc_rs5c372b }, | 78 | { "rs5c372b", rtc_rs5c372b }, |
75 | { "rv5c386", rtc_rv5c386 }, | 79 | { "rv5c386", rtc_rv5c386 }, |
@@ -89,6 +93,7 @@ struct rs5c372 { | |||
89 | enum rtc_type type; | 93 | enum rtc_type type; |
90 | unsigned time24:1; | 94 | unsigned time24:1; |
91 | unsigned has_irq:1; | 95 | unsigned has_irq:1; |
96 | unsigned smbus:1; | ||
92 | char buf[17]; | 97 | char buf[17]; |
93 | char *regs; | 98 | char *regs; |
94 | }; | 99 | }; |
@@ -106,10 +111,25 @@ static int rs5c_get_regs(struct rs5c372 *rs5c) | |||
106 | * | 111 | * |
107 | * The first method doesn't work with the iop3xx adapter driver, on at | 112 | * The first method doesn't work with the iop3xx adapter driver, on at |
108 | * least 80219 chips; this works around that bug. | 113 | * least 80219 chips; this works around that bug. |
114 | * | ||
115 | * The third method on the other hand doesn't work for the SMBus-only | ||
116 | * configurations, so we use the the first method there, stripping off | ||
117 | * the extra register in the process. | ||
109 | */ | 118 | */ |
110 | if ((i2c_transfer(client->adapter, msgs, 1)) != 1) { | 119 | if (rs5c->smbus) { |
111 | dev_warn(&client->dev, "can't read registers\n"); | 120 | int addr = RS5C_ADDR(RS5C372_REG_SECS); |
112 | return -EIO; | 121 | int size = sizeof(rs5c->buf) - 1; |
122 | |||
123 | if (i2c_smbus_read_i2c_block_data(client, addr, size, | ||
124 | rs5c->buf + 1) != size) { | ||
125 | dev_warn(&client->dev, "can't read registers\n"); | ||
126 | return -EIO; | ||
127 | } | ||
128 | } else { | ||
129 | if ((i2c_transfer(client->adapter, msgs, 1)) != 1) { | ||
130 | dev_warn(&client->dev, "can't read registers\n"); | ||
131 | return -EIO; | ||
132 | } | ||
113 | } | 133 | } |
114 | 134 | ||
115 | dev_dbg(&client->dev, | 135 | dev_dbg(&client->dev, |
@@ -187,6 +207,7 @@ static int rs5c372_set_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
187 | { | 207 | { |
188 | struct rs5c372 *rs5c = i2c_get_clientdata(client); | 208 | struct rs5c372 *rs5c = i2c_get_clientdata(client); |
189 | unsigned char buf[8]; | 209 | unsigned char buf[8]; |
210 | int addr; | ||
190 | 211 | ||
191 | dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d " | 212 | dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d " |
192 | "mday=%d, mon=%d, year=%d, wday=%d\n", | 213 | "mday=%d, mon=%d, year=%d, wday=%d\n", |
@@ -194,16 +215,16 @@ static int rs5c372_set_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
194 | tm->tm_sec, tm->tm_min, tm->tm_hour, | 215 | tm->tm_sec, tm->tm_min, tm->tm_hour, |
195 | tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); | 216 | tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); |
196 | 217 | ||
197 | buf[0] = RS5C_ADDR(RS5C372_REG_SECS); | 218 | addr = RS5C_ADDR(RS5C372_REG_SECS); |
198 | buf[1] = BIN2BCD(tm->tm_sec); | 219 | buf[0] = BIN2BCD(tm->tm_sec); |
199 | buf[2] = BIN2BCD(tm->tm_min); | 220 | buf[1] = BIN2BCD(tm->tm_min); |
200 | buf[3] = rs5c_hr2reg(rs5c, tm->tm_hour); | 221 | buf[2] = rs5c_hr2reg(rs5c, tm->tm_hour); |
201 | buf[4] = BIN2BCD(tm->tm_wday); | 222 | buf[3] = BIN2BCD(tm->tm_wday); |
202 | buf[5] = BIN2BCD(tm->tm_mday); | 223 | buf[4] = BIN2BCD(tm->tm_mday); |
203 | buf[6] = BIN2BCD(tm->tm_mon + 1); | 224 | buf[5] = BIN2BCD(tm->tm_mon + 1); |
204 | buf[7] = BIN2BCD(tm->tm_year - 100); | 225 | buf[6] = BIN2BCD(tm->tm_year - 100); |
205 | 226 | ||
206 | if ((i2c_master_send(client, buf, 8)) != 8) { | 227 | if (i2c_smbus_write_i2c_block_data(client, addr, sizeof(buf), buf) < 0) { |
207 | dev_err(&client->dev, "%s: write error\n", __func__); | 228 | dev_err(&client->dev, "%s: write error\n", __func__); |
208 | return -EIO; | 229 | return -EIO; |
209 | } | 230 | } |
@@ -266,16 +287,16 @@ rs5c_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | |||
266 | { | 287 | { |
267 | struct i2c_client *client = to_i2c_client(dev); | 288 | struct i2c_client *client = to_i2c_client(dev); |
268 | struct rs5c372 *rs5c = i2c_get_clientdata(client); | 289 | struct rs5c372 *rs5c = i2c_get_clientdata(client); |
269 | unsigned char buf[2]; | 290 | unsigned char buf; |
270 | int status; | 291 | int status, addr; |
271 | 292 | ||
272 | buf[1] = rs5c->regs[RS5C_REG_CTRL1]; | 293 | buf = rs5c->regs[RS5C_REG_CTRL1]; |
273 | switch (cmd) { | 294 | switch (cmd) { |
274 | case RTC_UIE_OFF: | 295 | case RTC_UIE_OFF: |
275 | case RTC_UIE_ON: | 296 | case RTC_UIE_ON: |
276 | /* some 327a modes use a different IRQ pin for 1Hz irqs */ | 297 | /* some 327a modes use a different IRQ pin for 1Hz irqs */ |
277 | if (rs5c->type == rtc_rs5c372a | 298 | if (rs5c->type == rtc_rs5c372a |
278 | && (buf[1] & RS5C372A_CTRL1_SL1)) | 299 | && (buf & RS5C372A_CTRL1_SL1)) |
279 | return -ENOIOCTLCMD; | 300 | return -ENOIOCTLCMD; |
280 | case RTC_AIE_OFF: | 301 | case RTC_AIE_OFF: |
281 | case RTC_AIE_ON: | 302 | case RTC_AIE_ON: |
@@ -293,28 +314,30 @@ rs5c_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | |||
293 | if (status < 0) | 314 | if (status < 0) |
294 | return status; | 315 | return status; |
295 | 316 | ||
296 | buf[0] = RS5C_ADDR(RS5C_REG_CTRL1); | 317 | addr = RS5C_ADDR(RS5C_REG_CTRL1); |
297 | switch (cmd) { | 318 | switch (cmd) { |
298 | case RTC_AIE_OFF: /* alarm off */ | 319 | case RTC_AIE_OFF: /* alarm off */ |
299 | buf[1] &= ~RS5C_CTRL1_AALE; | 320 | buf &= ~RS5C_CTRL1_AALE; |
300 | break; | 321 | break; |
301 | case RTC_AIE_ON: /* alarm on */ | 322 | case RTC_AIE_ON: /* alarm on */ |
302 | buf[1] |= RS5C_CTRL1_AALE; | 323 | buf |= RS5C_CTRL1_AALE; |
303 | break; | 324 | break; |
304 | case RTC_UIE_OFF: /* update off */ | 325 | case RTC_UIE_OFF: /* update off */ |
305 | buf[1] &= ~RS5C_CTRL1_CT_MASK; | 326 | buf &= ~RS5C_CTRL1_CT_MASK; |
306 | break; | 327 | break; |
307 | case RTC_UIE_ON: /* update on */ | 328 | case RTC_UIE_ON: /* update on */ |
308 | buf[1] &= ~RS5C_CTRL1_CT_MASK; | 329 | buf &= ~RS5C_CTRL1_CT_MASK; |
309 | buf[1] |= RS5C_CTRL1_CT4; | 330 | buf |= RS5C_CTRL1_CT4; |
310 | break; | 331 | break; |
311 | } | 332 | } |
312 | if ((i2c_master_send(client, buf, 2)) != 2) { | 333 | |
334 | if (i2c_smbus_write_byte_data(client, addr, buf) < 0) { | ||
313 | printk(KERN_WARNING "%s: can't update alarm\n", | 335 | printk(KERN_WARNING "%s: can't update alarm\n", |
314 | rs5c->rtc->name); | 336 | rs5c->rtc->name); |
315 | status = -EIO; | 337 | status = -EIO; |
316 | } else | 338 | } else |
317 | rs5c->regs[RS5C_REG_CTRL1] = buf[1]; | 339 | rs5c->regs[RS5C_REG_CTRL1] = buf; |
340 | |||
318 | return status; | 341 | return status; |
319 | } | 342 | } |
320 | 343 | ||
@@ -364,8 +387,8 @@ static int rs5c_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
364 | { | 387 | { |
365 | struct i2c_client *client = to_i2c_client(dev); | 388 | struct i2c_client *client = to_i2c_client(dev); |
366 | struct rs5c372 *rs5c = i2c_get_clientdata(client); | 389 | struct rs5c372 *rs5c = i2c_get_clientdata(client); |
367 | int status; | 390 | int status, addr, i; |
368 | unsigned char buf[4]; | 391 | unsigned char buf[3]; |
369 | 392 | ||
370 | /* only handle up to 24 hours in the future, like RTC_ALM_SET */ | 393 | /* only handle up to 24 hours in the future, like RTC_ALM_SET */ |
371 | if (t->time.tm_mday != -1 | 394 | if (t->time.tm_mday != -1 |
@@ -380,33 +403,36 @@ static int rs5c_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
380 | if (status < 0) | 403 | if (status < 0) |
381 | return status; | 404 | return status; |
382 | if (rs5c->regs[RS5C_REG_CTRL1] & RS5C_CTRL1_AALE) { | 405 | if (rs5c->regs[RS5C_REG_CTRL1] & RS5C_CTRL1_AALE) { |
383 | buf[0] = RS5C_ADDR(RS5C_REG_CTRL1); | 406 | addr = RS5C_ADDR(RS5C_REG_CTRL1); |
384 | buf[1] = rs5c->regs[RS5C_REG_CTRL1] & ~RS5C_CTRL1_AALE; | 407 | buf[0] = rs5c->regs[RS5C_REG_CTRL1] & ~RS5C_CTRL1_AALE; |
385 | if (i2c_master_send(client, buf, 2) != 2) { | 408 | if (i2c_smbus_write_byte_data(client, addr, buf[0]) < 0) { |
386 | pr_debug("%s: can't disable alarm\n", rs5c->rtc->name); | 409 | pr_debug("%s: can't disable alarm\n", rs5c->rtc->name); |
387 | return -EIO; | 410 | return -EIO; |
388 | } | 411 | } |
389 | rs5c->regs[RS5C_REG_CTRL1] = buf[1]; | 412 | rs5c->regs[RS5C_REG_CTRL1] = buf[0]; |
390 | } | 413 | } |
391 | 414 | ||
392 | /* set alarm */ | 415 | /* set alarm */ |
393 | buf[0] = RS5C_ADDR(RS5C_REG_ALARM_A_MIN); | 416 | buf[0] = BIN2BCD(t->time.tm_min); |
394 | buf[1] = BIN2BCD(t->time.tm_min); | 417 | buf[1] = rs5c_hr2reg(rs5c, t->time.tm_hour); |
395 | buf[2] = rs5c_hr2reg(rs5c, t->time.tm_hour); | 418 | buf[2] = 0x7f; /* any/all days */ |
396 | buf[3] = 0x7f; /* any/all days */ | 419 | |
397 | if ((i2c_master_send(client, buf, 4)) != 4) { | 420 | for (i = 0; i < sizeof(buf); i++) { |
398 | pr_debug("%s: can't set alarm time\n", rs5c->rtc->name); | 421 | addr = RS5C_ADDR(RS5C_REG_ALARM_A_MIN + i); |
399 | return -EIO; | 422 | if (i2c_smbus_write_byte_data(client, addr, buf[i]) < 0) { |
423 | pr_debug("%s: can't set alarm time\n", rs5c->rtc->name); | ||
424 | return -EIO; | ||
425 | } | ||
400 | } | 426 | } |
401 | 427 | ||
402 | /* ... and maybe enable its irq */ | 428 | /* ... and maybe enable its irq */ |
403 | if (t->enabled) { | 429 | if (t->enabled) { |
404 | buf[0] = RS5C_ADDR(RS5C_REG_CTRL1); | 430 | addr = RS5C_ADDR(RS5C_REG_CTRL1); |
405 | buf[1] = rs5c->regs[RS5C_REG_CTRL1] | RS5C_CTRL1_AALE; | 431 | buf[0] = rs5c->regs[RS5C_REG_CTRL1] | RS5C_CTRL1_AALE; |
406 | if ((i2c_master_send(client, buf, 2)) != 2) | 432 | if (i2c_smbus_write_byte_data(client, addr, buf[0]) < 0) |
407 | printk(KERN_WARNING "%s: can't enable alarm\n", | 433 | printk(KERN_WARNING "%s: can't enable alarm\n", |
408 | rs5c->rtc->name); | 434 | rs5c->rtc->name); |
409 | rs5c->regs[RS5C_REG_CTRL1] = buf[1]; | 435 | rs5c->regs[RS5C_REG_CTRL1] = buf[0]; |
410 | } | 436 | } |
411 | 437 | ||
412 | return 0; | 438 | return 0; |
@@ -503,18 +529,81 @@ static void rs5c_sysfs_unregister(struct device *dev) | |||
503 | 529 | ||
504 | static struct i2c_driver rs5c372_driver; | 530 | static struct i2c_driver rs5c372_driver; |
505 | 531 | ||
532 | static int rs5c_oscillator_setup(struct rs5c372 *rs5c372) | ||
533 | { | ||
534 | unsigned char buf[2]; | ||
535 | int addr, i, ret = 0; | ||
536 | |||
537 | if (rs5c372->type == rtc_r2025sd) { | ||
538 | if (!(rs5c372->regs[RS5C_REG_CTRL2] & R2025_CTRL2_XST)) | ||
539 | return ret; | ||
540 | rs5c372->regs[RS5C_REG_CTRL2] &= ~R2025_CTRL2_XST; | ||
541 | } else { | ||
542 | if (!(rs5c372->regs[RS5C_REG_CTRL2] & RS5C_CTRL2_XSTP)) | ||
543 | return ret; | ||
544 | rs5c372->regs[RS5C_REG_CTRL2] &= ~RS5C_CTRL2_XSTP; | ||
545 | } | ||
546 | |||
547 | addr = RS5C_ADDR(RS5C_REG_CTRL1); | ||
548 | buf[0] = rs5c372->regs[RS5C_REG_CTRL1]; | ||
549 | buf[1] = rs5c372->regs[RS5C_REG_CTRL2]; | ||
550 | |||
551 | /* use 24hr mode */ | ||
552 | switch (rs5c372->type) { | ||
553 | case rtc_rs5c372a: | ||
554 | case rtc_rs5c372b: | ||
555 | buf[1] |= RS5C372_CTRL2_24; | ||
556 | rs5c372->time24 = 1; | ||
557 | break; | ||
558 | case rtc_r2025sd: | ||
559 | case rtc_rv5c386: | ||
560 | case rtc_rv5c387a: | ||
561 | buf[0] |= RV5C387_CTRL1_24; | ||
562 | rs5c372->time24 = 1; | ||
563 | break; | ||
564 | default: | ||
565 | /* impossible */ | ||
566 | break; | ||
567 | } | ||
568 | |||
569 | for (i = 0; i < sizeof(buf); i++) { | ||
570 | addr = RS5C_ADDR(RS5C_REG_CTRL1 + i); | ||
571 | ret = i2c_smbus_write_byte_data(rs5c372->client, addr, buf[i]); | ||
572 | if (unlikely(ret < 0)) | ||
573 | return ret; | ||
574 | } | ||
575 | |||
576 | rs5c372->regs[RS5C_REG_CTRL1] = buf[0]; | ||
577 | rs5c372->regs[RS5C_REG_CTRL2] = buf[1]; | ||
578 | |||
579 | return 0; | ||
580 | } | ||
581 | |||
506 | static int rs5c372_probe(struct i2c_client *client, | 582 | static int rs5c372_probe(struct i2c_client *client, |
507 | const struct i2c_device_id *id) | 583 | const struct i2c_device_id *id) |
508 | { | 584 | { |
509 | int err = 0; | 585 | int err = 0; |
586 | int smbus_mode = 0; | ||
510 | struct rs5c372 *rs5c372; | 587 | struct rs5c372 *rs5c372; |
511 | struct rtc_time tm; | 588 | struct rtc_time tm; |
512 | 589 | ||
513 | dev_dbg(&client->dev, "%s\n", __func__); | 590 | dev_dbg(&client->dev, "%s\n", __func__); |
514 | 591 | ||
515 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | 592 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C | |
516 | err = -ENODEV; | 593 | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_I2C_BLOCK)) { |
517 | goto exit; | 594 | /* |
595 | * If we don't have any master mode adapter, try breaking | ||
596 | * it down in to the barest of capabilities. | ||
597 | */ | ||
598 | if (i2c_check_functionality(client->adapter, | ||
599 | I2C_FUNC_SMBUS_BYTE_DATA | | ||
600 | I2C_FUNC_SMBUS_I2C_BLOCK)) | ||
601 | smbus_mode = 1; | ||
602 | else { | ||
603 | /* Still no good, give up */ | ||
604 | err = -ENODEV; | ||
605 | goto exit; | ||
606 | } | ||
518 | } | 607 | } |
519 | 608 | ||
520 | if (!(rs5c372 = kzalloc(sizeof(struct rs5c372), GFP_KERNEL))) { | 609 | if (!(rs5c372 = kzalloc(sizeof(struct rs5c372), GFP_KERNEL))) { |
@@ -528,6 +617,7 @@ static int rs5c372_probe(struct i2c_client *client, | |||
528 | 617 | ||
529 | /* we read registers 0x0f then 0x00-0x0f; skip the first one */ | 618 | /* we read registers 0x0f then 0x00-0x0f; skip the first one */ |
530 | rs5c372->regs = &rs5c372->buf[1]; | 619 | rs5c372->regs = &rs5c372->buf[1]; |
620 | rs5c372->smbus = smbus_mode; | ||
531 | 621 | ||
532 | err = rs5c_get_regs(rs5c372); | 622 | err = rs5c_get_regs(rs5c372); |
533 | if (err < 0) | 623 | if (err < 0) |
@@ -543,6 +633,7 @@ static int rs5c372_probe(struct i2c_client *client, | |||
543 | if (rs5c372->regs[RS5C_REG_CTRL2] & RS5C372_CTRL2_24) | 633 | if (rs5c372->regs[RS5C_REG_CTRL2] & RS5C372_CTRL2_24) |
544 | rs5c372->time24 = 1; | 634 | rs5c372->time24 = 1; |
545 | break; | 635 | break; |
636 | case rtc_r2025sd: | ||
546 | case rtc_rv5c386: | 637 | case rtc_rv5c386: |
547 | case rtc_rv5c387a: | 638 | case rtc_rv5c387a: |
548 | if (rs5c372->regs[RS5C_REG_CTRL1] & RV5C387_CTRL1_24) | 639 | if (rs5c372->regs[RS5C_REG_CTRL1] & RV5C387_CTRL1_24) |
@@ -558,39 +649,14 @@ static int rs5c372_probe(struct i2c_client *client, | |||
558 | 649 | ||
559 | /* if the oscillator lost power and no other software (like | 650 | /* if the oscillator lost power and no other software (like |
560 | * the bootloader) set it up, do it here. | 651 | * the bootloader) set it up, do it here. |
652 | * | ||
653 | * The R2025S/D does this a little differently than the other | ||
654 | * parts, so we special case that.. | ||
561 | */ | 655 | */ |
562 | if (rs5c372->regs[RS5C_REG_CTRL2] & RS5C_CTRL2_XSTP) { | 656 | err = rs5c_oscillator_setup(rs5c372); |
563 | unsigned char buf[3]; | 657 | if (unlikely(err < 0)) { |
564 | 658 | dev_err(&client->dev, "setup error\n"); | |
565 | rs5c372->regs[RS5C_REG_CTRL2] &= ~RS5C_CTRL2_XSTP; | 659 | goto exit_kfree; |
566 | |||
567 | buf[0] = RS5C_ADDR(RS5C_REG_CTRL1); | ||
568 | buf[1] = rs5c372->regs[RS5C_REG_CTRL1]; | ||
569 | buf[2] = rs5c372->regs[RS5C_REG_CTRL2]; | ||
570 | |||
571 | /* use 24hr mode */ | ||
572 | switch (rs5c372->type) { | ||
573 | case rtc_rs5c372a: | ||
574 | case rtc_rs5c372b: | ||
575 | buf[2] |= RS5C372_CTRL2_24; | ||
576 | rs5c372->time24 = 1; | ||
577 | break; | ||
578 | case rtc_rv5c386: | ||
579 | case rtc_rv5c387a: | ||
580 | buf[1] |= RV5C387_CTRL1_24; | ||
581 | rs5c372->time24 = 1; | ||
582 | break; | ||
583 | default: | ||
584 | /* impossible */ | ||
585 | break; | ||
586 | } | ||
587 | |||
588 | if ((i2c_master_send(client, buf, 3)) != 3) { | ||
589 | dev_err(&client->dev, "setup error\n"); | ||
590 | goto exit_kfree; | ||
591 | } | ||
592 | rs5c372->regs[RS5C_REG_CTRL1] = buf[1]; | ||
593 | rs5c372->regs[RS5C_REG_CTRL2] = buf[2]; | ||
594 | } | 660 | } |
595 | 661 | ||
596 | if (rs5c372_get_datetime(client, &tm) < 0) | 662 | if (rs5c372_get_datetime(client, &tm) < 0) |
@@ -598,6 +664,7 @@ static int rs5c372_probe(struct i2c_client *client, | |||
598 | 664 | ||
599 | dev_info(&client->dev, "%s found, %s, driver version " DRV_VERSION "\n", | 665 | dev_info(&client->dev, "%s found, %s, driver version " DRV_VERSION "\n", |
600 | ({ char *s; switch (rs5c372->type) { | 666 | ({ char *s; switch (rs5c372->type) { |
667 | case rtc_r2025sd: s = "r2025sd"; break; | ||
601 | case rtc_rs5c372a: s = "rs5c372a"; break; | 668 | case rtc_rs5c372a: s = "rs5c372a"; break; |
602 | case rtc_rs5c372b: s = "rs5c372b"; break; | 669 | case rtc_rs5c372b: s = "rs5c372b"; break; |
603 | case rtc_rv5c386: s = "rv5c386"; break; | 670 | case rtc_rv5c386: s = "rv5c386"; break; |
@@ -667,7 +734,8 @@ module_exit(rs5c372_exit); | |||
667 | 734 | ||
668 | MODULE_AUTHOR( | 735 | MODULE_AUTHOR( |
669 | "Pavel Mironchik <pmironchik@optifacio.net>, " | 736 | "Pavel Mironchik <pmironchik@optifacio.net>, " |
670 | "Alessandro Zummo <a.zummo@towertech.it>"); | 737 | "Alessandro Zummo <a.zummo@towertech.it>, " |
738 | "Paul Mundt <lethal@linux-sh.org>"); | ||
671 | MODULE_DESCRIPTION("Ricoh RS5C372 RTC driver"); | 739 | MODULE_DESCRIPTION("Ricoh RS5C372 RTC driver"); |
672 | MODULE_LICENSE("GPL"); | 740 | MODULE_LICENSE("GPL"); |
673 | MODULE_VERSION(DRV_VERSION); | 741 | MODULE_VERSION(DRV_VERSION); |