Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/powerpc/platforms/cell/setup.c
10818 views
1
/*
2
* linux/arch/powerpc/platforms/cell/cell_setup.c
3
*
4
* Copyright (C) 1995 Linus Torvalds
5
* Adapted from 'alpha' version by Gary Thomas
6
* Modified by Cort Dougan ([email protected])
7
* Modified by PPC64 Team, IBM Corp
8
* Modified by Cell Team, IBM Deutschland Entwicklung GmbH
9
*
10
* This program is free software; you can redistribute it and/or
11
* modify it under the terms of the GNU General Public License
12
* as published by the Free Software Foundation; either version
13
* 2 of the License, or (at your option) any later version.
14
*/
15
#undef DEBUG
16
17
#include <linux/sched.h>
18
#include <linux/kernel.h>
19
#include <linux/mm.h>
20
#include <linux/stddef.h>
21
#include <linux/unistd.h>
22
#include <linux/user.h>
23
#include <linux/reboot.h>
24
#include <linux/init.h>
25
#include <linux/delay.h>
26
#include <linux/irq.h>
27
#include <linux/seq_file.h>
28
#include <linux/root_dev.h>
29
#include <linux/console.h>
30
#include <linux/mutex.h>
31
#include <linux/memory_hotplug.h>
32
#include <linux/of_platform.h>
33
34
#include <asm/mmu.h>
35
#include <asm/processor.h>
36
#include <asm/io.h>
37
#include <asm/pgtable.h>
38
#include <asm/prom.h>
39
#include <asm/rtas.h>
40
#include <asm/pci-bridge.h>
41
#include <asm/iommu.h>
42
#include <asm/dma.h>
43
#include <asm/machdep.h>
44
#include <asm/time.h>
45
#include <asm/nvram.h>
46
#include <asm/cputable.h>
47
#include <asm/ppc-pci.h>
48
#include <asm/irq.h>
49
#include <asm/spu.h>
50
#include <asm/spu_priv1.h>
51
#include <asm/udbg.h>
52
#include <asm/mpic.h>
53
#include <asm/cell-regs.h>
54
#include <asm/io-workarounds.h>
55
56
#include "interrupt.h"
57
#include "pervasive.h"
58
#include "ras.h"
59
60
#ifdef DEBUG
61
#define DBG(fmt...) udbg_printf(fmt)
62
#else
63
#define DBG(fmt...)
64
#endif
65
66
static void cell_show_cpuinfo(struct seq_file *m)
67
{
68
struct device_node *root;
69
const char *model = "";
70
71
root = of_find_node_by_path("/");
72
if (root)
73
model = of_get_property(root, "model", NULL);
74
seq_printf(m, "machine\t\t: CHRP %s\n", model);
75
of_node_put(root);
76
}
77
78
static void cell_progress(char *s, unsigned short hex)
79
{
80
printk("*** %04x : %s\n", hex, s ? s : "");
81
}
82
83
static void cell_fixup_pcie_rootcomplex(struct pci_dev *dev)
84
{
85
struct pci_controller *hose;
86
const char *s;
87
int i;
88
89
if (!machine_is(cell))
90
return;
91
92
/* We're searching for a direct child of the PHB */
93
if (dev->bus->self != NULL || dev->devfn != 0)
94
return;
95
96
hose = pci_bus_to_host(dev->bus);
97
if (hose == NULL)
98
return;
99
100
/* Only on PCIE */
101
if (!of_device_is_compatible(hose->dn, "pciex"))
102
return;
103
104
/* And only on axon */
105
s = of_get_property(hose->dn, "model", NULL);
106
if (!s || strcmp(s, "Axon") != 0)
107
return;
108
109
for (i = 0; i < PCI_BRIDGE_RESOURCES; i++) {
110
dev->resource[i].start = dev->resource[i].end = 0;
111
dev->resource[i].flags = 0;
112
}
113
114
printk(KERN_DEBUG "PCI: Hiding resources on Axon PCIE RC %s\n",
115
pci_name(dev));
116
}
117
DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, cell_fixup_pcie_rootcomplex);
118
119
static int __devinit cell_setup_phb(struct pci_controller *phb)
120
{
121
const char *model;
122
struct device_node *np;
123
124
int rc = rtas_setup_phb(phb);
125
if (rc)
126
return rc;
127
128
np = phb->dn;
129
model = of_get_property(np, "model", NULL);
130
if (model == NULL || strcmp(np->name, "pci"))
131
return 0;
132
133
/* Setup workarounds for spider */
134
if (strcmp(model, "Spider"))
135
return 0;
136
137
iowa_register_bus(phb, &spiderpci_ops, &spiderpci_iowa_init,
138
(void *)SPIDER_PCI_REG_BASE);
139
return 0;
140
}
141
142
static const struct of_device_id cell_bus_ids[] __initdata = {
143
{ .type = "soc", },
144
{ .compatible = "soc", },
145
{ .type = "spider", },
146
{ .type = "axon", },
147
{ .type = "plb5", },
148
{ .type = "plb4", },
149
{ .type = "opb", },
150
{ .type = "ebc", },
151
{},
152
};
153
154
static int __init cell_publish_devices(void)
155
{
156
struct device_node *root = of_find_node_by_path("/");
157
struct device_node *np;
158
int node;
159
160
/* Publish OF platform devices for southbridge IOs */
161
of_platform_bus_probe(NULL, cell_bus_ids, NULL);
162
163
/* On spider based blades, we need to manually create the OF
164
* platform devices for the PCI host bridges
165
*/
166
for_each_child_of_node(root, np) {
167
if (np->type == NULL || (strcmp(np->type, "pci") != 0 &&
168
strcmp(np->type, "pciex") != 0))
169
continue;
170
of_platform_device_create(np, NULL, NULL);
171
}
172
173
/* There is no device for the MIC memory controller, thus we create
174
* a platform device for it to attach the EDAC driver to.
175
*/
176
for_each_online_node(node) {
177
if (cbe_get_cpu_mic_tm_regs(cbe_node_to_cpu(node)) == NULL)
178
continue;
179
platform_device_register_simple("cbe-mic", node, NULL, 0);
180
}
181
182
return 0;
183
}
184
machine_subsys_initcall(cell, cell_publish_devices);
185
186
static void cell_mpic_cascade(unsigned int irq, struct irq_desc *desc)
187
{
188
struct irq_chip *chip = irq_desc_get_chip(desc);
189
struct mpic *mpic = irq_desc_get_handler_data(desc);
190
unsigned int virq;
191
192
virq = mpic_get_one_irq(mpic);
193
if (virq != NO_IRQ)
194
generic_handle_irq(virq);
195
196
chip->irq_eoi(&desc->irq_data);
197
}
198
199
static void __init mpic_init_IRQ(void)
200
{
201
struct device_node *dn;
202
struct mpic *mpic;
203
unsigned int virq;
204
205
for (dn = NULL;
206
(dn = of_find_node_by_name(dn, "interrupt-controller"));) {
207
if (!of_device_is_compatible(dn, "CBEA,platform-open-pic"))
208
continue;
209
210
/* The MPIC driver will get everything it needs from the
211
* device-tree, just pass 0 to all arguments
212
*/
213
mpic = mpic_alloc(dn, 0, 0, 0, 0, " MPIC ");
214
if (mpic == NULL)
215
continue;
216
mpic_init(mpic);
217
218
virq = irq_of_parse_and_map(dn, 0);
219
if (virq == NO_IRQ)
220
continue;
221
222
printk(KERN_INFO "%s : hooking up to IRQ %d\n",
223
dn->full_name, virq);
224
irq_set_handler_data(virq, mpic);
225
irq_set_chained_handler(virq, cell_mpic_cascade);
226
}
227
}
228
229
230
static void __init cell_init_irq(void)
231
{
232
iic_init_IRQ();
233
spider_init_IRQ();
234
mpic_init_IRQ();
235
}
236
237
static void __init cell_set_dabrx(void)
238
{
239
mtspr(SPRN_DABRX, DABRX_KERNEL | DABRX_USER);
240
}
241
242
static void __init cell_setup_arch(void)
243
{
244
#ifdef CONFIG_SPU_BASE
245
spu_priv1_ops = &spu_priv1_mmio_ops;
246
spu_management_ops = &spu_management_of_ops;
247
#endif
248
249
cbe_regs_init();
250
251
cell_set_dabrx();
252
253
#ifdef CONFIG_CBE_RAS
254
cbe_ras_init();
255
#endif
256
257
#ifdef CONFIG_SMP
258
smp_init_cell();
259
#endif
260
/* init to some ~sane value until calibrate_delay() runs */
261
loops_per_jiffy = 50000000;
262
263
/* Find and initialize PCI host bridges */
264
init_pci_config_tokens();
265
266
cbe_pervasive_init();
267
#ifdef CONFIG_DUMMY_CONSOLE
268
conswitchp = &dummy_con;
269
#endif
270
271
mmio_nvram_init();
272
}
273
274
static int __init cell_probe(void)
275
{
276
unsigned long root = of_get_flat_dt_root();
277
278
if (!of_flat_dt_is_compatible(root, "IBM,CBEA") &&
279
!of_flat_dt_is_compatible(root, "IBM,CPBW-1.0"))
280
return 0;
281
282
hpte_init_native();
283
284
return 1;
285
}
286
287
define_machine(cell) {
288
.name = "Cell",
289
.probe = cell_probe,
290
.setup_arch = cell_setup_arch,
291
.show_cpuinfo = cell_show_cpuinfo,
292
.restart = rtas_restart,
293
.power_off = rtas_power_off,
294
.halt = rtas_halt,
295
.get_boot_time = rtas_get_boot_time,
296
.get_rtc_time = rtas_get_rtc_time,
297
.set_rtc_time = rtas_set_rtc_time,
298
.calibrate_decr = generic_calibrate_decr,
299
.progress = cell_progress,
300
.init_IRQ = cell_init_irq,
301
.pci_setup_phb = cell_setup_phb,
302
};
303
304