| 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 2 | /* |
| 3 | * Board setup routines for the Emerson/Artesyn MVME7100 |
| 4 | * |
| 5 | * Copyright 2016 Elettra-Sincrotrone Trieste S.C.p.A. |
| 6 | * |
| 7 | * Author: Alessio Igor Bogani <alessio.bogani@elettra.eu> |
| 8 | * |
| 9 | * Based on earlier code by: |
| 10 | * |
| 11 | * Ajit Prem <ajit.prem@emerson.com> |
| 12 | * Copyright 2008 Emerson |
| 13 | * |
| 14 | * USB host fixup is borrowed by: |
| 15 | * |
| 16 | * Martyn Welch <martyn.welch@ge.com> |
| 17 | * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc. |
| 18 | */ |
| 19 | |
| 20 | #include <linux/pci.h> |
| 21 | #include <linux/of.h> |
| 22 | #include <linux/of_fdt.h> |
| 23 | #include <linux/of_address.h> |
| 24 | #include <asm/udbg.h> |
| 25 | #include <asm/mpic.h> |
| 26 | #include <sysdev/fsl_soc.h> |
| 27 | #include <sysdev/fsl_pci.h> |
| 28 | |
| 29 | #include "mpc86xx.h" |
| 30 | |
| 31 | #define MVME7100_INTERRUPT_REG_2_OFFSET 0x05 |
| 32 | #define MVME7100_DS1375_MASK 0x40 |
| 33 | #define MVME7100_MAX6649_MASK 0x20 |
| 34 | #define MVME7100_ABORT_MASK 0x10 |
| 35 | |
| 36 | /* |
| 37 | * Setup the architecture |
| 38 | */ |
| 39 | static void __init mvme7100_setup_arch(void) |
| 40 | { |
| 41 | struct device_node *bcsr_node; |
| 42 | void __iomem *mvme7100_regs = NULL; |
| 43 | u8 reg; |
| 44 | |
| 45 | if (ppc_md.progress) |
| 46 | ppc_md.progress("mvme7100_setup_arch()" , 0); |
| 47 | |
| 48 | #ifdef CONFIG_SMP |
| 49 | mpc86xx_smp_init(); |
| 50 | #endif |
| 51 | |
| 52 | fsl_pci_assign_primary(); |
| 53 | |
| 54 | /* Remap BCSR registers */ |
| 55 | bcsr_node = of_find_compatible_node(NULL, NULL, |
| 56 | compat: "artesyn,mvme7100-bcsr" ); |
| 57 | if (bcsr_node) { |
| 58 | mvme7100_regs = of_iomap(node: bcsr_node, index: 0); |
| 59 | of_node_put(node: bcsr_node); |
| 60 | } |
| 61 | |
| 62 | if (mvme7100_regs) { |
| 63 | /* Disable ds1375, max6649, and abort interrupts */ |
| 64 | reg = readb(addr: mvme7100_regs + MVME7100_INTERRUPT_REG_2_OFFSET); |
| 65 | reg |= MVME7100_DS1375_MASK | MVME7100_MAX6649_MASK |
| 66 | | MVME7100_ABORT_MASK; |
| 67 | writeb(val: reg, addr: mvme7100_regs + MVME7100_INTERRUPT_REG_2_OFFSET); |
| 68 | } else |
| 69 | pr_warn("Unable to map board registers\n" ); |
| 70 | |
| 71 | pr_info("MVME7100 board from Artesyn\n" ); |
| 72 | } |
| 73 | |
| 74 | /* |
| 75 | * Called very early, device-tree isn't unflattened |
| 76 | */ |
| 77 | static int __init mvme7100_probe(void) |
| 78 | { |
| 79 | unsigned long root = of_get_flat_dt_root(); |
| 80 | |
| 81 | return of_flat_dt_is_compatible(node: root, name: "artesyn,MVME7100" ); |
| 82 | } |
| 83 | |
| 84 | static void mvme7100_usb_host_fixup(struct pci_dev *pdev) |
| 85 | { |
| 86 | unsigned int val; |
| 87 | |
| 88 | if (!machine_is(mvme7100)) |
| 89 | return; |
| 90 | |
| 91 | /* Ensure only ports 1 & 2 are enabled */ |
| 92 | pci_read_config_dword(dev: pdev, where: 0xe0, val: &val); |
| 93 | pci_write_config_dword(dev: pdev, where: 0xe0, val: (val & ~7) | 0x2); |
| 94 | |
| 95 | /* System clock is 48-MHz Oscillator and EHCI Enabled. */ |
| 96 | pci_write_config_dword(dev: pdev, where: 0xe4, val: 1 << 5); |
| 97 | } |
| 98 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB, |
| 99 | mvme7100_usb_host_fixup); |
| 100 | |
| 101 | machine_arch_initcall(mvme7100, mpc86xx_common_publish_devices); |
| 102 | |
| 103 | define_machine(mvme7100) { |
| 104 | .name = "MVME7100" , |
| 105 | .probe = mvme7100_probe, |
| 106 | .setup_arch = mvme7100_setup_arch, |
| 107 | .init_IRQ = mpc86xx_init_irq, |
| 108 | .get_irq = mpic_get_irq, |
| 109 | .time_init = mpc86xx_time_init, |
| 110 | .progress = udbg_progress, |
| 111 | #ifdef CONFIG_PCI |
| 112 | .pcibios_fixup_bus = fsl_pcibios_fixup_bus, |
| 113 | #endif |
| 114 | }; |
| 115 | |