MN10300: And Panasonic AM34 subarch and implement SMP

Implement the Panasonic MN10300 AM34 CPU subarch and implement SMP support for
MN10300.  Also implement support for the MN2WS0060 processor and the ASB2364
evaluation board which are AM34 based.

Signed-off-by: Akira Takeuchi <takeuchi.akr@jp.panasonic.com>
Signed-off-by: Kiyoshi Owada <owada.kiyoshi@jp.panasonic.com>
Signed-off-by: David Howells <dhowells@redhat.com>
This commit is contained in:
Akira Takeuchi 2010-10-27 17:28:55 +01:00 committed by David Howells
parent 04157a6e7d
commit 368dd5acd1
80 changed files with 4500 additions and 487 deletions

View File

@ -4448,7 +4448,7 @@ L: platform-driver-x86@vger.kernel.org
S: Maintained
F: drivers/platform/x86/panasonic-laptop.c
PANASONIC MN10300/AM33 PORT
PANASONIC MN10300/AM33/AM34 PORT
M: David Howells <dhowells@redhat.com>
M: Koichi Yasutake <yasutake.koichi@jp.panasonic.com>
L: linux-am33-list@redhat.com (moderated for non-subscribers)

View File

@ -48,7 +48,7 @@ config GENERIC_CALIBRATE_DELAY
def_bool y
config GENERIC_CMOS_UPDATE
def_bool y
def_bool n
config GENERIC_FIND_NEXT_BIT
def_bool y
@ -72,10 +72,6 @@ config GENERIC_HARDIRQS
config HOTPLUG_CPU
def_bool n
config HZ
int
default 1000
mainmenu "Matsushita MN10300/AM33 Kernel Configuration"
source "init/Kconfig"
@ -98,6 +94,9 @@ config MN10300_UNIT_ASB2303
config MN10300_UNIT_ASB2305
bool "ASB2305"
config MN10300_UNIT_ASB2364
bool "ASB2364"
endchoice
choice
@ -115,17 +114,13 @@ config MN10300_PROC_MN103E010
select MN10300_PROC_HAS_TTYSM1
select MN10300_PROC_HAS_TTYSM2
endchoice
choice
prompt "Processor core support"
default MN10300_CPU_AM33V2
help
This option specifies the processor core for which the kernel will be
compiled. It affects the instruction set used.
config MN10300_CPU_AM33V2
bool "AM33v2"
config MN10300_PROC_MN2WS0050
bool "MN2WS0050"
depends on MN10300_UNIT_ASB2364
select AM34_2
select MN10300_PROC_HAS_TTYSM0
select MN10300_PROC_HAS_TTYSM1
select MN10300_PROC_HAS_TTYSM2
endchoice
@ -138,7 +133,7 @@ config MN10300_HAS_ATOMIC_OPS_UNIT
config FPU
bool "FPU present"
default y
depends on MN10300_PROC_MN103E010
depends on MN10300_PROC_MN103E010 || MN10300_PROC_MN2WS0050
config LAZY_SAVE_FPU
bool "Save FPU state lazily"
@ -179,24 +174,55 @@ config KERNEL_TEXT_ADDRESS
config KERNEL_ZIMAGE_BASE_ADDRESS
hex "Base address of compressed vmlinux image"
default "0x90700000"
default "0x50700000"
config BOOT_STACK_OFFSET
hex
default "0xF00" if SMP
default "0xFF0" if !SMP
config BOOT_STACK_SIZE
hex
depends on SMP
default "0x100"
endmenu
config PREEMPT
bool "Preemptible Kernel"
help
This option reduces the latency of the kernel when reacting to
real-time or interactive events by allowing a low priority process to
be preempted even if it is in kernel mode executing a system call.
This allows applications to run more reliably even when the system is
under load.
config SMP
bool "Symmetric multi-processing support"
default y
depends on MN10300_PROC_MN2WS0038 || MN10300_PROC_MN2WS0050
---help---
This enables support for systems with more than one CPU. If you have
a system with only one CPU, like most personal computers, say N. If
you have a system with more than one CPU, say Y.
Say Y here if you are building a kernel for a desktop, embedded
or real-time system. Say N if you are unsure.
If you say N here, the kernel will run on single and multiprocessor
machines, but will use only one CPU of a multiprocessor machine. If
you say Y here, the kernel will run on many, but not all,
singleprocessor machines. On a singleprocessor machine, the kernel
will run faster if you say N here.
See also <file:Documentation/i386/IO-APIC.txt>,
<file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available at
<http://www.tldp.org/docs.html#howto>.
If you don't know what to do here, say N.
config NR_CPUS
int
depends on SMP
default "2"
config USE_GENERIC_SMP_HELPERS
bool
depends on SMP
default y
source "kernel/Kconfig.preempt"
config MN10300_CURRENT_IN_E2
bool "Hold current task address in E2 register"
depends on !SMP
default y
help
This option removes the E2/R2 register from the set available to gcc
@ -218,12 +244,14 @@ config MN10300_USING_JTAG
suppresses the use of certain hardware debugging features, such as
single-stepping, which are taken over completely by the JTAG unit.
source "kernel/Kconfig.hz"
config MN10300_RTC
bool "Using MN10300 RTC"
depends on MN10300_PROC_MN103E010
depends on MN10300_PROC_MN103E010 || MN10300_PROC_MN2WS0050
select GENERIC_CMOS_UPDATE
default n
help
This option enables support for the RTC, thus enabling time to be
tracked, even when system is powered down. This is available on-chip
on the MN103E010.
@ -315,14 +343,23 @@ config MN10300_TTYSM1
choice
prompt "Select the timer to supply the clock for SIF1"
default MN10300_TTYSM0_TIMER9
default MN10300_TTYSM1_TIMER12 \
if !(AM33_2 || AM33_3)
default MN10300_TTYSM1_TIMER9 \
if AM33_2 || AM33_3
depends on MN10300_TTYSM1
config MN10300_TTYSM1_TIMER12
bool "Use timer 12 (16-bit)"
depends on !(AM33_2 || AM33_3)
config MN10300_TTYSM1_TIMER9
bool "Use timer 9 (16-bit)"
depends on AM33_2 || AM33_3
config MN10300_TTYSM1_TIMER3
bool "Use timer 3 (8-bit)"
depends on AM33_2 || AM33_3
endchoice
@ -337,17 +374,33 @@ config MN10300_TTYSM2
choice
prompt "Select the timer to supply the clock for SIF2"
default MN10300_TTYSM0_TIMER10
default MN10300_TTYSM2_TIMER3 \
if !(AM33_2 || AM33_3)
default MN10300_TTYSM2_TIMER10 \
if AM33_2 || AM33_3
depends on MN10300_TTYSM2
config MN10300_TTYSM2_TIMER9
bool "Use timer 9 (16-bit)"
depends on !(AM33_2 || AM33_3)
config MN10300_TTYSM2_TIMER1
bool "Use timer 1 (8-bit)"
depends on !(AM33_2 || AM33_3)
config MN10300_TTYSM2_TIMER3
bool "Use timer 3 (8-bit)"
depends on !(AM33_2 || AM33_3)
config MN10300_TTYSM2_TIMER10
bool "Use timer 10 (16-bit)"
depends on AM33_2 || AM33_3
endchoice
config MN10300_TTYSM2_CTS
bool "Enable the use of the CTS line /dev/ttySM2"
depends on MN10300_TTYSM2
depends on MN10300_TTYSM2 && AM33_2
endmenu

View File

@ -36,6 +36,9 @@ endif
ifeq ($(CONFIG_MN10300_PROC_MN103E010),y)
PROCESSOR := mn103e010
endif
ifeq ($(CONFIG_MN10300_PROC_MN2WS0050),y)
PROCESSOR := mn2ws0050
endif
ifeq ($(CONFIG_MN10300_UNIT_ASB2303),y)
UNIT := asb2303
@ -43,6 +46,9 @@ endif
ifeq ($(CONFIG_MN10300_UNIT_ASB2305),y)
UNIT := asb2305
endif
ifeq ($(CONFIG_MN10300_UNIT_ASB2364),y)
UNIT := asb2364
endif
head-y := arch/mn10300/kernel/head.o arch/mn10300/kernel/init_task.o

View File

@ -15,10 +15,28 @@
#include <linux/linkage.h>
#include <asm/cpu-regs.h>
#include <asm/cache.h>
#ifdef CONFIG_SMP
#include <proc/smp-regs.h>
#endif
.globl startup_32
startup_32:
# first save off parameters from bootloader
#ifdef CONFIG_SMP
#
# Secondary CPUs jump directly to the kernel entry point
#
# Must save primary CPU's D0-D2 registers as they hold boot parameters
#
mov (CPUID), d3
and CPUID_MASK,d3
beq startup_primary
mov CONFIG_KERNEL_TEXT_ADDRESS,a0
jmp (a0)
startup_primary:
#endif /* CONFIG_SMP */
# first save parameters from bootloader
mov param_save_area,a0
mov d0,(a0)
mov d1,(4,a0)

View File

@ -114,6 +114,8 @@ extern void die(const char *, struct pt_regs *, enum exception_code)
extern int die_if_no_fixup(const char *, struct pt_regs *, enum exception_code);
#define NUM2EXCEP_IRQ_LEVEL(num) (EXCEP_IRQ_LEVEL0 + (num) * 8)
#endif /* __ASSEMBLY__ */
#endif /* _ASM_EXCEPTIONS_H */

View File

@ -18,6 +18,9 @@
#ifndef __ASM_OFFSETS_H__
#include <asm/asm-offsets.h>
#endif
#ifdef CONFIG_SMP
#include <proc/smp-regs.h>
#endif
#define pi break
@ -37,9 +40,25 @@
movm [d2,d3,a2,a3,exreg0,exreg1,exother],(sp)
mov sp,fp # FRAME pointer in A3
add -12,sp # allow for calls to be made
#ifdef CONFIG_SMP
#ifdef CONFIG_PREEMPT /* FIXME */
mov epsw,d2
and ~EPSW_IE,epsw
#endif
mov (CPUID),a0
add a0,a0
add a0,a0
mov (___frame,a0),a1
mov a1,(REG_NEXT,fp)
mov fp,(___frame,a0)
#ifdef CONFIG_PREEMPT /* FIXME */
mov d2,epsw
#endif
#else /* CONFIG_SMP */
mov (__frame),a1
mov a1,(REG_NEXT,fp)
mov fp,(__frame)
#endif /* CONFIG_SMP */
and ~EPSW_FE,epsw # disable the FPU inside the kernel
@ -57,10 +76,27 @@
.macro RESTORE_ALL
# peel back the stack to the calling frame
# - this permits execve() to discard extra frames due to kernel syscalls
#ifdef CONFIG_SMP
#ifdef CONFIG_PREEMPT /* FIXME */
mov epsw,d2
and ~EPSW_IE,epsw
#endif
mov (CPUID),a0
add a0,a0
add a0,a0
mov (___frame,a0),fp
mov fp,sp
mov (REG_NEXT,fp),d0 # userspace has regs->next == 0
mov d0,(___frame,a0)
#ifdef CONFIG_PREEMPT /* FIXME */
mov d2,epsw
#endif
#else /* CONFIG_SMP */
mov (__frame),fp
mov fp,sp
mov (REG_NEXT,fp),d0 # userspace has regs->next == 0
mov d0,(__frame)
#endif /* CONFIG_SMP */
#ifndef CONFIG_MN10300_USING_JTAG
mov (REG_EPSW,fp),d0

View File

@ -19,8 +19,10 @@
/* assembly code in softirq.h is sensitive to the offsets of these fields */
typedef struct {
unsigned int __softirq_pending;
#ifdef CONFIG_MN10300_WD_TIMER
unsigned int __nmi_count; /* arch dependent */
unsigned int __irq_count; /* arch dependent */
#endif
} ____cacheline_aligned irq_cpustat_t;
#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */

View File

