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

📄 iq80310_pci.c

📁 Intel XScale PXA255 引导Linux的Redboot 版bootloader源代码!
💻 C
字号:
//==========================================================================////      iq80310_pci.c////      HAL board support code for XScale IQ80310 PCI////==========================================================================//####COPYRIGHTBEGIN####//                                                                          // -------------------------------------------                              // The contents of this file are subject to the Red Hat eCos Public License // Version 1.1 (the "License"); you may not use this file except in         // compliance with the License.  You may obtain a copy of the License at    // http://www.redhat.com/                                                   //                                                                          // Software distributed under the License is distributed on an "AS IS"      // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the // License for the specific language governing rights and limitations under // the License.                                                             //                                                                          // The Original Code is eCos - Embedded Configurable Operating System,      // released September 30, 1998.                                             //                                                                          // The Initial Developer of the Original Code is Red Hat.                   // Portions created by Red Hat are                                          // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.                             // All Rights Reserved.                                                     // -------------------------------------------                              //                                                                          //####COPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s):    msalter// Contributors: msalter// Date:         2000-10-10// Purpose:      PCI support// Description:  Implementations of HAL PCI interfaces////####DESCRIPTIONEND####////========================================================================*/#include <pkgconf/hal.h>#include <pkgconf/system.h>#include CYGBLD_HAL_PLATFORM_H#include CYGHWR_MEMORY_LAYOUT_H#include <cyg/infra/cyg_type.h>         // base types#include <cyg/infra/cyg_trac.h>         // tracing macros#include <cyg/infra/cyg_ass.h>          // assertion macros#include <cyg/hal/hal_io.h>             // IO macros#include <cyg/hal/hal_if.h>             // calling interface API#include <cyg/hal/hal_arch.h>           // Register state info#include <cyg/hal/hal_diag.h>#include <cyg/hal/hal_intr.h>           // Interrupt names#include <cyg/hal/hal_cache.h>#include <cyg/hal/hal_iq80310.h>        // Hardware definitions#include <cyg/io/pci_hw.h>#include <cyg/io/pci.h>static cyg_uint8 pbus_nr;static cyg_uint8 sbus_nr;void cyg_hal_plf_pci_init(void){    cyg_uint32 limit_reg, adj_dram_size;    cyg_uint8  next_bus;    // Initialize Secondary PCI bus (bus 1)    *(volatile cyg_uint16 *)BCR_ADDR |= 0x40;  // reset secondary bus    hal_delay_us(10 * 1000); 	// 10ms enough??    *(volatile cyg_uint16 *)BCR_ADDR &= ~0x40;  // release reset    // *********  vendor / device id **********    *(cyg_uint16 *)ASVIR_ADDR = 0x113C;    *(cyg_uint16 *)ASIR_ADDR = 0x0700;    // suppress secondary bus idsels to provide private secondary devices    *(cyg_uint16 *)SISR_ADDR = 0x03FF;    // ******* Primary Inbound ATU *********    // set primary inbound ATU translate value register to point to    // base of local DRAM    *(cyg_uint32 *)PIATVR_ADDR = MEMBASE_DRAM & 0xFFFFFFFC;    // set primary inbound ATU limit register to include all of installed DRAM.    // This value used as a mask.    adj_dram_size = hal_dram_size;    limit_reg = (0xFFFFFFFF-(adj_dram_size-1)) & 0xFFFFFFF0;    *(cyg_uint32 *)PIALR_ADDR = limit_reg;    if (iq80310_is_host()) {	// set the primary inbound ATU base address to the start of DRAM	*(cyg_uint32 *)PIABAR_ADDR = MEMBASE_DRAM & 0xFFFFF000;	// ********* Set Primary Outbound Windows *********	// Note: The primary outbound ATU memory window value register	//       and i/o window value registers are defaulted to 0	// set the primary outbound windows to directly map Local - PCI        // requests	// outbound memory window	*(cyg_uint32 *)POMWVR_ADDR = PRIMARY_MEM_BASE;	// outbound DAC Window	*(cyg_uint32 *)PODWVR_ADDR = PRIMARY_DAC_BASE;	// outbound I/O window        *(cyg_uint32 *)POIOWVR_ADDR = PRIMARY_IO_BASE;	    }    // clear RETRY    *(cyg_uint16 *)EBCR_ADDR = 0x0008;    // ******** Secondary Inbound ATU ***********    // set secondary inbound ATU translate value register to point to base    // of local DRAM    *(cyg_uint32 *)SIATVR_ADDR = MEMBASE_DRAM & 0xFFFFFFFC;    // set secondary inbound ATU base address to start of DRAM    *(cyg_uint32 *)SIABAR_ADDR = MEMBASE_DRAM & 0xFFFFF000;    // set secondary inbound ATU limit register to include all of    // installed DRAM. This value used as a mask.    //  always allow secondary pci access to all memory (even with A0 step)    limit_reg = (0xFFFFFFFF - (adj_dram_size - 1)) & 0xFFFFFFF0;    *(cyg_uint32 *)SIALR_ADDR = limit_reg;    // ********** Set Secondary Outbound Windows ***********    // Note: The secondary outbound ATU memory window value register    // and i/o window value registers are defaulted to 0    // set the secondary outbound window to directly map Local - PCI requests    // outbound memory window    *(cyg_uint32 *)SOMWVR_ADDR = SECONDARY_MEM_BASE;    // outbound DAC Window    *(cyg_uint32 *)SODWVR_ADDR = SECONDARY_DAC_BASE;    // outbound I/O window    *(cyg_uint32 *)SOIOWVR_ADDR = SECONDARY_IO_BASE;    // ***********  command / config / latency registers  ************    if (iq80310_is_host()) {	// allow primary ATU to act as a bus master, respond to PCI 	// memory accesses, assert P_SERR#, and enable parity checking	*(cyg_uint16 *)PATUCMD_ADDR = (CYG_PCI_CFG_COMMAND_SERR   | \				       CYG_PCI_CFG_COMMAND_PARITY | \				       CYG_PCI_CFG_COMMAND_MASTER | \				       CYG_PCI_CFG_COMMAND_MEMORY);    }    // allow secondary ATU to act as a bus master, respond to PCI memory    // accesses, and assert S_SERR#    *(cyg_uint16 *)SATUCMD_ADDR = (CYG_PCI_CFG_COMMAND_SERR   | \				   CYG_PCI_CFG_COMMAND_PARITY | \				   CYG_PCI_CFG_COMMAND_MASTER | \				   CYG_PCI_CFG_COMMAND_MEMORY);    // enable primary and secondary outbound ATUs, BIST, and primary bus    // direct addressing    *(cyg_uint32 *)ATUCR_ADDR = 0x00000006;    // ************ bridge registers *******************    if (iq80310_is_host()) {	// set the bridge command register	*(cyg_uint16 *)PCR_ADDR = (CYG_PCI_CFG_COMMAND_SERR   | \				   CYG_PCI_CFG_COMMAND_PARITY | \				   CYG_PCI_CFG_COMMAND_MASTER | \				   CYG_PCI_CFG_COMMAND_MEMORY);	// set the secondary bus number to 1	*(cyg_uint8 *)SBNR_ADDR = SECONDARY_BUS_NUM;	*(cyg_uint16 *)BCR_ADDR = 0x0823;	// set the primary bus number to 0	*(cyg_uint8 *)PBNR_ADDR = PRIMARY_BUS_NUM;    } else {	// Wait for PC BIOS to initialize bus number	int i;	for (i = 0; i < 15000; i++) {	    if (*((volatile cyg_uint8 *)SBNR_ADDR) != 0)		break;	    hal_delay_us(1000);  // 1msec	}	if (*((volatile cyg_uint8 *)SBNR_ADDR) == 0)	    *(cyg_uint8 *)SBNR_ADDR = SECONDARY_BUS_NUM;    }    pbus_nr = *(cyg_uint8 *)PBNR_ADDR;    sbus_nr = *(cyg_uint8 *)SBNR_ADDR;    // Now initialize the PCI busses.    // Next assignable bus number. Yavapai primary bus is fixed as    // bus zero and yavapai secondary is fixed as bus 1.    next_bus = sbus_nr + 1;    // If we are the host on the Primary bus, then configure it.    if (iq80310_is_host()) {	// Initialize Primary PCI bus (bus 0)	cyg_pci_set_memory_base(PRIMARY_MEM_BASE);	cyg_pci_set_io_base(PRIMARY_IO_BASE);	cyg_pci_configure_bus(0, &next_bus);    }    // Initialize Secondary PCI bus (bus 1)    cyg_pci_set_memory_base(SECONDARY_MEM_BASE);    cyg_pci_set_io_base(SECONDARY_IO_BASE);    cyg_pci_configure_bus(sbus_nr, &next_bus);    // clear RETRY    *(cyg_uint16 *)EBCR_ADDR = 0x0008;}void cyg_hal_plf_pci_config_setup( cyg_uint32 bus,				   cyg_uint32 devfn,				   cyg_uint32 offset){}// Use "naked" attribute to suppress C prologue/epiloguestatic void __attribute__ ((naked)) __pci_abort_handler(void) {    asm ( "subs	pc, lr, #4\n" );}static cyg_uint32 orig_abort_vec;static inline cyg_uint32 *pci_config_setup(cyg_uint32 bus,					   cyg_uint32 devfn,					   cyg_uint32 offset){    cyg_uint32 *pdata, *paddr;    cyg_uint32 dev = CYG_PCI_DEV_GET_DEV(devfn);    cyg_uint32 fn  = CYG_PCI_DEV_GET_FN(devfn);    if (bus == 0) {        paddr = (cyg_uint32 *)POCCAR_ADDR;        pdata = (cyg_uint32 *)POCCDR_ADDR;    } else {        paddr = (cyg_uint32 *)SOCCAR_ADDR;        pdata = (cyg_uint32 *)SOCCDR_ADDR;    }    /* Offsets must be dword-aligned */    offset &= ~3;	    /* Primary or secondary bus use type 0 config */    /* all others use type 1 config */    if (bus == pbus_nr || bus == sbus_nr)	*paddr = ( (1 << (dev + 16)) | (fn << 8) | offset | 0 );    else        *paddr = ( (bus << 16) | (dev << 11) | (fn << 8) | offset | 1 );    orig_abort_vec = ((volatile cyg_uint32 *)0x20)[4];    ((volatile unsigned *)0x20)[4] = (unsigned)__pci_abort_handler;    HAL_ICACHE_SYNC();    return pdata;}static inline int pci_config_cleanup(cyg_uint32 bus){    cyg_uint32 status = 0, err = 0;    if (bus == pbus_nr) {	status = *(cyg_uint16 *) PATUSR_ADDR;	if ((status & 0xF900) != 0) {	    err = 1;	    *(cyg_uint16 *)PATUSR_ADDR = status & 0xF980;	}	status = *(cyg_uint16 *) PSR_ADDR;	if ((status & 0xF900) != 0) {	    err = 1;	    *(cyg_uint16 *)PSR_ADDR = status & 0xF980;	}	status = *(cyg_uint32 *) PATUISR_ADDR;	if ((status & 0x79F) != 0) {	    err = 1;	    *(cyg_uint32 *) PATUISR_ADDR = status & 0x79f;	}	status = *(cyg_uint32 *) PBISR_ADDR;	if ((status & 0x3F) != 0) {	    err = 1;	    *(cyg_uint32 *) PBISR_ADDR = status & 0x3F;	}    } else {	status = *(cyg_uint16 *) SATUSR_ADDR;	if ((status & 0xF900) != 0) {	    err = 1;	    *(cyg_uint16 *) SATUSR_ADDR = status & 0xF900;	}	status = *(cyg_uint16 *) SSR_ADDR;	if ((status & 0xF900) != 0) {	    err = 1;	    *(cyg_uint16 *) SSR_ADDR = status & 0xF980;	}	status = *(cyg_uint32 *) SATUISR_ADDR;	if ((status & 0x69F) != 0) {	    err = 1;	    *(cyg_uint32 *) SATUISR_ADDR = status & 0x69F;	}    }    ((volatile unsigned *)0x20)[4] = orig_abort_vec;    HAL_ICACHE_SYNC();    return err;}cyg_uint32 cyg_hal_plf_pci_cfg_read_dword (cyg_uint32 bus,					   cyg_uint32 devfn,					   cyg_uint32 offset){    cyg_uint32 *pdata, config_data;    pdata = pci_config_setup(bus, devfn, offset);    config_data = *pdata;    if (pci_config_cleanup(bus))      return 0xffffffff;    else      return config_data;}void cyg_hal_plf_pci_cfg_write_dword (cyg_uint32 bus,				      cyg_uint32 devfn,				      cyg_uint32 offset,				      cyg_uint32 data){    cyg_uint32 *pdata;    pdata = pci_config_setup(bus, devfn, offset);    *pdata = data;    pci_config_cleanup(bus);}cyg_uint16 cyg_hal_plf_pci_cfg_read_word (cyg_uint32 bus,					  cyg_uint32 devfn,					  cyg_uint32 offset){    cyg_uint32 *pdata;    cyg_uint16 config_data;    pdata = pci_config_setup(bus, devfn, offset);    config_data = (cyg_uint16)(((*pdata) >> ((offset % 0x4) * 8)) & 0xffff);    if (pci_config_cleanup(bus))      return 0xffff;    else      return config_data;}void cyg_hal_plf_pci_cfg_write_word (cyg_uint32 bus,				     cyg_uint32 devfn,				     cyg_uint32 offset,				     cyg_uint16 data){    cyg_uint32 *pdata, mask, temp;    pdata = pci_config_setup(bus, devfn, offset);    mask = ~(0x0000ffff << ((offset % 0x4) * 8));    temp = (cyg_uint32)(((cyg_uint32)data) << ((offset % 0x4) * 8));    *pdata = (*pdata & mask) | temp;     pci_config_cleanup(bus);}cyg_uint8 cyg_hal_plf_pci_cfg_read_byte (cyg_uint32 bus,					 cyg_uint32 devfn,					 cyg_uint32 offset){    cyg_uint32 *pdata;    cyg_uint8 config_data;    pdata = pci_config_setup(bus, devfn, offset);    config_data = (cyg_uint8)(((*pdata) >> ((offset % 0x4) * 8)) & 0xff);    if (pci_config_cleanup(bus))	return 0xff;    else	return config_data;}void cyg_hal_plf_pci_cfg_write_byte (cyg_uint32 bus,				     cyg_uint32 devfn,				     cyg_uint32 offset,				     cyg_uint8 data){    cyg_uint32 *pdata, mask, temp;    pdata = pci_config_setup(bus, devfn, offset);    mask = ~(0x000000ff << ((offset % 0x4) * 8));    temp = (cyg_uint32)(((cyg_uint32)data) << ((offset % 0x4) * 8));    *pdata = (*pdata & mask) | temp;     pci_config_cleanup(bus);}

⌨️ 快捷键说明

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