From: <gn...@ch...> - 2000-05-02 11:28:34
|
Hello all, I'm hacking for supporting SolutionEngine. Actually, hacking part has already been done by Kaz and Takashi Yoshii. Now is the time of integration. Integrating interrupt handling of SolutionEngine, I've noticed that almost all of the code is SAME between on-chip support, on-chip2 support by Takashi, and SolutionEngine. So, I've replaced on-chip support into generalized one called "IPR (Interrupt Priority Register) based IRQ" support. Then, supporting SolutionEngine with this scheme. I'll commit this tomorrow. Next comes setup routine of SolutionEngine. Thanks Kaz for the implementation and discussion. I'd like to listen your comment. And Takeshi, As I added the comment, I think that initializing all of INTC registers is not relevant. I think that it's the job of boot loader, and wanna remove the code from the kernel. How do you think? -------------------------- 2000-05-02 NIIBE Yutaka <gn...@ch...> * arch/sh/mm/fault.c (do_page_fault): Bug fix. When "Oops", we don't try to follow the page handling data when PGDIR==0. * arch/sh/kernel/Makefile (O_OBJS): Added irq_ipr.o, removing irq_onchip.c. Added irq_se.c. * arch/sh/kernel/irq_se.c: New file for SolutionEngine support. * arch/sh/kernel/time.c (time_init): Removed IPR setting. * arch/sh/kernel/irq_ipr.c (init_IRQ): ... moved to here. * drivers/char/sh-sci.c (sci_init): Use new calling of set_ipr_data. * drivers/char/sh-sci.h (SCI_IPR_POS, SCI_IPR_ADDR): New macros. (SCI_IPR_OFFSET): Removed. * arch/sh/kernel/irq_ipr.c (startup_ipr_irq, ipr_irq_type, disable_ipr_irq, enable_ipr_irq, make_ipr_irq, mask_and_ack_ipr, end_ipr_irq): Renamed from *_onChip_*. (struct ipr_data): Added member POS. Remove OFFSET, and added ADDR. (startup_onChip2_irq, onChip2_irq_type, disable_onChip2_irq, enable_onChip2_irq, mask_and_ack_onChip2, end_onChip2_irq): Removed. * include/asm-sh/irq.h (make_ipr_irq): Renamed from make_onChip_irq. (set_ipr_data): Change the prototype for address. * arch/sh/kernel/irq_ipr.c: Renamed from irq_onchip.c. Index: arch/sh/config.in =================================================================== RCS file: /cvsroot/linuxsh/kernel/arch/sh/config.in,v retrieving revision 1.3 diff -u -r1.3 config.in --- arch/sh/config.in 2000/04/14 17:56:34 1.3 +++ arch/sh/config.in 2000/05/02 10:56:42 @@ -15,6 +15,10 @@ mainmenu_option next_comment comment 'Processor type and features' +choice 'SuperH system type' \ + "Generic CONFIG_SH_GENERIC \ + SolutionEngine CONFIG_SH_SOLUTION_ENGINE" Generic + choice 'Processor type' \ "SH7708 CONFIG_CPU_SUBTYPE_SH7708 \ SH7709 CONFIG_CPU_SUBTYPE_SH7709 \ Index: arch/sh/kernel/Makefile =================================================================== RCS file: /cvsroot/linuxsh/kernel/arch/sh/kernel/Makefile,v retrieving revision 1.2 diff -u -r1.2 Makefile --- arch/sh/kernel/Makefile 2000/04/14 19:14:01 1.2 +++ arch/sh/kernel/Makefile 2000/05/02 10:56:42 @@ -10,7 +10,7 @@ $(CC) $(AFLAGS) -traditional -c $< -o $*.o O_TARGET := kernel.o -O_OBJS := process.o signal.o entry.o traps.o irq.o irq_onchip.o \ +O_OBJS := process.o signal.o entry.o traps.o irq.o irq_ipr.o \ ptrace.o setup.o time.o sys_sh.o semaphore.o pci-sh.o \ irq_imask.o OX_OBJS := sh_ksyms.o @@ -18,6 +18,10 @@ ifdef CONFIG_CF_ENABLER O_OBJS += cf-enabler.o +endif + +ifdef CONFIG_SH_SOLUTION_ENGINE +O_OBJS += irq_se.o endif ifdef CONFIG_CPU_SH4 Index: arch/sh/kernel/irq_ipr.c =================================================================== RCS file: irq_ipr.c diff -N irq_ipr.c --- /dev/null Tue May 5 13:32:27 1998 +++ irq_ipr.c Tue May 2 03:56:42 2000 @@ -0,0 +1,167 @@ +/* $Id$ + * + * linux/arch/sh/kernel/irq_ipr.c + * + * Copyright (C) 1999 Niibe Yutaka & Takeshi Yaegashi + * Copyright (C) 2000 Kazumoto Kojima + * + * Interrupt handling for IPR-based IRQ. + * + * Supported system: + * On-chip supporting modules (TMU, RTC, etc.). + * On-chip supporting modules for SH7709/SH7709A/SH7729. + * Hitachi SolutionEngine external I/O: + * MS7709SE01, MS7709ASE01, and MS7750SE01 + * + */ + +#include <linux/config.h> +#include <linux/init.h> +#include <linux/irq.h> + +#include <asm/system.h> +#include <asm/io.h> + +struct ipr_data { + unsigned int addr; /* Address of Interrupt Priority Register */ + int shift; /* Shifts of the 16-bit data */ + int priority; /* The priority */ +}; +static struct ipr_data ipr_data[NR_IRQS]; + +void set_ipr_data(unsigned int irq, unsigned int addr, int pos, int priority) +{ + ipr_data[irq].addr = addr; + ipr_data[irq].shift = pos*4; /* POSition (0-3) x 4 means shift */ + ipr_data[irq].priority = priority; +} + +static void enable_ipr_irq(unsigned int irq); +void disable_ipr_irq(unsigned int irq); + +/* shutdown is same as "disable" */ +#define shutdown_ipr_irq disable_ipr_irq + +static void mask_and_ack_ipr(unsigned int); +static void end_ipr_irq(unsigned int irq); + +static unsigned int startup_ipr_irq(unsigned int irq) +{ + enable_ipr_irq(irq); + return 0; /* never anything pending */ +} + +static struct hw_interrupt_type ipr_irq_type = { + "IPR-based-IRQ", + startup_ipr_irq, + shutdown_ipr_irq, + enable_ipr_irq, + disable_ipr_irq, + mask_and_ack_ipr, + end_ipr_irq +}; + +void disable_ipr_irq(unsigned int irq) +{ + unsigned long val, flags; + unsigned int addr = ipr_data[irq].addr; + unsigned short mask = 0xffff ^ (0x0f << ipr_data[irq].shift); + + /* Set the priority in IPR to 0 */ + save_and_cli(flags); + val = ctrl_inw(addr); + val &= mask; + ctrl_outw(val, addr); + restore_flags(flags); +} + +static void enable_ipr_irq(unsigned int irq) +{ + unsigned long val, flags; + unsigned int addr = ipr_data[irq].addr; + int priority = ipr_data[irq].priority; + unsigned short value = (priority << ipr_data[irq].shift); + + /* Set priority in IPR back to original value */ + save_and_cli(flags); + val = ctrl_inw(addr); + val |= value; + ctrl_outw(val, addr); + restore_flags(flags); +} + +void make_ipr_irq(unsigned int irq) +{ + disable_irq_nosync(irq); + irq_desc[irq].handler = &ipr_irq_type; + enable_irq(irq); +} + +static void mask_and_ack_ipr(unsigned int irq) +{ + disable_ipr_irq(irq); + + /* This is needed when we use edge triggered setting */ + /* XXX: Is it really needed? */ + if (IRQ0_IRQ <= irq && irq <= IRQ5_IRQ) { + /* Clear external interrupt request */ + int a = ctrl_inb(INTC_IRR0); + a &= ~(1 << (irq - IRQ0_IRQ)); + ctrl_outb(a, INTC_IRR0); + } +} + +static void end_ipr_irq(unsigned int irq) +{ + enable_ipr_irq(irq); +} + +void __init init_IRQ(void) +{ + int i; + + for (i = TIMER_IRQ; i < NR_IRQS; i++) { + irq_desc[i].handler = &ipr_irq_type; + } + + set_ipr_data(TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY); + set_ipr_data(RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY); + +#ifdef CONFIG_CPU_SUBTYPE_SH7709 + /* + * Initialize the Interrupt Controller (INTC) + * registers to their power on values + */ + /* + * XXX: I think that this is the job of boot loader. -- gniibe + * + * When Takeshi released new boot loader following setting + * will be removed shortly. + */ + ctrl_outb(0, INTC_IRR0); + ctrl_outb(0, INTC_IRR1); + ctrl_outb(0, INTC_IRR2); + + ctrl_outw(0, INTC_ICR0); + ctrl_outw(0, INTC_ICR1); + ctrl_outw(0, INTC_ICR2); + ctrl_outw(0, INTC_INTER); + ctrl_outw(0, INTC_IPRA); + ctrl_outw(0, INTC_IPRB); + ctrl_outw(0, INTC_IPRC); + ctrl_outw(0, INTC_IPRD); + ctrl_outw(0, INTC_IPRE); + + /* + * Enable external irq (INTC IRQ mode). + * You should set corresponding bits of PFC to "00" + * to enable these interrupts. + */ + set_ipr_data(IRQ0_IRQ, IRQ0_IRP_ADDR, IRQ0_IRP_POS, IRQ0_PRIORITY); + set_ipr_data(IRQ1_IRQ, IRQ1_IRP_ADDR, IRQ1_IRP_POS, IRQ1_PRIORITY); + set_ipr_data(IRQ2_IRQ, IRQ2_IRP_ADDR, IRQ2_IRP_POS, IRQ2_PRIORITY); + set_ipr_data(IRQ3_IRQ, IRQ3_IRP_ADDR, IRQ3_IRP_POS, IRQ3_PRIORITY); + set_ipr_data(IRQ4_IRQ, IRQ4_IRP_ADDR, IRQ4_IRP_POS, IRQ4_PRIORITY); + set_ipr_data(IRQ5_IRQ, IRQ5_IRP_ADDR, IRQ5_IRP_POS, IRQ5_PRIORITY); +#endif /* CONFIG_CPU_SUBTYPE_SH7709 */ +} Index: arch/sh/kernel/irq_onchip.c =================================================================== RCS file: irq_onchip.c diff -N irq_onchip.c --- /tmp/cvsLlt0mr Tue May 2 03:57:16 2000 +++ /dev/null Tue May 5 13:32:27 1998 @@ -1,298 +0,0 @@ -/* $Id: irq_onchip.c,v 1.3 2000/04/28 17:58:50 mjd Exp $ - * - * linux/arch/sh/kernel/irq_onchip.c - * - * Copyright (C) 1999 Niibe Yutaka & Takeshi Yaegashi - * - * Interrupt handling for on-chip supporting modules (TMU, RTC, etc.). - * - */ - -#include <linux/config.h> -#include <linux/ptrace.h> -#include <linux/errno.h> -#include <linux/kernel_stat.h> -#include <linux/signal.h> -#include <linux/sched.h> -#include <linux/ioport.h> -#include <linux/interrupt.h> -#include <linux/timex.h> -#include <linux/malloc.h> -#include <linux/random.h> -#include <linux/smp.h> -#include <linux/smp_lock.h> -#include <linux/init.h> - -#include <asm/system.h> -#include <asm/io.h> -#include <asm/irq.h> -#include <asm/bitops.h> -#include <asm/smp.h> -#include <asm/pgtable.h> -#include <asm/delay.h> - -#include <linux/irq.h> - -struct ipr_data { - int offset; - int priority; -}; -static struct ipr_data ipr_data[NR_IRQS-TIMER_IRQ]; - -void set_ipr_data(unsigned int irq, int offset, int priority) -{ - ipr_data[irq-TIMER_IRQ].offset = offset; - ipr_data[irq-TIMER_IRQ].priority = priority; -} - -static void enable_onChip_irq(unsigned int irq); -void disable_onChip_irq(unsigned int irq); - -/* shutdown is same as "disable" */ -#define shutdown_onChip_irq disable_onChip_irq - -static void mask_and_ack_onChip(unsigned int); -static void end_onChip_irq(unsigned int irq); - -static unsigned int startup_onChip_irq(unsigned int irq) -{ - enable_onChip_irq(irq); - return 0; /* never anything pending */ -} - -static struct hw_interrupt_type onChip_irq_type = { - "On-Chip-IPR", - startup_onChip_irq, - shutdown_onChip_irq, - enable_onChip_irq, - disable_onChip_irq, - mask_and_ack_onChip, - end_onChip_irq -}; - -/* - * These have to be protected by the irq controller spinlock - * before being called. - * - * - * IPRA 15-12 11-8 7-4 3-0 - * IPRB 15-12 11-8 7-4 3-0 - * IPRC 15-12 11-8 7-4 3-0 - * - */ -#if defined(__sh3__) -#define INTC_IPR 0xfffffee2UL /* Word access */ -#define INTC_SIZE 0x2 -#elif defined(__SH4__) -#define INTC_IPR 0xffd00004UL /* Word access */ -#define INTC_SIZE 0x4 -#endif - -void disable_onChip_irq(unsigned int irq) -{ - unsigned long val, flags; - /* Set priority in IPR to 0 */ - int offset = ipr_data[irq-TIMER_IRQ].offset; - unsigned long intc_ipr_address = INTC_IPR + (offset/16*INTC_SIZE); - unsigned short mask = 0xffff ^ (0xf << (offset%16)); - - save_and_cli(flags); - val = ctrl_inw(intc_ipr_address); - val &= mask; - ctrl_outw(val, intc_ipr_address); - restore_flags(flags); -} - -static void enable_onChip_irq(unsigned int irq) -{ - unsigned long val, flags; - /* Set priority in IPR back to original value */ - int offset = ipr_data[irq-TIMER_IRQ].offset; - int priority = ipr_data[irq-TIMER_IRQ].priority; - unsigned long intc_ipr_address = INTC_IPR + (offset/16*INTC_SIZE); - unsigned short value = (priority << (offset%16)); - - save_and_cli(flags); - val = ctrl_inw(intc_ipr_address); - val |= value; - ctrl_outw(val, intc_ipr_address); - restore_flags(flags); -} - -void make_onChip_irq(unsigned int irq) -{ - disable_irq_nosync(irq); - irq_desc[irq].handler = &onChip_irq_type; - enable_irq(irq); -} - -static void mask_and_ack_onChip(unsigned int irq) -{ - disable_onChip_irq(irq); -} - -static void end_onChip_irq(unsigned int irq) -{ - enable_onChip_irq(irq); -} - - -#ifdef CONFIG_CPU_SUBTYPE_SH7709 -/* - * SH7707/SH7709/SH7709A/SH7729 Extended on-chip I/O - */ - -#define INTC_IRR0 0xa4000004UL -#define INTC_IRR1 0xa4000006UL -#define INTC_IRR2 0xa4000008UL - -#define INTC_ICR0 0xfffffee0 -#define INTC_ICR1 0xa4000010 -#define INTC_ICR2 0xa4000012 -#define INTC_INTER 0xa4000014 -#define INTC_IPRA 0xfffffee2 -#define INTC_IPRB 0xfffffee4 -#define INTC_IPRC 0xa4000016 -#define INTC_IPRD 0xa4000018 -#define INTC_IPRE 0xa400001a - -#define IRQ0_IRQ 32 -#define IRQ1_IRQ 33 -#define IRQ2_IRQ 34 -#define IRQ3_IRQ 35 -#define IRQ4_IRQ 36 -#define IRQ5_IRQ 37 - -#define IRQ0_IRP_OFFSET 32 -#define IRQ1_IRP_OFFSET 36 -#define IRQ2_IRP_OFFSET 40 -#define IRQ3_IRP_OFFSET 44 -#define IRQ4_IRP_OFFSET 48 -#define IRQ5_IRP_OFFSET 52 - -#define IRQ0_PRIORITY 1 -#define IRQ1_PRIORITY 1 -#define IRQ2_PRIORITY 1 -#define IRQ3_PRIORITY 1 -#define IRQ4_PRIORITY 1 -#define IRQ5_PRIORITY 1 - -static void enable_onChip2_irq(unsigned int irq); -void disable_onChip2_irq(unsigned int irq); - -/* shutdown is same as "disable" */ -#define shutdown_onChip2_irq disable_onChip2_irq - -static void mask_and_ack_onChip2(unsigned int); -static void end_onChip2_irq(unsigned int irq); - -static unsigned int startup_onChip2_irq(unsigned int irq) -{ - enable_onChip2_irq(irq); - return 0; /* never anything pending */ -} - -static struct hw_interrupt_type onChip2_irq_type = { - "Extended-IPR", - startup_onChip2_irq, - shutdown_onChip2_irq, - enable_onChip2_irq, - disable_onChip2_irq, - mask_and_ack_onChip2, - end_onChip2_irq -}; - -void disable_onChip2_irq(unsigned int irq) -{ - unsigned long val, flags; - /* Set priority in IPR to 0 */ - int offset = ipr_data[irq-TIMER_IRQ].offset - 32; - unsigned long intc_ipr_address = INTC_IPRC + (offset/16*INTC_SIZE); - unsigned short mask = 0xffff ^ (0xf << (offset%16)); - - save_and_cli(flags); - val = ctrl_inw(intc_ipr_address); - val &= mask; - ctrl_outw(val, intc_ipr_address); - restore_flags(flags); -} - -static void enable_onChip2_irq(unsigned int irq) -{ - unsigned long val, flags; - /* Set priority in IPR back to original value */ - int offset = ipr_data[irq-TIMER_IRQ].offset - 32; - int priority = ipr_data[irq-TIMER_IRQ].priority; - unsigned long intc_ipr_address = INTC_IPRC + (offset/16*INTC_SIZE); - unsigned short value = (priority << (offset%16)); - - save_and_cli(flags); - val = ctrl_inw(intc_ipr_address); - val |= value; - ctrl_outw(val, intc_ipr_address); - restore_flags(flags); -} - -static void mask_and_ack_onChip2(unsigned int irq) -{ - disable_onChip2_irq(irq); - if (IRQ0_IRQ <= irq && irq <= IRQ5_IRQ) { - /* Clear external interrupt request */ - int a = ctrl_inb(INTC_IRR0); - a &= ~(1 << (irq - IRQ0_IRQ)); - ctrl_outb(a, INTC_IRR0); - } -} - -static void end_onChip2_irq(unsigned int irq) -{ - enable_onChip2_irq(irq); -} -#endif /* CONFIG_CPU_SUBTYPE_SH7709 */ - -void __init init_IRQ(void) -{ - int i; - - for (i = TIMER_IRQ; i < NR_IRQS; i++) { - irq_desc[i].handler = &onChip_irq_type; - } - -#ifdef CONFIG_CPU_SUBTYPE_SH7709 - - /* - * Initialize the Interrupt Controller (INTC) - * registers to their power on values - */ - - ctrl_outb(0, INTC_IRR0); - ctrl_outb(0, INTC_IRR1); - ctrl_outb(0, INTC_IRR2); - - ctrl_outw(0, INTC_ICR0); - ctrl_outw(0, INTC_ICR1); - ctrl_outw(0, INTC_ICR2); - ctrl_outw(0, INTC_INTER); - ctrl_outw(0, INTC_IPRA); - ctrl_outw(0, INTC_IPRB); - ctrl_outw(0, INTC_IPRC); - ctrl_outw(0, INTC_IPRD); - ctrl_outw(0, INTC_IPRE); - - for (i = IRQ0_IRQ; i < NR_IRQS; i++) { - irq_desc[i].handler = &onChip2_irq_type; - } - - /* - * Enable external irq(INTC IRQ mode). - * You should set corresponding bits of PFC to "00" - * to enable these interrupts. - */ - set_ipr_data(IRQ0_IRQ, IRQ0_IRP_OFFSET, IRQ0_PRIORITY); - set_ipr_data(IRQ1_IRQ, IRQ1_IRP_OFFSET, IRQ1_PRIORITY); - set_ipr_data(IRQ2_IRQ, IRQ2_IRP_OFFSET, IRQ2_PRIORITY); - set_ipr_data(IRQ3_IRQ, IRQ3_IRP_OFFSET, IRQ3_PRIORITY); - set_ipr_data(IRQ4_IRQ, IRQ4_IRP_OFFSET, IRQ4_PRIORITY); - set_ipr_data(IRQ5_IRQ, IRQ5_IRP_OFFSET, IRQ5_PRIORITY); -#endif /* CONFIG_CPU_SUBTYPE_SH7709 */ -} Index: arch/sh/kernel/irq_se.c =================================================================== RCS file: irq_se.c diff -N irq_se.c --- /dev/null Tue May 5 13:32:27 1998 +++ irq_se.c Tue May 2 03:56:42 2000 @@ -0,0 +1,55 @@ +/* $Id$ + * + * linux/arch/sh/kernel/irq_se.c + * + * Copyright (C) 2000 Niibe Yutaka + * + * Interrupt handling for Hitachi SolutionEngine. + * + */ + +#include <linux/config.h> +#include <linux/init.h> +#include <linux/irq.h> + +void __init init_se_IRQ(void) +{ + int i; + + /* + * Super I/O (Just mimic PC): + * 1: keyboard + * 3: serial 0 + * 4: serial 1 + * 5: printer + * 6: floppy + * 8: rtc + * 12: mouse + * 14: ide0 + */ + set_ipr_data(14, BCR_IRP_ADDR+0, 2, 14); + set_ipr_data(12, BCR_IRP_ADDR+0, 1, 12); + set_ipr_data( 8, BCR_IRP_ADDR+2, 1, 8); + set_ipr_data( 6, BCR_IRP_ADDR+4, 3, 6); + set_ipr_data( 5, BCR_IRP_ADDR+4, 2, 5); + set_ipr_data( 4, BCR_IRP_ADDR+4, 1, 4); + set_ipr_data( 3, BCR_IRP_ADDR+4, 0, 3); + set_ipr_data( 1, BCR_IRP_ADDR+6, 3, 1); + + set_ipr_data(10, BCR_IRP_ADDR+6, 1, 10); /* LAN */ + + set_ipr_data(15, BCR_IRP_ADDR+8, 3, 13); /* PCIRQ3 */ + set_ipr_data(11, BCR_IRP_ADDR+8, 2, 11); /* PCIRQ2 */ + set_ipr_data( 9, BCR_IRP_ADDR+8, 1, 9); /* PCIRQ1 */ + set_ipr_data( 7, BCR_IRP_ADDR+8, 0, 7); /* PCIRQ0 */ + + /* #2, #13 are available for other interrupt sources. */ + /* NOTE: #2 and #13 are not used on PC (it's cascade to 9) */ + + make_ipr_irq(1); + for (i = 3; i < 15; i++) { + make_ipr_irq(i); + } +} + +module_init(init_se_IRQ); Index: arch/sh/kernel/time.c =================================================================== RCS file: /cvsroot/linuxsh/kernel/arch/sh/kernel/time.c,v retrieving revision 1.6 diff -u -r1.6 time.c --- arch/sh/kernel/time.c 2000/05/02 00:10:09 1.6 +++ arch/sh/kernel/time.c 2000/05/02 10:56:42 @@ -47,9 +47,6 @@ #define RCR2_RESET 0x02 /* Reset bit */ #define RCR2_START 0x01 /* Start bit */ -#define RTC_IRQ 22 -#define RTC_IPR_OFFSET 0 - #if defined(__sh3__) #define TMU_TOCR 0xfffffe90 /* Byte access */ #define TMU_TSTR 0xfffffe92 /* Byte access */ @@ -400,9 +397,7 @@ xtime.tv_sec = get_rtc_time(); xtime.tv_usec = 0; - set_ipr_data(TIMER_IRQ, TIMER_IPR_OFFSET, TIMER_PRIORITY); setup_irq(TIMER_IRQ, &irq0); - set_ipr_data(RTC_IRQ, RTC_IPR_OFFSET, TIMER_PRIORITY); setup_irq(RTC_IRQ, &irq1); /* Check how fast it is.. */ Index: arch/sh/mm/fault.c =================================================================== RCS file: /cvsroot/linuxsh/kernel/arch/sh/mm/fault.c,v retrieving revision 1.8 diff -u -r1.8 fault.c --- arch/sh/mm/fault.c 2000/04/30 23:33:47 1.8 +++ arch/sh/mm/fault.c 2000/05/02 10:56:42 @@ -210,18 +210,20 @@ printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference"); else printk(KERN_ALERT "Unable to handle kernel paging request"); - printk(" at virtual address %08lx\n",address); + printk(" at virtual address %08lx\n", address); printk(KERN_ALERT "pc = %08lx\n", regs->pc); - asm volatile("mov.l %1,%0" + asm volatile("mov.l %1, %0" : "=r" (page) : "m" (__m(MMU_TTB))); - page = ((unsigned long *) page)[address >> 22]; - printk(KERN_ALERT "*pde = %08lx\n", page); - if (page & _PAGE_PRESENT) { - page &= PAGE_MASK; - address &= 0x003ff000; - page = ((unsigned long *) __va(page))[address >> PAGE_SHIFT]; - printk(KERN_ALERT "*pte = %08lx\n", page); + if (page) { + page = ((unsigned long *) page)[address >> 22]; + printk(KERN_ALERT "*pde = %08lx\n", page); + if (page & _PAGE_PRESENT) { + page &= PAGE_MASK; + address &= 0x003ff000; + page = ((unsigned long *) __va(page))[address >> PAGE_SHIFT]; + printk(KERN_ALERT "*pte = %08lx\n", page); + } } die("Oops", regs, writeaccess); do_exit(SIGKILL); Index: drivers/char/sh-sci.c =================================================================== RCS file: /cvsroot/linuxsh/kernel/drivers/char/sh-sci.c,v retrieving revision 1.5 diff -u -r1.5 sh-sci.c --- drivers/char/sh-sci.c 2000/05/02 00:10:09 1.5 +++ drivers/char/sh-sci.c 2000/05/02 10:56:42 @@ -746,7 +746,7 @@ int i; for (i=SCI_ERI_IRQ; i<SCI_IRQ_END; i++) - set_ipr_data(i, SCI_IPR_OFFSET, SCI_PRIORITY); + set_ipr_data(i, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY); port = &sci_ports[0]; Index: drivers/char/sh-sci.h =================================================================== RCS file: /cvsroot/linuxsh/kernel/drivers/char/sh-sci.h,v retrieving revision 1.3 diff -u -r1.3 sh-sci.h --- drivers/char/sh-sci.h 2000/05/02 00:10:09 1.3 +++ drivers/char/sh-sci.h 2000/05/02 10:56:42 @@ -56,7 +56,8 @@ #define SCI_TEI_IRQ 26 #define SCI_IRQ_END 27 -#define SCI_IPR_OFFSET (16+4) +#define SCI_IPR_ADDR INTC_IPRB +#define SCI_IPR_POS 1 #endif #if defined(CONFIG_SH_SCIF_SERIAL) @@ -77,7 +78,8 @@ #define SCSCR_INIT 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ /* 0x33 when external clock is used */ -#define SCI_IPR_OFFSET (64+4) +#define SCI_IPR_ADDR INTC_IPRE +#define SCI_IPR_POS 1 #elif defined(__SH4__) #define SCSMR (volatile unsigned short *)0xFFE80000 @@ -92,7 +94,8 @@ #define SCLSR 0xFFE80024 #define SCSCR_INIT 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ -#define SCI_IPR_OFFSET (32+4) +#define SCI_IPR_ADDR INTC_IPRB +#define SCI_IPR_POS 1 #endif Index: include/asm-sh/irq.h =================================================================== RCS file: /cvsroot/linuxsh/kernel/include/asm-sh/irq.h,v retrieving revision 1.1.1.1 diff -u -r1.1.1.1 irq.h --- include/asm-sh/irq.h 2000/04/14 16:48:21 1.1.1.1 +++ include/asm-sh/irq.h 2000/05/02 10:56:44 @@ -6,15 +6,31 @@ * linux/include/asm-sh/irq.h * * Copyright (C) 1999 Niibe Yutaka + * Copyright (C) 2000 Kazumoto Kojima * */ #include <linux/config.h> -#define TIMER_IRQ 16 /* Hard-wired */ -#define TIMER_IPR_OFFSET 12 -#define TIMER_PRIORITY 2 +#if defined(__sh3__) +#define INTC_IPRA 0xfffffee2UL +#define INTC_IPRB 0xfffffee4UL +#elif defined(__SH4__) +#define INTC_IPRA 0xffd00004UL +#define INTC_IPRA 0xffd00008UL +#define INTC_IPRC 0xffd0000cUL +#endif + +#define TIMER_IRQ 16 +#define TIMER_IPR_ADDR INTC_IPRA +#define TIMER_IPR_POS 3 +#define TIMER_PRIORITY 2 +#define RTC_IRQ 22 +#define RTC_IPR_ADDR INTC_IPRA +#define RTC_IPR_POS 0 +#define RTC_PRIORITY TIMER_PRIORITY + #if defined(__SH4__) /* * 48 = 32+16 @@ -37,8 +53,56 @@ /* * Function for "on chip support modules". */ -extern void set_ipr_data(unsigned int irq, int offset, int priority); -extern void make_onChip_irq(unsigned int irq); +extern void set_ipr_data(unsigned int irq, unsigned int addr, + int pos, int priority); +extern void make_ipr_irq(unsigned int irq); extern void make_imask_irq(unsigned int irq); + +#if defined(CONFIG_CPU_SUBTYPE_SH7709) +#define INTC_IRR0 0xa4000004UL +#define INTC_IRR1 0xa4000006UL +#define INTC_IRR2 0xa4000008UL + +#define INTC_ICR0 0xfffffee0UL +#define INTC_ICR1 0xa4000010UL +#define INTC_ICR2 0xa4000012UL +#define INTC_INTER 0xa4000014UL + +#define INTC_IPRC 0xa4000016UL +#define INTC_IPRD 0xa4000018UL +#define INTC_IPRE 0xa400001aUL + +#define IRQ0_IRQ 32 +#define IRQ1_IRQ 33 +#define IRQ2_IRQ 34 +#define IRQ3_IRQ 35 +#define IRQ4_IRQ 36 +#define IRQ5_IRQ 37 + +#define IRQ0_IRP_ADDR INTC_IPRC +#define IRQ1_IRP_ADDR INTC_IPRC +#define IRQ2_IRP_ADDR INTC_IPRC +#define IRQ3_IRP_ADDR INTC_IPRC +#define IRQ4_IRP_ADDR INTC_IPRD +#define IRQ5_IRP_ADDR INTC_IPRD + +#define IRQ0_IRP_POS 0 +#define IRQ1_IRP_POS 1 +#define IRQ2_IRP_POS 2 +#define IRQ3_IRP_POS 3 +#define IRQ4_IRP_POS 0 +#define IRQ5_IRP_POS 1 + +#define IRQ0_PRIORITY 1 +#define IRQ1_PRIORITY 1 +#define IRQ2_PRIORITY 1 +#define IRQ3_PRIORITY 1 +#define IRQ4_PRIORITY 1 +#define IRQ5_PRIORITY 1 +#endif + +#ifdef CONFIG_SH_SOLUTION_ENGINE +#define BCR_IRP_ADDR 0xb1400000 /* FPGA */ +#endif #endif /* __ASM_SH_IRQ_H */ |
From: Mitch D. <mj...@au...> - 2000-05-03 02:15:50
|
gn...@ch... wrote: > > So, I've replaced on-chip support into generalized one called "IPR > (Interrupt Priority Register) based IRQ" support. A Totally Excellent Idea. > I think that it's the job of boot loader, and wanna remove > the code from the kernel. How do you think? I agree. Each type of hardware needs to be initialised in a certain (unique) way. It's really not feasible for the kernel to autoprobe to find out how to do the correct initialisation. And hard-coding the choices means it's not possible to make a basic binary people can download and try. The bootloaders I'm working with do the initialisation, then vector to the kernel. IMHO that's the correct place for initialisation. We could provide people with sample bootloader code, documenting what to change and why, and distribute this either separately, or in the arch/sh directory. Regards, Mitch. -- | mailto:mj...@au... | Not the official view of: | | mailto:mj...@al... | Australian Calculator Opn | | Certified Linux Evangelist! | Hewlett Packard Australia | |
From: NIIBE Y. <gn...@ch...> - 2000-05-06 07:31:33
|
With following change, integration of I/O handling is finished. For the type of PORT, it is intentionaly changed (from unsigned long to unsigned int) to detect the changes. I'll commit this soon. -------------------------- 2000-05-06 NIIBE Yutaka <gn...@m1...> * include/asm/io.h (outb, outb_p, outw, outl): Fix the prototype. * arch/sh/kernel/io_se.c (outb, outb_p, outw, outl): Follow the change of io.h. * arch/sh/kernel/io_generic.c (inb, inb_p, inw, inl, insb, insw, insl, outb, outb_p, outw, outl, outsb, outsw, outsl): Fix the prototype. * arch/sh/kernel/setup_se.c (init_smsc): Removed setting of POWER_CONTROL, since it is done by ACTIVATE. Index: arch/sh/kernel/io_generic.c =================================================================== RCS file: /cvsroot/linuxsh/kernel/arch/sh/kernel/io_generic.c,v retrieving revision 1.2 diff -u -r1.2 io_generic.c --- arch/sh/kernel/io_generic.c 2000/05/03 08:13:34 1.2 +++ arch/sh/kernel/io_generic.c 2000/05/06 07:23:26 @@ -18,12 +18,12 @@ ctrl_inw(0xa0000000); } -unsigned long inb(unsigned long port) +unsigned long inb(unsigned int port) { return *(volatile unsigned char*)PORT2ADDR(port); } -unsigned long inb_p(unsigned long port) +unsigned long inb_p(unsigned int port) { unsigned long v = *(volatile unsigned char*)PORT2ADDR(port); @@ -31,68 +31,68 @@ return v; } -unsigned long inw(unsigned long port) +unsigned long inw(unsigned int port) { return *(volatile unsigned short*)PORT2ADDR(port); } -unsigned long inl(unsigned long port) +unsigned long inl(unsigned int port) { return *(volatile unsigned long*)PORT2ADDR(port); } -void insb(unsigned long port, void *buffer, int count) +void insb(unsigned int port, void *buffer, unsigned long count) { unsigned char *buf=buffer; while(count--) *buf++=inb(port); } -void insw(unsigned long port, void *buffer, int count) +void insw(unsigned int port, void *buffer, unsigned long count) { unsigned short *buf=buffer; while(count--) *buf++=inw(port); } -void insl(unsigned long port, void *buffer, int count) +void insl(unsigned int port, void *buffer, unsigned long count) { unsigned long *buf=buffer; while(count--) *buf++=inl(port); } -void outb(unsigned char b, unsigned long port) +void outb(unsigned long b, unsigned int port) { *(volatile unsigned char*)PORT2ADDR(port) = b; } -void outb_p(unsigned char b, unsigned long port) +void outb_p(unsigned long b, unsigned int port) { *(volatile unsigned char*)PORT2ADDR(port) = b; delay(); } -void outw(unsigned short b, unsigned long port) +void outw(unsigned long b, unsigned int port) { *(volatile unsigned short*)PORT2ADDR(port) = b; } -void outl(unsigned int b, unsigned long port) +void outl(unsigned long b, unsigned int port) { *(volatile unsigned long*)PORT2ADDR(port) = b; } -void outsb(unsigned long port, const void *buffer, int count) +void outsb(unsigned int port, const void *buffer, unsigned long count) { const unsigned char *buf=buffer; while(count--) outb(*buf++, port); } -void outsw(unsigned long port, const void *buffer, int count) +void outsw(unsigned int port, const void *buffer, unsigned long count) { const unsigned short *buf=buffer; while(count--) outw(*buf++, port); } -void outsl(unsigned long port, const void *buffer, int count) +void outsl(unsigned int port, const void *buffer, unsigned long count) { const unsigned long *buf=buffer; while(count--) outl(*buf++, port); Index: arch/sh/kernel/io_se.c =================================================================== RCS file: /cvsroot/linuxsh/kernel/arch/sh/kernel/io_se.c,v retrieving revision 1.3 diff -u -r1.3 io_se.c --- arch/sh/kernel/io_se.c 2000/05/03 08:49:58 1.3 +++ arch/sh/kernel/io_se.c 2000/05/06 07:23:26 @@ -97,7 +97,7 @@ return 0; } -void outb(unsigned int value, unsigned int port) +void outb(unsigned long value, unsigned int port) { if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) *(__u8 *)(sh_pcic_io_wbase + port) = value; @@ -107,7 +107,7 @@ *(port2adr(port)) = value; } -void outb_p(unsigned int value, unsigned int port) +void outb_p(unsigned long value, unsigned int port) { if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) *(__u8 *)(sh_pcic_io_wbase + port) = value; @@ -118,7 +118,7 @@ delay(); } -void outw(unsigned int value, unsigned int port) +void outw(unsigned long value, unsigned int port) { if (port >= 0x2000 || (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)) @@ -127,7 +127,7 @@ maybebadio(outw, port); } -void outl(unsigned int value, unsigned int port) +void outl(unsigned long value, unsigned int port) { maybebadio(outl, port); } Index: arch/sh/kernel/setup_se.c =================================================================== RCS file: /cvsroot/linuxsh/kernel/arch/sh/kernel/setup_se.c,v retrieving revision 1.4 diff -u -r1.4 setup_se.c --- arch/sh/kernel/setup_se.c 2000/05/05 03:46:03 1.4 +++ arch/sh/kernel/setup_se.c 2000/05/06 07:23:26 @@ -32,22 +32,6 @@ outb_p(CONFIG_ENTER, CONFIG_PORT); outb_p(CONFIG_ENTER, CONFIG_PORT); -#if defined(__sh3__) - /* SolutionEngine SH7709A has power control feature */ - /* It reads "FDC37C935APM" */ - /* - * b0: FDC - * b1: IDE1 - * b2: IDE2 - * b3: Parallel port - * b4: Serial port 1 - * b5: Serial port 2 - * b6: ACCESS.bus - * b7: ---- - */ - smsc_config(POWER_CONTROL_INDEX, 0x13); /* Power on! */ -#endif - /* FDC */ smsc_config(CURRENT_LDN_INDEX, LDN_FDC); smsc_config(ACTIVATE_INDEX, 0x01); @@ -70,7 +54,7 @@ smsc_config(ACTIVATE_INDEX, 0x01); smsc_config(IRQ_SELECT_INDEX, 8); /* IRQ8 */ - /* XXX: COM2, PARPORT, KBD, and MOUSE come here... */ + /* XXX: COM2, PARPORT, KBD, and MOUSE will come here... */ outb_p(CONFIG_EXIT, CONFIG_PORT); } @@ -103,7 +87,7 @@ set_ipr_data(10, BCR_ILCRD, 1, 0x0f-10); /* LAN */ - set_ipr_data( 0, BCR_ILCRE, 3, 0x0f- 0); /* PCIRQ3 */ + set_ipr_data( 0, BCR_ILCRE, 3, 0x0f- 0); /* PCIRQ3 */ set_ipr_data(11, BCR_ILCRE, 2, 0x0f-11); /* PCIRQ2 */ set_ipr_data( 9, BCR_ILCRE, 1, 0x0f- 9); /* PCIRQ1 */ set_ipr_data( 7, BCR_ILCRE, 0, 0x0f- 7); /* PCIRQ0 */ Index: include/asm-sh/io.h =================================================================== RCS file: /cvsroot/linuxsh/kernel/include/asm-sh/io.h,v retrieving revision 1.3 diff -u -r1.3 io.h --- include/asm-sh/io.h 2000/05/03 08:13:34 1.3 +++ include/asm-sh/io.h 2000/05/06 07:23:28 @@ -58,10 +58,10 @@ extern void insw(unsigned int port, void *addr, unsigned long count); extern void insl(unsigned int port, void *addr, unsigned long count); -extern void outb(unsigned int value, unsigned int port); -extern void outb_p(unsigned int value, unsigned int port); -extern void outw(unsigned int value, unsigned int port); -extern void outl(unsigned int value, unsigned int port); +extern void outb(unsigned long value, unsigned int port); +extern void outb_p(unsigned long value, unsigned int port); +extern void outw(unsigned long value, unsigned int port); +extern void outl(unsigned long value, unsigned int port); extern void outsb(unsigned int port, const void *addr, unsigned long count); extern void outsw(unsigned int port, const void *addr, unsigned long count); extern void outsl(unsigned int port, const void *addr, unsigned long count); |