@ -15,24 +15,19 @@
#ifdef __KERNEL__
/* interrupt controller registers */
#define GxICR(X) __SYSREG(0xd4000000 + (X) * 4, u16) /* group irq ctrl regs */
/*
* Interrupt controller registers
* - Registers 64-191 are at addresses offset from the main array
*/
#define GxICR(X) \
__SYSREG(0xd4000000 + (X) * 4 + \
(((X) >= 64) && ((X) < 192)) * 0xf00, u16)
#define IAGR __SYSREG(0xd4000100, u16) /* intr acceptance group reg */
#define IAGR_GN 0x00fc /* group number register
* (documentation _has_ to be wrong)
*/
#define GxICR_u8(X) \
__SYSREG(0xd4000000 + (X) * 4 + \
(((X) >= 64) && ((X) < 192)) * 0xf00, u8)
#define EXTMD __SYSREG(0xd4000200, u16) /* external pin intr spec reg */
#define GET_XIRQ_TRIGGER(X) ((EXTMD >> ((X) * 2)) & 3)
#define SET_XIRQ_TRIGGER(X,Y) \
do { \
u16 x = EXTMD; \
x &= ~(3 << ((X) * 2)); \
x |= ((Y) & 3) << ((X) * 2); \
EXTMD = x; \
} while (0)
#include <proc/intctl-regs.h>
#define XIRQ_TRIGGER_LOWLEVEL 0
#define XIRQ_TRIGGER_HILEVEL 1
@ -59,10 +54,18 @@ do { \
#define GxICR_LEVEL_5 0x5000 /* - level 5 */
#define GxICR_LEVEL_6 0x6000 /* - level 6 */
#define GxICR_LEVEL_SHIFT 12
#define GxICR_NMI 0x8000 /* nmi request flag */
#define NUM2GxICR_LEVEL(num) ((num) << GxICR_LEVEL_SHIFT)
#ifndef __ASSEMBLY__
extern void set_intr_level(int irq, u16 level);
extern void set_intr_postackable(int irq);
extern void mn10300_intc_set_level(unsigned int irq, unsigned int level);
extern void mn10300_intc_clear(unsigned int irq);
extern void mn10300_intc_set(unsigned int irq);
extern void mn10300_intc_enable(unsigned int irq);
extern void mn10300_intc_disable(unsigned int irq);
extern void mn10300_set_lateack_irq_type(int irq);
#endif
/* external interrupts */

View File

@ -22,7 +22,11 @@
#define NO_IRQ INT_MAX
/* hardware irq numbers */
#ifdef CONFIG_SMP
#define NR_IRQS GxICR_NUM_EXT_IRQS
#else
#define NR_IRQS GxICR_NUM_IRQS
#endif
/* external hardware irq numbers */
#define NR_XIRQS GxICR_NUM_XIRQS

View File

@ -13,6 +13,9 @@
#define _ASM_IRQFLAGS_H
#include <asm/cpu-regs.h>
#ifndef __ASSEMBLY__
#include <linux/smp.h>
#endif
/*
* interrupt control
@ -60,11 +63,12 @@ static inline unsigned long arch_local_irq_save(void)
/*
* we make sure arch_irq_enable() doesn't cause priority inversion
*/
extern unsigned long __mn10300_irq_enabled_epsw;
extern unsigned long __mn10300_irq_enabled_epsw[];
static inline void arch_local_irq_enable(void)
{
unsigned long tmp;
int cpu = raw_smp_processor_id();
asm volatile(
" mov epsw,%0 \n"
@ -72,8 +76,8 @@ static inline void arch_local_irq_enable(void)
" or %2,%0 \n"
" mov %0,epsw \n"
: "=&d"(tmp)
: "i"(~EPSW_IM), "r"(__mn10300_irq_enabled_epsw)
: "memory");
: "i"(~EPSW_IM), "r"(__mn10300_irq_enabled_epsw[cpu])
: "memory", "cc");
}
static inline void arch_local_irq_restore(unsigned long flags)
@ -105,6 +109,9 @@ static inline bool arch_irqs_disabled(void)
*/
static inline void arch_safe_halt(void)
{
#ifdef CONFIG_SMP
arch_local_irq_enable();
#else
asm volatile(
" or %0,epsw \n"
" nop \n"
@ -113,8 +120,21 @@ static inline void arch_safe_halt(void)
:
: "i"(EPSW_IE|EPSW_IM), "n"(&CPUM), "i"(CPUM_SLEEP)
: "cc");
#endif
}
#define __sleep_cpu() \
do { \
asm volatile( \
" bset %1,(%0)\n" \
"1: btst %1,(%0)\n" \
" bne 1b\n" \
: \
: "i"(&CPUM), "i"(CPUM_SLEEP) \
: "cc" \
); \
} while (0)
static inline void arch_local_cli(void)
{
asm volatile(

View File

@ -90,9 +90,15 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
* The vmalloc() routines also leaves a hole of 4kB between each vmalloced
* area to catch addressing errors.
*/
#ifndef __ASSEMBLY__
#define VMALLOC_OFFSET (8UL * 1024 * 1024)
#define VMALLOC_START (0x70000000UL)
#define VMALLOC_END (0x7C000000UL)
#else
#define VMALLOC_OFFSET (8 * 1024 * 1024)
#define VMALLOC_START (0x70000000)
#define VMALLOC_END (0x7C000000)
#endif
#ifndef __ASSEMBLY__
extern pte_t kernel_vmalloc_ptes[(VMALLOC_END - VMALLOC_START) / PAGE_SIZE];
@ -329,11 +335,7 @@ static inline int pte_exec_kernel(pte_t pte)
return 1;
}
/*
* Bits 0 and 1 are taken, split up the 29 bits of offset
* into this range:
*/
#define PTE_FILE_MAX_BITS 29
#define PTE_FILE_MAX_BITS 30
#define pte_to_pgoff(pte) (pte_val(pte) >> 2)
#define pgoff_to_pte(off) __pte((off) << 2 | _PAGE_FILE)
@ -379,8 +381,13 @@ static inline void ptep_mkdirty(pte_t *ptep)
* Macro to mark a page protection value as "uncacheable". On processors which
* do not support it, this is a no-op.
*/
#define pgprot_noncached(prot) __pgprot(pgprot_val(prot) | _PAGE_CACHE)
#define pgprot_noncached(prot) __pgprot(pgprot_val(prot) & ~_PAGE_CACHE)
/*
* Macro to mark a page protection value as "Write-Through".
* On processors which do not support it, this is a no-op.
*/
#define pgprot_through(prot) __pgprot(pgprot_val(prot) | _PAGE_CACHE_WT)
/*
* Conversion functions: convert a page and protection to a page entry,

View File

@ -33,6 +33,8 @@ struct mm_struct;
__pc; \
})
extern void get_mem_info(unsigned long *mem_base, unsigned long *mem_size);
extern void show_registers(struct pt_regs *regs);
/*
@ -43,17 +45,22 @@ extern void show_registers(struct pt_regs *regs);
struct mn10300_cpuinfo {
int type;
unsigned long loops_per_sec;
unsigned long loops_per_jiffy;
char hard_math;
unsigned long *pgd_quick;
unsigned long *pte_quick;
unsigned long pgtable_cache_sz;
};
extern struct mn10300_cpuinfo boot_cpu_data;
#ifdef CONFIG_SMP
#if CONFIG_NR_CPUS < 2 || CONFIG_NR_CPUS > 8
# error Sorry, NR_CPUS should be 2 to 8
#endif
extern struct mn10300_cpuinfo cpu_data[];
#define current_cpu_data cpu_data[smp_processor_id()]
#else /* CONFIG_SMP */
#define cpu_data &boot_cpu_data
#define current_cpu_data boot_cpu_data
#endif /* CONFIG_SMP */
extern void identify_cpu(struct mn10300_cpuinfo *);
extern void print_cpu_info(struct mn10300_cpuinfo *);
@ -92,21 +99,21 @@ struct thread_struct {
unsigned long a3; /* kernel FP */
unsigned long wchan;
unsigned long usp;
struct pt_regs *__frame;
struct pt_regs *frame;
unsigned long fpu_flags;
#define THREAD_USING_FPU 0x00000001 /* T if this task is using the FPU */
#define THREAD_HAS_FPU 0x00000002 /* T if this task owns the FPU right now */
struct fpu_state_struct fpu_state;
};
#define INIT_THREAD \
{ \
.uregs = init_uregs, \
.pc = 0, \
.sp = 0, \
.a3 = 0, \
.wchan = 0, \
.__frame = NULL, \
#define INIT_THREAD \
{ \
.uregs = init_uregs, \
.pc = 0, \
.sp = 0, \
.a3 = 0, \
.wchan = 0, \
.frame = NULL, \
}
#define INIT_MMAP \
@ -118,6 +125,19 @@ struct thread_struct {
* - need to discard the frame stacked by the kernel thread invoking the execve
* syscall (see RESTORE_ALL macro)
*/
#if defined(CONFIG_SMP) && defined(CONFIG_PREEMPT) /* FIXME */
#define start_thread(regs, new_pc, new_sp) do { \
int cpu; \
preempt_disable(); \
cpu = CPUID; \
set_fs(USER_DS); \
___frame[cpu] = current->thread.uregs; \
___frame[cpu]->epsw = EPSW_nSL | EPSW_IE | EPSW_IM;\
___frame[cpu]->pc = new_pc; \
___frame[cpu]->sp = new_sp; \
preempt_enable(); \
} while (0)
#else /* CONFIG_SMP && CONFIG_PREEMPT */
#define start_thread(regs, new_pc, new_sp) do { \
set_fs(USER_DS); \
__frame = current->thread.uregs; \
@ -125,6 +145,7 @@ struct thread_struct {
__frame->pc = new_pc; \
__frame->sp = new_sp; \
} while (0)
#endif /* CONFIG_SMP && CONFIG_PREEMPT */
/* Free all resources held by a thread. */
extern void release_thread(struct task_struct *);

View File

@ -40,7 +40,6 @@
#define PT_PC 26
#define NR_PTREGS 27
#ifndef __ASSEMBLY__
/*
* This defines the way registers are stored in the event of an exception
* - the strange order is due to the MOVM instruction
@ -75,7 +74,6 @@ struct pt_regs {
unsigned long epsw;
unsigned long pc;
};
#endif
/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
#define PTRACE_GETREGS 12
@ -86,12 +84,13 @@ struct pt_regs {
/* options set using PTRACE_SETOPTIONS */
#define PTRACE_O_TRACESYSGOOD 0x00000001
#if defined(__KERNEL__)
#ifdef __KERNEL__
#ifdef CONFIG_SMP
extern struct pt_regs *___frame[]; /* current frame pointer */
#else
extern struct pt_regs *__frame; /* current frame pointer */
#if !defined(__ASSEMBLY__)
struct task_struct;
#endif
#define user_mode(regs) (((regs)->epsw & EPSW_nSL) == EPSW_nSL)
#define instruction_pointer(regs) ((regs)->pc)
@ -100,9 +99,7 @@ extern void show_regs(struct pt_regs *);
#define arch_has_single_step() (1)
#endif /* !__ASSEMBLY */
#define profile_pc(regs) ((regs)->pc)
#endif /* __KERNEL__ */
#endif /* __KERNEL__ */
#endif /* _ASM_PTRACE_H */

View File

@ -50,7 +50,7 @@ static inline void mn10300_proc_hard_reset(void)
RSTCTR |= RSTCTR_CHIPRST;
}
extern unsigned int watchdog_alert_counter;
extern unsigned int watchdog_alert_counter[];
extern void watchdog_go(void);
extern asmlinkage void watchdog_handler(void);

View File

@ -15,25 +15,14 @@
#include <linux/init.h>
extern void check_rtc_time(void);
extern void __init calibrate_clock(void);
extern unsigned long __init get_initial_rtc_time(void);
#else /* !CONFIG_MN10300_RTC */
static inline void check_rtc_time(void)
{
}
static inline void calibrate_clock(void)
{
}
static inline unsigned long get_initial_rtc_time(void)
{
return 0;
}
#endif /* !CONFIG_MN10300_RTC */
#include <asm-generic/rtc.h>

View File

@ -0,0 +1,125 @@
/*
* Helpers used by both rw spinlocks and rw semaphores.
*
* Based in part on code from semaphore.h and
* spinlock.h Copyright 1996 Linus Torvalds.
*
* Copyright 1999 Red Hat, Inc.
*
* Written by Benjamin LaHaise.
*
* Modified by Matsushita Electric Industrial Co., Ltd.
* Modifications:
* 13-Nov-2006 MEI Temporarily delete lock functions for SMP support.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*/
#ifndef _ASM_RWLOCK_H
#define _ASM_RWLOCK_H
#define RW_LOCK_BIAS 0x01000000
#ifndef CONFIG_SMP
typedef struct { unsigned long a[100]; } __dummy_lock_t;
#define __dummy_lock(lock) (*(__dummy_lock_t *)(lock))
#define RW_LOCK_BIAS_STR "0x01000000"
#define __build_read_lock_ptr(rw, helper) \
do { \
asm volatile( \
" mov (%0),d3 \n" \
" sub 1,d3 \n" \
" mov d3,(%0) \n" \
" blt 1f \n" \
" bra 2f \n" \
"1: jmp 3f \n" \
"2: \n" \
" .section .text.lock,\"ax\" \n" \
"3: call "helper"[],0 \n" \
" jmp 2b \n" \
" .previous" \
: \
: "d" (rw) \
: "memory", "d3", "cc"); \
} while (0)
#define __build_read_lock_const(rw, helper) \
do { \
asm volatile( \
" mov (%0),d3 \n" \
" sub 1,d3 \n" \
" mov d3,(%0) \n" \
" blt 1f \n" \
" bra 2f \n" \
"1: jmp 3f \n" \
"2: \n" \
" .section .text.lock,\"ax\" \n" \
"3: call "helper"[],0 \n" \
" jmp 2b \n" \
" .previous" \
: \
: "d" (rw) \
: "memory", "d3", "cc"); \
} while (0)
#define __build_read_lock(rw, helper) \
do { \
if (__builtin_constant_p(rw)) \
__build_read_lock_const(rw, helper); \
else \
__build_read_lock_ptr(rw, helper); \
} while (0)
#define __build_write_lock_ptr(rw, helper) \
do { \
asm volatile( \
" mov (%0),d3 \n" \
" sub 1,d3 \n" \
" mov d3,(%0) \n" \
" blt 1f \n" \
" bra 2f \n" \
"1: jmp 3f \n" \
"2: \n" \
" .section .text.lock,\"ax\" \n" \
"3: call "helper"[],0 \n" \
" jmp 2b \n" \
" .previous" \
: \
: "d" (rw) \
: "memory", "d3", "cc"); \
} while (0)
#define __build_write_lock_const(rw, helper) \
do { \
asm volatile( \
" mov (%0),d3 \n" \
" sub 1,d3 \n" \
" mov d3,(%0) \n" \
" blt 1f \n" \
" bra 2f \n" \
"1: jmp 3f \n" \
"2: \n" \
" .section .text.lock,\"ax\" \n" \
"3: call "helper"[],0 \n" \
" jmp 2b \n" \
" .previous" \
: \
: "d" (rw) \
: "memory", "d3", "cc"); \
} while (0)
#define __build_write_lock(rw, helper) \
do { \
if (__builtin_constant_p(rw)) \
__build_write_lock_const(rw, helper); \
else \
__build_write_lock_ptr(rw, helper); \
} while (0)
#endif /* CONFIG_SMP */
#endif /* _ASM_RWLOCK_H */

View File

@ -20,18 +20,25 @@
/* serial port 0 */
#define SC0CTR __SYSREG(0xd4002000, u16) /* control reg */
#define SC01CTR_CK 0x0007 /* clock source select */
#define SC0CTR_CK_TM8UFLOW_8 0x0000 /* - 1/8 timer 8 underflow (serial port 0 only) */
#define SC1CTR_CK_TM9UFLOW_8 0x0000 /* - 1/8 timer 9 underflow (serial port 1 only) */
#define SC01CTR_CK_IOCLK_8 0x0001 /* - 1/8 IOCLK */
#define SC01CTR_CK_IOCLK_32 0x0002 /* - 1/32 IOCLK */
#define SC0CTR_CK_TM2UFLOW_2 0x0003 /* - 1/2 timer 2 underflow (serial port 0 only) */
#define SC1CTR_CK_TM3UFLOW_2 0x0003 /* - 1/2 timer 3 underflow (serial port 1 only) */
#define SC0CTR_CK_TM0UFLOW_8 0x0004 /* - 1/8 timer 1 underflow (serial port 0 only) */
#define SC1CTR_CK_TM1UFLOW_8 0x0004 /* - 1/8 timer 2 underflow (serial port 1 only) */
#define SC0CTR_CK_TM2UFLOW_8 0x0005 /* - 1/8 timer 2 underflow (serial port 0 only) */
#define SC1CTR_CK_TM3UFLOW_8 0x0005 /* - 1/8 timer 3 underflow (serial port 1 only) */
#define SC01CTR_CK_EXTERN_8 0x0006 /* - 1/8 external closk */
#define SC01CTR_CK_EXTERN 0x0007 /* - external closk */
#if defined(CONFIG_AM33_2) || defined(CONFIG_AM33_3)
#define SC0CTR_CK_TM8UFLOW_8 0x0000 /* - 1/8 timer 8 underflow (serial port 0 only) */
#define SC0CTR_CK_TM2UFLOW_2 0x0003 /* - 1/2 timer 2 underflow (serial port 0 only) */
#define SC0CTR_CK_TM0UFLOW_8 0x0004 /* - 1/8 timer 0 underflow (serial port 0 only) */
#define SC0CTR_CK_TM2UFLOW_8 0x0005 /* - 1/8 timer 2 underflow (serial port 0 only) */
#define SC1CTR_CK_TM9UFLOW_8 0x0000 /* - 1/8 timer 9 underflow (serial port 1 only) */
#define SC1CTR_CK_TM3UFLOW_2 0x0003 /* - 1/2 timer 3 underflow (serial port 1 only) */
#define SC1CTR_CK_TM1UFLOW_8 0x0004 /* - 1/8 timer 1 underflow (serial port 1 only) */
#define SC1CTR_CK_TM3UFLOW_8 0x0005 /* - 1/8 timer 3 underflow (serial port 1 only) */
#else /* CONFIG_AM33_2 || CONFIG_AM33_3 */
#define SC0CTR_CK_TM8UFLOW_8 0x0000 /* - 1/8 timer 8 underflow (serial port 0 only) */
#define SC0CTR_CK_TM0UFLOW_8 0x0004 /* - 1/8 timer 0 underflow (serial port 0 only) */
#define SC0CTR_CK_TM2UFLOW_8 0x0005 /* - 1/8 timer 2 underflow (serial port 0 only) */
#define SC1CTR_CK_TM12UFLOW_8 0x0000 /* - 1/8 timer 12 underflow (serial port 1 only) */
#endif /* CONFIG_AM33_2 || CONFIG_AM33_3 */
#define SC01CTR_STB 0x0008 /* stop bit select */
#define SC01CTR_STB_1BIT 0x0000 /* - 1 stop bit */
#define SC01CTR_STB_2BIT 0x0008 /* - 2 stop bits */
@ -100,11 +107,23 @@
/* serial port 2 */
#define SC2CTR __SYSREG(0xd4002020, u16) /* control reg */
#ifdef CONFIG_AM33_2
#define SC2CTR_CK 0x0003 /* clock source select */
#define SC2CTR_CK_TM10UFLOW 0x0000 /* - timer 10 underflow */
#define SC2CTR_CK_TM2UFLOW 0x0001 /* - timer 2 underflow */
#define SC2CTR_CK_EXTERN 0x0002 /* - external closk */
#define SC2CTR_CK_TM3UFLOW 0x0003 /* - timer 3 underflow */
#else /* CONFIG_AM33_2 */
#define SC2CTR_CK 0x0007 /* clock source select */
#define SC2CTR_CK_TM9UFLOW_8 0x0000 /* - 1/8 timer 9 underflow */
#define SC2CTR_CK_IOCLK_8 0x0001 /* - 1/8 IOCLK */
#define SC2CTR_CK_IOCLK_32 0x0002 /* - 1/32 IOCLK */
#define SC2CTR_CK_TM3UFLOW_2 0x0003 /* - 1/2 timer 3 underflow */
#define SC2CTR_CK_TM1UFLOW_8 0x0004 /* - 1/8 timer 1 underflow */
#define SC2CTR_CK_TM3UFLOW_8 0x0005 /* - 1/8 timer 3 underflow */
#define SC2CTR_CK_EXTERN_8 0x0006 /* - 1/8 external closk */
#define SC2CTR_CK_EXTERN 0x0007 /* - external closk */
#endif /* CONFIG_AM33_2 */
#define SC2CTR_STB 0x0008 /* stop bit select */
#define SC2CTR_STB_1BIT 0x0000 /* - 1 stop bit */
#define SC2CTR_STB_2BIT 0x0008 /* - 2 stop bits */
@ -134,9 +153,14 @@
#define SC2ICR_RES 0x04 /* receive error select */
#define SC2ICR_RI 0x01 /* receive interrupt cause */
#define SC2TXB __SYSREG(0xd4002018, u8) /* transmit buffer reg */
#define SC2RXB __SYSREG(0xd4002019, u8) /* receive buffer reg */
#define SC2STR __SYSREG(0xd400201c, u8) /* status reg */
#define SC2TXB __SYSREG(0xd4002028, u8) /* transmit buffer reg */
#define SC2RXB __SYSREG(0xd4002029, u8) /* receive buffer reg */
#ifdef CONFIG_AM33_2
#define SC2STR __SYSREG(0xd400202c, u8) /* status reg */
#else /* CONFIG_AM33_2 */
#define SC2STR __SYSREG(0xd400202c, u16) /* status reg */
#endif /* CONFIG_AM33_2 */
#define SC2STR_OEF 0x0001 /* overrun error found */
#define SC2STR_PEF 0x0002 /* parity error found */
#define SC2STR_FEF 0x0004 /* framing error found */
@ -146,10 +170,17 @@
#define SC2STR_RXF 0x0040 /* receive status */
#define SC2STR_TXF 0x0080 /* transmit status */
#ifdef CONFIG_AM33_2
#define SC2TIM __SYSREG(0xd400202d, u8) /* status reg */
#endif
#ifdef CONFIG_AM33_2
#define SC2RXIRQ 24 /* serial 2 Receive IRQ */
#define SC2TXIRQ 25 /* serial 2 Transmit IRQ */
#else /* CONFIG_AM33_2 */
#define SC2RXIRQ 68 /* serial 2 Receive IRQ */
#define SC2TXIRQ 69 /* serial 2 Transmit IRQ */
#endif /* CONFIG_AM33_2 */
#define SC2RXICR GxICR(SC2RXIRQ) /* serial 2 receive intr ctrl reg */
#define SC2TXICR GxICR(SC2TXIRQ) /* serial 2 transmit intr ctrl reg */

View File

@ -9,10 +9,8 @@
* 2 of the Licence, or (at your option) any later version.
*/
/*
* The ASB2305 has an 18.432 MHz clock the UART
*/
#define BASE_BAUD (18432000 / 16)
#ifndef _ASM_SERIAL_H
#define _ASM_SERIAL_H
/* Standard COM flags (except for COM4, because of the 8514 problem) */
#ifdef CONFIG_SERIAL_DETECT_IRQ
@ -34,3 +32,5 @@
#endif
#include <unit/serial.h>
#endif /* _ASM_SERIAL_H */

View File

@ -3,6 +3,16 @@
* Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* Modified by Matsushita Electric Industrial Co., Ltd.
* Modifications:
* 13-Nov-2006 MEI Define IPI-IRQ number and add inline/macro function
* for SMP support.
* 22-Jan-2007 MEI Add the define related to SMP_BOOT_IRQ.
* 23-Feb-2007 MEI Add the define related to SMP icahce invalidate.
* 23-Jun-2008 MEI Delete INTC_IPI.
* 22-Jul-2008 MEI Add smp_nmi_call_function and related defines.
* 04-Aug-2008 MEI Delete USE_DOIRQ_CACHE_IPI.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public Licence
* as published by the Free Software Foundation; either version
@ -11,8 +21,98 @@
#ifndef _ASM_SMP_H
#define _ASM_SMP_H
#ifdef CONFIG_SMP
#error SMP not yet supported for MN10300
#ifndef __ASSEMBLY__
#include <linux/threads.h>
#include <linux/cpumask.h>
#endif
#ifdef CONFIG_SMP
#include <proc/smp-regs.h>
#define RESCHEDULE_IPI 63
#define CALL_FUNC_SINGLE_IPI 192
#define LOCAL_TIMER_IPI 193
#define FLUSH_CACHE_IPI 194
#define CALL_FUNCTION_NMI_IPI 195
#define GDB_NMI_IPI 196
#define SMP_BOOT_IRQ 195
#define RESCHEDULE_GxICR_LV GxICR_LEVEL_6
#define CALL_FUNCTION_GxICR_LV GxICR_LEVEL_4
#define LOCAL_TIMER_GxICR_LV GxICR_LEVEL_4
#define FLUSH_CACHE_GxICR_LV GxICR_LEVEL_0
#define SMP_BOOT_GxICR_LV GxICR_LEVEL_0
#define TIME_OUT_COUNT_BOOT_IPI 100
#define DELAY_TIME_BOOT_IPI 75000
#ifndef __ASSEMBLY__
/**
* raw_smp_processor_id - Determine the raw CPU ID of the CPU running it
*
* What we really want to do is to use the CPUID hardware CPU register to get
* this information, but accesses to that aren't cached, and run at system bus
* speed, not CPU speed. A copy of this value is, however, stored in the
* thread_info struct, and that can be cached.
*
* An alternate way of dealing with this could be to use the EPSW.S bits to
* cache this information for systems with up to four CPUs.
*/
#if 0
#define raw_smp_processor_id() (CPUID)
#else
#define raw_smp_processor_id() (current_thread_info()->cpu)
#endif
static inline int cpu_logical_map(int cpu)
{
return cpu;
}
static inline int cpu_number_map(int cpu)
{
return cpu;
}
extern cpumask_t cpu_boot_map;
extern void smp_init_cpus(void);
extern void smp_cache_interrupt(void);
extern void send_IPI_allbutself(int irq);
extern int smp_nmi_call_function(smp_call_func_t func, void *info, int wait);
extern void arch_send_call_function_single_ipi(int cpu);
extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
#ifdef CONFIG_HOTPLUG_CPU
extern int __cpu_disable(void);
extern void __cpu_die(unsigned int cpu);
#endif /* CONFIG_HOTPLUG_CPU */
#ifdef CONFIG_PREEMPT /* FIXME */
#define __frame \
({ \
struct pt_regs *f; \
preempt_disable(); \
f = ___frame[CPUID]; \
preempt_enable(); \
f; \
})
#else
#define __frame ___frame[CPUID]
#endif
#endif /* __ASSEMBLY__ */
#else /* CONFIG_SMP */
#ifndef __ASSEMBLY__
static inline void smp_init_cpus(void) {}
#endif /* __ASSEMBLY__ */
#endif /* CONFIG_SMP */
#endif /* _ASM_SMP_H */

View File

@ -11,6 +11,183 @@
#ifndef _ASM_SPINLOCK_H
#define _ASM_SPINLOCK_H
#error SMP spinlocks not implemented for MN10300
#include <asm/atomic.h>
#include <asm/rwlock.h>
#include <asm/page.h>
/*
* Simple spin lock operations. There are two variants, one clears IRQ's
* on the local processor, one does not.
*
* We make no fairness assumptions. They have a cost.
*/
#define arch_spin_is_locked(x) (*(volatile signed char *)(&(x)->slock) != 0)
#define arch_spin_unlock_wait(x) do { barrier(); } while (arch_spin_is_locked(x))
static inline void arch_spin_unlock(arch_spinlock_t *lock)
{
asm volatile(
" bclr 1,(0,%0) \n"
:
: "a"(&lock->slock)
: "memory", "cc");
}
static inline int arch_spin_trylock(arch_spinlock_t *lock)
{
int ret;
asm volatile(
" mov 1,%0 \n"
" bset %0,(%1) \n"
" bne 1f \n"
" clr %0 \n"
"1: xor 1,%0 \n"
: "=d"(ret)
: "a"(&lock->slock)
: "memory", "cc");
return ret;
}
static inline void arch_spin_lock(arch_spinlock_t *lock)
{
asm volatile(
"1: bset 1,(0,%0) \n"
" bne 1b \n"
:
: "a"(&lock->slock)
: "memory", "cc");
}
static inline void arch_spin_lock_flags(arch_spinlock_t *lock,
unsigned long flags)
{
int temp;
asm volatile(
"1: bset 1,(0,%2) \n"
" beq 3f \n"
" mov %1,epsw \n"
"2: mov (0,%2),%0 \n"
" or %0,%0 \n"
" bne 2b \n"
" mov %3,%0 \n"
" mov %0,epsw \n"
" nop \n"
" nop \n"
" bra 1b\n"
"3: \n"
: "=&d" (temp)
: "d" (flags), "a"(&lock->slock), "i"(EPSW_IE | MN10300_CLI_LEVEL)
: "memory", "cc");
}
#ifdef __KERNEL__
/*
* Read-write spinlocks, allowing multiple readers
* but only one writer.
*
* NOTE! it is quite common to have readers in interrupts
* but no interrupt writers. For those circumstances we
* can "mix" irq-safe locks - any writer needs to get a
* irq-safe write-lock, but readers can get non-irqsafe
* read-locks.
*/
/**
* read_can_lock - would read_trylock() succeed?
* @lock: the rwlock in question.
*/
#define arch_read_can_lock(x) ((int)(x)->lock > 0)
/**
* write_can_lock - would write_trylock() succeed?
* @lock: the rwlock in question.
*/
#define arch_write_can_lock(x) ((x)->lock == RW_LOCK_BIAS)
/*
* On mn10300, we implement read-write locks as a 32-bit counter
* with the high bit (sign) being the "contended" bit.
*/
static inline void arch_read_lock(arch_rwlock_t *rw)
{
#if 0 //def CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT
__build_read_lock(rw, "__read_lock_failed");
#else
{
atomic_t *count = (atomic_t *)rw;
while (atomic_dec_return(count) < 0)
atomic_inc(count);
}
#endif
}
static inline void arch_write_lock(arch_rwlock_t *rw)
{
#if 0 //def CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT
__build_write_lock(rw, "__write_lock_failed");
#else
{
atomic_t *count = (atomic_t *)rw;
while (!atomic_sub_and_test(RW_LOCK_BIAS, count))
atomic_add(RW_LOCK_BIAS, count);
}
#endif
}
static inline void arch_read_unlock(arch_rwlock_t *rw)
{
#if 0 //def CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT
__build_read_unlock(rw);
#else
{
atomic_t *count = (atomic_t *)rw;
atomic_inc(count);
}
#endif
}
static inline void arch_write_unlock(arch_rwlock_t *rw)
{
#if 0 //def CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT
__build_write_unlock(rw);
#else
{
atomic_t *count = (atomic_t *)rw;
atomic_add(RW_LOCK_BIAS, count);
}
#endif
}
static inline int arch_read_trylock(arch_rwlock_t *lock)
{
atomic_t *count = (atomic_t *)lock;
atomic_dec(count);
if (atomic_read(count) >= 0)
return 1;
atomic_inc(count);
return 0;
}
static inline int arch_write_trylock(arch_rwlock_t *lock)
{
atomic_t *count = (atomic_t *)lock;
if (atomic_sub_and_test(RW_LOCK_BIAS, count))
return 1;
atomic_add(RW_LOCK_BIAS, count);
return 0;
}
#define arch_read_lock_flags(lock, flags) arch_read_lock(lock)
#define arch_write_lock_flags(lock, flags) arch_write_lock(lock)
#define _raw_spin_relax(lock) cpu_relax()
#define _raw_read_relax(lock) cpu_relax()
#define _raw_write_relax(lock) cpu_relax()
#endif /* __KERNEL__ */
#endif /* _ASM_SPINLOCK_H */

View File

@ -0,0 +1,20 @@
#ifndef _ASM_SPINLOCK_TYPES_H
#define _ASM_SPINLOCK_TYPES_H
#ifndef __LINUX_SPINLOCK_TYPES_H
# error "please don't include this file directly"
#endif
typedef struct arch_spinlock {
unsigned int slock;
} arch_spinlock_t;
#define __ARCH_SPIN_LOCK_UNLOCKED { 0 }
typedef struct {
unsigned int lock;
} arch_rwlock_t;
#define __ARCH_RW_LOCK_UNLOCKED { RW_LOCK_BIAS }
#endif /* _ASM_SPINLOCK_TYPES_H */

View File

@ -12,6 +12,7 @@
#define _ASM_SYSTEM_H
#include <asm/cpu-regs.h>
#include <asm/intctl-regs.h>
#ifdef __KERNEL__
#ifndef __ASSEMBLY__
@ -57,8 +58,6 @@ do { \
#define nop() asm volatile ("nop")
#endif /* !__ASSEMBLY__ */
/*
* Force strict CPU ordering.
* And yes, this is required on UP too when we're talking
@ -85,17 +84,19 @@ do { \
#define smp_mb() mb()
#define smp_rmb() rmb()
#define smp_wmb() wmb()
#else
#define set_mb(var, value) do { xchg(&var, value); } while (0)
#else /* CONFIG_SMP */
#define smp_mb() barrier()
#define smp_rmb() barrier()
#define smp_wmb() barrier()
#endif
#define set_mb(var, value) do { var = value; mb(); } while (0)
#endif /* CONFIG_SMP */
#define set_wmb(var, value) do { var = value; wmb(); } while (0)
#define read_barrier_depends() do {} while (0)
#define smp_read_barrier_depends() do {} while (0)
#endif /* !__ASSEMBLY__ */
#endif /* __KERNEL__ */
#endif /* _ASM_SYSTEM_H */

View File

@ -17,21 +17,27 @@
#ifdef __KERNEL__
/* timer prescalar control */
/*
* Timer prescalar control
*/
#define TMPSCNT __SYSREG(0xd4003071, u8) /* timer prescaler control */
#define TMPSCNT_ENABLE 0x80 /* timer prescaler enable */
#define TMPSCNT_DISABLE 0x00 /* timer prescaler disable */
/* 8 bit timers */
/*
* 8-bit timers
*/
#define TM0MD __SYSREG(0xd4003000, u8) /* timer 0 mode register */
#define TM0MD_SRC 0x07 /* timer source */
#define TM0MD_SRC_IOCLK 0x00 /* - IOCLK */
#define TM0MD_SRC_IOCLK_8 0x01 /* - 1/8 IOCLK */
#define TM0MD_SRC_IOCLK_32 0x02 /* - 1/32 IOCLK */
#define TM0MD_SRC_TM2IO 0x03 /* - TM2IO pin input */
#define TM0MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */
#define TM0MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */
#if defined(CONFIG_AM33_2)
#define TM0MD_SRC_TM2IO 0x03 /* - TM2IO pin input */
#define TM0MD_SRC_TM0IO 0x07 /* - TM0IO pin input */
#endif /* CONFIG_AM33_2 */
#define TM0MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */
#define TM0MD_COUNT_ENABLE 0x80 /* timer count enable */
@ -43,7 +49,9 @@
#define TM1MD_SRC_TM0CASCADE 0x03 /* - cascade with timer 0 */
#define TM1MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */
#define TM1MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */
#if defined(CONFIG_AM33_2)
#define TM1MD_SRC_TM1IO 0x07 /* - TM1IO pin input */
#endif /* CONFIG_AM33_2 */
#define TM1MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */
#define TM1MD_COUNT_ENABLE 0x80 /* timer count enable */
@ -55,7 +63,9 @@
#define TM2MD_SRC_TM1CASCADE 0x03 /* - cascade with timer 1 */
#define TM2MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */
#define TM2MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */
#if defined(CONFIG_AM33_2)
#define TM2MD_SRC_TM2IO 0x07 /* - TM2IO pin input */
#endif /* CONFIG_AM33_2 */
#define TM2MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */
#define TM2MD_COUNT_ENABLE 0x80 /* timer count enable */
@ -64,11 +74,13 @@
#define TM3MD_SRC_IOCLK 0x00 /* - IOCLK */
#define TM3MD_SRC_IOCLK_8 0x01 /* - 1/8 IOCLK */
#define TM3MD_SRC_IOCLK_32 0x02 /* - 1/32 IOCLK */
#define TM3MD_SRC_TM1CASCADE 0x03 /* - cascade with timer 2 */
#define TM3MD_SRC_TM2CASCADE 0x03 /* - cascade with timer 2 */
#define TM3MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */
#define TM3MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */
#define TM3MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */
#if defined(CONFIG_AM33_2)
#define TM3MD_SRC_TM3IO 0x07 /* - TM3IO pin input */
#endif /* CONFIG_AM33_2 */
#define TM3MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */
#define TM3MD_COUNT_ENABLE 0x80 /* timer count enable */
@ -96,7 +108,9 @@
#define TM2ICR GxICR(TM2IRQ) /* timer 2 uflow intr ctrl reg */
#define TM3ICR GxICR(TM3IRQ) /* timer 3 uflow intr ctrl reg */
/* 16-bit timers 4,5 & 7-11 */
/*
* 16-bit timers 4,5 & 7-15
*/
#define TM4MD __SYSREG(0xd4003080, u8) /* timer 4 mode register */
#define TM4MD_SRC 0x07 /* timer source */
#define TM4MD_SRC_IOCLK 0x00 /* - IOCLK */
@ -105,7 +119,9 @@
#define TM4MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */
#define TM4MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */
#define TM4MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */
#if defined(CONFIG_AM33_2)
#define TM4MD_SRC_TM4IO 0x07 /* - TM4IO pin input */
#endif /* CONFIG_AM33_2 */
#define TM4MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */
#define TM4MD_COUNT_ENABLE 0x80 /* timer count enable */
@ -118,7 +134,11 @@
#define TM5MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */
#define TM5MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */
#define TM5MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */
#if defined(CONFIG_AM33_2)
#define TM5MD_SRC_TM5IO 0x07 /* - TM5IO pin input */
#else /* !CONFIG_AM33_2 */
#define TM5MD_SRC_TM7UFLOW 0x07 /* - timer 7 underflow */
#endif /* CONFIG_AM33_2 */
#define TM5MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */
#define TM5MD_COUNT_ENABLE 0x80 /* timer count enable */
@ -130,7 +150,9 @@
#define TM7MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */
#define TM7MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */
#define TM7MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */
#if defined(CONFIG_AM33_2)
#define TM7MD_SRC_TM7IO 0x07 /* - TM7IO pin input */
#endif /* CONFIG_AM33_2 */
#define TM7MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */
#define TM7MD_COUNT_ENABLE 0x80 /* timer count enable */
@ -143,7 +165,11 @@
#define TM8MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */
#define TM8MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */
#define TM8MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */
#if defined(CONFIG_AM33_2)
#define TM8MD_SRC_TM8IO 0x07 /* - TM8IO pin input */
#else /* !CONFIG_AM33_2 */
#define TM8MD_SRC_TM7UFLOW 0x07 /* - timer 7 underflow */
#endif /* CONFIG_AM33_2 */
#define TM8MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */
#define TM8MD_COUNT_ENABLE 0x80 /* timer count enable */
@ -156,7 +182,11 @@
#define TM9MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */
#define TM9MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */
#define TM9MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */
#if defined(CONFIG_AM33_2)
#define TM9MD_SRC_TM9IO 0x07 /* - TM9IO pin input */
#else /* !CONFIG_AM33_2 */
#define TM9MD_SRC_TM7UFLOW 0x07 /* - timer 7 underflow */
#endif /* CONFIG_AM33_2 */
#define TM9MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */
#define TM9MD_COUNT_ENABLE 0x80 /* timer count enable */
@ -169,7 +199,11 @@
#define TM10MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */
#define TM10MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */
#define TM10MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */
#if defined(CONFIG_AM33_2)
#define TM10MD_SRC_TM10IO 0x07 /* - TM10IO pin input */
#else /* !CONFIG_AM33_2 */
#define TM10MD_SRC_TM7UFLOW 0x07 /* - timer 7 underflow */
#endif /* CONFIG_AM33_2 */
#define TM10MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */
#define TM10MD_COUNT_ENABLE 0x80 /* timer count enable */
@ -178,32 +212,101 @@
#define TM11MD_SRC_IOCLK 0x00 /* - IOCLK */
#define TM11MD_SRC_IOCLK_8 0x01 /* - 1/8 IOCLK */
#define TM11MD_SRC_IOCLK_32 0x02 /* - 1/32 IOCLK */
#define TM11MD_SRC_TM7CASCADE 0x03 /* - cascade with timer 7 */
#define TM11MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */
#define TM11MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */
#define TM11MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */
#if defined(CONFIG_AM33_2)
#define TM11MD_SRC_TM11IO 0x07 /* - TM11IO pin input */
#else /* !CONFIG_AM33_2 */
#define TM11MD_SRC_TM7UFLOW 0x07 /* - timer 7 underflow */
#endif /* CONFIG_AM33_2 */
#define TM11MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */
#define TM11MD_COUNT_ENABLE 0x80 /* timer count enable */
#if defined(CONFIG_AM34_2)
#define TM12MD __SYSREG(0xd4003180, u8) /* timer 11 mode register */
#define TM12MD_SRC 0x07 /* timer source */
#define TM12MD_SRC_IOCLK 0x00 /* - IOCLK */
#define TM12MD_SRC_IOCLK_8 0x01 /* - 1/8 IOCLK */
#define TM12MD_SRC_IOCLK_32 0x02 /* - 1/32 IOCLK */
#define TM12MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */
#define TM12MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */
#define TM12MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */
#define TM12MD_SRC_TM7UFLOW 0x07 /* - timer 7 underflow */
#define TM12MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */
#define TM12MD_COUNT_ENABLE 0x80 /* timer count enable */
#define TM13MD __SYSREG(0xd4003182, u8) /* timer 11 mode register */
#define TM13MD_SRC 0x07 /* timer source */
#define TM13MD_SRC_IOCLK 0x00 /* - IOCLK */
#define TM13MD_SRC_IOCLK_8 0x01 /* - 1/8 IOCLK */
#define TM13MD_SRC_IOCLK_32 0x02 /* - 1/32 IOCLK */
#define TM13MD_SRC_TM12CASCADE 0x03 /* - cascade with timer 12 */
#define TM13MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */
#define TM13MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */
#define TM13MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */
#define TM13MD_SRC_TM7UFLOW 0x07 /* - timer 7 underflow */
#define TM13MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */
#define TM13MD_COUNT_ENABLE 0x80 /* timer count enable */
#define TM14MD __SYSREG(0xd4003184, u8) /* timer 11 mode register */
#define TM14MD_SRC 0x07 /* timer source */
#define TM14MD_SRC_IOCLK 0x00 /* - IOCLK */
#define TM14MD_SRC_IOCLK_8 0x01 /* - 1/8 IOCLK */
#define TM14MD_SRC_IOCLK_32 0x02 /* - 1/32 IOCLK */
#define TM14MD_SRC_TM13CASCADE 0x03 /* - cascade with timer 13 */
#define TM14MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */
#define TM14MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */
#define TM14MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */
#define TM14MD_SRC_TM7UFLOW 0x07 /* - timer 7 underflow */
#define TM14MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */
#define TM14MD_COUNT_ENABLE 0x80 /* timer count enable */
#define TM15MD __SYSREG(0xd4003186, u8) /* timer 11 mode register */
#define TM15MD_SRC 0x07 /* timer source */
#define TM15MD_SRC_IOCLK 0x00 /* - IOCLK */
#define TM15MD_SRC_IOCLK_8 0x01 /* - 1/8 IOCLK */
#define TM15MD_SRC_IOCLK_32 0x02 /* - 1/32 IOCLK */
#define TM15MD_SRC_TM0UFLOW 0x04 /* - timer 0 underflow */
#define TM15MD_SRC_TM1UFLOW 0x05 /* - timer 1 underflow */
#define TM15MD_SRC_TM2UFLOW 0x06 /* - timer 2 underflow */
#define TM15MD_SRC_TM7UFLOW 0x07 /* - timer 7 underflow */
#define TM15MD_INIT_COUNTER 0x40 /* initialize TMnBC = TMnBR */
#define TM15MD_COUNT_ENABLE 0x80 /* timer count enable */
#endif /* CONFIG_AM34_2 */
#define TM4BR __SYSREG(0xd4003090, u16) /* timer 4 base register */
#define TM5BR __SYSREG(0xd4003092, u16) /* timer 5 base register */
#define TM45BR __SYSREG(0xd4003090, u32) /* timer 4:5 base register */
#define TM7BR __SYSREG(0xd4003096, u16) /* timer 7 base register */
#define TM8BR __SYSREG(0xd4003098, u16) /* timer 8 base register */
#define TM9BR __SYSREG(0xd400309a, u16) /* timer 9 base register */
#define TM89BR __SYSREG(0xd4003098, u32) /* timer 8:9 base register */
#define TM10BR __SYSREG(0xd400309c, u16) /* timer 10 base register */
#define TM11BR __SYSREG(0xd400309e, u16) /* timer 11 base register */
#define TM45BR __SYSREG(0xd4003090, u32) /* timer 4:5 base register */
#if defined(CONFIG_AM34_2)
#define TM12BR __SYSREG(0xd4003190, u16) /* timer 12 base register */
#define TM13BR __SYSREG(0xd4003192, u16) /* timer 13 base register */
#define TM14BR __SYSREG(0xd4003194, u16) /* timer 14 base register */
#define TM15BR __SYSREG(0xd4003196, u16) /* timer 15 base register */
#endif /* CONFIG_AM34_2 */
#define TM4BC __SYSREG(0xd40030a0, u16) /* timer 4 binary counter */
#define TM5BC __SYSREG(0xd40030a2, u16) /* timer 5 binary counter */
#define TM45BC __SYSREG(0xd40030a0, u32) /* timer 4:5 binary counter */
#define TM7BC __SYSREG(0xd40030a6, u16) /* timer 7 binary counter */
#define TM8BC __SYSREG(0xd40030a8, u16) /* timer 8 binary counter */
#define TM9BC __SYSREG(0xd40030aa, u16) /* timer 9 binary counter */
#define TM89BC __SYSREG(0xd40030a8, u32) /* timer 8:9 binary counter */
#define TM10BC __SYSREG(0xd40030ac, u16) /* timer 10 binary counter */
#define TM11BC __SYSREG(0xd40030ae, u16) /* timer 11 binary counter */
#if defined(CONFIG_AM34_2)
#define TM12BC __SYSREG(0xd40031a0, u16) /* timer 12 binary counter */
#define TM13BC __SYSREG(0xd40031a2, u16) /* timer 13 binary counter */
#define TM14BC __SYSREG(0xd40031a4, u16) /* timer 14 binary counter */
#define TM15BC __SYSREG(0xd40031a6, u16) /* timer 15 binary counter */
#endif /* CONFIG_AM34_2 */
#define TM4IRQ 6 /* timer 4 IRQ */
#define TM5IRQ 7 /* timer 5 IRQ */
@ -212,6 +315,12 @@
#define TM9IRQ 13 /* timer 9 IRQ */
#define TM10IRQ 14 /* timer 10 IRQ */
#define TM11IRQ 15 /* timer 11 IRQ */
#if defined(CONFIG_AM34_2)
#define TM12IRQ 64 /* timer 12 IRQ */
#define TM13IRQ 65 /* timer 13 IRQ */
#define TM14IRQ 66 /* timer 14 IRQ */
#define TM15IRQ 67 /* timer 15 IRQ */
#endif /* CONFIG_AM34_2 */
#define TM4ICR GxICR(TM4IRQ) /* timer 4 uflow intr ctrl reg */
#define TM5ICR GxICR(TM5IRQ) /* timer 5 uflow intr ctrl reg */
@ -220,8 +329,16 @@
#define TM9ICR GxICR(TM9IRQ) /* timer 9 uflow intr ctrl reg */
#define TM10ICR GxICR(TM10IRQ) /* timer 10 uflow intr ctrl reg */
#define TM11ICR GxICR(TM11IRQ) /* timer 11 uflow intr ctrl reg */
#if defined(CONFIG_AM34_2)
#define TM12ICR GxICR(TM12IRQ) /* timer 12 uflow intr ctrl reg */
#define TM13ICR GxICR(TM13IRQ) /* timer 13 uflow intr ctrl reg */
#define TM14ICR GxICR(TM14IRQ) /* timer 14 uflow intr ctrl reg */
#define TM15ICR GxICR(TM15IRQ) /* timer 15 uflow intr ctrl reg */
#endif /* CONFIG_AM34_2 */
/* 16-bit timer 6 */
/*
* 16-bit timer 6
*/
#define TM6MD __SYSREG(0xd4003084, u16) /* timer6 mode register */
#define TM6MD_SRC 0x0007 /* timer source */
#define TM6MD_SRC_IOCLK 0x0000 /* - IOCLK */
@ -229,10 +346,14 @@
#define TM6MD_SRC_IOCLK_32 0x0002 /* - 1/32 IOCLK */
#define TM6MD_SRC_TM0UFLOW 0x0004 /* - timer 0 underflow */
#define TM6MD_SRC_TM1UFLOW 0x0005 /* - timer 1 underflow */
#define TM6MD_SRC_TM6IOB_BOTH 0x0006 /* - TM6IOB pin input (both edges) */
#define TM6MD_SRC_TM2UFLOW 0x0006 /* - timer 2 underflow */
#if defined(CONFIG_AM33_2)
/* #define TM6MD_SRC_TM6IOB_BOTH 0x0006 */ /* - TM6IOB pin input (both edges) */
#define TM6MD_SRC_TM6IOB_SINGLE 0x0007 /* - TM6IOB pin input (single edge) */
#define TM6MD_CLR_ENABLE 0x0010 /* clear count enable */
#endif /* CONFIG_AM33_2 */
#define TM6MD_ONESHOT_ENABLE 0x0040 /* oneshot count */
#define TM6MD_CLR_ENABLE 0x0010 /* clear count enable */
#if defined(CONFIG_AM33_2)
#define TM6MD_TRIG_ENABLE 0x0080 /* TM6IOB pin trigger enable */
#define TM6MD_PWM 0x3800 /* PWM output mode */
#define TM6MD_PWM_DIS 0x0000 /* - disabled */
@ -240,10 +361,15 @@
#define TM6MD_PWM_11BIT 0x1800 /* - 11 bits mode */
#define TM6MD_PWM_12BIT 0x3000 /* - 12 bits mode */
#define TM6MD_PWM_14BIT 0x3800 /* - 14 bits mode */
#endif /* CONFIG_AM33_2 */
#define TM6MD_INIT_COUNTER 0x4000 /* initialize TMnBC to zero */
#define TM6MD_COUNT_ENABLE 0x8000 /* timer count enable */
#define TM6MDA __SYSREG(0xd40030b4, u8) /* timer6 cmp/cap A mode reg */
#define TM6MDA_MODE_CMP_SINGLE 0x00 /* - compare, single buffer mode */
#define TM6MDA_MODE_CMP_DOUBLE 0x40 /* - compare, double buffer mode */
#if defined(CONFIG_AM33_2)
#define TM6MDA_OUT 0x07 /* output select */
#define TM6MDA_OUT_SETA_RESETB 0x00 /* - set at match A, reset at match B */
#define TM6MDA_OUT_SETA_RESETOV 0x01 /* - set at match A, reset at overflow */
@ -251,30 +377,35 @@
#define TM6MDA_OUT_RESETA 0x03 /* - reset at match A */
#define TM6MDA_OUT_TOGGLE 0x04 /* - toggle on match A */
#define TM6MDA_MODE 0xc0 /* compare A register mode */
#define TM6MDA_MODE_CMP_SINGLE 0x00 /* - compare, single buffer mode */
#define TM6MDA_MODE_CMP_DOUBLE 0x40 /* - compare, double buffer mode */
#define TM6MDA_MODE_CAP_S_EDGE 0x80 /* - capture, single edge mode */
#define TM6MDA_MODE_CAP_D_EDGE 0xc0 /* - capture, double edge mode */
#define TM6MDA_EDGE 0x20 /* compare A edge select */
#define TM6MDA_EDGE_FALLING 0x00 /* capture on falling edge */
#define TM6MDA_EDGE_RISING 0x20 /* capture on rising edge */
#define TM6MDA_CAPTURE_ENABLE 0x10 /* capture enable */
#else /* !CONFIG_AM33_2 */
#define TM6MDA_MODE 0x40 /* compare A register mode */
#endif /* CONFIG_AM33_2 */
#define TM6MDB __SYSREG(0xd40030b5, u8) /* timer6 cmp/cap B mode reg */
#define TM6MDB_MODE_CMP_SINGLE 0x00 /* - compare, single buffer mode */
#define TM6MDB_MODE_CMP_DOUBLE 0x40 /* - compare, double buffer mode */
#if defined(CONFIG_AM33_2)
#define TM6MDB_OUT 0x07 /* output select */
#define TM6MDB_OUT_SETB_RESETA 0x00 /* - set at match B, reset at match A */
#define TM6MDB_OUT_SETB_RESETOV 0x01 /* - set at match B */
#define TM6MDB_OUT_RESETB 0x03 /* - reset at match B */
#define TM6MDB_OUT_TOGGLE 0x04 /* - toggle on match B */
#define TM6MDB_MODE 0xc0 /* compare B register mode */
#define TM6MDB_MODE_CMP_SINGLE 0x00 /* - compare, single buffer mode */
#define TM6MDB_MODE_CMP_DOUBLE 0x40 /* - compare, double buffer mode */
#define TM6MDB_MODE_CAP_S_EDGE 0x80 /* - capture, single edge mode */
#define TM6MDB_MODE_CAP_D_EDGE 0xc0 /* - capture, double edge mode */
#define TM6MDB_EDGE 0x20 /* compare B edge select */
#define TM6MDB_EDGE_FALLING 0x00 /* capture on falling edge */
#define TM6MDB_EDGE_RISING 0x20 /* capture on rising edge */
#define TM6MDB_CAPTURE_ENABLE 0x10 /* capture enable */
#else /* !CONFIG_AM33_2 */
#define TM6MDB_MODE 0x40 /* compare B register mode */
#endif /* CONFIG_AM33_2 */
#define TM6CA __SYSREG(0xd40030c4, u16) /* timer6 cmp/capture reg A */
#define TM6CB __SYSREG(0xd40030d4, u16) /* timer6 cmp/capture reg B */
@ -288,6 +419,34 @@
#define TM6AICR GxICR(TM6AIRQ) /* timer 6A intr control reg */
#define TM6BICR GxICR(TM6BIRQ) /* timer 6B intr control reg */
#if defined(CONFIG_AM34_2)
/*
* MTM: OS Tick-Timer
*/
#define TMTMD __SYSREG(0xd4004100, u8) /* Tick Timer mode register */
#define TMTMD_TMTLDE 0x40 /* initialize TMTBC = TMTBR */
#define TMTMD_TMTCNE 0x80 /* timer count enable */
#define TMTBR __SYSREG(0xd4004110, u32) /* Tick Timer mode reg */
#define TMTBC __SYSREG(0xd4004120, u32) /* Tick Timer mode reg */
/*
* MTM: OS Timestamp-Timer
*/
#define TMSMD __SYSREG(0xd4004140, u8) /* Tick Timer mode register */
#define TMSMD_TMSLDE 0x40 /* initialize TMSBC = TMSBR */
#define TMSMD_TMSCNE 0x80 /* timer count enable */
#define TMSBR __SYSREG(0xd4004150, u32) /* Tick Timer mode register */
#define TMSBC __SYSREG(0xd4004160, u32) /* Tick Timer mode register */
#define TMTIRQ 119 /* OS Tick timer IRQ */
#define TMSIRQ 120 /* Timestamp timer IRQ */
#define TMTICR GxICR(TMTIRQ) /* OS Tick timer uflow intr ctrl reg */
#define TMSICR GxICR(TMSIRQ) /* Timestamp timer uflow intr ctrl reg */
#endif /* CONFIG_AM34_2 */
#endif /* __KERNEL__ */
#endif /* _ASM_TIMER_REGS_H */

View File

@ -16,8 +16,7 @@
#define TICK_SIZE (tick_nsec / 1000)
#define CLOCK_TICK_RATE 1193180 /* Underlying HZ - this should probably be set
* to something appropriate, but what? */
#define CLOCK_TICK_RATE MN10300_JCCLK /* Underlying HZ */
extern cycles_t cacheflush_time;

View File

@ -377,7 +377,7 @@ unsigned long __generic_copy_to_user_nocheck(void *to, const void *from,
#if 0
#error don't use - these macros don't increment to & from pointers
#error "don't use - these macros don't increment to & from pointers"
/* Optimize just a little bit when we know the size of the move. */
#define __constant_copy_user(to, from, size) \
do { \

View File

@ -10,8 +10,9 @@ obj-y := process.o signal.o entry.o traps.o irq.o \
ptrace.o setup.o time.o sys_mn10300.o io.o kthread.o \
switch_to.o mn10300_ksyms.o kernel_execve.o $(fpu-obj-y)
obj-$(CONFIG_MN10300_WD_TIMER) += mn10300-watchdog.o mn10300-watchdog-low.o
obj-$(CONFIG_SMP) += smp.o smp-low.o
obj-$(CONFIG_MN10300_WD_TIMER) += mn10300-watchdog.o mn10300-watchdog-low.o
obj-$(CONFIG_MN10300_TTYSM) += mn10300-serial.o mn10300-serial-low.o \
mn10300-debug.o

View File

@ -66,7 +66,7 @@ void foo(void)
OFFSET(THREAD_SP, thread_struct, sp);
OFFSET(THREAD_A3, thread_struct, a3);
OFFSET(THREAD_USP, thread_struct, usp);
OFFSET(THREAD_FRAME, thread_struct, __frame);
OFFSET(THREAD_FRAME, thread_struct, frame);
#ifdef CONFIG_FPU
OFFSET(THREAD_FPU_FLAGS, thread_struct, fpu_flags);
OFFSET(THREAD_FPU_STATE, thread_struct, fpu_state);

View File

@ -28,25 +28,17 @@
#include <asm/asm-offsets.h>
#include <asm/frame.inc>
#if defined(CONFIG_SMP) && defined(CONFIG_GDBSTUB)
#include <asm/gdb-stub.h>
#endif /* CONFIG_SMP && CONFIG_GDBSTUB */
#ifdef CONFIG_PREEMPT
#define preempt_stop __cli
#define preempt_stop LOCAL_IRQ_DISABLE
#else
#define preempt_stop
#define resume_kernel restore_all
#endif
.macro __cli
and ~EPSW_IM,epsw
or EPSW_IE|MN10300_CLI_LEVEL,epsw
nop
nop
nop
.endm
.macro __sti
or EPSW_IE|EPSW_IM_7,epsw
.endm
.am33_2
###############################################################################
@ -88,7 +80,7 @@ syscall_call:
syscall_exit:
# make sure we don't miss an interrupt setting need_resched or
# sigpending between sampling and the rti
__cli
LOCAL_IRQ_DISABLE
mov (TI_flags,a2),d2
btst _TIF_ALLWORK_MASK,d2
bne syscall_exit_work
@ -105,7 +97,7 @@ restore_all:
syscall_exit_work:
btst _TIF_SYSCALL_TRACE,d2
beq work_pending
__sti # could let syscall_trace_exit() call
LOCAL_IRQ_ENABLE # could let syscall_trace_exit() call
# schedule() instead
mov fp,d0
call syscall_trace_exit[],0 # do_syscall_trace(regs)
@ -121,7 +113,7 @@ work_resched:
# make sure we don't miss an interrupt setting need_resched or
# sigpending between sampling and the rti
__cli
LOCAL_IRQ_DISABLE
# is there any work to be done other than syscall tracing?
mov (TI_flags,a2),d2
@ -168,7 +160,7 @@ ret_from_intr:
ENTRY(resume_userspace)
# make sure we don't miss an interrupt setting need_resched or
# sigpending between sampling and the rti
__cli
LOCAL_IRQ_DISABLE
# is there any work to be done on int/exception return?
mov (TI_flags,a2),d2
@ -178,7 +170,7 @@ ENTRY(resume_userspace)
#ifdef CONFIG_PREEMPT
ENTRY(resume_kernel)
__cli
LOCAL_IRQ_DISABLE
mov (TI_preempt_count,a2),d0 # non-zero preempt_count ?
cmp 0,d0
bne restore_all
@ -281,6 +273,79 @@ ENTRY(nmi_handler)
add -4,sp
mov d0,(sp)
mov (TBR),d0
#ifdef CONFIG_SMP
add -4,sp
mov d0,(sp) # save d0(TBR)
movhu (NMIAGR),d0
and NMIAGR_GN,d0
lsr 0x2,d0
cmp CALL_FUNCTION_NMI_IPI,d0
bne 5f # if not call function, jump
# function call nmi ipi
add 4,sp # no need to store TBR
mov GxICR_DETECT,d0 # clear NMI request
movbu d0,(GxICR(CALL_FUNCTION_NMI_IPI))
movhu (GxICR(CALL_FUNCTION_NMI_IPI)),d0
and ~EPSW_NMID,epsw # enable NMI
mov (sp),d0 # restore d0
SAVE_ALL
call smp_nmi_call_function_interrupt[],0
RESTORE_ALL
5:
#ifdef CONFIG_GDBSTUB
cmp GDB_NMI_IPI,d0
bne 3f # if not gdb nmi ipi, jump
# gdb nmi ipi
add 4,sp # no need to store TBR
mov GxICR_DETECT,d0 # clear NMI
movbu d0,(GxICR(GDB_NMI_IPI))
movhu (GxICR(GDB_NMI_IPI)),d0
and ~EPSW_NMID,epsw # enable NMI
#ifdef CONFIG_MN10300_CACHE_ENABLED
mov (gdbstub_nmi_opr_type),d0
cmp GDBSTUB_NMI_CACHE_PURGE,d0
bne 4f # if not gdb cache purge, jump
# gdb cache purge nmi ipi
add -20,sp
mov d1,(4,sp)
mov a0,(8,sp)
mov a1,(12,sp)
mov mdr,d0
mov d0,(16,sp)
call gdbstub_local_purge_cache[],0
mov 0x1,d0
mov (CPUID),d1
asl d1,d0
mov gdbstub_nmi_cpumask,a0
bclr d0,(a0)
mov (4,sp),d1
mov (8,sp),a0
mov (12,sp),a1
mov (16,sp),d0
mov d0,mdr
add 20,sp
mov (sp),d0
add 4,sp
rti
4:
#endif /* CONFIG_MN10300_CACHE_ENABLED */
# gdb wait nmi ipi
mov (sp),d0
SAVE_ALL
call gdbstub_nmi_wait[],0
RESTORE_ALL
3:
#endif /* CONFIG_GDBSTUB */
mov (sp),d0 # restore TBR to d0
add 4,sp
#endif /* CONFIG_SMP */
bra __common_exception_nonmi
ENTRY(__common_exception)
@ -314,15 +379,21 @@ __common_exception_nonmi:
mov d0,(REG_ORIG_D0,fp)
#ifdef CONFIG_GDBSTUB
#ifdef CONFIG_SMP
call gdbstub_busy_check[],0
and d0,d0 # check return value
beq 2f
#else /* CONFIG_SMP */
btst 0x01,(gdbstub_busy)
beq 2f
#endif /* CONFIG_SMP */
and ~EPSW_IE,epsw
mov fp,d0
mov a2,d1
call gdbstub_exception[],0 # gdbstub itself caused an exception
bra restore_all
2:
#endif
#endif /* CONFIG_GDBSTUB */
mov fp,d0 # arg 0: stacked register file
mov a2,d1 # arg 1: exception number
@ -357,11 +428,7 @@ ENTRY(set_excp_vector)
add exception_table,d0
mov d1,(d0)
mov 4,d1
#if defined(CONFIG_MN10300_CACHE_WBACK)
jmp mn10300_dcache_flush_inv_range2
#else
ret [],0
#endif
###############################################################################
#

View File

@ -18,6 +18,7 @@
#include <asm/thread_info.h>
#include <asm/frame.inc>
#include <asm/intctl-regs.h>
#include <asm/irqflags.h>
#include <unit/serial.h>
.text
@ -69,7 +70,7 @@ gdbstub_io_rx_overflow:
bra gdbstub_io_rx_done
gdbstub_io_rx_enter:
or EPSW_IE|EPSW_IM_1,epsw
LOCAL_CHANGE_INTR_MASK_LEVEL(NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL+1))
add -4,sp
SAVE_ALL
@ -80,7 +81,7 @@ gdbstub_io_rx_enter:
mov fp,d0
call gdbstub_rx_irq[],0 # gdbstub_rx_irq(regs,excep)
and ~EPSW_IE,epsw
LOCAL_CLI
bclr 0x01,(gdbstub_busy)
.globl gdbstub_return

View File

@ -23,6 +23,7 @@
#include <asm/exceptions.h>
#include <asm/serial-regs.h>
#include <unit/serial.h>
#include <asm/smp.h>
/*
* initialise the GDB stub
@ -45,22 +46,34 @@ void gdbstub_io_init(void)
XIRQxICR(GDBPORT_SERIAL_IRQ) = 0;
tmp = XIRQxICR(GDBPORT_SERIAL_IRQ);
#if CONFIG_GDBSTUB_IRQ_LEVEL == 0
IVAR0 = EXCEP_IRQ_LEVEL0;
set_intr_stub(EXCEP_IRQ_LEVEL0, gdbstub_io_rx_handler);
#elif CONFIG_GDBSTUB_IRQ_LEVEL == 1
IVAR1 = EXCEP_IRQ_LEVEL1;
#elif CONFIG_GDBSTUB_IRQ_LEVEL == 2
IVAR2 = EXCEP_IRQ_LEVEL2;
#elif CONFIG_GDBSTUB_IRQ_LEVEL == 3
IVAR3 = EXCEP_IRQ_LEVEL3;
#elif CONFIG_GDBSTUB_IRQ_LEVEL == 4
IVAR4 = EXCEP_IRQ_LEVEL4;
#elif CONFIG_GDBSTUB_IRQ_LEVEL == 5
IVAR5 = EXCEP_IRQ_LEVEL5;
#else
#error "Unknown irq level for gdbstub."
#endif
set_intr_stub(NUM2EXCEP_IRQ_LEVEL(CONFIG_GDBSTUB_IRQ_LEVEL),
gdbstub_io_rx_handler);
XIRQxICR(GDBPORT_SERIAL_IRQ) &= ~GxICR_REQUEST;
XIRQxICR(GDBPORT_SERIAL_IRQ) = GxICR_ENABLE | GxICR_LEVEL_0;
XIRQxICR(GDBPORT_SERIAL_IRQ) =
GxICR_ENABLE | NUM2GxICR_LEVEL(CONFIG_GDBSTUB_IRQ_LEVEL);
tmp = XIRQxICR(GDBPORT_SERIAL_IRQ);
GDBPORT_SERIAL_IER = UART_IER_RDI | UART_IER_RLSI;
/* permit level 0 IRQs to take place */
asm volatile(
" and %0,epsw \n"
" or %1,epsw \n"
:
: "i"(~EPSW_IM), "i"(EPSW_IE | EPSW_IM_1)
);
local_change_intr_mask_level(NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL + 1));
}
/*
@ -87,6 +100,9 @@ int gdbstub_io_rx_char(unsigned char *_ch, int nonblock)
{
unsigned ix;
u8 ch, st;
#if defined(CONFIG_MN10300_WD_TIMER)
int cpu;
#endif
*_ch = 0xff;
@ -104,8 +120,9 @@ int gdbstub_io_rx_char(unsigned char *_ch, int nonblock)
if (nonblock)
return -EAGAIN;
#ifdef CONFIG_MN10300_WD_TIMER
watchdog_alert_counter = 0;
#endif /* CONFIG_MN10300_WD_TIMER */
for (cpu = 0; cpu < NR_CPUS; cpu++)
watchdog_alert_counter[cpu] = 0;
#endif
goto try_again;
}

