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