1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * arch/powerpc/boot/wii.c 4 * 5 * Nintendo Wii bootwrapper support 6 * Copyright (C) 2008-2009 The GameCube Linux Team 7 * Copyright (C) 2008,2009 Albert Herranz 8 */ 9 10 #include <stddef.h> 11 #include "stdio.h" 12 #include "types.h" 13 #include "io.h" 14 #include "ops.h" 15 16 #include "ugecon.h" 17 18 BSS_STACK(8192); 19 20 #define HW_REG(x) ((void *)(x)) 21 22 #define EXI_CTRL HW_REG(0x0d800070) 23 #define EXI_CTRL_ENABLE (1<<0) 24 25 #define MEM2_TOP (0x10000000 + 64*1024*1024) 26 #define FIRMWARE_DEFAULT_SIZE (12*1024*1024) 27 28 29 struct mipc_infohdr { 30 char magic[3]; 31 u8 version; 32 u32 mem2_boundary; 33 u32 ipc_in; 34 size_t ipc_in_size; 35 u32 ipc_out; 36 size_t ipc_out_size; 37 }; 38 39 static int mipc_check_address(u32 pa) 40 { 41 /* only MEM2 addresses */ 42 if (pa < 0x10000000 || pa > 0x14000000) 43 return -EINVAL; 44 return 0; 45 } 46 47 static struct mipc_infohdr *mipc_get_infohdr(void) 48 { 49 struct mipc_infohdr **hdrp, *hdr; 50 51 /* 'mini' header pointer is the last word of MEM2 memory */ 52 hdrp = (struct mipc_infohdr **)0x13fffffc; 53 if (mipc_check_address((u32)hdrp)) { 54 printf("mini: invalid hdrp %08X\n", (u32)hdrp); 55 hdr = NULL; 56 goto out; 57 } 58 59 hdr = *hdrp; 60 if (mipc_check_address((u32)hdr)) { 61 printf("mini: invalid hdr %08X\n", (u32)hdr); 62 hdr = NULL; 63 goto out; 64 } 65 if (memcmp(hdr->magic, "IPC", 3)) { 66 printf("mini: invalid magic\n"); 67 hdr = NULL; 68 goto out; 69 } 70 71 out: 72 return hdr; 73 } 74 75 static int mipc_get_mem2_boundary(u32 *mem2_boundary) 76 { 77 struct mipc_infohdr *hdr; 78 int error; 79 80 hdr = mipc_get_infohdr(); 81 if (!hdr) { 82 error = -1; 83 goto out; 84 } 85 86 if (mipc_check_address(hdr->mem2_boundary)) { 87 printf("mini: invalid mem2_boundary %08X\n", 88 hdr->mem2_boundary); 89 error = -EINVAL; 90 goto out; 91 } 92 *mem2_boundary = hdr->mem2_boundary; 93 error = 0; 94 out: 95 return error; 96 97 } 98 99 static void platform_fixups(void) 100 { 101 void *mem; 102 u32 reg[4]; 103 u32 mem2_boundary; 104 int len; 105 int error; 106 107 mem = finddevice("/memory"); 108 if (!mem) 109 fatal("Can't find memory node\n"); 110 111 /* two ranges of (address, size) words */ 112 len = getprop(mem, "reg", reg, sizeof(reg)); 113 if (len != sizeof(reg)) { 114 /* nothing to do */ 115 goto out; 116 } 117 118 /* retrieve MEM2 boundary from 'mini' */ 119 error = mipc_get_mem2_boundary(&mem2_boundary); 120 if (error) { 121 /* if that fails use a sane value */ 122 mem2_boundary = MEM2_TOP - FIRMWARE_DEFAULT_SIZE; 123 } 124 125 if (mem2_boundary > reg[2] && mem2_boundary < reg[2] + reg[3]) { 126 reg[3] = mem2_boundary - reg[2]; 127 printf("top of MEM2 @ %08X\n", reg[2] + reg[3]); 128 setprop(mem, "reg", reg, sizeof(reg)); 129 } 130 131 out: 132 return; 133 } 134 135 void platform_init(unsigned long r3, unsigned long r4, unsigned long r5) 136 { 137 u32 heapsize = 24*1024*1024 - (u32)_end; 138 139 simple_alloc_init(_end, heapsize, 32, 64); 140 fdt_init(_dtb_start); 141 142 /* 143 * 'mini' boots the Broadway processor with EXI disabled. 144 * We need it enabled before probing for the USB Gecko. 145 */ 146 out_be32(EXI_CTRL, in_be32(EXI_CTRL) | EXI_CTRL_ENABLE); 147 148 if (ug_probe()) 149 console_ops.write = ug_console_write; 150 151 platform_ops.fixups = platform_fixups; 152 } 153 154