View File

@ -58,9 +58,12 @@ void __init gdbstub_io_init(void)
gdbstub_io_set_baud(115200);
/* we want to get serial receive interrupts */
set_intr_level(gdbstub_port->rx_irq, GxICR_LEVEL_0);
set_intr_level(gdbstub_port->tx_irq, GxICR_LEVEL_0);
set_intr_stub(EXCEP_IRQ_LEVEL0, gdbstub_io_rx_handler);
set_intr_level(gdbstub_port->rx_irq,
NUM2GxICR_LEVEL(CONFIG_GDBSTUB_IRQ_LEVEL));
set_intr_level(gdbstub_port->tx_irq,
NUM2GxICR_LEVEL(CONFIG_GDBSTUB_IRQ_LEVEL));
set_intr_stub(NUM2EXCEP_IRQ_LEVEL(CONFIG_GDBSTUB_IRQ_LEVEL),
gdbstub_io_rx_handler);
*gdbstub_port->rx_icr |= GxICR_ENABLE;
tmp = *gdbstub_port->rx_icr;
@ -84,12 +87,7 @@ void __init gdbstub_io_init(void)
tmp = *gdbstub_port->_control;
/* permit level 0 IRQs only */
asm volatile(
" and %0,epsw \n"
" or %1,epsw \n"
:
: "i"(~EPSW_IM), "i"(EPSW_IE|EPSW_IM_1)
);
local_change_intr_mask_level(NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL + 1));
}
/*
@ -184,6 +182,9 @@ int gdbstub_io_rx_char(unsigned char *_ch, int nonblock)
{
unsigned ix;
u8 ch, st;
#if defined(CONFIG_MN10300_WD_TIMER)
int cpu;
#endif
*_ch = 0xff;
@ -201,8 +202,9 @@ try_again:
if (nonblock)
return -EAGAIN;
#ifdef CONFIG_MN10300_WD_TIMER
watchdog_alert_counter = 0;
#endif /* CONFIG_MN10300_WD_TIMER */
for (cpu = 0; cpu < NR_CPUS; cpu++)
watchdog_alert_counter[cpu] = 0;
#endif
goto try_again;
}

