aboutsummaryrefslogtreecommitdiffstats
path: root/recipes/linux/linux-jlime-jornada6xx-2.6.17/rtc-2.6.17.patch
diff options
context:
space:
mode:
authorKristoffer Ericson <kristoffer.ericson@gmail.com>2009-12-27 20:25:22 +0100
committerKristoffer Ericson <kristoffer.ericson@gmail.com>2009-12-27 20:25:22 +0100
commit6e7bc0863c7228f02045b439c9ebf54b7ef67469 (patch)
treec91b91801085fdbb29db4a7d7c24f2d45b6d4f56 /recipes/linux/linux-jlime-jornada6xx-2.6.17/rtc-2.6.17.patch
parent371a4860922514c2ae28c0209c8b0c6ccc41d623 (diff)
downloadopenembedded-6e7bc0863c7228f02045b439c9ebf54b7ef67469.tar.gz
Updated JLiMe 2.6.17 kernel. Changes include addition of alsa driver and also rtc.
Signed-off-by: Alex Ferguson <thoughtmonster@gmail.com> Signed-off-by: Kristoffer Ericson <kristoffer.ericson@gmail.com>
Diffstat (limited to 'recipes/linux/linux-jlime-jornada6xx-2.6.17/rtc-2.6.17.patch')
-rw-r--r--recipes/linux/linux-jlime-jornada6xx-2.6.17/rtc-2.6.17.patch987
1 files changed, 987 insertions, 0 deletions
diff --git a/recipes/linux/linux-jlime-jornada6xx-2.6.17/rtc-2.6.17.patch b/recipes/linux/linux-jlime-jornada6xx-2.6.17/rtc-2.6.17.patch
new file mode 100644
index 0000000000..a744c268c8
--- /dev/null
+++ b/recipes/linux/linux-jlime-jornada6xx-2.6.17/rtc-2.6.17.patch
@@ -0,0 +1,987 @@
+diff -ru linux-2.6.17.old/arch/sh/boards/hp6xx/pm.c linux-2.6.17/arch/sh/boards/hp6xx/pm.c
+--- linux-2.6.17.old/arch/sh/boards/hp6xx/pm.c 2009-12-21 10:27:22.776442805 +0200
++++ linux-2.6.17/arch/sh/boards/hp6xx/pm.c 2009-12-21 10:30:09.366428509 +0200
+@@ -17,6 +17,10 @@
+ #include <asm/cpu/dac.h>
+ #include <asm/pm.h>
+
++#include <asm-sh/rtc.h>
++#include <linux/time.h>
++#include <asm-sh/rtc.h>
++
+ #define STBCR 0xffffff82
+ #define STBCR2 0xffffff88
+
+@@ -68,6 +72,8 @@
+ outb(0x00, HD64461_PCC1CSCR);
+ #endif
+
++ rtc_sh_get_time(&xtime);
++
+ return 0;
+ }
+
+diff -ru linux-2.6.17.old/arch/sh/kernel/cpu/irq/ipr.c linux-2.6.17/arch/sh/kernel/cpu/irq/ipr.c
+--- linux-2.6.17.old/arch/sh/kernel/cpu/irq/ipr.c 2006-06-18 04:49:35.000000000 +0300
++++ linux-2.6.17/arch/sh/kernel/cpu/irq/ipr.c 2009-12-21 10:29:58.713508059 +0200
+@@ -125,7 +125,12 @@
+ make_ipr_irq(TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY);
+ make_ipr_irq(TIMER1_IRQ, TIMER1_IPR_ADDR, TIMER1_IPR_POS, TIMER1_PRIORITY);
+ #if defined(CONFIG_SH_RTC)
++ make_ipr_irq(20, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY);
++ printk("kernel IRQ RTC =%i\n",20);
++ make_ipr_irq(21, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY);
++ printk("kernel IRQ RTC =%i\n",21);
+ make_ipr_irq(RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY);
++ printk("kernel IRQ RTC =%i\n",RTC_IRQ);
+ #endif
+
+ #ifdef SCI_ERI_IRQ
+diff -ru linux-2.6.17.old/arch/sh/kernel/cpu/sh3/Makefile linux-2.6.17/arch/sh/kernel/cpu/sh3/Makefile
+--- linux-2.6.17.old/arch/sh/kernel/cpu/sh3/Makefile 2006-06-18 04:49:35.000000000 +0300
++++ linux-2.6.17/arch/sh/kernel/cpu/sh3/Makefile 2009-12-21 10:29:58.713508059 +0200
+@@ -4,10 +4,13 @@
+
+ obj-y := ex.o probe.o
+
++obj-$(CONFIG_CPU_SUBTYPE_SH7709) += setup-sh770x.o
++
+ clock-$(CONFIG_CPU_SH3) := clock-sh3.o
+ clock-$(CONFIG_CPU_SUBTYPE_SH7300) := clock-sh7300.o
+ clock-$(CONFIG_CPU_SUBTYPE_SH7705) := clock-sh7705.o
+-clock-$(CONFIG_CPU_SUBTYPE_SH7709) := clock-sh7709.o
++# clock-$(CONFIG_CPU_SUBTYPE_SH7709) := clock-sh7709.o
++clock-$(CONFIG_CPU_SUBTYPE_SH7709) := clock-sh7709.o
+
+ obj-y += $(clock-y)
+
+diff -ru linux-2.6.17.old/arch/sh/kernel/cpu/sh3/setup-sh770x.c linux-2.6.17/arch/sh/kernel/cpu/sh3/setup-sh770x.c
+--- linux-2.6.17.old/arch/sh/kernel/cpu/sh3/setup-sh770x.c 2009-12-21 10:32:06.699746910 +0200
++++ linux-2.6.17/arch/sh/kernel/cpu/sh3/setup-sh770x.c 2009-12-21 10:29:58.713508059 +0200
+@@ -0,0 +1,217 @@
++/*
++ * SH3 Setup code for SH7706, SH7707, SH7708, SH7709
++ *
++ * Copyright (C) 2007 Magnus Damm
++ *
++ * Based on setup-sh7709.c
++ *
++ * Copyright (C) 2006 Paul Mundt
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ */
++#include <linux/init.h>
++#include <linux/io.h>
++#include <linux/irq.h>
++#include <linux/platform_device.h>
++#include <linux/serial.h>
++#include <linux/serial_sci.h>
++
++enum {
++ UNUSED = 0,
++
++ /* interrupt sources */
++ IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5,
++ PINT07, PINT815,
++ DMAC_DEI0, DMAC_DEI1, DMAC_DEI2, DMAC_DEI3,
++ SCIF0_ERI, SCIF0_RXI, SCIF0_BRI, SCIF0_TXI,
++ SCIF2_ERI, SCIF2_RXI, SCIF2_BRI, SCIF2_TXI,
++ SCI_ERI, SCI_RXI, SCI_TXI, SCI_TEI,
++ ADC_ADI,
++ LCDC, PCC0, PCC1,
++ TMU0, TMU1, TMU2_TUNI, TMU2_TICPI,
++ RTC_ATI, RTC_PRI, RTC_CUI,
++ WDT,
++ REF_RCMI, REF_ROVI,
++
++ /* interrupt groups */
++ RTC, REF, TMU2, DMAC, SCI, SCIF2, SCIF0,
++};
++
++static struct intc_vect vectors[] __initdata = {
++ INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
++ INTC_VECT(TMU2_TUNI, 0x440), INTC_VECT(TMU2_TICPI, 0x460),
++ INTC_VECT(RTC_ATI, 0x480), INTC_VECT(RTC_PRI, 0x4a0),
++ INTC_VECT(RTC_CUI, 0x4c0),
++ INTC_VECT(SCI_ERI, 0x4e0), INTC_VECT(SCI_RXI, 0x500),
++ INTC_VECT(SCI_TXI, 0x520), INTC_VECT(SCI_TEI, 0x540),
++ INTC_VECT(WDT, 0x560),
++ INTC_VECT(REF_RCMI, 0x580),
++ INTC_VECT(REF_ROVI, 0x5a0),
++#if defined(CONFIG_CPU_SUBTYPE_SH7706) || \
++ defined(CONFIG_CPU_SUBTYPE_SH7707) || \
++ defined(CONFIG_CPU_SUBTYPE_SH7709)
++ INTC_VECT(IRQ4, 0x680), INTC_VECT(IRQ5, 0x6a0),
++ INTC_VECT(DMAC_DEI0, 0x800), INTC_VECT(DMAC_DEI1, 0x820),
++ INTC_VECT(DMAC_DEI2, 0x840), INTC_VECT(DMAC_DEI3, 0x860),
++ INTC_VECT(ADC_ADI, 0x980),
++ INTC_VECT(SCIF2_ERI, 0x900), INTC_VECT(SCIF2_RXI, 0x920),
++ INTC_VECT(SCIF2_BRI, 0x940), INTC_VECT(SCIF2_TXI, 0x960),
++#endif
++#if defined(CONFIG_CPU_SUBTYPE_SH7707) || \
++ defined(CONFIG_CPU_SUBTYPE_SH7709)
++ INTC_VECT(PINT07, 0x700), INTC_VECT(PINT815, 0x720),
++ INTC_VECT(SCIF0_ERI, 0x880), INTC_VECT(SCIF0_RXI, 0x8a0),
++ INTC_VECT(SCIF0_BRI, 0x8c0), INTC_VECT(SCIF0_TXI, 0x8e0),
++#endif
++#if defined(CONFIG_CPU_SUBTYPE_SH7707)
++ INTC_VECT(LCDC, 0x9a0),
++ INTC_VECT(PCC0, 0x9c0), INTC_VECT(PCC1, 0x9e0),
++#endif
++};
++
++static struct intc_group groups[] __initdata = {
++ INTC_GROUP(RTC, RTC_ATI, RTC_PRI, RTC_CUI),
++ INTC_GROUP(TMU2, TMU2_TUNI, TMU2_TICPI),
++ INTC_GROUP(REF, REF_RCMI, REF_ROVI),
++ INTC_GROUP(DMAC, DMAC_DEI0, DMAC_DEI1, DMAC_DEI2, DMAC_DEI3),
++ INTC_GROUP(SCI, SCI_ERI, SCI_RXI, SCI_TXI, SCI_TEI),
++ INTC_GROUP(SCIF0, SCIF0_ERI, SCIF0_RXI, SCIF0_BRI, SCIF0_TXI),
++ INTC_GROUP(SCIF2, SCIF2_ERI, SCIF2_RXI, SCIF2_BRI, SCIF2_TXI),
++};
++
++static struct intc_prio_reg prio_registers[] __initdata = {
++ { 0xfffffee2, 0, 16, 4, /* IPRA */ { TMU0, TMU1, TMU2, RTC } },
++ { 0xfffffee4, 0, 16, 4, /* IPRB */ { WDT, REF, SCI, 0 } },
++#if defined(CONFIG_CPU_SUBTYPE_SH7706) || \
++ defined(CONFIG_CPU_SUBTYPE_SH7707) || \
++ defined(CONFIG_CPU_SUBTYPE_SH7709)
++ { 0xa4000016, 0, 16, 4, /* IPRC */ { IRQ3, IRQ2, IRQ1, IRQ0 } },
++ { 0xa4000018, 0, 16, 4, /* IPRD */ { 0, 0, IRQ5, IRQ4 } },
++ { 0xa400001a, 0, 16, 4, /* IPRE */ { DMAC, 0, SCIF2, ADC_ADI } },
++#endif
++#if defined(CONFIG_CPU_SUBTYPE_SH7707) || \
++ defined(CONFIG_CPU_SUBTYPE_SH7709)
++ { 0xa4000018, 0, 16, 4, /* IPRD */ { PINT07, PINT815, } },
++ { 0xa400001a, 0, 16, 4, /* IPRE */ { 0, SCIF0 } },
++#endif
++#if defined(CONFIG_CPU_SUBTYPE_SH7707)
++ { 0xa400001c, 0, 16, 4, /* IPRF */ { 0, LCDC, PCC0, PCC1, } },
++#endif
++};
++
++static DECLARE_INTC_DESC(intc_desc, "sh770x", vectors, groups,
++ NULL, prio_registers, NULL);
++
++#if defined(CONFIG_CPU_SUBTYPE_SH7706) || \
++ defined(CONFIG_CPU_SUBTYPE_SH7707) || \
++ defined(CONFIG_CPU_SUBTYPE_SH7709)
++static struct intc_vect vectors_irq[] __initdata = {
++ INTC_VECT(IRQ0, 0x600), INTC_VECT(IRQ1, 0x620),
++ INTC_VECT(IRQ2, 0x640), INTC_VECT(IRQ3, 0x660),
++};
++
++static DECLARE_INTC_DESC(intc_desc_irq, "sh770x-irq", vectors_irq, NULL,
++ NULL, prio_registers, NULL);
++#endif
++
++static struct resource rtc_resources[] = {
++ [0] = {
++ .start = 0xfffffec0,
++ .end = 0xfffffec0 + 0x1e,
++ .flags = IORESOURCE_IO,
++ },
++ [1] = {
++ .start = 21,
++ .flags = IORESOURCE_IRQ,
++ },
++ [2] = {
++ .start = 22,
++ .flags = IORESOURCE_IRQ,
++ },
++ [3] = {
++ .start = 20,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device rtc_device = {
++ .name = "sh-rtc",
++ .id = -1,
++ .num_resources = ARRAY_SIZE(rtc_resources),
++ .resource = rtc_resources,
++};
++
++static struct plat_sci_port sci_platform_data[] = {
++ {
++ .mapbase = 0xfffffe80,
++ .flags = UPF_BOOT_AUTOCONF,
++ .type = PORT_SCI,
++ .irqs = { 23, 24, 25, 0 },
++ },
++#if defined(CONFIG_CPU_SUBTYPE_SH7706) || \
++ defined(CONFIG_CPU_SUBTYPE_SH7707) || \
++ defined(CONFIG_CPU_SUBTYPE_SH7709)
++ {
++ .mapbase = 0xa4000150,
++ .flags = UPF_BOOT_AUTOCONF,
++ .type = PORT_SCIF,
++ .irqs = { 56, 57, 59, 58 },
++ },
++#endif
++#if defined(CONFIG_CPU_SUBTYPE_SH7707) || \
++ defined(CONFIG_CPU_SUBTYPE_SH7709)
++ {
++ .mapbase = 0xa4000140,
++ .flags = UPF_BOOT_AUTOCONF,
++ .type = PORT_IRDA,
++ .irqs = { 52, 53, 55, 54 },
++ },
++#endif
++ {
++ .flags = 0,
++ }
++};
++
++static struct platform_device sci_device = {
++ .name = "sh-sci",
++ .id = -1,
++ .dev = {
++ .platform_data = sci_platform_data,
++ },
++};
++
++static struct platform_device *sh770x_devices[] __initdata = {
++ &sci_device,
++ &rtc_device,
++};
++
++static int __init sh770x_devices_setup(void)
++{
++ return platform_add_devices(sh770x_devices,
++ ARRAY_SIZE(sh770x_devices));
++}
++__initcall(sh770x_devices_setup);
++
++#define INTC_ICR1 0xa4000010UL
++#define INTC_ICR1_IRQLVL (1<<14)
++
++void __init plat_irq_setup_pins(int mode)
++{
++ if (mode == IRQ_MODE_IRQ) {
++#if defined(CONFIG_CPU_SUBTYPE_SH7706) || \
++ defined(CONFIG_CPU_SUBTYPE_SH7707) || \
++ defined(CONFIG_CPU_SUBTYPE_SH7709)
++ ctrl_outw(ctrl_inw(INTC_ICR1) & ~INTC_ICR1_IRQLVL, INTC_ICR1);
++/* register_intc_controller(&intc_desc_irq); */
++ return;
++#endif
++ }
++ BUG();
++}
++
++void __init plat_irq_setup(void)
++{
++/* register_intc_controller(&intc_desc); */
++}
+diff -ru linux-2.6.17.old/drivers/rtc/interface.c linux-2.6.17/drivers/rtc/interface.c
+--- linux-2.6.17.old/drivers/rtc/interface.c 2006-06-18 04:49:35.000000000 +0300
++++ linux-2.6.17/drivers/rtc/interface.c 2009-12-21 10:29:58.713508059 +0200
+@@ -145,11 +145,16 @@
+ }
+ EXPORT_SYMBOL_GPL(rtc_set_alarm);
+
+-void rtc_update_irq(struct class_device *class_dev,
++/**
++ * rtc_update_irq - report RTC periodic, alarm, and/or update irqs
++ * @rtc: the rtc device
++ * @num: how many irqs are being reported (usually one)
++ * @events: mask of RTC_IRQF with one or more of RTC_PF, RTC_AF, RTC_UF
++ * Context: in_interrupt(), irqs blocked
++ */
++void rtc_update_irq(struct rtc_device *rtc,
+ unsigned long num, unsigned long events)
+ {
+- struct rtc_device *rtc = to_rtc_device(class_dev);
+-
+ spin_lock(&rtc->irq_lock);
+ rtc->irq_data = (rtc->irq_data + (num << 8)) | events;
+ spin_unlock(&rtc->irq_lock);
+diff -ru linux-2.6.17.old/drivers/rtc/rtc-sh.c linux-2.6.17/drivers/rtc/rtc-sh.c
+--- linux-2.6.17.old/drivers/rtc/rtc-sh.c 2009-12-21 10:27:23.403110577 +0200
++++ linux-2.6.17/drivers/rtc/rtc-sh.c 2009-12-21 10:29:58.716840103 +0200
+@@ -1,7 +1,8 @@
+ /*
+ * 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:
+ *
+@@ -21,34 +22,46 @@
+ #include <linux/seq_file.h>
+ #include <linux/interrupt.h>
+ #include <linux/spinlock.h>
+-#include <asm/io.h>
++#include <linux/io.h>
++#include <asm/rtc.h>
+
+-#ifdef CONFIG_CPU_SH3
+-#define rtc_reg_size sizeof(u16)
+-#define RTC_BIT_INVERTED 0 /* No bug on SH7708, SH7709A */
+-#elif defined(CONFIG_CPU_SH4)
+-#define rtc_reg_size sizeof(u32)
+-#define RTC_BIT_INVERTED 0x40 /* bug on SH7750, SH7750S */
+-#endif
++#define DRV_NAME "sh-rtc"
++#define DRV_VERSION "0.1.6"
+
+ #define RTC_REG(r) ((r) * rtc_reg_size)
+
+-#define R64CNT RTC_REG(0)
+-#define RSECCNT RTC_REG(1)
+-#define RMINCNT RTC_REG(2)
+-#define RHRCNT RTC_REG(3)
+-#define RWKCNT RTC_REG(4)
+-#define RDAYCNT RTC_REG(5)
+-#define RMONCNT RTC_REG(6)
+-#define RYRCNT RTC_REG(7)
+-#define RSECAR RTC_REG(8)
+-#define RMINAR RTC_REG(9)
+-#define RHRAR RTC_REG(10)
+-#define RWKAR RTC_REG(11)
+-#define RDAYAR RTC_REG(12)
+-#define RMONAR RTC_REG(13)
+-#define RCR1 RTC_REG(14)
+-#define RCR2 RTC_REG(15)
++#define R64CNT RTC_REG(0)
++
++#define RSECCNT RTC_REG(1) /* RTC sec */
++#define RMINCNT RTC_REG(2) /* RTC min */
++#define RHRCNT RTC_REG(3) /* RTC hour */
++#define RWKCNT RTC_REG(4) /* RTC week */
++#define RDAYCNT RTC_REG(5) /* RTC day */
++#define RMONCNT RTC_REG(6) /* RTC month */
++#define RYRCNT RTC_REG(7) /* RTC year */
++#define RSECAR RTC_REG(8) /* ALARM sec */
++#define RMINAR RTC_REG(9) /* ALARM min */
++#define RHRAR RTC_REG(10) /* ALARM hour */
++#define RWKAR RTC_REG(11) /* ALARM week */
++#define RDAYAR RTC_REG(12) /* ALARM day */
++#define RMONAR RTC_REG(13) /* ALARM month */
++#define RCR1 RTC_REG(14) /* Control */
++#define RCR2 RTC_REG(15) /* Control */
++
++/*
++ * Note on RYRAR and RCR3: Up until this point most of the register
++ * definitions are consistent across all of the available parts. However,
++ * the placement of the optional RYRAR and RCR3 (the RYRAR control
++ * register used to control RYRCNT/RYRAR compare) varies considerably
++ * across various parts, occasionally being mapped in to a completely
++ * unrelated address space. For proper RYRAR support a separate resource
++ * would have to be handed off, but as this is purely optional in
++ * practice, we simply opt not to support it, thereby keeping the code
++ * quite a bit more simplified.
++ */
++
++/* ALARM Bits - or with BCD encoded value */
++#define AR_ENB 0x80 /* Enable for alarm cmp */
+
+ /* RCR1 Bits */
+ #define RCR1_CF 0x80 /* Carry Flag */
+@@ -71,39 +84,82 @@
+ unsigned int alarm_irq, periodic_irq, carry_irq;
+ 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 *id, struct pt_regs *regs)
++static irqreturn_t sh_rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+ {
+- struct platform_device *pdev = id;
++ struct platform_device *pdev = to_platform_device(dev_id);
+ struct sh_rtc *rtc = platform_get_drvdata(pdev);
+ unsigned int tmp, events = 0;
+
+ spin_lock(&rtc->lock);
+
+ tmp = readb(rtc->regbase + RCR1);
++ tmp &= ~RCR1_CF;
+
+- if (tmp & RCR1_AF)
+- events |= RTC_AF | RTC_IRQF;
+-
+- tmp &= ~(RCR1_CF | RCR1_AF);
++ if (rtc->rearm_aie) {
++ if (tmp & RCR1_AF)
++ tmp &= ~RCR1_AF; /* try to clear AF again */
++ else {
++ tmp |= RCR1_AIE; /* AF has cleared, rearm IRQ */
++ rtc->rearm_aie = 0;
++ }
++ }
+
+ writeb(tmp, rtc->regbase + RCR1);
+-
+- rtc_update_irq(&rtc->rtc_dev->class_dev, 1, events);
++
++ rtc_update_irq(rtc->rtc_dev, 1, events);
+
+ spin_unlock(&rtc->lock);
+
+ return IRQ_HANDLED;
+ }
+
+-static irqreturn_t sh_rtc_periodic(int irq, void *id, struct pt_regs *regs)
++static irqreturn_t sh_rtc_alarm(int irq, void *dev_id, struct pt_regs *regs)
++{
++ struct platform_device *pdev = to_platform_device(dev_id);
++ struct sh_rtc *rtc = platform_get_drvdata(pdev);
++ unsigned int tmp, events = 0;
++
++ spin_lock(&rtc->lock);
++
++ tmp = readb(rtc->regbase + RCR1);
++
++ /*
++ * If AF is set then the alarm has triggered. If we clear AF while
++ * the alarm time still matches the RTC time then AF will
++ * immediately be set again, and if AIE is enabled then the alarm
++ * interrupt will immediately be retrigger. So we clear AIE here
++ * and use rtc->rearm_aie so that the carry interrupt will keep
++ * trying to clear AF and once it stays cleared it'll re-enable
++ * AIE.
++ */
++ if (tmp & RCR1_AF) {
++ events |= RTC_AF | RTC_IRQF;
++
++ tmp &= ~(RCR1_AF|RCR1_AIE);
++
++ writeb(tmp, rtc->regbase + RCR1);
++
++ rtc->rearm_aie = 1;
++
++ rtc_update_irq(rtc->rtc_dev, 1, events);
++ }
++
++ spin_unlock(&rtc->lock);
++ return IRQ_HANDLED;
++}
++
++static irqreturn_t sh_rtc_periodic(int irq, void *dev_id, struct pt_regs *regs)
+ {
+- struct sh_rtc *rtc = dev_get_drvdata(id);
++ struct platform_device *pdev = to_platform_device(dev_id);
++ struct sh_rtc *rtc = platform_get_drvdata(pdev);
+
+ spin_lock(&rtc->lock);
+
+- rtc_update_irq(&rtc->rtc_dev->class_dev, 1, RTC_PF | RTC_IRQF);
++ rtc_update_irq(rtc->rtc_dev, 1, RTC_PF | RTC_IRQF);
+
+ spin_unlock(&rtc->lock);
+
+@@ -139,10 +195,11 @@
+
+ tmp = readb(rtc->regbase + RCR1);
+
+- if (enable)
+- tmp |= RCR1_AIE;
+- else
++ if (!enable) {
+ tmp &= ~RCR1_AIE;
++ rtc->rearm_aie = 0;
++ } else if (rtc->rearm_aie == 0)
++ tmp |= RCR1_AIE;
+
+ writeb(tmp, rtc->regbase + RCR1);
+
+@@ -177,14 +234,14 @@
+ goto err_bad_carry;
+ }
+
+- ret = request_irq(rtc->alarm_irq, sh_rtc_interrupt, SA_INTERRUPT,
++ ret = request_irq(rtc->alarm_irq, sh_rtc_alarm, SA_INTERRUPT,
+ "sh-rtc alarm", dev);
+ if (unlikely(ret)) {
+ dev_err(dev, "request alarm IRQ failed with %d, IRQ %d\n",
+ ret, rtc->alarm_irq);
+ goto err_bad_alarm;
+ }
+-
++
+ return 0;
+
+ err_bad_alarm:
+@@ -200,6 +257,7 @@
+ struct sh_rtc *rtc = dev_get_drvdata(dev);
+
+ sh_rtc_setpie(dev, 0);
++ sh_rtc_setaie(dev, 0);
+
+ free_irq(rtc->periodic_irq, dev);
+ free_irq(rtc->carry_irq, dev);
+@@ -212,8 +270,6 @@
+ unsigned int tmp;
+
+ tmp = readb(rtc->regbase + RCR1);
+- seq_printf(seq, "alarm_IRQ\t: %s\n",
+- (tmp & RCR1_AIE) ? "yes" : "no");
+ seq_printf(seq, "carry_IRQ\t: %s\n",
+ (tmp & RCR1_CIE) ? "yes" : "no");
+
+@@ -267,16 +323,16 @@
+ tm->tm_hour = BCD2BIN(readb(rtc->regbase + RHRCNT));
+ tm->tm_wday = BCD2BIN(readb(rtc->regbase + RWKCNT));
+ tm->tm_mday = BCD2BIN(readb(rtc->regbase + RDAYCNT));
+- tm->tm_mon = BCD2BIN(readb(rtc->regbase + RMONCNT));
++ 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;
+
+@@ -291,14 +347,16 @@
+ tm->tm_sec--;
+ #endif
+
+- dev_dbg(&dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
++ dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
+ "mday=%d, mon=%d, year=%d, wday=%d\n",
+ __FUNCTION__,
+ tm->tm_sec, tm->tm_min, tm->tm_hour,
+- tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
++ tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_wday);
+
+- if (rtc_valid_tm(tm) < 0)
++ if (rtc_valid_tm(tm) < 0) {
+ dev_err(dev, "invalid date\n");
++ rtc_time_to_tm(0, tm);
++ }
+
+ return 0;
+ }
+@@ -315,6 +373,7 @@
+ /* Reset pre-scaler & stop RTC */
+ tmp = readb(rtc->regbase + RCR2);
+ tmp |= RCR2_RESET;
++ tmp &= ~RCR2_START;
+ writeb(tmp, rtc->regbase + RCR2);
+
+ writeb(BIN2BCD(tm->tm_sec), rtc->regbase + RSECCNT);
+@@ -322,16 +381,16 @@
+ writeb(BIN2BCD(tm->tm_hour), rtc->regbase + RHRCNT);
+ writeb(BIN2BCD(tm->tm_wday), rtc->regbase + RWKCNT);
+ writeb(BIN2BCD(tm->tm_mday), rtc->regbase + RDAYCNT);
+- writeb(BIN2BCD(tm->tm_mon), rtc->regbase + RMONCNT);
++ 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);
+@@ -344,12 +403,140 @@
+ return 0;
+ }
+
++static inline int sh_rtc_read_alarm_value(struct sh_rtc *rtc, int reg_off)
++{
++ unsigned int byte;
++ int value = 0xff; /* return 0xff for ignored values */
++
++ byte = readb(rtc->regbase + reg_off);
++ if (byte & AR_ENB) {
++ byte &= ~AR_ENB; /* strip the enable bit */
++ value = BCD2BIN(byte);
++ }
++
++ return value;
++}
++
++static int sh_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
++{
++ struct platform_device *pdev = to_platform_device(dev);
++ struct sh_rtc *rtc = platform_get_drvdata(pdev);
++ struct rtc_time* tm = &wkalrm->time;
++
++ spin_lock_irq(&rtc->lock);
++
++ tm->tm_sec = sh_rtc_read_alarm_value(rtc, RSECAR);
++ tm->tm_min = sh_rtc_read_alarm_value(rtc, RMINAR);
++ tm->tm_hour = sh_rtc_read_alarm_value(rtc, RHRAR);
++ tm->tm_wday = sh_rtc_read_alarm_value(rtc, RWKAR);
++ tm->tm_mday = sh_rtc_read_alarm_value(rtc, RDAYAR);
++ tm->tm_mon = sh_rtc_read_alarm_value(rtc, RMONAR);
++ if (tm->tm_mon > 0)
++ tm->tm_mon -= 1; /* RTC is 1-12, tm_mon is 0-11 */
++ tm->tm_year = 0xffff;
++
++ wkalrm->enabled = (readb(rtc->regbase + RCR1) & RCR1_AIE) ? 1 : 0;
++
++ spin_unlock_irq(&rtc->lock);
++
++ return 0;
++}
++
++static inline void sh_rtc_write_alarm_value(struct sh_rtc *rtc,
++ int value, int reg_off)
++{
++ /* < 0 for a value that is ignored */
++ if (value < 0)
++ writeb(0, rtc->regbase + reg_off);
++ else
++ writeb(BIN2BCD(value) | AR_ENB, rtc->regbase + reg_off);
++}
++
++static int sh_rtc_check_alarm(struct rtc_time* tm)
++{
++ /*
++ * The original rtc says anything > 0xc0 is "don't care" or "match
++ * all" - most users use 0xff but rtc-dev uses -1 for the same thing.
++ * The original rtc doesn't support years - some things use -1 and
++ * some 0xffff. We use -1 to make out tests easier.
++ */
++ if (tm->tm_year == 0xffff)
++ tm->tm_year = -1;
++ if (tm->tm_mon >= 0xff)
++ tm->tm_mon = -1;
++ if (tm->tm_mday >= 0xff)
++ tm->tm_mday = -1;
++ if (tm->tm_wday >= 0xff)
++ tm->tm_wday = -1;
++ if (tm->tm_hour >= 0xff)
++ tm->tm_hour = -1;
++ if (tm->tm_min >= 0xff)
++ tm->tm_min = -1;
++ if (tm->tm_sec >= 0xff)
++ tm->tm_sec = -1;
++
++ if (tm->tm_year > 9999 ||
++ tm->tm_mon >= 12 ||
++ tm->tm_mday == 0 || tm->tm_mday >= 32 ||
++ tm->tm_wday >= 7 ||
++ tm->tm_hour >= 24 ||
++ tm->tm_min >= 60 ||
++ tm->tm_sec >= 60)
++ return -EINVAL;
++
++ return 0;
++}
++
++static int sh_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
++{
++ struct platform_device *pdev = to_platform_device(dev);
++ struct sh_rtc *rtc = platform_get_drvdata(pdev);
++ unsigned int rcr1;
++ struct rtc_time *tm = &wkalrm->time;
++ int mon, err;
++
++ err = sh_rtc_check_alarm(tm);
++ if (unlikely(err < 0))
++ return err;
++
++ spin_lock_irq(&rtc->lock);
++
++ /* disable alarm interrupt and clear the alarm flag */
++ rcr1 = readb(rtc->regbase + RCR1);
++ rcr1 &= ~(RCR1_AF|RCR1_AIE);
++ writeb(rcr1, rtc->regbase + RCR1);
++
++ rtc->rearm_aie = 0;
++
++ /* set alarm time */
++ sh_rtc_write_alarm_value(rtc, tm->tm_sec, RSECAR);
++ sh_rtc_write_alarm_value(rtc, tm->tm_min, RMINAR);
++ sh_rtc_write_alarm_value(rtc, tm->tm_hour, RHRAR);
++ sh_rtc_write_alarm_value(rtc, tm->tm_wday, RWKAR);
++ sh_rtc_write_alarm_value(rtc, tm->tm_mday, RDAYAR);
++ mon = tm->tm_mon;
++ if (mon >= 0)
++ mon += 1;
++ sh_rtc_write_alarm_value(rtc, mon, RMONAR);
++
++ if (wkalrm->enabled) {
++ rcr1 |= RCR1_AIE;
++ writeb(rcr1, rtc->regbase + RCR1);
++ }
++
++ spin_unlock_irq(&rtc->lock);
++
++ return 0;
++}
++
+ static struct rtc_class_ops sh_rtc_ops = {
+ .open = sh_rtc_open,
+ .release = sh_rtc_release,
+ .ioctl = sh_rtc_ioctl,
+ .read_time = sh_rtc_read_time,
+ .set_time = sh_rtc_set_time,
++ .read_alarm = sh_rtc_read_alarm,
++ .set_alarm = sh_rtc_set_alarm,
+ .proc = sh_rtc_proc,
+ };
+
+@@ -405,11 +592,22 @@
+
+ rtc->rtc_dev = rtc_device_register("sh", &pdev->dev,
+ &sh_rtc_ops, THIS_MODULE);
+- if (IS_ERR(rtc)) {
++ if (IS_ERR(rtc->rtc_dev)) {
+ ret = PTR_ERR(rtc->rtc_dev);
+ 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;
+@@ -425,7 +623,7 @@
+ static int __devexit sh_rtc_remove(struct platform_device *pdev)
+ {
+ struct sh_rtc *rtc = platform_get_drvdata(pdev);
+-
++
+ if (likely(rtc->rtc_dev))
+ rtc_device_unregister(rtc->rtc_dev);
+
+@@ -442,7 +640,7 @@
+ }
+ static struct platform_driver sh_rtc_platform_driver = {
+ .driver = {
+- .name = "sh-rtc",
++ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = sh_rtc_probe,
+@@ -463,5 +661,7 @@
+ module_exit(sh_rtc_exit);
+
+ MODULE_DESCRIPTION("SuperH on-chip RTC driver");
+-MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
++MODULE_VERSION(DRV_VERSION);
++MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>, Jamie Lenehan <lenehan@twibble.org>");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:" DRV_NAME);
+diff -ru linux-2.6.17.old/include/asm-sh/cpu-sh3/rtc.h linux-2.6.17/include/asm-sh/cpu-sh3/rtc.h
+--- linux-2.6.17.old/include/asm-sh/cpu-sh3/rtc.h 2006-06-18 04:49:35.000000000 +0300
++++ linux-2.6.17/include/asm-sh/cpu-sh3/rtc.h 2009-12-21 10:30:05.923092336 +0200
+@@ -20,6 +20,8 @@
+ #define RCR2 0xfffffede
+
+ #define RTC_BIT_INVERTED 0 /* No bug on SH7708, SH7709A */
++#define RTC_DEF_CAPABILITIES 0UL
++#define rtc_reg_size sizeof(u16)
+
+ #endif /* __ASM_CPU_SH3_RTC_H */
+
+diff -ru linux-2.6.17.old/include/asm-sh/hw_irq.h linux-2.6.17/include/asm-sh/hw_irq.h
+--- linux-2.6.17.old/include/asm-sh/hw_irq.h 2006-06-18 04:49:35.000000000 +0300
++++ linux-2.6.17/include/asm-sh/hw_irq.h 2009-12-21 10:29:58.716840103 +0200
+@@ -1,6 +1,111 @@
+ #ifndef __ASM_SH_HW_IRQ_H
+ #define __ASM_SH_HW_IRQ_H
+
++#include <linux/init.h>
++#include <asm/atomic.h>
++
++extern atomic_t irq_err_count;
++
++/*
++struct ipr_data {
++ unsigned char irq;
++ unsigned char ipr_idx;*/ /* Index for the IPR registered */
++/*
++ unsigned char shift; */ /* Number of bits to shift the data */
++/*
++ unsigned char priority; *//* The priority */
++/* };*/
++
++/*
++struct ipr_desc {
++ unsigned long *ipr_offsets;
++ unsigned int nr_offsets;
++ struct ipr_data *ipr_data;
++ unsigned int nr_irqs;
++ struct irq_chip chip;
++};
++
++void register_ipr_controller(struct ipr_desc *);
++*/
++
++typedef unsigned char intc_enum;
++
++struct intc_vect {
++ intc_enum enum_id;
++ unsigned short vect;
++};
++
++#define INTC_VECT(enum_id, vect) { enum_id, vect }
++#define INTC_IRQ(enum_id, irq) INTC_VECT(enum_id, irq2evt(irq))
++
++struct intc_group {
++ intc_enum enum_id;
++ intc_enum enum_ids[32];
++};
++
++#define INTC_GROUP(enum_id, ids...) { enum_id, { ids } }
++
++struct intc_mask_reg {
++ unsigned long set_reg, clr_reg, reg_width;
++ intc_enum enum_ids[32];
++#ifdef CONFIG_SMP
++ unsigned long smp;
++#endif
++};
++
++struct intc_prio_reg {
++ unsigned long set_reg, clr_reg, reg_width, field_width;
++ intc_enum enum_ids[16];
++#ifdef CONFIG_SMP
++ unsigned long smp;
++#endif
++};
++
++struct intc_sense_reg {
++ unsigned long reg, reg_width, field_width;
++ intc_enum enum_ids[16];
++};
++
++#ifdef CONFIG_SMP
++#define INTC_SMP(stride, nr) .smp = (stride) | ((nr) << 8)
++#else
++#define INTC_SMP(stride, nr)
++#endif
++
++struct intc_desc {
++ struct intc_vect *vectors;
++ unsigned int nr_vectors;
++ struct intc_group *groups;
++ unsigned int nr_groups;
++ struct intc_mask_reg *mask_regs;
++ unsigned int nr_mask_regs;
++ struct intc_prio_reg *prio_regs;
++ unsigned int nr_prio_regs;
++ struct intc_sense_reg *sense_regs;
++ unsigned int nr_sense_regs;
++ char *name;
++};
++
++#define _INTC_ARRAY(a) a, sizeof(a)/sizeof(*a)
++#define DECLARE_INTC_DESC(symbol, chipname, vectors, groups, \
++ mask_regs, prio_regs, sense_regs) \
++struct intc_desc symbol __initdata = { \
++ _INTC_ARRAY(vectors), _INTC_ARRAY(groups), \
++ _INTC_ARRAY(mask_regs), _INTC_ARRAY(prio_regs), \
++ _INTC_ARRAY(sense_regs), \
++ chipname, \
++}
++
++void __init register_intc_controller(struct intc_desc *desc);
++int intc_set_priority(unsigned int irq, unsigned int prio);
++
++void __init plat_irq_setup(void);
++
++enum { IRQ_MODE_IRQ, IRQ_MODE_IRQ7654, IRQ_MODE_IRQ3210,
++ IRQ_MODE_IRL7654_MASK, IRQ_MODE_IRL3210_MASK,
++ IRQ_MODE_IRL7654, IRQ_MODE_IRL3210 };
++void __init plat_irq_setup_pins(int mode);
++
+ static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i)
+ {
+ /* Nothing to do */
+diff -ru linux-2.6.17.old/include/asm-sh/rtc.h linux-2.6.17/include/asm-sh/rtc.h
+--- linux-2.6.17.old/include/asm-sh/rtc.h 2009-12-21 10:27:23.566444610 +0200
++++ linux-2.6.17/include/asm-sh/rtc.h 2009-12-21 10:29:58.716840103 +0200
+@@ -25,5 +25,7 @@
+ #define RCR2_RESET 0x02 /* Reset bit */
+ #define RCR2_START 0x01 /* Start bit */
+
++#define RTC_CAP_4_DIGIT_YEAR (1 << 0)
++
+ #endif /* __KERNEL__ */
+ #endif /* _ASM_RTC_H */
+diff -ru linux-2.6.17.old/include/linux/rtc.h linux-2.6.17/include/linux/rtc.h
+--- linux-2.6.17.old/include/linux/rtc.h 2006-06-18 04:49:35.000000000 +0300
++++ linux-2.6.17/include/linux/rtc.h 2009-12-21 10:29:58.716840103 +0200
+@@ -172,7 +172,8 @@
+ struct rtc_wkalrm *alrm);
+ extern int rtc_set_alarm(struct class_device *class_dev,
+ struct rtc_wkalrm *alrm);
+-extern void rtc_update_irq(struct class_device *class_dev,
++
++extern void rtc_update_irq(struct rtc_device *rtc,
+ unsigned long num, unsigned long events);
+
+ extern struct class_device *rtc_class_open(char *name);
+diff -ru linux-2.6.17.old/include/linux/serial_sci.h linux-2.6.17/include/linux/serial_sci.h
+--- linux-2.6.17.old/include/linux/serial_sci.h 2009-12-21 10:33:00.536412963 +0200
++++ linux-2.6.17/include/linux/serial_sci.h 2009-12-21 10:29:58.716840103 +0200
+@@ -0,0 +1,32 @@
++#ifndef __LINUX_SERIAL_SCI_H
++#define __LINUX_SERIAL_SCI_H
++
++#include <linux/serial_core.h>
++
++/*
++ * Generic header for SuperH SCI(F) (used by sh/sh64/h8300 and related parts)
++ */
++
++/* Offsets into the sci_port->irqs array */
++enum {
++ SCIx_ERI_IRQ,
++ SCIx_RXI_IRQ,
++ SCIx_TXI_IRQ,
++ SCIx_BRI_IRQ,
++ SCIx_NR_IRQS,
++};
++
++/*
++ * Platform device specific platform_data struct
++ */
++struct plat_sci_port {
++ void __iomem *membase; /* io cookie */
++ unsigned long mapbase; /* resource base */
++ unsigned int irqs[SCIx_NR_IRQS]; /* ERI, RXI, TXI, BRI */
++ unsigned int type; /* SCI / SCIF / IRDA */
++ upf_t flags; /* UPF_* flags */
++};
++
++int early_sci_setup(struct uart_port *port);
++
++#endif /* __LINUX_SERIAL_SCI_H */