18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * AmigaOne platform setup 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright 2008 Gerhard Pircher (gerhard_pircher@gmx.net) 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Based on original amigaone_setup.c source code 88c2ecf20Sopenharmony_ci * Copyright 2003 by Hans-Joerg Frieden and Thomas Frieden 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/kernel.h> 128c2ecf20Sopenharmony_ci#include <linux/of.h> 138c2ecf20Sopenharmony_ci#include <linux/of_address.h> 148c2ecf20Sopenharmony_ci#include <linux/seq_file.h> 158c2ecf20Sopenharmony_ci#include <generated/utsrelease.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#include <asm/machdep.h> 188c2ecf20Sopenharmony_ci#include <asm/cputable.h> 198c2ecf20Sopenharmony_ci#include <asm/pci-bridge.h> 208c2ecf20Sopenharmony_ci#include <asm/i8259.h> 218c2ecf20Sopenharmony_ci#include <asm/time.h> 228c2ecf20Sopenharmony_ci#include <asm/udbg.h> 238c2ecf20Sopenharmony_ci#include <asm/dma.h> 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ciextern void __flush_disable_L1(void); 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_civoid amigaone_show_cpuinfo(struct seq_file *m) 288c2ecf20Sopenharmony_ci{ 298c2ecf20Sopenharmony_ci seq_printf(m, "vendor\t\t: Eyetech Ltd.\n"); 308c2ecf20Sopenharmony_ci} 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_cistatic int __init amigaone_add_bridge(struct device_node *dev) 338c2ecf20Sopenharmony_ci{ 348c2ecf20Sopenharmony_ci const u32 *cfg_addr, *cfg_data; 358c2ecf20Sopenharmony_ci int len; 368c2ecf20Sopenharmony_ci const int *bus_range; 378c2ecf20Sopenharmony_ci struct pci_controller *hose; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci printk(KERN_INFO "Adding PCI host bridge %pOF\n", dev); 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci cfg_addr = of_get_address(dev, 0, NULL, NULL); 428c2ecf20Sopenharmony_ci cfg_data = of_get_address(dev, 1, NULL, NULL); 438c2ecf20Sopenharmony_ci if ((cfg_addr == NULL) || (cfg_data == NULL)) 448c2ecf20Sopenharmony_ci return -ENODEV; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci bus_range = of_get_property(dev, "bus-range", &len); 478c2ecf20Sopenharmony_ci if ((bus_range == NULL) || (len < 2 * sizeof(int))) 488c2ecf20Sopenharmony_ci printk(KERN_WARNING "Can't get bus-range for %pOF, assume" 498c2ecf20Sopenharmony_ci " bus 0\n", dev); 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci hose = pcibios_alloc_controller(dev); 528c2ecf20Sopenharmony_ci if (hose == NULL) 538c2ecf20Sopenharmony_ci return -ENOMEM; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci hose->first_busno = bus_range ? bus_range[0] : 0; 568c2ecf20Sopenharmony_ci hose->last_busno = bus_range ? bus_range[1] : 0xff; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci setup_indirect_pci(hose, cfg_addr[0], cfg_data[0], 0); 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci /* Interpret the "ranges" property */ 618c2ecf20Sopenharmony_ci /* This also maps the I/O region and sets isa_io/mem_base */ 628c2ecf20Sopenharmony_ci pci_process_bridge_OF_ranges(hose, dev, 1); 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci return 0; 658c2ecf20Sopenharmony_ci} 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_civoid __init amigaone_setup_arch(void) 688c2ecf20Sopenharmony_ci{ 698c2ecf20Sopenharmony_ci struct device_node *np; 708c2ecf20Sopenharmony_ci int phb = -ENODEV; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci /* Lookup PCI host bridges. */ 738c2ecf20Sopenharmony_ci for_each_compatible_node(np, "pci", "mai-logic,articia-s") 748c2ecf20Sopenharmony_ci phb = amigaone_add_bridge(np); 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci BUG_ON(phb != 0); 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci if (ppc_md.progress) 798c2ecf20Sopenharmony_ci ppc_md.progress("Linux/PPC "UTS_RELEASE"\n", 0); 808c2ecf20Sopenharmony_ci} 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_civoid __init amigaone_init_IRQ(void) 838c2ecf20Sopenharmony_ci{ 848c2ecf20Sopenharmony_ci struct device_node *pic, *np = NULL; 858c2ecf20Sopenharmony_ci const unsigned long *prop = NULL; 868c2ecf20Sopenharmony_ci unsigned long int_ack = 0; 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci /* Search for ISA interrupt controller. */ 898c2ecf20Sopenharmony_ci pic = of_find_compatible_node(NULL, "interrupt-controller", 908c2ecf20Sopenharmony_ci "pnpPNP,000"); 918c2ecf20Sopenharmony_ci BUG_ON(pic == NULL); 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci /* Look for interrupt acknowledge address in the PCI root node. */ 948c2ecf20Sopenharmony_ci np = of_find_compatible_node(NULL, "pci", "mai-logic,articia-s"); 958c2ecf20Sopenharmony_ci if (np) { 968c2ecf20Sopenharmony_ci prop = of_get_property(np, "8259-interrupt-acknowledge", NULL); 978c2ecf20Sopenharmony_ci if (prop) 988c2ecf20Sopenharmony_ci int_ack = prop[0]; 998c2ecf20Sopenharmony_ci of_node_put(np); 1008c2ecf20Sopenharmony_ci } 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci if (int_ack == 0) 1038c2ecf20Sopenharmony_ci printk(KERN_WARNING "Cannot find PCI interrupt acknowledge" 1048c2ecf20Sopenharmony_ci " address, polling\n"); 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci i8259_init(pic, int_ack); 1078c2ecf20Sopenharmony_ci ppc_md.get_irq = i8259_irq; 1088c2ecf20Sopenharmony_ci irq_set_default_host(i8259_get_host()); 1098c2ecf20Sopenharmony_ci} 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_cistatic int __init request_isa_regions(void) 1128c2ecf20Sopenharmony_ci{ 1138c2ecf20Sopenharmony_ci request_region(0x00, 0x20, "dma1"); 1148c2ecf20Sopenharmony_ci request_region(0x40, 0x20, "timer"); 1158c2ecf20Sopenharmony_ci request_region(0x80, 0x10, "dma page reg"); 1168c2ecf20Sopenharmony_ci request_region(0xc0, 0x20, "dma2"); 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci return 0; 1198c2ecf20Sopenharmony_ci} 1208c2ecf20Sopenharmony_cimachine_device_initcall(amigaone, request_isa_regions); 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_civoid __noreturn amigaone_restart(char *cmd) 1238c2ecf20Sopenharmony_ci{ 1248c2ecf20Sopenharmony_ci local_irq_disable(); 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci /* Flush and disable caches. */ 1278c2ecf20Sopenharmony_ci __flush_disable_L1(); 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci /* Set SRR0 to the reset vector and turn on MSR_IP. */ 1308c2ecf20Sopenharmony_ci mtspr(SPRN_SRR0, 0xfff00100); 1318c2ecf20Sopenharmony_ci mtspr(SPRN_SRR1, MSR_IP); 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci /* Do an rfi to jump back to firmware. */ 1348c2ecf20Sopenharmony_ci __asm__ __volatile__("rfi" : : : "memory"); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci /* Not reached. */ 1378c2ecf20Sopenharmony_ci while (1); 1388c2ecf20Sopenharmony_ci} 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_cistatic int __init amigaone_probe(void) 1418c2ecf20Sopenharmony_ci{ 1428c2ecf20Sopenharmony_ci if (of_machine_is_compatible("eyetech,amigaone")) { 1438c2ecf20Sopenharmony_ci /* 1448c2ecf20Sopenharmony_ci * Coherent memory access cause complete system lockup! Thus 1458c2ecf20Sopenharmony_ci * disable this CPU feature, even if the CPU needs it. 1468c2ecf20Sopenharmony_ci */ 1478c2ecf20Sopenharmony_ci cur_cpu_spec->cpu_features &= ~CPU_FTR_NEED_COHERENT; 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci DMA_MODE_READ = 0x44; 1508c2ecf20Sopenharmony_ci DMA_MODE_WRITE = 0x48; 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci return 1; 1538c2ecf20Sopenharmony_ci } 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci return 0; 1568c2ecf20Sopenharmony_ci} 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_cidefine_machine(amigaone) { 1598c2ecf20Sopenharmony_ci .name = "AmigaOne", 1608c2ecf20Sopenharmony_ci .probe = amigaone_probe, 1618c2ecf20Sopenharmony_ci .setup_arch = amigaone_setup_arch, 1628c2ecf20Sopenharmony_ci .show_cpuinfo = amigaone_show_cpuinfo, 1638c2ecf20Sopenharmony_ci .init_IRQ = amigaone_init_IRQ, 1648c2ecf20Sopenharmony_ci .restart = amigaone_restart, 1658c2ecf20Sopenharmony_ci .calibrate_decr = generic_calibrate_decr, 1668c2ecf20Sopenharmony_ci .progress = udbg_progress, 1678c2ecf20Sopenharmony_ci}; 168