View File

@ -440,15 +440,11 @@ static const unsigned char gdbstub_insn_sizes[256] =
static int __gdbstub_mark_bp(u8 *addr, int ix)
{
if (addr < (u8 *) 0x70000000UL)
return 0;
/* 70000000-7fffffff: vmalloc area */
if (addr < (u8 *) 0x80000000UL)
/* vmalloc area */
if (((u8 *) VMALLOC_START <= addr) && (addr < (u8 *) VMALLOC_END))
goto okay;
if (addr < (u8 *) 0x8c000000UL)
return 0;
/* 8c000000-93ffffff: SRAM, SDRAM */
if (addr < (u8 *) 0x94000000UL)
/* SRAM, SDRAM */
if (((u8 *) 0x80000000UL <= addr) && (addr < (u8 *) 0xa0000000UL))
goto okay;
return 0;
@ -1197,9 +1193,8 @@ static int gdbstub(struct pt_regs *regs, enum exception_code excep)
mn10300_set_gdbleds(1);
asm volatile("mov mdr,%0" : "=d"(mdr));
asm volatile("mov epsw,%0" : "=d"(epsw));
asm volatile("mov %0,epsw"
:: "d"((epsw & ~EPSW_IM) | EPSW_IE | EPSW_IM_1));
local_save_flags(epsw);
local_change_intr_mask_level(NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL + 1));
gdbstub_store_fpu();

View File

@ -19,6 +19,12 @@
#include <asm/frame.inc>
#include <asm/param.h>
#include <unit/serial.h>
#ifdef CONFIG_SMP
#include <asm/smp.h>
#include <asm/intctl-regs.h>
#include <asm/cpu-regs.h>
#include <proc/smp-regs.h>
#endif /* CONFIG_SMP */
__HEAD
@ -30,17 +36,51 @@
.globl _start
.type _start,@function
_start:
#ifdef CONFIG_SMP
#
# If this is a secondary CPU (AP), then deal with that elsewhere
#
mov (CPUID),d3
and CPUID_MASK,d3
bne startup_secondary
#
# We're dealing with the primary CPU (BP) here, then.
# Keep BP's D0,D1,D2 register for boot check.
#
# Set up the Boot IPI for each secondary CPU
mov 0x1,a0
loop_set_secondary_icr:
mov a0,a1
asl CROSS_ICR_CPU_SHIFT,a1
add CROSS_GxICR(SMP_BOOT_IRQ,0),a1
movhu (a1),d3
or GxICR_ENABLE|GxICR_LEVEL_0,d3
movhu d3,(a1)
movhu (a1),d3 # flush
inc a0
cmp NR_CPUS,a0
bne loop_set_secondary_icr
#endif /* CONFIG_SMP */
# save commandline pointer
mov d0,a3
# preload the PGD pointer register
mov swapper_pg_dir,d0
mov d0,(PTBR)
clr d0
movbu d0,(PIDR)
# turn on the TLBs
mov MMUCTR_IIV|MMUCTR_DIV,d0
mov d0,(MMUCTR)
#ifdef CONFIG_AM34_2
mov MMUCTR_ITE|MMUCTR_DTE|MMUCTR_CE|MMUCTR_WTE,d0
#else
mov MMUCTR_ITE|MMUCTR_DTE|MMUCTR_CE,d0
#endif
mov d0,(MMUCTR)
# turn on AM33v2 exception handling mode and set the trap table base
@ -51,6 +91,11 @@ _start:
mov d0,(TBR)
# invalidate and enable both of the caches
#ifdef CONFIG_SMP
mov ECHCTR,a0
clr d0
mov d0,(a0)
#endif
mov CHCTR,a0
clr d0
movhu d0,(a0) # turn off first
@ -206,6 +251,44 @@ __no_parameters:
call processor_init[],0
call unit_init[],0
#ifdef CONFIG_SMP
# mark the primary CPU in cpu_boot_map
mov cpu_boot_map,a0
mov 0x1,d0
mov d0,(a0)
# signal each secondary CPU to begin booting
mov 0x1,d2 # CPU ID
loop_request_boot_secondary:
mov d2,a0
# send SMP_BOOT_IPI to secondary CPU
asl CROSS_ICR_CPU_SHIFT,a0
add CROSS_GxICR(SMP_BOOT_IRQ,0),a0
movhu (a0),d0
or GxICR_REQUEST|GxICR_DETECT,d0
movhu d0,(a0)
movhu (a0),d0 # flush
# wait up to 100ms for AP's IPI to be received
clr d3
wait_on_secondary_boot:
mov DELAY_TIME_BOOT_IPI,d0
call __delay[],0
inc d3
mov cpu_boot_map,a0
mov (a0),d0
lsr d2,d0
btst 0x1,d0
bne 1f
cmp TIME_OUT_COUNT_BOOT_IPI,d3
bne wait_on_secondary_boot
1:
inc d2
cmp NR_CPUS,d2
bne loop_request_boot_secondary
#endif /* CONFIG_SMP */
#ifdef CONFIG_GDBSTUB
call gdbstub_init[],0
@ -217,7 +300,118 @@ __gdbstub_pause:
#endif
jmp start_kernel
.size _start, _start-.
.size _start,.-_start
###############################################################################
#
# Secondary CPU boot point
#
###############################################################################
#ifdef CONFIG_SMP
startup_secondary:
# preload the PGD pointer register
mov swapper_pg_dir,d0
mov d0,(PTBR)
clr d0
movbu d0,(PIDR)
# turn on the TLBs
mov MMUCTR_IIV|MMUCTR_DIV,d0
mov d0,(MMUCTR)
#ifdef CONFIG_AM34_2
mov MMUCTR_ITE|MMUCTR_DTE|MMUCTR_CE|MMUCTR_WTE,d0
#else
mov MMUCTR_ITE|MMUCTR_DTE|MMUCTR_CE,d0
#endif
mov d0,(MMUCTR)
# turn on AM33v2 exception handling mode and set the trap table base
movhu (CPUP),d0
or CPUP_EXM_AM33V2,d0
movhu d0,(CPUP)
# set the interrupt vector table
mov CONFIG_INTERRUPT_VECTOR_BASE,d0
mov d0,(TBR)
# invalidate and enable both of the caches
mov ECHCTR,a0
clr d0
mov d0,(a0)
mov CHCTR,a0
clr d0
movhu d0,(a0) # turn off first
mov CHCTR_ICINV|CHCTR_DCINV,d0
movhu d0,(a0)
setlb
mov (a0),d0
btst CHCTR_ICBUSY|CHCTR_DCBUSY,d0 # wait till not busy (use CPU loop buffer)
lne
#ifdef CONFIG_MN10300_CACHE_ENABLED
#ifdef CONFIG_MN10300_CACHE_WBACK
#ifndef CONFIG_MN10300_CACHE_WBACK_NOWRALLOC
mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRBACK,d0
#else
mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRBACK|CHCTR_DCALMD,d0
#endif /* !NOWRALLOC */
#else
mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRTHROUGH,d0
#endif /* WBACK */
movhu d0,(a0) # enable
#endif /* ENABLED */
# Clear the boot IPI interrupt for this CPU
movhu (GxICR(SMP_BOOT_IRQ)),d0
and ~GxICR_REQUEST,d0
movhu d0,(GxICR(SMP_BOOT_IRQ))
movhu (GxICR(SMP_BOOT_IRQ)),d0 # flush
/* get stack */
mov CONFIG_INTERRUPT_VECTOR_BASE + CONFIG_BOOT_STACK_OFFSET,a0
mov (CPUID),d0
and CPUID_MASK,d0
mulu CONFIG_BOOT_STACK_SIZE,d0
sub d0,a0
mov a0,sp
# init interrupt for AP
call smp_prepare_cpu_init[],0
# mark this secondary CPU in cpu_boot_map
mov (CPUID),d0
mov 0x1,d1
asl d0,d1
mov cpu_boot_map,a0
bset d1,(a0)
or EPSW_IE|EPSW_IM_1,epsw # permit level 0 interrupts
nop
nop
#ifdef CONFIG_MN10300_CACHE_WBACK
# flush the local cache if it's in writeback mode
call mn10300_local_dcache_flush_inv[],0
setlb
mov (CHCTR),d0
btst CHCTR_DCBUSY,d0 # wait till not busy (use CPU loop buffer)
lne
#endif
# now sleep waiting for further instructions
secondary_sleep:
mov CPUM_SLEEP,d0
movhu d0,(CPUM)
nop
nop
bra secondary_sleep
.size startup_secondary,.-startup_secondary
#endif /* CONFIG_SMP */
###############################################################################
#
#
#
###############################################################################
ENTRY(__head_end)
/*

View File

@ -18,3 +18,15 @@ extern int kernel_thread_helper(int);
* entry.S
*/
extern void ret_from_fork(struct task_struct *) __attribute__((noreturn));
/*
* smp-low.S
*/
#ifdef CONFIG_SMP
extern void mn10300_low_ipi_handler(void);
#endif
/*
* time.c
*/
extern irqreturn_t local_timer_interrupt(void);

View File

@ -12,11 +12,34 @@
#include <linux/interrupt.h>
#include <linux/kernel_stat.h>
#include <linux/seq_file.h>
#include <linux/cpumask.h>
#include <asm/setup.h>
#include <asm/serial-regs.h>
unsigned long __mn10300_irq_enabled_epsw = EPSW_IE | EPSW_IM_7;
#ifdef CONFIG_SMP
#undef GxICR
#define GxICR(X) CROSS_GxICR(X, irq_affinity_online[X])
#undef GxICR_u8
#define GxICR_u8(X) CROSS_GxICR_u8(X, irq_affinity_online[X])
#endif /* CONFIG_SMP */
unsigned long __mn10300_irq_enabled_epsw[NR_CPUS] __cacheline_aligned_in_smp = {
[0 ... NR_CPUS - 1] = EPSW_IE | EPSW_IM_7
};
EXPORT_SYMBOL(__mn10300_irq_enabled_epsw);
#ifdef CONFIG_SMP
static char irq_affinity_online[NR_IRQS] = {
[0 ... NR_IRQS - 1] = 0
};
#define NR_IRQ_WORDS ((NR_IRQS + 31) / 32)
static unsigned long irq_affinity_request[NR_IRQ_WORDS] = {
[0 ... NR_IRQ_WORDS - 1] = 0
};
#endif /* CONFIG_SMP */
atomic_t irq_err_count;
/*
@ -24,30 +47,65 @@ atomic_t irq_err_count;
*/
static void mn10300_cpupic_ack(unsigned int irq)
{
unsigned long flags;
u16 tmp;
*(volatile u8 *) &GxICR(irq) = GxICR_DETECT;
flags = arch_local_cli_save();
GxICR_u8(irq) = GxICR_DETECT;
tmp = GxICR(irq);
arch_local_irq_restore(flags);
}
static void __mask_and_set_icr(unsigned int irq,
unsigned int mask, unsigned int set)
{
unsigned long flags;
u16 tmp;
flags = arch_local_cli_save();
tmp = GxICR(irq);
GxICR(irq) = (tmp & mask) | set;
tmp = GxICR(irq);
arch_local_irq_restore(flags);
}
static void mn10300_cpupic_mask(unsigned int irq)
{
u16 tmp = GxICR(irq);
GxICR(irq) = (tmp & GxICR_LEVEL);
tmp = GxICR(irq);
__mask_and_set_icr(irq, GxICR_LEVEL, 0);
}
static void mn10300_cpupic_mask_ack(unsigned int irq)
{
u16 tmp = GxICR(irq);
GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_DETECT;
tmp = GxICR(irq);
#ifdef CONFIG_SMP
unsigned long flags;
u16 tmp;
flags = arch_local_cli_save();
if (!test_and_clear_bit(irq, irq_affinity_request)) {
tmp = GxICR(irq);
GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_DETECT;
tmp = GxICR(irq);
} else {
u16 tmp2;
tmp = GxICR(irq);
GxICR(irq) = (tmp & GxICR_LEVEL);
tmp2 = GxICR(irq);
irq_affinity_online[irq] = any_online_cpu(*irq_desc[irq].affinity);
GxICR(irq) = (tmp & (GxICR_LEVEL | GxICR_ENABLE)) | GxICR_DETECT;
tmp = GxICR(irq);
}
arch_local_irq_restore(flags);
#else /* CONFIG_SMP */
__mask_and_set_icr(irq, GxICR_LEVEL, GxICR_DETECT);
#endif /* CONFIG_SMP */
}
static void mn10300_cpupic_unmask(unsigned int irq)
{
u16 tmp = GxICR(irq);
GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE;
tmp = GxICR(irq);
__mask_and_set_icr(irq, GxICR_LEVEL, GxICR_ENABLE);
}
static void mn10300_cpupic_unmask_clear(unsigned int irq)
@ -56,11 +114,89 @@ static void mn10300_cpupic_unmask_clear(unsigned int irq)
* device has ceased to assert its interrupt line and the interrupt
* channel has been disabled in the PIC, so for level-triggered
* interrupts we need to clear the request bit when we re-enable */
u16 tmp = GxICR(irq);
GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE | GxICR_DETECT;
tmp = GxICR(irq);
#ifdef CONFIG_SMP
unsigned long flags;
u16 tmp;
flags = arch_local_cli_save();
if (!test_and_clear_bit(irq, irq_affinity_request)) {
tmp = GxICR(irq);
GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE | GxICR_DETECT;
tmp = GxICR(irq);
} else {
tmp = GxICR(irq);
irq_affinity_online[irq] = any_online_cpu(*irq_desc[irq].affinity);
GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE | GxICR_DETECT;
tmp = GxICR(irq);
}
arch_local_irq_restore(flags);
#else /* CONFIG_SMP */
__mask_and_set_icr(irq, GxICR_LEVEL, GxICR_ENABLE | GxICR_DETECT);
#endif /* CONFIG_SMP */
}
#ifdef CONFIG_SMP
static int
mn10300_cpupic_setaffinity(unsigned int irq, const struct cpumask *mask)
{
unsigned long flags;
int err;
flags = arch_local_cli_save();
/* check irq no */
switch (irq) {
case TMJCIRQ:
case RESCHEDULE_IPI:
case CALL_FUNC_SINGLE_IPI:
case LOCAL_TIMER_IPI:
case FLUSH_CACHE_IPI:
case CALL_FUNCTION_NMI_IPI:
case GDB_NMI_IPI:
#ifdef CONFIG_MN10300_TTYSM0
case SC0RXIRQ:
case SC0TXIRQ:
#ifdef CONFIG_MN10300_TTYSM0_TIMER8
case TM8IRQ:
#elif CONFIG_MN10300_TTYSM0_TIMER2
case TM2IRQ:
#endif /* CONFIG_MN10300_TTYSM0_TIMER8 */
#endif /* CONFIG_MN10300_TTYSM0 */
#ifdef CONFIG_MN10300_TTYSM1
case SC1RXIRQ:
case SC1TXIRQ:
#ifdef CONFIG_MN10300_TTYSM1_TIMER12
case TM12IRQ:
#elif CONFIG_MN10300_TTYSM1_TIMER9
case TM9IRQ:
#elif CONFIG_MN10300_TTYSM1_TIMER3
case TM3IRQ:
#endif /* CONFIG_MN10300_TTYSM1_TIMER12 */
#endif /* CONFIG_MN10300_TTYSM1 */
#ifdef CONFIG_MN10300_TTYSM2
case SC2RXIRQ:
case SC2TXIRQ:
case TM10IRQ:
#endif /* CONFIG_MN10300_TTYSM2 */
err = -1;
break;
default:
set_bit(irq, irq_affinity_request);
err = 0;
break;
}
arch_local_irq_restore(flags);
return err;
}
#endif /* CONFIG_SMP */
/*
* MN10300 PIC level-triggered IRQ handling.
*
@ -79,6 +215,9 @@ static struct irq_chip mn10300_cpu_pic_level = {
.mask = mn10300_cpupic_mask,
.mask_ack = mn10300_cpupic_mask,
.unmask = mn10300_cpupic_unmask_clear,
#ifdef CONFIG_SMP
.set_affinity = mn10300_cpupic_setaffinity,
#endif /* CONFIG_SMP */
};
/*
@ -94,6 +233,9 @@ static struct irq_chip mn10300_cpu_pic_edge = {
.mask = mn10300_cpupic_mask,
.mask_ack = mn10300_cpupic_mask_ack,
.unmask = mn10300_cpupic_unmask,
#ifdef CONFIG_SMP
.set_affinity = mn10300_cpupic_setaffinity,
#endif /* CONFIG_SMP */
};
/*
@ -111,14 +253,34 @@ void ack_bad_irq(int irq)
*/
void set_intr_level(int irq, u16 level)
{
u16 tmp;
BUG_ON(in_interrupt());
if (in_interrupt())
BUG();
__mask_and_set_icr(irq, GxICR_ENABLE, level);
}
tmp = GxICR(irq);
GxICR(irq) = (tmp & GxICR_ENABLE) | level;
tmp = GxICR(irq);
void mn10300_intc_set_level(unsigned int irq, unsigned int level)
{
set_intr_level(irq, NUM2GxICR_LEVEL(level) & GxICR_LEVEL);
}
void mn10300_intc_clear(unsigned int irq)
{
__mask_and_set_icr(irq, GxICR_LEVEL | GxICR_ENABLE, GxICR_DETECT);
}
void mn10300_intc_set(unsigned int irq)
{
__mask_and_set_icr(irq, 0, GxICR_REQUEST | GxICR_DETECT);
}
void mn10300_intc_enable(unsigned int irq)
{
mn10300_cpupic_unmask(irq);
}
void mn10300_intc_disable(unsigned int irq)
{
mn10300_cpupic_mask(irq);
}
/*
@ -126,7 +288,7 @@ void set_intr_level(int irq, u16 level)
* than before
* - see Documentation/mn10300/features.txt
*/
void set_intr_postackable(int irq)
void mn10300_set_lateack_irq_type(int irq)
{
set_irq_chip_and_handler(irq, &mn10300_cpu_pic_level,
handle_level_irq);
@ -147,6 +309,7 @@ void __init init_IRQ(void)
* interrupts */
set_irq_chip_and_handler(irq, &mn10300_cpu_pic_edge,
handle_level_irq);
unit_init_IRQ();
}
@ -156,6 +319,7 @@ void __init init_IRQ(void)
asmlinkage void do_IRQ(void)
{
unsigned long sp, epsw, irq_disabled_epsw, old_irq_enabled_epsw;
unsigned int cpu_id = smp_processor_id();
int irq;
sp = current_stack_pointer();
@ -163,12 +327,14 @@ asmlinkage void do_IRQ(void)
/* make sure local_irq_enable() doesn't muck up the interrupt priority
* setting in EPSW */
old_irq_enabled_epsw = __mn10300_irq_enabled_epsw;
old_irq_enabled_epsw = __mn10300_irq_enabled_epsw[cpu_id];
local_save_flags(epsw);
__mn10300_irq_enabled_epsw = EPSW_IE | (EPSW_IM & epsw);
__mn10300_irq_enabled_epsw[cpu_id] = EPSW_IE | (EPSW_IM & epsw);
irq_disabled_epsw = EPSW_IE | MN10300_CLI_LEVEL;
__IRQ_STAT(smp_processor_id(), __irq_count)++;
#ifdef CONFIG_MN10300_WD_TIMER
__IRQ_STAT(cpu_id, __irq_count)++;
#endif
irq_enter();
@ -188,7 +354,7 @@ asmlinkage void do_IRQ(void)
local_irq_restore(epsw);
}
__mn10300_irq_enabled_epsw = old_irq_enabled_epsw;
__mn10300_irq_enabled_epsw[cpu_id] = old_irq_enabled_epsw;
irq_exit();
}
@ -239,11 +405,13 @@ int show_interrupts(struct seq_file *p, void *v)
/* polish off with NMI and error counters */
case NR_IRQS:
#ifdef CONFIG_MN10300_WD_TIMER
seq_printf(p, "NMI: ");
for (j = 0; j < NR_CPUS; j++)
if (cpu_online(j))
seq_printf(p, "%10u ", nmi_count(j));
seq_putc(p, '\n');
#endif
seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
break;
@ -251,3 +419,51 @@ int show_interrupts(struct seq_file *p, void *v)
return 0;
}
#ifdef CONFIG_HOTPLUG_CPU
void migrate_irqs(void)
{
irq_desc_t *desc;
int irq;
unsigned int self, new;
unsigned long flags;
self = smp_processor_id();
for (irq = 0; irq < NR_IRQS; irq++) {
desc = irq_desc + irq;
if (desc->status == IRQ_PER_CPU)
continue;
if (cpu_isset(self, irq_desc[irq].affinity) &&
!cpus_intersects(irq_affinity[irq], cpu_online_map)) {
int cpu_id;
cpu_id = first_cpu(cpu_online_map);
cpu_set(cpu_id, irq_desc[irq].affinity);
}
/* We need to operate irq_affinity_online atomically. */
arch_local_cli_save(flags);
if (irq_affinity_online[irq] == self) {
u16 x, tmp;
x = CROSS_GxICR(irq, self);
CROSS_GxICR(irq, self) = x & GxICR_LEVEL;
tmp = CROSS_GxICR(irq, self);
new = any_online_cpu(irq_desc[irq].affinity);
irq_affinity_online[irq] = new;
CROSS_GxICR(irq, new) =
(x & GxICR_LEVEL) | GxICR_DETECT;
tmp = CROSS_GxICR(irq, new);
x &= GxICR_LEVEL | GxICR_ENABLE;
if (CROSS_GxICR(irq, self) & GxICR_REQUEST)
x |= GxICR_REQUEST | GxICR_DETECT;
CROSS_GxICR(irq, new) = x;
tmp = CROSS_GxICR(irq, new);
}
arch_local_irq_restore(flags);
}
}
#endif /* CONFIG_HOTPLUG_CPU */

View File

