Commit ad89f87a authored by Paul Mundt's avatar Paul Mundt
Browse files

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: default avatarMarkus Brunner <super.firetwister@gmail.com>
Signed-off-by: default avatarPaul Mundt <lethal@linux-sh.org>
parent 7da3b8ef
Loading
Loading
Loading
Loading
+10 −2
Original line number Diff line number Diff line
/*
 * 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,6 +13,7 @@
#include <linux/irq.h>
#include <linux/serial.h>
#include <asm/sci.h>
#include <asm/rtc.h>

enum {
	UNUSED = 0,
@@ -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 = {
+9 −1
Original line number Diff line number Diff line
/*
 * 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[] = {
+33 −18
Original line number Diff line number Diff line
/*
 * 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:
@@ -23,16 +23,19 @@
#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)
		if (rtc->capabilities & RTC_CAP_4_DIGIT_YEAR) {
			yr  = readw(rtc->regbase + RYRCNT);
			yr100 = BCD2BIN(yr >> 8);
			yr &= 0xff;
#else
		} else {
			yr  = readb(rtc->regbase + RYRCNT);
			yr100 = BCD2BIN((yr == 0x99) ? 0x19 : 0x20);
#endif
		}

		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
	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);
#endif
	} 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;
+6 −0
Original line number Diff line number Diff line
@@ -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 */