⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sb1250_pci_machdep.c

📁 一个很好的嵌入式linux平台下的bootloader
💻 C
📖 第 1 页 / 共 4 页
字号:
	/* Try again.  Do a reset iff an LDT master, since a poorly           timed reset by a slave will break any link initialization           in progress. */	retry--;	if (sb1250_ldt_slave_mode)	    cfe_sleep(CFE_HZ/10);	else	    lhb_link_reset(CFE_HZ/10);    }    /* Rev 0.17 does not support dyanmic frequency updates. */    if (!rev017) {	/* Leave the target frequency in the LinkFreq register, which is	   just a shadow until a link reset happens.  */	pci_conf_write8(SB1250_LDT_BRIDGE, LHB_LFREQ_REG, ldt_freq);    }     finish:    t = pci_conf_read32(SB1250_LDT_BRIDGE, LHB_LINKCTRL_REG);    if ((t & LDT_LINKCTRL_INITDONE) == 0) {	xprintf("HyperTransport not initialized: InitDone not set\n");	if (_pciverbose > PCI_FLG_NORMAL)	    pci_tagprintf(SB1250_LDT_BRIDGE,			  "  Link Cmd = 0x%08x, Link Ctrl = 0x%08x\n",			  pci_conf_read32(SB1250_LDT_BRIDGE, LHB_LINKCMD_REG),			  pci_conf_read32(SB1250_LDT_BRIDGE, LHB_LINKCTRL_REG));	/* In production code, consider doing a chip cold reset (via           the SCD) here if the system requires an initialized HT bus.           See the advisory on HT PLL problems.  */    } else if ((t & LHB_LINKCTRL_ERRORS) != 0) {	xprintf("HyperTransport not initialized: "		"LinkFail or CRCErr set, LinkCtrl = 0x%08x\n", t);    } else if (!sb1250_ldt_slave_mode)	sb1250_ldt_init = 1;    /* Clear any pending error bits */    t = pci_conf_read32(SB1250_LDT_BRIDGE, LHB_ERR_CTRL_REG);    pci_conf_write32(SB1250_LDT_BRIDGE, LHB_ERR_CTRL_REG, t & 0xFF000000);    if (sb1250_ldt_slave_mode) {	/* This is LDT slave mode.  The documentation is not very clear	   on how much low level initialization should be done before	   sleeping.  We just set Master Enable so that we can subsequently           access LDT space. */	pcireg_t cmd;	/* If there are intermediate devices on the LDT, we would like           our addressing to match the master's, but we don't know it           and can't force it here.  Instead, we close all the windows           into configurable space, which is at least safe. */	lhb_null_config();	cmd = pci_conf_read32(SB1250_LDT_BRIDGE, PCI_COMMAND_STATUS_REG);	cmd &= (PCI_COMMAND_MASK << PCI_COMMAND_SHIFT);  /* preserve status */	cmd |= PCI_COMMAND_MASTER_ENABLE;	pci_conf_write32(SB1250_LDT_BRIDGE, PCI_COMMAND_STATUS_REG, cmd);    } else if (!sb1250_ldt_init) {	pcireg_t lr;  	lhb_null_config();	/* Also, terminate the link */	lr = pci_conf_read32(SB1250_LDT_BRIDGE, LHB_LINKCTRL_REG);	lr |= LDT_LINKCTRL_EOC;	pci_conf_write32(SB1250_LDT_BRIDGE, LHB_LINKCTRL_REG, lr);	lr |= LDT_LINKCTRL_TXOFF;	pci_conf_write32(SB1250_LDT_BRIDGE, LHB_LINKCTRL_REG, lr);    }    show_ldt_status();}/* * Called to initialise IOB0 and the host bridges at the beginning of time. */intpci_hwinit (int port, pci_flags_t flags){    int i;    int rev017;    unsigned linkfreq, buffctl;    uint64_t syscfg;    const char *str;    /* define the address spaces and capabilities */    if (port != 0)	return -1;    pci_set_root();    /* initialise global data */    syscfg = SBREADCSR(A_SCD_SYSTEM_CFG);    sb1250_in_device_mode = ((syscfg & M_SYS_PCI_HOST) == 0);    if (cfe_startflags & CFE_LDT_SLAVE)        sb1250_ldt_slave_mode = 1;    else        sb1250_ldt_slave_mode = 0;    eoi_implemented = 0;   /* conservative default */    /* Check for any relevant environment variables. */    rev017 = ((flags & PCI_FLG_LDT_REV_017) != 0);    /* Choose the LDT link frequency.  [C]SWARM boards are now set for       400 MHz by default */    str = env_getenv("LDT_LINKFREQ");    linkfreq = (str ? atoi(str) : 400);    /* Choose the buffer allocation (favor posted writes by default) */    str = env_getenv("LDT_BUFFERS");    buffctl = (str ? atoi(str) & 0xFFFF : 0x2525);    _pci_bus[_pci_nbus] = sb1250_pci_bus;    _pci_bus[_pci_nbus].port = port;    _pci_nbus++;    for (i = _pci_nbus; i < MAXBUS; i++)	_pci_bus[i] = secondary_pci_bus;    /* stop the SB-1250 from servicing any further PCI or LDT requests */    pci_conf_write32(SB1250_PCI_BRIDGE, PCI_COMMAND_STATUS_REG, 0);    pci_conf_write32(SB1250_LDT_BRIDGE, PCI_COMMAND_STATUS_REG, 0);    /* initialize the PCI host bridge */    phb_init();    /* initialize the LDT host bridge */    lhb_init(rev017, linkfreq, buffctl);    cfe_sleep(CFE_HZ);   /* add some delay */    return 0;}/* * Called to update the host bridge after we've scanned each PCI device * and know what is possible. */voidpci_hwreinit (int port, pci_flags_t flags){    pcireg_t cmd;    /* note: this is not officially supported by sb1250, perhaps no effect! */    if (_pci_bus[0].fast_b2b) {	/* fast back-to-back is supported by all devices */	cmd = pci_conf_read32(SB1250_PCI_BRIDGE, PCI_COMMAND_STATUS_REG);	cmd &= (PCI_COMMAND_MASK << PCI_COMMAND_SHIFT);  /* preserve status */	cmd |= PCI_COMMAND_BACKTOBACK_ENABLE;	pci_conf_write32(SB1250_PCI_BRIDGE, PCI_COMMAND_STATUS_REG, cmd);    }    /* Latency timer, cache line size set by pci_setup_devices (pciconf.c) */    /* enable PCI read/write error interrupts */    /* XXX */}/* The following functions provide for device-specific setup required   during configuration.  There is nothing SiByte-specific about them,   and it would be better to do the packaging and registration in a   more modular way. */#if CFG_LDT#define	PCI_VENDOR_ALSC			0x14D9#define PCI_PRODUCT_ALSC_SP1011		0x0010#define PCI_PRODUCT_ALSC_AS90L10208	0x9000extern void sp1011_setup(pcitag_t tag, pci_flags_t flags);extern void as90l10208_setup(pcitag_t tag, pci_flags_t flags);#define	PCI_VENDOR_AMD			0x1022#define PCI_PRODUCT_PLX_HT7520		0x7450#define PCI_PRODUCT_PLX_HT7520_APIC	0x7451extern void ht7520apic_preset(pcitag_t tag);extern void ht7520apic_setup(pcitag_t tag);#define PCI_PRODUCT_AMD_8151            0x7454#endif /* CFG_LDT *//* Dispatch functions for device pre- and post-configuration hooks. *//* Called for each hostbridge, to discover and scan secondary buses */voidpci_businit_hostbridge (pcitag_t tag, pci_flags_t flags){}/* Called for each function prior to assigning PCI resources.  */intpci_device_preset (pcitag_t tag){    pcireg_t id;    int skip;    skip = 0;    id = pci_conf_read(tag, PCI_ID_REG);    switch (PCI_VENDOR(id)) {	case PCI_VENDOR_SIBYTE:	    /* Check for a host bridge seen internally, in which case	       we don't want to allocate any address space for its	       BARs. */	    if (tag == SB1250_PCI_BRIDGE)		skip = 1;	    break;#if CFG_LDT	case PCI_VENDOR_AMD:	    switch (PCI_PRODUCT(id)) {		case PCI_PRODUCT_PLX_HT7520_APIC:		    ht7520apic_preset (tag);		    break;		case PCI_PRODUCT_AMD_8151:		    skip = 1;		    break;		default:		    break;	    }	    break;#endif /* CFG_LDT */	default:	    break;    }    return skip;}/* Called for each non-bridge (Type 0) function after assigning the BAR   and InterruptLine (XXX check this) resources.. */voidpci_device_setup (pcitag_t tag){    pcireg_t id = pci_conf_read(tag, PCI_ID_REG);    switch (PCI_VENDOR(id)) {#if CFG_LDT	case PCI_VENDOR_AMD:	    if (PCI_PRODUCT(id) == PCI_PRODUCT_PLX_HT7520_APIC)		ht7520apic_setup (tag);	    break;#endif /* CFG_LDT */	default:	    break;    }}/* Called for each bridge (Type 1) function after configuring the   secondary bus, to allow device-specific initialization. */voidpci_bridge_setup (pcitag_t tag, pci_flags_t flags){    pcireg_t id = pci_conf_read(tag, PCI_ID_REG);    switch (PCI_VENDOR(id)) {#if CFG_LDT	case PCI_VENDOR_ALSC:	    switch (PCI_PRODUCT(id)) {		case PCI_PRODUCT_ALSC_SP1011:		    sp1011_setup (tag, flags);		    break;		case PCI_PRODUCT_ALSC_AS90L10208:		    as90l10208_setup (tag, flags);		    break;		default:		    break;	    }	    break;        case PCI_VENDOR_AMD:	    /* The PLX ht7520 requires configuration of the	       interrupt mapping, but it packages the IOAPIC as a	       separate function, registers of which will not yet have	       been initialized if the standard traversal order is	       followed.  See pci_device_setup above.  */	    break;#endif /* CFG_LDT */	default:	    break;    }}/* Machine dependent access primitives and utility functions */voidpci_flush (void){    /* note: this is a noop for the SB-1250. */}pcitag_tpci_make_tag (int port, int bus, int device, int function){    return SB1250_PCI_MAKE_TAG(bus, device, function);}voidpci_break_tag (pcitag_t tag,	       int *portp, int *busp, int *devicep, int *functionp){    if (portp) *portp = (tag >> 24) & PCI_PORTMAX;    if (busp) *busp = (tag >> 16) & PCI_BUSMAX;    if (devicep) *devicep = (tag >> 11) & PCI_DEVMAX;    if (functionp) *functionp = (tag >> 8) & PCI_FUNCMAX;}intpci_canscan (pcitag_t tag){    int port, bus, device, function;    pci_break_tag (tag, &port, &bus, &device, &function);     if (port > PCI_PORTMAX	|| bus > PCI_BUSMAX || device > PCI_DEVMAX || function > PCI_FUNCMAX)	return 0;    if (bus == 0) {	if (sb1250_in_device_mode) {	    /* Scan the LDT chain, but only the LDT host bridge on PCI. */	    if (device != 1)	        return 0;	}	if (sb1250_ldt_slave_mode || !sb1250_ldt_init) {	    /* Scan the PCI devices but not the LDT chain. */            if (device == 1)	        return 0;	}	if (device > 20) {	    /* Chip bug: asserts IDSEL for device 20 for all devices > 20. */	    return 0;	}    }    return 1;}intpci_probe_tag(pcitag_t tag){    physaddr_t addrp;    pcireg_t data;    if (!pci_canscan(tag))	return 0;    addrp = (physaddr_t) SB1250_CFG_ADDR(tag, PCI_ID_REG, 4);    /* An earlier version of this code cleared the MasterAbort and       TargetAbort bits in the PCI host bridge, did the read, and       looked for those bits to be set.  For the SB-1250, that's       inappropriate because	 - it's the wrong host bridge for devices behind LDT.	 - PCI host bridge registers aren't readable in Device mode.	 - it loses status if testing the PCI host bridge itself.       We rely on getting 0xffff when reading the vendor ID.  Note       that this still has side effects on the host bridge registers.    */    data = phys_read32(addrp);  /* device + vendor ID */    mips_wbflush();    /* if it returned all vendor id bits set, it's not a device */    return (PCI_VENDOR(data) != 0xFFFF);}/* Read/write access to PCI configuration registers.  For most   applications, pci_conf_read<N> and pci_conf_write<N> are deprecated   unless N = 32. */static pcireg_tpci_conf_readn(pcitag_t tag, int reg, int width){    physaddr_t addrp;    pcireg_t data;#if (PCI_DEBUG != 0)    int port, bus, device, function;    if (reg & (width-1) || reg < 0 || reg >= PCI_REGMAX) {	if (_pciverbose != 0)	    pci_tagprintf(tag, "pci_conf_readn: bad reg 0x%x\n", reg);	return 0;    }    pci_break_tag(tag, &port, &bus, &device, &function);     if (bus > PCI_BUSMAX || device > PCI_DEVMAX || function > PCI_FUNCMAX) {	if (_pciverbose != 0)	    pci_tagprintf(tag, "pci_conf_readn: bad tag 0x%x\n", tag);	return 0;    }#endif /* PCI_DEBUG */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -