aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc/rtc-sh.c
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2007-08-03 01:19:58 -0400
committerPaul Mundt <lethal@linux-sh.org>2007-09-20 22:57:47 -0400
commitad89f87a84040a57c4a78ca2759b364f72f423ab (patch)
treea34207175da4338cc8e4e7b7ea323193e199eb3c /drivers/rtc/rtc-sh.c
parent7da3b8ef662af6252aa17c55cc0aa6d74cbf02e4 (diff)
rtc: rtc-sh: Support 4-digit year on SH7705/SH7710/SH7712.
All SH-4 parts have a 4-digit year, while the SH-3 parts typically only use a 2-digit one. The SH7705, SH7710, and SH7712 SH-3 parts however opted to extend it to 4-digit and still look and act like an SH-3 RTC in all other ways. This adds a capability flag (RTC_CAP_4_DIGIT_YEAR) that these corner-case CPU subtypes can set in their platform data and cleans up some of the ifdef mess in the driver as a result. Reported-by: Markus Brunner <super.firetwister@gmail.com> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'drivers/rtc/rtc-sh.c')
-rw-r--r--drivers/rtc/rtc-sh.c51
1 files changed, 33 insertions, 18 deletions
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c
index 93ee05eeaeba..78277a118b67 100644
--- a/drivers/rtc/rtc-sh.c
+++ b/drivers/rtc/rtc-sh.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * SuperH On-Chip RTC Support 2 * SuperH On-Chip RTC Support
3 * 3 *
4 * Copyright (C) 2006 Paul Mundt 4 * Copyright (C) 2006, 2007 Paul Mundt
5 * Copyright (C) 2006 Jamie Lenehan 5 * Copyright (C) 2006 Jamie Lenehan
6 * 6 *
7 * Based on the old arch/sh/kernel/cpu/rtc.c by: 7 * Based on the old arch/sh/kernel/cpu/rtc.c by:
@@ -23,16 +23,19 @@
23#include <linux/interrupt.h> 23#include <linux/interrupt.h>
24#include <linux/spinlock.h> 24#include <linux/spinlock.h>
25#include <linux/io.h> 25#include <linux/io.h>
26#include <asm/rtc.h>
26 27
27#define DRV_NAME "sh-rtc" 28#define DRV_NAME "sh-rtc"
28#define DRV_VERSION "0.1.2" 29#define DRV_VERSION "0.1.3"
29 30
30#ifdef CONFIG_CPU_SH3 31#ifdef CONFIG_CPU_SH3
31#define rtc_reg_size sizeof(u16) 32#define rtc_reg_size sizeof(u16)
32#define RTC_BIT_INVERTED 0 /* No bug on SH7708, SH7709A */ 33#define RTC_BIT_INVERTED 0 /* No bug on SH7708, SH7709A */
34#define RTC_DEF_CAPABILITIES 0UL
33#elif defined(CONFIG_CPU_SH4) 35#elif defined(CONFIG_CPU_SH4)
34#define rtc_reg_size sizeof(u32) 36#define rtc_reg_size sizeof(u32)
35#define RTC_BIT_INVERTED 0x40 /* bug on SH7750, SH7750S */ 37#define RTC_BIT_INVERTED 0x40 /* bug on SH7750, SH7750S */
38#define RTC_DEF_CAPABILITIES RTC_CAP_4_DIGIT_YEAR
36#endif 39#endif
37 40
38#define RTC_REG(r) ((r) * rtc_reg_size) 41#define RTC_REG(r) ((r) * rtc_reg_size)
@@ -80,6 +83,7 @@ struct sh_rtc {
80 struct rtc_device *rtc_dev; 83 struct rtc_device *rtc_dev;
81 spinlock_t lock; 84 spinlock_t lock;
82 int rearm_aie; 85 int rearm_aie;
86 unsigned long capabilities; /* See asm-sh/rtc.h for cap bits */
83}; 87};
84 88
85static irqreturn_t sh_rtc_interrupt(int irq, void *dev_id) 89static irqreturn_t sh_rtc_interrupt(int irq, void *dev_id)
@@ -319,14 +323,14 @@ static int sh_rtc_read_time(struct device *dev, struct rtc_time *tm)
319 tm->tm_mday = BCD2BIN(readb(rtc->regbase + RDAYCNT)); 323 tm->tm_mday = BCD2BIN(readb(rtc->regbase + RDAYCNT));
320 tm->tm_mon = BCD2BIN(readb(rtc->regbase + RMONCNT)) - 1; 324 tm->tm_mon = BCD2BIN(readb(rtc->regbase + RMONCNT)) - 1;
321 325
322#if defined(CONFIG_CPU_SH4) 326 if (rtc->capabilities & RTC_CAP_4_DIGIT_YEAR) {
323 yr = readw(rtc->regbase + RYRCNT); 327 yr = readw(rtc->regbase + RYRCNT);
324 yr100 = BCD2BIN(yr >> 8); 328 yr100 = BCD2BIN(yr >> 8);
325 yr &= 0xff; 329 yr &= 0xff;
326#else 330 } else {
327 yr = readb(rtc->regbase + RYRCNT); 331 yr = readb(rtc->regbase + RYRCNT);
328 yr100 = BCD2BIN((yr == 0x99) ? 0x19 : 0x20); 332 yr100 = BCD2BIN((yr == 0x99) ? 0x19 : 0x20);
329#endif 333 }
330 334
331 tm->tm_year = (yr100 * 100 + BCD2BIN(yr)) - 1900; 335 tm->tm_year = (yr100 * 100 + BCD2BIN(yr)) - 1900;
332 336
@@ -375,14 +379,14 @@ static int sh_rtc_set_time(struct device *dev, struct rtc_time *tm)
375 writeb(BIN2BCD(tm->tm_mday), rtc->regbase + RDAYCNT); 379 writeb(BIN2BCD(tm->tm_mday), rtc->regbase + RDAYCNT);
376 writeb(BIN2BCD(tm->tm_mon + 1), rtc->regbase + RMONCNT); 380 writeb(BIN2BCD(tm->tm_mon + 1), rtc->regbase + RMONCNT);
377 381
378#ifdef CONFIG_CPU_SH3 382 if (rtc->capabilities & RTC_CAP_4_DIGIT_YEAR) {
379 year = tm->tm_year % 100; 383 year = (BIN2BCD((tm->tm_year + 1900) / 100) << 8) |
380 writeb(BIN2BCD(year), rtc->regbase + RYRCNT); 384 BIN2BCD(tm->tm_year % 100);
381#else 385 writew(year, rtc->regbase + RYRCNT);
382 year = (BIN2BCD((tm->tm_year + 1900) / 100) << 8) | 386 } else {
383 BIN2BCD(tm->tm_year % 100); 387 year = tm->tm_year % 100;
384 writew(year, rtc->regbase + RYRCNT); 388 writeb(BIN2BCD(year), rtc->regbase + RYRCNT);
385#endif 389 }
386 390
387 /* Start RTC */ 391 /* Start RTC */
388 tmp = readb(rtc->regbase + RCR2); 392 tmp = readb(rtc->regbase + RCR2);
@@ -589,6 +593,17 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev)
589 goto err_badmap; 593 goto err_badmap;
590 } 594 }
591 595
596 rtc->capabilities = RTC_DEF_CAPABILITIES;
597 if (pdev->dev.platform_data) {
598 struct sh_rtc_platform_info *pinfo = pdev->dev.platform_data;
599
600 /*
601 * Some CPUs have special capabilities in addition to the
602 * default set. Add those in here.
603 */
604 rtc->capabilities |= pinfo->capabilities;
605 }
606
592 platform_set_drvdata(pdev, rtc); 607 platform_set_drvdata(pdev, rtc);
593 608
594 return 0; 609 return 0;