mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
217 lines
4.7 KiB
217 lines
4.7 KiB
// SPDX-License-Identifier: GPL-2.0-or-later |
|
/* |
|
* 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. |
|
* |
|
* Author: Stephen Chivers <[email protected]> |
|
*/ |
|
|
|
#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(struct irq_desc *desc) |
|
{ |
|
struct irq_chip *chip = irq_desc_get_chip(desc); |
|
unsigned int cascade_irq = i8259_irq(); |
|
|
|
if (cascade_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) { |
|
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 %pOF\n", dev); |
|
|
|
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 const struct of_device_id mvme5100_of_bus_ids[] __initconst = { |
|
{ .compatible = "hawk-bridge", }, |
|
{}, |
|
}; |
|
|
|
/* |
|
* Setup the architecture |
|
*/ |
|
static void __init mvme5100_setup_arch(void) |
|
{ |
|
if (ppc_md.progress) |
|
ppc_md.progress("mvme5100_setup_arch()", 0); |
|
|
|
restart = ioremap(BOARD_MODRST_REG, 4); |
|
} |
|
|
|
static void __init mvme5100_setup_pci(void) |
|
{ |
|
struct device_node *np; |
|
|
|
for_each_compatible_node(np, "pci", "hawk-pci") |
|
mvme5100_add_bridge(np); |
|
} |
|
|
|
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 __noreturn 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) |
|
{ |
|
return of_machine_is_compatible("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, |
|
.discover_phbs = mvme5100_setup_pci, |
|
.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, |
|
};
|
|
|