diff options
Diffstat (limited to 'recipes-kernel/linux/linux-jlime-jornada6xx-2.6.17/rtc-2.6.17.patch')
-rw-r--r-- | recipes-kernel/linux/linux-jlime-jornada6xx-2.6.17/rtc-2.6.17.patch | 987 |
1 files changed, 987 insertions, 0 deletions
diff --git a/recipes-kernel/linux/linux-jlime-jornada6xx-2.6.17/rtc-2.6.17.patch b/recipes-kernel/linux/linux-jlime-jornada6xx-2.6.17/rtc-2.6.17.patch new file mode 100644 index 0000000..a744c26 --- /dev/null +++ b/recipes-kernel/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 */ |