aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/time.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-08-29 01:16:15 -0400
committerDavid S. Miller <davem@davemloft.net>2008-08-29 17:16:48 -0400
commitda86783dda5ad8c64b945157108d1ace7aa79bbf (patch)
tree171219d3d198d823c5eb2cf0fd9ce1f4b5ae090f /arch/sparc64/kernel/time.c
parente8b75c4fd6e3bec57d268b76a0a9a8f58f1612e3 (diff)
sparc64: Use generic CMOS driver.
Based largely upon a patch by Krzysztof Helt <krzysztof.h1@poczta.fm> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64/kernel/time.c')
-rw-r--r--arch/sparc64/kernel/time.c372
1 files changed, 120 insertions, 252 deletions
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
index 9c2c3d84443d..abdeead4e5b9 100644
--- a/arch/sparc64/kernel/time.c
+++ b/arch/sparc64/kernel/time.c
@@ -52,10 +52,7 @@
52#include "entry.h" 52#include "entry.h"
53 53
54DEFINE_SPINLOCK(rtc_lock); 54DEFINE_SPINLOCK(rtc_lock);
55#ifdef CONFIG_PCI
56unsigned long ds1287_regs = 0UL;
57static void __iomem *bq4802_regs; 55static void __iomem *bq4802_regs;
58#endif
59 56
60static int set_rtc_mmss(unsigned long); 57static int set_rtc_mmss(unsigned long);
61 58
@@ -413,69 +410,38 @@ int update_persistent_clock(struct timespec now)
413static void __init set_system_time(void) 410static void __init set_system_time(void)
414{ 411{
415 unsigned int year, mon, day, hour, min, sec; 412 unsigned int year, mon, day, hour, min, sec;
416#ifdef CONFIG_PCI
417 unsigned long dregs = ds1287_regs;
418 void __iomem *bregs = bq4802_regs; 413 void __iomem *bregs = bq4802_regs;
419#else 414 unsigned char val = readb(bregs + 0x0e);
420 unsigned long dregs = 0UL; 415 unsigned int century;
421 void __iomem *bregs = 0UL;
422#endif
423 416
424 if (!dregs && !bregs) { 417 if (!bregs) {
425 prom_printf("Something wrong, clock regs not mapped yet.\n"); 418 prom_printf("Something wrong, clock regs not mapped yet.\n");
426 prom_halt(); 419 prom_halt();
427 } 420 }
428 421
429 if (bregs) { 422 /* BQ4802 RTC chip. */
430 unsigned char val = readb(bregs + 0x0e);
431 unsigned int century;
432 423
433 /* BQ4802 RTC chip. */ 424 writeb(val | 0x08, bregs + 0x0e);
434 425
435 writeb(val | 0x08, bregs + 0x0e); 426 sec = readb(bregs + 0x00);
427 min = readb(bregs + 0x02);
428 hour = readb(bregs + 0x04);
429 day = readb(bregs + 0x06);
430 mon = readb(bregs + 0x09);
431 year = readb(bregs + 0x0a);
432 century = readb(bregs + 0x0f);
436 433
437 sec = readb(bregs + 0x00); 434 writeb(val, bregs + 0x0e);
438 min = readb(bregs + 0x02);
439 hour = readb(bregs + 0x04);
440 day = readb(bregs + 0x06);
441 mon = readb(bregs + 0x09);
442 year = readb(bregs + 0x0a);
443 century = readb(bregs + 0x0f);
444 435
445 writeb(val, bregs + 0x0e); 436 BCD_TO_BIN(sec);
446 437 BCD_TO_BIN(min);
447 BCD_TO_BIN(sec); 438 BCD_TO_BIN(hour);
448 BCD_TO_BIN(min); 439 BCD_TO_BIN(day);
449 BCD_TO_BIN(hour); 440 BCD_TO_BIN(mon);
450 BCD_TO_BIN(day); 441 BCD_TO_BIN(year);
451 BCD_TO_BIN(mon); 442 BCD_TO_BIN(century);
452 BCD_TO_BIN(year);
453 BCD_TO_BIN(century);
454 443
455 year += (century * 100); 444 year += (century * 100);
456 } else {
457 /* Dallas 12887 RTC chip. */
458
459 do {
460 sec = CMOS_READ(RTC_SECONDS);
461 min = CMOS_READ(RTC_MINUTES);
462 hour = CMOS_READ(RTC_HOURS);
463 day = CMOS_READ(RTC_DAY_OF_MONTH);
464 mon = CMOS_READ(RTC_MONTH);
465 year = CMOS_READ(RTC_YEAR);
466 } while (sec != CMOS_READ(RTC_SECONDS));
467
468 if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
469 BCD_TO_BIN(sec);
470 BCD_TO_BIN(min);
471 BCD_TO_BIN(hour);
472 BCD_TO_BIN(day);
473 BCD_TO_BIN(mon);
474 BCD_TO_BIN(year);
475 }
476 if ((year += 1900) < 1970)
477 year += 100;
478 }
479 445
480 xtime.tv_sec = mktime(year, mon, day, hour, min, sec); 446 xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
481 xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); 447 xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
@@ -546,48 +512,79 @@ retry:
546 return -EOPNOTSUPP; 512 return -EOPNOTSUPP;
547} 513}
548 514
549static int __init rtc_model_matches(const char *model) 515unsigned long cmos_regs;
550{ 516EXPORT_SYMBOL(cmos_regs);
551 if (strcmp(model, "m5819") &&
552 strcmp(model, "m5819p") &&
553 strcmp(model, "m5823") &&
554 strcmp(model, "ds1287") &&
555 strcmp(model, "bq4802"))
556 return 0;
557 517
558 return 1; 518struct resource rtc_cmos_resource;
559} 519
520static struct platform_device rtc_cmos_device = {
521 .name = "rtc_cmos",
522 .id = -1,
523 .resource = &rtc_cmos_resource,
524 .num_resources = 1,
525};
560 526
561static int __devinit rtc_probe(struct of_device *op, const struct of_device_id *match) 527static int __devinit rtc_probe(struct of_device *op, const struct of_device_id *match)
562{ 528{
563 struct device_node *dp = op->node; 529 struct resource *r;
564 const char *model = of_get_property(dp, "model", NULL);
565 const char *compat = of_get_property(dp, "compatible", NULL);
566 unsigned long size, flags;
567 void __iomem *regs;
568 530
569 if (!model) 531 printk(KERN_INFO "%s: RTC regs at 0x%lx\n",
570 model = compat; 532 op->node->full_name, op->resource[0].start);
571 533
572 if (!model || !rtc_model_matches(model)) 534 /* The CMOS RTC driver only accepts IORESOURCE_IO, so cons
573 return -ENODEV; 535 * up a fake resource so that the probe works for all cases.
536 * When the RTC is behind an ISA bus it will have IORESOURCE_IO
537 * already, whereas when it's behind EBUS is will be IORESOURCE_MEM.
538 */
539
540 r = &rtc_cmos_resource;
541 r->flags = IORESOURCE_IO;
542 r->name = op->resource[0].name;
543 r->start = op->resource[0].start;
544 r->end = op->resource[0].end;
545
546 cmos_regs = op->resource[0].start;
547 return platform_device_register(&rtc_cmos_device);
548}
549
550static struct of_device_id rtc_match[] = {
551 {
552 .name = "rtc",
553 .compatible = "m5819",
554 },
555 {
556 .name = "rtc",
557 .compatible = "isa-m5819p",
558 },
559 {
560 .name = "rtc",
561 .compatible = "isa-m5823p",
562 },
563 {
564 .name = "rtc",
565 .compatible = "ds1287",
566 },
567 {},
568};
569
570static struct of_platform_driver rtc_driver = {
571 .match_table = rtc_match,
572 .probe = rtc_probe,
573 .driver = {
574 .name = "rtc",
575 },
576};
574 577
575 size = (op->resource[0].end - op->resource[0].start) + 1; 578static int __devinit bq4802_probe(struct of_device *op, const struct of_device_id *match)
576 regs = of_ioremap(&op->resource[0], 0, size, "clock"); 579{
577 if (!regs) 580 struct device_node *dp = op->node;
581 unsigned long flags;
582
583 bq4802_regs = of_ioremap(&op->resource[0], 0, resource_size(&op->resource[0]), "bq4802");
584 if (!bq4802_regs)
578 return -ENOMEM; 585 return -ENOMEM;
579 586
580#ifdef CONFIG_PCI 587 printk(KERN_INFO "%s: Clock regs at %p\n", dp->full_name, bq4802_regs);
581 if (!strcmp(model, "ds1287") ||
582 !strcmp(model, "m5819") ||
583 !strcmp(model, "m5819p") ||
584 !strcmp(model, "m5823")) {
585 ds1287_regs = (unsigned long) regs;
586 } else if (!strcmp(model, "bq4802")) {
587 bq4802_regs = regs;
588 }
589#endif
590 printk(KERN_INFO "%s: Clock regs at %p\n", dp->full_name, regs);
591 588
592 local_irq_save(flags); 589 local_irq_save(flags);
593 590
@@ -598,18 +595,18 @@ static int __devinit rtc_probe(struct of_device *op, const struct of_device_id *
598 return 0; 595 return 0;
599} 596}
600 597
601static struct of_device_id rtc_match[] = { 598static struct of_device_id bq4802_match[] = {
602 { 599 {
603 .name = "rtc", 600 .name = "rtc",
601 .compatible = "bq4802",
604 }, 602 },
605 {},
606}; 603};
607 604
608static struct of_platform_driver rtc_driver = { 605static struct of_platform_driver bq4802_driver = {
609 .match_table = rtc_match, 606 .match_table = bq4802_match,
610 .probe = rtc_probe, 607 .probe = bq4802_probe,
611 .driver = { 608 .driver = {
612 .name = "rtc", 609 .name = "bq4802",
613 }, 610 },
614}; 611};
615 612
@@ -716,6 +713,7 @@ static int __init clock_init(void)
716 713
717 (void) of_register_driver(&rtc_driver, &of_platform_bus_type); 714 (void) of_register_driver(&rtc_driver, &of_platform_bus_type);
718 (void) of_register_driver(&mostek_driver, &of_platform_bus_type); 715 (void) of_register_driver(&mostek_driver, &of_platform_bus_type);
716 (void) of_register_driver(&bq4802_driver, &of_platform_bus_type);
719 717
720 return 0; 718 return 0;
721} 719}
@@ -989,96 +987,51 @@ unsigned long long sched_clock(void)
989static int set_rtc_mmss(unsigned long nowtime) 987static int set_rtc_mmss(unsigned long nowtime)
990{ 988{
991 int real_seconds, real_minutes, chip_minutes; 989 int real_seconds, real_minutes, chip_minutes;
992#ifdef CONFIG_PCI
993 unsigned long dregs = ds1287_regs;
994 void __iomem *bregs = bq4802_regs; 990 void __iomem *bregs = bq4802_regs;
995#else
996 unsigned long dregs = 0UL;
997 void __iomem *bregs = 0UL;
998#endif
999 unsigned long flags; 991 unsigned long flags;
992 unsigned char val;
993 int retval = 0;
1000 994
1001 /* 995 /*
1002 * Not having a register set can lead to trouble. 996 * Not having a register set can lead to trouble.
1003 * Also starfire doesn't have a tod clock. 997 * Also starfire doesn't have a tod clock.
1004 */ 998 */
1005 if (!dregs && !bregs) 999 if (!bregs)
1006 return -1; 1000 return -1;
1007 1001
1008 if (bregs) { 1002 spin_lock_irqsave(&rtc_lock, flags);
1009 int retval = 0;
1010 unsigned char val = readb(bregs + 0x0e);
1011 1003
1012 /* BQ4802 RTC chip. */ 1004 val = readb(bregs + 0x0e);
1013 1005
1014 writeb(val | 0x08, bregs + 0x0e); 1006 /* BQ4802 RTC chip. */
1015 1007
1016 chip_minutes = readb(bregs + 0x02); 1008 writeb(val | 0x08, bregs + 0x0e);
1017 BCD_TO_BIN(chip_minutes);
1018 real_seconds = nowtime % 60;
1019 real_minutes = nowtime / 60;
1020 if (((abs(real_minutes - chip_minutes) + 15)/30) & 1)
1021 real_minutes += 30;
1022 real_minutes %= 60;
1023 1009
1024 if (abs(real_minutes - chip_minutes) < 30) { 1010 chip_minutes = readb(bregs + 0x02);
1025 BIN_TO_BCD(real_seconds); 1011 BCD_TO_BIN(chip_minutes);
1026 BIN_TO_BCD(real_minutes); 1012 real_seconds = nowtime % 60;
1027 writeb(real_seconds, bregs + 0x00); 1013 real_minutes = nowtime / 60;
1028 writeb(real_minutes, bregs + 0x02); 1014 if (((abs(real_minutes - chip_minutes) + 15)/30) & 1)
1029 } else { 1015 real_minutes += 30;
1030 printk(KERN_WARNING 1016 real_minutes %= 60;
1031 "set_rtc_mmss: can't update from %d to %d\n",
1032 chip_minutes, real_minutes);
1033 retval = -1;
1034 }
1035 1017
1036 writeb(val, bregs + 0x0e); 1018 if (abs(real_minutes - chip_minutes) < 30) {
1037 1019 BIN_TO_BCD(real_seconds);
1038 return retval; 1020 BIN_TO_BCD(real_minutes);
1021 writeb(real_seconds, bregs + 0x00);
1022 writeb(real_minutes, bregs + 0x02);
1039 } else { 1023 } else {
1040 int retval = 0; 1024 printk(KERN_WARNING
1041 unsigned char save_control, save_freq_select; 1025 "set_rtc_mmss: can't update from %d to %d\n",
1042 1026 chip_minutes, real_minutes);
1043 /* Stolen from arch/i386/kernel/time.c, see there for 1027 retval = -1;
1044 * credits and descriptive comments. 1028 }
1045 */
1046 spin_lock_irqsave(&rtc_lock, flags);
1047 save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */
1048 CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
1049
1050 save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */
1051 CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
1052
1053 chip_minutes = CMOS_READ(RTC_MINUTES);
1054 if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
1055 BCD_TO_BIN(chip_minutes);
1056 real_seconds = nowtime % 60;
1057 real_minutes = nowtime / 60;
1058 if (((abs(real_minutes - chip_minutes) + 15)/30) & 1)
1059 real_minutes += 30;
1060 real_minutes %= 60;
1061
1062 if (abs(real_minutes - chip_minutes) < 30) {
1063 if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
1064 BIN_TO_BCD(real_seconds);
1065 BIN_TO_BCD(real_minutes);
1066 }
1067 CMOS_WRITE(real_seconds,RTC_SECONDS);
1068 CMOS_WRITE(real_minutes,RTC_MINUTES);
1069 } else {
1070 printk(KERN_WARNING
1071 "set_rtc_mmss: can't update from %d to %d\n",
1072 chip_minutes, real_minutes);
1073 retval = -1;
1074 }
1075 1029
1076 CMOS_WRITE(save_control, RTC_CONTROL); 1030 writeb(val, bregs + 0x0e);
1077 CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
1078 spin_unlock_irqrestore(&rtc_lock, flags);
1079 1031
1080 return retval; 1032 spin_unlock_irqrestore(&rtc_lock, flags);
1081 } 1033
1034 return retval;
1082} 1035}
1083 1036
1084#define RTC_IS_OPEN 0x01 /* means /dev/rtc is in use */ 1037#define RTC_IS_OPEN 0x01 /* means /dev/rtc is in use */
@@ -1202,7 +1155,6 @@ static int hypervisor_set_rtc_time(struct rtc_time *time)
1202 return hypervisor_set_time(seconds); 1155 return hypervisor_set_time(seconds);
1203} 1156}
1204 1157
1205#ifdef CONFIG_PCI
1206static void bq4802_get_rtc_time(struct rtc_time *time) 1158static void bq4802_get_rtc_time(struct rtc_time *time)
1207{ 1159{
1208 unsigned char val = readb(bq4802_regs + 0x0e); 1160 unsigned char val = readb(bq4802_regs + 0x0e);
@@ -1275,79 +1227,6 @@ static int bq4802_set_rtc_time(struct rtc_time *time)
1275 return 0; 1227 return 0;
1276} 1228}
1277 1229
1278static void cmos_get_rtc_time(struct rtc_time *rtc_tm)
1279{
1280 unsigned char ctrl;
1281
1282 rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS);
1283 rtc_tm->tm_min = CMOS_READ(RTC_MINUTES);
1284 rtc_tm->tm_hour = CMOS_READ(RTC_HOURS);
1285 rtc_tm->tm_mday = CMOS_READ(RTC_DAY_OF_MONTH);
1286 rtc_tm->tm_mon = CMOS_READ(RTC_MONTH);
1287 rtc_tm->tm_year = CMOS_READ(RTC_YEAR);
1288 rtc_tm->tm_wday = CMOS_READ(RTC_DAY_OF_WEEK);
1289
1290 ctrl = CMOS_READ(RTC_CONTROL);
1291 if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
1292 BCD_TO_BIN(rtc_tm->tm_sec);
1293 BCD_TO_BIN(rtc_tm->tm_min);
1294 BCD_TO_BIN(rtc_tm->tm_hour);
1295 BCD_TO_BIN(rtc_tm->tm_mday);
1296 BCD_TO_BIN(rtc_tm->tm_mon);
1297 BCD_TO_BIN(rtc_tm->tm_year);
1298 BCD_TO_BIN(rtc_tm->tm_wday);
1299 }
1300
1301 if (rtc_tm->tm_year <= 69)
1302 rtc_tm->tm_year += 100;
1303
1304 rtc_tm->tm_mon--;
1305}
1306
1307static int cmos_set_rtc_time(struct rtc_time *rtc_tm)
1308{
1309 unsigned char mon, day, hrs, min, sec;
1310 unsigned char save_control, save_freq_select;
1311 unsigned int yrs;
1312
1313 yrs = rtc_tm->tm_year;
1314 mon = rtc_tm->tm_mon + 1;
1315 day = rtc_tm->tm_mday;
1316 hrs = rtc_tm->tm_hour;
1317 min = rtc_tm->tm_min;
1318 sec = rtc_tm->tm_sec;
1319
1320 if (yrs >= 100)
1321 yrs -= 100;
1322
1323 if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
1324 BIN_TO_BCD(sec);
1325 BIN_TO_BCD(min);
1326 BIN_TO_BCD(hrs);
1327 BIN_TO_BCD(day);
1328 BIN_TO_BCD(mon);
1329 BIN_TO_BCD(yrs);
1330 }
1331
1332 save_control = CMOS_READ(RTC_CONTROL);
1333 CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
1334 save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
1335 CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
1336
1337 CMOS_WRITE(yrs, RTC_YEAR);
1338 CMOS_WRITE(mon, RTC_MONTH);
1339 CMOS_WRITE(day, RTC_DAY_OF_MONTH);
1340 CMOS_WRITE(hrs, RTC_HOURS);
1341 CMOS_WRITE(min, RTC_MINUTES);
1342 CMOS_WRITE(sec, RTC_SECONDS);
1343
1344 CMOS_WRITE(save_control, RTC_CONTROL);
1345 CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
1346
1347 return 0;
1348}
1349#endif /* CONFIG_PCI */
1350
1351struct mini_rtc_ops { 1230struct mini_rtc_ops {
1352 void (*get_rtc_time)(struct rtc_time *); 1231 void (*get_rtc_time)(struct rtc_time *);
1353 int (*set_rtc_time)(struct rtc_time *); 1232 int (*set_rtc_time)(struct rtc_time *);
@@ -1363,18 +1242,11 @@ static struct mini_rtc_ops hypervisor_rtc_ops = {
1363 .set_rtc_time = hypervisor_set_rtc_time, 1242 .set_rtc_time = hypervisor_set_rtc_time,
1364}; 1243};
1365 1244
1366#ifdef CONFIG_PCI
1367static struct mini_rtc_ops bq4802_rtc_ops = { 1245static struct mini_rtc_ops bq4802_rtc_ops = {
1368 .get_rtc_time = bq4802_get_rtc_time, 1246 .get_rtc_time = bq4802_get_rtc_time,
1369 .set_rtc_time = bq4802_set_rtc_time, 1247 .set_rtc_time = bq4802_set_rtc_time,
1370}; 1248};
1371 1249
1372static struct mini_rtc_ops cmos_rtc_ops = {
1373 .get_rtc_time = cmos_get_rtc_time,
1374 .set_rtc_time = cmos_set_rtc_time,
1375};
1376#endif /* CONFIG_PCI */
1377
1378static struct mini_rtc_ops *mini_rtc_ops; 1250static struct mini_rtc_ops *mini_rtc_ops;
1379 1251
1380static inline void mini_get_rtc_time(struct rtc_time *time) 1252static inline void mini_get_rtc_time(struct rtc_time *time)
@@ -1501,12 +1373,8 @@ static int __init rtc_mini_init(void)
1501 mini_rtc_ops = &hypervisor_rtc_ops; 1373 mini_rtc_ops = &hypervisor_rtc_ops;
1502 else if (this_is_starfire) 1374 else if (this_is_starfire)
1503 mini_rtc_ops = &starfire_rtc_ops; 1375 mini_rtc_ops = &starfire_rtc_ops;
1504#ifdef CONFIG_PCI
1505 else if (bq4802_regs) 1376 else if (bq4802_regs)
1506 mini_rtc_ops = &bq4802_rtc_ops; 1377 mini_rtc_ops = &bq4802_rtc_ops;
1507 else if (ds1287_regs)
1508 mini_rtc_ops = &cmos_rtc_ops;
1509#endif /* CONFIG_PCI */
1510 else 1378 else
1511 return -ENODEV; 1379 return -ENODEV;
1512 1380