Merge branch 'next' of git://git.secretlab.ca/git/linux-2.6

* 'next' of git://git.secretlab.ca/git/linux-2.6: (23 commits)
  powerpc: fix up for mmu_mapin_ram api change
  powerpc: wii: allow ioremap within the memory hole
  powerpc: allow ioremap within reserved memory regions
  wii: use both mem1 and mem2 as ram
  wii: bootwrapper: add fixup to calc useable mem2
  powerpc: gamecube/wii: early debugging using usbgecko
  powerpc: reserve fixmap entries for early debug
  powerpc: wii: default config
  powerpc: wii: platform support
  powerpc: wii: hollywood interrupt controller support
  powerpc: broadway processor support
  powerpc: wii: bootwrapper bits
  powerpc: wii: device tree
  powerpc: gamecube: default config
  powerpc: gamecube: platform support
  powerpc: gamecube/wii: flipper interrupt controller support
  powerpc: gamecube/wii: udbg support for usbgecko
  powerpc: gamecube/wii: do not include PCI support
  powerpc: gamecube/wii: declare as non-coherent platforms
  powerpc: gamecube/wii: introduce GAMECUBE_COMMON
  ...

Fix up conflicts in arch/powerpc/mm/fsl_booke_mmu.c.

Hopefully even close to correctly.
This commit is contained in:
Linus Torvalds 2009-12-16 13:26:53 -08:00
commit a73611b6aa
41 changed files with 5161 additions and 22 deletions

View File

@ -0,0 +1,109 @@
Nintendo GameCube device tree
=============================
1) The "flipper" node
This node represents the multi-function "Flipper" chip, which packages
many of the devices found in the Nintendo GameCube.
Required properties:
- compatible : Should be "nintendo,flipper"
1.a) The Video Interface (VI) node
Represents the interface between the graphics processor and a external
video encoder.
Required properties:
- compatible : should be "nintendo,flipper-vi"
- reg : should contain the VI registers location and length
- interrupts : should contain the VI interrupt
1.b) The Processor Interface (PI) node
Represents the data and control interface between the main processor
and graphics and audio processor.
Required properties:
- compatible : should be "nintendo,flipper-pi"
- reg : should contain the PI registers location and length
1.b.i) The "Flipper" interrupt controller node
Represents the interrupt controller within the "Flipper" chip.
The node for the "Flipper" interrupt controller must be placed under
the PI node.
Required properties:
- compatible : should be "nintendo,flipper-pic"
1.c) The Digital Signal Procesor (DSP) node
Represents the digital signal processor interface, designed to offload
audio related tasks.
Required properties:
- compatible : should be "nintendo,flipper-dsp"
- reg : should contain the DSP registers location and length
- interrupts : should contain the DSP interrupt
1.c.i) The Auxiliary RAM (ARAM) node
Represents the non cpu-addressable ram designed mainly to store audio
related information.
The ARAM node must be placed under the DSP node.
Required properties:
- compatible : should be "nintendo,flipper-aram"
- reg : should contain the ARAM start (zero-based) and length
1.d) The Disk Interface (DI) node
Represents the interface used to communicate with mass storage devices.
Required properties:
- compatible : should be "nintendo,flipper-di"
- reg : should contain the DI registers location and length
- interrupts : should contain the DI interrupt
1.e) The Audio Interface (AI) node
Represents the interface to the external 16-bit stereo digital-to-analog
converter.
Required properties:
- compatible : should be "nintendo,flipper-ai"
- reg : should contain the AI registers location and length
- interrupts : should contain the AI interrupt
1.f) The Serial Interface (SI) node
Represents the interface to the four single bit serial interfaces.
The SI is a proprietary serial interface used normally to control gamepads.
It's NOT a RS232-type interface.
Required properties:
- compatible : should be "nintendo,flipper-si"
- reg : should contain the SI registers location and length
- interrupts : should contain the SI interrupt
1.g) The External Interface (EXI) node
Represents the multi-channel SPI-like interface.
Required properties:
- compatible : should be "nintendo,flipper-exi"
- reg : should contain the EXI registers location and length
- interrupts : should contain the EXI interrupt

View File

@ -0,0 +1,184 @@
Nintendo Wii device tree
========================
0) The root node
This node represents the Nintendo Wii video game console.
Required properties:
- model : Should be "nintendo,wii"
- compatible : Should be "nintendo,wii"
1) The "hollywood" node
This node represents the multi-function "Hollywood" chip, which packages
many of the devices found in the Nintendo Wii.
Required properties:
- compatible : Should be "nintendo,hollywood"
1.a) The Video Interface (VI) node
Represents the interface between the graphics processor and a external
video encoder.
Required properties:
- compatible : should be "nintendo,hollywood-vi","nintendo,flipper-vi"
- reg : should contain the VI registers location and length
- interrupts : should contain the VI interrupt
1.b) The Processor Interface (PI) node
Represents the data and control interface between the main processor
and graphics and audio processor.
Required properties:
- compatible : should be "nintendo,hollywood-pi","nintendo,flipper-pi"
- reg : should contain the PI registers location and length
1.b.i) The "Flipper" interrupt controller node
Represents the "Flipper" interrupt controller within the "Hollywood" chip.
The node for the "Flipper" interrupt controller must be placed under
the PI node.
Required properties:
- #interrupt-cells : <1>
- compatible : should be "nintendo,flipper-pic"
- interrupt-controller
1.c) The Digital Signal Procesor (DSP) node
Represents the digital signal processor interface, designed to offload
audio related tasks.
Required properties:
- compatible : should be "nintendo,hollywood-dsp","nintendo,flipper-dsp"
- reg : should contain the DSP registers location and length
- interrupts : should contain the DSP interrupt
1.d) The Serial Interface (SI) node
Represents the interface to the four single bit serial interfaces.
The SI is a proprietary serial interface used normally to control gamepads.
It's NOT a RS232-type interface.
Required properties:
- compatible : should be "nintendo,hollywood-si","nintendo,flipper-si"
- reg : should contain the SI registers location and length
- interrupts : should contain the SI interrupt
1.e) The Audio Interface (AI) node
Represents the interface to the external 16-bit stereo digital-to-analog
converter.
Required properties:
- compatible : should be "nintendo,hollywood-ai","nintendo,flipper-ai"
- reg : should contain the AI registers location and length
- interrupts : should contain the AI interrupt
1.f) The External Interface (EXI) node
Represents the multi-channel SPI-like interface.
Required properties:
- compatible : should be "nintendo,hollywood-exi","nintendo,flipper-exi"
- reg : should contain the EXI registers location and length
- interrupts : should contain the EXI interrupt
1.g) The Open Host Controller Interface (OHCI) nodes
Represent the USB 1.x Open Host Controller Interfaces.
Required properties:
- compatible : should be "nintendo,hollywood-usb-ohci","usb-ohci"
- reg : should contain the OHCI registers location and length
- interrupts : should contain the OHCI interrupt
1.h) The Enhanced Host Controller Interface (EHCI) node
Represents the USB 2.0 Enhanced Host Controller Interface.
Required properties:
- compatible : should be "nintendo,hollywood-usb-ehci","usb-ehci"
- reg : should contain the EHCI registers location and length
- interrupts : should contain the EHCI interrupt
1.i) The Secure Digital Host Controller Interface (SDHCI) nodes
Represent the Secure Digital Host Controller Interfaces.
Required properties:
- compatible : should be "nintendo,hollywood-sdhci","sdhci"
- reg : should contain the SDHCI registers location and length
- interrupts : should contain the SDHCI interrupt
1.j) The Inter-Processsor Communication (IPC) node
Represent the Inter-Processor Communication interface. This interface
enables communications between the Broadway and the Starlet processors.
- compatible : should be "nintendo,hollywood-ipc"
- reg : should contain the IPC registers location and length
- interrupts : should contain the IPC interrupt
1.k) The "Hollywood" interrupt controller node
Represents the "Hollywood" interrupt controller within the
"Hollywood" chip.
Required properties:
- #interrupt-cells : <1>
- compatible : should be "nintendo,hollywood-pic"
- reg : should contain the controller registers location and length
- interrupt-controller
- interrupts : should contain the cascade interrupt of the "flipper" pic
- interrupt-parent: should contain the phandle of the "flipper" pic
1.l) The General Purpose I/O (GPIO) controller node
Represents the dual access 32 GPIO controller interface.
Required properties:
- #gpio-cells : <2>
- compatible : should be "nintendo,hollywood-gpio"
- reg : should contain the IPC registers location and length
- gpio-controller
1.m) The control node
Represents the control interface used to setup several miscellaneous
settings of the "Hollywood" chip like boot memory mappings, resets,
disk interface mode, etc.
Required properties:
- compatible : should be "nintendo,hollywood-control"
- reg : should contain the control registers location and length
1.n) The Disk Interface (DI) node
Represents the interface used to communicate with mass storage devices.
Required properties:
- compatible : should be "nintendo,hollywood-di"
- reg : should contain the DI registers location and length
- interrupts : should contain the DI interrupt

View File

@ -704,7 +704,7 @@ config PPC_PCI_CHOICE
config PCI
bool "PCI support" if PPC_PCI_CHOICE
default y if !40x && !CPM2 && !8xx && !PPC_83xx \
&& !PPC_85xx && !PPC_86xx
&& !PPC_85xx && !PPC_86xx && !GAMECUBE_COMMON
default PCI_PERMEDIA if !4xx && !CPM2 && !8xx
default PCI_QSPAN if !4xx && !CPM2 && 8xx
select ARCH_SUPPORTS_MSI

View File

@ -254,6 +254,14 @@ config PPC_EARLY_DEBUG_CPM
using a CPM-based serial port. This assumes that the bootwrapper
has run, and set up the CPM in a particular way.
config PPC_EARLY_DEBUG_USBGECKO
bool "Early debugging through the USB Gecko adapter"
depends on GAMECUBE_COMMON
select USBGECKO_UDBG
help
Select this to enable early debugging for Nintendo GameCube/Wii
consoles via an external USB Gecko adapter.
endchoice
config PPC_EARLY_DEBUG_44x_PHYSLOW

View File

