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 | |
| 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>
| -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 | ||||
| -rw-r--r-- | include/asm-powerpc/mpc52xx.h | 4 |
4 files changed, 151 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 | |||
diff --git a/include/asm-powerpc/mpc52xx.h b/include/asm-powerpc/mpc52xx.h index fff752c4bd17..4a28a850998c 100644 --- a/include/asm-powerpc/mpc52xx.h +++ b/include/asm-powerpc/mpc52xx.h | |||
| @@ -241,6 +241,10 @@ struct mpc52xx_cdm { | |||
| 241 | 241 | ||
| 242 | #ifndef __ASSEMBLY__ | 242 | #ifndef __ASSEMBLY__ |
| 243 | 243 | ||
| 244 | extern void __iomem * mpc52xx_find_and_map(const char *); | ||
| 245 | extern unsigned int mpc52xx_find_ipb_freq(struct device_node *node); | ||
| 246 | extern void mpc52xx_setup_cpu(void); | ||
| 247 | |||
| 244 | extern void mpc52xx_init_irq(void); | 248 | extern void mpc52xx_init_irq(void); |
| 245 | extern unsigned int mpc52xx_get_irq(void); | 249 | extern unsigned int mpc52xx_get_irq(void); |
| 246 | 250 | ||
