diff options
author | Paul Mundt <lethal@linux-sh.org> | 2007-08-03 01:19:58 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2007-09-20 22:57:47 -0400 |
commit | ad89f87a84040a57c4a78ca2759b364f72f423ab (patch) | |
tree | a34207175da4338cc8e4e7b7ea323193e199eb3c /drivers/rtc | |
parent | 7da3b8ef662af6252aa17c55cc0aa6d74cbf02e4 (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')
-rw-r--r-- | drivers/rtc/rtc-sh.c | 51 |
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 | ||
85 | static irqreturn_t sh_rtc_interrupt(int irq, void *dev_id) | 89 | static 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; |