updated RTC patches for alphas

a sun (asun@zoology.washington.edu)
Fri, 24 Jan 1997 18:09:57 -0800 (PST)


following is an updated patch for rtc support on alphas. it does a
couple things differently now:
1) if CONFIG_RTC=n, it will report the rtc as the "timer" in
/proc/interrupts and /proc/ioports

2) it now asks if you want to use the ARC-based starting epoch
in a config question.

if this does the right thing on all alphas, how do people feel about
always using the interval timer on the alpha?

apply to 2.1.22 with patch -p1 (should work on earlier versions as
well):

--- linux/include/linux/timex.h.save Thu Jan 9 01:37:10 1997
+++ linux/include/linux/timex.h Sun Jan 19 01:47:57 1997
@@ -17,6 +17,9 @@
/*
* Modification history timex.h
*
+ * 9 Jan 97 Adrian Sun
+ * Shifted LATCH define to allow access to alpha machines.
+ *
* 26 Sep 94 David L. Mills
* Added defines for hybrid phase/frequency-lock loop.
*
@@ -122,15 +125,17 @@
#define PPS_VALID 120 /* pps signal watchdog max (s) */
#define MAXGLITCH 30 /* pps signal glitch max (s) */

+/* LATCH is used in the interval timer and ftape setup. based on the RTC,
+ * CLOCK_TICK_RATE results in ~1050HZ instead of 1024HZ on the alpha. */
+#define CLOCK_TICK_RATE 1193180 /* Underlying HZ */
+#define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ) /* For divider */
+
#ifndef __alpha__
/*
* This definitively is wrong for the Alpha and none of the
* kernel code seems to reference this anymore.
*/
-#define CLOCK_TICK_RATE 1193180 /* Underlying HZ */
#define CLOCK_TICK_FACTOR 20 /* Factor of both 1000000 and CLOCK_TICK_RATE */
-#define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ) /* For divider */
-
#define FINETUNE ((((((long)LATCH * HZ - CLOCK_TICK_RATE) << SHIFT_HZ) * \
(1000000/CLOCK_TICK_FACTOR) / (CLOCK_TICK_RATE/CLOCK_TICK_FACTOR)) \
<< (SHIFT_SCALE-SHIFT_HZ)) / HZ)
--- linux/drivers/char/rtc.c.save Mon Dec 23 23:56:42 1996
+++ linux/drivers/char/rtc.c Thu Jan 23 21:44:09 1997
@@ -55,6 +55,13 @@
#include <asm/uaccess.h>
#include <asm/system.h>

+/* Adjust starting epoch if ARC console time is being used */
+#ifdef CONFIG_RTC_ARC
+#define ARCFUDGE 20
+#else
+#define ARCFUDGE 0
+#endif
+
/*
* We sponge a minor off of the misc major. No need slurping
* up another valuable major dev number for this. If you add
@@ -336,7 +343,7 @@

copy_from_user(&rtc_tm, (struct rtc_time*)arg, sizeof(struct rtc_time));

- yrs = rtc_tm.tm_year + 1900;
+ yrs = rtc_tm.tm_year + 1900 + ARCFUDGE;
mon = rtc_tm.tm_mon + 1; /* tm_mon starts at zero */
day = rtc_tm.tm_mday;
hrs = rtc_tm.tm_hour;
@@ -726,6 +733,9 @@
*/
if (rtc_tm->tm_year <= 69)
rtc_tm->tm_year += 100;
+
+ /* if ARCFUDGE == 0, the optimizer should do away with this */
+ rtc_tm->tm_year -= ARCFUDGE;

rtc_tm->tm_mon--;
}
--- linux/arch/alpha/kernel/irq.c.save Thu Nov 21 22:19:35 1996
+++ linux/arch/alpha/kernel/irq.c Thu Jan 23 21:44:49 1997
@@ -26,7 +26,12 @@
#include <asm/bitops.h>
#include <asm/dma.h>

-extern void timer_interrupt(struct pt_regs * regs);
+#define RTC_IRQ 8
+#ifdef CONFIG_RTC
+#define TIMER_IRQ 0 /* timer is the pit */
+#else
+#define TIMER_IRQ RTC_IRQ /* the timer is, in fact, the rtc */
+#endif