@ -66,7 +66,7 @@ src-wlib := string.S crt0.S crtsavres.S stdio.c main.c \
gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \
4xx.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c bamboo.c \
cpm-serial.c stdlib.c mpc52xx-psc.c planetcore.c uartlite.c \
fsl-soc.c mpc8xx.c pq2.c
fsl-soc.c mpc8xx.c pq2.c ugecon.c
src-plat := of.c cuboot-52xx.c cuboot-824x.c cuboot-83xx.c cuboot-85xx.c holly.c \
cuboot-ebony.c cuboot-hotfoot.c treeboot-ebony.c prpmc2800.c \
ps3-head.S ps3-hvcall.S ps3.c treeboot-bamboo.c cuboot-8xx.c \
@ -76,7 +76,8 @@ src-plat := of.c cuboot-52xx.c cuboot-824x.c cuboot-83xx.c cuboot-85xx.c holly.c
cuboot-katmai.c cuboot-rainier.c redboot-8xx.c ep8248e.c \
cuboot-warp.c cuboot-85xx-cpm2.c cuboot-yosemite.c simpleboot.c \
virtex405-head.S virtex.c redboot-83xx.c cuboot-sam440ep.c \
cuboot-acadia.c cuboot-amigaone.c cuboot-kilauea.c
cuboot-acadia.c cuboot-amigaone.c cuboot-kilauea.c \
gamecube-head.S gamecube.c wii-head.S wii.c
src-boot := $(src-wlib) $(src-plat) empty.c
src-boot := $(addprefix $(obj)/, $(src-boot))
@ -254,6 +255,8 @@ image-$(CONFIG_KSI8560) += cuImage.ksi8560
image-$(CONFIG_STORCENTER) += cuImage.storcenter
image-$(CONFIG_MPC7448HPC2) += cuImage.mpc7448hpc2
image-$(CONFIG_PPC_C2K) += cuImage.c2k
image-$(CONFIG_GAMECUBE) += dtbImage.gamecube
image-$(CONFIG_WII) += dtbImage.wii
# Board port in arch/powerpc/platform/amigaone/Kconfig
image-$(CONFIG_AMIGAONE) += cuImage.amigaone

View File

@ -0,0 +1,114 @@
/*
* arch/powerpc/boot/dts/gamecube.dts
*
* Nintendo GameCube platform device tree source
* Copyright (C) 2007-2009 The GameCube Linux Team
* Copyright (C) 2007,2008,2009 Albert Herranz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
*/
/dts-v1/;
/ {
model = "nintendo,gamecube";
compatible = "nintendo,gamecube";
#address-cells = <1>;
#size-cells = <1>;
chosen {
bootargs = "root=/dev/gcnsda2 rootwait udbg-immortal";
};
memory {
device_type = "memory";
reg = <0x00000000 0x01800000>;
};
cpus {
#address-cells = <1>;
#size-cells = <0>;
PowerPC,gekko@0 {
device_type = "cpu";
reg = <0>;
clock-frequency = <486000000>; /* 486MHz */
bus-frequency = <162000000>; /* 162MHz core-to-bus 3x */
timebase-frequency = <40500000>; /* 162MHz / 4 */
i-cache-line-size = <32>;
d-cache-line-size = <32>;
i-cache-size = <32768>;
d-cache-size = <32768>;
};
};
/* devices contained int the flipper chipset */
flipper {
#address-cells = <1>;
#size-cells = <1>;
compatible = "nintendo,flipper";
ranges = <0x0c000000 0x0c000000 0x00010000>;
interrupt-parent = <&PIC>;
video@0c002000 {
compatible = "nintendo,flipper-vi";
reg = <0x0c002000 0x100>;
interrupts = <8>;
};
processor-interface@0c003000 {
compatible = "nintendo,flipper-pi";
reg = <0x0c003000 0x100>;
PIC: pic {
#interrupt-cells = <1>;
compatible = "nintendo,flipper-pic";
interrupt-controller;
};
};
dsp@0c005000 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "nintendo,flipper-dsp";
reg = <0x0c005000 0x200>;
interrupts = <6>;
memory@0 {
compatible = "nintendo,flipper-aram";
reg = <0 0x1000000>; /* 16MB */
};
};
disk@0c006000 {
compatible = "nintendo,flipper-di";
reg = <0x0c006000 0x40>;
interrupts = <2>;
};
audio@0c006c00 {
compatible = "nintendo,flipper-ai";
reg = <0x0c006c00 0x20>;
interrupts = <6>;
};
gamepad-controller@0c006400 {
compatible = "nintendo,flipper-si";
reg = <0x0c006400 0x100>;
interrupts = <3>;
};
/* External Interface bus */
exi@0c006800 {
compatible = "nintendo,flipper-exi";
reg = <0x0c006800 0x40>;
virtual-reg = <0x0c006800>;
interrupts = <4>;
};
};
};

View File

@ -0,0 +1,218 @@
/*
* arch/powerpc/boot/dts/wii.dts
*
* Nintendo Wii platform device tree source
* Copyright (C) 2008-2009 The GameCube Linux Team
* Copyright (C) 2008,2009 Albert Herranz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
*/
/dts-v1/;
/*
* This is commented-out for now.
* Until a later patch is merged, the kernel can use only the first
* contiguous RAM range and will BUG() if the memreserve is outside
* that range.
*/
/*/memreserve/ 0x10000000 0x0004000;*/ /* DSP RAM */
/ {
model = "nintendo,wii";
compatible = "nintendo,wii";
#address-cells = <1>;
#size-cells = <1>;
chosen {
bootargs = "root=/dev/mmcblk0p2 rootwait udbg-immortal";
};
memory {
device_type = "memory";
reg = <0x00000000 0x01800000 /* MEM1 24MB 1T-SRAM */
0x10000000 0x04000000>; /* MEM2 64MB GDDR3 */
};
cpus {
#address-cells = <1>;
#size-cells = <0>;
PowerPC,broadway@0 {
device_type = "cpu";
reg = <0>;
clock-frequency = <729000000>; /* 729MHz */
bus-frequency = <243000000>; /* 243MHz core-to-bus 3x */
timebase-frequency = <60750000>; /* 243MHz / 4 */
i-cache-line-size = <32>;
d-cache-line-size = <32>;
i-cache-size = <32768>;
d-cache-size = <32768>;
};
};
/* devices contained in the hollywood chipset */
hollywood {
#address-cells = <1>;
#size-cells = <1>;
compatible = "nintendo,hollywood";
ranges = <0x0c000000 0x0c000000 0x01000000
0x0d000000 0x0d000000 0x00800000
0x0d800000 0x0d800000 0x00800000>;
interrupt-parent = <&PIC0>;
video@0c002000 {
compatible = "nintendo,hollywood-vi",
"nintendo,flipper-vi";
reg = <0x0c002000 0x100>;
interrupts = <8>;
};
processor-interface@0c003000 {
compatible = "nintendo,hollywood-pi",
"nintendo,flipper-pi";
reg = <0x0c003000 0x100>;
PIC0: pic0 {
#interrupt-cells = <1>;
compatible = "nintendo,flipper-pic";
interrupt-controller;
};
};
dsp@0c005000 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "nintendo,hollywood-dsp",
"nintendo,flipper-dsp";
reg = <0x0c005000 0x200>;
interrupts = <6>;
};
gamepad-controller@0d006400 {
compatible = "nintendo,hollywood-si",
"nintendo,flipper-si";
reg = <0x0d006400 0x100>;
interrupts = <3>;
};
audio@0c006c00 {
compatible = "nintendo,hollywood-ai",
"nintendo,flipper-ai";
reg = <0x0d006c00 0x20>;
interrupts = <6>;
};
/* External Interface bus */
exi@0d006800 {
compatible = "nintendo,hollywood-exi",
"nintendo,flipper-exi";
reg = <0x0d006800 0x40>;
virtual-reg = <0x0d006800>;
interrupts = <4>;
};
usb@0d040000 {
compatible = "nintendo,hollywood-usb-ehci",
"usb-ehci";
reg = <0x0d040000 0x100>;
interrupts = <4>;
interrupt-parent = <&PIC1>;
};
usb@0d050000 {
compatible = "nintendo,hollywood-usb-ohci",
"usb-ohci";
reg = <0x0d050000 0x100>;
interrupts = <5>;
interrupt-parent = <&PIC1>;
};
usb@0d060000 {
compatible = "nintendo,hollywood-usb-ohci",
"usb-ohci";
reg = <0x0d060000 0x100>;
interrupts = <6>;
interrupt-parent = <&PIC1>;
};
sd@0d070000 {
compatible = "nintendo,hollywood-sdhci",
"sdhci";
reg = <0x0d070000 0x200>;
interrupts = <7>;
interrupt-parent = <&PIC1>;
};
sdio@0d080000 {
compatible = "nintendo,hollywood-sdhci",
"sdhci";
reg = <0x0d080000 0x200>;
interrupts = <8>;
interrupt-parent = <&PIC1>;
};
ipc@0d000000 {
compatible = "nintendo,hollywood-ipc";
reg = <0x0d000000 0x10>;
interrupts = <30>;
interrupt-parent = <&PIC1>;
};
PIC1: pic1@0d800030 {
#interrupt-cells = <1>;
compatible = "nintendo,hollywood-pic";
reg = <0x0d800030 0x10>;
interrupt-controller;
interrupts = <14>;
};
GPIO: gpio@0d8000c0 {
#gpio-cells = <2>;
compatible = "nintendo,hollywood-gpio";
reg = <0x0d8000c0 0x40>;
gpio-controller;
/*
* This is commented out while a standard binding
* for i2c over gpio is defined.
*/
/*
i2c-video {
#address-cells = <1>;
#size-cells = <0>;
compatible = "i2c-gpio";
gpios = <&GPIO 15 0
&GPIO 14 0>;
clock-frequency = <250000>;
no-clock-stretching;
scl-is-open-drain;
sda-is-open-drain;
sda-enforce-dir;
AVE: audio-video-encoder@70 {
compatible = "nintendo,wii-audio-video-encoder";
reg = <0x70>;
};
};
*/
};
control@0d800100 {
compatible = "nintendo,hollywood-control";
reg = <0x0d800100 0x300>;
};
disk@0d806000 {
compatible = "nintendo,hollywood-di";
reg = <0x0d806000 0x40>;
interrupts = <2>;
};
};
};

View File

