linux/arch/powerpc/platforms/embedded6xx/mvme5100.c
<<
>>
Prefs
   1/*
   2 * Board setup routines for the Motorola/Emerson MVME5100.
   3 *
   4 * Copyright 2013 CSC Australia Pty. Ltd.
   5 *
   6 * Based on earlier code by:
   7 *
   8 *    Matt Porter, MontaVista Software Inc.
   9 *    Copyright 2001 MontaVista Software Inc.
  10 *
  11 * This program is free software; you can redistribute  it and/or modify it
  12 * under  the terms of  the GNU General  Public License as published by the
  13 * Free Software Foundation;  either version 2 of the  License, or (at your
  14 * option) any later version.
  15 *
  16 * Author: Stephen Chivers <schivers@csc.com>
  17 *
  18 */
  19
  20#include <linux/of_platform.h>
  21
  22#include <asm/i8259.h>
  23#include <asm/pci-bridge.h>
  24#include <asm/mpic.h>
  25#include <asm/prom.h>
  26#include <mm/mmu_decl.h>
  27#include <asm/udbg.h>
  28
  29#define HAWK_MPIC_SIZE          0x00040000U
  30#define MVME5100_PCI_MEM_OFFSET 0x00000000
  31
  32/* Board register addresses. */
  33#define BOARD_STATUS_REG        0xfef88080
  34#define BOARD_MODFAIL_REG       0xfef88090
  35#define BOARD_MODRST_REG        0xfef880a0
  36#define BOARD_TBEN_REG          0xfef880c0
  37#define BOARD_SW_READ_REG       0xfef880e0
  38#define BOARD_GEO_ADDR_REG      0xfef880e8
  39#define BOARD_EXT_FEATURE1_REG  0xfef880f0
  40#define BOARD_EXT_FEATURE2_REG  0xfef88100
  41
  42static phys_addr_t pci_membase;
  43static u_char *restart;
  44
  45static void mvme5100_8259_cascade(struct irq_desc *desc)
  46{
  47        struct irq_chip *chip = irq_desc_get_chip(desc);
  48        unsigned int cascade_irq = i8259_irq();
  49
  50        if (cascade_irq)
  51                generic_handle_irq(cascade_irq);
  52
  53        chip->irq_eoi(&desc->irq_data);
  54}
  55
  56static void __init mvme5100_pic_init(void)
  57{
  58        struct mpic *mpic;
  59        struct device_node *np;
  60        struct device_node *cp = NULL;
  61        unsigned int cirq;
  62        unsigned long intack = 0;
  63        const u32 *prop = NULL;
  64
  65        np = of_find_node_by_type(NULL, "open-pic");
  66        if (!np) {
  67                pr_err("Could not find open-pic node\n");
  68                return;
  69        }
  70
  71        mpic = mpic_alloc(np, pci_membase, 0, 16, 256, " OpenPIC  ");
  72
  73        BUG_ON(mpic == NULL);
  74        of_node_put(np);
  75
  76        mpic_assign_isu(mpic, 0, pci_membase + 0x10000);
  77
  78        mpic_init(mpic);
  79
  80        cp = of_find_compatible_node(NULL, NULL, "chrp,iic");
  81        if (cp == NULL) {
  82                pr_warn("mvme5100_pic_init: couldn't find i8259\n");
  83                return;
  84        }
  85
  86        cirq = irq_of_parse_and_map(cp, 0);
  87        if (!cirq) {
  88                pr_warn("mvme5100_pic_init: no cascade interrupt?\n");
  89                return;
  90        }
  91
  92        np = of_find_compatible_node(NULL, "pci", "mpc10x-pci");
  93        if (np) {
  94                prop = of_get_property(np, "8259-interrupt-acknowledge", NULL);
  95
  96                if (prop)
  97                        intack = prop[0];
  98
  99                of_node_put(np);
 100        }
 101
 102        if (intack)
 103                pr_debug("mvme5100_pic_init: PCI 8259 intack at 0x%016lx\n",
 104                   intack);
 105
 106        i8259_init(cp, intack);
 107        of_node_put(cp);
 108        irq_set_chained_handler(cirq, mvme5100_8259_cascade);
 109}
 110
 111static int __init mvme5100_add_bridge(struct device_node *dev)
 112{
 113        const int               *bus_range;
 114        int                     len;
 115        struct pci_controller   *hose;
 116        unsigned short          devid;
 117
 118        pr_info("Adding PCI host bridge %pOF\n", dev);
 119
 120        bus_range = of_get_property(dev, "bus-range", &len);
 121
 122        hose = pcibios_alloc_controller(dev);
 123        if (hose == NULL)
 124                return -ENOMEM;
 125
 126        hose->first_busno = bus_range ? bus_range[0] : 0;
 127        hose->last_busno = bus_range ? bus_range[1] : 0xff;
 128
 129        setup_indirect_pci(hose, 0xfe000cf8, 0xfe000cfc, 0);
 130
 131        pci_process_bridge_OF_ranges(hose, dev, 1);
 132
 133        early_read_config_word(hose, 0, 0, PCI_DEVICE_ID, &devid);
 134
 135        if (devid != PCI_DEVICE_ID_MOTOROLA_HAWK) {
 136                pr_err("HAWK PHB not present?\n");
 137                return 0;
 138        }
 139
 140        early_read_config_dword(hose, 0, 0, PCI_BASE_ADDRESS_1, &pci_membase);
 141
 142        if (pci_membase == 0) {
 143                pr_err("HAWK PHB mibar not correctly set?\n");
 144                return 0;
 145        }
 146
 147        pr_info("mvme5100_pic_init: pci_membase: %x\n", pci_membase);
 148
 149        return 0;
 150}
 151
 152static const struct of_device_id mvme5100_of_bus_ids[] __initconst = {
 153        { .compatible = "hawk-bridge", },
 154        {},
 155};
 156
 157/*
 158 * Setup the architecture
 159 */
 160static void __init mvme5100_setup_arch(void)
 161{
 162        struct device_node *np;
 163
 164        if (ppc_md.progress)
 165                ppc_md.progress("mvme5100_setup_arch()", 0);
 166
 167        for_each_compatible_node(np, "pci", "hawk-pci")
 168                mvme5100_add_bridge(np);
 169
 170        restart = ioremap(BOARD_MODRST_REG, 4);
 171}
 172
 173
 174static void mvme5100_show_cpuinfo(struct seq_file *m)
 175{
 176        seq_puts(m, "Vendor\t\t: Motorola/Emerson\n");
 177        seq_puts(m, "Machine\t\t: MVME5100\n");
 178}
 179
 180static void __noreturn mvme5100_restart(char *cmd)
 181{
 182
 183        local_irq_disable();
 184        mtmsr(mfmsr() | MSR_IP);
 185
 186        out_8((u_char *) restart, 0x01);
 187
 188        while (1)
 189                ;
 190}
 191
 192/*
 193 * Called very early, device-tree isn't unflattened
 194 */
 195static int __init mvme5100_probe(void)
 196{
 197        return of_machine_is_compatible("MVME5100");
 198}
 199
 200static int __init probe_of_platform_devices(void)
 201{
 202
 203        of_platform_bus_probe(NULL, mvme5100_of_bus_ids, NULL);
 204        return 0;
 205}
 206
 207machine_device_initcall(mvme5100, probe_of_platform_devices);
 208
 209define_machine(mvme5100) {
 210        .name                   = "MVME5100",
 211        .probe                  = mvme5100_probe,
 212        .setup_arch             = mvme5100_setup_arch,
 213        .init_IRQ               = mvme5100_pic_init,
 214        .show_cpuinfo           = mvme5100_show_cpuinfo,
 215        .get_irq                = mpic_get_irq,
 216        .restart                = mvme5100_restart,
 217        .calibrate_decr         = generic_calibrate_decr,
 218        .progress               = udbg_progress,
 219};
 220