diff mbox

[v2,1/4] Add platform support for AmigaOne

Message ID 20090202213910.258290@gmx.net (mailing list archive)
State Changes Requested, archived
Headers show

Commit Message

Gerhard Pircher Feb. 2, 2009, 9:39 p.m. UTC
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>
---
 arch/powerpc/platforms/Kconfig           |    1 +
 arch/powerpc/platforms/Makefile          |    1 +
 arch/powerpc/platforms/amigaone/Kconfig  |   18 ++++
 arch/powerpc/platforms/amigaone/Makefile |    1 +
 arch/powerpc/platforms/amigaone/setup.c  |  161 ++++++++++++++++++++++++++++++
 5 files changed, 182 insertions(+), 0 deletions(-)
 create mode 100644 arch/powerpc/platforms/amigaone/Kconfig
 create mode 100644 arch/powerpc/platforms/amigaone/Makefile
 create mode 100644 arch/powerpc/platforms/amigaone/setup.c

Comments

Benjamin Herrenschmidt Feb. 4, 2009, 3:50 a.m. UTC | #1
> + hose->first_busno = bus_range ? bus_range[0] : 0;
> + hose->last_busno = bus_range ? bus_range[1] : 0xff;
> +
> + setup_indirect_pci(hose, 0xfec00cf8, 0xfee00cfc, 0);

Minor in the context of amigaone but still... the above should come from
the device-tree... I suppose those are really just IO space addresses
cf8 and cfc, in which case, an option is to call that first:

> + /* 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);

And -then- use hose->io_resource.start + 0xcf8 / 0xcfc, the later can be
hard coded as they are pretty standard values.

Ben.
Gerhard Pircher Feb. 4, 2009, 12:09 p.m. UTC | #2
-------- Original-Nachricht --------
> Datum: Wed, 04 Feb 2009 14:50:07 +1100
> Von: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> An: Gerhard Pircher <gerhard_pircher@gmx.net>
> CC: linuxppc-dev list <linuxppc-dev@ozlabs.org>
> Betreff: Re: [PATCH v2 1/4] Add platform support for AmigaOne

> > + hose->first_busno = bus_range ? bus_range[0] : 0;
> > + hose->last_busno = bus_range ? bus_range[1] : 0xff;
> > +
> > + setup_indirect_pci(hose, 0xfec00cf8, 0xfee00cfc, 0);
> 
> Minor in the context of amigaone but still... the above should come from
> the device-tree... I suppose those are really just IO space addresses
> cf8 and cfc, in which case, an option is to call that first:
I agree that these addresses should come from the device-tree, but these
two config registers are not located within the normal PCI I/O address
space (0xfe000000-0xfec00000).
Maybe I should add a "reg" property to the PHB node, but I don't know if
this is the right approach. The OF PCI spec isn't very clear about this.
What do you think?

Gerhard
Benjamin Herrenschmidt Feb. 4, 2009, 8:47 p.m. UTC | #3
On Wed, 2009-02-04 at 13:09 +0100, Gerhard Pircher wrote:
> I agree that these addresses should come from the device-tree, but these
> two config registers are not located within the normal PCI I/O address
> space (0xfe000000-0xfec00000).
> Maybe I should add a "reg" property to the PHB node, but I don't know if
> this is the right approach. The OF PCI spec isn't very clear about this.
> What do you think?

Yup, "reg" in the PHB is what most machines use for that.

Cheers,
Ben.
Gabriel Paubert Feb. 4, 2009, 8:59 p.m. UTC | #4
On Wed, Feb 04, 2009 at 02:50:07PM +1100, Benjamin Herrenschmidt wrote:
> 
> > + hose->first_busno = bus_range ? bus_range[0] : 0;
> > + hose->last_busno = bus_range ? bus_range[1] : 0xff;
> > +
> > + setup_indirect_pci(hose, 0xfec00cf8, 0xfee00cfc, 0);
> 
> Minor in the context of amigaone but still... the above should come from
> the device-tree... I suppose those are really just IO space addresses
> cf8 and cfc, in which case, an option is to call that first:

Hmm, the first is feC...,the other one feE..., 2Mbytes apart.

I don't know the hardware but I've never seen something like that.
Of course a typo is always a possibility...

	Gabriel
Gerhard Pircher Feb. 4, 2009, 9:35 p.m. UTC | #5
-------- Original-Nachricht --------
> Datum: Wed, 4 Feb 2009 21:59:41 +0100
> Von: Gabriel Paubert <paubert@iram.es>
> An: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> CC: Gerhard Pircher <gerhard_pircher@gmx.net>, linuxppc-dev list <linuxppc-dev@ozlabs.org>
> Betreff: Re: [PATCH v2 1/4] Add platform support for AmigaOne

> On Wed, Feb 04, 2009 at 02:50:07PM +1100, Benjamin Herrenschmidt wrote:
> > 
> > > + hose->first_busno = bus_range ? bus_range[0] : 0;
> > > + hose->last_busno = bus_range ? bus_range[1] : 0xff;
> > > +
> > > + setup_indirect_pci(hose, 0xfec00cf8, 0xfee00cfc, 0);
> > 
> > Minor in the context of amigaone but still... the above should come
> > from the device-tree... I suppose those are really just IO space
> > addresses cf8 and cfc, in which case, an option is to call that first:
> 
> Hmm, the first is feC...,the other one feE..., 2Mbytes apart.
> 
> I don't know the hardware but I've never seen something like that.
> Of course a typo is always a possibility...
The Pegasos 1 uses the same northbridge and chrp_find_bridges() calls
setup_indirect_pci() with the same addresses.

Gerhard
John W. Linville Feb. 4, 2009, 9:39 p.m. UTC | #6
On Wed, Feb 04, 2009 at 10:35:31PM +0100, Gerhard Pircher wrote:
> 
> -------- Original-Nachricht --------
> > Datum: Wed, 4 Feb 2009 21:59:41 +0100
> > Von: Gabriel Paubert <paubert@iram.es>
> > An: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> > CC: Gerhard Pircher <gerhard_pircher@gmx.net>, linuxppc-dev list <linuxppc-dev@ozlabs.org>
> > Betreff: Re: [PATCH v2 1/4] Add platform support for AmigaOne
> 
> > On Wed, Feb 04, 2009 at 02:50:07PM +1100, Benjamin Herrenschmidt wrote:
> > > 
> > > > + hose->first_busno = bus_range ? bus_range[0] : 0;
> > > > + hose->last_busno = bus_range ? bus_range[1] : 0xff;
> > > > +
> > > > + setup_indirect_pci(hose, 0xfec00cf8, 0xfee00cfc, 0);
> > > 
> > > Minor in the context of amigaone but still... the above should come
> > > from the device-tree... I suppose those are really just IO space
> > > addresses cf8 and cfc, in which case, an option is to call that first:
> > 
> > Hmm, the first is feC...,the other one feE..., 2Mbytes apart.
> > 
> > I don't know the hardware but I've never seen something like that.
> > Of course a typo is always a possibility...
> The Pegasos 1 uses the same northbridge and chrp_find_bridges() calls
> setup_indirect_pci() with the same addresses.

As a proud owner, I concur that those numbers are correct...
Gerhard Pircher Feb. 5, 2009, 1:36 p.m. UTC | #7
Hi!

I have a minor question about the error handling in the various *_add/find_bridges functions, which are used to detect and initialize
PHBs. AFAIK all of them return an error code that is never checked in
the platform setup code (e.g. when there is no memory for the
pci_controller struct).
Shouldn't the kernel panic (BUG();), when it can't initialize the PHB
for whatever reason and the platform depends on a working PCI bus?

Thanks!

regards,

Gerhard
diff mbox

Patch

diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index 200b9cb..b25404c 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -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
diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile
index 8079e0b..f741919 100644
--- a/arch/powerpc/platforms/Makefile
+++ b/arch/powerpc/platforms/Makefile
@@ -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/
diff --git a/arch/powerpc/platforms/amigaone/Kconfig b/arch/powerpc/platforms/amigaone/Kconfig
new file mode 100644
index 0000000..9276a96
--- /dev/null
+++ b/arch/powerpc/platforms/amigaone/Kconfig
@@ -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/>.
diff --git a/arch/powerpc/platforms/amigaone/Makefile b/arch/powerpc/platforms/amigaone/Makefile
new file mode 100644
index 0000000..e6885b3
--- /dev/null
+++ b/arch/powerpc/platforms/amigaone/Makefile
@@ -0,0 +1 @@ 
+obj-y	+= setup.o
diff --git a/arch/powerpc/platforms/amigaone/setup.c b/arch/powerpc/platforms/amigaone/setup.c
new file mode 100644
index 0000000..c20244a
--- /dev/null
+++ b/arch/powerpc/platforms/amigaone/setup.c
@@ -0,0 +1,161 @@ 
+/*
+ * 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)
+{
+	int len;
+	struct pci_controller *hose;
+	const int *bus_range;
+
+	printk(KERN_INFO "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, 0xfec00cf8, 0xfee00cfc, 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;
+
+	/* Lookup PCI host bridges. */
+	for_each_compatible_node(np, "pci", "mai-logic,articia-s")
+		amigaone_add_bridge(np);
+
+	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,
+};