@ -0,0 +1,111 @@
/*
* arch/powerpc/boot/gamecube-head.S
*
* Nintendo GameCube bootwrapper entry.
* Copyright (C) 2004-2009 The GameCube Linux Team
* Copyright (C) 2008,2009 Albert Herranz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
*/
#include "ppc_asm.h"
/*
* The entry code does no assumptions regarding:
* - if the data and instruction caches are enabled or not
* - if the MMU is enabled or not
*
* We enable the caches if not already enabled, enable the MMU with an
* identity mapping scheme and jump to the start code.
*/
.text
.globl _zimage_start
_zimage_start:
/* turn the MMU off */
mfmsr 9
rlwinm 9, 9, 0, ~((1<<4)|(1<<5)) /* MSR_DR|MSR_IR */
bcl 20, 31, 1f
1:
mflr 8
clrlwi 8, 8, 3 /* convert to a real address */
addi 8, 8, _mmu_off - 1b
mtsrr0 8
mtsrr1 9
rfi
_mmu_off:
/* MMU disabled */
/* setup BATs */
isync
li 8, 0
mtspr 0x210, 8 /* IBAT0U */
mtspr 0x212, 8 /* IBAT1U */
mtspr 0x214, 8 /* IBAT2U */
mtspr 0x216, 8 /* IBAT3U */
mtspr 0x218, 8 /* DBAT0U */
mtspr 0x21a, 8 /* DBAT1U */
mtspr 0x21c, 8 /* DBAT2U */
mtspr 0x21e, 8 /* DBAT3U */
li 8, 0x01ff /* first 16MiB */
li 9, 0x0002 /* rw */
mtspr 0x211, 9 /* IBAT0L */
mtspr 0x210, 8 /* IBAT0U */
mtspr 0x219, 9 /* DBAT0L */
mtspr 0x218, 8 /* DBAT0U */
lis 8, 0x0c00 /* I/O mem */
ori 8, 8, 0x3ff /* 32MiB */
lis 9, 0x0c00
ori 9, 9, 0x002a /* uncached, guarded, rw */
mtspr 0x21b, 9 /* DBAT1L */
mtspr 0x21a, 8 /* DBAT1U */
lis 8, 0x0100 /* next 8MiB */
ori 8, 8, 0x00ff /* 8MiB */
lis 9, 0x0100
ori 9, 9, 0x0002 /* rw */
mtspr 0x215, 9 /* IBAT2L */
mtspr 0x214, 8 /* IBAT2U */
mtspr 0x21d, 9 /* DBAT2L */
mtspr 0x21c, 8 /* DBAT2U */
/* enable and invalidate the caches if not already enabled */
mfspr 8, 0x3f0 /* HID0 */
andi. 0, 8, (1<<15) /* HID0_ICE */
bne 1f
ori 8, 8, (1<<15)|(1<<11) /* HID0_ICE|HID0_ICFI*/
1:
andi. 0, 8, (1<<14) /* HID0_DCE */
bne 1f
ori 8, 8, (1<<14)|(1<<10) /* HID0_DCE|HID0_DCFI*/
1:
mtspr 0x3f0, 8 /* HID0 */
isync
/* initialize arguments */
li 3, 0
li 4, 0
li 5, 0
/* turn the MMU on */
bcl 20, 31, 1f
1:
mflr 8
addi 8, 8, _mmu_on - 1b
mfmsr 9
ori 9, 9, (1<<4)|(1<<5) /* MSR_DR|MSR_IR */
mtsrr0 8
mtsrr1 9
sync
rfi
_mmu_on:
b _zimage_start_lib

View File

@ -0,0 +1,35 @@
/*
* arch/powerpc/boot/gamecube.c
*
* Nintendo GameCube bootwrapper support
* Copyright (C) 2004-2009 The GameCube Linux Team
* Copyright (C) 2008,2009 Albert Herranz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
*/
#include <stddef.h>
#include "stdio.h"
#include "types.h"
#include "io.h"
#include "ops.h"
#include "ugecon.h"
BSS_STACK(8192);
void platform_init(unsigned long r3, unsigned long r4, unsigned long r5)
{
u32 heapsize = 16*1024*1024 - (u32)_end;
simple_alloc_init(_end, heapsize, 32, 64);
fdt_init(_dtb_start);
if (ug_probe())
console_ops.write = ug_console_write;
}

147
arch/powerpc/boot/ugecon.c Normal file
View File

@ -0,0 +1,147 @@
/*
* arch/powerpc/boot/ugecon.c
*
* USB Gecko bootwrapper console.
* Copyright (C) 2008-2009 The GameCube Linux Team
* Copyright (C) 2008,2009 Albert Herranz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
*/
#include <stddef.h>
#include "stdio.h"
#include "types.h"
#include "io.h"
#include "ops.h"
#define EXI_CLK_32MHZ 5
#define EXI_CSR 0x00
#define EXI_CSR_CLKMASK (0x7<<4)
#define EXI_CSR_CLK_32MHZ (EXI_CLK_32MHZ<<4)
#define EXI_CSR_CSMASK (0x7<<7)
#define EXI_CSR_CS_0 (0x1<<7) /* Chip Select 001 */
#define EXI_CR 0x0c
#define EXI_CR_TSTART (1<<0)
#define EXI_CR_WRITE (1<<2)
#define EXI_CR_READ_WRITE (2<<2)
#define EXI_CR_TLEN(len) (((len)-1)<<4)
#define EXI_DATA 0x10
/* virtual address base for input/output, retrieved from device tree */
static void *ug_io_base;
static u32 ug_io_transaction(u32 in)
{
u32 *csr_reg = ug_io_base + EXI_CSR;
u32 *data_reg = ug_io_base + EXI_DATA;
u32 *cr_reg = ug_io_base + EXI_CR;
u32 csr, data, cr;
/* select */
csr = EXI_CSR_CLK_32MHZ | EXI_CSR_CS_0;
out_be32(csr_reg, csr);
/* read/write */
data = in;
out_be32(data_reg, data);
cr = EXI_CR_TLEN(2) | EXI_CR_READ_WRITE | EXI_CR_TSTART;
out_be32(cr_reg, cr);
while (in_be32(cr_reg) & EXI_CR_TSTART)
barrier();
/* deselect */
out_be32(csr_reg, 0);
data = in_be32(data_reg);
return data;
}
static int ug_is_txfifo_ready(void)
{
return ug_io_transaction(0xc0000000) & 0x04000000;
}
static void ug_raw_putc(char ch)
{
ug_io_transaction(0xb0000000 | (ch << 20));
}
static void ug_putc(char ch)
{
int count = 16;
if (!ug_io_base)
return;
while (!ug_is_txfifo_ready() && count--)
barrier();
if (count)
ug_raw_putc(ch);
}
void ug_console_write(const char *buf, int len)
{
char *b = (char *)buf;
while (len--) {
if (*b == '\n')
ug_putc('\r');
ug_putc(*b++);
}
}
static int ug_is_adapter_present(void)
{
if (!ug_io_base)
return 0;
return ug_io_transaction(0x90000000) == 0x04700000;
}
static void *ug_grab_exi_io_base(void)
{
u32 v;
void *devp;
devp = find_node_by_compatible(NULL, "nintendo,flipper-exi");
if (devp == NULL)
goto err_out;
if (getprop(devp, "virtual-reg", &v, sizeof(v)) != sizeof(v))
goto err_out;
return (void *)v;
err_out:
return NULL;
}
void *ug_probe(void)
{
void *exi_io_base;
int i;
exi_io_base = ug_grab_exi_io_base();
if (!exi_io_base)
return NULL;
/* look for a usbgecko on memcard slots A and B */
for (i = 0; i < 2; i++) {
ug_io_base = exi_io_base + 0x14 * i;
if (ug_is_adapter_present())
break;
}
if (i == 2)
ug_io_base = NULL;
return ug_io_base;
}

View File

@ -0,0 +1,24 @@
/*
* arch/powerpc/boot/ugecon.h
*
* USB Gecko early bootwrapper console.
* Copyright (C) 2008-2009 The GameCube Linux Team
* Copyright (C) 2008,2009 Albert Herranz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
*/
#ifndef __UGECON_H
#define __UGECON_H
extern void *ug_probe(void);
extern void ug_putc(char ch);
extern void ug_console_write(const char *buf, int len);
#endif /* __UGECON_H */

View File

@ -0,0 +1,142 @@
/*
* arch/powerpc/boot/wii-head.S
*
* Nintendo Wii bootwrapper entry.
* Copyright (C) 2008-2009 The GameCube Linux Team
* Copyright (C) 2008,2009 Albert Herranz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
*/
#include "ppc_asm.h"
/*
* The entry code does no assumptions regarding:
* - if the data and instruction caches are enabled or not
* - if the MMU is enabled or not
* - if the high BATs are enabled or not
*
* We enable the high BATs, enable the caches if not already enabled,
* enable the MMU with an identity mapping scheme and jump to the start code.
*/
.text
.globl _zimage_start
_zimage_start:
/* turn the MMU off */
mfmsr 9
rlwinm 9, 9, 0, ~((1<<4)|(1<<5)) /* MSR_DR|MSR_IR */
bcl 20, 31, 1f
1:
mflr 8
clrlwi 8, 8, 3 /* convert to a real address */
addi 8, 8, _mmu_off - 1b
mtsrr0 8
mtsrr1 9
rfi
_mmu_off:
/* MMU disabled */
/* setup BATs */
isync
li 8, 0
mtspr 0x210, 8 /* IBAT0U */
mtspr 0x212, 8 /* IBAT1U */
mtspr 0x214, 8 /* IBAT2U */
mtspr 0x216, 8 /* IBAT3U */
mtspr 0x218, 8 /* DBAT0U */
mtspr 0x21a, 8 /* DBAT1U */
mtspr 0x21c, 8 /* DBAT2U */
mtspr 0x21e, 8 /* DBAT3U */
mtspr 0x230, 8 /* IBAT4U */
mtspr 0x232, 8 /* IBAT5U */
mtspr 0x234, 8 /* IBAT6U */
mtspr 0x236, 8 /* IBAT7U */
mtspr 0x238, 8 /* DBAT4U */
mtspr 0x23a, 8 /* DBAT5U */
mtspr 0x23c, 8 /* DBAT6U */
mtspr 0x23e, 8 /* DBAT7U */
li 8, 0x01ff /* first 16MiB */
li 9, 0x0002 /* rw */
mtspr 0x211, 9 /* IBAT0L */
mtspr 0x210, 8 /* IBAT0U */
mtspr 0x219, 9 /* DBAT0L */
mtspr 0x218, 8 /* DBAT0U */
lis 8, 0x0c00 /* I/O mem */
ori 8, 8, 0x3ff /* 32MiB */
lis 9, 0x0c00
ori 9, 9, 0x002a /* uncached, guarded, rw */
mtspr 0x21b, 9 /* DBAT1L */
mtspr 0x21a, 8 /* DBAT1U */
lis 8, 0x0100 /* next 8MiB */
ori 8, 8, 0x00ff /* 8MiB */
lis 9, 0x0100
ori 9, 9, 0x0002 /* rw */
mtspr 0x215, 9 /* IBAT2L */
mtspr 0x214, 8 /* IBAT2U */
mtspr 0x21d, 9 /* DBAT2L */
mtspr 0x21c, 8 /* DBAT2U */
lis 8, 0x1000 /* MEM2 */
ori 8, 8, 0x07ff /* 64MiB */
lis 9, 0x1000
ori 9, 9, 0x0002 /* rw */
mtspr 0x216, 8 /* IBAT3U */
mtspr 0x217, 9 /* IBAT3L */
mtspr 0x21e, 8 /* DBAT3U */
mtspr 0x21f, 9 /* DBAT3L */
/* enable the high BATs */
mfspr 8, 0x3f3 /* HID4 */
oris 8, 8, 0x0200
mtspr 0x3f3, 8 /* HID4 */
/* enable and invalidate the caches if not already enabled */
mfspr 8, 0x3f0 /* HID0 */
andi. 0, 8, (1<<15) /* HID0_ICE */
bne 1f
ori 8, 8, (1<<15)|(1<<11) /* HID0_ICE|HID0_ICFI*/
1:
andi. 0, 8, (1<<14) /* HID0_DCE */
bne 1f
ori 8, 8, (1<<14)|(1<<10) /* HID0_DCE|HID0_DCFI*/
1:
mtspr 0x3f0, 8 /* HID0 */
isync
/* initialize arguments */
li 3, 0
li 4, 0
li 5, 0
/* turn the MMU on */
bcl 20, 31, 1f
1:
mflr 8
addi 8, 8, _mmu_on - 1b
mfmsr 9
ori 9, 9, (1<<4)|(1<<5) /* MSR_DR|MSR_IR */
mtsrr0 8
mtsrr1 9
sync
rfi
_mmu_on:
/* turn on the front blue led (aka: yay! we got here!) */
lis 8, 0x0d00
ori 8, 8, 0x00c0
lwz 9, 0(8)
ori 9, 9, 0x20
stw 9, 0(8)
b _zimage_start_lib

