rtc: rtc-sh: Support 4-digit year on SH7705/SH7710/SH7712.
authorPaul Mundt <lethal@linux-sh.org>
Fri, 3 Aug 2007 05:19:58 +0000 (14:19 +0900)
committerPaul Mundt <lethal@linux-sh.org>
Fri, 21 Sep 2007 02:57:47 +0000 (11:57 +0900)
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>
arch/sh/kernel/cpu/sh3/setup-sh7705.c
arch/sh/kernel/cpu/sh3/setup-sh7710.c
drivers/rtc/rtc-sh.c
include/asm-sh/rtc.h

index 6fc68e77102f46b406c7d91210948ca45a6d08ca..568cc08c254b885c7082dde238b8c1ee5c49f7be 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * SH7705 Setup
  *
- *  Copyright (C) 2006  Paul Mundt
+ *  Copyright (C) 2006, 2007  Paul Mundt
  *  Copyright (C) 2007  Nobuhiro Iwamatsu
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -13,8 +13,9 @@
 #include <linux/irq.h>
 #include <linux/serial.h>
 #include <asm/sci.h>
+#include <asm/rtc.h>
 
-enum
+enum {
        UNUSED = 0,
 
        /* interrupt sources */
@@ -138,11 +139,18 @@ static struct resource rtc_resources[] = {
        },
 };
 
+static struct sh_rtc_platform_info rtc_info = {
+       .capabilities   = RTC_CAP_4_DIGIT_YEAR,
+};
+
 static struct platform_device rtc_device = {
        .name           = "sh-rtc",
        .id             = -1,
        .num_resources  = ARRAY_SIZE(rtc_resources),
        .resource       = rtc_resources,
+       .dev            = {
+               .platform_data = &rtc_info,
+       },
 };
 
 static struct platform_device *sh7705_devices[] __initdata = {
index 07f26ab75d97c08f8d29fbceb46db3c83c6a321b..eb55ac9dbf717d47a24fc4abc98e4b7e4a819b62 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * SH3 Setup code for SH7710, SH7712
  *
- *  Copyright (C) 2006  Paul Mundt
+ *  Copyright (C) 2006, 2007  Paul Mundt
  *  Copyright (C) 2007  Nobuhiro Iwamatsu
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -13,6 +13,7 @@
 #include <linux/irq.h>
 #include <linux/serial.h>
 #include <asm/sci.h>
+#include <asm/rtc.h>
 
 enum {
        UNUSED = 0,
@@ -130,11 +131,18 @@ static struct resource rtc_resources[] = {
        },
 };
 
+static struct sh_rtc_platform_info rtc_info = {
+       .capabilities   = RTC_CAP_4_DIGIT_YEAR,
+};
+
 static struct platform_device rtc_device = {
        .name           = "sh-rtc",
        .id             = -1,
        .num_resources  = ARRAY_SIZE(rtc_resources),
        .resource       = rtc_resources,
+       .dev            = {
+               .platform_data = &rtc_info,
+       },
 };
 
 static struct plat_sci_port sci_platform_data[] = {
index 93ee05eeaeba810f6bda495c5655cccc4031de7f..78277a118b6773268d7813b33d3fbe19dc79d6d0 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * SuperH On-Chip RTC Support
  *
- * Copyright (C) 2006  Paul Mundt
+ * Copyright (C) 2006, 2007  Paul Mundt
  * Copyright (C) 2006  Jamie Lenehan
  *
  * Based on the old arch/sh/kernel/cpu/rtc.c by:
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
 #include <linux/io.h>
+#include <asm/rtc.h>
 
 #define DRV_NAME       "sh-rtc"
-#define DRV_VERSION    "0.1.2"
+#define DRV_VERSION    "0.1.3"
 
 #ifdef CONFIG_CPU_SH3
 #define rtc_reg_size           sizeof(u16)
 #define RTC_BIT_INVERTED       0       /* No bug on SH7708, SH7709A */
+#define RTC_DEF_CAPABILITIES   0UL
 #elif defined(CONFIG_CPU_SH4)
 #define rtc_reg_size           sizeof(u32)
 #define RTC_BIT_INVERTED       0x40    /* bug on SH7750, SH7750S */
+#define RTC_DEF_CAPABILITIES   RTC_CAP_4_DIGIT_YEAR
 #endif
 
 #define RTC_REG(r)     ((r) * rtc_reg_size)
@@ -80,6 +83,7 @@ struct sh_rtc {
        struct rtc_device *rtc_dev;
        spinlock_t lock;
        int rearm_aie;
+       unsigned long capabilities;     /* See asm-sh/rtc.h for cap bits */
 };
 
 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)
                tm->tm_mday     = BCD2BIN(readb(rtc->regbase + RDAYCNT));
                tm->tm_mon      = BCD2BIN(readb(rtc->regbase + RMONCNT)) - 1;
 
-#if defined(CONFIG_CPU_SH4)
-               yr  = readw(rtc->regbase + RYRCNT);
-               yr100 = BCD2BIN(yr >> 8);
-               yr &= 0xff;
-#else
-               yr  = readb(rtc->regbase + RYRCNT);
-               yr100 = BCD2BIN((yr == 0x99) ? 0x19 : 0x20);
-#endif
+               if (rtc->capabilities & RTC_CAP_4_DIGIT_YEAR) {
+                       yr  = readw(rtc->regbase + RYRCNT);
+                       yr100 = BCD2BIN(yr >> 8);
+                       yr &= 0xff;
+               } else {
+                       yr  = readb(rtc->regbase + RYRCNT);
+                       yr100 = BCD2BIN((yr == 0x99) ? 0x19 : 0x20);
+               }
 
                tm->tm_year = (yr100 * 100 + BCD2BIN(yr)) - 1900;
 
@@ -375,14 +379,14 @@ static int sh_rtc_set_time(struct device *dev, struct rtc_time *tm)
        writeb(BIN2BCD(tm->tm_mday), rtc->regbase + RDAYCNT);
        writeb(BIN2BCD(tm->tm_mon + 1), rtc->regbase + RMONCNT);
 
-#ifdef CONFIG_CPU_SH3
-       year = tm->tm_year % 100;
-       writeb(BIN2BCD(year), rtc->regbase + RYRCNT);
-#else
-       year = (BIN2BCD((tm->tm_year + 1900) / 100) << 8) |
-               BIN2BCD(tm->tm_year % 100);
-       writew(year, rtc->regbase + RYRCNT);
-#endif
+       if (rtc->capabilities & RTC_CAP_4_DIGIT_YEAR) {
+               year = (BIN2BCD((tm->tm_year + 1900) / 100) << 8) |
+                       BIN2BCD(tm->tm_year % 100);
+               writew(year, rtc->regbase + RYRCNT);
+       } else {
+               year = tm->tm_year % 100;
+               writeb(BIN2BCD(year), rtc->regbase + RYRCNT);
+       }
 
        /* Start RTC */
        tmp = readb(rtc->regbase + RCR2);
@@ -589,6 +593,17 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev)
                goto err_badmap;
        }
 
+       rtc->capabilities = RTC_DEF_CAPABILITIES;
+       if (pdev->dev.platform_data) {
+               struct sh_rtc_platform_info *pinfo = pdev->dev.platform_data;
+
+               /*
+                * Some CPUs have special capabilities in addition to the
+                * default set. Add those in here.
+                */
+               rtc->capabilities |= pinfo->capabilities;
+       }
+
        platform_set_drvdata(pdev, rtc);
 
        return 0;
index 91aacc96151b2fab63a10aa1eb87f92bf0a80d66..858da99d37e0f7f07c1a4b79439aec70fad67cc6 100644 (file)
@@ -5,4 +5,10 @@ extern void (*board_time_init)(void);
 extern void (*rtc_sh_get_time)(struct timespec *);
 extern int (*rtc_sh_set_time)(const time_t);
 
+#define RTC_CAP_4_DIGIT_YEAR   (1 << 0)
+
+struct sh_rtc_platform_info {
+       unsigned long capabilities;
+};
+
 #endif /* _ASM_RTC_H */