Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc/amigaone: Add platform support for AmigaOne

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>

authored by

Gerhard Pircher and committed by
Benjamin Herrenschmidt
54b318aa 8535ef05

+191
+1
arch/powerpc/platforms/Kconfig
··· 28 28 source "arch/powerpc/platforms/embedded6xx/Kconfig" 29 29 source "arch/powerpc/platforms/44x/Kconfig" 30 30 source "arch/powerpc/platforms/40x/Kconfig" 31 + source "arch/powerpc/platforms/amigaone/Kconfig" 31 32 32 33 config PPC_NATIVE 33 34 bool
+1
arch/powerpc/platforms/Makefile
··· 19 19 obj-$(CONFIG_PPC_CELL) += cell/ 20 20 obj-$(CONFIG_PPC_PS3) += ps3/ 21 21 obj-$(CONFIG_EMBEDDED6xx) += embedded6xx/ 22 + obj-$(CONFIG_AMIGAONE) += amigaone/
+18
arch/powerpc/platforms/amigaone/Kconfig
··· 1 + config AMIGAONE 2 + bool "Eyetech AmigaOne/MAI Teron" 3 + depends on PPC32 && BROKEN_ON_SMP && PPC_MULTIPLATFORM 4 + select PPC_I8259 5 + select PPC_INDIRECT_PCI 6 + select PPC_UDBG_16550 7 + select PCI 8 + select NOT_COHERENT_CACHE 9 + select CHECK_CACHE_COHERENCY 10 + select DEFAULT_UIMAGE 11 + select PCSPKR_PLATFORM 12 + help 13 + Select AmigaOne for the following machines: 14 + - AmigaOne SE/Teron CX (G3 only) 15 + - AmigaOne XE/Teron PX 16 + - uA1/Teron mini 17 + More information is available at: 18 + <http://amigaone-linux.sourceforge.net/>.
+1
arch/powerpc/platforms/amigaone/Makefile
··· 1 + obj-y += setup.o
+170
arch/powerpc/platforms/amigaone/setup.c
··· 1 + /* 2 + * AmigaOne platform setup 3 + * 4 + * Copyright 2008 Gerhard Pircher (gerhard_pircher@gmx.net) 5 + * 6 + * Based on original amigaone_setup.c source code 7 + * Copyright 2003 by Hans-Joerg Frieden and Thomas Frieden 8 + * 9 + * This program is free software; you can redistribute it and/or modify it 10 + * under the terms of the GNU General Public License as published by the 11 + * Free Software Foundation; either version 2 of the License, or (at your 12 + * option) any later version. 13 + */ 14 + 15 + #include <linux/kernel.h> 16 + #include <linux/seq_file.h> 17 + #include <linux/utsrelease.h> 18 + 19 + #include <asm/machdep.h> 20 + #include <asm/cputable.h> 21 + #include <asm/prom.h> 22 + #include <asm/pci-bridge.h> 23 + #include <asm/i8259.h> 24 + #include <asm/time.h> 25 + #include <asm/udbg.h> 26 + 27 + extern void __flush_disable_L1(void); 28 + 29 + void amigaone_show_cpuinfo(struct seq_file *m) 30 + { 31 + seq_printf(m, "vendor\t\t: Eyetech Ltd.\n"); 32 + } 33 + 34 + static int __init amigaone_add_bridge(struct device_node *dev) 35 + { 36 + const u32 *cfg_addr, *cfg_data; 37 + int len; 38 + const int *bus_range; 39 + struct pci_controller *hose; 40 + 41 + printk(KERN_INFO "Adding PCI host bridge %s\n", dev->full_name); 42 + 43 + cfg_addr = of_get_address(dev, 0, NULL, NULL); 44 + cfg_data = of_get_address(dev, 1, NULL, NULL); 45 + if ((cfg_addr == NULL) || (cfg_data == NULL)) 46 + return -ENODEV; 47 + 48 + bus_range = of_get_property(dev, "bus-range", &len); 49 + if ((bus_range == NULL) || (len < 2 * sizeof(int))) 50 + printk(KERN_WARNING "Can't get bus-range for %s, assume" 51 + " bus 0\n", dev->full_name); 52 + 53 + hose = pcibios_alloc_controller(dev); 54 + if (hose == NULL) 55 + return -ENOMEM; 56 + 57 + hose->first_busno = bus_range ? bus_range[0] : 0; 58 + hose->last_busno = bus_range ? bus_range[1] : 0xff; 59 + 60 + setup_indirect_pci(hose, cfg_addr[0], cfg_data[0], 0); 61 + 62 + /* Interpret the "ranges" property */ 63 + /* This also maps the I/O region and sets isa_io/mem_base */ 64 + pci_process_bridge_OF_ranges(hose, dev, 1); 65 + 66 + return 0; 67 + } 68 + 69 + void __init amigaone_setup_arch(void) 70 + { 71 + struct device_node *np; 72 + int phb = -ENODEV; 73 + 74 + /* Lookup PCI host bridges. */ 75 + for_each_compatible_node(np, "pci", "mai-logic,articia-s") 76 + phb = amigaone_add_bridge(np); 77 + 78 + BUG_ON(phb != 0); 79 + 80 + if (ppc_md.progress) 81 + ppc_md.progress("Linux/PPC "UTS_RELEASE"\n", 0); 82 + } 83 + 84 + void __init amigaone_init_IRQ(void) 85 + { 86 + struct device_node *pic, *np = NULL; 87 + const unsigned long *prop = NULL; 88 + unsigned long int_ack = 0; 89 + 90 + /* Search for ISA interrupt controller. */ 91 + pic = of_find_compatible_node(NULL, "interrupt-controller", 92 + "pnpPNP,000"); 93 + BUG_ON(pic == NULL); 94 + 95 + /* Look for interrupt acknowledge address in the PCI root node. */ 96 + np = of_find_compatible_node(NULL, "pci", "mai-logic,articia-s"); 97 + if (np) { 98 + prop = of_get_property(np, "8259-interrupt-acknowledge", NULL); 99 + if (prop) 100 + int_ack = prop[0]; 101 + of_node_put(np); 102 + } 103 + 104 + if (int_ack == 0) 105 + printk(KERN_WARNING "Cannot find PCI interrupt acknowledge" 106 + " address, polling\n"); 107 + 108 + i8259_init(pic, int_ack); 109 + ppc_md.get_irq = i8259_irq; 110 + irq_set_default_host(i8259_get_host()); 111 + } 112 + 113 + void __init amigaone_init(void) 114 + { 115 + request_region(0x00, 0x20, "dma1"); 116 + request_region(0x40, 0x20, "timer"); 117 + request_region(0x80, 0x10, "dma page reg"); 118 + request_region(0xc0, 0x20, "dma2"); 119 + } 120 + 121 + void amigaone_restart(char *cmd) 122 + { 123 + local_irq_disable(); 124 + 125 + /* Flush and disable caches. */ 126 + __flush_disable_L1(); 127 + 128 + /* Set SRR0 to the reset vector and turn on MSR_IP. */ 129 + mtspr(SPRN_SRR0, 0xfff00100); 130 + mtspr(SPRN_SRR1, MSR_IP); 131 + 132 + /* Do an rfi to jump back to firmware. */ 133 + __asm__ __volatile__("rfi" : : : "memory"); 134 + 135 + /* Not reached. */ 136 + while (1); 137 + } 138 + 139 + static int __init amigaone_probe(void) 140 + { 141 + unsigned long root = of_get_flat_dt_root(); 142 + 143 + if (of_flat_dt_is_compatible(root, "eyetech,amigaone")) { 144 + /* 145 + * Coherent memory access cause complete system lockup! Thus 146 + * disable this CPU feature, even if the CPU needs it. 147 + */ 148 + cur_cpu_spec->cpu_features &= ~CPU_FTR_NEED_COHERENT; 149 + 150 + ISA_DMA_THRESHOLD = 0x00ffffff; 151 + DMA_MODE_READ = 0x44; 152 + DMA_MODE_WRITE = 0x48; 153 + 154 + return 1; 155 + } 156 + 157 + return 0; 158 + } 159 + 160 + define_machine(amigaone) { 161 + .name = "AmigaOne", 162 + .probe = amigaone_probe, 163 + .setup_arch = amigaone_setup_arch, 164 + .init = amigaone_init, 165 + .show_cpuinfo = amigaone_show_cpuinfo, 166 + .init_IRQ = amigaone_init_IRQ, 167 + .restart = amigaone_restart, 168 + .calibrate_decr = generic_calibrate_decr, 169 + .progress = udbg_progress, 170 + };