linux/arch/powerpc/platforms/85xx/mpc85xx_ds.c
<<
>>
Prefs
   1/*
   2 * MPC85xx DS Board Setup
   3 *
   4 * Author Xianghua Xiao (x.xiao@freescale.com)
   5 * Roy Zang <tie-fei.zang@freescale.com>
   6 *      - Add PCI/PCI Exprees support
   7 * Copyright 2007 Freescale Semiconductor Inc.
   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/stddef.h>
  16#include <linux/kernel.h>
  17#include <linux/pci.h>
  18#include <linux/kdev_t.h>
  19#include <linux/delay.h>
  20#include <linux/seq_file.h>
  21#include <linux/interrupt.h>
  22#include <linux/of_platform.h>
  23#include <linux/memblock.h>
  24
  25#include <asm/system.h>
  26#include <asm/time.h>
  27#include <asm/machdep.h>
  28#include <asm/pci-bridge.h>
  29#include <mm/mmu_decl.h>
  30#include <asm/prom.h>
  31#include <asm/udbg.h>
  32#include <asm/mpic.h>
  33#include <asm/i8259.h>
  34#include <asm/swiotlb.h>
  35
  36#include <sysdev/fsl_soc.h>
  37#include <sysdev/fsl_pci.h>
  38#include "smp.h"
  39
  40#include "mpc85xx.h"
  41
  42#undef DEBUG
  43
  44#ifdef DEBUG
  45#define DBG(fmt, args...) printk(KERN_ERR "%s: " fmt, __func__, ## args)
  46#else
  47#define DBG(fmt, args...)
  48#endif
  49
  50#ifdef CONFIG_PPC_I8259
  51static void mpc85xx_8259_cascade(unsigned int irq, struct irq_desc *desc)
  52{
  53        struct irq_chip *chip = irq_desc_get_chip(desc);
  54        unsigned int cascade_irq = i8259_irq();
  55
  56        if (cascade_irq != NO_IRQ) {
  57                generic_handle_irq(cascade_irq);
  58        }
  59        chip->irq_eoi(&desc->irq_data);
  60}
  61#endif  /* CONFIG_PPC_I8259 */
  62
  63void __init mpc85xx_ds_pic_init(void)
  64{
  65        struct mpic *mpic;
  66#ifdef CONFIG_PPC_I8259
  67        struct device_node *np;
  68        struct device_node *cascade_node = NULL;
  69        int cascade_irq;
  70#endif
  71        unsigned long root = of_get_flat_dt_root();
  72
  73        if (of_flat_dt_is_compatible(root, "fsl,MPC8572DS-CAMP")) {
  74                mpic = mpic_alloc(NULL, 0,
  75                        MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS |
  76                        MPIC_SINGLE_DEST_CPU,
  77                        0, 256, " OpenPIC  ");
  78        } else {
  79                mpic = mpic_alloc(NULL, 0,
  80                          MPIC_WANTS_RESET |
  81                          MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS |
  82                          MPIC_SINGLE_DEST_CPU,
  83                        0, 256, " OpenPIC  ");
  84        }
  85
  86        BUG_ON(mpic == NULL);
  87        mpic_init(mpic);
  88
  89#ifdef CONFIG_PPC_I8259
  90        /* Initialize the i8259 controller */
  91        for_each_node_by_type(np, "interrupt-controller")
  92            if (of_device_is_compatible(np, "chrp,iic")) {
  93                cascade_node = np;
  94                break;
  95        }
  96
  97        if (cascade_node == NULL) {
  98                printk(KERN_DEBUG "Could not find i8259 PIC\n");
  99                return;
 100        }
 101
 102        cascade_irq = irq_of_parse_and_map(cascade_node, 0);
 103        if (cascade_irq == NO_IRQ) {
 104                printk(KERN_ERR "Failed to map cascade interrupt\n");
 105                return;
 106        }
 107
 108        DBG("mpc85xxds: cascade mapped to irq %d\n", cascade_irq);
 109
 110        i8259_init(cascade_node, 0);
 111        of_node_put(cascade_node);
 112
 113        irq_set_chained_handler(cascade_irq, mpc85xx_8259_cascade);
 114#endif  /* CONFIG_PPC_I8259 */
 115}
 116
 117#ifdef CONFIG_PCI
 118static int primary_phb_addr;
 119extern int uli_exclude_device(struct pci_controller *hose,
 120                                u_char bus, u_char devfn);
 121
 122static int mpc85xx_exclude_device(struct pci_controller *hose,
 123                                   u_char bus, u_char devfn)
 124{
 125        struct device_node* node;
 126        struct resource rsrc;
 127
 128        node = hose->dn;
 129        of_address_to_resource(node, 0, &rsrc);
 130
 131        if ((rsrc.start & 0xfffff) == primary_phb_addr) {
 132                return uli_exclude_device(hose, bus, devfn);
 133        }
 134
 135        return PCIBIOS_SUCCESSFUL;
 136}
 137#endif  /* CONFIG_PCI */
 138
 139/*
 140 * Setup the architecture
 141 */
 142static void __init mpc85xx_ds_setup_arch(void)
 143{
 144#ifdef CONFIG_PCI
 145        struct device_node *np;
 146        struct pci_controller *hose;
 147#endif
 148        dma_addr_t max = 0xffffffff;
 149
 150        if (ppc_md.progress)
 151                ppc_md.progress("mpc85xx_ds_setup_arch()", 0);
 152
 153#ifdef CONFIG_PCI
 154        for_each_node_by_type(np, "pci") {
 155                if (of_device_is_compatible(np, "fsl,mpc8540-pci") ||
 156                    of_device_is_compatible(np, "fsl,mpc8548-pcie") ||
 157                    of_device_is_compatible(np, "fsl,p2020-pcie")) {
 158                        struct resource rsrc;
 159                        of_address_to_resource(np, 0, &rsrc);
 160                        if ((rsrc.start & 0xfffff) == primary_phb_addr)
 161                                fsl_add_bridge(np, 1);
 162                        else
 163                                fsl_add_bridge(np, 0);
 164
 165                        hose = pci_find_hose_for_OF_device(np);
 166                        max = min(max, hose->dma_window_base_cur +
 167                                        hose->dma_window_size);
 168                }
 169        }
 170
 171        ppc_md.pci_exclude_device = mpc85xx_exclude_device;
 172#endif
 173
 174        mpc85xx_smp_init();
 175
 176#ifdef CONFIG_SWIOTLB
 177        if (memblock_end_of_DRAM() > max) {
 178                ppc_swiotlb_enable = 1;
 179                set_pci_dma_ops(&swiotlb_dma_ops);
 180                ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
 181        }
 182#endif
 183
 184        printk("MPC85xx DS board from Freescale Semiconductor\n");
 185}
 186
 187/*
 188 * Called very early, device-tree isn't unflattened
 189 */
 190static int __init mpc8544_ds_probe(void)
 191{
 192        unsigned long root = of_get_flat_dt_root();
 193
 194        if (of_flat_dt_is_compatible(root, "MPC8544DS")) {
 195#ifdef CONFIG_PCI
 196                primary_phb_addr = 0xb000;
 197#endif
 198                return 1;
 199        }
 200
 201        return 0;
 202}
 203
 204machine_device_initcall(mpc8544_ds, mpc85xx_common_publish_devices);
 205machine_device_initcall(mpc8572_ds, mpc85xx_common_publish_devices);
 206machine_device_initcall(p2020_ds, mpc85xx_common_publish_devices);
 207
 208machine_arch_initcall(mpc8544_ds, swiotlb_setup_bus_notifier);
 209machine_arch_initcall(mpc8572_ds, swiotlb_setup_bus_notifier);
 210machine_arch_initcall(p2020_ds, swiotlb_setup_bus_notifier);
 211
 212/*
 213 * Called very early, device-tree isn't unflattened
 214 */
 215static int __init mpc8572_ds_probe(void)
 216{
 217        unsigned long root = of_get_flat_dt_root();
 218
 219        if (of_flat_dt_is_compatible(root, "fsl,MPC8572DS")) {
 220#ifdef CONFIG_PCI
 221                primary_phb_addr = 0x8000;
 222#endif
 223                return 1;
 224        }
 225
 226        return 0;
 227}
 228
 229/*
 230 * Called very early, device-tree isn't unflattened
 231 */
 232static int __init p2020_ds_probe(void)
 233{
 234        unsigned long root = of_get_flat_dt_root();
 235
 236        if (of_flat_dt_is_compatible(root, "fsl,P2020DS")) {
 237#ifdef CONFIG_PCI
 238                primary_phb_addr = 0x9000;
 239#endif
 240                return 1;
 241        }
 242
 243        return 0;
 244}
 245
 246define_machine(mpc8544_ds) {
 247        .name                   = "MPC8544 DS",
 248        .probe                  = mpc8544_ds_probe,
 249        .setup_arch             = mpc85xx_ds_setup_arch,
 250        .init_IRQ               = mpc85xx_ds_pic_init,
 251#ifdef CONFIG_PCI
 252        .pcibios_fixup_bus      = fsl_pcibios_fixup_bus,
 253#endif
 254        .get_irq                = mpic_get_irq,
 255        .restart                = fsl_rstcr_restart,
 256        .calibrate_decr         = generic_calibrate_decr,
 257        .progress               = udbg_progress,
 258};
 259
 260define_machine(mpc8572_ds) {
 261        .name                   = "MPC8572 DS",
 262        .probe                  = mpc8572_ds_probe,
 263        .setup_arch             = mpc85xx_ds_setup_arch,
 264        .init_IRQ               = mpc85xx_ds_pic_init,
 265#ifdef CONFIG_PCI
 266        .pcibios_fixup_bus      = fsl_pcibios_fixup_bus,
 267#endif
 268        .get_irq                = mpic_get_irq,
 269        .restart                = fsl_rstcr_restart,
 270        .calibrate_decr         = generic_calibrate_decr,
 271        .progress               = udbg_progress,
 272};
 273
 274define_machine(p2020_ds) {
 275        .name                   = "P2020 DS",
 276        .probe                  = p2020_ds_probe,
 277        .setup_arch             = mpc85xx_ds_setup_arch,
 278        .init_IRQ               = mpc85xx_ds_pic_init,
 279#ifdef CONFIG_PCI
 280        .pcibios_fixup_bus      = fsl_pcibios_fixup_bus,
 281#endif
 282        .get_irq                = mpic_get_irq,
 283        .restart                = fsl_rstcr_restart,
 284        .calibrate_decr         = generic_calibrate_decr,
 285        .progress               = udbg_progress,
 286};
 287