Commit 2b1bd1ac authored by Paul Mundt's avatar Paul Mundt

sh: Preliminary support for the SH-X3 CPU.

This adds basic support for UP SH-X3.
Signed-off-by: default avatarPaul Mundt <lethal@linux-sh.org>
parent 027e56e6
......@@ -598,6 +598,7 @@ config NR_CPUS
int "Maximum number of CPUs (2-32)"
range 2 32
depends on SMP
default "4" if CPU_SHX3
default "2"
help
This allows you to specify the maximum number of CPUs which this
......
This diff is collapsed.
......@@ -340,8 +340,27 @@ ENTRY(vbr_base)
general_exception:
mov.l 1f, k2
mov.l 2f, k3
#ifdef CONFIG_CPU_SUBTYPE_SHX3
mov.l @k2, k2
! Is EXPEVT larger than 0x800?
mov #0x8, k0
shll8 k0
cmp/hs k0, k2
bf 0f
! then add 0x580 (k2 is 0xd80 or 0xda0)
mov #0x58, k0
shll2 k0
shll2 k0
add k0, k2
0:
bra handle_exception
nop
#else
bra handle_exception
mov.l @k2, k2
#endif
.align 2
1: .long EXPEVT
2: .long ret_from_exception
......
......@@ -141,6 +141,14 @@ int __init detect_cpu_and_cache_system(void)
current_cpu_data.flags |= CPU_HAS_LLSC;
}
break;
case 0x4000: /* 1st cut */
case 0x4001: /* 2nd cut */
current_cpu_data.type = CPU_SHX3;
current_cpu_data.icache.ways = 4;
current_cpu_data.dcache.ways = 4;
current_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_PERF_COUNTER |
CPU_HAS_LLSC;
break;
case 0x8000:
current_cpu_data.type = CPU_ST40RA;
current_cpu_data.flags |= CPU_HAS_FPU;
......
......@@ -9,6 +9,7 @@ obj-$(CONFIG_CPU_SUBTYPE_SH7785) += setup-sh7785.o
obj-$(CONFIG_CPU_SUBTYPE_SH73180) += setup-sh73180.o
obj-$(CONFIG_CPU_SUBTYPE_SH7343) += setup-sh7343.o
obj-$(CONFIG_CPU_SUBTYPE_SH7722) += setup-sh7722.o
obj-$(CONFIG_CPU_SUBTYPE_SHX3) += setup-shx3.o
# Primary on-chip clocks (common)
clock-$(CONFIG_CPU_SUBTYPE_SH73180) := clock-sh73180.o
......@@ -17,5 +18,6 @@ clock-$(CONFIG_CPU_SUBTYPE_SH7780) := clock-sh7780.o
clock-$(CONFIG_CPU_SUBTYPE_SH7785) := clock-sh7785.o
clock-$(CONFIG_CPU_SUBTYPE_SH7343) := clock-sh7343.o
clock-$(CONFIG_CPU_SUBTYPE_SH7722) := clock-sh7722.o
clock-$(CONFIG_CPU_SUBTYPE_SHX3) := clock-shx3.o
obj-y += $(clock-y)
/*
* arch/sh/kernel/cpu/sh4/clock-shx3.c
*
* SH-X3 support for the clock framework
*
* Copyright (C) 2006-2007 Renesas Technology Corp.
* Copyright (C) 2006-2007 Renesas Solutions Corp.
* Copyright (C) 2006-2007 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>
static int ifc_divisors[] = { 1, 2, 4 ,6 };
static int bfc_divisors[] = { 1, 1, 1, 1, 1, 12, 16, 18, 24, 32, 36, 48 };
static int pfc_divisors[] = { 1, 1, 1, 1, 1, 1, 1, 18, 24, 32, 36, 48 };
static int cfc_divisors[] = { 1, 1, 4, 6 };
#define IFC_POS 28
#define IFC_MSK 0x0003
#define BFC_MSK 0x000f
#define PFC_MSK 0x000f
#define CFC_MSK 0x0003
#define BFC_POS 16
#define PFC_POS 0
#define CFC_POS 20
static void master_clk_init(struct clk *clk)
{
clk->rate *= pfc_divisors[(ctrl_inl(FRQCR) >> PFC_POS) & PFC_MSK];
}
static struct clk_ops shx3_master_clk_ops = {
.init = master_clk_init,
};
static void module_clk_recalc(struct clk *clk)
{
int idx = ((ctrl_inl(FRQCR) >> PFC_POS) & PFC_MSK);
clk->rate = clk->parent->rate / pfc_divisors[idx];
}
static struct clk_ops shx3_module_clk_ops = {
.recalc = module_clk_recalc,
};
static void bus_clk_recalc(struct clk *clk)
{
int idx = ((ctrl_inl(FRQCR) >> BFC_POS) & BFC_MSK);
clk->rate = clk->parent->rate / bfc_divisors[idx];
}
static struct clk_ops shx3_bus_clk_ops = {
.recalc = bus_clk_recalc,
};
static void cpu_clk_recalc(struct clk *clk)
{
int idx = ((ctrl_inl(FRQCR) >> IFC_POS) & IFC_MSK);
clk->rate = clk->parent->rate / ifc_divisors[idx];
}
static struct clk_ops shx3_cpu_clk_ops = {
.recalc = cpu_clk_recalc,
};
static struct clk_ops *shx3_clk_ops[] = {
&shx3_master_clk_ops,
&shx3_module_clk_ops,
&shx3_bus_clk_ops,
&shx3_cpu_clk_ops,
};
void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
{
if (idx < ARRAY_SIZE(shx3_clk_ops))
*ops = shx3_clk_ops[idx];
}
static void shyway_clk_recalc(struct clk *clk)
{
int idx = ((ctrl_inl(FRQCR) >> CFC_POS) & CFC_MSK);
clk->rate = clk->parent->rate / cfc_divisors[idx];
}
static struct clk_ops shx3_shyway_clk_ops = {
.recalc = shyway_clk_recalc,
};
static struct clk shx3_shyway_clk = {
.name = "shyway_clk",
.flags = CLK_ALWAYS_ENABLED,
.ops = &shx3_shyway_clk_ops,
};
/*
* Additional SHx3-specific on-chip clocks that aren't already part of the
* clock framework
*/
static struct clk *shx3_onchip_clocks[] = {
&shx3_shyway_clk,
};
static int __init shx3_clk_init(void)
{
struct clk *clk = clk_get(NULL, "master_clk");
int i;
for (i = 0; i < ARRAY_SIZE(shx3_onchip_clocks); i++) {
struct clk *clkp = shx3_onchip_clocks[i];
clkp->parent = clk;
clk_register(clkp);
clk_enable(clkp);
}
/*
* Now that we have the rest of the clocks registered, we need to
* force the parent clock to propagate so that these clocks will
* automatically figure out their rate. We cheat by handing the
* parent clock its current rate and forcing child propagation.
*/
clk_set_rate(clk, clk_get_rate(clk));
clk_put(clk);
return 0;
}
arch_initcall(shx3_clk_init);
/*
* SH-X3 Setup
*
* Copyright (C) 2007 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/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[] = {
{
.mapbase = 0xffc30000,
.flags = UPF_BOOT_AUTOCONF,
.type = PORT_SCIF,
.irqs = { 40, 41, 43, 42 },
}, {
.mapbase = 0xffc40000,
.flags = UPF_BOOT_AUTOCONF,
.type = PORT_SCIF,
.irqs = { 44, 45, 47, 46 },
}, {
.mapbase = 0xffc50000,
.flags = UPF_BOOT_AUTOCONF,
.type = PORT_SCIF,
.irqs = { 48, 49, 51, 50 },
}, {
.mapbase = 0xffc60000,
.flags = UPF_BOOT_AUTOCONF,
.type = PORT_SCIF,
.irqs = { 52, 53, 55, 54 },
}, {
.flags = 0,
}
};
static struct platform_device sci_device = {
.name = "sh-sci",
.id = -1,
.dev = {
.platform_data = sci_platform_data,
},
};
static struct platform_device *shx3_devices[] __initdata = {
&sci_device,
};
static int __init shx3_devices_setup(void)
{
return platform_add_devices(shx3_devices,
ARRAY_SIZE(shx3_devices));
}
__initcall(shx3_devices_setup);
static struct intc2_data intc2_irq_table[] = {
{ 16, 0, 0, 0, 1, 2 }, /* TMU0 */
{ 40, 4, 0, 0x20, 0, 3 }, /* SCIF0 ERI */
{ 41, 4, 0, 0x20, 1, 3 }, /* SCIF0 RXI */
{ 42, 4, 0, 0x20, 2, 3 }, /* SCIF0 BRI */
{ 43, 4, 0, 0x20, 3, 3 }, /* SCIF0 TXI */
};
static struct intc2_desc intc2_irq_desc __read_mostly = {
.prio_base = 0xfe410000,
.msk_base = 0xfe410820,
.mskclr_base = 0xfe410850,
.intc2_data = intc2_irq_table,
.nr_irqs = ARRAY_SIZE(intc2_irq_table),
.chip = {
.name = "INTC2-SHX3",
},
};
void __init init_IRQ_intc2(void)
{
register_intc2_controller(&intc2_irq_desc);
}
......@@ -285,7 +285,7 @@ static const char *cpu_name[] = {
[CPU_SH7770] = "SH7770", [CPU_SH7780] = "SH7780",
[CPU_SH7781] = "SH7781", [CPU_SH7343] = "SH7343",
[CPU_SH7785] = "SH7785", [CPU_SH7722] = "SH7722",
[CPU_SH_NONE] = "Unknown"
[CPU_SHX3] = "SH-X3", [CPU_SH_NONE] = "Unknown"
};
const char *get_cpu_subtype(struct sh_cpuinfo *c)
......
......@@ -30,7 +30,7 @@
static int tmu_timer_start(void)
{
ctrl_outb(ctrl_inb(TMU_TSTR) | 0x3, TMU_TSTR);
ctrl_outb(ctrl_inb(TMU_012_TSTR) | 0x3, TMU_012_TSTR);
return 0;
}
......@@ -52,7 +52,7 @@ static void tmu0_timer_set_interval(unsigned long interval, unsigned int reload)
static int tmu_timer_stop(void)
{
ctrl_outb(ctrl_inb(TMU_TSTR) & ~0x3, TMU_TSTR);
ctrl_outb(ctrl_inb(TMU_012_TSTR) & ~0x3, TMU_012_TSTR);
return 0;
}
......@@ -174,7 +174,8 @@ static int tmu_timer_init(void)
#if !defined(CONFIG_CPU_SUBTYPE_SH7300) && \
!defined(CONFIG_CPU_SUBTYPE_SH7760) && \
!defined(CONFIG_CPU_SUBTYPE_SH7785)
!defined(CONFIG_CPU_SUBTYPE_SH7785) && \
!defined(CONFIG_CPU_SUBTYPE_SHX3)
ctrl_outb(TMU_TOCR_INIT, TMU_TOCR);
#endif
......
......@@ -36,6 +36,9 @@ config CPU_SUBTYPE_ST40
config CPU_SHX2
bool
config CPU_SHX3
bool
choice
prompt "Processor sub-type selection"
......@@ -193,6 +196,12 @@ config CPU_SUBTYPE_SH7785
select CPU_SHX2
select CPU_HAS_INTC2_IRQ
config CPU_SUBTYPE_SHX3
bool "Support SH-X3 processor"
select CPU_SH4A
select CPU_SHX3
select CPU_HAS_INTC2_IRQ
# SH4AL-DSP Processor Support
config CPU_SUBTYPE_SH73180
......
......@@ -367,7 +367,9 @@ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
} else {
#ifdef CONFIG_CPU_SUBTYPE_SH7343
/* Nothing */
#elif defined(CONFIG_CPU_SUBTYPE_SH7780) || defined(CONFIG_CPU_SUBTYPE_SH7785)
#elif defined(CONFIG_CPU_SUBTYPE_SH7780) || \
defined(CONFIG_CPU_SUBTYPE_SH7785) || \
defined(CONFIG_CPU_SUBTYPE_SHX3)
ctrl_outw(0x0080, SCSPTR0); /* Set RTS = 1 */
#else
ctrl_outw(0x0080, SCSPTR2); /* Set RTS = 1 */
......
......@@ -173,6 +173,14 @@
# 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
#elif defined(CONFIG_CPU_SUBTYPE_SHX3)
# define SCSPTR0 0xffc30020 /* 16 bit SCIF */
# define SCSPTR1 0xffc40020 /* 16 bit SCIF */
# define SCSPTR2 0xffc50020 /* 16 bit SCIF */
# define SCSPTR3 0xffc60020 /* 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
......@@ -189,7 +197,8 @@
defined(CONFIG_CPU_SUBTYPE_SH7751) || \
defined(CONFIG_CPU_SUBTYPE_SH7751R) || \
defined(CONFIG_CPU_SUBTYPE_SH7780) || \
defined(CONFIG_CPU_SUBTYPE_SH7785)
defined(CONFIG_CPU_SUBTYPE_SH7785) || \
defined(CONFIG_CPU_SUBTYPE_SHX3)
#define SCI_CTRL_FLAGS_REIE 0x08 /* 7750 SCIF */
#else
#define SCI_CTRL_FLAGS_REIE 0
......@@ -666,6 +675,18 @@ static inline int sci_rxd_in(struct uart_port *port)
return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
return 1;
}
#elif defined(CONFIG_CPU_SUBTYPE_SHX3)
static inline int sci_rxd_in(struct uart_port *port)
{
if (port->mapbase == 0xffc30000)
return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */
if (port->mapbase == 0xffc40000)
return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
if (port->mapbase == 0xffc50000)
return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
if (port->mapbase == 0xffc60000)
return ctrl_inw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */
}
#endif
/*
......
......@@ -35,7 +35,7 @@ static void __init check_bugs(void)
case CPU_SH7750 ... CPU_SH4_501:
*p++ = '4';
break;
case CPU_SH7770 ... CPU_SH7785:
case CPU_SH7770 ... CPU_SHX3:
*p++ = '4';
*p++ = 'a';
break;
......
......@@ -22,6 +22,8 @@
#define FRQCR0 0xffc80000
#define FRQCR1 0xffc80004
#define FRQMR1 0xffc80014
#elif defined(CONFIG_CPU_SUBTYPE_SHX3)
#define FRQCR 0xffc00014
#else
#define FRQCR 0xffc00000
#define FRQCR_PSTBY 0x0200
......
......@@ -16,36 +16,45 @@
* SH7750S/SH7750R
* SH7751/SH7751R
* SH7760
* SH-X3
* ---------------------------------------------------------------------------
*/
#if !defined(CONFIG_CPU_SUBTYPE_SH7760)
#define TMU_TOCR 0xffd80000 /* Byte access */
#ifdef CONFIG_CPU_SUBTYPE_SHX3
#define TMU_012_BASE 0xffc10000
#define TMU_345_BASE 0xffc20000
#else
#define TMU_012_BASE 0xffd80000
#define TMU_345_BASE 0xfe100000
#endif
#define TMU_TSTR 0xffd80004 /* Byte access */
#define TMU0_TCOR 0xffd80008 /* Long access */
#define TMU0_TCNT 0xffd8000c /* Long access */
#define TMU0_TCR 0xffd80010 /* Word access */
#define TMU_TOCR TMU_012_BASE /* Not supported on all CPUs */
#define TMU1_TCOR 0xffd80014 /* Long access */
#define TMU1_TCNT 0xffd80018 /* Long access */
#define TMU1_TCR 0xffd8001c /* Word access */
#define TMU_012_TSTR (TMU_012_BASE + 0x04)
#define TMU_345_TSTR (TMU_345_BASE + 0x04)
#define TMU2_TCOR 0xffd80020 /* Long access */
#define TMU2_TCNT 0xffd80024 /* Long access */
#define TMU2_TCR 0xffd80028 /* Word access */
#define TMU2_TCPR 0xffd8002c /* Long access */
#define TMU0_TCOR (TMU_012_BASE + 0x08)
#define TMU0_TCNT (TMU_012_BASE + 0x0c)
#define TMU0_TCR (TMU_012_BASE + 0x10)
#if !defined(CONFIG_CPU_SUBTYPE_SH7760)
#define TMU3_TCOR 0xfe100008 /* Long access */
#define TMU3_TCNT 0xfe10000c /* Long access */
#define TMU3_TCR 0xfe100010 /* Word access */
#define TMU1_TCOR (TMU_012_BASE + 0x14)
#define TMU1_TCNT (TMU_012_BASE + 0x18)
#define TMU1_TCR (TMU_012_BASE + 0x1c)
#define TMU4_TCOR 0xfe100014 /* Long access */
#define TMU4_TCNT 0xfe100018 /* Long access */
#define TMU4_TCR 0xfe10001c /* Word access */
#endif
#define TMU2_TCOR (TMU_012_BASE + 0x20)
#define TMU2_TCNT (TMU_012_BASE + 0x24)
#define TMU2_TCR (TMU_012_BASE + 0x28)
#define TMU2_TCPR (TMU_012_BASE + 0x2c)
#endif /* __ASM_CPU_SH4_TIMER_H */
#define TMU3_TCOR (TMU_345_BASE + 0x08)
#define TMU3_TCNT (TMU_345_BASE + 0x0c)
#define TMU3_TCR (TMU_345_BASE + 0x10)
#define TMU4_TCOR (TMU_345_BASE + 0x14)
#define TMU4_TCNT (TMU_345_BASE + 0x18)
#define TMU4_TCR (TMU_345_BASE + 0x1c)
#define TMU5_TCOR (TMU_345_BASE + 0x20)
#define TMU5_TCNT (TMU_345_BASE + 0x24)
#define TMU5_TCR (TMU_345_BASE + 0x28)
#endif /* __ASM_CPU_SH4_TIMER_H */
......@@ -52,7 +52,7 @@ enum cpu_type {
CPU_SH7760, CPU_ST40RA, CPU_ST40GX1, CPU_SH4_202, CPU_SH4_501,
/* SH-4A types */
CPU_SH7770, CPU_SH7780, CPU_SH7781, CPU_SH7785,
CPU_SH7770, CPU_SH7780, CPU_SH7781, CPU_SH7785, CPU_SHX3,
/* SH4AL-DSP types */
CPU_SH73180, CPU_SH7343, CPU_SH7722,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment