diff options
author | Grant Likely <grant.likely@secretlab.ca> | 2006-11-27 16:16:27 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2006-12-04 04:41:42 -0500 |
commit | 6065170cf75c64267f6edec5fd359ce8444bd13d (patch) | |
tree | a55c64e512282f545b35876906e8ffb2a597078c /arch/powerpc | |
parent | e65fdfd6ca447353ad1b4c0a0d20df55f3f6f233 (diff) |
[POWERPC] Add common routines for 52xx support in arch/powerpc
Adds utility routines used by 52xx device drivers and board support
code. Main functionality is to add device nodes to the of_platform_bus,
retrieve the IPB bus frequency, and find+ioremap device registers.
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/platforms/52xx/Makefile | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/52xx/mpc52xx_common.c | 124 | ||||
-rw-r--r-- | arch/powerpc/platforms/52xx/mpc52xx_pic.c | 110 |
3 files changed, 147 insertions, 89 deletions
diff --git a/arch/powerpc/platforms/52xx/Makefile b/arch/powerpc/platforms/52xx/Makefile index 1c9c122123d8..b8f27a864069 100644 --- a/arch/powerpc/platforms/52xx/Makefile +++ b/arch/powerpc/platforms/52xx/Makefile | |||
@@ -2,7 +2,7 @@ | |||
2 | # Makefile for 52xx based boards | 2 | # Makefile for 52xx based boards |
3 | # | 3 | # |
4 | ifeq ($(CONFIG_PPC_MERGE),y) | 4 | ifeq ($(CONFIG_PPC_MERGE),y) |
5 | obj-y += mpc52xx_pic.o | 5 | obj-y += mpc52xx_pic.o mpc52xx_common.o |
6 | endif | 6 | endif |
7 | 7 | ||
8 | obj-$(CONFIG_PPC_EFIKA) += efika-setup.o efika-pci.o | 8 | obj-$(CONFIG_PPC_EFIKA) += efika-setup.o efika-pci.o |
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_common.c b/arch/powerpc/platforms/52xx/mpc52xx_common.c new file mode 100644 index 000000000000..05b214441275 --- /dev/null +++ b/arch/powerpc/platforms/52xx/mpc52xx_common.c | |||
@@ -0,0 +1,124 @@ | |||
1 | /* | ||
2 | * | ||
3 | * Utility functions for the Freescale MPC52xx. | ||
4 | * | ||
5 | * Copyright (C) 2006 Sylvain Munaut <tnt@246tNt.com> | ||
6 | * | ||
7 | * This file is licensed under the terms of the GNU General Public License | ||
8 | * version 2. This program is licensed "as is" without any warranty of any | ||
9 | * kind, whether express or implied. | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #undef DEBUG | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | |||
17 | #include <asm/io.h> | ||
18 | #include <asm/prom.h> | ||
19 | #include <asm/of_platform.h> | ||
20 | #include <asm/mpc52xx.h> | ||
21 | |||
22 | |||
23 | void __iomem * | ||
24 | mpc52xx_find_and_map(const char *compatible) | ||
25 | { | ||
26 | struct device_node *ofn; | ||
27 | const u32 *regaddr_p; | ||
28 | u64 regaddr64, size64; | ||
29 | |||
30 | ofn = of_find_compatible_node(NULL, NULL, compatible); | ||
31 | if (!ofn) | ||
32 | return NULL; | ||
33 | |||
34 | regaddr_p = of_get_address(ofn, 0, &size64, NULL); | ||
35 | if (!regaddr_p) { | ||
36 | of_node_put(ofn); | ||
37 | return NULL; | ||
38 | } | ||
39 | |||
40 | regaddr64 = of_translate_address(ofn, regaddr_p); | ||
41 | |||
42 | of_node_put(ofn); | ||
43 | |||
44 | return ioremap((u32)regaddr64, (u32)size64); | ||
45 | } | ||
46 | |||
47 | |||
48 | /** | ||
49 | * mpc52xx_find_ipb_freq - Find the IPB bus frequency for a device | ||
50 | * @node: device node | ||
51 | * | ||
52 | * Returns IPB bus frequency, or 0 if the bus frequency cannot be found. | ||
53 | */ | ||
54 | unsigned int | ||
55 | mpc52xx_find_ipb_freq(struct device_node *node) | ||
56 | { | ||
57 | struct device_node *np; | ||
58 | const unsigned int *p_ipb_freq = NULL; | ||
59 | |||
60 | of_node_get(node); | ||
61 | while (node) { | ||
62 | p_ipb_freq = get_property(node, "bus-frequency", NULL); | ||
63 | if (p_ipb_freq) | ||
64 | break; | ||
65 | |||
66 | np = of_get_parent(node); | ||
67 | of_node_put(node); | ||
68 | node = np; | ||
69 | } | ||
70 | if (node) | ||
71 | of_node_put(node); | ||
72 | |||
73 | return p_ipb_freq ? *p_ipb_freq : 0; | ||
74 | } | ||
75 | |||
76 | |||
77 | void __init | ||
78 | mpc52xx_setup_cpu(void) | ||
79 | { | ||
80 | struct mpc52xx_cdm __iomem *cdm; | ||
81 | struct mpc52xx_xlb __iomem *xlb; | ||
82 | |||
83 | /* Map zones */ | ||
84 | cdm = mpc52xx_find_and_map("mpc52xx-cdm"); | ||
85 | xlb = mpc52xx_find_and_map("mpc52xx-xlb"); | ||
86 | |||
87 | if (!cdm || !xlb) { | ||
88 | printk(KERN_ERR __FILE__ ": " | ||
89 | "Error while mapping CDM/XLB during mpc52xx_setup_cpu. " | ||
90 | "Expect some abnormal behavior\n"); | ||
91 | goto unmap_regs; | ||
92 | } | ||
93 | |||
94 | /* Use internal 48 Mhz */ | ||
95 | out_8(&cdm->ext_48mhz_en, 0x00); | ||
96 | out_8(&cdm->fd_enable, 0x01); | ||
97 | if (in_be32(&cdm->rstcfg) & 0x40) /* Assumes 33Mhz clock */ | ||
98 | out_be16(&cdm->fd_counters, 0x0001); | ||
99 | else | ||
100 | out_be16(&cdm->fd_counters, 0x5555); | ||
101 | |||
102 | /* Configure the XLB Arbiter priorities */ | ||
103 | out_be32(&xlb->master_pri_enable, 0xff); | ||
104 | out_be32(&xlb->master_priority, 0x11111111); | ||
105 | |||
106 | /* Disable XLB pipelining */ | ||
107 | /* (cfr errate 292. We could do this only just before ATA PIO | ||
108 | transaction and re-enable it afterwards ...) */ | ||
109 | out_be32(&xlb->config, in_be32(&xlb->config) | MPC52xx_XLB_CFG_PLDIS); | ||
110 | |||
111 | /* Unmap zones */ | ||
112 | unmap_regs: | ||
113 | if (cdm) iounmap(cdm); | ||
114 | if (xlb) iounmap(xlb); | ||
115 | } | ||
116 | |||
117 | static int __init | ||
118 | mpc52xx_declare_of_platform_devices(void) | ||
119 | { | ||
120 | /* Find every child of the SOC node and add it to of_platform */ | ||
121 | return of_platform_bus_probe(NULL, NULL, NULL); | ||
122 | } | ||
123 | |||
124 | device_initcall(mpc52xx_declare_of_platform_devices); | ||
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pic.c b/arch/powerpc/platforms/52xx/mpc52xx_pic.c index 504154fdf6a6..cd91a6c3aafa 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_pic.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_pic.c | |||
@@ -54,12 +54,12 @@ static unsigned char mpc52xx_map_senses[4] = { | |||
54 | * | 54 | * |
55 | */ | 55 | */ |
56 | 56 | ||
57 | static inline void io_be_setbit(u32 __iomem * addr, int bitno) | 57 | static inline void io_be_setbit(u32 __iomem *addr, int bitno) |
58 | { | 58 | { |
59 | out_be32(addr, in_be32(addr) | (1 << bitno)); | 59 | out_be32(addr, in_be32(addr) | (1 << bitno)); |
60 | } | 60 | } |
61 | 61 | ||
62 | static inline void io_be_clrbit(u32 __iomem * addr, int bitno) | 62 | static inline void io_be_clrbit(u32 __iomem *addr, int bitno) |
63 | { | 63 | { |
64 | out_be32(addr, in_be32(addr) & ~(1 << bitno)); | 64 | out_be32(addr, in_be32(addr) & ~(1 << bitno)); |
65 | } | 65 | } |
@@ -104,7 +104,7 @@ static void mpc52xx_extirq_ack(unsigned int virq) | |||
104 | 104 | ||
105 | pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq); | 105 | pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq); |
106 | 106 | ||
107 | io_be_setbit(&intr->ctrl, 27 - l2irq); | 107 | io_be_setbit(&intr->ctrl, 27-l2irq); |
108 | } | 108 | } |
109 | 109 | ||
110 | static struct irq_chip mpc52xx_extirq_irqchip = { | 110 | static struct irq_chip mpc52xx_extirq_irqchip = { |
@@ -379,81 +379,21 @@ static struct irq_host_ops mpc52xx_irqhost_ops = { | |||
379 | 379 | ||
380 | void __init mpc52xx_init_irq(void) | 380 | void __init mpc52xx_init_irq(void) |
381 | { | 381 | { |
382 | struct device_node *picnode = NULL; | ||
383 | int picnode_regsize; | ||
384 | u32 picnode_regoffset; | ||
385 | |||
386 | struct device_node *sdmanode = NULL; | ||
387 | int sdmanode_regsize; | ||
388 | u32 sdmanode_regoffset; | ||
389 | |||
390 | u64 size64; | ||
391 | int flags; | ||
392 | |||
393 | u32 intr_ctrl; | 382 | u32 intr_ctrl; |
394 | 383 | struct device_node *picnode; | |
395 | picnode = of_find_compatible_node(NULL, "interrupt-controller", | ||
396 | "mpc5200-pic"); | ||
397 | if (picnode == NULL) { | ||
398 | printk(KERN_ERR "MPC52xx PIC: " | ||
399 | "Unable to find the interrupt controller " | ||
400 | "in the OpenFirmware device tree\n"); | ||
401 | goto end; | ||
402 | } | ||
403 | |||
404 | sdmanode = of_find_compatible_node(NULL, "dma-controller", | ||
405 | "mpc5200-bestcomm"); | ||
406 | if (sdmanode == NULL) { | ||
407 | printk(KERN_ERR "MPC52xx PIC" | ||
408 | "Unable to find the Bestcomm DMA controller device " | ||
409 | "in the OpenFirmware device tree\n"); | ||
410 | goto end; | ||
411 | } | ||
412 | |||
413 | /* Retrieve PIC ressources */ | ||
414 | picnode_regoffset = (u32) of_get_address(picnode, 0, &size64, &flags); | ||
415 | if (picnode_regoffset == 0) { | ||
416 | printk(KERN_ERR "MPC52xx PIC" | ||
417 | "Unable to get the interrupt controller address\n"); | ||
418 | goto end; | ||
419 | } | ||
420 | |||
421 | picnode_regoffset = | ||
422 | of_translate_address(picnode, (u32 *) picnode_regoffset); | ||
423 | picnode_regsize = (int)size64; | ||
424 | |||
425 | /* Retrieve SDMA ressources */ | ||
426 | sdmanode_regoffset = (u32) of_get_address(sdmanode, 0, &size64, &flags); | ||
427 | if (sdmanode_regoffset == 0) { | ||
428 | printk(KERN_ERR "MPC52xx PIC: " | ||
429 | "Unable to get the Bestcomm DMA controller address\n"); | ||
430 | goto end; | ||
431 | } | ||
432 | |||
433 | sdmanode_regoffset = | ||
434 | of_translate_address(sdmanode, (u32 *) sdmanode_regoffset); | ||
435 | sdmanode_regsize = (int)size64; | ||
436 | 384 | ||
437 | /* Remap the necessary zones */ | 385 | /* Remap the necessary zones */ |
438 | intr = ioremap(picnode_regoffset, picnode_regsize); | 386 | picnode = of_find_compatible_node(NULL, NULL, "mpc52xx-pic"); |
439 | if (intr == NULL) { | ||
440 | printk(KERN_ERR "MPC52xx PIC: " | ||
441 | "Unable to ioremap interrupt controller registers!\n"); | ||
442 | goto end; | ||
443 | } | ||
444 | 387 | ||
445 | sdma = ioremap(sdmanode_regoffset, sdmanode_regsize); | 388 | intr = mpc52xx_find_and_map("mpc52xx-pic"); |
446 | if (sdma == NULL) { | 389 | if (!intr) |
447 | iounmap(intr); | 390 | panic(__FILE__ ": find_and_map failed on 'mpc52xx-pic'. " |
448 | printk(KERN_ERR "MPC52xx PIC: " | 391 | "Check node !"); |
449 | "Unable to ioremap Bestcomm DMA registers!\n"); | ||
450 | goto end; | ||
451 | } | ||
452 | 392 | ||
453 | printk(KERN_INFO "MPC52xx PIC: MPC52xx PIC Remapped at 0x%8.8x\n", | 393 | sdma = mpc52xx_find_and_map("mpc52xx-bestcomm"); |
454 | picnode_regoffset); | 394 | if (!sdma) |
455 | printk(KERN_INFO "MPC52xx PIC: MPC52xx SDMA Remapped at 0x%8.8x\n", | 395 | panic(__FILE__ ": find_and_map failed on 'mpc52xx-bestcomm'. " |
456 | sdmanode_regoffset); | 396 | "Check node !"); |
457 | 397 | ||
458 | /* Disable all interrupt sources. */ | 398 | /* Disable all interrupt sources. */ |
459 | out_be32(&sdma->IntPend, 0xffffffff); /* 1 means clear pending */ | 399 | out_be32(&sdma->IntPend, 0xffffffff); /* 1 means clear pending */ |
@@ -480,21 +420,15 @@ void __init mpc52xx_init_irq(void) | |||
480 | * hw irq information provided by the ofw to linux virq | 420 | * hw irq information provided by the ofw to linux virq |
481 | */ | 421 | */ |
482 | 422 | ||
483 | mpc52xx_irqhost = | 423 | mpc52xx_irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR, |
484 | irq_alloc_host(IRQ_HOST_MAP_LINEAR, MPC52xx_IRQ_HIGHTESTHWIRQ, | 424 | MPC52xx_IRQ_HIGHTESTHWIRQ, |
485 | &mpc52xx_irqhost_ops, -1); | 425 | &mpc52xx_irqhost_ops, -1); |
486 | 426 | ||
487 | if (mpc52xx_irqhost) { | 427 | if (!mpc52xx_irqhost) |
488 | mpc52xx_irqhost->host_data = picnode; | 428 | panic(__FILE__ ": Cannot allocate the IRQ host\n"); |
489 | printk(KERN_INFO "MPC52xx PIC is up and running!\n"); | ||
490 | } else { | ||
491 | printk(KERN_ERR | ||
492 | "MPC52xx PIC: Unable to allocate the IRQ host\n"); | ||
493 | } | ||
494 | 429 | ||
495 | end: | 430 | mpc52xx_irqhost->host_data = picnode; |
496 | of_node_put(picnode); | 431 | printk(KERN_INFO "MPC52xx PIC is up and running!\n"); |
497 | of_node_put(sdmanode); | ||
498 | } | 432 | } |
499 | 433 | ||
500 | /* | 434 | /* |
@@ -526,9 +460,10 @@ unsigned int mpc52xx_get_irq(void) | |||
526 | irq = ffs(status) - 1; | 460 | irq = ffs(status) - 1; |
527 | irq |= (MPC52xx_IRQ_L1_SDMA << MPC52xx_IRQ_L1_OFFSET) & | 461 | irq |= (MPC52xx_IRQ_L1_SDMA << MPC52xx_IRQ_L1_OFFSET) & |
528 | MPC52xx_IRQ_L1_MASK; | 462 | MPC52xx_IRQ_L1_MASK; |
529 | } else | 463 | } else { |
530 | irq |= (MPC52xx_IRQ_L1_PERP << MPC52xx_IRQ_L1_OFFSET) & | 464 | irq |= (MPC52xx_IRQ_L1_PERP << MPC52xx_IRQ_L1_OFFSET) & |
531 | MPC52xx_IRQ_L1_MASK; | 465 | MPC52xx_IRQ_L1_MASK; |
466 | } | ||
532 | } | 467 | } |
533 | 468 | ||
534 | pr_debug("%s: irq=%x. virq=%d\n", __func__, irq, | 469 | pr_debug("%s: irq=%x. virq=%d\n", __func__, irq, |
@@ -536,4 +471,3 @@ unsigned int mpc52xx_get_irq(void) | |||
536 | 471 | ||
537 | return irq_linear_revmap(mpc52xx_irqhost, irq); | 472 | return irq_linear_revmap(mpc52xx_irqhost, irq); |
538 | } | 473 | } |
539 | |||