Skip to content

Commit

Permalink
powerpc/amigaone: Add platform support for AmigaOne
Browse files Browse the repository at this point in the history
This commit adds the setup code for booting Linux on AmigaOne G3SE (G3
only), AmigaOne XE and uA1 (G3/G4) desktop computers. These boards were
sold by Eyetech and are based on MAI Logic's Teron boards and its
Articia S northbridge.
The AmigaOne uses U-boot as firmware, which doesn't support a flattened
device tree yet. The northbridge has some design flaws, which makes it
necessary to use non cacheable memory for DMA operations
(CONFIG_NOT_COHERENT_CACHE) and to avoid setting the coherence (M) flag
for memory pages.

Signed-off-by: Gerhard Pircher <gerhard_pircher@gmx.net>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
  • Loading branch information
Gerhard Pircher authored and Benjamin Herrenschmidt committed Feb 11, 2009
1 parent 8535ef0 commit 54b318a
Show file tree
Hide file tree
Showing 5 changed files with 191 additions and 0 deletions.
1 change: 1 addition & 0 deletions arch/powerpc/platforms/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ source "arch/powerpc/platforms/86xx/Kconfig"
source "arch/powerpc/platforms/embedded6xx/Kconfig"
source "arch/powerpc/platforms/44x/Kconfig"
source "arch/powerpc/platforms/40x/Kconfig"
source "arch/powerpc/platforms/amigaone/Kconfig"

config PPC_NATIVE
bool
Expand Down
1 change: 1 addition & 0 deletions arch/powerpc/platforms/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ obj-$(CONFIG_PPC_PASEMI) += pasemi/
obj-$(CONFIG_PPC_CELL) += cell/
obj-$(CONFIG_PPC_PS3) += ps3/
obj-$(CONFIG_EMBEDDED6xx) += embedded6xx/
obj-$(CONFIG_AMIGAONE) += amigaone/
18 changes: 18 additions & 0 deletions arch/powerpc/platforms/amigaone/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
config AMIGAONE
bool "Eyetech AmigaOne/MAI Teron"
depends on PPC32 && BROKEN_ON_SMP && PPC_MULTIPLATFORM
select PPC_I8259
select PPC_INDIRECT_PCI
select PPC_UDBG_16550
select PCI
select NOT_COHERENT_CACHE
select CHECK_CACHE_COHERENCY
select DEFAULT_UIMAGE
select PCSPKR_PLATFORM
help
Select AmigaOne for the following machines:
- AmigaOne SE/Teron CX (G3 only)
- AmigaOne XE/Teron PX
- uA1/Teron mini
More information is available at:
<http://amigaone-linux.sourceforge.net/>.
1 change: 1 addition & 0 deletions arch/powerpc/platforms/amigaone/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
obj-y += setup.o
170 changes: 170 additions & 0 deletions arch/powerpc/platforms/amigaone/setup.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
/*
* AmigaOne platform setup
*
* Copyright 2008 Gerhard Pircher (gerhard_pircher@gmx.net)
*
* Based on original amigaone_setup.c source code
* Copyright 2003 by Hans-Joerg Frieden and Thomas Frieden
*
* 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/seq_file.h>
#include <linux/utsrelease.h>

#include <asm/machdep.h>
#include <asm/cputable.h>
#include <asm/prom.h>
#include <asm/pci-bridge.h>
#include <asm/i8259.h>
#include <asm/time.h>
#include <asm/udbg.h>

extern void __flush_disable_L1(void);

void amigaone_show_cpuinfo(struct seq_file *m)
{
seq_printf(m, "vendor\t\t: Eyetech Ltd.\n");
}

static int __init amigaone_add_bridge(struct device_node *dev)
{
const u32 *cfg_addr, *cfg_data;
int len;
const int *bus_range;
struct pci_controller *hose;

printk(KERN_INFO "Adding PCI host bridge %s\n", dev->full_name);

cfg_addr = of_get_address(dev, 0, NULL, NULL);
cfg_data = of_get_address(dev, 1, NULL, NULL);
if ((cfg_addr == NULL) || (cfg_data == NULL))
return -ENODEV;

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, cfg_addr[0], cfg_data[0], 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);

return 0;
}

void __init amigaone_setup_arch(void)
{
struct device_node *np;
int phb = -ENODEV;

/* Lookup PCI host bridges. */
for_each_compatible_node(np, "pci", "mai-logic,articia-s")
phb = amigaone_add_bridge(np);

BUG_ON(phb != 0);

if (ppc_md.progress)
ppc_md.progress("Linux/PPC "UTS_RELEASE"\n", 0);
}

void __init amigaone_init_IRQ(void)
{
struct device_node *pic, *np = NULL;
const unsigned long *prop = NULL;
unsigned long int_ack = 0;

/* Search for ISA interrupt controller. */
pic = of_find_compatible_node(NULL, "interrupt-controller",
"pnpPNP,000");
BUG_ON(pic == NULL);

/* Look for interrupt acknowledge address in the PCI root node. */
np = of_find_compatible_node(NULL, "pci", "mai-logic,articia-s");
if (np) {
prop = of_get_property(np, "8259-interrupt-acknowledge", NULL);
if (prop)
int_ack = prop[0];
of_node_put(np);
}

if (int_ack == 0)
printk(KERN_WARNING "Cannot find PCI interrupt acknowledge"
" address, polling\n");

i8259_init(pic, int_ack);
ppc_md.get_irq = i8259_irq;
irq_set_default_host(i8259_get_host());
}

void __init amigaone_init(void)
{
request_region(0x00, 0x20, "dma1");
request_region(0x40, 0x20, "timer");
request_region(0x80, 0x10, "dma page reg");
request_region(0xc0, 0x20, "dma2");
}

void amigaone_restart(char *cmd)
{
local_irq_disable();

/* Flush and disable caches. */
__flush_disable_L1();

/* 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. */
__asm__ __volatile__("rfi" : : : "memory");

/* Not reached. */
while (1);
}

static int __init amigaone_probe(void)
{
unsigned long root = of_get_flat_dt_root();

if (of_flat_dt_is_compatible(root, "eyetech,amigaone")) {
/*
* Coherent memory access cause complete system lockup! Thus
* disable this CPU feature, even if the CPU needs it.
*/
cur_cpu_spec->cpu_features &= ~CPU_FTR_NEED_COHERENT;

ISA_DMA_THRESHOLD = 0x00ffffff;
DMA_MODE_READ = 0x44;
DMA_MODE_WRITE = 0x48;

return 1;
}

return 0;
}

define_machine(amigaone) {
.name = "AmigaOne",
.probe = amigaone_probe,
.setup_arch = amigaone_setup_arch,
.init = amigaone_init,
.show_cpuinfo = amigaone_show_cpuinfo,
.init_IRQ = amigaone_init_IRQ,
.restart = amigaone_restart,
.calibrate_decr = generic_calibrate_decr,
.progress = udbg_progress,
};

0 comments on commit 54b318a

Please sign in to comment.