158
arch/powerpc/boot/wii.c Normal file
View File

@ -0,0 +1,158 @@
/*
* arch/powerpc/boot/wii.c
*
* Nintendo Wii bootwrapper support
* Copyright (C) 2008-2009 The GameCube Linux Team
* Copyright (C) 2008,2009 Albert Herranz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
*/
#include <stddef.h>
#include "stdio.h"
#include "types.h"
#include "io.h"
#include "ops.h"
#include "ugecon.h"
BSS_STACK(8192);
#define HW_REG(x) ((void *)(x))
#define EXI_CTRL HW_REG(0x0d800070)
#define EXI_CTRL_ENABLE (1<<0)
#define MEM2_TOP (0x10000000 + 64*1024*1024)
#define FIRMWARE_DEFAULT_SIZE (12*1024*1024)
struct mipc_infohdr {
char magic[3];
u8 version;
u32 mem2_boundary;
u32 ipc_in;
size_t ipc_in_size;
u32 ipc_out;
size_t ipc_out_size;
};
static int mipc_check_address(u32 pa)
{
/* only MEM2 addresses */
if (pa < 0x10000000 || pa > 0x14000000)
return -EINVAL;
return 0;
}
static struct mipc_infohdr *mipc_get_infohdr(void)
{
struct mipc_infohdr **hdrp, *hdr;
/* 'mini' header pointer is the last word of MEM2 memory */
hdrp = (struct mipc_infohdr **)0x13fffffc;
if (mipc_check_address((u32)hdrp)) {
printf("mini: invalid hdrp %08X\n", (u32)hdrp);
hdr = NULL;
goto out;
}
hdr = *hdrp;
if (mipc_check_address((u32)hdr)) {
printf("mini: invalid hdr %08X\n", (u32)hdr);
hdr = NULL;
goto out;
}
if (memcmp(hdr->magic, "IPC", 3)) {
printf("mini: invalid magic\n");
hdr = NULL;
goto out;
}
out:
return hdr;
}
static int mipc_get_mem2_boundary(u32 *mem2_boundary)
{
struct mipc_infohdr *hdr;
int error;
hdr = mipc_get_infohdr();
if (!hdr) {
error = -1;
goto out;
}
if (mipc_check_address(hdr->mem2_boundary)) {
printf("mini: invalid mem2_boundary %08X\n",
hdr->mem2_boundary);
error = -EINVAL;
goto out;
}
*mem2_boundary = hdr->mem2_boundary;
error = 0;
out:
return error;
}
static void platform_fixups(void)
{
void *mem;
u32 reg[4];
u32 mem2_boundary;
int len;
int error;
mem = finddevice("/memory");
if (!mem)
fatal("Can't find memory node\n");
/* two ranges of (address, size) words */
len = getprop(mem, "reg", reg, sizeof(reg));
if (len != sizeof(reg)) {
/* nothing to do */
goto out;
}
/* retrieve MEM2 boundary from 'mini' */
error = mipc_get_mem2_boundary(&mem2_boundary);
if (error) {
/* if that fails use a sane value */
mem2_boundary = MEM2_TOP - FIRMWARE_DEFAULT_SIZE;
}
if (mem2_boundary > reg[2] && mem2_boundary < reg[2] + reg[3]) {
reg[3] = mem2_boundary - reg[2];
printf("top of MEM2 @ %08X\n", reg[2] + reg[3]);
setprop(mem, "reg", reg, sizeof(reg));
}
out:
return;
}
void platform_init(unsigned long r3, unsigned long r4, unsigned long r5)
{
u32 heapsize = 24*1024*1024 - (u32)_end;
simple_alloc_init(_end, heapsize, 32, 64);
fdt_init(_dtb_start);
/*
* 'mini' boots the Broadway processor with EXI disabled.
* We need it enabled before probing for the USB Gecko.
*/
out_be32(EXI_CTRL, in_be32(EXI_CTRL) | EXI_CTRL_ENABLE);
if (ug_probe())
console_ops.write = ug_console_write;
platform_ops.fixups = platform_fixups;
}

View File

@ -230,6 +230,10 @@ xpedite52*)
link_address='0x1400000'
platformo=$object/cuboot-85xx.o
;;
gamecube|wii)
link_address='0x600000'
platformo="$object/$platform-head.o $object/$platform.o"
;;
esac
vmz="$tmpdir/`basename \"$kernel\"`.$ext"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -44,6 +44,9 @@
*/
enum fixed_addresses {
FIX_HOLE,
/* reserve the top 128K for early debugging purposes */
FIX_EARLY_DEBUG_TOP = FIX_HOLE,
FIX_EARLY_DEBUG_BASE = FIX_EARLY_DEBUG_TOP+((128*1024)/PAGE_SIZE)-1,
#ifdef CONFIG_HIGHMEM
FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */
FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,

View File

@ -51,6 +51,7 @@ extern void __init udbg_init_btext(void);
extern void __init udbg_init_44x_as1(void);
extern void __init udbg_init_40x_realmode(void);
extern void __init udbg_init_cpm(void);
extern void __init udbg_init_usbgecko(void);
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_UDBG_H */

View File

@ -697,9 +697,9 @@ static struct cpu_spec __initdata cpu_specs[] = {
.machine_check = machine_check_generic,
.platform = "ppc750",
},
{ /* 750CL */
.pvr_mask = 0xfffff0f0,
.pvr_value = 0x00087010,
{ /* 750CL (and "Broadway") */
.pvr_mask = 0xfffff0e0,
.pvr_value = 0x00087000,
.cpu_name = "750CL",
.cpu_features = CPU_FTRS_750CL,
.cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,

View File

@ -164,6 +164,9 @@ __after_mmu_off:
#ifdef CONFIG_PPC_EARLY_DEBUG_CPM
bl setup_cpm_bat
#endif
#ifdef CONFIG_PPC_EARLY_DEBUG_USBGECKO
bl setup_usbgecko_bat
#endif
/*
* Call setup_cpu for CPU 0 and initialize 6xx Idle
@ -1203,6 +1206,28 @@ setup_cpm_bat:
blr
#endif
#ifdef CONFIG_PPC_EARLY_DEBUG_USBGECKO
setup_usbgecko_bat:
/* prepare a BAT for early io */
#if defined(CONFIG_GAMECUBE)
lis r8, 0x0c00
#elif defined(CONFIG_WII)
lis r8, 0x0d00
#else
#error Invalid platform for USB Gecko based early debugging.
#endif
/*
* The virtual address used must match the virtual address
* associated to the fixmap entry FIX_EARLY_DEBUG_BASE.
*/
lis r11, 0xfffe /* top 128K */
ori r8, r8, 0x002a /* uncached, guarded ,rw */
ori r11, r11, 0x2 /* 128K, Vs=1, Vp=0 */
mtspr SPRN_DBAT1L, r8
mtspr SPRN_DBAT1U, r11
blr
#endif
#ifdef CONFIG_8260
/* Jump into the system reset for the rom.
* We first disable the MMU, and then jump to the ROM reset address.

View File

@ -60,6 +60,8 @@ void __init udbg_early_init(void)
udbg_init_40x_realmode();
#elif defined(CONFIG_PPC_EARLY_DEBUG_CPM)
udbg_init_cpm();
#elif defined(CONFIG_PPC_EARLY_DEBUG_USBGECKO)
udbg_init_usbgecko();
#endif
#ifdef CONFIG_PPC_EARLY_DEBUG

View File

@ -91,7 +91,7 @@ void __init MMU_init_hw(void)
#define LARGE_PAGE_SIZE_16M (1<<24)
#define LARGE_PAGE_SIZE_4M (1<<22)
unsigned long __init mmu_mapin_ram(void)
unsigned long __init mmu_mapin_ram(unsigned long top)
{
unsigned long v, s, mapped;
phys_addr_t p;

View File

@ -88,7 +88,7 @@ void __init MMU_init_hw(void)
flush_instruction_cache();
}
unsigned long __init mmu_mapin_ram(void)
unsigned long __init mmu_mapin_ram(unsigned long top)
{
unsigned long addr;

View File

@ -207,7 +207,7 @@ unsigned long map_mem_in_cams(unsigned long ram, int max_cam_idx)
return amount_mapped;
}
unsigned long __init mmu_mapin_ram(void)
unsigned long __init mmu_mapin_ram(unsigned long top)
{
return tlbcam_addrs[tlbcam_index - 1].limit - PAGE_OFFSET + 1;
}

View File

@ -82,6 +82,11 @@ extern struct task_struct *current_set[NR_CPUS];
int __map_without_bats;
int __map_without_ltlbs;
/*
* This tells the system to allow ioremapping memory marked as reserved.
*/
int __allow_ioremap_reserved;
/* max amount of low RAM to map in */
unsigned long __max_low_memory = MAX_LOW_MEM;
@ -131,9 +136,13 @@ void __init MMU_init(void)
MMU_setup();
if (lmb.memory.cnt > 1) {
#ifndef CONFIG_WII
lmb.memory.cnt = 1;
lmb_analyze();
printk(KERN_WARNING "Only using first contiguous memory region");
#else
wii_memory_fixups();
#endif
}
total_lowmem = total_memory = lmb_end_of_DRAM() - memstart_addr;

View File

@ -104,6 +104,7 @@ extern void setbat(int index, unsigned long virt, phys_addr_t phys,
unsigned int size, int flags);
extern int __map_without_bats;
extern int __allow_ioremap_reserved;
extern unsigned long ioremap_base;
extern unsigned int rtas_data, rtas_size;
@ -125,24 +126,32 @@ extern phys_addr_t total_lowmem;
extern phys_addr_t memstart_addr;
extern phys_addr_t lowmem_end_addr;
#ifdef CONFIG_WII
extern unsigned long wii_hole_start;
extern unsigned long wii_hole_size;
extern unsigned long wii_mmu_mapin_mem2(unsigned long top);
extern void wii_memory_fixups(void);
#endif
/* ...and now those things that may be slightly different between processor
* architectures. -- Dan
*/
#if defined(CONFIG_8xx)
#define MMU_init_hw() do { } while(0)
#define mmu_mapin_ram() (0UL)
#define mmu_mapin_ram(top) (0UL)
#elif defined(CONFIG_4xx)
extern void MMU_init_hw(void);
extern unsigned long mmu_mapin_ram(void);
extern unsigned long mmu_mapin_ram(unsigned long top);
#elif defined(CONFIG_FSL_BOOKE)
extern void MMU_init_hw(void);
extern unsigned long mmu_mapin_ram(void);
extern unsigned long mmu_mapin_ram(unsigned long top);
extern void adjust_total_lowmem(void);
#elif defined(CONFIG_PPC32)
/* anything 32-bit except 4xx or 8xx */
extern void MMU_init_hw(void);
extern unsigned long mmu_mapin_ram(void);
extern unsigned long mmu_mapin_ram(unsigned long top);
#endif

View File

@ -26,6 +26,7 @@
#include <linux/vmalloc.h>
#include <linux/init.h>
#include <linux/highmem.h>
#include <linux/lmb.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
@ -191,7 +192,8 @@ __ioremap_caller(phys_addr_t addr, unsigned long size, unsigned long flags,
* Don't allow anybody to remap normal RAM that we're using.
* mem_init() sets high_memory so only do the check after that.
*/
if (mem_init_done && (p < virt_to_phys(high_memory))) {
if (mem_init_done && (p < virt_to_phys(high_memory)) &&
!(__allow_ioremap_reserved && lmb_is_region_reserved(p, size))) {
printk("__ioremap(): phys addr 0x%llx is RAM lr %p\n",
(unsigned long long)p, __builtin_return_address(0));
return NULL;
@ -283,18 +285,18 @@ int map_page(unsigned long va, phys_addr_t pa, int flags)
}
/*
* Map in a big chunk of physical memory starting at PAGE_OFFSET.
* Map in a chunk of physical memory starting at start.
*/
void __init mapin_ram(void)
void __init __mapin_ram_chunk(unsigned long offset, unsigned long top)
{
unsigned long v, s, f;
phys_addr_t p;
int ktext;
s = mmu_mapin_ram();
s = offset;
v = PAGE_OFFSET + s;
p = memstart_addr + s;
for (; s < total_lowmem; s += PAGE_SIZE) {
for (; s < top; s += PAGE_SIZE) {
ktext = ((char *) v >= _stext && (char *) v < etext);
f = ktext ? PAGE_KERNEL_TEXT : PAGE_KERNEL;
map_page(v, p, f);
@ -307,6 +309,30 @@ void __init mapin_ram(void)
}
}
void __init mapin_ram(void)
{
unsigned long s, top;
#ifndef CONFIG_WII
top = total_lowmem;
s = mmu_mapin_ram(top);
__mapin_ram_chunk(s, top);
#else
if (!wii_hole_size) {
s = mmu_mapin_ram(total_lowmem);
__mapin_ram_chunk(s, total_lowmem);
} else {
top = wii_hole_start;
s = mmu_mapin_ram(top);
__mapin_ram_chunk(s, top);
top = lmb_end_of_DRAM();
s = wii_mmu_mapin_mem2(top);
__mapin_ram_chunk(s, top);
}
#endif
}
/* Scan the real Linux page tables and return a PTE pointer for
* a virtual address in a context.
* Returns true (1) if PTE was found, zero otherwise. The pointer to

View File

@ -72,7 +72,7 @@ unsigned long p_mapped_by_bats(phys_addr_t pa)
return 0;
}
unsigned long __init mmu_mapin_ram(void)
unsigned long __init mmu_mapin_ram(unsigned long top)
{
unsigned long tot, bl, done;
unsigned long max_size = (256<<20);
@ -86,7 +86,7 @@ unsigned long __init mmu_mapin_ram(void)
/* Make sure we don't map a block larger than the
smallest alignment of the physical address. */
tot = total_lowmem;
tot = top;
for (bl = 128<<10; bl < max_size; bl <<= 1) {
if (bl * 2 > tot)
break;

View File

@ -311,7 +311,7 @@ config NR_CPUS
config NOT_COHERENT_CACHE
bool
depends on 4xx || 8xx || E200 || PPC_MPC512x
depends on 4xx || 8xx || E200 || PPC_MPC512x || GAMECUBE_COMMON
default y
config CHECK_CACHE_COHERENCY

View File

@ -90,3 +90,36 @@ config MPC10X_OPENPIC
config MPC10X_STORE_GATHERING
bool "Enable MPC10x store gathering"
depends on MPC10X_BRIDGE
config GAMECUBE_COMMON
bool
config USBGECKO_UDBG
bool "USB Gecko udbg console for the Nintendo GameCube/Wii"
depends on GAMECUBE_COMMON
help
If you say yes to this option, support will be included for the
USB Gecko adapter as an udbg console.
The USB Gecko is a EXI to USB Serial converter that can be plugged
into a memcard slot in the Nintendo GameCube/Wii.
This driver bypasses the EXI layer completely.
If in doubt, say N here.
config GAMECUBE
bool "Nintendo-GameCube"
depends on EMBEDDED6xx
select GAMECUBE_COMMON
help
Select GAMECUBE if configuring for the Nintendo GameCube.
More information at: <http://gc-linux.sourceforge.net/>
config WII
bool "Nintendo-Wii"
depends on EMBEDDED6xx
select GAMECUBE_COMMON
help
Select WII if configuring for the Nintendo Wii.
More information at: <http://gc-linux.sourceforge.net/>

View File

@ -7,3 +7,7 @@ obj-$(CONFIG_STORCENTER) += storcenter.o
obj-$(CONFIG_PPC_HOLLY) += holly.o
obj-$(CONFIG_PPC_PRPMC2800) += prpmc2800.o
obj-$(CONFIG_PPC_C2K) += c2k.o
obj-$(CONFIG_USBGECKO_UDBG) += usbgecko_udbg.o
obj-$(CONFIG_GAMECUBE_COMMON) += flipper-pic.o
obj-$(CONFIG_GAMECUBE) += gamecube.o
obj-$(CONFIG_WII) += wii.o hlwd-pic.o

View File

@ -0,0 +1,263 @@
/*
* arch/powerpc/platforms/embedded6xx/flipper-pic.c
*
* Nintendo GameCube/Wii "Flipper" interrupt controller support.
* Copyright (C) 2004-2009 The GameCube Linux Team
* Copyright (C) 2007,2008,2009 Albert Herranz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
*/
#define DRV_MODULE_NAME "flipper-pic"
#define pr_fmt(fmt) DRV_MODULE_NAME ": " fmt
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/of.h>
#include <asm/io.h>
#include "flipper-pic.h"
#define FLIPPER_NR_IRQS 32
/*
* Each interrupt has a corresponding bit in both
* the Interrupt Cause (ICR) and Interrupt Mask (IMR) registers.
*
* Enabling/disabling an interrupt line involves setting/clearing
* the corresponding bit in IMR.
* Except for the RSW interrupt, all interrupts get deasserted automatically
* when the source deasserts the interrupt.
*/
#define FLIPPER_ICR 0x00
#define FLIPPER_ICR_RSS (1<<16) /* reset switch state */
#define FLIPPER_IMR 0x04
#define FLIPPER_RESET 0x24
/*
* IRQ chip hooks.
*
*/
static void flipper_pic_mask_and_ack(unsigned int virq)
{
int irq = virq_to_hw(virq);
void __iomem *io_base = get_irq_chip_data(virq);
u32 mask = 1 << irq;
clrbits32(io_base + FLIPPER_IMR, mask);
/* this is at least needed for RSW */
out_be32(io_base + FLIPPER_ICR, mask);
}
static void flipper_pic_ack(unsigned int virq)
{
int irq = virq_to_hw(virq);
void __iomem *io_base = get_irq_chip_data(virq);
/* this is at least needed for RSW */
out_be32(io_base + FLIPPER_ICR, 1 << irq);
}
static void flipper_pic_mask(unsigned int virq)
{
int irq = virq_to_hw(virq);
void __iomem *io_base = get_irq_chip_data(virq);
clrbits32(io_base + FLIPPER_IMR, 1 << irq);
}
static void flipper_pic_unmask(unsigned int virq)
{
int irq = virq_to_hw(virq);
void __iomem *io_base = get_irq_chip_data(virq);
setbits32(io_base + FLIPPER_IMR, 1 << irq);
}
static struct irq_chip flipper_pic = {
.name = "flipper-pic",
.ack = flipper_pic_ack,
.mask_ack = flipper_pic_mask_and_ack,
.mask = flipper_pic_mask,
.unmask = flipper_pic_unmask,
};
/*
* IRQ host hooks.
*
*/
static struct irq_host *flipper_irq_host;
static int flipper_pic_map(struct irq_host *h, unsigned int virq,
irq_hw_number_t hwirq)
{
set_irq_chip_data(virq, h->host_data);
get_irq_desc(virq)->status |= IRQ_LEVEL;
set_irq_chip_and_handler(virq, &flipper_pic, handle_level_irq);
return 0;
}
static void flipper_pic_unmap(struct irq_host *h, unsigned int irq)
{
set_irq_chip_data(irq, NULL);
set_irq_chip(irq, NULL);
}
static int flipper_pic_match(struct irq_host *h, struct device_node *np)
{
return 1;
}
static struct irq_host_ops flipper_irq_host_ops = {
.map = flipper_pic_map,
.unmap = flipper_pic_unmap,
.match = flipper_pic_match,
};
/*
* Platform hooks.
*
*/
static void __flipper_quiesce(void __iomem *io_base)
{
/* mask and ack all IRQs */
out_be32(io_base + FLIPPER_IMR, 0x00000000);
out_be32(io_base + FLIPPER_ICR, 0xffffffff);
}
struct irq_host * __init flipper_pic_init(struct device_node *np)
{
struct device_node *pi;
struct irq_host *irq_host = NULL;
struct resource res;
void __iomem *io_base;
int retval;
pi = of_get_parent(np);
if (!pi) {
pr_err("no parent found\n");
goto out;
}
if (!of_device_is_compatible(pi, "nintendo,flipper-pi")) {
pr_err("unexpected parent compatible\n");
goto out;
}
retval = of_address_to_resource(pi, 0, &res);
if (retval) {
pr_err("no io memory range found\n");
goto out;
}
io_base = ioremap(res.start, resource_size(&res));
pr_info("controller at 0x%08x mapped to 0x%p\n", res.start, io_base);
__flipper_quiesce(io_base);
irq_host = irq_alloc_host(np, IRQ_HOST_MAP_LINEAR, FLIPPER_NR_IRQS,
&flipper_irq_host_ops, -1);
if (!irq_host) {
pr_err("failed to allocate irq_host\n");
return NULL;
}
irq_host->host_data = io_base;
out:
return irq_host;
}
unsigned int flipper_pic_get_irq(void)
{
void __iomem *io_base = flipper_irq_host->host_data;
int irq;
u32 irq_status;
irq_status = in_be32(io_base + FLIPPER_ICR) &
in_be32(io_base + FLIPPER_IMR);
if (irq_status == 0)
return NO_IRQ; /* no more IRQs pending */
irq = __ffs(irq_status);
return irq_linear_revmap(flipper_irq_host, irq);
}
/*
* Probe function.
*
*/
void __init flipper_pic_probe(void)
{
struct device_node *np;
np = of_find_compatible_node(NULL, NULL, "nintendo,flipper-pic");
BUG_ON(!np);
flipper_irq_host = flipper_pic_init(np);
BUG_ON(!flipper_irq_host);
irq_set_default_host(flipper_irq_host);
of_node_put(np);
}
/*
* Misc functions related to the flipper chipset.
*
*/
/**
* flipper_quiesce() - quiesce flipper irq controller
*
* Mask and ack all interrupt sources.
*
*/
void flipper_quiesce(void)
{
void __iomem *io_base = flipper_irq_host->host_data;
__flipper_quiesce(io_base);
}
/*
* Resets the platform.
*/
void flipper_platform_reset(void)
{
void __iomem *io_base;
if (flipper_irq_host && flipper_irq_host->host_data) {
io_base = flipper_irq_host->host_data;
out_8(io_base + FLIPPER_RESET, 0x00);
}
}
/*
* Returns non-zero if the reset button is pressed.
*/
int flipper_is_reset_button_pressed(void)
{
void __iomem *io_base;
u32 icr;
if (flipper_irq_host && flipper_irq_host->host_data) {
io_base = flipper_irq_host->host_data;
icr = in_be32(io_base + FLIPPER_ICR);
return !(icr & FLIPPER_ICR_RSS);
}
return 0;
}

View File

@ -0,0 +1,25 @@
/*
* arch/powerpc/platforms/embedded6xx/flipper-pic.h
*
* Nintendo GameCube/Wii "Flipper" interrupt controller support.
* Copyright (C) 2004-2009 The GameCube Linux Team
* Copyright (C) 2007,2008,2009 Albert Herranz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
*/
#ifndef __FLIPPER_PIC_H
#define __FLIPPER_PIC_H
unsigned int flipper_pic_get_irq(void);
void __init flipper_pic_probe(void);
void flipper_quiesce(void);
void flipper_platform_reset(void);
int flipper_is_reset_button_pressed(void);
#endif

View File

@ -0,0 +1,118 @@
/*
* arch/powerpc/platforms/embedded6xx/gamecube.c
*
* Nintendo GameCube board-specific support
* Copyright (C) 2004-2009 The GameCube Linux Team
* Copyright (C) 2007,2008,2009 Albert Herranz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/kexec.h>
#include <linux/seq_file.h>
#include <linux/of_platform.h>
#include <asm/io.h>
#include <asm/machdep.h>
#include <asm/prom.h>
#include <asm/time.h>
#include <asm/udbg.h>
#include "flipper-pic.h"
#include "usbgecko_udbg.h"
static void gamecube_spin(void)
{
/* spin until power button pressed */
for (;;)
cpu_relax();
}
static void gamecube_restart(char *cmd)
{
local_irq_disable();
flipper_platform_reset();
gamecube_spin();
}
static void gamecube_power_off(void)
{
local_irq_disable();
gamecube_spin();
}
static void gamecube_halt(void)
{
gamecube_restart(NULL);
}
static void __init gamecube_init_early(void)
{
ug_udbg_init();
}
static int __init gamecube_probe(void)
{
unsigned long dt_root;
dt_root = of_get_flat_dt_root();
if (!of_flat_dt_is_compatible(dt_root, "nintendo,gamecube"))
return 0;
return 1;
}
static void gamecube_shutdown(void)
{
flipper_quiesce();
}
#ifdef CONFIG_KEXEC
static int gamecube_kexec_prepare(struct kimage *image)
{
return 0;
}
#endif /* CONFIG_KEXEC */
define_machine(gamecube) {
.name = "gamecube",
.probe = gamecube_probe,
.init_early = gamecube_init_early,
.restart = gamecube_restart,
.power_off = gamecube_power_off,
.halt = gamecube_halt,
.init_IRQ = flipper_pic_probe,
.get_irq = flipper_pic_get_irq,
.calibrate_decr = generic_calibrate_decr,
.progress = udbg_progress,
.machine_shutdown = gamecube_shutdown,
#ifdef CONFIG_KEXEC
.machine_kexec_prepare = gamecube_kexec_prepare,
#endif
};
static struct of_device_id gamecube_of_bus[] = {
{ .compatible = "nintendo,flipper", },
{ },
};
static int __init gamecube_device_probe(void)
{
if (!machine_is(gamecube))
return 0;
of_platform_bus_probe(NULL, gamecube_of_bus, NULL);
return 0;
}
device_initcall(gamecube_device_probe);

View File

@ -0,0 +1,241 @@
/*
* arch/powerpc/platforms/embedded6xx/hlwd-pic.c
*
* Nintendo Wii "Hollywood" interrupt controller support.
* Copyright (C) 2009 The GameCube Linux Team
* Copyright (C) 2009 Albert Herranz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
*/
#define DRV_MODULE_NAME "hlwd-pic"
#define pr_fmt(fmt) DRV_MODULE_NAME ": " fmt
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/of.h>
#include <asm/io.h>
#include "hlwd-pic.h"
#define HLWD_NR_IRQS 32
/*
* Each interrupt has a corresponding bit in both
* the Interrupt Cause (ICR) and Interrupt Mask (IMR) registers.
*
* Enabling/disabling an interrupt line involves asserting/clearing
* the corresponding bit in IMR. ACK'ing a request simply involves
* asserting the corresponding bit in ICR.
*/
#define HW_BROADWAY_ICR 0x00
#define HW_BROADWAY_IMR 0x04
/*
* IRQ chip hooks.
*
*/
static void hlwd_pic_mask_and_ack(unsigned int virq)
{
int irq = virq_to_hw(virq);
void __iomem *io_base = get_irq_chip_data(virq);
u32 mask = 1 << irq;
clrbits32(io_base + HW_BROADWAY_IMR, mask);
out_be32(io_base + HW_BROADWAY_ICR, mask);
}
static void hlwd_pic_ack(unsigned int virq)
{
int irq = virq_to_hw(virq);
void __iomem *io_base = get_irq_chip_data(virq);
out_be32(io_base + HW_BROADWAY_ICR, 1 << irq);
}
static void hlwd_pic_mask(unsigned int virq)
{
int irq = virq_to_hw(virq);
void __iomem *io_base = get_irq_chip_data(virq);
clrbits32(io_base + HW_BROADWAY_IMR, 1 << irq);
}
static void hlwd_pic_unmask(unsigned int virq)
{
int irq = virq_to_hw(virq);
void __iomem *io_base = get_irq_chip_data(virq);
setbits32(io_base + HW_BROADWAY_IMR, 1 << irq);
}
static struct irq_chip hlwd_pic = {
.name = "hlwd-pic",
.ack = hlwd_pic_ack,
.mask_ack = hlwd_pic_mask_and_ack,
.mask = hlwd_pic_mask,
.unmask = hlwd_pic_unmask,
};
/*
* IRQ host hooks.
*
*/
static struct irq_host *hlwd_irq_host;
static int hlwd_pic_map(struct irq_host *h, unsigned int virq,
irq_hw_number_t hwirq)
{
set_irq_chip_data(virq, h->host_data);
get_irq_desc(virq)->status |= IRQ_LEVEL;
set_irq_chip_and_handler(virq, &hlwd_pic, handle_level_irq);
return 0;
}
static void hlwd_pic_unmap(struct irq_host *h, unsigned int irq)
{
set_irq_chip_data(irq, NULL);
set_irq_chip(irq, NULL);
}
static struct irq_host_ops hlwd_irq_host_ops = {
.map = hlwd_pic_map,
.unmap = hlwd_pic_unmap,
};
static unsigned int __hlwd_pic_get_irq(struct irq_host *h)
{
void __iomem *io_base = h->host_data;
int irq;
u32 irq_status;
irq_status = in_be32(io_base + HW_BROADWAY_ICR) &
in_be32(io_base + HW_BROADWAY_IMR);
if (irq_status == 0)
return NO_IRQ; /* no more IRQs pending */
irq = __ffs(irq_status);
return irq_linear_revmap(h, irq);
}
static void hlwd_pic_irq_cascade(unsigned int cascade_virq,
struct irq_desc *desc)
{
struct irq_host *irq_host = get_irq_data(cascade_virq);
unsigned int virq;
spin_lock(&desc->lock);
desc->chip->mask(cascade_virq); /* IRQ_LEVEL */
spin_unlock(&desc->lock);
virq = __hlwd_pic_get_irq(irq_host);
if (virq != NO_IRQ)
generic_handle_irq(virq);
else
pr_err("spurious interrupt!\n");
spin_lock(&desc->lock);
desc->chip->ack(cascade_virq); /* IRQ_LEVEL */
if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask)
desc->chip->unmask(cascade_virq);
spin_unlock(&desc->lock);
}
/*
* Platform hooks.
*
*/
static void __hlwd_quiesce(void __iomem *io_base)
{
/* mask and ack all IRQs */
out_be32(io_base + HW_BROADWAY_IMR, 0);
out_be32(io_base + HW_BROADWAY_ICR, 0xffffffff);
}
struct irq_host *hlwd_pic_init(struct device_node *np)
{
struct irq_host *irq_host;
struct resource res;
void __iomem *io_base;
int retval;
retval = of_address_to_resource(np, 0, &res);
if (retval) {
pr_err("no io memory range found\n");
return NULL;
}
io_base = ioremap(res.start, resource_size(&res));
if (!io_base) {
pr_err("ioremap failed\n");
return NULL;
}
pr_info("controller at 0x%08x mapped to 0x%p\n", res.start, io_base);
__hlwd_quiesce(io_base);
irq_host = irq_alloc_host(np, IRQ_HOST_MAP_LINEAR, HLWD_NR_IRQS,
&hlwd_irq_host_ops, -1);
if (!irq_host) {
pr_err("failed to allocate irq_host\n");
return NULL;
}
irq_host->host_data = io_base;
return irq_host;
}
unsigned int hlwd_pic_get_irq(void)
{
return __hlwd_pic_get_irq(hlwd_irq_host);
}
/*
* Probe function.
*
*/
void hlwd_pic_probe(void)
{
struct irq_host *host;
struct device_node *np;
const u32 *interrupts;
int cascade_virq;
for_each_compatible_node(np, NULL, "nintendo,hollywood-pic") {
interrupts = of_get_property(np, "interrupts", NULL);
if (interrupts) {
host = hlwd_pic_init(np);
BUG_ON(!host);
cascade_virq = irq_of_parse_and_map(np, 0);
set_irq_data(cascade_virq, host);
set_irq_chained_handler(cascade_virq,
hlwd_pic_irq_cascade);
hlwd_irq_host = host;
break;
}
}
}
/**
* hlwd_quiesce() - quiesce hollywood irq controller
*
* Mask and ack all interrupt sources.
*
*/
void hlwd_quiesce(void)
{
void __iomem *io_base = hlwd_irq_host->host_data;
__hlwd_quiesce(io_base);
}

View File

@ -0,0 +1,22 @@
/*
* arch/powerpc/platforms/embedded6xx/hlwd-pic.h
*
* Nintendo Wii "Hollywood" interrupt controller support.
* Copyright (C) 2009 The GameCube Linux Team
* Copyright (C) 2009 Albert Herranz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
*/
#ifndef __HLWD_PIC_H
#define __HLWD_PIC_H
extern unsigned int hlwd_pic_get_irq(void);
extern void hlwd_pic_probe(void);
extern void hlwd_quiesce(void);
#endif

View File

@ -0,0 +1,328 @@
/*
* arch/powerpc/platforms/embedded6xx/usbgecko_udbg.c
*
* udbg serial input/output routines for the USB Gecko adapter.
* Copyright (C) 2008-2009 The GameCube Linux Team
* Copyright (C) 2008,2009 Albert Herranz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
*/
#include <mm/mmu_decl.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/udbg.h>
#include <asm/fixmap.h>
#include "usbgecko_udbg.h"
#define EXI_CLK_32MHZ 5
#define EXI_CSR 0x00
#define EXI_CSR_CLKMASK (0x7<<4)
#define EXI_CSR_CLK_32MHZ (EXI_CLK_32MHZ<<4)
#define EXI_CSR_CSMASK (0x7<<7)
#define EXI_CSR_CS_0 (0x1<<7) /* Chip Select 001 */
#define EXI_CR 0x0c
#define EXI_CR_TSTART (1<<0)
#define EXI_CR_WRITE (1<<2)
#define EXI_CR_READ_WRITE (2<<2)
#define EXI_CR_TLEN(len) (((len)-1)<<4)
#define EXI_DATA 0x10
#define UG_READ_ATTEMPTS 100
#define UG_WRITE_ATTEMPTS 100
static void __iomem *ug_io_base;
/*
* Performs one input/output transaction between the exi host and the usbgecko.
*/
static u32 ug_io_transaction(u32 in)
{
u32 __iomem *csr_reg = ug_io_base + EXI_CSR;
u32 __iomem *data_reg = ug_io_base + EXI_DATA;
u32 __iomem *cr_reg = ug_io_base + EXI_CR;
u32 csr, data, cr;
/* select */
csr = EXI_CSR_CLK_32MHZ | EXI_CSR_CS_0;
out_be32(csr_reg, csr);
/* read/write */
data = in;
out_be32(data_reg, data);
cr = EXI_CR_TLEN(2) | EXI_CR_READ_WRITE | EXI_CR_TSTART;
out_be32(cr_reg, cr);
while (in_be32(cr_reg) & EXI_CR_TSTART)
barrier();
/* deselect */
out_be32(csr_reg, 0);
/* result */
data = in_be32(data_reg);
return data;
}
/*
* Returns true if an usbgecko adapter is found.
*/
static int ug_is_adapter_present(void)
{
if (!ug_io_base)
return 0;
return ug_io_transaction(0x90000000) == 0x04700000;
}
/*
* Returns true if the TX fifo is ready for transmission.
*/
static int ug_is_txfifo_ready(void)
{
return ug_io_transaction(0xc0000000) & 0x04000000;
}
/*
* Tries to transmit a character.
* If the TX fifo is not ready the result is undefined.
*/
static void ug_raw_putc(char ch)
{
ug_io_transaction(0xb0000000 | (ch << 20));
}
/*
* Transmits a character.
* It silently fails if the TX fifo is not ready after a number of retries.
*/
static void ug_putc(char ch)
{
int count = UG_WRITE_ATTEMPTS;
if (!ug_io_base)
return;
if (ch == '\n')
ug_putc('\r');
while (!ug_is_txfifo_ready() && count--)
barrier();
if (count)
ug_raw_putc(ch);
}
/*
* Returns true if the RX fifo is ready for transmission.
*/
static int ug_is_rxfifo_ready(void)
{
return ug_io_transaction(0xd0000000) & 0x04000000;
}
/*
* Tries to receive a character.
* If a character is unavailable the function returns -1.
*/
static int ug_raw_getc(void)
{
u32 data = ug_io_transaction(0xa0000000);
if (data & 0x08000000)
return (data >> 16) & 0xff;
else
return -1;
}
/*
* Receives a character.
* It fails if the RX fifo is not ready after a number of retries.
*/
static int ug_getc(void)
{
int count = UG_READ_ATTEMPTS;
if (!ug_io_base)
return -1;
while (!ug_is_rxfifo_ready() && count--)
barrier();
return ug_raw_getc();
}
/*
* udbg functions.
*
*/
/*
* Transmits a character.
*/
void ug_udbg_putc(char ch)
{
ug_putc(ch);
}
/*
* Receives a character. Waits until a character is available.
*/
static int ug_udbg_getc(void)
{
int ch;
while ((ch = ug_getc()) == -1)
barrier();
return ch;
}
/*
* Receives a character. If a character is not available, returns -1.
*/
static int ug_udbg_getc_poll(void)
{
if (!ug_is_rxfifo_ready())
return -1;
return ug_getc();
}
/*
* Retrieves and prepares the virtual address needed to access the hardware.
*/
static void __iomem *ug_udbg_setup_exi_io_base(struct device_node *np)
{
void __iomem *exi_io_base = NULL;
phys_addr_t paddr;
const unsigned int *reg;
reg = of_get_property(np, "reg", NULL);
if (reg) {
paddr = of_translate_address(np, reg);
if (paddr)
exi_io_base = ioremap(paddr, reg[1]);
}
return exi_io_base;
}
/*
* Checks if a USB Gecko adapter is inserted in any memory card slot.
*/
static void __iomem *ug_udbg_probe(void __iomem *exi_io_base)
{
int i;
/* look for a usbgecko on memcard slots A and B */
for (i = 0; i < 2; i++) {
ug_io_base = exi_io_base + 0x14 * i;
if (ug_is_adapter_present())
break;
}
if (i == 2)
ug_io_base = NULL;
return ug_io_base;
}
/*
* USB Gecko udbg support initialization.
*/
void __init ug_udbg_init(void)
{
struct device_node *np;
void __iomem *exi_io_base;
if (ug_io_base)
udbg_printf("%s: early -> final\n", __func__);
np = of_find_compatible_node(NULL, NULL, "nintendo,flipper-exi");
if (!np) {
udbg_printf("%s: EXI node not found\n", __func__);
goto done;
}
exi_io_base = ug_udbg_setup_exi_io_base(np);
if (!exi_io_base) {
udbg_printf("%s: failed to setup EXI io base\n", __func__);
goto done;
}
if (!ug_udbg_probe(exi_io_base)) {
udbg_printf("usbgecko_udbg: not found\n");
iounmap(exi_io_base);
} else {
udbg_putc = ug_udbg_putc;
udbg_getc = ug_udbg_getc;
udbg_getc_poll = ug_udbg_getc_poll;
udbg_printf("usbgecko_udbg: ready\n");
}
done:
if (np)
of_node_put(np);
return;
}
#ifdef CONFIG_PPC_EARLY_DEBUG_USBGECKO
static phys_addr_t __init ug_early_grab_io_addr(void)
{
#if defined(CONFIG_GAMECUBE)
return 0x0c000000;
#elif defined(CONFIG_WII)
return 0x0d000000;
#else
#error Invalid platform for USB Gecko based early debugging.
#endif
}
/*
* USB Gecko early debug support initialization for udbg.
*/
void __init udbg_init_usbgecko(void)
{
void __iomem *early_debug_area;
void __iomem *exi_io_base;
/*
* At this point we have a BAT already setup that enables I/O
* to the EXI hardware.
*
* The BAT uses a virtual address range reserved at the fixmap.
* This must match the virtual address configured in
* head_32.S:setup_usbgecko_bat().
*/
early_debug_area = (void __iomem *)__fix_to_virt(FIX_EARLY_DEBUG_BASE);
exi_io_base = early_debug_area + 0x00006800;
/* try to detect a USB Gecko */
if (!ug_udbg_probe(exi_io_base))
return;
/* we found a USB Gecko, load udbg hooks */
udbg_putc = ug_udbg_putc;
udbg_getc = ug_udbg_getc;
udbg_getc_poll = ug_udbg_getc_poll;
/*
* Prepare again the same BAT for MMU_init.
* This allows udbg I/O to continue working after the MMU is
* turned on for real.
* It is safe to continue using the same virtual address as it is
* a reserved fixmap area.
*/
setbat(1, (unsigned long)early_debug_area,
ug_early_grab_io_addr(), 128*1024, PAGE_KERNEL_NCG);
}
#endif /* CONFIG_PPC_EARLY_DEBUG_USBGECKO */

View File

@ -0,0 +1,32 @@
/*
* arch/powerpc/platforms/embedded6xx/usbgecko_udbg.h
*
* udbg serial input/output routines for the USB Gecko adapter.
* Copyright (C) 2008-2009 The GameCube Linux Team
* Copyright (C) 2008,2009 Albert Herranz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
*/
#ifndef __USBGECKO_UDBG_H
#define __USBGECKO_UDBG_H
#ifdef CONFIG_USBGECKO_UDBG
extern void __init ug_udbg_init(void);
#else
static inline void __init ug_udbg_init(void)
{
}
#endif /* CONFIG_USBGECKO_UDBG */
void __init udbg_init_usbgecko(void);
#endif /* __USBGECKO_UDBG_H */

View File

@ -0,0 +1,268 @@
/*
* arch/powerpc/platforms/embedded6xx/wii.c
*
* Nintendo Wii board-specific support
* Copyright (C) 2008-2009 The GameCube Linux Team
* Copyright (C) 2008,2009 Albert Herranz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
*/
#define DRV_MODULE_NAME "wii"
#define pr_fmt(fmt) DRV_MODULE_NAME ": " fmt
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/seq_file.h>
#include <linux/kexec.h>
#include <linux/of_platform.h>
#include <linux/lmb.h>
#include <mm/mmu_decl.h>
#include <asm/io.h>
#include <asm/machdep.h>
#include <asm/prom.h>
#include <asm/time.h>
#include <asm/udbg.h>
#include "flipper-pic.h"
#include "hlwd-pic.h"
#include "usbgecko_udbg.h"
/* control block */
#define HW_CTRL_COMPATIBLE "nintendo,hollywood-control"
#define HW_CTRL_RESETS 0x94
#define HW_CTRL_RESETS_SYS (1<<0)
/* gpio */
#define HW_GPIO_COMPATIBLE "nintendo,hollywood-gpio"
#define HW_GPIO_BASE(idx) (idx * 0x20)
#define HW_GPIO_OUT(idx) (HW_GPIO_BASE(idx) + 0)
#define HW_GPIO_DIR(idx) (HW_GPIO_BASE(idx) + 4)
#define HW_GPIO_SHUTDOWN (1<<1)
#define HW_GPIO_SLOT_LED (1<<5)
#define HW_GPIO_SENSOR_BAR (1<<8)
static void __iomem *hw_ctrl;
static void __iomem *hw_gpio;
unsigned long wii_hole_start;
unsigned long wii_hole_size;
static int __init page_aligned(unsigned long x)
{
return !(x & (PAGE_SIZE-1));
}
void __init wii_memory_fixups(void)
{
struct lmb_property *p = lmb.memory.region;
/*
* This is part of a workaround to allow the use of two
* discontiguous RAM ranges on the Wii, even if this is
* currently unsupported on 32-bit PowerPC Linux.
*
* We coealesce the two memory ranges of the Wii into a
* single range, then create a reservation for the "hole"
* between both ranges.
*/
BUG_ON(lmb.memory.cnt != 2);
BUG_ON(!page_aligned(p[0].base) || !page_aligned(p[1].base));
p[0].size = _ALIGN_DOWN(p[0].size, PAGE_SIZE);
p[1].size = _ALIGN_DOWN(p[1].size, PAGE_SIZE);
wii_hole_start = p[0].base + p[0].size;
wii_hole_size = p[1].base - wii_hole_start;
pr_info("MEM1: <%08llx %08llx>\n", p[0].base, p[0].size);
pr_info("HOLE: <%08lx %08lx>\n", wii_hole_start, wii_hole_size);
pr_info("MEM2: <%08llx %08llx>\n", p[1].base, p[1].size);
p[0].size += wii_hole_size + p[1].size;
lmb.memory.cnt = 1;
lmb_analyze();
/* reserve the hole */
lmb_reserve(wii_hole_start, wii_hole_size);
/* allow ioremapping the address space in the hole */
__allow_ioremap_reserved = 1;
}
unsigned long __init wii_mmu_mapin_mem2(unsigned long top)
{
unsigned long delta, size, bl;
unsigned long max_size = (256<<20);
/* MEM2 64MB@0x10000000 */
delta = wii_hole_start + wii_hole_size;
size = top - delta;
for (bl = 128<<10; bl < max_size; bl <<= 1) {
if (bl * 2 > size)
break;
}
setbat(4, PAGE_OFFSET+delta, delta, bl, PAGE_KERNEL_X);
return delta + bl;
}
static void wii_spin(void)
{
local_irq_disable();
for (;;)
cpu_relax();
}
static void __iomem *wii_ioremap_hw_regs(char *name, char *compatible)
{
void __iomem *hw_regs = NULL;
struct device_node *np;
struct resource res;
int error = -ENODEV;
np = of_find_compatible_node(NULL, NULL, compatible);
if (!np) {
pr_err("no compatible node found for %s\n", compatible);
goto out;
}
error = of_address_to_resource(np, 0, &res);
if (error) {
pr_err("no valid reg found for %s\n", np->name);
goto out_put;
}
hw_regs = ioremap(res.start, resource_size(&res));
if (hw_regs) {
pr_info("%s at 0x%08x mapped to 0x%p\n", name,
res.start, hw_regs);
}
out_put:
of_node_put(np);
out:
return hw_regs;
}
static void __init wii_setup_arch(void)
{
hw_ctrl = wii_ioremap_hw_regs("hw_ctrl", HW_CTRL_COMPATIBLE);
hw_gpio = wii_ioremap_hw_regs("hw_gpio", HW_GPIO_COMPATIBLE);
if (hw_gpio) {
/* turn off the front blue led and IR light */
clrbits32(hw_gpio + HW_GPIO_OUT(0),
HW_GPIO_SLOT_LED | HW_GPIO_SENSOR_BAR);
}
}
static void wii_restart(char *cmd)
{
local_irq_disable();
if (hw_ctrl) {
/* clear the system reset pin to cause a reset */
clrbits32(hw_ctrl + HW_CTRL_RESETS, HW_CTRL_RESETS_SYS);
}
wii_spin();
}
static void wii_power_off(void)
{
local_irq_disable();
if (hw_gpio) {
/* make sure that the poweroff GPIO is configured as output */
setbits32(hw_gpio + HW_GPIO_DIR(1), HW_GPIO_SHUTDOWN);
/* drive the poweroff GPIO high */
setbits32(hw_gpio + HW_GPIO_OUT(1), HW_GPIO_SHUTDOWN);
}
wii_spin();
}
static void wii_halt(void)
{
if (ppc_md.restart)
ppc_md.restart(NULL);
wii_spin();
}
static void __init wii_init_early(void)
{
ug_udbg_init();
}
static void __init wii_pic_probe(void)
{
flipper_pic_probe();
hlwd_pic_probe();
}
static int __init wii_probe(void)
{
unsigned long dt_root;
dt_root = of_get_flat_dt_root();
if (!of_flat_dt_is_compatible(dt_root, "nintendo,wii"))
return 0;
return 1;
}
static void wii_shutdown(void)
{
hlwd_quiesce();
flipper_quiesce();
}
#ifdef CONFIG_KEXEC
static int wii_machine_kexec_prepare(struct kimage *image)
{
return 0;
}
#endif /* CONFIG_KEXEC */
define_machine(wii) {
.name = "wii",
.probe = wii_probe,
.init_early = wii_init_early,
.setup_arch = wii_setup_arch,
.restart = wii_restart,
.power_off = wii_power_off,
.halt = wii_halt,
.init_IRQ = wii_pic_probe,
.get_irq = flipper_pic_get_irq,
.calibrate_decr = generic_calibrate_decr,
.progress = udbg_progress,
.machine_shutdown = wii_shutdown,
#ifdef CONFIG_KEXEC
.machine_kexec_prepare = wii_machine_kexec_prepare,
#endif
};
static struct of_device_id wii_of_bus[] = {
{ .compatible = "nintendo,hollywood", },
{ },
};
static int __init wii_device_probe(void)
{
if (!machine_is(wii))
return 0;
of_platform_bus_probe(NULL, wii_of_bus, NULL);
return 0;
}
device_initcall(wii_device_probe);

View File

@ -54,6 +54,7 @@ extern u64 __init lmb_phys_mem_size(void);
extern u64 lmb_end_of_DRAM(void);
extern void __init lmb_enforce_memory_limit(u64 memory_limit);
extern int __init lmb_is_reserved(u64 addr);
extern int lmb_is_region_reserved(u64 base, u64 size);
extern int lmb_find(struct lmb_property *res);
extern void lmb_dump_all(void);

View File

@ -263,7 +263,7 @@ long __init lmb_reserve(u64 base, u64 size)
return lmb_add_region(_rgn, base, size);
}
long __init lmb_overlaps_region(struct lmb_region *rgn, u64 base, u64 size)
long lmb_overlaps_region(struct lmb_region *rgn, u64 base, u64 size)
{
unsigned long i;
@ -493,6 +493,11 @@ int __init lmb_is_reserved(u64 addr)
return 0;
}
int lmb_is_region_reserved(u64 base, u64 size)
{
return lmb_overlaps_region(&lmb.reserved, base, size);
}
/*
* Given a <base, len>, find which memory regions belong to this range.
* Adjust the request and return a contiguous chunk.