sh: SH-MobileR SH7722 CPU support.

This adds CPU support for the SH7722.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
This commit is contained in:
Paul Mundt
2006-12-11 20:28:03 +09:00
parent 5432143464
commit 41504c3972
22 changed files with 284 additions and 20 deletions

View File

@ -6,6 +6,7 @@ obj-$(CONFIG_CPU_SH2) = sh2/
obj-$(CONFIG_CPU_SH2A) = sh2a/
obj-$(CONFIG_CPU_SH3) = sh3/
obj-$(CONFIG_CPU_SH4) = sh4/
obj-$(CONFIG_CPU_SH4A) += sh4a/
obj-$(CONFIG_UBC_WAKEUP) += ubc.o
obj-$(CONFIG_SH_ADC) += adc.o

View File

@ -12,17 +12,12 @@ obj-$(CONFIG_SH_STORE_QUEUES) += sq.o
obj-$(CONFIG_CPU_SUBTYPE_SH7750) += setup-sh7750.o
obj-$(CONFIG_CPU_SUBTYPE_SH7751) += setup-sh7750.o
obj-$(CONFIG_CPU_SUBTYPE_SH7760) += setup-sh7760.o
obj-$(CONFIG_CPU_SUBTYPE_SH7770) += setup-sh7770.o
obj-$(CONFIG_CPU_SUBTYPE_SH7780) += setup-sh7780.o
obj-$(CONFIG_CPU_SUBTYPE_SH73180) += setup-sh73180.o
obj-$(CONFIG_CPU_SUBTYPE_SH7343) += setup-sh7343.o
obj-$(CONFIG_CPU_SUBTYPE_SH4_202) += setup-sh4-202.o
# Primary on-chip clocks (common)
ifndef CONFIG_CPU_SH4A
clock-$(CONFIG_CPU_SH4) := clock-sh4.o
clock-$(CONFIG_CPU_SUBTYPE_SH73180) := clock-sh73180.o
clock-$(CONFIG_CPU_SUBTYPE_SH7770) := clock-sh7770.o
clock-$(CONFIG_CPU_SUBTYPE_SH7780) := clock-sh7780.o
endif
# Additional clocks by subtype
clock-$(CONFIG_CPU_SUBTYPE_SH4_202) += clock-sh4-202.o

View File

@ -119,11 +119,20 @@ int __init detect_cpu_and_cache_system(void)
break;
case 0x3000:
case 0x3003:
case 0x3009:
cpu_data->type = CPU_SH7343;
cpu_data->icache.ways = 4;
cpu_data->dcache.ways = 4;
cpu_data->flags |= CPU_HAS_LLSC;
break;
case 0x3008:
if (prr == 0xa0) {
cpu_data->type = CPU_SH7722;
cpu_data->icache.ways = 4;
cpu_data->dcache.ways = 4;
cpu_data->flags |= CPU_HAS_LLSC;
}
break;
case 0x8000:
cpu_data->type = CPU_ST40RA;
cpu_data->flags |= CPU_HAS_FPU;

View File

@ -0,0 +1,19 @@
#
# Makefile for the Linux/SuperH SH-4 backends.
#
# CPU subtype setup
obj-$(CONFIG_CPU_SUBTYPE_SH7770) += setup-sh7770.o
obj-$(CONFIG_CPU_SUBTYPE_SH7780) += setup-sh7780.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
# Primary on-chip clocks (common)
clock-$(CONFIG_CPU_SUBTYPE_SH73180) := clock-sh73180.o
clock-$(CONFIG_CPU_SUBTYPE_SH7770) := clock-sh7770.o
clock-$(CONFIG_CPU_SUBTYPE_SH7780) := clock-sh7780.o
clock-$(CONFIG_CPU_SUBTYPE_SH7343) := clock-sh7343.o
clock-$(CONFIG_CPU_SUBTYPE_SH7722) := clock-sh7343.o
obj-y += $(clock-y)

View File

@ -0,0 +1,99 @@
/*
* arch/sh/kernel/cpu/sh4/clock-sh7343.c
*
* SH7343/SH7722 support for the clock 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/kernel.h>
#include <linux/io.h>
#include <asm/clock.h>
#include <asm/freq.h>
/*
* SH7343/SH7722 uses a common set of multipliers and divisors, so this
* is quite simple..
*/
static int multipliers[] = { 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
static int divisors[] = { 1, 3, 2, 5, 3, 4, 5, 6, 8, 10, 12, 16, 20 };
#define pll_calc() (((ctrl_inl(FRQCR) >> 24) & 0x1f) + 1)
static void master_clk_init(struct clk *clk)
{
clk->parent = clk_get(NULL, "cpu_clk");
}
static void master_clk_recalc(struct clk *clk)
{
int idx = (ctrl_inl(FRQCR) & 0x000f);
clk->rate *= clk->parent->rate * multipliers[idx] / divisors[idx];
}
static struct clk_ops sh7343_master_clk_ops = {
.init = master_clk_init,
.recalc = master_clk_recalc,
};
static void module_clk_init(struct clk *clk)
{
clk->parent = NULL;
clk->rate = CONFIG_SH_PCLK_FREQ;
}
static struct clk_ops sh7343_module_clk_ops = {
.init = module_clk_init,
};
static void bus_clk_init(struct clk *clk)
{
clk->parent = clk_get(NULL, "cpu_clk");
}
static void bus_clk_recalc(struct clk *clk)
{
int idx = (ctrl_inl(FRQCR) >> 8) & 0x000f;
clk->rate = clk->parent->rate * multipliers[idx] / divisors[idx];
}
static struct clk_ops sh7343_bus_clk_ops = {
.init = bus_clk_init,
.recalc = bus_clk_recalc,
};
static void cpu_clk_init(struct clk *clk)
{
clk->parent = clk_get(NULL, "module_clk");
clk->flags |= CLK_RATE_PROPAGATES;
clk_set_rate(clk, clk_get_rate(clk));
}
static void cpu_clk_recalc(struct clk *clk)
{
int idx = (ctrl_inl(FRQCR) >> 20) & 0x000f;
clk->rate = clk->parent->rate * pll_calc() *
multipliers[idx] / divisors[idx];
}
static struct clk_ops sh7343_cpu_clk_ops = {
.init = cpu_clk_init,
.recalc = cpu_clk_recalc,
};
static struct clk_ops *sh7343_clk_ops[] = {
&sh7343_master_clk_ops,
&sh7343_module_clk_ops,
&sh7343_bus_clk_ops,
&sh7343_cpu_clk_ops,
};
void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
{
if (idx < ARRAY_SIZE(sh7343_clk_ops))
*ops = sh7343_clk_ops[idx];
}

View File

@ -0,0 +1,76 @@
/*
* SH7722 Setup
*
* 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/platform_device.h>
#include <linux/init.h>
#include <linux/serial.h>
#include <asm/sci.h>
static struct plat_sci_port sci_platform_data[] = {
{
.mapbase = 0xffe00000,
.flags = UPF_BOOT_AUTOCONF,
.type = PORT_SCIF,
.irqs = { 80, 81, 83, 82 },
}, {
.flags = 0,
}
};
static struct platform_device sci_device = {
.name = "sh-sci",
.id = -1,
.dev = {
.platform_data = sci_platform_data,
},
};
static struct platform_device *sh7722_devices[] __initdata = {
&sci_device,
};
static int __init sh7722_devices_setup(void)
{
return platform_add_devices(sh7722_devices,
ARRAY_SIZE(sh7722_devices));
}
__initcall(sh7722_devices_setup);
static struct ipr_data sh7722_ipr_map[] = {
/* IRQ, IPR-idx, shift, prio */
{ 16, 0, 12, 2 }, /* TMU0 */
{ 17, 0, 8, 2 }, /* TMU1 */
};
static unsigned long ipr_offsets[] = {
0xa4080000, /* 0: IPRA */
0xa4080004, /* 1: IPRB */
0xa4080008, /* 2: IPRC */
0xa408000c, /* 3: IPRD */
0xa4080010, /* 4: IPRE */
0xa4080014, /* 5: IPRF */
0xa4080018, /* 6: IPRG */
0xa408001c, /* 7: IPRH */
0xa4080020, /* 8: IPRI */
0xa4080024, /* 9: IPRJ */
0xa4080028, /* 10: IPRK */
0xa408002c, /* 11: IPRL */
};
unsigned int map_ipridx_to_addr(int idx)
{
if (unlikely(idx >= ARRAY_SIZE(ipr_offsets)))
return 0;
return ipr_offsets[idx];
}
void __init init_IRQ_ipr(void)
{
make_ipr_irq(sh7722_ipr_map, ARRAY_SIZE(sh7722_ipr_map));
}