diff options
author | Paul Mundt <lethal@linux-sh.org> | 2007-06-20 05:27:10 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2007-06-20 05:27:10 -0400 |
commit | 2b1bd1ac5d4bffe3fd542bfe1784a583bd7df4fa (patch) | |
tree | 9c9840807d84cb4d9ca981fbae5093eef1c9ed12 /arch/sh/kernel | |
parent | 027e56e68543780870fda74360ca45e392c50e1c (diff) |
sh: Preliminary support for the SH-X3 CPU.
This adds basic support for UP SH-X3.
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/kernel')
-rw-r--r-- | arch/sh/kernel/cpu/sh3/entry.S | 19 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/sh4/probe.c | 8 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/sh4a/Makefile | 2 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/sh4a/clock-shx3.c | 135 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/sh4a/setup-shx3.c | 85 | ||||
-rw-r--r-- | arch/sh/kernel/setup.c | 2 | ||||
-rw-r--r-- | arch/sh/kernel/timers/timer-tmu.c | 7 |
7 files changed, 254 insertions, 4 deletions
diff --git a/arch/sh/kernel/cpu/sh3/entry.S b/arch/sh/kernel/cpu/sh3/entry.S index b0b59d4a33ca..d8e122971c3e 100644 --- a/arch/sh/kernel/cpu/sh3/entry.S +++ b/arch/sh/kernel/cpu/sh3/entry.S | |||
@@ -340,8 +340,27 @@ ENTRY(vbr_base) | |||
340 | general_exception: | 340 | general_exception: |
341 | mov.l 1f, k2 | 341 | mov.l 1f, k2 |
342 | mov.l 2f, k3 | 342 | mov.l 2f, k3 |
343 | #ifdef CONFIG_CPU_SUBTYPE_SHX3 | ||
344 | mov.l @k2, k2 | ||
345 | |||
346 | ! Is EXPEVT larger than 0x800? | ||
347 | mov #0x8, k0 | ||
348 | shll8 k0 | ||
349 | cmp/hs k0, k2 | ||
350 | bf 0f | ||
351 | |||
352 | ! then add 0x580 (k2 is 0xd80 or 0xda0) | ||
353 | mov #0x58, k0 | ||
354 | shll2 k0 | ||
355 | shll2 k0 | ||
356 | add k0, k2 | ||
357 | 0: | ||
358 | bra handle_exception | ||
359 | nop | ||
360 | #else | ||
343 | bra handle_exception | 361 | bra handle_exception |
344 | mov.l @k2, k2 | 362 | mov.l @k2, k2 |
363 | #endif | ||
345 | .align 2 | 364 | .align 2 |
346 | 1: .long EXPEVT | 365 | 1: .long EXPEVT |
347 | 2: .long ret_from_exception | 366 | 2: .long ret_from_exception |
diff --git a/arch/sh/kernel/cpu/sh4/probe.c b/arch/sh/kernel/cpu/sh4/probe.c index fab2eb07196b..66c3f75647b2 100644 --- a/arch/sh/kernel/cpu/sh4/probe.c +++ b/arch/sh/kernel/cpu/sh4/probe.c | |||
@@ -141,6 +141,14 @@ int __init detect_cpu_and_cache_system(void) | |||
141 | current_cpu_data.flags |= CPU_HAS_LLSC; | 141 | current_cpu_data.flags |= CPU_HAS_LLSC; |
142 | } | 142 | } |
143 | break; | 143 | break; |
144 | case 0x4000: /* 1st cut */ | ||
145 | case 0x4001: /* 2nd cut */ | ||
146 | current_cpu_data.type = CPU_SHX3; | ||
147 | current_cpu_data.icache.ways = 4; | ||
148 | current_cpu_data.dcache.ways = 4; | ||
149 | current_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_PERF_COUNTER | | ||
150 | CPU_HAS_LLSC; | ||
151 | break; | ||
144 | case 0x8000: | 152 | case 0x8000: |
145 | current_cpu_data.type = CPU_ST40RA; | 153 | current_cpu_data.type = CPU_ST40RA; |
146 | current_cpu_data.flags |= CPU_HAS_FPU; | 154 | current_cpu_data.flags |= CPU_HAS_FPU; |
diff --git a/arch/sh/kernel/cpu/sh4a/Makefile b/arch/sh/kernel/cpu/sh4a/Makefile index ab7422f8f820..400623286487 100644 --- a/arch/sh/kernel/cpu/sh4a/Makefile +++ b/arch/sh/kernel/cpu/sh4a/Makefile | |||
@@ -9,6 +9,7 @@ obj-$(CONFIG_CPU_SUBTYPE_SH7785) += setup-sh7785.o | |||
9 | obj-$(CONFIG_CPU_SUBTYPE_SH73180) += setup-sh73180.o | 9 | obj-$(CONFIG_CPU_SUBTYPE_SH73180) += setup-sh73180.o |
10 | obj-$(CONFIG_CPU_SUBTYPE_SH7343) += setup-sh7343.o | 10 | obj-$(CONFIG_CPU_SUBTYPE_SH7343) += setup-sh7343.o |
11 | obj-$(CONFIG_CPU_SUBTYPE_SH7722) += setup-sh7722.o | 11 | obj-$(CONFIG_CPU_SUBTYPE_SH7722) += setup-sh7722.o |
12 | obj-$(CONFIG_CPU_SUBTYPE_SHX3) += setup-shx3.o | ||
12 | 13 | ||
13 | # Primary on-chip clocks (common) | 14 | # Primary on-chip clocks (common) |
14 | clock-$(CONFIG_CPU_SUBTYPE_SH73180) := clock-sh73180.o | 15 | clock-$(CONFIG_CPU_SUBTYPE_SH73180) := clock-sh73180.o |
@@ -17,5 +18,6 @@ clock-$(CONFIG_CPU_SUBTYPE_SH7780) := clock-sh7780.o | |||
17 | clock-$(CONFIG_CPU_SUBTYPE_SH7785) := clock-sh7785.o | 18 | clock-$(CONFIG_CPU_SUBTYPE_SH7785) := clock-sh7785.o |
18 | clock-$(CONFIG_CPU_SUBTYPE_SH7343) := clock-sh7343.o | 19 | clock-$(CONFIG_CPU_SUBTYPE_SH7343) := clock-sh7343.o |
19 | clock-$(CONFIG_CPU_SUBTYPE_SH7722) := clock-sh7722.o | 20 | clock-$(CONFIG_CPU_SUBTYPE_SH7722) := clock-sh7722.o |
21 | clock-$(CONFIG_CPU_SUBTYPE_SHX3) := clock-shx3.o | ||
20 | 22 | ||
21 | obj-y += $(clock-y) | 23 | obj-y += $(clock-y) |
diff --git a/arch/sh/kernel/cpu/sh4a/clock-shx3.c b/arch/sh/kernel/cpu/sh4a/clock-shx3.c new file mode 100644 index 000000000000..c630b29e06a8 --- /dev/null +++ b/arch/sh/kernel/cpu/sh4a/clock-shx3.c | |||
@@ -0,0 +1,135 @@ | |||
1 | /* | ||
2 | * arch/sh/kernel/cpu/sh4/clock-shx3.c | ||
3 | * | ||
4 | * SH-X3 support for the clock framework | ||
5 | * | ||
6 | * Copyright (C) 2006-2007 Renesas Technology Corp. | ||
7 | * Copyright (C) 2006-2007 Renesas Solutions Corp. | ||
8 | * Copyright (C) 2006-2007 Paul Mundt | ||
9 | * | ||
10 | * This file is subject to the terms and conditions of the GNU General Public | ||
11 | * License. See the file "COPYING" in the main directory of this archive | ||
12 | * for more details. | ||
13 | */ | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <asm/clock.h> | ||
17 | #include <asm/freq.h> | ||
18 | #include <asm/io.h> | ||
19 | |||
20 | static int ifc_divisors[] = { 1, 2, 4 ,6 }; | ||
21 | static int bfc_divisors[] = { 1, 1, 1, 1, 1, 12, 16, 18, 24, 32, 36, 48 }; | ||
22 | static int pfc_divisors[] = { 1, 1, 1, 1, 1, 1, 1, 18, 24, 32, 36, 48 }; | ||
23 | static int cfc_divisors[] = { 1, 1, 4, 6 }; | ||
24 | |||
25 | #define IFC_POS 28 | ||
26 | #define IFC_MSK 0x0003 | ||
27 | #define BFC_MSK 0x000f | ||
28 | #define PFC_MSK 0x000f | ||
29 | #define CFC_MSK 0x0003 | ||
30 | #define BFC_POS 16 | ||
31 | #define PFC_POS 0 | ||
32 | #define CFC_POS 20 | ||
33 | |||
34 | static void master_clk_init(struct clk *clk) | ||
35 | { | ||
36 | clk->rate *= pfc_divisors[(ctrl_inl(FRQCR) >> PFC_POS) & PFC_MSK]; | ||
37 | } | ||
38 | |||
39 | static struct clk_ops shx3_master_clk_ops = { | ||
40 | .init = master_clk_init, | ||
41 | }; | ||
42 | |||
43 | static void module_clk_recalc(struct clk *clk) | ||
44 | { | ||
45 | int idx = ((ctrl_inl(FRQCR) >> PFC_POS) & PFC_MSK); | ||
46 | clk->rate = clk->parent->rate / pfc_divisors[idx]; | ||
47 | } | ||
48 | |||
49 | static struct clk_ops shx3_module_clk_ops = { | ||
50 | .recalc = module_clk_recalc, | ||
51 | }; | ||
52 | |||
53 | static void bus_clk_recalc(struct clk *clk) | ||
54 | { | ||
55 | int idx = ((ctrl_inl(FRQCR) >> BFC_POS) & BFC_MSK); | ||
56 | clk->rate = clk->parent->rate / bfc_divisors[idx]; | ||
57 | } | ||
58 | |||
59 | static struct clk_ops shx3_bus_clk_ops = { | ||
60 | .recalc = bus_clk_recalc, | ||
61 | }; | ||
62 | |||
63 | static void cpu_clk_recalc(struct clk *clk) | ||
64 | { | ||
65 | int idx = ((ctrl_inl(FRQCR) >> IFC_POS) & IFC_MSK); | ||
66 | clk->rate = clk->parent->rate / ifc_divisors[idx]; | ||
67 | } | ||
68 | |||
69 | static struct clk_ops shx3_cpu_clk_ops = { | ||
70 | .recalc = cpu_clk_recalc, | ||
71 | }; | ||
72 | |||
73 | static struct clk_ops *shx3_clk_ops[] = { | ||
74 | &shx3_master_clk_ops, | ||
75 | &shx3_module_clk_ops, | ||
76 | &shx3_bus_clk_ops, | ||
77 | &shx3_cpu_clk_ops, | ||
78 | }; | ||
79 | |||
80 | void __init arch_init_clk_ops(struct clk_ops **ops, int idx) | ||
81 | { | ||
82 | if (idx < ARRAY_SIZE(shx3_clk_ops)) | ||
83 | *ops = shx3_clk_ops[idx]; | ||
84 | } | ||
85 | |||
86 | static void shyway_clk_recalc(struct clk *clk) | ||
87 | { | ||
88 | int idx = ((ctrl_inl(FRQCR) >> CFC_POS) & CFC_MSK); | ||
89 | clk->rate = clk->parent->rate / cfc_divisors[idx]; | ||
90 | } | ||
91 | |||
92 | static struct clk_ops shx3_shyway_clk_ops = { | ||
93 | .recalc = shyway_clk_recalc, | ||
94 | }; | ||
95 | |||
96 | static struct clk shx3_shyway_clk = { | ||
97 | .name = "shyway_clk", | ||
98 | .flags = CLK_ALWAYS_ENABLED, | ||
99 | .ops = &shx3_shyway_clk_ops, | ||
100 | }; | ||
101 | |||
102 | /* | ||
103 | * Additional SHx3-specific on-chip clocks that aren't already part of the | ||
104 | * clock framework | ||
105 | */ | ||
106 | static struct clk *shx3_onchip_clocks[] = { | ||
107 | &shx3_shyway_clk, | ||
108 | }; | ||
109 | |||
110 | static int __init shx3_clk_init(void) | ||
111 | { | ||
112 | struct clk *clk = clk_get(NULL, "master_clk"); | ||
113 | int i; | ||
114 | |||
115 | for (i = 0; i < ARRAY_SIZE(shx3_onchip_clocks); i++) { | ||
116 | struct clk *clkp = shx3_onchip_clocks[i]; | ||
117 | |||
118 | clkp->parent = clk; | ||
119 | clk_register(clkp); | ||
120 | clk_enable(clkp); | ||
121 | } | ||
122 | |||
123 | /* | ||
124 | * Now that we have the rest of the clocks registered, we need to | ||
125 | * force the parent clock to propagate so that these clocks will | ||
126 | * automatically figure out their rate. We cheat by handing the | ||
127 | * parent clock its current rate and forcing child propagation. | ||
128 | */ | ||
129 | clk_set_rate(clk, clk_get_rate(clk)); | ||
130 | |||
131 | clk_put(clk); | ||
132 | |||
133 | return 0; | ||
134 | } | ||
135 | arch_initcall(shx3_clk_init); | ||
diff --git a/arch/sh/kernel/cpu/sh4a/setup-shx3.c b/arch/sh/kernel/cpu/sh4a/setup-shx3.c new file mode 100644 index 000000000000..70683ea12b83 --- /dev/null +++ b/arch/sh/kernel/cpu/sh4a/setup-shx3.c | |||
@@ -0,0 +1,85 @@ | |||
1 | /* | ||
2 | * SH-X3 Setup | ||
3 | * | ||
4 | * Copyright (C) 2007 Paul Mundt | ||
5 | * | ||
6 | * This file is subject to the terms and conditions of the GNU General Public | ||
7 | * License. See the file "COPYING" in the main directory of this archive | ||
8 | * for more details. | ||
9 | */ | ||
10 | #include <linux/platform_device.h> | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/serial.h> | ||
13 | #include <linux/io.h> | ||
14 | #include <asm/sci.h> | ||
15 | |||
16 | static struct plat_sci_port sci_platform_data[] = { | ||
17 | { | ||
18 | .mapbase = 0xffc30000, | ||
19 | .flags = UPF_BOOT_AUTOCONF, | ||
20 | .type = PORT_SCIF, | ||
21 | .irqs = { 40, 41, 43, 42 }, | ||
22 | }, { | ||
23 | .mapbase = 0xffc40000, | ||
24 | .flags = UPF_BOOT_AUTOCONF, | ||
25 | .type = PORT_SCIF, | ||
26 | .irqs = { 44, 45, 47, 46 }, | ||
27 | }, { | ||
28 | .mapbase = 0xffc50000, | ||
29 | .flags = UPF_BOOT_AUTOCONF, | ||
30 | .type = PORT_SCIF, | ||
31 | .irqs = { 48, 49, 51, 50 }, | ||
32 | }, { | ||
33 | .mapbase = 0xffc60000, | ||
34 | .flags = UPF_BOOT_AUTOCONF, | ||
35 | .type = PORT_SCIF, | ||
36 | .irqs = { 52, 53, 55, 54 }, | ||
37 | }, { | ||
38 | .flags = 0, | ||
39 | } | ||
40 | }; | ||
41 | |||
42 | static struct platform_device sci_device = { | ||
43 | .name = "sh-sci", | ||
44 | .id = -1, | ||
45 | .dev = { | ||
46 | .platform_data = sci_platform_data, | ||
47 | }, | ||
48 | }; | ||
49 | |||
50 | static struct platform_device *shx3_devices[] __initdata = { | ||
51 | &sci_device, | ||
52 | }; | ||
53 | |||
54 | static int __init shx3_devices_setup(void) | ||
55 | { | ||
56 | return platform_add_devices(shx3_devices, | ||
57 | ARRAY_SIZE(shx3_devices)); | ||
58 | } | ||
59 | __initcall(shx3_devices_setup); | ||
60 | |||
61 | static struct intc2_data intc2_irq_table[] = { | ||
62 | { 16, 0, 0, 0, 1, 2 }, /* TMU0 */ | ||
63 | { 40, 4, 0, 0x20, 0, 3 }, /* SCIF0 ERI */ | ||
64 | { 41, 4, 0, 0x20, 1, 3 }, /* SCIF0 RXI */ | ||
65 | { 42, 4, 0, 0x20, 2, 3 }, /* SCIF0 BRI */ | ||
66 | { 43, 4, 0, 0x20, 3, 3 }, /* SCIF0 TXI */ | ||
67 | }; | ||
68 | |||
69 | static struct intc2_desc intc2_irq_desc __read_mostly = { | ||
70 | .prio_base = 0xfe410000, | ||
71 | .msk_base = 0xfe410820, | ||
72 | .mskclr_base = 0xfe410850, | ||
73 | |||
74 | .intc2_data = intc2_irq_table, | ||
75 | .nr_irqs = ARRAY_SIZE(intc2_irq_table), | ||
76 | |||
77 | .chip = { | ||
78 | .name = "INTC2-SHX3", | ||
79 | }, | ||
80 | }; | ||
81 | |||
82 | void __init init_IRQ_intc2(void) | ||
83 | { | ||
84 | register_intc2_controller(&intc2_irq_desc); | ||
85 | } | ||
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 765f83c1bca4..de8e6e2f2c87 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c | |||
@@ -285,7 +285,7 @@ static const char *cpu_name[] = { | |||
285 | [CPU_SH7770] = "SH7770", [CPU_SH7780] = "SH7780", | 285 | [CPU_SH7770] = "SH7770", [CPU_SH7780] = "SH7780", |
286 | [CPU_SH7781] = "SH7781", [CPU_SH7343] = "SH7343", | 286 | [CPU_SH7781] = "SH7781", [CPU_SH7343] = "SH7343", |
287 | [CPU_SH7785] = "SH7785", [CPU_SH7722] = "SH7722", | 287 | [CPU_SH7785] = "SH7785", [CPU_SH7722] = "SH7722", |
288 | [CPU_SH_NONE] = "Unknown" | 288 | [CPU_SHX3] = "SH-X3", [CPU_SH_NONE] = "Unknown" |
289 | }; | 289 | }; |
290 | 290 | ||
291 | const char *get_cpu_subtype(struct sh_cpuinfo *c) | 291 | const char *get_cpu_subtype(struct sh_cpuinfo *c) |
diff --git a/arch/sh/kernel/timers/timer-tmu.c b/arch/sh/kernel/timers/timer-tmu.c index 2d997e2a5b6c..097ebd49f1bf 100644 --- a/arch/sh/kernel/timers/timer-tmu.c +++ b/arch/sh/kernel/timers/timer-tmu.c | |||
@@ -30,7 +30,7 @@ | |||
30 | 30 | ||
31 | static int tmu_timer_start(void) | 31 | static int tmu_timer_start(void) |
32 | { | 32 | { |
33 | ctrl_outb(ctrl_inb(TMU_TSTR) | 0x3, TMU_TSTR); | 33 | ctrl_outb(ctrl_inb(TMU_012_TSTR) | 0x3, TMU_012_TSTR); |
34 | return 0; | 34 | return 0; |
35 | } | 35 | } |
36 | 36 | ||
@@ -52,7 +52,7 @@ static void tmu0_timer_set_interval(unsigned long interval, unsigned int reload) | |||
52 | 52 | ||
53 | static int tmu_timer_stop(void) | 53 | static int tmu_timer_stop(void) |
54 | { | 54 | { |
55 | ctrl_outb(ctrl_inb(TMU_TSTR) & ~0x3, TMU_TSTR); | 55 | ctrl_outb(ctrl_inb(TMU_012_TSTR) & ~0x3, TMU_012_TSTR); |
56 | return 0; | 56 | return 0; |
57 | } | 57 | } |
58 | 58 | ||
@@ -174,7 +174,8 @@ static int tmu_timer_init(void) | |||
174 | 174 | ||
175 | #if !defined(CONFIG_CPU_SUBTYPE_SH7300) && \ | 175 | #if !defined(CONFIG_CPU_SUBTYPE_SH7300) && \ |
176 | !defined(CONFIG_CPU_SUBTYPE_SH7760) && \ | 176 | !defined(CONFIG_CPU_SUBTYPE_SH7760) && \ |
177 | !defined(CONFIG_CPU_SUBTYPE_SH7785) | 177 | !defined(CONFIG_CPU_SUBTYPE_SH7785) && \ |
178 | !defined(CONFIG_CPU_SUBTYPE_SHX3) | ||
178 | ctrl_outb(TMU_TOCR_INIT, TMU_TOCR); | 179 | ctrl_outb(TMU_TOCR_INIT, TMU_TOCR); |
179 | #endif | 180 | #endif |
180 | 181 | ||