162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * AmigaOne platform setup 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright 2008 Gerhard Pircher (gerhard_pircher@gmx.net) 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Based on original amigaone_setup.c source code 862306a36Sopenharmony_ci * Copyright 2003 by Hans-Joerg Frieden and Thomas Frieden 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/irqdomain.h> 1262306a36Sopenharmony_ci#include <linux/kernel.h> 1362306a36Sopenharmony_ci#include <linux/of.h> 1462306a36Sopenharmony_ci#include <linux/of_address.h> 1562306a36Sopenharmony_ci#include <linux/seq_file.h> 1662306a36Sopenharmony_ci#include <generated/utsrelease.h> 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#include <asm/machdep.h> 1962306a36Sopenharmony_ci#include <asm/cputable.h> 2062306a36Sopenharmony_ci#include <asm/pci-bridge.h> 2162306a36Sopenharmony_ci#include <asm/i8259.h> 2262306a36Sopenharmony_ci#include <asm/time.h> 2362306a36Sopenharmony_ci#include <asm/udbg.h> 2462306a36Sopenharmony_ci#include <asm/dma.h> 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ciextern void __flush_disable_L1(void); 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_civoid amigaone_show_cpuinfo(struct seq_file *m) 2962306a36Sopenharmony_ci{ 3062306a36Sopenharmony_ci seq_printf(m, "vendor\t\t: Eyetech Ltd.\n"); 3162306a36Sopenharmony_ci} 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_cistatic int __init amigaone_add_bridge(struct device_node *dev) 3462306a36Sopenharmony_ci{ 3562306a36Sopenharmony_ci const u32 *cfg_addr, *cfg_data; 3662306a36Sopenharmony_ci int len; 3762306a36Sopenharmony_ci const int *bus_range; 3862306a36Sopenharmony_ci struct pci_controller *hose; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci printk(KERN_INFO "Adding PCI host bridge %pOF\n", dev); 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci cfg_addr = of_get_address(dev, 0, NULL, NULL); 4362306a36Sopenharmony_ci cfg_data = of_get_address(dev, 1, NULL, NULL); 4462306a36Sopenharmony_ci if ((cfg_addr == NULL) || (cfg_data == NULL)) 4562306a36Sopenharmony_ci return -ENODEV; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci bus_range = of_get_property(dev, "bus-range", &len); 4862306a36Sopenharmony_ci if ((bus_range == NULL) || (len < 2 * sizeof(int))) 4962306a36Sopenharmony_ci printk(KERN_WARNING "Can't get bus-range for %pOF, assume" 5062306a36Sopenharmony_ci " bus 0\n", dev); 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci hose = pcibios_alloc_controller(dev); 5362306a36Sopenharmony_ci if (hose == NULL) 5462306a36Sopenharmony_ci return -ENOMEM; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci hose->first_busno = bus_range ? bus_range[0] : 0; 5762306a36Sopenharmony_ci hose->last_busno = bus_range ? bus_range[1] : 0xff; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci setup_indirect_pci(hose, cfg_addr[0], cfg_data[0], 0); 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci /* Interpret the "ranges" property */ 6262306a36Sopenharmony_ci /* This also maps the I/O region and sets isa_io/mem_base */ 6362306a36Sopenharmony_ci pci_process_bridge_OF_ranges(hose, dev, 1); 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci return 0; 6662306a36Sopenharmony_ci} 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_civoid __init amigaone_setup_arch(void) 6962306a36Sopenharmony_ci{ 7062306a36Sopenharmony_ci if (ppc_md.progress) 7162306a36Sopenharmony_ci ppc_md.progress("Linux/PPC "UTS_RELEASE"\n", 0); 7262306a36Sopenharmony_ci} 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_cistatic void __init amigaone_discover_phbs(void) 7562306a36Sopenharmony_ci{ 7662306a36Sopenharmony_ci struct device_node *np; 7762306a36Sopenharmony_ci int phb = -ENODEV; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci /* Lookup PCI host bridges. */ 8062306a36Sopenharmony_ci for_each_compatible_node(np, "pci", "mai-logic,articia-s") 8162306a36Sopenharmony_ci phb = amigaone_add_bridge(np); 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci BUG_ON(phb != 0); 8462306a36Sopenharmony_ci} 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_civoid __init amigaone_init_IRQ(void) 8762306a36Sopenharmony_ci{ 8862306a36Sopenharmony_ci struct device_node *pic, *np = NULL; 8962306a36Sopenharmony_ci const unsigned long *prop = NULL; 9062306a36Sopenharmony_ci unsigned long int_ack = 0; 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci /* Search for ISA interrupt controller. */ 9362306a36Sopenharmony_ci pic = of_find_compatible_node(NULL, "interrupt-controller", 9462306a36Sopenharmony_ci "pnpPNP,000"); 9562306a36Sopenharmony_ci BUG_ON(pic == NULL); 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci /* Look for interrupt acknowledge address in the PCI root node. */ 9862306a36Sopenharmony_ci np = of_find_compatible_node(NULL, "pci", "mai-logic,articia-s"); 9962306a36Sopenharmony_ci if (np) { 10062306a36Sopenharmony_ci prop = of_get_property(np, "8259-interrupt-acknowledge", NULL); 10162306a36Sopenharmony_ci if (prop) 10262306a36Sopenharmony_ci int_ack = prop[0]; 10362306a36Sopenharmony_ci of_node_put(np); 10462306a36Sopenharmony_ci } 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci if (int_ack == 0) 10762306a36Sopenharmony_ci printk(KERN_WARNING "Cannot find PCI interrupt acknowledge" 10862306a36Sopenharmony_ci " address, polling\n"); 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci i8259_init(pic, int_ack); 11162306a36Sopenharmony_ci ppc_md.get_irq = i8259_irq; 11262306a36Sopenharmony_ci irq_set_default_host(i8259_get_host()); 11362306a36Sopenharmony_ci} 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_cistatic int __init request_isa_regions(void) 11662306a36Sopenharmony_ci{ 11762306a36Sopenharmony_ci request_region(0x00, 0x20, "dma1"); 11862306a36Sopenharmony_ci request_region(0x40, 0x20, "timer"); 11962306a36Sopenharmony_ci request_region(0x80, 0x10, "dma page reg"); 12062306a36Sopenharmony_ci request_region(0xc0, 0x20, "dma2"); 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci return 0; 12362306a36Sopenharmony_ci} 12462306a36Sopenharmony_cimachine_device_initcall(amigaone, request_isa_regions); 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_civoid __noreturn amigaone_restart(char *cmd) 12762306a36Sopenharmony_ci{ 12862306a36Sopenharmony_ci local_irq_disable(); 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci /* Flush and disable caches. */ 13162306a36Sopenharmony_ci __flush_disable_L1(); 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci /* Set SRR0 to the reset vector and turn on MSR_IP. */ 13462306a36Sopenharmony_ci mtspr(SPRN_SRR0, 0xfff00100); 13562306a36Sopenharmony_ci mtspr(SPRN_SRR1, MSR_IP); 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci /* Do an rfi to jump back to firmware. */ 13862306a36Sopenharmony_ci __asm__ __volatile__("rfi" : : : "memory"); 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci /* Not reached. */ 14162306a36Sopenharmony_ci while (1); 14262306a36Sopenharmony_ci} 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_cistatic int __init amigaone_probe(void) 14562306a36Sopenharmony_ci{ 14662306a36Sopenharmony_ci /* 14762306a36Sopenharmony_ci * Coherent memory access cause complete system lockup! Thus 14862306a36Sopenharmony_ci * disable this CPU feature, even if the CPU needs it. 14962306a36Sopenharmony_ci */ 15062306a36Sopenharmony_ci cur_cpu_spec->cpu_features &= ~CPU_FTR_NEED_COHERENT; 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci DMA_MODE_READ = 0x44; 15362306a36Sopenharmony_ci DMA_MODE_WRITE = 0x48; 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci return 1; 15662306a36Sopenharmony_ci} 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_cidefine_machine(amigaone) { 15962306a36Sopenharmony_ci .name = "AmigaOne", 16062306a36Sopenharmony_ci .compatible = "eyetech,amigaone", 16162306a36Sopenharmony_ci .probe = amigaone_probe, 16262306a36Sopenharmony_ci .setup_arch = amigaone_setup_arch, 16362306a36Sopenharmony_ci .discover_phbs = amigaone_discover_phbs, 16462306a36Sopenharmony_ci .show_cpuinfo = amigaone_show_cpuinfo, 16562306a36Sopenharmony_ci .init_IRQ = amigaone_init_IRQ, 16662306a36Sopenharmony_ci .restart = amigaone_restart, 16762306a36Sopenharmony_ci .progress = udbg_progress, 16862306a36Sopenharmony_ci}; 169