📄 bcm1480_pci_machdep.c
字号:
/* ********************************************************************* * Broadcom Common Firmware Environment (CFE) * * BCM1400-specific PCI support File: bcm1480_pci_machdep.c * ********************************************************************* * * Copyright 2001,2002,2003,2004 * 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. *//* * BCM1280/BCM1480 machine-specific functions for PCI autoconfiguration. */#include "cfe.h"#include "sbmips.h"#include "bcm1480_regs.h"#include "bcm1480_pci.h"#include "bcm1480_ht.h"#include "bcm1480_hsp.h"#include "bcm1480_scd.h"#include "lib_physio.h"#include "env_subr.h"#include "pcivar.h"#include "pci_internal.h"#include "pcireg.h"#include "ldtreg.h"#ifndef CONFIG_HT#define CONFIG_HT 1#endifconst cons_t pci_optnames[] = { {"verbose",PCI_FLG_VERBOSE}, {NULL,0}};extern int _pciverbose;/* PCI regions in system physical (ZBbus) space. See Figure 17. */#define PCI_PORTMAX (PCI_HOST_PORTS-1)struct host_port { /* 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;};static struct host_port P[PCI_HOST_PORTS];/* The current bus space */static int root;static struct host_port *pci_select_root (int bus_space){ struct host_port *p; switch (bus_space) { case 0: /* PCI interface (Figure 17) */ root = 0; p = &P[0]; p->mem_space = A_BCM1480_PHYS_PCI_MEM_MATCH_BYTES; /* 0x0030000000 */ p->mem_space_size = 0x0010000000; p->io_space = A_BCM1480_PHYS_PCI_IO_MATCH_BYTES; /* 0x002C000000 */ p->io_space_size = 0x0002000000; p->cfg_space = A_BCM1480_PHYS_PCI_CFG_MATCH_BYTES; /* 0x002E000000 */ p->cfg_space_size = 0x0001000000; p->pci_mem_base = p->mem_space; /* now transparent */ p->pci_io_base = 0x00000000; p->mem_bit_endian = 0x0080000000; /* now all the same */ p->io_bit_endian = 0x0080000000; p->cfg_bit_endian = 0x0080000000; break; case 1: /* HT interface (Figure 26) */ root = 1; p = &P[1]; p->mem_space = A_BCM1480_PHYS_HT_MEM_MATCH_BYTES; /* 0x0040000000 */ p->mem_space_size = 0x0020000000; p->io_space = A_BCM1480_PHYS_HT_IO_MATCH_BYTES; /* 0x00DC000000 */ p->io_space_size = 0x0020000000; p->cfg_space = A_BCM1480_PHYS_HT_CFG_MATCH_BYTES; /* 0x00DE000000 */ p->cfg_space_size = 0x0001000000; p->pci_mem_base = p->mem_space; /* transparent */ p->pci_io_base = 0x00000000; p->mem_bit_endian = 0x0020000000; p->io_bit_endian = 0x0020000000; p->cfg_bit_endian = 0x0020000000; break; default: return NULL; } p->cfg_base = PHYS_TO_XKSEG_UNCACHED(p->cfg_space | p->cfg_bit_endian); return p;}/* Templates for bus attributes. */static const struct pci_bus bcm1400_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 */ 1, /* we support 64 bit addressing and DAC */ 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 BCM1400_PCI_MAKE_TAG(p,b,d,f) \ (((p) << 24) | ((b) << 16) | ((d) << 11) | ((f) << 8))#define BCM1400_HOST_PORT(tag) (((tag) >> 24) & 0xFF)#if defined(__MIPSEB)/* This is for big-endian with a match bits policy. */#define BCM1400_CFG_ADDR(t, o, w) \ ((P[BCM1400_HOST_PORT(t)].cfg_base + ((t) & 0xFFFF00) + (o)) ^ (4 - (w)))#elif defined(__MIPSEL)/* This is for little-endian, either policy. */#define BCM1400_CFG_ADDR(t, o, w) \ (P[BCM1400_HOST_PORT(t)].cfg_base + ((t) & 0xFFFF00) + (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 (less than the maximum for the bcm1255, bcm1455, etc.) */intpci_maxport (void){ uint64_t sysrev; sysrev = SBREADCSR(A_SCD_SYSTEM_REVISION); return ((G_SYS_PART(sysrev) & 0xF) == 0x6 ? 2 : 1) - 1;}/* 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 P[port].pci_mem_base + 0x1000000;}pcireg_tpci_maxmemaddr (int port){ return P[port].pci_mem_base + P[port].mem_space_size;}pcireg_tpci_minioaddr (int port){ /* Skip the 32KB reserved for ISA i/o space. */ return P[port].pci_io_base + 0x8000;}pcireg_tpci_maxioaddr (int port){ return P[port].pci_io_base + P[port].io_space_size;}/* The BCM1400 integrated host bridges. */#define PCI_VENDOR_SIBYTE 0x166d#define BCM1400_PCI_BRIDGE (BCM1400_PCI_MAKE_TAG(0,0,0,0))#define BCM1400_LDT_BRIDGE (BCM1400_PCI_MAKE_TAG(1,0,4,0))/* The BCM1400 integrated external PCI/HT bridges. */#define BCM1400_EXT0_BRIDGE (BCM1400_PCI_MAKE_TAG(1,0,0,0))#define BCM1400_EXT1_BRIDGE (BCM1400_PCI_MAKE_TAG(1,0,1,0))#define BCM1400_EXT2_BRIDGE (BCM1400_PCI_MAKE_TAG(1,0,2,0))static int bcm1400_in_device_mode;static int bcm1400_ldt_slave_mode;int eoi_implemented; /* vestigal 1250 *//* Convenience definitions for the PCI Host Bridge (PHB) */#define M_BCM1480_PCI_RST_ASSERTS (M_BCM1480_PCI_PERR_RST_ASSERT | \ M_BCM1480_PCI_DEVSEL_RST_ASSERT | \ M_BCM1480_PCI_STOP_RST_ASSERT | \ M_BCM1480_PCI_TRDY_RST_ASSERT)#define M_BCM1480_PHB_FCTRL_MEM_EN (M_BCM1480_PHB_FCTRL_LOW_MEM_EN | \ M_BCM1480_PHB_FCTRL_UPPER_MEM_EN)#define V_BCM1480_PHB_READHOST_DISABLE 0#define V_BCM1480_PHB_READHOST_ENABLE M_BCM1480_PHB_EXT_CONFIG_DIS/* * PCI-X host bridge configuration */static voidphb_init (void){ uint64_t reset_ctl, reset_stat; enum {pci33, pci66, pcix66, pcix133} mode; enum {pci_bus, pcix_bus} protocol; unsigned int clock; int i; pcireg_t csr, icr; pcireg_t id; pcireg_t t; /* used for reads that push writes */ /* PCI: reset the busses rooted in this host bridge */ reset_ctl = SBREADCSR(A_BCM1480_PCI_RESET); if ((reset_ctl & M_BCM1480_PCI_RESET_PIN) == 0) { reset_ctl |= M_BCM1480_PCI_RESET_PIN; SBWRITECSR(A_BCM1480_PCI_RESET, reset_ctl); cfe_usleep(100); } pci_clock_reset(); reset_ctl &= ~M_BCM1480_PCI_PCIXCAP_PULLUP; SBWRITECSR(A_BCM1480_PCI_RESET, reset_ctl); cfe_usleep(100); reset_stat = SBREADCSR(A_BCM1480_PCI_RESET); if ((reset_stat & M_BCM1480_PCI_PCIXCAP_STATUS) != 0) { mode = pcix133; protocol = pcix_bus; } else { reset_ctl |= M_BCM1480_PCI_PCIXCAP_PULLUP; SBWRITECSR(A_BCM1480_PCI_RESET, reset_ctl); cfe_usleep(100); reset_stat = SBREADCSR(A_BCM1480_PCI_RESET); if ((reset_stat & M_BCM1480_PCI_PCIXCAP_STATUS) != 0) { mode = pcix66; protocol = pcix_bus; } else { protocol = pci_bus; if ((reset_stat & M_BCM1480_PCI_M66EN_STATUS) != 0) mode = pci66; else mode = pci33; } reset_ctl &= ~M_BCM1480_PCI_PCIXCAP_PULLUP; SBWRITECSR(A_BCM1480_PCI_RESET, reset_ctl); } /* Choose the clock speed. */ pci_tagprintf(BCM1400_PCI_BRIDGE, "configuring bus for "); reset_ctl &= ~M_BCM1480_PCI_RST_ASSERTS; switch (mode) { case pci33: default: clock = pci_clock_select(33); break; case pci66: clock = pci_clock_select(66); break; case pcix66: reset_ctl |= M_BCM1480_PCI_STOP_RST_ASSERT; clock = pci_clock_select(66); break; case pcix133: reset_ctl |= (M_BCM1480_PCI_TRDY_RST_ASSERT | M_BCM1480_PCI_STOP_RST_ASSERT); clock = pci_clock_select(133); break; } xprintf("%dMHz PCI%s\n", clock, (protocol == pcix_bus ? "-X" : "")); pci_clock_enable(1); cfe_usleep(1000); /* Let clocks stabilize. */ SBWRITECSR(A_BCM1480_PCI_RESET, reset_ctl); cfe_usleep(1000); /* Set up Init Pattern */ pci_clock_enable(1); cfe_usleep(1000); /* Let clocks stabilize. */ /* Release PCI reset */ reset_ctl &= ~M_BCM1480_PCI_RESET_PIN; SBWRITECSR(A_BCM1480_PCI_RESET, reset_ctl); for (i = 1000; i > 0; i--) { reset_stat = SBREADCSR(A_BCM1480_PCI_RESET); if ((reset_stat & 0x3) == 0) break; cfe_usleep(100); } if (i == 0) xprintf("phb: PCI reset failed to clear\n"); /* Delay here to guarantee 0.5 sec device initialization time. */ cfe_sleep(CFE_HZ/2); /* The ResetIntr bit is always set here; clear it. */ SBWRITECSR(A_BCM1480_PCI_RESET, reset_ctl | M_BCM1480_PCI_RESET_INTR);#if (PCI_DEBUG != 0) xprintf("phb: post-reset %08llx\n", SBREADCSR(A_BCM1480_PCI_RESET) & 0xFFFFFFFF);#endif /* PCI: disable and clear the BAR0 MAP registers */ for (i = 0; i < BCM1480_PHB_MAPENTRIES; i++) pci_conf_write32(BCM1400_PCI_BRIDGE, R_BCM1480_PHB_MAPBASE + 4*i, 0); /* PCI: set feature register to its default. */ pci_conf_write32(BCM1400_PCI_BRIDGE, R_BCM1480_PHB_FCTRL,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -