Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  *  Nintendo 64 init.
0004  *
0005  *  Copyright (C) 2021  Lauri Kasanen
0006  */
0007 #include <linux/init.h>
0008 #include <linux/ioport.h>
0009 #include <linux/irq.h>
0010 #include <linux/memblock.h>
0011 #include <linux/platform_device.h>
0012 #include <linux/platform_data/simplefb.h>
0013 #include <linux/string.h>
0014 
0015 #include <asm/bootinfo.h>
0016 #include <asm/fw/fw.h>
0017 #include <asm/time.h>
0018 
0019 #define IO_MEM_RESOURCE_START   0UL
0020 #define IO_MEM_RESOURCE_END 0x1fffffffUL
0021 
0022 /*
0023  * System-specifc irq names for clarity
0024  */
0025 #define MIPS_CPU_IRQ(x)     (MIPS_CPU_IRQ_BASE + (x))
0026 #define MIPS_SOFTINT0_IRQ   MIPS_CPU_IRQ(0)
0027 #define MIPS_SOFTINT1_IRQ   MIPS_CPU_IRQ(1)
0028 #define RCP_IRQ         MIPS_CPU_IRQ(2)
0029 #define CART_IRQ        MIPS_CPU_IRQ(3)
0030 #define PRENMI_IRQ      MIPS_CPU_IRQ(4)
0031 #define RDBR_IRQ        MIPS_CPU_IRQ(5)
0032 #define RDBW_IRQ        MIPS_CPU_IRQ(6)
0033 #define TIMER_IRQ       MIPS_CPU_IRQ(7)
0034 
0035 static void __init iomem_resource_init(void)
0036 {
0037     iomem_resource.start = IO_MEM_RESOURCE_START;
0038     iomem_resource.end = IO_MEM_RESOURCE_END;
0039 }
0040 
0041 const char *get_system_type(void)
0042 {
0043     return "Nintendo 64";
0044 }
0045 
0046 void __init prom_init(void)
0047 {
0048     fw_init_cmdline();
0049 }
0050 
0051 #define W 320
0052 #define H 240
0053 #define REG_BASE ((u32 *) CKSEG1ADDR(0x4400000))
0054 
0055 static void __init n64rdp_write_reg(const u8 reg, const u32 value)
0056 {
0057     __raw_writel(value, REG_BASE + reg);
0058 }
0059 
0060 #undef REG_BASE
0061 
0062 static const u32 ntsc_320[] __initconst = {
0063     0x00013212, 0x00000000, 0x00000140, 0x00000200,
0064     0x00000000, 0x03e52239, 0x0000020d, 0x00000c15,
0065     0x0c150c15, 0x006c02ec, 0x002501ff, 0x000e0204,
0066     0x00000200, 0x00000400
0067 };
0068 
0069 #define MI_REG_BASE 0x4300000
0070 #define NUM_MI_REGS 4
0071 #define AI_REG_BASE 0x4500000
0072 #define NUM_AI_REGS 6
0073 #define PI_REG_BASE 0x4600000
0074 #define NUM_PI_REGS 5
0075 #define SI_REG_BASE 0x4800000
0076 #define NUM_SI_REGS 7
0077 
0078 static int __init n64_platform_init(void)
0079 {
0080     static const char simplefb_resname[] = "FB";
0081     static const struct simplefb_platform_data mode = {
0082         .width = W,
0083         .height = H,
0084         .stride = W * 2,
0085         .format = "r5g5b5a1"
0086     };
0087     struct resource res[3];
0088     void *orig;
0089     unsigned long phys;
0090     unsigned i;
0091 
0092     memset(res, 0, sizeof(struct resource) * 3);
0093     res[0].flags = IORESOURCE_MEM;
0094     res[0].start = MI_REG_BASE;
0095     res[0].end = MI_REG_BASE + NUM_MI_REGS * 4 - 1;
0096 
0097     res[1].flags = IORESOURCE_MEM;
0098     res[1].start = AI_REG_BASE;
0099     res[1].end = AI_REG_BASE + NUM_AI_REGS * 4 - 1;
0100 
0101     res[2].flags = IORESOURCE_IRQ;
0102     res[2].start = RCP_IRQ;
0103     res[2].end = RCP_IRQ;
0104 
0105     platform_device_register_simple("n64audio", -1, res, 3);
0106 
0107     memset(&res[0], 0, sizeof(res[0]));
0108     res[0].flags = IORESOURCE_MEM;
0109     res[0].start = PI_REG_BASE;
0110     res[0].end = PI_REG_BASE + NUM_PI_REGS * 4 - 1;
0111 
0112     platform_device_register_simple("n64cart", -1, res, 1);
0113 
0114     memset(&res[0], 0, sizeof(res[0]));
0115     res[0].flags = IORESOURCE_MEM;
0116     res[0].start = SI_REG_BASE;
0117     res[0].end = SI_REG_BASE + NUM_SI_REGS * 4 - 1;
0118 
0119     platform_device_register_simple("n64joy", -1, res, 1);
0120 
0121     /* The framebuffer needs 64-byte alignment */
0122     orig = kzalloc(W * H * 2 + 63, GFP_DMA | GFP_KERNEL);
0123     if (!orig)
0124         return -ENOMEM;
0125     phys = virt_to_phys(orig);
0126     phys += 63;
0127     phys &= ~63;
0128 
0129     for (i = 0; i < ARRAY_SIZE(ntsc_320); i++) {
0130         if (i == 1)
0131             n64rdp_write_reg(i, phys);
0132         else
0133             n64rdp_write_reg(i, ntsc_320[i]);
0134     }
0135 
0136     /* setup IORESOURCE_MEM as framebuffer memory */
0137     memset(&res[0], 0, sizeof(res[0]));
0138     res[0].flags = IORESOURCE_MEM;
0139     res[0].name = simplefb_resname;
0140     res[0].start = phys;
0141     res[0].end = phys + W * H * 2 - 1;
0142 
0143     platform_device_register_resndata(NULL, "simple-framebuffer", 0,
0144                       &res[0], 1, &mode, sizeof(mode));
0145 
0146     return 0;
0147 }
0148 
0149 #undef W
0150 #undef H
0151 
0152 arch_initcall(n64_platform_init);
0153 
0154 void __init plat_mem_setup(void)
0155 {
0156     iomem_resource_init();
0157     memblock_add(0x0, 8 * 1024 * 1024); /* Bootloader blocks the 4mb config */
0158 }
0159 
0160 void __init plat_time_init(void)
0161 {
0162     /* 93.75 MHz cpu, count register runs at half rate */
0163     mips_hpt_frequency = 93750000 / 2;
0164 }