Skip to content

Commit baec970

Browse files
clbrtsbogend
authored andcommitted
mips: Add N64 machine type
Add support for the Nintendo 64. Signed-off-by: Lauri Kasanen <cand@gmx.com> Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
1 parent 65ce619 commit baec970

File tree

8 files changed

+223
-0
lines changed

8 files changed

+223
-0
lines changed

arch/mips/Kbuild.platforms

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ platform-$(CONFIG_MACH_LOONGSON2EF) += loongson2ef/
1818
platform-$(CONFIG_MACH_LOONGSON32) += loongson32/
1919
platform-$(CONFIG_MACH_LOONGSON64) += loongson64/
2020
platform-$(CONFIG_MIPS_MALTA) += mti-malta/
21+
platform-$(CONFIG_MACH_NINTENDO64) += n64/
2122
platform-$(CONFIG_NLM_COMMON) += netlogic/
2223
platform-$(CONFIG_PIC32MZDA) += pic32/
2324
platform-$(CONFIG_MACH_PISTACHIO) += pistachio/

arch/mips/Kconfig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,18 @@ config MACH_VR41XX
607607
select SYS_SUPPORTS_MIPS16
608608
select GPIOLIB
609609

610+
config MACH_NINTENDO64
611+
bool "Nintendo 64 console"
612+
select CEVT_R4K
613+
select CSRC_R4K
614+
select SYS_HAS_CPU_R4300
615+
select SYS_SUPPORTS_BIG_ENDIAN
616+
select SYS_SUPPORTS_ZBOOT
617+
select SYS_SUPPORTS_32BIT_KERNEL
618+
select SYS_SUPPORTS_64BIT_KERNEL
619+
select DMA_NONCOHERENT
620+
select IRQ_MIPS_CPU
621+
610622
config RALINK
611623
bool "Ralink based machines"
612624
select CEVT_R4K
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
#ifndef __ASM_MACH_N64_IRQ_H
3+
#define __ASM_MACH_N64_IRQ_H
4+
5+
#define NR_IRQS 8
6+
7+
#include <asm/mach-generic/irq.h>
8+
9+
#endif /* __ASM_MACH_N64_IRQ_H */
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
#ifndef __ASM_MACH_N64_KMALLOC_H
3+
#define __ASM_MACH_N64_KMALLOC_H
4+
5+
/* The default of 128 bytes wastes too much, use 32 (the largest cacheline, I) */
6+
#define ARCH_DMA_MINALIGN L1_CACHE_BYTES
7+
8+
#endif /* __ASM_MACH_N64_KMALLOC_H */

arch/mips/n64/Makefile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# SPDX-License-Identifier: GPL-2.0
2+
#
3+
# Nintendo 64
4+
#
5+
6+
obj-y := init.o irq.o

arch/mips/n64/Platform

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# SPDX-License-Identifier: GPL-2.0
2+
#
3+
# Nintendo 64
4+
#
5+
6+
cflags-$(CONFIG_MACH_NINTENDO64) += -I$(srctree)/arch/mips/include/asm/mach-n64
7+
load-$(CONFIG_MACH_NINTENDO64) += 0xffffffff80101000

