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