diff options
author | David S. Miller <davem@davemloft.net> | 2008-08-29 00:54:34 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-08-29 17:16:50 -0400 |
commit | 29b503f11cd648b3628be3a546f97da95a6670ce (patch) | |
tree | 534ac37509091dd14b03d5cd84e89a757eafae27 /arch/sparc64/kernel/time.c | |
parent | cca4c231028405950a15f5a27d7326d18d909784 (diff) |
sparc64: Use generic BQ4802 RTC driver.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64/kernel/time.c')
-rw-r--r-- | arch/sparc64/kernel/time.c | 201 |
1 files changed, 11 insertions, 190 deletions
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index abdeead4e5b9..5e199a0e4378 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c | |||
@@ -52,9 +52,6 @@ | |||
52 | #include "entry.h" | 52 | #include "entry.h" |
53 | 53 | ||
54 | DEFINE_SPINLOCK(rtc_lock); | 54 | DEFINE_SPINLOCK(rtc_lock); |
55 | static void __iomem *bq4802_regs; | ||
56 | |||
57 | static int set_rtc_mmss(unsigned long); | ||
58 | 55 | ||
59 | #define TICK_PRIV_BIT (1UL << 63) | 56 | #define TICK_PRIV_BIT (1UL << 63) |
60 | #define TICKCMP_IRQ_BIT (1UL << 63) | 57 | #define TICKCMP_IRQ_BIT (1UL << 63) |
@@ -403,50 +400,7 @@ int update_persistent_clock(struct timespec now) | |||
403 | if (rtc) | 400 | if (rtc) |
404 | return rtc_set_mmss(rtc, now.tv_sec); | 401 | return rtc_set_mmss(rtc, now.tv_sec); |
405 | 402 | ||
406 | return set_rtc_mmss(now.tv_sec); | 403 | return -1; |
407 | } | ||
408 | |||
409 | /* Probe for the real time clock chip. */ | ||
410 | static void __init set_system_time(void) | ||
411 | { | ||
412 | unsigned int year, mon, day, hour, min, sec; | ||
413 | void __iomem *bregs = bq4802_regs; | ||
414 | unsigned char val = readb(bregs + 0x0e); | ||
415 | unsigned int century; | ||
416 | |||
417 | if (!bregs) { | ||
418 | prom_printf("Something wrong, clock regs not mapped yet.\n"); | ||
419 | prom_halt(); | ||
420 | } | ||
421 | |||
422 | /* BQ4802 RTC chip. */ | ||
423 | |||
424 | writeb(val | 0x08, bregs + 0x0e); | ||
425 | |||
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); | ||
433 | |||
434 | writeb(val, bregs + 0x0e); | ||
435 | |||
436 | BCD_TO_BIN(sec); | ||
437 | BCD_TO_BIN(min); | ||
438 | BCD_TO_BIN(hour); | ||
439 | BCD_TO_BIN(day); | ||
440 | BCD_TO_BIN(mon); | ||
441 | BCD_TO_BIN(year); | ||
442 | BCD_TO_BIN(century); | ||
443 | |||
444 | year += (century * 100); | ||
445 | |||
446 | xtime.tv_sec = mktime(year, mon, day, hour, min, sec); | ||
447 | xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); | ||
448 | set_normalized_timespec(&wall_to_monotonic, | ||
449 | -xtime.tv_sec, -xtime.tv_nsec); | ||
450 | } | 404 | } |
451 | 405 | ||
452 | /* davem suggests we keep this within the 4M locked kernel image */ | 406 | /* davem suggests we keep this within the 4M locked kernel image */ |
@@ -575,24 +529,20 @@ static struct of_platform_driver rtc_driver = { | |||
575 | }, | 529 | }, |
576 | }; | 530 | }; |
577 | 531 | ||
532 | static struct platform_device rtc_bq4802_device = { | ||
533 | .name = "rtc-bq4802", | ||
534 | .id = -1, | ||
535 | .num_resources = 1, | ||
536 | }; | ||
537 | |||
578 | static int __devinit bq4802_probe(struct of_device *op, const struct of_device_id *match) | 538 | static int __devinit bq4802_probe(struct of_device *op, const struct of_device_id *match) |
579 | { | 539 | { |
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) | ||
585 | return -ENOMEM; | ||
586 | |||
587 | printk(KERN_INFO "%s: Clock regs at %p\n", dp->full_name, bq4802_regs); | ||
588 | 540 | ||
589 | local_irq_save(flags); | 541 | printk(KERN_INFO "%s: BQ4802 regs at 0x%lx\n", |
590 | 542 | op->node->full_name, op->resource[0].start); | |
591 | set_system_time(); | ||
592 | |||
593 | local_irq_restore(flags); | ||
594 | 543 | ||
595 | return 0; | 544 | rtc_bq4802_device.resource = &op->resource[0]; |
545 | return platform_device_register(&rtc_bq4802_device); | ||
596 | } | 546 | } |
597 | 547 | ||
598 | static struct of_device_id bq4802_match[] = { | 548 | static struct of_device_id bq4802_match[] = { |
@@ -984,56 +934,6 @@ unsigned long long sched_clock(void) | |||
984 | >> SPARC64_NSEC_PER_CYC_SHIFT; | 934 | >> SPARC64_NSEC_PER_CYC_SHIFT; |
985 | } | 935 | } |
986 | 936 | ||
987 | static int set_rtc_mmss(unsigned long nowtime) | ||
988 | { | ||
989 | int real_seconds, real_minutes, chip_minutes; | ||
990 | void __iomem *bregs = bq4802_regs; | ||
991 | unsigned long flags; | ||
992 | unsigned char val; | ||
993 | int retval = 0; | ||
994 | |||
995 | /* | ||
996 | * Not having a register set can lead to trouble. | ||
997 | * Also starfire doesn't have a tod clock. | ||
998 | */ | ||
999 | if (!bregs) | ||
1000 | return -1; | ||
1001 | |||
1002 | spin_lock_irqsave(&rtc_lock, flags); | ||
1003 | |||
1004 | val = readb(bregs + 0x0e); | ||
1005 | |||
1006 | /* BQ4802 RTC chip. */ | ||
1007 | |||
1008 | writeb(val | 0x08, bregs + 0x0e); | ||
1009 | |||
1010 | chip_minutes = readb(bregs + 0x02); | ||
1011 | BCD_TO_BIN(chip_minutes); | ||
1012 | real_seconds = nowtime % 60; | ||
1013 | real_minutes = nowtime / 60; | ||
1014 | if (((abs(real_minutes - chip_minutes) + 15)/30) & 1) | ||
1015 | real_minutes += 30; | ||
1016 | real_minutes %= 60; | ||
1017 | |||
1018 | if (abs(real_minutes - chip_minutes) < 30) { | ||
1019 | BIN_TO_BCD(real_seconds); | ||
1020 | BIN_TO_BCD(real_minutes); | ||
1021 | writeb(real_seconds, bregs + 0x00); | ||
1022 | writeb(real_minutes, bregs + 0x02); | ||
1023 | } else { | ||
1024 | printk(KERN_WARNING | ||
1025 | "set_rtc_mmss: can't update from %d to %d\n", | ||
1026 | chip_minutes, real_minutes); | ||
1027 | retval = -1; | ||
1028 | } | ||
1029 | |||
1030 | writeb(val, bregs + 0x0e); | ||
1031 | |||
1032 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
1033 | |||
1034 | return retval; | ||
1035 | } | ||
1036 | |||
1037 | #define RTC_IS_OPEN 0x01 /* means /dev/rtc is in use */ | 937 | #define RTC_IS_OPEN 0x01 /* means /dev/rtc is in use */ |
1038 | static unsigned char mini_rtc_status; /* bitmapped status byte. */ | 938 | static unsigned char mini_rtc_status; /* bitmapped status byte. */ |
1039 | 939 | ||
@@ -1155,78 +1055,6 @@ static int hypervisor_set_rtc_time(struct rtc_time *time) | |||
1155 | return hypervisor_set_time(seconds); | 1055 | return hypervisor_set_time(seconds); |
1156 | } | 1056 | } |
1157 | 1057 | ||
1158 | static void bq4802_get_rtc_time(struct rtc_time *time) | ||
1159 | { | ||
1160 | unsigned char val = readb(bq4802_regs + 0x0e); | ||
1161 | unsigned int century; | ||
1162 | |||
1163 | writeb(val | 0x08, bq4802_regs + 0x0e); | ||
1164 | |||
1165 | time->tm_sec = readb(bq4802_regs + 0x00); | ||
1166 | time->tm_min = readb(bq4802_regs + 0x02); | ||
1167 | time->tm_hour = readb(bq4802_regs + 0x04); | ||
1168 | time->tm_mday = readb(bq4802_regs + 0x06); | ||
1169 | time->tm_mon = readb(bq4802_regs + 0x09); | ||
1170 | time->tm_year = readb(bq4802_regs + 0x0a); | ||
1171 | time->tm_wday = readb(bq4802_regs + 0x08); | ||
1172 | century = readb(bq4802_regs + 0x0f); | ||
1173 | |||
1174 | writeb(val, bq4802_regs + 0x0e); | ||
1175 | |||
1176 | BCD_TO_BIN(time->tm_sec); | ||
1177 | BCD_TO_BIN(time->tm_min); | ||
1178 | BCD_TO_BIN(time->tm_hour); | ||
1179 | BCD_TO_BIN(time->tm_mday); | ||
1180 | BCD_TO_BIN(time->tm_mon); | ||
1181 | BCD_TO_BIN(time->tm_year); | ||
1182 | BCD_TO_BIN(time->tm_wday); | ||
1183 | BCD_TO_BIN(century); | ||
1184 | |||
1185 | time->tm_year += (century * 100); | ||
1186 | time->tm_year -= 1900; | ||
1187 | |||
1188 | time->tm_mon--; | ||
1189 | } | ||
1190 | |||
1191 | static int bq4802_set_rtc_time(struct rtc_time *time) | ||
1192 | { | ||
1193 | unsigned char val = readb(bq4802_regs + 0x0e); | ||
1194 | unsigned char sec, min, hrs, day, mon, yrs, century; | ||
1195 | unsigned int year; | ||
1196 | |||
1197 | year = time->tm_year + 1900; | ||
1198 | century = year / 100; | ||
1199 | yrs = year % 100; | ||
1200 | |||
1201 | mon = time->tm_mon + 1; /* tm_mon starts at zero */ | ||
1202 | day = time->tm_mday; | ||
1203 | hrs = time->tm_hour; | ||
1204 | min = time->tm_min; | ||
1205 | sec = time->tm_sec; | ||
1206 | |||
1207 | BIN_TO_BCD(sec); | ||
1208 | BIN_TO_BCD(min); | ||
1209 | BIN_TO_BCD(hrs); | ||
1210 | BIN_TO_BCD(day); | ||
1211 | BIN_TO_BCD(mon); | ||
1212 | BIN_TO_BCD(yrs); | ||
1213 | BIN_TO_BCD(century); | ||
1214 | |||
1215 | writeb(val | 0x08, bq4802_regs + 0x0e); | ||
1216 | |||
1217 | writeb(sec, bq4802_regs + 0x00); | ||
1218 | writeb(min, bq4802_regs + 0x02); | ||
1219 | writeb(hrs, bq4802_regs + 0x04); | ||
1220 | writeb(day, bq4802_regs + 0x06); | ||
1221 | writeb(mon, bq4802_regs + 0x09); | ||
1222 | writeb(yrs, bq4802_regs + 0x0a); | ||
1223 | writeb(century, bq4802_regs + 0x0f); | ||
1224 | |||
1225 | writeb(val, bq4802_regs + 0x0e); | ||
1226 | |||
1227 | return 0; | ||
1228 | } | ||
1229 | |||
1230 | struct mini_rtc_ops { | 1058 | struct mini_rtc_ops { |
1231 | void (*get_rtc_time)(struct rtc_time *); | 1059 | void (*get_rtc_time)(struct rtc_time *); |
1232 | int (*set_rtc_time)(struct rtc_time *); | 1060 | int (*set_rtc_time)(struct rtc_time *); |
@@ -1242,11 +1070,6 @@ static struct mini_rtc_ops hypervisor_rtc_ops = { | |||
1242 | .set_rtc_time = hypervisor_set_rtc_time, | 1070 | .set_rtc_time = hypervisor_set_rtc_time, |
1243 | }; | 1071 | }; |
1244 | 1072 | ||
1245 | static struct mini_rtc_ops bq4802_rtc_ops = { | ||
1246 | .get_rtc_time = bq4802_get_rtc_time, | ||
1247 | .set_rtc_time = bq4802_set_rtc_time, | ||
1248 | }; | ||
1249 | |||
1250 | static struct mini_rtc_ops *mini_rtc_ops; | 1073 | static struct mini_rtc_ops *mini_rtc_ops; |
1251 | 1074 | ||
1252 | static inline void mini_get_rtc_time(struct rtc_time *time) | 1075 | static inline void mini_get_rtc_time(struct rtc_time *time) |
@@ -1373,8 +1196,6 @@ static int __init rtc_mini_init(void) | |||
1373 | mini_rtc_ops = &hypervisor_rtc_ops; | 1196 | mini_rtc_ops = &hypervisor_rtc_ops; |
1374 | else if (this_is_starfire) | 1197 | else if (this_is_starfire) |
1375 | mini_rtc_ops = &starfire_rtc_ops; | 1198 | mini_rtc_ops = &starfire_rtc_ops; |
1376 | else if (bq4802_regs) | ||
1377 | mini_rtc_ops = &bq4802_rtc_ops; | ||
1378 | else | 1199 | else |
1379 | return -ENODEV; | 1200 | return -ENODEV; |
1380 | 1201 | ||