]>
Commit | Line | Data |
---|---|---|
2874c5fd | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
54b318aa GP |
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 | |
54b318aa GP |
9 | */ |
10 | ||
11 | #include <linux/kernel.h> | |
22ae782f GL |
12 | #include <linux/of.h> |
13 | #include <linux/of_address.h> | |
54b318aa | 14 | #include <linux/seq_file.h> |
273b281f | 15 | #include <generated/utsrelease.h> |
54b318aa GP |
16 | |
17 | #include <asm/machdep.h> | |
18 | #include <asm/cputable.h> | |
54b318aa GP |
19 | #include <asm/pci-bridge.h> |
20 | #include <asm/i8259.h> | |
21 | #include <asm/time.h> | |
22 | #include <asm/udbg.h> | |
308c09f1 | 23 | #include <asm/dma.h> |
54b318aa GP |
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 | ||
b7c670d6 | 39 | printk(KERN_INFO "Adding PCI host bridge %pOF\n", dev); |
54b318aa GP |
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))) | |
b7c670d6 RH |
48 | printk(KERN_WARNING "Can't get bus-range for %pOF, assume" |
49 | " bus 0\n", dev); | |
54b318aa GP |
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 | ||
66dc3304 | 111 | static int __init request_isa_regions(void) |
54b318aa GP |
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"); | |
66dc3304 GP |
117 | |
118 | return 0; | |
54b318aa | 119 | } |
66dc3304 | 120 | machine_device_initcall(amigaone, request_isa_regions); |
54b318aa | 121 | |
95ec77c0 | 122 | void __noreturn amigaone_restart(char *cmd) |
54b318aa GP |
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 | { | |
56571384 | 142 | if (of_machine_is_compatible("eyetech,amigaone")) { |
54b318aa GP |
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 | ISA_DMA_THRESHOLD = 0x00ffffff; | |
150 | DMA_MODE_READ = 0x44; | |
151 | DMA_MODE_WRITE = 0x48; | |
152 | ||
153 | return 1; | |
154 | } | |
155 | ||
156 | return 0; | |
157 | } | |
158 | ||
159 | define_machine(amigaone) { | |
160 | .name = "AmigaOne", | |
161 | .probe = amigaone_probe, | |
162 | .setup_arch = amigaone_setup_arch, | |
54b318aa GP |
163 | .show_cpuinfo = amigaone_show_cpuinfo, |
164 | .init_IRQ = amigaone_init_IRQ, | |
165 | .restart = amigaone_restart, | |
166 | .calibrate_decr = generic_calibrate_decr, | |
167 | .progress = udbg_progress, | |
168 | }; |