Commit 368dd5ac authored by Akira Takeuchi's avatar Akira Takeuchi Committed by David Howells
Browse files

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: default avatarAkira Takeuchi <takeuchi.akr@jp.panasonic.com>
Signed-off-by: default avatarKiyoshi Owada <owada.kiyoshi@jp.panasonic.com>
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
parent 04157a6e
......@@ -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)
......
......@@ -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.
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>.
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 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
......
......@@ -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
......
......@@ -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)
......
......@@ -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 */
......@@ -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
......
......@@ -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 */
......
......@@ -15,24 +15,19 @@
#ifdef __KERNEL__
/* interrupt controller registers */
#define GxICR(X) __SYSREG(0xd4000000 + (X) * 4, u16) /* group irq ctrl regs */
#define IAGR __SYSREG(0xd4000100, u16) /* intr acceptance group reg */
#define IAGR_GN 0x00fc /* group number register
* (documentation _has_ to be wrong)
*/
/*
* 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 EXTMD __SYSREG(0xd4000200, u16) /* external pin intr spec reg */
#define GET_XIRQ_TRIGGER(X) ((EXTMD >> ((X) * 2)) & 3)
#define GxICR_u8(X) \
__SYSREG(0xd4000000 + (X) * 4 + \
(((X) >= 64) && ((X) < 192)) * 0xf00, u8)
#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 */
......
......@@ -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
......
......@@ -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(
......
......@@ -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,
......
......@@ -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 *);
......
......@@ -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 */
......@@ -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);
......
......@@ -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>
......
/*
* 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 */
......@@ -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 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 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_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) */
#define SC01CTR_CK_EXTERN_8 0x0006 /* - 1/8 external closk */
#define SC01CTR_CK_EXTERN 0x0007 /* - external closk */
#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 */
......
......@@ -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 */
......@@ -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
#ifndef __ASSEMBLY__
#include <linux/threads.h>
#include <linux/cpumask.h>
#endif
#ifdef CONFIG_SMP
#error SMP not yet supported for MN10300
#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 */
......@@ -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 */
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment