📄 sb1250_pci_machdep.c
字号:
/* ********************************************************************* * Broadcom Common Firmware Environment (CFE) * * BCM1250-specific PCI support File: sb1250_pci_machdep.c * ********************************************************************* * * Copyright 2001,2002,2003 * Broadcom Corporation. All rights reserved. * * This software is furnished under license and may be used and * copied only in accordance with the following terms and * conditions. Subject to these conditions, you may download, * copy, install, use, modify and distribute modified or unmodified * copies of this software in source and/or binary form. No title * or ownership is transferred hereby. * * 1) Any source code used, modified or distributed must reproduce * and retain this copyright notice and list of conditions * as they appear in the source file. * * 2) No right is granted to use any trade name, trademark, or * logo of Broadcom Corporation. The "Broadcom Corporation" * name may not be used to endorse or promote products derived * from this software without the prior written permission of * Broadcom Corporation. * * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. ********************************************************************* *//* * Based in part on the algor p5064 version of pci_machdep.c, * from SiByte sources dated 20000824, which was distributed with * the copyright and license notices below: *//* Very loosely based on: *//* $NetBSD: pci_machdep.c,v 1.17 1995/07/27 21:39:59 cgd Exp $ *//* * Copyright (c) 1994 Charles Hannum. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Charles Hannum. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *//* * Sibyte SB-1250 machine-specific functions for PCI autoconfiguration. */#include "cfe.h"#include "sbmips.h"#include "sb1250_defs.h"#include "sb1250_regs.h"#include "sb1250_scd.h"#include "lib_physio.h"#include "env_subr.h"extern void cfe_ledstr(const char *);#include "pcivar.h"#include "pci_internal.h"#include "pcireg.h"#include "ldtreg.h"#define SBD_DISPLAY(msg) cfe_ledstr(msg)const cons_t pci_optnames[] = { {"verbose",PCI_FLG_VERBOSE}, {"ldt_rev_017",PCI_FLG_LDT_REV_017}, {NULL,0}};extern int _pciverbose;/* PCI regions in system physical (ZBbus) space. See Figure 37. */#define PCI_PORTMAX (PCI_HOST_PORTS-1)static struct { /* ZBbus space allocated for mapping to the standard PCI address spaces */ uint32_t mem_space; uint32_t mem_space_size; uint32_t io_space; uint32_t io_space_size; uint32_t cfg_space; uint32_t cfg_space_size; /* PCI space available for configuration */ uint32_t pci_mem_base; uint32_t pci_io_base; /* Bits for endian policy (0: match bytes, 1: match bits) */ uint32_t mem_bit_endian; uint32_t io_bit_endian; uint32_t cfg_bit_endian; /* Match bits base for configuration (convenience variable) */ physaddr_t cfg_base; /* Message Signaled Interrupt destinations. */ uint64_t msi_set_base; uint64_t msi_clear_base; uint64_t msi_bit_endian;} Q;static voidpci_set_root (void){ Q.mem_space = A_PHYS_LDTPCI_IO_MATCH_BYTES_32; /* 0x0040000000 */ Q.mem_space_size = 0x0020000000; Q.io_space = A_PHYS_LDTPCI_IO_MATCH_BYTES; /* 0x00DC000000 */ Q.io_space_size = 0x0002000000; Q.cfg_space = A_PHYS_LDTPCI_CFG_MATCH_BYTES; /* 0x00DE000000 */ Q.cfg_space_size = 0x0001000000; Q.pci_mem_base = 0x40000000; Q.pci_io_base = 0x00000000; Q.mem_bit_endian = 0x0020000000; Q.io_bit_endian = 0x0020000000; Q.cfg_bit_endian = 0x0020000000; Q.cfg_base = PHYS_TO_XKSEG_UNCACHED(Q.cfg_space | Q.cfg_bit_endian); Q.msi_set_base = A_IMR_REGISTER(0, R_IMR_ALIAS_MAILBOX_SET_CPU); Q.msi_clear_base = A_IMR_REGISTER(0, R_IMR_MAILBOX_CLR_CPU); Q.msi_bit_endian = 0x0020000000;}/* Templates for bus attributes. */static const struct pci_bus sb1250_pci_bus = { 0, /* minimum grant */ 255, /* maximum latency */ 1, /* devsel time = medium */ 1, /* we support fast back-to-back */ 1, /* we support prefetch */ 1, /* we support 66 MHz */ 0, /* we don't support 64 bits */ 4000000, /* bandwidth: in 0.25us cycles / sec */ 0, /* initially no devices on bus */};static const struct pci_bus secondary_pci_bus = { 0, /* minimum grant */ 255, /* maximum latency */ 0, /* devsel time = unknown */ 0, /* configure fast back-to-back */ 0, /* we don't prefetch */ 0, /* configure 66 MHz */ 0, /* we don't support 64 bits */ 4000000, /* bandwidth: in 0.25us cycles / sec */ 0, /* initially no devices on bus */};#define MAXBUS 10static struct pci_bus _pci_bus[MAXBUS];static int _pci_nbus = 0;#define SB1250_PCI_MAKE_TAG(b,d,f) \ (((b) << 16) | ((d) << 11) | ((f) << 8))#if defined(__MIPSEB)/* This is for big-endian with a match bits policy. */#define SB1250_CFG_ADDR(t, o, w) \ ((Q.cfg_base + (t) + (o)) ^ (4 - (w)))#elif defined(__MIPSEL)/* This is for little-endian, either policy. */#define SB1250_CFG_ADDR(t, o, w) \ (Q.cfg_base + (t) + (o))#else#error "Must specifiy either MIPSEL or MIPSEB"#endifpcireg_t pci_conf_read8(pcitag_t, int);void pci_conf_write8(pcitag_t, int, pcireg_t);#ifndef pci_conf_read32#define pci_conf_read32 pci_conf_read#endif#ifndef pci_conf_write32#define pci_conf_write32 pci_conf_write#endif/* Access functions *//* The following should return the index of the last usable bus port. */intpci_maxport (void){ return PCI_PORTMAX;}/* The following must either fail or return the next sequential bus number to make secondary/subordinate numbering work correctly. */intpci_nextbus (int port){ int bus = _pci_nbus; if (bus >= MAXBUS) return -1; _pci_nbus++; return bus;} intpci_maxbus (int port){ return _pci_nbus - 1;}struct pci_bus *pci_businfo (int port, int bus){ return (bus < _pci_nbus ? &_pci_bus[bus] : NULL);}/* * PCI address resources. * NB: initial limits for address allocation are assumed to be aligned * appropriately for PCI bridges (4K boundaries for I/O, 1M for memory). */pcireg_tpci_minmemaddr (int port){ /* skip the 16MB reserved for ISA mem space */ return Q.pci_mem_base + 0x1000000;}pcireg_tpci_maxmemaddr (int port){ return Q.pci_mem_base + Q.mem_space_size;}pcireg_tpci_minioaddr (int port){ /* Skip the 32KB reserved for ISA i/o space. */ return Q.pci_io_base + 0x8000;}pcireg_tpci_maxioaddr (int port){ return Q.pci_io_base + Q.io_space_size;}/* The SB-1250 integrated host bridges. */#define PCI_VENDOR_SIBYTE 0x166d#define SB1250_PCI_BRIDGE (SB1250_PCI_MAKE_TAG(0,0,0))#define SB1250_LDT_BRIDGE (SB1250_PCI_MAKE_TAG(0,1,0))static int sb1250_in_device_mode;static int sb1250_ldt_slave_mode;static int sb1250_ldt_init; /* Set to one after LHB sees InitDone *//* The pass 1 BCM1250 does not implement EOI cycles correctly. Later passes do. The following variable controls whether PCI interrupt mappings are programmed to be level-sensitive (EOI) or edge-sensitive (no EOI) in LDT-PCI bridges. */int eoi_implemented;/* Implementation-specific registers for the PCI Host Bridge (PHB) */#define PHB_FEATURE_REG 0x40#define PHB_FEATURE_DEFAULTS 0x7DB38080#define PHB_MAP_REG_BASE 0x44#define PHB_MAP_N_ENTRIES 16/* The format of MAP table entries */#define PHB_MAP_ENABLE (1 << 0)#define PHB_MAP_SEND_LDT (1 << 1)#define PHB_MAP_L2CA (1 << 2)#define PHB_MAP_ENDIAN (1 << 3)#define PHB_MAP_ADDR_SHIFT 12#define PHB_MAP_ADDR_MASK 0xFFFFF000#define PHB_MAP_ENTRY_SPAN (1 << 20)#define PHB_ERRORADDR_REG 0x84#define PHB_ADD_STAT_CMD_REG 0x88#define PHB_SUBSYSSET_REG 0x8C/* pass 2 additions */#define PHB_READHOST_REG 0x94#define PHB_READHOST_DISABLE (0 << 0) /* write only */#define PHB_READHOST_ENABLE (1 << 0)#define PHB_ADAPTEXT_REG 0x98#define PHB_DIS_DMAR_IOW_DEP (1 << 6)/* PCI host bridge configuration * * Note that the PCI host bridge has two, mostly disjoint, sets of * configuration registers. One is used in Host mode and is * accessible from the ZBbus; the other is used in Device mode and is * accessible from the PCI bus. The MAP registers are shared but in * Pass 1 are write-only, from the ZBbus side. In pass 2, they are * readable iff read_host is set. */static voidphb_init (void){ int i; pcireg_t csr, cr, aer, icr; pcireg_t t; /* used for reads that push writes */ /* reset the PCI busses */ /* PCI is only reset at system reset */ /* PCI: disable and clear the BAR0 MAP registers */ for (i = 0; i < PHB_MAP_N_ENTRIES; i++) pci_conf_write32(SB1250_PCI_BRIDGE, PHB_MAP_REG_BASE + 4*i, 0); /* Because they write to the ZBbus bank of configuration registers, some of the following initializations are noops in Device mode, but they do no harm. */ /* PCI: set feature and timeout registers to their default. */ pci_conf_write32(SB1250_PCI_BRIDGE, PHB_FEATURE_REG, PHB_FEATURE_DEFAULTS); /* PCI: enable bridge to PCI and PCI memory accesses, including write-invalidate, plus error handling */ csr = PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_INVALIDATE_ENABLE | PCI_COMMAND_SERR_ENABLE | PCI_COMMAND_PARITY_ENABLE; pci_conf_write32(SB1250_PCI_BRIDGE, PCI_COMMAND_STATUS_REG, csr); /* PCI: clear errors */ csr = pci_conf_read32(SB1250_PCI_BRIDGE, PCI_COMMAND_STATUS_REG); csr |= PCI_STATUS_PARITY_ERROR | PCI_STATUS_SYSTEM_ERROR | PCI_STATUS_MASTER_ABORT | PCI_STATUS_MASTER_TARGET_ABORT | PCI_STATUS_TARGET_TARGET_ABORT | PCI_STATUS_PARITY_DETECT; pci_conf_write32(SB1250_PCI_BRIDGE, PCI_COMMAND_STATUS_REG, csr); /* PCI: allow liberal ordering rules */ /* Despite the manual, setting dis_dmar_iow_dep is recommended unless strict ordering is required, since it can substantially improve performance in the presence of slow devices. */ aer = pci_conf_read32(SB1250_PCI_BRIDGE, PHB_ADAPTEXT_REG); aer |= PHB_DIS_DMAR_IOW_DEP; pci_conf_write32(SB1250_PCI_BRIDGE, PHB_ADAPTEXT_REG, aer); /* PCI: set up interrupt mapping */ icr = pci_conf_read32(SB1250_PCI_BRIDGE, PCI_BPARAM_INTERRUPT_REG);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -