Commit 19ad546a authored by Yoshinori Sato's avatar Yoshinori Sato Committed by Linus Torvalds

[PATCH] h8300: interrupt management update

interrupt management update
target-support file update
gcc-3.3 support
blkdev location cleanup
parent 4f7a28bb
#
# h8300h/Makefile
#
# This file is included by the global makefile so that you can add your own
# platform-specific flags and dependencies.
#
# This file is subject to the terms and conditions of the GNU General Public
# License. See the file "COPYING" in the main directory of this archive
# for more details.
#
# Copyright (c) 2001 Lineo, Inc, <www.lineo.com>
# Copyright (c) 2000,2001 D. Jeff Dionne <jeff@lineo.ca>
# Copyright (c) 1998,1999 D. Jeff Dionne <jeff@uclinux.org>
# Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com>
# Copyright (C) 1994 Hamish Macdonald
#
# 68VZ328 Fixes By Evan Stawnyczy <e@lineo.ca>
# H8/300H Modify By Yoshinori Sato <ysato@users.sourceforge.jp>
CROSS_COMPILE = h8300-elf-
GCC_DIR = $(shell $(CC) -v 2>&1 | grep specs | sed -e 's/.* \(.*\)specs/\1\./')
INCGCC = $(GCC_DIR)/include
LIBGCC = $(GCC_DIR)/h8300h/int32/libgcc.a
CFLAGS := -fno-builtin -DNO_CACHE $(CFLAGS) -pipe -DNO_MM -DNO_FPU -DNO_CACHE -mh -mint32 -malign-300 -D__ELF__ -DNO_FORGET -DUTS_SYSNAME=\"uClinux\" -D__linux__ -DTARGET=$(BOARD)
AFLAGS := $(AFLAGS) -pipe -DNO_MM -DNO_FPU -DNO_CACHE -mh -D__ELF__ -DUTS_SYSNAME=\"uClinux\"
LINKFLAGS = -T arch/$(ARCH)/platform/$(PLATFORM)/$(BOARD)/$(MODEL).ld
LDFLAGS := $(LDFLAGS) -mh8300helf
HEAD := arch/$(ARCH)/platform/$(PLATFORM)/$(BOARD)/crt0_$(MODEL).o
SUBDIRS := arch/$(ARCH)/kernel arch/$(ARCH)/mm arch/$(ARCH)/lib \
arch/$(ARCH)/platform/$(PLATFORM) \
arch/$(ARCH)/platform/$(PLATFORM)/$(BOARD) \
$(SUBDIRS)
CORE_FILES := arch/$(ARCH)/kernel/kernel.o arch/$(ARCH)/mm/mm.o \
arch/$(ARCH)/platform/$(PLATFORM)/platform.o \
arch/$(ARCH)/platform/$(PLATFORM)/$(BOARD)/$(BOARD).o \
$(CORE_FILES)
LIBS += arch/$(ARCH)/lib/lib.a $(LIBGCC)
linux.bin: linux
$(OBJCOPY) -O binary linux linux.bin
archclean:
rm -f linux
...@@ -6,8 +6,7 @@ ...@@ -6,8 +6,7 @@
# unless it's something special (ie not a .c file). # unless it's something special (ie not a .c file).
# #
all: $(BOARD).o extra-y := crt0_ram.o
O_TARGET := $(BOARD).o
obj-y := timer.o obj-y := timer.o
timer.o: timer.c timer.o: timer.c
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* *
* Yoshinori Sato <ysato@users.sourceforge.jp> * Yoshinori Sato <ysato@users.sourceforge.jp>
* *
* Platform depend startup for uClinux-2.4.x * Platform depend startup
* Target Archtecture: AE-3068 (aka. aki3068net) * Target Archtecture: AE-3068 (aka. aki3068net)
* Memory Layout : RAM * Memory Layout : RAM
*/ */
...@@ -13,6 +13,16 @@ ...@@ -13,6 +13,16 @@
#include <linux/config.h> #include <linux/config.h>
#include <asm/linkage.h> #include <asm/linkage.h>
#if !defined(CONFIG_BLKDEV_RESERVE)
#if defined(CONFIG_GDB_DEBUG)
#define RAMEND (__ramend - 0xc000)
#else
#define RAMEND __ramend
#endif
#else
#define RAMEND CONFIG_BLKDEV_RESERVE_ADDRESS
#endif
.global SYMBOL_NAME(_start) .global SYMBOL_NAME(_start)
.global SYMBOL_NAME(command_line) .global SYMBOL_NAME(command_line)
.global SYMBOL_NAME(_platform_gpio_table) .global SYMBOL_NAME(_platform_gpio_table)
...@@ -25,23 +35,28 @@ ...@@ -25,23 +35,28 @@
/* CPU Reset entry */ /* CPU Reset entry */
SYMBOL_NAME_LABEL(_start) SYMBOL_NAME_LABEL(_start)
mov.l #__ramend,sp mov.l #RAMEND,sp
ldc #0x80,ccr ldc #0x80,ccr
/* Peripheral Setup */ /* Peripheral Setup */
#if defined(CONFIG_BLK_DEV_BLKMEM)
/* move romfs image */
jsr @__move_romfs
#endif
/* .bss clear */ /* .bss clear */
mov.l #__sbss,er5 mov.l #__sbss,er5
mov.l er5,er6
inc.l #1,er6
mov.l #__ebss,er4 mov.l #__ebss,er4
sub.l er5,er4 sub.l er5,er4
sub.w r0,r0 shlr er4
mov.b r0l,@er5 shlr er4
sub.l er0,er0
1: 1:
eepmov.w mov.l er0,@er5
dec.w #1,e4 adds #4,er5
bpl 1b dec.l #1,er4
bne 1b
/* copy kernel commandline */ /* copy kernel commandline */
mov.l #COMMAND_START,er5 mov.l #COMMAND_START,er5
...@@ -49,22 +64,9 @@ SYMBOL_NAME_LABEL(_start) ...@@ -49,22 +64,9 @@ SYMBOL_NAME_LABEL(_start)
mov.w #512,r4 mov.w #512,r4
eepmov.w eepmov.w
/* RAM Interrupt Vector Table Setup */
#if defined(CONFIG_GDB_DEBUG)
mov.l @SYMBOL_NAME(interrupt_redirect_table)+11*4,er0
#endif
mov.l #SYMBOL_NAME(_vector_lma),er5
mov.l #SYMBOL_NAME(interrupt_redirect_table),er6
mov.w #0x100,r4
eepmov.w
#if defined(CONFIG_GDB_DEBUG)
mov.l er0,@SYMBOL_NAME(interrupt_redirect_table)+11*4
#endif
/* uClinux kernel start */ /* uClinux kernel start */
ldc #0x90,ccr /* running kernel */ ldc #0x90,ccr /* running kernel */
mov.l #SYMBOL_NAME(init_task_union),sp mov.l #SYMBOL_NAME(init_thread_union),sp
mov.l sp,@SYMBOL_NAME(_current_task)
add.l #0x2000,sp add.l #0x2000,sp
jsr @_start_kernel jsr @_start_kernel
_exit: _exit:
......
...@@ -5,86 +5,7 @@ ENTRY("__start") ...@@ -5,86 +5,7 @@ ENTRY("__start")
MEMORY MEMORY
{ {
ram : ORIGIN = 0x400000, LENGTH = 0x600000-0x400000-0x80000 ram : ORIGIN = 0x400000, LENGTH = 0x600000-0x400000
disk : ORIGIN = 0x600000-0x80000, LENGTH = 0x60000
eram : ORIGIN = 0x600000, LENGTH = 0 eram : ORIGIN = 0x600000, LENGTH = 0
iram : ORIGIN = 0xffbf20, LENGTH = 0x4000 iram : ORIGIN = 0xffbf20, LENGTH = 0x4000
} }
SECTIONS
{
.bootvec :
{
*(.bootvec)
} > ram
.text :
{
__stext = . ;
*(.text)
. = ALIGN(0x4) ;
*(.text.*)
. = ALIGN(0x4) ;
*(.kstrtab)
. = ALIGN(0x4) ;
*(.rodata*)
. = ALIGN(16); /* Exception table */
___start___ex_table = .;
*(__ex_table)
___stop___ex_table = .;
___start___ksymtab = .; /* Kernel symbol table */
*(__ksymtab)
___stop___ksymtab = .;
. = ALIGN(0x4) ;
__etext = . ;
} > ram
.data :
{
__sdata = . ;
___data_start = . ;
*(.data)
*(.data.*)
*(.exitcall.exit)
. = ALIGN(0x2000) ;
*(.data.init_task)
. = ALIGN(0x2000) ;
___init_begin = .;
*(.text.init)
*(.data.init)
. = ALIGN(16);
___setup_start = .;
*(.setup.init)
___setup_end = .;
___initcall_start = .;
*(.initcall.init)
. = ALIGN(4) ;
___initcall_end = .;
___init_end = .;
__edata = . ;
. = ALIGN(0x4) ;
__sbss = . ;
*(.bss)
. = ALIGN(0x4) ;
*(COMMON)
. = ALIGN(0x4) ;
__ebss = . ;
__end = . ;
__ramstart = .;
} > ram
.blkimg :
{
__ramend = . ;
__blkimg = . ;
} > disk
.ram_vec : AT(ADDR(.data) + SIZEOF(.data))
{
*(.int_redirect)
} > iram
__vector_lma = LOADADDR(.ram_vec);
.dummy2 :
{
COMMAND_START = . - 0x200 ;
} > eram
}
...@@ -14,29 +14,32 @@ ...@@ -14,29 +14,32 @@
#include <linux/param.h> #include <linux/param.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/timex.h>
#include <asm/segment.h> #include <asm/segment.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/regs306x.h>
#include <linux/timex.h>
#define TMR8CMA2 0x00ffff94
#define TMR8TCSR2 0x00ffff92
#define TMR8TCNT2 0x00ffff90
#define CMFA 6 #define CMFA 6
int platform_timer_setup(void (*timer_int)(int, void *, struct pt_regs *)) extern int request_irq_boot(unsigned int,
irqreturn_t (*handler)(int, void *, struct pt_regs *),
unsigned long, const char *, void *);
void __init platform_timer_setup(irqreturn_t (*timer_int)(int, void *, struct pt_regs *))
{ {
outb(CONFIG_CLK_FREQ*10/8192,TMR8CMA2); outb(H8300_TIMER_COUNT_DATA,TCORA2);
outb(0x00,TMR8TCSR2); outb(0x00,_8TCSR2);
request_irq(40,timer_int,0,"timer",0); request_irq_boot(40,timer_int,0,"timer",0);
outb(0x40|0x08|0x03,TMR8TCNT2); outb(0x40|0x08|0x03,_8TCR2);
} }
void platform_timer_eoi(void) void platform_timer_eoi(void)
{ {
*(unsigned char *)TMR8TCSR2 &= ~(1 << CMFA); *(volatile unsigned char *)_8TCSR2 &= ~(1 << CMFA);
} }
void platform_gettod(int *year, int *mon, int *day, int *hour, void platform_gettod(int *year, int *mon, int *day, int *hour,
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
* linux/arch/h8300/platform/h8300h/entry.S * linux/arch/h8300/platform/h8300h/entry.S
* *
* Yoshinori Sato <ysato@users.sourceforge.jp> * Yoshinori Sato <ysato@users.sourceforge.jp>
* David McCullough <davidm@snapgear.com>
* *
*/ */
...@@ -29,14 +30,17 @@ SOFTIRQ_PENDING = 0 ...@@ -29,14 +30,17 @@ SOFTIRQ_PENDING = 0
/* the following macro is used when enabling interrupts */ /* the following macro is used when enabling interrupts */
LER3 = 0 LER4 = 0
LER2 = 4 LER5 = 4
LER1 = 8 LER6 = 8
LORIG = 12 LER3 = 12
LCCR = 16 LER2 = 16
LER0 = 18 LER1 = 20
LVEC = 22 LORIG = 24
LRET = 24 LCCR = 28
LER0 = 30
LVEC = 34
LRET = 38
.h8300h .h8300h
...@@ -44,100 +48,123 @@ LRET = 24 ...@@ -44,100 +48,123 @@ LRET = 24
.macro SAVE_ALL .macro SAVE_ALL
mov.l er0,@-sp mov.l er0,@-sp
stc ccr,r0l
stc ccr,r0l /* check kernel mode */
orc #0x10,ccr orc #0x10,ccr
btst #4,r0l btst #4,r0l
bne 1f bne 5f
mov.l sp,@SYMBOL_NAME(sw_usp)
mov.l sp,@SYMBOL_NAME(sw_usp) /* user mode */
mov.l @sp,er0 mov.l @sp,er0
mov.l @SYMBOL_NAME(sw_ksp),sp mov.l @SYMBOL_NAME(sw_ksp),sp
sub.l #(LRET-LORIG),sp /* allocate LORIG - LRET */
mov.l er0,@-sp mov.l er0,@-sp
stc ccr,r0l mov.l er1,@-sp
and #0xef,r0l mov.l @SYMBOL_NAME(sw_usp),er0
mov.w r0,@-sp mov.l @(8:16,er0),er1 /* copy the RET addr */
mov.l @(2:16,sp),er0 mov.l er1,@(LRET-LER1:16,sp)
bra 2f
1: mov.w e1,r1 /* e1 highbyte = ccr */
mov.l @sp,er0 and #0xef,r1h /* mask mode? flag */
stc ccr,@-sp sub.w r0,r0
2: mov.b r1h,r0l
mov.w r0,@(LCCR-LER1:16,sp) /* copy ccr */
mov.l @(LORIG-LER1:16,sp),er0
mov.l er0,@(LER0-LER1:16,sp) /* copy ER0 */
bra 6f
5:
mov.l @sp,er0 /* kernel mode */
subs #2,sp /* dummy ccr */
mov.l er0,@-sp mov.l er0,@-sp
mov.l er1,@-sp mov.l er1,@-sp
mov.w @(LRET-LER1:16,sp),r1 /* copy old ccr */
mov.b r1h,r1l
mov.b #0,r1h
mov.w r1,@(LCCR-LER1:16,sp) /* set ccr */
6:
mov.l er2,@-sp mov.l er2,@-sp
mov.l er3,@-sp mov.l er3,@-sp
mov.l er6,@-sp /* syscall arg #6 */
mov.l er5,@-sp /* syscall arg #5 */
mov.l er4,@-sp /* syscall arg #4 */
.endm .endm
.macro RESTORE_REGS .macro RESTORE_ALL
mov.w @(LCCR:16,sp),r0 mov.l @sp+,er4
mov.l @sp+,er5
mov.l @sp+,er6
mov.l @sp+,er3
mov.l @sp+,er2
mov.w @(LCCR-LER1:16,sp),r0 /* check kernel mode */
btst #4,r0l btst #4,r0l
bne 1f bne 7f
orc #0x80,ccr
mov.l @SYMBOL_NAME(sw_usp),er0 mov.l @SYMBOL_NAME(sw_usp),er0
mov.l @(LER0:16,sp),er1 mov.l @(LER0-LER1:16,sp),er1 /* restore ER0 */
mov.l er1,@er0 mov.l er1,@er0
mov.l @sp+,er3 mov.w @(LCCR-LER1:16,sp),r1 /* restore the RET addr */
mov.l @sp+,er2 mov.b r1l,r1h
mov.b @(LRET+1-LER1:16,sp),r1l
mov.w r1,e1
mov.w @(LRET+2-LER1:16,sp),r1
mov.l er1,@(8:16,er0)
mov.l @sp+,er1 mov.l @sp+,er1
add.l #10,sp add.l #(LRET-LORIG),sp /* remove LORIG - LRET */
mov.l sp,@SYMBOL_NAME(sw_ksp) mov.l sp,@SYMBOL_NAME(sw_ksp)
mov.l er0,sp mov.l er0,sp
bra 2f bra 8f
1: 7:
mov.l @sp+,er3
mov.l @sp+,er2
mov.l @sp+,er1 mov.l @sp+,er1
adds #4,sp adds #4,sp
adds #2,sp adds #2,sp
2: 8:
mov.l @sp+,er0 mov.l @sp+,er0
adds #4,sp adds #4,sp /* remove the sw created LVEC */
.endm
.macro RESTORE_ALL
RESTORE_REGS
rte rte
.endm .endm
#define SWITCH_STACK_SIZE (3*4+12) /* includes return address */
.macro SAVE_SWITCH_STACK
mov.l er4,@-sp
mov.l er5,@-sp
mov.l er6,@-sp
.endm
.macro RESTORE_SWITCH_STACK
mov.l @sp+,er6
mov.l @sp+,er5
mov.l @sp+,er4
.endm
.globl SYMBOL_NAME(system_call) .globl SYMBOL_NAME(system_call)
.globl SYMBOL_NAME(ret_from_exception) .globl SYMBOL_NAME(ret_from_exception)
.globl SYMBOL_NAME(ret_from_fork)
.globl SYMBOL_NAME(ret_from_signal) .globl SYMBOL_NAME(ret_from_signal)
.globl SYMBOL_NAME(ret_from_interrupt), SYMBOL_NAME(bad_interrupt) .globl SYMBOL_NAME(ret_from_interrupt)
.globl SYMBOL_NAME(interrupt_redirect_table) .globl SYMBOL_NAME(interrupt_redirect_table)
.globl SYMBOL_NAME(sw_ksp),SYMBOL_NAME(sw_usp) .globl SYMBOL_NAME(sw_ksp),SYMBOL_NAME(sw_usp)
.globl SYMBOL_NAME(resume) .globl SYMBOL_NAME(resume)
.globl SYMBOL_NAME(sys_vfork)
.globl SYMBOL_NAME(syscall_trampoline) .globl SYMBOL_NAME(syscall_trampoline)
.globl SYMBOL_NAME(interrupt_redirect_table)
.globl SYMBOL_NAME(interrupt_entry)
.globl SYMBOL_NAME(system_call)
.globl SYMBOL_NAME(trace_break)
#if defined(CONFIG_ROMKERNEL)
INTERRUPTS = 64
.section .int_redirect,"ax" .section .int_redirect,"ax"
SYMBOL_NAME_LABEL(interrupt_redirect_table) SYMBOL_NAME_LABEL(interrupt_redirect_table)
.rept 7 .rept 7
.long 0 .long 0
.endr .endr
jsr @interrupt_entry /* NMI */ jsr @SYMBOL_NAME(interrupt_entry) /* NMI */
jmp @SYMBOL_NAME(system_call) /* TRAPA #0 (System call) */ jmp @SYMBOL_NAME(system_call) /* TRAPA #0 (System call) */
.long 0 .long 0
.long 0 .long 0
jmp @SYMBOL_NAME(trace_break) /* TRAPA #3 (breakpoint) */ jmp @SYMBOL_NAME(trace_break) /* TRAPA #3 (breakpoint) */
.rept 64-12 .rept INTERRUPTS-12
jsr @interrupt_entry jsr @SYMBOL_NAME(interrupt_entry)
.endr .endr
#endif
#if defined(CONFIG_RAMKERNEL)
.globl SYMBOL_NAME(interrupt_redirect_table)
.section .bss
SYMBOL_NAME_LABEL(interrupt_redirect_table)
.space 4
#endif
.section .text .section .text
.align 2 .align 2
interrupt_entry: SYMBOL_NAME_LABEL(interrupt_entry)
SAVE_ALL SAVE_ALL
mov.w @(LCCR,sp),r0 mov.w @(LCCR,sp),r0
btst #4,r0l btst #4,r0l
...@@ -148,11 +175,18 @@ interrupt_entry: ...@@ -148,11 +175,18 @@ interrupt_entry:
1: 1:
mov.l @(LVEC,sp),er0 mov.l @(LVEC,sp),er0
2: 2:
#if defined(CONFIG_ROMKERNEL)
sub.l #SYMBOL_NAME(interrupt_redirect_table),er0 sub.l #SYMBOL_NAME(interrupt_redirect_table),er0
#endif
#if defined(CONFIG_RAMKERNEL)
mov.l @SYMBOL_NAME(interrupt_redirect_table),er1
sub.l er1,er0
#endif
shlr.l er0 shlr.l er0
shlr.l er0 shlr.l er0
dec.l #1,er0 dec.l #1,er0
mov.l sp,er1 mov.l sp,er1
subs #4,er1 /* adjust ret_pc */
jsr @SYMBOL_NAME(process_int) jsr @SYMBOL_NAME(process_int)
mov.l @SYMBOL_NAME(irq_stat)+SOFTIRQ_PENDING,er0 mov.l @SYMBOL_NAME(irq_stat)+SOFTIRQ_PENDING,er0
beq 1f beq 1f
...@@ -161,100 +195,70 @@ interrupt_entry: ...@@ -161,100 +195,70 @@ interrupt_entry:
jmp @SYMBOL_NAME(ret_from_exception) jmp @SYMBOL_NAME(ret_from_exception)
SYMBOL_NAME_LABEL(system_call) SYMBOL_NAME_LABEL(system_call)
subs #4,sp subs #4,sp /* dummy LVEC */
SAVE_ALL SAVE_ALL
mov.l er0,er3 mov.w @(LCCR:16,sp),r1
bset #4,r1l
ldc r1l,ccr
mov.l er0,er4
mov.l #-ENOSYS,er0 mov.l #-ENOSYS,er0
mov.l er0,@(LER0:16,sp) mov.l er0,@(LER0:16,sp)
/* save top of frame */ /* save top of frame */
mov.l sp,er0 mov.l sp,er0
mov.l er3,@-sp
jsr @SYMBOL_NAME(set_esp0) jsr @SYMBOL_NAME(set_esp0)
mov.l @sp+,er3 cmp.l #NR_syscalls,er4
cmp.l #NR_syscalls,er3
bcc SYMBOL_NAME(ret_from_exception):16 bcc SYMBOL_NAME(ret_from_exception):16
shll.l er3 shll.l er4
shll.l er3 shll.l er4
mov.l #SYMBOL_NAME(sys_call_table),er0 mov.l #SYMBOL_NAME(sys_call_table),er0
add.l er3,er0 add.l er4,er0
mov.l @er0,er0 mov.l @er0,er4
mov.l er0,er3
beq SYMBOL_NAME(ret_from_exception):16 beq SYMBOL_NAME(ret_from_exception):16
mov.l @SYMBOL_NAME(_current_task),er2 mov.l sp,er2
and.w #0xe000,r2
mov.b @((TASK_FLAGS+3-(TIF_SYSCALL_TRACE >> 3)):16,er2),r2l mov.b @((TASK_FLAGS+3-(TIF_SYSCALL_TRACE >> 3)):16,er2),r2l
btst #(TIF_SYSCALL_TRACE & 7),r2l btst #(TIF_SYSCALL_TRACE & 7),r2l
bne 1f bne 1f
mov.l @(LER1:16,sp),er0 mov.l @(LER1:16,sp),er0
mov.l @(LER2:16,sp),er1 mov.l @(LER2:16,sp),er1
mov.l @(LER3:16,sp),er2 mov.l @(LER3:16,sp),er2
mov.l er5,@-sp jsr @er4
mov.l er4,@-sp
jsr @er3
adds #4,sp
adds #4,sp
mov.l er0,@(LER0,sp) /* save the return value */ mov.l er0,@(LER0,sp) /* save the return value */
#if defined(CONFIG_SYSCALL_PRINT) #if defined(CONFIG_SYSCALL_PRINT)
jsr @SYMBOL_NAME(syscall_print) jsr @SYMBOL_NAME(syscall_print)
#endif #endif
jmp @SYMBOL_NAME(ret_from_exception) jmp @SYMBOL_NAME(ret_from_exception)
1: 1:
SAVE_SWITCH_STACK
mov.l er3,er5 /* save syscall entry */
jsr SYMBOL_NAME(syscall_trace) jsr SYMBOL_NAME(syscall_trace)
mov.l er5,er3
RESTORE_SWITCH_STACK
mov.l @(LER1:16,sp),er0 mov.l @(LER1:16,sp),er0
mov.l @(LER2:16,sp),er1 mov.l @(LER2:16,sp),er1
mov.l @(LER3:16,sp),er2 mov.l @(LER3:16,sp),er2
mov.l er5,@-sp jsr @er4
mov.l er4,@-sp
jsr @er3
adds #4,sp
adds #4,sp
mov.l er0,@(LER0:16,sp) /* save the return value */ mov.l er0,@(LER0:16,sp) /* save the return value */
SAVE_SWITCH_STACK
jsr SYMBOL_NAME(syscall_trace) jsr SYMBOL_NAME(syscall_trace)
SYMBOL_NAME_LABEL(ret_from_signal) SYMBOL_NAME_LABEL(ret_from_signal)
RESTORE_SWITCH_STACK
SYMBOL_NAME_LABEL(ret_from_exception) SYMBOL_NAME_LABEL(ret_from_exception)
mov.b @(LCCR+1:16,sp),r0l mov.b @(LCCR+1:16,sp),r0l
btst #4,r0l /* check if returning to kernel */ btst #4,r0l /* check if returning to kernel */
bne 3f /* if so, skip resched, signals */ bne 3f /* if so, skip resched, signals */
andc #0x7f,ccr andc #0x7f,ccr
mov.l @SYMBOL_NAME(_current_task),er0 mov.l sp,er2
and.w #0xe000,r2
mov.l @(TI_FLAGS:16,er2),er1 mov.l @(TI_FLAGS:16,er2),er1
and.l #_TIF_WORK_MASK,er1 and.l #_TIF_WORK_MASK,er1
bne 1f beq 3f
mov.l @((TASK_THREAD+THREAD_VFORK):16,er0),er1
bne Lvfork_return
3:
RESTORE_ALL /* Does RTE */
1: 1:
mov.l @(TI_FLAGS:16,er2),er1 mov.l @(TI_FLAGS:16,er2),er1
btst #TIF_NEED_RESCHED,r1l btst #TIF_NEED_RESCHED,r1l
bne @SYMBOL_NAME(reschedule):16 bne @SYMBOL_NAME(reschedule):16
Lsignal_return:
SAVE_SWITCH_STACK
mov.l sp,er1 mov.l sp,er1
add #12,er1
mov.l er2,er0 mov.l er2,er0
jsr @SYMBOL_NAME(do_signal) jsr @SYMBOL_NAME(do_signal)
RESTORE_SWITCH_STACK 3:
mov.l @SYMBOL_NAME(_current_task),er0 RESTORE_ALL /* Does RTE */
mov.l @((TASK_THREAD+THREAD_VFORK):16,er0),er1
bne Lvfork_return
RESTORE_ALL
Lvfork_return:
sub.l er2,er2
mov.l er2,@((TASK_THREAD+THREAD_VFORK):16,er0)
mov.l @SYMBOL_NAME(sw_usp),er0
mov.l er1,@(8:16,er0)
RESTORE_ALL
SYMBOL_NAME_LABEL(reschedule) SYMBOL_NAME_LABEL(reschedule)
/* save top of frame */ /* save top of frame */
...@@ -265,6 +269,11 @@ SYMBOL_NAME_LABEL(reschedule) ...@@ -265,6 +269,11 @@ SYMBOL_NAME_LABEL(reschedule)
mov.l er0,@-sp mov.l er0,@-sp
jmp @SYMBOL_NAME(schedule) jmp @SYMBOL_NAME(schedule)
SYMBOL_NAME_LABEL(ret_from_fork)
mov.l er2,er0
jsr @SYMBOL_NAME(schedule_tail)
jmp @SYMBOL_NAME_LABEL(ret_from_exception)
SYMBOL_NAME_LABEL(resume) SYMBOL_NAME_LABEL(resume)
/* /*
* Beware - when entering resume, offset of tss is in d1, * Beware - when entering resume, offset of tss is in d1,
...@@ -277,8 +286,7 @@ SYMBOL_NAME_LABEL(resume) ...@@ -277,8 +286,7 @@ SYMBOL_NAME_LABEL(resume)
/* save sr */ /* save sr */
sub.w r3,r3 sub.w r3,r3
stc ccr,r3l stc ccr,r3l
mov.w r3,@(THREAD_CCR:16,er0) mov.w r3,@(THREAD_CCR+2:16,er0)
SAVE_SWITCH_STACK
/* disable interrupts */ /* disable interrupts */
orc #0x80,ccr orc #0x80,ccr
...@@ -286,30 +294,17 @@ SYMBOL_NAME_LABEL(resume) ...@@ -286,30 +294,17 @@ SYMBOL_NAME_LABEL(resume)
mov.l er3,@(THREAD_USP:16,er0) mov.l er3,@(THREAD_USP:16,er0)
mov.l sp,@(THREAD_KSP:16,er0) mov.l sp,@(THREAD_KSP:16,er0)
/* get pointer to tss struct (a1 contains new task) */
mov.l er1,@SYMBOL_NAME(_current_task)
/* Skip address space switching if they are the same. */ /* Skip address space switching if they are the same. */
/* FIXME: what did we hack out of here, this does nothing! */ /* FIXME: what did we hack out of here, this does nothing! */
mov.l @(THREAD_USP:16,er1),er0 mov.l @(THREAD_USP:16,er1),er0
mov.l er0,@SYMBOL_NAME(sw_usp) mov.l er0,@SYMBOL_NAME(sw_usp)
mov.l @(THREAD_KSP:16,er1),sp mov.l @(THREAD_KSP:16,er1),sp
RESTORE_SWITCH_STACK
/* restore status register */ /* restore status register */
mov.w @(THREAD_CCR:16,er1),r3 mov.w @(THREAD_CCR+2:16,er1),r3
ldc r3l,ccr ldc r3l,ccr
rts
/* Handler for uninitialized and spurious interrupts */
SYMBOL_NAME_LABEL(bad_interrupt)
mov.l @SYMBOL_NAME(num_spurious),er0
inc.l #1,er0
mov.l er0,@SYMBOL_NAME(num_spurious)
rts rts
SYMBOL_NAME_LABEL(trace_break) SYMBOL_NAME_LABEL(trace_break)
...@@ -329,26 +324,10 @@ SYMBOL_NAME_LABEL(trace_break) ...@@ -329,26 +324,10 @@ SYMBOL_NAME_LABEL(trace_break)
jsr @SYMBOL_NAME(trace_trap) jsr @SYMBOL_NAME(trace_trap)
jmp @SYMBOL_NAME(ret_from_exception) jmp @SYMBOL_NAME(ret_from_exception)
SYMBOL_NAME_LABEL(sys_vfork)
SAVE_SWITCH_STACK
mov.l @SYMBOL_NAME(sw_usp),er6
mov.l @(8:16,er6),er6
mov.l sp,er0
add.l #SWITCH_STACK_SIZE,er0
jsr @SYMBOL_NAME(h8300_vfork)
mov.l @SYMBOL_NAME(_current_task),er5
mov.l er6,@((TASK_THREAD+THREAD_VFORK):16,er5)
RESTORE_SWITCH_STACK
rts
SYMBOL_NAME_LABEL(syscall_trampoline) SYMBOL_NAME_LABEL(syscall_trampoline)
SAVE_SWITCH_STACK
mov.l er0,er6 mov.l er0,er6
mov.l sp,er0 mov.l sp,er0
add.l #SWITCH_STACK_SIZE,er0 jmp @er6
jsr @er6
RESTORE_SWITCH_STACK
rts
.section .bss .section .bss
SYMBOL_NAME_LABEL(sw_ksp) SYMBOL_NAME_LABEL(sw_ksp)
......
...@@ -6,7 +6,8 @@ ...@@ -6,7 +6,8 @@
# unless it's something special (ie not a .c file). # unless it's something special (ie not a .c file).
# #
obj-y := timer.o crt0_$(MODEL).o obj-y := timer.o
extra-y = crt0_$(MODEL).o
clean: clean:
rm -f *.[oa] rm -f *.[oa]
/*
* linux/arch/h8300/platform/h8300h/generic/crt0_ram.S
*
* Yoshinori Sato <ysato@users.sourceforge.jp>
*
* Platform depend startup
* Target Archtecture: AE-3068 (aka. aki3068net)
* Memory Layout : RAM
*/
#define ASSEMBLY
#include <linux/config.h>
#include <asm/linkage.h>
#if !defined(CONFIG_BLKDEV_RESERVE)
#if defined(CONFIG_GDB_DEBUG)
#define RAMEND (__ramend - 0xc000)
#else
#define RAMEND __ramend
#endif
#else
#define RAMEND CONFIG_BLKDEV_RESERVE_ADDRESS
#endif
.global SYMBOL_NAME(_start)
.global SYMBOL_NAME(command_line)
.global SYMBOL_NAME(_platform_gpio_table)
.global SYMBOL_NAME(_target_name)
.h8300h
.section .text
.file "crt0_ram.S"
/* CPU Reset entry */
SYMBOL_NAME_LABEL(_start)
mov.l #RAMEND,sp
ldc #0x80,ccr
/* Peripheral Setup */
#if defined(CONFIG_BLK_DEV_BLKMEM)
/* move romfs image */
jsr @__move_romfs
#endif
/* .bss clear */
mov.l #__sbss,er5
mov.l #__ebss,er4
sub.l er5,er4
shlr er4
shlr er4
sub.l er0,er0
1:
mov.l er0,@er5
adds #4,er5
dec.l #1,er4
bne 1b
/* copy kernel commandline */
mov.l #COMMAND_START,er5
mov.l #SYMBOL_NAME(command_line),er6
mov.w #512,r4
eepmov.w
/* uClinux kernel start */
ldc #0x90,ccr /* running kernel */
mov.l #SYMBOL_NAME(init_thread_union),sp
add.l #0x2000,sp
jsr @_start_kernel
_exit:
jmp _exit
rts
/* I/O port assign information */
__platform_gpio_table:
mov.l #gpio_table,er0
rts
gpio_table:
;; P1DDR
.byte 0x00,0x00
;; P2DDR
.byte 0x00,0x00
;; P3DDR
.byte 0x00,0x00
;; P4DDR
.byte 0x00,0x00
;; P5DDR
.byte 0x00,0x00
;; P6DDR
.byte 0x00,0x00
;; dummy
.byte 0x00,0x00
;; P8DDR
.byte 0x00,0x00
;; P9DDR
.byte 0x00,0x00
;; PADDR
.byte 0x00,0x00
;; PBDDR
.byte 0x00,0x00
__target_name:
.asciz "generic"
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* *
* Yoshinori Sato <ysato@users.sourceforge.jp> * Yoshinori Sato <ysato@users.sourceforge.jp>
* *
* Platform depend startup for uClinux-2.4.x * Platform depend startup
* Target Archtecture: generic * Target Archtecture: generic
* Memory Layout : ROM * Memory Layout : ROM
*/ */
...@@ -31,16 +31,16 @@ SYMBOL_NAME_LABEL(_start) ...@@ -31,16 +31,16 @@ SYMBOL_NAME_LABEL(_start)
/* .bss clear */ /* .bss clear */
mov.l #__sbss,er5 mov.l #__sbss,er5
mov.l er5,er6
inc.l #1,er6
mov.l #__ebss,er4 mov.l #__ebss,er4
sub.l er5,er4 sub.l er5,er4
sub.w r0,r0 shlr er4
mov.b r0l,@er5 shlr er4
sub.l er0,er0
1: 1:
eepmov.w mov.l er0,@er5
dec.w #1,e4 adds #4,er5
bpl 1b dec.l #1,er4
bne 1b
/* copy .data */ /* copy .data */
#if !defined(CONFIG_H8300H_SIM) #if !defined(CONFIG_H8300H_SIM)
...@@ -60,10 +60,9 @@ SYMBOL_NAME_LABEL(_start) ...@@ -60,10 +60,9 @@ SYMBOL_NAME_LABEL(_start)
mov.w #512,r4 mov.w #512,r4
eepmov.w eepmov.w
/* uClinux kernel start */ /* linux kernel start */
ldc #0x90,ccr /* running kernel */ ldc #0x90,ccr /* running kernel */
mov.l #SYMBOL_NAME(init_thread_union),sp mov.l #SYMBOL_NAME(init_thread_union),sp
mov.l sp,@SYMBOL_NAME(_current_task)
add.l #0x2000,sp add.l #0x2000,sp
jsr @_start_kernel jsr @_start_kernel
_exit: _exit:
......
/* AKI3068NET RAM */ /* Generic RAM */
OUTPUT_ARCH(h8300h) OUTPUT_ARCH(h8300h)
ENTRY("__start") ENTRY("__start")
MEMORY MEMORY
{ {
ram : ORIGIN = 0x400000, LENGTH = 0xA0000 ram : ORIGIN = 0x400000, LENGTH = 0x200000
/* rdisk : ORIGIN = 0x4A0000, LENGTH = 0x70000 */
/* uram : ORIGIN = 0x510000, LENGTH = 0xF0000 */
uram : ORIGIN = 0x4A0000, LENGTH = 0x160000
eram : ORIGIN = 0x600000, LENGTH = 0 eram : ORIGIN = 0x600000, LENGTH = 0
iram : ORIGIN = 0xffbf20, LENGTH = 0x4000 iram : ORIGIN = 0xffbf20, LENGTH = 0x4000
} }
SECTIONS
{
.bootvec :
{
*(.bootvec)
} > ram
.text :
{
__stext = . ;
*(.text)
__etext = . ;
} > ram
.rodata :
{
___data_rom_start = ALIGN ( 4 ) ;
} > ram
.erom :
{
__erom = . ;
} > ram
.data :
{
__ramstart = . ;
__sdata = . ;
___data_start = . ;
*(.data)
__edata = . ;
edata = ALIGN( 0x10 ) ;
___data_end = ALIGN( 0x10 ) ;
} > ram
.bss :
{
__sbss = . ;
___bss_start = . ;
*(.bss)
*(COMMON)
__ebss = . ;
___bss_end = . ;
} > ram
/*
.rootimg :
{
__rootimage = . ;
} > rdisk
*/
.dummy1 :
{
end = ALIGN( 0x10 ) ;
__end = ALIGN( 0x10 ) ;
} > uram
.ram_vec : AT(___bss_end)
{
__ram_vector = . ;
} > iram
__ram_vector_image = LOADADDR(.ram_vec) ;
.dummy2 :
{
_COMMAND_START = . - 0x200 ;
__ramend = . ;
} > eram
}
OUTPUT_ARCH(h8300h) OUTPUT_ARCH(h8300h)
ENTRY("__start") ENTRY("__start")
/*INPUT(rootimage.o)*/
_jiffies = _jiffies_64 + 4;
MEMORY MEMORY
{ {
vector : ORIGIN = 0x000000, LENGTH = 0x000100 vector : ORIGIN = 0x000000, LENGTH = 0x000100
rom : ORIGIN = 0x000100, LENGTH = 0x200000-0x000100 rom : ORIGIN = 0x000100, LENGTH = 0x200000-0x000100
erom : ORIGIN = 0x200000, LENGTH = 1 erom : ORIGIN = 0x200000, LENGTH = 0
ram : ORIGIN = 0x200000, LENGTH = 0x100000 ram : ORIGIN = 0x200000, LENGTH = 0x400000
eram : ORIGIN = 0x2fa000, LENGTH = 1 eram : ORIGIN = 0x600000, LENGTH = 0
} }
SECTIONS
{
.vectors :
{
__vector = . ;
*(.vectors*)
} > vector
.text :
{
*(.int_redirect)
__stext = . ;
*(.text)
. = ALIGN(0x4) ;
*(.exit.text)
*(.text.*)
. = ALIGN(0x4) ;
*(.exitcall.exit)
. = ALIGN(0x4) ;
*(.kstrtab)
. = ALIGN(0x4) ;
*(.rodata*)
. = ALIGN(16); /* Exception table */
___start___ex_table = .;
*(__ex_table)
___stop___ex_table = .;
___start___ksymtab = .; /* Kernel symbol table */
*(__ksymtab)
___stop___ksymtab = .;
. = ALIGN(0x4) ;
__etext = . ;
} > rom
.data : AT( ADDR(.text)+SIZEOF(.text))
{
__sdata = . ;
___data_start = . ;
. = ALIGN(0x2000) ;
*(.data.init_task)
. = ALIGN(0x4) ;
*(.data)
. = ALIGN(0x4) ;
*(.data.*)
. = ALIGN(0x4) ;
___init_begin = .;
*(.init.text)
*(.init.data)
. = ALIGN(0x4) ;
___setup_start = .;
*(.init.setup)
. = ALIGN(0x4) ;
___setup_end = .;
___start___param = .;
*(__param)
___stop___param = .;
___initcall_start = .;
*(.initcall1.init)
*(.initcall2.init)
*(.initcall3.init)
*(.initcall4.init)
*(.initcall5.init)
*(.initcall6.init)
*(.initcall7.init)
___initcall_end = .;
___con_initcall_start = .;
*(.con_initcall.init)
___con_initcall_end = .;
SECURITY_INIT
. = ALIGN(4);
___initramfs_start = .;
*(.init.ramfs)
___initramfs_end = .;
. = ALIGN(0x4) ;
___init_end = .;
__edata = . ;
} > ram
__begin_data = LOADADDR(.data) ;
.blkimg : AT( LOADADDR(.data) + SIZEOF(.data))
{
__blkimg = . ;
*(.rootimg*)
} > rom
.erom :
{
__erom = . ;
} > erom
.bss :
{
. = ALIGN(0x4) ;
__sbss = . ;
*(.bss)
. = ALIGN(0x4) ;
*(COMMON)
. = ALIGN(0x4) ;
__ebss = . ;
__end = . ;
__ramstart = .;
} > ram
.dummy :
{
COMMAND_START = . - 0x200 ;
__ramend = . ;
} > eram
}
/* /*
* linux/arch/h8300/platform/h8300h/generic/timer.c * linux/arch/h8300/platform/h8300h/generic/timer.c
* *
* Yoshinori Sato <qzb04471@nifty.ne.jp> * Yoshinori Sato <ysato@users.sourceforge.jp>
* *
* Platform depend Timer Handler * Platform depend Timer Handler
* *
...@@ -22,27 +22,31 @@ ...@@ -22,27 +22,31 @@
#include <linux/timex.h> #include <linux/timex.h>
extern int request_irq_boot(unsigned int,
irqreturn_t (*handler)(int, void *, struct pt_regs *),
unsigned long, const char *, void *);
#if defined(CONFIG_H83007) || defined(CONFIG_H83068) #if defined(CONFIG_H83007) || defined(CONFIG_H83068)
#define TMR8CMA2 0x00ffff94 #include <asm/regs306x.h>
#define TMR8TCSR2 0x00ffff92
#define TMR8TCNT2 0x00ffff90
int platform_timer_setup(void (*timer_int)(int, void *, struct pt_regs *)) int platform_timer_setup(void (*timer_int)(int, void *, struct pt_regs *))
{ {
outb(H8300_TIMER_COUNT_DATA,TMR8CMA2); outb(H8300_TIMER_COUNT_DATA,TMR8CMA2);
outb(0x00,TMR8TCSR2); outb(0x00,TMR8TCSR2);
request_irq(40,timer_int,0,"timer",0); request_irq_boot(40,timer_int,0,"timer",0);
outb(0x40|0x08|0x03,TMR8TCNT2); outb(0x40|0x08|0x03,TMR8TCNT2);
return 0; return 0;
} }
void platform_timer_eoi(void) void platform_timer_eoi(void)
{ {
__asm__("bclr #6,@0xffff92:8"); *(volatile unsigned char *)_8TCSR2 &= ~(1 << CMFA);
} }
#endif #endif
#if defined(H8_3002) || defined(CONFIG_H83048) #if defined(H8_3002) || defined(CONFIG_H83048)
/* FIXME! */
#define TSTR 0x00ffff60 #define TSTR 0x00ffff60
#define TSNC 0x00ffff61 #define TSNC 0x00ffff61
#define TMDR 0x00ffff62 #define TMDR 0x00ffff62
...@@ -63,7 +67,7 @@ int platform_timer_setup(void (*timer_int)(int, void *, struct pt_regs *)) ...@@ -63,7 +67,7 @@ int platform_timer_setup(void (*timer_int)(int, void *, struct pt_regs *))
*(unsigned short *)TCNT=0; *(unsigned short *)TCNT=0;
outb(0x23,TCR); outb(0x23,TCR);
outb(0x00,TIOR); outb(0x00,TIOR);
request_irq(26,timer_int,0,"timer",0); request_timer_irq(26,timer_int,0,"timer",0);
outb(inb(TIER) | 0x01,TIER); outb(inb(TIER) | 0x01,TIER);
outb(inb(TSNC) & ~0x01,TSNC); outb(inb(TSNC) & ~0x01,TSNC);
outb(inb(TMDR) & ~0x01,TMDR); outb(inb(TMDR) & ~0x01,TMDR);
......
...@@ -6,8 +6,7 @@ ...@@ -6,8 +6,7 @@
# unless it's something special (ie not a .c file). # unless it's something special (ie not a .c file).
# #
all: $(BOARD).o extra-y := crt0_ram.o
O_TARGET := $(BOARD).o
obj-y := timer.o obj-y := timer.o
timer.o: timer.c timer.o: timer.c
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* *
* Yoshinori Sato <ysato@users.sourceforge.jp> * Yoshinori Sato <ysato@users.sourceforge.jp>
* *
* Platform depend startup for uClinux-2.4.x * Platform depend startup
* Target Archtecture: H8MAX * Target Archtecture: H8MAX
* Memory Layout : RAM * Memory Layout : RAM
*/ */
...@@ -13,6 +13,16 @@ ...@@ -13,6 +13,16 @@
#include <linux/config.h> #include <linux/config.h>
#include <asm/linkage.h> #include <asm/linkage.h>
#if !defined(CONFIG_BLKDEV_RESERVE)
#if defined(CONFIG_GDB_DEBUG)
#define RAMEND (__ramend - 0xc000)
#else
#define RAMEND __ramend
#endif
#else
#define RAMEND CONFIG_BLKDEV_RESERVE_ADDRESS
#endif
.global SYMBOL_NAME(_start) .global SYMBOL_NAME(_start)
.global SYMBOL_NAME(command_line) .global SYMBOL_NAME(command_line)
.global SYMBOL_NAME(_platform_gpio_table) .global SYMBOL_NAME(_platform_gpio_table)
...@@ -25,23 +35,28 @@ ...@@ -25,23 +35,28 @@
/* CPU Reset entry */ /* CPU Reset entry */
SYMBOL_NAME_LABEL(_start) SYMBOL_NAME_LABEL(_start)
mov.l #__ramend,sp mov.l #RAMEND,sp
ldc #0x80,ccr ldc #0x80,ccr
/* Peripheral Setup */ /* Peripheral Setup */
#if defined(CONFIG_BLK_DEV_BLKMEM)
/* move romfs image */
jsr @__move_romfs
#endif
/* .bss clear */ /* .bss clear */
mov.l #__sbss,er5 mov.l #__sbss,er5
mov.l er5,er6
inc.l #1,er6
mov.l #__ebss,er4 mov.l #__ebss,er4
sub.l er5,er4 sub.l er5,er4
sub.w r0,r0 shlr er4
mov.b r0l,@er5 shlr er4
sub.l er0,er0
1: 1:
eepmov.w mov.l er0,@er5
dec.w #1,e4 adds #4,er5
bpl 1b dec.l #1,er4
bne 1b
/* copy kernel commandline */ /* copy kernel commandline */
mov.l #COMMAND_START,er5 mov.l #COMMAND_START,er5
...@@ -49,22 +64,9 @@ SYMBOL_NAME_LABEL(_start) ...@@ -49,22 +64,9 @@ SYMBOL_NAME_LABEL(_start)
mov.w #512,r4 mov.w #512,r4
eepmov.w eepmov.w
/* RAM Interrupt Vector Table Setup */
#if defined(CONFIG_GDB_DEBUG)
mov.l @SYMBOL_NAME(interrupt_redirect_table)+11*4,er0
#endif
mov.l #SYMBOL_NAME(_vector_lma),er5
mov.l #SYMBOL_NAME(interrupt_redirect_table),er6
mov.w #0x100,r4
eepmov.w
#if defined(CONFIG_GDB_DEBUG)
mov.l er0,@SYMBOL_NAME(interrupt_redirect_table)+11*4
#endif
/* uClinux kernel start */ /* uClinux kernel start */
ldc #0x90,ccr /* running kernel */ ldc #0x90,ccr /* running kernel */
mov.l #SYMBOL_NAME(init_task_union),sp mov.l #SYMBOL_NAME(init_thread_union),sp
mov.l sp,@SYMBOL_NAME(_current_task)
add.l #0x2000,sp add.l #0x2000,sp
jsr @_start_kernel jsr @_start_kernel
_exit: _exit:
......
...@@ -5,86 +5,7 @@ ENTRY("__start") ...@@ -5,86 +5,7 @@ ENTRY("__start")
MEMORY MEMORY
{ {
ram : ORIGIN = 0x400000, LENGTH = 0x600000-0x400000-0xc000 ram : ORIGIN = 0x400000, LENGTH = 0x600000-0x400000
disk : ORIGIN = 0x600000-0xc000, LENGTH = 0xc000
eram : ORIGIN = 0x600000, LENGTH = 0 eram : ORIGIN = 0x600000, LENGTH = 0
iram : ORIGIN = 0xfffd20, LENGTH = 0x100 iram : ORIGIN = 0xfffd20, LENGTH = 0x100
} }
SECTIONS
{
.bootvec :
{
*(.bootvec)
} > ram
.text :
{
__stext = . ;
*(.text)
. = ALIGN(0x4) ;
*(.text.*)
. = ALIGN(0x4) ;
*(.kstrtab)
. = ALIGN(0x4) ;
*(.rodata*)
. = ALIGN(16); /* Exception table */
___start___ex_table = .;
*(__ex_table)
___stop___ex_table = .;
___start___ksymtab = .; /* Kernel symbol table */
*(__ksymtab)
___stop___ksymtab = .;
. = ALIGN(0x4) ;
__etext = . ;
} > ram
.data :
{
__sdata = . ;
___data_start = . ;
*(.data)
*(.data.*)
*(.exitcall.exit)
. = ALIGN(0x2000) ;
*(.data.init_task)
. = ALIGN(0x2000) ;
___init_begin = .;
*(.text.init)
*(.data.init)
. = ALIGN(16);
___setup_start = .;
*(.setup.init)
___setup_end = .;
___initcall_start = .;
*(.initcall.init)
. = ALIGN(4) ;
___initcall_end = .;
___init_end = .;
__edata = . ;
. = ALIGN(0x4) ;
__sbss = . ;
*(.bss)
. = ALIGN(0x4) ;
*(COMMON)
. = ALIGN(0x4) ;
__ebss = . ;
__end = . ;
__ramstart = .;
} > ram
.blkimg :
{
__ramend = . ;
__blkimg = . ;
} > disk
.ram_vec : AT(ADDR(.data) + SIZEOF(.data))
{
*(.int_redirect)
} > iram
__vector_lma = LOADADDR(.ram_vec);
.dummy2 :
{
COMMAND_START = . - 0x200 ;
} > eram
}
...@@ -14,29 +14,32 @@ ...@@ -14,29 +14,32 @@
#include <linux/param.h> #include <linux/param.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/timex.h>
#include <asm/segment.h> #include <asm/segment.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/regs306x.h>
#include <linux/timex.h>
#define TMR8CMA2 0x00ffff94
#define TMR8TCSR2 0x00ffff92
#define TMR8TCNT2 0x00ffff90
#define CMFA 6 #define CMFA 6
int platform_timer_setup(void (*timer_int)(int, void *, struct pt_regs *)) extern int request_irq_boot(unsigned int,
irqreturn_t (*handler)(int, void *, struct pt_regs *),
unsigned long, const char *, void *);
void __init platform_timer_setup(irqreturn_t (*timer_int)(int, void *, struct pt_regs *))
{ {
outb(CONFIG_CLK_FREQ*10/8192,TMR8CMA2); outb(H8300_TIMER_COUNT_DATA,TCORA2);
outb(0x00,TMR8TCSR2); outb(0x00,_8TCSR2);
request_irq(40,timer_int,0,"timer",0); request_irq_boot(40,timer_int,0,"timer",0);
outb(0x40|0x08|0x03,TMR8TCNT2); outb(0x40|0x08|0x03,_8TCR2);
} }
void platform_timer_eoi(void) void platform_timer_eoi(void)
{ {
*(unsigned char *)TMR8TCSR2 &= ~(1 << CMFA); *(volatile unsigned char *)_8TCSR2 &= ~(1 << CMFA);
} }
void platform_gettod(int *year, int *mon, int *day, int *hour, void platform_gettod(int *year, int *mon, int *day, int *hour,
...@@ -44,3 +47,4 @@ void platform_gettod(int *year, int *mon, int *day, int *hour, ...@@ -44,3 +47,4 @@ void platform_gettod(int *year, int *mon, int *day, int *hour,
{ {
*year = *mon = *day = *hour = *min = *sec = 0; *year = *mon = *day = *hour = *min = *sec = 0;
} }
...@@ -18,6 +18,9 @@ ...@@ -18,6 +18,9 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kernel_stat.h> #include <linux/kernel_stat.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/init.h>
#include <linux/random.h>
#include <linux/bootmem.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/irq.h> #include <asm/irq.h>
...@@ -27,8 +30,7 @@ ...@@ -27,8 +30,7 @@
#include <asm/gpio.h> #include <asm/gpio.h>
#include <asm/hardirq.h> #include <asm/hardirq.h>
#include <asm/regs306x.h> #include <asm/regs306x.h>
#include <asm/errno.h>
#define INTERNAL_IRQS (64)
#define EXT_IRQ0 12 #define EXT_IRQ0 12
#define EXT_IRQ1 13 #define EXT_IRQ1 13
...@@ -39,75 +41,144 @@ ...@@ -39,75 +41,144 @@
#define EXT_IRQ6 18 #define EXT_IRQ6 18
#define EXT_IRQ7 19 #define EXT_IRQ7 19
#define WDT_IRQ 20 /*
* This structure has only 4 elements for speed reasons
*/
typedef struct irq_handler {
irqreturn_t (*handler)(int, void *, struct pt_regs *);
int flags;
int count;
void *dev_id;
const char *devname;
} irq_handler_t;
irq_handler_t *irq_list[NR_IRQS];
/* table for system interrupt handlers */ extern unsigned long *interrupt_redirect_table;
static irq_handler_t irq_list[SYS_IRQS];
/* The number of spurious interrupts */ static inline unsigned long *get_vector_address(void)
volatile unsigned int num_spurious; {
unsigned long *rom_vector = (unsigned long *)0x000000;
unsigned long base,tmp;
int vec_no;
base = rom_vector[EXT_IRQ0];
/* assembler routines */ /* check romvector format */
asmlinkage void system_call(void); for (vec_no = EXT_IRQ1; vec_no <= EXT_IRQ5; vec_no++) {
asmlinkage void bad_interrupt(void); if ((base+(vec_no - EXT_IRQ0)*4) != rom_vector[vec_no])
return NULL;
}
/* irq node variables for the 32 (potential) on chip sources */ /* ramvector base address */
/*static irq_node_t *int_irq_list[INTERNAL_IRQS];*/ base -= EXT_IRQ0*4;
static int int_irq_count[INTERNAL_IRQS];
#if 0 /* writerble check */
static void int_badint(int irq, void *dev_id, struct pt_regs *fp) tmp = ~(*(volatile unsigned long *)base);
{ (*(volatile unsigned long *)base) = tmp;
num_spurious += 1; if ((*(volatile unsigned long *)base) != tmp)
return NULL;
return (unsigned long *)base;
} }
#endif
void init_IRQ(void) void __init init_IRQ(void)
{ {
#if defined(CONFIG_RAMKERNEL)
int i; int i;
unsigned long *ramvec,*ramvec_p;
unsigned long break_vec;
#if defined(CONFIG_GDB_DEBUG)
break_vec = ramvec[TRAP3_VEC];
#else
break_vec = VECTOR(trace_break);
#endif
ramvec = get_vector_address();
if (ramvec == NULL)
panic("interrupt vector serup failed.");
else
printk("virtual vector at 0x%08lx\n",(unsigned long)ramvec);
for (i = 0; i < SYS_IRQS; i++) { for (ramvec_p = ramvec, i = 0; i < NR_IRQS; i++)
irq_list[i].handler = NULL; *ramvec_p++ = REDIRECT(interrupt_entry);
irq_list[i].flags = 0;
irq_list[i].devname = NULL; ramvec[TRAP0_VEC] = VECTOR(system_call);
irq_list[i].dev_id = NULL; ramvec[TRAP3_VEC] = break_vec;
interrupt_redirect_table = ramvec;
#ifdef DUMP_VECTOR
ramvec_p = interrupt_redirect_table;
for (i = 0; i < NR_IRQS; i++) {
if ((i % 8) == 0)
printk("\n%p: ",ramvec_p);
printk("%p ",*ramvec_p);
ramvec_p++;
} }
printk("\n");
#endif
#endif
}
void __init request_irq_boot(unsigned int irq,
irqreturn_t (*handler)(int, void *, struct pt_regs *),
unsigned long flags, const char *devname, void *dev_id)
{
irq_handler_t *irq_handle;
irq_handle = alloc_bootmem(sizeof(irq_handler_t));
irq_handle->handler = handler;
irq_handle->flags = flags;
irq_handle->count = 0;
irq_handle->dev_id = dev_id;
irq_handle->devname = devname;
irq_list[irq] = irq_handle;
} }
int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), int request_irq(unsigned int irq,
irqreturn_t (*handler)(int, void *, struct pt_regs *),
unsigned long flags, const char *devname, void *dev_id) unsigned long flags, const char *devname, void *dev_id)
{ {
irq_handler_t *irq_handle;
if (irq < 0 || irq >= NR_IRQS) {
printk("Incorrect IRQ %d from %s\n", irq, devname);
return -EINVAL;
}
if (irq_list[irq])
return -EBUSY;
if (irq >= EXT_IRQ0 && irq <= EXT_IRQ3) { if (irq >= EXT_IRQ0 && irq <= EXT_IRQ3) {
if (H8300_GPIO_RESERVE(H8300_GPIO_P8, 1 << (irq - EXT_IRQ0)) == 0) if (H8300_GPIO_RESERVE(H8300_GPIO_P8, 1 << (irq - EXT_IRQ0)) == 0)
return 1; return -EBUSY;
H8300_GPIO_DDR(H8300_GPIO_P8, (irq - EXT_IRQ0), 0); H8300_GPIO_DDR(H8300_GPIO_P8, (irq - EXT_IRQ0), 0);
} }
if (irq >= EXT_IRQ4 && irq <= EXT_IRQ5) { if (irq >= EXT_IRQ4 && irq <= EXT_IRQ5) {
if (H8300_GPIO_RESERVE(H8300_GPIO_P9, 1 << (irq - EXT_IRQ0)) == 0) if (H8300_GPIO_RESERVE(H8300_GPIO_P9, 1 << (irq - EXT_IRQ0)) == 0)
return 1; return -EBUSY;
H8300_GPIO_DDR(H8300_GPIO_P9, (irq - EXT_IRQ0), 0); H8300_GPIO_DDR(H8300_GPIO_P9, (irq - EXT_IRQ0), 0);
} }
irq_list[irq].handler = handler; irq_handle = (irq_handler_t *)kmalloc(sizeof(irq_handler_t), GFP_ATOMIC);
irq_list[irq].flags = flags; if (irq_handle == NULL)
irq_list[irq].devname = devname; return -ENOMEM;
irq_list[irq].dev_id = dev_id;
if (irq >= EXT_IRQ0 && irq <= EXT_IRQ5) irq_handle->handler = handler;
*(volatile unsigned char *)IER |= 1 << (irq - EXT_IRQ0); irq_handle->flags = flags;
irq_handle->count = 0;
irq_handle->dev_id = dev_id;
irq_handle->devname = devname;
irq_list[irq] = irq_handle;
return 0; return 0;
} }
void free_irq(unsigned int irq, void *dev_id) void free_irq(unsigned int irq, void *dev_id)
{ {
if (irq_list[irq].dev_id != dev_id) if (irq >= NR_IRQS) {
printk("%s: Removing probably wrong IRQ %d from %s\n", return;
__FUNCTION__, irq, irq_list[irq].devname); }
if (!irq_list[irq] || irq_list[irq]->dev_id != dev_id)
printk("Removing probably wrong IRQ %d from %s\n",
irq, irq_list[irq]->devname);
if (irq >= EXT_IRQ0 && irq <= EXT_IRQ5) if (irq >= EXT_IRQ0 && irq <= EXT_IRQ5)
*(volatile unsigned char *)IER &= ~(1 << (irq - EXT_IRQ0)); *(volatile unsigned char *)IER &= ~(1 << (irq - EXT_IRQ0));
irq_list[irq].handler = NULL; kfree(irq_list[irq]);
irq_list[irq].flags = 0; irq_list[irq] = NULL;
irq_list[irq].dev_id = NULL;
irq_list[irq].devname = NULL;
} }
/* /*
...@@ -123,115 +194,36 @@ int probe_irq_off (unsigned long irqs) ...@@ -123,115 +194,36 @@ int probe_irq_off (unsigned long irqs)
return 0; return 0;
} }
struct int_regs {
unsigned long ier;
unsigned long isr;
unsigned char mask;
};
#define REGS_DEF(ier,isr,mask) {ier,isr,mask}
const struct int_regs interrupt_registers[]= {
REGS_DEF(IER,ISR,0x01),
REGS_DEF(IER,ISR,0x02),
REGS_DEF(IER,ISR,0x04),
REGS_DEF(IER,ISR,0x08),
REGS_DEF(IER,ISR,0x10),
REGS_DEF(IER,ISR,0x20),
REGS_DEF(IER,ISR,0x40),
REGS_DEF(IER,ISR,0x80),
REGS_DEF(TCSR,TCSR,0x20),
REGS_DEF(RTMCSR,RTMCSR,0x40),
REGS_DEF(0,0,0),
REGS_DEF(ADCSR,ADCSR,0x40),
REGS_DEF(TISRA,TISRA,0x10),
REGS_DEF(TISRB,TISRB,0x10),
REGS_DEF(TISRC,TISRC,0x10),
REGS_DEF(0,0,0),
REGS_DEF(TISRA,TISRA,0x20),
REGS_DEF(TISRB,TISRB,0x20),
REGS_DEF(TISRC,TISRC,0x20),
REGS_DEF(0,0,0),
REGS_DEF(TISRA,TISRA,0x40),
REGS_DEF(TISRB,TISRB,0x40),
REGS_DEF(TISRC,TISRC,0x40),
REGS_DEF(0,0,0),
REGS_DEF(_8TCR0,_8TCSR0,0x40),
REGS_DEF(_8TCR0,_8TCSR0,0x80),
REGS_DEF(_8TCR1,_8TCSR1,0xC0),
REGS_DEF(_8TCR0,_8TCSR0,0x20),
REGS_DEF(_8TCR2,_8TCSR2,0x40),
REGS_DEF(_8TCR2,_8TCSR2,0x80),
REGS_DEF(_8TCR3,_8TCSR3,0xC0),
REGS_DEF(_8TCR2,_8TCSR2,0x20),
REGS_DEF(DTCR0A,DTCR0A,0x0),
REGS_DEF(DTCR0B,DTCR0B,0x0),
REGS_DEF(DTCR1A,DTCR1A,0x0),
REGS_DEF(DTCR1B,DTCR1B,0x0),
REGS_DEF(0,0,0),
REGS_DEF(0,0,0),
REGS_DEF(0,0,0),
REGS_DEF(0,0,0),
REGS_DEF(SCR0,SSR0,0x40),
REGS_DEF(SCR0,SSR0,0x40),
REGS_DEF(SCR0,SSR0,0x80),
REGS_DEF(SCR0,SSR0,0x04),
REGS_DEF(SCR1,SSR1,0x40),
REGS_DEF(SCR1,SSR1,0x40),
REGS_DEF(SCR1,SSR1,0x80),
REGS_DEF(SCR1,SSR1,0x04),
REGS_DEF(SCR2,SSR2,0x40),
REGS_DEF(SCR2,SSR2,0x40),
REGS_DEF(SCR2,SSR2,0x80),
REGS_DEF(SCR2,SSR2,0x04)
};
void enable_irq(unsigned int irq) void enable_irq(unsigned int irq)
{ {
unsigned char ier; if (irq >= EXT_IRQ0 && irq <= EXT_IRQ5) {
const struct int_regs *regs=&interrupt_registers[irq - 12]; *(volatile unsigned char *)IER |= (1 << (irq - EXT_IRQ0));
if (irq == WDT_IRQ) { *(volatile unsigned char *)ISR &= ~(1 << (irq - EXT_IRQ0));
ier = ctrl_inb(TCSR);
ier |= 0x20;
ctrl_outb((0xa500 | ier),TCSR);
} else {
if ((irq > 12) && regs->ier) {
ier = ctrl_inb(regs->ier);
ier |= regs->mask;
ctrl_outb(ier, regs->ier);
} else
panic("Unknown interrupt vector");
} }
} }
void disable_irq(unsigned int irq) void disable_irq(unsigned int irq)
{ {
unsigned char ier; if (irq >= EXT_IRQ0 && irq <= EXT_IRQ5) {
const struct int_regs *regs=&interrupt_registers[irq - 12]; *(volatile unsigned char *)IER &= ~(1 << (irq - EXT_IRQ0));
if (irq == WDT_IRQ) {
ier = ctrl_inb(TCSR);
ier &= ~0x20;
ctrl_outb((0xa500 | ier),TCSR);
} else {
if ((irq > 12) && regs->ier) {
ier = ctrl_inb(regs->ier);
ier &= ~(regs->mask);
ctrl_outb(ier, regs->ier);
} else
panic("Unknown interrupt vector");
} }
} }
asmlinkage void process_int(unsigned long vec, struct pt_regs *fp) asmlinkage void process_int(int vec, struct pt_regs *fp)
{ {
irq_enter(); irq_enter();
if (irq_list[vec].handler) {
irq_list[vec].handler(vec, irq_list[vec].dev_id, fp);
int_irq_count[vec]++;
} else
panic("No interrupt handler for %ld\n", vec);
if (vec >= EXT_IRQ0 && vec <= EXT_IRQ5) if (vec >= EXT_IRQ0 && vec <= EXT_IRQ5)
*(volatile unsigned char *)ISR &= ~(1 << (vec - EXT_IRQ0)); *(volatile unsigned char *)ISR &= ~(1 << (vec - EXT_IRQ0));
if (vec < NR_IRQS) {
if (irq_list[vec]) {
irq_list[vec]->handler(vec, irq_list[vec]->dev_id, fp);
irq_list[vec]->count++;
if (irq_list[vec]->flags & SA_SAMPLE_RANDOM)
add_interrupt_randomness(vec);
}
} else {
BUG();
}
irq_exit(); irq_exit();
} }
...@@ -240,8 +232,10 @@ int show_interrupts(struct seq_file *p, void *v) ...@@ -240,8 +232,10 @@ int show_interrupts(struct seq_file *p, void *v)
int i; int i;
for (i = 0; i < NR_IRQS; i++) { for (i = 0; i < NR_IRQS; i++) {
seq_printf(p, "%3d: %10u ",i,int_irq_count[i]); if (irq_list[i]) {
seq_printf(p, "%s\n", irq_list[i].devname); seq_printf(p, "%3d: %10u ",i,irq_list[i]->count);
seq_printf(p, "%s\n", irq_list[i]->devname);
}
} }
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment