mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git/
synced 2026-04-17 22:23:45 -04:00
Fix a regression that has caused accesses to the PCI MMIO window to
complete unclaimed in non-EVA configurations with the SOC-it family of
system controllers, preventing PCI devices from working that use MMIO.
In the non-EVA case PHYS_OFFSET is set to 0, meaning that PCI_BAR0 is
set with an empty mask (and PCI_HEAD4 matches addresses starting from 0
accordingly). Consequently all addresses are matched for incoming DMA
accesses from PCI. This seems to confuse the system controller's logic
and outgoing bus cycles targeting the PCI MMIO window seem not to make
it to the intended devices.
This happens as well when a wider mask is used with PCI_BAR0, such as
0x80000000 or 0xe0000000, that makes addresses match that overlap with
the PCI MMIO window, which starts at 0x10000000 in our configuration.
Set the mask in PCI_BAR0 to 0xf0000000 for non-EVA then, covering the
non-EVA maximum 256 MiB of RAM, which is what YAMON does and which used
to work correctly up to the offending commit. Set PCI_P2SCMSKL to match
PCI_BAR0 as required by the system controller's specification, and match
PCI_P2SCMAPL to PCI_HEAD4 for identity mapping.
Verified with:
Core board type/revision = 0x0d (Core74K) / 0x01
System controller/revision = MIPS SOC-it 101 OCP / 1.3 SDR-FW-4:1
Processor Company ID/options = 0x01 (MIPS Technologies, Inc.) / 0x1c
Processor ID/revision = 0x97 (MIPS 74Kf) / 0x4c
for non-EVA and with:
Core board type/revision = 0x0c (CoreFPGA-5) / 0x00
System controller/revision = MIPS ROC-it2 / 0.0 FW-1:1 (CLK_unknown) GIC
Processor Company ID/options = 0x01 (MIPS Technologies, Inc.) / 0x00
Processor ID/revision = 0xa0 (MIPS interAptiv UP) / 0x20
for EVA/non-EVA, fixing:
defxx 0000:00:12.0: assign IRQ: got 10
defxx: v1.12 2021/03/10 Lawrence V. Stefani and others
0000:00:12.0: Could not read adapter factory MAC address!
vs:
defxx 0000:00:12.0: assign IRQ: got 10
defxx: v1.12 2021/03/10 Lawrence V. Stefani and others
0000:00:12.0: DEFPA at MMIO addr = 0x10142000, IRQ = 10, Hardware addr = 00-00-f8-xx-xx-xx
0000:00:12.0: registered as fddi0
for non-EVA and causing no change for EVA.
Signed-off-by: Maciej W. Rozycki <macro@orcam.me.uk>
Fixes: 422dd25664 ("MIPS: Malta: Allow PCI devices DMA to lower 2GB physical")
Cc: stable@vger.kernel.org # v4.9+
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
302 lines
7.9 KiB
C
302 lines
7.9 KiB
C
/*
|
|
* This file is subject to the terms and conditions of the GNU General Public
|
|
* License. See the file "COPYING" in the main directory of this archive
|
|
* for more details.
|
|
*
|
|
* PROM library initialisation code.
|
|
*
|
|
* Copyright (C) 1999,2000,2004,2005,2012 MIPS Technologies, Inc.
|
|
* All rights reserved.
|
|
* Authors: Carsten Langgaard <carstenl@mips.com>
|
|
* Maciej W. Rozycki <macro@mips.com>
|
|
* Steven J. Hill <sjhill@mips.com>
|
|
*/
|
|
#include <linux/init.h>
|
|
#include <linux/string.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/pci_regs.h>
|
|
#include <linux/serial_core.h>
|
|
|
|
#include <asm/cacheflush.h>
|
|
#include <asm/smp-ops.h>
|
|
#include <asm/traps.h>
|
|
#include <asm/fw/fw.h>
|
|
#include <asm/mips-cps.h>
|
|
#include <asm/mips-boards/generic.h>
|
|
#include <asm/mips-boards/malta.h>
|
|
|
|
static int mips_revision_corid;
|
|
int mips_revision_sconid;
|
|
|
|
/* Bonito64 system controller register base. */
|
|
unsigned long _pcictrl_bonito;
|
|
unsigned long _pcictrl_bonito_pcicfg;
|
|
|
|
/* GT64120 system controller register base */
|
|
unsigned long _pcictrl_gt64120;
|
|
|
|
/* MIPS System controller register base */
|
|
unsigned long _pcictrl_msc;
|
|
|
|
#ifdef CONFIG_SERIAL_8250_CONSOLE
|
|
static void __init console_config(void)
|
|
{
|
|
char console_string[40];
|
|
int baud = 0;
|
|
char parity = '\0', bits = '\0', flow = '\0';
|
|
char *s;
|
|
|
|
s = fw_getenv("modetty0");
|
|
if (s) {
|
|
while (*s >= '0' && *s <= '9')
|
|
baud = baud*10 + *s++ - '0';
|
|
if (*s == ',')
|
|
s++;
|
|
if (*s)
|
|
parity = *s++;
|
|
if (*s == ',')
|
|
s++;
|
|
if (*s)
|
|
bits = *s++;
|
|
if (*s == ',')
|
|
s++;
|
|
if (*s == 'h')
|
|
flow = 'r';
|
|
}
|
|
if (baud == 0)
|
|
baud = 38400;
|
|
if (parity != 'n' && parity != 'o' && parity != 'e')
|
|
parity = 'n';
|
|
if (bits != '7' && bits != '8')
|
|
bits = '8';
|
|
if (flow == '\0')
|
|
flow = 'r';
|
|
|
|
if ((strstr(fw_getcmdline(), "earlycon=")) == NULL) {
|
|
sprintf(console_string, "uart8250,io,0x3f8,%d%c%c", baud,
|
|
parity, bits);
|
|
setup_earlycon(console_string);
|
|
}
|
|
|
|
if ((strstr(fw_getcmdline(), "console=")) == NULL) {
|
|
sprintf(console_string, " console=ttyS0,%d%c%c%c", baud,
|
|
parity, bits, flow);
|
|
strcat(fw_getcmdline(), console_string);
|
|
pr_info("Config serial console:%s\n", console_string);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
static void __init mips_nmi_setup(void)
|
|
{
|
|
void *base;
|
|
|
|
base = cpu_has_veic ?
|
|
(void *)(CAC_BASE + 0xa80) :
|
|
(void *)(CAC_BASE + 0x380);
|
|
memcpy(base, except_vec_nmi, 0x80);
|
|
flush_icache_range((unsigned long)base, (unsigned long)base + 0x80);
|
|
}
|
|
|
|
static void __init mips_ejtag_setup(void)
|
|
{
|
|
void *base;
|
|
extern char except_vec_ejtag_debug[];
|
|
|
|
base = cpu_has_veic ?
|
|
(void *)(CAC_BASE + 0xa00) :
|
|
(void *)(CAC_BASE + 0x300);
|
|
memcpy(base, except_vec_ejtag_debug, 0x80);
|
|
flush_icache_range((unsigned long)base, (unsigned long)base + 0x80);
|
|
}
|
|
|
|
phys_addr_t mips_cpc_default_phys_base(void)
|
|
{
|
|
return CPC_BASE_ADDR;
|
|
}
|
|
|
|
void __init prom_init(void)
|
|
{
|
|
/*
|
|
* early setup of _pcictrl_bonito so that we can determine
|
|
* the system controller on a CORE_EMUL board
|
|
*/
|
|
_pcictrl_bonito = (unsigned long)ioremap(BONITO_REG_BASE, BONITO_REG_SIZE);
|
|
|
|
mips_revision_corid = MIPS_REVISION_CORID;
|
|
|
|
if (mips_revision_corid == MIPS_REVISION_CORID_CORE_EMUL) {
|
|
if (BONITO_PCIDID == 0x0001df53 ||
|
|
BONITO_PCIDID == 0x0003df53)
|
|
mips_revision_corid = MIPS_REVISION_CORID_CORE_EMUL_BON;
|
|
else
|
|
mips_revision_corid = MIPS_REVISION_CORID_CORE_EMUL_MSC;
|
|
}
|
|
|
|
mips_revision_sconid = MIPS_REVISION_SCONID;
|
|
if (mips_revision_sconid == MIPS_REVISION_SCON_OTHER) {
|
|
switch (mips_revision_corid) {
|
|
case MIPS_REVISION_CORID_QED_RM5261:
|
|
case MIPS_REVISION_CORID_CORE_LV:
|
|
case MIPS_REVISION_CORID_CORE_FPGA:
|
|
case MIPS_REVISION_CORID_CORE_FPGAR2:
|
|
mips_revision_sconid = MIPS_REVISION_SCON_GT64120;
|
|
break;
|
|
case MIPS_REVISION_CORID_CORE_EMUL_BON:
|
|
case MIPS_REVISION_CORID_BONITO64:
|
|
case MIPS_REVISION_CORID_CORE_20K:
|
|
mips_revision_sconid = MIPS_REVISION_SCON_BONITO;
|
|
break;
|
|
case MIPS_REVISION_CORID_CORE_MSC:
|
|
case MIPS_REVISION_CORID_CORE_FPGA2:
|
|
case MIPS_REVISION_CORID_CORE_24K:
|
|
/*
|
|
* SOCit/ROCit support is essentially identical
|
|
* but make an attempt to distinguish them
|
|
*/
|
|
mips_revision_sconid = MIPS_REVISION_SCON_SOCIT;
|
|
break;
|
|
case MIPS_REVISION_CORID_CORE_FPGA3:
|
|
case MIPS_REVISION_CORID_CORE_FPGA4:
|
|
case MIPS_REVISION_CORID_CORE_FPGA5:
|
|
case MIPS_REVISION_CORID_CORE_EMUL_MSC:
|
|
default:
|
|
/* See above */
|
|
mips_revision_sconid = MIPS_REVISION_SCON_ROCIT;
|
|
break;
|
|
}
|
|
}
|
|
|
|
switch (mips_revision_sconid) {
|
|
u32 start, map, mask, data;
|
|
|
|
case MIPS_REVISION_SCON_GT64120:
|
|
/*
|
|
* Setup the North bridge to do Master byte-lane swapping
|
|
* when running in bigendian.
|
|
*/
|
|
_pcictrl_gt64120 = (unsigned long)ioremap(MIPS_GT_BASE, 0x2000);
|
|
|
|
#ifdef CONFIG_CPU_LITTLE_ENDIAN
|
|
GT_WRITE(GT_PCI0_CMD_OFS, GT_PCI0_CMD_MBYTESWAP_BIT |
|
|
GT_PCI0_CMD_SBYTESWAP_BIT);
|
|
#else
|
|
GT_WRITE(GT_PCI0_CMD_OFS, 0);
|
|
#endif
|
|
/* Fix up PCI I/O mapping if necessary (for Atlas). */
|
|
start = GT_READ(GT_PCI0IOLD_OFS);
|
|
map = GT_READ(GT_PCI0IOREMAP_OFS);
|
|
if ((start & map) != 0) {
|
|
map &= ~start;
|
|
GT_WRITE(GT_PCI0IOREMAP_OFS, map);
|
|
}
|
|
|
|
set_io_port_base(MALTA_GT_PORT_BASE);
|
|
break;
|
|
|
|
case MIPS_REVISION_SCON_BONITO:
|
|
_pcictrl_bonito_pcicfg = (unsigned long)ioremap(BONITO_PCICFG_BASE, BONITO_PCICFG_SIZE);
|
|
|
|
/*
|
|
* Disable Bonito IOBC.
|
|
*/
|
|
BONITO_PCIMEMBASECFG = BONITO_PCIMEMBASECFG &
|
|
~(BONITO_PCIMEMBASECFG_MEMBASE0_CACHED |
|
|
BONITO_PCIMEMBASECFG_MEMBASE1_CACHED);
|
|
|
|
/*
|
|
* Setup the North bridge to do Master byte-lane swapping
|
|
* when running in bigendian.
|
|
*/
|
|
#ifdef CONFIG_CPU_LITTLE_ENDIAN
|
|
BONITO_BONGENCFG = BONITO_BONGENCFG &
|
|
~(BONITO_BONGENCFG_MSTRBYTESWAP |
|
|
BONITO_BONGENCFG_BYTESWAP);
|
|
#else
|
|
BONITO_BONGENCFG = BONITO_BONGENCFG |
|
|
BONITO_BONGENCFG_MSTRBYTESWAP |
|
|
BONITO_BONGENCFG_BYTESWAP;
|
|
#endif
|
|
|
|
set_io_port_base(MALTA_BONITO_PORT_BASE);
|
|
break;
|
|
|
|
case MIPS_REVISION_SCON_SOCIT:
|
|
case MIPS_REVISION_SCON_ROCIT:
|
|
_pcictrl_msc = (unsigned long)ioremap(MIPS_MSC01_PCI_REG_BASE, 0x2000);
|
|
mips_pci_controller:
|
|
mb();
|
|
MSC_READ(MSC01_PCI_CFG, data);
|
|
MSC_WRITE(MSC01_PCI_CFG, data & ~MSC01_PCI_CFG_EN_BIT);
|
|
wmb();
|
|
|
|
/* Fix up lane swapping. */
|
|
#ifdef CONFIG_CPU_LITTLE_ENDIAN
|
|
MSC_WRITE(MSC01_PCI_SWAP, MSC01_PCI_SWAP_NOSWAP);
|
|
#else
|
|
MSC_WRITE(MSC01_PCI_SWAP,
|
|
MSC01_PCI_SWAP_BYTESWAP << MSC01_PCI_SWAP_IO_SHF |
|
|
MSC01_PCI_SWAP_BYTESWAP << MSC01_PCI_SWAP_MEM_SHF |
|
|
MSC01_PCI_SWAP_BYTESWAP << MSC01_PCI_SWAP_BAR0_SHF);
|
|
#endif
|
|
|
|
/*
|
|
* Set up memory mapping in host bridge for PCI DMA masters,
|
|
* in transparent addressing mode. For EVA use the Malta
|
|
* maximum of 2 GiB memory in the alias space at 0x80000000
|
|
* as per PHYS_OFFSET. Otherwise use 256 MiB of memory in
|
|
* the regular space, avoiding mapping the PCI MMIO window
|
|
* for DMA as it seems to confuse the system controller's
|
|
* logic, causing PCI MMIO to stop working.
|
|
*/
|
|
mask = PHYS_OFFSET ? PHYS_OFFSET : 0xf0000000;
|
|
MSC_WRITE(MSC01_PCI_BAR0,
|
|
mask | PCI_BASE_ADDRESS_MEM_PREFETCH);
|
|
MSC_WRITE(MSC01_PCI_HEAD4,
|
|
PHYS_OFFSET | PCI_BASE_ADDRESS_MEM_PREFETCH);
|
|
|
|
MSC_WRITE(MSC01_PCI_P2SCMSKL, mask);
|
|
MSC_WRITE(MSC01_PCI_P2SCMAPL, PHYS_OFFSET);
|
|
|
|
/* Don't handle target retries indefinitely. */
|
|
if ((data & MSC01_PCI_CFG_MAXRTRY_MSK) ==
|
|
MSC01_PCI_CFG_MAXRTRY_MSK)
|
|
data = (data & ~(MSC01_PCI_CFG_MAXRTRY_MSK <<
|
|
MSC01_PCI_CFG_MAXRTRY_SHF)) |
|
|
((MSC01_PCI_CFG_MAXRTRY_MSK - 1) <<
|
|
MSC01_PCI_CFG_MAXRTRY_SHF);
|
|
|
|
wmb();
|
|
MSC_WRITE(MSC01_PCI_CFG, data);
|
|
mb();
|
|
|
|
set_io_port_base(MALTA_MSC_PORT_BASE);
|
|
break;
|
|
|
|
case MIPS_REVISION_SCON_SOCITSC:
|
|
case MIPS_REVISION_SCON_SOCITSCP:
|
|
_pcictrl_msc = (unsigned long)ioremap(MIPS_SOCITSC_PCI_REG_BASE, 0x2000);
|
|
goto mips_pci_controller;
|
|
|
|
default:
|
|
/* Unknown system controller */
|
|
while (1); /* We die here... */
|
|
}
|
|
board_nmi_handler_setup = mips_nmi_setup;
|
|
board_ejtag_handler_setup = mips_ejtag_setup;
|
|
|
|
fw_init_cmdline();
|
|
fw_meminit();
|
|
#ifdef CONFIG_SERIAL_8250_CONSOLE
|
|
console_config();
|
|
#endif
|
|
/* Early detection of CMP support */
|
|
mips_cpc_probe();
|
|
|
|
if (!register_cps_smp_ops())
|
|
return;
|
|
if (!register_vsmp_smp_ops())
|
|
return;
|
|
register_up_smp_ops();
|
|
}
|