|
@@ -0,0 +1,221 @@
|
|
|
+/*
|
|
|
+ * Board setup routines for the Motorola/Emerson MVME5100.
|
|
|
+ *
|
|
|
+ * Copyright 2013 CSC Australia Pty. Ltd.
|
|
|
+ *
|
|
|
+ * Based on earlier code by:
|
|
|
+ *
|
|
|
+ * Matt Porter, MontaVista Software Inc.
|
|
|
+ * Copyright 2001 MontaVista Software Inc.
|
|
|
+ *
|
|
|
+ * This program is free software; you can redistribute it and/or modify it
|
|
|
+ * under the terms of the GNU General Public License as published by the
|
|
|
+ * Free Software Foundation; either version 2 of the License, or (at your
|
|
|
+ * option) any later version.
|
|
|
+ *
|
|
|
+ * Author: Stephen Chivers <schivers@csc.com>
|
|
|
+ *
|
|
|
+ */
|
|
|
+
|
|
|
+#include <linux/of_platform.h>
|
|
|
+
|
|
|
+#include <asm/i8259.h>
|
|
|
+#include <asm/pci-bridge.h>
|
|
|
+#include <asm/mpic.h>
|
|
|
+#include <asm/prom.h>
|
|
|
+#include <mm/mmu_decl.h>
|
|
|
+#include <asm/udbg.h>
|
|
|
+
|
|
|
+#define HAWK_MPIC_SIZE 0x00040000U
|
|
|
+#define MVME5100_PCI_MEM_OFFSET 0x00000000
|
|
|
+
|
|
|
+/* Board register addresses. */
|
|
|
+#define BOARD_STATUS_REG 0xfef88080
|
|
|
+#define BOARD_MODFAIL_REG 0xfef88090
|
|
|
+#define BOARD_MODRST_REG 0xfef880a0
|
|
|
+#define BOARD_TBEN_REG 0xfef880c0
|
|
|
+#define BOARD_SW_READ_REG 0xfef880e0
|
|
|
+#define BOARD_GEO_ADDR_REG 0xfef880e8
|
|
|
+#define BOARD_EXT_FEATURE1_REG 0xfef880f0
|
|
|
+#define BOARD_EXT_FEATURE2_REG 0xfef88100
|
|
|
+
|
|
|
+static phys_addr_t pci_membase;
|
|
|
+static u_char *restart;
|
|
|
+
|
|
|
+static void mvme5100_8259_cascade(unsigned int irq, struct irq_desc *desc)
|
|
|
+{
|
|
|
+ struct irq_chip *chip = irq_desc_get_chip(desc);
|
|
|
+ unsigned int cascade_irq = i8259_irq();
|
|
|
+
|
|
|
+ if (cascade_irq != NO_IRQ)
|
|
|
+ generic_handle_irq(cascade_irq);
|
|
|
+
|
|
|
+ chip->irq_eoi(&desc->irq_data);
|
|
|
+}
|
|
|
+
|
|
|
+static void __init mvme5100_pic_init(void)
|
|
|
+{
|
|
|
+ struct mpic *mpic;
|
|
|
+ struct device_node *np;
|
|
|
+ struct device_node *cp = NULL;
|
|
|
+ unsigned int cirq;
|
|
|
+ unsigned long intack = 0;
|
|
|
+ const u32 *prop = NULL;
|
|
|
+
|
|
|
+ np = of_find_node_by_type(NULL, "open-pic");
|
|
|
+ if (!np) {
|
|
|
+ pr_err("Could not find open-pic node\n");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ mpic = mpic_alloc(np, pci_membase, 0, 16, 256, " OpenPIC ");
|
|
|
+
|
|
|
+ BUG_ON(mpic == NULL);
|
|
|
+ of_node_put(np);
|
|
|
+
|
|
|
+ mpic_assign_isu(mpic, 0, pci_membase + 0x10000);
|
|
|
+
|
|
|
+ mpic_init(mpic);
|
|
|
+
|
|
|
+ cp = of_find_compatible_node(NULL, NULL, "chrp,iic");
|
|
|
+ if (cp == NULL) {
|
|
|
+ pr_warn("mvme5100_pic_init: couldn't find i8259\n");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ cirq = irq_of_parse_and_map(cp, 0);
|
|
|
+ if (cirq == NO_IRQ) {
|
|
|
+ pr_warn("mvme5100_pic_init: no cascade interrupt?\n");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ np = of_find_compatible_node(NULL, "pci", "mpc10x-pci");
|
|
|
+ if (np) {
|
|
|
+ prop = of_get_property(np, "8259-interrupt-acknowledge", NULL);
|
|
|
+
|
|
|
+ if (prop)
|
|
|
+ intack = prop[0];
|
|
|
+
|
|
|
+ of_node_put(np);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (intack)
|
|
|
+ pr_debug("mvme5100_pic_init: PCI 8259 intack at 0x%016lx\n",
|
|
|
+ intack);
|
|
|
+
|
|
|
+ i8259_init(cp, intack);
|
|
|
+ of_node_put(cp);
|
|
|
+ irq_set_chained_handler(cirq, mvme5100_8259_cascade);
|
|
|
+}
|
|
|
+
|
|
|
+static int __init mvme5100_add_bridge(struct device_node *dev)
|
|
|
+{
|
|
|
+ const int *bus_range;
|
|
|
+ int len;
|
|
|
+ struct pci_controller *hose;
|
|
|
+ unsigned short devid;
|
|
|
+
|
|
|
+ pr_info("Adding PCI host bridge %s\n", dev->full_name);
|
|
|
+
|
|
|
+ bus_range = of_get_property(dev, "bus-range", &len);
|
|
|
+
|
|
|
+ hose = pcibios_alloc_controller(dev);
|
|
|
+ if (hose == NULL)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ hose->first_busno = bus_range ? bus_range[0] : 0;
|
|
|
+ hose->last_busno = bus_range ? bus_range[1] : 0xff;
|
|
|
+
|
|
|
+ setup_indirect_pci(hose, 0xfe000cf8, 0xfe000cfc, 0);
|
|
|
+
|
|
|
+ pci_process_bridge_OF_ranges(hose, dev, 1);
|
|
|
+
|
|
|
+ early_read_config_word(hose, 0, 0, PCI_DEVICE_ID, &devid);
|
|
|
+
|
|
|
+ if (devid != PCI_DEVICE_ID_MOTOROLA_HAWK) {
|
|
|
+ pr_err("HAWK PHB not present?\n");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ early_read_config_dword(hose, 0, 0, PCI_BASE_ADDRESS_1, &pci_membase);
|
|
|
+
|
|
|
+ if (pci_membase == 0) {
|
|
|
+ pr_err("HAWK PHB mibar not correctly set?\n");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ pr_info("mvme5100_pic_init: pci_membase: %x\n", pci_membase);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static struct of_device_id mvme5100_of_bus_ids[] __initdata = {
|
|
|
+ { .compatible = "hawk-bridge", },
|
|
|
+ {},
|
|
|
+};
|
|
|
+
|
|
|
+/*
|
|
|
+ * Setup the architecture
|
|
|
+ */
|
|
|
+static void __init mvme5100_setup_arch(void)
|
|
|
+{
|
|
|
+ struct device_node *np;
|
|
|
+
|
|
|
+ if (ppc_md.progress)
|
|
|
+ ppc_md.progress("mvme5100_setup_arch()", 0);
|
|
|
+
|
|
|
+ for_each_compatible_node(np, "pci", "hawk-pci")
|
|
|
+ mvme5100_add_bridge(np);
|
|
|
+
|
|
|
+ restart = ioremap(BOARD_MODRST_REG, 4);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+static void mvme5100_show_cpuinfo(struct seq_file *m)
|
|
|
+{
|
|
|
+ seq_puts(m, "Vendor\t\t: Motorola/Emerson\n");
|
|
|
+ seq_puts(m, "Machine\t\t: MVME5100\n");
|
|
|
+}
|
|
|
+
|
|
|
+static void mvme5100_restart(char *cmd)
|
|
|
+{
|
|
|
+
|
|
|
+ local_irq_disable();
|
|
|
+ mtmsr(mfmsr() | MSR_IP);
|
|
|
+
|
|
|
+ out_8((u_char *) restart, 0x01);
|
|
|
+
|
|
|
+ while (1)
|
|
|
+ ;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Called very early, device-tree isn't unflattened
|
|
|
+ */
|
|
|
+static int __init mvme5100_probe(void)
|
|
|
+{
|
|
|
+ unsigned long root = of_get_flat_dt_root();
|
|
|
+
|
|
|
+ return of_flat_dt_is_compatible(root, "MVME5100");
|
|
|
+}
|
|
|
+
|
|
|
+static int __init probe_of_platform_devices(void)
|
|
|
+{
|
|
|
+
|
|
|
+ of_platform_bus_probe(NULL, mvme5100_of_bus_ids, NULL);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+machine_device_initcall(mvme5100, probe_of_platform_devices);
|
|
|
+
|
|
|
+define_machine(mvme5100) {
|
|
|
+ .name = "MVME5100",
|
|
|
+ .probe = mvme5100_probe,
|
|
|
+ .setup_arch = mvme5100_setup_arch,
|
|
|
+ .init_IRQ = mvme5100_pic_init,
|
|
|
+ .show_cpuinfo = mvme5100_show_cpuinfo,
|
|
|
+ .get_irq = mpic_get_irq,
|
|
|
+ .restart = mvme5100_restart,
|
|
|
+ .calibrate_decr = generic_calibrate_decr,
|
|
|
+ .progress = udbg_progress,
|
|
|
+};
|