#if NR_IRQS > 64
# error Unable to handle more than 64 irq levels.
@@ -133,6 +138,7 @@
/*
* Initial irq handlers.
*/
+static struct irqaction timer_irq = { NULL, 0, 0, NULL, NULL, NULL};
static struct irqaction *irq_action[NR_IRQS];

int get_irq_list(char *buf)
@@ -144,7 +150,7 @@
action = irq_action[i];
if (!action)
continue;
- len += sprintf(buf+len, "%2d: %8d %c %s",
+ len += sprintf(buf+len, "%2d: %10u %c %s",
i, kstat.interrupts[i],
(action->flags & SA_INTERRUPT) ? '+' : ' ',
action->name);
@@ -212,7 +218,10 @@
shared = 1;
}

- action = (struct irqaction *)kmalloc(sizeof(struct irqaction),
+ if (irq == TIMER_IRQ)
+ action = &timer_irq;
+ else
+ action = (struct irqaction *)kmalloc(sizeof(struct irqaction),
GFP_KERNEL);
if (!action)
return -ENOMEM;
@@ -646,7 +655,9 @@
{
int i;

- irqs &= irq_mask & ~1; /* always mask out irq 0---it's the unused timer */
+ /* as irq 0 & 8 handling don't use this function, i didn't
+ * bother changing the following: */
+ irqs &= irq_mask & ~1; /* always mask out irq 0---it's the unused timer */
#ifdef CONFIG_ALPHA_P2K
irqs &= ~(1 << 8); /* mask out irq 8 since that's the unused RTC input to PIC */
#endif
@@ -686,7 +697,7 @@
printk("Interprocessor interrupt? You must be kidding\n");
break;
case 1:
- timer_interrupt(&regs);
+ handle_irq(RTC_IRQ, &regs);
return;
case 2:
machine_check(vector, la_ptr, &regs);
--- linux/arch/alpha/kernel/time.c.save Wed Jan 8 23:56:02 1997
+++ linux/arch/alpha/kernel/time.c Thu Jan 23 21:31:46 1997
@@ -10,6 +10,8 @@
* 1995-03-26 Markus Kuhn
* fixed 500 ms bug at call to set_rtc_mmss, fixed DS12887
* precision CMOS clock update
+ * 1997-01-09 Adrian Sun
+ * use interval timer if CONFIG_RTC=y
*/
#include <linux/errno.h>
#include <linux/sched.h>
@@ -25,7 +27,11 @@
#include <linux/mc146818rtc.h>
#include <linux/timex.h>

-#define TIMER_IRQ 0
+#ifdef CONFIG_RTC
+#define TIMER_IRQ 0 /* using pit for timer */
+#else
+#define TIMER_IRQ 8 /* using rtc for timer */
+#endif

extern struct hwrpb_struct *hwrpb;

@@ -61,7 +67,7 @@
* timer_interrupt() needs to keep up the real-time clock,
* as well as call the "do_timer()" routine every clocktick
*/
-void timer_interrupt(struct pt_regs * regs)
+void timer_interrupt(int irq, void *dev, struct pt_regs * regs)
{
__u32 delta, now;

@@ -125,6 +131,10 @@

void time_init(void)
{
+#ifdef CONFIG_RTC
+ unsigned char save_control;
+#endif
+ void (*irq_handler)(int, void *, struct pt_regs *);
unsigned int year, mon, day, hour, min, sec;
int i;

@@ -178,6 +188,21 @@
state.scaled_ticks_per_cycle = ((unsigned long) HZ << FIX_SHIFT) / hwrpb->cycle_freq;
state.max_cycles_per_tick = (2 * hwrpb->cycle_freq) / HZ;
state.last_rtc_update = 0;
+
+#ifdef CONFIG_RTC
+ /* turn off RTC interrupts before /dev/rtc is initialized */
+ save_control = CMOS_READ(RTC_CONTROL);
+ save_control &= ~RTC_PIE;
+ save_control &= ~RTC_AIE;
+ save_control &= ~RTC_UIE;
+ CMOS_WRITE(save_control, RTC_CONTROL);
+ CMOS_READ(RTC_INTR_FLAGS);
+#endif
+
+ /* setup timer */
+ irq_handler = timer_interrupt;
+ if (request_irq(TIMER_IRQ, irq_handler, 0, "timer", NULL))
+ panic("Could not allocate timer IRQ!");
}

/*
--- linux/arch/alpha/kernel/process.c.save Sun Jan 12 01:09:58 1997
+++ linux/arch/alpha/kernel/process.c Sun Jan 12 18:17:42 1997
@@ -26,6 +26,10 @@
#include <linux/mman.h>
#include <linux/elfcore.h>

+#ifdef CONFIG_RTC
+#include <linux/mc146818rtc.h>
+#endif
+
#include <asm/reg.h>
#include <asm/uaccess.h>
#include <asm/system.h>
@@ -53,6 +57,24 @@

void hard_reset_now(void)
{
+#ifdef CONFIG_RTC /* reset rtc to defaults */
+ unsigned char control;
+ unsigned long flags;
+
+ /* i'm not sure if i really need to disable interrupts here */
+ save_flags(flags);
+ cli();
+ /* reset periodic interrupt frequency */
+ CMOS_WRITE(0x26, RTC_FREQ_SELECT);
+
+ /* turn on periodic interrupts */
+ control = CMOS_READ(RTC_CONTROL);
+ control |= RTC_PIE;
+ CMOS_WRITE(control, RTC_CONTROL);
+ CMOS_READ(RTC_INTR_FLAGS);
+ restore_flags(flags);
+#endif
+
#if defined(CONFIG_ALPHA_SRM) && defined(CONFIG_ALPHA_ALCOR)
/* who said DEC engineer's have no sense of humor? ;-)) */
*(int *) GRU_RESET = 0x0000dead;
--- linux/arch/alpha/kernel/setup.c.save Thu Jan 9 09:24:55 1997
+++ linux/arch/alpha/kernel/setup.c Thu Jan 23 21:37:58 1997
@@ -22,6 +22,11 @@
#include <linux/delay.h>
#include <linux/config.h> /* CONFIG_ALPHA_LCA etc */

+#ifdef CONFIG_RTC
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#endif
+
#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include <asm/system.h>
@@ -83,9 +88,17 @@
outb(0x18, 0x41);
#endif

+#ifdef CONFIG_RTC /* setup interval timer if /dev/rtc is being used */
+ outb(0x34, 0x43); /* binary, mode 2, LSB/MSB, ch 0 */
+ outb(LATCH & 0xff, 0x40); /* LSB */
+ outb(LATCH >> 8, 0x40); /* MSB */
+ request_region(0x40, 0x20, "timer"); /* reserve pit */
+#else
outb(0x36, 0x43); /* counter 0: system timer */
outb(0x00, 0x40);
outb(0x00, 0x40);
+ request_region(0x70, 0x10, "timer"); /* reserve rtc */
+#endif

outb(0xb6, 0x43); /* counter 2: speaker */
outb(0x31, 0x42);
--- linux/arch/alpha/config.in.save Sat Jan 18 15:19:36 1997
+++ linux/arch/alpha/config.in Sat Jan 18 15:35:37 1997
@@ -144,6 +144,9 @@
source fs/Config.in

source drivers/char/Config.in
+if [ "$CONFIG_RTC" != "n" ]; then
+ bool ' ARC console time' CONFIG_RTC_ARC
+fi

mainmenu_option next_comment
comment 'Sound'
--- linux/arch/alpha/defconfig.save Thu Jan 23 21:17:22 1997
+++ linux/arch/alpha/defconfig Thu Jan 23 21:14:25 1997
@@ -222,6 +222,7 @@
# CONFIG_APM is not set
# CONFIG_WATCHDOG is not set
# CONFIG_RTC is not set
+CONFIG_RTC_ARC=y

#
# Sound
--- linux/Documentation/Configure.help.save Thu Jan 23 21:48:26 1997
+++ linux/Documentation/Configure.help Thu Jan 23 21:14:24 1997
@@ -3840,6 +3840,12 @@
(such as periodic data sampling), then say Y here, and go read the
file Documentation/rtc.txt for details.

+ARC console time
+CONFIG_RTC_ARC
+ If you boot your Alpha using the ARC firmware, say Y here. This option
+ adjusts the RTC clock to take into account the different starting epoch
+ used by ARC.
+
Sound card support
CONFIG_SOUND
If you have a Sound Card in your Computer, i.e. if it can say more