aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2007-05-12 00:18:50 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-05-12 00:39:27 -0400
commitd037e0532e7dbb5a7936cbc6747206d2352f2974 (patch)
treedadc69601b421bc240a4478be331ba8a9c65c254
parent95d71e663e79b3e8c64bd7b7321389394b16276e (diff)
[SPARC64]: Add support for bq4802 TOD chip, as found on ultra45.
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--arch/sparc64/kernel/time.c230
1 files changed, 210 insertions, 20 deletions
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
index 259063f41f95..6b9a06e42542 100644
--- a/arch/sparc64/kernel/time.c
+++ b/arch/sparc64/kernel/time.c
@@ -55,6 +55,7 @@ DEFINE_SPINLOCK(rtc_lock);
55void __iomem *mstk48t02_regs = NULL; 55void __iomem *mstk48t02_regs = NULL;
56#ifdef CONFIG_PCI 56#ifdef CONFIG_PCI
57unsigned long ds1287_regs = 0UL; 57unsigned long ds1287_regs = 0UL;
58static void __iomem *bq4802_regs;
58#endif 59#endif
59 60
60static void __iomem *mstk48t08_regs; 61static void __iomem *mstk48t08_regs;
@@ -565,12 +566,14 @@ static void __init set_system_time(void)
565 void __iomem *mregs = mstk48t02_regs; 566 void __iomem *mregs = mstk48t02_regs;
566#ifdef CONFIG_PCI 567#ifdef CONFIG_PCI
567 unsigned long dregs = ds1287_regs; 568 unsigned long dregs = ds1287_regs;
569 void __iomem *bregs = bq4802_regs;
568#else 570#else
569 unsigned long dregs = 0UL; 571 unsigned long dregs = 0UL;
572 void __iomem *bregs = 0UL;
570#endif 573#endif
571 u8 tmp; 574 u8 tmp;
572 575
573 if (!mregs && !dregs) { 576 if (!mregs && !dregs && !bregs) {
574 prom_printf("Something wrong, clock regs not mapped yet.\n"); 577 prom_printf("Something wrong, clock regs not mapped yet.\n");
575 prom_halt(); 578 prom_halt();
576 } 579 }
@@ -589,6 +592,33 @@ static void __init set_system_time(void)
589 day = MSTK_REG_DOM(mregs); 592 day = MSTK_REG_DOM(mregs);
590 mon = MSTK_REG_MONTH(mregs); 593 mon = MSTK_REG_MONTH(mregs);
591 year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) ); 594 year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) );
595 } else if (bregs) {
596 unsigned char val = readb(bregs + 0x0e);
597 unsigned int century;
598
599 /* BQ4802 RTC chip. */
600
601 writeb(val | 0x08, bregs + 0x0e);
602
603 sec = readb(bregs + 0x00);
604 min = readb(bregs + 0x02);
605 hour = readb(bregs + 0x04);
606 day = readb(bregs + 0x06);
607 mon = readb(bregs + 0x09);
608 year = readb(bregs + 0x0a);
609 century = readb(bregs + 0x0f);
610
611 writeb(val, bregs + 0x0e);
612
613 BCD_TO_BIN(sec);
614 BCD_TO_BIN(min);
615 BCD_TO_BIN(hour);
616 BCD_TO_BIN(day);
617 BCD_TO_BIN(mon);
618 BCD_TO_BIN(year);
619 BCD_TO_BIN(century);
620
621 year += (century * 100);
592 } else { 622 } else {
593 /* Dallas 12887 RTC chip. */ 623 /* Dallas 12887 RTC chip. */
594 624
@@ -712,7 +742,8 @@ static int __init clock_model_matches(const char *model)
712 strcmp(model, "m5819") && 742 strcmp(model, "m5819") &&
713 strcmp(model, "m5819p") && 743 strcmp(model, "m5819p") &&
714 strcmp(model, "m5823") && 744 strcmp(model, "m5823") &&
715 strcmp(model, "ds1287")) 745 strcmp(model, "ds1287") &&
746 strcmp(model, "bq4802"))
716 return 0; 747 return 0;
717 748
718 return 1; 749 return 1;
@@ -722,9 +753,13 @@ static int __devinit clock_probe(struct of_device *op, const struct of_device_id
722{ 753{
723 struct device_node *dp = op->node; 754 struct device_node *dp = op->node;
724 const char *model = of_get_property(dp, "model", NULL); 755 const char *model = of_get_property(dp, "model", NULL);
756 const char *compat = of_get_property(dp, "compatible", NULL);
725 unsigned long size, flags; 757 unsigned long size, flags;
726 void __iomem *regs; 758 void __iomem *regs;
727 759
760 if (!model)
761 model = compat;
762
728 if (!model || !clock_model_matches(model)) 763 if (!model || !clock_model_matches(model))
729 return -ENODEV; 764 return -ENODEV;
730 765
@@ -746,6 +781,8 @@ static int __devinit clock_probe(struct of_device *op, const struct of_device_id
746 !strcmp(model, "m5819p") || 781 !strcmp(model, "m5819p") ||
747 !strcmp(model, "m5823")) { 782 !strcmp(model, "m5823")) {
748 ds1287_regs = (unsigned long) regs; 783 ds1287_regs = (unsigned long) regs;
784 } else if (!strcmp(model, "bq4802")) {
785 bq4802_regs = regs;
749 } else 786 } else
750#endif 787#endif
751 if (model[5] == '0' && model[6] == '2') { 788 if (model[5] == '0' && model[6] == '2') {
@@ -1070,8 +1107,10 @@ static int set_rtc_mmss(unsigned long nowtime)
1070 void __iomem *mregs = mstk48t02_regs; 1107 void __iomem *mregs = mstk48t02_regs;
1071#ifdef CONFIG_PCI 1108#ifdef CONFIG_PCI
1072 unsigned long dregs = ds1287_regs; 1109 unsigned long dregs = ds1287_regs;
1110 void __iomem *bregs = bq4802_regs;
1073#else 1111#else
1074 unsigned long dregs = 0UL; 1112 unsigned long dregs = 0UL;
1113 void __iomem *bregs = 0UL;
1075#endif 1114#endif
1076 unsigned long flags; 1115 unsigned long flags;
1077 u8 tmp; 1116 u8 tmp;
@@ -1080,7 +1119,7 @@ static int set_rtc_mmss(unsigned long nowtime)
1080 * Not having a register set can lead to trouble. 1119 * Not having a register set can lead to trouble.
1081 * Also starfire doesn't have a tod clock. 1120 * Also starfire doesn't have a tod clock.
1082 */ 1121 */
1083 if (!mregs && !dregs) 1122 if (!mregs && !dregs & !bregs)
1084 return -1; 1123 return -1;
1085 1124
1086 if (mregs) { 1125 if (mregs) {
@@ -1129,6 +1168,37 @@ static int set_rtc_mmss(unsigned long nowtime)
1129 1168
1130 return -1; 1169 return -1;
1131 } 1170 }
1171 } else if (bregs) {
1172 int retval = 0;
1173 unsigned char val = readb(bregs + 0x0e);
1174
1175 /* BQ4802 RTC chip. */
1176
1177 writeb(val | 0x08, bregs + 0x0e);
1178
1179 chip_minutes = readb(bregs + 0x02);
1180 BCD_TO_BIN(chip_minutes);
1181 real_seconds = nowtime % 60;
1182 real_minutes = nowtime / 60;
1183 if (((abs(real_minutes - chip_minutes) + 15)/30) & 1)
1184 real_minutes += 30;
1185 real_minutes %= 60;
1186
1187 if (abs(real_minutes - chip_minutes) < 30) {
1188 BIN_TO_BCD(real_seconds);
1189 BIN_TO_BCD(real_minutes);
1190 writeb(real_seconds, bregs + 0x00);
1191 writeb(real_minutes, bregs + 0x02);
1192 } else {
1193 printk(KERN_WARNING
1194 "set_rtc_mmss: can't update from %d to %d\n",
1195 chip_minutes, real_minutes);
1196 retval = -1;
1197 }
1198
1199 writeb(val, bregs + 0x0e);
1200
1201 return retval;
1132 } else { 1202 } else {
1133 int retval = 0; 1203 int retval = 0;
1134 unsigned char save_control, save_freq_select; 1204 unsigned char save_control, save_freq_select;
@@ -1259,38 +1329,152 @@ static void to_tm(int tim, struct rtc_time *tm)
1259/* Both Starfire and SUN4V give us seconds since Jan 1st, 1970, 1329/* Both Starfire and SUN4V give us seconds since Jan 1st, 1970,
1260 * aka Unix time. So we have to convert to/from rtc_time. 1330 * aka Unix time. So we have to convert to/from rtc_time.
1261 */ 1331 */
1262static inline void mini_get_rtc_time(struct rtc_time *time) 1332static void starfire_get_rtc_time(struct rtc_time *time)
1263{ 1333{
1264 unsigned long flags; 1334 u32 seconds = starfire_get_time();
1265 u32 seconds;
1266 1335
1267 spin_lock_irqsave(&rtc_lock, flags); 1336 to_tm(seconds, time);
1268 seconds = 0; 1337 time->tm_year -= 1900;
1269 if (this_is_starfire) 1338 time->tm_mon -= 1;
1270 seconds = starfire_get_time(); 1339}
1271 else if (tlb_type == hypervisor) 1340
1272 seconds = hypervisor_get_time(); 1341static int starfire_set_rtc_time(struct rtc_time *time)
1273 spin_unlock_irqrestore(&rtc_lock, flags); 1342{
1343 u32 seconds = mktime(time->tm_year + 1900, time->tm_mon + 1,
1344 time->tm_mday, time->tm_hour,
1345 time->tm_min, time->tm_sec);
1346
1347 return starfire_set_time(seconds);
1348}
1349
1350static void hypervisor_get_rtc_time(struct rtc_time *time)
1351{
1352 u32 seconds = hypervisor_get_time();
1274 1353
1275 to_tm(seconds, time); 1354 to_tm(seconds, time);
1276 time->tm_year -= 1900; 1355 time->tm_year -= 1900;
1277 time->tm_mon -= 1; 1356 time->tm_mon -= 1;
1278} 1357}
1279 1358
1280static inline int mini_set_rtc_time(struct rtc_time *time) 1359static int hypervisor_set_rtc_time(struct rtc_time *time)
1281{ 1360{
1282 u32 seconds = mktime(time->tm_year + 1900, time->tm_mon + 1, 1361 u32 seconds = mktime(time->tm_year + 1900, time->tm_mon + 1,
1283 time->tm_mday, time->tm_hour, 1362 time->tm_mday, time->tm_hour,
1284 time->tm_min, time->tm_sec); 1363 time->tm_min, time->tm_sec);
1364
1365 return hypervisor_set_time(seconds);
1366}
1367
1368static void bq4802_get_rtc_time(struct rtc_time *time)
1369{
1370 unsigned char val = readb(bq4802_regs + 0x0e);
1371 unsigned int century;
1372
1373 writeb(val | 0x08, bq4802_regs + 0x0e);
1374
1375 time->tm_sec = readb(bq4802_regs + 0x00);
1376 time->tm_min = readb(bq4802_regs + 0x02);
1377 time->tm_hour = readb(bq4802_regs + 0x04);
1378 time->tm_mday = readb(bq4802_regs + 0x06);
1379 time->tm_mon = readb(bq4802_regs + 0x09);
1380 time->tm_year = readb(bq4802_regs + 0x0a);
1381 time->tm_wday = readb(bq4802_regs + 0x08);
1382 century = readb(bq4802_regs + 0x0f);
1383
1384 writeb(val, bq4802_regs + 0x0e);
1385
1386 BCD_TO_BIN(time->tm_sec);
1387 BCD_TO_BIN(time->tm_min);
1388 BCD_TO_BIN(time->tm_hour);
1389 BCD_TO_BIN(time->tm_mday);
1390 BCD_TO_BIN(time->tm_mon);
1391 BCD_TO_BIN(time->tm_year);
1392 BCD_TO_BIN(time->tm_wday);
1393 BCD_TO_BIN(century);
1394
1395 time->tm_year += (century * 100);
1396 time->tm_year -= 1900;
1397
1398 time->tm_mon--;
1399}
1400
1401static int bq4802_set_rtc_time(struct rtc_time *time)
1402{
1403 unsigned char val = readb(bq4802_regs + 0x0e);
1404 unsigned char sec, min, hrs, day, mon, yrs, century;
1405 unsigned int year;
1406
1407 year = time->tm_year + 1900;
1408 century = year / 100;
1409 yrs = year % 100;
1410
1411 mon = time->tm_mon + 1; /* tm_mon starts at zero */
1412 day = time->tm_mday;
1413 hrs = time->tm_hour;
1414 min = time->tm_min;
1415 sec = time->tm_sec;
1416
1417 BIN_TO_BCD(sec);
1418 BIN_TO_BCD(min);
1419 BIN_TO_BCD(hrs);
1420 BIN_TO_BCD(day);
1421 BIN_TO_BCD(mon);
1422 BIN_TO_BCD(yrs);
1423 BIN_TO_BCD(century);
1424
1425 writeb(val | 0x08, bq4802_regs + 0x0e);
1426
1427 writeb(sec, bq4802_regs + 0x00);
1428 writeb(min, bq4802_regs + 0x02);
1429 writeb(hrs, bq4802_regs + 0x04);
1430 writeb(day, bq4802_regs + 0x06);
1431 writeb(mon, bq4802_regs + 0x09);
1432 writeb(yrs, bq4802_regs + 0x0a);
1433 writeb(century, bq4802_regs + 0x0f);
1434
1435 writeb(val, bq4802_regs + 0x0e);
1436
1437 return 0;
1438}
1439
1440struct mini_rtc_ops {
1441 void (*get_rtc_time)(struct rtc_time *);
1442 int (*set_rtc_time)(struct rtc_time *);
1443};
1444
1445static struct mini_rtc_ops starfire_rtc_ops = {
1446 .get_rtc_time = starfire_get_rtc_time,
1447 .set_rtc_time = starfire_set_rtc_time,
1448};
1449
1450static struct mini_rtc_ops hypervisor_rtc_ops = {
1451 .get_rtc_time = hypervisor_get_rtc_time,
1452 .set_rtc_time = hypervisor_set_rtc_time,
1453};
1454
1455static struct mini_rtc_ops bq4802_rtc_ops = {
1456 .get_rtc_time = bq4802_get_rtc_time,
1457 .set_rtc_time = bq4802_set_rtc_time,
1458};
1459
1460static struct mini_rtc_ops *mini_rtc_ops;
1461
1462static inline void mini_get_rtc_time(struct rtc_time *time)
1463{
1464 unsigned long flags;
1465
1466 spin_lock_irqsave(&rtc_lock, flags);
1467 mini_rtc_ops->get_rtc_time(time);
1468 spin_unlock_irqrestore(&rtc_lock, flags);
1469}
1470
1471static inline int mini_set_rtc_time(struct rtc_time *time)
1472{
1285 unsigned long flags; 1473 unsigned long flags;
1286 int err; 1474 int err;
1287 1475
1288 spin_lock_irqsave(&rtc_lock, flags); 1476 spin_lock_irqsave(&rtc_lock, flags);
1289 err = -ENODEV; 1477 err = mini_rtc_ops->set_rtc_time(time);
1290 if (this_is_starfire)
1291 err = starfire_set_time(seconds);
1292 else if (tlb_type == hypervisor)
1293 err = hypervisor_set_time(seconds);
1294 spin_unlock_irqrestore(&rtc_lock, flags); 1478 spin_unlock_irqrestore(&rtc_lock, flags);
1295 1479
1296 return err; 1480 return err;
@@ -1391,7 +1575,13 @@ static int __init rtc_mini_init(void)
1391{ 1575{
1392 int retval; 1576 int retval;
1393 1577
1394 if (tlb_type != hypervisor && !this_is_starfire) 1578 if (tlb_type == hypervisor)
1579 mini_rtc_ops = &hypervisor_rtc_ops;
1580 else if (this_is_starfire)
1581 mini_rtc_ops = &starfire_rtc_ops;
1582 else if (bq4802_regs)
1583 mini_rtc_ops = &bq4802_rtc_ops;
1584 else
1395 return -ENODEV; 1585 return -ENODEV;
1396 1586
1397 printk(KERN_INFO "Mini RTC Driver\n"); 1587 printk(KERN_INFO "Mini RTC Driver\n");