diff options
Diffstat (limited to 'arch/sh/kernel')
-rw-r--r-- | arch/sh/kernel/Makefile | 35 | ||||
-rw-r--r-- | arch/sh/kernel/cf-enabler.c | 24 | ||||
-rw-r--r-- | arch/sh/kernel/entry.S | 15 | ||||
-rw-r--r-- | arch/sh/kernel/io.c | 202 | ||||
-rw-r--r-- | arch/sh/kernel/io_generic.c | 119 | ||||
-rw-r--r-- | arch/sh/kernel/io_hd64461.c | 59 | ||||
-rw-r--r-- | arch/sh/kernel/io_se.c | 62 | ||||
-rw-r--r-- | arch/sh/kernel/io_unknown.c | 47 | ||||
-rw-r--r-- | arch/sh/kernel/irq.c | 29 | ||||
-rw-r--r-- | arch/sh/kernel/irq_imask.c | 5 | ||||
-rw-r--r-- | arch/sh/kernel/irq_ipr.c | 75 | ||||
-rw-r--r-- | arch/sh/kernel/led_se.c | 67 | ||||
-rw-r--r-- | arch/sh/kernel/mach_hp600.c | 63 | ||||
-rw-r--r-- | arch/sh/kernel/mach_se.c | 80 | ||||
-rw-r--r-- | arch/sh/kernel/mach_unknown.c | 68 | ||||
-rw-r--r-- | arch/sh/kernel/pci-sh.c | 19 | ||||
-rw-r--r-- | arch/sh/kernel/semaphore.c | 2 | ||||
-rw-r--r-- | arch/sh/kernel/setup.c | 134 | ||||
-rw-r--r-- | arch/sh/kernel/setup_cqreek.c | 224 | ||||
-rw-r--r-- | arch/sh/kernel/setup_hd64461.c | 19 | ||||
-rw-r--r-- | arch/sh/kernel/setup_se.c | 51 | ||||
-rw-r--r-- | arch/sh/kernel/sh_bios.c | 2 | ||||
-rw-r--r-- | arch/sh/kernel/signal.c | 7 | ||||
-rw-r--r-- | arch/sh/kernel/time.c | 16 |
24 files changed, 1252 insertions, 172 deletions
diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile index 7b3852295..c9de70daf 100644 --- a/arch/sh/kernel/Makefile +++ b/arch/sh/kernel/Makefile @@ -11,8 +11,8 @@ O_TARGET := kernel.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 + ptrace.o setup.o time.o sys_sh.o semaphore.o \ + irq_imask.o io.o OX_OBJS := sh_ksyms.o MX_OBJS := @@ -21,26 +21,45 @@ O_OBJS += cf-enabler.o endif ifdef CONFIG_SH_GENERIC + +O_OBJS += mach_se.o setup_se.o setup_cqreek.o io_se.o led_se.o \ + mach_hp600.o io_hd64461.o \ + mach_unknown.o io_unknown.o \ + io_generic.o + +else + +ifdef CONFIG_SH_HP600 +O_OBJS += mach_hp600.o io_hd64461.o io_generic.o +endif + +ifdef CONFIG_SH_OVERDRIVE O_OBJS += io_generic.o endif ifdef CONFIG_SH_SOLUTION_ENGINE -O_OBJS += setup_se.o io_se.o +O_OBJS += mach_se.o setup_se.o io_se.o io_generic.o led_se.o endif -ifdef CONFIG_SH_OVERDRIVE -O_OBJS += setup_od.o io_generic.o +ifdef CONFIG_SH_CQREEK +O_OBJS += setup_cqreek.o +endif + +ifdef CONFIG_SH_UNKNOWN +O_OBJS += mach_unknown.o io_unknown.o io_generic.o endif -ifdef CONFIG_SH_HP600 -O_OBJS += io_hd64461.o endif ifdef CONFIG_CPU_SH4 O_OBJS += fpu.o endif -ifdef CONFIG_HD64461 +ifdef CONFIG_PCI +O_OBJS += pci-sh.o +endif + +ifneq ($(CONFIG_SH_GENERIC)$(CONFIG_HD64461),) O_OBJS += setup_hd64461.o endif diff --git a/arch/sh/kernel/cf-enabler.c b/arch/sh/kernel/cf-enabler.c index 3727c7264..c446a1151 100644 --- a/arch/sh/kernel/cf-enabler.c +++ b/arch/sh/kernel/cf-enabler.c @@ -14,15 +14,18 @@ #include <asm/io.h> #include <asm/irq.h> -#ifdef CONFIG_SH_SOLUTION_ENGINE #include <asm/hitachi_se.h> + + /* + * SolutionEngine + * * 0xB8400000 : Common Memory * 0xB8500000 : Attribute * 0xB8600000 : I/O */ -int __init cf_init(void) +static int __init cf_init_se(void) { if ((ctrl_inw(MRSHPC_CSR) & 0x000c) != 0) return 0; /* Not detected */ @@ -68,11 +71,15 @@ int __init cf_init(void) ctrl_outb(0x42, PA_MRSHPC_MW2 + 0x200); return 0; } -#else /* then generic system type */ + #define CF_CIS_BASE 0xb8000000 /* * You can connect Compact Flash directly to the bus of SuperH. * This is the enabler for that. + * + * SIM: How generic is this really? It looks pretty board, or at + * least SH sub-type, specific to me. + * I know it doesn't work on the Overdrive! */ /* @@ -81,7 +88,7 @@ int __init cf_init(void) * 0xBA000000 : I/O */ -int __init cf_init(void) +static int __init cf_init_default(void) { /* Enable the card, and set the level interrupt */ ctrl_outw(0x0042, CF_CIS_BASE+0x0200); @@ -89,6 +96,13 @@ int __init cf_init(void) disable_irq(14); return 0; } -#endif + +int __init cf_init(void) +{ + if (MACH_SE) { + return cf_init_se(); + } + return cf_init_default(); +} __initcall (cf_init); diff --git a/arch/sh/kernel/entry.S b/arch/sh/kernel/entry.S index 450d49824..4e57175e7 100644 --- a/arch/sh/kernel/entry.S +++ b/arch/sh/kernel/entry.S @@ -62,7 +62,7 @@ ENOSYS = 38 #if defined(__sh3__) TRA = 0xffffffd0 EXPEVT = 0xffffffd4 -#ifdef CONFIG_CPU_SUBTYPE_SH7709 +#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) INTEVT = 0xa4000000 ! INTEVTE2(0xa4000000) #else INTEVT = 0xffffffd8 @@ -182,7 +182,7 @@ tlb_protection_violation_store: 1: .long SYMBOL_NAME(do_page_fault) 2: .long MMU_TEA -#ifdef CONFIG_DEBUG_KERNEL_WITH_GDB_STUB +#if defined(CONFIG_DEBUG_KERNEL_WITH_GDB_STUB) || defined(CONFIG_SH_STANDARD_BIOS) .align 2 /* Unwind the stack and jmp to the debug entry */ debug_kernel: @@ -219,12 +219,12 @@ debug_kernel: ldc $k1, $ssr .align 2 1: .long 0x300000f0 -2: .long 0xa0000100 +2: .long CONFIG_GDB_STUB_VBR + 0x100 #endif .align 2 debug_trap: -#ifdef CONFIG_DEBUG_KERNEL_WITH_GDB_STUB +#if defined(CONFIG_DEBUG_KERNEL_WITH_GDB_STUB) || defined(CONFIG_SH_STANDARD_BIOS) mov #SR, $r0 mov.l @($r0,$r15), $r0 ! get status register shll $r0 @@ -829,7 +829,7 @@ ENTRY(interrupt_table) .long SYMBOL_NAME(do_IRQ) ! rovi .long SYMBOL_NAME(do_IRQ) .long SYMBOL_NAME(do_IRQ) -#if defined(CONFIG_CPU_SUBTYPE_SH7709) +#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) .long SYMBOL_NAME(do_IRQ) ! 32 IRQ irq0 .long SYMBOL_NAME(do_IRQ) ! 33 irq1 .long SYMBOL_NAME(do_IRQ) ! 34 irq2 @@ -859,6 +859,11 @@ ENTRY(interrupt_table) .long SYMBOL_NAME(do_IRQ) ! 58 bri2 .long SYMBOL_NAME(do_IRQ) ! 59 txi2 .long SYMBOL_NAME(do_IRQ) ! 60 ADC adi +#if defined(CONFIG_CPU_SUBTYPE_SH7707) + .long SYMBOL_NAME(do_IRQ) ! 61 LCDC lcdi + .long SYMBOL_NAME(do_IRQ) ! 62 PCC pcc0i + .long SYMBOL_NAME(do_IRQ) ! 63 pcc1i +#endif #elif defined(__SH4__) .long SYMBOL_NAME(do_IRQ) ! Hitachi UDI .long SYMBOL_NAME(do_IRQ) ! GPIO diff --git a/arch/sh/kernel/io.c b/arch/sh/kernel/io.c new file mode 100644 index 000000000..27f250f9f --- /dev/null +++ b/arch/sh/kernel/io.c @@ -0,0 +1,202 @@ +/* + * linux/arch/sh/kernel/io_generic.c + * + * Copyright (C) 2000 Stuart Menefy + * + * Provide real functions which expand to whatever the header file defined. + * Also definitions of machine independant IO functions. + */ + +#include <linux/config.h> +#include <asm/io.h> + +unsigned int _inb(unsigned long port) +{ + return __inb(port); +} + +unsigned int _inw(unsigned long port) +{ + return __inw(port); +} + +unsigned int _inl(unsigned long port) +{ + return __inl(port); +} + +void _outb(unsigned char b, unsigned long port) +{ + __outb(b, port); +} + +void _outw(unsigned short b, unsigned long port) +{ + __outw(b, port); +} + +void _outl(unsigned int b, unsigned long port) +{ + __outl(b, port); +} + +unsigned int _inb_p(unsigned long port) +{ + return __inb_p(port); +} + +unsigned int _inw_p(unsigned long port) +{ + return __inw_p(port); +} + +void _outb_p(unsigned char b, unsigned long port) +{ + __outb_p(b, port); +} + +void _outw_p(unsigned short b, unsigned long port) +{ + __outw_p(b, port); +} + +void _insb(unsigned long port, void *buffer, unsigned long count) +{ + return __insb(port, buffer, count); +} + +void _insw(unsigned long port, void *buffer, unsigned long count) +{ + __insw(port, buffer, count); +} + +void _insl(unsigned long port, void *buffer, unsigned long count) +{ + __insl(port, buffer, count); +} + +void _outsb(unsigned long port, const void *buffer, unsigned long count) +{ + __outsb(port, buffer, count); +} + +void _outsw(unsigned long port, const void *buffer, unsigned long count) +{ + __outsw(port, buffer, count); +} + +void _outsl(unsigned long port, const void *buffer, unsigned long count) +{ + __outsl(port, buffer, count); + +} + +unsigned long ___raw_readb(unsigned long addr) +{ + return __readb(addr); +} + +unsigned long ___raw_readw(unsigned long addr) +{ + return __readw(addr); +} + +unsigned long ___raw_readl(unsigned long addr) +{ + return __readl(addr); +} + +unsigned long _readb(unsigned long addr) +{ + unsigned long r = __readb(addr); + mb(); + return r; +} + +unsigned long _readw(unsigned long addr) +{ + unsigned long r = __readw(addr); + mb(); + return r; +} + +unsigned long _readl(unsigned long addr) +{ + unsigned long r = __readl(addr); + mb(); + return r; +} + +void ___raw_writeb(unsigned char b, unsigned long addr) +{ + __writeb(b, addr); +} + +void ___raw_writew(unsigned short b, unsigned long addr) +{ + __writew(b, addr); +} + +void ___raw_writel(unsigned int b, unsigned long addr) +{ + __writel(b, addr); +} + +void _writeb(unsigned char b, unsigned long addr) +{ + __writeb(b, addr); + mb(); +} + +void _writew(unsigned short b, unsigned long addr) +{ + __writew(b, addr); + mb(); +} + +void _writel(unsigned int b, unsigned long addr) +{ + __writel(b, addr); + mb(); +} + +/* + * Copy data from IO memory space to "real" memory space. + * This needs to be optimized. + */ +void memcpy_fromio(void * to, unsigned long from, unsigned long count) +{ + while (count) { + count--; + *(char *) to = readb(from); + ((char *) to)++; + from++; + } +} + +/* + * Copy data from "real" memory space to IO memory space. + * This needs to be optimized. + */ +void memcpy_toio(unsigned long to, const void * from, unsigned long count) +{ + while (count) { + count--; + writeb(*(char *) from, to); + ((char *) from)++; + to++; + } +} + +/* + * "memset" on IO memory space. + * This needs to be optimized. + */ +void memset_io(unsigned long dst, int c, unsigned long count) +{ + while (count) { + count--; + writeb(c, dst); + dst++; + } +} diff --git a/arch/sh/kernel/io_generic.c b/arch/sh/kernel/io_generic.c index 1faa01ce3..9e5793450 100644 --- a/arch/sh/kernel/io_generic.c +++ b/arch/sh/kernel/io_generic.c @@ -4,7 +4,8 @@ * * Copyright (C) 2000 Niibe Yutaka * - * Generic I/O routine. + * Generic I/O routine. These can be used where a machine specific version + * is not required. * * 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 @@ -14,6 +15,7 @@ #include <linux/config.h> #include <asm/io.h> +#include <asm/machvec.h> #if defined(__sh3__) /* I'm not sure SH7709 has this kind of bug */ @@ -21,19 +23,31 @@ #define DUMMY_READ_AREA6 0xba000000 #endif -#define PORT2ADDR(x) (CONFIG_IOPORT_START+(x)) +#define PORT2ADDR(x) (sh_mv.mv_isa_port2addr(x)) + +unsigned long generic_io_base; static inline void delay(void) { ctrl_inw(0xa0000000); } -unsigned long inb(unsigned int port) +unsigned long generic_inb(unsigned int port) { return *(volatile unsigned char*)PORT2ADDR(port); } -unsigned long inb_p(unsigned int port) +unsigned long generic_inw(unsigned int port) +{ + return *(volatile unsigned short*)PORT2ADDR(port); +} + +unsigned long generic_inl(unsigned int port) +{ + return *(volatile unsigned long*)PORT2ADDR(port); +} + +unsigned long generic_inb_p(unsigned int port) { unsigned long v = *(volatile unsigned char*)PORT2ADDR(port); @@ -41,23 +55,29 @@ unsigned long inb_p(unsigned int port) return v; } -unsigned long inw(unsigned int port) +unsigned long generic_inw_p(unsigned int port) { - return *(volatile unsigned short*)PORT2ADDR(port); + unsigned long v = *(volatile unsigned short*)PORT2ADDR(port); + + delay(); + return v; } -unsigned long inl(unsigned int port) +unsigned long generic_inl_p(unsigned int port) { - return *(volatile unsigned long*)PORT2ADDR(port); + unsigned long v = *(volatile unsigned long*)PORT2ADDR(port); + + delay(); + return v; } -void insb(unsigned int port, void *buffer, unsigned long count) +void generic_insb(unsigned int port, void *buffer, unsigned long count) { unsigned char *buf=buffer; while(count--) *buf++=inb(port); } -void insw(unsigned int port, void *buffer, unsigned long count) +void generic_insw(unsigned int port, void *buffer, unsigned long count) { unsigned short *buf=buffer; while(count--) *buf++=inw(port); @@ -66,7 +86,7 @@ void insw(unsigned int port, void *buffer, unsigned long count) #endif } -void insl(unsigned int port, void *buffer, unsigned long count) +void generic_insl(unsigned int port, void *buffer, unsigned long count) { unsigned long *buf=buffer; while(count--) *buf++=inl(port); @@ -75,34 +95,46 @@ void insl(unsigned int port, void *buffer, unsigned long count) #endif } -void outb(unsigned long b, unsigned int port) +void generic_outb(unsigned long b, unsigned int port) { *(volatile unsigned char*)PORT2ADDR(port) = b; } -void outb_p(unsigned long b, unsigned int port) +void generic_outw(unsigned long b, unsigned int port) +{ + *(volatile unsigned short*)PORT2ADDR(port) = b; +} + +void generic_outl(unsigned long b, unsigned int port) +{ + *(volatile unsigned long*)PORT2ADDR(port) = b; +} + +void generic_outb_p(unsigned long b, unsigned int port) { *(volatile unsigned char*)PORT2ADDR(port) = b; delay(); } -void outw(unsigned long b, unsigned int port) +void generic_outw_p(unsigned long b, unsigned int port) { *(volatile unsigned short*)PORT2ADDR(port) = b; + delay(); } -void outl(unsigned long b, unsigned int port) +void generic_outl_p(unsigned long b, unsigned int port) { - *(volatile unsigned long*)PORT2ADDR(port) = b; + *(volatile unsigned long*)PORT2ADDR(port) = b; + delay(); } -void outsb(unsigned int port, const void *buffer, unsigned long count) +void generic_outsb(unsigned int port, const void *buffer, unsigned long count) { const unsigned char *buf=buffer; while(count--) outb(*buf++, port); } -void outsw(unsigned int port, const void *buffer, unsigned long count) +void generic_outsw(unsigned int port, const void *buffer, unsigned long count) { const unsigned short *buf=buffer; while(count--) outw(*buf++, port); @@ -111,7 +143,7 @@ void outsw(unsigned int port, const void *buffer, unsigned long count) #endif } -void outsl(unsigned int port, const void *buffer, unsigned long count) +void generic_outsl(unsigned int port, const void *buffer, unsigned long count) { const unsigned long *buf=buffer; while(count--) outl(*buf++, port); @@ -119,3 +151,52 @@ void outsl(unsigned int port, const void *buffer, unsigned long count) ctrl_inb (DUMMY_READ_AREA6); #endif } + +unsigned long generic_readb(unsigned long addr) +{ + return *(volatile unsigned char*)addr; +} + +unsigned long generic_readw(unsigned long addr) +{ + return *(volatile unsigned short*)addr; +} + +unsigned long generic_readl(unsigned long addr) +{ + return *(volatile unsigned long*)addr; +} + +void generic_writeb(unsigned char b, unsigned long addr) +{ + *(volatile unsigned char*)addr = b; +} + +void generic_writew(unsigned short b, unsigned long addr) +{ + *(volatile unsigned short*)addr = b; +} + +void generic_writel(unsigned int b, unsigned long addr) +{ + *(volatile unsigned long*)addr = b; +} + +void * generic_ioremap(unsigned long offset, unsigned long size) +{ + return (void *) P2SEGADDR(offset); +} + +void * generic_ioremap_nocache (unsigned long offset, unsigned long size) +{ + return (void *) P2SEGADDR(offset); +} + +void generic_iounmap(void *addr) +{ +} + +unsigned long generic_isa_port2addr(unsigned long offset) +{ + return offset + generic_io_base; +} diff --git a/arch/sh/kernel/io_hd64461.c b/arch/sh/kernel/io_hd64461.c index 7c655942b..3fbe6f2d0 100644 --- a/arch/sh/kernel/io_hd64461.c +++ b/arch/sh/kernel/io_hd64461.c @@ -10,15 +10,36 @@ static __inline__ unsigned long PORT2ADDR(unsigned long port) { + /* 16550A: HD64461 internal */ + if (0x3f8<=port && port<=0x3ff) + return CONFIG_HD64461_IOBASE + 0x8000 + ((port-0x3f8)<<1); + if (0x2f8<=port && port<=0x2ff) + return CONFIG_HD64461_IOBASE + 0x7000 + ((port-0x2f8)<<1); + +#ifdef CONFIG_HD64461_ENABLER + /* NE2000: HD64461 PCMCIA channel 0 (I/O) */ + if (0x300<=port && port<=0x31f) + return 0xba000000 + port; + + /* ide0: HD64461 PCMCIA channel 1 (memory) */ + /* On HP690, CF in slot 1 is configured as a memory card + device. See CF+ and CompactFlash Specification for the + detail of CF's memory mapped addressing. */ + if (0x1f0<=port && port<=0x1f7) return 0xb5000000 + port; + if (port == 0x3f6) return 0xb50001fe; +#endif + + /* ??? */ + if (port < 0x10000) return 0xa0000000 + port; + /* HD64461 internal devices (0xb0000000) */ - if (port < 0x10000) return CONFIG_HD64461_IOBASE + port; + if (port < 0x20000) return CONFIG_HD64461_IOBASE + port - 0x10000; /* PCMCIA channel 0, I/O (0xba000000) */ - if (port < 0x20000) return 0xba000000 + port - 0x10000; + if (port < 0x30000) return 0xba000000 + port - 0x20000; - /* PCMCIA channel 1, memory (0xb5000000) - SH7709 cannot support I/O card attached to Area 5 */ - if (port < 0x30000) return 0xb5000000 + port - 0x20000; + /* PCMCIA channel 1, memory (0xb5000000) */ + if (port < 0x40000) return 0xb5000000 + port - 0x30000; /* Whole physical address space (0xa0000000) */ return 0xa0000000 + (port & 0x1fffffff); @@ -29,80 +50,80 @@ static inline void delay(void) ctrl_inw(0xa0000000); } -unsigned long inb(unsigned int port) +unsigned long hd64461_inb(unsigned int port) { return *(volatile unsigned char*)PORT2ADDR(port); } -unsigned long inb_p(unsigned int port) +unsigned long hd64461_inb_p(unsigned int port) { unsigned long v = *(volatile unsigned char*)PORT2ADDR(port); delay(); return v; } -unsigned long inw(unsigned int port) +unsigned long hd64461_inw(unsigned int port) { return *(volatile unsigned short*)PORT2ADDR(port); } -unsigned long inl(unsigned int port) +unsigned long hd64461_inl(unsigned int port) { return *(volatile unsigned long*)PORT2ADDR(port); } -void insb(unsigned int port, void *buffer, unsigned long count) +void hd64461_insb(unsigned int port, void *buffer, unsigned long count) { unsigned char *buf=buffer; while(count--) *buf++=inb(port); } -void insw(unsigned int port, void *buffer, unsigned long count) +void hd64461_insw(unsigned int port, void *buffer, unsigned long count) { unsigned short *buf=buffer; while(count--) *buf++=inw(port); } -void insl(unsigned int port, void *buffer, unsigned long count) +void hd64461_insl(unsigned int port, void *buffer, unsigned long count) { unsigned long *buf=buffer; while(count--) *buf++=inl(port); } -void outb(unsigned long b, unsigned int port) +void hd64461_outb(unsigned long b, unsigned int port) { *(volatile unsigned char*)PORT2ADDR(port) = b; } -void outb_p(unsigned long b, unsigned int port) +void hd64461_outb_p(unsigned long b, unsigned int port) { *(volatile unsigned char*)PORT2ADDR(port) = b; delay(); } -void outw(unsigned long b, unsigned int port) +void hd64461_outw(unsigned long b, unsigned int port) { *(volatile unsigned short*)PORT2ADDR(port) = b; } -void outl(unsigned long b, unsigned int port) +void hd64461_outl(unsigned long b, unsigned int port) { *(volatile unsigned long*)PORT2ADDR(port) = b; } -void outsb(unsigned int port, const void *buffer, unsigned long count) +void hd64461_outsb(unsigned int port, const void *buffer, unsigned long count) { const unsigned char *buf=buffer; while(count--) outb(*buf++, port); } -void outsw(unsigned int port, const void *buffer, unsigned long count) +void hd64461_outsw(unsigned int port, const void *buffer, unsigned long count) { const unsigned short *buf=buffer; while(count--) outw(*buf++, port); } -void outsl(unsigned int port, const void *buffer, unsigned long count) +void hd64461_outsl(unsigned int port, const void *buffer, unsigned long count) { const unsigned long *buf=buffer; while(count--) outl(*buf++, port); diff --git a/arch/sh/kernel/io_se.c b/arch/sh/kernel/io_se.c index a16c4738d..4d9eeca3b 100644 --- a/arch/sh/kernel/io_se.c +++ b/arch/sh/kernel/io_se.c @@ -56,7 +56,7 @@ shifted_port(unsigned int port) printk("bad PC-like io %s for port 0x%x at 0x%08x\n", \ #name, (port), (__u32) __builtin_return_address(0)) -unsigned long inb(unsigned int port) +unsigned long se_inb(unsigned int port) { if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) return *(__u8 *) (sh_pcic_io_wbase + 0x40000 + port); @@ -66,7 +66,7 @@ unsigned long inb(unsigned int port) return (*port2adr(port))&0xff; } -unsigned long inb_p(unsigned int port) +unsigned long se_inb_p(unsigned int port) { unsigned long v; @@ -80,7 +80,7 @@ unsigned long inb_p(unsigned int port) return v; } -unsigned long inw(unsigned int port) +unsigned long se_inw(unsigned int port) { if (port >= 0x2000 || (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)) @@ -90,13 +90,13 @@ unsigned long inw(unsigned int port) return 0; } -unsigned long inl(unsigned int port) +unsigned long se_inl(unsigned int port) { maybebadio(inl, port); return 0; } -void outb(unsigned long value, unsigned int port) +void se_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; @@ -106,7 +106,7 @@ void outb(unsigned long value, unsigned int port) *(port2adr(port)) = value; } -void outb_p(unsigned long value, unsigned int port) +void se_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; @@ -117,7 +117,7 @@ void outb_p(unsigned long value, unsigned int port) delay(); } -void outw(unsigned long value, unsigned int port) +void se_outw(unsigned long value, unsigned int port) { if (port >= 0x2000 || (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)) @@ -126,12 +126,12 @@ void outw(unsigned long value, unsigned int port) maybebadio(outw, port); } -void outl(unsigned long value, unsigned int port) +void se_outl(unsigned long value, unsigned int port) { maybebadio(outl, port); } -void insb(unsigned int port, void *addr, unsigned long count) +void se_insb(unsigned int port, void *addr, unsigned long count) { volatile __u16 *p = port2adr(port); @@ -148,19 +148,19 @@ void insb(unsigned int port, void *addr, unsigned long count) } } -void insw(unsigned int port, void *addr, unsigned long count) +void se_insw(unsigned int port, void *addr, unsigned long count) { volatile __u16 *p = port2adr(port); while (count--) *((__u16 *) addr)++ = *p; } -void insl(unsigned int port, void *addr, unsigned long count) +void se_insl(unsigned int port, void *addr, unsigned long count) { maybebadio(insl, port); } -void outsb(unsigned int port, const void *addr, unsigned long count) +void se_outsb(unsigned int port, const void *addr, unsigned long count) { volatile __u16 *p = port2adr(port); @@ -177,24 +177,54 @@ void outsb(unsigned int port, const void *addr, unsigned long count) } } -void outsw(unsigned int port, const void *addr, unsigned long count) +void se_outsw(unsigned int port, const void *addr, unsigned long count) { volatile __u16 *p = port2adr(port); while (count--) *p = *((__u16 *) addr)++; } -void outsl(unsigned int port, const void *addr, unsigned long count) +void se_outsl(unsigned int port, const void *addr, unsigned long count) { maybebadio(outsw, port); } + +unsigned long se_readb(unsigned long addr) +{ + return *(volatile unsigned char*)addr; +} + +unsigned long se_readw(unsigned long addr) +{ + return *(volatile unsigned short*)addr; +} + +unsigned long se_readl(unsigned long addr) +{ + return *(volatile unsigned long*)addr; +} + +void se_writeb(unsigned char b, unsigned long addr) +{ + *(volatile unsigned char*)addr = b; +} + +void se_writew(unsigned short b, unsigned long addr) +{ + *(volatile unsigned short*)addr = b; +} + +void se_writel(unsigned int b, unsigned long addr) +{ + *(volatile unsigned long*)addr = b; +} /* Map ISA bus address to the real address. Only for PCMCIA. */ /* ISA page descriptor. */ static __u32 sh_isa_memmap[256]; -int +static int sh_isa_mmap(__u32 start, __u32 length, __u32 offset) { int idx; @@ -212,7 +242,7 @@ sh_isa_mmap(__u32 start, __u32 length, __u32 offset) } unsigned long -sh_isa_slot(unsigned long offset) +se_isa_port2addr(unsigned long offset) { int idx; diff --git a/arch/sh/kernel/io_unknown.c b/arch/sh/kernel/io_unknown.c new file mode 100644 index 000000000..a0407cade --- /dev/null +++ b/arch/sh/kernel/io_unknown.c @@ -0,0 +1,47 @@ +/* + * linux/arch/sh/kernel/io_unknown.c + * + * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * I/O routine for unknown hardware. + */ + +static unsigned int unknown_handler(void) +{ + return 0; +} + +#define UNKNOWN_ALIAS(fn) \ + void unknown_##fn(void) __attribute__ ((alias ("unknown_handler"))); + +UNKNOWN_ALIAS(inb) +UNKNOWN_ALIAS(inw) +UNKNOWN_ALIAS(inl) +UNKNOWN_ALIAS(outb) +UNKNOWN_ALIAS(outw) +UNKNOWN_ALIAS(outl) +UNKNOWN_ALIAS(inb_p) +UNKNOWN_ALIAS(inw_p) +UNKNOWN_ALIAS(inl_p) +UNKNOWN_ALIAS(outb_p) +UNKNOWN_ALIAS(outw_p) +UNKNOWN_ALIAS(outl_p) +UNKNOWN_ALIAS(insb) +UNKNOWN_ALIAS(insw) +UNKNOWN_ALIAS(insl) +UNKNOWN_ALIAS(outsb) +UNKNOWN_ALIAS(outsw) +UNKNOWN_ALIAS(outsl) +UNKNOWN_ALIAS(readb) +UNKNOWN_ALIAS(readw) +UNKNOWN_ALIAS(readl) +UNKNOWN_ALIAS(writeb) +UNKNOWN_ALIAS(writew) +UNKNOWN_ALIAS(writel) +UNKNOWN_ALIAS(isa_port2addr) +UNKNOWN_ALIAS(ioremap) +UNKNOWN_ALIAS(ioremap_nocache) +UNKNOWN_ALIAS(iounmap) diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c index a353b0995..6451c4c9e 100644 --- a/arch/sh/kernel/irq.c +++ b/arch/sh/kernel/irq.c @@ -37,10 +37,6 @@ #include <asm/irq.h> #include <linux/irq.h> -#ifdef CONFIG_HD64461 -#include <asm/hd64461.h> -#endif - /* * Micro-access to controllers is serialized over the whole * system. We never hold this lock when we call the actual @@ -94,6 +90,7 @@ struct hw_interrupt_type no_irq_type = { * Generic, controller-independent functions: */ +#if defined(CONFIG_PROC_FS) int get_irq_list(char *buf) { int i, j; @@ -105,7 +102,7 @@ int get_irq_list(char *buf) p += sprintf(p, "CPU%d ",j); *p++ = '\n'; - for (i = 0 ; i < NR_IRQS ; i++) { + for (i = 0 ; i < ACTUAL_NR_IRQS ; i++) { action = irq_desc[i].action; if (!action) continue; @@ -120,6 +117,7 @@ int get_irq_list(char *buf) } return p - buf; } +#endif /* * This should really return information about whether @@ -243,18 +241,7 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5, "shlr %0\n\t" "add #-16, %0\n\t" :"=z" (irq)); -#if defined(CONFIG_HD64461) - if (irq == CONFIG_HD64461_IRQ) { - unsigned short bit; - unsigned short nirr = inw(HD64461_NIRR); - unsigned short nimr = inw(HD64461_NIMR); - nirr &= ~nimr; - for (bit = 1, irq = 0; irq < 16; bit <<= 1, irq++) - if (nirr & bit) break; - if (irq == 16) irq = CONFIG_HD64461_IRQ; - else irq += HD64461_IRQBASE; - } -#endif + irq = irq_demux(irq); kstat.irqs[cpu][irq]++; desc = irq_desc + irq; @@ -330,7 +317,7 @@ int request_irq(unsigned int irq, int retval; struct irqaction * action; - if (irq >= NR_IRQS) + if (irq >= ACTUAL_NR_IRQS) return -EINVAL; if (!handler) return -EINVAL; @@ -358,7 +345,7 @@ void free_irq(unsigned int irq, void *dev_id) struct irqaction **p; unsigned long flags; - if (irq >= NR_IRQS) + if (irq >= ACTUAL_NR_IRQS) return; spin_lock_irqsave(&irq_controller_lock,flags); @@ -408,7 +395,7 @@ unsigned long probe_irq_on(void) for (i = NR_IRQS-1; i > 0; i--) { if (!irq_desc[i].action) { irq_desc[i].status |= IRQ_AUTODETECT | IRQ_WAITING; - if(irq_desc[i].handler->startup(i)) + if (irq_desc[i].handler->startup(i)) irq_desc[i].status |= IRQ_PENDING; } } @@ -430,7 +417,7 @@ unsigned long probe_irq_on(void) if (!(status & IRQ_AUTODETECT)) continue; - + /* It triggered already - consider it spurious. */ if (!(status & IRQ_WAITING)) { irq_desc[i].status = status & ~IRQ_AUTODETECT; diff --git a/arch/sh/kernel/irq_imask.c b/arch/sh/kernel/irq_imask.c index 7237ba3b5..8ac95823b 100644 --- a/arch/sh/kernel/irq_imask.c +++ b/arch/sh/kernel/irq_imask.c @@ -8,6 +8,9 @@ * */ +/* NOTE: Will not work on level 15 */ + + #include <linux/ptrace.h> #include <linux/errno.h> #include <linux/kernel_stat.h> @@ -71,7 +74,7 @@ void static inline set_interrupt_registers(int ip) : "r" (~0xf0), "r" (ip << 4)); } -void disable_imask_irq(unsigned int irq) +static void disable_imask_irq(unsigned int irq) { clear_bit(irq, &imask_mask); if (interrupt_priority < IMASK_PRIORITY - irq) diff --git a/arch/sh/kernel/irq_ipr.c b/arch/sh/kernel/irq_ipr.c index 8b6b0f5ee..f229e8a12 100644 --- a/arch/sh/kernel/irq_ipr.c +++ b/arch/sh/kernel/irq_ipr.c @@ -21,6 +21,7 @@ #include <asm/system.h> #include <asm/io.h> +#include <asm/machvec.h> struct ipr_data { unsigned int addr; /* Address of Interrupt Priority Register */ @@ -29,15 +30,8 @@ struct ipr_data { }; 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); +static void disable_ipr_irq(unsigned int irq); /* shutdown is same as "disable" */ #define shutdown_ipr_irq disable_ipr_irq @@ -61,7 +55,7 @@ static struct hw_interrupt_type ipr_irq_type = { end_ipr_irq }; -void disable_ipr_irq(unsigned int irq) +static void disable_ipr_irq(unsigned int irq) { unsigned long val, flags; unsigned int addr = ipr_data[irq].addr; @@ -90,18 +84,11 @@ static void enable_ipr_irq(unsigned int irq) restore_flags(flags); } -void make_ipr_irq(unsigned int irq) -{ - disable_irq_nosync(irq); - irq_desc[irq].handler = &ipr_irq_type; - disable_ipr_irq(irq); -} - static void mask_and_ack_ipr(unsigned int irq) { disable_ipr_irq(irq); -#ifdef CONFIG_CPU_SUBTYPE_SH7709 +#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) /* This is needed when we use edge triggered setting */ /* XXX: Is it really needed? */ if (IRQ0_IRQ <= irq && irq <= IRQ5_IRQ) { @@ -118,18 +105,39 @@ static void end_ipr_irq(unsigned int irq) enable_ipr_irq(irq); } +void make_ipr_irq(unsigned int irq, unsigned int addr, int pos, int priority) +{ + disable_irq_nosync(irq); + ipr_data[irq].addr = addr; + ipr_data[irq].shift = pos*4; /* POSition (0-3) x 4 means shift */ + ipr_data[irq].priority = priority; + + irq_desc[irq].handler = &ipr_irq_type; + disable_ipr_irq(irq); +} + void __init init_IRQ(void) { - int i; + make_ipr_irq(TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY); + make_ipr_irq(RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY); - for (i = TIMER_IRQ; i < NR_IRQS; i++) { - irq_desc[i].handler = &ipr_irq_type; - } + make_ipr_irq(SCI_ERI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY); + make_ipr_irq(SCI_RXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY); + make_ipr_irq(SCI_TXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY); + +#ifdef SCIF_ERI_IRQ + make_ipr_irq(SCIF_ERI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY); + make_ipr_irq(SCIF_RXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY); + make_ipr_irq(SCIF_TXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY); +#endif - 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 IRDA_ERI_IRQ + make_ipr_irq(IRDA_ERI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY); + make_ipr_irq(IRDA_RXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY); + make_ipr_irq(IRDA_TXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY); +#endif -#ifdef CONFIG_CPU_SUBTYPE_SH7709 +#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) /* * Initialize the Interrupt Controller (INTC) * registers to their power on values @@ -161,11 +169,16 @@ void __init init_IRQ(void) * 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 */ + make_ipr_irq(IRQ0_IRQ, IRQ0_IRP_ADDR, IRQ0_IRP_POS, IRQ0_PRIORITY); + make_ipr_irq(IRQ1_IRQ, IRQ1_IRP_ADDR, IRQ1_IRP_POS, IRQ1_PRIORITY); + make_ipr_irq(IRQ2_IRQ, IRQ2_IRP_ADDR, IRQ2_IRP_POS, IRQ2_PRIORITY); + make_ipr_irq(IRQ3_IRQ, IRQ3_IRP_ADDR, IRQ3_IRP_POS, IRQ3_PRIORITY); + make_ipr_irq(IRQ4_IRQ, IRQ4_IRP_ADDR, IRQ4_IRP_POS, IRQ4_PRIORITY); + make_ipr_irq(IRQ5_IRQ, IRQ5_IRP_ADDR, IRQ5_IRP_POS, IRQ5_PRIORITY); +#endif /* CONFIG_CPU_SUBTYPE_SH7707 || CONFIG_CPU_SUBTYPE_SH7709 */ + + /* Perform the machine specific initialisation */ + if (sh_mv.mv_init_irq != NULL) { + sh_mv.mv_init_irq(); + } } diff --git a/arch/sh/kernel/led_se.c b/arch/sh/kernel/led_se.c new file mode 100644 index 000000000..0476f1bd8 --- /dev/null +++ b/arch/sh/kernel/led_se.c @@ -0,0 +1,67 @@ +/* + * linux/arch/sh/kernel/led_se.c + * + * Copyright (C) 2000 Stuart Menefy <stuart.menefy@st.com> + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * This file contains Solution Engine specific LED code. + */ + +#include <linux/config.h> + +static void mach_led(int position, int value) +{ + volatile unsigned short* p = (volatile unsigned short*)0xb0c00000; + + if (value) { + *p |= (1<<8); + } else { + *p &= ~(1<<8); + } +} + +#ifdef CONFIG_HEARTBEAT + +#include <linux/sched.h> + +/* Cycle the LED's in the clasic Knightrider/Sun pattern */ +void heartbeat_se(void) +{ + static unsigned int cnt = 0, period = 0; + volatile unsigned short* p = (volatile unsigned short*)0xb0c00000; + static unsigned bit = 0, up = 1; + + cnt += 1; + if (cnt < period) { + return; + } + + cnt = 0; + + /* Go through the points (roughly!): + * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110 + */ + period = 110 - ( (300<<FSHIFT)/ + ((avenrun[0]/5) + (3<<FSHIFT)) ); + + if (up) { + if (bit == 7) { + bit--; + up=0; + } else { + bit ++; + } + } else { + if (bit == 0) { + bit++; + up=1; + } else { + bit--; + } + } + *p = 1<<(bit+8); + +} +#endif /* CONFIG_HEARTBEAT */ diff --git a/arch/sh/kernel/mach_hp600.c b/arch/sh/kernel/mach_hp600.c new file mode 100644 index 000000000..6f68d1af7 --- /dev/null +++ b/arch/sh/kernel/mach_hp600.c @@ -0,0 +1,63 @@ +/* + * linux/arch/sh/kernel/mach_hp600.c + * + * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * Machine vector for the HP600 + */ + +#include <linux/init.h> + +#include <asm/machvec.h> +#include <asm/machvec_init.h> + +#include <asm/io_hd64461.h> +#include <asm/io_generic.h> +#include <asm/irq.h> + +/* + * The Machine Vector + */ + +struct sh_machine_vector mv_hp600 __initmv = { + mv_name: "HP600", + + mv_nr_irqs: 80, /* HD64461_IRQBASE+16, see hd64461.h */ + + mv_inb: hd64461_inb, + mv_inw: hd64461_inw, + mv_inl: hd64461_inl, + mv_outb: hd64461_outb, + mv_outw: hd64461_outw, + mv_outl: hd64461_outl, + + mv_inb_p: hd64461_inb_p, + mv_inw_p: hd64461_inw, + mv_inl_p: hd64461_inl, + mv_outb_p: hd64461_outb_p, + mv_outw_p: hd64461_outw, + mv_outl_p: hd64461_outl, + + mv_insb: hd64461_insb, + mv_insw: hd64461_insw, + mv_insl: hd64461_insl, + mv_outsb: hd64461_outsb, + mv_outsw: hd64461_outsw, + mv_outsl: hd64461_outsl, + + mv_readb: generic_readb, + mv_readw: generic_readw, + mv_readl: generic_readl, + mv_writeb: generic_writeb, + mv_writew: generic_writew, + mv_writel: generic_writel, + + mv_irq_demux: hd64461_irq_demux, + + mv_hw_hp600: 1, + mv_hw_hd64461: 1, +}; +ALIAS_MV(hp600) diff --git a/arch/sh/kernel/mach_se.c b/arch/sh/kernel/mach_se.c new file mode 100644 index 000000000..ce142a399 --- /dev/null +++ b/arch/sh/kernel/mach_se.c @@ -0,0 +1,80 @@ +/* + * linux/arch/sh/kernel/mach_se.c + * + * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * Machine vector for the Hitachi SolutionEngine + */ + +#include <linux/init.h> + +#include <asm/machvec.h> +#include <asm/machvec_init.h> + +#include <asm/io_se.h> + +void heartbeat_se(void); +void setup_se(void); +void init_se_IRQ(void); + +/* + * The Machine Vector + */ + +struct sh_machine_vector mv_se __initmv = { + mv_name: "SolutionEngine", + +#if defined(__SH4__) + mv_nr_irqs: 48, +#elif defined(CONFIG_CPU_SUBTYPE_SH7708) + mv_nr_irqs: 32, +#elif defined(CONFIG_CPU_SUBTYPE_SH7709) + mv_nr_irqs: 61, +#endif + + mv_inb: se_inb, + mv_inw: se_inw, + mv_inl: se_inl, + mv_outb: se_outb, + mv_outw: se_outw, + mv_outl: se_outl, + + mv_inb_p: se_inb_p, + mv_inw_p: se_inw, + mv_inl_p: se_inl, + mv_outb_p: se_outb_p, + mv_outw_p: se_outw, + mv_outl_p: se_outl, + + mv_insb: se_insb, + mv_insw: se_insw, + mv_insl: se_insl, + mv_outsb: se_outsb, + mv_outsw: se_outsw, + mv_outsl: se_outsl, + + mv_readb: se_readb, + mv_readw: se_readw, + mv_readl: se_readl, + mv_writeb: se_writeb, + mv_writew: se_writew, + mv_writel: se_writel, + + mv_ioremap: generic_ioremap, + mv_ioremap_nocache: generic_ioremap_nocache, + mv_iounmap: generic_iounmap, + + mv_isa_port2addr: se_isa_port2addr, + + mv_init_arch: setup_se, + mv_init_irq: init_se_IRQ, +#ifdef CONFIG_HEARTBEAT + mv_heartbeat: heartbeat_se, +#endif + + mv_hw_se: 1, +}; +ALIAS_MV(se) diff --git a/arch/sh/kernel/mach_unknown.c b/arch/sh/kernel/mach_unknown.c new file mode 100644 index 000000000..895a65c1d --- /dev/null +++ b/arch/sh/kernel/mach_unknown.c @@ -0,0 +1,68 @@ +/* + * linux/arch/sh/kernel/mach_unknown.c + * + * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * Machine specific code for an unknown machine (internal peripherials only) + */ + +#include <linux/init.h> + +#include <asm/machvec.h> +#include <asm/machvec_init.h> + +#include <asm/io_unknown.h> + +/* + * The Machine Vector + */ + +struct sh_machine_vector mv_unknown __initmv = { + mv_name: "Unknown", + +#if defined(__SH4__) + mv_nr_irqs: 48, +#elif defined(CONFIG_CPU_SUBTYPE_SH7708) + mv_nr_irqs: 32, +#elif defined(CONFIG_CPU_SUBTYPE_SH7709) + mv_nr_irqs: 61, +#endif + + mv_inb: unknown_inb, + mv_inw: unknown_inw, + mv_inl: unknown_inl, + mv_outb: unknown_outb, + mv_outw: unknown_outw, + mv_outl: unknown_outl, + + mv_inb_p: unknown_inb_p, + mv_inw_p: unknown_inw_p, + mv_inl_p: unknown_inl_p, + mv_outb_p: unknown_outb_p, + mv_outw_p: unknown_outw_p, + mv_outl_p: unknown_outl_p, + + mv_insb: unknown_insb, + mv_insw: unknown_insw, + mv_insl: unknown_insl, + mv_outsb: unknown_outsb, + mv_outsw: unknown_outsw, + mv_outsl: unknown_outsl, + + mv_readb: unknown_readb, + mv_readw: unknown_readw, + mv_readl: unknown_readl, + mv_writeb: unknown_writeb, + mv_writew: unknown_writew, + mv_writel: unknown_writel, + + mv_ioremap: unknown_ioremap, + mv_ioremap_nocache: unknown_ioremap_nocache, + mv_iounmap: unknown_iounmap, + + mv_isa_port2addr: unknown_isa_port2addr, +}; +ALIAS_MV(unknown) diff --git a/arch/sh/kernel/pci-sh.c b/arch/sh/kernel/pci-sh.c index 3613596f7..a4a6c6918 100644 --- a/arch/sh/kernel/pci-sh.c +++ b/arch/sh/kernel/pci-sh.c @@ -4,9 +4,22 @@ #include <linux/init.h> #include <linux/ioport.h> #include <linux/errno.h> +#include <asm/machvec.h> -unsigned long resource_fixup(struct pci_dev * dev, struct resource * res, - unsigned long start, unsigned long size) +void __init pcibios_init(void) { - return start; + if (sh_mv.mv_init_pci != NULL) { + sh_mv.mv_init_pci(); + } } + +/* Haven't done anything here as yet */ +char * __init pcibios_setup(char *str) +{ + return str; +} + +/* We don't have anything here to fixup */ +struct pci_fixup pcibios_fixups[] = { + {0, 0, 0, NULL} +}; diff --git a/arch/sh/kernel/semaphore.c b/arch/sh/kernel/semaphore.c index c958745b5..f733501c1 100644 --- a/arch/sh/kernel/semaphore.c +++ b/arch/sh/kernel/semaphore.c @@ -12,6 +12,8 @@ #include <asm/semaphore.h> #include <asm/semaphore-helper.h> +spinlock_t semaphore_wake_lock; + /* * Semaphores are implemented using a two-way counter: * The "count" variable is decremented for each process diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index be56f8570..aaea2e6df 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -30,13 +30,16 @@ #endif #include <linux/bootmem.h> #include <linux/console.h> +#include <linux/ctype.h> #include <asm/processor.h> #include <asm/page.h> #include <asm/pgtable.h> #include <asm/uaccess.h> #include <asm/system.h> #include <asm/io.h> +#include <asm/io_generic.h> #include <asm/smp.h> +#include <asm/machvec.h> #ifdef CONFIG_SH_EARLY_PRINTK #include <asm/sh_bios.h> #endif @@ -53,10 +56,18 @@ extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt */ extern int rd_image_start; /* starting block # of image */ #endif +#if defined(CONFIG_SH_GENERIC) || defined(CONFIG_SH_UNKNOWN) +struct sh_machine_vector sh_mv; +#endif + extern void fpu_init(void); extern int root_mountflags; extern int _text, _etext, _edata, _end; +#define MV_NAME_SIZE 32 + +static struct sh_machine_vector* __init get_mv_byname(const char* name); + /* * This is set up by the setup-routine at boot-time */ @@ -180,8 +191,10 @@ void sh_console_unregister(void) #endif - -static inline void parse_mem_cmdline (char ** cmdline_p) +static inline void parse_cmdline (char ** cmdline_p, char mv_name[MV_NAME_SIZE], + struct sh_machine_vector** mvp, + unsigned long *mv_io_base, + int *mv_mmio_enable) { char c = ' ', *to = command_line, *from = COMMAND_LINE; int len = 0; @@ -208,6 +221,35 @@ static inline void parse_mem_cmdline (char ** cmdline_p) memory_end = memory_start + mem_size; } } + if (c == ' ' && !memcmp(from, "sh_mv=", 6)) { + char* mv_end; + char* mv_comma; + int mv_len; + if (to != command_line) + to--; + from += 6; + mv_end = strchr(from, ' '); + if (mv_end == NULL) + mv_end = from + strlen(from); + + mv_comma = strchr(from, ','); + if ((mv_comma != NULL) && (mv_comma < mv_end)) { + int ints[3]; + get_options(mv_comma+1, ARRAY_SIZE(ints), ints); + *mv_io_base = ints[1]; + *mv_mmio_enable = ints[2]; + mv_len = mv_comma - from; + } else { + mv_len = mv_end - from; + } + if (mv_len > (MV_NAME_SIZE-1)) + mv_len = MV_NAME_SIZE-1; + memcpy(mv_name, from, mv_len); + mv_name[mv_len] = '\0'; + from = mv_end; + + *mvp = get_mv_byname(mv_name); + } c = *(from++); if (!c) break; @@ -221,6 +263,10 @@ static inline void parse_mem_cmdline (char ** cmdline_p) void __init setup_arch(char **cmdline_p) { + struct sh_machine_vector *mv = NULL; + char mv_name[MV_NAME_SIZE] = ""; + unsigned long mv_io_base = 0; + int mv_mmio_enable = 0; unsigned long bootmap_size; unsigned long start_pfn, max_pfn, max_low_pfn; @@ -248,7 +294,58 @@ void __init setup_arch(char **cmdline_p) data_resource.start = virt_to_bus(&_etext); data_resource.end = virt_to_bus(&_edata)-1; - parse_mem_cmdline(cmdline_p); + parse_cmdline(cmdline_p, mv_name, &mv, &mv_io_base, &mv_mmio_enable); + +#ifdef CONFIG_SH_GENERIC + if (mv == NULL) { + extern struct sh_machine_vector mv_unknown; + mv = &mv_unknown; + if (*mv_name != '\0') { + printk("Warning: Unsupported machine %s, using unknown\n", + mv_name); + } + } + sh_mv = *mv; +#endif +#ifdef CONFIG_SH_UNKNOWN + sh_mv = mv_unknown; +#endif + +#if defined(CONFIG_SH_GENERIC) || defined(CONFIG_SH_UNKNOWN) + if (mv_io_base != 0) { + sh_mv.mv_inb = generic_inb; + sh_mv.mv_inw = generic_inw; + sh_mv.mv_inl = generic_inl; + sh_mv.mv_outb = generic_outb; + sh_mv.mv_outw = generic_outw; + sh_mv.mv_outl = generic_outl; + + sh_mv.mv_inb_p = generic_inb_p; + sh_mv.mv_inw_p = generic_inw_p; + sh_mv.mv_inl_p = generic_inl_p; + sh_mv.mv_outb_p = generic_outb_p; + sh_mv.mv_outw_p = generic_outw_p; + sh_mv.mv_outl_p = generic_outl_p; + + sh_mv.mv_insb = generic_insb; + sh_mv.mv_insw = generic_insw; + sh_mv.mv_insl = generic_insl; + sh_mv.mv_outsb = generic_outsb; + sh_mv.mv_outsw = generic_outsw; + sh_mv.mv_outsl = generic_outsl; + + sh_mv.mv_isa_port2addr = generic_isa_port2addr; + generic_io_base = mv_io_base; + } + if (mv_mmio_enable != 0) { + sh_mv.mv_readb = generic_readb; + sh_mv.mv_readw = generic_readw; + sh_mv.mv_readl = generic_readl; + sh_mv.mv_writeb = generic_writeb; + sh_mv.mv_writew = generic_writew; + sh_mv.mv_writel = generic_writel; + } +#endif #define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) #define PFN_DOWN(x) ((x) >> PAGE_SHIFT) @@ -358,6 +455,11 @@ void __init setup_arch(char **cmdline_p) #endif #endif + /* Perform the machine specific initialisation */ + if (sh_mv.mv_init_arch != NULL) { + sh_mv.mv_init_arch(); + } + #if defined(__SH4__) /* We already grab/initialized FPU in head.S. Make it consisitent. */ init_task.used_math = 1; @@ -366,10 +468,32 @@ void __init setup_arch(char **cmdline_p) paging_init(); } +struct sh_machine_vector* __init get_mv_byname(const char* name) +{ + extern int strcasecmp(const char *, const char *); + extern long __machvec_start, __machvec_end; + struct sh_machine_vector *all_vecs = + (struct sh_machine_vector *)&__machvec_start; + + int i, n = ((unsigned long)&__machvec_end + - (unsigned long)&__machvec_start)/ + sizeof(struct sh_machine_vector); + + for (i = 0; i < n; ++i) { + struct sh_machine_vector *mv = &all_vecs[i]; + if (mv == NULL) + continue; + if (strcasecmp(name, mv->mv_name) == 0) { + return mv; + } + } + return NULL; +} + /* * Get CPU information for use by the procfs. */ - +#ifdef CONFIG_PROC_FS int get_cpuinfo(char *buffer) { char *p = buffer; @@ -384,6 +508,7 @@ int get_cpuinfo(char *buffer) p += sprintf(p, "bogomips\t: %lu.%02lu\n\n", (loops_per_sec+2500)/500000, ((loops_per_sec+2500)/5000) % 100); + p += sprintf(p, "Machine: %s\n", sh_mv.mv_name); #define PRINT_CLOCK(name, value) \ p += sprintf(p, name " clock: %d.%02dMHz\n", \ @@ -395,3 +520,4 @@ int get_cpuinfo(char *buffer) return p - buffer; } +#endif diff --git a/arch/sh/kernel/setup_cqreek.c b/arch/sh/kernel/setup_cqreek.c new file mode 100644 index 000000000..3e0422154 --- /dev/null +++ b/arch/sh/kernel/setup_cqreek.c @@ -0,0 +1,224 @@ +/* $Id: setup_cqreek.c,v 1.1 2000/08/05 06:25:23 gniibe Exp $ + * + * arch/sh/kernel/setup_cqreek.c + * + * Copyright (C) 2000 Niibe Yutaka + * + * CqREEK IDE/ISA Bridge Support. + * + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/irq.h> + +#include <asm/io.h> +#include <asm/io_generic.h> +#include <asm/irq.h> +#include <asm/machvec.h> +#include <asm/machvec_init.h> + +#define BRIDGE_FEATURE 0x0002 + +#define BRIDGE_IDE_CTRL 0x0018 +#define BRIDGE_IDE_INTR_LVL 0x001A +#define BRIDGE_IDE_INTR_MASK 0x001C +#define BRIDGE_IDE_INTR_STAT 0x001E + +#define BRIDGE_ISA_CTRL 0x0028 +#define BRIDGE_ISA_INTR_LVL 0x002A +#define BRIDGE_ISA_INTR_MASK 0x002C +#define BRIDGE_ISA_INTR_STAT 0x002E + +#define IDE_OFFSET 0xA4000000UL +#define ISA_OFFSET 0xA4A00000UL + +static unsigned long cqreek_port2addr(unsigned long port) +{ + if (0x0000<=port && port<=0x0040) + return IDE_OFFSET + port; + if ((0x01f0<=port && port<=0x01f7) || port == 0x03f6) + return IDE_OFFSET + port; + + return ISA_OFFSET + port; +} + +static void disable_cqreek_irq(unsigned int irq) +{ + unsigned long flags; + unsigned short mask; + + save_and_cli(flags); + /* Disable IRQ */ + mask = inw(BRIDGE_ISA_INTR_MASK) & ~(1 << irq); + outw_p(mask, BRIDGE_ISA_INTR_MASK); + restore_flags(flags); +} + +static void enable_cqreek_irq(unsigned int irq) +{ + unsigned long flags; + unsigned short mask; + + save_and_cli(flags); + /* Enable IRQ */ + mask = inw(BRIDGE_ISA_INTR_MASK) | (1 << irq); + outw_p(mask, BRIDGE_ISA_INTR_MASK); + restore_flags(flags); +} + +#define CLEAR_AT_ACCEPT + +static void mask_and_ack_cqreek(unsigned int irq) +{ + inw(BRIDGE_ISA_INTR_STAT); + disable_cqreek_irq(irq); +#ifdef CLEAR_AT_ACCEPT + /* Clear IRQ (it might be edge IRQ) */ + outw_p((1<<irq), BRIDGE_ISA_INTR_STAT); +#endif +} + +static void end_cqreek_irq(unsigned int irq) +{ +#ifndef CLEAR_AT_ACCEPT + /* Clear IRQ (it might be edge IRQ) */ + outw_p((1<<irq), BRIDGE_ISA_INTR_STAT); +#endif + enable_cqreek_irq(irq); +} + +static unsigned int startup_cqreek_irq(unsigned int irq) +{ + enable_cqreek_irq(irq); + return 0; +} + +static void shutdown_cqreek_irq(unsigned int irq) +{ + disable_cqreek_irq(irq); +} + +static struct hw_interrupt_type cqreek_irq_type = { + "CQREEK-IRQ", + startup_cqreek_irq, + shutdown_cqreek_irq, + enable_cqreek_irq, + disable_cqreek_irq, + mask_and_ack_cqreek, + end_cqreek_irq +}; + +static int has_ide, has_isa; + +/* XXX: This is just for test for my NE2000 ISA board + What we really need is virtualized IRQ and demultiplexer like HP600 port */ +void __init init_cqreek_IRQ(void) +{ + if (has_ide) + make_ipr_irq(14, IDE_OFFSET+BRIDGE_IDE_INTR_LVL, 0, 0x0f-14); + + if (has_isa) { + /* XXX: Err... we may need demultiplexer for ISA irq... */ + irq_desc[10].handler = &cqreek_irq_type; + irq_desc[10].status = IRQ_DISABLED; + irq_desc[10].action = 0; + irq_desc[10].depth = 1; + + disable_cqreek_irq(10); + } +} + +/* + * Initialize the board + */ +void __init setup_cqreek(void) +{ + int i; +/* udelay is not available at setup time yet... */ +#define DELAY() do {for (i=0; i<10000; i++) ctrl_inw(0xa0000000);} while(0) + + if ((inw (BRIDGE_FEATURE) & 1)) { /* We have IDE interface */ + outw_p(0, BRIDGE_IDE_INTR_LVL); + outw_p(0, BRIDGE_IDE_INTR_MASK); + + outw_p(0, BRIDGE_IDE_CTRL); + DELAY(); + + outw_p(0x8000, BRIDGE_IDE_CTRL); + DELAY(); + + outw_p(0xffff, BRIDGE_IDE_INTR_STAT); /* Clear interrupt status */ + outw_p(0x0f-14, BRIDGE_IDE_INTR_LVL); /* Use 14 IPR */ + outw_p(1, BRIDGE_IDE_INTR_MASK); /* Enable interrupt */ + has_ide=1; + } + + if ((inw (BRIDGE_FEATURE) & 2)) { /* We have ISA interface */ + outw_p(0, BRIDGE_ISA_INTR_LVL); + outw_p(0, BRIDGE_ISA_INTR_MASK); + + outw_p(0, BRIDGE_ISA_CTRL); + DELAY(); + outw_p(0x8000, BRIDGE_ISA_CTRL); + DELAY(); + + outw_p(0xffff, BRIDGE_ISA_INTR_STAT); /* Clear interrupt status */ + outw_p(0x0f-10, BRIDGE_ISA_INTR_LVL); /* Use 10 IPR */ + outw_p(0xfff8, BRIDGE_ISA_INTR_MASK); /* Enable interrupt */ + has_isa=1; + } + + printk(KERN_INFO "CqREEK Setup (IDE=%d, ISA=%d)...done\n", has_ide, has_isa); +} + +/* + * The Machine Vector + */ + +struct sh_machine_vector mv_cqreek __initmv = { + mv_name: "CqREEK", + +#if defined(__SH4__) + mv_nr_irqs: 48, +#elif defined(CONFIG_CPU_SUBTYPE_SH7708) + mv_nr_irqs: 32, +#elif defined(CONFIG_CPU_SUBTYPE_SH7709) + mv_nr_irqs: 61, +#endif + + mv_inb: generic_inb, + mv_inw: generic_inw, + mv_inl: generic_inl, + mv_outb: generic_outb, + mv_outw: generic_outw, + mv_outl: generic_outl, + + mv_inb_p: generic_inb_p, + mv_inw_p: generic_inw_p, + mv_inl_p: generic_inl_p, + mv_outb_p: generic_outb_p, + mv_outw_p: generic_outw_p, + mv_outl_p: generic_outl_p, + + mv_insb: generic_insb, + mv_insw: generic_insw, + mv_insl: generic_insl, + mv_outsb: generic_outsb, + mv_outsw: generic_outsw, + mv_outsl: generic_outsl, + + mv_readb: generic_readb, + mv_readw: generic_readw, + mv_readl: generic_readl, + mv_writeb: generic_writeb, + mv_writew: generic_writew, + mv_writel: generic_writel, + + mv_init_arch: setup_cqreek, + mv_init_irq: init_cqreek_IRQ, + + mv_port2addr: cqreek_port2addr, + mv_isa_port2addr: cqreek_port2addr, +}; +ALIAS_MV(cqreek) diff --git a/arch/sh/kernel/setup_hd64461.c b/arch/sh/kernel/setup_hd64461.c index 0ee07e887..6132e420d 100644 --- a/arch/sh/kernel/setup_hd64461.c +++ b/arch/sh/kernel/setup_hd64461.c @@ -92,6 +92,20 @@ static void hd64461_interrupt(int irq, void *dev_id, struct pt_regs *regs) inw(HD64461_NIRR), inw(HD64461_NIMR)); } +int hd64461_irq_demux(int irq) +{ + if (irq == CONFIG_HD64461_IRQ) { + unsigned short bit; + unsigned short nirr = inw(HD64461_NIRR); + unsigned short nimr = inw(HD64461_NIMR); + nirr &= ~nimr; + for (bit = 1, irq = 0; irq < 16; bit <<= 1, irq++) + if (nirr & bit) break; + if (irq == 16) irq = CONFIG_HD64461_IRQ; + else irq += HD64461_IRQBASE; + } + return irq; +} static struct irqaction irq0 = { hd64461_interrupt, SA_INTERRUPT, 0, "HD64461", NULL, NULL}; @@ -100,10 +114,13 @@ int __init setup_hd64461(void) { int i; + if (!MACH_HD64461) + return 0; + printk(KERN_INFO "HD64461 configured at 0x%x on irq %d(mapped into %d to %d)\n", CONFIG_HD64461_IOBASE, CONFIG_HD64461_IRQ, HD64461_IRQBASE, HD64461_IRQBASE+15); -#if 1 +#ifdef CONFIG_CPU_SUBTYPE_SH7709 /* IRQ line for HD64461 should be set level trigger mode("10"). */ /* And this should be done earlier than the kernel starts. */ ctrl_outw(0x0200, INTC_ICR1); /* when connected to IRQ4. */ diff --git a/arch/sh/kernel/setup_se.c b/arch/sh/kernel/setup_se.c index cd9436fff..8b2f59972 100644 --- a/arch/sh/kernel/setup_se.c +++ b/arch/sh/kernel/setup_se.c @@ -73,10 +73,8 @@ static void __init init_smsc(void) /* * Initialize IRQ setting */ -static void __init init_se_IRQ(void) +void __init init_se_IRQ(void) { - int i; - /* * Super I/O (Just mimic PC): * 1: keyboard @@ -88,43 +86,34 @@ static void __init init_se_IRQ(void) * 12: mouse * 14: ide0 */ - set_ipr_data(14, BCR_ILCRA, 2, 0x0f-14); - set_ipr_data(12, BCR_ILCRA, 1, 0x0f-12); - set_ipr_data( 8, BCR_ILCRB, 1, 0x0f- 8); - set_ipr_data( 6, BCR_ILCRC, 3, 0x0f- 6); - set_ipr_data( 5, BCR_ILCRC, 2, 0x0f- 5); - set_ipr_data( 4, BCR_ILCRC, 1, 0x0f- 4); - set_ipr_data( 3, BCR_ILCRC, 0, 0x0f- 3); - set_ipr_data( 1, BCR_ILCRD, 3, 0x0f- 1); - - set_ipr_data(10, BCR_ILCRD, 1, 0x0f-10); /* LAN */ - - 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 */ + make_ipr_irq(14, BCR_ILCRA, 2, 0x0f-14); + make_ipr_irq(12, BCR_ILCRA, 1, 0x0f-12); + make_ipr_irq( 8, BCR_ILCRB, 1, 0x0f- 8); + make_ipr_irq( 6, BCR_ILCRC, 3, 0x0f- 6); + make_ipr_irq( 5, BCR_ILCRC, 2, 0x0f- 5); + make_ipr_irq( 4, BCR_ILCRC, 1, 0x0f- 4); + make_ipr_irq( 3, BCR_ILCRC, 0, 0x0f- 3); + make_ipr_irq( 1, BCR_ILCRD, 3, 0x0f- 1); + + make_ipr_irq(10, BCR_ILCRD, 1, 0x0f-10); /* LAN */ + + make_ipr_irq( 0, BCR_ILCRE, 3, 0x0f- 0); /* PCIRQ3 */ + make_ipr_irq(11, BCR_ILCRE, 2, 0x0f-11); /* PCIRQ2 */ + make_ipr_irq( 9, BCR_ILCRE, 1, 0x0f- 9); /* PCIRQ1 */ + make_ipr_irq( 7, BCR_ILCRE, 0, 0x0f- 7); /* PCIRQ0 */ /* #2, #13 are allocated for SLOT IRQ #1 and #2 (for now) */ /* NOTE: #2 and #13 are not used on PC */ - set_ipr_data(13, BCR_ILCRG, 1, 0x0f-13); /* SLOTIRQ2 */ - set_ipr_data( 2, BCR_ILCRG, 0, 0x0f- 2); /* SLOTIRQ1 */ - - for (i = 0; i < 15; i++) { - make_ipr_irq(i); - } + make_ipr_irq(13, BCR_ILCRG, 1, 0x0f-13); /* SLOTIRQ2 */ + make_ipr_irq( 2, BCR_ILCRG, 0, 0x0f- 2); /* SLOTIRQ1 */ } + /* * Initialize the board */ -int __init setup_se(void) +void __init setup_se(void) { - init_se_IRQ(); init_smsc(); /* XXX: RTC setting comes here */ - - printk(KERN_INFO "Hitach SolutionEngine Setup...done\n"); - return 0; } - -module_init(setup_se); diff --git a/arch/sh/kernel/sh_bios.c b/arch/sh/kernel/sh_bios.c index a24b4a842..12f716249 100644 --- a/arch/sh/kernel/sh_bios.c +++ b/arch/sh/kernel/sh_bios.c @@ -1,4 +1,4 @@ -/* $Id$ +/* $Id: sh_bios.c,v 1.2 2000/07/26 04:37:32 gniibe Exp $ * * linux/arch/sh/kernel/sh_bios.c * C interface for trapping into the standard LinuxSH BIOS. diff --git a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c index 221af3022..9bdddc9d9 100644 --- a/arch/sh/kernel/signal.c +++ b/arch/sh/kernel/signal.c @@ -198,13 +198,16 @@ static inline int save_sigcontext_fpu(struct sigcontext *sc) { struct task_struct *tsk = current; unsigned long flags; + int val; if (!tsk->used_math) { - __copy_to_user(&sc->sc_ownedfp, 0, sizeof(int)); + val = 0; + __copy_to_user(&sc->sc_ownedfp, &val, sizeof(int)); return 0; } - __copy_to_user(&sc->sc_ownedfp, 1, sizeof(int)); + val = 1; + __copy_to_user(&sc->sc_ownedfp, &val, sizeof(int)); /* This will cause a "finit" to be triggered by the next attempted FPU operation by the 'current' process. diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c index 2c73255f4..f1e8d28bf 100644 --- a/arch/sh/kernel/time.c +++ b/arch/sh/kernel/time.c @@ -26,6 +26,7 @@ #include <asm/io.h> #include <asm/irq.h> #include <asm/delay.h> +#include <asm/machvec.h> #include <linux/timex.h> #include <linux/irq.h> @@ -226,6 +227,11 @@ static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *reg sh_do_profile(regs->pc); #endif +#ifdef CONFIG_HEARTBEAT + if (sh_mv.mv_heartbeat != NULL) + sh_mv.mv_heartbeat(); +#endif + /* * If we have an externally synchronized Linux clock, then update * RTC clock accordingly every ~11 minutes. Set_rtc_mmss() has to be @@ -441,11 +447,11 @@ void __init time_init(void) tmp = (frqcr & 0x2000) >> 11; tmp |= frqcr & 0x0003; pfc = pfc_table[tmp]; -#ifdef CONFIG_SH_HP600 - master_clock = cpu_clock/6; -#else - master_clock = cpu_clock; -#endif + if (MACH_HP600) { + master_clock = cpu_clock/6; + } else { + master_clock = cpu_clock; + } bus_clock = master_clock/pfc; } #elif defined(__SH4__) |