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> | |
16 | #include <linux/seq_file.h> | |
273b281f | 17 | #include <generated/utsrelease.h> |
54b318aa GP |
18 | |
19 | #include <asm/machdep.h> | |
20 | #include <asm/cputable.h> | |
21 | #include <asm/prom.h> | |
22 | #include <asm/pci-bridge.h> | |
23 | #include <asm/i8259.h> | |
24 | #include <asm/time.h> | |
25 | #include <asm/udbg.h> | |
26 | ||
27 | extern void __flush_disable_L1(void); | |
28 | ||
29 | void amigaone_show_cpuinfo(struct seq_file *m) | |
30 | { | |
31 | seq_printf(m, "vendor\t\t: Eyetech Ltd.\n"); | |
32 | } | |
33 | ||
34 | static int __init amigaone_add_bridge(struct device_node *dev) | |
35 | { | |
36 | const u32 *cfg_addr, *cfg_data; | |
37 | int len; | |
38 | const int *bus_range; | |
39 | struct pci_controller *hose; | |
40 | ||
41 | printk(KERN_INFO "Adding PCI host bridge %s\n", dev->full_name); | |
42 | ||
43 | cfg_addr = of_get_address(dev, 0, NULL, NULL); | |
44 | cfg_data = of_get_address(dev, 1, NULL, NULL); | |
45 | if ((cfg_addr == NULL) || (cfg_data == NULL)) | |
46 | return -ENODEV; | |
47 | ||
48 | bus_range = of_get_property(dev, "bus-range", &len); | |
49 | if ((bus_range == NULL) || (len < 2 * sizeof(int))) | |
50 | printk(KERN_WARNING "Can't get bus-range for %s, assume" | |
51 | " bus 0\n", dev->full_name); | |
52 | ||
53 | hose = pcibios_alloc_controller(dev); | |
54 | if (hose == NULL) | |
55 | return -ENOMEM; | |
56 | ||
57 | hose->first_busno = bus_range ? bus_range[0] : 0; | |
58 | hose->last_busno = bus_range ? bus_range[1] : 0xff; | |
59 | ||
60 | setup_indirect_pci(hose, cfg_addr[0], cfg_data[0], 0); | |
61 | ||
62 | /* Interpret the "ranges" property */ | |
63 | /* This also maps the I/O region and sets isa_io/mem_base */ | |
64 | pci_process_bridge_OF_ranges(hose, dev, 1); | |
65 | ||
66 | return 0; | |
67 | } | |
68 | ||
69 | void __init amigaone_setup_arch(void) | |
70 | { | |
71 | struct device_node *np; | |
72 | int phb = -ENODEV; | |
73 | ||
74 | /* Lookup PCI host bridges. */ | |
75 | for_each_compatible_node(np, "pci", "mai-logic,articia-s") | |
76 | phb = amigaone_add_bridge(np); | |
77 | ||
78 | BUG_ON(phb != 0); | |
79 | ||
80 | if (ppc_md.progress) | |
81 | ppc_md.progress("Linux/PPC "UTS_RELEASE"\n", 0); | |
82 | } | |
83 | ||
84 | void __init amigaone_init_IRQ(void) | |
85 | { | |
86 | struct device_node *pic, *np = NULL; | |
87 | const unsigned long *prop = NULL; | |
88 | unsigned long int_ack = 0; | |
89 | ||
90 | /* Search for ISA interrupt controller. */ | |
91 | pic = of_find_compatible_node(NULL, "interrupt-controller", | |
92 | "pnpPNP,000"); | |
93 | BUG_ON(pic == NULL); | |
94 | ||
95 | /* Look for interrupt acknowledge address in the PCI root node. */ | |
96 | np = of_find_compatible_node(NULL, "pci", "mai-logic,articia-s"); | |
97 | if (np) { | |
98 | prop = of_get_property(np, "8259-interrupt-acknowledge", NULL); | |
99 | if (prop) | |
100 | int_ack = prop[0]; | |
101 | of_node_put(np); | |
102 | } | |
103 | ||
104 | if (int_ack == 0) | |
105 | printk(KERN_WARNING "Cannot find PCI interrupt acknowledge" | |
106 | " address, polling\n"); | |
107 | ||
108 | i8259_init(pic, int_ack); | |
109 | ppc_md.get_irq = i8259_irq; | |
110 | irq_set_default_host(i8259_get_host()); | |
111 | } | |
112 | ||
66dc3304 | 113 | static int __init request_isa_regions(void) |
54b318aa GP |
114 | { |
115 | request_region(0x00, 0x20, "dma1"); | |
116 | request_region(0x40, 0x20, "timer"); | |
117 | request_region(0x80, 0x10, "dma page reg"); | |
118 | request_region(0xc0, 0x20, "dma2"); | |
66dc3304 GP |
119 | |
120 | return 0; | |
54b318aa | 121 | } |
66dc3304 | 122 | machine_device_initcall(amigaone, request_isa_regions); |
54b318aa GP |
123 | |
124 | void amigaone_restart(char *cmd) | |
125 | { | |
126 | local_irq_disable(); | |
127 | ||
128 | /* Flush and disable caches. */ | |
129 | __flush_disable_L1(); | |
130 | ||
131 | /* Set SRR0 to the reset vector and turn on MSR_IP. */ | |
132 | mtspr(SPRN_SRR0, 0xfff00100); | |
133 | mtspr(SPRN_SRR1, MSR_IP); | |
134 | ||
135 | /* Do an rfi to jump back to firmware. */ | |
136 | __asm__ __volatile__("rfi" : : : "memory"); | |
137 | ||
138 | /* Not reached. */ | |
139 | while (1); | |
140 | } | |
141 | ||
142 | static int __init amigaone_probe(void) | |
143 | { | |
144 | unsigned long root = of_get_flat_dt_root(); | |
145 | ||
146 | if (of_flat_dt_is_compatible(root, "eyetech,amigaone")) { | |
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 | }; |