@ -39,7 +39,7 @@
###############################################################################
.balign L1_CACHE_BYTES
ENTRY(mn10300_serial_vdma_interrupt)
or EPSW_IE,psw # permit overriding by
# or EPSW_IE,psw # permit overriding by
# debugging interrupts
movm [d2,d3,a2,a3,exreg0],(sp)
@ -164,7 +164,7 @@ mnsc_vdma_tx_noint:
rti
mnsc_vdma_tx_empty:
mov +(GxICR_LEVEL_1|GxICR_DETECT),d2
mov +(NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL)|GxICR_DETECT),d2
movhu d2,(e3) # disable the interrupt
movhu (e3),d2 # flush
@ -175,7 +175,7 @@ mnsc_vdma_tx_break:
movhu (SCxCTR,e2),d2 # turn on break mode
or SC01CTR_BKE,d2
movhu d2,(SCxCTR,e2)
mov +(GxICR_LEVEL_1|GxICR_DETECT),d2
mov +(NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL)|GxICR_DETECT),d2
movhu d2,(e3) # disable transmit interrupts on this
# channel
movhu (e3),d2 # flush

View File

@ -44,6 +44,11 @@ static const char serial_revdate[] = "2007-11-06";
#include <unit/timex.h>
#include "mn10300-serial.h"
#ifdef CONFIG_SMP
#undef GxICR
#define GxICR(X) CROSS_GxICR(X, 0)
#endif /* CONFIG_SMP */
#define kenter(FMT, ...) \
printk(KERN_DEBUG "-->%s(" FMT ")\n", __func__, ##__VA_ARGS__)
#define _enter(FMT, ...) \
@ -57,6 +62,11 @@ static const char serial_revdate[] = "2007-11-06";
#define _proto(FMT, ...) \
no_printk(KERN_DEBUG "### MNSERIAL " FMT " ###\n", ##__VA_ARGS__)
#ifndef CODMSB
/* c_cflag bit meaning */
#define CODMSB 004000000000 /* change Transfer bit-order */
#endif
#define NR_UARTS 3
#ifdef CONFIG_MN10300_TTYSM_CONSOLE
@ -152,26 +162,35 @@ struct mn10300_serial_port mn10300_serial_port_sif0 = {
.name = "ttySM0",
._iobase = &SC0CTR,
._control = &SC0CTR,
._status = (volatile u8 *) &SC0STR,
._status = (volatile u8 *)&SC0STR,
._intr = &SC0ICR,
._rxb = &SC0RXB,
._txb = &SC0TXB,
.rx_name = "ttySM0:Rx",
.tx_name = "ttySM0:Tx",
#ifdef CONFIG_MN10300_TTYSM0_TIMER8
#if defined(CONFIG_MN10300_TTYSM0_TIMER8)
.tm_name = "ttySM0:Timer8",
._tmxmd = &TM8MD,
._tmxbr = &TM8BR,
._tmicr = &TM8ICR,
.tm_irq = TM8IRQ,
.div_timer = MNSCx_DIV_TIMER_16BIT,
#else /* CONFIG_MN10300_TTYSM0_TIMER2 */
#elif defined(CONFIG_MN10300_TTYSM0_TIMER0)
.tm_name = "ttySM0:Timer0",
._tmxmd = &TM0MD,
._tmxbr = (volatile u16 *)&TM0BR,
._tmicr = &TM0ICR,
.tm_irq = TM0IRQ,
.div_timer = MNSCx_DIV_TIMER_8BIT,
#elif defined(CONFIG_MN10300_TTYSM0_TIMER2)
.tm_name = "ttySM0:Timer2",
._tmxmd = &TM2MD,
._tmxbr = (volatile u16 *) &TM2BR,
._tmxbr = (volatile u16 *)&TM2BR,
._tmicr = &TM2ICR,
.tm_irq = TM2IRQ,
.div_timer = MNSCx_DIV_TIMER_8BIT,
#else
#error "Unknown config for ttySM0"
#endif
.rx_irq = SC0RXIRQ,
.tx_irq = SC0TXIRQ,
@ -205,26 +224,35 @@ struct mn10300_serial_port mn10300_serial_port_sif1 = {
.name = "ttySM1",
._iobase = &SC1CTR,
._control = &SC1CTR,
._status = (volatile u8 *) &SC1STR,
._status = (volatile u8 *)&SC1STR,
._intr = &SC1ICR,
._rxb = &SC1RXB,
._txb = &SC1TXB,
.rx_name = "ttySM1:Rx",
.tx_name = "ttySM1:Tx",
#ifdef CONFIG_MN10300_TTYSM1_TIMER9
#if defined(CONFIG_MN10300_TTYSM1_TIMER9)
.tm_name = "ttySM1:Timer9",
._tmxmd = &TM9MD,
._tmxbr = &TM9BR,
._tmicr = &TM9ICR,
.tm_irq = TM9IRQ,
.div_timer = MNSCx_DIV_TIMER_16BIT,
#else /* CONFIG_MN10300_TTYSM1_TIMER3 */
#elif defined(CONFIG_MN10300_TTYSM1_TIMER3)
.tm_name = "ttySM1:Timer3",
._tmxmd = &TM3MD,
._tmxbr = (volatile u16 *) &TM3BR,
._tmxbr = (volatile u16 *)&TM3BR,
._tmicr = &TM3ICR,
.tm_irq = TM3IRQ,
.div_timer = MNSCx_DIV_TIMER_8BIT,
#elif defined(CONFIG_MN10300_TTYSM1_TIMER12)
.tm_name = "ttySM1/Timer12",
._tmxmd = &TM12MD,
._tmxbr = &TM12BR,
._tmicr = &TM12ICR,
.tm_irq = TM12IRQ,
.div_timer = MNSCx_DIV_TIMER_16BIT,
#else
#error "Unknown config for ttySM1"
#endif
.rx_irq = SC1RXIRQ,
.tx_irq = SC1TXIRQ,
@ -260,20 +288,45 @@ struct mn10300_serial_port mn10300_serial_port_sif2 = {
.uart.lock =
__SPIN_LOCK_UNLOCKED(mn10300_serial_port_sif2.uart.lock),
.name = "ttySM2",
.rx_name = "ttySM2:Rx",
.tx_name = "ttySM2:Tx",
.tm_name = "ttySM2:Timer10",
._iobase = &SC2CTR,
._control = &SC2CTR,
._status = &SC2STR,
._status = (volatile u8 *)&SC2STR,
._intr = &SC2ICR,
._rxb = &SC2RXB,
._txb = &SC2TXB,
.rx_name = "ttySM2:Rx",
.tx_name = "ttySM2:Tx",
#if defined(CONFIG_MN10300_TTYSM2_TIMER10)
.tm_name = "ttySM2/Timer10",
._tmxmd = &TM10MD,
._tmxbr = &TM10BR,
._tmicr = &TM10ICR,
.tm_irq = TM10IRQ,
.div_timer = MNSCx_DIV_TIMER_16BIT,
#elif defined(CONFIG_MN10300_TTYSM2_TIMER9)
.tm_name = "ttySM2/Timer9",
._tmxmd = &TM9MD,
._tmxbr = &TM9BR,
._tmicr = &TM9ICR,
.tm_irq = TM9IRQ,
.div_timer = MNSCx_DIV_TIMER_16BIT,
#elif defined(CONFIG_MN10300_TTYSM2_TIMER1)
.tm_name = "ttySM2/Timer1",
._tmxmd = &TM1MD,
._tmxbr = (volatile u16 *)&TM1BR,
._tmicr = &TM1ICR,
.tm_irq = TM1IRQ,
.div_timer = MNSCx_DIV_TIMER_8BIT,
#elif defined(CONFIG_MN10300_TTYSM2_TIMER3)
.tm_name = "ttySM2/Timer3",
._tmxmd = &TM3MD,
._tmxbr = (volatile u16 *)&TM3BR,
._tmicr = &TM3ICR,
.tm_irq = TM3IRQ,
.div_timer = MNSCx_DIV_TIMER_8BIT,
#else
#error "Unknown config for ttySM2"
#endif
.rx_irq = SC2RXIRQ,
.tx_irq = SC2TXIRQ,
.rx_icr = &GxICR(SC2RXIRQ),
@ -322,9 +375,13 @@ struct mn10300_serial_port *mn10300_serial_ports[NR_UARTS + 1] = {
*/
static void mn10300_serial_mask_ack(unsigned int irq)
{
unsigned long flags;
u16 tmp;
flags = arch_local_cli_save();
GxICR(irq) = GxICR_LEVEL_6;
tmp = GxICR(irq); /* flush write buffer */
arch_local_irq_restore(flags);
}
static void mn10300_serial_nop(unsigned int irq)
@ -348,23 +405,36 @@ struct mn10300_serial_int mn10300_serial_int_tbl[NR_IRQS];
static void mn10300_serial_dis_tx_intr(struct mn10300_serial_port *port)
{
unsigned long flags;
u16 x;
*port->tx_icr = GxICR_LEVEL_1 | GxICR_DETECT;
flags = arch_local_cli_save();
*port->tx_icr = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL);
x = *port->tx_icr;
arch_local_irq_restore(flags);
}
static void mn10300_serial_en_tx_intr(struct mn10300_serial_port *port)
{
unsigned long flags;
u16 x;
*port->tx_icr = GxICR_LEVEL_1 | GxICR_ENABLE;
flags = arch_local_cli_save();
*port->tx_icr =
NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL) | GxICR_ENABLE;
x = *port->tx_icr;
arch_local_irq_restore(flags);
}
static void mn10300_serial_dis_rx_intr(struct mn10300_serial_port *port)
{
unsigned long flags;
u16 x;
*port->rx_icr = GxICR_LEVEL_1 | GxICR_DETECT;
flags = arch_local_cli_save();
*port->rx_icr = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL);
x = *port->rx_icr;
arch_local_irq_restore(flags);
}
/*
@ -650,7 +720,7 @@ static unsigned int mn10300_serial_tx_empty(struct uart_port *_port)
static void mn10300_serial_set_mctrl(struct uart_port *_port,
unsigned int mctrl)
{
struct mn10300_serial_port *port =
struct mn10300_serial_port *port __attribute__ ((unused)) =
container_of(_port, struct mn10300_serial_port, uart);
_enter("%s,%x", port->name, mctrl);
@ -706,6 +776,7 @@ static void mn10300_serial_start_tx(struct uart_port *_port)
UART_XMIT_SIZE));
/* kick the virtual DMA controller */
arch_local_cli();
x = *port->tx_icr;
x |= GxICR_ENABLE;
@ -716,10 +787,14 @@ static void mn10300_serial_start_tx(struct uart_port *_port)
_debug("CTR=%04hx ICR=%02hx STR=%04x TMD=%02hx TBR=%04hx ICR=%04hx",
*port->_control, *port->_intr, *port->_status,
*port->_tmxmd, *port->_tmxbr, *port->tx_icr);
*port->_tmxmd,
(port->div_timer == MNSCx_DIV_TIMER_8BIT) ?
*(volatile u8 *)port->_tmxbr : *port->_tmxbr,
*port->tx_icr);
*port->tx_icr = x;
x = *port->tx_icr;
arch_local_sti();
}
/*
@ -842,8 +917,10 @@ static int mn10300_serial_startup(struct uart_port *_port)
pint->port = port;
pint->vdma = mn10300_serial_vdma_tx_handler;
set_intr_level(port->rx_irq, GxICR_LEVEL_1);
set_intr_level(port->tx_irq, GxICR_LEVEL_1);
set_intr_level(port->rx_irq,
NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL));
set_intr_level(port->tx_irq,
NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL));
set_irq_chip(port->tm_irq, &mn10300_serial_pic);
if (request_irq(port->rx_irq, mn10300_serial_interrupt,
@ -876,6 +953,7 @@ error:
*/
static void mn10300_serial_shutdown(struct uart_port *_port)
{
u16 x;
struct mn10300_serial_port *port =
container_of(_port, struct mn10300_serial_port, uart);
@ -897,8 +975,12 @@ static void mn10300_serial_shutdown(struct uart_port *_port)
free_irq(port->rx_irq, port);
free_irq(port->tx_irq, port);
*port->rx_icr = GxICR_LEVEL_1;
*port->tx_icr = GxICR_LEVEL_1;
arch_local_cli();
*port->rx_icr = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL);
x = *port->rx_icr;
*port->tx_icr = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL);
x = *port->tx_icr;
arch_local_sti();
}
/*
@ -947,11 +1029,66 @@ static void mn10300_serial_change_speed(struct mn10300_serial_port *port,
/* Determine divisor based on baud rate */
battempt = 0;
if (div_timer == MNSCx_DIV_TIMER_16BIT)
scxctr |= SC0CTR_CK_TM8UFLOW_8; /* ( == SC1CTR_CK_TM9UFLOW_8
* == SC2CTR_CK_TM10UFLOW) */
else if (div_timer == MNSCx_DIV_TIMER_8BIT)
switch (port->uart.line) {
#ifdef CONFIG_MN10300_TTYSM0
case 0: /* ttySM0 */
#if defined(CONFIG_MN10300_TTYSM0_TIMER8)
scxctr |= SC0CTR_CK_TM8UFLOW_8;
#elif defined(CONFIG_MN10300_TTYSM0_TIMER0)
scxctr |= SC0CTR_CK_TM0UFLOW_8;
#elif defined(CONFIG_MN10300_TTYSM0_TIMER2)
scxctr |= SC0CTR_CK_TM2UFLOW_8;
#else
#error "Unknown config for ttySM0"
#endif
break;
#endif /* CONFIG_MN10300_TTYSM0 */
#ifdef CONFIG_MN10300_TTYSM1
case 1: /* ttySM1 */
#if defined(CONFIG_AM33_2) || defined(CONFIG_AM33_3)
#if defined(CONFIG_MN10300_TTYSM1_TIMER9)
scxctr |= SC1CTR_CK_TM9UFLOW_8;
#elif defined(CONFIG_MN10300_TTYSM1_TIMER3)
scxctr |= SC1CTR_CK_TM3UFLOW_8;
#else
#error "Unknown config for ttySM1"
#endif
#else /* CONFIG_AM33_2 || CONFIG_AM33_3 */
#if defined(CONFIG_MN10300_TTYSM1_TIMER12)
scxctr |= SC1CTR_CK_TM12UFLOW_8;
#else
#error "Unknown config for ttySM1"
#endif
#endif /* CONFIG_AM33_2 || CONFIG_AM33_3 */
break;
#endif /* CONFIG_MN10300_TTYSM1 */
#ifdef CONFIG_MN10300_TTYSM2
case 2: /* ttySM2 */
#if defined(CONFIG_AM33_2)
#if defined(CONFIG_MN10300_TTYSM2_TIMER10)
scxctr |= SC2CTR_CK_TM10UFLOW;
#else
#error "Unknown config for ttySM2"
#endif
#else /* CONFIG_AM33_2 */
#if defined(CONFIG_MN10300_TTYSM2_TIMER9)
scxctr |= SC2CTR_CK_TM9UFLOW_8;
#elif defined(CONFIG_MN10300_TTYSM2_TIMER1)
scxctr |= SC2CTR_CK_TM1UFLOW_8;
#elif defined(CONFIG_MN10300_TTYSM2_TIMER3)
scxctr |= SC2CTR_CK_TM3UFLOW_8;
#else
#error "Unknown config for ttySM2"
#endif
#endif /* CONFIG_AM33_2 */
break;
#endif /* CONFIG_MN10300_TTYSM2 */
default:
break;
}
try_alternative:
baud = uart_get_baud_rate(&port->uart, new, old, 0,
@ -1195,6 +1332,12 @@ static void mn10300_serial_set_termios(struct uart_port *_port,
ctr &= ~SC2CTR_TWE;
*port->_control = ctr;
}
/* change Transfer bit-order (LSB/MSB) */
if (new->c_cflag & CODMSB)
*port->_control |= SC01CTR_OD_MSBFIRST; /* MSB MODE */
else
*port->_control &= ~SC01CTR_OD_MSBFIRST; /* LSB MODE */
}
/*
@ -1302,11 +1445,16 @@ static int __init mn10300_serial_init(void)
printk(KERN_INFO "%s version %s (%s)\n",
serial_name, serial_version, serial_revdate);
#ifdef CONFIG_MN10300_TTYSM2
SC2TIM = 8; /* make the baud base of timer 2 IOCLK/8 */
#if defined(CONFIG_MN10300_TTYSM2) && defined(CONFIG_AM33_2)
{
int tmp;
SC2TIM = 8; /* make the baud base of timer 2 IOCLK/8 */
tmp = SC2TIM;
}
#endif
set_intr_stub(EXCEP_IRQ_LEVEL1, mn10300_serial_vdma_interrupt);
set_intr_stub(NUM2EXCEP_IRQ_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL),
mn10300_serial_vdma_interrupt);
ret = uart_register_driver(&mn10300_serial_driver);
if (!ret) {
@ -1366,9 +1514,11 @@ static void mn10300_serial_console_write(struct console *co,
port = mn10300_serial_ports[co->index];
/* firstly hijack the serial port from the "virtual DMA" controller */
arch_local_cli();
txicr = *port->tx_icr;
*port->tx_icr = GxICR_LEVEL_1;
*port->tx_icr = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL);
tmp = *port->tx_icr;
arch_local_sti();
/* the transmitter may be disabled */
scxctr = *port->_control;
@ -1422,8 +1572,10 @@ static void mn10300_serial_console_write(struct console *co,
if (!(scxctr & SC01CTR_TXE))
*port->_control = scxctr;
arch_local_cli();
*port->tx_icr = txicr;
tmp = *port->tx_icr;
arch_local_sti();
}
/*

View File

@ -16,6 +16,7 @@
#include <asm/intctl-regs.h>
#include <asm/timer-regs.h>
#include <asm/frame.inc>
#include <linux/threads.h>
.text
@ -53,7 +54,13 @@ watchdog_handler:
.type touch_nmi_watchdog,@function
touch_nmi_watchdog:
clr d0
mov d0,(watchdog_alert_counter)
clr d1
mov watchdog_alert_counter, a0
setlb
mov d0, (a0+)
inc d1
cmp NR_CPUS, d1
lne
ret [],0
.size touch_nmi_watchdog,.-touch_nmi_watchdog

View File

@ -30,7 +30,7 @@
static DEFINE_SPINLOCK(watchdog_print_lock);
static unsigned int watchdog;
static unsigned int watchdog_hz = 1;
unsigned int watchdog_alert_counter;
unsigned int watchdog_alert_counter[NR_CPUS];
EXPORT_SYMBOL(touch_nmi_watchdog);
@ -39,9 +39,6 @@ EXPORT_SYMBOL(touch_nmi_watchdog);
* is to check its timer makes IRQ counts. If they are not
* changing then that CPU has some problem.
*
* as these watchdog NMI IRQs are generated on every CPU, we only
* have to check the current processor.
*
* since NMIs dont listen to _any_ locks, we have to be extremely
* careful not to rely on unsafe variables. The printk might lock
* up though, so we have to break up any console locks first ...
@ -69,8 +66,8 @@ int __init check_watchdog(void)
printk(KERN_INFO "OK.\n");
/* now that we know it works we can reduce NMI frequency to
* something more reasonable; makes a difference in some configs
/* now that we know it works we can reduce NMI frequency to something
* more reasonable; makes a difference in some configs
*/
watchdog_hz = 1;
@ -121,15 +118,22 @@ void __init watchdog_go(void)
}
}
#ifdef CONFIG_SMP
static void watchdog_dump_register(void *dummy)
{
printk(KERN_ERR "--- Register Dump (CPU%d) ---\n", CPUID);
show_registers(__frame);
}
#endif
asmlinkage
void watchdog_interrupt(struct pt_regs *regs, enum exception_code excep)
{
/*
* Since current-> is always on the stack, and we always switch
* the stack NMI-atomically, it's safe to use smp_processor_id().
*/
int sum, cpu = smp_processor_id();
int sum, cpu;
int irq = NMIIRQ;
u8 wdt, tmp;
@ -138,43 +142,61 @@ void watchdog_interrupt(struct pt_regs *regs, enum exception_code excep)
tmp = WDCTR;
NMICR = NMICR_WDIF;
nmi_count(cpu)++;
nmi_count(smp_processor_id())++;
kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq));
sum = irq_stat[cpu].__irq_count;
if (last_irq_sums[cpu] == sum) {
/*
* Ayiee, looks like this CPU is stuck ...
* wait a few IRQs (5 seconds) before doing the oops ...
*/
watchdog_alert_counter++;
if (watchdog_alert_counter == 5 * watchdog_hz) {
spin_lock(&watchdog_print_lock);
/*
* We are in trouble anyway, lets at least try
* to get a message out.
*/
bust_spinlocks(1);
printk(KERN_ERR
"NMI Watchdog detected LOCKUP on CPU%d,"
" pc %08lx, registers:\n",
cpu, regs->pc);
show_registers(regs);
printk("console shuts up ...\n");
console_silent();
spin_unlock(&watchdog_print_lock);
bust_spinlocks(0);
#ifdef CONFIG_GDBSTUB
if (gdbstub_busy)
gdbstub_exception(regs, excep);
else
gdbstub_intercept(regs, excep);
for_each_online_cpu(cpu) {
sum = irq_stat[cpu].__irq_count;
if ((last_irq_sums[cpu] == sum)
#if defined(CONFIG_GDBSTUB) && defined(CONFIG_SMP)
&& !(CHK_GDBSTUB_BUSY()
|| atomic_read(&cpu_doing_single_step))
#endif
do_exit(SIGSEGV);
) {
/*
* Ayiee, looks like this CPU is stuck ...
* wait a few IRQs (5 seconds) before doing the oops ...
*/
watchdog_alert_counter[cpu]++;
if (watchdog_alert_counter[cpu] == 5 * watchdog_hz) {
spin_lock(&watchdog_print_lock);
/*
* We are in trouble anyway, lets at least try
* to get a message out.
*/
bust_spinlocks(1);
printk(KERN_ERR
"NMI Watchdog detected LOCKUP on CPU%d,"
" pc %08lx, registers:\n",
cpu, regs->pc);
#ifdef CONFIG_SMP
printk(KERN_ERR
"--- Register Dump (CPU%d) ---\n",
CPUID);
#endif
show_registers(regs);
#ifdef CONFIG_SMP
smp_nmi_call_function(watchdog_dump_register,
NULL, 1);
#endif
printk(KERN_NOTICE "console shuts up ...\n");
console_silent();
spin_unlock(&watchdog_print_lock);
bust_spinlocks(0);
#ifdef CONFIG_GDBSTUB
if (CHK_GDBSTUB_BUSY_AND_ACTIVE())
gdbstub_exception(regs, excep);
else
gdbstub_intercept(regs, excep);
#endif
do_exit(SIGSEGV);
}
} else {
last_irq_sums[cpu] = sum;
watchdog_alert_counter[cpu] = 0;
}
} else {
last_irq_sums[cpu] = sum;
watchdog_alert_counter = 0;
}
WDCTR = wdt | WDCTR_WDRST;

View File

@ -57,6 +57,7 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
void (*pm_power_off)(void);
EXPORT_SYMBOL(pm_power_off);
#if !defined(CONFIG_SMP) || defined(CONFIG_HOTPLUG_CPU)
/*
* we use this if we don't have any better idle routine
*/
@ -69,6 +70,35 @@ static void default_idle(void)
local_irq_enable();
}
#else /* !CONFIG_SMP || CONFIG_HOTPLUG_CPU */
/*
* On SMP it's slightly faster (but much more power-consuming!)
* to poll the ->work.need_resched flag instead of waiting for the
* cross-CPU IPI to arrive. Use this option with caution.
*/
static inline void poll_idle(void)
{
int oldval;
local_irq_enable();
/*
* Deal with another CPU just having chosen a thread to
* run here:
*/
oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED);
if (!oldval) {
set_thread_flag(TIF_POLLING_NRFLAG);
while (!need_resched())
cpu_relax();
clear_thread_flag(TIF_POLLING_NRFLAG);
} else {
set_need_resched();
}
}
#endif /* !CONFIG_SMP || CONFIG_HOTPLUG_CPU */
/*
* the idle thread
* - there's no useful work to be done, so just try to conserve power and have
@ -77,8 +107,6 @@ static void default_idle(void)
*/
void cpu_idle(void)
{
int cpu = smp_processor_id();
/* endless idle loop with no priority at all */
for (;;) {
while (!need_resched()) {
@ -86,8 +114,13 @@ void cpu_idle(void)
smp_rmb();
idle = pm_idle;
if (!idle)
if (!idle) {
#if defined(CONFIG_SMP) && !defined(CONFIG_HOTPLUG_CPU)
idle = poll_idle;
#else /* CONFIG_SMP && !CONFIG_HOTPLUG_CPU */
idle = default_idle;
#endif /* CONFIG_SMP && !CONFIG_HOTPLUG_CPU */
}
idle();
}
@ -233,7 +266,7 @@ int copy_thread(unsigned long clone_flags,
}
/* set up things up so the scheduler can start the new task */
p->thread.__frame = c_kregs;
p->thread.frame = c_kregs;
p->thread.a3 = (unsigned long) c_kregs;
p->thread.sp = c_ksp;
p->thread.pc = (unsigned long) ret_from_fork;

View File

@ -41,7 +41,7 @@ static __init int profile_init(void)
tmp = TM11ICR;
printk(KERN_INFO "Profiling initiated on timer 11, priority 0, %uHz\n",
mn10300_ioclk / 8 / (TM11BR + 1));
MN10300_IOCLK / 8 / (TM11BR + 1));
printk(KERN_INFO "Profile histogram stored %p-%p\n",
prof_buffer, (u8 *)(prof_buffer + prof_len) - 1);

View File

@ -20,18 +20,22 @@
DEFINE_SPINLOCK(rtc_lock);
EXPORT_SYMBOL(rtc_lock);
/* time for RTC to update itself in ioclks */
static unsigned long mn10300_rtc_update_period;
/*
* Read the current RTC time
*/
void read_persistent_clock(struct timespec *ts)
{
struct rtc_time tm;
get_rtc_time(&tm);
ts->tv_sec = mktime(tm.tm_year, tm.tm_mon, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec);
ts->tv_nsec = 0;
ts->tv_sec = mktime(tm.tm_year, tm.tm_mon, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec);
/* if rtc is way off in the past, set something reasonable */
if (ts->tv_sec < 0)
ts->tv_sec = mktime(2009, 1, 1, 12, 0, 0);
}
/*
@ -115,39 +119,14 @@ int update_persistent_clock(struct timespec now)
*/
void __init calibrate_clock(void)
{
unsigned long count0, counth, count1;
unsigned char status;
/* make sure the RTC is running and is set to operate in 24hr mode */
status = RTSRC;
RTCRB |= RTCRB_SET;
RTCRB |= RTCRB_TM_24HR;
RTCRB &= ~RTCRB_DM_BINARY;
RTCRA |= RTCRA_DVR;
RTCRA &= ~RTCRA_DVR;
RTCRB &= ~RTCRB_SET;
/* work out the clock speed by counting clock cycles between ends of
* the RTC update cycle - track the RTC through one complete update
* cycle (1 second)
*/
startup_timestamp_counter();
while (!(RTCRA & RTCRA_UIP)) {}
while ((RTCRA & RTCRA_UIP)) {}
count0 = TMTSCBC;
while (!(RTCRA & RTCRA_UIP)) {}
counth = TMTSCBC;
while ((RTCRA & RTCRA_UIP)) {}
count1 = TMTSCBC;
shutdown_timestamp_counter();
MN10300_TSCCLK = count0 - count1; /* the timers count down */
mn10300_rtc_update_period = counth - count1;
MN10300_TSC_PER_HZ = MN10300_TSCCLK / HZ;
}

View File

@ -22,6 +22,7 @@
#include <linux/init.h>
#include <linux/bootmem.h>
#include <linux/seq_file.h>
#include <linux/cpu.h>
#include <asm/processor.h>
#include <linux/console.h>
#include <asm/uaccess.h>
@ -30,7 +31,6 @@
#include <asm/io.h>
#include <asm/smp.h>
#include <proc/proc.h>
#include <asm/busctl-regs.h>
#include <asm/fpu.h>
#include <asm/sections.h>
@ -64,11 +64,13 @@ unsigned long memory_size;
struct thread_info *__current_ti = &init_thread_union.thread_info;
struct task_struct *__current = &init_task;
#define mn10300_known_cpus 3
#define mn10300_known_cpus 5
static const char *const mn10300_cputypes[] = {
"am33v1",
"am33v2",
"am34v1",
"am33-1",
"am33-2",
"am34-1",
"am33-3",
"am34-2",
"unknown"
};
@ -123,6 +125,7 @@ void __init setup_arch(char **cmdline_p)
cpu_init();
unit_setup();
smp_init_cpus();
parse_mem_cmdline(cmdline_p);
init_mm.start_code = (unsigned long)&_text;
@ -179,7 +182,6 @@ void __init setup_arch(char **cmdline_p)
void __init cpu_init(void)
{
unsigned long cpurev = CPUREV, type;
unsigned long base, size;
type = (CPUREV & CPUREV_TYPE) >> CPUREV_TYPE_S;
if (type > mn10300_known_cpus)
@ -189,47 +191,46 @@ void __init cpu_init(void)
mn10300_cputypes[type],
(cpurev & CPUREV_REVISION) >> CPUREV_REVISION_S);
/* determine the memory size and base from the memory controller regs */
memory_size = 0;
base = SDBASE(0);
if (base & SDBASE_CE) {
size = (base & SDBASE_CBAM) << SDBASE_CBAM_SHIFT;
size = ~size + 1;
base &= SDBASE_CBA;
printk(KERN_INFO "SDRAM[0]: %luMb @%08lx\n", size >> 20, base);
memory_size += size;
phys_memory_base = base;
}
base = SDBASE(1);
if (base & SDBASE_CE) {
size = (base & SDBASE_CBAM) << SDBASE_CBAM_SHIFT;
size = ~size + 1;
base &= SDBASE_CBA;
printk(KERN_INFO "SDRAM[1]: %luMb @%08lx\n", size >> 20, base);
memory_size += size;
if (phys_memory_base == 0)
phys_memory_base = base;
}
get_mem_info(&phys_memory_base, &memory_size);
phys_memory_end = phys_memory_base + memory_size;
#ifdef CONFIG_FPU
fpu_init_state();
#endif
}
static struct cpu cpu_devices[NR_CPUS];
static int __init topology_init(void)
{
int i;
for_each_present_cpu(i)
register_cpu(&cpu_devices[i], i);
return 0;
}
subsys_initcall(topology_init);
/*
* Get CPU information for use by the procfs.
*/
static int show_cpuinfo(struct seq_file *m, void *v)
{
#ifdef CONFIG_SMP
struct mn10300_cpuinfo *c = v;
unsigned long cpu_id = c - cpu_data;
unsigned long cpurev = c->type, type, icachesz, dcachesz;
#else /* CONFIG_SMP */
unsigned long cpu_id = 0;
unsigned long cpurev = CPUREV, type, icachesz, dcachesz;
#endif /* CONFIG_SMP */
type = (CPUREV & CPUREV_TYPE) >> CPUREV_TYPE_S;
#ifdef CONFIG_SMP
if (!cpu_online(cpu_id))
return 0;
#endif
type = (cpurev & CPUREV_TYPE) >> CPUREV_TYPE_S;
if (type > mn10300_known_cpus)
type = mn10300_known_cpus;
@ -244,13 +245,14 @@ static int show_cpuinfo(struct seq_file *m, void *v)
1024;
seq_printf(m,
"processor : 0\n"
"processor : %ld\n"
"vendor_id : Matsushita\n"
"cpu core : %s\n"
"cpu rev : %lu\n"
"model name : " PROCESSOR_MODEL_NAME "\n"
"icache size: %lu\n"
"dcache size: %lu\n",
cpu_id,
mn10300_cputypes[type],
(cpurev & CPUREV_REVISION) >> CPUREV_REVISION_S,
icachesz,
@ -262,8 +264,13 @@ static int show_cpuinfo(struct seq_file *m, void *v)
"bogomips : %lu.%02lu\n\n",
MN10300_IOCLK / 1000000,
(MN10300_IOCLK / 10000) % 100,
#ifdef CONFIG_SMP
c->loops_per_jiffy / (500000 / HZ),
(c->loops_per_jiffy / (5000 / HZ)) % 100
#else /* CONFIG_SMP */
loops_per_jiffy / (500000 / HZ),
(loops_per_jiffy / (5000 / HZ)) % 100
#endif /* CONFIG_SMP */
);
return 0;

View File

@ -0,0 +1,97 @@
/* SMP IPI low-level handler
*
* Copyright (C) 2006-2007 Matsushita Electric Industrial Co., Ltd.
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
*/
#include <linux/sys.h>
#include <linux/linkage.h>
#include <asm/smp.h>
#include <asm/system.h>
#include <asm/thread_info.h>
#include <asm/cpu-regs.h>
#include <proc/smp-regs.h>
#include <asm/asm-offsets.h>
#include <asm/frame.inc>
.am33_2
###############################################################################
#
# IPI interrupt handler
#
###############################################################################
.globl mn10300_low_ipi_handler
mn10300_low_ipi_handler:
add -4,sp
mov d0,(sp)
movhu (IAGR),d0
and IAGR_GN,d0
lsr 0x2,d0
#ifdef CONFIG_MN10300_CACHE_ENABLED
cmp FLUSH_CACHE_IPI,d0
beq mn10300_flush_cache_ipi
#endif
cmp SMP_BOOT_IRQ,d0
beq mn10300_smp_boot_ipi
/* OTHERS */
mov (sp),d0
add 4,sp
#ifdef CONFIG_GDBSTUB
jmp gdbstub_io_rx_handler
#else
jmp end
#endif
###############################################################################
#
# Cache flush IPI interrupt handler
#
###############################################################################
#ifdef CONFIG_MN10300_CACHE_ENABLED
mn10300_flush_cache_ipi:
mov (sp),d0
add 4,sp
/* FLUSH_CACHE_IPI */
add -4,sp
SAVE_ALL
mov GxICR_DETECT,d2
movbu d2,(GxICR(FLUSH_CACHE_IPI)) # ACK the interrupt
movhu (GxICR(FLUSH_CACHE_IPI)),d2
call smp_cache_interrupt[],0
RESTORE_ALL
jmp end
#endif
###############################################################################
#
# SMP boot CPU IPI interrupt handler
#
###############################################################################
mn10300_smp_boot_ipi:
/* clear interrupt */
movhu (GxICR(SMP_BOOT_IRQ)),d0
and ~GxICR_REQUEST,d0
movhu d0,(GxICR(SMP_BOOT_IRQ))
mov (sp),d0
add 4,sp
# get stack
mov (CPUID),a0
add -1,a0
add a0,a0
add a0,a0
mov (start_stack,a0),a0
mov a0,sp
jmp initialize_secondary
# Jump here after RTI to suppress the icache lookahead
end:

1141
arch/mn10300/kernel/smp.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -15,6 +15,9 @@
#include <linux/linkage.h>
#include <asm/thread_info.h>
#include <asm/cpu-regs.h>
#ifdef CONFIG_SMP
#include <proc/smp-regs.h>
#endif /* CONFIG_SMP */
.text
@ -35,7 +38,14 @@ ENTRY(__switch_to)
mov d1,a1
# save prev context
#ifdef CONFIG_SMP
mov (CPUID),a2
add a2,a2
add a2,a2
mov (___frame,a2),d0
#else /* CONFIG_SMP */
mov (__frame),d0
#endif /* CONFIG_SMP */
mov d0,(THREAD_FRAME,a0)
mov __switch_back,d0
mov d0,(THREAD_PC,a0)
@ -59,7 +69,14 @@ ENTRY(__switch_to)
#endif
mov (THREAD_FRAME,a1),a2
#ifdef CONFIG_SMP
mov (CPUID),a0
add a0,a0
add a0,a0
mov a2,(___frame,a0)
#else /* CONFIG_SMP */
mov a2,(__frame)
#endif /* CONFIG_SMP */
mov (THREAD_PC,a1),a2
mov d2,d0 # for ret_from_fork
mov d0,a0 # for __switch_to

View File

@ -22,12 +22,7 @@
#include <asm/processor.h>
#include <asm/intctl-regs.h>
#include <asm/rtc.h>
#ifdef CONFIG_MN10300_RTC
unsigned long mn10300_ioclk; /* system I/O clock frequency */
unsigned long mn10300_iobclk; /* system I/O clock frequency */
unsigned long mn10300_tsc_per_HZ; /* number of ioclks per jiffy */
#endif /* CONFIG_MN10300_RTC */
#include "internal.h"
static unsigned long mn10300_last_tsc; /* time-stamp counter at last time
* interrupt occurred */
@ -95,6 +90,19 @@ static void __init mn10300_sched_clock_init(void)
__muldiv64u(NSEC_PER_SEC, 1 << 16, MN10300_TSCCLK);
}
/**
* local_timer_interrupt - Local timer interrupt handler
*
* Handle local timer interrupts for this CPU. They may have been propagated
* to this CPU from the CPU that actually gets them by way of an IPI.
*/
irqreturn_t local_timer_interrupt(void)
{
profile_tick(CPU_PROFILING);
update_process_times(user_mode(get_irq_regs()));
return IRQ_HANDLED;
}
/*
* advance the kernel's time keeping clocks (xtime and jiffies)
* - we use Timer 0 & 1 cascaded as a clock to nudge us the next time
@ -103,6 +111,7 @@ static void __init mn10300_sched_clock_init(void)
static irqreturn_t timer_interrupt(int irq, void *dev_id)
{
unsigned tsc, elapse;
irqreturn_t ret;
write_seqlock(&xtime_lock);
@ -114,15 +123,16 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id)
mn10300_last_tsc -= MN10300_TSC_PER_HZ;
/* advance the kernel's time tracking system */
profile_tick(CPU_PROFILING);
do_timer(1);
}
write_sequnlock(&xtime_lock);
update_process_times(user_mode(get_irq_regs()));
return IRQ_HANDLED;
ret = local_timer_interrupt();
#ifdef CONFIG_SMP
send_IPI_allbutself(LOCAL_TIMER_IPI);
#endif
return ret;
}
/*
@ -148,7 +158,7 @@ void __init time_init(void)
/* use timer 0 & 1 cascaded to tick at as close to HZ as possible */
setup_irq(TMJCIRQ, &timer_irq);
set_intr_level(TMJCIRQ, TMJCICR_LEVEL);
set_intr_level(TMJCIRQ, NUM2GxICR_LEVEL(CONFIG_TIMER_IRQ_LEVEL));
startup_jiffies_counter();

