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