aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc64
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2005-10-29 08:07:56 -0400
committerPaul Mackerras <paulus@samba.org>2005-10-29 08:07:56 -0400
commit0cb7b2afd79c5715cbd1d4eee826571fb17fdd65 (patch)
tree6748e2d741c731aa8afa458152d934b7ad81715c /arch/ppc64
parentd3f67fbb96b827c1a6a7a82689e589865581155c (diff)
powerpc: Merge maple support code to arch/powerpc/platforms/maple
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/ppc64')
-rw-r--r--arch/ppc64/kernel/Makefile3
-rw-r--r--arch/ppc64/kernel/maple_pci.c520
-rw-r--r--arch/ppc64/kernel/maple_setup.c300
-rw-r--r--arch/ppc64/kernel/maple_time.c178
4 files changed, 1 insertions, 1000 deletions
diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile
index 3cf7f3dab511..327c08ce4291 100644
--- a/arch/ppc64/kernel/Makefile
+++ b/arch/ppc64/kernel/Makefile
@@ -55,8 +55,7 @@ obj-$(CONFIG_HVCS) += hvcserver.o
55 55
56obj-$(CONFIG_PPC_PMAC) += udbg_scc.o 56obj-$(CONFIG_PPC_PMAC) += udbg_scc.o
57 57
58obj-$(CONFIG_PPC_MAPLE) += maple_setup.o maple_pci.o maple_time.o \ 58obj-$(CONFIG_PPC_MAPLE) += udbg_16550.o
59 udbg_16550.o
60 59
61ifdef CONFIG_SMP 60ifdef CONFIG_SMP
62obj-$(CONFIG_PPC_PMAC) += smp-tbsync.o 61obj-$(CONFIG_PPC_PMAC) += smp-tbsync.o
diff --git a/arch/ppc64/kernel/maple_pci.c b/arch/ppc64/kernel/maple_pci.c
deleted file mode 100644
index 633324b5e61b..000000000000
--- a/arch/ppc64/kernel/maple_pci.c
+++ /dev/null
@@ -1,520 +0,0 @@
1/*
2 * Copyright (C) 2004 Benjamin Herrenschmuidt (benh@kernel.crashing.org),
3 * IBM Corp.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version
8 * 2 of the License, or (at your option) any later version.
9 */
10
11#define DEBUG
12
13#include <linux/kernel.h>
14#include <linux/pci.h>
15#include <linux/delay.h>
16#include <linux/string.h>
17#include <linux/init.h>
18#include <linux/bootmem.h>
19
20#include <asm/sections.h>
21#include <asm/io.h>
22#include <asm/prom.h>
23#include <asm/pci-bridge.h>
24#include <asm/machdep.h>
25#include <asm/iommu.h>
26#include <asm/ppc-pci.h>
27
28#ifdef DEBUG
29#define DBG(x...) printk(x)
30#else
31#define DBG(x...)
32#endif
33
34static struct pci_controller *u3_agp, *u3_ht;
35
36static int __init fixup_one_level_bus_range(struct device_node *node, int higher)
37{
38 for (; node != 0;node = node->sibling) {
39 int * bus_range;
40 unsigned int *class_code;
41 int len;
42
43 /* For PCI<->PCI bridges or CardBus bridges, we go down */
44 class_code = (unsigned int *) get_property(node, "class-code", NULL);
45 if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
46 (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS))
47 continue;
48 bus_range = (int *) get_property(node, "bus-range", &len);
49 if (bus_range != NULL && len > 2 * sizeof(int)) {
50 if (bus_range[1] > higher)
51 higher = bus_range[1];
52 }
53 higher = fixup_one_level_bus_range(node->child, higher);
54 }
55 return higher;
56}
57
58/* This routine fixes the "bus-range" property of all bridges in the
59 * system since they tend to have their "last" member wrong on macs
60 *
61 * Note that the bus numbers manipulated here are OF bus numbers, they
62 * are not Linux bus numbers.
63 */
64static void __init fixup_bus_range(struct device_node *bridge)
65{
66 int * bus_range;
67 int len;
68
69 /* Lookup the "bus-range" property for the hose */
70 bus_range = (int *) get_property(bridge, "bus-range", &len);
71 if (bus_range == NULL || len < 2 * sizeof(int)) {
72 printk(KERN_WARNING "Can't get bus-range for %s\n",
73 bridge->full_name);
74 return;
75 }
76 bus_range[1] = fixup_one_level_bus_range(bridge->child, bus_range[1]);
77}
78
79
80#define U3_AGP_CFA0(devfn, off) \
81 ((1 << (unsigned long)PCI_SLOT(dev_fn)) \
82 | (((unsigned long)PCI_FUNC(dev_fn)) << 8) \
83 | (((unsigned long)(off)) & 0xFCUL))
84
85#define U3_AGP_CFA1(bus, devfn, off) \
86 ((((unsigned long)(bus)) << 16) \
87 |(((unsigned long)(devfn)) << 8) \
88 |(((unsigned long)(off)) & 0xFCUL) \
89 |1UL)
90
91static unsigned long u3_agp_cfg_access(struct pci_controller* hose,
92 u8 bus, u8 dev_fn, u8 offset)
93{
94 unsigned int caddr;
95
96 if (bus == hose->first_busno) {
97 if (dev_fn < (11 << 3))
98 return 0;
99 caddr = U3_AGP_CFA0(dev_fn, offset);
100 } else
101 caddr = U3_AGP_CFA1(bus, dev_fn, offset);
102
103 /* Uninorth will return garbage if we don't read back the value ! */
104 do {
105 out_le32(hose->cfg_addr, caddr);
106 } while (in_le32(hose->cfg_addr) != caddr);
107
108 offset &= 0x07;
109 return ((unsigned long)hose->cfg_data) + offset;
110}
111
112static int u3_agp_read_config(struct pci_bus *bus, unsigned int devfn,
113 int offset, int len, u32 *val)
114{
115 struct pci_controller *hose;
116 unsigned long addr;
117
118 hose = pci_bus_to_host(bus);
119 if (hose == NULL)
120 return PCIBIOS_DEVICE_NOT_FOUND;
121
122 addr = u3_agp_cfg_access(hose, bus->number, devfn, offset);
123 if (!addr)
124 return PCIBIOS_DEVICE_NOT_FOUND;
125 /*
126 * Note: the caller has already checked that offset is
127 * suitably aligned and that len is 1, 2 or 4.
128 */
129 switch (len) {
130 case 1:
131 *val = in_8((u8 *)addr);
132 break;
133 case 2:
134 *val = in_le16((u16 *)addr);
135 break;
136 default:
137 *val = in_le32((u32 *)addr);
138 break;
139 }
140 return PCIBIOS_SUCCESSFUL;
141}
142
143static int u3_agp_write_config(struct pci_bus *bus, unsigned int devfn,
144 int offset, int len, u32 val)
145{
146 struct pci_controller *hose;
147 unsigned long addr;
148
149 hose = pci_bus_to_host(bus);
150 if (hose == NULL)
151 return PCIBIOS_DEVICE_NOT_FOUND;
152
153 addr = u3_agp_cfg_access(hose, bus->number, devfn, offset);
154 if (!addr)
155 return PCIBIOS_DEVICE_NOT_FOUND;
156 /*
157 * Note: the caller has already checked that offset is
158 * suitably aligned and that len is 1, 2 or 4.
159 */
160 switch (len) {
161 case 1:
162 out_8((u8 *)addr, val);
163 (void) in_8((u8 *)addr);
164 break;
165 case 2:
166 out_le16((u16 *)addr, val);
167 (void) in_le16((u16 *)addr);
168 break;
169 default:
170 out_le32((u32 *)addr, val);
171 (void) in_le32((u32 *)addr);
172 break;
173 }
174 return PCIBIOS_SUCCESSFUL;
175}
176
177static struct pci_ops u3_agp_pci_ops =
178{
179 u3_agp_read_config,
180 u3_agp_write_config
181};
182
183
184#define U3_HT_CFA0(devfn, off) \
185 ((((unsigned long)devfn) << 8) | offset)
186#define U3_HT_CFA1(bus, devfn, off) \
187 (U3_HT_CFA0(devfn, off) \
188 + (((unsigned long)bus) << 16) \
189 + 0x01000000UL)
190
191static unsigned long u3_ht_cfg_access(struct pci_controller* hose,
192 u8 bus, u8 devfn, u8 offset)
193{
194 if (bus == hose->first_busno) {
195 if (PCI_SLOT(devfn) == 0)
196 return 0;
197 return ((unsigned long)hose->cfg_data) + U3_HT_CFA0(devfn, offset);
198 } else
199 return ((unsigned long)hose->cfg_data) + U3_HT_CFA1(bus, devfn, offset);
200}
201
202static int u3_ht_read_config(struct pci_bus *bus, unsigned int devfn,
203 int offset, int len, u32 *val)
204{
205 struct pci_controller *hose;
206 unsigned long addr;
207
208 hose = pci_bus_to_host(bus);
209 if (hose == NULL)
210 return PCIBIOS_DEVICE_NOT_FOUND;
211
212 addr = u3_ht_cfg_access(hose, bus->number, devfn, offset);
213 if (!addr)
214 return PCIBIOS_DEVICE_NOT_FOUND;
215
216 /*
217 * Note: the caller has already checked that offset is
218 * suitably aligned and that len is 1, 2 or 4.
219 */
220 switch (len) {
221 case 1:
222 *val = in_8((u8 *)addr);
223 break;
224 case 2:
225 *val = in_le16((u16 *)addr);
226 break;
227 default:
228 *val = in_le32((u32 *)addr);
229 break;
230 }
231 return PCIBIOS_SUCCESSFUL;
232}
233
234static int u3_ht_write_config(struct pci_bus *bus, unsigned int devfn,
235 int offset, int len, u32 val)
236{
237 struct pci_controller *hose;
238 unsigned long addr;
239
240 hose = pci_bus_to_host(bus);
241 if (hose == NULL)
242 return PCIBIOS_DEVICE_NOT_FOUND;
243
244 addr = u3_ht_cfg_access(hose, bus->number, devfn, offset);
245 if (!addr)
246 return PCIBIOS_DEVICE_NOT_FOUND;
247 /*
248 * Note: the caller has already checked that offset is
249 * suitably aligned and that len is 1, 2 or 4.
250 */
251 switch (len) {
252 case 1:
253 out_8((u8 *)addr, val);
254 (void) in_8((u8 *)addr);
255 break;
256 case 2:
257 out_le16((u16 *)addr, val);
258 (void) in_le16((u16 *)addr);
259 break;
260 default:
261 out_le32((u32 *)addr, val);
262 (void) in_le32((u32 *)addr);
263 break;
264 }
265 return PCIBIOS_SUCCESSFUL;
266}
267
268static struct pci_ops u3_ht_pci_ops =
269{
270 u3_ht_read_config,
271 u3_ht_write_config
272};
273
274static void __init setup_u3_agp(struct pci_controller* hose)
275{
276 /* On G5, we move AGP up to high bus number so we don't need
277 * to reassign bus numbers for HT. If we ever have P2P bridges
278 * on AGP, we'll have to move pci_assign_all_buses to the
279 * pci_controller structure so we enable it for AGP and not for
280 * HT childs.
281 * We hard code the address because of the different size of
282 * the reg address cell, we shall fix that by killing struct
283 * reg_property and using some accessor functions instead
284 */
285 hose->first_busno = 0xf0;
286 hose->last_busno = 0xff;
287 hose->ops = &u3_agp_pci_ops;
288 hose->cfg_addr = ioremap(0xf0000000 + 0x800000, 0x1000);
289 hose->cfg_data = ioremap(0xf0000000 + 0xc00000, 0x1000);
290
291 u3_agp = hose;
292}
293
294static void __init setup_u3_ht(struct pci_controller* hose)
295{
296 hose->ops = &u3_ht_pci_ops;
297
298 /* We hard code the address because of the different size of
299 * the reg address cell, we shall fix that by killing struct
300 * reg_property and using some accessor functions instead
301 */
302 hose->cfg_data = (volatile unsigned char *)ioremap(0xf2000000, 0x02000000);
303
304 hose->first_busno = 0;
305 hose->last_busno = 0xef;
306
307 u3_ht = hose;
308}
309
310static int __init add_bridge(struct device_node *dev)
311{
312 int len;
313 struct pci_controller *hose;
314 char* disp_name;
315 int *bus_range;
316 int primary = 1;
317 struct property *of_prop;
318
319 DBG("Adding PCI host bridge %s\n", dev->full_name);
320
321 bus_range = (int *) get_property(dev, "bus-range", &len);
322 if (bus_range == NULL || len < 2 * sizeof(int)) {
323 printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n",
324 dev->full_name);
325 }
326
327 hose = alloc_bootmem(sizeof(struct pci_controller));
328 if (hose == NULL)
329 return -ENOMEM;
330 pci_setup_pci_controller(hose);
331
332 hose->arch_data = dev;
333 hose->first_busno = bus_range ? bus_range[0] : 0;
334 hose->last_busno = bus_range ? bus_range[1] : 0xff;
335
336 of_prop = alloc_bootmem(sizeof(struct property) +
337 sizeof(hose->global_number));
338 if (of_prop) {
339 memset(of_prop, 0, sizeof(struct property));
340 of_prop->name = "linux,pci-domain";
341 of_prop->length = sizeof(hose->global_number);
342 of_prop->value = (unsigned char *)&of_prop[1];
343 memcpy(of_prop->value, &hose->global_number, sizeof(hose->global_number));
344 prom_add_property(dev, of_prop);
345 }
346
347 disp_name = NULL;
348 if (device_is_compatible(dev, "u3-agp")) {
349 setup_u3_agp(hose);
350 disp_name = "U3-AGP";
351 primary = 0;
352 } else if (device_is_compatible(dev, "u3-ht")) {
353 setup_u3_ht(hose);
354 disp_name = "U3-HT";
355 primary = 1;
356 }
357 printk(KERN_INFO "Found %s PCI host bridge. Firmware bus number: %d->%d\n",
358 disp_name, hose->first_busno, hose->last_busno);
359
360 /* Interpret the "ranges" property */
361 /* This also maps the I/O region and sets isa_io/mem_base */
362 pci_process_bridge_OF_ranges(hose, dev, primary);
363 pci_setup_phb_io(hose, primary);
364
365 /* Fixup "bus-range" OF property */
366 fixup_bus_range(dev);
367
368 return 0;
369}
370
371
372void __init maple_pcibios_fixup(void)
373{
374 struct pci_dev *dev = NULL;
375
376 DBG(" -> maple_pcibios_fixup\n");
377
378 for_each_pci_dev(dev)
379 pci_read_irq_line(dev);
380
381 /* Do the mapping of the IO space */
382 phbs_remap_io();
383
384 DBG(" <- maple_pcibios_fixup\n");
385}
386
387static void __init maple_fixup_phb_resources(void)
388{
389 struct pci_controller *hose, *tmp;
390
391 list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
392 unsigned long offset = (unsigned long)hose->io_base_virt - pci_io_base;
393 hose->io_resource.start += offset;
394 hose->io_resource.end += offset;
395 printk(KERN_INFO "PCI Host %d, io start: %lx; io end: %lx\n",
396 hose->global_number,
397 hose->io_resource.start, hose->io_resource.end);
398 }
399}
400
401void __init maple_pci_init(void)
402{
403 struct device_node *np, *root;
404 struct device_node *ht = NULL;
405
406 /* Probe root PCI hosts, that is on U3 the AGP host and the
407 * HyperTransport host. That one is actually "kept" around
408 * and actually added last as it's resource management relies
409 * on the AGP resources to have been setup first
410 */
411 root = of_find_node_by_path("/");
412 if (root == NULL) {
413 printk(KERN_CRIT "maple_find_bridges: can't find root of device tree\n");
414 return;
415 }
416 for (np = NULL; (np = of_get_next_child(root, np)) != NULL;) {
417 if (np->name == NULL)
418 continue;
419 if (strcmp(np->name, "pci") == 0) {
420 if (add_bridge(np) == 0)
421 of_node_get(np);
422 }
423 if (strcmp(np->name, "ht") == 0) {
424 of_node_get(np);
425 ht = np;
426 }
427 }
428 of_node_put(root);
429
430 /* Now setup the HyperTransport host if we found any
431 */
432 if (ht && add_bridge(ht) != 0)
433 of_node_put(ht);
434
435 /* Fixup the IO resources on our host bridges as the common code
436 * does it only for childs of the host bridges
437 */
438 maple_fixup_phb_resources();
439
440 /* Setup the linkage between OF nodes and PHBs */
441 pci_devs_phb_init();
442
443 /* Fixup the PCI<->OF mapping for U3 AGP due to bus renumbering. We
444 * assume there is no P2P bridge on the AGP bus, which should be a
445 * safe assumptions hopefully.
446 */
447 if (u3_agp) {
448 struct device_node *np = u3_agp->arch_data;
449 PCI_DN(np)->busno = 0xf0;
450 for (np = np->child; np; np = np->sibling)
451 PCI_DN(np)->busno = 0xf0;
452 }
453
454 /* Tell pci.c to use the common resource allocation mecanism */
455 pci_probe_only = 0;
456
457 /* Allow all IO */
458 io_page_mask = -1;
459}
460
461int maple_pci_get_legacy_ide_irq(struct pci_dev *pdev, int channel)
462{
463 struct device_node *np;
464 int irq = channel ? 15 : 14;
465
466 if (pdev->vendor != PCI_VENDOR_ID_AMD ||
467 pdev->device != PCI_DEVICE_ID_AMD_8111_IDE)
468 return irq;
469
470 np = pci_device_to_OF_node(pdev);
471 if (np == NULL)
472 return irq;
473 if (np->n_intrs < 2)
474 return irq;
475 return np->intrs[channel & 0x1].line;
476}
477
478/* XXX: To remove once all firmwares are ok */
479static void fixup_maple_ide(struct pci_dev* dev)
480{
481#if 0 /* Enable this to enable IDE port 0 */
482 {
483 u8 v;
484
485 pci_read_config_byte(dev, 0x40, &v);
486 v |= 2;
487 pci_write_config_byte(dev, 0x40, v);
488 }
489#endif
490#if 0 /* fix bus master base */
491 pci_write_config_dword(dev, 0x20, 0xcc01);
492 printk("old ide resource: %lx -> %lx \n",
493 dev->resource[4].start, dev->resource[4].end);
494 dev->resource[4].start = 0xcc00;
495 dev->resource[4].end = 0xcc10;
496#endif
497#if 1 /* Enable this to fixup IDE sense/polarity of irqs in IO-APICs */
498 {
499 struct pci_dev *apicdev;
500 u32 v;
501
502 apicdev = pci_get_slot (dev->bus, PCI_DEVFN(5,0));
503 if (apicdev == NULL)
504 printk("IDE Fixup IRQ: Can't find IO-APIC !\n");
505 else {
506 pci_write_config_byte(apicdev, 0xf2, 0x10 + 2*14);
507 pci_read_config_dword(apicdev, 0xf4, &v);
508 v &= ~0x00000022;
509 pci_write_config_dword(apicdev, 0xf4, v);
510 pci_write_config_byte(apicdev, 0xf2, 0x10 + 2*15);
511 pci_read_config_dword(apicdev, 0xf4, &v);
512 v &= ~0x00000022;
513 pci_write_config_dword(apicdev, 0xf4, v);
514 pci_dev_put(apicdev);
515 }
516 }
517#endif
518}
519DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_IDE,
520 fixup_maple_ide);
diff --git a/arch/ppc64/kernel/maple_setup.c b/arch/ppc64/kernel/maple_setup.c
deleted file mode 100644
index a107ed69a355..000000000000
--- a/arch/ppc64/kernel/maple_setup.c
+++ /dev/null
@@ -1,300 +0,0 @@
1/*
2 * arch/ppc64/kernel/maple_setup.c
3 *
4 * (c) Copyright 2004 Benjamin Herrenschmidt (benh@kernel.crashing.org),
5 * IBM Corp.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 *
12 */
13
14#define DEBUG
15
16#include <linux/config.h>
17#include <linux/init.h>
18#include <linux/errno.h>
19#include <linux/sched.h>
20#include <linux/kernel.h>
21#include <linux/mm.h>
22#include <linux/stddef.h>
23#include <linux/unistd.h>
24#include <linux/ptrace.h>
25#include <linux/slab.h>
26#include <linux/user.h>
27#include <linux/a.out.h>
28#include <linux/tty.h>
29#include <linux/string.h>
30#include <linux/delay.h>
31#include <linux/ioport.h>
32#include <linux/major.h>
33#include <linux/initrd.h>
34#include <linux/vt_kern.h>
35#include <linux/console.h>
36#include <linux/ide.h>
37#include <linux/pci.h>
38#include <linux/adb.h>
39#include <linux/cuda.h>
40#include <linux/pmu.h>
41#include <linux/irq.h>
42#include <linux/seq_file.h>
43#include <linux/root_dev.h>
44#include <linux/serial.h>
45#include <linux/smp.h>
46
47#include <asm/processor.h>
48#include <asm/sections.h>
49#include <asm/prom.h>
50#include <asm/system.h>
51#include <asm/pgtable.h>
52#include <asm/bitops.h>
53#include <asm/io.h>
54#include <asm/pci-bridge.h>
55#include <asm/iommu.h>
56#include <asm/machdep.h>
57#include <asm/dma.h>
58#include <asm/cputable.h>
59#include <asm/time.h>
60#include <asm/of_device.h>
61#include <asm/lmb.h>
62#include <asm/mpic.h>
63#include <asm/udbg.h>
64
65#ifdef DEBUG
66#define DBG(fmt...) udbg_printf(fmt)
67#else
68#define DBG(fmt...)
69#endif
70
71extern int maple_set_rtc_time(struct rtc_time *tm);
72extern void maple_get_rtc_time(struct rtc_time *tm);
73extern unsigned long maple_get_boot_time(void);
74extern void maple_calibrate_decr(void);
75extern void maple_pci_init(void);
76extern void maple_pcibios_fixup(void);
77extern int maple_pci_get_legacy_ide_irq(struct pci_dev *dev, int channel);
78extern void generic_find_legacy_serial_ports(u64 *physport,
79 unsigned int *default_speed);
80
81static void maple_restart(char *cmd)
82{
83 unsigned int maple_nvram_base;
84 unsigned int maple_nvram_offset;
85 unsigned int maple_nvram_command;
86 struct device_node *rtcs;
87
88 /* find NVRAM device */
89 rtcs = find_compatible_devices("nvram", "AMD8111");
90 if (rtcs && rtcs->addrs) {
91 maple_nvram_base = rtcs->addrs[0].address;
92 } else {
93 printk(KERN_EMERG "Maple: Unable to find NVRAM\n");
94 printk(KERN_EMERG "Maple: Manual Restart Required\n");
95 return;
96 }
97
98 /* find service processor device */
99 rtcs = find_devices("service-processor");
100 if (!rtcs) {
101 printk(KERN_EMERG "Maple: Unable to find Service Processor\n");
102 printk(KERN_EMERG "Maple: Manual Restart Required\n");
103 return;
104 }
105 maple_nvram_offset = *(unsigned int*) get_property(rtcs,
106 "restart-addr", NULL);
107 maple_nvram_command = *(unsigned int*) get_property(rtcs,
108 "restart-value", NULL);
109
110 /* send command */
111 outb_p(maple_nvram_command, maple_nvram_base + maple_nvram_offset);
112 for (;;) ;
113}
114
115static void maple_power_off(void)
116{
117 unsigned int maple_nvram_base;
118 unsigned int maple_nvram_offset;
119 unsigned int maple_nvram_command;
120 struct device_node *rtcs;
121
122 /* find NVRAM device */
123 rtcs = find_compatible_devices("nvram", "AMD8111");
124 if (rtcs && rtcs->addrs) {
125 maple_nvram_base = rtcs->addrs[0].address;
126 } else {
127 printk(KERN_EMERG "Maple: Unable to find NVRAM\n");
128 printk(KERN_EMERG "Maple: Manual Power-Down Required\n");
129 return;
130 }
131
132 /* find service processor device */
133 rtcs = find_devices("service-processor");
134 if (!rtcs) {
135 printk(KERN_EMERG "Maple: Unable to find Service Processor\n");
136 printk(KERN_EMERG "Maple: Manual Power-Down Required\n");
137 return;
138 }
139 maple_nvram_offset = *(unsigned int*) get_property(rtcs,
140 "power-off-addr", NULL);
141 maple_nvram_command = *(unsigned int*) get_property(rtcs,
142 "power-off-value", NULL);
143
144 /* send command */
145 outb_p(maple_nvram_command, maple_nvram_base + maple_nvram_offset);
146 for (;;) ;
147}
148
149static void maple_halt(void)
150{
151 maple_power_off();
152}
153
154#ifdef CONFIG_SMP
155struct smp_ops_t maple_smp_ops = {
156 .probe = smp_mpic_probe,
157 .message_pass = smp_mpic_message_pass,
158 .kick_cpu = smp_generic_kick_cpu,
159 .setup_cpu = smp_mpic_setup_cpu,
160 .give_timebase = smp_generic_give_timebase,
161 .take_timebase = smp_generic_take_timebase,
162};
163#endif /* CONFIG_SMP */
164
165void __init maple_setup_arch(void)
166{
167 /* init to some ~sane value until calibrate_delay() runs */
168 loops_per_jiffy = 50000000;
169
170 /* Setup SMP callback */
171#ifdef CONFIG_SMP
172 smp_ops = &maple_smp_ops;
173#endif
174 /* Lookup PCI hosts */
175 maple_pci_init();
176
177#ifdef CONFIG_DUMMY_CONSOLE
178 conswitchp = &dummy_con;
179#endif
180
181 printk(KERN_INFO "Using native/NAP idle loop\n");
182}
183
184/*
185 * Early initialization.
186 */
187static void __init maple_init_early(void)
188{
189 unsigned int default_speed;
190 u64 physport;
191
192 DBG(" -> maple_init_early\n");
193
194 /* Initialize hash table, from now on, we can take hash faults
195 * and call ioremap
196 */
197 hpte_init_native();
198
199 /* Find the serial port */
200 generic_find_legacy_serial_ports(&physport, &default_speed);
201
202 DBG("phys port addr: %lx\n", (long)physport);
203
204 if (physport) {
205 void *comport;
206 /* Map the uart for udbg. */
207 comport = (void *)ioremap(physport, 16);
208 udbg_init_uart(comport, default_speed);
209
210 DBG("Hello World !\n");
211 }
212
213 /* Setup interrupt mapping options */
214 ppc64_interrupt_controller = IC_OPEN_PIC;
215
216 iommu_init_early_u3();
217
218 DBG(" <- maple_init_early\n");
219}
220
221
222static __init void maple_init_IRQ(void)
223{
224 struct device_node *root;
225 unsigned int *opprop;
226 unsigned long opic_addr;
227 struct mpic *mpic;
228 unsigned char senses[128];
229 int n;
230
231 DBG(" -> maple_init_IRQ\n");
232
233 /* XXX: Non standard, replace that with a proper openpic/mpic node
234 * in the device-tree. Find the Open PIC if present */
235 root = of_find_node_by_path("/");
236 opprop = (unsigned int *) get_property(root,
237 "platform-open-pic", NULL);
238 if (opprop == 0)
239 panic("OpenPIC not found !\n");
240
241 n = prom_n_addr_cells(root);
242 for (opic_addr = 0; n > 0; --n)
243 opic_addr = (opic_addr << 32) + *opprop++;
244 of_node_put(root);
245
246 /* Obtain sense values from device-tree */
247 prom_get_irq_senses(senses, 0, 128);
248
249 mpic = mpic_alloc(opic_addr,
250 MPIC_PRIMARY | MPIC_BIG_ENDIAN |
251 MPIC_BROKEN_U3 | MPIC_WANTS_RESET,
252 0, 0, 128, 128, senses, 128, "U3-MPIC");
253 BUG_ON(mpic == NULL);
254 mpic_init(mpic);
255
256 DBG(" <- maple_init_IRQ\n");
257}
258
259static void __init maple_progress(char *s, unsigned short hex)
260{
261 printk("*** %04x : %s\n", hex, s ? s : "");
262}
263
264
265/*
266 * Called very early, MMU is off, device-tree isn't unflattened
267 */
268static int __init maple_probe(int platform)
269{
270 if (platform != PLATFORM_MAPLE)
271 return 0;
272 /*
273 * On U3, the DART (iommu) must be allocated now since it
274 * has an impact on htab_initialize (due to the large page it
275 * occupies having to be broken up so the DART itself is not
276 * part of the cacheable linar mapping
277 */
278 alloc_u3_dart_table();
279
280 return 1;
281}
282
283struct machdep_calls __initdata maple_md = {
284 .probe = maple_probe,
285 .setup_arch = maple_setup_arch,
286 .init_early = maple_init_early,
287 .init_IRQ = maple_init_IRQ,
288 .get_irq = mpic_get_irq,
289 .pcibios_fixup = maple_pcibios_fixup,
290 .pci_get_legacy_ide_irq = maple_pci_get_legacy_ide_irq,
291 .restart = maple_restart,
292 .power_off = maple_power_off,
293 .halt = maple_halt,
294 .get_boot_time = maple_get_boot_time,
295 .set_rtc_time = maple_set_rtc_time,
296 .get_rtc_time = maple_get_rtc_time,
297 .calibrate_decr = generic_calibrate_decr,
298 .progress = maple_progress,
299 .idle_loop = native_idle,
300};
diff --git a/arch/ppc64/kernel/maple_time.c b/arch/ppc64/kernel/maple_time.c
deleted file mode 100644
index 445cb7470bf5..000000000000
--- a/arch/ppc64/kernel/maple_time.c
+++ /dev/null
@@ -1,178 +0,0 @@
1/*
2 * arch/ppc64/kernel/maple_time.c
3 *
4 * (c) Copyright 2004 Benjamin Herrenschmidt (benh@kernel.crashing.org),
5 * IBM Corp.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 *
12 */
13
14#undef DEBUG
15
16#include <linux/config.h>
17#include <linux/errno.h>
18#include <linux/sched.h>
19#include <linux/kernel.h>
20#include <linux/param.h>
21#include <linux/string.h>
22#include <linux/mm.h>
23#include <linux/init.h>
24#include <linux/time.h>
25#include <linux/adb.h>
26#include <linux/pmu.h>
27#include <linux/interrupt.h>
28#include <linux/mc146818rtc.h>
29#include <linux/bcd.h>
30
31#include <asm/sections.h>
32#include <asm/prom.h>
33#include <asm/system.h>
34#include <asm/io.h>
35#include <asm/pgtable.h>
36#include <asm/machdep.h>
37#include <asm/time.h>
38
39#ifdef DEBUG
40#define DBG(x...) printk(x)
41#else
42#define DBG(x...)
43#endif
44
45extern void GregorianDay(struct rtc_time * tm);
46
47static int maple_rtc_addr;
48
49static int maple_clock_read(int addr)
50{
51 outb_p(addr, maple_rtc_addr);
52 return inb_p(maple_rtc_addr+1);
53}
54
55static void maple_clock_write(unsigned long val, int addr)
56{
57 outb_p(addr, maple_rtc_addr);
58 outb_p(val, maple_rtc_addr+1);
59}
60
61void maple_get_rtc_time(struct rtc_time *tm)
62{
63 int uip, i;
64
65 /* The Linux interpretation of the CMOS clock register contents:
66 * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
67 * RTC registers show the second which has precisely just started.
68 * Let's hope other operating systems interpret the RTC the same way.
69 */
70
71 /* Since the UIP flag is set for about 2.2 ms and the clock
72 * is typically written with a precision of 1 jiffy, trying
73 * to obtain a precision better than a few milliseconds is
74 * an illusion. Only consistency is interesting, this also
75 * allows to use the routine for /dev/rtc without a potential
76 * 1 second kernel busy loop triggered by any reader of /dev/rtc.
77 */
78
79 for (i = 0; i<1000000; i++) {
80 uip = maple_clock_read(RTC_FREQ_SELECT);
81 tm->tm_sec = maple_clock_read(RTC_SECONDS);
82 tm->tm_min = maple_clock_read(RTC_MINUTES);
83 tm->tm_hour = maple_clock_read(RTC_HOURS);
84 tm->tm_mday = maple_clock_read(RTC_DAY_OF_MONTH);
85 tm->tm_mon = maple_clock_read(RTC_MONTH);
86 tm->tm_year = maple_clock_read(RTC_YEAR);
87 uip |= maple_clock_read(RTC_FREQ_SELECT);
88 if ((uip & RTC_UIP)==0)
89 break;
90 }
91
92 if (!(maple_clock_read(RTC_CONTROL) & RTC_DM_BINARY)
93 || RTC_ALWAYS_BCD) {
94 BCD_TO_BIN(tm->tm_sec);
95 BCD_TO_BIN(tm->tm_min);
96 BCD_TO_BIN(tm->tm_hour);
97 BCD_TO_BIN(tm->tm_mday);
98 BCD_TO_BIN(tm->tm_mon);
99 BCD_TO_BIN(tm->tm_year);
100 }
101 if ((tm->tm_year + 1900) < 1970)
102 tm->tm_year += 100;
103
104 GregorianDay(tm);
105}
106
107int maple_set_rtc_time(struct rtc_time *tm)
108{
109 unsigned char save_control, save_freq_select;
110 int sec, min, hour, mon, mday, year;
111
112 spin_lock(&rtc_lock);
113
114 save_control = maple_clock_read(RTC_CONTROL); /* tell the clock it's being set */
115
116 maple_clock_write((save_control|RTC_SET), RTC_CONTROL);
117
118 save_freq_select = maple_clock_read(RTC_FREQ_SELECT); /* stop and reset prescaler */
119
120 maple_clock_write((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
121
122 sec = tm->tm_sec;
123 min = tm->tm_min;
124 hour = tm->tm_hour;
125 mon = tm->tm_mon;
126 mday = tm->tm_mday;
127 year = tm->tm_year;
128
129 if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
130 BIN_TO_BCD(sec);
131 BIN_TO_BCD(min);
132 BIN_TO_BCD(hour);
133 BIN_TO_BCD(mon);
134 BIN_TO_BCD(mday);
135 BIN_TO_BCD(year);
136 }
137 maple_clock_write(sec, RTC_SECONDS);
138 maple_clock_write(min, RTC_MINUTES);
139 maple_clock_write(hour, RTC_HOURS);
140 maple_clock_write(mon, RTC_MONTH);
141 maple_clock_write(mday, RTC_DAY_OF_MONTH);
142 maple_clock_write(year, RTC_YEAR);
143
144 /* The following flags have to be released exactly in this order,
145 * otherwise the DS12887 (popular MC146818A clone with integrated
146 * battery and quartz) will not reset the oscillator and will not
147 * update precisely 500 ms later. You won't find this mentioned in
148 * the Dallas Semiconductor data sheets, but who believes data
149 * sheets anyway ... -- Markus Kuhn
150 */
151 maple_clock_write(save_control, RTC_CONTROL);
152 maple_clock_write(save_freq_select, RTC_FREQ_SELECT);
153
154 spin_unlock(&rtc_lock);
155
156 return 0;
157}
158
159unsigned long __init maple_get_boot_time(void)
160{
161 struct rtc_time tm;
162 struct device_node *rtcs;
163
164 rtcs = find_compatible_devices("rtc", "pnpPNP,b00");
165 if (rtcs && rtcs->addrs) {
166 maple_rtc_addr = rtcs->addrs[0].address;
167 printk(KERN_INFO "Maple: Found RTC at 0x%x\n", maple_rtc_addr);
168 } else {
169 maple_rtc_addr = RTC_PORT(0); /* legacy address */
170 printk(KERN_INFO "Maple: No device node for RTC, assuming "
171 "legacy address (0x%x)\n", maple_rtc_addr);
172 }
173
174 maple_get_rtc_time(&tm);
175 return mktime(tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
176 tm.tm_hour, tm.tm_min, tm.tm_sec);
177}
178