View File

@ -45,8 +45,13 @@
#error "INTERRUPT_VECTOR_BASE not aligned to 16MiB boundary!"
#endif
#ifdef CONFIG_SMP
struct pt_regs *___frame[NR_CPUS]; /* current frame pointer */
EXPORT_SYMBOL(___frame);
#else /* CONFIG_SMP */
struct pt_regs *__frame; /* current frame pointer */
EXPORT_SYMBOL(__frame);
#endif /* CONFIG_SMP */
int kstack_depth_to_print = 24;
@ -221,11 +226,14 @@ void show_registers_only(struct pt_regs *regs)
printk(KERN_EMERG "threadinfo=%p task=%p)\n",
current_thread_info(), current);
if ((unsigned long) current >= 0x90000000UL &&
(unsigned long) current < 0x94000000UL)
if ((unsigned long) current >= PAGE_OFFSET &&
(unsigned long) current < (unsigned long)high_memory)
printk(KERN_EMERG "Process %s (pid: %d)\n",
current->comm, current->pid);
#ifdef CONFIG_SMP
printk(KERN_EMERG "CPUID: %08x\n", CPUID);
#endif
printk(KERN_EMERG "CPUP: %04hx\n", CPUP);
printk(KERN_EMERG "TBR: %08x\n", TBR);
printk(KERN_EMERG "DEAR: %08x\n", DEAR);
@ -521,8 +529,12 @@ void __init set_intr_stub(enum exception_code code, void *handler)
{
unsigned long addr;
u8 *vector = (u8 *)(CONFIG_INTERRUPT_VECTOR_BASE + code);
unsigned long flags;
addr = (unsigned long) handler - (unsigned long) vector;
flags = arch_local_cli_save();
vector[0] = 0xdc; /* JMP handler */
vector[1] = addr;
vector[2] = addr >> 8;
@ -532,6 +544,8 @@ void __init set_intr_stub(enum exception_code code, void *handler)
vector[6] = 0xcb;
vector[7] = 0xcb;
arch_local_irq_restore(flags);
#ifndef CONFIG_MN10300_CACHE_SNOOP
mn10300_dcache_flush_inv();
mn10300_icache_inv();

View File

@ -38,14 +38,14 @@ EXPORT_SYMBOL(__delay);
*/
void __udelay(unsigned long usecs)
{
signed long ioclk, stop;
unsigned long start, stop, cnt;
/* usecs * CLK / 1E6 */
stop = __muldiv64u(usecs, MN10300_TSCCLK, 1000000);
stop = TMTSCBC - stop;
start = TMTSCBC;
do {
ioclk = TMTSCBC;
} while (stop < ioclk);
cnt = start - TMTSCBC;
} while (cnt < stop);
}
EXPORT_SYMBOL(__udelay);

View File

