commit 0df02de5b4e582c22962361ca7104c75c795dc15 Author: Gerhard Pircher Date: Wed Jan 30 20:59:27 2008 +0100 Add suppot for AmigaOne platform. diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index 18e3271..b849808 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile @@ -56,7 +56,7 @@ src-plat := of.c cuboot-52xx.c cuboot-83xx.c cuboot-85xx.c holly.c \ cuboot-ebony.c treeboot-ebony.c prpmc2800.c \ ps3-head.S ps3-hvcall.S ps3.c treeboot-bamboo.c cuboot-8xx.c \ cuboot-pq2.c cuboot-sequoia.c treeboot-walnut.c cuboot-bamboo.c \ - fixed-head.S ep88xc.c cuboot-hpc2.c + fixed-head.S ep88xc.c cuboot-hpc2.c cuboot-amigaone.c src-boot := $(src-wlib) $(src-plat) empty.c src-boot := $(addprefix $(obj)/, $(src-boot)) @@ -159,6 +159,7 @@ image-$(CONFIG_EBONY) += treeImage.ebony cuImage.ebony image-$(CONFIG_BAMBOO) += treeImage.bamboo cuImage.bamboo image-$(CONFIG_SEQUOIA) += cuImage.sequoia image-$(CONFIG_WALNUT) += treeImage.walnut +image-$(CONFIG_AMIGAONE) += cuImage.amigaone endif # For 32-bit powermacs, build the COFF and miboot images diff --git a/arch/powerpc/boot/cuboot-amigaone.c b/arch/powerpc/boot/cuboot-amigaone.c new file mode 100644 index 0000000..d95d4d1 --- /dev/null +++ b/arch/powerpc/boot/cuboot-amigaone.c @@ -0,0 +1,36 @@ +/* + * Old U-boot compatibility for AmigaOne + * + * Author: Gerhard Pircher (gerhard_pircher@gmx.net) + * + * Based on cuboot-83xx.c + * Copyright (c) 2007 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 version 2 as published + * by the Free Software Foundation. + */ + +#include "ops.h" +#include "stdio.h" +#include "cuboot.h" + +#include "ppcboot.h" + +static bd_t bd; +extern char _dtb_start[], _dtb_end[]; + +static void platform_fixups(void) +{ + dt_fixup_memory(bd.bi_memstart, bd.bi_memsize); + dt_fixup_cpu_clocks(bd.bi_intfreq, bd.bi_busfreq / 4, bd.bi_busfreq); +} + +void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7) +{ + CUBOOT_INIT(); + ft_init(_dtb_start, _dtb_end - _dtb_start, 32); + serial_console_init(); + platform_ops.fixups = platform_fixups; +} diff --git a/arch/powerpc/boot/dts/amigaone.dts b/arch/powerpc/boot/dts/amigaone.dts new file mode 100644 index 0000000..f91d1de --- /dev/null +++ b/arch/powerpc/boot/dts/amigaone.dts @@ -0,0 +1,224 @@ +/* + * AmigaOne Device Tree Source + * + * Copyright 2007 Gerhard Pircher (gerhard_pircher@gmx.net) + * + * 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. + */ + +/ { + model = "AmigaOne"; + compatible = "eyetech,amigaone","mai-logic,teron"; + coherency-off; + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #cpus = <1>; + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + reg = <0>; + d-cache-line-size = <20>; // 32 bytes + i-cache-line-size = <20>; // 32 bytes + d-cache-size = <8000>; // L1, 32K + i-cache-size = <8000>; // L1, 32K + timebase-frequency = <0>; // 33.3 MHz, from U-boot + clock-frequency = <0>; // From U-boot + bus-frequency = <0>; // From U-boot + 32-bit; + }; + }; + + memory { + device_type = "memory"; + reg = <0 0>; // From U-boot + }; + + pci@80000000 { + device_type = "pci"; + compatible = "mai-logic,articia-s"; + bus-frequency = <01fca055>; // 33.3MHz + bus-range = <0 ff>; + ranges = <01000000 0 00000000 fe000000 0 00c00000 // PCI I/O + 02000000 0 80000000 80000000 0 7d000000 // PCI memory + 02000000 0 fd000000 fd000000 0 01000000>; // PCI alias memory + 8259-interrupt-acknowledge = ; + /* Do not define a interrupt-parent here, if there is no interrupt-map property. */ + #address-cells = <3>; + #size-cells = <2>; + + host@0 { + compatible = "pciclass,0600"; + vendor-id = <000010cc>; + device-id = <00000660>; + revision-id = <00000001>; + class-code = <00060000>; + subsystem-id = <0>; + subsystem-vendor-id = <0>; + devsel-speed = <00000001>; + 66mhz-capable; + min-grant = <0>; + max-latency = <0>; + // AGP aperture is unset. +// reg = <42000010 0 00000000 0 00400000>; +// assigned-addresses = <42000010 0 00000000 0 00400000>; + }; + + isa@7 { + device_type = "isa"; + compatible = "pciclass,0601"; + vendor-id = <00001106>; + device-id = <00000686>; + revision-id = <00000010>; + class-code = <00060100>; + subsystem-id = <0>; + subsystem-vendor-id = <0>; + devsel-speed = <00000001>; + min-grant = <0>; + max-latency = <0>; + /* First 64k for I/O at 0x0 on PCI mapped to 0x0 on ISA. */ + ranges = <00000001 0 01000000 0 00000000 00010000>; + interrupt-parent = <&i8259>; + #interrupt-cells = <2>; + #address-cells = <2>; + #size-cells = <1>; + + dma-controller@0 { + device_type = "dma-controller"; + compatible = "pnpPNP,200"; + reg = <00000001 00000000 00000020 + 00000001 00000080 00000010 + 00000001 000000c0 00000020>; + /* Channel 4 reserverd, cascade mode, 2x32k transfer/counter + * widths and bus master capability. Is this really necessary? + */ +/* dma = <4 4 20 20 1>; */ + }; + + i8259: interrupt-controller@20 { + device_type = "interrupt-controller"; + compatible = "pnpPNP,000"; + interrupt-controller; + reg = <00000001 00000020 00000002 + 00000001 000000a0 00000002 + 00000001 000004d0 00000002>; + reserved-interrupts = <2>; + #interrupt-cells = <2>; + }; + + timer@40 { +/* device_type = "timer"; */ // No device type binding for now. + compatible = "pnpPNP,100"; // Also add pcspkr to platform devices. + reg = <00000001 00000040 00000020>; + }; + + 8042@60 { + device_type = "8042"; + reg = <00000001 00000060 00000001 + 00000001 00000064 00000001>; + interrupts = <1 3 c 3>; // IRQ1, IRQ12 (rising edge) + #address-cells = <1>; + #size-cells = <0>; + + keyboard@0 { + device_type = "keyboard"; + compatible = "pnpPNP,303"; + reg = <0>; + }; + + mouse@1 { + device_type = "mouse"; + compatible = "pnpPNP,f03"; + reg = <1>; + }; + }; + + rtc@70 { + device_type = "rtc"; + compatible = "pnpPNP,b00"; + reg = <00000001 00000070 00000002>; + interrupts = <8 3>; + }; + + serial@2f8 { + device_type = "serial"; + compatible = "pnpPNP,501","pnpPNP,500"; // "ns16550"; add property check to OF serial code. + reg = <00000001 000002f8 00000008>; + interrupts = <3 3>; // IRQ3 (rising edge) + clock-frequency = <001C2000>; // Not necessary? + }; + + serial@3f8 { + device_type = "serial"; + compatible = "pnpPNP,501","pnpPNP,500"; // "ns16550"; add property check to OF serial code. + reg = <00000001 000003f8 00000008>; + interrupts = <4 3>; // IRQ4 (rising edge) + clock-frequency = <001C2000>; // Not necessary? + }; + + parallel@378 { + device_type = "parallel"; + compatible = "pnpPNP,400"; // "pnpPNP,401" // No ECP support for now. + reg = <00000001 00000378 00000003 + 00000001 00000778 00000003>; +/* interrupts = <7 3>; */ +/* dma = <3 0 0 0>; */ // Parallel port DMA mode? + }; + + fdc@3f0 { + device_type = "fdc"; + compatible = "pnpPNP,700"; + reg = <00000001 000003f0 00000008>; + interrupts = <6 3>; // IRQ6 (rising edge) +/* dma = < >; */ // Floppy DMA mode? + #address-cells = <1>; + #size-cells = <0>; + + disk@0 { + device_type = "block"; + reg = <0>; + }; + }; + }; + + ide@7,1 { + compatible = "pciclass,01018b"; + vendor-id = <00001106>; + device-id = <00000571>; + revision-id = <00000006>; + // Class code with PCI IDE programming interface indicator. + class-code = <0001018b>; + subsystem-id = <0>; + subsystem-vendor-id = <0>; + devsel-speed = <00000001>; + min-grant = <0>; + max-latency = <0>; + fast-back-to-back; + // Assume base addresses are relocateable, even if + // controller operates in compatibility mode. + reg = <21003910 0 00000000 0 00000000 + 21003914 0 00000000 0 00000000 + 21003918 0 00000000 0 00000000 + 2100391c 0 00000000 0 00000000 + 21003920 0 00000000 0 00000000>; + assigned-addresses = <01003910 0 000001f0 0 00000008 + 01003914 0 000003f4 0 00000004 + 01003918 0 00000170 0 00000008 + 0100391c 0 00000374 0 00000004 + 01003920 0 0000cc00 0 00000010>; +/* interrupt-parent = <&i8259>; + interrupts = ; + #interrupt-cells = <2>; */ + }; + }; + + chosen { + linux,stdout-path = "/pci@80000000/isa@7/serial@2f8"; + }; +}; diff --git a/arch/powerpc/boot/zImage.lds.S b/arch/powerpc/boot/zImage.lds.S index f6e380f..dd0fde8 100644 --- a/arch/powerpc/boot/zImage.lds.S +++ b/arch/powerpc/boot/zImage.lds.S @@ -3,7 +3,7 @@ ENTRY(_zimage_start) EXTERN(_zimage_start) SECTIONS { - . = (4*1024*1024); + . = (8*1024*1024); _start = .; .text : { diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c index 0e2bee4..5b5ed76 100644 --- a/arch/powerpc/kernel/pci_32.c +++ b/arch/powerpc/kernel/pci_32.c @@ -585,7 +585,9 @@ pcibios_assign_resources(void) r->flags &= ~IORESOURCE_UNSET; rc = pci_assign_resource(dev, idx); +#ifndef CONFIG_AMIGAONE BUG_ON(rc); +#endif } } diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index ea22cad..18026ad 100644 --- a/arch/powerpc/platforms/Kconfig +++ b/arch/powerpc/platforms/Kconfig @@ -56,6 +56,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 6d9079d..6460efa 100644 --- a/arch/powerpc/platforms/Makefile +++ b/arch/powerpc/platforms/Makefile @@ -25,3 +25,4 @@ obj-$(CONFIG_PPC_CELL) += cell/ obj-$(CONFIG_PPC_PS3) += ps3/ obj-$(CONFIG_PPC_CELLEB) += celleb/ 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..8e62d12 --- /dev/null +++ b/arch/powerpc/platforms/amigaone/Kconfig @@ -0,0 +1,17 @@ +config AMIGAONE + bool "Eyetech AmigaOne/MAI Teron" + depends on PPC_MULTIPLATFORM && PPC32 + select PPC_I8259 + select PPC_INDIRECT_PCI + select PPC_UDBG_16550 + select NOT_COHERENT_CACHE + select CHECK_CACHE_COHERENCY + select DEFAULT_UIMAGE + select WANT_DEVICE_TREE + 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: + . diff --git a/arch/powerpc/platforms/amigaone/Makefile b/arch/powerpc/platforms/amigaone/Makefile new file mode 100644 index 0000000..5d66f66 --- /dev/null +++ b/arch/powerpc/platforms/amigaone/Makefile @@ -0,0 +1,3 @@ +obj-y += setup.o +obj-$(CONFIG_PCI) += pci.o +#obj-$(CONFIG_NVRAM) += nvram.o diff --git a/arch/powerpc/platforms/amigaone/pci.c b/arch/powerpc/platforms/amigaone/pci.c new file mode 100644 index 0000000..21a5638 --- /dev/null +++ b/arch/powerpc/platforms/amigaone/pci.c @@ -0,0 +1,71 @@ +/* + * AmigaOne platform PCI setup + * + * Copyright 2007 Gerhard Pircher (gerhard_pircher@gmx.net) + * + * 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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +void __init +amigaone_find_bridges(void) +{ + struct device_node *dev; + const int *bus_range; + int len, index = -1; + struct pci_controller *hose; + struct device_node *root = of_find_node_by_path("/"); + + for (dev = root->child; dev != NULL; dev = dev->sibling) { + if (dev->type == NULL || strcmp(dev->type, "pci") != 0) + continue; + ++index; + + 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\n", + dev->full_name); + continue; + } + +/* if (bus_range[1] == bus_range[0]) + printk(KERN_INFO "PCI bus %d", bus_range[0]); + else + printk(KERN_INFO "PCI buses %d..%d", + bus_range[0], bus_range[1]); + printk(" controlled by %s", dev->full_name); */ + + hose = pcibios_alloc_controller(dev); + if (!hose) { + printk("Can't allocate PCI controller structure for %s\n", + dev->full_name); + continue; + } + hose->arch_data = dev; + hose->first_busno = bus_range[0]; + hose->last_busno = bus_range[1]; + + 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, index == 0); + } + + of_node_put(root); +} diff --git a/arch/powerpc/platforms/amigaone/setup.c b/arch/powerpc/platforms/amigaone/setup.c new file mode 100644 index 0000000..8eeef69 --- /dev/null +++ b/arch/powerpc/platforms/amigaone/setup.c @@ -0,0 +1,242 @@ +/* + * AmigaOne platform setup + * + * Copyright 2007 Gerhard Pircher (gerhard_pircher@gmx.net) + * + * Based on original amigaone_setup.c source code + * Copyright 2003 by Hans-Jörg and Thomas Frieden + * and chrp/setup.c + * Copyright 1995 by Linus Torvalds + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern void amigaone_find_bridges(void); + +void amigaone_set_l2cr(void) +{ + /* This disables the L2 hardware prefetch. It is normally disabled and + * enabled again within _set_L2CR(), but the L2 prefetch enable is not + * compiled in for the AmigaOne. + */ + _set_L2CR(_get_L2CR()); + + if(((_get_L2CR() & L2CR_L2E) == 0) && (strstr(cmd_line, "l2cr=") == NULL)) + { + printk("AmigaOne l2cr : L2 cache was not active, activating.\n"); + _set_L2CR(0); + _set_L2CR(L2CR_L2E | L2CR_L2PE); + } +} + +void amigaone_show_cpuinfo(struct seq_file *m) +{ + struct device_node *root; + const char *model = ""; + + root = of_find_node_by_path("/"); + if (root) + model = of_get_property(root, "model", NULL); + seq_printf(m, "machine\t\t: %s\n", model); + + of_node_put(root); + + seq_printf(m, "l2cr\t\t: 0x%08lX\n", _get_L2CR()); + seq_printf(m, "msscr0\t\t: 0x%08lX\n", mfspr(SPRN_MSSCR0)); + + return; +} + +void __init amigaone_setup_arch(void) +{ + /* init to some ~sane value until calibrate_delay() runs */ + loops_per_jiffy = 50000000/HZ; + + /* Enable the L2 cache. */ + amigaone_set_l2cr(); + + /* Lookup PCI host bridges */ + /* setup PCI host bridge */ + +#ifdef CONFIG_PCI_HOST_DRIVER + for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) + articias_setup_pci(np); +#else + amigaone_find_bridges(); +#endif + + /* Uncomment, when U-boot was updated. */ +// pci_create_OF_bus_map(); + + /* vgacon.c needs to know where VGA memory is mapped. */ +// vgacon_remap_base = (unsigned long) ioremap(0xfd000000, 0x00100000); +// conswitchp = &vga_con; + + if (ppc_md.progress) + ppc_md.progress("Linux/PPC "UTS_RELEASE"\n", 0x0); +} + +void __init amigaone_init_IRQ(void) +{ + struct device_node *np, *pic = NULL; + unsigned long amigaone_int_ack = 0; + + /* Search for ISA interrupt controller. */ + for_each_node_by_type(np, "interrupt-controller") + if (of_device_is_compatible(np, "pnpPNP,000")) { + pic = np; + break; + } + + BUG_ON(pic == NULL); + + /* Look for interrupt acknowledge address in the PCI root node. */ + for_each_node_by_name(np, "pci") { + const unsigned int *addrp = of_get_property(np, + "8259-interrupt-acknowledge", NULL); + + if (addrp == NULL) + continue; + amigaone_int_ack = addrp[of_n_addr_cells(np)-1]; + break; + } + of_node_put(np); + + if (np == NULL) + printk(KERN_WARNING "Cannot find PCI interrupt acknowledge" + " address, polling\n"); + + i8259_init(pic, amigaone_int_ack); + ppc_md.get_irq = i8259_irq; + irq_set_default_host(i8259_get_host()); +} + +void __init amigaone_init(void) +{ +#ifdef CONFIG_NVRAM +// amigaone_nvram_init(); +#endif + + request_region(0x20,0x20,"pic1"); + request_region(0xa0,0x20,"pic2"); + request_region(0x00,0x20,"dma1"); + request_region(0x40,0x20,"timer"); + request_region(0x80,0x10,"dma page reg"); + request_region(0xc0,0x20,"dma2"); +} + +/* Copied from U-Boot. */ +static inline void soft_restart(unsigned long addr) +{ + /* SRR0 has system reset vector, SRR1 has default MSR value. + * rfi restores MSR from SRR1 and sets the PC to the SRR0 value. + */ + __asm__ __volatile__ ("mtspr 26, %0" :: "r" (addr)); + __asm__ __volatile__ ("li 4, (1 << 6)" ::: "r4"); + __asm__ __volatile__ ("mtspr 27, 4"); + __asm__ __volatile__ ("rfi"); + + /* Not reached. */ + while(1); +} + +void amigaone_restart(char *cmd) +{ + unsigned long addr; + + local_irq_disable(); + + /* Flush and disable I/D cache. */ + __asm__ __volatile__ ("mfspr 3, 1008" ::: "r3"); + __asm__ __volatile__ ("ori 5, 5, 0xcc00" ::: "r5"); + __asm__ __volatile__ ("ori 4, 3, 0xc00" ::: "r4"); + __asm__ __volatile__ ("andc 5, 3, 5" ::: "r5"); + __asm__ __volatile__ ("sync"); + __asm__ __volatile__ ("mtspr 1008, 4"); + __asm__ __volatile__ ("isync"); + __asm__ __volatile__ ("sync"); + __asm__ __volatile__ ("mtspr 1008, 5"); + __asm__ __volatile__ ("isync"); + __asm__ __volatile__ ("sync"); + + addr = 0xfff00100; + soft_restart(addr); + 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 + * remove it in any case, even if the CPU needs it. We'll + * disable the L2 cache prefetch later on. + */ + 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, + .phys_mem_access_prot = pci_phys_mem_access_prot, +}; diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c index a0d3c16..8ebc87e 100644 --- a/drivers/ide/pci/via82cxxx.c +++ b/drivers/ide/pci/via82cxxx.c @@ -478,6 +478,10 @@ static int __devinit via_init_one(struct pci_dev *dev, const struct pci_device_i if (machine_is(chrp) && _chrp_type == _CHRP_Pegasos) d.host_flags |= IDE_HFLAG_FORCE_LEGACY_IRQS; #endif +#ifdef CONFIG_AMIGAONE + if (machine_is(amigaone)) + d.host_flags |= IDE_HFLAG_FORCE_LEGACY_IRQS; +#endif d.udma_mask = via_config->udma_mask; diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 8f5c7b9..9716d76 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -14,7 +14,7 @@ if INPUT_MISC config INPUT_PCSPKR tristate "PC Speaker support" - depends on ALPHA || X86 || MIPS || PPC_PREP || PPC_CHRP || PPC_PSERIES + depends on ALPHA || X86 || MIPS || PPC_PREP || PPC_CHRP || PPC_PSERIES || AMIGAONE help Say Y here if you want the standard PC Speaker to be used for bells and whistles.