提交 9d4436a6 编写于 作者: Y Yoshinori Sato 提交者: Paul Mundt

sh: Add support for SH7206 and SH7619 CPU subtypes.

This implements initial support for the SH7206 (SH-2A) and SH7619
(SH-2) MMU-less CPUs.
Signed-off-by: NYoshinori Sato <ysato@users.sourceforge.jp>
Signed-off-by: NPaul Mundt <lethal@linux-sh.org>
上级 e6243863
...@@ -219,6 +219,20 @@ config SH_SHMIN ...@@ -219,6 +219,20 @@ config SH_SHMIN
help help
Select SHMIN if configuring for the SHMIN board. 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 config SH_UNKNOWN
bool "BareCPU" bool "BareCPU"
help help
...@@ -364,10 +378,25 @@ depends on !GENERIC_TIME ...@@ -364,10 +378,25 @@ depends on !GENERIC_TIME
config SH_TMU config SH_TMU
bool "TMU timer support" bool "TMU timer support"
depends on CPU_SH3 || CPU_SH4
default y default y
help help
This enables the use of the TMU as the system timer. 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 endmenu
source "arch/sh/boards/renesas/hs7751rvoip/Kconfig" source "arch/sh/boards/renesas/hs7751rvoip/Kconfig"
...@@ -378,17 +407,25 @@ source "arch/sh/boards/renesas/r7780rp/Kconfig" ...@@ -378,17 +407,25 @@ source "arch/sh/boards/renesas/r7780rp/Kconfig"
config SH_PCLK_FREQ config SH_PCLK_FREQ
int "Peripheral clock frequency (in Hz)" 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 "50000000" if CPU_SUBTYPE_SH7750 || CPU_SUBTYPE_SH7780
default "60000000" if CPU_SUBTYPE_SH7751 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 default "66000000" if CPU_SUBTYPE_SH4_202
help help
This option is used to specify the peripheral clock frequency. This option is used to specify the peripheral clock frequency.
This is necessary for determining the reference clock value on This is necessary for determining the reference clock value on
platforms lacking an RTC. 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" menu "CPU Frequency scaling"
source "drivers/cpufreq/Kconfig" source "drivers/cpufreq/Kconfig"
......
...@@ -109,6 +109,8 @@ machdir-$(CONFIG_SH_SH4202_MICRODEV) := superh/microdev ...@@ -109,6 +109,8 @@ machdir-$(CONFIG_SH_SH4202_MICRODEV) := superh/microdev
machdir-$(CONFIG_SH_LANDISK) := landisk machdir-$(CONFIG_SH_LANDISK) := landisk
machdir-$(CONFIG_SH_TITAN) := titan machdir-$(CONFIG_SH_TITAN) := titan
machdir-$(CONFIG_SH_SHMIN) := shmin 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 machdir-$(CONFIG_SH_UNKNOWN) := unknown
incdir-y := $(notdir $(machdir-y)) incdir-y := $(notdir $(machdir-y))
...@@ -124,6 +126,7 @@ core-$(CONFIG_HD64465) += arch/sh/cchips/hd6446x/hd64465/ ...@@ -124,6 +126,7 @@ core-$(CONFIG_HD64465) += arch/sh/cchips/hd6446x/hd64465/
core-$(CONFIG_VOYAGERGX) += arch/sh/cchips/voyagergx/ core-$(CONFIG_VOYAGERGX) += arch/sh/cchips/voyagergx/
cpuincdir-$(CONFIG_CPU_SH2) := cpu-sh2 cpuincdir-$(CONFIG_CPU_SH2) := cpu-sh2
cpuincdir-$(CONFIG_CPU_SH2A) := cpu-sh2a
cpuincdir-$(CONFIG_CPU_SH3) := cpu-sh3 cpuincdir-$(CONFIG_CPU_SH3) := cpu-sh3
cpuincdir-$(CONFIG_CPU_SH4) := cpu-sh4 cpuincdir-$(CONFIG_CPU_SH4) := cpu-sh4
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
*/ */
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/addrspace.h>
#ifdef CONFIG_SH_STANDARD_BIOS #ifdef CONFIG_SH_STANDARD_BIOS
#include <asm/sh_bios.h> #include <asm/sh_bios.h>
#endif #endif
...@@ -228,7 +229,7 @@ long* stack_start = &user_stack[STACK_SIZE]; ...@@ -228,7 +229,7 @@ long* stack_start = &user_stack[STACK_SIZE];
void decompress_kernel(void) void decompress_kernel(void)
{ {
output_data = 0; output_data = 0;
output_ptr = (unsigned long)&_text+0x20001000; output_ptr = P2SEGADDR((unsigned long)&_text+0x1000);
free_mem_ptr = (unsigned long)&_end; free_mem_ptr = (unsigned long)&_end;
free_mem_end_ptr = free_mem_ptr + HEAP_SIZE; free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
extra-y := head.o init_task.o vmlinux.lds 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 \ ptrace.o setup.o time.o sys_sh.o semaphore.o \
io.o io_generic.o sh_ksyms.o syscalls.o io.o io_generic.o sh_ksyms.o syscalls.o
......
...@@ -2,11 +2,12 @@ ...@@ -2,11 +2,12 @@
# Makefile for the Linux/SuperH CPU-specifc backends. # Makefile for the Linux/SuperH CPU-specifc backends.
# #
obj-y += irq/ init.o clock.o obj-$(CONFIG_CPU_SH2) = sh2/
obj-$(CONFIG_CPU_SH2A) = sh2a/
obj-$(CONFIG_CPU_SH2) += sh2/ obj-$(CONFIG_CPU_SH3) = sh3/
obj-$(CONFIG_CPU_SH3) += sh3/ obj-$(CONFIG_CPU_SH4) = sh4/
obj-$(CONFIG_CPU_SH4) += sh4/
obj-$(CONFIG_UBC_WAKEUP) += ubc.o obj-$(CONFIG_UBC_WAKEUP) += ubc.o
obj-$(CONFIG_SH_ADC) += adc.o obj-$(CONFIG_SH_ADC) += adc.o
obj-y += irq/ init.o clock.o
...@@ -68,12 +68,14 @@ static void __init cache_init(void) ...@@ -68,12 +68,14 @@ static void __init cache_init(void)
waysize = cpu_data->dcache.sets; waysize = cpu_data->dcache.sets;
#ifdef CCR_CACHE_ORA
/* /*
* If the OC is already in RAM mode, we only have * If the OC is already in RAM mode, we only have
* half of the entries to flush.. * half of the entries to flush..
*/ */
if (ccr & CCR_CACHE_ORA) if (ccr & CCR_CACHE_ORA)
waysize >>= 1; waysize >>= 1;
#endif
waysize <<= cpu_data->dcache.entry_shift; waysize <<= cpu_data->dcache.entry_shift;
......
...@@ -53,7 +53,10 @@ void static inline set_interrupt_registers(int ip) ...@@ -53,7 +53,10 @@ void static inline set_interrupt_registers(int ip)
{ {
unsigned long __dummy; 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" "stc sr, %0\n\t"
"and #0xf0, %0\n\t" "and #0xf0, %0\n\t"
"shlr2 %0\n\t" "shlr2 %0\n\t"
......
...@@ -62,6 +62,10 @@ void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs) ...@@ -62,6 +62,10 @@ void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs)
} }
EXPORT_SYMBOL(make_ipr_irq); EXPORT_SYMBOL(make_ipr_irq);
/*
* XXX: Move this garbage in to the drivers, and kill off the ridiculous CPU
* subtype checks.
*/
static struct ipr_data sys_ipr_map[] = { static struct ipr_data sys_ipr_map[] = {
#ifndef CONFIG_CPU_SUBTYPE_SH7780 #ifndef CONFIG_CPU_SUBTYPE_SH7780
{ TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY }, { TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY },
...@@ -80,6 +84,18 @@ static struct ipr_data sys_ipr_map[] = { ...@@ -80,6 +84,18 @@ static struct ipr_data sys_ipr_map[] = {
{ SCIF1_BRI_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 }, { SCIF1_TXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY },
#endif #endif
#ifdef SCIF2_ERI_IRQ
{ SCIF2_ERI_IRQ, SCIF2_IPR_ADDR, SCIF2_IPR_POS, SCIF2_PRIORITY },
{ SCIF2_RXI_IRQ, SCIF2_IPR_ADDR, SCIF2_IPR_POS, SCIF2_PRIORITY },
{ SCIF2_BRI_IRQ, SCIF2_IPR_ADDR, SCIF2_IPR_POS, SCIF2_PRIORITY },
{ SCIF2_TXI_IRQ, SCIF2_IPR_ADDR, SCIF2_IPR_POS, SCIF2_PRIORITY },
#endif
#ifdef SCIF3_ERI_IRQ
{ SCIF3_ERI_IRQ, SCIF3_IPR_ADDR, SCIF3_IPR_POS, SCIF3_PRIORITY },
{ SCIF3_RXI_IRQ, SCIF3_IPR_ADDR, SCIF3_IPR_POS, SCIF3_PRIORITY },
{ SCIF3_BRI_IRQ, SCIF3_IPR_ADDR, SCIF3_IPR_POS, SCIF3_PRIORITY },
{ SCIF3_TXI_IRQ, SCIF3_IPR_ADDR, SCIF3_IPR_POS, SCIF3_PRIORITY },
#endif
#if defined(CONFIG_CPU_SUBTYPE_SH7300) #if defined(CONFIG_CPU_SUBTYPE_SH7300)
{ SCIF0_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS, SCIF0_PRIORITY }, { SCIF0_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS, SCIF0_PRIORITY },
{ DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY }, { DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY },
......
...@@ -2,5 +2,6 @@ ...@@ -2,5 +2,6 @@
# Makefile for the Linux/SuperH SH-2 backends. # 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
/*
* 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];
}
...@@ -17,17 +17,23 @@ ...@@ -17,17 +17,23 @@
int __init detect_cpu_and_cache_system(void) int __init detect_cpu_and_cache_system(void)
{ {
/* #if defined(CONFIG_CPU_SUBTYPE_SH7604)
* For now, assume SH7604 .. fix this later.
*/
cpu_data->type = CPU_SH7604; cpu_data->type = CPU_SH7604;
cpu_data->dcache.ways = 4; 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.sets = 64;
cpu_data->dcache.entry_shift = 4; cpu_data->dcache.entry_shift = 4;
cpu_data->dcache.linesz = L1_CACHE_BYTES; cpu_data->dcache.linesz = L1_CACHE_BYTES;
cpu_data->dcache.flags = 0; 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 * SH-2 doesn't have separate caches
*/ */
......
/*
* 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);
#
# 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
/*
* 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];
}
/*
* 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;
}
/*
* 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);
...@@ -404,6 +404,7 @@ static const char *cpu_name[] = { ...@@ -404,6 +404,7 @@ static const char *cpu_name[] = {
[CPU_SH4_202] = "SH4-202", [CPU_SH4_501] = "SH4-501", [CPU_SH4_202] = "SH4-202", [CPU_SH4_501] = "SH4-501",
[CPU_SH7770] = "SH7770", [CPU_SH7780] = "SH7780", [CPU_SH7770] = "SH7770", [CPU_SH7780] = "SH7780",
[CPU_SH7781] = "SH7781", [CPU_SH7343] = "SH7343", [CPU_SH7781] = "SH7781", [CPU_SH7343] = "SH7343",
[CPU_SH7206] = "SH7206", [CPU_SH7619] = "SH7619",
[CPU_SH_NONE] = "Unknown" [CPU_SH_NONE] = "Unknown"
}; };
......
...@@ -98,7 +98,11 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, ...@@ -98,7 +98,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 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) */ #define OR_R0_R0 0x200b /* or r0,r0 (insert to avoid hardware bug) */
struct sigframe struct sigframe
...@@ -350,7 +354,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, ...@@ -350,7 +354,7 @@ static int setup_frame(int sig, struct k_sigaction *ka,
} else { } else {
/* Generate return code (system call to sigreturn) */ /* Generate return code (system call to sigreturn) */
err |= __put_user(MOVW(7), &frame->retcode[0]); 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[2]);
err |= __put_user(OR_R0_R0, &frame->retcode[3]); err |= __put_user(OR_R0_R0, &frame->retcode[3]);
err |= __put_user(OR_R0_R0, &frame->retcode[4]); err |= __put_user(OR_R0_R0, &frame->retcode[4]);
...@@ -430,7 +434,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -430,7 +434,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
} else { } else {
/* Generate return code (system call to rt_sigreturn) */ /* Generate return code (system call to rt_sigreturn) */
err |= __put_user(MOVW(7), &frame->retcode[0]); 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[2]);
err |= __put_user(OR_R0_R0, &frame->retcode[3]); err |= __put_user(OR_R0_R0, &frame->retcode[3]);
err |= __put_user(OR_R0_R0, &frame->retcode[4]); err |= __put_user(OR_R0_R0, &frame->retcode[4]);
......
...@@ -5,4 +5,6 @@ ...@@ -5,4 +5,6 @@
obj-y := timer.o obj-y := timer.o
obj-$(CONFIG_SH_TMU) += timer-tmu.o obj-$(CONFIG_SH_TMU) += timer-tmu.o
obj-$(CONFIG_SH_MTU2) += timer-mtu2.o
obj-$(CONFIG_SH_CMT) += timer-cmt.o
/*
* 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/spinlock.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 DEFINE_SPINLOCK(cmt0_lock);
static unsigned long cmt_timer_get_offset(void)
{
int count;
unsigned long flags;
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;
spin_lock_irqsave(&cmt0_lock, flags);
/* 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;
spin_unlock_irqrestore(&cmt0_lock, flags);
count = ((LATCH-1) - count) * TICK_SIZE;
count = (count + LATCH/2) / LATCH;
return count;
}
static irqreturn_t cmt_timer_interrupt(int irq, void *dev_id,
struct pt_regs *regs)
{
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(regs);
write_sequnlock(&xtime_lock);
return IRQ_HANDLED;
}
static struct irqaction cmt_irq = {
.name = "timer",
.handler = cmt_timer_interrupt,
.flags = SA_INTERRUPT,
.mask = CPU_MASK_NONE,
};
/*
* Hah! We'll see if this works (switching from usecs to nsecs).
*/
static unsigned long cmt_timer_get_frequency(void)
{
u32 freq;
struct timespec ts1, ts2;
unsigned long diff_nsec;
unsigned long factor;
/* Setup the timer: We don't want to generate interrupts, just
* have it count down at its natural rate.
*/
ctrl_outw(ctrl_inw(CMT_CMSTR) & ~0x01, CMT_CMSTR);
ctrl_outw(CMT_CMCSR_CALIB, CMT_CMCSR_0);
ctrl_outw(0xffff, CMT_CMCOR_0);
ctrl_outw(0xffff, CMT_CMCNT_0);
rtc_sh_get_time(&ts2);
do {
rtc_sh_get_time(&ts1);
} while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec);
/* actually start the timer */
ctrl_outw(ctrl_inw(CMT_CMSTR) | 0x01, CMT_CMSTR);
do {
rtc_sh_get_time(&ts2);
} while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec);
freq = 0xffff - ctrl_inw(CMT_CMCNT_0);
if (ts2.tv_nsec < ts1.tv_nsec) {
ts2.tv_nsec += 1000000000;
ts2.tv_sec--;
}
diff_nsec = (ts2.tv_sec - ts1.tv_sec) * 1000000000 + (ts2.tv_nsec - ts1.tv_nsec);
/* this should work well if the RTC has a precision of n Hz, where
* n is an integer. I don't think we have to worry about the other
* cases. */
factor = (1000000000 + diff_nsec/2) / diff_nsec;
if (factor * diff_nsec > 1100000000 ||
factor * diff_nsec < 900000000)
panic("weird RTC (diff_nsec %ld)", diff_nsec);
return freq * factor;
}
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("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(TIMER_IRQ, &cmt_irq);
cmt0_clk.parent = clk_get("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,
.get_frequency = cmt_timer_get_frequency,
.get_offset = cmt_timer_get_offset,
};
struct sys_timer cmt_timer = {
.name = "cmt",
.ops = &cmt_timer_ops,
};
/*
* 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/spinlock.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.
*/
static DEFINE_SPINLOCK(mtu2_lock);
#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;
unsigned long flags;
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;
spin_lock_irqsave(&mtu2_lock, flags);
/* 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;
spin_unlock_irqrestore(&mtu2_lock, flags);
count = ((LATCH-1) - count) * TICK_SIZE;
count = (count + LATCH/2) / LATCH;
return count;
}
static irqreturn_t mtu2_timer_interrupt(int irq, void *dev_id,
struct pt_regs *regs)
{
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(regs);
write_sequnlock(&xtime_lock);
return IRQ_HANDLED;
}
static struct irqaction mtu2_irq = {
.name = "timer",
.handler = mtu2_timer_interrupt,
.flags = SA_INTERRUPT,
.mask = CPU_MASK_NONE,
};
/*
* Hah! We'll see if this works (switching from usecs to nsecs).
*/
static unsigned long mtu2_timer_get_frequency(void)
{
u32 freq;
struct timespec ts1, ts2;
unsigned long diff_nsec;
unsigned long factor;
/* Setup the timer: We don't want to generate interrupts, just
* have it count down at its natural rate.
*/
ctrl_outb(ctrl_inb(MTU2_TSTR) & ~MTU2_TSTR_CST1, MTU2_TSTR);
ctrl_outb(MTU2_TCR_CALIB, MTU2_TCR_1);
ctrl_outb(ctrl_inb(MTU2_TIER_1) & ~MTU2_TIER_TGIEA, MTU2_TIER_1);
ctrl_outw(0, MTU2_TCNT_1);
rtc_get_time(&ts2);
do {
rtc_get_time(&ts1);
} while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec);
/* actually start the timer */
ctrl_outw(ctrl_inw(CMT_CMSTR) | 0x01, CMT_CMSTR);
do {
rtc_get_time(&ts2);
} while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec);
freq = ctrl_inw(MTU2_TCNT_0);
if (ts2.tv_nsec < ts1.tv_nsec) {
ts2.tv_nsec += 1000000000;
ts2.tv_sec--;
}
diff_nsec = (ts2.tv_sec - ts1.tv_sec) * 1000000000 + (ts2.tv_nsec - ts1.tv_nsec);
/* this should work well if the RTC has a precision of n Hz, where
* n is an integer. I don't think we have to worry about the other
* cases. */
factor = (1000000000 + diff_nsec/2) / diff_nsec;
if (factor * diff_nsec > 1100000000 ||
factor * diff_nsec < 900000000)
panic("weird RTC (diff_nsec %ld)", diff_nsec);
return freq * factor;
}
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(TIMER_IRQ, &mtu2_irq);
mtu2_clk1.parent = clk_get("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,
.get_frequency = mtu2_timer_get_frequency,
.get_offset = mtu2_timer_get_offset,
};
struct sys_timer mtu2_timer = {
.name = "mtu2",
.ops = &mtu2_timer_ops,
};
...@@ -16,6 +16,12 @@ ...@@ -16,6 +16,12 @@
static struct sys_timer *sys_timers[] __initdata = { static struct sys_timer *sys_timers[] __initdata = {
#ifdef CONFIG_SH_TMU #ifdef CONFIG_SH_TMU
&tmu_timer, &tmu_timer,
#endif
#ifdef CONFIG_SH_MTU2
&mtu2_timer,
#endif
#ifdef CONFIG_SH_CMT
&cmt_timer,
#endif #endif
NULL, NULL,
}; };
......
...@@ -4,8 +4,12 @@ menu "Processor selection" ...@@ -4,8 +4,12 @@ menu "Processor selection"
# Processor families # Processor families
# #
config CPU_SH2 config CPU_SH2
select SH_WRITETHROUGH if !CPU_SH2A
bool bool
select SH_WRITETHROUGH
config CPU_SH2A
bool
select CPU_SH2
config CPU_SH3 config CPU_SH3
bool bool
...@@ -40,6 +44,16 @@ config CPU_SUBTYPE_SH7604 ...@@ -40,6 +44,16 @@ config CPU_SUBTYPE_SH7604
bool "Support SH7604 processor" bool "Support SH7604 processor"
select CPU_SH2 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" comment "SH-3 Processor Support"
config CPU_SUBTYPE_SH7300 config CPU_SUBTYPE_SH7300
...@@ -274,7 +288,6 @@ config SH_DIRECT_MAPPED ...@@ -274,7 +288,6 @@ config SH_DIRECT_MAPPED
config SH_WRITETHROUGH config SH_WRITETHROUGH
bool "Use write-through caching" bool "Use write-through caching"
default y if CPU_SH2
help help
Selecting this option will configure the caches in write-through Selecting this option will configure the caches in write-through
mode, as opposed to the default write-back configuration. mode, as opposed to the default write-back configuration.
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
* *
* Released under the terms of the GNU GPL v2.0. * Released under the terms of the GNU GPL v2.0.
*/ */
#include <linux/init.h> #include <linux/init.h>
#include <linux/mm.h> #include <linux/mm.h>
...@@ -14,37 +15,43 @@ ...@@ -14,37 +15,43 @@
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/io.h> #include <asm/io.h>
/* void __flush_wback_region(void *start, int size)
* 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)
{ {
unsigned long ccr; unsigned long v;
unsigned long begin, end;
/*
* On SH-2 the way bit isn't tracked in the address field begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);
* if we're doing address array access .. instead, we need end = ((unsigned long)start + size + L1_CACHE_BYTES-1)
* to manually switch out the way in the CCR. & ~(L1_CACHE_BYTES-1);
*/ for (v = begin; v < end; v+=L1_CACHE_BYTES) {
ccr = ctrl_inl(CCR); /* FIXME cache purge */
ccr &= ~0x00c0; ctrl_outl((v & 0x1ffffc00), (v & 0x00000ff0) | 0x00000008);
ccr |= way << cpu_data->dcache.way_shift; }
}
/*
* Despite the number of sets being halved, we end up losing void __flush_purge_region(void *start, int size)
* 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 unsigned long v;
* bumps us up 2 ways. unsigned long begin, end;
*/
if (ccr & CCR_CACHE_ORA) begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);
ccr |= 1 << (cpu_data->dcache.way_shift + 1); end = ((unsigned long)start + size + L1_CACHE_BYTES-1)
& ~(L1_CACHE_BYTES-1);
ctrl_outl(ccr, CCR); for (v = begin; v < end; v+=L1_CACHE_BYTES) {
ctrl_outl((v & 0x1ffffc00), (v & 0x00000ff0) | 0x00000008);
return CACHE_OC_ADDRESS_ARRAY | (set << cpu_data->dcache.entry_shift); }
}
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);
}
} }
...@@ -30,3 +30,5 @@ R7780MP SH_R7780MP ...@@ -30,3 +30,5 @@ R7780MP SH_R7780MP
TITAN SH_TITAN TITAN SH_TITAN
SHMIN SH_SHMIN SHMIN SH_SHMIN
7710VOIPGW SH_7710VOIPGW 7710VOIPGW SH_7710VOIPGW
7206SE SH_7206_SOLUTION_ENGINE
7619SE SH_7619_SOLUTION_ENGINE
...@@ -133,6 +133,20 @@ ...@@ -133,6 +133,20 @@
# define SCIF_ORER 0x0001 /* Overrun error bit */ # define SCIF_ORER 0x0001 /* Overrun error bit */
# define SCSCR_INIT(port) 0x3a /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ # define SCSCR_INIT(port) 0x3a /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
# define SCIF_ONLY # 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 #else
# error CPU subtype not defined # error CPU subtype not defined
#endif #endif
...@@ -544,6 +558,28 @@ static inline int sci_rxd_in(struct uart_port *port) ...@@ -544,6 +558,28 @@ static inline int sci_rxd_in(struct uart_port *port)
if (port->mapbase == 0xffe10000) if (port->mapbase == 0xffe10000)
return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ 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 #endif
/* /*
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册