aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/mti-malta
diff options
context:
space:
mode:
authorWe-unite <3205135446@qq.com>2025-03-08 22:04:20 +0800
committerWe-unite <3205135446@qq.com>2025-03-08 22:04:20 +0800
commita07bb8fd1299070229f0e8f3dcb57ffd5ef9870a (patch)
tree84f21bd0bf7071bc5fc7dd989e77d7ceb5476682 /arch/mips/mti-malta
downloadohosKernel-a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a.tar.gz
ohosKernel-a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a.zip
Initial commit: OpenHarmony-v4.0-ReleaseOpenHarmony-v4.0-Release
Diffstat (limited to 'arch/mips/mti-malta')
-rw-r--r--arch/mips/mti-malta/Makefile20
-rw-r--r--arch/mips/mti-malta/Platform10
-rw-r--r--arch/mips/mti-malta/malta-amon.c88
-rw-r--r--arch/mips/mti-malta/malta-dt.c15
-rw-r--r--arch/mips/mti-malta/malta-dtshim.c333
-rw-r--r--arch/mips/mti-malta/malta-init.c298
-rw-r--r--arch/mips/mti-malta/malta-int.c223
-rw-r--r--arch/mips/mti-malta/malta-memory.c48
-rw-r--r--arch/mips/mti-malta/malta-platform.c76
-rw-r--r--arch/mips/mti-malta/malta-setup.c249
-rw-r--r--arch/mips/mti-malta/malta-time.c256
11 files changed, 1616 insertions, 0 deletions
diff --git a/arch/mips/mti-malta/Makefile b/arch/mips/mti-malta/Makefile
new file mode 100644
index 000000000..94c11f5ea
--- /dev/null
+++ b/arch/mips/mti-malta/Makefile
@@ -0,0 +1,20 @@
1# SPDX-License-Identifier: GPL-2.0
2#
3# Carsten Langgaard, carstenl@mips.com
4# Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
5#
6# Copyright (C) 2008 Wind River Systems, Inc.
7# written by Ralf Baechle <ralf@linux-mips.org>
8#
9obj-y += malta-dt.o
10obj-y += malta-dtshim.o
11obj-y += malta-init.o
12obj-y += malta-int.o
13obj-y += malta-memory.o
14obj-y += malta-platform.o
15obj-y += malta-setup.o
16obj-y += malta-time.o
17
18obj-$(CONFIG_MIPS_CMP) += malta-amon.o
19
20CFLAGS_malta-dtshim.o = -I$(src)/../../../scripts/dtc/libfdt
diff --git a/arch/mips/mti-malta/Platform b/arch/mips/mti-malta/Platform
new file mode 100644
index 000000000..41e0d2a2d
--- /dev/null
+++ b/arch/mips/mti-malta/Platform
@@ -0,0 +1,10 @@
1#
2# MIPS Malta board
3#
4cflags-$(CONFIG_MIPS_MALTA) += -I$(srctree)/arch/mips/include/asm/mach-malta
5ifdef CONFIG_KVM_GUEST
6 load-$(CONFIG_MIPS_MALTA) += 0x0000000040100000
7else
8 load-$(CONFIG_MIPS_MALTA) += 0xffffffff80100000
9endif
10all-$(CONFIG_MIPS_MALTA) := $(COMPRESSION_FNAME).bin
diff --git a/arch/mips/mti-malta/malta-amon.c b/arch/mips/mti-malta/malta-amon.c
new file mode 100644
index 000000000..84ac523b0
--- /dev/null
+++ b/arch/mips/mti-malta/malta-amon.c
@@ -0,0 +1,88 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2007 MIPS Technologies, Inc. All rights reserved.
7 * Copyright (C) 2013 Imagination Technologies Ltd.
8 *
9 * Arbitrary Monitor Interface
10 */
11#include <linux/kernel.h>
12#include <linux/smp.h>
13
14#include <asm/addrspace.h>
15#include <asm/mipsmtregs.h>
16#include <asm/mips-boards/launch.h>
17#include <asm/vpe.h>
18
19int amon_cpu_avail(int cpu)
20{
21 struct cpulaunch *launch = (struct cpulaunch *)CKSEG0ADDR(CPULAUNCH);
22
23 if (cpu < 0 || cpu >= NCPULAUNCH) {
24 pr_debug("avail: cpu%d is out of range\n", cpu);
25 return 0;
26 }
27
28 launch += cpu;
29 if (!(launch->flags & LAUNCH_FREADY)) {
30 pr_debug("avail: cpu%d is not ready\n", cpu);
31 return 0;
32 }
33 if (launch->flags & (LAUNCH_FGO|LAUNCH_FGONE)) {
34 pr_debug("avail: too late.. cpu%d is already gone\n", cpu);
35 return 0;
36 }
37
38 return 1;
39}
40
41int amon_cpu_start(int cpu,
42 unsigned long pc, unsigned long sp,
43 unsigned long gp, unsigned long a0)
44{
45 volatile struct cpulaunch *launch =
46 (struct cpulaunch *)CKSEG0ADDR(CPULAUNCH);
47
48 if (!amon_cpu_avail(cpu))
49 return -1;
50 if (cpu == smp_processor_id()) {
51 pr_debug("launch: I am cpu%d!\n", cpu);
52 return -1;
53 }
54 launch += cpu;
55
56 pr_debug("launch: starting cpu%d\n", cpu);
57
58 launch->pc = pc;
59 launch->gp = gp;
60 launch->sp = sp;
61 launch->a0 = a0;
62
63 smp_wmb(); /* Target must see parameters before go */
64 launch->flags |= LAUNCH_FGO;
65 smp_wmb(); /* Target must see go before we poll */
66
67 while ((launch->flags & LAUNCH_FGONE) == 0)
68 ;
69 smp_rmb(); /* Target will be updating flags soon */
70 pr_debug("launch: cpu%d gone!\n", cpu);
71
72 return 0;
73}
74
75#ifdef CONFIG_MIPS_VPE_LOADER_CMP
76int vpe_run(struct vpe *v)
77{
78 struct vpe_notifications *n;
79
80 if (amon_cpu_start(aprp_cpu_index(), v->__start, 0, 0, 0) < 0)
81 return -1;
82
83 list_for_each_entry(n, &v->notify, list)
84 n->start(VPE_MODULE_MINOR);
85
86 return 0;
87}
88#endif
diff --git a/arch/mips/mti-malta/malta-dt.c b/arch/mips/mti-malta/malta-dt.c
new file mode 100644
index 000000000..d045c9149
--- /dev/null
+++ b/arch/mips/mti-malta/malta-dt.c
@@ -0,0 +1,15 @@
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (C) 2015 Imagination Technologies
4 * Author: Paul Burton <paul.burton@mips.com>
5 */
6
7#include <linux/clk-provider.h>
8#include <linux/init.h>
9#include <linux/of_fdt.h>
10#include <linux/of_platform.h>
11
12void __init device_tree_init(void)
13{
14 unflatten_and_copy_device_tree();
15}
diff --git a/arch/mips/mti-malta/malta-dtshim.c b/arch/mips/mti-malta/malta-dtshim.c
new file mode 100644
index 000000000..f451268f6
--- /dev/null
+++ b/arch/mips/mti-malta/malta-dtshim.c
@@ -0,0 +1,333 @@
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (C) 2015 Imagination Technologies
4 * Author: Paul Burton <paul.burton@mips.com>
5 */
6
7#include <linux/bug.h>
8#include <linux/kernel.h>
9#include <linux/libfdt.h>
10#include <linux/of_fdt.h>
11#include <linux/sizes.h>
12#include <asm/addrspace.h>
13#include <asm/bootinfo.h>
14#include <asm/fw/fw.h>
15#include <asm/mips-boards/generic.h>
16#include <asm/mips-boards/malta.h>
17#include <asm/mips-cps.h>
18#include <asm/page.h>
19
20#define ROCIT_REG_BASE 0x1f403000
21#define ROCIT_CONFIG_GEN1 (ROCIT_REG_BASE + 0x04)
22#define ROCIT_CONFIG_GEN1_MEMMAP_SHIFT 8
23#define ROCIT_CONFIG_GEN1_MEMMAP_MASK (0xf << 8)
24
25static unsigned char fdt_buf[16 << 10] __initdata __aligned(8);
26
27/* determined physical memory size, not overridden by command line args */
28extern unsigned long physical_memsize;
29
30enum mem_map {
31 MEM_MAP_V1 = 0,
32 MEM_MAP_V2,
33};
34
35#define MAX_MEM_ARRAY_ENTRIES 2
36
37static __init int malta_scon(void)
38{
39 int scon = MIPS_REVISION_SCONID;
40
41 if (scon != MIPS_REVISION_SCON_OTHER)
42 return scon;
43
44 switch (MIPS_REVISION_CORID) {
45 case MIPS_REVISION_CORID_QED_RM5261:
46 case MIPS_REVISION_CORID_CORE_LV:
47 case MIPS_REVISION_CORID_CORE_FPGA:
48 case MIPS_REVISION_CORID_CORE_FPGAR2:
49 return MIPS_REVISION_SCON_GT64120;
50
51 case MIPS_REVISION_CORID_CORE_EMUL_BON:
52 case MIPS_REVISION_CORID_BONITO64:
53 case MIPS_REVISION_CORID_CORE_20K:
54 return MIPS_REVISION_SCON_BONITO;
55
56 case MIPS_REVISION_CORID_CORE_MSC:
57 case MIPS_REVISION_CORID_CORE_FPGA2:
58 case MIPS_REVISION_CORID_CORE_24K:
59 return MIPS_REVISION_SCON_SOCIT;
60
61 case MIPS_REVISION_CORID_CORE_FPGA3:
62 case MIPS_REVISION_CORID_CORE_FPGA4:
63 case MIPS_REVISION_CORID_CORE_FPGA5:
64 case MIPS_REVISION_CORID_CORE_EMUL_MSC:
65 default:
66 return MIPS_REVISION_SCON_ROCIT;
67 }
68}
69
70static unsigned __init gen_fdt_mem_array(__be32 *mem_array, unsigned long size,
71 enum mem_map map)
72{
73 unsigned long size_preio;
74 unsigned entries;
75
76 entries = 1;
77 mem_array[0] = cpu_to_be32(PHYS_OFFSET);
78 if (IS_ENABLED(CONFIG_EVA)) {
79 /*
80 * The current Malta EVA configuration is "special" in that it
81 * always makes use of addresses in the upper half of the 32 bit
82 * physical address map, which gives it a contiguous region of
83 * DDR but limits it to 2GB.
84 */
85 mem_array[1] = cpu_to_be32(size);
86 goto done;
87 }
88
89 size_preio = min_t(unsigned long, size, SZ_256M);
90 mem_array[1] = cpu_to_be32(size_preio);
91 size -= size_preio;
92 if (!size)
93 goto done;
94
95 if (map == MEM_MAP_V2) {
96 /*
97 * We have a flat 32 bit physical memory map with DDR filling
98 * all 4GB of the memory map, apart from the I/O region which
99 * obscures 256MB from 0x10000000-0x1fffffff.
100 *
101 * Therefore we discard the 256MB behind the I/O region.
102 */
103 if (size <= SZ_256M)
104 goto done;
105 size -= SZ_256M;
106
107 /* Make use of the memory following the I/O region */
108 entries++;
109 mem_array[2] = cpu_to_be32(PHYS_OFFSET + SZ_512M);
110 mem_array[3] = cpu_to_be32(size);
111 } else {
112 /*
113 * We have a 32 bit physical memory map with a 2GB DDR region
114 * aliased in the upper & lower halves of it. The I/O region
115 * obscures 256MB from 0x10000000-0x1fffffff in the low alias
116 * but the DDR it obscures is accessible via the high alias.
117 *
118 * Simply access everything beyond the lowest 256MB of DDR using
119 * the high alias.
120 */
121 entries++;
122 mem_array[2] = cpu_to_be32(PHYS_OFFSET + SZ_2G + SZ_256M);
123 mem_array[3] = cpu_to_be32(size);
124 }
125
126done:
127 BUG_ON(entries > MAX_MEM_ARRAY_ENTRIES);
128 return entries;
129}
130
131static void __init append_memory(void *fdt, int root_off)
132{
133 __be32 mem_array[2 * MAX_MEM_ARRAY_ENTRIES];
134 unsigned long memsize;
135 unsigned mem_entries;
136 int i, err, mem_off;
137 enum mem_map mem_map;
138 u32 config;
139 char *var, param_name[10], *var_names[] = {
140 "ememsize", "memsize",
141 };
142
143 /* if a memory node already exists, leave it alone */
144 mem_off = fdt_path_offset(fdt, "/memory");
145 if (mem_off >= 0)
146 return;
147
148 /* find memory size from the bootloader environment */
149 for (i = 0; i < ARRAY_SIZE(var_names); i++) {
150 var = fw_getenv(var_names[i]);
151 if (!var)
152 continue;
153
154 err = kstrtoul(var, 0, &physical_memsize);
155 if (!err)
156 break;
157
158 pr_warn("Failed to read the '%s' env variable '%s'\n",
159 var_names[i], var);
160 }
161
162 if (!physical_memsize) {
163 pr_warn("The bootloader didn't provide memsize: defaulting to 32MB\n");
164 physical_memsize = 32 << 20;
165 }
166
167 if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) {
168 /*
169 * SOC-it swaps, or perhaps doesn't swap, when DMA'ing
170 * the last word of physical memory.
171 */
172 physical_memsize -= PAGE_SIZE;
173 }
174
175 /* default to using all available RAM */
176 memsize = physical_memsize;
177
178 /* allow the user to override the usable memory */
179 for (i = 0; i < ARRAY_SIZE(var_names); i++) {
180 snprintf(param_name, sizeof(param_name), "%s=", var_names[i]);
181 var = strstr(arcs_cmdline, param_name);
182 if (!var)
183 continue;
184
185 memsize = memparse(var + strlen(param_name), NULL);
186 }
187
188 /* if the user says there's more RAM than we thought, believe them */
189 physical_memsize = max_t(unsigned long, physical_memsize, memsize);
190
191 /* detect the memory map in use */
192 if (malta_scon() == MIPS_REVISION_SCON_ROCIT) {
193 /* ROCit has a register indicating the memory map in use */
194 config = readl((void __iomem *)CKSEG1ADDR(ROCIT_CONFIG_GEN1));
195 mem_map = config & ROCIT_CONFIG_GEN1_MEMMAP_MASK;
196 mem_map >>= ROCIT_CONFIG_GEN1_MEMMAP_SHIFT;
197 } else {
198 /* if not using ROCit, presume the v1 memory map */
199 mem_map = MEM_MAP_V1;
200 }
201 if (mem_map > MEM_MAP_V2)
202 panic("Unsupported physical memory map v%u detected",
203 (unsigned int)mem_map);
204
205 /* append memory to the DT */
206 mem_off = fdt_add_subnode(fdt, root_off, "memory");
207 if (mem_off < 0)
208 panic("Unable to add memory node to DT: %d", mem_off);
209
210 err = fdt_setprop_string(fdt, mem_off, "device_type", "memory");
211 if (err)
212 panic("Unable to set memory node device_type: %d", err);
213
214 mem_entries = gen_fdt_mem_array(mem_array, physical_memsize, mem_map);
215 err = fdt_setprop(fdt, mem_off, "reg", mem_array,
216 mem_entries * 2 * sizeof(mem_array[0]));
217 if (err)
218 panic("Unable to set memory regs property: %d", err);
219
220 mem_entries = gen_fdt_mem_array(mem_array, memsize, mem_map);
221 err = fdt_setprop(fdt, mem_off, "linux,usable-memory", mem_array,
222 mem_entries * 2 * sizeof(mem_array[0]));
223 if (err)
224 panic("Unable to set linux,usable-memory property: %d", err);
225}
226
227static void __init remove_gic(void *fdt)
228{
229 int err, gic_off, i8259_off, cpu_off;
230 void __iomem *biu_base;
231 uint32_t cpu_phandle, sc_cfg;
232
233 /* if we have a CM which reports a GIC is present, leave the DT alone */
234 err = mips_cm_probe();
235 if (!err && (read_gcr_gic_status() & CM_GCR_GIC_STATUS_EX))
236 return;
237
238 if (malta_scon() == MIPS_REVISION_SCON_ROCIT) {
239 /*
240 * On systems using the RocIT system controller a GIC may be
241 * present without a CM. Detect whether that is the case.
242 */
243 biu_base = ioremap(MSC01_BIU_REG_BASE,
244 MSC01_BIU_ADDRSPACE_SZ);
245 sc_cfg = __raw_readl(biu_base + MSC01_SC_CFG_OFS);
246 if (sc_cfg & MSC01_SC_CFG_GICPRES_MSK) {
247 /* enable the GIC at the system controller level */
248 sc_cfg |= BIT(MSC01_SC_CFG_GICENA_SHF);
249 __raw_writel(sc_cfg, biu_base + MSC01_SC_CFG_OFS);
250 return;
251 }
252 }
253
254 gic_off = fdt_node_offset_by_compatible(fdt, -1, "mti,gic");
255 if (gic_off < 0) {
256 pr_warn("malta-dtshim: unable to find DT GIC node: %d\n",
257 gic_off);
258 return;
259 }
260
261 err = fdt_nop_node(fdt, gic_off);
262 if (err)
263 pr_warn("malta-dtshim: unable to nop GIC node\n");
264
265 i8259_off = fdt_node_offset_by_compatible(fdt, -1, "intel,i8259");
266 if (i8259_off < 0) {
267 pr_warn("malta-dtshim: unable to find DT i8259 node: %d\n",
268 i8259_off);
269 return;
270 }
271
272 cpu_off = fdt_node_offset_by_compatible(fdt, -1,
273 "mti,cpu-interrupt-controller");
274 if (cpu_off < 0) {
275 pr_warn("malta-dtshim: unable to find CPU intc node: %d\n",
276 cpu_off);
277 return;
278 }
279
280 cpu_phandle = fdt_get_phandle(fdt, cpu_off);
281 if (!cpu_phandle) {
282 pr_warn("malta-dtshim: unable to get CPU intc phandle\n");
283 return;
284 }
285
286 err = fdt_setprop_u32(fdt, i8259_off, "interrupt-parent", cpu_phandle);
287 if (err) {
288 pr_warn("malta-dtshim: unable to set i8259 interrupt-parent: %d\n",
289 err);
290 return;
291 }
292
293 err = fdt_setprop_u32(fdt, i8259_off, "interrupts", 2);
294 if (err) {
295 pr_warn("malta-dtshim: unable to set i8259 interrupts: %d\n",
296 err);
297 return;
298 }
299}
300
301void __init *malta_dt_shim(void *fdt)
302{
303 int root_off, len, err;
304 const char *compat;
305
306 if (fdt_check_header(fdt))
307 panic("Corrupt DT");
308
309 err = fdt_open_into(fdt, fdt_buf, sizeof(fdt_buf));
310 if (err)
311 panic("Unable to open FDT: %d", err);
312
313 root_off = fdt_path_offset(fdt_buf, "/");
314 if (root_off < 0)
315 panic("No / node in DT");
316
317 compat = fdt_getprop(fdt_buf, root_off, "compatible", &len);
318 if (!compat)
319 panic("No root compatible property in DT: %d", len);
320
321 /* if this isn't Malta, leave the DT alone */
322 if (strncmp(compat, "mti,malta", len))
323 return fdt;
324
325 append_memory(fdt_buf, root_off);
326 remove_gic(fdt_buf);
327
328 err = fdt_pack(fdt_buf);
329 if (err)
330 panic("Unable to pack FDT: %d\n", err);
331
332 return fdt_buf;
333}
diff --git a/arch/mips/mti-malta/malta-init.c b/arch/mips/mti-malta/malta-init.c
new file mode 100644
index 000000000..893af377a
--- /dev/null
+++ b/arch/mips/mti-malta/malta-init.c
@@ -0,0 +1,298 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * PROM library initialisation code.
7 *
8 * Copyright (C) 1999,2000,2004,2005,2012 MIPS Technologies, Inc.
9 * All rights reserved.
10 * Authors: Carsten Langgaard <carstenl@mips.com>
11 * Maciej W. Rozycki <macro@mips.com>
12 * Steven J. Hill <sjhill@mips.com>
13 */
14#include <linux/init.h>
15#include <linux/string.h>
16#include <linux/kernel.h>
17#include <linux/pci_regs.h>
18#include <linux/serial_core.h>
19
20#include <asm/cacheflush.h>
21#include <asm/smp-ops.h>
22#include <asm/traps.h>
23#include <asm/fw/fw.h>
24#include <asm/mips-cps.h>
25#include <asm/mips-boards/generic.h>
26#include <asm/mips-boards/malta.h>
27
28static int mips_revision_corid;
29int mips_revision_sconid;
30
31/* Bonito64 system controller register base. */
32unsigned long _pcictrl_bonito;
33unsigned long _pcictrl_bonito_pcicfg;
34
35/* GT64120 system controller register base */
36unsigned long _pcictrl_gt64120;
37
38/* MIPS System controller register base */
39unsigned long _pcictrl_msc;
40
41#ifdef CONFIG_SERIAL_8250_CONSOLE
42static void __init console_config(void)
43{
44 char console_string[40];
45 int baud = 0;
46 char parity = '\0', bits = '\0', flow = '\0';
47 char *s;
48
49 s = fw_getenv("modetty0");
50 if (s) {
51 while (*s >= '0' && *s <= '9')
52 baud = baud*10 + *s++ - '0';
53 if (*s == ',')
54 s++;
55 if (*s)
56 parity = *s++;
57 if (*s == ',')
58 s++;
59 if (*s)
60 bits = *s++;
61 if (*s == ',')
62 s++;
63 if (*s == 'h')
64 flow = 'r';
65 }
66 if (baud == 0)
67 baud = 38400;
68 if (parity != 'n' && parity != 'o' && parity != 'e')
69 parity = 'n';
70 if (bits != '7' && bits != '8')
71 bits = '8';
72 if (flow == '\0')
73 flow = 'r';
74
75 if ((strstr(fw_getcmdline(), "earlycon=")) == NULL) {
76 sprintf(console_string, "uart8250,io,0x3f8,%d%c%c", baud,
77 parity, bits);
78 setup_earlycon(console_string);
79 }
80
81 if ((strstr(fw_getcmdline(), "console=")) == NULL) {
82 sprintf(console_string, " console=ttyS0,%d%c%c%c", baud,
83 parity, bits, flow);
84 strcat(fw_getcmdline(), console_string);
85 pr_info("Config serial console:%s\n", console_string);
86 }
87}
88#endif
89
90static void __init mips_nmi_setup(void)
91{
92 void *base;
93 extern char except_vec_nmi[];
94
95 base = cpu_has_veic ?
96 (void *)(CAC_BASE + 0xa80) :
97 (void *)(CAC_BASE + 0x380);
98 memcpy(base, except_vec_nmi, 0x80);
99 flush_icache_range((unsigned long)base, (unsigned long)base + 0x80);
100}
101
102static void __init mips_ejtag_setup(void)
103{
104 void *base;
105 extern char except_vec_ejtag_debug[];
106
107 base = cpu_has_veic ?
108 (void *)(CAC_BASE + 0xa00) :
109 (void *)(CAC_BASE + 0x300);
110 memcpy(base, except_vec_ejtag_debug, 0x80);
111 flush_icache_range((unsigned long)base, (unsigned long)base + 0x80);
112}
113
114phys_addr_t mips_cpc_default_phys_base(void)
115{
116 return CPC_BASE_ADDR;
117}
118
119void __init prom_init(void)
120{
121 /*
122 * early setup of _pcictrl_bonito so that we can determine
123 * the system controller on a CORE_EMUL board
124 */
125 _pcictrl_bonito = (unsigned long)ioremap(BONITO_REG_BASE, BONITO_REG_SIZE);
126
127 mips_revision_corid = MIPS_REVISION_CORID;
128
129 if (mips_revision_corid == MIPS_REVISION_CORID_CORE_EMUL) {
130 if (BONITO_PCIDID == 0x0001df53 ||
131 BONITO_PCIDID == 0x0003df53)
132 mips_revision_corid = MIPS_REVISION_CORID_CORE_EMUL_BON;
133 else
134 mips_revision_corid = MIPS_REVISION_CORID_CORE_EMUL_MSC;
135 }
136
137 mips_revision_sconid = MIPS_REVISION_SCONID;
138 if (mips_revision_sconid == MIPS_REVISION_SCON_OTHER) {
139 switch (mips_revision_corid) {
140 case MIPS_REVISION_CORID_QED_RM5261:
141 case MIPS_REVISION_CORID_CORE_LV:
142 case MIPS_REVISION_CORID_CORE_FPGA:
143 case MIPS_REVISION_CORID_CORE_FPGAR2:
144 mips_revision_sconid = MIPS_REVISION_SCON_GT64120;
145 break;
146 case MIPS_REVISION_CORID_CORE_EMUL_BON:
147 case MIPS_REVISION_CORID_BONITO64:
148 case MIPS_REVISION_CORID_CORE_20K:
149 mips_revision_sconid = MIPS_REVISION_SCON_BONITO;
150 break;
151 case MIPS_REVISION_CORID_CORE_MSC:
152 case MIPS_REVISION_CORID_CORE_FPGA2:
153 case MIPS_REVISION_CORID_CORE_24K:
154 /*
155 * SOCit/ROCit support is essentially identical
156 * but make an attempt to distinguish them
157 */
158 mips_revision_sconid = MIPS_REVISION_SCON_SOCIT;
159 break;
160 case MIPS_REVISION_CORID_CORE_FPGA3:
161 case MIPS_REVISION_CORID_CORE_FPGA4:
162 case MIPS_REVISION_CORID_CORE_FPGA5:
163 case MIPS_REVISION_CORID_CORE_EMUL_MSC:
164 default:
165 /* See above */
166 mips_revision_sconid = MIPS_REVISION_SCON_ROCIT;
167 break;
168 }
169 }
170
171 switch (mips_revision_sconid) {
172 u32 start, map, mask, data;
173
174 case MIPS_REVISION_SCON_GT64120:
175 /*
176 * Setup the North bridge to do Master byte-lane swapping
177 * when running in bigendian.
178 */
179 _pcictrl_gt64120 = (unsigned long)ioremap(MIPS_GT_BASE, 0x2000);
180
181#ifdef CONFIG_CPU_LITTLE_ENDIAN
182 GT_WRITE(GT_PCI0_CMD_OFS, GT_PCI0_CMD_MBYTESWAP_BIT |
183 GT_PCI0_CMD_SBYTESWAP_BIT);
184#else
185 GT_WRITE(GT_PCI0_CMD_OFS, 0);
186#endif
187 /* Fix up PCI I/O mapping if necessary (for Atlas). */
188 start = GT_READ(GT_PCI0IOLD_OFS);
189 map = GT_READ(GT_PCI0IOREMAP_OFS);
190 if ((start & map) != 0) {
191 map &= ~start;
192 GT_WRITE(GT_PCI0IOREMAP_OFS, map);
193 }
194
195 set_io_port_base(MALTA_GT_PORT_BASE);
196 break;
197
198 case MIPS_REVISION_SCON_BONITO:
199 _pcictrl_bonito_pcicfg = (unsigned long)ioremap(BONITO_PCICFG_BASE, BONITO_PCICFG_SIZE);
200
201 /*
202 * Disable Bonito IOBC.
203 */
204 BONITO_PCIMEMBASECFG = BONITO_PCIMEMBASECFG &
205 ~(BONITO_PCIMEMBASECFG_MEMBASE0_CACHED |
206 BONITO_PCIMEMBASECFG_MEMBASE1_CACHED);
207
208 /*
209 * Setup the North bridge to do Master byte-lane swapping
210 * when running in bigendian.
211 */
212#ifdef CONFIG_CPU_LITTLE_ENDIAN
213 BONITO_BONGENCFG = BONITO_BONGENCFG &
214 ~(BONITO_BONGENCFG_MSTRBYTESWAP |
215 BONITO_BONGENCFG_BYTESWAP);
216#else
217 BONITO_BONGENCFG = BONITO_BONGENCFG |
218 BONITO_BONGENCFG_MSTRBYTESWAP |
219 BONITO_BONGENCFG_BYTESWAP;
220#endif
221
222 set_io_port_base(MALTA_BONITO_PORT_BASE);
223 break;
224
225 case MIPS_REVISION_SCON_SOCIT:
226 case MIPS_REVISION_SCON_ROCIT:
227 _pcictrl_msc = (unsigned long)ioremap(MIPS_MSC01_PCI_REG_BASE, 0x2000);
228mips_pci_controller:
229 mb();
230 MSC_READ(MSC01_PCI_CFG, data);
231 MSC_WRITE(MSC01_PCI_CFG, data & ~MSC01_PCI_CFG_EN_BIT);
232 wmb();
233
234 /* Fix up lane swapping. */
235#ifdef CONFIG_CPU_LITTLE_ENDIAN
236 MSC_WRITE(MSC01_PCI_SWAP, MSC01_PCI_SWAP_NOSWAP);
237#else
238 MSC_WRITE(MSC01_PCI_SWAP,
239 MSC01_PCI_SWAP_BYTESWAP << MSC01_PCI_SWAP_IO_SHF |
240 MSC01_PCI_SWAP_BYTESWAP << MSC01_PCI_SWAP_MEM_SHF |
241 MSC01_PCI_SWAP_BYTESWAP << MSC01_PCI_SWAP_BAR0_SHF);
242#endif
243
244 /*
245 * Setup the Malta max (2GB) memory for PCI DMA in host bridge
246 * in transparent addressing mode.
247 */
248 mask = PHYS_OFFSET | PCI_BASE_ADDRESS_MEM_PREFETCH;
249 MSC_WRITE(MSC01_PCI_BAR0, mask);
250 MSC_WRITE(MSC01_PCI_HEAD4, mask);
251
252 mask &= MSC01_PCI_BAR0_SIZE_MSK;
253 MSC_WRITE(MSC01_PCI_P2SCMSKL, mask);
254 MSC_WRITE(MSC01_PCI_P2SCMAPL, mask);
255
256 /* Don't handle target retries indefinitely. */
257 if ((data & MSC01_PCI_CFG_MAXRTRY_MSK) ==
258 MSC01_PCI_CFG_MAXRTRY_MSK)
259 data = (data & ~(MSC01_PCI_CFG_MAXRTRY_MSK <<
260 MSC01_PCI_CFG_MAXRTRY_SHF)) |
261 ((MSC01_PCI_CFG_MAXRTRY_MSK - 1) <<
262 MSC01_PCI_CFG_MAXRTRY_SHF);
263
264 wmb();
265 MSC_WRITE(MSC01_PCI_CFG, data);
266 mb();
267
268 set_io_port_base(MALTA_MSC_PORT_BASE);
269 break;
270
271 case MIPS_REVISION_SCON_SOCITSC:
272 case MIPS_REVISION_SCON_SOCITSCP:
273 _pcictrl_msc = (unsigned long)ioremap(MIPS_SOCITSC_PCI_REG_BASE, 0x2000);
274 goto mips_pci_controller;
275
276 default:
277 /* Unknown system controller */
278 while (1); /* We die here... */
279 }
280 board_nmi_handler_setup = mips_nmi_setup;
281 board_ejtag_handler_setup = mips_ejtag_setup;
282
283 fw_init_cmdline();
284 fw_meminit();
285#ifdef CONFIG_SERIAL_8250_CONSOLE
286 console_config();
287#endif
288 /* Early detection of CMP support */
289 mips_cpc_probe();
290
291 if (!register_cps_smp_ops())
292 return;
293 if (!register_cmp_smp_ops())
294 return;
295 if (!register_vsmp_smp_ops())
296 return;
297 register_up_smp_ops();
298}
diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c
new file mode 100644
index 000000000..03d85b2b3
--- /dev/null
+++ b/arch/mips/mti-malta/malta-int.c
@@ -0,0 +1,223 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Carsten Langgaard, carstenl@mips.com
7 * Copyright (C) 2000, 2001, 2004 MIPS Technologies, Inc.
8 * Copyright (C) 2001 Ralf Baechle
9 * Copyright (C) 2013 Imagination Technologies Ltd.
10 *
11 * Routines for generic manipulation of the interrupts found on the MIPS
12 * Malta board. The interrupt controller is located in the South Bridge
13 * a PIIX4 device with two internal 82C95 interrupt controllers.
14 */
15#include <linux/init.h>
16#include <linux/irq.h>
17#include <linux/irqchip.h>
18#include <linux/sched.h>
19#include <linux/smp.h>
20#include <linux/interrupt.h>
21#include <linux/io.h>
22#include <linux/of_irq.h>
23#include <linux/kernel_stat.h>
24#include <linux/kernel.h>
25#include <linux/random.h>
26
27#include <asm/traps.h>
28#include <asm/i8259.h>
29#include <asm/irq_cpu.h>
30#include <asm/irq_regs.h>
31#include <asm/mips-boards/malta.h>
32#include <asm/mips-boards/maltaint.h>
33#include <asm/mips-cps.h>
34#include <asm/gt64120.h>
35#include <asm/mips-boards/generic.h>
36#include <asm/mips-boards/msc01_pci.h>
37#include <asm/msc01_ic.h>
38#include <asm/setup.h>
39#include <asm/rtlx.h>
40
41static inline int mips_pcibios_iack(void)
42{
43 int irq;
44
45 /*
46 * Determine highest priority pending interrupt by performing
47 * a PCI Interrupt Acknowledge cycle.
48 */
49 switch (mips_revision_sconid) {
50 case MIPS_REVISION_SCON_SOCIT:
51 case MIPS_REVISION_SCON_ROCIT:
52 case MIPS_REVISION_SCON_SOCITSC:
53 case MIPS_REVISION_SCON_SOCITSCP:
54 MSC_READ(MSC01_PCI_IACK, irq);
55 irq &= 0xff;
56 break;
57 case MIPS_REVISION_SCON_GT64120:
58 irq = GT_READ(GT_PCI0_IACK_OFS);
59 irq &= 0xff;
60 break;
61 case MIPS_REVISION_SCON_BONITO:
62 /* The following will generate a PCI IACK cycle on the
63 * Bonito controller. It's a little bit kludgy, but it
64 * was the easiest way to implement it in hardware at
65 * the given time.
66 */
67 BONITO_PCIMAP_CFG = 0x20000;
68
69 /* Flush Bonito register block */
70 (void) BONITO_PCIMAP_CFG;
71 iob(); /* sync */
72
73 irq = __raw_readl((u32 *)_pcictrl_bonito_pcicfg);
74 iob(); /* sync */
75 irq &= 0xff;
76 BONITO_PCIMAP_CFG = 0;
77 break;
78 default:
79 pr_emerg("Unknown system controller.\n");
80 return -1;
81 }
82 return irq;
83}
84
85static void corehi_irqdispatch(void)
86{
87 unsigned int intedge, intsteer, pcicmd, pcibadaddr;
88 unsigned int pcimstat, intisr, inten, intpol;
89 unsigned int intrcause, datalo, datahi;
90 struct pt_regs *regs = get_irq_regs();
91
92 pr_emerg("CoreHI interrupt, shouldn't happen, we die here!\n");
93 pr_emerg("epc : %08lx\nStatus: %08lx\n"
94 "Cause : %08lx\nbadVaddr : %08lx\n",
95 regs->cp0_epc, regs->cp0_status,
96 regs->cp0_cause, regs->cp0_badvaddr);
97
98 /* Read all the registers and then print them as there is a
99 problem with interspersed printk's upsetting the Bonito controller.
100 Do it for the others too.
101 */
102
103 switch (mips_revision_sconid) {
104 case MIPS_REVISION_SCON_SOCIT:
105 case MIPS_REVISION_SCON_ROCIT:
106 case MIPS_REVISION_SCON_SOCITSC:
107 case MIPS_REVISION_SCON_SOCITSCP:
108 ll_msc_irq();
109 break;
110 case MIPS_REVISION_SCON_GT64120:
111 intrcause = GT_READ(GT_INTRCAUSE_OFS);
112 datalo = GT_READ(GT_CPUERR_ADDRLO_OFS);
113 datahi = GT_READ(GT_CPUERR_ADDRHI_OFS);
114 pr_emerg("GT_INTRCAUSE = %08x\n", intrcause);
115 pr_emerg("GT_CPUERR_ADDR = %02x%08x\n",
116 datahi, datalo);
117 break;
118 case MIPS_REVISION_SCON_BONITO:
119 pcibadaddr = BONITO_PCIBADADDR;
120 pcimstat = BONITO_PCIMSTAT;
121 intisr = BONITO_INTISR;
122 inten = BONITO_INTEN;
123 intpol = BONITO_INTPOL;
124 intedge = BONITO_INTEDGE;
125 intsteer = BONITO_INTSTEER;
126 pcicmd = BONITO_PCICMD;
127 pr_emerg("BONITO_INTISR = %08x\n", intisr);
128 pr_emerg("BONITO_INTEN = %08x\n", inten);
129 pr_emerg("BONITO_INTPOL = %08x\n", intpol);
130 pr_emerg("BONITO_INTEDGE = %08x\n", intedge);
131 pr_emerg("BONITO_INTSTEER = %08x\n", intsteer);
132 pr_emerg("BONITO_PCICMD = %08x\n", pcicmd);
133 pr_emerg("BONITO_PCIBADADDR = %08x\n", pcibadaddr);
134 pr_emerg("BONITO_PCIMSTAT = %08x\n", pcimstat);
135 break;
136 }
137
138 die("CoreHi interrupt", regs);
139}
140
141static irqreturn_t corehi_handler(int irq, void *dev_id)
142{
143 corehi_irqdispatch();
144 return IRQ_HANDLED;
145}
146
147static msc_irqmap_t msc_irqmap[] __initdata = {
148 {MSC01C_INT_TMR, MSC01_IRQ_EDGE, 0},
149 {MSC01C_INT_PCI, MSC01_IRQ_LEVEL, 0},
150};
151static int msc_nr_irqs __initdata = ARRAY_SIZE(msc_irqmap);
152
153static msc_irqmap_t msc_eicirqmap[] __initdata = {
154 {MSC01E_INT_SW0, MSC01_IRQ_LEVEL, 0},
155 {MSC01E_INT_SW1, MSC01_IRQ_LEVEL, 0},
156 {MSC01E_INT_I8259A, MSC01_IRQ_LEVEL, 0},
157 {MSC01E_INT_SMI, MSC01_IRQ_LEVEL, 0},
158 {MSC01E_INT_COREHI, MSC01_IRQ_LEVEL, 0},
159 {MSC01E_INT_CORELO, MSC01_IRQ_LEVEL, 0},
160 {MSC01E_INT_TMR, MSC01_IRQ_EDGE, 0},
161 {MSC01E_INT_PCI, MSC01_IRQ_LEVEL, 0},
162 {MSC01E_INT_PERFCTR, MSC01_IRQ_LEVEL, 0},
163 {MSC01E_INT_CPUCTR, MSC01_IRQ_LEVEL, 0}
164};
165
166static int msc_nr_eicirqs __initdata = ARRAY_SIZE(msc_eicirqmap);
167
168void __init arch_init_irq(void)
169{
170 int corehi_irq;
171
172 /*
173 * Preallocate the i8259's expected virq's here. Since irqchip_init()
174 * will probe the irqchips in hierarchial order, i8259 is probed last.
175 * If anything allocates a virq before the i8259 is probed, it will
176 * be given one of the i8259's expected range and consequently setup
177 * of the i8259 will fail.
178 */
179 WARN(irq_alloc_descs(I8259A_IRQ_BASE, I8259A_IRQ_BASE,
180 16, numa_node_id()) < 0,
181 "Cannot reserve i8259 virqs at IRQ%d\n", I8259A_IRQ_BASE);
182
183 i8259_set_poll(mips_pcibios_iack);
184 irqchip_init();
185
186 switch (mips_revision_sconid) {
187 case MIPS_REVISION_SCON_SOCIT:
188 case MIPS_REVISION_SCON_ROCIT:
189 if (cpu_has_veic)
190 init_msc_irqs(MIPS_MSC01_IC_REG_BASE,
191 MSC01E_INT_BASE, msc_eicirqmap,
192 msc_nr_eicirqs);
193 else
194 init_msc_irqs(MIPS_MSC01_IC_REG_BASE,
195 MSC01C_INT_BASE, msc_irqmap,
196 msc_nr_irqs);
197 break;
198
199 case MIPS_REVISION_SCON_SOCITSC:
200 case MIPS_REVISION_SCON_SOCITSCP:
201 if (cpu_has_veic)
202 init_msc_irqs(MIPS_SOCITSC_IC_REG_BASE,
203 MSC01E_INT_BASE, msc_eicirqmap,
204 msc_nr_eicirqs);
205 else
206 init_msc_irqs(MIPS_SOCITSC_IC_REG_BASE,
207 MSC01C_INT_BASE, msc_irqmap,
208 msc_nr_irqs);
209 }
210
211 if (mips_gic_present()) {
212 corehi_irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_COREHI;
213 } else if (cpu_has_veic) {
214 set_vi_handler(MSC01E_INT_COREHI, corehi_irqdispatch);
215 corehi_irq = MSC01E_INT_BASE + MSC01E_INT_COREHI;
216 } else {
217 corehi_irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_COREHI;
218 }
219
220 if (request_irq(corehi_irq, corehi_handler, IRQF_NO_THREAD, "CoreHi",
221 NULL))
222 pr_err("Failed to request irq %d (CoreHi)\n", corehi_irq);
223}
diff --git a/arch/mips/mti-malta/malta-memory.c b/arch/mips/mti-malta/malta-memory.c
new file mode 100644
index 000000000..7c25a0a23
--- /dev/null
+++ b/arch/mips/mti-malta/malta-memory.c
@@ -0,0 +1,48 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * PROM library functions for acquiring/using memory descriptors given to
7 * us from the YAMON.
8 *
9 * Copyright (C) 1999,2000,2012 MIPS Technologies, Inc.
10 * All rights reserved.
11 * Authors: Carsten Langgaard <carstenl@mips.com>
12 * Steven J. Hill <sjhill@mips.com>
13 */
14#include <linux/init.h>
15#include <linux/memblock.h>
16#include <linux/string.h>
17
18#include <asm/bootinfo.h>
19#include <asm/cdmm.h>
20#include <asm/maar.h>
21#include <asm/sections.h>
22#include <asm/fw/fw.h>
23
24/* determined physical memory size, not overridden by command line args */
25unsigned long physical_memsize = 0L;
26
27static void free_init_pages_eva_malta(void *begin, void *end)
28{
29 free_init_pages("unused kernel", __pa_symbol((unsigned long *)begin),
30 __pa_symbol((unsigned long *)end));
31}
32
33void __init fw_meminit(void)
34{
35 bool eva = IS_ENABLED(CONFIG_EVA);
36
37 free_init_pages_eva = eva ? free_init_pages_eva_malta : NULL;
38}
39
40void __init prom_free_prom_memory(void)
41{
42}
43
44phys_addr_t mips_cdmm_phys_base(void)
45{
46 /* This address is "typically unused" */
47 return 0x1fc10000;
48}
diff --git a/arch/mips/mti-malta/malta-platform.c b/arch/mips/mti-malta/malta-platform.c
new file mode 100644
index 000000000..62ffac500
--- /dev/null
+++ b/arch/mips/mti-malta/malta-platform.c
@@ -0,0 +1,76 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2006, 07 MIPS Technologies, Inc.
7 * written by Ralf Baechle (ralf@linux-mips.org)
8 * written by Ralf Baechle <ralf@linux-mips.org>
9 *
10 * Copyright (C) 2008 Wind River Systems, Inc.
11 * updated by Tiejun Chen <tiejun.chen@windriver.com>
12 *
13 * 1. Probe driver for the Malta's UART ports:
14 *
15 * o 2 ports in the SMC SuperIO
16 * o 1 port in the CBUS UART, a discrete 16550 which normally is only used
17 * for bringups.
18 *
19 * We don't use 8250_platform.c on Malta as it would result in the CBUS
20 * UART becoming ttyS0.
21 *
22 * 2. Register RTC-CMOS platform device on Malta.
23 */
24#include <linux/init.h>
25#include <linux/serial_8250.h>
26#include <linux/irq.h>
27#include <linux/platform_device.h>
28#include <asm/mips-boards/maltaint.h>
29
30#define SMC_PORT(base, int) \
31{ \
32 .iobase = base, \
33 .irq = int, \
34 .uartclk = 1843200, \
35 .iotype = UPIO_PORT, \
36 .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, \
37 .regshift = 0, \
38}
39
40#define CBUS_UART_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP)
41
42static struct plat_serial8250_port uart8250_data[] = {
43 SMC_PORT(0x3F8, 4),
44 SMC_PORT(0x2F8, 3),
45#ifndef CONFIG_MIPS_CMP
46 {
47 .mapbase = 0x1f000900, /* The CBUS UART */
48 .irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_MB2,
49 .uartclk = 3686400, /* Twice the usual clk! */
50 .iotype = IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) ?
51 UPIO_MEM32BE : UPIO_MEM32,
52 .flags = CBUS_UART_FLAGS,
53 .regshift = 3,
54 },
55#endif
56 { },
57};
58
59static struct platform_device malta_uart8250_device = {
60 .name = "serial8250",
61 .id = PLAT8250_DEV_PLATFORM,
62 .dev = {
63 .platform_data = uart8250_data,
64 },
65};
66
67static struct platform_device *malta_devices[] __initdata = {
68 &malta_uart8250_device,
69};
70
71static int __init malta_add_devices(void)
72{
73 return platform_add_devices(malta_devices, ARRAY_SIZE(malta_devices));
74}
75
76device_initcall(malta_add_devices);
diff --git a/arch/mips/mti-malta/malta-setup.c b/arch/mips/mti-malta/malta-setup.c
new file mode 100644
index 000000000..e1fb8b534
--- /dev/null
+++ b/arch/mips/mti-malta/malta-setup.c
@@ -0,0 +1,249 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Carsten Langgaard, carstenl@mips.com
4 * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
5 * Copyright (C) 2008 Dmitri Vorobiev
6 */
7#include <linux/cpu.h>
8#include <linux/init.h>
9#include <linux/sched.h>
10#include <linux/ioport.h>
11#include <linux/irq.h>
12#include <linux/of_fdt.h>
13#include <linux/pci.h>
14#include <linux/screen_info.h>
15#include <linux/time.h>
16
17#include <asm/dma-coherence.h>
18#include <asm/fw/fw.h>
19#include <asm/mips-cps.h>
20#include <asm/mips-boards/generic.h>
21#include <asm/mips-boards/malta.h>
22#include <asm/mips-boards/maltaint.h>
23#include <asm/dma.h>
24#include <asm/prom.h>
25#include <asm/traps.h>
26#ifdef CONFIG_VT
27#include <linux/console.h>
28#endif
29
30#define ROCIT_CONFIG_GEN0 0x1f403000
31#define ROCIT_CONFIG_GEN0_PCI_IOCU BIT(7)
32
33static struct resource standard_io_resources[] = {
34 {
35 .name = "dma1",
36 .start = 0x00,
37 .end = 0x1f,
38 .flags = IORESOURCE_IO | IORESOURCE_BUSY
39 },
40 {
41 .name = "timer",
42 .start = 0x40,
43 .end = 0x5f,
44 .flags = IORESOURCE_IO | IORESOURCE_BUSY
45 },
46 {
47 .name = "keyboard",
48 .start = 0x60,
49 .end = 0x6f,
50 .flags = IORESOURCE_IO | IORESOURCE_BUSY
51 },
52 {
53 .name = "dma page reg",
54 .start = 0x80,
55 .end = 0x8f,
56 .flags = IORESOURCE_IO | IORESOURCE_BUSY
57 },
58 {
59 .name = "dma2",
60 .start = 0xc0,
61 .end = 0xdf,
62 .flags = IORESOURCE_IO | IORESOURCE_BUSY
63 },
64};
65
66const char *get_system_type(void)
67{
68 return "MIPS Malta";
69}
70
71#ifdef CONFIG_BLK_DEV_FD
72static void __init fd_activate(void)
73{
74 /*
75 * Activate Floppy Controller in the SMSC FDC37M817 Super I/O
76 * Controller.
77 * Done by YAMON 2.00 onwards
78 */
79 /* Entering config state. */
80 SMSC_WRITE(SMSC_CONFIG_ENTER, SMSC_CONFIG_REG);
81
82 /* Activate floppy controller. */
83 SMSC_WRITE(SMSC_CONFIG_DEVNUM, SMSC_CONFIG_REG);
84 SMSC_WRITE(SMSC_CONFIG_DEVNUM_FLOPPY, SMSC_DATA_REG);
85 SMSC_WRITE(SMSC_CONFIG_ACTIVATE, SMSC_CONFIG_REG);
86 SMSC_WRITE(SMSC_CONFIG_ACTIVATE_ENABLE, SMSC_DATA_REG);
87
88 /* Exit config state. */
89 SMSC_WRITE(SMSC_CONFIG_EXIT, SMSC_CONFIG_REG);
90}
91#endif
92
93static int __init plat_enable_iocoherency(void)
94{
95 int supported = 0;
96 u32 cfg;
97
98 if (mips_revision_sconid == MIPS_REVISION_SCON_BONITO) {
99 if (BONITO_PCICACHECTRL & BONITO_PCICACHECTRL_CPUCOH_PRES) {
100 BONITO_PCICACHECTRL |= BONITO_PCICACHECTRL_CPUCOH_EN;
101 pr_info("Enabled Bonito CPU coherency\n");
102 supported = 1;
103 }
104 if (strstr(fw_getcmdline(), "iobcuncached")) {
105 BONITO_PCICACHECTRL &= ~BONITO_PCICACHECTRL_IOBCCOH_EN;
106 BONITO_PCIMEMBASECFG = BONITO_PCIMEMBASECFG &
107 ~(BONITO_PCIMEMBASECFG_MEMBASE0_CACHED |
108 BONITO_PCIMEMBASECFG_MEMBASE1_CACHED);
109 pr_info("Disabled Bonito IOBC coherency\n");
110 } else {
111 BONITO_PCICACHECTRL |= BONITO_PCICACHECTRL_IOBCCOH_EN;
112 BONITO_PCIMEMBASECFG |=
113 (BONITO_PCIMEMBASECFG_MEMBASE0_CACHED |
114 BONITO_PCIMEMBASECFG_MEMBASE1_CACHED);
115 pr_info("Enabled Bonito IOBC coherency\n");
116 }
117 } else if (mips_cps_numiocu(0) != 0) {
118 /* Nothing special needs to be done to enable coherency */
119 pr_info("CMP IOCU detected\n");
120 cfg = __raw_readl((u32 *)CKSEG1ADDR(ROCIT_CONFIG_GEN0));
121 if (!(cfg & ROCIT_CONFIG_GEN0_PCI_IOCU)) {
122 pr_crit("IOCU OPERATION DISABLED BY SWITCH - DEFAULTING TO SW IO COHERENCY\n");
123 return 0;
124 }
125 supported = 1;
126 }
127 hw_coherentio = supported;
128 return supported;
129}
130
131static void __init plat_setup_iocoherency(void)
132{
133 if (plat_enable_iocoherency()) {
134 if (coherentio == IO_COHERENCE_DISABLED)
135 pr_info("Hardware DMA cache coherency disabled\n");
136 else
137 pr_info("Hardware DMA cache coherency enabled\n");
138 } else {
139 if (coherentio == IO_COHERENCE_ENABLED)
140 pr_info("Hardware DMA cache coherency unsupported, but enabled from command line!\n");
141 else
142 pr_info("Software DMA cache coherency enabled\n");
143 }
144}
145
146static void __init pci_clock_check(void)
147{
148 unsigned int __iomem *jmpr_p =
149 (unsigned int *) ioremap(MALTA_JMPRS_REG, sizeof(unsigned int));
150 int jmpr = (__raw_readl(jmpr_p) >> 2) & 0x07;
151 static const int pciclocks[] __initconst = {
152 33, 20, 25, 30, 12, 16, 37, 10
153 };
154 int pciclock = pciclocks[jmpr];
155 char *optptr, *argptr = fw_getcmdline();
156
157 /*
158 * If user passed a pci_clock= option, don't tack on another one
159 */
160 optptr = strstr(argptr, "pci_clock=");
161 if (optptr && (optptr == argptr || optptr[-1] == ' '))
162 return;
163
164 if (pciclock != 33) {
165 pr_warn("WARNING: PCI clock is %dMHz, setting pci_clock\n",
166 pciclock);
167 argptr += strlen(argptr);
168 sprintf(argptr, " pci_clock=%d", pciclock);
169 if (pciclock < 20 || pciclock > 66)
170 pr_warn("WARNING: IDE timing calculations will be "
171 "incorrect\n");
172 }
173}
174
175#if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE)
176static void __init screen_info_setup(void)
177{
178 screen_info = (struct screen_info) {
179 .orig_x = 0,
180 .orig_y = 25,
181 .ext_mem_k = 0,
182 .orig_video_page = 0,
183 .orig_video_mode = 0,
184 .orig_video_cols = 80,
185 .unused2 = 0,
186 .orig_video_ega_bx = 0,
187 .unused3 = 0,
188 .orig_video_lines = 25,
189 .orig_video_isVGA = VIDEO_TYPE_VGAC,
190 .orig_video_points = 16
191 };
192}
193#endif
194
195static void __init bonito_quirks_setup(void)
196{
197 char *argptr;
198
199 argptr = fw_getcmdline();
200 if (strstr(argptr, "debug")) {
201 BONITO_BONGENCFG |= BONITO_BONGENCFG_DEBUGMODE;
202 pr_info("Enabled Bonito debug mode\n");
203 } else
204 BONITO_BONGENCFG &= ~BONITO_BONGENCFG_DEBUGMODE;
205}
206
207void __init *plat_get_fdt(void)
208{
209 return (void *)__dtb_start;
210}
211
212void __init plat_mem_setup(void)
213{
214 unsigned int i;
215 void *fdt = plat_get_fdt();
216
217 fdt = malta_dt_shim(fdt);
218 __dt_setup_arch(fdt);
219
220 if (IS_ENABLED(CONFIG_EVA))
221 /* EVA has already been configured in mach-malta/kernel-init.h */
222 pr_info("Enhanced Virtual Addressing (EVA) activated\n");
223
224 mips_pcibios_init();
225
226 /* Request I/O space for devices used on the Malta board. */
227 for (i = 0; i < ARRAY_SIZE(standard_io_resources); i++)
228 request_resource(&ioport_resource, standard_io_resources+i);
229
230 /*
231 * Enable DMA channel 4 (cascade channel) in the PIIX4 south bridge.
232 */
233 enable_dma(4);
234
235 if (mips_revision_sconid == MIPS_REVISION_SCON_BONITO)
236 bonito_quirks_setup();
237
238 plat_setup_iocoherency();
239
240 pci_clock_check();
241
242#ifdef CONFIG_BLK_DEV_FD
243 fd_activate();
244#endif
245
246#if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE)
247 screen_info_setup();
248#endif
249}
diff --git a/arch/mips/mti-malta/malta-time.c b/arch/mips/mti-malta/malta-time.c
new file mode 100644
index 000000000..7efcfe0c9
--- /dev/null
+++ b/arch/mips/mti-malta/malta-time.c
@@ -0,0 +1,256 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Carsten Langgaard, carstenl@mips.com
4 * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
5 *
6 * Setting up the clock on the MIPS boards.
7 */
8#include <linux/types.h>
9#include <linux/i8253.h>
10#include <linux/init.h>
11#include <linux/kernel_stat.h>
12#include <linux/libfdt.h>
13#include <linux/math64.h>
14#include <linux/sched.h>
15#include <linux/spinlock.h>
16#include <linux/interrupt.h>
17#include <linux/timex.h>
18#include <linux/mc146818rtc.h>
19
20#include <asm/cpu.h>
21#include <asm/mipsregs.h>
22#include <asm/mipsmtregs.h>
23#include <asm/hardirq.h>
24#include <asm/irq.h>
25#include <asm/div64.h>
26#include <asm/setup.h>
27#include <asm/time.h>
28#include <asm/mc146818-time.h>
29#include <asm/msc01_ic.h>
30#include <asm/mips-cps.h>
31
32#include <asm/mips-boards/generic.h>
33#include <asm/mips-boards/maltaint.h>
34
35static int mips_cpu_timer_irq;
36static int mips_cpu_perf_irq;
37extern int cp0_perfcount_irq;
38
39static unsigned int gic_frequency;
40
41static void mips_timer_dispatch(void)
42{
43 do_IRQ(mips_cpu_timer_irq);
44}
45
46static void mips_perf_dispatch(void)
47{
48 do_IRQ(mips_cpu_perf_irq);
49}
50
51static unsigned int freqround(unsigned int freq, unsigned int amount)
52{
53 freq += amount;
54 freq -= freq % (amount*2);
55 return freq;
56}
57
58/*
59 * Estimate CPU and GIC frequencies.
60 */
61static void __init estimate_frequencies(void)
62{
63 unsigned long flags;
64 unsigned int count, start;
65 unsigned char secs1, secs2, ctrl;
66 int secs;
67 u64 giccount = 0, gicstart = 0;
68
69#if defined(CONFIG_KVM_GUEST) && CONFIG_KVM_GUEST_TIMER_FREQ
70 mips_hpt_frequency = CONFIG_KVM_GUEST_TIMER_FREQ * 1000000;
71 return;
72#endif
73
74 local_irq_save(flags);
75
76 if (mips_gic_present())
77 clear_gic_config(GIC_CONFIG_COUNTSTOP);
78
79 /*
80 * Read counters exactly on rising edge of update flag.
81 * This helps get an accurate reading under virtualisation.
82 */
83 while (CMOS_READ(RTC_REG_A) & RTC_UIP);
84 while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
85 start = read_c0_count();
86 if (mips_gic_present())
87 gicstart = read_gic_counter();
88
89 /* Wait for falling edge before reading RTC. */
90 while (CMOS_READ(RTC_REG_A) & RTC_UIP);
91 secs1 = CMOS_READ(RTC_SECONDS);
92
93 /* Read counters again exactly on rising edge of update flag. */
94 while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
95 count = read_c0_count();
96 if (mips_gic_present())
97 giccount = read_gic_counter();
98
99 /* Wait for falling edge before reading RTC again. */
100 while (CMOS_READ(RTC_REG_A) & RTC_UIP);
101 secs2 = CMOS_READ(RTC_SECONDS);
102
103 ctrl = CMOS_READ(RTC_CONTROL);
104
105 local_irq_restore(flags);
106
107 if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
108 secs1 = bcd2bin(secs1);
109 secs2 = bcd2bin(secs2);
110 }
111 secs = secs2 - secs1;
112 if (secs < 1)
113 secs += 60;
114
115 count -= start;
116 count /= secs;
117 mips_hpt_frequency = count;
118
119 if (mips_gic_present()) {
120 giccount = div_u64(giccount - gicstart, secs);
121 gic_frequency = giccount;
122 }
123}
124
125void read_persistent_clock64(struct timespec64 *ts)
126{
127 ts->tv_sec = mc146818_get_cmos_time();
128 ts->tv_nsec = 0;
129}
130
131int get_c0_fdc_int(void)
132{
133 /*
134 * Some cores claim the FDC is routable through the GIC, but it doesn't
135 * actually seem to be connected for those Malta bitstreams.
136 */
137 switch (current_cpu_type()) {
138 case CPU_INTERAPTIV:
139 case CPU_PROAPTIV:
140 return -1;
141 };
142
143 if (cpu_has_veic)
144 return -1;
145 else if (mips_gic_present())
146 return gic_get_c0_fdc_int();
147 else if (cp0_fdc_irq >= 0)
148 return MIPS_CPU_IRQ_BASE + cp0_fdc_irq;
149 else
150 return -1;
151}
152
153int get_c0_perfcount_int(void)
154{
155 if (cpu_has_veic) {
156 set_vi_handler(MSC01E_INT_PERFCTR, mips_perf_dispatch);
157 mips_cpu_perf_irq = MSC01E_INT_BASE + MSC01E_INT_PERFCTR;
158 } else if (mips_gic_present()) {
159 mips_cpu_perf_irq = gic_get_c0_perfcount_int();
160 } else if (cp0_perfcount_irq >= 0) {
161 mips_cpu_perf_irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq;
162 } else {
163 mips_cpu_perf_irq = -1;
164 }
165
166 return mips_cpu_perf_irq;
167}
168EXPORT_SYMBOL_GPL(get_c0_perfcount_int);
169
170unsigned int get_c0_compare_int(void)
171{
172 if (cpu_has_veic) {
173 set_vi_handler(MSC01E_INT_CPUCTR, mips_timer_dispatch);
174 mips_cpu_timer_irq = MSC01E_INT_BASE + MSC01E_INT_CPUCTR;
175 } else if (mips_gic_present()) {
176 mips_cpu_timer_irq = gic_get_c0_compare_int();
177 } else {
178 mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq;
179 }
180
181 return mips_cpu_timer_irq;
182}
183
184static void __init init_rtc(void)
185{
186 unsigned char freq, ctrl;
187
188 /* Set 32KHz time base if not already set */
189 freq = CMOS_READ(RTC_FREQ_SELECT);
190 if ((freq & RTC_DIV_CTL) != RTC_REF_CLCK_32KHZ)
191 CMOS_WRITE(RTC_REF_CLCK_32KHZ, RTC_FREQ_SELECT);
192
193 /* Ensure SET bit is clear so RTC can run */
194 ctrl = CMOS_READ(RTC_CONTROL);
195 if (ctrl & RTC_SET)
196 CMOS_WRITE(ctrl & ~RTC_SET, RTC_CONTROL);
197}
198
199#ifdef CONFIG_CLKSRC_MIPS_GIC
200static u32 gic_frequency_dt;
201
202static struct property gic_frequency_prop = {
203 .name = "clock-frequency",
204 .length = sizeof(u32),
205 .value = &gic_frequency_dt,
206};
207
208static void update_gic_frequency_dt(void)
209{
210 struct device_node *node;
211
212 gic_frequency_dt = cpu_to_be32(gic_frequency);
213
214 node = of_find_compatible_node(NULL, NULL, "mti,gic-timer");
215 if (!node) {
216 pr_err("mti,gic-timer device node not found\n");
217 return;
218 }
219
220 if (of_update_property(node, &gic_frequency_prop) < 0)
221 pr_err("error updating gic frequency property\n");
222}
223
224#endif
225
226void __init plat_time_init(void)
227{
228 unsigned int prid = read_c0_prid() & (PRID_COMP_MASK | PRID_IMP_MASK);
229 unsigned int freq;
230
231 init_rtc();
232 estimate_frequencies();
233
234 freq = mips_hpt_frequency;
235 if ((prid != (PRID_COMP_MIPS | PRID_IMP_20KC)) &&
236 (prid != (PRID_COMP_MIPS | PRID_IMP_25KF)))
237 freq *= 2;
238 freq = freqround(freq, 5000);
239 printk("CPU frequency %d.%02d MHz\n", freq/1000000,
240 (freq%1000000)*100/1000000);
241
242#ifdef CONFIG_I8253
243 /* Only Malta has a PIT. */
244 setup_pit_timer();
245#endif
246
247 if (mips_gic_present()) {
248 freq = freqround(gic_frequency, 5000);
249 printk("GIC frequency %d.%02d MHz\n", freq/1000000,
250 (freq%1000000)*100/1000000);
251#ifdef CONFIG_CLKSRC_MIPS_GIC
252 update_gic_frequency_dt();
253 timer_probe();
254#endif
255 }
256}