@ -39,10 +39,6 @@ void bust_spinlocks(int yes)
{
if (yes) {
oops_in_progress = 1;
#ifdef CONFIG_SMP
/* Many serial drivers do __global_cli() */
global_irq_lock = 0;
#endif
} else {
int loglevel_save = console_loglevel;
#ifdef CONFIG_VT
@ -334,10 +330,10 @@ no_context:
*/
out_of_memory:
up_read(&mm->mmap_sem);
if ((fault_code & MMUFCR_xFC_ACCESS) != MMUFCR_xFC_ACCESS_USR)
goto no_context;
pagefault_out_of_memory();
return;
printk(KERN_ALERT "VM: killing process %s\n", tsk->comm);
if ((fault_code & MMUFCR_xFC_ACCESS) == MMUFCR_xFC_ACCESS_USR)
do_exit(SIGKILL);
goto no_context;
do_sigbus:
up_read(&mm->mmap_sem);

View File

@ -13,6 +13,4 @@
#include <unit/clock.h>
#define MN10300_WDCLK MN10300_IOCLK
#endif /* _ASM_PROC_CLOCK_H */

View File

@ -0,0 +1,29 @@
#ifndef _ASM_PROC_INTCTL_REGS_H
#define _ASM_PROC_INTCTL_REGS_H
#ifndef _ASM_INTCTL_REGS_H
# error "please don't include this file directly"
#endif
/* intr acceptance group reg */
#define IAGR __SYSREG(0xd4000100, u16)
/* group number register */
#define IAGR_GN 0x00fc
#define __GET_XIRQ_TRIGGER(X, Z) (((Z) >> ((X) * 2)) & 3)
#define __SET_XIRQ_TRIGGER(X, Y, Z) \
({ \
typeof(Z) x = (Z); \
x &= ~(3 << ((X) * 2)); \
x |= ((Y) & 3) << ((X) * 2); \
(Z) = x; \
})
/* external pin intr spec reg */
#define EXTMD __SYSREG(0xd4000200, u16)
#define GET_XIRQ_TRIGGER(X) __GET_XIRQ_TRIGGER(X, EXTMD)
#define SET_XIRQ_TRIGGER(X, Y) __SET_XIRQ_TRIGGER(X, Y, EXTMD)
#endif /* _ASM_PROC_INTCTL_REGS_H */

View File

@ -11,6 +11,7 @@
#include <linux/kernel.h>
#include <asm/fpu.h>
#include <asm/rtc.h>
#include <asm/busctl-regs.h>
/*
* initialise the on-silicon processor peripherals
@ -75,3 +76,37 @@ asmlinkage void __init processor_init(void)
calibrate_clock();
}
/*
* determine the memory size and base from the memory controller regs
*/
void __init get_mem_info(unsigned long *mem_base, unsigned long *mem_size)
{
unsigned long base, size;
*mem_base = 0;
*mem_size = 0;
base = SDBASE(0);
if (base & SDBASE_CE) {
size = (base & SDBASE_CBAM) << SDBASE_CBAM_SHIFT;
size = ~size + 1;
base &= SDBASE_CBA;
printk(KERN_INFO "SDRAM[0]: %luMb @%08lx\n", size >> 20, base);
*mem_size += size;
*mem_base = base;
}
base = SDBASE(1);
if (base & SDBASE_CE) {
size = (base & SDBASE_CBAM) << SDBASE_CBAM_SHIFT;
size = ~size + 1;
base &= SDBASE_CBA;
printk(KERN_INFO "SDRAM[1]: %luMb @%08lx\n", size >> 20, base);
*mem_size += size;
if (*mem_base == 0)
*mem_base = base;
}
}

View File

@ -0,0 +1,5 @@
#
# Makefile for the linux kernel.
#
obj-y := proc-init.o

View File

@ -0,0 +1,48 @@
/* Cache specification
*
* Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* Modified by Matsushita Electric Industrial Co., Ltd.
* Modifications:
* 13-Nov-2006 MEI Add L1_CACHE_SHIFT_MAX definition.
* 29-Jul-2008 MEI Add define for MN10300_HAS_AREAPURGE_REG.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#ifndef _ASM_PROC_CACHE_H
#define _ASM_PROC_CACHE_H
/*
* L1 cache
*/
#define L1_CACHE_NWAYS 4 /* number of ways in caches */
#define L1_CACHE_NENTRIES 128 /* number of entries in each way */
#define L1_CACHE_BYTES 32 /* bytes per entry */
#define L1_CACHE_SHIFT 5 /* shift for bytes per entry */
#define L1_CACHE_WAYDISP 0x1000 /* distance from one way to the next */
#define L1_CACHE_TAG_VALID 0x00000001 /* cache tag valid bit */
#define L1_CACHE_TAG_DIRTY 0x00000008 /* data cache tag dirty bit */
#define L1_CACHE_TAG_ENTRY 0x00000fe0 /* cache tag entry address mask */
#define L1_CACHE_TAG_ADDRESS 0xfffff000 /* cache tag line address mask */
/*
* specification of the interval between interrupt checking intervals whilst
* managing the cache with the interrupts disabled
*/
#define MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL 4
/*
* The size of range at which it becomes more economical to just flush the
* whole cache rather than trying to flush the specified range.
*/
#define MN10300_DCACHE_FLUSH_BORDER \
+(L1_CACHE_NWAYS * L1_CACHE_NENTRIES * L1_CACHE_BYTES)
#define MN10300_DCACHE_FLUSH_INV_BORDER \
+(L1_CACHE_NWAYS * L1_CACHE_NENTRIES * L1_CACHE_BYTES)
#endif /* _ASM_PROC_CACHE_H */

View File

@ -0,0 +1,20 @@
/* clock.h: proc-specific clocks
*
* Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* Modified by Matsushita Electric Industrial Co., Ltd.
* Modifications:
* 23-Feb-2007 MEI Delete define for watchdog timer.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#ifndef _ASM_PROC_CLOCK_H
#define _ASM_PROC_CLOCK_H
#include <unit/clock.h>
#endif /* _ASM_PROC_CLOCK_H */

View File

@ -0,0 +1,103 @@
/* MN2WS0050 on-board DMA controller registers
*
* Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*/
#ifndef _ASM_PROC_DMACTL_REGS_H
#define _ASM_PROC_DMACTL_REGS_H
#include <asm/cpu-regs.h>
#ifdef __KERNEL__
/* DMA registers */
#define DMxCTR(N) __SYSREG(0xd4005000+(N*0x100), u32) /* control reg */
#define DMxCTR_BG 0x0000001f /* transfer request source */
#define DMxCTR_BG_SOFT 0x00000000 /* - software source */
#define DMxCTR_BG_SC0TX 0x00000002 /* - serial port 0 transmission */
#define DMxCTR_BG_SC0RX 0x00000003 /* - serial port 0 reception */
#define DMxCTR_BG_SC1TX 0x00000004 /* - serial port 1 transmission */
#define DMxCTR_BG_SC1RX 0x00000005 /* - serial port 1 reception */
#define DMxCTR_BG_SC2TX 0x00000006 /* - serial port 2 transmission */
#define DMxCTR_BG_SC2RX 0x00000007 /* - serial port 2 reception */
#define DMxCTR_BG_TM0UFLOW 0x00000008 /* - timer 0 underflow */
#define DMxCTR_BG_TM1UFLOW 0x00000009 /* - timer 1 underflow */
#define DMxCTR_BG_TM2UFLOW 0x0000000a /* - timer 2 underflow */
#define DMxCTR_BG_TM3UFLOW 0x0000000b /* - timer 3 underflow */
#define DMxCTR_BG_TM6ACMPCAP 0x0000000c /* - timer 6A compare/capture */
#define DMxCTR_BG_RYBY 0x0000000d /* - NAND Flash RY/BY request source */
#define DMxCTR_BG_RMC 0x0000000e /* - remote controller output */
#define DMxCTR_BG_XIRQ12 0x00000011 /* - XIRQ12 pin interrupt source */
#define DMxCTR_BG_XIRQ13 0x00000012 /* - XIRQ13 pin interrupt source */
#define DMxCTR_BG_TCK 0x00000014 /* - tick timer underflow */
#define DMxCTR_BG_SC4TX 0x00000019 /* - serial port4 transmission */
#define DMxCTR_BG_SC4RX 0x0000001a /* - serial port4 reception */
#define DMxCTR_BG_SC5TX 0x0000001b /* - serial port5 transmission */
#define DMxCTR_BG_SC5RX 0x0000001c /* - serial port5 reception */
#define DMxCTR_BG_SC6TX 0x0000001d /* - serial port6 transmission */
#define DMxCTR_BG_SC6RX 0x0000001e /* - serial port6 reception */
#define DMxCTR_BG_TMSUFLOW 0x0000001f /* - timestamp timer underflow */
#define DMxCTR_SAM 0x00000060 /* DMA transfer src addr mode */
#define DMxCTR_SAM_INCR 0x00000000 /* - increment */
#define DMxCTR_SAM_DECR 0x00000020 /* - decrement */
#define DMxCTR_SAM_FIXED 0x00000040 /* - fixed */
#define DMxCTR_DAM 0x00000300 /* DMA transfer dest addr mode */
#define DMxCTR_DAM_INCR 0x00000000 /* - increment */
#define DMxCTR_DAM_DECR 0x00000100 /* - decrement */
#define DMxCTR_DAM_FIXED 0x00000200 /* - fixed */
#define DMxCTR_UT 0x00006000 /* DMA transfer unit */
#define DMxCTR_UT_1 0x00000000 /* - 1 byte */
#define DMxCTR_UT_2 0x00002000 /* - 2 byte */
#define DMxCTR_UT_4 0x00004000 /* - 4 byte */
#define DMxCTR_UT_16 0x00006000 /* - 16 byte */
#define DMxCTR_RRE 0x00008000 /* DMA round robin enable */
#define DMxCTR_TEN 0x00010000 /* DMA channel transfer enable */
#define DMxCTR_RQM 0x00060000 /* external request input source mode */
#define DMxCTR_RQM_FALLEDGE 0x00000000 /* - falling edge */
#define DMxCTR_RQM_RISEEDGE 0x00020000 /* - rising edge */
#define DMxCTR_RQM_LOLEVEL 0x00040000 /* - low level */
#define DMxCTR_RQM_HILEVEL 0x00060000 /* - high level */
#define DMxCTR_RQF 0x01000000 /* DMA transfer request flag */
#define DMxCTR_PERR 0x40000000 /* DMA transfer parameter error flag */
#define DMxCTR_XEND 0x80000000 /* DMA transfer end flag */
#define DMxSRC(N) __SYSREG(0xd4005004+(N*0x100), u32) /* control reg */
#define DMxDST(N) __SYSREG(0xd4005008+(N*0x100), u32) /* source addr reg */
#define DMxSIZ(N) __SYSREG(0xd400500c+(N*0x100), u32) /* dest addr reg */
#define DMxSIZ_CT 0x000fffff /* number of bytes to transfer */
#define DMxCYC(N) __SYSREG(0xd4005010+(N*0x100), u32) /* intermittent size reg */
#define DMxCYC_CYC 0x000000ff /* number of interrmittent transfers -1 */
#define DM0IRQ 16 /* DMA channel 0 complete IRQ */
#define DM1IRQ 17 /* DMA channel 1 complete IRQ */
#define DM2IRQ 18 /* DMA channel 2 complete IRQ */
#define DM3IRQ 19 /* DMA channel 3 complete IRQ */
#define DM0ICR GxICR(DM0IRQ) /* DMA channel 0 complete intr ctrl reg */
#define DM1ICR GxICR(DM0IR1) /* DMA channel 1 complete intr ctrl reg */
#define DM2ICR GxICR(DM0IR2) /* DMA channel 2 complete intr ctrl reg */
#define DM3ICR GxICR(DM0IR3) /* DMA channel 3 complete intr ctrl reg */
#ifndef __ASSEMBLY__
struct mn10300_dmactl_regs {
u32 ctr;
const void *src;
void *dst;
u32 siz;
u32 cyc;
} __attribute__((aligned(0x100)));
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
#endif /* _ASM_PROC_DMACTL_REGS_H */

View File

@ -0,0 +1,29 @@
#ifndef _ASM_PROC_INTCTL_REGS_H
#define _ASM_PROC_INTCTL_REGS_H
#ifndef _ASM_INTCTL_REGS_H
# error "please don't include this file directly"
#endif
/* intr acceptance group reg */
#define IAGR __SYSREG(0xd4000100, u16)
/* group number register */
#define IAGR_GN 0x003fc
#define __GET_XIRQ_TRIGGER(X, Z) (((Z) >> ((X) * 2)) & 3)
#define __SET_XIRQ_TRIGGER(X, Y, Z) \
({ \
typeof(Z) x = (Z); \
x &= ~(3 << ((X) * 2)); \
x |= ((Y) & 3) << ((X) * 2); \
(Z) = x; \
})
/* external pin intr spec reg */
#define EXTMD0 __SYSREG(0xd4000200, u32)
#define GET_XIRQ_TRIGGER(X) __GET_XIRQ_TRIGGER(X, EXTMD0)
#define SET_XIRQ_TRIGGER(X, Y) __SET_XIRQ_TRIGGER(X, Y, EXTMD0)
#endif /* _ASM_PROC_INTCTL_REGS_H */

View File

@ -0,0 +1,49 @@
/* MN2WS0050 on-board interrupt controller registers
*
* Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* Modified by Matsushita Electric Industrial Co., Ltd.
* Modifications:
* 13-Nov-2006 MEI Define extended IRQ number for SMP support.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#ifndef _PROC_IRQ_H
#define _PROC_IRQ_H
#ifdef __KERNEL__
#define GxICR_NUM_IRQS 163
#ifdef CONFIG_SMP
#define GxICR_NUM_EXT_IRQS 197
#endif /* CONFIG_SMP */
#define GxICR_NUM_XIRQS 16
#define XIRQ0 34
#define XIRQ1 35
#define XIRQ2 36
#define XIRQ3 37
#define XIRQ4 38
#define XIRQ5 39
#define XIRQ6 40
#define XIRQ7 41
#define XIRQ8 42
#define XIRQ9 43
#define XIRQ10 44
#define XIRQ11 45
#define XIRQ12 46
#define XIRQ13 47
#define XIRQ14 48
#define XIRQ15 49
#define XIRQ2IRQ(num) (XIRQ0 + num)
#endif /* __KERNEL__ */
#endif /* _PROC_IRQ_H */

View File

@ -0,0 +1,120 @@
/* NAND flash interface register definitions
*
* Copyright (C) 2008-2009 Panasonic Corporation
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef _PROC_NAND_REGS_H_
#define _PROC_NAND_REGS_H_
/* command register */
#define FCOMMAND_0 __SYSREG(0xd8f00000, u8) /* fcommand[24:31] */
#define FCOMMAND_1 __SYSREG(0xd8f00001, u8) /* fcommand[16:23] */
#define FCOMMAND_2 __SYSREG(0xd8f00002, u8) /* fcommand[8:15] */
#define FCOMMAND_3 __SYSREG(0xd8f00003, u8) /* fcommand[0:7] */
/* for dma 16 byte trans, use FCOMMAND2 register */
#define FCOMMAND2_0 __SYSREG(0xd8f00110, u8) /* fcommand2[24:31] */
#define FCOMMAND2_1 __SYSREG(0xd8f00111, u8) /* fcommand2[16:23] */
#define FCOMMAND2_2 __SYSREG(0xd8f00112, u8) /* fcommand2[8:15] */
#define FCOMMAND2_3 __SYSREG(0xd8f00113, u8) /* fcommand2[0:7] */
#define FCOMMAND_FIEN 0x80 /* nand flash I/F enable */
#define FCOMMAND_BW_8BIT 0x00 /* 8bit bus width */
#define FCOMMAND_BW_16BIT 0x40 /* 16bit bus width */
#define FCOMMAND_BLOCKSZ_SMALL 0x00 /* small block */
#define FCOMMAND_BLOCKSZ_LARGE 0x20 /* large block */
#define FCOMMAND_DMASTART 0x10 /* dma start */
#define FCOMMAND_RYBY 0x08 /* ready/busy flag */
#define FCOMMAND_RYBYINTMSK 0x04 /* mask ready/busy interrupt */
#define FCOMMAND_XFWP 0x02 /* write protect enable */
#define FCOMMAND_XFCE 0x01 /* flash device disable */
#define FCOMMAND_SEQKILL 0x10 /* stop seq-read */
#define FCOMMAND_ANUM 0x07 /* address cycle */
#define FCOMMAND_ANUM_NONE 0x00 /* address cycle none */
#define FCOMMAND_ANUM_1CYC 0x01 /* address cycle 1cycle */
#define FCOMMAND_ANUM_2CYC 0x02 /* address cycle 2cycle */
#define FCOMMAND_ANUM_3CYC 0x03 /* address cycle 3cycle */
#define FCOMMAND_ANUM_4CYC 0x04 /* address cycle 4cycle */
#define FCOMMAND_ANUM_5CYC 0x05 /* address cycle 5cycle */
#define FCOMMAND_FCMD_READ0 0x00 /* read1 command */
#define FCOMMAND_FCMD_SEQIN 0x80 /* page program 1st command */
#define FCOMMAND_FCMD_PAGEPROG 0x10 /* page program 2nd command */
#define FCOMMAND_FCMD_RESET 0xff /* reset command */
#define FCOMMAND_FCMD_ERASE1 0x60 /* erase 1st command */
#define FCOMMAND_FCMD_ERASE2 0xd0 /* erase 2nd command */
#define FCOMMAND_FCMD_STATUS 0x70 /* read status command */
#define FCOMMAND_FCMD_READID 0x90 /* read id command */
#define FCOMMAND_FCMD_READOOB 0x50 /* read3 command */
/* address register */
#define FADD __SYSREG(0xd8f00004, u32)
/* address register 2 */
#define FADD2 __SYSREG(0xd8f00008, u32)
/* error judgement register */
#define FJUDGE __SYSREG(0xd8f0000c, u32)
#define FJUDGE_NOERR 0x0 /* no error */
#define FJUDGE_1BITERR 0x1 /* 1bit error in data area */
#define FJUDGE_PARITYERR 0x2 /* parity error */
#define FJUDGE_UNCORRECTABLE 0x3 /* uncorrectable error */
#define FJUDGE_ERRJDG_MSK 0x3 /* mask of judgement result */
/* 1st ECC store register */
#define FECC11 __SYSREG(0xd8f00010, u32)
/* 2nd ECC store register */
#define FECC12 __SYSREG(0xd8f00014, u32)
/* 3rd ECC store register */
#define FECC21 __SYSREG(0xd8f00018, u32)
/* 4th ECC store register */
#define FECC22 __SYSREG(0xd8f0001c, u32)
/* 5th ECC store register */
#define FECC31 __SYSREG(0xd8f00020, u32)
/* 6th ECC store register */
#define FECC32 __SYSREG(0xd8f00024, u32)
/* 7th ECC store register */
#define FECC41 __SYSREG(0xd8f00028, u32)
/* 8th ECC store register */
#define FECC42 __SYSREG(0xd8f0002c, u32)
/* data register */
#define FDATA __SYSREG(0xd8f00030, u32)
/* access pulse register */
#define FPWS __SYSREG(0xd8f00100, u32)
#define FPWS_PWS1W_2CLK 0x00000000 /* write pulse width 1clock */
#define FPWS_PWS1W_3CLK 0x01000000 /* write pulse width 2clock */
#define FPWS_PWS1W_4CLK 0x02000000 /* write pulse width 4clock */
#define FPWS_PWS1W_5CLK 0x03000000 /* write pulse width 5clock */
#define FPWS_PWS1W_6CLK 0x04000000 /* write pulse width 6clock */
#define FPWS_PWS1W_7CLK 0x05000000 /* write pulse width 7clock */
#define FPWS_PWS1W_8CLK 0x06000000 /* write pulse width 8clock */
#define FPWS_PWS1R_3CLK 0x00010000 /* read pulse width 3clock */
#define FPWS_PWS1R_4CLK 0x00020000 /* read pulse width 4clock */
#define FPWS_PWS1R_5CLK 0x00030000 /* read pulse width 5clock */
#define FPWS_PWS1R_6CLK 0x00040000 /* read pulse width 6clock */
#define FPWS_PWS1R_7CLK 0x00050000 /* read pulse width 7clock */
#define FPWS_PWS1R_8CLK 0x00060000 /* read pulse width 8clock */
#define FPWS_PWS2W_2CLK 0x00000100 /* write pulse interval 2clock */
#define FPWS_PWS2W_3CLK 0x00000200 /* write pulse interval 3clock */
#define FPWS_PWS2W_4CLK 0x00000300 /* write pulse interval 4clock */
#define FPWS_PWS2W_5CLK 0x00000400 /* write pulse interval 5clock */
#define FPWS_PWS2W_6CLK 0x00000500 /* write pulse interval 6clock */
#define FPWS_PWS2R_2CLK 0x00000001 /* read pulse interval 2clock */
#define FPWS_PWS2R_3CLK 0x00000002 /* read pulse interval 3clock */
#define FPWS_PWS2R_4CLK 0x00000003 /* read pulse interval 4clock */
#define FPWS_PWS2R_5CLK 0x00000004 /* read pulse interval 5clock */
#define FPWS_PWS2R_6CLK 0x00000005 /* read pulse interval 6clock */
/* command register 2 */
#define FCOMMAND2 __SYSREG(0xd8f00110, u32)
/* transfer frequency register */
#define FNUM __SYSREG(0xd8f00114, u32)
#define FSDATA_ADDR 0xd8f00400
/* active data register */
#define FSDATA __SYSREG(FSDATA_ADDR, u32)
#endif /* _PROC_NAND_REGS_H_ */

View File

@ -0,0 +1,18 @@
/* proc.h: MN2WS0050 processor description
*
* Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#ifndef _ASM_PROC_PROC_H
#define _ASM_PROC_PROC_H
#define PROCESSOR_VENDOR_NAME "Panasonic"
#define PROCESSOR_MODEL_NAME "mn2ws0050"
#endif /* _ASM_PROC_PROC_H */

View File

@ -0,0 +1,51 @@
/* MN10300/AM33v2 Microcontroller SMP registers
*
* Copyright (C) 2006 Matsushita Electric Industrial Co., Ltd.
* All Rights Reserved.
* Created:
* 13-Nov-2006 MEI Add extended cache and atomic operation register
* for SMP support.
* 23-Feb-2007 MEI Add define for gdbstub SMP.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#ifndef _ASM_PROC_SMP_REGS_H
#define _ASM_PROC_SMP_REGS_H
#ifdef __KERNEL__
#ifndef __ASSEMBLY__
#include <linux/types.h>
#endif
#include <asm/cpu-regs.h>
/*
* Reference to the interrupt controllers of other CPUs
*/
#define CROSS_ICR_CPU_SHIFT 16
#define CROSS_GxICR(X, CPU) __SYSREG(0xc4000000 + (X) * 4 + \
((X) >= 64 && (X) < 192) * 0xf00 + ((CPU) << CROSS_ICR_CPU_SHIFT), u16)
#define CROSS_GxICR_u8(X, CPU) __SYSREG(0xc4000000 + (X) * 4 + \
(((X) >= 64) && ((X) < 192)) * 0xf00 + ((CPU) << CROSS_ICR_CPU_SHIFT), u8)
/* CPU ID register */
#define CPUID __SYSREGC(0xc0000054, u32)
#define CPUID_MASK 0x00000007 /* CPU ID mask */
/* extended cache control register */
#define ECHCTR __SYSREG(0xc0000c20, u32)
#define ECHCTR_IBCM 0x00000001 /* instruction cache broad cast mask */
#define ECHCTR_DBCM 0x00000002 /* data cache broad cast mask */
#define ECHCTR_ISPM 0x00000004 /* instruction cache snoop mask */
#define ECHCTR_DSPM 0x00000008 /* data cache snoop mask */
#define NMIAGR __SYSREG(0xd400013c, u16)
#define NMIAGR_GN 0x03fc
#endif /* __KERNEL__ */
#endif /* _ASM_PROC_SMP_REGS_H */

View File

@ -0,0 +1,134 @@
/* MN2WS0050 processor initialisation
*
* Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <asm/processor.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/atomic.h>
#include <asm/smp.h>
#include <asm/pgalloc.h>
#include <asm/busctl-regs.h>
#include <unit/timex.h>
#include <asm/fpu.h>
#include <asm/rtc.h>
#define MEMCONF __SYSREGC(0xdf800400, u32)
/*
* initialise the on-silicon processor peripherals
*/
asmlinkage void __init processor_init(void)
{
int loop;
/* set up the exception table first */
for (loop = 0x000; loop < 0x400; loop += 8)
__set_intr_stub(loop, __common_exception);
__set_intr_stub(EXCEP_ITLBMISS, itlb_miss);
__set_intr_stub(EXCEP_DTLBMISS, dtlb_miss);
__set_intr_stub(EXCEP_IAERROR, itlb_aerror);
__set_intr_stub(EXCEP_DAERROR, dtlb_aerror);
__set_intr_stub(EXCEP_BUSERROR, raw_bus_error);
__set_intr_stub(EXCEP_DOUBLE_FAULT, double_fault);
__set_intr_stub(EXCEP_FPU_DISABLED, fpu_disabled);
__set_intr_stub(EXCEP_SYSCALL0, system_call);
__set_intr_stub(EXCEP_NMI, nmi_handler);
__set_intr_stub(EXCEP_WDT, nmi_handler);
__set_intr_stub(EXCEP_IRQ_LEVEL0, irq_handler);
__set_intr_stub(EXCEP_IRQ_LEVEL1, irq_handler);
__set_intr_stub(EXCEP_IRQ_LEVEL2, irq_handler);
__set_intr_stub(EXCEP_IRQ_LEVEL3, irq_handler);
__set_intr_stub(EXCEP_IRQ_LEVEL4, irq_handler);
__set_intr_stub(EXCEP_IRQ_LEVEL5, irq_handler);
__set_intr_stub(EXCEP_IRQ_LEVEL6, irq_handler);
IVAR0 = EXCEP_IRQ_LEVEL0;
IVAR1 = EXCEP_IRQ_LEVEL1;
IVAR2 = EXCEP_IRQ_LEVEL2;
IVAR3 = EXCEP_IRQ_LEVEL3;
IVAR4 = EXCEP_IRQ_LEVEL4;
IVAR5 = EXCEP_IRQ_LEVEL5;
IVAR6 = EXCEP_IRQ_LEVEL6;
#ifndef CONFIG_MN10300_HAS_CACHE_SNOOP
mn10300_dcache_flush_inv();
mn10300_icache_inv();
#endif
/* disable all interrupts and set to priority 6 (lowest) */
#ifdef CONFIG_SMP
for (loop = 0; loop < GxICR_NUM_IRQS; loop++)
GxICR(loop) = GxICR_LEVEL_6 | GxICR_DETECT;
#else /* !CONFIG_SMP */
for (loop = 0; loop < NR_IRQS; loop++)
GxICR(loop) = GxICR_LEVEL_6 | GxICR_DETECT;
#endif /* !CONFIG_SMP */
/* clear the timers */
TM0MD = 0;
TM1MD = 0;
TM2MD = 0;
TM3MD = 0;
TM4MD = 0;
TM5MD = 0;
TM6MD = 0;
TM6MDA = 0;
TM6MDB = 0;
TM7MD = 0;
TM8MD = 0;
TM9MD = 0;
TM10MD = 0;
TM11MD = 0;
TM12MD = 0;
TM13MD = 0;
TM14MD = 0;
TM15MD = 0;
calibrate_clock();
}
/*
* determine the memory size and base from the memory controller regs
*/
void __init get_mem_info(unsigned long *mem_base, unsigned long *mem_size)
{
unsigned long memconf = MEMCONF;
unsigned long size = 0; /* order: MByte */
*mem_base = 0x90000000; /* fixed address */
switch (memconf & 0x00000003) {
case 0x01:
size = 256 / 8; /* 256 Mbit per chip */
break;
case 0x02:
size = 512 / 8; /* 512 Mbit per chip */
break;
case 0x03:
size = 1024 / 8; /* 1 Gbit per chip */
break;
default:
panic("Invalid SDRAM size");
break;
}
printk(KERN_INFO "DDR2-SDRAM: %luMB x 2 @%08lx\n", size, *mem_base);
*mem_size = (size * 2) << 20;
}

View File

@ -14,32 +14,11 @@
#ifndef __ASSEMBLY__
#ifdef CONFIG_MN10300_RTC
extern unsigned long mn10300_ioclk; /* IOCLK (crystal speed) in HZ */
extern unsigned long mn10300_iobclk;
extern unsigned long mn10300_tsc_per_HZ;
#define MN10300_IOCLK mn10300_ioclk
/* If this processors has a another clock, uncomment the below. */
/* #define MN10300_IOBCLK mn10300_iobclk */
#else /* !CONFIG_MN10300_RTC */
#define MN10300_IOCLK 33333333UL
/* #define MN10300_IOBCLK 66666666UL */
#endif /* !CONFIG_MN10300_RTC */
#define MN10300_JCCLK MN10300_IOCLK
#define MN10300_TSCCLK MN10300_IOCLK
#ifdef CONFIG_MN10300_RTC
#define MN10300_TSC_PER_HZ mn10300_tsc_per_HZ
#else /* !CONFIG_MN10300_RTC */
#define MN10300_TSC_PER_HZ (MN10300_TSCCLK/HZ)
#endif /* !CONFIG_MN10300_RTC */
#endif /* !__ASSEMBLY__ */
#define MN10300_WDCLK MN10300_IOCLK
#endif /* _ASM_UNIT_CLOCK_H */

View File

@ -21,6 +21,11 @@
#define SERIAL_IRQ XIRQ0 /* Dual serial (PC16552) (Hi) */
/*
* The ASB2303 has an 18.432 MHz clock the UART
*/
#define BASE_BAUD (18432000 / 16)
/*
* dispose of the /dev/ttyS0 and /dev/ttyS1 serial ports
*/

View File

