mirror of
https://github.com/AetherDroid/android_kernel_samsung_on5xelte.git
synced 2025-10-29 23:28:52 +01:00
Fixed MTP to work with TWRP
This commit is contained in:
commit
f6dfaef42e
50820 changed files with 20846062 additions and 0 deletions
118
arch/powerpc/platforms/embedded6xx/Kconfig
Normal file
118
arch/powerpc/platforms/embedded6xx/Kconfig
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
config EMBEDDED6xx
|
||||
bool "Embedded 6xx/7xx/7xxx-based boards"
|
||||
depends on 6xx && BROKEN_ON_SMP
|
||||
|
||||
config LINKSTATION
|
||||
bool "Linkstation / Kurobox(HG) from Buffalo"
|
||||
depends on EMBEDDED6xx
|
||||
select MPIC
|
||||
select FSL_SOC
|
||||
select PPC_UDBG_16550 if SERIAL_8250
|
||||
select DEFAULT_UIMAGE
|
||||
select MPC10X_BRIDGE
|
||||
help
|
||||
Select LINKSTATION if configuring for one of PPC- (MPC8241)
|
||||
based NAS systems from Buffalo Technology. So far only
|
||||
KuroboxHG has been tested. In the future classical Kurobox,
|
||||
Linkstation-I HD-HLAN and HD-HGLAN versions, and PPC-based
|
||||
Terastation systems should be supported too.
|
||||
|
||||
config STORCENTER
|
||||
bool "IOMEGA StorCenter"
|
||||
depends on EMBEDDED6xx
|
||||
select MPIC
|
||||
select FSL_SOC
|
||||
select PPC_UDBG_16550 if SERIAL_8250
|
||||
select MPC10X_BRIDGE
|
||||
help
|
||||
Select STORCENTER if configuring for the iomega StorCenter
|
||||
with an 8241 CPU in it.
|
||||
|
||||
config MPC7448HPC2
|
||||
bool "Freescale MPC7448HPC2(Taiga)"
|
||||
depends on EMBEDDED6xx
|
||||
select TSI108_BRIDGE
|
||||
select DEFAULT_UIMAGE
|
||||
select PPC_UDBG_16550
|
||||
help
|
||||
Select MPC7448HPC2 if configuring for Freescale MPC7448HPC2 (Taiga)
|
||||
platform
|
||||
|
||||
config PPC_HOLLY
|
||||
bool "PPC750GX/CL with TSI10x bridge (Hickory/Holly)"
|
||||
depends on EMBEDDED6xx
|
||||
select TSI108_BRIDGE
|
||||
select PPC_UDBG_16550
|
||||
help
|
||||
Select PPC_HOLLY if configuring for an IBM 750GX/CL Eval
|
||||
Board with TSI108/9 bridge (Hickory/Holly)
|
||||
|
||||
config PPC_C2K
|
||||
bool "SBS/GEFanuc C2K board"
|
||||
depends on EMBEDDED6xx
|
||||
select MV64X60
|
||||
select NOT_COHERENT_CACHE
|
||||
select MTD_CFI_I4
|
||||
help
|
||||
This option enables support for the GE Fanuc C2K board (formerly
|
||||
an SBS board).
|
||||
|
||||
config MVME5100
|
||||
bool "Motorola/Emerson MVME5100"
|
||||
depends on EMBEDDED6xx
|
||||
select MPIC
|
||||
select PCI
|
||||
select PPC_INDIRECT_PCI
|
||||
select PPC_I8259
|
||||
select PPC_NATIVE
|
||||
select PPC_UDBG_16550
|
||||
help
|
||||
This option enables support for the Motorola (now Emerson) MVME5100
|
||||
board.
|
||||
|
||||
config TSI108_BRIDGE
|
||||
bool
|
||||
select PCI
|
||||
select MPIC
|
||||
select MPIC_WEIRD
|
||||
|
||||
config MPC10X_BRIDGE
|
||||
bool
|
||||
select PPC_INDIRECT_PCI
|
||||
|
||||
config MV64X60
|
||||
bool
|
||||
select PPC_INDIRECT_PCI
|
||||
select CHECK_CACHE_COHERENCY
|
||||
|
||||
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/>
|
||||
13
arch/powerpc/platforms/embedded6xx/Makefile
Normal file
13
arch/powerpc/platforms/embedded6xx/Makefile
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#
|
||||
# Makefile for the 6xx/7xx/7xxxx linux kernel.
|
||||
#
|
||||
obj-$(CONFIG_MPC7448HPC2) += mpc7448_hpc2.o
|
||||
obj-$(CONFIG_LINKSTATION) += linkstation.o ls_uart.o
|
||||
obj-$(CONFIG_STORCENTER) += storcenter.o
|
||||
obj-$(CONFIG_PPC_HOLLY) += holly.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
|
||||
obj-$(CONFIG_MVME5100) += mvme5100.o
|
||||
148
arch/powerpc/platforms/embedded6xx/c2k.c
Normal file
148
arch/powerpc/platforms/embedded6xx/c2k.c
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* Board setup routines for the GEFanuc C2K board
|
||||
*
|
||||
* Author: Remi Machet <rmachet@slac.stanford.edu>
|
||||
*
|
||||
* Originated from prpmc2800.c
|
||||
*
|
||||
* 2008 (c) Stanford University
|
||||
* 2007 (c) MontaVista, Software, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published
|
||||
* by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/time.h>
|
||||
|
||||
#include <mm/mmu_decl.h>
|
||||
|
||||
#include <sysdev/mv64x60.h>
|
||||
|
||||
#define MV64x60_MPP_CNTL_0 0x0000
|
||||
#define MV64x60_MPP_CNTL_2 0x0008
|
||||
|
||||
#define MV64x60_GPP_IO_CNTL 0x0000
|
||||
#define MV64x60_GPP_LEVEL_CNTL 0x0010
|
||||
#define MV64x60_GPP_VALUE_SET 0x0018
|
||||
|
||||
static void __iomem *mv64x60_mpp_reg_base;
|
||||
static void __iomem *mv64x60_gpp_reg_base;
|
||||
|
||||
static void __init c2k_setup_arch(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
phys_addr_t paddr;
|
||||
const unsigned int *reg;
|
||||
|
||||
/*
|
||||
* ioremap mpp and gpp registers in case they are later
|
||||
* needed by c2k_reset_board().
|
||||
*/
|
||||
np = of_find_compatible_node(NULL, NULL, "marvell,mv64360-mpp");
|
||||
reg = of_get_property(np, "reg", NULL);
|
||||
paddr = of_translate_address(np, reg);
|
||||
of_node_put(np);
|
||||
mv64x60_mpp_reg_base = ioremap(paddr, reg[1]);
|
||||
|
||||
np = of_find_compatible_node(NULL, NULL, "marvell,mv64360-gpp");
|
||||
reg = of_get_property(np, "reg", NULL);
|
||||
paddr = of_translate_address(np, reg);
|
||||
of_node_put(np);
|
||||
mv64x60_gpp_reg_base = ioremap(paddr, reg[1]);
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
mv64x60_pci_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void c2k_reset_board(void)
|
||||
{
|
||||
u32 temp;
|
||||
|
||||
local_irq_disable();
|
||||
|
||||
temp = in_le32(mv64x60_mpp_reg_base + MV64x60_MPP_CNTL_0);
|
||||
temp &= 0xFFFF0FFF;
|
||||
out_le32(mv64x60_mpp_reg_base + MV64x60_MPP_CNTL_0, temp);
|
||||
|
||||
temp = in_le32(mv64x60_gpp_reg_base + MV64x60_GPP_LEVEL_CNTL);
|
||||
temp |= 0x00000004;
|
||||
out_le32(mv64x60_gpp_reg_base + MV64x60_GPP_LEVEL_CNTL, temp);
|
||||
|
||||
temp = in_le32(mv64x60_gpp_reg_base + MV64x60_GPP_IO_CNTL);
|
||||
temp |= 0x00000004;
|
||||
out_le32(mv64x60_gpp_reg_base + MV64x60_GPP_IO_CNTL, temp);
|
||||
|
||||
temp = in_le32(mv64x60_mpp_reg_base + MV64x60_MPP_CNTL_2);
|
||||
temp &= 0xFFFF0FFF;
|
||||
out_le32(mv64x60_mpp_reg_base + MV64x60_MPP_CNTL_2, temp);
|
||||
|
||||
temp = in_le32(mv64x60_gpp_reg_base + MV64x60_GPP_LEVEL_CNTL);
|
||||
temp |= 0x00080000;
|
||||
out_le32(mv64x60_gpp_reg_base + MV64x60_GPP_LEVEL_CNTL, temp);
|
||||
|
||||
temp = in_le32(mv64x60_gpp_reg_base + MV64x60_GPP_IO_CNTL);
|
||||
temp |= 0x00080000;
|
||||
out_le32(mv64x60_gpp_reg_base + MV64x60_GPP_IO_CNTL, temp);
|
||||
|
||||
out_le32(mv64x60_gpp_reg_base + MV64x60_GPP_VALUE_SET, 0x00080004);
|
||||
}
|
||||
|
||||
static void c2k_restart(char *cmd)
|
||||
{
|
||||
c2k_reset_board();
|
||||
msleep(100);
|
||||
panic("restart failed\n");
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NOT_COHERENT_CACHE
|
||||
#define COHERENCY_SETTING "off"
|
||||
#else
|
||||
#define COHERENCY_SETTING "on"
|
||||
#endif
|
||||
|
||||
void c2k_show_cpuinfo(struct seq_file *m)
|
||||
{
|
||||
seq_printf(m, "Vendor\t\t: GEFanuc\n");
|
||||
seq_printf(m, "coherency\t: %s\n", COHERENCY_SETTING);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called very early, device-tree isn't unflattened
|
||||
*/
|
||||
static int __init c2k_probe(void)
|
||||
{
|
||||
unsigned long root = of_get_flat_dt_root();
|
||||
|
||||
if (!of_flat_dt_is_compatible(root, "GEFanuc,C2K"))
|
||||
return 0;
|
||||
|
||||
printk(KERN_INFO "Detected a GEFanuc C2K board\n");
|
||||
|
||||
_set_L2CR(0);
|
||||
_set_L2CR(L2CR_L2E | L2CR_L2PE | L2CR_L2I);
|
||||
return 1;
|
||||
}
|
||||
|
||||
define_machine(c2k) {
|
||||
.name = "C2K",
|
||||
.probe = c2k_probe,
|
||||
.setup_arch = c2k_setup_arch,
|
||||
.init_early = mv64x60_init_early,
|
||||
.show_cpuinfo = c2k_show_cpuinfo,
|
||||
.init_IRQ = mv64x60_init_irq,
|
||||
.get_irq = mv64x60_get_irq,
|
||||
.restart = c2k_restart,
|
||||
.calibrate_decr = generic_calibrate_decr,
|
||||
};
|
||||
255
arch/powerpc/platforms/embedded6xx/flipper-pic.c
Normal file
255
arch/powerpc/platforms/embedded6xx/flipper-pic.c
Normal file
|
|
@ -0,0 +1,255 @@
|
|||
/*
|
||||
* 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 <linux/of_address.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(struct irq_data *d)
|
||||
{
|
||||
int irq = irqd_to_hwirq(d);
|
||||
void __iomem *io_base = irq_data_get_irq_chip_data(d);
|
||||
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(struct irq_data *d)
|
||||
{
|
||||
int irq = irqd_to_hwirq(d);
|
||||
void __iomem *io_base = irq_data_get_irq_chip_data(d);
|
||||
|
||||
/* this is at least needed for RSW */
|
||||
out_be32(io_base + FLIPPER_ICR, 1 << irq);
|
||||
}
|
||||
|
||||
static void flipper_pic_mask(struct irq_data *d)
|
||||
{
|
||||
int irq = irqd_to_hwirq(d);
|
||||
void __iomem *io_base = irq_data_get_irq_chip_data(d);
|
||||
|
||||
clrbits32(io_base + FLIPPER_IMR, 1 << irq);
|
||||
}
|
||||
|
||||
static void flipper_pic_unmask(struct irq_data *d)
|
||||
{
|
||||
int irq = irqd_to_hwirq(d);
|
||||
void __iomem *io_base = irq_data_get_irq_chip_data(d);
|
||||
|
||||
setbits32(io_base + FLIPPER_IMR, 1 << irq);
|
||||
}
|
||||
|
||||
|
||||
static struct irq_chip flipper_pic = {
|
||||
.name = "flipper-pic",
|
||||
.irq_ack = flipper_pic_ack,
|
||||
.irq_mask_ack = flipper_pic_mask_and_ack,
|
||||
.irq_mask = flipper_pic_mask,
|
||||
.irq_unmask = flipper_pic_unmask,
|
||||
};
|
||||
|
||||
/*
|
||||
* IRQ host hooks.
|
||||
*
|
||||
*/
|
||||
|
||||
static struct irq_domain *flipper_irq_host;
|
||||
|
||||
static int flipper_pic_map(struct irq_domain *h, unsigned int virq,
|
||||
irq_hw_number_t hwirq)
|
||||
{
|
||||
irq_set_chip_data(virq, h->host_data);
|
||||
irq_set_status_flags(virq, IRQ_LEVEL);
|
||||
irq_set_chip_and_handler(virq, &flipper_pic, handle_level_irq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int flipper_pic_match(struct irq_domain *h, struct device_node *np)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static const struct irq_domain_ops flipper_irq_domain_ops = {
|
||||
.map = flipper_pic_map,
|
||||
.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_domain * __init flipper_pic_init(struct device_node *np)
|
||||
{
|
||||
struct device_node *pi;
|
||||
struct irq_domain *irq_domain = 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_domain = irq_domain_add_linear(np, FLIPPER_NR_IRQS,
|
||||
&flipper_irq_domain_ops, io_base);
|
||||
if (!irq_domain) {
|
||||
pr_err("failed to allocate irq_domain\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
out:
|
||||
return irq_domain;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
25
arch/powerpc/platforms/embedded6xx/flipper-pic.h
Normal file
25
arch/powerpc/platforms/embedded6xx/flipper-pic.h
Normal 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
|
||||
107
arch/powerpc/platforms/embedded6xx/gamecube.c
Normal file
107
arch/powerpc/platforms/embedded6xx/gamecube.c
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* 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();
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
|
||||
static const 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);
|
||||
|
||||
236
arch/powerpc/platforms/embedded6xx/hlwd-pic.c
Normal file
236
arch/powerpc/platforms/embedded6xx/hlwd-pic.c
Normal file
|
|
@ -0,0 +1,236 @@
|
|||
/*
|
||||
* 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/irq.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.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(struct irq_data *d)
|
||||
{
|
||||
int irq = irqd_to_hwirq(d);
|
||||
void __iomem *io_base = irq_data_get_irq_chip_data(d);
|
||||
u32 mask = 1 << irq;
|
||||
|
||||
clrbits32(io_base + HW_BROADWAY_IMR, mask);
|
||||
out_be32(io_base + HW_BROADWAY_ICR, mask);
|
||||
}
|
||||
|
||||
static void hlwd_pic_ack(struct irq_data *d)
|
||||
{
|
||||
int irq = irqd_to_hwirq(d);
|
||||
void __iomem *io_base = irq_data_get_irq_chip_data(d);
|
||||
|
||||
out_be32(io_base + HW_BROADWAY_ICR, 1 << irq);
|
||||
}
|
||||
|
||||
static void hlwd_pic_mask(struct irq_data *d)
|
||||
{
|
||||
int irq = irqd_to_hwirq(d);
|
||||
void __iomem *io_base = irq_data_get_irq_chip_data(d);
|
||||
|
||||
clrbits32(io_base + HW_BROADWAY_IMR, 1 << irq);
|
||||
}
|
||||
|
||||
static void hlwd_pic_unmask(struct irq_data *d)
|
||||
{
|
||||
int irq = irqd_to_hwirq(d);
|
||||
void __iomem *io_base = irq_data_get_irq_chip_data(d);
|
||||
|
||||
setbits32(io_base + HW_BROADWAY_IMR, 1 << irq);
|
||||
}
|
||||
|
||||
|
||||
static struct irq_chip hlwd_pic = {
|
||||
.name = "hlwd-pic",
|
||||
.irq_ack = hlwd_pic_ack,
|
||||
.irq_mask_ack = hlwd_pic_mask_and_ack,
|
||||
.irq_mask = hlwd_pic_mask,
|
||||
.irq_unmask = hlwd_pic_unmask,
|
||||
};
|
||||
|
||||
/*
|
||||
* IRQ host hooks.
|
||||
*
|
||||
*/
|
||||
|
||||
static struct irq_domain *hlwd_irq_host;
|
||||
|
||||
static int hlwd_pic_map(struct irq_domain *h, unsigned int virq,
|
||||
irq_hw_number_t hwirq)
|
||||
{
|
||||
irq_set_chip_data(virq, h->host_data);
|
||||
irq_set_status_flags(virq, IRQ_LEVEL);
|
||||
irq_set_chip_and_handler(virq, &hlwd_pic, handle_level_irq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct irq_domain_ops hlwd_irq_domain_ops = {
|
||||
.map = hlwd_pic_map,
|
||||
};
|
||||
|
||||
static unsigned int __hlwd_pic_get_irq(struct irq_domain *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_chip *chip = irq_desc_get_chip(desc);
|
||||
struct irq_domain *irq_domain = irq_get_handler_data(cascade_virq);
|
||||
unsigned int virq;
|
||||
|
||||
raw_spin_lock(&desc->lock);
|
||||
chip->irq_mask(&desc->irq_data); /* IRQ_LEVEL */
|
||||
raw_spin_unlock(&desc->lock);
|
||||
|
||||
virq = __hlwd_pic_get_irq(irq_domain);
|
||||
if (virq != NO_IRQ)
|
||||
generic_handle_irq(virq);
|
||||
else
|
||||
pr_err("spurious interrupt!\n");
|
||||
|
||||
raw_spin_lock(&desc->lock);
|
||||
chip->irq_ack(&desc->irq_data); /* IRQ_LEVEL */
|
||||
if (!irqd_irq_disabled(&desc->irq_data) && chip->irq_unmask)
|
||||
chip->irq_unmask(&desc->irq_data);
|
||||
raw_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_domain *hlwd_pic_init(struct device_node *np)
|
||||
{
|
||||
struct irq_domain *irq_domain;
|
||||
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_domain = irq_domain_add_linear(np, HLWD_NR_IRQS,
|
||||
&hlwd_irq_domain_ops, io_base);
|
||||
if (!irq_domain) {
|
||||
pr_err("failed to allocate irq_domain\n");
|
||||
iounmap(io_base);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return irq_domain;
|
||||
}
|
||||
|
||||
unsigned int hlwd_pic_get_irq(void)
|
||||
{
|
||||
return __hlwd_pic_get_irq(hlwd_irq_host);
|
||||
}
|
||||
|
||||
/*
|
||||
* Probe function.
|
||||
*
|
||||
*/
|
||||
|
||||
void hlwd_pic_probe(void)
|
||||
{
|
||||
struct irq_domain *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);
|
||||
irq_set_handler_data(cascade_virq, host);
|
||||
irq_set_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);
|
||||
}
|
||||
|
||||
22
arch/powerpc/platforms/embedded6xx/hlwd-pic.h
Normal file
22
arch/powerpc/platforms/embedded6xx/hlwd-pic.h
Normal 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
|
||||
285
arch/powerpc/platforms/embedded6xx/holly.c
Normal file
285
arch/powerpc/platforms/embedded6xx/holly.c
Normal file
|
|
@ -0,0 +1,285 @@
|
|||
/*
|
||||
* Board setup routines for the IBM 750GX/CL platform w/ TSI10x bridge
|
||||
*
|
||||
* Copyright 2007 IBM Corporation
|
||||
*
|
||||
* Stephen Winiecki <stevewin@us.ibm.com>
|
||||
* Josh Boyer <jwboyer@linux.vnet.ibm.com>
|
||||
*
|
||||
* Based on code from mpc7448_hpc2.c
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/kdev_t.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/root_dev.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <asm/time.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/udbg.h>
|
||||
#include <asm/tsi108.h>
|
||||
#include <asm/pci-bridge.h>
|
||||
#include <asm/reg.h>
|
||||
#include <mm/mmu_decl.h>
|
||||
#include <asm/tsi108_irq.h>
|
||||
#include <asm/tsi108_pci.h>
|
||||
#include <asm/mpic.h>
|
||||
|
||||
#undef DEBUG
|
||||
|
||||
#define HOLLY_PCI_CFG_PHYS 0x7c000000
|
||||
|
||||
int holly_exclude_device(struct pci_controller *hose, u_char bus, u_char devfn)
|
||||
{
|
||||
if (bus == 0 && PCI_SLOT(devfn) == 0)
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
else
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
static void holly_remap_bridge(void)
|
||||
{
|
||||
u32 lut_val, lut_addr;
|
||||
int i;
|
||||
|
||||
printk(KERN_INFO "Remapping PCI bridge\n");
|
||||
|
||||
/* Re-init the PCI bridge and LUT registers to have mappings that don't
|
||||
* rely on PIBS
|
||||
*/
|
||||
lut_addr = 0x900;
|
||||
for (i = 0; i < 31; i++) {
|
||||
tsi108_write_reg(TSI108_PB_OFFSET + lut_addr, 0x00000201);
|
||||
lut_addr += 4;
|
||||
tsi108_write_reg(TSI108_PB_OFFSET + lut_addr, 0x0);
|
||||
lut_addr += 4;
|
||||
}
|
||||
|
||||
/* Reserve the last LUT entry for PCI I/O space */
|
||||
tsi108_write_reg(TSI108_PB_OFFSET + lut_addr, 0x00000241);
|
||||
lut_addr += 4;
|
||||
tsi108_write_reg(TSI108_PB_OFFSET + lut_addr, 0x0);
|
||||
|
||||
/* Map PCI I/O space */
|
||||
tsi108_write_reg(TSI108_PCI_PFAB_IO_UPPER, 0x0);
|
||||
tsi108_write_reg(TSI108_PCI_PFAB_IO, 0x1);
|
||||
|
||||
/* Map PCI CFG space */
|
||||
tsi108_write_reg(TSI108_PCI_PFAB_BAR0_UPPER, 0x0);
|
||||
tsi108_write_reg(TSI108_PCI_PFAB_BAR0, 0x7c000000 | 0x01);
|
||||
|
||||
/* We don't need MEM32 and PRM remapping so disable them */
|
||||
tsi108_write_reg(TSI108_PCI_PFAB_MEM32, 0x0);
|
||||
tsi108_write_reg(TSI108_PCI_PFAB_PFM3, 0x0);
|
||||
tsi108_write_reg(TSI108_PCI_PFAB_PFM4, 0x0);
|
||||
|
||||
/* Set P2O_BAR0 */
|
||||
tsi108_write_reg(TSI108_PCI_P2O_BAR0_UPPER, 0x0);
|
||||
tsi108_write_reg(TSI108_PCI_P2O_BAR0, 0xc0000000);
|
||||
|
||||
/* Init the PCI LUTs to do no remapping */
|
||||
lut_addr = 0x500;
|
||||
lut_val = 0x00000002;
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
tsi108_write_reg(TSI108_PCI_OFFSET + lut_addr, lut_val);
|
||||
lut_addr += 4;
|
||||
tsi108_write_reg(TSI108_PCI_OFFSET + lut_addr, 0x40000000);
|
||||
lut_addr += 4;
|
||||
lut_val += 0x02000000;
|
||||
}
|
||||
tsi108_write_reg(TSI108_PCI_P2O_PAGE_SIZES, 0x00007900);
|
||||
|
||||
/* Set 64-bit PCI bus address for system memory */
|
||||
tsi108_write_reg(TSI108_PCI_P2O_BAR2_UPPER, 0x0);
|
||||
tsi108_write_reg(TSI108_PCI_P2O_BAR2, 0x0);
|
||||
}
|
||||
|
||||
static void __init holly_setup_arch(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
|
||||
if (ppc_md.progress)
|
||||
ppc_md.progress("holly_setup_arch():set_bridge", 0);
|
||||
|
||||
tsi108_csr_vir_base = get_vir_csrbase();
|
||||
|
||||
/* setup PCI host bridge */
|
||||
holly_remap_bridge();
|
||||
|
||||
np = of_find_node_by_type(NULL, "pci");
|
||||
if (np)
|
||||
tsi108_setup_pci(np, HOLLY_PCI_CFG_PHYS, 1);
|
||||
|
||||
ppc_md.pci_exclude_device = holly_exclude_device;
|
||||
if (ppc_md.progress)
|
||||
ppc_md.progress("tsi108: resources set", 0x100);
|
||||
|
||||
printk(KERN_INFO "PPC750GX/CL Platform\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Interrupt setup and service. Interrupts on the holly come
|
||||
* from the four external INT pins, PCI interrupts are routed via
|
||||
* PCI interrupt control registers, it generates internal IRQ23
|
||||
*
|
||||
* Interrupt routing on the Holly Board:
|
||||
* TSI108:PB_INT[0] -> CPU0:INT#
|
||||
* TSI108:PB_INT[1] -> CPU0:MCP#
|
||||
* TSI108:PB_INT[2] -> N/C
|
||||
* TSI108:PB_INT[3] -> N/C
|
||||
*/
|
||||
static void __init holly_init_IRQ(void)
|
||||
{
|
||||
struct mpic *mpic;
|
||||
#ifdef CONFIG_PCI
|
||||
unsigned int cascade_pci_irq;
|
||||
struct device_node *tsi_pci;
|
||||
struct device_node *cascade_node = NULL;
|
||||
#endif
|
||||
|
||||
mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN |
|
||||
MPIC_SPV_EOI | MPIC_NO_PTHROU_DIS | MPIC_REGSET_TSI108,
|
||||
24, 0,
|
||||
"Tsi108_PIC");
|
||||
|
||||
BUG_ON(mpic == NULL);
|
||||
|
||||
mpic_assign_isu(mpic, 0, mpic->paddr + 0x100);
|
||||
|
||||
mpic_init(mpic);
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
tsi_pci = of_find_node_by_type(NULL, "pci");
|
||||
if (tsi_pci == NULL) {
|
||||
printk(KERN_ERR "%s: No tsi108 pci node found !\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
cascade_node = of_find_node_by_type(NULL, "pic-router");
|
||||
if (cascade_node == NULL) {
|
||||
printk(KERN_ERR "%s: No tsi108 pci cascade node found !\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
cascade_pci_irq = irq_of_parse_and_map(tsi_pci, 0);
|
||||
pr_debug("%s: tsi108 cascade_pci_irq = 0x%x\n", __func__, (u32) cascade_pci_irq);
|
||||
tsi108_pci_int_init(cascade_node);
|
||||
irq_set_handler_data(cascade_pci_irq, mpic);
|
||||
irq_set_chained_handler(cascade_pci_irq, tsi108_irq_cascade);
|
||||
#endif
|
||||
/* Configure MPIC outputs to CPU0 */
|
||||
tsi108_write_reg(TSI108_MPIC_OFFSET + 0x30c, 0);
|
||||
}
|
||||
|
||||
void holly_show_cpuinfo(struct seq_file *m)
|
||||
{
|
||||
seq_printf(m, "vendor\t\t: IBM\n");
|
||||
seq_printf(m, "machine\t\t: PPC750 GX/CL\n");
|
||||
}
|
||||
|
||||
void holly_restart(char *cmd)
|
||||
{
|
||||
__be32 __iomem *ocn_bar1 = NULL;
|
||||
unsigned long bar;
|
||||
struct device_node *bridge = NULL;
|
||||
const void *prop;
|
||||
int size;
|
||||
phys_addr_t addr = 0xc0000000;
|
||||
|
||||
local_irq_disable();
|
||||
|
||||
bridge = of_find_node_by_type(NULL, "tsi-bridge");
|
||||
if (bridge) {
|
||||
prop = of_get_property(bridge, "reg", &size);
|
||||
addr = of_translate_address(bridge, prop);
|
||||
}
|
||||
addr += (TSI108_PB_OFFSET + 0x414);
|
||||
|
||||
ocn_bar1 = ioremap(addr, 0x4);
|
||||
|
||||
/* Turn on the BOOT bit so the addresses are correctly
|
||||
* routed to the HLP interface */
|
||||
bar = ioread32be(ocn_bar1);
|
||||
bar |= 2;
|
||||
iowrite32be(bar, ocn_bar1);
|
||||
iosync();
|
||||
|
||||
/* Set SRR0 to the reset vector and turn on MSR_IP */
|
||||
mtspr(SPRN_SRR0, 0xfff00100);
|
||||
mtspr(SPRN_SRR1, MSR_IP);
|
||||
|
||||
/* Do an rfi to jump back to firmware. Somewhat evil,
|
||||
* but it works
|
||||
*/
|
||||
__asm__ __volatile__("rfi" : : : "memory");
|
||||
|
||||
/* Spin until reset happens. Shouldn't really get here */
|
||||
for (;;) ;
|
||||
}
|
||||
|
||||
void holly_power_off(void)
|
||||
{
|
||||
local_irq_disable();
|
||||
/* No way to shut power off with software */
|
||||
for (;;) ;
|
||||
}
|
||||
|
||||
void holly_halt(void)
|
||||
{
|
||||
holly_power_off();
|
||||
}
|
||||
|
||||
/*
|
||||
* Called very early, device-tree isn't unflattened
|
||||
*/
|
||||
static int __init holly_probe(void)
|
||||
{
|
||||
unsigned long root = of_get_flat_dt_root();
|
||||
|
||||
if (!of_flat_dt_is_compatible(root, "ibm,holly"))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ppc750_machine_check_exception(struct pt_regs *regs)
|
||||
{
|
||||
const struct exception_table_entry *entry;
|
||||
|
||||
/* Are we prepared to handle this fault */
|
||||
if ((entry = search_exception_tables(regs->nip)) != NULL) {
|
||||
tsi108_clear_pci_cfg_error();
|
||||
regs->msr |= MSR_RI;
|
||||
regs->nip = entry->fixup;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
define_machine(holly){
|
||||
.name = "PPC750 GX/CL TSI",
|
||||
.probe = holly_probe,
|
||||
.setup_arch = holly_setup_arch,
|
||||
.init_IRQ = holly_init_IRQ,
|
||||
.show_cpuinfo = holly_show_cpuinfo,
|
||||
.get_irq = mpic_get_irq,
|
||||
.restart = holly_restart,
|
||||
.calibrate_decr = generic_calibrate_decr,
|
||||
.machine_check_exception = ppc750_machine_check_exception,
|
||||
.progress = udbg_progress,
|
||||
};
|
||||
164
arch/powerpc/platforms/embedded6xx/linkstation.c
Normal file
164
arch/powerpc/platforms/embedded6xx/linkstation.c
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
/*
|
||||
* Board setup routines for the Buffalo Linkstation / Kurobox Platform.
|
||||
*
|
||||
* Copyright (C) 2006 G. Liakhovetski (g.liakhovetski@gmx.de)
|
||||
*
|
||||
* Based on sandpoint.c by Mark A. Greer
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public License
|
||||
* version 2. This program is licensed "as is" without any warranty of
|
||||
* any kind, whether express or implied.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/initrd.h>
|
||||
#include <linux/of_platform.h>
|
||||
|
||||
#include <asm/time.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/mpic.h>
|
||||
#include <asm/pci-bridge.h>
|
||||
|
||||
#include "mpc10x.h"
|
||||
|
||||
static const struct of_device_id of_bus_ids[] __initconst = {
|
||||
{ .type = "soc", },
|
||||
{ .compatible = "simple-bus", },
|
||||
{},
|
||||
};
|
||||
|
||||
static int __init declare_of_platform_devices(void)
|
||||
{
|
||||
of_platform_bus_probe(NULL, of_bus_ids, NULL);
|
||||
return 0;
|
||||
}
|
||||
machine_device_initcall(linkstation, declare_of_platform_devices);
|
||||
|
||||
static int __init linkstation_add_bridge(struct device_node *dev)
|
||||
{
|
||||
#ifdef CONFIG_PCI
|
||||
int len;
|
||||
struct pci_controller *hose;
|
||||
const int *bus_range;
|
||||
|
||||
printk("Adding PCI host bridge %s\n", dev->full_name);
|
||||
|
||||
bus_range = of_get_property(dev, "bus-range", &len);
|
||||
if (bus_range == NULL || len < 2 * sizeof(int))
|
||||
printk(KERN_WARNING "Can't get bus-range for %s, assume"
|
||||
" bus 0\n", dev->full_name);
|
||||
|
||||
hose = pcibios_alloc_controller(dev);
|
||||
if (hose == NULL)
|
||||
return -ENOMEM;
|
||||
hose->first_busno = bus_range ? bus_range[0] : 0;
|
||||
hose->last_busno = bus_range ? bus_range[1] : 0xff;
|
||||
setup_indirect_pci(hose, 0xfec00000, 0xfee00000, 0);
|
||||
|
||||
/* Interpret the "ranges" property */
|
||||
/* This also maps the I/O region and sets isa_io/mem_base */
|
||||
pci_process_bridge_OF_ranges(hose, dev, 1);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __init linkstation_setup_arch(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
|
||||
/* Lookup PCI host bridges */
|
||||
for_each_compatible_node(np, "pci", "mpc10x-pci")
|
||||
linkstation_add_bridge(np);
|
||||
|
||||
printk(KERN_INFO "BUFFALO Network Attached Storage Series\n");
|
||||
printk(KERN_INFO "(C) 2002-2005 BUFFALO INC.\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Interrupt setup and service. Interrupts on the linkstation come
|
||||
* from the four PCI slots plus onboard 8241 devices: I2C, DUART.
|
||||
*/
|
||||
static void __init linkstation_init_IRQ(void)
|
||||
{
|
||||
struct mpic *mpic;
|
||||
|
||||
mpic = mpic_alloc(NULL, 0, 0, 4, 0, " EPIC ");
|
||||
BUG_ON(mpic == NULL);
|
||||
|
||||
/* PCI IRQs */
|
||||
mpic_assign_isu(mpic, 0, mpic->paddr + 0x10200);
|
||||
|
||||
/* I2C */
|
||||
mpic_assign_isu(mpic, 1, mpic->paddr + 0x11000);
|
||||
|
||||
/* ttyS0, ttyS1 */
|
||||
mpic_assign_isu(mpic, 2, mpic->paddr + 0x11100);
|
||||
|
||||
mpic_init(mpic);
|
||||
}
|
||||
|
||||
extern void avr_uart_configure(void);
|
||||
extern void avr_uart_send(const char);
|
||||
|
||||
static void linkstation_restart(char *cmd)
|
||||
{
|
||||
local_irq_disable();
|
||||
|
||||
/* Reset system via AVR */
|
||||
avr_uart_configure();
|
||||
/* Send reboot command */
|
||||
avr_uart_send('C');
|
||||
|
||||
for(;;) /* Spin until reset happens */
|
||||
avr_uart_send('G'); /* "kick" */
|
||||
}
|
||||
|
||||
static void linkstation_power_off(void)
|
||||
{
|
||||
local_irq_disable();
|
||||
|
||||
/* Power down system via AVR */
|
||||
avr_uart_configure();
|
||||
/* send shutdown command */
|
||||
avr_uart_send('E');
|
||||
|
||||
for(;;) /* Spin until power-off happens */
|
||||
avr_uart_send('G'); /* "kick" */
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
static void linkstation_halt(void)
|
||||
{
|
||||
linkstation_power_off();
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
static void linkstation_show_cpuinfo(struct seq_file *m)
|
||||
{
|
||||
seq_printf(m, "vendor\t\t: Buffalo Technology\n");
|
||||
seq_printf(m, "machine\t\t: Linkstation I/Kurobox(HG)\n");
|
||||
}
|
||||
|
||||
static int __init linkstation_probe(void)
|
||||
{
|
||||
unsigned long root;
|
||||
|
||||
root = of_get_flat_dt_root();
|
||||
|
||||
if (!of_flat_dt_is_compatible(root, "linkstation"))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
define_machine(linkstation){
|
||||
.name = "Buffalo Linkstation",
|
||||
.probe = linkstation_probe,
|
||||
.setup_arch = linkstation_setup_arch,
|
||||
.init_IRQ = linkstation_init_IRQ,
|
||||
.show_cpuinfo = linkstation_show_cpuinfo,
|
||||
.get_irq = mpic_get_irq,
|
||||
.restart = linkstation_restart,
|
||||
.power_off = linkstation_power_off,
|
||||
.halt = linkstation_halt,
|
||||
.calibrate_decr = generic_calibrate_decr,
|
||||
};
|
||||
142
arch/powerpc/platforms/embedded6xx/ls_uart.c
Normal file
142
arch/powerpc/platforms/embedded6xx/ls_uart.c
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
* AVR power-management chip interface for the Buffalo Linkstation /
|
||||
* Kurobox Platform.
|
||||
*
|
||||
* Author: 2006 (c) G. Liakhovetski
|
||||
* g.liakhovetski@gmx.de
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public License
|
||||
* version 2. This program is licensed "as is" without any warranty of
|
||||
* any kind, whether express or implied.
|
||||
*/
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/serial_reg.h>
|
||||
#include <linux/serial_8250.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/termbits.h>
|
||||
|
||||
#include "mpc10x.h"
|
||||
|
||||
static void __iomem *avr_addr;
|
||||
static unsigned long avr_clock;
|
||||
|
||||
static struct work_struct wd_work;
|
||||
|
||||
static void wd_stop(struct work_struct *unused)
|
||||
{
|
||||
const char string[] = "AAAAFFFFJJJJ>>>>VVVV>>>>ZZZZVVVVKKKK";
|
||||
int i = 0, rescue = 8;
|
||||
int len = strlen(string);
|
||||
|
||||
while (rescue--) {
|
||||
int j;
|
||||
char lsr = in_8(avr_addr + UART_LSR);
|
||||
|
||||
if (lsr & (UART_LSR_THRE | UART_LSR_TEMT)) {
|
||||
for (j = 0; j < 16 && i < len; j++, i++)
|
||||
out_8(avr_addr + UART_TX, string[i]);
|
||||
if (i == len) {
|
||||
/* Read "OK" back: 4ms for the last "KKKK"
|
||||
plus a couple bytes back */
|
||||
msleep(7);
|
||||
printk("linkstation: disarming the AVR watchdog: ");
|
||||
while (in_8(avr_addr + UART_LSR) & UART_LSR_DR)
|
||||
printk("%c", in_8(avr_addr + UART_RX));
|
||||
break;
|
||||
}
|
||||
}
|
||||
msleep(17);
|
||||
}
|
||||
printk("\n");
|
||||
}
|
||||
|
||||
#define AVR_QUOT(clock) ((clock) + 8 * 9600) / (16 * 9600)
|
||||
|
||||
void avr_uart_configure(void)
|
||||
{
|
||||
unsigned char cval = UART_LCR_WLEN8;
|
||||
unsigned int quot = AVR_QUOT(avr_clock);
|
||||
|
||||
if (!avr_addr || !avr_clock)
|
||||
return;
|
||||
|
||||
out_8(avr_addr + UART_LCR, cval); /* initialise UART */
|
||||
out_8(avr_addr + UART_MCR, 0);
|
||||
out_8(avr_addr + UART_IER, 0);
|
||||
|
||||
cval |= UART_LCR_STOP | UART_LCR_PARITY | UART_LCR_EPAR;
|
||||
|
||||
out_8(avr_addr + UART_LCR, cval); /* Set character format */
|
||||
|
||||
out_8(avr_addr + UART_LCR, cval | UART_LCR_DLAB); /* set DLAB */
|
||||
out_8(avr_addr + UART_DLL, quot & 0xff); /* LS of divisor */
|
||||
out_8(avr_addr + UART_DLM, quot >> 8); /* MS of divisor */
|
||||
out_8(avr_addr + UART_LCR, cval); /* reset DLAB */
|
||||
out_8(avr_addr + UART_FCR, UART_FCR_ENABLE_FIFO); /* enable FIFO */
|
||||
}
|
||||
|
||||
void avr_uart_send(const char c)
|
||||
{
|
||||
if (!avr_addr || !avr_clock)
|
||||
return;
|
||||
|
||||
out_8(avr_addr + UART_TX, c);
|
||||
out_8(avr_addr + UART_TX, c);
|
||||
out_8(avr_addr + UART_TX, c);
|
||||
out_8(avr_addr + UART_TX, c);
|
||||
}
|
||||
|
||||
static void __init ls_uart_init(void)
|
||||
{
|
||||
local_irq_disable();
|
||||
|
||||
#ifndef CONFIG_SERIAL_8250
|
||||
out_8(avr_addr + UART_FCR, UART_FCR_ENABLE_FIFO); /* enable FIFO */
|
||||
out_8(avr_addr + UART_FCR, UART_FCR_ENABLE_FIFO |
|
||||
UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); /* clear FIFOs */
|
||||
out_8(avr_addr + UART_FCR, 0);
|
||||
out_8(avr_addr + UART_IER, 0);
|
||||
|
||||
/* Clear up interrupts */
|
||||
(void) in_8(avr_addr + UART_LSR);
|
||||
(void) in_8(avr_addr + UART_RX);
|
||||
(void) in_8(avr_addr + UART_IIR);
|
||||
(void) in_8(avr_addr + UART_MSR);
|
||||
#endif
|
||||
avr_uart_configure();
|
||||
|
||||
local_irq_enable();
|
||||
}
|
||||
|
||||
static int __init ls_uarts_init(void)
|
||||
{
|
||||
struct device_node *avr;
|
||||
phys_addr_t phys_addr;
|
||||
int len;
|
||||
|
||||
avr = of_find_node_by_path("/soc10x/serial@80004500");
|
||||
if (!avr)
|
||||
return -EINVAL;
|
||||
|
||||
avr_clock = *(u32*)of_get_property(avr, "clock-frequency", &len);
|
||||
phys_addr = ((u32*)of_get_property(avr, "reg", &len))[0];
|
||||
|
||||
if (!avr_clock || !phys_addr)
|
||||
return -EINVAL;
|
||||
|
||||
avr_addr = ioremap(phys_addr, 32);
|
||||
if (!avr_addr)
|
||||
return -EFAULT;
|
||||
|
||||
ls_uart_init();
|
||||
|
||||
INIT_WORK(&wd_work, wd_stop);
|
||||
schedule_work(&wd_work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
machine_late_initcall(linkstation, ls_uarts_init);
|
||||
169
arch/powerpc/platforms/embedded6xx/mpc10x.h
Normal file
169
arch/powerpc/platforms/embedded6xx/mpc10x.h
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
* Common routines for the Motorola SPS MPC106/8240/107 Host bridge/Mem
|
||||
* ctlr/EPIC/etc.
|
||||
*
|
||||
* Author: Mark A. Greer
|
||||
* mgreer@mvista.com
|
||||
*
|
||||
* 2001 (c) MontaVista, Software, Inc. This file is licensed under
|
||||
* the terms of the GNU General Public License version 2. This program
|
||||
* is licensed "as is" without any warranty of any kind, whether express
|
||||
* or implied.
|
||||
*/
|
||||
#ifndef __PPC_KERNEL_MPC10X_H
|
||||
#define __PPC_KERNEL_MPC10X_H
|
||||
|
||||
#include <linux/pci_ids.h>
|
||||
#include <asm/pci-bridge.h>
|
||||
|
||||
/*
|
||||
* The values here don't completely map everything but should work in most
|
||||
* cases.
|
||||
*
|
||||
* MAP A (PReP Map)
|
||||
* Processor: 0x80000000 - 0x807fffff -> PCI I/O: 0x00000000 - 0x007fffff
|
||||
* Processor: 0xc0000000 - 0xdfffffff -> PCI MEM: 0x00000000 - 0x1fffffff
|
||||
* PCI MEM: 0x80000000 -> Processor System Memory: 0x00000000
|
||||
* EUMB mapped to: ioremap_base - 0x00100000 (ioremap_base - 1 MB)
|
||||
*
|
||||
* MAP B (CHRP Map)
|
||||
* Processor: 0xfe000000 - 0xfebfffff -> PCI I/O: 0x00000000 - 0x00bfffff
|
||||
* Processor: 0x80000000 - 0xbfffffff -> PCI MEM: 0x80000000 - 0xbfffffff
|
||||
* PCI MEM: 0x00000000 -> Processor System Memory: 0x00000000
|
||||
* EUMB mapped to: ioremap_base - 0x00100000 (ioremap_base - 1 MB)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Define the vendor/device IDs for the various bridges--should be added to
|
||||
* <linux/pci_ids.h>
|
||||
*/
|
||||
#define MPC10X_BRIDGE_106 ((PCI_DEVICE_ID_MOTOROLA_MPC106 << 16) | \
|
||||
PCI_VENDOR_ID_MOTOROLA)
|
||||
#define MPC10X_BRIDGE_8240 ((0x0003 << 16) | PCI_VENDOR_ID_MOTOROLA)
|
||||
#define MPC10X_BRIDGE_107 ((0x0004 << 16) | PCI_VENDOR_ID_MOTOROLA)
|
||||
#define MPC10X_BRIDGE_8245 ((0x0006 << 16) | PCI_VENDOR_ID_MOTOROLA)
|
||||
|
||||
/* Define the type of map to use */
|
||||
#define MPC10X_MEM_MAP_A 1
|
||||
#define MPC10X_MEM_MAP_B 2
|
||||
|
||||
/* Map A (PReP Map) Defines */
|
||||
#define MPC10X_MAPA_CNFG_ADDR 0x80000cf8
|
||||
#define MPC10X_MAPA_CNFG_DATA 0x80000cfc
|
||||
|
||||
#define MPC10X_MAPA_ISA_IO_BASE 0x80000000
|
||||
#define MPC10X_MAPA_ISA_MEM_BASE 0xc0000000
|
||||
#define MPC10X_MAPA_DRAM_OFFSET 0x80000000
|
||||
|
||||
#define MPC10X_MAPA_PCI_INTACK_ADDR 0xbffffff0
|
||||
#define MPC10X_MAPA_PCI_IO_START 0x00000000
|
||||
#define MPC10X_MAPA_PCI_IO_END (0x00800000 - 1)
|
||||
#define MPC10X_MAPA_PCI_MEM_START 0x00000000
|
||||
#define MPC10X_MAPA_PCI_MEM_END (0x20000000 - 1)
|
||||
|
||||
#define MPC10X_MAPA_PCI_MEM_OFFSET (MPC10X_MAPA_ISA_MEM_BASE - \
|
||||
MPC10X_MAPA_PCI_MEM_START)
|
||||
|
||||
/* Map B (CHRP Map) Defines */
|
||||
#define MPC10X_MAPB_CNFG_ADDR 0xfec00000
|
||||
#define MPC10X_MAPB_CNFG_DATA 0xfee00000
|
||||
|
||||
#define MPC10X_MAPB_ISA_IO_BASE 0xfe000000
|
||||
#define MPC10X_MAPB_ISA_MEM_BASE 0x80000000
|
||||
#define MPC10X_MAPB_DRAM_OFFSET 0x00000000
|
||||
|
||||
#define MPC10X_MAPB_PCI_INTACK_ADDR 0xfef00000
|
||||
#define MPC10X_MAPB_PCI_IO_START 0x00000000
|
||||
#define MPC10X_MAPB_PCI_IO_END (0x00c00000 - 1)
|
||||
#define MPC10X_MAPB_PCI_MEM_START 0x80000000
|
||||
#define MPC10X_MAPB_PCI_MEM_END (0xc0000000 - 1)
|
||||
|
||||
#define MPC10X_MAPB_PCI_MEM_OFFSET (MPC10X_MAPB_ISA_MEM_BASE - \
|
||||
MPC10X_MAPB_PCI_MEM_START)
|
||||
|
||||
/* Miscellaneous Configuration register offsets */
|
||||
#define MPC10X_CFG_PIR_REG 0x09
|
||||
#define MPC10X_CFG_PIR_HOST_BRIDGE 0x00
|
||||
#define MPC10X_CFG_PIR_AGENT 0x01
|
||||
|
||||
#define MPC10X_CFG_EUMBBAR 0x78
|
||||
|
||||
#define MPC10X_CFG_PICR1_REG 0xa8
|
||||
#define MPC10X_CFG_PICR1_ADDR_MAP_MASK 0x00010000
|
||||
#define MPC10X_CFG_PICR1_ADDR_MAP_A 0x00010000
|
||||
#define MPC10X_CFG_PICR1_ADDR_MAP_B 0x00000000
|
||||
#define MPC10X_CFG_PICR1_SPEC_PCI_RD 0x00000004
|
||||
#define MPC10X_CFG_PICR1_ST_GATH_EN 0x00000040
|
||||
|
||||
#define MPC10X_CFG_PICR2_REG 0xac
|
||||
#define MPC10X_CFG_PICR2_COPYBACK_OPT 0x00000001
|
||||
|
||||
#define MPC10X_CFG_MAPB_OPTIONS_REG 0xe0
|
||||
#define MPC10X_CFG_MAPB_OPTIONS_CFAE 0x80 /* CPU_FD_ALIAS_EN */
|
||||
#define MPC10X_CFG_MAPB_OPTIONS_PFAE 0x40 /* PCI_FD_ALIAS_EN */
|
||||
#define MPC10X_CFG_MAPB_OPTIONS_DR 0x20 /* DLL_RESET */
|
||||
#define MPC10X_CFG_MAPB_OPTIONS_PCICH 0x08 /* PCI_COMPATIBILITY_HOLE */
|
||||
#define MPC10X_CFG_MAPB_OPTIONS_PROCCH 0x04 /* PROC_COMPATIBILITY_HOLE */
|
||||
|
||||
/* Define offsets for the memory controller registers in the config space */
|
||||
#define MPC10X_MCTLR_MEM_START_1 0x80 /* Banks 0-3 */
|
||||
#define MPC10X_MCTLR_MEM_START_2 0x84 /* Banks 4-7 */
|
||||
#define MPC10X_MCTLR_EXT_MEM_START_1 0x88 /* Banks 0-3 */
|
||||
#define MPC10X_MCTLR_EXT_MEM_START_2 0x8c /* Banks 4-7 */
|
||||
|
||||
#define MPC10X_MCTLR_MEM_END_1 0x90 /* Banks 0-3 */
|
||||
#define MPC10X_MCTLR_MEM_END_2 0x94 /* Banks 4-7 */
|
||||
#define MPC10X_MCTLR_EXT_MEM_END_1 0x98 /* Banks 0-3 */
|
||||
#define MPC10X_MCTLR_EXT_MEM_END_2 0x9c /* Banks 4-7 */
|
||||
|
||||
#define MPC10X_MCTLR_MEM_BANK_ENABLES 0xa0
|
||||
|
||||
/* Define some offset in the EUMB */
|
||||
#define MPC10X_EUMB_SIZE 0x00100000 /* Total EUMB size (1MB) */
|
||||
|
||||
#define MPC10X_EUMB_MU_OFFSET 0x00000000 /* Msg Unit reg offset */
|
||||
#define MPC10X_EUMB_MU_SIZE 0x00001000 /* Msg Unit reg size */
|
||||
#define MPC10X_EUMB_DMA_OFFSET 0x00001000 /* DMA Unit reg offset */
|
||||
#define MPC10X_EUMB_DMA_SIZE 0x00001000 /* DMA Unit reg size */
|
||||
#define MPC10X_EUMB_ATU_OFFSET 0x00002000 /* Addr xlate reg offset */
|
||||
#define MPC10X_EUMB_ATU_SIZE 0x00001000 /* Addr xlate reg size */
|
||||
#define MPC10X_EUMB_I2C_OFFSET 0x00003000 /* I2C Unit reg offset */
|
||||
#define MPC10X_EUMB_I2C_SIZE 0x00001000 /* I2C Unit reg size */
|
||||
#define MPC10X_EUMB_DUART_OFFSET 0x00004000 /* DUART Unit reg offset (8245) */
|
||||
#define MPC10X_EUMB_DUART_SIZE 0x00001000 /* DUART Unit reg size (8245) */
|
||||
#define MPC10X_EUMB_EPIC_OFFSET 0x00040000 /* EPIC offset in EUMB */
|
||||
#define MPC10X_EUMB_EPIC_SIZE 0x00030000 /* EPIC size */
|
||||
#define MPC10X_EUMB_PM_OFFSET 0x000fe000 /* Performance Monitor reg offset (8245) */
|
||||
#define MPC10X_EUMB_PM_SIZE 0x00001000 /* Performance Monitor reg size (8245) */
|
||||
#define MPC10X_EUMB_WP_OFFSET 0x000ff000 /* Data path diagnostic, watchpoint reg offset */
|
||||
#define MPC10X_EUMB_WP_SIZE 0x00001000 /* Data path diagnostic, watchpoint reg size */
|
||||
|
||||
/*
|
||||
* Define some recommended places to put the EUMB regs.
|
||||
* For both maps, recommend putting the EUMB from 0xeff00000 to 0xefffffff.
|
||||
*/
|
||||
extern unsigned long ioremap_base;
|
||||
#define MPC10X_MAPA_EUMB_BASE (ioremap_base - MPC10X_EUMB_SIZE)
|
||||
#define MPC10X_MAPB_EUMB_BASE MPC10X_MAPA_EUMB_BASE
|
||||
|
||||
enum ppc_sys_devices {
|
||||
MPC10X_IIC1,
|
||||
MPC10X_DMA0,
|
||||
MPC10X_DMA1,
|
||||
MPC10X_UART0,
|
||||
MPC10X_UART1,
|
||||
NUM_PPC_SYS_DEVS,
|
||||
};
|
||||
|
||||
int mpc10x_bridge_init(struct pci_controller *hose,
|
||||
uint current_map,
|
||||
uint new_map,
|
||||
uint phys_eumb_base);
|
||||
unsigned long mpc10x_get_mem_size(uint mem_map);
|
||||
int mpc10x_enable_store_gathering(struct pci_controller *hose);
|
||||
int mpc10x_disable_store_gathering(struct pci_controller *hose);
|
||||
|
||||
/* For MPC107 boards that use the built-in openpic */
|
||||
void mpc10x_set_openpic(void);
|
||||
|
||||
#endif /* __PPC_KERNEL_MPC10X_H */
|
||||
207
arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
Normal file
207
arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
/*
|
||||
* mpc7448_hpc2.c
|
||||
*
|
||||
* Board setup routines for the Freescale mpc7448hpc2(taiga) platform
|
||||
*
|
||||
* Author: Jacob Pan
|
||||
* jacob.pan@freescale.com
|
||||
* Author: Xianghua Xiao
|
||||
* x.xiao@freescale.com
|
||||
* Maintainer: Roy Zang <tie-fei.zang@freescale.com>
|
||||
* Add Flat Device Tree support fot mpc7448hpc2 board
|
||||
*
|
||||
* Copyright 2004-2006 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* 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/stddef.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/kdev_t.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/root_dev.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/serial_core.h>
|
||||
|
||||
#include <asm/time.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/udbg.h>
|
||||
#include <asm/tsi108.h>
|
||||
#include <asm/pci-bridge.h>
|
||||
#include <asm/reg.h>
|
||||
#include <mm/mmu_decl.h>
|
||||
#include <asm/tsi108_pci.h>
|
||||
#include <asm/tsi108_irq.h>
|
||||
#include <asm/mpic.h>
|
||||
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
#define DBG(fmt...) do { printk(fmt); } while(0)
|
||||
#else
|
||||
#define DBG(fmt...) do { } while(0)
|
||||
#endif
|
||||
|
||||
#define MPC7448HPC2_PCI_CFG_PHYS 0xfb000000
|
||||
|
||||
int mpc7448_hpc2_exclude_device(struct pci_controller *hose,
|
||||
u_char bus, u_char devfn)
|
||||
{
|
||||
if (bus == 0 && PCI_SLOT(devfn) == 0)
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
else
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
static void __init mpc7448_hpc2_setup_arch(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
if (ppc_md.progress)
|
||||
ppc_md.progress("mpc7448_hpc2_setup_arch():set_bridge", 0);
|
||||
|
||||
tsi108_csr_vir_base = get_vir_csrbase();
|
||||
|
||||
/* setup PCI host bridge */
|
||||
#ifdef CONFIG_PCI
|
||||
for_each_compatible_node(np, "pci", "tsi108-pci")
|
||||
tsi108_setup_pci(np, MPC7448HPC2_PCI_CFG_PHYS, 0);
|
||||
|
||||
ppc_md.pci_exclude_device = mpc7448_hpc2_exclude_device;
|
||||
if (ppc_md.progress)
|
||||
ppc_md.progress("tsi108: resources set", 0x100);
|
||||
#endif
|
||||
|
||||
printk(KERN_INFO "MPC7448HPC2 (TAIGA) Platform\n");
|
||||
printk(KERN_INFO
|
||||
"Jointly ported by Freescale and Tundra Semiconductor\n");
|
||||
printk(KERN_INFO
|
||||
"Enabling L2 cache then enabling the HID0 prefetch engine.\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Interrupt setup and service. Interrupts on the mpc7448_hpc2 come
|
||||
* from the four external INT pins, PCI interrupts are routed via
|
||||
* PCI interrupt control registers, it generates internal IRQ23
|
||||
*
|
||||
* Interrupt routing on the Taiga Board:
|
||||
* TSI108:PB_INT[0] -> CPU0:INT#
|
||||
* TSI108:PB_INT[1] -> CPU0:MCP#
|
||||
* TSI108:PB_INT[2] -> N/C
|
||||
* TSI108:PB_INT[3] -> N/C
|
||||
*/
|
||||
static void __init mpc7448_hpc2_init_IRQ(void)
|
||||
{
|
||||
struct mpic *mpic;
|
||||
#ifdef CONFIG_PCI
|
||||
unsigned int cascade_pci_irq;
|
||||
struct device_node *tsi_pci;
|
||||
struct device_node *cascade_node = NULL;
|
||||
#endif
|
||||
|
||||
mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN |
|
||||
MPIC_SPV_EOI | MPIC_NO_PTHROU_DIS | MPIC_REGSET_TSI108,
|
||||
24, 0,
|
||||
"Tsi108_PIC");
|
||||
|
||||
BUG_ON(mpic == NULL);
|
||||
|
||||
mpic_assign_isu(mpic, 0, mpic->paddr + 0x100);
|
||||
|
||||
mpic_init(mpic);
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
tsi_pci = of_find_node_by_type(NULL, "pci");
|
||||
if (tsi_pci == NULL) {
|
||||
printk("%s: No tsi108 pci node found !\n", __func__);
|
||||
return;
|
||||
}
|
||||
cascade_node = of_find_node_by_type(NULL, "pic-router");
|
||||
if (cascade_node == NULL) {
|
||||
printk("%s: No tsi108 pci cascade node found !\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
cascade_pci_irq = irq_of_parse_and_map(tsi_pci, 0);
|
||||
DBG("%s: tsi108 cascade_pci_irq = 0x%x\n", __func__,
|
||||
(u32) cascade_pci_irq);
|
||||
tsi108_pci_int_init(cascade_node);
|
||||
irq_set_handler_data(cascade_pci_irq, mpic);
|
||||
irq_set_chained_handler(cascade_pci_irq, tsi108_irq_cascade);
|
||||
#endif
|
||||
/* Configure MPIC outputs to CPU0 */
|
||||
tsi108_write_reg(TSI108_MPIC_OFFSET + 0x30c, 0);
|
||||
}
|
||||
|
||||
void mpc7448_hpc2_show_cpuinfo(struct seq_file *m)
|
||||
{
|
||||
seq_printf(m, "vendor\t\t: Freescale Semiconductor\n");
|
||||
}
|
||||
|
||||
void mpc7448_hpc2_restart(char *cmd)
|
||||
{
|
||||
local_irq_disable();
|
||||
|
||||
/* Set exception prefix high - to the firmware */
|
||||
_nmask_and_or_msr(0, MSR_IP);
|
||||
|
||||
for (;;) ; /* Spin until reset happens */
|
||||
}
|
||||
|
||||
void mpc7448_hpc2_power_off(void)
|
||||
{
|
||||
local_irq_disable();
|
||||
for (;;) ; /* No way to shut power off with software */
|
||||
}
|
||||
|
||||
void mpc7448_hpc2_halt(void)
|
||||
{
|
||||
mpc7448_hpc2_power_off();
|
||||
}
|
||||
|
||||
/*
|
||||
* Called very early, device-tree isn't unflattened
|
||||
*/
|
||||
static int __init mpc7448_hpc2_probe(void)
|
||||
{
|
||||
unsigned long root = of_get_flat_dt_root();
|
||||
|
||||
if (!of_flat_dt_is_compatible(root, "mpc74xx"))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int mpc7448_machine_check_exception(struct pt_regs *regs)
|
||||
{
|
||||
const struct exception_table_entry *entry;
|
||||
|
||||
/* Are we prepared to handle this fault */
|
||||
if ((entry = search_exception_tables(regs->nip)) != NULL) {
|
||||
tsi108_clear_pci_cfg_error();
|
||||
regs->msr |= MSR_RI;
|
||||
regs->nip = entry->fixup;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
define_machine(mpc7448_hpc2){
|
||||
.name = "MPC7448 HPC2",
|
||||
.probe = mpc7448_hpc2_probe,
|
||||
.setup_arch = mpc7448_hpc2_setup_arch,
|
||||
.init_IRQ = mpc7448_hpc2_init_IRQ,
|
||||
.show_cpuinfo = mpc7448_hpc2_show_cpuinfo,
|
||||
.get_irq = mpic_get_irq,
|
||||
.restart = mpc7448_hpc2_restart,
|
||||
.calibrate_decr = generic_calibrate_decr,
|
||||
.machine_check_exception= mpc7448_machine_check_exception,
|
||||
.progress = udbg_progress,
|
||||
};
|
||||
221
arch/powerpc/platforms/embedded6xx/mvme5100.c
Normal file
221
arch/powerpc/platforms/embedded6xx/mvme5100.c
Normal file
|
|
@ -0,0 +1,221 @@
|
|||
/*
|
||||
* Board setup routines for the Motorola/Emerson MVME5100.
|
||||
*
|
||||
* Copyright 2013 CSC Australia Pty. Ltd.
|
||||
*
|
||||
* Based on earlier code by:
|
||||
*
|
||||
* Matt Porter, MontaVista Software Inc.
|
||||
* Copyright 2001 MontaVista Software Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Author: Stephen Chivers <schivers@csc.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/of_platform.h>
|
||||
|
||||
#include <asm/i8259.h>
|
||||
#include <asm/pci-bridge.h>
|
||||
#include <asm/mpic.h>
|
||||
#include <asm/prom.h>
|
||||
#include <mm/mmu_decl.h>
|
||||
#include <asm/udbg.h>
|
||||
|
||||
#define HAWK_MPIC_SIZE 0x00040000U
|
||||
#define MVME5100_PCI_MEM_OFFSET 0x00000000
|
||||
|
||||
/* Board register addresses. */
|
||||
#define BOARD_STATUS_REG 0xfef88080
|
||||
#define BOARD_MODFAIL_REG 0xfef88090
|
||||
#define BOARD_MODRST_REG 0xfef880a0
|
||||
#define BOARD_TBEN_REG 0xfef880c0
|
||||
#define BOARD_SW_READ_REG 0xfef880e0
|
||||
#define BOARD_GEO_ADDR_REG 0xfef880e8
|
||||
#define BOARD_EXT_FEATURE1_REG 0xfef880f0
|
||||
#define BOARD_EXT_FEATURE2_REG 0xfef88100
|
||||
|
||||
static phys_addr_t pci_membase;
|
||||
static u_char *restart;
|
||||
|
||||
static void mvme5100_8259_cascade(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||
unsigned int cascade_irq = i8259_irq();
|
||||
|
||||
if (cascade_irq != NO_IRQ)
|
||||
generic_handle_irq(cascade_irq);
|
||||
|
||||
chip->irq_eoi(&desc->irq_data);
|
||||
}
|
||||
|
||||
static void __init mvme5100_pic_init(void)
|
||||
{
|
||||
struct mpic *mpic;
|
||||
struct device_node *np;
|
||||
struct device_node *cp = NULL;
|
||||
unsigned int cirq;
|
||||
unsigned long intack = 0;
|
||||
const u32 *prop = NULL;
|
||||
|
||||
np = of_find_node_by_type(NULL, "open-pic");
|
||||
if (!np) {
|
||||
pr_err("Could not find open-pic node\n");
|
||||
return;
|
||||
}
|
||||
|
||||
mpic = mpic_alloc(np, pci_membase, 0, 16, 256, " OpenPIC ");
|
||||
|
||||
BUG_ON(mpic == NULL);
|
||||
of_node_put(np);
|
||||
|
||||
mpic_assign_isu(mpic, 0, pci_membase + 0x10000);
|
||||
|
||||
mpic_init(mpic);
|
||||
|
||||
cp = of_find_compatible_node(NULL, NULL, "chrp,iic");
|
||||
if (cp == NULL) {
|
||||
pr_warn("mvme5100_pic_init: couldn't find i8259\n");
|
||||
return;
|
||||
}
|
||||
|
||||
cirq = irq_of_parse_and_map(cp, 0);
|
||||
if (cirq == NO_IRQ) {
|
||||
pr_warn("mvme5100_pic_init: no cascade interrupt?\n");
|
||||
return;
|
||||
}
|
||||
|
||||
np = of_find_compatible_node(NULL, "pci", "mpc10x-pci");
|
||||
if (np) {
|
||||
prop = of_get_property(np, "8259-interrupt-acknowledge", NULL);
|
||||
|
||||
if (prop)
|
||||
intack = prop[0];
|
||||
|
||||
of_node_put(np);
|
||||
}
|
||||
|
||||
if (intack)
|
||||
pr_debug("mvme5100_pic_init: PCI 8259 intack at 0x%016lx\n",
|
||||
intack);
|
||||
|
||||
i8259_init(cp, intack);
|
||||
of_node_put(cp);
|
||||
irq_set_chained_handler(cirq, mvme5100_8259_cascade);
|
||||
}
|
||||
|
||||
static int __init mvme5100_add_bridge(struct device_node *dev)
|
||||
{
|
||||
const int *bus_range;
|
||||
int len;
|
||||
struct pci_controller *hose;
|
||||
unsigned short devid;
|
||||
|
||||
pr_info("Adding PCI host bridge %s\n", dev->full_name);
|
||||
|
||||
bus_range = of_get_property(dev, "bus-range", &len);
|
||||
|
||||
hose = pcibios_alloc_controller(dev);
|
||||
if (hose == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
hose->first_busno = bus_range ? bus_range[0] : 0;
|
||||
hose->last_busno = bus_range ? bus_range[1] : 0xff;
|
||||
|
||||
setup_indirect_pci(hose, 0xfe000cf8, 0xfe000cfc, 0);
|
||||
|
||||
pci_process_bridge_OF_ranges(hose, dev, 1);
|
||||
|
||||
early_read_config_word(hose, 0, 0, PCI_DEVICE_ID, &devid);
|
||||
|
||||
if (devid != PCI_DEVICE_ID_MOTOROLA_HAWK) {
|
||||
pr_err("HAWK PHB not present?\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
early_read_config_dword(hose, 0, 0, PCI_BASE_ADDRESS_1, &pci_membase);
|
||||
|
||||
if (pci_membase == 0) {
|
||||
pr_err("HAWK PHB mibar not correctly set?\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
pr_info("mvme5100_pic_init: pci_membase: %x\n", pci_membase);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id mvme5100_of_bus_ids[] __initconst = {
|
||||
{ .compatible = "hawk-bridge", },
|
||||
{},
|
||||
};
|
||||
|
||||
/*
|
||||
* Setup the architecture
|
||||
*/
|
||||
static void __init mvme5100_setup_arch(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
|
||||
if (ppc_md.progress)
|
||||
ppc_md.progress("mvme5100_setup_arch()", 0);
|
||||
|
||||
for_each_compatible_node(np, "pci", "hawk-pci")
|
||||
mvme5100_add_bridge(np);
|
||||
|
||||
restart = ioremap(BOARD_MODRST_REG, 4);
|
||||
}
|
||||
|
||||
|
||||
static void mvme5100_show_cpuinfo(struct seq_file *m)
|
||||
{
|
||||
seq_puts(m, "Vendor\t\t: Motorola/Emerson\n");
|
||||
seq_puts(m, "Machine\t\t: MVME5100\n");
|
||||
}
|
||||
|
||||
static void mvme5100_restart(char *cmd)
|
||||
{
|
||||
|
||||
local_irq_disable();
|
||||
mtmsr(mfmsr() | MSR_IP);
|
||||
|
||||
out_8((u_char *) restart, 0x01);
|
||||
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called very early, device-tree isn't unflattened
|
||||
*/
|
||||
static int __init mvme5100_probe(void)
|
||||
{
|
||||
unsigned long root = of_get_flat_dt_root();
|
||||
|
||||
return of_flat_dt_is_compatible(root, "MVME5100");
|
||||
}
|
||||
|
||||
static int __init probe_of_platform_devices(void)
|
||||
{
|
||||
|
||||
of_platform_bus_probe(NULL, mvme5100_of_bus_ids, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
machine_device_initcall(mvme5100, probe_of_platform_devices);
|
||||
|
||||
define_machine(mvme5100) {
|
||||
.name = "MVME5100",
|
||||
.probe = mvme5100_probe,
|
||||
.setup_arch = mvme5100_setup_arch,
|
||||
.init_IRQ = mvme5100_pic_init,
|
||||
.show_cpuinfo = mvme5100_show_cpuinfo,
|
||||
.get_irq = mpic_get_irq,
|
||||
.restart = mvme5100_restart,
|
||||
.calibrate_decr = generic_calibrate_decr,
|
||||
.progress = udbg_progress,
|
||||
};
|
||||
125
arch/powerpc/platforms/embedded6xx/storcenter.c
Normal file
125
arch/powerpc/platforms/embedded6xx/storcenter.c
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* Board setup routines for the storcenter
|
||||
*
|
||||
* Copyright 2007 (C) Oyvind Repvik (nail@nslu2-linux.org)
|
||||
* Copyright 2007 Andy Wilcox, Jon Loeliger
|
||||
*
|
||||
* Based on linkstation.c by G. Liakhovetski
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public License
|
||||
* version 2. This program is licensed "as is" without any warranty of
|
||||
* any kind, whether express or implied.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/initrd.h>
|
||||
#include <linux/of_platform.h>
|
||||
|
||||
#include <asm/time.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/mpic.h>
|
||||
#include <asm/pci-bridge.h>
|
||||
|
||||
#include "mpc10x.h"
|
||||
|
||||
|
||||
static const struct of_device_id storcenter_of_bus[] __initconst = {
|
||||
{ .name = "soc", },
|
||||
{},
|
||||
};
|
||||
|
||||
static int __init storcenter_device_probe(void)
|
||||
{
|
||||
of_platform_bus_probe(NULL, storcenter_of_bus, NULL);
|
||||
return 0;
|
||||
}
|
||||
machine_device_initcall(storcenter, storcenter_device_probe);
|
||||
|
||||
|
||||
static int __init storcenter_add_bridge(struct device_node *dev)
|
||||
{
|
||||
#ifdef CONFIG_PCI
|
||||
int len;
|
||||
struct pci_controller *hose;
|
||||
const int *bus_range;
|
||||
|
||||
printk("Adding PCI host bridge %s\n", dev->full_name);
|
||||
|
||||
hose = pcibios_alloc_controller(dev);
|
||||
if (hose == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
bus_range = of_get_property(dev, "bus-range", &len);
|
||||
hose->first_busno = bus_range ? bus_range[0] : 0;
|
||||
hose->last_busno = bus_range ? bus_range[1] : 0xff;
|
||||
|
||||
setup_indirect_pci(hose, MPC10X_MAPB_CNFG_ADDR, MPC10X_MAPB_CNFG_DATA, 0);
|
||||
|
||||
/* Interpret the "ranges" property */
|
||||
/* This also maps the I/O region and sets isa_io/mem_base */
|
||||
pci_process_bridge_OF_ranges(hose, dev, 1);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __init storcenter_setup_arch(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
|
||||
/* Lookup PCI host bridges */
|
||||
for_each_compatible_node(np, "pci", "mpc10x-pci")
|
||||
storcenter_add_bridge(np);
|
||||
|
||||
printk(KERN_INFO "IOMEGA StorCenter\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Interrupt setup and service. Interrupts on the turbostation come
|
||||
* from the four PCI slots plus onboard 8241 devices: I2C, DUART.
|
||||
*/
|
||||
static void __init storcenter_init_IRQ(void)
|
||||
{
|
||||
struct mpic *mpic;
|
||||
|
||||
mpic = mpic_alloc(NULL, 0, 0, 16, 0, " OpenPIC ");
|
||||
BUG_ON(mpic == NULL);
|
||||
|
||||
/*
|
||||
* 16 Serial Interrupts followed by 16 Internal Interrupts.
|
||||
* I2C is the second internal, so it is at 17, 0x11020.
|
||||
*/
|
||||
mpic_assign_isu(mpic, 0, mpic->paddr + 0x10200);
|
||||
mpic_assign_isu(mpic, 1, mpic->paddr + 0x11000);
|
||||
|
||||
mpic_init(mpic);
|
||||
}
|
||||
|
||||
static void storcenter_restart(char *cmd)
|
||||
{
|
||||
local_irq_disable();
|
||||
|
||||
/* Set exception prefix high - to the firmware */
|
||||
_nmask_and_or_msr(0, MSR_IP);
|
||||
|
||||
/* Wait for reset to happen */
|
||||
for (;;) ;
|
||||
}
|
||||
|
||||
static int __init storcenter_probe(void)
|
||||
{
|
||||
unsigned long root = of_get_flat_dt_root();
|
||||
|
||||
return of_flat_dt_is_compatible(root, "iomega,storcenter");
|
||||
}
|
||||
|
||||
define_machine(storcenter){
|
||||
.name = "IOMEGA StorCenter",
|
||||
.probe = storcenter_probe,
|
||||
.setup_arch = storcenter_setup_arch,
|
||||
.init_IRQ = storcenter_init_IRQ,
|
||||
.get_irq = mpic_get_irq,
|
||||
.restart = storcenter_restart,
|
||||
.calibrate_decr = generic_calibrate_decr,
|
||||
};
|
||||
328
arch/powerpc/platforms/embedded6xx/usbgecko_udbg.c
Normal file
328
arch/powerpc/platforms/embedded6xx/usbgecko_udbg.c
Normal 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 >= 0)
|
||||
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 */
|
||||
|
||||
32
arch/powerpc/platforms/embedded6xx/usbgecko_udbg.h
Normal file
32
arch/powerpc/platforms/embedded6xx/usbgecko_udbg.h
Normal 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 */
|
||||
252
arch/powerpc/platforms/embedded6xx/wii.c
Normal file
252
arch/powerpc/platforms/embedded6xx/wii.c
Normal file
|
|
@ -0,0 +1,252 @@
|
|||
/*
|
||||
* 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/of_platform.h>
|
||||
#include <linux/memblock.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 memblock_region *p = memblock.memory.regions;
|
||||
|
||||
/*
|
||||
* This is part of a workaround to allow the use of two
|
||||
* discontinuous RAM ranges on the Wii, even if this is
|
||||
* currently unsupported on 32-bit PowerPC Linux.
|
||||
*
|
||||
* We coalesce the two memory ranges of the Wii into a
|
||||
* single range, then create a reservation for the "hole"
|
||||
* between both ranges.
|
||||
*/
|
||||
|
||||
BUG_ON(memblock.memory.cnt != 2);
|
||||
BUG_ON(!page_aligned(p[0].base) || !page_aligned(p[1].base));
|
||||
|
||||
/* trim unaligned tail */
|
||||
memblock_remove(ALIGN(p[1].base + p[1].size, PAGE_SIZE),
|
||||
(phys_addr_t)ULLONG_MAX);
|
||||
|
||||
/* determine hole, add & reserve them */
|
||||
wii_hole_start = ALIGN(p[0].base + p[0].size, PAGE_SIZE);
|
||||
wii_hole_size = p[1].base - wii_hole_start;
|
||||
memblock_add(wii_hole_start, wii_hole_size);
|
||||
memblock_reserve(wii_hole_start, wii_hole_size);
|
||||
|
||||
BUG_ON(memblock.memory.cnt != 1);
|
||||
__memblock_dump_all();
|
||||
|
||||
/* 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();
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
static const 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);
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue