1
0
Fork 0

Merge master.kernel.org:/pub/scm/linux/kernel/git/lethal/sh-2.6

* master.kernel.org:/pub/scm/linux/kernel/git/lethal/sh-2.6: (43 commits)
  sh: sh775x/titan fixes for irq header changes.
  sh: update r7780rp defconfig.
  sh: compile fixes for header cleanup.
  sh: Fixup pte_mkhuge() build failure.
  sh: set KBUILD_IMAGE to something sensible.
  sh: show held locks in stack trace with lockdep.
  sh: platform_pata support for R7780RP
  sh: stacktrace/lockdep/irqflags tracing support.
  sh: Fixup movli.l/movco.l atomic ops for gcc4.
  sh: dyntick infrastructure.
  sh: Clock framework tidying.
  sh: Turn off IRQs around get_timer_offset() calls.
  sh: Get the PGD right in oops case with 64-bit PTEs.
  sh: Fix store queue bitmap end.
  sh: More flexible + SH7780 earlyprintk SCIF support.
  sh: Fixup various PAGE_SIZE == 4096 assumptions.
  sh: Fixup 4K irq stacks.
  sh: dma-api channel capability extensions.
  sh: Drop name overload in dma-sh.
  sh: Make dma-isa depend on ISA_DMA_API.
  ...
hifive-unleashed-5.1
Linus Torvalds 2006-12-06 08:10:55 -08:00
commit dd6a7c19e4
126 changed files with 5656 additions and 2971 deletions

View File

@ -51,6 +51,14 @@ config GENERIC_TIME
config ARCH_MAY_HAVE_PC_FDC
bool
config STACKTRACE_SUPPORT
bool
default y
config LOCKDEP_SUPPORT
bool
default y
source "init/Kconfig"
menu "System type"
@ -219,6 +227,20 @@ config SH_SHMIN
help
Select SHMIN if configuring for the SHMIN board.
config SH_7206_SOLUTION_ENGINE
bool "SolutionEngine7206"
select CPU_SUBTYPE_SH7206
help
Select 7206 SolutionEngine if configuring for a Hitachi SH7206
evaluation board.
config SH_7619_SOLUTION_ENGINE
bool "SolutionEngine7619"
select CPU_SUBTYPE_SH7619
help
Select 7619 SolutionEngine if configuring for a Hitachi SH7619
evaluation board.
config SH_UNKNOWN
bool "BareCPU"
help
@ -280,12 +302,20 @@ config CF_BASE_ADDR
menu "Processor features"
config CPU_LITTLE_ENDIAN
bool "Little Endian"
choice
prompt "Endianess selection"
default CPU_LITTLE_ENDIAN
help
Some SuperH machines can be configured for either little or big
endian byte order. These modes require different kernels. Say Y if
your machine is little endian, N if it's a big endian machine.
endian byte order. These modes require different kernels.
config CPU_LITTLE_ENDIAN
bool "Little Endian"
config CPU_BIG_ENDIAN
bool "Big Endian"
endchoice
config SH_FPU
bool "FPU support"
@ -345,6 +375,9 @@ config CPU_HAS_MASKREG_IRQ
config CPU_HAS_INTC2_IRQ
bool
config CPU_HAS_IPR_IRQ
bool
config CPU_HAS_SR_RB
bool "CPU has SR.RB"
depends on CPU_SH3 || CPU_SH4
@ -357,6 +390,9 @@ config CPU_HAS_SR_RB
See <file:Documentation/sh/register-banks.txt> for further
information on SR.RB and register banking in the kernel in general.
config CPU_HAS_PTEA
bool
endmenu
menu "Timer support"
@ -364,10 +400,25 @@ depends on !GENERIC_TIME
config SH_TMU
bool "TMU timer support"
depends on CPU_SH3 || CPU_SH4
default y
help
This enables the use of the TMU as the system timer.
config SH_CMT
bool "CMT timer support"
depends on CPU_SH2
default y
help
This enables the use of the CMT as the system timer.
config SH_MTU2
bool "MTU2 timer support"
depends on CPU_SH2A
default n
help
This enables the use of the MTU2 as the system timer.
endmenu
source "arch/sh/boards/renesas/hs7751rvoip/Kconfig"
@ -376,19 +427,52 @@ source "arch/sh/boards/renesas/rts7751r2d/Kconfig"
source "arch/sh/boards/renesas/r7780rp/Kconfig"
config SH_TIMER_IRQ
int
default "28" if CPU_SUBTYPE_SH7780
default "86" if CPU_SUBTYPE_SH7619
default "140" if CPU_SUBTYPE_SH7206
default "16"
config NO_IDLE_HZ
bool "Dynamic tick timer"
help
Select this option if you want to disable continuous timer ticks
and have them programmed to occur as required. This option saves
power as the system can remain in idle state for longer.
By default dynamic tick is disabled during the boot, and can be
manually enabled with:
echo 1 > /sys/devices/system/timer/timer0/dyn_tick
Alternatively, if you want dynamic tick automatically enabled
during boot, pass "dyntick=enable" via the kernel command string.
Please note that dynamic tick may affect the accuracy of
timekeeping on some platforms depending on the implementation.
config SH_PCLK_FREQ
int "Peripheral clock frequency (in Hz)"
default "27000000" if CPU_SUBTYPE_SH73180 || CPU_SUBTYPE_SH7343
default "31250000" if CPU_SUBTYPE_SH7619
default "33333333" if CPU_SUBTYPE_SH7300 || CPU_SUBTYPE_SH7770 || \
CPU_SUBTYPE_SH7760 || CPU_SUBTYPE_SH7705 || \
CPU_SUBTYPE_SH7206
default "50000000" if CPU_SUBTYPE_SH7750 || CPU_SUBTYPE_SH7780
default "60000000" if CPU_SUBTYPE_SH7751
default "33333333" if CPU_SUBTYPE_SH7300 || CPU_SUBTYPE_SH7770 || \
CPU_SUBTYPE_SH7760 || CPU_SUBTYPE_SH7705
default "27000000" if CPU_SUBTYPE_SH73180 || CPU_SUBTYPE_SH7343
default "66000000" if CPU_SUBTYPE_SH4_202
help
This option is used to specify the peripheral clock frequency.
This is necessary for determining the reference clock value on
platforms lacking an RTC.
config SH_CLK_MD
int "CPU Mode Pin Setting"
depends on CPU_SUBTYPE_SH7619 || CPU_SUBTYPE_SH7206
help
MD2 - MD0 Setting.
menu "CPU Frequency scaling"
source "drivers/cpufreq/Kconfig"
@ -421,6 +505,8 @@ config HEARTBEAT
behavior is platform-dependent, but normally the flash frequency is
a hyperbolic function of the 5-minute load average.
source "arch/sh/drivers/Kconfig"
endmenu
config ISA_DMA_API

View File

@ -1,5 +1,9 @@
menu "Kernel hacking"
config TRACE_IRQFLAGS_SUPPORT
bool
default y
source "lib/Kconfig.debug"
config SH_STANDARD_BIOS
@ -17,7 +21,18 @@ config SH_STANDARD_BIOS
config EARLY_SCIF_CONSOLE
bool "Use early SCIF console"
depends on CPU_SH4 || CPU_SH2A && !SH_STANDARD_BIOS
help
This enables an early console using a fixed SCIF port. This can
be used by platforms that are either not running the SH
standard BIOS, or do not wish to use the BIOS callbacks for the
serial I/O.
config EARLY_SCIF_CONSOLE_PORT
hex "SCIF port for early console"
depends on EARLY_SCIF_CONSOLE
default "0xffe00000" if CPU_SUBTYPE_SH7780
default "0xfffe9800" if CPU_SUBTYPE_SH72060
default "0xffe80000" if CPU_SH4
config EARLY_PRINTK
bool "Early printk support"
@ -30,6 +45,11 @@ config EARLY_PRINTK
when the kernel may crash or hang before the serial console is
initialised. If unsure, say N.
On devices that are running SH-IPL and want to keep the port
initialization consistent while not using the BIOS callbacks,
select both the EARLY_SCIF_CONSOLE and SH_STANDARD_BIOS, using
the kernel command line option to toggle back and forth.
config DEBUG_STACKOVERFLOW
bool "Check for stack overflows"
depends on DEBUG_KERNEL

View File

@ -13,10 +13,6 @@
# for "archclean" and "archdep" for cleaning up and making dependencies for
# this architecture
#
cflags-y := -mb
cflags-$(CONFIG_CPU_LITTLE_ENDIAN) := -ml
isa-y := any
isa-$(CONFIG_SH_DSP) := sh
isa-$(CONFIG_CPU_SH2) := sh2
@ -38,13 +34,16 @@ isa-y := $(isa-y)-nofpu
endif
endif
cflags-y += $(call as-option,-Wa$(comma)-isa=$(isa-y),)
cflags-$(CONFIG_CPU_SH2) += -m2
cflags-$(CONFIG_CPU_SH3) += -m3
cflags-$(CONFIG_CPU_SH4) += -m4 \
cflags-$(CONFIG_CPU_SH2) := -m2
cflags-$(CONFIG_CPU_SH3) := -m3
cflags-$(CONFIG_CPU_SH4) := -m4 \
$(call cc-option,-mno-implicit-fp,-m4-nofpu)
cflags-$(CONFIG_CPU_SH4A) += $(call cc-option,-m4a-nofpu,)
cflags-$(CONFIG_CPU_SH4A) := -m4a $(call cc-option,-m4a-nofpu,)
cflags-$(CONFIG_CPU_BIG_ENDIAN) += -mb
cflags-$(CONFIG_CPU_LITTLE_ENDIAN) += -ml
cflags-y += $(call as-option,-Wa$(comma)-isa=$(isa-y),) -ffreestanding
cflags-$(CONFIG_SH_DSP) += -Wa,-dsp
cflags-$(CONFIG_SH_KGDB) += -g
@ -59,7 +58,9 @@ OBJCOPYFLAGS := -O binary -R .note -R .comment -R .stab -R .stabstr -S
# never be used by anyone. Use a board-specific defconfig that has a
# reasonable chance of being current instead.
#
KBUILD_DEFCONFIG := rts7751r2d_defconfig
KBUILD_DEFCONFIG := r7780rp_defconfig
KBUILD_IMAGE := arch/sh/boot/zImage
#
# Choosing incompatible machines durings configuration will result in
@ -109,6 +110,8 @@ machdir-$(CONFIG_SH_SH4202_MICRODEV) := superh/microdev
machdir-$(CONFIG_SH_LANDISK) := landisk
machdir-$(CONFIG_SH_TITAN) := titan
machdir-$(CONFIG_SH_SHMIN) := shmin
machdir-$(CONFIG_SH_7206_SOLUTION_ENGINE) := se/7206
machdir-$(CONFIG_SH_7619_SOLUTION_ENGINE) := se/7619
machdir-$(CONFIG_SH_UNKNOWN) := unknown
incdir-y := $(notdir $(machdir-y))
@ -124,6 +127,7 @@ core-$(CONFIG_HD64465) += arch/sh/cchips/hd6446x/hd64465/
core-$(CONFIG_VOYAGERGX) += arch/sh/cchips/voyagergx/
cpuincdir-$(CONFIG_CPU_SH2) := cpu-sh2
cpuincdir-$(CONFIG_CPU_SH2A) := cpu-sh2a
cpuincdir-$(CONFIG_CPU_SH3) := cpu-sh3
cpuincdir-$(CONFIG_CPU_SH4) := cpu-sh4

View File

@ -3,4 +3,6 @@
#
obj-y := setup.o io.o irq.o
obj-$(CONFIG_HEARTBEAT) += led.o
obj-$(CONFIG_HEARTBEAT) += led.o
obj-$(CONFIG_PUSH_SWITCH) += psw.o

View File

@ -10,6 +10,7 @@
*/
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <asm/r7780rp.h>

View File

@ -0,0 +1,122 @@
/*
* arch/sh/boards/renesas/r7780rp/psw.c
*
* push switch support for RDBRP-1/RDBREVRP-1 debug boards.
*
* Copyright (C) 2006 Paul Mundt
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#include <linux/io.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <asm/mach/r7780rp.h>
#include <asm/push-switch.h>
static irqreturn_t psw_irq_handler(int irq, void *arg)
{
struct platform_device *pdev = arg;
struct push_switch *psw = platform_get_drvdata(pdev);
struct push_switch_platform_info *psw_info = pdev->dev.platform_data;
unsigned int l, mask;
int ret = 0;
l = ctrl_inw(PA_DBSW);
/* Nothing to do if there's no state change */
if (psw->state) {
ret = 1;
goto out;
}
mask = l & 0x70;
/* Figure out who raised it */
if (mask & (1 << psw_info->bit)) {
psw->state = !!(mask & (1 << psw_info->bit));
if (psw->state) /* debounce */
mod_timer(&psw->debounce, jiffies + 50);
ret = 1;
}
out:
/* Clear the switch IRQs */
l |= (0x7 << 12);
ctrl_outw(l, PA_DBSW);
return IRQ_RETVAL(ret);
}
static struct resource psw_resources[] = {
[0] = {
.start = IRQ_PSW,
.flags = IORESOURCE_IRQ,
},
};
static struct push_switch_platform_info s2_platform_data = {
.name = "s2",
.bit = 6,
.irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
IRQF_SHARED,
.irq_handler = psw_irq_handler,
};
static struct platform_device s2_switch_device = {
.name = "push-switch",
.id = 0,
.num_resources = ARRAY_SIZE(psw_resources),
.resource = psw_resources,
.dev = {
.platform_data = &s2_platform_data,
},
};
static struct push_switch_platform_info s3_platform_data = {
.name = "s3",
.bit = 5,
.irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
IRQF_SHARED,
.irq_handler = psw_irq_handler,
};
static struct platform_device s3_switch_device = {
.name = "push-switch",
.id = 1,
.num_resources = ARRAY_SIZE(psw_resources),
.resource = psw_resources,
.dev = {
.platform_data = &s3_platform_data,
},
};
static struct push_switch_platform_info s4_platform_data = {
.name = "s4",
.bit = 4,
.irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
IRQF_SHARED,
.irq_handler = psw_irq_handler,
};
static struct platform_device s4_switch_device = {
.name = "push-switch",
.id = 2,
.num_resources = ARRAY_SIZE(psw_resources),
.resource = psw_resources,
.dev = {
.platform_data = &s4_platform_data,
},
};
static struct platform_device *psw_devices[] = {
&s2_switch_device, &s3_switch_device, &s4_switch_device,
};
static int __init psw_init(void)
{
return platform_add_devices(psw_devices, ARRAY_SIZE(psw_devices));
}
module_init(psw_init);

View File

@ -44,8 +44,37 @@ static struct platform_device m66596_usb_host_device = {
.resource = m66596_usb_host_resources,
};
static struct resource cf_ide_resources[] = {
[0] = {
.start = 0x1f0,
.end = 0x1f0 + 8,
.flags = IORESOURCE_IO,
},
[1] = {
.start = 0x1f0 + 0x206,
.end = 0x1f0 + 8 + 0x206 + 8,
.flags = IORESOURCE_IO,
},
[2] = {
#ifdef CONFIG_SH_R7780MP
.start = 1,
#else
.start = 4,
#endif
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device cf_ide_device = {
.name = "pata_platform",
.id = -1,
.num_resources = ARRAY_SIZE(cf_ide_resources),
.resource = cf_ide_resources,
};
static struct platform_device *r7780rp_devices[] __initdata = {
&m66596_usb_host_device,
&cf_ide_device,
};
static int __init r7780rp_devices_setup(void)

View File

@ -0,0 +1,7 @@
#
# Makefile for the 7206 SolutionEngine specific parts of the kernel
#
obj-y := setup.o io.o irq.o
obj-$(CONFIG_HEARTBEAT) += led.o

View File

@ -0,0 +1,123 @@
/* $Id: io.c,v 1.5 2004/02/22 23:08:43 kkojima Exp $
*
* linux/arch/sh/boards/se/7206/io.c
*
* Copyright (C) 2006 Yoshinori Sato
*
* I/O routine for Hitachi 7206 SolutionEngine.
*
*/
#include <linux/kernel.h>
#include <linux/types.h>
#include <asm/io.h>
#include <asm/se7206.h>
static inline void delay(void)
{
ctrl_inw(0x20000000); /* P2 ROM Area */
}
/* MS7750 requires special versions of in*, out* routines, since
PC-like io ports are located at upper half byte of 16-bit word which
can be accessed only with 16-bit wide. */
static inline volatile __u16 *
port2adr(unsigned int port)
{
if (port >= 0x2000)
return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000));
else if (port >= 0x300 || port < 0x310)
return (volatile __u16 *) (PA_SMSC + (port - 0x300));
}
unsigned char se7206_inb(unsigned long port)
{
return (*port2adr(port))&0xff;
}
unsigned char se7206_inb_p(unsigned long port)
{
unsigned long v;
v = (*port2adr(port))&0xff;
delay();
return v;
}
unsigned short se7206_inw(unsigned long port)
{
return *port2adr(port);;
}
unsigned int se7206_inl(unsigned long port)
{
maybebadio(port);
return 0;
}
void se7206_outb(unsigned char value, unsigned long port)
{
*(port2adr(port)) = value;
}
void se7206_outb_p(unsigned char value, unsigned long port)
{
*(port2adr(port)) = value;
delay();
}
void se7206_outw(unsigned short value, unsigned long port)
{
*port2adr(port) = value;
}
void se7206_outl(unsigned int value, unsigned long port)
{
maybebadio(port);
}
void se7206_insb(unsigned long port, void *addr, unsigned long count)
{
volatile __u16 *p = port2adr(port);
__u8 *ap = addr;
while (count--)
*ap++ = *p;
}
void se7206_insw(unsigned long port, void *addr, unsigned long count)
{
volatile __u16 *p = port2adr(port);
__u16 *ap = addr;
while (count--)
*ap++ = *p;
}
void se7206_insl(unsigned long port, void *addr, unsigned long count)
{
maybebadio(port);
}
void se7206_outsb(unsigned long port, const void *addr, unsigned long count)
{
volatile __u16 *p = port2adr(port);
const __u8 *ap = addr;
while (count--)
*p = *ap++;
}
void se7206_outsw(unsigned long port, const void *addr, unsigned long count)
{
volatile __u16 *p = port2adr(port);
const __u16 *ap = addr;
while (count--)
*p = *ap++;
}
void se7206_outsl(unsigned long port, const void *addr, unsigned long count)
{
maybebadio(port);
}

View File

@ -0,0 +1,139 @@
/*
* linux/arch/sh/boards/se/7206/irq.c
*
* Copyright (C) 2005,2006 Yoshinori Sato
*
* Hitachi SolutionEngine Support.
*
*/
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <asm/se7206.h>
#define INTSTS0 0x31800000
#define INTSTS1 0x31800002
#define INTMSK0 0x31800004
#define INTMSK1 0x31800006
#define INTSEL 0x31800008
static void disable_se7206_irq(unsigned int irq)
{
unsigned short val;
unsigned short mask = 0xffff ^ (0x0f << 4 * (3 - (IRQ0_IRQ - irq)));
unsigned short msk0,msk1;
/* Set the priority in IPR to 0 */
val = ctrl_inw(INTC_IPR01);
val &= mask;
ctrl_outw(val, INTC_IPR01);
/* FPGA mask set */
msk0 = ctrl_inw(INTMSK0);
msk1 = ctrl_inw(INTMSK1);
switch (irq) {
case IRQ0_IRQ:
msk0 |= 0x0010;
break;
case IRQ1_IRQ:
msk0 |= 0x000f;
break;
case IRQ2_IRQ:
msk0 |= 0x0f00;
msk1 |= 0x00ff;
break;
}
ctrl_outw(msk0, INTMSK0);
ctrl_outw(msk1, INTMSK1);
}
static void enable_se7206_irq(unsigned int irq)
{
unsigned short val;
unsigned short value = (0x0001 << 4 * (3 - (IRQ0_IRQ - irq)));
unsigned short msk0,msk1;
/* Set priority in IPR back to original value */
val = ctrl_inw(INTC_IPR01);
val |= value;
ctrl_outw(val, INTC_IPR01);
/* FPGA mask reset */
msk0 = ctrl_inw(INTMSK0);
msk1 = ctrl_inw(INTMSK1);
switch (irq) {
case IRQ0_IRQ:
msk0 &= ~0x0010;
break;
case IRQ1_IRQ:
msk0 &= ~0x000f;
break;
case IRQ2_IRQ:
msk0 &= ~0x0f00;
msk1 &= ~0x00ff;
break;
}
ctrl_outw(msk0, INTMSK0);
ctrl_outw(msk1, INTMSK1);
}
static void eoi_se7206_irq(unsigned int irq)
{
unsigned short sts0,sts1;
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
enable_se7206_irq(irq);
/* FPGA isr clear */
sts0 = ctrl_inw(INTSTS0);
sts1 = ctrl_inw(INTSTS1);
switch (irq) {
case IRQ0_IRQ:
sts0 &= ~0x0010;
break;
case IRQ1_IRQ:
sts0 &= ~0x000f;
break;
case IRQ2_IRQ:
sts0 &= ~0x0f00;
sts1 &= ~0x00ff;
break;
}
ctrl_outw(sts0, INTSTS0);
ctrl_outw(sts1, INTSTS1);
}
static struct irq_chip se7206_irq_chip __read_mostly = {
.name = "SE7206-FPGA-IRQ",
.mask = disable_se7206_irq,
.unmask = enable_se7206_irq,
.mask_ack = disable_se7206_irq,
.eoi = eoi_se7206_irq,
};
static void make_se7206_irq(unsigned int irq)
{
disable_irq_nosync(irq);
set_irq_chip_and_handler_name(irq, &se7206_irq_chip,
handle_level_irq, "level");
disable_se7206_irq(irq);
}
/*
* Initialize IRQ setting
*/
void __init init_se7206_IRQ(void)
{
make_se7206_irq(IRQ0_IRQ); /* SMC91C111 */
make_se7206_irq(IRQ1_IRQ); /* ATA */
make_se7206_irq(IRQ3_IRQ); /* SLOT / PCM */
ctrl_outw(inw(INTC_ICR1) | 0x000b ,INTC_ICR1 ) ; /* ICR1 */
/* FPGA System register setup*/
ctrl_outw(0x0000,INTSTS0); /* Clear INTSTS0 */
ctrl_outw(0x0000,INTSTS1); /* Clear INTSTS1 */
/* IRQ0=LAN, IRQ1=ATA, IRQ3=SLT,PCM */
ctrl_outw(0x0001,INTSEL);
}

View File

@ -0,0 +1,57 @@
/*
* linux/arch/sh/kernel/led_se.c
*
* Copyright (C) 2000 Stuart Menefy <stuart.menefy@st.com>
*
* May be copied or modified under the terms of the GNU General Public
* License. See linux/COPYING for more information.
*
* This file contains Solution Engine specific LED code.
*/
#include <linux/config.h>
#include <asm/se7206.h>
#ifdef CONFIG_HEARTBEAT
#include <linux/sched.h>
/* Cycle the LED's in the clasic Knightrider/Sun pattern */
void heartbeat_se(void)
{
static unsigned int cnt = 0, period = 0;
volatile unsigned short* p = (volatile unsigned short*)PA_LED;
static unsigned bit = 0, up = 1;
cnt += 1;
if (cnt < period) {
return;
}
cnt = 0;
/* Go through the points (roughly!):
* f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
*/
period = 110 - ( (300<<FSHIFT)/
((avenrun[0]/5) + (3<<FSHIFT)) );
if (up) {
if (bit == 7) {
bit--;
up=0;
} else {
bit ++;
}
} else {
if (bit == 0) {
bit++;
up=1;
} else {
bit--;
}
}
*p = 1<<(bit+8);
}
#endif /* CONFIG_HEARTBEAT */

View File

@ -0,0 +1,79 @@
/*
*
* linux/arch/sh/boards/se/7206/setup.c
*
* Copyright (C) 2006 Yoshinori Sato
*
* Hitachi 7206 SolutionEngine Support.
*
*/
#include <linux/init.h>
#include <linux/platform_device.h>
#include <asm/se7206.h>
#include <asm/io.h>
#include <asm/machvec.h>
static struct resource smc91x_resources[] = {
[0] = {
.start = 0x300,
.end = 0x300 + 0x020 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = 64,
.end = 64,
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device smc91x_device = {
.name = "smc91x",
.id = -1,
.num_resources = ARRAY_SIZE(smc91x_resources),
.resource = smc91x_resources,
};
static int __init se7206_devices_setup(void)
{
return platform_device_register(&smc91x_device);
}
__initcall(se7206_devices_setup);
void heartbeat_se(void);
/*
* The Machine Vector
*/
struct sh_machine_vector mv_se __initmv = {
.mv_name = "SolutionEngine",
.mv_nr_irqs = 256,
.mv_inb = se7206_inb,
.mv_inw = se7206_inw,
.mv_inl = se7206_inl,
.mv_outb = se7206_outb,
.mv_outw = se7206_outw,
.mv_outl = se7206_outl,
.mv_inb_p = se7206_inb_p,
.mv_inw_p = se7206_inw,
.mv_inl_p = se7206_inl,
.mv_outb_p = se7206_outb_p,
.mv_outw_p = se7206_outw,
.mv_outl_p = se7206_outl,
.mv_insb = se7206_insb,
.mv_insw = se7206_insw,
.mv_insl = se7206_insl,
.mv_outsb = se7206_outsb,
.mv_outsw = se7206_outsw,
.mv_outsl = se7206_outsl,
.mv_init_irq = init_se7206_IRQ,
#ifdef CONFIG_HEARTBEAT
.mv_heartbeat = heartbeat_se,
#endif
};
ALIAS_MV(se)

View File

@ -0,0 +1,5 @@
#
# Makefile for the 7619 SolutionEngine specific parts of the kernel
#
obj-y := setup.o io.o

View File

@ -0,0 +1,102 @@
/*
*
* linux/arch/sh/boards/se/7619/io.c
*
* Copyright (C) 2006 Yoshinori Sato
*
* I/O routine for Hitachi 7619 SolutionEngine.
*
*/
#include <linux/kernel.h>
#include <linux/types.h>
#include <asm/io.h>
#include <asm/se7619.h>
#include <asm/irq.h>
/* FIXME: M3A-ZAB7 Compact Flash Slot support */
static inline void delay(void)
{
ctrl_inw(0xa0000000); /* Uncached ROM area (P2) */
}
#define badio(name,port) \
printk("bad I/O operation (%s) for port 0x%lx at 0x%08x\n", \
#name, (port), (__u32) __builtin_return_address(0))
unsigned char se7619___inb(unsigned long port)
{
badio(inb, port);
return 0;
}
unsigned char se7619___inb_p(unsigned long port)
{
badio(inb_p, port);
delay();
return 0;
}
unsigned short se7619___inw(unsigned long port)
{
badio(inw, port);
return 0;
}
unsigned int se7619___inl(unsigned long port)
{
badio(inl, port);
return 0;
}
void se7619___outb(unsigned char value, unsigned long port)
{
badio(outb, port);
}
void se7619___outb_p(unsigned char value, unsigned long port)
{
badio(outb_p, port);
delay();
}
void se7619___outw(unsigned short value, unsigned long port)
{
badio(outw, port);
}
void se7619___outl(unsigned int value, unsigned long port)
{
badio(outl, port);
}
void se7619___insb(unsigned long port, void *addr, unsigned long count)
{
badio(inw, port);
}
void se7619___insw(unsigned long port, void *addr, unsigned long count)
{
badio(inw, port);
}
void se7619___insl(unsigned long port, void *addr, unsigned long count)
{
badio(insl, port);
}
void se7619___outsb(unsigned long port, const void *addr, unsigned long count)
{
badio(insl, port);
}
void se7619___outsw(unsigned long port, const void *addr, unsigned long count)
{
badio(insl, port);
}
void se7619___outsl(unsigned long port, const void *addr, unsigned long count)
{
badio(outsw, port);
}

View File

@ -0,0 +1,43 @@
/*
* arch/sh/boards/se/7619/setup.c
*
* Copyright (C) 2006 Yoshinori Sato
*
* Hitachi SH7619 SolutionEngine Support.
*/
#include <linux/init.h>
#include <linux/platform_device.h>
#include <asm/io.h>
#include <asm/se7619.h>
#include <asm/machvec.h>
/*
* The Machine Vector
*/
struct sh_machine_vector mv_se __initmv = {
.mv_name = "SolutionEngine",
.mv_nr_irqs = 108,
.mv_inb = se7619___inb,
.mv_inw = se7619___inw,
.mv_inl = se7619___inl,
.mv_outb = se7619___outb,
.mv_outw = se7619___outw,
.mv_outl = se7619___outl,
.mv_inb_p = se7619___inb_p,
.mv_inw_p = se7619___inw,
.mv_inl_p = se7619___inl,
.mv_outb_p = se7619___outb_p,
.mv_outw_p = se7619___outw,
.mv_outl_p = se7619___outl,
.mv_insb = se7619___insb,
.mv_insw = se7619___insw,
.mv_insl = se7619___insl,
.mv_outsb = se7619___outsb,
.mv_outsw = se7619___outsw,
.mv_outsl = se7619___outsl,
};
ALIAS_MV(se)

View File

@ -1,26 +1,30 @@
/*
* Setup for Titan
* arch/sh/boards/titan/setup.c - Setup for Titan
*
* Copyright (C) 2006 Jamie Lenehan
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#include <linux/init.h>
#include <asm/irq.h>
#include <linux/irq.h>
#include <asm/titan.h>
#include <asm/io.h>
extern void __init pcibios_init_platform(void);
static struct ipr_data titan_ipr_map[] = {
{ TITAN_IRQ_WAN, IRL0_IPR_ADDR, IRL0_IPR_POS, IRL0_PRIORITY },
{ TITAN_IRQ_LAN, IRL1_IPR_ADDR, IRL1_IPR_POS, IRL1_PRIORITY },
{ TITAN_IRQ_MPCIA, IRL2_IPR_ADDR, IRL2_IPR_POS, IRL2_PRIORITY },
{ TITAN_IRQ_USB, IRL3_IPR_ADDR, IRL3_IPR_POS, IRL3_PRIORITY },
/* IRQ, IPR idx, shift, prio */
{ TITAN_IRQ_WAN, 3, 12, 8 }, /* eth0 (WAN) */
{ TITAN_IRQ_LAN, 3, 8, 8 }, /* eth1 (LAN) */
{ TITAN_IRQ_MPCIA, 3, 4, 8 }, /* mPCI A (top) */
{ TITAN_IRQ_USB, 3, 0, 8 }, /* mPCI B (bottom), USB */
};
static void __init init_titan_irq(void)
{
/* enable individual interrupt mode for externals */
ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);
ipr_irq_enable_irlm();
/* register ipr irqs */
make_ipr_irq(titan_ipr_map, ARRAY_SIZE(titan_ipr_map));
}
@ -47,6 +51,5 @@ struct sh_machine_vector mv_titan __initmv = {
.mv_ioport_map = titan_ioport_map,
.mv_init_irq = init_titan_irq,
.mv_init_pci = pcibios_init_platform,
};
ALIAS_MV(titan)

View File

@ -12,6 +12,7 @@
*/
#include <asm/uaccess.h>
#include <asm/addrspace.h>
#ifdef CONFIG_SH_STANDARD_BIOS
#include <asm/sh_bios.h>
#endif
@ -228,7 +229,7 @@ long* stack_start = &user_stack[STACK_SIZE];
void decompress_kernel(void)
{
output_data = 0;
output_ptr = (unsigned long)&_text+0x20001000;
output_ptr = P2SEGADDR((unsigned long)&_text+0x1000);
free_mem_ptr = (unsigned long)&_end;
free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;

View File

@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.19-rc3
# Tue Oct 31 12:32:06 2006
# Linux kernel version: 2.6.19
# Wed Dec 6 11:59:38 2006
#
CONFIG_SUPERH=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
@ -11,6 +11,8 @@ CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
# CONFIG_GENERIC_TIME is not set
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
@ -37,6 +39,7 @@ CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
# CONFIG_SYSFS_DEPRECATED is not set
# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
@ -118,6 +121,8 @@ CONFIG_SH_R7780RP=y
# CONFIG_SH_LANDISK is not set
# CONFIG_SH_TITAN is not set
# CONFIG_SH_SHMIN is not set
# CONFIG_SH_7206_SOLUTION_ENGINE is not set
# CONFIG_SH_7619_SOLUTION_ENGINE is not set
# CONFIG_SH_UNKNOWN is not set
#
@ -130,6 +135,12 @@ CONFIG_CPU_SH4A=y
# SH-2 Processor Support
#
# CONFIG_CPU_SUBTYPE_SH7604 is not set
# CONFIG_CPU_SUBTYPE_SH7619 is not set
#
# SH-2A Processor Support
#
# CONFIG_CPU_SUBTYPE_SH7206 is not set
#
# SH-3 Processor Support
@ -165,6 +176,7 @@ CONFIG_CPU_SH4A=y
#
# CONFIG_CPU_SUBTYPE_SH7770 is not set
CONFIG_CPU_SUBTYPE_SH7780=y
# CONFIG_CPU_SUBTYPE_SH7785 is not set
#
# SH4AL-DSP Processor Support
@ -181,8 +193,14 @@ CONFIG_MEMORY_START=0x08000000
CONFIG_MEMORY_SIZE=0x08000000
# CONFIG_32BIT is not set
CONFIG_VSYSCALL=y
CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_8KB is not set
# CONFIG_PAGE_SIZE_64KB is not set
CONFIG_HUGETLB_PAGE_SIZE_64K=y
# CONFIG_HUGETLB_PAGE_SIZE_256K is not set
# CONFIG_HUGETLB_PAGE_SIZE_1MB is not set
# CONFIG_HUGETLB_PAGE_SIZE_4MB is not set
# CONFIG_HUGETLB_PAGE_SIZE_64MB is not set
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
# CONFIG_DISCONTIGMEM_MANUAL is not set
@ -204,12 +222,14 @@ CONFIG_SPLIT_PTLOCK_CPUS=4
# Processor features
#
CONFIG_CPU_LITTLE_ENDIAN=y
# CONFIG_CPU_BIG_ENDIAN is not set
CONFIG_SH_FPU=y
# CONFIG_SH_DSP is not set
CONFIG_SH_STORE_QUEUES=y
CONFIG_CPU_HAS_INTEVT=y
CONFIG_CPU_HAS_INTC2_IRQ=y
CONFIG_CPU_HAS_SR_RB=y
CONFIG_CPU_HAS_PTEA=y
#
# Timer support
@ -220,6 +240,8 @@ CONFIG_SH_TMU=y
# R7780RP options
#
CONFIG_SH_R7780MP=y
CONFIG_SH_TIMER_IRQ=28
CONFIG_NO_IDLE_HZ=y
CONFIG_SH_PCLK_FREQ=32000000
#
@ -237,6 +259,11 @@ CONFIG_SH_PCLK_FREQ=32000000
#
# CONFIG_HD6446X_SERIES is not set
#
# Additional SuperH Device Drivers
#
CONFIG_PUSH_SWITCH=y
#
# Kernel features
#
@ -244,7 +271,7 @@ CONFIG_SH_PCLK_FREQ=32000000
CONFIG_HZ_250=y
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
# CONFIG_KEXEC is not set
CONFIG_KEXEC=y
# CONFIG_SMP is not set
# CONFIG_PREEMPT_NONE is not set
# CONFIG_PREEMPT_VOLUNTARY is not set
@ -278,10 +305,7 @@ CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
#
# PCI Hotplug Support
#
CONFIG_HOTPLUG_PCI=y
# CONFIG_HOTPLUG_PCI_FAKE is not set
# CONFIG_HOTPLUG_PCI_CPCI is not set
# CONFIG_HOTPLUG_PCI_SHPC is not set
# CONFIG_HOTPLUG_PCI is not set
#
# Executable file formats
@ -341,6 +365,7 @@ CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
# CONFIG_IPV6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
@ -556,6 +581,7 @@ CONFIG_SATA_SIL=y
# CONFIG_PATA_IT821X is not set
# CONFIG_PATA_JMICRON is not set
# CONFIG_PATA_TRIFLEX is not set
# CONFIG_PATA_MARVELL is not set
# CONFIG_PATA_MPIIX is not set
# CONFIG_PATA_OLDPIIX is not set
# CONFIG_PATA_NETCELL is not set
@ -572,6 +598,7 @@ CONFIG_SATA_SIL=y
# CONFIG_PATA_SIS is not set
# CONFIG_PATA_VIA is not set
# CONFIG_PATA_WINBOND is not set
CONFIG_PATA_PLATFORM=y
#
# Multi-device support (RAID and LVM)
@ -688,6 +715,7 @@ CONFIG_R8169=y
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
#
# Token Ring devices
@ -830,10 +858,6 @@ CONFIG_HW_RANDOM=y
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
#
# Ftape, the floppy tape device driver
#
# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
@ -1020,7 +1044,7 @@ CONFIG_INOTIFY_USER=y
CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
# CONFIG_FUSE_FS is not set
CONFIG_FUSE_FS=m
#
# CD-ROM/DVD Filesystems
@ -1052,7 +1076,7 @@ CONFIG_TMPFS=y
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
CONFIG_CONFIGFS_FS=m
#
# Miscellaneous filesystems
@ -1153,28 +1177,33 @@ CONFIG_NLS_ISO8859_1=y
#
# Profiling support
#
# CONFIG_PROFILING is not set
CONFIG_PROFILING=y
CONFIG_OPROFILE=m
#
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
CONFIG_PRINTK_TIME=y
CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_MAGIC_SYSRQ is not set
CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=14
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB is not set
CONFIG_DEBUG_SPINLOCK=y
# CONFIG_DEBUG_PREEMPT is not set
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_MUTEXES is not set
# CONFIG_DEBUG_RWSEMS is not set
# CONFIG_DEBUG_LOCK_ALLOC is not set
# CONFIG_PROVE_LOCKING is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set
# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_DEBUG_INFO is not set
CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_FS=y
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_LIST is not set
@ -1184,7 +1213,7 @@ CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_SH_STANDARD_BIOS is not set
# CONFIG_EARLY_SCIF_CONSOLE is not set
# CONFIG_DEBUG_STACKOVERFLOW is not set
CONFIG_DEBUG_STACKOVERFLOW=y
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_4KSTACKS is not set
# CONFIG_KGDB is not set

View File

@ -0,0 +1,826 @@
#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.19-rc4
# Sun Nov 5 16:20:10 2006
#
CONFIG_SUPERH=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
# CONFIG_GENERIC_TIME is not set
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
#
# General setup
#
CONFIG_LOCALVERSION=""
# CONFIG_LOCALVERSION_AUTO is not set
# CONFIG_SYSVIPC is not set
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
CONFIG_UID16=y
# CONFIG_SYSCTL_SYSCALL is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
# CONFIG_HOTPLUG is not set
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
# CONFIG_FUTEX is not set
# CONFIG_EPOLL is not set
CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_TINY_SHMEM=y
CONFIG_BASE_SMALL=0
# CONFIG_SLOB is not set
#
# Loadable module support
#
# CONFIG_MODULES is not set
#
# Block layer
#
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_LSF is not set
#
# IO Schedulers
#
CONFIG_IOSCHED_NOOP=y
# CONFIG_IOSCHED_AS is not set
# CONFIG_IOSCHED_DEADLINE is not set
# CONFIG_IOSCHED_CFQ is not set
# CONFIG_DEFAULT_AS is not set
# CONFIG_DEFAULT_DEADLINE is not set
# CONFIG_DEFAULT_CFQ is not set
CONFIG_DEFAULT_NOOP=y
CONFIG_DEFAULT_IOSCHED="noop"
#
# System type
#
# CONFIG_SH_SOLUTION_ENGINE is not set
# CONFIG_SH_7751_SOLUTION_ENGINE is not set
# CONFIG_SH_7300_SOLUTION_ENGINE is not set
# CONFIG_SH_7343_SOLUTION_ENGINE is not set
# CONFIG_SH_73180_SOLUTION_ENGINE is not set
# CONFIG_SH_7751_SYSTEMH is not set
# CONFIG_SH_HP6XX is not set
# CONFIG_SH_EC3104 is not set
# CONFIG_SH_SATURN is not set
# CONFIG_SH_DREAMCAST is not set
# CONFIG_SH_BIGSUR is not set
# CONFIG_SH_MPC1211 is not set
# CONFIG_SH_SH03 is not set
# CONFIG_SH_SECUREEDGE5410 is not set
# CONFIG_SH_HS7751RVOIP is not set
# CONFIG_SH_7710VOIPGW is not set
# CONFIG_SH_RTS7751R2D is not set
# CONFIG_SH_R7780RP is not set
# CONFIG_SH_EDOSK7705 is not set
# CONFIG_SH_SH4202_MICRODEV is not set
# CONFIG_SH_LANDISK is not set
# CONFIG_SH_TITAN is not set
# CONFIG_SH_SHMIN is not set
CONFIG_SH_7206_SOLUTION_ENGINE=y
# CONFIG_SH_7619_SOLUTION_ENGINE is not set
# CONFIG_SH_UNKNOWN is not set
#
# Processor selection
#
CONFIG_CPU_SH2=y
CONFIG_CPU_SH2A=y
#
# SH-2 Processor Support
#
# CONFIG_CPU_SUBTYPE_SH7604 is not set
# CONFIG_CPU_SUBTYPE_SH7619 is not set
#
# SH-2A Processor Support
#
CONFIG_CPU_SUBTYPE_SH7206=y
#
# SH-3 Processor Support
#
# CONFIG_CPU_SUBTYPE_SH7300 is not set
# CONFIG_CPU_SUBTYPE_SH7705 is not set
# CONFIG_CPU_SUBTYPE_SH7706 is not set
# CONFIG_CPU_SUBTYPE_SH7707 is not set
# CONFIG_CPU_SUBTYPE_SH7708 is not set
# CONFIG_CPU_SUBTYPE_SH7709 is not set
# CONFIG_CPU_SUBTYPE_SH7710 is not set
#
# SH-4 Processor Support
#
# CONFIG_CPU_SUBTYPE_SH7750 is not set
# CONFIG_CPU_SUBTYPE_SH7091 is not set
# CONFIG_CPU_SUBTYPE_SH7750R is not set
# CONFIG_CPU_SUBTYPE_SH7750S is not set
# CONFIG_CPU_SUBTYPE_SH7751 is not set
# CONFIG_CPU_SUBTYPE_SH7751R is not set
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
#
# ST40 Processor Support
#
# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
#
# SH-4A Processor Support
#
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
#
# SH4AL-DSP Processor Support
#
# CONFIG_CPU_SUBTYPE_SH73180 is not set
# CONFIG_CPU_SUBTYPE_SH7343 is not set
#
# Memory management options
#
CONFIG_PAGE_OFFSET=0x00000000
CONFIG_MEMORY_START=0x0c000000
CONFIG_MEMORY_SIZE=0x02000000
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
# CONFIG_DISCONTIGMEM_MANUAL is not set
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
#
# Cache configuration
#
# CONFIG_SH_DIRECT_MAPPED is not set
# CONFIG_SH_WRITETHROUGH is not set
# CONFIG_SH_OCRAM is not set
#
# Processor features
#
# CONFIG_CPU_LITTLE_ENDIAN is not set
# CONFIG_SH_FPU is not set
# CONFIG_SH_FPU_EMU is not set
# CONFIG_SH_DSP is not set
#
# Timer support
#
CONFIG_SH_CMT=y
# CONFIG_SH_MTU2 is not set
CONFIG_SH_PCLK_FREQ=33333333
CONFIG_SH_CLK_MD=6
#
# CPU Frequency scaling
#
# CONFIG_CPU_FREQ is not set
#
# DMA support
#
# CONFIG_SH_DMA is not set
#
# Companion Chips
#
# CONFIG_HD6446X_SERIES is not set
#
# Kernel features
#
CONFIG_HZ_100=y
# CONFIG_HZ_250 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=100
# CONFIG_KEXEC is not set
# CONFIG_SMP is not set
CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
#
# Boot options
#
CONFIG_ZERO_PAGE_OFFSET=0x00001000
CONFIG_BOOT_LINK_OFFSET=0x00800000
# CONFIG_UBC_WAKEUP is not set
# CONFIG_CMDLINE_BOOL is not set
#
# Bus options
#
# CONFIG_PCI is not set
#
# PCCARD (PCMCIA/CardBus) support
#
#
# PCI Hotplug Support
#
#
# Executable file formats
#
CONFIG_BINFMT_FLAT=y
CONFIG_BINFMT_ZFLAT=y
# CONFIG_BINFMT_SHARED_FLAT is not set
# CONFIG_BINFMT_MISC is not set
#
# Power management options (EXPERIMENTAL)
#
# CONFIG_PM is not set
#
# Networking
#
CONFIG_NET=y
#
# Networking options
#
# CONFIG_NETDEBUG is not set
# CONFIG_PACKET is not set
# CONFIG_UNIX is not set
CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
# CONFIG_XFRM_SUB_POLICY is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
# CONFIG_IP_ADVANCED_ROUTER is not set
CONFIG_IP_FIB_HASH=y
# CONFIG_IP_PNP is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
# CONFIG_ARPD is not set
# CONFIG_SYN_COOKIES is not set
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
# CONFIG_INET_XFRM_TUNNEL is not set
# CONFIG_INET_TUNNEL is not set
CONFIG_INET_XFRM_MODE_TRANSPORT=y
CONFIG_INET_XFRM_MODE_TUNNEL=y
CONFIG_INET_XFRM_MODE_BEET=y
# CONFIG_INET_DIAG is not set
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_IPV6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
#
# DCCP Configuration (EXPERIMENTAL)
#
# CONFIG_IP_DCCP is not set
#
# SCTP Configuration (EXPERIMENTAL)
#
# CONFIG_IP_SCTP is not set
#
# TIPC Configuration (EXPERIMENTAL)
#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
#
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
#
# Network testing
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_IEEE80211 is not set
#
# Device Drivers
#
#
# Generic Driver Options
#
# CONFIG_STANDALONE is not set
# CONFIG_PREVENT_FIRMWARE_BUILD is not set
# CONFIG_SYS_HYPERVISOR is not set
#
# Connector - unified userspace <-> kernelspace linker
#
# CONFIG_CONNECTOR is not set
#
# Memory Technology Devices (MTD)
#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_CONCAT is not set
CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_REDBOOT_PARTS=y
CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
# CONFIG_MTD_CMDLINE_PARTS is not set
#
# User Modules And Translation Layers
#
CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
# CONFIG_FTL is not set
# CONFIG_NFTL is not set
# CONFIG_INFTL is not set
# CONFIG_RFD_FTL is not set
# CONFIG_SSFDC is not set
#
# RAM/ROM/Flash chip drivers
#
CONFIG_MTD_CFI=y
# CONFIG_MTD_JEDECPROBE is not set
CONFIG_MTD_GEN_PROBE=y
# CONFIG_MTD_CFI_ADV_OPTIONS is not set
CONFIG_MTD_MAP_BANK_WIDTH_1=y
CONFIG_MTD_MAP_BANK_WIDTH_2=y
CONFIG_MTD_MAP_BANK_WIDTH_4=y
# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
CONFIG_MTD_CFI_I1=y
CONFIG_MTD_CFI_I2=y
# CONFIG_MTD_CFI_I4 is not set
# CONFIG_MTD_CFI_I8 is not set
# CONFIG_MTD_CFI_INTELEXT is not set
CONFIG_MTD_CFI_AMDSTD=y
# CONFIG_MTD_CFI_STAA is not set
CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
# CONFIG_MTD_OBSOLETE_CHIPS is not set
#
# Mapping drivers for chip access
#
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
CONFIG_MTD_PHYSMAP=y
CONFIG_MTD_PHYSMAP_START=0x20000000
CONFIG_MTD_PHYSMAP_LEN=0x1000000
CONFIG_MTD_PHYSMAP_BANKWIDTH=4
# CONFIG_MTD_SOLUTIONENGINE is not set
# CONFIG_MTD_UCLINUX is not set
# CONFIG_MTD_PLATRAM is not set
#
# Self-contained MTD device drivers
#
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
# CONFIG_MTD_BLOCK2MTD is not set
#
# Disk-On-Chip Device Drivers
#
# CONFIG_MTD_DOC2000 is not set
# CONFIG_MTD_DOC2001 is not set
# CONFIG_MTD_DOC2001PLUS is not set
#
# NAND Flash Device Drivers
#
# CONFIG_MTD_NAND is not set
#
# OneNAND Flash Device Drivers
#
# CONFIG_MTD_ONENAND is not set
#
# Parallel port support
#
# CONFIG_PARPORT is not set
#
# Plug and Play support
#
#
# Block devices
#
# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
#
# Misc devices
#
# CONFIG_TIFM_CORE is not set
#
# ATA/ATAPI/MFM/RLL support
#
# CONFIG_IDE is not set
#
# SCSI device support
#
# CONFIG_RAID_ATTRS is not set
# CONFIG_SCSI is not set
# CONFIG_SCSI_NETLINK is not set
#
# Serial ATA (prod) and Parallel ATA (experimental) drivers
#
# CONFIG_ATA is not set
#
# Multi-device support (RAID and LVM)
#
# CONFIG_MD is not set
#
# Fusion MPT device support
#
# CONFIG_FUSION is not set
#
# IEEE 1394 (FireWire) support
#
#
# I2O device support
#
#
# Network device support
#
# CONFIG_NETDEVICES is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
#
# ISDN subsystem
#
# CONFIG_ISDN is not set
#
# Telephony Support
#
# CONFIG_PHONE is not set
#
# Input device support
#
# CONFIG_INPUT is not set
#
# Hardware I/O ports
#
# CONFIG_SERIO is not set
# CONFIG_GAMEPORT is not set
#
# Character devices
#
# CONFIG_VT is not set
# CONFIG_SERIAL_NONSTANDARD is not set
#
# Serial drivers
#
# CONFIG_SERIAL_8250 is not set
#
# Non-8250 serial port support
#
CONFIG_SERIAL_SH_SCI=y
CONFIG_SERIAL_SH_SCI_NR_UARTS=4
CONFIG_SERIAL_SH_SCI_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_UNIX98_PTYS is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
#
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
#
# Watchdog Cards
#
# CONFIG_WATCHDOG is not set
CONFIG_HW_RANDOM=y
# CONFIG_GEN_RTC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
#
# Ftape, the floppy tape device driver
#
# CONFIG_RAW_DRIVER is not set
#
# TPM devices
#
# CONFIG_TCG_TPM is not set
#
# I2C support
#
# CONFIG_I2C is not set
#
# SPI support
#
# CONFIG_SPI is not set
# CONFIG_SPI_MASTER is not set
#
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
#
# Hardware Monitoring support
#
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
# CONFIG_SENSORS_ABITUGURU is not set
# CONFIG_SENSORS_F71805F is not set
# CONFIG_SENSORS_VT1211 is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
#
# Digital Video Broadcasting Devices
#
# CONFIG_DVB is not set
#
# Graphics support
#
CONFIG_FIRMWARE_EDID=y
# CONFIG_FB is not set
#
# Sound
#
# CONFIG_SOUND is not set
#
# USB support
#
# CONFIG_USB_ARCH_HAS_HCD is not set
# CONFIG_USB_ARCH_HAS_OHCI is not set
# CONFIG_USB_ARCH_HAS_EHCI is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
#
#
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
#
# MMC/SD Card support
#
# CONFIG_MMC is not set
#
# LED devices
#
# CONFIG_NEW_LEDS is not set
#
# LED drivers
#
#
# LED Triggers
#
#
# InfiniBand support
#
#
# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
#
#
# Real Time Clock
#
# CONFIG_RTC_CLASS is not set
#
# DMA Engine support
#
# CONFIG_DMA_ENGINE is not set
#
# DMA Clients
#
#
# DMA Devices
#
#
# File systems
#
CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT3_FS is not set
# CONFIG_EXT4DEV_FS is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
# CONFIG_XFS_FS is not set
# CONFIG_GFS2_FS is not set
# CONFIG_MINIX_FS is not set
CONFIG_ROMFS_FS=y
# CONFIG_INOTIFY is not set
# CONFIG_QUOTA is not set
# CONFIG_DNOTIFY is not set
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
# CONFIG_FUSE_FS is not set
#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
# CONFIG_UDF_FS is not set
#
# DOS/FAT/NT Filesystems
#
# CONFIG_MSDOS_FS is not set
# CONFIG_VFAT_FS is not set
# CONFIG_NTFS_FS is not set
#
# Pseudo filesystems
#
CONFIG_PROC_FS=y
CONFIG_PROC_SYSCTL=y
# CONFIG_SYSFS is not set
# CONFIG_TMPFS is not set
# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
#
# Miscellaneous filesystems
#
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
# CONFIG_HFSPLUS_FS is not set
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
# CONFIG_JFFS_FS is not set
# CONFIG_JFFS2_FS is not set
CONFIG_CRAMFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
#
# Network File Systems
#
# CONFIG_NFS_FS is not set
# CONFIG_NFSD is not set
# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
# CONFIG_9P_FS is not set
#
# Partition Types
#
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
#
# Native Language Support
#
# CONFIG_NLS is not set
#
# Profiling support
#
# CONFIG_PROFILING is not set
#
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_UNWIND_INFO is not set
# CONFIG_HEADERS_CHECK is not set
# CONFIG_SH_STANDARD_BIOS is not set
# CONFIG_EARLY_SCIF_CONSOLE is not set
# CONFIG_KGDB is not set
#
# Security options
#
# CONFIG_KEYS is not set
#
# Cryptographic options
#
# CONFIG_CRYPTO is not set
#
# Library routines
#
CONFIG_CRC_CCITT=y
# CONFIG_CRC16 is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y

View File

@ -0,0 +1,9 @@
menu "Additional SuperH Device Drivers"
config PUSH_SWITCH
tristate "Push switch support"
help
This enables support for the push switch framework, a simple
framework that allows for sysfs driven switch status reporting.
endmenu

View File

@ -5,4 +5,4 @@
obj-$(CONFIG_PCI) += pci/
obj-$(CONFIG_SH_DMA) += dma/
obj-$(CONFIG_SUPERHYWAY) += superhyway/
obj-$(CONFIG_PUSH_SWITCH) += push-switch.o

View File

@ -2,8 +2,8 @@
# Makefile for the SuperH DMA specific kernel interface routines under Linux.
#
obj-y += dma-api.o dma-isa.o
obj-y += dma-api.o
obj-$(CONFIG_ISA_DMA_API) += dma-isa.o
obj-$(CONFIG_SYSFS) += dma-sysfs.o
obj-$(CONFIG_SH_DMA) += dma-sh.o
obj-$(CONFIG_SH_DREAMCAST) += dma-pvr2.o dma-g2.o

View File

@ -11,61 +11,27 @@
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/proc_fs.h>
#include <linux/list.h>
#include <linux/platform_device.h>
#include <linux/mm.h>
#include <asm/dma.h>
DEFINE_SPINLOCK(dma_spin_lock);
static LIST_HEAD(registered_dmac_list);
/*
* A brief note about the reasons for this API as it stands.
*
* For starters, the old ISA DMA API didn't work for us for a number of
* reasons, for one, the vast majority of channels on the SH DMAC are
* dual-address mode only, and both the new and the old DMA APIs are after the
* concept of managing a DMA buffer, which doesn't overly fit this model very
* well. In addition to which, the new API is largely geared at IOMMUs and
* GARTs, and doesn't even support the channel notion very well.
*
* The other thing that's a marginal issue, is the sheer number of random DMA
* engines that are present (ie, in boards like the Dreamcast), some of which
* cascade off of the SH DMAC, and others do not. As such, there was a real
* need for a scalable subsystem that could deal with both single and
* dual-address mode usage, in addition to interoperating with cascaded DMACs.
*
* There really isn't any reason why this needs to be SH specific, though I'm
* not aware of too many other processors (with the exception of some MIPS)
* that have the same concept of a dual address mode, or any real desire to
* actually make use of the DMAC even if such a subsystem were exposed
* elsewhere.
*
* The idea for this was derived from the ARM port, which acted as an excellent
* reference when trying to address these issues.
*
* It should also be noted that the decision to add Yet Another DMA API(tm) to
* the kernel wasn't made easily, and was only decided upon after conferring
* with jejb with regards to the state of the old and new APIs as they applied
* to these circumstances. Philip Blundell was also a great help in figuring
* out some single-address mode DMA semantics that were otherwise rather
* confusing.
*/
struct dma_info *get_dma_info(unsigned int chan)
{
struct dma_info *info;
unsigned int total = 0;
/*
* Look for each DMAC's range to determine who the owner of
* the channel is.
*/
list_for_each_entry(info, &registered_dmac_list, list) {
total += info->nr_channels;
if (chan > total)
if ((chan < info->first_channel_nr) ||
(chan >= info->first_channel_nr + info->nr_channels))
continue;
return info;
@ -73,6 +39,22 @@ struct dma_info *get_dma_info(unsigned int chan)
return NULL;
}
EXPORT_SYMBOL(get_dma_info);
struct dma_info *get_dma_info_by_name(const char *dmac_name)
{
struct dma_info *info;
list_for_each_entry(info, &registered_dmac_list, list) {
if (dmac_name && (strcmp(dmac_name, info->name) != 0))
continue;
else
return info;
}
return NULL;
}
EXPORT_SYMBOL(get_dma_info_by_name);
static unsigned int get_nr_channels(void)
{
@ -91,63 +73,161 @@ static unsigned int get_nr_channels(void)
struct dma_channel *get_dma_channel(unsigned int chan)
{
struct dma_info *info = get_dma_info(chan);
struct dma_channel *channel;
int i;
if (!info)
if (unlikely(!info))
return ERR_PTR(-EINVAL);
return info->channels + chan;
for (i = 0; i < info->nr_channels; i++) {
channel = &info->channels[i];
if (channel->chan == chan)
return channel;
}
return NULL;
}
EXPORT_SYMBOL(get_dma_channel);
int get_dma_residue(unsigned int chan)
{
struct dma_info *info = get_dma_info(chan);
struct dma_channel *channel = &info->channels[chan];
struct dma_channel *channel = get_dma_channel(chan);
if (info->ops->get_residue)
return info->ops->get_residue(channel);
return 0;
}
EXPORT_SYMBOL(get_dma_residue);
int request_dma(unsigned int chan, const char *dev_id)
static int search_cap(const char **haystack, const char *needle)
{
struct dma_info *info = get_dma_info(chan);
struct dma_channel *channel = &info->channels[chan];
const char **p;
down(&channel->sem);
if (!info->ops || chan >= MAX_DMA_CHANNELS) {
up(&channel->sem);
return -EINVAL;
}
atomic_set(&channel->busy, 1);
strlcpy(channel->dev_id, dev_id, sizeof(channel->dev_id));
up(&channel->sem);
if (info->ops->request)
return info->ops->request(channel);
for (p = haystack; *p; p++)
if (strcmp(*p, needle) == 0)
return 1;
return 0;
}
/**
* request_dma_bycap - Allocate a DMA channel based on its capabilities
* @dmac: List of DMA controllers to search
* @caps: List of capabilites
*
* Search all channels of all DMA controllers to find a channel which
* matches the requested capabilities. The result is the channel
* number if a match is found, or %-ENODEV if no match is found.
*
* Note that not all DMA controllers export capabilities, in which
* case they can never be allocated using this API, and so
* request_dma() must be used specifying the channel number.
*/
int request_dma_bycap(const char **dmac, const char **caps, const char *dev_id)
{
unsigned int found = 0;
struct dma_info *info;
const char **p;
int i;
BUG_ON(!dmac || !caps);
list_for_each_entry(info, &registered_dmac_list, list)
if (strcmp(*dmac, info->name) == 0) {
found = 1;
break;
}
if (!found)
return -ENODEV;
for (i = 0; i < info->nr_channels; i++) {
struct dma_channel *channel = &info->channels[i];
if (unlikely(!channel->caps))
continue;
for (p = caps; *p; p++) {
if (!search_cap(channel->caps, *p))
break;
if (request_dma(channel->chan, dev_id) == 0)
return channel->chan;
}
}
return -EINVAL;
}
EXPORT_SYMBOL(request_dma_bycap);
int dmac_search_free_channel(const char *dev_id)
{
struct dma_channel *channel = { 0 };
struct dma_info *info = get_dma_info(0);
int i;
for (i = 0; i < info->nr_channels; i++) {
channel = &info->channels[i];
if (unlikely(!channel))
return -ENODEV;
if (atomic_read(&channel->busy) == 0)
break;
}
if (info->ops->request) {
int result = info->ops->request(channel);
if (result)
return result;
atomic_set(&channel->busy, 1);
return channel->chan;
}
return -ENOSYS;
}
int request_dma(unsigned int chan, const char *dev_id)
{
struct dma_channel *channel = { 0 };
struct dma_info *info = get_dma_info(chan);
int result;
channel = get_dma_channel(chan);
if (atomic_xchg(&channel->busy, 1))
return -EBUSY;
strlcpy(channel->dev_id, dev_id, sizeof(channel->dev_id));
if (info->ops->request) {
result = info->ops->request(channel);
if (result)
atomic_set(&channel->busy, 0);
return result;
}
return 0;
}
EXPORT_SYMBOL(request_dma);
void free_dma(unsigned int chan)
{
struct dma_info *info = get_dma_info(chan);
struct dma_channel *channel = &info->channels[chan];
struct dma_channel *channel = get_dma_channel(chan);
if (info->ops->free)
info->ops->free(channel);
atomic_set(&channel->busy, 0);
}
EXPORT_SYMBOL(free_dma);
void dma_wait_for_completion(unsigned int chan)
{
struct dma_info *info = get_dma_info(chan);
struct dma_channel *channel = &info->channels[chan];
struct dma_channel *channel = get_dma_channel(chan);
if (channel->flags & DMA_TEI_CAPABLE) {
wait_event(channel->wait_queue,
@ -158,21 +238,52 @@ void dma_wait_for_completion(unsigned int chan)
while (info->ops->get_residue(channel))
cpu_relax();
}
EXPORT_SYMBOL(dma_wait_for_completion);
int register_chan_caps(const char *dmac, struct dma_chan_caps *caps)
{
struct dma_info *info;
unsigned int found = 0;
int i;
list_for_each_entry(info, &registered_dmac_list, list)
if (strcmp(dmac, info->name) == 0) {
found = 1;
break;
}
if (unlikely(!found))
return -ENODEV;
for (i = 0; i < info->nr_channels; i++, caps++) {
struct dma_channel *channel;
if ((info->first_channel_nr + i) != caps->ch_num)
return -EINVAL;
channel = &info->channels[i];
channel->caps = caps->caplist;
}
return 0;
}
EXPORT_SYMBOL(register_chan_caps);
void dma_configure_channel(unsigned int chan, unsigned long flags)
{
struct dma_info *info = get_dma_info(chan);
struct dma_channel *channel = &info->channels[chan];
struct dma_channel *channel = get_dma_channel(chan);
if (info->ops->configure)
info->ops->configure(channel, flags);
}
EXPORT_SYMBOL(dma_configure_channel);
int dma_xfer(unsigned int chan, unsigned long from,
unsigned long to, size_t size, unsigned int mode)
{
struct dma_info *info = get_dma_info(chan);
struct dma_channel *channel = &info->channels[chan];
struct dma_channel *channel = get_dma_channel(chan);
channel->sar = from;
channel->dar = to;
@ -181,8 +292,20 @@ int dma_xfer(unsigned int chan, unsigned long from,
return info->ops->xfer(channel);
}
EXPORT_SYMBOL(dma_xfer);
int dma_extend(unsigned int chan, unsigned long op, void *param)
{
struct dma_info *info = get_dma_info(chan);
struct dma_channel *channel = get_dma_channel(chan);
if (info->ops->extend)
return info->ops->extend(channel, op, param);
return -ENOSYS;
}
EXPORT_SYMBOL(dma_extend);
#ifdef CONFIG_PROC_FS
static int dma_read_proc(char *buf, char **start, off_t off,
int len, int *eof, void *data)
{
@ -214,8 +337,6 @@ static int dma_read_proc(char *buf, char **start, off_t off,
return p - buf;
}
#endif
int register_dmac(struct dma_info *info)
{
@ -224,8 +345,7 @@ int register_dmac(struct dma_info *info)
INIT_LIST_HEAD(&info->list);
printk(KERN_INFO "DMA: Registering %s handler (%d channel%s).\n",
info->name, info->nr_channels,
info->nr_channels > 1 ? "s" : "");
info->name, info->nr_channels, info->nr_channels > 1 ? "s" : "");
BUG_ON((info->flags & DMAC_CHANNELS_CONFIGURED) && !info->channels);
@ -242,28 +362,26 @@ int register_dmac(struct dma_info *info)
size = sizeof(struct dma_channel) * info->nr_channels;
info->channels = kmalloc(size, GFP_KERNEL);
info->channels = kzalloc(size, GFP_KERNEL);
if (!info->channels)
return -ENOMEM;
memset(info->channels, 0, size);
}
total_channels = get_nr_channels();
for (i = 0; i < info->nr_channels; i++) {
struct dma_channel *chan = info->channels + i;
struct dma_channel *chan = &info->channels[i];
chan->chan = i;
chan->vchan = i + total_channels;
atomic_set(&chan->busy, 0);
chan->chan = info->first_channel_nr + i;
chan->vchan = info->first_channel_nr + i + total_channels;
memcpy(chan->dev_id, "Unused", 7);
if (info->flags & DMAC_CHANNELS_TEI_CAPABLE)
chan->flags |= DMA_TEI_CAPABLE;
init_MUTEX(&chan->sem);
init_waitqueue_head(&chan->wait_queue);
dma_create_sysfs_files(chan, info);
}
@ -271,6 +389,7 @@ int register_dmac(struct dma_info *info)
return 0;
}
EXPORT_SYMBOL(register_dmac);
void unregister_dmac(struct dma_info *info)
{
@ -285,31 +404,16 @@ void unregister_dmac(struct dma_info *info)
list_del(&info->list);
platform_device_unregister(info->pdev);
}
EXPORT_SYMBOL(unregister_dmac);
static int __init dma_api_init(void)
{
printk("DMA: Registering DMA API.\n");
#ifdef CONFIG_PROC_FS
printk(KERN_NOTICE "DMA: Registering DMA API.\n");
create_proc_read_entry("dma", 0, 0, dma_read_proc, 0);
#endif
return 0;
}
subsys_initcall(dma_api_init);
MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
MODULE_DESCRIPTION("DMA API for SuperH");
MODULE_LICENSE("GPL");
EXPORT_SYMBOL(request_dma);
EXPORT_SYMBOL(free_dma);
EXPORT_SYMBOL(register_dmac);
EXPORT_SYMBOL(get_dma_residue);
EXPORT_SYMBOL(get_dma_info);
EXPORT_SYMBOL(get_dma_channel);
EXPORT_SYMBOL(dma_xfer);
EXPORT_SYMBOL(dma_wait_for_completion);
EXPORT_SYMBOL(dma_configure_channel);

View File

@ -94,20 +94,13 @@ static int sh_dmac_request_dma(struct dma_channel *chan)
if (unlikely(!chan->flags & DMA_TEI_CAPABLE))
return 0;
chan->name = kzalloc(32, GFP_KERNEL);
if (unlikely(chan->name == NULL))
return -ENOMEM;
snprintf(chan->name, 32, "DMAC Transfer End (Channel %d)",
chan->chan);
return request_irq(get_dmte_irq(chan->chan), dma_tei,
IRQF_DISABLED, chan->name, chan);
IRQF_DISABLED, chan->dev_id, chan);
}
static void sh_dmac_free_dma(struct dma_channel *chan)
{
free_irq(get_dmte_irq(chan->chan), chan);
kfree(chan->name);
}
static void

View File

@ -3,7 +3,7 @@
*
* sysfs interface for SH DMA API
*
* Copyright (C) 2004, 2005 Paul Mundt
* Copyright (C) 2004 - 2006 Paul Mundt
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
@ -21,7 +21,6 @@
static struct sysdev_class dma_sysclass = {
set_kset_name("dma"),
};
EXPORT_SYMBOL(dma_sysclass);
static ssize_t dma_show_devices(struct sys_device *dev, char *buf)
@ -31,7 +30,10 @@ static ssize_t dma_show_devices(struct sys_device *dev, char *buf)
for (i = 0; i < MAX_DMA_CHANNELS; i++) {
struct dma_info *info = get_dma_info(i);
struct dma_channel *channel = &info->channels[i];
struct dma_channel *channel = get_dma_channel(i);
if (unlikely(!info) || !channel)
continue;
len += sprintf(buf + len, "%2d: %14s %s\n",
channel->chan, info->name,
@ -125,11 +127,16 @@ int dma_create_sysfs_files(struct dma_channel *chan, struct dma_info *info)
if (ret)
return ret;
sysdev_create_file(dev, &attr_dev_id);
sysdev_create_file(dev, &attr_count);
sysdev_create_file(dev, &attr_mode);
sysdev_create_file(dev, &attr_flags);
sysdev_create_file(dev, &attr_config);
ret |= sysdev_create_file(dev, &attr_dev_id);
ret |= sysdev_create_file(dev, &attr_count);
ret |= sysdev_create_file(dev, &attr_mode);
ret |= sysdev_create_file(dev, &attr_flags);
ret |= sysdev_create_file(dev, &attr_config);
if (unlikely(ret)) {
dev_err(&info->pdev->dev, "Failed creating attrs\n");
return ret;
}
snprintf(name, sizeof(name), "dma%d", chan->chan);
return sysfs_create_link(&info->pdev->dev.kobj, &dev->kobj, name);

View File

@ -15,25 +15,21 @@
#include <linux/types.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <asm/io.h>
#include <linux/io.h>
#include <asm/titan.h>
#include "pci-sh4.h"
static char titan_irq_tab[] __initdata = {
TITAN_IRQ_WAN,
TITAN_IRQ_LAN,
TITAN_IRQ_MPCIA,
TITAN_IRQ_MPCIB,
TITAN_IRQ_USB,
};
int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
{
int irq = -1;
switch (slot) {
case 0: irq = TITAN_IRQ_WAN; break; /* eth0 (WAN) */
case 1: irq = TITAN_IRQ_LAN; break; /* eth1 (LAN) */
case 2: irq = TITAN_IRQ_MPCIA; break; /* mPCI A */
case 3: irq = TITAN_IRQ_MPCIB; break; /* mPCI B */
case 4: irq = TITAN_IRQ_USB; break; /* USB */
default:
printk(KERN_INFO "PCI: Bad IRQ mapping "
"request for slot %d\n", slot);
return -1;
}
int irq = titan_irq_tab[slot];
printk("PCI: Mapping TITAN IRQ for slot %d, pin %c to irq %d\n",
slot, pin - 1 + 'A', irq);

View File

@ -22,6 +22,20 @@
#include <linux/delay.h>
#include "pci-sh4.h"
#define INTC_BASE 0xffd00000
#define INTC_ICR0 (INTC_BASE+0x0)
#define INTC_ICR1 (INTC_BASE+0x1c)
#define INTC_INTPRI (INTC_BASE+0x10)
#define INTC_INTREQ (INTC_BASE+0x24)
#define INTC_INTMSK0 (INTC_BASE+0x44)
#define INTC_INTMSK1 (INTC_BASE+0x48)
#define INTC_INTMSK2 (INTC_BASE+0x40080)
#define INTC_INTMSKCLR0 (INTC_BASE+0x64)
#define INTC_INTMSKCLR1 (INTC_BASE+0x68)
#define INTC_INTMSKCLR2 (INTC_BASE+0x40084)
#define INTC_INT2MSKR (INTC_BASE+0x40038)
#define INTC_INT2MSKCR (INTC_BASE+0x4003c)
/*
* Initialization. Try all known PCI access methods. Note that we support
* using both PCI BIOS and direct access: in such cases, we use I/O ports

View File

@ -0,0 +1,138 @@
/*
* Generic push-switch framework
*
* Copyright (C) 2006 Paul Mundt
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <asm/push-switch.h>
#define DRV_NAME "push-switch"
#define DRV_VERSION "0.1.0"
static ssize_t switch_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct push_switch_platform_info *psw_info = dev->platform_data;
return sprintf(buf, "%s\n", psw_info->name);
}
static DEVICE_ATTR(switch, S_IRUGO, switch_show, NULL);
static void switch_timer(unsigned long data)
{
struct push_switch *psw = (struct push_switch *)data;
schedule_work(&psw->work);
}
static void switch_work_handler(void *data)
{
struct platform_device *pdev = data;
struct push_switch *psw = platform_get_drvdata(pdev);
psw->state = 0;
kobject_uevent(&pdev->dev.kobj, KOBJ_CHANGE);
}
static int switch_drv_probe(struct platform_device *pdev)
{
struct push_switch_platform_info *psw_info;
struct push_switch *psw;
int ret, irq;
psw = kzalloc(sizeof(struct push_switch), GFP_KERNEL);
if (unlikely(!psw))
return -ENOMEM;
irq = platform_get_irq(pdev, 0);
if (unlikely(irq < 0)) {
ret = -ENODEV;
goto err;
}
psw_info = pdev->dev.platform_data;
BUG_ON(!psw_info);
ret = request_irq(irq, psw_info->irq_handler,
IRQF_DISABLED | psw_info->irq_flags,
psw_info->name ? psw_info->name : DRV_NAME, pdev);
if (unlikely(ret < 0))
goto err;
if (psw_info->name) {
ret = device_create_file(&pdev->dev, &dev_attr_switch);
if (unlikely(ret)) {
dev_err(&pdev->dev, "Failed creating device attrs\n");
ret = -EINVAL;
goto err_irq;
}
}
INIT_WORK(&psw->work, switch_work_handler, pdev);
init_timer(&psw->debounce);
psw->debounce.function = switch_timer;
psw->debounce.data = (unsigned long)psw;
platform_set_drvdata(pdev, psw);
return 0;
err_irq:
free_irq(irq, pdev);
err:
kfree(psw);
return ret;
}
static int switch_drv_remove(struct platform_device *pdev)
{
struct push_switch *psw = platform_get_drvdata(pdev);
struct push_switch_platform_info *psw_info = pdev->dev.platform_data;
int irq = platform_get_irq(pdev, 0);
if (psw_info->name)
device_remove_file(&pdev->dev, &dev_attr_switch);
platform_set_drvdata(pdev, NULL);
flush_scheduled_work();
del_timer_sync(&psw->debounce);
free_irq(irq, pdev);
kfree(psw);
return 0;
}
static struct platform_driver switch_driver = {
.probe = switch_drv_probe,
.remove = switch_drv_remove,
.driver = {
.name = DRV_NAME,
},
};
static int __init switch_init(void)
{
printk(KERN_NOTICE DRV_NAME ": version %s loaded\n", DRV_VERSION);
return platform_driver_register(&switch_driver);
}
static void __exit switch_exit(void)
{
platform_driver_unregister(&switch_driver);
}
module_init(switch_init);
module_exit(switch_exit);
MODULE_VERSION(DRV_VERSION);
MODULE_AUTHOR("Paul Mundt");
MODULE_LICENSE("GPLv2");

View File

@ -4,7 +4,7 @@
extra-y := head.o init_task.o vmlinux.lds
obj-y := process.o signal.o entry.o traps.o irq.o \
obj-y := process.o signal.o traps.o irq.o \
ptrace.o setup.o time.o sys_sh.o semaphore.o \
io.o io_generic.o sh_ksyms.o syscalls.o
@ -21,3 +21,4 @@ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
obj-$(CONFIG_APM) += apm.o
obj-$(CONFIG_PM) += pm.o
obj-$(CONFIG_STACKTRACE) += stacktrace.o

View File

@ -2,11 +2,12 @@
# Makefile for the Linux/SuperH CPU-specifc backends.
#
obj-y += irq/ init.o clock.o
obj-$(CONFIG_CPU_SH2) += sh2/
obj-$(CONFIG_CPU_SH3) += sh3/
obj-$(CONFIG_CPU_SH4) += sh4/
obj-$(CONFIG_CPU_SH2) = sh2/
obj-$(CONFIG_CPU_SH2A) = sh2a/
obj-$(CONFIG_CPU_SH3) = sh3/
obj-$(CONFIG_CPU_SH4) = sh4/
obj-$(CONFIG_UBC_WAKEUP) += ubc.o
obj-$(CONFIG_SH_ADC) += adc.o
obj-y += irq/ init.o clock.o

View File

@ -5,9 +5,11 @@
*
* This clock framework is derived from the OMAP version by:
*
* Copyright (C) 2004 Nokia Corporation
* Copyright (C) 2004 - 2005 Nokia Corporation
* Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
*
* Modified for omap shared clock framework by Tony Lindgren <tony@atomide.com>
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
@ -20,6 +22,7 @@
#include <linux/kref.h>
#include <linux/seq_file.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <asm/clock.h>
#include <asm/timer.h>
@ -195,17 +198,37 @@ void clk_recalc_rate(struct clk *clk)
propagate_rate(clk);
}
struct clk *clk_get(const char *id)
/*
* Returns a clock. Note that we first try to use device id on the bus
* and clock name. If this fails, we try to use clock name only.
*/
struct clk *clk_get(struct device *dev, const char *id)
{
struct clk *p, *clk = ERR_PTR(-ENOENT);
int idno;
if (dev == NULL || dev->bus != &platform_bus_type)
idno = -1;
else
idno = to_platform_device(dev)->id;
mutex_lock(&clock_list_sem);
list_for_each_entry(p, &clock_list, node) {
if (p->id == idno &&
strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
clk = p;
goto found;
}
}
list_for_each_entry(p, &clock_list, node) {
if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
clk = p;
break;
}
}
found:
mutex_unlock(&clock_list_sem);
return clk;

View File

@ -68,12 +68,14 @@ static void __init cache_init(void)
waysize = cpu_data->dcache.sets;
#ifdef CCR_CACHE_ORA
/*
* If the OC is already in RAM mode, we only have
* half of the entries to flush..
*/
if (ccr & CCR_CACHE_ORA)
waysize >>= 1;
#endif
waysize <<= cpu_data->dcache.entry_shift;

View File

@ -1,8 +1,9 @@
#
# Makefile for the Linux/SuperH CPU-specifc IRQ handlers.
#
obj-y += ipr.o imask.o
obj-y += imask.o
obj-$(CONFIG_CPU_HAS_IPR_IRQ) += ipr.o
obj-$(CONFIG_CPU_HAS_PINT_IRQ) += pint.o
obj-$(CONFIG_CPU_HAS_MASKREG_IRQ) += maskreg.o
obj-$(CONFIG_CPU_HAS_INTC2_IRQ) += intc2.o

View File

@ -53,7 +53,10 @@ void static inline set_interrupt_registers(int ip)
{
unsigned long __dummy;
asm volatile("ldc %2, r6_bank\n\t"
asm volatile(
#ifdef CONFIG_CPU_HAS_SR_RB
"ldc %2, r6_bank\n\t"
#endif
"stc sr, %0\n\t"
"and #0xf0, %0\n\t"
"shlr2 %0\n\t"

View File

@ -11,22 +11,29 @@
* Hitachi 7751, the STM ST40 STB1, SH7760, and SH7780.
*/
#include <linux/kernel.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <asm/system.h>
#if defined(CONFIG_CPU_SUBTYPE_SH7760)
#define INTC2_BASE 0xfe080000
#define INTC2_INTMSK (INTC2_BASE + 0x40)
#define INTC2_INTMSKCLR (INTC2_BASE + 0x60)
#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
#define INTC2_BASE 0xffd40000
#define INTC2_INTMSK (INTC2_BASE + 0x38)
#define INTC2_INTMSKCLR (INTC2_BASE + 0x3c)
#endif
static void disable_intc2_irq(unsigned int irq)
{
struct intc2_data *p = get_irq_chip_data(irq);
ctrl_outl(1 << p->msk_shift,
INTC2_BASE + INTC2_INTMSK_OFFSET + p->msk_offset);
ctrl_outl(1 << p->msk_shift, INTC2_INTMSK + p->msk_offset);
}
static void enable_intc2_irq(unsigned int irq)
{
struct intc2_data *p = get_irq_chip_data(irq);
ctrl_outl(1 << p->msk_shift,
INTC2_BASE + INTC2_INTMSKCLR_OFFSET + p->msk_offset);
ctrl_outl(1 << p->msk_shift, INTC2_INTMSKCLR + p->msk_offset);
}
static struct irq_chip intc2_irq_chip = {
@ -61,12 +68,10 @@ void make_intc2_irq(struct intc2_data *table, unsigned int nr_irqs)
/* Set the priority level */
local_irq_save(flags);
ipr = ctrl_inl(INTC2_BASE + INTC2_INTPRI_OFFSET +
p->ipr_offset);
ipr = ctrl_inl(INTC2_BASE + p->ipr_offset);
ipr &= ~(0xf << p->ipr_shift);
ipr |= p->priority << p->ipr_shift;
ctrl_outl(ipr, INTC2_BASE + INTC2_INTPRI_OFFSET +
p->ipr_offset);
ctrl_outl(ipr, INTC2_BASE + p->ipr_offset);
local_irq_restore(flags);

View File

@ -19,25 +19,21 @@
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/machvec.h>
#include <linux/io.h>
#include <linux/interrupt.h>
static void disable_ipr_irq(unsigned int irq)
{
struct ipr_data *p = get_irq_chip_data(irq);
int shift = p->shift*4;
/* Set the priority in IPR to 0 */
ctrl_outw(ctrl_inw(p->addr) & (0xffff ^ (0xf << shift)), p->addr);
ctrl_outw(ctrl_inw(p->addr) & (0xffff ^ (0xf << p->shift)), p->addr);
}
static void enable_ipr_irq(unsigned int irq)
{
struct ipr_data *p = get_irq_chip_data(irq);
int shift = p->shift*4;
/* Set priority in IPR back to original value */
ctrl_outw(ctrl_inw(p->addr) | (p->priority << shift), p->addr);
ctrl_outw(ctrl_inw(p->addr) | (p->priority << p->shift), p->addr);
}
static struct irq_chip ipr_irq_chip = {
@ -53,6 +49,10 @@ void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs)
for (i = 0; i < nr_irqs; i++) {
unsigned int irq = table[i].irq;
table[i].addr = map_ipridx_to_addr(table[i].ipr_idx);
/* could the IPR index be mapped, if not we ignore this */
if (table[i].addr == 0)
continue;
disable_irq_nosync(irq);
set_irq_chip_and_handler_name(irq, &ipr_irq_chip,
handle_level_irq, "level");
@ -62,83 +62,6 @@ void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs)
}
EXPORT_SYMBOL(make_ipr_irq);
static struct ipr_data sys_ipr_map[] = {
#ifndef CONFIG_CPU_SUBTYPE_SH7780
{ TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY },
{ TIMER1_IRQ, TIMER1_IPR_ADDR, TIMER1_IPR_POS, TIMER1_PRIORITY },
#ifdef RTC_IRQ
{ RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY },
#endif
#ifdef SCI_ERI_IRQ
{ SCI_ERI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY },
{ SCI_RXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY },
{ SCI_TXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY },
#endif
#ifdef SCIF1_ERI_IRQ
{ SCIF1_ERI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY },
{ SCIF1_RXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY },
{ SCIF1_BRI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY },
{ SCIF1_TXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY },
#endif
#if defined(CONFIG_CPU_SUBTYPE_SH7300)
{ SCIF0_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS, SCIF0_PRIORITY },
{ DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY },
{ DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY },
{ VIO_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY },
#endif
#ifdef SCIF_ERI_IRQ
{ SCIF_ERI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY },
{ SCIF_RXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY },
{ SCIF_BRI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY },
{ SCIF_TXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY },
#endif
#ifdef IRDA_ERI_IRQ
{ IRDA_ERI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY },
{ IRDA_RXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY },
{ IRDA_BRI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY },
{ IRDA_TXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY },
#endif
#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \
defined(CONFIG_CPU_SUBTYPE_SH7706) || \
defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705)
/*
* Initialize the Interrupt Controller (INTC)
* registers to their power on values
*/
/*
* Enable external irq (INTC IRQ mode).
* You should set corresponding bits of PFC to "00"
* to enable these interrupts.
*/
{ IRQ0_IRQ, IRQ0_IPR_ADDR, IRQ0_IPR_POS, IRQ0_PRIORITY },
{ IRQ1_IRQ, IRQ1_IPR_ADDR, IRQ1_IPR_POS, IRQ1_PRIORITY },
{ IRQ2_IRQ, IRQ2_IPR_ADDR, IRQ2_IPR_POS, IRQ2_PRIORITY },
{ IRQ3_IRQ, IRQ3_IPR_ADDR, IRQ3_IPR_POS, IRQ3_PRIORITY },
{ IRQ4_IRQ, IRQ4_IPR_ADDR, IRQ4_IPR_POS, IRQ4_PRIORITY },
{ IRQ5_IRQ, IRQ5_IPR_ADDR, IRQ5_IPR_POS, IRQ5_PRIORITY },
#endif
#endif
};
void __init init_IRQ(void)
{
make_ipr_irq(sys_ipr_map, ARRAY_SIZE(sys_ipr_map));
#ifdef CONFIG_CPU_HAS_PINT_IRQ
init_IRQ_pint();
#endif
#ifdef CONFIG_CPU_HAS_INTC2_IRQ
init_IRQ_intc2();
#endif
/* Perform the machine specific initialisation */
if (sh_mv.mv_init_irq != NULL)
sh_mv.mv_init_irq();
irq_ctx_init(smp_processor_id());
}
#if !defined(CONFIG_CPU_HAS_PINT_IRQ)
int ipr_irq_demux(int irq)
{

View File

@ -2,5 +2,6 @@
# Makefile for the Linux/SuperH SH-2 backends.
#
obj-y := probe.o
obj-y := ex.o probe.o entry.o
obj-$(CONFIG_CPU_SUBTYPE_SH7619) += setup-sh7619.o clock-sh7619.o

View File

@ -0,0 +1,81 @@
/*
* arch/sh/kernel/cpu/sh2/clock-sh7619.c
*
* SH7619 support for the clock framework
*
* Copyright (C) 2006 Yoshinori Sato
*
* Based on clock-sh4.c
* Copyright (C) 2005 Paul Mundt
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <asm/clock.h>
#include <asm/freq.h>
#include <asm/io.h>
const static int pll1rate[]={1,2};
const static int pfc_divisors[]={1,2,0,4};
#if (CONFIG_SH_CLK_MD == 1) || (CONFIG_SH_CLK_MD == 2)
#define PLL2 (4)
#elif (CONFIG_SH_CLK_MD == 5) || (CONFIG_SH_CLK_MD == 6)
#define PLL2 (2)
#else
#error "Illigal Clock Mode!"
#endif
static void master_clk_init(struct clk *clk)
{
clk->rate *= PLL2 * pll1rate[(ctrl_inw(FREQCR) >> 8) & 7];
}
static struct clk_ops sh7619_master_clk_ops = {
.init = master_clk_init,
};
static void module_clk_recalc(struct clk *clk)
{
int idx = (ctrl_inw(FREQCR) & 0x0007);
clk->rate = clk->parent->rate / pfc_divisors[idx];
}
static struct clk_ops sh7619_module_clk_ops = {
.recalc = module_clk_recalc,
};
static void bus_clk_recalc(struct clk *clk)
{
clk->rate = clk->parent->rate / pll1rate[(ctrl_inw(FREQCR) >> 8) & 7];
}
static struct clk_ops sh7619_bus_clk_ops = {
.recalc = bus_clk_recalc,
};
static void cpu_clk_recalc(struct clk *clk)
{
clk->rate = clk->parent->rate;
}
static struct clk_ops sh7619_cpu_clk_ops = {
.recalc = cpu_clk_recalc,
};
static struct clk_ops *sh7619_clk_ops[] = {
&sh7619_master_clk_ops,
&sh7619_module_clk_ops,
&sh7619_bus_clk_ops,
&sh7619_cpu_clk_ops,
};
void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
{
if (idx < ARRAY_SIZE(sh7619_clk_ops))
*ops = sh7619_clk_ops[idx];
}

View File

@ -0,0 +1,341 @@
/*
* arch/sh/kernel/cpu/sh2/entry.S
*
* The SH-2 exception entry
*
* Copyright (C) 2005,2006 Yoshinori Sato
* Copyright (C) 2005 AXE,Inc.
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#include <linux/linkage.h>
#include <asm/asm-offsets.h>
#include <asm/thread_info.h>
#include <asm/cpu/mmu_context.h>
#include <asm/unistd.h>
#include <asm/errno.h>
#include <asm/page.h>
/* Offsets to the stack */
OFF_R0 = 0 /* Return value. New ABI also arg4 */
OFF_R1 = 4 /* New ABI: arg5 */
OFF_R2 = 8 /* New ABI: arg6 */
OFF_R3 = 12 /* New ABI: syscall_nr */
OFF_R4 = 16 /* New ABI: arg0 */
OFF_R5 = 20 /* New ABI: arg1 */
OFF_R6 = 24 /* New ABI: arg2 */
OFF_R7 = 28 /* New ABI: arg3 */
OFF_SP = (15*4)
OFF_PC = (16*4)
OFF_SR = (16*4+2*4)
OFF_TRA = (16*4+6*4)
#include <asm/entry-macros.S>
ENTRY(exception_handler)
! already saved r0/r1
mov.l r2,@-sp
mov.l r3,@-sp
mov r0,r1
cli
mov.l $cpu_mode,r2
mov.l @r2,r0
mov.l @(5*4,r15),r3 ! previous SR
shll2 r3 ! set "S" flag
rotl r0 ! T <- "S" flag
rotl r0 ! "S" flag is LSB
rotcr r3 ! T -> r3:b30
shlr r3
shlr r0
bt/s 1f
mov.l r3,@(5*4,r15) ! copy cpu mode to SR
! switch to kernel mode
mov #1,r0
rotr r0
rotr r0
mov.l r0,@r2 ! enter kernel mode
mov.l $current_thread_info,r2
mov.l @r2,r2
mov #0x20,r0
shll8 r0
add r2,r0
mov r15,r2 ! r2 = user stack top
mov r0,r15 ! switch kernel stack
add #-4,r15 ! dummy
mov.l r1,@-r15 ! TRA
sts.l macl, @-r15
sts.l mach, @-r15
stc.l gbr, @-r15
mov.l @(4*4,r2),r0
mov.l @(5*4,r2),r1
mov.l r1,@-r15 ! original SR
sts.l pr,@-r15
mov.l r0,@-r15 ! original PC
mov r2,r3
add #(4+2)*4,r3 ! rewind r0 - r3 + exception frame
mov.l r3,@-r15 ! original SP
mov.l r14,@-r15
mov.l r13,@-r15
mov.l r12,@-r15
mov.l r11,@-r15
mov.l r10,@-r15
mov.l r9,@-r15
mov.l r8,@-r15
mov.l r7,@-r15
mov.l r6,@-r15
mov.l r5,@-r15
mov.l r4,@-r15
mov r2,r8 ! copy user -> kernel stack
mov.l @r8+,r3
mov.l r3,@-r15
mov.l @r8+,r2
mov.l r2,@-r15
mov.l @r8+,r1
mov.l r1,@-r15
mov.l @r8+,r0
bra 2f
mov.l r0,@-r15
1:
! in kernel exception
mov #(22-4-4-1)*4+4,r0
mov r15,r2
sub r0,r15
mov.l @r2+,r0 ! old R3
mov.l r0,@-r15
mov.l @r2+,r0 ! old R2
mov.l r0,@-r15
mov.l @r2+,r0 ! old R1
mov.l r0,@-r15
mov.l @r2+,r0 ! old R0
mov.l r0,@-r15
mov.l @r2+,r3 ! old PC
mov.l @r2+,r0 ! old SR
add #-4,r2 ! exception frame stub (sr)
mov.l r1,@-r2 ! TRA
sts.l macl, @-r2
sts.l mach, @-r2
stc.l gbr, @-r2
mov.l r0,@-r2 ! save old SR
sts.l pr,@-r2
mov.l r3,@-r2 ! save old PC
mov r2,r0
add #8*4,r0
mov.l r0,@-r2 ! save old SP
mov.l r14,@-r2
mov.l r13,@-r2
mov.l r12,@-r2
mov.l r11,@-r2
mov.l r10,@-r2
mov.l r9,@-r2
mov.l r8,@-r2
mov.l r7,@-r2
mov.l r6,@-r2
mov.l r5,@-r2
mov.l r4,@-r2
mov.l @(OFF_R0,r15),r0
mov.l @(OFF_R1,r15),r1
mov.l @(OFF_R2,r15),r2
mov.l @(OFF_R3,r15),r3
2:
mov #OFF_TRA,r8
add r15,r8
mov.l @r8,r9
mov #64,r8
cmp/hs r8,r9
bt interrupt_entry ! vec >= 64 is interrupt
mov #32,r8
cmp/hs r8,r9
bt trap_entry ! 64 > vec >= 32 is trap
mov.l 4f,r8
mov r9,r4
shll2 r9
add r9,r8
mov.l @r8,r8
mov #0,r9
cmp/eq r9,r8
bf 3f
mov.l 8f,r8 ! unhandled exception
3:
mov.l 5f,r10
jmp @r8
lds r10,pr
interrupt_entry:
mov r9,r4
mov.l 6f,r9
mov.l 7f,r8
jmp @r8
lds r9,pr
.align 2
4: .long exception_handling_table
5: .long ret_from_exception
6: .long ret_from_irq
7: .long do_IRQ
8: .long do_exception_error
trap_entry:
add #-0x10,r9
shll2 r9 ! TRA
mov #OFF_TRA,r8
add r15,r8
mov.l r9,@r8
mov r9,r8
#ifdef CONFIG_TRACE_IRQFLAGS
mov.l 5f, r9
jsr @r9
nop
#endif
sti
bra system_call
nop
.align 2
1: .long syscall_exit
2: .long break_point_trap_software
3: .long NR_syscalls
4: .long sys_call_table
#ifdef CONFIG_TRACE_IRQFLAGS
5: .long trace_hardirqs_on
#endif
#if defined(CONFIG_SH_STANDARD_BIOS)
/* Unwind the stack and jmp to the debug entry */
debug_kernel_fw:
mov r15,r0
add #(22-4)*4-4,r0
ldc.l @r0+,gbr
lds.l @r0+,mach
lds.l @r0+,macl
mov r15,r0
mov.l @(OFF_SP,r0),r1
mov #OFF_SR,r2
mov.l @(r0,r2),r3
mov.l r3,@-r1
mov #OFF_SP,r2
mov.l @(r0,r2),r3
mov.l r3,@-r1
mov r15,r0
add #(22-4)*4-8,r0
mov.l 1f,r2
mov.l @r2,r2
stc sr,r3
mov.l r2,@r0
mov.l r3,@r0
mov.l r1,@(8,r0)
mov.l @r15+, r0
mov.l @r15+, r1
mov.l @r15+, r2
mov.l @r15+, r3
mov.l @r15+, r4
mov.l @r15+, r5
mov.l @r15+, r6
mov.l @r15+, r7
mov.l @r15+, r8
mov.l @r15+, r9
mov.l @r15+, r10
mov.l @r15+, r11
mov.l @r15+, r12
mov.l @r15+, r13
mov.l @r15+, r14
add #8,r15
lds.l @r15+, pr
rte
mov.l @r15+,r15
.align 2
1: .long gdb_vbr_vector
#endif /* CONFIG_SH_STANDARD_BIOS */
ENTRY(address_error_handler)
mov r15,r4 ! regs
add #4,r4
mov #OFF_PC,r0
mov.l @(r0,r15),r6 ! pc
mov.l 1f,r0
jmp @r0
mov #0,r5 ! writeaccess is unknown
.align 2
1: .long do_address_error
restore_all:
cli
#ifdef CONFIG_TRACE_IRQFLAGS
mov.l 3f, r0
jsr @r0
nop
#endif
mov r15,r0
mov.l $cpu_mode,r2
mov #OFF_SR,r3
mov.l @(r0,r3),r1
mov.l r1,@r2
shll2 r1 ! clear MD bit
shlr2 r1
mov.l @(OFF_SP,r0),r2
add #-8,r2
mov.l r2,@(OFF_SP,r0) ! point exception frame top
mov.l r1,@(4,r2) ! set sr
mov #OFF_PC,r3
mov.l @(r0,r3),r1
mov.l r1,@r2 ! set pc
add #4*16+4,r0
lds.l @r0+,pr
add #4,r0 ! skip sr
ldc.l @r0+,gbr
lds.l @r0+,mach
lds.l @r0+,macl
get_current_thread_info r0, r1
mov.l $current_thread_info,r1
mov.l r0,@r1
mov.l @r15+,r0
mov.l @r15+,r1
mov.l @r15+,r2
mov.l @r15+,r3
mov.l @r15+,r4
mov.l @r15+,r5
mov.l @r15+,r6
mov.l @r15+,r7
mov.l @r15+,r8
mov.l @r15+,r9
mov.l @r15+,r10
mov.l @r15+,r11
mov.l @r15+,r12
mov.l @r15+,r13
mov.l @r15+,r14
mov.l @r15,r15
rte
nop
2:
mov.l 1f,r8
mov.l 2f,r9
jmp @r9
lds r8,pr
.align 2
$current_thread_info:
.long __current_thread_info
$cpu_mode:
.long __cpu_mode
#ifdef CONFIG_TRACE_IRQFLAGS
3: .long trace_hardirqs_off
#endif
! common exception handler
#include "../../entry-common.S"
.data
! cpu operation mode
! bit30 = MD (compatible SH3/4)
__cpu_mode:
.long 0x40000000
.section .bss
__current_thread_info:
.long 0
ENTRY(exception_handling_table)
.space 4*32

View File

@ -0,0 +1,46 @@
/*
* arch/sh/kernel/cpu/sh2/ex.S
*
* The SH-2 exception vector table
*
* Copyright (C) 2005 Yoshinori Sato
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#include <linux/linkage.h>
!
! convert Exception Vector to Exception Number
!
exception_entry:
no = 0
.rept 256
mov.l r0,@-sp
mov #no,r0
bra exception_trampoline
and #0xff,r0
no = no + 1
.endr
exception_trampoline:
mov.l r1,@-sp
mov.l $exception_handler,r1
jmp @r1
.align 2
$exception_entry:
.long exception_entry
$exception_handler:
.long exception_handler
!
! Exception Vector Base
!
.align 2
ENTRY(vbr_base)
vector = 0
.rept 256
.long exception_entry + vector * 8
vector = vector + 1
.endr

View File

@ -17,17 +17,23 @@
int __init detect_cpu_and_cache_system(void)
{
/*
* For now, assume SH7604 .. fix this later.
*/
#if defined(CONFIG_CPU_SUBTYPE_SH7604)
cpu_data->type = CPU_SH7604;
cpu_data->dcache.ways = 4;
cpu_data->dcache.way_shift = 6;
cpu_data->dcache.way_incr = (1<<10);
cpu_data->dcache.sets = 64;
cpu_data->dcache.entry_shift = 4;
cpu_data->dcache.linesz = L1_CACHE_BYTES;
cpu_data->dcache.flags = 0;
#elif defined(CONFIG_CPU_SUBTYPE_SH7619)
cpu_data->type = CPU_SH7619;
cpu_data->dcache.ways = 4;
cpu_data->dcache.way_incr = (1<<12);
cpu_data->dcache.sets = 256;
cpu_data->dcache.entry_shift = 4;
cpu_data->dcache.linesz = L1_CACHE_BYTES;
cpu_data->dcache.flags = 0;
#endif
/*
* SH-2 doesn't have separate caches
*/

View File

@ -0,0 +1,53 @@
/*
* SH7619 Setup
*
* Copyright (C) 2006 Yoshinori Sato
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#include <linux/platform_device.h>
#include <linux/init.h>
#include <linux/serial.h>
#include <asm/sci.h>
static struct plat_sci_port sci_platform_data[] = {
{
.mapbase = 0xf8400000,
.flags = UPF_BOOT_AUTOCONF,
.type = PORT_SCIF,
.irqs = { 88, 89, 91, 90},
}, {
.mapbase = 0xf8410000,
.flags = UPF_BOOT_AUTOCONF,
.type = PORT_SCIF,
.irqs = { 92, 93, 95, 94},
}, {
.mapbase = 0xf8420000,
.flags = UPF_BOOT_AUTOCONF,
.type = PORT_SCIF,
.irqs = { 96, 97, 99, 98},
}, {
.flags = 0,
}
};
static struct platform_device sci_device = {
.name = "sh-sci",
.id = -1,
.dev = {
.platform_data = sci_platform_data,
},
};
static struct platform_device *sh7619_devices[] __initdata = {
&sci_device,
};
static int __init sh7619_devices_setup(void)
{
return platform_add_devices(sh7619_devices,
ARRAY_SIZE(sh7619_devices));
}
__initcall(sh7619_devices_setup);

View File

@ -0,0 +1,10 @@
#
# Makefile for the Linux/SuperH SH-2A backends.
#
obj-y := common.o probe.o
common-y += $(addprefix ../sh2/, ex.o)
common-y += $(addprefix ../sh2/, entry.o)
obj-$(CONFIG_CPU_SUBTYPE_SH7206) += setup-sh7206.o clock-sh7206.o

View File

@ -0,0 +1,85 @@
/*
* arch/sh/kernel/cpu/sh2a/clock-sh7206.c
*
* SH7206 support for the clock framework
*
* Copyright (C) 2006 Yoshinori Sato
*
* Based on clock-sh4.c
* Copyright (C) 2005 Paul Mundt
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <asm/clock.h>
#include <asm/freq.h>
#include <asm/io.h>
const static int pll1rate[]={1,2,3,4,6,8};
const static int pfc_divisors[]={1,2,3,4,6,8,12};
#define ifc_divisors pfc_divisors
#if (CONFIG_SH_CLK_MD == 2)
#define PLL2 (4)
#elif (CONFIG_SH_CLK_MD == 6)
#define PLL2 (2)
#elif (CONFIG_SH_CLK_MD == 7)
#define PLL2 (1)
#else
#error "Illigal Clock Mode!"
#endif
static void master_clk_init(struct clk *clk)
{
clk->rate *= PLL2 * pll1rate[(ctrl_inw(FREQCR) >> 8) & 0x0007];
}
static struct clk_ops sh7206_master_clk_ops = {
.init = master_clk_init,
};
static void module_clk_recalc(struct clk *clk)
{
int idx = (ctrl_inw(FREQCR) & 0x0007);
clk->rate = clk->parent->rate / pfc_divisors[idx];
}
static struct clk_ops sh7206_module_clk_ops = {
.recalc = module_clk_recalc,
};
static void bus_clk_recalc(struct clk *clk)
{
clk->rate = clk->parent->rate / pll1rate[(ctrl_inw(FREQCR) >> 8) & 0x0007];
}
static struct clk_ops sh7206_bus_clk_ops = {
.recalc = bus_clk_recalc,
};
static void cpu_clk_recalc(struct clk *clk)
{
int idx = (ctrl_inw(FREQCR) & 0x0007);
clk->rate = clk->parent->rate / ifc_divisors[idx];
}
static struct clk_ops sh7206_cpu_clk_ops = {
.recalc = cpu_clk_recalc,
};
static struct clk_ops *sh7206_clk_ops[] = {
&sh7206_master_clk_ops,
&sh7206_module_clk_ops,
&sh7206_bus_clk_ops,
&sh7206_cpu_clk_ops,
};
void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
{
if (idx < ARRAY_SIZE(sh7206_clk_ops))
*ops = sh7206_clk_ops[idx];
}

View File

@ -0,0 +1,39 @@
/*
* arch/sh/kernel/cpu/sh2a/probe.c
*
* CPU Subtype Probing for SH-2A.
*
* Copyright (C) 2004, 2005 Paul Mundt
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#include <linux/init.h>
#include <asm/processor.h>
#include <asm/cache.h>
int __init detect_cpu_and_cache_system(void)
{
/* Just SH7206 for now .. */
cpu_data->type = CPU_SH7206;
cpu_data->dcache.ways = 4;
cpu_data->dcache.way_incr = (1 << 11);
cpu_data->dcache.sets = 128;
cpu_data->dcache.entry_shift = 4;
cpu_data->dcache.linesz = L1_CACHE_BYTES;
cpu_data->dcache.flags = 0;
/*
* The icache is the same as the dcache as far as this setup is
* concerned. The only real difference in hardware is that the icache
* lacks the U bit that the dcache has, none of this has any bearing
* on the cache info.
*/
cpu_data->icache = cpu_data->dcache;
return 0;
}

View File

@ -0,0 +1,58 @@
/*
* SH7206 Setup
*
* Copyright (C) 2006 Yoshinori Sato
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#include <linux/platform_device.h>
#include <linux/init.h>
#include <linux/serial.h>
#include <asm/sci.h>
static struct plat_sci_port sci_platform_data[] = {
{
.mapbase = 0xfffe8000,
.flags = UPF_BOOT_AUTOCONF,
.type = PORT_SCIF,
.irqs = { 240, 241, 242, 243},
}, {
.mapbase = 0xfffe8800,
.flags = UPF_BOOT_AUTOCONF,
.type = PORT_SCIF,
.irqs = { 244, 245, 246, 247},
}, {
.mapbase = 0xfffe9000,
.flags = UPF_BOOT_AUTOCONF,
.type = PORT_SCIF,
.irqs = { 248, 249, 250, 251},
}, {
.mapbase = 0xfffe9800,
.flags = UPF_BOOT_AUTOCONF,
.type = PORT_SCIF,
.irqs = { 252, 253, 254, 255},
}, {
.flags = 0,
}
};
static struct platform_device sci_device = {
.name = "sh-sci",
.id = -1,
.dev = {
.platform_data = sci_platform_data,
},
};
static struct platform_device *sh7206_devices[] __initdata = {
&sci_device,
};
static int __init sh7206_devices_setup(void)
{
return platform_add_devices(sh7206_devices,
ARRAY_SIZE(sh7206_devices));
}
__initcall(sh7206_devices_setup);

View File

@ -2,7 +2,7 @@
# Makefile for the Linux/SuperH SH-3 backends.
#
obj-y := ex.o probe.o
obj-y := ex.o probe.o entry.o
# CPU subtype setup
obj-$(CONFIG_CPU_SUBTYPE_SH7705) += setup-sh7705.o

View File

@ -24,7 +24,7 @@ static int pfc_divisors[] = { 1, 2, 4, 1, 3, 6, 1, 1 };
static void set_bus_parent(struct clk *clk)
{
struct clk *bus_clk = clk_get("bus_clk");
struct clk *bus_clk = clk_get(NULL, "bus_clk");
clk->parent = bus_clk;
clk_put(bus_clk);
}

View File

@ -1,5 +1,5 @@
/*
* linux/arch/sh/entry.S
* arch/sh/kernel/entry.S
*
* Copyright (C) 1999, 2000, 2002 Niibe Yutaka
* Copyright (C) 2003 - 2006 Paul Mundt
@ -7,15 +7,16 @@
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
*/
#include <linux/sys.h>
#include <linux/errno.h>
#include <linux/linkage.h>
#include <asm/asm-offsets.h>
#include <asm/thread_info.h>
#include <asm/cpu/mmu_context.h>
#include <asm/unistd.h>
#include <asm/cpu/mmu_context.h>
#include <asm/pgtable.h>
#include <asm/page.h>
! NOTE:
! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address
@ -81,6 +82,8 @@ OFF_TRA = (16*4+6*4)
#define k_g_imask r6_bank /* r6_bank1 */
#define current r7 /* r7_bank1 */
#include <asm/entry-macros.S>
/*
* Kernel mode register usage:
* k0 scratch
@ -107,26 +110,6 @@ OFF_TRA = (16*4+6*4)
! this first version depends *much* on C implementation.
!
#define CLI() \
stc sr, r0; \
or #0xf0, r0; \
ldc r0, sr
#define STI() \
mov.l __INV_IMASK, r11; \
stc sr, r10; \
and r11, r10; \
stc k_g_imask, r11; \
or r11, r10; \
ldc r10, sr
#if defined(CONFIG_PREEMPT)
# define preempt_stop() CLI()
#else
# define preempt_stop()
# define resume_kernel restore_all
#endif
#if defined(CONFIG_MMU)
.align 2
ENTRY(tlb_miss_load)
@ -155,29 +138,14 @@ ENTRY(tlb_protection_violation_store)
call_dpf:
mov.l 1f, r0
mov r5, r8
mov.l @r0, r6
mov r6, r9
mov.l 2f, r0
sts pr, r10
jsr @r0
mov r15, r4
!
tst r0, r0
bf/s 0f
lds r10, pr
rts
nop
0: STI()
mov.l @r0, r6 ! address
mov.l 3f, r0
mov r9, r6
mov r8, r5
jmp @r0
mov r15, r4
mov r15, r4 ! regs
.align 2
1: .long MMU_TEA
2: .long __do_page_fault
3: .long do_page_fault
.align 2
@ -203,32 +171,6 @@ call_dae:
2: .long do_address_error
#endif /* CONFIG_MMU */
#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
! Handle kernel debug if either kgdb (SW) or gdb-stub (FW) is present.
! If both are configured, handle the debug traps (breakpoints) in SW,
! but still allow BIOS traps to FW.
.align 2
debug_kernel:
#if defined(CONFIG_SH_STANDARD_BIOS) && defined(CONFIG_SH_KGDB)
/* Force BIOS call to FW (debug_trap put TRA in r8) */
mov r8,r0
shlr2 r0
cmp/eq #0x3f,r0
bt debug_kernel_fw
#endif /* CONFIG_SH_STANDARD_BIOS && CONFIG_SH_KGDB */
debug_enter:
#if defined(CONFIG_SH_KGDB)
/* Jump to kgdb, pass stacked regs as arg */
debug_kernel_sw:
mov.l 3f, r0
jmp @r0
mov r15, r4
.align 2
3: .long kgdb_handle_exception
#endif /* CONFIG_SH_KGDB */
#if defined(CONFIG_SH_STANDARD_BIOS)
/* Unwind the stack and jmp to the debug entry */
debug_kernel_fw:
@ -269,276 +211,6 @@ debug_kernel_fw:
2: .long gdb_vbr_vector
#endif /* CONFIG_SH_STANDARD_BIOS */
#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */
.align 2
debug_trap:
#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
mov #OFF_SR, r0
mov.l @(r0,r15), r0 ! get status register
shll r0
shll r0 ! kernel space?
bt/s debug_kernel
#endif
mov.l @r15, r0 ! Restore R0 value
mov.l 1f, r8
jmp @r8
nop
.align 2
ENTRY(exception_error)
!
STI()
mov.l 2f, r0
jmp @r0
nop
!
.align 2
1: .long break_point_trap_software
2: .long do_exception_error
.align 2
ret_from_exception:
preempt_stop()
ENTRY(ret_from_irq)
!
mov #OFF_SR, r0
mov.l @(r0,r15), r0 ! get status register
shll r0
shll r0 ! kernel space?
bt/s resume_kernel ! Yes, it's from kernel, go back soon
GET_THREAD_INFO(r8)
#ifdef CONFIG_PREEMPT
bra resume_userspace
nop
ENTRY(resume_kernel)
mov.l @(TI_PRE_COUNT,r8), r0 ! current_thread_info->preempt_count
tst r0, r0
bf noresched
need_resched:
mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
tst #_TIF_NEED_RESCHED, r0 ! need_resched set?
bt noresched
mov #OFF_SR, r0
mov.l @(r0,r15), r0 ! get status register
and #0xf0, r0 ! interrupts off (exception path)?
cmp/eq #0xf0, r0
bt noresched
mov.l 1f, r0
mov.l r0, @(TI_PRE_COUNT,r8)
STI()
mov.l 2f, r0
jsr @r0
nop
mov #0, r0
mov.l r0, @(TI_PRE_COUNT,r8)
CLI()
bra need_resched
nop
noresched:
bra restore_all
nop
.align 2
1: .long PREEMPT_ACTIVE
2: .long schedule
#endif
ENTRY(resume_userspace)
! r8: current_thread_info
CLI()
mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
tst #_TIF_WORK_MASK, r0
bt/s restore_all
tst #_TIF_NEED_RESCHED, r0
.align 2
work_pending:
! r0: current_thread_info->flags
! r8: current_thread_info
! t: result of "tst #_TIF_NEED_RESCHED, r0"
bf/s work_resched
tst #(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), r0
work_notifysig:
bt/s restore_all
mov r15, r4
mov r12, r5 ! set arg1(save_r0)
mov r0, r6
mov.l 2f, r1
mova restore_all, r0
jmp @r1
lds r0, pr
work_resched:
#ifndef CONFIG_PREEMPT
! gUSA handling
mov.l @(OFF_SP,r15), r0 ! get user space stack pointer
mov r0, r1
shll r0
bf/s 1f
shll r0
bf/s 1f
mov #OFF_PC, r0
! SP >= 0xc0000000 : gUSA mark
mov.l @(r0,r15), r2 ! get user space PC (program counter)
mov.l @(OFF_R0,r15), r3 ! end point
cmp/hs r3, r2 ! r2 >= r3?
bt 1f
add r3, r1 ! rewind point #2
mov.l r1, @(r0,r15) ! reset PC to rewind point #2
!
1:
#endif
mov.l 1f, r1
jsr @r1 ! schedule
nop
CLI()
!
mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
tst #_TIF_WORK_MASK, r0
bt restore_all
bra work_pending
tst #_TIF_NEED_RESCHED, r0
.align 2
1: .long schedule
2: .long do_notify_resume
.align 2
syscall_exit_work:
! r0: current_thread_info->flags
! r8: current_thread_info
tst #_TIF_SYSCALL_TRACE, r0
bt/s work_pending
tst #_TIF_NEED_RESCHED, r0
STI()
! XXX setup arguments...
mov.l 4f, r0 ! do_syscall_trace
jsr @r0
nop
bra resume_userspace
nop
.align 2
syscall_trace_entry:
! Yes it is traced.
! XXX setup arguments...
mov.l 4f, r11 ! Call do_syscall_trace which notifies
jsr @r11 ! superior (will chomp R[0-7])
nop
! Reload R0-R4 from kernel stack, where the
! parent may have modified them using
! ptrace(POKEUSR). (Note that R0-R2 are
! used by the system call handler directly
! from the kernel stack anyway, so don't need
! to be reloaded here.) This allows the parent
! to rewrite system calls and args on the fly.
mov.l @(OFF_R4,r15), r4 ! arg0
mov.l @(OFF_R5,r15), r5
mov.l @(OFF_R6,r15), r6
mov.l @(OFF_R7,r15), r7 ! arg3
mov.l @(OFF_R3,r15), r3 ! syscall_nr
! Arrange for do_syscall_trace to be called
! again as the system call returns.
mov.l 2f, r10 ! Number of syscalls
cmp/hs r10, r3
bf syscall_call
mov #-ENOSYS, r0
bra syscall_exit
mov.l r0, @(OFF_R0,r15) ! Return value
/*
* Syscall interface:
*
* Syscall #: R3
* Arguments #0 to #3: R4--R7
* Arguments #4 to #6: R0, R1, R2
* TRA: (number of arguments + 0x10) x 4
*
* This code also handles delegating other traps to the BIOS/gdb stub
* according to:
*
* Trap number
* (TRA>>2) Purpose
* -------- -------
* 0x0-0xf old syscall ABI
* 0x10-0x1f new syscall ABI
* 0x20-0xff delegated through debug_trap to BIOS/gdb stub.
*
* Note: When we're first called, the TRA value must be shifted
* right 2 bits in order to get the value that was used as the "trapa"
* argument.
*/
.align 2
.globl ret_from_fork
ret_from_fork:
mov.l 1f, r8
jsr @r8
mov r0, r4
bra syscall_exit
nop
.align 2
1: .long schedule_tail
!
ENTRY(system_call)
mov.l 1f, r9
mov.l @r9, r8 ! Read from TRA (Trap Address) Register
!
! Is the trap argument >= 0x20? (TRA will be >= 0x80)
mov #0x7f, r9
cmp/hi r9, r8
bt/s 0f
mov #OFF_TRA, r9
add r15, r9
!
mov.l r8, @r9 ! set TRA value to tra
STI()
! Call the system call handler through the table.
! First check for bad syscall number
mov r3, r9
mov.l 2f, r8 ! Number of syscalls
cmp/hs r8, r9
bf/s good_system_call
GET_THREAD_INFO(r8)
syscall_badsys: ! Bad syscall number
mov #-ENOSYS, r0
bra resume_userspace
mov.l r0, @(OFF_R0,r15) ! Return value
!
0:
bra debug_trap
nop
!
good_system_call: ! Good syscall number
mov.l @(TI_FLAGS,r8), r8
mov #_TIF_SYSCALL_TRACE, r10
tst r10, r8
bf syscall_trace_entry
!
syscall_call:
shll2 r9 ! x4
mov.l 3f, r8 ! Load the address of sys_call_table
add r8, r9
mov.l @r9, r8
jsr @r8 ! jump to specific syscall handler
nop
mov.l @(OFF_R0,r15), r12 ! save r0
mov.l r0, @(OFF_R0,r15) ! save the return value
!
syscall_exit:
CLI()
!
GET_THREAD_INFO(r8)
mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
tst #_TIF_ALLWORK_MASK, r0
bf syscall_exit_work
restore_all:
mov.l @r15+, r0
mov.l @r15+, r1
@ -606,7 +278,9 @@ skip_restore:
!
! Calculate new SR value
mov k3, k2 ! original SR value
mov.l 9f, k1
mov #0xf0, k1
extu.b k1, k1
not k1, k1
and k1, k2 ! Mask orignal SR value
!
mov k3, k0 ! Calculate IMASK-bits
@ -632,16 +306,12 @@ skip_restore:
nop
.align 2
1: .long TRA
2: .long NR_syscalls
3: .long sys_call_table
4: .long do_syscall_trace
5: .long 0x00001000 ! DSP
7: .long 0x30000000
9:
__INV_IMASK:
.long 0xffffff0f ! ~(IMASK)
! common exception handler
#include "../../entry-common.S"
! Exception Vector Base
!
! Should be aligned page boundary.
@ -661,9 +331,176 @@ general_exception:
2: .long ret_from_exception
!
!
/* This code makes some assumptions to improve performance.
* Make sure they are stil true. */
#if PTRS_PER_PGD != PTRS_PER_PTE
#error PGD and PTE sizes don't match
#endif
/* gas doesn't flag impossible values for mov #immediate as an error */
#if (_PAGE_PRESENT >> 2) > 0x7f
#error cannot load PAGE_PRESENT as an immediate
#endif
#if _PAGE_DIRTY > 0x7f
#error cannot load PAGE_DIRTY as an immediate
#endif
#if (_PAGE_PRESENT << 2) != _PAGE_ACCESSED
#error cannot derive PAGE_ACCESSED from PAGE_PRESENT
#endif
#if defined(CONFIG_CPU_SH4)
#define ldmmupteh(r) mov.l 8f, r
#else
#define ldmmupteh(r) mov #MMU_PTEH, r
#endif
.balign 1024,0,1024
tlb_miss:
mov.l 1f, k2
#ifdef COUNT_EXCEPTIONS
! Increment the counts
mov.l 9f, k1
mov.l @k1, k2
add #1, k2
mov.l k2, @k1
#endif
! k0 scratch
! k1 pgd and pte pointers
! k2 faulting address
! k3 pgd and pte index masks
! k4 shift
! Load up the pgd entry (k1)
ldmmupteh(k0) ! 9 LS (latency=2) MMU_PTEH
mov.w 4f, k3 ! 8 LS (latency=2) (PTRS_PER_PGD-1) << 2
mov #-(PGDIR_SHIFT-2), k4 ! 6 EX
mov.l @(MMU_TEA-MMU_PTEH,k0), k2 ! 18 LS (latency=2)
mov.l @(MMU_TTB-MMU_PTEH,k0), k1 ! 18 LS (latency=2)
mov k2, k0 ! 5 MT (latency=0)
shld k4, k0 ! 99 EX
and k3, k0 ! 78 EX
mov.l @(k0, k1), k1 ! 21 LS (latency=2)
mov #-(PAGE_SHIFT-2), k4 ! 6 EX
! Load up the pte entry (k2)
mov k2, k0 ! 5 MT (latency=0)
shld k4, k0 ! 99 EX
tst k1, k1 ! 86 MT
bt 20f ! 110 BR
and k3, k0 ! 78 EX
mov.w 5f, k4 ! 8 LS (latency=2) _PAGE_PRESENT
mov.l @(k0, k1), k2 ! 21 LS (latency=2)
add k0, k1 ! 49 EX
#ifdef CONFIG_CPU_HAS_PTEA
! Test the entry for present and _PAGE_ACCESSED
mov #-28, k3 ! 6 EX
mov k2, k0 ! 5 MT (latency=0)
tst k4, k2 ! 68 MT
shld k3, k0 ! 99 EX
bt 20f ! 110 BR
! Set PTEA register
! MMU_PTEA = ((pteval >> 28) & 0xe) | (pteval & 0x1)
!
! k0=pte>>28, k1=pte*, k2=pte, k3=<unused>, k4=_PAGE_PRESENT
and #0xe, k0 ! 79 EX
mov k0, k3 ! 5 MT (latency=0)
mov k2, k0 ! 5 MT (latency=0)
and #1, k0 ! 79 EX
or k0, k3 ! 82 EX
ldmmupteh(k0) ! 9 LS (latency=2)
shll2 k4 ! 101 EX _PAGE_ACCESSED
tst k4, k2 ! 68 MT
mov.l k3, @(MMU_PTEA-MMU_PTEH,k0) ! 27 LS
mov.l 7f, k3 ! 9 LS (latency=2) _PAGE_FLAGS_HARDWARE_MASK
! k0=MMU_PTEH, k1=pte*, k2=pte, k3=_PAGE_FLAGS_HARDWARE, k4=_PAGE_ACCESSED
#else
! Test the entry for present and _PAGE_ACCESSED
mov.l 7f, k3 ! 9 LS (latency=2) _PAGE_FLAGS_HARDWARE_MASK
tst k4, k2 ! 68 MT
shll2 k4 ! 101 EX _PAGE_ACCESSED
ldmmupteh(k0) ! 9 LS (latency=2)
bt 20f ! 110 BR
tst k4, k2 ! 68 MT
! k0=MMU_PTEH, k1=pte*, k2=pte, k3=_PAGE_FLAGS_HARDWARE, k4=_PAGE_ACCESSED
#endif
! Set up the entry
and k2, k3 ! 78 EX
bt/s 10f ! 108 BR
mov.l k3, @(MMU_PTEL-MMU_PTEH,k0) ! 27 LS
ldtlb ! 128 CO
! At least one instruction between ldtlb and rte
nop ! 119 NOP
rte ! 126 CO
nop ! 119 NOP
10: or k4, k2 ! 82 EX
ldtlb ! 128 CO
! At least one instruction between ldtlb and rte
mov.l k2, @k1 ! 27 LS
rte ! 126 CO
! Note we cannot execute mov here, because it is executed after
! restoring SSR, so would be executed in user space.
nop ! 119 NOP
.align 5
! Once cache line if possible...
1: .long swapper_pg_dir
4: .short (PTRS_PER_PGD-1) << 2
5: .short _PAGE_PRESENT
7: .long _PAGE_FLAGS_HARDWARE_MASK
8: .long MMU_PTEH
#ifdef COUNT_EXCEPTIONS
9: .long exception_count_miss
#endif
! Either pgd or pte not present
20: mov.l 1f, k2
mov.l 4f, k3
bra handle_exception
mov.l @k2, k2
@ -710,8 +547,9 @@ ENTRY(handle_exception)
bt/s 1f ! It's a kernel to kernel transition.
mov r15, k0 ! save original stack to k0
/* User space to kernel */
mov #(THREAD_SIZE >> 8), k1
mov #(THREAD_SIZE >> 10), k1
shll8 k1 ! k1 := THREAD_SIZE
shll2 k1
add current, k1
mov k1, r15 ! change to kernel stack
!
@ -761,7 +599,7 @@ skip_save:
! Save the user registers on the stack.
mov.l k2, @-r15 ! EXPEVT
mov #-1, k4
mov #-1, k4
mov.l k4, @-r15 ! set TRA (default: -1)
!
sts.l macl, @-r15
@ -813,6 +651,15 @@ skip_save:
bf interrupt_exception
shlr2 r8
shlr r8
#ifdef COUNT_EXCEPTIONS
mov.l 5f, r9
add r8, r9
mov.l @r9, r10
add #1, r10
mov.l r10, @r9
#endif
mov.l 4f, r9
add r8, r9
mov.l @r9, r9
@ -826,6 +673,9 @@ skip_save:
2: .long 0x000080f0 ! FD=1, IMASK=15
3: .long 0xcfffffff ! RB=0, BL=0
4: .long exception_handling_table
#ifdef COUNT_EXCEPTIONS
5: .long exception_count_table
#endif
interrupt_exception:
mov.l 1f, r9

View File

@ -2,7 +2,8 @@
# Makefile for the Linux/SuperH SH-4 backends.
#
obj-y := ex.o probe.o
obj-y := ex.o probe.o common.o
common-y += $(addprefix ../sh3/, entry.o)
obj-$(CONFIG_SH_FPU) += fpu.o
obj-$(CONFIG_SH_STORE_QUEUES) += sq.o

View File

@ -97,7 +97,7 @@ static void shoc_clk_recalc(struct clk *clk)
static int shoc_clk_verify_rate(struct clk *clk, unsigned long rate)
{
struct clk *bclk = clk_get("bus_clk");
struct clk *bclk = clk_get(NULL, "bus_clk");
unsigned long bclk_rate = clk_get_rate(bclk);
clk_put(bclk);
@ -151,7 +151,7 @@ static struct clk *sh4202_onchip_clocks[] = {
static int __init sh4202_clk_init(void)
{
struct clk *clk = clk_get("master_clk");
struct clk *clk = clk_get(NULL, "master_clk");
int i;
for (i = 0; i < ARRAY_SIZE(sh4202_onchip_clocks); i++) {

View File

@ -98,7 +98,7 @@ static struct clk *sh7780_onchip_clocks[] = {
static int __init sh7780_clk_init(void)
{
struct clk *clk = clk_get("master_clk");
struct clk *clk = clk_get(NULL, "master_clk");
int i;
for (i = 0; i < ARRAY_SIZE(sh7780_onchip_clocks); i++) {

View File

@ -282,11 +282,8 @@ ieee_fpe_handler (struct pt_regs *regs)
grab_fpu(regs);
restore_fpu(tsk);
set_tsk_thread_flag(tsk, TIF_USEDFPU);
} else {
tsk->thread.trap_no = 11;
tsk->thread.error_code = 0;
} else
force_sig(SIGFPE, tsk);
}
regs->pc = nextpc;
return 1;
@ -296,29 +293,29 @@ ieee_fpe_handler (struct pt_regs *regs)
}
asmlinkage void
do_fpu_error(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7,
struct pt_regs regs)
do_fpu_error(unsigned long r4, unsigned long r5, unsigned long r6,
unsigned long r7, struct pt_regs __regs)
{
struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
struct task_struct *tsk = current;
if (ieee_fpe_handler (&regs))
if (ieee_fpe_handler(regs))
return;
regs.pc += 2;
save_fpu(tsk, &regs);
tsk->thread.trap_no = 11;
tsk->thread.error_code = 0;
regs->pc += 2;
save_fpu(tsk, regs);
force_sig(SIGFPE, tsk);
}
asmlinkage void
do_fpu_state_restore(unsigned long r4, unsigned long r5, unsigned long r6,
unsigned long r7, struct pt_regs regs)
unsigned long r7, struct pt_regs __regs)
{
struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
struct task_struct *tsk = current;
grab_fpu(&regs);
if (!user_mode(&regs)) {
grab_fpu(regs);
if (!user_mode(regs)) {
printk(KERN_ERR "BUG: FPU is used in kernel mode.\n");
return;
}

View File

@ -79,16 +79,16 @@ int __init detect_cpu_and_cache_system(void)
case 0x205:
cpu_data->type = CPU_SH7750;
cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU |
CPU_HAS_PERF_COUNTER | CPU_HAS_PTEA;
CPU_HAS_PERF_COUNTER;
break;
case 0x206:
cpu_data->type = CPU_SH7750S;
cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU |
CPU_HAS_PERF_COUNTER | CPU_HAS_PTEA;
CPU_HAS_PERF_COUNTER;
break;
case 0x1100:
cpu_data->type = CPU_SH7751;
cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA;
cpu_data->flags |= CPU_HAS_FPU;
break;
case 0x2000:
cpu_data->type = CPU_SH73180;
@ -126,23 +126,22 @@ int __init detect_cpu_and_cache_system(void)
break;
case 0x8000:
cpu_data->type = CPU_ST40RA;
cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA;
cpu_data->flags |= CPU_HAS_FPU;
break;
case 0x8100:
cpu_data->type = CPU_ST40GX1;
cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA;
cpu_data->flags |= CPU_HAS_FPU;
break;
case 0x700:
cpu_data->type = CPU_SH4_501;
cpu_data->icache.ways = 2;
cpu_data->dcache.ways = 2;
cpu_data->flags |= CPU_HAS_PTEA;
break;
case 0x600:
cpu_data->type = CPU_SH4_202;
cpu_data->icache.ways = 2;
cpu_data->dcache.ways = 2;
cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA;
cpu_data->flags |= CPU_HAS_FPU;
break;
case 0x500 ... 0x501:
switch (prr) {
@ -160,7 +159,7 @@ int __init detect_cpu_and_cache_system(void)
cpu_data->icache.ways = 2;
cpu_data->dcache.ways = 2;
cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA;
cpu_data->flags |= CPU_HAS_FPU;
break;
default:
@ -173,6 +172,10 @@ int __init detect_cpu_and_cache_system(void)
cpu_data->dcache.ways = 1;
#endif
#ifdef CONFIG_CPU_HAS_PTEA
cpu_data->flags |= CPU_HAS_PTEA;
#endif
/*
* On anything that's not a direct-mapped cache, look to the CVR
* for I/D-cache specifics.

View File

@ -2,6 +2,7 @@
* SH7750/SH7751 Setup
*
* Copyright (C) 2006 Paul Mundt
* Copyright (C) 2006 Jamie Lenehan
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
@ -10,6 +11,7 @@
#include <linux/platform_device.h>
#include <linux/init.h>
#include <linux/serial.h>
#include <linux/io.h>
#include <asm/sci.h>
static struct plat_sci_port sci_platform_data[] = {
@ -46,3 +48,71 @@ static int __init sh7750_devices_setup(void)
ARRAY_SIZE(sh7750_devices));
}
__initcall(sh7750_devices_setup);
static struct ipr_data sh7750_ipr_map[] = {
/* IRQ, IPR-idx, shift, priority */
{ 16, 0, 12, 2 }, /* TMU0 TUNI*/
{ 17, 0, 12, 2 }, /* TMU1 TUNI */
{ 18, 0, 4, 2 }, /* TMU2 TUNI */
{ 19, 0, 4, 2 }, /* TMU2 TIPCI */
{ 27, 1, 12, 2 }, /* WDT ITI */
{ 20, 0, 0, 2 }, /* RTC ATI (alarm) */
{ 21, 0, 0, 2 }, /* RTC PRI (period) */
{ 22, 0, 0, 2 }, /* RTC CUI (carry) */
{ 23, 1, 4, 3 }, /* SCI ERI */
{ 24, 1, 4, 3 }, /* SCI RXI */
{ 25, 1, 4, 3 }, /* SCI TXI */
{ 40, 2, 4, 3 }, /* SCIF ERI */
{ 41, 2, 4, 3 }, /* SCIF RXI */
{ 42, 2, 4, 3 }, /* SCIF BRI */
{ 43, 2, 4, 3 }, /* SCIF TXI */
{ 34, 2, 8, 7 }, /* DMAC DMTE0 */
{ 35, 2, 8, 7 }, /* DMAC DMTE1 */
{ 36, 2, 8, 7 }, /* DMAC DMTE2 */
{ 37, 2, 8, 7 }, /* DMAC DMTE3 */
{ 28, 2, 8, 7 }, /* DMAC DMAE */
};
static struct ipr_data sh7751_ipr_map[] = {
{ 44, 2, 8, 7 }, /* DMAC DMTE4 */
{ 45, 2, 8, 7 }, /* DMAC DMTE5 */
{ 46, 2, 8, 7 }, /* DMAC DMTE6 */
{ 47, 2, 8, 7 }, /* DMAC DMTE7 */
/* The following use INTC_INPRI00 for masking, which is a 32-bit
register, not a 16-bit register like the IPRx registers, so it
would need special support */
/*{ 72, INTPRI00, 8, ? },*/ /* TMU3 TUNI */
/*{ 76, INTPRI00, 12, ? },*/ /* TMU4 TUNI */
};
static unsigned long ipr_offsets[] = {
0xffd00004UL, /* 0: IPRA */
0xffd00008UL, /* 1: IPRB */
0xffd0000cUL, /* 2: IPRC */
0xffd00010UL, /* 3: IPRD */
};
/* given the IPR index return the address of the IPR register */
unsigned int map_ipridx_to_addr(int idx)
{
if (idx >= ARRAY_SIZE(ipr_offsets))
return 0;
return ipr_offsets[idx];
}
#define INTC_ICR 0xffd00000UL
#define INTC_ICR_IRLM (1<<7)
/* enable individual interrupt mode for external interupts */
void ipr_irq_enable_irlm(void)
{
ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);
}
void __init init_IRQ_ipr()
{
make_ipr_irq(sh7750_ipr_map, ARRAY_SIZE(sh7750_ipr_map));
#ifdef CONFIG_CPU_SUBTYPE_SH7751
make_ipr_irq(sh7751_ipr_map, ARRAY_SIZE(sh7751_ipr_map));
#endif
}

View File

@ -79,25 +79,27 @@ static int __init sh7780_devices_setup(void)
__initcall(sh7780_devices_setup);
static struct intc2_data intc2_irq_table[] = {
{ TIMER_IRQ, 0, 24, 0, INTC_TMU0_MSK, 2 },
{ 21, 1, 0, 0, INTC_RTC_MSK, TIMER_PRIORITY },
{ 22, 1, 1, 0, INTC_RTC_MSK, TIMER_PRIORITY },
{ 23, 1, 2, 0, INTC_RTC_MSK, TIMER_PRIORITY },
{ SCIF0_ERI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY },
{ SCIF0_RXI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY },
{ SCIF0_BRI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY },
{ SCIF0_TXI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY },
{ 28, 0, 24, 0, 0, 2 }, /* TMU0 */
{ SCIF1_ERI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY },
{ SCIF1_RXI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY },
{ SCIF1_BRI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY },
{ SCIF1_TXI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY },
{ 21, 1, 0, 0, 2, 2 },
{ 22, 1, 1, 0, 2, 2 },
{ 23, 1, 2, 0, 2, 2 },
{ PCIC0_IRQ, 0x10, 8, 0, INTC_PCIC0_MSK, PCIC0_PRIORITY },
{ PCIC1_IRQ, 0x10, 0, 0, INTC_PCIC1_MSK, PCIC1_PRIORITY },
{ PCIC2_IRQ, 0x14, 24, 0, INTC_PCIC2_MSK, PCIC2_PRIORITY },
{ PCIC3_IRQ, 0x14, 16, 0, INTC_PCIC3_MSK, PCIC3_PRIORITY },
{ PCIC4_IRQ, 0x14, 8, 0, INTC_PCIC4_MSK, PCIC4_PRIORITY },
{ 40, 8, 24, 0, 3, 3 }, /* SCIF0 ERI */
{ 41, 8, 24, 0, 3, 3 }, /* SCIF0 RXI */
{ 42, 8, 24, 0, 3, 3 }, /* SCIF0 BRI */
{ 43, 8, 24, 0, 3, 3 }, /* SCIF0 TXI */
{ 76, 8, 16, 0, 4, 3 }, /* SCIF1 ERI */
{ 77, 8, 16, 0, 4, 3 }, /* SCIF1 RXI */
{ 78, 8, 16, 0, 4, 3 }, /* SCIF1 BRI */
{ 79, 8, 16, 0, 4, 3 }, /* SCIF1 TXI */
{ 64, 0x10, 8, 0, 14, 2 }, /* PCIC0 */
{ 65, 0x10, 0, 0, 15, 2 }, /* PCIC1 */
{ 66, 0x14, 24, 0, 16, 2 }, /* PCIC2 */
{ 67, 0x14, 16, 0, 17, 2 }, /* PCIC3 */
{ 68, 0x14, 8, 0, 18, 2 }, /* PCIC4 */
};
void __init init_IRQ_intc2(void)

View File

@ -19,7 +19,7 @@
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/mm.h>
#include <asm/io.h>
#include <linux/io.h>
#include <asm/page.h>
#include <asm/cacheflush.h>
#include <asm/cpu/sq.h>
@ -67,6 +67,7 @@ void sq_flush_range(unsigned long start, unsigned int len)
/* Wait for completion */
store_queue_barrier();
}
EXPORT_SYMBOL(sq_flush_range);
static inline void sq_mapping_list_add(struct sq_mapping *map)
{
@ -166,7 +167,7 @@ unsigned long sq_remap(unsigned long phys, unsigned int size,
map->size = size;
map->name = name;
page = bitmap_find_free_region(sq_bitmap, 0x04000000,
page = bitmap_find_free_region(sq_bitmap, 0x04000000 >> PAGE_SHIFT,
get_order(map->size));
if (unlikely(page < 0)) {
ret = -ENOSPC;
@ -193,6 +194,7 @@ out:
kmem_cache_free(sq_cache, map);
return ret;
}
EXPORT_SYMBOL(sq_remap);
/**
* sq_unmap - Unmap a Store Queue allocation
@ -234,6 +236,7 @@ void sq_unmap(unsigned long vaddr)
kmem_cache_free(sq_cache, map);
}
EXPORT_SYMBOL(sq_unmap);
/*
* Needlessly complex sysfs interface. Unfortunately it doesn't seem like
@ -402,7 +405,3 @@ module_exit(sq_api_exit);
MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>, M. R. Brown <mrbrown@0xd6.org>");
MODULE_DESCRIPTION("Simple API for SH-4 integrated Store Queues");
MODULE_LICENSE("GPL");
EXPORT_SYMBOL(sq_remap);
EXPORT_SYMBOL(sq_unmap);
EXPORT_SYMBOL(sq_flush_range);

View File

@ -12,7 +12,7 @@
#include <linux/console.h>
#include <linux/tty.h>
#include <linux/init.h>
#include <asm/io.h>
#include <linux/io.h>
#ifdef CONFIG_SH_STANDARD_BIOS
#include <asm/sh_bios.h>
@ -62,17 +62,9 @@ static struct console bios_console = {
#include <linux/serial_core.h>
#include "../../../drivers/serial/sh-sci.h"
#ifdef CONFIG_CPU_SH4
#define SCIF_REG 0xffe80000
#elif defined(CONFIG_CPU_SUBTYPE_SH72060)
#define SCIF_REG 0xfffe9800
#else
#error "Undefined SCIF for this subtype"
#endif
static struct uart_port scif_port = {
.mapbase = SCIF_REG,
.membase = (char __iomem *)SCIF_REG,
.mapbase = CONFIG_EARLY_SCIF_CONSOLE_PORT,
.membase = (char __iomem *)CONFIG_EARLY_SCIF_CONSOLE_PORT,
};
static void scif_sercon_putc(int c)
@ -113,23 +105,29 @@ static struct console scif_console = {
.index = -1,
};
#if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SH_STANDARD_BIOS)
/*
* Simple SCIF init, primarily aimed at SH7750 and other similar SH-4
* devices that aren't using sh-ipl+g.
*/
static void scif_sercon_init(int baud)
{
ctrl_outw(0, SCIF_REG + 8);
ctrl_outw(0, SCIF_REG);
ctrl_outw(0, scif_port.mapbase + 8);
ctrl_outw(0, scif_port.mapbase);
/* Set baud rate */
ctrl_outb((CONFIG_SH_PCLK_FREQ + 16 * baud) /
(32 * baud) - 1, SCIF_REG + 4);
(32 * baud) - 1, scif_port.mapbase + 4);
ctrl_outw(12, SCIF_REG + 24);
ctrl_outw(8, SCIF_REG + 24);
ctrl_outw(0, SCIF_REG + 32);
ctrl_outw(0x60, SCIF_REG + 16);
ctrl_outw(0, SCIF_REG + 36);
ctrl_outw(0x30, SCIF_REG + 8);
ctrl_outw(12, scif_port.mapbase + 24);
ctrl_outw(8, scif_port.mapbase + 24);
ctrl_outw(0, scif_port.mapbase + 32);
ctrl_outw(0x60, scif_port.mapbase + 16);
ctrl_outw(0, scif_port.mapbase + 36);
ctrl_outw(0x30, scif_port.mapbase + 8);
}
#endif
#endif /* CONFIG_CPU_SH4 && !CONFIG_SH_STANDARD_BIOS */
#endif /* CONFIG_EARLY_SCIF_CONSOLE */
/*
* Setup a default console, if more than one is compiled in, rely on the
@ -168,7 +166,7 @@ int __init setup_early_printk(char *opt)
if (!strncmp(buf, "serial", 6)) {
early_console = &scif_console;
#ifdef CONFIG_CPU_SH4
#if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SH_STANDARD_BIOS)
scif_sercon_init(115200);
#endif
}

View File

@ -0,0 +1,433 @@
/* $Id: entry.S,v 1.37 2004/06/11 13:02:46 doyu Exp $
*
* linux/arch/sh/entry.S
*
* Copyright (C) 1999, 2000, 2002 Niibe Yutaka
* Copyright (C) 2003 Paul Mundt
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
*/
! NOTE:
! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address
! to be jumped is too far, but it causes illegal slot exception.
/*
* entry.S contains the system-call and fault low-level handling routines.
* This also contains the timer-interrupt handler, as well as all interrupts
* and faults that can result in a task-switch.
*
* NOTE: This code handles signal-recognition, which happens every time
* after a timer-interrupt and after each system call.
*
* NOTE: This code uses a convention that instructions in the delay slot
* of a transfer-control instruction are indented by an extra space, thus:
*
* jmp @k0 ! control-transfer instruction
* ldc k1, ssr ! delay slot
*
* Stack layout in 'ret_from_syscall':
* ptrace needs to have all regs on the stack.
* if the order here is changed, it needs to be
* updated in ptrace.c and ptrace.h
*
* r0
* ...
* r15 = stack pointer
* spc
* pr
* ssr
* gbr
* mach
* macl
* syscall #
*
*/
#if defined(CONFIG_PREEMPT)
# define preempt_stop() cli
#else
# define preempt_stop()
# define resume_kernel __restore_all
#endif
#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
! Handle kernel debug if either kgdb (SW) or gdb-stub (FW) is present.
! If both are configured, handle the debug traps (breakpoints) in SW,
! but still allow BIOS traps to FW.
.align 2
debug_kernel:
#if defined(CONFIG_SH_STANDARD_BIOS) && defined(CONFIG_SH_KGDB)
/* Force BIOS call to FW (debug_trap put TRA in r8) */
mov r8,r0
shlr2 r0
cmp/eq #0x3f,r0
bt debug_kernel_fw
#endif /* CONFIG_SH_STANDARD_BIOS && CONFIG_SH_KGDB */
debug_enter:
#if defined(CONFIG_SH_KGDB)
/* Jump to kgdb, pass stacked regs as arg */
debug_kernel_sw:
mov.l 3f, r0
jmp @r0
mov r15, r4
.align 2
3: .long kgdb_handle_exception
#endif /* CONFIG_SH_KGDB */
#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */
.align 2
debug_trap:
#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
mov #OFF_SR, r0
mov.l @(r0,r15), r0 ! get status register
shll r0
shll r0 ! kernel space?
bt/s debug_kernel
#endif
mov.l @r15, r0 ! Restore R0 value
mov.l 1f, r8
jmp @r8
nop
.align 2
ENTRY(exception_error)
!
#ifdef CONFIG_TRACE_IRQFLAGS
mov.l 3f, r0
jsr @r0
nop
#endif
sti
mov.l 2f, r0
jmp @r0
nop
!
.align 2
1: .long break_point_trap_software
2: .long do_exception_error
#ifdef CONFIG_TRACE_IRQFLAGS
3: .long trace_hardirqs_on
#endif
.align 2
ret_from_exception:
preempt_stop()
#ifdef CONFIG_TRACE_IRQFLAGS
mov.l 4f, r0
jsr @r0
nop
#endif
ENTRY(ret_from_irq)
!
mov #OFF_SR, r0
mov.l @(r0,r15), r0 ! get status register
shll r0
shll r0 ! kernel space?
get_current_thread_info r8, r0
bt resume_kernel ! Yes, it's from kernel, go back soon
#ifdef CONFIG_PREEMPT
bra resume_userspace
nop
ENTRY(resume_kernel)
mov.l @(TI_PRE_COUNT,r8), r0 ! current_thread_info->preempt_count
tst r0, r0
bf noresched
need_resched:
mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
tst #_TIF_NEED_RESCHED, r0 ! need_resched set?
bt noresched
mov #OFF_SR, r0
mov.l @(r0,r15), r0 ! get status register
and #0xf0, r0 ! interrupts off (exception path)?
cmp/eq #0xf0, r0
bt noresched
mov.l 1f, r0
mov.l r0, @(TI_PRE_COUNT,r8)
#ifdef CONFIG_TRACE_IRQFLAGS
mov.l 3f, r0
jsr @r0
nop
#endif
sti
mov.l 2f, r0
jsr @r0
nop
mov #0, r0
mov.l r0, @(TI_PRE_COUNT,r8)
cli
#ifdef CONFIG_TRACE_IRQFLAGS
mov.l 4f, r0
jsr @r0
nop
#endif
bra need_resched
nop
noresched:
bra __restore_all
nop
.align 2
1: .long PREEMPT_ACTIVE
2: .long schedule
#ifdef CONFIG_TRACE_IRQFLAGS
3: .long trace_hardirqs_on
4: .long trace_hardirqs_off
#endif
#endif
ENTRY(resume_userspace)
! r8: current_thread_info
cli
#ifdef CONFIG_TRACE_IRQFLAGS
mov.l 5f, r0
jsr @r0
nop
#endif
mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
tst #_TIF_WORK_MASK, r0
bt/s __restore_all
tst #_TIF_NEED_RESCHED, r0
.align 2
work_pending:
! r0: current_thread_info->flags
! r8: current_thread_info
! t: result of "tst #_TIF_NEED_RESCHED, r0"
bf/s work_resched
tst #(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), r0
work_notifysig:
bt/s __restore_all
mov r15, r4
mov r12, r5 ! set arg1(save_r0)
mov r0, r6
mov.l 2f, r1
mov.l 3f, r0
jmp @r1
lds r0, pr
work_resched:
#ifndef CONFIG_PREEMPT
! gUSA handling
mov.l @(OFF_SP,r15), r0 ! get user space stack pointer
mov r0, r1
shll r0
bf/s 1f
shll r0
bf/s 1f
mov #OFF_PC, r0
! SP >= 0xc0000000 : gUSA mark
mov.l @(r0,r15), r2 ! get user space PC (program counter)
mov.l @(OFF_R0,r15), r3 ! end point
cmp/hs r3, r2 ! r2 >= r3?
bt 1f
add r3, r1 ! rewind point #2
mov.l r1, @(r0,r15) ! reset PC to rewind point #2
!
1:
#endif
mov.l 1f, r1
jsr @r1 ! schedule
nop
cli
#ifdef CONFIG_TRACE_IRQFLAGS
mov.l 5f, r0
jsr @r0
nop
#endif
!
mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
tst #_TIF_WORK_MASK, r0
bt __restore_all
bra work_pending
tst #_TIF_NEED_RESCHED, r0
.align 2
1: .long schedule
2: .long do_notify_resume
3: .long restore_all
#ifdef CONFIG_TRACE_IRQFLAGS
4: .long trace_hardirqs_on
5: .long trace_hardirqs_off
#endif
.align 2
syscall_exit_work:
! r0: current_thread_info->flags
! r8: current_thread_info
tst #_TIF_SYSCALL_TRACE, r0
bt/s work_pending
tst #_TIF_NEED_RESCHED, r0
#ifdef CONFIG_TRACE_IRQFLAGS
mov.l 5f, r0
jsr @r0
nop
#endif
sti
! XXX setup arguments...
mov.l 4f, r0 ! do_syscall_trace
jsr @r0
nop
bra resume_userspace
nop
.align 2
syscall_trace_entry:
! Yes it is traced.
! XXX setup arguments...
mov.l 4f, r11 ! Call do_syscall_trace which notifies
jsr @r11 ! superior (will chomp R[0-7])
nop
! Reload R0-R4 from kernel stack, where the
! parent may have modified them using
! ptrace(POKEUSR). (Note that R0-R2 are
! used by the system call handler directly
! from the kernel stack anyway, so don't need
! to be reloaded here.) This allows the parent
! to rewrite system calls and args on the fly.
mov.l @(OFF_R4,r15), r4 ! arg0
mov.l @(OFF_R5,r15), r5
mov.l @(OFF_R6,r15), r6
mov.l @(OFF_R7,r15), r7 ! arg3
mov.l @(OFF_R3,r15), r3 ! syscall_nr
!
mov.l 2f, r10 ! Number of syscalls
cmp/hs r10, r3
bf syscall_call
mov #-ENOSYS, r0
bra syscall_exit
mov.l r0, @(OFF_R0,r15) ! Return value
__restore_all:
mov.l 1f, r0
jmp @r0
nop
.align 2
1: .long restore_all
.align 2
not_syscall_tra:
bra debug_trap
nop
.align 2
syscall_badsys: ! Bad syscall number
mov #-ENOSYS, r0
bra resume_userspace
mov.l r0, @(OFF_R0,r15) ! Return value
/*
* Syscall interface:
*
* Syscall #: R3
* Arguments #0 to #3: R4--R7
* Arguments #4 to #6: R0, R1, R2
* TRA: (number of arguments + 0x10) x 4
*
* This code also handles delegating other traps to the BIOS/gdb stub
* according to:
*
* Trap number
* (TRA>>2) Purpose
* -------- -------
* 0x0-0xf old syscall ABI
* 0x10-0x1f new syscall ABI
* 0x20-0xff delegated through debug_trap to BIOS/gdb stub.
*
* Note: When we're first called, the TRA value must be shifted
* right 2 bits in order to get the value that was used as the "trapa"
* argument.
*/
.align 2
.globl ret_from_fork
ret_from_fork:
mov.l 1f, r8
jsr @r8
mov r0, r4
bra syscall_exit
nop
.align 2
1: .long schedule_tail
!
ENTRY(system_call)
#if !defined(CONFIG_CPU_SH2)
mov.l 1f, r9
mov.l @r9, r8 ! Read from TRA (Trap Address) Register
#endif
!
! Is the trap argument >= 0x20? (TRA will be >= 0x80)
mov #0x7f, r9
cmp/hi r9, r8
bt/s not_syscall_tra
mov #OFF_TRA, r9
add r15, r9
mov.l r8, @r9 ! set TRA value to tra
#ifdef CONFIG_TRACE_IRQFLAGS
mov.l 5f, r10
jsr @r10
nop
#endif
sti
!
get_current_thread_info r8, r10
mov.l @(TI_FLAGS,r8), r8
mov #_TIF_SYSCALL_TRACE, r10
tst r10, r8
bf syscall_trace_entry
!
mov.l 2f, r8 ! Number of syscalls
cmp/hs r8, r3
bt syscall_badsys
!
syscall_call:
shll2 r3 ! x4
mov.l 3f, r8 ! Load the address of sys_call_table
add r8, r3
mov.l @r3, r8
jsr @r8 ! jump to specific syscall handler
nop
mov.l @(OFF_R0,r15), r12 ! save r0
mov.l r0, @(OFF_R0,r15) ! save the return value
!
syscall_exit:
cli
#ifdef CONFIG_TRACE_IRQFLAGS
mov.l 6f, r0
jsr @r0
nop
#endif
!
get_current_thread_info r8, r0
mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
tst #_TIF_ALLWORK_MASK, r0
bf syscall_exit_work
bra __restore_all
nop
.align 2
#if !defined(CONFIG_CPU_SH2)
1: .long TRA
#endif
2: .long NR_syscalls
3: .long sys_call_table
4: .long do_syscall_trace
#ifdef CONFIG_TRACE_IRQFLAGS
5: .long trace_hardirqs_on
6: .long trace_hardirqs_off
#endif

View File

@ -33,7 +33,7 @@ ENTRY(empty_zero_page)
.long 0x00360000 /* INITRD_START */
.long 0x000a0000 /* INITRD_SIZE */
.long 0
.balign 4096,0,4096
.balign PAGE_SIZE,0,PAGE_SIZE
.text
/*
@ -53,8 +53,10 @@ ENTRY(_stext)
ldc r0, sr
! Initialize global interrupt mask
mov #0, r0
#ifdef CONFIG_CPU_HAS_SR_RB
ldc r0, r6_bank
#endif
/*
* Prefetch if possible to reduce cache miss penalty.
*
@ -68,11 +70,14 @@ ENTRY(_stext)
!
mov.l 2f, r0
mov r0, r15 ! Set initial r15 (stack pointer)
mov #(THREAD_SIZE >> 8), r1
mov #(THREAD_SIZE >> 10), r1
shll8 r1 ! r1 = THREAD_SIZE
shll2 r1
sub r1, r0 !
#ifdef CONFIG_CPU_HAS_SR_RB
ldc r0, r7_bank ! ... and initial thread_info
#endif
! Clear BSS area
mov.l 3f, r1
add #4, r1
@ -95,7 +100,11 @@ ENTRY(_stext)
nop
.balign 4
#if defined(CONFIG_CPU_SH2)
1: .long 0x000000F0 ! IMASK=0xF
#else
1: .long 0x400080F0 ! MD=1, RB=0, BL=0, FD=1, IMASK=0xF
#endif
2: .long init_thread_union+THREAD_SIZE
3: .long __bss_start
4: .long _end

View File

@ -12,7 +12,7 @@
#include <linux/kernel_stat.h>
#include <linux/seq_file.h>
#include <linux/io.h>
#include <asm/irq.h>
#include <linux/irq.h>
#include <asm/processor.h>
#include <asm/uaccess.h>
#include <asm/thread_info.h>
@ -78,15 +78,16 @@ union irq_ctx {
u32 stack[THREAD_SIZE/sizeof(u32)];
};
static union irq_ctx *hardirq_ctx[NR_CPUS];
static union irq_ctx *softirq_ctx[NR_CPUS];
static union irq_ctx *hardirq_ctx[NR_CPUS] __read_mostly;
static union irq_ctx *softirq_ctx[NR_CPUS] __read_mostly;
#endif
asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
struct pt_regs regs)
struct pt_regs __regs)
{
struct pt_regs *old_regs = set_irq_regs(&regs);
struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
struct pt_regs *old_regs = set_irq_regs(regs);
int irq;
#ifdef CONFIG_4KSTACKS
union irq_ctx *curctx, *irqctx;
@ -111,7 +112,7 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
#endif
#ifdef CONFIG_CPU_HAS_INTEVT
irq = (ctrl_inl(INTEVT) >> 5) - 16;
irq = evt2irq(ctrl_inl(INTEVT));
#else
irq = r4;
#endif
@ -135,17 +136,24 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
irqctx->tinfo.task = curctx->tinfo.task;
irqctx->tinfo.previous_sp = current_stack_pointer;
/*
* Copy the softirq bits in preempt_count so that the
* softirq checks work in the hardirq context.
*/
irqctx->tinfo.preempt_count =
(irqctx->tinfo.preempt_count & ~SOFTIRQ_MASK) |
(curctx->tinfo.preempt_count & SOFTIRQ_MASK);
__asm__ __volatile__ (
"mov %0, r4 \n"
"mov r15, r9 \n"
"mov r15, r8 \n"
"jsr @%1 \n"
/* swith to the irq stack */
" mov %2, r15 \n"
/* restore the stack (ring zero) */
"mov r9, r15 \n"
"mov r8, r15 \n"
: /* no outputs */
: "r" (irq), "r" (generic_handle_irq), "r" (isp)
/* XXX: A somewhat excessive clobber list? -PFM */
: "memory", "r0", "r1", "r2", "r3", "r4",
"r5", "r6", "r7", "r8", "t", "pr"
);
@ -193,7 +201,7 @@ void irq_ctx_init(int cpu)
irqctx->tinfo.task = NULL;
irqctx->tinfo.exec_domain = NULL;
irqctx->tinfo.cpu = cpu;
irqctx->tinfo.preempt_count = SOFTIRQ_OFFSET;
irqctx->tinfo.preempt_count = 0;
irqctx->tinfo.addr_limit = MAKE_MM_SEG(0);
softirq_ctx[cpu] = irqctx;
@ -239,13 +247,38 @@ asmlinkage void do_softirq(void)
"mov r9, r15 \n"
: /* no outputs */
: "r" (__do_softirq), "r" (isp)
/* XXX: A somewhat excessive clobber list? -PFM */
: "memory", "r0", "r1", "r2", "r3", "r4",
"r5", "r6", "r7", "r8", "r9", "r15", "t", "pr"
);
/*
* Shouldnt happen, we returned above if in_interrupt():
*/
WARN_ON_ONCE(softirq_count());
}
local_irq_restore(flags);
}
EXPORT_SYMBOL(do_softirq);
#endif
void __init init_IRQ(void)
{
#ifdef CONFIG_CPU_HAS_PINT_IRQ
init_IRQ_pint();
#endif
#ifdef CONFIG_CPU_HAS_INTC2_IRQ
init_IRQ_intc2();
#endif
#ifdef CONFIG_CPU_HAS_IPR_IRQ
init_IRQ_ipr();
#endif
/* Perform the machine specific initialisation */
if (sh_mv.mv_init_irq)
sh_mv.mv_init_irq();
irq_ctx_init(smp_processor_id());
}

View File

@ -385,10 +385,11 @@ struct task_struct *__switch_to(struct task_struct *prev, struct task_struct *ne
asmlinkage int sys_fork(unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
struct pt_regs regs)
struct pt_regs __regs)
{
struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
#ifdef CONFIG_MMU
return do_fork(SIGCHLD, regs.regs[15], &regs, 0, NULL, NULL);
return do_fork(SIGCHLD, regs->regs[15], regs, 0, NULL, NULL);
#else
/* fork almost works, enough to trick you into looking elsewhere :-( */
return -EINVAL;
@ -398,11 +399,12 @@ asmlinkage int sys_fork(unsigned long r4, unsigned long r5,
asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
unsigned long parent_tidptr,
unsigned long child_tidptr,
struct pt_regs regs)
struct pt_regs __regs)
{
struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
if (!newsp)
newsp = regs.regs[15];
return do_fork(clone_flags, newsp, &regs, 0,
newsp = regs->regs[15];
return do_fork(clone_flags, newsp, regs, 0,
(int __user *)parent_tidptr, (int __user *)child_tidptr);
}
@ -418,9 +420,10 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
*/
asmlinkage int sys_vfork(unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
struct pt_regs regs)
struct pt_regs __regs)
{
return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.regs[15], &regs,
struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->regs[15], regs,
0, NULL, NULL);
}
@ -429,8 +432,9 @@ asmlinkage int sys_vfork(unsigned long r4, unsigned long r5,
*/
asmlinkage int sys_execve(char *ufilename, char **uargv,
char **uenvp, unsigned long r7,
struct pt_regs regs)
struct pt_regs __regs)
{
struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
int error;
char *filename;
@ -442,7 +446,7 @@ asmlinkage int sys_execve(char *ufilename, char **uargv,
error = do_execve(filename,
(char __user * __user *)uargv,
(char __user * __user *)uenvp,
&regs);
regs);
if (error == 0) {
task_lock(current);
current->ptrace &= ~PT_DTRACE;
@ -472,9 +476,7 @@ unsigned long get_wchan(struct task_struct *p)
return pc;
}
asmlinkage void break_point_trap(unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
struct pt_regs regs)
asmlinkage void break_point_trap(void)
{
/* Clear tracing. */
#if defined(CONFIG_CPU_SH4A)
@ -492,8 +494,10 @@ asmlinkage void break_point_trap(unsigned long r4, unsigned long r5,
asmlinkage void break_point_trap_software(unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
struct pt_regs regs)
struct pt_regs __regs)
{
regs.pc -= 2;
struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
regs->pc -= 2;
force_sig(SIGTRAP, current);
}

View File

@ -7,11 +7,9 @@
* This source code is licensed under the GNU General Public License,
* Version 2. See the file COPYING for more details.
*/
#include <linux/linkage.h>
#define PAGE_SIZE 4096 /* must be same value as in <asm/page.h> */
#include <asm/addrspace.h>
#include <asm/page.h>
.globl relocate_new_kernel
relocate_new_kernel:
@ -20,8 +18,8 @@ relocate_new_kernel:
/* r6 = start_address */
/* r7 = vbr_reg */
mov.l 10f,r8 /* 4096 */
mov.l 11f,r9 /* 0xa0000000 */
mov.l 10f,r8 /* PAGE_SIZE */
mov.l 11f,r9 /* P2SEG */
/* stack setting */
add r8,r5
@ -32,7 +30,7 @@ relocate_new_kernel:
0:
mov.l @r4+,r0 /* cmd = *ind++ */
1: /* addr = (cmd | 0xa0000000) & 0xfffffff0 */
1: /* addr = (cmd | P2SEG) & 0xfffffff0 */
mov r0,r2
or r9,r2
mov #-16,r1
@ -92,7 +90,7 @@ relocate_new_kernel:
10:
.long PAGE_SIZE
11:
.long 0xa0000000
.long P2SEG
relocate_new_kernel_end:

View File

@ -392,6 +392,7 @@ static int __init topology_init(void)
subsys_initcall(topology_init);
static const char *cpu_name[] = {
[CPU_SH7206] = "SH7206", [CPU_SH7619] = "SH7619",
[CPU_SH7604] = "SH7604", [CPU_SH7300] = "SH7300",
[CPU_SH7705] = "SH7705", [CPU_SH7706] = "SH7706",
[CPU_SH7707] = "SH7707", [CPU_SH7708] = "SH7708",
@ -404,6 +405,7 @@ static const char *cpu_name[] = {
[CPU_SH4_202] = "SH4-202", [CPU_SH4_501] = "SH4-501",
[CPU_SH7770] = "SH7770", [CPU_SH7780] = "SH7780",
[CPU_SH7781] = "SH7781", [CPU_SH7343] = "SH7343",
[CPU_SH7785] = "SH7785",
[CPU_SH_NONE] = "Unknown"
};

View File

@ -73,8 +73,6 @@ DECLARE_EXPORT(__lshrdi3);
DECLARE_EXPORT(__movstr);
DECLARE_EXPORT(__movstrSI16);
EXPORT_SYMBOL(strcpy);
#ifdef CONFIG_CPU_SH4
DECLARE_EXPORT(__movstr_i4_even);
DECLARE_EXPORT(__movstr_i4_odd);

View File

@ -37,7 +37,7 @@
asmlinkage int
sys_sigsuspend(old_sigset_t mask,
unsigned long r5, unsigned long r6, unsigned long r7,
struct pt_regs regs)
struct pt_regs __regs)
{
mask &= _BLOCKABLE;
spin_lock_irq(&current->sighand->siglock);
@ -52,7 +52,7 @@ sys_sigsuspend(old_sigset_t mask,
return -ERESTARTNOHAND;
}
asmlinkage int
asmlinkage int
sys_sigaction(int sig, const struct old_sigaction __user *act,
struct old_sigaction __user *oact)
{
@ -87,9 +87,11 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
asmlinkage int
sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
unsigned long r6, unsigned long r7,
struct pt_regs regs)
struct pt_regs __regs)
{
return do_sigaltstack(uss, uoss, regs.regs[15]);
struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
return do_sigaltstack(uss, uoss, regs->regs[15]);
}
@ -98,7 +100,11 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
*/
#define MOVW(n) (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */
#define TRAP16 0xc310 /* Syscall w/no args (NR in R3) */
#if defined(CONFIG_CPU_SH2) || defined(CONFIG_CPU_SH2A)
#define TRAP_NOARG 0xc320 /* Syscall w/no args (NR in R3) */
#else
#define TRAP_NOARG 0xc310 /* Syscall w/no args (NR in R3) */
#endif
#define OR_R0_R0 0x200b /* or r0,r0 (insert to avoid hardware bug) */
struct sigframe
@ -194,9 +200,10 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *r0_p
asmlinkage int sys_sigreturn(unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
struct pt_regs regs)
struct pt_regs __regs)
{
struct sigframe __user *frame = (struct sigframe __user *)regs.regs[15];
struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
struct sigframe __user *frame = (struct sigframe __user *)regs->regs[15];
sigset_t set;
int r0;
@ -216,7 +223,7 @@ asmlinkage int sys_sigreturn(unsigned long r4, unsigned long r5,
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
if (restore_sigcontext(&regs, &frame->sc, &r0))
if (restore_sigcontext(regs, &frame->sc, &r0))
goto badframe;
return r0;
@ -227,9 +234,10 @@ badframe:
asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
struct pt_regs regs)
struct pt_regs __regs)
{
struct rt_sigframe __user *frame = (struct rt_sigframe __user *)regs.regs[15];
struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
struct rt_sigframe __user *frame = (struct rt_sigframe __user *)regs->regs[15];
sigset_t set;
stack_t st;
int r0;
@ -246,14 +254,14 @@ asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5,
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
if (restore_sigcontext(&regs, &frame->uc.uc_mcontext, &r0))
if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0))
goto badframe;
if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
goto badframe;
/* It is more difficult to avoid calling this function than to
call it and ignore errors. */
do_sigaltstack(&st, NULL, regs.regs[15]);
do_sigaltstack(&st, NULL, regs->regs[15]);
return r0;
@ -350,7 +358,7 @@ static int setup_frame(int sig, struct k_sigaction *ka,
} else {
/* Generate return code (system call to sigreturn) */
err |= __put_user(MOVW(7), &frame->retcode[0]);
err |= __put_user(TRAP16, &frame->retcode[1]);
err |= __put_user(TRAP_NOARG, &frame->retcode[1]);
err |= __put_user(OR_R0_R0, &frame->retcode[2]);
err |= __put_user(OR_R0_R0, &frame->retcode[3]);
err |= __put_user(OR_R0_R0, &frame->retcode[4]);
@ -430,7 +438,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
} else {
/* Generate return code (system call to rt_sigreturn) */
err |= __put_user(MOVW(7), &frame->retcode[0]);
err |= __put_user(TRAP16, &frame->retcode[1]);
err |= __put_user(TRAP_NOARG, &frame->retcode[1]);
err |= __put_user(OR_R0_R0, &frame->retcode[2]);
err |= __put_user(OR_R0_R0, &frame->retcode[3]);
err |= __put_user(OR_R0_R0, &frame->retcode[4]);

View File

@ -0,0 +1,43 @@
/*
* arch/sh/kernel/stacktrace.c
*
* Stack trace management functions
*
* Copyright (C) 2006 Paul Mundt
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#include <linux/sched.h>
#include <linux/stacktrace.h>
#include <linux/thread_info.h>
#include <asm/ptrace.h>
/*
* Save stack-backtrace addresses into a stack_trace buffer.
*/
void save_stack_trace(struct stack_trace *trace, struct task_struct *task)
{
unsigned long *sp;
if (!task)
task = current;
if (task == current)
sp = (unsigned long *)current_stack_pointer;
else
sp = (unsigned long *)task->thread.sp;
while (!kstack_end(sp)) {
unsigned long addr = *sp++;
if (__kernel_text_address(addr)) {
if (trace->skip > 0)
trace->skip--;
else
trace->entries[trace->nr_entries++] = addr;
if (trace->nr_entries >= trace->max_entries)
break;
}
}
}

View File

@ -33,14 +33,15 @@
*/
asmlinkage int sys_pipe(unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
struct pt_regs regs)
struct pt_regs __regs)
{
struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
int fd[2];
int error;
error = do_pipe(fd);
if (!error) {
regs.regs[1] = fd[1];
regs->regs[1] = fd[1];
return fd[0];
}
return error;
@ -50,6 +51,7 @@ unsigned long shm_align_mask = PAGE_SIZE - 1; /* Sane caches */
EXPORT_SYMBOL(shm_align_mask);
#ifdef CONFIG_MMU
/*
* To avoid cache aliases, we map the shared page with same color.
*/
@ -135,6 +137,7 @@ full_search:
addr = COLOUR_ALIGN(addr, pgoff);
}
}
#endif /* CONFIG_MMU */
static inline long
do_mmap2(unsigned long addr, unsigned long len, unsigned long prot,

View File

@ -13,6 +13,8 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/profile.h>
#include <linux/timex.h>
#include <linux/sched.h>
#include <asm/clock.h>
#include <asm/rtc.h>
#include <asm/timer.h>
@ -50,15 +52,20 @@ unsigned long long __attribute__ ((weak)) sched_clock(void)
#ifndef CONFIG_GENERIC_TIME
void do_gettimeofday(struct timeval *tv)
{
unsigned long flags;
unsigned long seq;
unsigned long usec, sec;
do {
seq = read_seqbegin(&xtime_lock);
/*
* Turn off IRQs when grabbing xtime_lock, so that
* the sys_timer get_offset code doesn't have to handle it.
*/
seq = read_seqbegin_irqsave(&xtime_lock, flags);
usec = get_timer_offset();
sec = xtime.tv_sec;
usec += xtime.tv_nsec / 1000;
} while (read_seqretry(&xtime_lock, seq));
usec += xtime.tv_nsec / NSEC_PER_USEC;
} while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
while (usec >= 1000000) {
usec -= 1000000;
@ -85,7 +92,7 @@ int do_settimeofday(struct timespec *tv)
* wall time. Discover what correction gettimeofday() would have
* made, and then undo it!
*/
nsec -= 1000 * get_timer_offset();
nsec -= get_timer_offset() * NSEC_PER_USEC;
wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
@ -169,6 +176,108 @@ static struct sysdev_class timer_sysclass = {
.resume = timer_resume,
};
#ifdef CONFIG_NO_IDLE_HZ
static int timer_dyn_tick_enable(void)
{
struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick;
unsigned long flags;
int ret = -ENODEV;
if (dyn_tick) {
spin_lock_irqsave(&dyn_tick->lock, flags);
ret = 0;
if (!(dyn_tick->state & DYN_TICK_ENABLED)) {
ret = dyn_tick->enable();
if (ret == 0)
dyn_tick->state |= DYN_TICK_ENABLED;
}
spin_unlock_irqrestore(&dyn_tick->lock, flags);
}
return ret;
}
static int timer_dyn_tick_disable(void)
{
struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick;
unsigned long flags;
int ret = -ENODEV;
if (dyn_tick) {
spin_lock_irqsave(&dyn_tick->lock, flags);
ret = 0;
if (dyn_tick->state & DYN_TICK_ENABLED) {
ret = dyn_tick->disable();
if (ret == 0)
dyn_tick->state &= ~DYN_TICK_ENABLED;
}
spin_unlock_irqrestore(&dyn_tick->lock, flags);
}
return ret;
}
/*
* Reprogram the system timer for at least the calculated time interval.
* This function should be called from the idle thread with IRQs disabled,
* immediately before sleeping.
*/
void timer_dyn_reprogram(void)
{
struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick;
unsigned long next, seq, flags;
if (!dyn_tick)
return;
spin_lock_irqsave(&dyn_tick->lock, flags);
if (dyn_tick->state & DYN_TICK_ENABLED) {
next = next_timer_interrupt();
do {
seq = read_seqbegin(&xtime_lock);
dyn_tick->reprogram(next - jiffies);
} while (read_seqretry(&xtime_lock, seq));
}
spin_unlock_irqrestore(&dyn_tick->lock, flags);
}
static ssize_t timer_show_dyn_tick(struct sys_device *dev, char *buf)
{
return sprintf(buf, "%i\n",
(sys_timer->dyn_tick->state & DYN_TICK_ENABLED) >> 1);
}
static ssize_t timer_set_dyn_tick(struct sys_device *dev, const char *buf,
size_t count)
{
unsigned int enable = simple_strtoul(buf, NULL, 2);
if (enable)
timer_dyn_tick_enable();
else
timer_dyn_tick_disable();
return count;
}
static SYSDEV_ATTR(dyn_tick, 0644, timer_show_dyn_tick, timer_set_dyn_tick);
/*
* dyntick=enable|disable
*/
static char dyntick_str[4] __initdata = "";
static int __init dyntick_setup(char *str)
{
if (str)
strlcpy(dyntick_str, str, sizeof(dyntick_str));
return 1;
}
__setup("dyntick=", dyntick_setup);
#endif
static int __init timer_init_sysfs(void)
{
int ret = sysdev_class_register(&timer_sysclass);
@ -176,7 +285,22 @@ static int __init timer_init_sysfs(void)
return ret;
sys_timer->dev.cls = &timer_sysclass;
return sysdev_register(&sys_timer->dev);
ret = sysdev_register(&sys_timer->dev);
#ifdef CONFIG_NO_IDLE_HZ
if (ret == 0 && sys_timer->dyn_tick) {
ret = sysdev_create_file(&sys_timer->dev, &attr_dyn_tick);
/*
* Turn on dynamic tick after calibrate delay
* for correct bogomips
*/
if (ret == 0 && dyntick_str[0] == 'e')
ret = timer_dyn_tick_enable();
}
#endif
return ret;
}
device_initcall(timer_init_sysfs);
@ -200,6 +324,11 @@ void __init time_init(void)
sys_timer = get_sys_timer();
printk(KERN_INFO "Using %s for system timer\n", sys_timer->name);
#ifdef CONFIG_NO_IDLE_HZ
if (sys_timer->dyn_tick)
spin_lock_init(&sys_timer->dyn_tick->lock);
#endif
#if defined(CONFIG_SH_KGDB)
/*
* Set up kgdb as requested. We do it here because the serial

View File

@ -5,4 +5,6 @@
obj-y := timer.o
obj-$(CONFIG_SH_TMU) += timer-tmu.o
obj-$(CONFIG_SH_MTU2) += timer-mtu2.o
obj-$(CONFIG_SH_CMT) += timer-cmt.o

View File

@ -0,0 +1,196 @@
/*
* arch/sh/kernel/timers/timer-cmt.c - CMT Timer Support
*
* Copyright (C) 2005 Yoshinori Sato
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/seqlock.h>
#include <asm/timer.h>
#include <asm/rtc.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/clock.h>
#if defined(CONFIG_CPU_SUBTYPE_SH7619)
#define CMT_CMSTR 0xf84a0070
#define CMT_CMCSR_0 0xf84a0072
#define CMT_CMCNT_0 0xf84a0074
#define CMT_CMCOR_0 0xf84a0076
#define CMT_CMCSR_1 0xf84a0078
#define CMT_CMCNT_1 0xf84a007a
#define CMT_CMCOR_1 0xf84a007c
#define STBCR3 0xf80a0000
#define cmt_clock_enable() do { ctrl_outb(ctrl_inb(STBCR3) & ~0x10, STBCR3); } while(0)
#define CMT_CMCSR_INIT 0x0040
#define CMT_CMCSR_CALIB 0x0000
#elif defined(CONFIG_CPU_SUBTYPE_SH7206)
#define CMT_CMSTR 0xfffec000
#define CMT_CMCSR_0 0xfffec002
#define CMT_CMCNT_0 0xfffec004
#define CMT_CMCOR_0 0xfffec006
#define STBCR4 0xfffe040c
#define cmt_clock_enable() do { ctrl_outb(ctrl_inb(STBCR4) & ~0x04, STBCR4); } while(0)
#define CMT_CMCSR_INIT 0x0040
#define CMT_CMCSR_CALIB 0x0000
#else
#error "Unknown CPU SUBTYPE"
#endif
static unsigned long cmt_timer_get_offset(void)
{
int count;
static unsigned short count_p = 0xffff; /* for the first call after boot */
static unsigned long jiffies_p = 0;
/*
* cache volatile jiffies temporarily; we have IRQs turned off.
*/
unsigned long jiffies_t;
/* timer count may underflow right here */
count = ctrl_inw(CMT_CMCOR_0);
count -= ctrl_inw(CMT_CMCNT_0);
jiffies_t = jiffies;
/*
* avoiding timer inconsistencies (they are rare, but they happen)...
* there is one kind of problem that must be avoided here:
* 1. the timer counter underflows
*/
if (jiffies_t == jiffies_p) {
if (count > count_p) {
/* the nutcase */
if (ctrl_inw(CMT_CMCSR_0) & 0x80) { /* Check CMF bit */
count -= LATCH;
} else {
printk("%s (): hardware timer problem?\n",
__FUNCTION__);
}
}
} else
jiffies_p = jiffies_t;
count_p = count;
count = ((LATCH-1) - count) * TICK_SIZE;
count = (count + LATCH/2) / LATCH;
return count;
}
static irqreturn_t cmt_timer_interrupt(int irq, void *dev_id)
{
unsigned long timer_status;
/* Clear CMF bit */
timer_status = ctrl_inw(CMT_CMCSR_0);
timer_status &= ~0x80;
ctrl_outw(timer_status, CMT_CMCSR_0);
/*
* Here we are in the timer irq handler. We just have irqs locally
* disabled but we don't know if the timer_bh is running on the other
* CPU. We need to avoid to SMP race with it. NOTE: we don' t need
* the irq version of write_lock because as just said we have irq
* locally disabled. -arca
*/
write_seqlock(&xtime_lock);
handle_timer_tick();
write_sequnlock(&xtime_lock);
return IRQ_HANDLED;
}
static struct irqaction cmt_irq = {
.name = "timer",
.handler = cmt_timer_interrupt,
.flags = IRQF_DISABLED | IRQF_TIMER,
.mask = CPU_MASK_NONE,
};
static void cmt_clk_init(struct clk *clk)
{
u8 divisor = CMT_CMCSR_INIT & 0x3;
ctrl_inw(CMT_CMCSR_0);
ctrl_outw(CMT_CMCSR_INIT, CMT_CMCSR_0);
clk->parent = clk_get(NULL, "module_clk");
clk->rate = clk->parent->rate / (8 << (divisor << 1));
}
static void cmt_clk_recalc(struct clk *clk)
{
u8 divisor = ctrl_inw(CMT_CMCSR_0) & 0x3;
clk->rate = clk->parent->rate / (8 << (divisor << 1));
}
static struct clk_ops cmt_clk_ops = {
.init = cmt_clk_init,
.recalc = cmt_clk_recalc,
};
static struct clk cmt0_clk = {
.name = "cmt0_clk",
.ops = &cmt_clk_ops,
};
static int cmt_timer_start(void)
{
ctrl_outw(ctrl_inw(CMT_CMSTR) | 0x01, CMT_CMSTR);
return 0;
}
static int cmt_timer_stop(void)
{
ctrl_outw(ctrl_inw(CMT_CMSTR) & ~0x01, CMT_CMSTR);
return 0;
}
static int cmt_timer_init(void)
{
unsigned long interval;
cmt_clock_enable();
setup_irq(CONFIG_SH_TIMER_IRQ, &cmt_irq);
cmt0_clk.parent = clk_get(NULL, "module_clk");
cmt_timer_stop();
interval = cmt0_clk.parent->rate / 8 / HZ;
printk(KERN_INFO "Interval = %ld\n", interval);
ctrl_outw(interval, CMT_CMCOR_0);
clk_register(&cmt0_clk);
clk_enable(&cmt0_clk);
cmt_timer_start();
return 0;
}
struct sys_timer_ops cmt_timer_ops = {
.init = cmt_timer_init,
.start = cmt_timer_start,
.stop = cmt_timer_stop,
#ifndef CONFIG_GENERIC_TIME
.get_offset = cmt_timer_get_offset,
#endif
};
struct sys_timer cmt_timer = {
.name = "cmt",
.ops = &cmt_timer_ops,
};

View File

@ -0,0 +1,200 @@
/*
* arch/sh/kernel/timers/timer-mtu2.c - MTU2 Timer Support
*
* Copyright (C) 2005 Paul Mundt
*
* Based off of arch/sh/kernel/timers/timer-tmu.c
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/seqlock.h>
#include <asm/timer.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/clock.h>
/*
* We use channel 1 for our lowly system timer. Channel 2 would be the other
* likely candidate, but we leave it alone as it has higher divisors that
* would be of more use to other more interesting applications.
*
* TODO: Presently we only implement a 16-bit single-channel system timer.
* However, we can implement channel cascade if we go the overflow route and
* get away with using 2 MTU2 channels as a 32-bit timer.
*/
#define MTU2_TSTR 0xfffe4280
#define MTU2_TCR_1 0xfffe4380
#define MTU2_TMDR_1 0xfffe4381
#define MTU2_TIOR_1 0xfffe4382
#define MTU2_TIER_1 0xfffe4384
#define MTU2_TSR_1 0xfffe4385
#define MTU2_TCNT_1 0xfffe4386 /* 16-bit counter */
#define MTU2_TGRA_1 0xfffe438a
#define STBCR3 0xfffe0408
#define MTU2_TSTR_CST1 (1 << 1) /* Counter Start 1 */
#define MTU2_TSR_TGFA (1 << 0) /* GRA compare match */
#define MTU2_TIER_TGIEA (1 << 0) /* GRA compare match interrupt enable */
#define MTU2_TCR_INIT 0x22
#define MTU2_TCR_CALIB 0x00
static unsigned long mtu2_timer_get_offset(void)
{
int count;
static int count_p = 0x7fff; /* for the first call after boot */
static unsigned long jiffies_p = 0;
/*
* cache volatile jiffies temporarily; we have IRQs turned off.
*/
unsigned long jiffies_t;
/* timer count may underflow right here */
count = ctrl_inw(MTU2_TCNT_1); /* read the latched count */
jiffies_t = jiffies;
/*
* avoiding timer inconsistencies (they are rare, but they happen)...
* there is one kind of problem that must be avoided here:
* 1. the timer counter underflows
*/
if (jiffies_t == jiffies_p) {
if (count > count_p) {
if (ctrl_inb(MTU2_TSR_1) & MTU2_TSR_TGFA) {
count -= LATCH;
} else {
printk("%s (): hardware timer problem?\n",
__FUNCTION__);
}
}
} else
jiffies_p = jiffies_t;
count_p = count;
count = ((LATCH-1) - count) * TICK_SIZE;
count = (count + LATCH/2) / LATCH;
return count;
}
static irqreturn_t mtu2_timer_interrupt(int irq, void *dev_id)
{
unsigned long timer_status;
/* Clear TGFA bit */
timer_status = ctrl_inb(MTU2_TSR_1);
timer_status &= ~MTU2_TSR_TGFA;
ctrl_outb(timer_status, MTU2_TSR_1);
/* Do timer tick */
write_seqlock(&xtime_lock);
handle_timer_tick();
write_sequnlock(&xtime_lock);
return IRQ_HANDLED;
}
static struct irqaction mtu2_irq = {
.name = "timer",
.handler = mtu2_timer_interrupt,
.flags = IRQF_DISABLED | IRQF_TIMER,
.mask = CPU_MASK_NONE,
};
static unsigned int divisors[] = { 1, 4, 16, 64, 1, 1, 256 };
static void mtu2_clk_init(struct clk *clk)
{
u8 idx = MTU2_TCR_INIT & 0x7;
clk->rate = clk->parent->rate / divisors[idx];
/* Start TCNT counting */
ctrl_outb(ctrl_inb(MTU2_TSTR) | MTU2_TSTR_CST1, MTU2_TSTR);
}
static void mtu2_clk_recalc(struct clk *clk)
{
u8 idx = ctrl_inb(MTU2_TCR_1) & 0x7;
clk->rate = clk->parent->rate / divisors[idx];
}
static struct clk_ops mtu2_clk_ops = {
.init = mtu2_clk_init,
.recalc = mtu2_clk_recalc,
};
static struct clk mtu2_clk1 = {
.name = "mtu2_clk1",
.ops = &mtu2_clk_ops,
};
static int mtu2_timer_start(void)
{
ctrl_outb(ctrl_inb(MTU2_TSTR) | MTU2_TSTR_CST1, MTU2_TSTR);
return 0;
}
static int mtu2_timer_stop(void)
{
ctrl_outb(ctrl_inb(MTU2_TSTR) & ~MTU2_TSTR_CST1, MTU2_TSTR);
return 0;
}
static int mtu2_timer_init(void)
{
u8 tmp;
unsigned long interval;
setup_irq(CONFIG_SH_TIMER_IRQ, &mtu2_irq);
mtu2_clk1.parent = clk_get(NULL, "module_clk");
ctrl_outb(ctrl_inb(STBCR3) & (~0x20), STBCR3);
/* Normal operation */
ctrl_outb(0, MTU2_TMDR_1);
ctrl_outb(MTU2_TCR_INIT, MTU2_TCR_1);
ctrl_outb(0x01, MTU2_TIOR_1);
/* Enable underflow interrupt */
ctrl_outb(ctrl_inb(MTU2_TIER_1) | MTU2_TIER_TGIEA, MTU2_TIER_1);
interval = CONFIG_SH_PCLK_FREQ / 16 / HZ;
printk(KERN_INFO "Interval = %ld\n", interval);
ctrl_outw(interval, MTU2_TGRA_1);
ctrl_outw(0, MTU2_TCNT_1);
clk_register(&mtu2_clk1);
clk_enable(&mtu2_clk1);
return 0;
}
struct sys_timer_ops mtu2_timer_ops = {
.init = mtu2_timer_init,
.start = mtu2_timer_start,
.stop = mtu2_timer_stop,
#ifndef CONFIG_GENERIC_TIME
.get_offset = mtu2_timer_get_offset,
#endif
};
struct sys_timer mtu2_timer = {
.name = "mtu2",
.ops = &mtu2_timer_ops,
};

View File

@ -17,7 +17,6 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/seqlock.h>
#include <asm/timer.h>
#include <asm/rtc.h>
@ -31,13 +30,9 @@
#define TMU0_TCR_CALIB 0x0000
static DEFINE_SPINLOCK(tmu0_lock);
static unsigned long tmu_timer_get_offset(void)
{
int count;
unsigned long flags;
static int count_p = 0x7fffffff; /* for the first call after boot */
static unsigned long jiffies_p = 0;
@ -46,7 +41,6 @@ static unsigned long tmu_timer_get_offset(void)
*/
unsigned long jiffies_t;
spin_lock_irqsave(&tmu0_lock, flags);
/* timer count may underflow right here */
count = ctrl_inl(TMU0_TCNT); /* read the latched count */
@ -72,7 +66,6 @@ static unsigned long tmu_timer_get_offset(void)
jiffies_p = jiffies_t;
count_p = count;
spin_unlock_irqrestore(&tmu0_lock, flags);
count = ((LATCH-1) - count) * TICK_SIZE;
count = (count + LATCH/2) / LATCH;
@ -106,7 +99,7 @@ static irqreturn_t tmu_timer_interrupt(int irq, void *dummy)
static struct irqaction tmu_irq = {
.name = "timer",
.handler = tmu_timer_interrupt,
.flags = IRQF_DISABLED,
.flags = IRQF_DISABLED | IRQF_TIMER,
.mask = CPU_MASK_NONE,
};
@ -149,9 +142,9 @@ static int tmu_timer_init(void)
{
unsigned long interval;
setup_irq(TIMER_IRQ, &tmu_irq);
setup_irq(CONFIG_SH_TIMER_IRQ, &tmu_irq);
tmu0_clk.parent = clk_get("module_clk");
tmu0_clk.parent = clk_get(NULL, "module_clk");
/* Start TMU0 */
tmu_timer_stop();

View File

@ -16,6 +16,12 @@
static struct sys_timer *sys_timers[] __initdata = {
#ifdef CONFIG_SH_TMU
&tmu_timer,
#endif
#ifdef CONFIG_SH_MTU2
&mtu2_timer,
#endif
#ifdef CONFIG_SH_CMT
&cmt_timer,
#endif
NULL,
};

View File

@ -18,13 +18,14 @@
#include <linux/module.h>
#include <linux/kallsyms.h>
#include <linux/io.h>
#include <linux/debug_locks.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#ifdef CONFIG_SH_KGDB
#include <asm/kgdb.h>
#define CHK_REMOTE_DEBUG(regs) \
{ \
#define CHK_REMOTE_DEBUG(regs) \
{ \
if (kgdb_debug_hook && !user_mode(regs))\
(*kgdb_debug_hook)(regs); \
}
@ -33,8 +34,13 @@
#endif
#ifdef CONFIG_CPU_SH2
#define TRAP_RESERVED_INST 4
#define TRAP_ILLEGAL_SLOT_INST 6
# define TRAP_RESERVED_INST 4
# define TRAP_ILLEGAL_SLOT_INST 6
# define TRAP_ADDRESS_ERROR 9
# ifdef CONFIG_CPU_SH2A
# define TRAP_DIVZERO_ERROR 17
# define TRAP_DIVOVF_ERROR 18
# endif
#else
#define TRAP_RESERVED_INST 12
#define TRAP_ILLEGAL_SLOT_INST 13
@ -88,7 +94,7 @@ void die(const char * str, struct pt_regs * regs, long err)
if (!user_mode(regs) || in_interrupt())
dump_mem("Stack: ", regs->regs[15], THREAD_SIZE +
(unsigned long)task_stack_page(current));
(unsigned long)task_stack_page(current));
bust_spinlocks(0);
spin_unlock_irq(&die_lock);
@ -102,8 +108,6 @@ static inline void die_if_kernel(const char *str, struct pt_regs *regs,
die(str, regs, err);
}
static int handle_unaligned_notify_count = 10;
/*
* try and fix up kernelspace address errors
* - userspace errors just cause EFAULT to be returned, resulting in SEGV
@ -198,7 +202,7 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs)
if (copy_to_user(dst,src,4))
goto fetch_fault;
ret = 0;
break;
break;
case 2: /* mov.[bwl] to memory, possibly with pre-decrement */
if (instruction & 4)
@ -222,7 +226,7 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs)
if (copy_from_user(dst,src,4))
goto fetch_fault;
ret = 0;
break;
break;
case 6: /* mov.[bwl] from memory, possibly with post-increment */
src = (unsigned char*) *rm;
@ -230,7 +234,7 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs)
*rm += count;
dst = (unsigned char*) rn;
*(unsigned long*)dst = 0;
#ifdef __LITTLE_ENDIAN__
if (copy_from_user(dst, src, count))
goto fetch_fault;
@ -241,7 +245,7 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs)
}
#else
dst += 4-count;
if (copy_from_user(dst, src, count))
goto fetch_fault;
@ -320,7 +324,8 @@ static inline int handle_unaligned_delayslot(struct pt_regs *regs)
return -EFAULT;
/* kernel */
die("delay-slot-insn faulting in handle_unaligned_delayslot", regs, 0);
die("delay-slot-insn faulting in handle_unaligned_delayslot",
regs, 0);
}
return handle_unaligned_ins(instruction,regs);
@ -342,6 +347,13 @@ static inline int handle_unaligned_delayslot(struct pt_regs *regs)
#define SH_PC_8BIT_OFFSET(instr) ((((signed char)(instr))*2) + 4)
#define SH_PC_12BIT_OFFSET(instr) ((((signed short)(instr<<4))>>3) + 4)
/*
* XXX: SH-2A needs this too, but it needs an overhaul thanks to mixed 32-bit
* opcodes..
*/
#ifndef CONFIG_CPU_SH2A
static int handle_unaligned_notify_count = 10;
static int handle_unaligned_access(u16 instruction, struct pt_regs *regs)
{
u_int rm;
@ -354,7 +366,8 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs)
if (user_mode(regs) && handle_unaligned_notify_count>0) {
handle_unaligned_notify_count--;
printk("Fixing up unaligned userspace access in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n",
printk(KERN_NOTICE "Fixing up unaligned userspace access "
"in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n",
current->comm,current->pid,(u16*)regs->pc,instruction);
}
@ -478,32 +491,58 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs)
regs->pc += 2;
return ret;
}
#endif /* CONFIG_CPU_SH2A */
#ifdef CONFIG_CPU_HAS_SR_RB
#define lookup_exception_vector(x) \
__asm__ __volatile__ ("stc r2_bank, %0\n\t" : "=r" ((x)))
#else
#define lookup_exception_vector(x) \
__asm__ __volatile__ ("mov r4, %0\n\t" : "=r" ((x)))
#endif
/*
* Handle various address error exceptions
* Handle various address error exceptions:
* - instruction address error:
* misaligned PC
* PC >= 0x80000000 in user mode
* - data address error (read and write)
* misaligned data access
* access to >= 0x80000000 is user mode
* Unfortuntaly we can't distinguish between instruction address error
* and data address errors caused by read acceses.
*/
asmlinkage void do_address_error(struct pt_regs *regs,
asmlinkage void do_address_error(struct pt_regs *regs,
unsigned long writeaccess,
unsigned long address)
{
unsigned long error_code;
unsigned long error_code = 0;
mm_segment_t oldfs;
siginfo_t info;
#ifndef CONFIG_CPU_SH2A
u16 instruction;
int tmp;
#endif
asm volatile("stc r2_bank,%0": "=r" (error_code));
/* Intentional ifdef */
#ifdef CONFIG_CPU_HAS_SR_RB
lookup_exception_vector(error_code);
#endif
oldfs = get_fs();
if (user_mode(regs)) {
int si_code = BUS_ADRERR;
local_irq_enable();
current->thread.error_code = error_code;
current->thread.trap_no = (writeaccess) ? 8 : 7;
/* bad PC is not something we can fix */
if (regs->pc & 1)
if (regs->pc & 1) {
si_code = BUS_ADRALN;
goto uspace_segv;
}
#ifndef CONFIG_CPU_SH2A
set_fs(USER_DS);
if (copy_from_user(&instruction, (u16 *)(regs->pc), 2)) {
/* Argh. Fault on the instruction itself.
@ -518,14 +557,23 @@ asmlinkage void do_address_error(struct pt_regs *regs,
if (tmp==0)
return; /* sorted */
#endif
uspace_segv:
printk(KERN_NOTICE "Killing process \"%s\" due to unaligned access\n", current->comm);
force_sig(SIGSEGV, current);
uspace_segv:
printk(KERN_NOTICE "Sending SIGBUS to \"%s\" due to unaligned "
"access (PC %lx PR %lx)\n", current->comm, regs->pc,
regs->pr);
info.si_signo = SIGBUS;
info.si_errno = 0;
info.si_code = si_code;
info.si_addr = (void *) address;
force_sig_info(SIGBUS, &info, current);
} else {
if (regs->pc & 1)
die("unaligned program counter", regs, error_code);
#ifndef CONFIG_CPU_SH2A
set_fs(KERNEL_DS);
if (copy_from_user(&instruction, (u16 *)(regs->pc), 2)) {
/* Argh. Fault on the instruction itself.
@ -537,6 +585,12 @@ asmlinkage void do_address_error(struct pt_regs *regs,
handle_unaligned_access(instruction, regs);
set_fs(oldfs);
#else
printk(KERN_NOTICE "Killing process \"%s\" due to unaligned "
"access\n", current->comm);
force_sig(SIGSEGV, current);
#endif
}
}
@ -548,7 +602,7 @@ int is_dsp_inst(struct pt_regs *regs)
{
unsigned short inst;
/*
/*
* Safe guard if DSP mode is already enabled or we're lacking
* the DSP altogether.
*/
@ -569,27 +623,49 @@ int is_dsp_inst(struct pt_regs *regs)
#define is_dsp_inst(regs) (0)
#endif /* CONFIG_SH_DSP */
#ifdef CONFIG_CPU_SH2A
asmlinkage void do_divide_error(unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
struct pt_regs __regs)
{
struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
siginfo_t info;
switch (r4) {
case TRAP_DIVZERO_ERROR:
info.si_code = FPE_INTDIV;
break;
case TRAP_DIVOVF_ERROR:
info.si_code = FPE_INTOVF;
break;
}
force_sig_info(SIGFPE, &info, current);
}
#endif
/* arch/sh/kernel/cpu/sh4/fpu.c */
extern int do_fpu_inst(unsigned short, struct pt_regs *);
extern asmlinkage void do_fpu_state_restore(unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7, struct pt_regs regs);
unsigned long r6, unsigned long r7, struct pt_regs __regs);
asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
struct pt_regs regs)
struct pt_regs __regs)
{
struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
unsigned long error_code;
struct task_struct *tsk = current;
#ifdef CONFIG_SH_FPU_EMU
unsigned short inst;
unsigned short inst = 0;
int err;
get_user(inst, (unsigned short*)regs.pc);
get_user(inst, (unsigned short*)regs->pc);
err = do_fpu_inst(inst, &regs);
err = do_fpu_inst(inst, regs);
if (!err) {
regs.pc += 2;
regs->pc += 2;
return;
}
/* not a FPU inst. */
@ -597,20 +673,19 @@ asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5,
#ifdef CONFIG_SH_DSP
/* Check if it's a DSP instruction */
if (is_dsp_inst(&regs)) {
if (is_dsp_inst(regs)) {
/* Enable DSP mode, and restart instruction. */
regs.sr |= SR_DSP;
regs->sr |= SR_DSP;
return;
}
#endif
asm volatile("stc r2_bank, %0": "=r" (error_code));
lookup_exception_vector(error_code);
local_irq_enable();
tsk->thread.error_code = error_code;
tsk->thread.trap_no = TRAP_RESERVED_INST;
CHK_REMOTE_DEBUG(&regs);
CHK_REMOTE_DEBUG(regs);
force_sig(SIGILL, tsk);
die_if_no_fixup("reserved instruction", &regs, error_code);
die_if_no_fixup("reserved instruction", regs, error_code);
}
#ifdef CONFIG_SH_FPU_EMU
@ -658,39 +733,41 @@ static int emulate_branch(unsigned short inst, struct pt_regs* regs)
asmlinkage void do_illegal_slot_inst(unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
struct pt_regs regs)
struct pt_regs __regs)
{
struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
unsigned long error_code;
struct task_struct *tsk = current;
#ifdef CONFIG_SH_FPU_EMU
unsigned short inst;
unsigned short inst = 0;
get_user(inst, (unsigned short *)regs.pc + 1);
if (!do_fpu_inst(inst, &regs)) {
get_user(inst, (unsigned short *)regs.pc);
if (!emulate_branch(inst, &regs))
get_user(inst, (unsigned short *)regs->pc + 1);
if (!do_fpu_inst(inst, regs)) {
get_user(inst, (unsigned short *)regs->pc);
if (!emulate_branch(inst, regs))
return;
/* fault in branch.*/
}
/* not a FPU inst. */
#endif
asm volatile("stc r2_bank, %0": "=r" (error_code));
lookup_exception_vector(error_code);
local_irq_enable();
tsk->thread.error_code = error_code;
tsk->thread.trap_no = TRAP_RESERVED_INST;
CHK_REMOTE_DEBUG(&regs);
CHK_REMOTE_DEBUG(regs);
force_sig(SIGILL, tsk);
die_if_no_fixup("illegal slot instruction", &regs, error_code);
die_if_no_fixup("illegal slot instruction", regs, error_code);
}
asmlinkage void do_exception_error(unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
struct pt_regs regs)
struct pt_regs __regs)
{
struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
long ex;
asm volatile("stc r2_bank, %0" : "=r" (ex));
die_if_kernel("exception", &regs, ex);
lookup_exception_vector(ex);
die_if_kernel("exception", regs, ex);
}
#if defined(CONFIG_SH_STANDARD_BIOS)
@ -735,12 +812,16 @@ void *set_exception_table_vec(unsigned int vec, void *handler)
{
extern void *exception_handling_table[];
void *old_handler;
old_handler = exception_handling_table[vec];
exception_handling_table[vec] = handler;
return old_handler;
}
extern asmlinkage void address_error_handler(unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
struct pt_regs __regs);
void __init trap_init(void)
{
set_exception_table_vec(TRAP_RESERVED_INST, do_reserved_inst);
@ -759,7 +840,15 @@ void __init trap_init(void)
set_exception_table_evt(0x800, do_fpu_state_restore);
set_exception_table_evt(0x820, do_fpu_state_restore);
#endif
#ifdef CONFIG_CPU_SH2
set_exception_table_vec(TRAP_ADDRESS_ERROR, address_error_handler);
#endif
#ifdef CONFIG_CPU_SH2A
set_exception_table_vec(TRAP_DIVZERO_ERROR, do_divide_error);
set_exception_table_vec(TRAP_DIVOVF_ERROR, do_divide_error);
#endif
/* Setup VBR for boot cpu */
per_cpu_trap_init();
}
@ -784,6 +873,11 @@ void show_trace(struct task_struct *tsk, unsigned long *sp,
}
printk("\n");
if (!tsk)
tsk = current;
debug_show_held_locks(tsk);
}
void show_stack(struct task_struct *tsk, unsigned long *sp)

View File

@ -4,8 +4,12 @@ menu "Processor selection"
# Processor families
#
config CPU_SH2
select SH_WRITETHROUGH if !CPU_SH2A
bool
select SH_WRITETHROUGH
config CPU_SH2A
bool
select CPU_SH2
config CPU_SH3
bool
@ -16,6 +20,7 @@ config CPU_SH4
bool
select CPU_HAS_INTEVT
select CPU_HAS_SR_RB
select CPU_HAS_PTEA if !CPU_SUBTYPE_ST40
config CPU_SH4A
bool
@ -40,6 +45,16 @@ config CPU_SUBTYPE_SH7604
bool "Support SH7604 processor"
select CPU_SH2
config CPU_SUBTYPE_SH7619
bool "Support SH7619 processor"
select CPU_SH2
comment "SH-2A Processor Support"
config CPU_SUBTYPE_SH7206
bool "Support SH7206 processor"
select CPU_SH2A
comment "SH-3 Processor Support"
config CPU_SUBTYPE_SH7300
@ -89,6 +104,7 @@ comment "SH-4 Processor Support"
config CPU_SUBTYPE_SH7750
bool "Support SH7750 processor"
select CPU_SH4
select CPU_HAS_IPR_IRQ
help
Select SH7750 if you have a 200 Mhz SH-4 HD6417750 CPU.
@ -104,15 +120,18 @@ config CPU_SUBTYPE_SH7750R
bool "Support SH7750R processor"
select CPU_SH4
select CPU_SUBTYPE_SH7750
select CPU_HAS_IPR_IRQ
config CPU_SUBTYPE_SH7750S
bool "Support SH7750S processor"
select CPU_SH4
select CPU_SUBTYPE_SH7750
select CPU_HAS_IPR_IRQ
config CPU_SUBTYPE_SH7751
bool "Support SH7751 processor"
select CPU_SH4
select CPU_HAS_IPR_IRQ
help
Select SH7751 if you have a 166 Mhz SH-4 HD6417751 CPU,
or if you have a HD6417751R CPU.
@ -121,6 +140,7 @@ config CPU_SUBTYPE_SH7751R
bool "Support SH7751R processor"
select CPU_SH4
select CPU_SUBTYPE_SH7751
select CPU_HAS_IPR_IRQ
config CPU_SUBTYPE_SH7760
bool "Support SH7760 processor"
@ -157,6 +177,11 @@ config CPU_SUBTYPE_SH7780
select CPU_SH4A
select CPU_HAS_INTC2_IRQ
config CPU_SUBTYPE_SH7785
bool "Support SH7785 processor"
select CPU_SH4A
select CPU_HAS_INTC2_IRQ
comment "SH4AL-DSP Processor Support"
config CPU_SUBTYPE_SH73180
@ -216,13 +241,22 @@ config MEMORY_SIZE
config 32BIT
bool "Support 32-bit physical addressing through PMB"
depends on CPU_SH4A && MMU
depends on CPU_SH4A && MMU && (!X2TLB || BROKEN)
default y
help
If you say Y here, physical addressing will be extended to
32-bits through the SH-4A PMB. If this is not set, legacy
29-bit physical addressing will be used.
config X2TLB
bool "Enable extended TLB mode"
depends on CPU_SUBTYPE_SH7785 && MMU && EXPERIMENTAL
help
Selecting this option will enable the extended mode of the SH-X2
TLB. For legacy SH-X behaviour and interoperability, say N. For
all of the fun new features and a willingless to submit bug reports,
say Y.
config VSYSCALL
bool "Support vsyscall page"
depends on MMU
@ -236,17 +270,53 @@ config VSYSCALL
For systems with an MMU that can afford to give up a page,
(the default value) say Y.
choice
prompt "Kernel page size"
default PAGE_SIZE_4KB
config PAGE_SIZE_4KB
bool "4kB"
help
This is the default page size used by all SuperH CPUs.
config PAGE_SIZE_8KB
bool "8kB"
depends on EXPERIMENTAL && X2TLB
help
This enables 8kB pages as supported by SH-X2 and later MMUs.
config PAGE_SIZE_64KB
bool "64kB"
depends on EXPERIMENTAL && CPU_SH4
help
This enables support for 64kB pages, possible on all SH-4
CPUs and later. Highly experimental, not recommended.
endchoice
choice
prompt "HugeTLB page size"
depends on HUGETLB_PAGE && CPU_SH4 && MMU
default HUGETLB_PAGE_SIZE_64K
config HUGETLB_PAGE_SIZE_64K
bool "64K"
bool "64kB"
config HUGETLB_PAGE_SIZE_256K
bool "256kB"
depends on X2TLB
config HUGETLB_PAGE_SIZE_1MB
bool "1MB"
config HUGETLB_PAGE_SIZE_4MB
bool "4MB"
depends on X2TLB
config HUGETLB_PAGE_SIZE_64MB
bool "64MB"
depends on X2TLB
endchoice
source "mm/Kconfig"
@ -274,7 +344,6 @@ config SH_DIRECT_MAPPED
config SH_WRITETHROUGH
bool "Use write-through caching"
default y if CPU_SH2
help
Selecting this option will configure the caches in write-through
mode, as opposed to the default write-back configuration.

View File

@ -5,6 +5,7 @@
*
* Released under the terms of the GNU GPL v2.0.
*/
#include <linux/init.h>
#include <linux/mm.h>
@ -14,37 +15,43 @@
#include <asm/cacheflush.h>
#include <asm/io.h>
/*
* Calculate the OC address and set the way bit on the SH-2.
*
* We must have already jump_to_P2()'ed prior to calling this
* function, since we rely on CCR manipulation to do the
* Right Thing(tm).
*/
unsigned long __get_oc_addr(unsigned long set, unsigned long way)
void __flush_wback_region(void *start, int size)
{
unsigned long ccr;
unsigned long v;
unsigned long begin, end;
/*
* On SH-2 the way bit isn't tracked in the address field
* if we're doing address array access .. instead, we need
* to manually switch out the way in the CCR.
*/
ccr = ctrl_inl(CCR);
ccr &= ~0x00c0;
ccr |= way << cpu_data->dcache.way_shift;
/*
* Despite the number of sets being halved, we end up losing
* the first 2 ways to OCRAM instead of the last 2 (if we're
* 4-way). As a result, forcibly setting the W1 bit handily
* bumps us up 2 ways.
*/
if (ccr & CCR_CACHE_ORA)
ccr |= 1 << (cpu_data->dcache.way_shift + 1);
ctrl_outl(ccr, CCR);
return CACHE_OC_ADDRESS_ARRAY | (set << cpu_data->dcache.entry_shift);
begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);
end = ((unsigned long)start + size + L1_CACHE_BYTES-1)
& ~(L1_CACHE_BYTES-1);
for (v = begin; v < end; v+=L1_CACHE_BYTES) {
/* FIXME cache purge */
ctrl_outl((v & 0x1ffffc00), (v & 0x00000ff0) | 0x00000008);
}
}
void __flush_purge_region(void *start, int size)
{
unsigned long v;
unsigned long begin, end;
begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);
end = ((unsigned long)start + size + L1_CACHE_BYTES-1)
& ~(L1_CACHE_BYTES-1);
for (v = begin; v < end; v+=L1_CACHE_BYTES) {
ctrl_outl((v & 0x1ffffc00), (v & 0x00000ff0) | 0x00000008);
}
}
void __flush_invalidate_region(void *start, int size)
{
unsigned long v;
unsigned long begin, end;
begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);
end = ((unsigned long)start + size + L1_CACHE_BYTES-1)
& ~(L1_CACHE_BYTES-1);
for (v = begin; v < end; v+=L1_CACHE_BYTES) {
ctrl_outl((v & 0x1ffffc00), (v & 0x00000ff0) | 0x00000008);
}
}

View File

@ -11,12 +11,8 @@
*/
#include <linux/init.h>
#include <linux/mm.h>
#include <asm/addrspace.h>
#include <asm/pgtable.h>
#include <asm/processor.h>
#include <asm/cache.h>
#include <asm/io.h>
#include <asm/pgalloc.h>
#include <linux/io.h>
#include <linux/mutex.h>
#include <asm/mmu_context.h>
#include <asm/cacheflush.h>
@ -83,9 +79,9 @@ static void __init emit_cache_params(void)
*/
/* Worst case assumed to be 64k cache, direct-mapped i.e. 4 synonym bits. */
#define MAX_P3_SEMAPHORES 16
#define MAX_P3_MUTEXES 16
struct semaphore p3map_sem[MAX_P3_SEMAPHORES];
struct mutex p3map_mutex[MAX_P3_MUTEXES];
void __init p3_cache_init(void)
{
@ -115,7 +111,7 @@ void __init p3_cache_init(void)
panic("%s failed.", __FUNCTION__);
for (i = 0; i < cpu_data->dcache.n_aliases; i++)
sema_init(&p3map_sem[i], 1);
mutex_init(&p3map_mutex[i]);
}
/*
@ -229,7 +225,7 @@ static inline void flush_cache_4096(unsigned long start,
*/
if ((cpu_data->flags & CPU_HAS_P2_FLUSH_BUG) ||
(start < CACHE_OC_ADDRESS_ARRAY))
exec_offset = 0x20000000;
exec_offset = 0x20000000;
local_irq_save(flags);
__flush_cache_4096(start | SH_CACHE_ASSOC,
@ -250,7 +246,7 @@ void flush_dcache_page(struct page *page)
/* Loop all the D-cache */
n = cpu_data->dcache.n_aliases;
for (i = 0; i < n; i++, addr += PAGE_SIZE)
for (i = 0; i < n; i++, addr += 4096)
flush_cache_4096(addr, phys);
}

View File

@ -1,12 +1,12 @@
/* $Id: clear_page.S,v 1.13 2003/08/25 17:03:10 lethal Exp $
*
/*
* __clear_user_page, __clear_user, clear_page implementation of SuperH
*
* Copyright (C) 2001 Kaz Kojima
* Copyright (C) 2001, 2002 Niibe Yutaka
*
* Copyright (C) 2006 Paul Mundt
*/
#include <linux/linkage.h>
#include <asm/page.h>
/*
* clear_page_slow
@ -18,11 +18,11 @@
/*
* r0 --- scratch
* r4 --- to
* r5 --- to + 4096
* r5 --- to + PAGE_SIZE
*/
ENTRY(clear_page_slow)
mov r4,r5
mov.w .Llimit,r0
mov.l .Llimit,r0
add r0,r5
mov #0,r0
!
@ -50,7 +50,7 @@ ENTRY(clear_page_slow)
!
rts
nop
.Llimit: .word (4096-28)
.Llimit: .long (PAGE_SIZE-28)
ENTRY(__clear_user)
!
@ -164,10 +164,10 @@ ENTRY(__clear_user)
* r0 --- scratch
* r4 --- to
* r5 --- orig_to
* r6 --- to + 4096
* r6 --- to + PAGE_SIZE
*/
ENTRY(__clear_user_page)
mov.w .L4096,r0
mov.l .Lpsz,r0
mov r4,r6
add r0,r6
mov #0,r0
@ -191,7 +191,7 @@ ENTRY(__clear_user_page)
!
rts
nop
.L4096: .word 4096
.Lpsz: .long PAGE_SIZE
#endif

View File

@ -1,12 +1,12 @@
/* $Id: copy_page.S,v 1.8 2003/08/25 17:03:10 lethal Exp $
*
/*
* copy_page, __copy_user_page, __copy_user implementation of SuperH
*
* Copyright (C) 2001 Niibe Yutaka & Kaz Kojima
* Copyright (C) 2002 Toshinobu Sugioka
*
* Copyright (C) 2006 Paul Mundt
*/
#include <linux/linkage.h>
#include <asm/page.h>
/*
* copy_page_slow
@ -18,7 +18,7 @@
/*
* r0, r1, r2, r3, r4, r5, r6, r7 --- scratch
* r8 --- from + 4096
* r8 --- from + PAGE_SIZE
* r9 --- not used
* r10 --- to
* r11 --- from
@ -30,7 +30,7 @@ ENTRY(copy_page_slow)
mov r4,r10
mov r5,r11
mov r5,r8
mov.w .L4096,r0
mov.l .Lpsz,r0
add r0,r8
!
1: mov.l @r11+,r0
@ -80,7 +80,7 @@ ENTRY(copy_page_slow)
/*
* r0, r1, r2, r3, r4, r5, r6, r7 --- scratch
* r8 --- from + 4096
* r8 --- from + PAGE_SIZE
* r9 --- orig_to
* r10 --- to
* r11 --- from
@ -94,7 +94,7 @@ ENTRY(__copy_user_page)
mov r5,r11
mov r6,r9
mov r5,r8
mov.w .L4096,r0
mov.l .Lpsz,r0
add r0,r8
!
1: ocbi @r9
@ -129,7 +129,7 @@ ENTRY(__copy_user_page)
rts
nop
#endif
.L4096: .word 4096
.Lpsz: .long PAGE_SIZE
/*
* __kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n);
* Return the number of bytes NOT copied

View File

@ -26,13 +26,19 @@ extern void die(const char *,struct pt_regs *,long);
* and the problem, and then passes it off to one of the appropriate
* routines.
*/
asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
unsigned long address)
asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
unsigned long writeaccess,
unsigned long address)
{
struct task_struct *tsk;
struct mm_struct *mm;
struct vm_area_struct * vma;
unsigned long page;
int si_code;
siginfo_t info;
trace_hardirqs_on();
local_irq_enable();
#ifdef CONFIG_SH_KGDB
if (kgdb_nofault && kgdb_bus_err_hook)
@ -41,6 +47,46 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
tsk = current;
mm = tsk->mm;
si_code = SEGV_MAPERR;
if (unlikely(address >= TASK_SIZE)) {
/*
* Synchronize this task's top level page-table
* with the 'reference' page table.
*
* Do _not_ use "tsk" here. We might be inside
* an interrupt in the middle of a task switch..
*/
int offset = pgd_index(address);
pgd_t *pgd, *pgd_k;
pud_t *pud, *pud_k;
pmd_t *pmd, *pmd_k;
pgd = get_TTB() + offset;
pgd_k = swapper_pg_dir + offset;
/* This will never happen with the folded page table. */
if (!pgd_present(*pgd)) {
if (!pgd_present(*pgd_k))
goto bad_area_nosemaphore;
set_pgd(pgd, *pgd_k);
return;
}
pud = pud_offset(pgd, address);
pud_k = pud_offset(pgd_k, address);
if (pud_present(*pud) || !pud_present(*pud_k))
goto bad_area_nosemaphore;
set_pud(pud, *pud_k);
pmd = pmd_offset(pud, address);
pmd_k = pmd_offset(pud_k, address);
if (pmd_present(*pmd) || !pmd_present(*pmd_k))
goto bad_area_nosemaphore;
set_pmd(pmd, *pmd_k);
return;
}
/*
* If we're in an interrupt or have no user
@ -65,6 +111,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
* we can handle it..
*/
good_area:
si_code = SEGV_ACCERR;
if (writeaccess) {
if (!(vma->vm_flags & VM_WRITE))
goto bad_area;
@ -104,10 +151,13 @@ survive:
bad_area:
up_read(&mm->mmap_sem);
bad_area_nosemaphore:
if (user_mode(regs)) {
tsk->thread.address = address;
tsk->thread.error_code = writeaccess;
force_sig(SIGSEGV, tsk);
info.si_signo = SIGSEGV;
info.si_errno = 0;
info.si_code = si_code;
info.si_addr = (void *) address;
force_sig_info(SIGSEGV, &info, tsk);
return;
}
@ -127,11 +177,9 @@ no_context:
printk(KERN_ALERT "Unable to handle kernel paging request");
printk(" at virtual address %08lx\n", address);
printk(KERN_ALERT "pc = %08lx\n", regs->pc);
asm volatile("mov.l %1, %0"
: "=r" (page)
: "m" (__m(MMU_TTB)));
page = (unsigned long)get_TTB();
if (page) {
page = ((unsigned long *) page)[address >> 22];
page = ((unsigned long *) page)[address >> PGDIR_SHIFT];
printk(KERN_ALERT "*pde = %08lx\n", page);
if (page & _PAGE_PRESENT) {
page &= PAGE_MASK;
@ -166,98 +214,13 @@ do_sigbus:
* Send a sigbus, regardless of whether we were in kernel
* or user mode.
*/
tsk->thread.address = address;
tsk->thread.error_code = writeaccess;
tsk->thread.trap_no = 14;
force_sig(SIGBUS, tsk);
info.si_signo = SIGBUS;
info.si_errno = 0;
info.si_code = BUS_ADRERR;
info.si_addr = (void *)address;
force_sig_info(SIGBUS, &info, tsk);
/* Kernel mode? Handle exceptions or die */
if (!user_mode(regs))
goto no_context;
}
#ifdef CONFIG_SH_STORE_QUEUES
/*
* This is a special case for the SH-4 store queues, as pages for this
* space still need to be faulted in before it's possible to flush the
* store queue cache for writeout to the remapped region.
*/
#define P3_ADDR_MAX (P4SEG_STORE_QUE + 0x04000000)
#else
#define P3_ADDR_MAX P4SEG
#endif
/*
* Called with interrupts disabled.
*/
asmlinkage int __kprobes __do_page_fault(struct pt_regs *regs,
unsigned long writeaccess,
unsigned long address)
{
pgd_t *pgd;
pud_t *pud;
pmd_t *pmd;
pte_t *pte;
pte_t entry;
struct mm_struct *mm = current->mm;
spinlock_t *ptl;
int ret = 1;
#ifdef CONFIG_SH_KGDB
if (kgdb_nofault && kgdb_bus_err_hook)
kgdb_bus_err_hook();
#endif
/*
* We don't take page faults for P1, P2, and parts of P4, these
* are always mapped, whether it be due to legacy behaviour in
* 29-bit mode, or due to PMB configuration in 32-bit mode.
*/
if (address >= P3SEG && address < P3_ADDR_MAX) {
pgd = pgd_offset_k(address);
mm = NULL;
} else {
if (unlikely(address >= TASK_SIZE || !mm))
return 1;
pgd = pgd_offset(mm, address);
}
pud = pud_offset(pgd, address);
if (pud_none_or_clear_bad(pud))
return 1;
pmd = pmd_offset(pud, address);
if (pmd_none_or_clear_bad(pmd))
return 1;
if (mm)
pte = pte_offset_map_lock(mm, pmd, address, &ptl);
else
pte = pte_offset_kernel(pmd, address);
entry = *pte;
if (unlikely(pte_none(entry) || pte_not_present(entry)))
goto unlock;
if (unlikely(writeaccess && !pte_write(entry)))
goto unlock;
if (writeaccess)
entry = pte_mkdirty(entry);
entry = pte_mkyoung(entry);
#ifdef CONFIG_CPU_SH4
/*
* ITLB is not affected by "ldtlb" instruction.
* So, we need to flush the entry by ourselves.
*/
__flush_tlb_page(get_asid(), address & PAGE_MASK);
#endif
set_pte(pte, entry);
update_mmu_cache(NULL, address, entry);
ret = 0;
unlock:
if (mm)
pte_unmap_unlock(pte, ptl);
return ret;
}

View File

@ -84,30 +84,22 @@ static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot)
pmd_t *pmd;
pte_t *pte;
pgd = swapper_pg_dir + pgd_index(addr);
pgd = pgd_offset_k(addr);
if (pgd_none(*pgd)) {
pgd_ERROR(*pgd);
return;
}
pud = pud_offset(pgd, addr);
if (pud_none(*pud)) {
pmd = (pmd_t *)get_zeroed_page(GFP_ATOMIC);
set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE | _PAGE_USER));
if (pmd != pmd_offset(pud, 0)) {
pud_ERROR(*pud);
return;
}
pud = pud_alloc(NULL, pgd, addr);
if (unlikely(!pud)) {
pud_ERROR(*pud);
return;
}
pmd = pmd_offset(pud, addr);
if (pmd_none(*pmd)) {
pte = (pte_t *)get_zeroed_page(GFP_ATOMIC);
set_pmd(pmd, __pmd(__pa(pte) | _KERNPG_TABLE | _PAGE_USER));
if (pte != pte_offset_kernel(pmd, 0)) {
pmd_ERROR(*pmd);
return;
}
pmd = pmd_alloc(NULL, pud, addr);
if (unlikely(!pmd)) {
pmd_ERROR(*pmd);
return;
}
pte = pte_offset_kernel(pmd, addr);
@ -155,9 +147,6 @@ extern char __init_begin, __init_end;
/*
* paging_init() sets up the page tables
*
* This routines also unmaps the page at virtual kernel address 0, so
* that we can trap those pesky NULL-reference errors in the kernel.
*/
void __init paging_init(void)
{
@ -180,14 +169,11 @@ void __init paging_init(void)
*/
{
unsigned long max_dma, low, start_pfn;
pgd_t *pg_dir;
int i;
/* We don't need kernel mapping as hardware support that. */
pg_dir = swapper_pg_dir;
for (i = 0; i < PTRS_PER_PGD; i++)
pgd_val(pg_dir[i]) = 0;
/* We don't need to map the kernel through the TLB, as
* it is permanatly mapped using P1. So clear the
* entire pgd. */
memset(swapper_pg_dir, 0, sizeof(swapper_pg_dir));
/* Turn on the MMU */
enable_mmu();
@ -206,6 +192,10 @@ void __init paging_init(void)
}
}
/* Set an initial value for the MMU.TTB so we don't have to
* check for a null value. */
set_TTB(swapper_pg_dir);
#elif defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4)
/*
* If we don't have CONFIG_MMU set and the processor in question
@ -227,7 +217,6 @@ static struct kcore_list kcore_mem, kcore_vmalloc;
void __init mem_init(void)
{
extern unsigned long empty_zero_page[1024];
int codesize, reservedpages, datasize, initsize;
int tmp;
extern unsigned long memory_start;

View File

@ -28,9 +28,7 @@ static inline void remap_area_pte(pte_t * pte, unsigned long address,
{
unsigned long end;
unsigned long pfn;
pgprot_t pgprot = __pgprot(_PAGE_PRESENT | _PAGE_RW |
_PAGE_DIRTY | _PAGE_ACCESSED |
_PAGE_HW_SHARED | _PAGE_FLAGS_HARD | flags);
pgprot_t pgprot = __pgprot(pgprot_val(PAGE_KERNEL_NOCACHE) | flags);
address &= ~PMD_MASK;
end = address + size;

View File

@ -39,8 +39,6 @@ static void copy_page_dma(void *to, void *from)
static void clear_page_dma(void *to)
{
extern unsigned long empty_zero_page[1024];
/*
* We get invoked quite early on, if the DMAC hasn't been initialized
* yet, fall back on the slow manual implementation.

View File

@ -6,22 +6,12 @@
*
* Released under the terms of the GNU GPL v2.0.
*/
#include <linux/init.h>
#include <linux/mman.h>
#include <linux/mm.h>
#include <linux/threads.h>
#include <asm/addrspace.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/processor.h>
#include <asm/cache.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/pgalloc.h>
#include <linux/mutex.h>
#include <asm/mmu_context.h>
#include <asm/cacheflush.h>
extern struct semaphore p3map_sem[];
extern struct mutex p3map_mutex[];
#define CACHE_ALIAS (cpu_data->dcache.alias_mask)
@ -37,10 +27,6 @@ void clear_user_page(void *to, unsigned long address, struct page *page)
if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0)
clear_page(to);
else {
pgprot_t pgprot = __pgprot(_PAGE_PRESENT |
_PAGE_RW | _PAGE_CACHABLE |
_PAGE_DIRTY | _PAGE_ACCESSED |
_PAGE_HW_SHARED | _PAGE_FLAGS_HARD);
unsigned long phys_addr = PHYSADDR(to);
unsigned long p3_addr = P3SEG + (address & CACHE_ALIAS);
pgd_t *pgd = pgd_offset_k(p3_addr);
@ -50,8 +36,8 @@ void clear_user_page(void *to, unsigned long address, struct page *page)
pte_t entry;
unsigned long flags;
entry = pfn_pte(phys_addr >> PAGE_SHIFT, pgprot);
down(&p3map_sem[(address & CACHE_ALIAS)>>12]);
entry = pfn_pte(phys_addr >> PAGE_SHIFT, PAGE_KERNEL);
mutex_lock(&p3map_mutex[(address & CACHE_ALIAS)>>12]);
set_pte(pte, entry);
local_irq_save(flags);
__flush_tlb_page(get_asid(), p3_addr);
@ -59,7 +45,7 @@ void clear_user_page(void *to, unsigned long address, struct page *page)
update_mmu_cache(NULL, p3_addr, entry);
__clear_user_page((void *)p3_addr, to);
pte_clear(&init_mm, p3_addr, pte);
up(&p3map_sem[(address & CACHE_ALIAS)>>12]);
mutex_unlock(&p3map_mutex[(address & CACHE_ALIAS)>>12]);
}
}
@ -77,10 +63,6 @@ void copy_user_page(void *to, void *from, unsigned long address,
if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0)
copy_page(to, from);
else {
pgprot_t pgprot = __pgprot(_PAGE_PRESENT |
_PAGE_RW | _PAGE_CACHABLE |
_PAGE_DIRTY | _PAGE_ACCESSED |
_PAGE_HW_SHARED | _PAGE_FLAGS_HARD);
unsigned long phys_addr = PHYSADDR(to);
unsigned long p3_addr = P3SEG + (address & CACHE_ALIAS);
pgd_t *pgd = pgd_offset_k(p3_addr);
@ -90,8 +72,8 @@ void copy_user_page(void *to, void *from, unsigned long address,
pte_t entry;
unsigned long flags;
entry = pfn_pte(phys_addr >> PAGE_SHIFT, pgprot);
down(&p3map_sem[(address & CACHE_ALIAS)>>12]);
entry = pfn_pte(phys_addr >> PAGE_SHIFT, PAGE_KERNEL);
mutex_lock(&p3map_mutex[(address & CACHE_ALIAS)>>12]);
set_pte(pte, entry);
local_irq_save(flags);
__flush_tlb_page(get_asid(), p3_addr);
@ -99,7 +81,7 @@ void copy_user_page(void *to, void *from, unsigned long address,
update_mmu_cache(NULL, p3_addr, entry);
__copy_user_page((void *)p3_addr, from, to);
pte_clear(&init_mm, p3_addr, pte);
up(&p3map_sem[(address & CACHE_ALIAS)>>12]);
mutex_unlock(&p3map_mutex[(address & CACHE_ALIAS)>>12]);
}
}
@ -122,4 +104,3 @@ inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t
}
return pte;
}

View File

@ -30,3 +30,5 @@ R7780MP SH_R7780MP
TITAN SH_TITAN
SHMIN SH_SHMIN
7710VOIPGW SH_7710VOIPGW
7206SE SH_7206_SOLUTION_ENGINE
7619SE SH_7619_SOLUTION_ENGINE

View File

@ -775,7 +775,7 @@ static int sci_notifier(struct notifier_block *self,
*
* Clean this up later..
*/
clk = clk_get("module_clk");
clk = clk_get(NULL, "module_clk");
port->uartclk = clk_get_rate(clk) * 16;
clk_put(clk);
}
@ -960,7 +960,7 @@ static void sci_set_termios(struct uart_port *port, struct termios *termios,
default:
{
#if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64)
struct clk *clk = clk_get("module_clk");
struct clk *clk = clk_get(NULL, "module_clk");
t = SCBRR_VALUE(baud, clk_get_rate(clk));
clk_put(clk);
#else
@ -1128,7 +1128,7 @@ static void __init sci_init_ports(void)
* XXX: We should use a proper SCI/SCIF clock
*/
{
struct clk *clk = clk_get("module_clk");
struct clk *clk = clk_get(NULL, "module_clk");
sci_ports[i].port.uartclk = clk_get_rate(clk) * 16;
clk_put(clk);
}

View File

@ -133,6 +133,20 @@
# define SCIF_ORER 0x0001 /* Overrun error bit */
# define SCSCR_INIT(port) 0x3a /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
# define SCIF_ONLY
#elif defined(CONFIG_CPU_SUBTYPE_SH7206)
# define SCSPTR0 0xfffe8020 /* 16 bit SCIF */
# define SCSPTR1 0xfffe8820 /* 16 bit SCIF */
# define SCSPTR2 0xfffe9020 /* 16 bit SCIF */
# define SCSPTR3 0xfffe9820 /* 16 bit SCIF */
# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
# define SCIF_ONLY
#elif defined(CONFIG_CPU_SUBTYPE_SH7619)
# define SCSPTR0 0xf8400020 /* 16 bit SCIF */
# define SCSPTR1 0xf8410020 /* 16 bit SCIF */
# define SCSPTR2 0xf8420020 /* 16 bit SCIF */
# define SCIF_ORER 0x0001 /* overrun error bit */
# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
# define SCIF_ONLY
#else
# error CPU subtype not defined
#endif
@ -365,6 +379,7 @@ SCIx_FNS(SCxSR, 0x08, 8, 0x10, 8, 0x08, 16, 0x10, 16, 0x04, 8)
SCIx_FNS(SCxRDR, 0x0a, 8, 0x14, 8, 0x0A, 8, 0x14, 8, 0x05, 8)
SCIF_FNS(SCFCR, 0x0c, 8, 0x18, 16)
#if defined(CONFIG_CPU_SUBTYPE_SH7760) || defined(CONFIG_CPU_SUBTYPE_SH7780)
SCIF_FNS(SCFDR, 0x0e, 16, 0x1C, 16)
SCIF_FNS(SCTFDR, 0x0e, 16, 0x1C, 16)
SCIF_FNS(SCRFDR, 0x0e, 16, 0x20, 16)
SCIF_FNS(SCSPTR, 0, 0, 0x24, 16)
@ -544,6 +559,28 @@ static inline int sci_rxd_in(struct uart_port *port)
if (port->mapbase == 0xffe10000)
return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
}
#elif defined(CONFIG_CPU_SUBTYPE_SH7206)
static inline int sci_rxd_in(struct uart_port *port)
{
if (port->mapbase == 0xfffe8000)
return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */
if (port->mapbase == 0xfffe8800)
return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
if (port->mapbase == 0xfffe9000)
return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
if (port->mapbase == 0xfffe9800)
return ctrl_inw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */
}
#elif defined(CONFIG_CPU_SUBTYPE_SH7619)
static inline int sci_rxd_in(struct uart_port *port)
{
if (port->mapbase == 0xf8400000)
return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */
if (port->mapbase == 0xf8410000)
return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
if (port->mapbase == 0xf8420000)
return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
}
#endif
/*

View File

@ -28,11 +28,11 @@ static inline void atomic_add(int i, atomic_t *v)
unsigned long tmp;
__asm__ __volatile__ (
"1: movli.l @%3, %0 ! atomic_add \n"
" add %2, %0 \n"
" movco.l %0, @%3 \n"
"1: movli.l @%2, %0 ! atomic_add \n"
" add %1, %0 \n"
" movco.l %0, @%2 \n"
" bf 1b \n"
: "=&z" (tmp), "=r" (&v->counter)
: "=&z" (tmp)
: "r" (i), "r" (&v->counter)
: "t");
#else
@ -50,11 +50,11 @@ static inline void atomic_sub(int i, atomic_t *v)
unsigned long tmp;
__asm__ __volatile__ (
"1: movli.l @%3, %0 ! atomic_sub \n"
" sub %2, %0 \n"
" movco.l %0, @%3 \n"
"1: movli.l @%2, %0 ! atomic_sub \n"
" sub %1, %0 \n"
" movco.l %0, @%2 \n"
" bf 1b \n"
: "=&z" (tmp), "=r" (&v->counter)
: "=&z" (tmp)
: "r" (i), "r" (&v->counter)
: "t");
#else
@ -80,12 +80,12 @@ static inline int atomic_add_return(int i, atomic_t *v)
#ifdef CONFIG_CPU_SH4A
__asm__ __volatile__ (
"1: movli.l @%3, %0 ! atomic_add_return \n"
" add %2, %0 \n"
" movco.l %0, @%3 \n"
"1: movli.l @%2, %0 ! atomic_add_return \n"
" add %1, %0 \n"
" movco.l %0, @%2 \n"
" bf 1b \n"
" synco \n"
: "=&z" (temp), "=r" (&v->counter)
: "=&z" (temp)
: "r" (i), "r" (&v->counter)
: "t");
#else
@ -109,12 +109,12 @@ static inline int atomic_sub_return(int i, atomic_t *v)
#ifdef CONFIG_CPU_SH4A
__asm__ __volatile__ (
"1: movli.l @%3, %0 ! atomic_sub_return \n"
" sub %2, %0 \n"
" movco.l %0, @%3 \n"
"1: movli.l @%2, %0 ! atomic_sub_return \n"
" sub %1, %0 \n"
" movco.l %0, @%2 \n"
" bf 1b \n"
" synco \n"
: "=&z" (temp), "=r" (&v->counter)
: "=&z" (temp)
: "r" (i), "r" (&v->counter)
: "t");
#else
@ -186,11 +186,11 @@ static inline void atomic_clear_mask(unsigned int mask, atomic_t *v)
unsigned long tmp;
__asm__ __volatile__ (
"1: movli.l @%3, %0 ! atomic_clear_mask \n"
" and %2, %0 \n"
" movco.l %0, @%3 \n"
"1: movli.l @%2, %0 ! atomic_clear_mask \n"
" and %1, %0 \n"
" movco.l %0, @%2 \n"
" bf 1b \n"
: "=&z" (tmp), "=r" (&v->counter)
: "=&z" (tmp)
: "r" (~mask), "r" (&v->counter)
: "t");
#else
@ -208,11 +208,11 @@ static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
unsigned long tmp;
__asm__ __volatile__ (
"1: movli.l @%3, %0 ! atomic_set_mask \n"
" or %2, %0 \n"
" movco.l %0, @%3 \n"
"1: movli.l @%2, %0 ! atomic_set_mask \n"
" or %1, %0 \n"
" movco.l %0, @%2 \n"
" bf 1b \n"
: "=&z" (tmp), "=r" (&v->counter)
: "=&z" (tmp)
: "r" (mask), "r" (&v->counter)
: "t");
#else

View File

@ -23,16 +23,20 @@ static void __init check_bugs(void)
cpu_data->loops_per_jiffy = loops_per_jiffy;
switch (cpu_data->type) {
case CPU_SH7604:
case CPU_SH7604 ... CPU_SH7619:
*p++ = '2';
break;
case CPU_SH7206:
*p++ = '2';
*p++ = 'a';
break;
case CPU_SH7705 ... CPU_SH7300:
*p++ = '3';
break;
case CPU_SH7750 ... CPU_SH4_501:
*p++ = '4';
break;
case CPU_SH7770 ... CPU_SH7781:
case CPU_SH7770 ... CPU_SH7785:
*p++ = '4';
*p++ = 'a';
break;

View File

@ -4,6 +4,7 @@
#include <linux/kref.h>
#include <linux/list.h>
#include <linux/seq_file.h>
#include <linux/clk.h>
struct clk;
@ -18,7 +19,7 @@ struct clk_ops {
struct clk {
struct list_head node;
const char *name;
int id;
struct module *owner;
struct clk *parent;
@ -40,22 +41,13 @@ void arch_init_clk_ops(struct clk_ops **, int type);
int clk_init(void);
int __clk_enable(struct clk *);
int clk_enable(struct clk *);
void __clk_disable(struct clk *);
void clk_disable(struct clk *);
int clk_set_rate(struct clk *, unsigned long rate);
unsigned long clk_get_rate(struct clk *);
void clk_recalc_rate(struct clk *);
struct clk *clk_get(const char *id);
void clk_put(struct clk *);
int clk_register(struct clk *);
void clk_unregister(struct clk *);
int show_clocks(struct seq_file *m);
#endif /* __ASM_SH_CLOCK_H */

View File

@ -12,6 +12,7 @@
#define L1_CACHE_SHIFT 4
#if defined(CONFIG_CPU_SUBTYPE_SH7604)
#define CCR 0xfffffe92 /* Address of Cache Control Register */
#define CCR_CACHE_CE 0x01 /* Cache enable */
@ -27,5 +28,26 @@
#define CCR_CACHE_ORA CCR_CACHE_TW
#define CCR_CACHE_WT 0x00 /* SH-2 is _always_ write-through */
#elif defined(CONFIG_CPU_SUBTYPE_SH7619)
#define CCR1 0xffffffec
#define CCR CCR1
#define CCR_CACHE_CE 0x01 /* Cache enable */
#define CCR_CACHE_WT 0x06 /* CCR[bit1=1,bit2=1] */
/* 0x00000000-0x7fffffff: Write-through */
/* 0x80000000-0x9fffffff: Write-back */
/* 0xc0000000-0xdfffffff: Write-through */
#define CCR_CACHE_CB 0x00 /* CCR[bit1=0,bit2=0] */
/* 0x00000000-0x7fffffff: Write-back */
/* 0x80000000-0x9fffffff: Write-through */
/* 0xc0000000-0xdfffffff: Write-back */
#define CCR_CACHE_CF 0x08 /* Cache invalidate */
#define CACHE_OC_ADDRESS_ARRAY 0xf0000000
#define CACHE_OC_DATA_ARRAY 0xf1000000
#define CCR_CACHE_ENABLE CCR_CACHE_CE
#define CCR_CACHE_INVALIDATE CCR_CACHE_CF
#endif
#endif /* __ASM_CPU_SH2_CACHE_H */

View File

@ -0,0 +1,18 @@
/*
* include/asm-sh/cpu-sh2/freq.h
*
* Copyright (C) 2006 Yoshinori Sato
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#ifndef __ASM_CPU_SH2_FREQ_H
#define __ASM_CPU_SH2_FREQ_H
#if defined(CONFIG_CPU_SUBTYPE_SH7619)
#define FREQCR 0xf815ff80
#endif
#endif /* __ASM_CPU_SH2_FREQ_H */

View File

@ -0,0 +1,16 @@
/*
* include/asm-sh/cpu-sh2/mmu_context.h
*
* Copyright (C) 2003 Paul Mundt
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#ifndef __ASM_CPU_SH2_MMU_CONTEXT_H
#define __ASM_CPU_SH2_MMU_CONTEXT_H
/* No MMU */
#endif /* __ASM_CPU_SH2_MMU_CONTEXT_H */

View File

@ -0,0 +1,6 @@
#ifndef __ASM_CPU_SH2_TIMER_H
#define __ASM_CPU_SH2_TIMER_H
/* Nothing needed yet */
#endif /* __ASM_CPU_SH2_TIMER_H */

View File

@ -0,0 +1 @@
#include <asm/cpu-sh2/addrspace.h>

View File

@ -0,0 +1,39 @@
/*
* include/asm-sh/cpu-sh2a/cache.h
*
* Copyright (C) 2004 Paul Mundt
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#ifndef __ASM_CPU_SH2A_CACHE_H
#define __ASM_CPU_SH2A_CACHE_H
#define L1_CACHE_SHIFT 4
#define CCR1 0xfffc1000
#define CCR2 0xfffc1004
/* CCR1 behaves more like the traditional CCR */
#define CCR CCR1
/*
* Most of the SH-2A CCR1 definitions resemble the SH-4 ones. All others not
* listed here are reserved.
*/
#define CCR_CACHE_CB 0x0000 /* Hack */
#define CCR_CACHE_OCE 0x0001
#define CCR_CACHE_WT 0x0002
#define CCR_CACHE_OCI 0x0008 /* OCF */
#define CCR_CACHE_ICE 0x0100
#define CCR_CACHE_ICI 0x0800 /* ICF */
#define CACHE_IC_ADDRESS_ARRAY 0xf0000000
#define CACHE_OC_ADDRESS_ARRAY 0xf0800000
#define CCR_CACHE_ENABLE (CCR_CACHE_OCE | CCR_CACHE_ICE)
#define CCR_CACHE_INVALIDATE (CCR_CACHE_OCI | CCR_CACHE_ICI)
#endif /* __ASM_CPU_SH2A_CACHE_H */

View File

@ -0,0 +1 @@
#include <asm/cpu-sh2/cacheflush.h>

View File

@ -0,0 +1 @@
#include <asm/cpu-sh2/dma.h>

View File

@ -0,0 +1,18 @@
/*
* include/asm-sh/cpu-sh2a/freq.h
*
* Copyright (C) 2006 Yoshinori Sato
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#ifndef __ASM_CPU_SH2A_FREQ_H
#define __ASM_CPU_SH2A_FREQ_H
#if defined(CONFIG_CPU_SUBTYPE_SH7206)
#define FREQCR 0xfffe0010
#endif
#endif /* __ASM_CPU_SH2A_FREQ_H */

Some files were not shown because too many files have changed in this diff Show More