Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Lauri Kasanen and committed by
Thomas Bogendoerfer
baec970a 65ce6197

+223
+1
arch/mips/Kbuild.platforms
··· 18 18 platform-$(CONFIG_MACH_LOONGSON32) += loongson32/ 19 19 platform-$(CONFIG_MACH_LOONGSON64) += loongson64/ 20 20 platform-$(CONFIG_MIPS_MALTA) += mti-malta/ 21 + platform-$(CONFIG_MACH_NINTENDO64) += n64/ 21 22 platform-$(CONFIG_NLM_COMMON) += netlogic/ 22 23 platform-$(CONFIG_PIC32MZDA) += pic32/ 23 24 platform-$(CONFIG_MACH_PISTACHIO) += pistachio/
+12
arch/mips/Kconfig
··· 607 607 select SYS_SUPPORTS_MIPS16 608 608 select GPIOLIB 609 609 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 + 610 622 config RALINK 611 623 bool "Ralink based machines" 612 624 select CEVT_R4K
+9
arch/mips/include/asm/mach-n64/irq.h
··· 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 */
+8
arch/mips/include/asm/mach-n64/kmalloc.h
··· 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 */
+6
arch/mips/n64/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + # 3 + # Nintendo 64 4 + # 5 + 6 + obj-y := init.o irq.o
+7
arch/mips/n64/Platform
··· 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
+164
arch/mips/n64/init.c
··· 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 + }
+16
arch/mips/n64/irq.c
··· 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 + }