@ -1,4 +1,4 @@
/* ASB2303-specific timer specifcations
/* ASB2303-specific timer specifications
*
* Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
@ -17,6 +17,7 @@
#include <asm/timer-regs.h>
#include <unit/clock.h>
#include <asm/param.h>
/*
* jiffies counter specifications
@ -29,32 +30,43 @@
#define TMJCBR TM01BR
#define TMJCIRQ TM1IRQ
#define TMJCICR TM1ICR
#define TMJCICR_LEVEL GxICR_LEVEL_5
#ifndef __ASSEMBLY__
#define MN10300_SRC_IOCLK MN10300_IOCLK
#ifndef HZ
# error HZ undeclared.
#endif /* !HZ */
/* use as little prescaling as possible to avoid losing accuracy */
#if (MN10300_SRC_IOCLK + HZ / 2) / HZ - 1 <= TMJCBR_MAX
# define IOCLK_PRESCALE 1
# define JC_TIMER_CLKSRC TM0MD_SRC_IOCLK
# define TSC_TIMER_CLKSRC TM4MD_SRC_IOCLK
#elif (MN10300_SRC_IOCLK / 8 + HZ / 2) / HZ - 1 <= TMJCBR_MAX
# define IOCLK_PRESCALE 8
# define JC_TIMER_CLKSRC TM0MD_SRC_IOCLK_8
# define TSC_TIMER_CLKSRC TM4MD_SRC_IOCLK_8
#elif (MN10300_SRC_IOCLK / 32 + HZ / 2) / HZ - 1 <= TMJCBR_MAX
# define IOCLK_PRESCALE 32
# define JC_TIMER_CLKSRC TM0MD_SRC_IOCLK_32
# define TSC_TIMER_CLKSRC TM4MD_SRC_IOCLK_32
#else
# error You lose.
#endif
#define MN10300_JCCLK (MN10300_SRC_IOCLK / IOCLK_PRESCALE)
#define MN10300_TSCCLK (MN10300_SRC_IOCLK / IOCLK_PRESCALE)
#define MN10300_JC_PER_HZ ((MN10300_JCCLK + HZ / 2) / HZ)
#define MN10300_TSC_PER_HZ ((MN10300_TSCCLK + HZ / 2) / HZ)
static inline void startup_jiffies_counter(void)
{
unsigned rate;
u16 md, t16;
/* use as little prescaling as possible to avoid losing accuracy */
md = TM0MD_SRC_IOCLK;
rate = MN10300_JCCLK / HZ;
if (rate > TMJCBR_MAX) {
md = TM0MD_SRC_IOCLK_8;
rate = MN10300_JCCLK / 8 / HZ;
if (rate > TMJCBR_MAX) {
md = TM0MD_SRC_IOCLK_32;
rate = MN10300_JCCLK / 32 / HZ;
BUG_ON(rate > TMJCBR_MAX);
}
}
TMJCBR = rate - 1;
md = JC_TIMER_CLKSRC;
TMJCBR = MN10300_JC_PER_HZ - 1;
t16 = TMJCBR;
TMJCMD =
@ -93,29 +105,39 @@ static inline void shutdown_jiffies_counter(void)
static inline void startup_timestamp_counter(void)
{
u32 t32;
/* set up timer 4 & 5 cascaded as a 32-bit counter to count real time
* - count down from 4Gig-1 to 0 and wrap at IOCLK rate
*/
TM45BR = TMTSCBR_MAX;
t32 = TM45BR;
TM4MD = TM4MD_SRC_IOCLK;
TM4MD = TSC_TIMER_CLKSRC;
TM4MD |= TM4MD_INIT_COUNTER;
TM4MD &= ~TM4MD_INIT_COUNTER;
TM4ICR = 0;
t32 = TM4ICR;
TM5MD = TM5MD_SRC_TM4CASCADE;
TM5MD |= TM5MD_INIT_COUNTER;
TM5MD &= ~TM5MD_INIT_COUNTER;
TM5ICR = 0;
t32 = TM5ICR;
TM5MD |= TM5MD_COUNT_ENABLE;
TM4MD |= TM4MD_COUNT_ENABLE;
t32 = TM5MD;
t32 = TM4MD;
}
static inline void shutdown_timestamp_counter(void)
{
u8 t8;
TM4MD = 0;
TM5MD = 0;
t8 = TM4MD;
t8 = TM5MD;
}
/*

View File

@ -31,6 +31,14 @@ asmlinkage void __init unit_init(void)
SET_XIRQ_TRIGGER(3, XIRQ_TRIGGER_HILEVEL);
SET_XIRQ_TRIGGER(4, XIRQ_TRIGGER_LOWLEVEL);
SET_XIRQ_TRIGGER(5, XIRQ_TRIGGER_LOWLEVEL);
#ifdef CONFIG_EXT_SERIAL_IRQ_LEVEL
set_intr_level(XIRQ0, NUM2GxICR_LEVEL(CONFIG_EXT_SERIAL_IRQ_LEVEL));
#endif
#ifdef CONFIG_ETHERNET_IRQ_LEVEL
set_intr_level(XIRQ3, NUM2GxICR_LEVEL(CONFIG_ETHERNET_IRQ_LEVEL));
#endif
}
/*
@ -51,7 +59,7 @@ void __init unit_init_IRQ(void)
switch (GET_XIRQ_TRIGGER(extnum)) {
case XIRQ_TRIGGER_HILEVEL:
case XIRQ_TRIGGER_LOWLEVEL:
set_intr_postackable(XIRQ2IRQ(extnum));
mn10300_set_lateack_irq_type(XIRQ2IRQ(extnum));
break;
default:
break;

View File

@ -14,32 +14,11 @@
#ifndef __ASSEMBLY__
#ifdef CONFIG_MN10300_RTC
extern unsigned long mn10300_ioclk; /* IOCLK (crystal speed) in HZ */
extern unsigned long mn10300_iobclk;
extern unsigned long mn10300_tsc_per_HZ;
#define MN10300_IOCLK mn10300_ioclk
/* If this processors has a another clock, uncomment the below. */
/* #define MN10300_IOBCLK mn10300_iobclk */
#else /* !CONFIG_MN10300_RTC */
#define MN10300_IOCLK 33333333UL
/* #define MN10300_IOBCLK 66666666UL */
#endif /* !CONFIG_MN10300_RTC */
#define MN10300_JCCLK MN10300_IOCLK
#define MN10300_TSCCLK MN10300_IOCLK
#ifdef CONFIG_MN10300_RTC
#define MN10300_TSC_PER_HZ mn10300_tsc_per_HZ
#else /* !CONFIG_MN10300_RTC */
#define MN10300_TSC_PER_HZ (MN10300_TSCCLK/HZ)
#endif /* !CONFIG_MN10300_RTC */
#endif /* !__ASSEMBLY__ */
#define MN10300_WDCLK MN10300_IOCLK
#endif /* _ASM_UNIT_CLOCK_H */

View File

@ -20,6 +20,11 @@
#define SERIAL_IRQ XIRQ0 /* Dual serial (PC16552) (Hi) */
/*
* The ASB2305 has an 18.432 MHz clock the UART
*/
#define BASE_BAUD (18432000 / 16)
/*
* dispose of the /dev/ttyS0 serial port
*/

View File

@ -1,4 +1,4 @@
/* ASB2305 timer specifcations
/* ASB2305-specific timer specifications
*
* Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
@ -17,6 +17,7 @@
#include <asm/timer-regs.h>
#include <unit/clock.h>
#include <asm/param.h>
/*
* jiffies counter specifications
@ -29,32 +30,43 @@
#define TMJCBR TM01BR
#define TMJCIRQ TM1IRQ
#define TMJCICR TM1ICR
#define TMJCICR_LEVEL GxICR_LEVEL_5
#ifndef __ASSEMBLY__
#define MN10300_SRC_IOCLK MN10300_IOCLK
#ifndef HZ
# error HZ undeclared.
#endif /* !HZ */
/* use as little prescaling as possible to avoid losing accuracy */
#if (MN10300_SRC_IOCLK + HZ / 2) / HZ - 1 <= TMJCBR_MAX
# define IOCLK_PRESCALE 1
# define JC_TIMER_CLKSRC TM0MD_SRC_IOCLK
# define TSC_TIMER_CLKSRC TM4MD_SRC_IOCLK
#elif (MN10300_SRC_IOCLK / 8 + HZ / 2) / HZ - 1 <= TMJCBR_MAX
# define IOCLK_PRESCALE 8
# define JC_TIMER_CLKSRC TM0MD_SRC_IOCLK_8
# define TSC_TIMER_CLKSRC TM4MD_SRC_IOCLK_8
#elif (MN10300_SRC_IOCLK / 32 + HZ / 2) / HZ - 1 <= TMJCBR_MAX
# define IOCLK_PRESCALE 32
# define JC_TIMER_CLKSRC TM0MD_SRC_IOCLK_32
# define TSC_TIMER_CLKSRC TM4MD_SRC_IOCLK_32
#else
# error You lose.
#endif
#define MN10300_JCCLK (MN10300_SRC_IOCLK / IOCLK_PRESCALE)
#define MN10300_TSCCLK (MN10300_SRC_IOCLK / IOCLK_PRESCALE)
#define MN10300_JC_PER_HZ ((MN10300_JCCLK + HZ / 2) / HZ)
#define MN10300_TSC_PER_HZ ((MN10300_TSCCLK + HZ / 2) / HZ)
static inline void startup_jiffies_counter(void)
{
unsigned rate;
u16 md, t16;
/* use as little prescaling as possible to avoid losing accuracy */
md = TM0MD_SRC_IOCLK;
rate = MN10300_JCCLK / HZ;
if (rate > TMJCBR_MAX) {
md = TM0MD_SRC_IOCLK_8;
rate = MN10300_JCCLK / 8 / HZ;
if (rate > TMJCBR_MAX) {
md = TM0MD_SRC_IOCLK_32;
rate = MN10300_JCCLK / 32 / HZ;
BUG_ON(rate > TMJCBR_MAX);
}
}
TMJCBR = rate - 1;
md = JC_TIMER_CLKSRC;
TMJCBR = MN10300_JC_PER_HZ - 1;
t16 = TMJCBR;
TMJCMD =
@ -93,29 +105,39 @@ static inline void shutdown_jiffies_counter(void)
static inline void startup_timestamp_counter(void)
{
u32 t32;
/* set up timer 4 & 5 cascaded as a 32-bit counter to count real time
* - count down from 4Gig-1 to 0 and wrap at IOCLK rate
*/
TM45BR = TMTSCBR_MAX;
t32 = TM45BR;
TM4MD = TM4MD_SRC_IOCLK;
TM4MD = TSC_TIMER_CLKSRC;
TM4MD |= TM4MD_INIT_COUNTER;
TM4MD &= ~TM4MD_INIT_COUNTER;
TM4ICR = 0;
t32 = TM4ICR;
TM5MD = TM5MD_SRC_TM4CASCADE;
TM5MD |= TM5MD_INIT_COUNTER;
TM5MD &= ~TM5MD_INIT_COUNTER;
TM5ICR = 0;
t32 = TM5ICR;
TM5MD |= TM5MD_COUNT_ENABLE;
TM4MD |= TM4MD_COUNT_ENABLE;
t32 = TM5MD;
t32 = TM4MD;
}
static inline void shutdown_timestamp_counter(void)
{
u8 t8;
TM4MD = 0;
TM5MD = 0;
t8 = TM4MD;
t8 = TM5MD;
}
/*
@ -126,7 +148,7 @@ typedef unsigned long cycles_t;
static inline cycles_t read_timestamp_counter(void)
{
return (cycles_t) TMTSCBC;
return (cycles_t)TMTSCBC;
}
#endif /* !__ASSEMBLY__ */

View File

@ -503,7 +503,7 @@ asmlinkage void __init unit_pci_init(void)
struct pci_ops *o = &pci_direct_ampci;
u32 x;
set_intr_level(XIRQ1, GxICR_LEVEL_3);
set_intr_level(XIRQ1, NUM2GxICR_LEVEL(CONFIG_PCI_IRQ_LEVEL));
memset(&bus, 0, sizeof(bus));

View File

@ -26,8 +26,10 @@ asmlinkage void __init unit_init(void)
{
#ifndef CONFIG_GDBSTUB_ON_TTYSx
/* set the 16550 interrupt line to level 3 if not being used for GDB */
set_intr_level(XIRQ0, GxICR_LEVEL_3);
#ifdef CONFIG_EXT_SERIAL_IRQ_LEVEL
set_intr_level(XIRQ0, NUM2GxICR_LEVEL(CONFIG_EXT_SERIAL_IRQ_LEVEL));
#endif
#endif /* CONFIG_GDBSTUB_ON_TTYSx */
}
/*
@ -51,7 +53,7 @@ void __init unit_init_IRQ(void)
switch (GET_XIRQ_TRIGGER(extnum)) {
case XIRQ_TRIGGER_HILEVEL:
case XIRQ_TRIGGER_LOWLEVEL:
set_intr_postackable(XIRQ2IRQ(extnum));
mn10300_set_lateack_irq_type(XIRQ2IRQ(extnum));
break;
default:
break;

View File

@ -0,0 +1,10 @@
#
# Makefile for the linux kernel.
#
# Note! Dependencies are done automagically by 'make dep', which also
# removes any old dependencies. DON'T put your own dependencies here
# unless it's something special (ie not a .c file).
#
# Note 2! The CFLAGS definitions are now in the main makefile...
obj-y := unit-init.o leds.o

View File

@ -0,0 +1,29 @@
/* clock.h: unit-specific clocks
*
* Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* Modified by Matsushita Electric Industrial Co., Ltd.
* Modifications:
* 23-Feb-2007 MEI Add define for watchdog timer.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#ifndef _ASM_UNIT_CLOCK_H
#define _ASM_UNIT_CLOCK_H
#ifndef __ASSEMBLY__
#define MN10300_IOCLK 100000000UL /* for DDR800 */
/*#define MN10300_IOCLK 83333333UL */ /* for DDR667 */
#define MN10300_IOBCLK MN10300_IOCLK /* IOBCLK is equal to IOCLK */
#endif /* !__ASSEMBLY__ */
#define MN10300_WDCLK 27000000UL
#endif /* _ASM_UNIT_CLOCK_H */

View File

@ -0,0 +1,50 @@
/* ASB2364 FPGA registers
*/
#ifndef _ASM_UNIT_FPGA_REGS_H
#define _ASM_UNIT_FPGA_REGS_H
#include <asm/cpu-regs.h>
#ifdef __KERNEL__
#define ASB2364_FPGA_REG_RESET_LAN __SYSREG(0xa9001300, u16)
#define ASB2364_FPGA_REG_RESET_UART __SYSREG(0xa9001304, u16)
#define ASB2364_FPGA_REG_RESET_I2C __SYSREG(0xa9001308, u16)
#define ASB2364_FPGA_REG_RESET_USB __SYSREG(0xa900130c, u16)
#define ASB2364_FPGA_REG_RESET_AV __SYSREG(0xa9001310, u16)
#define ASB2364_FPGA_REG_IRQ_LAN __SYSREG(0xa9001510, u16)
#define ASB2364_FPGA_REG_IRQ_UART __SYSREG(0xa9001514, u16)
#define ASB2364_FPGA_REG_IRQ_I2C __SYSREG(0xa9001518, u16)
#define ASB2364_FPGA_REG_IRQ_USB __SYSREG(0xa900151c, u16)
#define ASB2364_FPGA_REG_IRQ_FPGA __SYSREG(0xa9001524, u16)
#define ASB2364_FPGA_REG_MASK_LAN __SYSREG(0xa9001590, u16)
#define ASB2364_FPGA_REG_MASK_UART __SYSREG(0xa9001594, u16)
#define ASB2364_FPGA_REG_MASK_I2C __SYSREG(0xa9001598, u16)
#define ASB2364_FPGA_REG_MASK_USB __SYSREG(0xa900159c, u16)
#define ASB2364_FPGA_REG_MASK_FPGA __SYSREG(0xa90015a4, u16)
#define ASB2364_FPGA_REG_CPLD5_SET1 __SYSREG(0xa9002500, u16)
#define ASB2364_FPGA_REG_CPLD5_SET2 __SYSREG(0xa9002504, u16)
#define ASB2364_FPGA_REG_CPLD6_SET1 __SYSREG(0xa9002600, u16)
#define ASB2364_FPGA_REG_CPLD6_SET2 __SYSREG(0xa9002604, u16)
#define ASB2364_FPGA_REG_CPLD7_SET1 __SYSREG(0xa9002700, u16)
#define ASB2364_FPGA_REG_CPLD7_SET2 __SYSREG(0xa9002704, u16)
#define ASB2364_FPGA_REG_CPLD8_SET1 __SYSREG(0xa9002800, u16)
#define ASB2364_FPGA_REG_CPLD8_SET2 __SYSREG(0xa9002804, u16)
#define ASB2364_FPGA_REG_CPLD9_SET1 __SYSREG(0xa9002900, u16)
#define ASB2364_FPGA_REG_CPLD9_SET2 __SYSREG(0xa9002904, u16)
#define ASB2364_FPGA_REG_CPLD10_SET1 __SYSREG(0xa9002a00, u16)
#define ASB2364_FPGA_REG_CPLD10_SET2 __SYSREG(0xa9002a04, u16)
#define SyncExBus() \
do { \
unsigned short w; \
w = *(volatile short *)0xa9000000; \
} while (0)
#endif /* __KERNEL__ */
#endif /* _ASM_UNIT_FPGA_REGS_H */

View File

@ -0,0 +1,54 @@
/* Unit-specific leds
*
* Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#ifndef _ASM_UNIT_LEDS_H
#define _ASM_UNIT_LEDS_H
#include <asm/pio-regs.h>
#include <asm/cpu-regs.h>
#include <asm/exceptions.h>
#define MN10300_USE_7SEGLEDS 0
#define ASB2364_7SEGLEDS __SYSREG(0xA9001630, u32)
/*
* use the 7-segment LEDs to indicate states
*/
#if MN10300_USE_7SEGLEDS
/* flip the 7-segment LEDs between "Gdb-" and "----" */
#define mn10300_set_gdbleds(ONOFF) \
do { \
ASB2364_7SEGLEDS = (ONOFF) ? 0x8543077f : 0x7f7f7f7f; \
} while (0)
#else
#define mn10300_set_gdbleds(ONOFF) do {} while (0)
#endif
#if MN10300_USE_7SEGLEDS
/* indicate double-fault by displaying "db-f" on the LEDs */
#define mn10300_set_dbfleds \
mov 0x43077f1d,d0 ; \
mov d0,(ASB2364_7SEGLEDS)
#else
#define mn10300_set_dbfleds
#endif
#ifndef __ASSEMBLY__
extern void peripheral_leds_display_exception(enum exception_code);
extern void peripheral_leds_led_chase(void);
extern void peripheral_leds7x4_display_dec(unsigned int, unsigned int);
extern void peripheral_leds7x4_display_hex(unsigned int, unsigned int);
extern void debug_to_serial(const char *, int);
#endif /* __ASSEMBLY__ */
#endif /* _ASM_UNIT_LEDS_H */

View File

@ -0,0 +1,151 @@
/* Unit-specific 8250 serial ports
*
* Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#ifndef _ASM_UNIT_SERIAL_H
#define _ASM_UNIT_SERIAL_H
#include <asm/cpu-regs.h>
#include <proc/irq.h>
#include <unit/fpga-regs.h>
#include <linux/serial_reg.h>
#define SERIAL_PORT0_BASE_ADDRESS 0xA8200000
#define SERIAL_IRQ XIRQ1 /* single serial (TL16C550C) (Lo) */
/*
* The ASB2364 has an 12.288 MHz clock
* for your UART.
*
* It'd be nice if someone built a serial card with a 24.576 MHz
* clock, since the 16550A is capable of handling a top speed of 1.5
* megabits/second; but this requires the faster clock.
*/
#define BASE_BAUD (12288000 / 16)
/*
* dispose of the /dev/ttyS0 and /dev/ttyS1 serial ports
*/
#ifndef CONFIG_GDBSTUB_ON_TTYSx
#define SERIAL_PORT_DFNS \
{ \
.baud_base = BASE_BAUD, \
.irq = SERIAL_IRQ, \
.flags = STD_COM_FLAGS, \
.iomem_base = (u8 *) SERIAL_PORT0_BASE_ADDRESS, \
.iomem_reg_shift = 1, \
.io_type = SERIAL_IO_MEM, \
},
#ifndef __ASSEMBLY__
static inline void __debug_to_serial(const char *p, int n)
{
}
#endif /* !__ASSEMBLY__ */
#else /* CONFIG_GDBSTUB_ON_TTYSx */
#define SERIAL_PORT_DFNS /* stolen by gdb-stub */
#if defined(CONFIG_GDBSTUB_ON_TTYS0)
#define GDBPORT_SERIAL_RX __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_RX * 4, u8)
#define GDBPORT_SERIAL_TX __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_TX * 4, u8)
#define GDBPORT_SERIAL_DLL __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_DLL * 4, u8)
#define GDBPORT_SERIAL_DLM __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_DLM * 4, u8)
#define GDBPORT_SERIAL_IER __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_IER * 4, u8)
#define GDBPORT_SERIAL_IIR __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_IIR * 4, u8)
#define GDBPORT_SERIAL_FCR __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_FCR * 4, u8)
#define GDBPORT_SERIAL_LCR __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_LCR * 4, u8)
#define GDBPORT_SERIAL_MCR __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_MCR * 4, u8)
#define GDBPORT_SERIAL_LSR __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_LSR * 4, u8)
#define GDBPORT_SERIAL_MSR __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_MSR * 4, u8)
#define GDBPORT_SERIAL_SCR __SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_SCR * 4, u8)
#define GDBPORT_SERIAL_IRQ SERIAL_IRQ
#elif defined(CONFIG_GDBSTUB_ON_TTYS1)
#error The ASB2364 does not have a /dev/ttyS1
#endif
#ifndef __ASSEMBLY__
static inline void __debug_to_serial(const char *p, int n)
{
char ch;
#define LSR_WAIT_FOR(STATE) \
do {} while (!(GDBPORT_SERIAL_LSR & UART_LSR_##STATE))
#define FLOWCTL_QUERY(LINE) \
({ GDBPORT_SERIAL_MSR & UART_MSR_##LINE; })
#define FLOWCTL_WAIT_FOR(LINE) \
do {} while (!(GDBPORT_SERIAL_MSR & UART_MSR_##LINE))
#define FLOWCTL_CLEAR(LINE) \
do { GDBPORT_SERIAL_MCR &= ~UART_MCR_##LINE; } while (0)
#define FLOWCTL_SET(LINE) \
do { GDBPORT_SERIAL_MCR |= UART_MCR_##LINE; } while (0)
FLOWCTL_SET(DTR);
for (; n > 0; n--) {
LSR_WAIT_FOR(THRE);
FLOWCTL_WAIT_FOR(CTS);
ch = *p++;
if (ch == 0x0a) {
GDBPORT_SERIAL_TX = 0x0d;
LSR_WAIT_FOR(THRE);
FLOWCTL_WAIT_FOR(CTS);
}
GDBPORT_SERIAL_TX = ch;
}
FLOWCTL_CLEAR(DTR);
}
#endif /* !__ASSEMBLY__ */
#endif /* CONFIG_GDBSTUB_ON_TTYSx */
#define SERIAL_INITIALIZE \
do { \
/* release reset */ \
ASB2364_FPGA_REG_RESET_UART = 0x0001; \
SyncExBus(); \
} while (0)
#define SERIAL_CHECK_INTERRUPT \
do { \
if ((ASB2364_FPGA_REG_IRQ_UART & 0x0001) == 0x0001) { \
return IRQ_NONE; \
} \
} while (0)
#define SERIAL_CLEAR_INTERRUPT \
do { \
ASB2364_FPGA_REG_IRQ_UART = 0x0001; \
SyncExBus(); \
} while (0)
#define SERIAL_SET_INT_MASK \
do { \
ASB2364_FPGA_REG_MASK_UART = 0x0001; \
SyncExBus(); \
} while (0)
#define SERIAL_CLEAR_INT_MASK \
do { \
ASB2364_FPGA_REG_MASK_UART = 0x0000; \
SyncExBus(); \
} while (0)
#endif /* _ASM_UNIT_SERIAL_H */

View File

@ -0,0 +1,125 @@
/* timex.h: MN2WS0038 architecture timer specifications
*
* Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#ifndef _ASM_UNIT_TIMEX_H
#define _ASM_UNIT_TIMEX_H
#ifndef __ASSEMBLY__
#include <linux/irq.h>
#endif /* __ASSEMBLY__ */
#include <asm/timer-regs.h>
#include <unit/clock.h>
#include <asm/param.h>
/*
* jiffies counter specifications
*/
#define TMJCBR_MAX 0xffffff /* 24bit */
#define TMJCBC TMTBC
#define TMJCMD TMTMD
#define TMJCBR TMTBR
#define TMJCIRQ TMTIRQ
#define TMJCICR TMTICR
#ifndef __ASSEMBLY__
#define MN10300_SRC_IOBCLK MN10300_IOBCLK
#ifndef HZ
# error HZ undeclared.
#endif /* !HZ */
#define MN10300_JCCLK (MN10300_SRC_IOBCLK)
#define MN10300_TSCCLK (MN10300_SRC_IOBCLK)
#define MN10300_JC_PER_HZ ((MN10300_JCCLK + HZ / 2) / HZ)
#define MN10300_TSC_PER_HZ ((MN10300_TSCCLK + HZ / 2) / HZ)
/* Check bit width of MTM interval value that sets base register */
#if (MN10300_JC_PER_HZ - 1) > TMJCBR_MAX
# error MTM tick timer interval value is overflow.
#endif
static inline void startup_jiffies_counter(void)
{
u32 sync;
TMJCBR = MN10300_JC_PER_HZ - 1;
sync = TMJCBR;
TMJCMD = TMTMD_TMTLDE;
TMJCMD = TMTMD_TMTCNE;
sync = TMJCMD;
TMJCICR |= GxICR_ENABLE | GxICR_DETECT | GxICR_REQUEST;
sync = TMJCICR;
}
static inline void shutdown_jiffies_counter(void)
{
}
#endif /* !__ASSEMBLY__ */
/*
* timestamp counter specifications
*/
#define TMTSCBR_MAX 0xffffffff
#define TMTSCMD TMSMD
#define TMTSCBR TMSBR
#define TMTSCBC TMSBC
#define TMTSCICR TMSICR
#ifndef __ASSEMBLY__
static inline void startup_timestamp_counter(void)
{
u32 sync;
/* set up TMS(Timestamp) 32bit timer register to count real time
* - count down from 4Gig-1 to 0 and wrap at IOBCLK rate
*/
TMTSCBR = TMTSCBR_MAX;
sync = TMTSCBR;
TMTSCICR = 0;
sync = TMTSCICR;
TMTSCMD = TMTMD_TMTLDE;
TMTSCMD = TMTMD_TMTCNE;
sync = TMTSCMD;
}
static inline void shutdown_timestamp_counter(void)
{
TMTSCMD = 0;
}
/*
* we use a cascaded pair of 16-bit down-counting timers to count I/O
* clock cycles for the purposes of time keeping
*/
typedef unsigned long cycles_t;
static inline cycles_t read_timestamp_counter(void)
{
return (cycles_t)TMTSCBC;
}
#endif /* !__ASSEMBLY__ */
#endif /* _ASM_UNIT_TIMEX_H */

View File

@ -0,0 +1,98 @@
/* leds.c: ASB2364 peripheral 7seg LEDs x4 support
*
* Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#include <linux/kernel.h>
#include <linux/param.h>
#include <linux/init.h>
#include <asm/io.h>
#include <asm/processor.h>
#include <asm/intctl-regs.h>
#include <asm/rtc-regs.h>
#include <unit/leds.h>
#if MN10300_USE_7SEGLEDS
static const u8 asb2364_led_hex_tbl[16] = {
0x80, 0xf2, 0x48, 0x60, 0x32, 0x24, 0x04, 0xf0,
0x00, 0x20, 0x10, 0x06, 0x8c, 0x42, 0x0c, 0x1c
};
static const u32 asb2364_led_chase_tbl[6] = {
~0x02020202, /* top - segA */
~0x04040404, /* right top - segB */
~0x08080808, /* right bottom - segC */
~0x10101010, /* bottom - segD */
~0x20202020, /* left bottom - segE */
~0x40404040, /* left top - segF */
};
static unsigned asb2364_led_chase;
void peripheral_leds7x4_display_dec(unsigned int val, unsigned int points)
{
u32 leds;
leds = asb2364_led_hex_tbl[(val/1000) % 10];
leds <<= 8;
leds |= asb2364_led_hex_tbl[(val/100) % 10];
leds <<= 8;
leds |= asb2364_led_hex_tbl[(val/10) % 10];
leds <<= 8;
leds |= asb2364_led_hex_tbl[val % 10];
leds |= points^0x01010101;
ASB2364_7SEGLEDS = leds;
}
void peripheral_leds7x4_display_hex(unsigned int val, unsigned int points)
{
u32 leds;
leds = asb2364_led_hex_tbl[(val/1000) % 10];
leds <<= 8;
leds |= asb2364_led_hex_tbl[(val/100) % 10];
leds <<= 8;
leds |= asb2364_led_hex_tbl[(val/10) % 10];
leds <<= 8;
leds |= asb2364_led_hex_tbl[val % 10];
leds |= points^0x01010101;
ASB2364_7SEGLEDS = leds;
}
/* display triple horizontal bar and exception code */
void peripheral_leds_display_exception(enum exception_code code)
{
u32 leds;
leds = asb2364_led_hex_tbl[(code/0x100) % 0x10];
leds <<= 8;
leds |= asb2364_led_hex_tbl[(code/0x10) % 0x10];
leds <<= 8;
leds |= asb2364_led_hex_tbl[code % 0x10];
leds |= 0x6d010101;
ASB2364_7SEGLEDS = leds;
}
void peripheral_leds_led_chase(void)
{
ASB2364_7SEGLEDS = asb2364_led_chase_tbl[asb2364_led_chase];
asb2364_led_chase++;
if (asb2364_led_chase >= 6)
asb2364_led_chase = 0;
}
#else /* MN10300_USE_7SEGLEDS */
void peripheral_leds7x4_display_dec(unsigned int val, unsigned int points) { }
void peripheral_leds7x4_display_hex(unsigned int val, unsigned int points) { }
void peripheral_leds_display_exception(enum exception_code code) { }
void peripheral_leds_led_chase(void) { }
#endif /* MN10300_USE_7SEGLEDS */

View File

@ -0,0 +1,85 @@
/* ASB2364 initialisation
*
* Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#include <linux/kernel.h>
#include <linux/param.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/delay.h>
#include <asm/io.h>
#include <asm/setup.h>
#include <asm/processor.h>
#include <asm/irq.h>
#include <asm/intctl-regs.h>
/*
* initialise some of the unit hardware before gdbstub is set up
*/
asmlinkage void __init unit_init(void)
{
/* set up the external interrupts */
/* XIRQ[0]: NAND RXBY */
/* SET_XIRQ_TRIGGER(0, XIRQ_TRIGGER_LOWLEVEL); */
/* XIRQ[1]: LAN, UART, I2C, USB, PCI, FPGA */
SET_XIRQ_TRIGGER(1, XIRQ_TRIGGER_LOWLEVEL);
/* XIRQ[2]: Extend Slot 1-9 */
/* SET_XIRQ_TRIGGER(2, XIRQ_TRIGGER_LOWLEVEL); */
#if defined(CONFIG_EXT_SERIAL_IRQ_LEVEL) && \
defined(CONFIG_ETHERNET_IRQ_LEVEL) && \
(CONFIG_EXT_SERIAL_IRQ_LEVEL != CONFIG_ETHERNET_IRQ_LEVEL)
# error CONFIG_EXT_SERIAL_IRQ_LEVEL != CONFIG_ETHERNET_IRQ_LEVEL
#endif
#if defined(CONFIG_EXT_SERIAL_IRQ_LEVEL)
set_intr_level(XIRQ1, NUM2GxICR_LEVEL(CONFIG_EXT_SERIAL_IRQ_LEVEL));
#elif defined(CONFIG_ETHERNET_IRQ_LEVEL)
set_intr_level(XIRQ1, NUM2GxICR_LEVEL(CONFIG_ETHERNET_IRQ_LEVEL));
#endif
}
/*
* initialise the rest of the unit hardware after gdbstub is ready
*/
asmlinkage void __init unit_setup(void)
{
}
/*
* initialise the external interrupts used by a unit of this type
*/
void __init unit_init_IRQ(void)
{
unsigned int extnum;
for (extnum = 0 ; extnum < NR_XIRQS ; extnum++) {
switch (GET_XIRQ_TRIGGER(extnum)) {
/* LEVEL triggered interrupts should be made
* post-ACK'able as they hold their lines until
* serviced
*/
case XIRQ_TRIGGER_HILEVEL:
case XIRQ_TRIGGER_LOWLEVEL:
mn10300_set_lateack_irq_type(XIRQ2IRQ(extnum));
break;
default:
break;
}
}
#define IRQCTL __SYSREG(0xd5000090, u32)
IRQCTL |= 0x02;
}