arch/mips/n64/init.c

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* Nintendo 64 init.
4+
*
5+
* Copyright (C) 2021 Lauri Kasanen
6+
*/
7+
#include <linux/init.h>
8+
#include <linux/ioport.h>
9+
#include <linux/irq.h>
10+
#include <linux/memblock.h>
11+
#include <linux/platform_device.h>
12+
#include <linux/platform_data/simplefb.h>
13+
#include <linux/string.h>
14+
15+
#include <asm/bootinfo.h>
16+
#include <asm/fw/fw.h>
17+
#include <asm/time.h>
18+
19+
#define IO_MEM_RESOURCE_START 0UL
20+
#define IO_MEM_RESOURCE_END 0x1fffffffUL
21+
22+
/*
23+
* System-specifc irq names for clarity
24+
*/
25+
#define MIPS_CPU_IRQ(x) (MIPS_CPU_IRQ_BASE + (x))
26+
#define MIPS_SOFTINT0_IRQ MIPS_CPU_IRQ(0)
27+
#define MIPS_SOFTINT1_IRQ MIPS_CPU_IRQ(1)
28+
#define RCP_IRQ MIPS_CPU_IRQ(2)
29+
#define CART_IRQ MIPS_CPU_IRQ(3)
30+
#define PRENMI_IRQ MIPS_CPU_IRQ(4)
31+
#define RDBR_IRQ MIPS_CPU_IRQ(5)
32+
#define RDBW_IRQ MIPS_CPU_IRQ(6)
33+
#define TIMER_IRQ MIPS_CPU_IRQ(7)
34+
35+
static void __init iomem_resource_init(void)
36+
{
37+
iomem_resource.start = IO_MEM_RESOURCE_START;
38+
iomem_resource.end = IO_MEM_RESOURCE_END;
39+
}
40+
41+
const char *get_system_type(void)
42+
{
43+
return "Nintendo 64";
44+
}
45+
46+
void __init prom_init(void)
47+
{
48+
fw_init_cmdline();
49+
}
50+
51+
#define W 320
52+
#define H 240
53+
#define REG_BASE ((u32 *) CKSEG1ADDR(0x4400000))
54+
55+
static void __init n64rdp_write_reg(const u8 reg, const u32 value)
56+
{
57+
__raw_writel(value, REG_BASE + reg);
58+
}
59+
60+
#undef REG_BASE
61+
62+
static const u32 ntsc_320[] __initconst = {
63+
0x00013212, 0x00000000, 0x00000140, 0x00000200,
64+
0x00000000, 0x03e52239, 0x0000020d, 0x00000c15,
65+
0x0c150c15, 0x006c02ec, 0x002501ff, 0x000e0204,
66+
0x00000200, 0x00000400
67+
};
68+
69+
#define MI_REG_BASE 0x4300000
70+
#define NUM_MI_REGS 4
71+
#define AI_REG_BASE 0x4500000
72+
#define NUM_AI_REGS 6
73+
#define PI_REG_BASE 0x4600000
74+
#define NUM_PI_REGS 5
75+
#define SI_REG_BASE 0x4800000
76+
#define NUM_SI_REGS 7
77+
78+
static int __init n64_platform_init(void)
79+
{
80+
static const char simplefb_resname[] = "FB";
81+
static const struct simplefb_platform_data mode = {
82+
.width = W,
83+
.height = H,
84+
.stride = W * 2,
85+
.format = "r5g5b5a1"
86+
};
87+
struct resource res[3];
88+
void *orig;
89+
unsigned long phys;
90+
unsigned i;
91+
92+
memset(res, 0, sizeof(struct resource) * 3);
93+
res[0].flags = IORESOURCE_MEM;
94+
res[0].start = MI_REG_BASE;
95+
res[0].end = MI_REG_BASE + NUM_MI_REGS * 4 - 1;
96+
97+
res[1].flags = IORESOURCE_MEM;
98+
res[1].start = AI_REG_BASE;
99+
res[1].end = AI_REG_BASE + NUM_AI_REGS * 4 - 1;
100+
101+
res[2].flags = IORESOURCE_IRQ;
102+
res[2].start = RCP_IRQ;
103+
res[2].end = RCP_IRQ;
104+
105+
platform_device_register_simple("n64audio", -1, res, 3);
106+
107+
memset(&res[0], 0, sizeof(res[0]));
108+
res[0].flags = IORESOURCE_MEM;
109+
res[0].start = PI_REG_BASE;
110+
res[0].end = PI_REG_BASE + NUM_PI_REGS * 4 - 1;
111+
112+
platform_device_register_simple("n64cart", -1, res, 1);
113+
114+
memset(&res[0], 0, sizeof(res[0]));
115+
res[0].flags = IORESOURCE_MEM;
116+
res[0].start = SI_REG_BASE;
117+
res[0].end = SI_REG_BASE + NUM_SI_REGS * 4 - 1;
118+
119+
platform_device_register_simple("n64joy", -1, res, 1);
120+
121+
/* The framebuffer needs 64-byte alignment */
122+
orig = kzalloc(W * H * 2 + 63, GFP_DMA | GFP_KERNEL);
123+
if (!orig)
124+
return -ENOMEM;
125+
phys = virt_to_phys(orig);
126+
phys += 63;
127+
phys &= ~63;
128+
129+
for (i = 0; i < ARRAY_SIZE(ntsc_320); i++) {
130+
if (i == 1)
131+
n64rdp_write_reg(i, phys);
132+
else
133+
n64rdp_write_reg(i, ntsc_320[i]);
134+
}
135+
136+
/* setup IORESOURCE_MEM as framebuffer memory */
137+
memset(&res[0], 0, sizeof(res[0]));
138+
res[0].flags = IORESOURCE_MEM;
139+
res[0].name = simplefb_resname;
140+
res[0].start = phys;
141+
res[0].end = phys + W * H * 2 - 1;
142+
143+
platform_device_register_resndata(NULL, "simple-framebuffer", 0,
144+
&res[0], 1, &mode, sizeof(mode));
145+
146+
return 0;
147+
}
148+
149+
#undef W
150+
#undef H
151+
152+
arch_initcall(n64_platform_init);
153+
154+
void __init plat_mem_setup(void)
155+
{
156+
iomem_resource_init();
157+
memblock_add(0x0, 8 * 1024 * 1024); /* Bootloader blocks the 4mb config */
158+
}
159+
160+
void __init plat_time_init(void)
161+
{
162+
/* 93.75 MHz cpu, count register runs at half rate */
163+
mips_hpt_frequency = 93750000 / 2;
164+
}

arch/mips/n64/irq.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* N64 IRQ
4+
*
5+
* Copyright (C) 2021 Lauri Kasanen
6+
*/
7+
#include <linux/export.h>
8+
#include <linux/interrupt.h>
9+
#include <linux/irq.h>
10+
11+
#include <asm/irq_cpu.h>
12+
13+
void __init arch_init_irq(void)
14+
{
15+
mips_cpu_irq_init();
16+
}

0 commit comments

Comments
 (0)