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

📄 ixdp2400_pci.c

📁 基于ecos的redboot
💻 C
📖 第 1 页 / 共 3 页
字号:
        aligned_addr = (*addr_ext) << 29;
    }
    else
    {
        aligned_addr = (*base + size - 1) & ~(size - 1);
        // Update the resource pointer and return values.
        *base = aligned_addr + size;
    }

    return aligned_addr;
}

void cyg_hal_plf_pci_init(void)
{
    cyg_pci_device_id dev_id = CYG_PCI_NULL_DEVID;
	cyg_pci_device_id master_dev_id;
	cyg_uint8 next_bus = SECONDARY_BUS_NUM;
	int slave_found = 0;
	int sram_bar_mask_array[] = {0x1FC0000, 0x3FC0000, 0x7FC0000, 0xFFC0000};
	int dram_bar_mask_array[] = {0x7F00000, 0xFF00000, 0x1FF00000, 0x3FF00000};
	int sram_bar_size, dram_bar_size, sram_bar, dram_bar;

	display_led('P', 'C', 'I', 'I');

	// if there is no flash then pci init. is done by master. so don't do it again
	if(strap_options_val() & CFG_PROM_BOOT)
	{
		/* set the upper bits for pci mem and io transactions */
		*(PCI_ADDR_EXT_REG) = 0x0;
				
		/* Setup SRAM Base Address Mask Reg */
		sram_bar_size = (strap_options_val() & 0xC0) >> 6;
		*(SRAM_BASE_ADDR_MASK_REG) = sram_bar_mask_array[sram_bar_size];
		sram_bar = 0x2000000 * (1 << sram_bar_size);

		/* Setup SDRAM Base Address Mask Reg */
		dram_bar_size = (strap_options_val() & 0x30) >> 4;
		*(DRAM_BASE_ADDR_MASK_REG) = dram_bar_mask_array[dram_bar_size];
		dram_bar = 0x8000000 * (1 << dram_bar_size);

		if(strap_options_val() & CFG_PCI_BOOT_HOST)
		{
            CYG_PCI_ADDRESS64 pci_base = HAL_PCI_ALLOC_BASE_MEMORY;
            int addr_ext = 0;

			*(PCI_CMD_STAT_REG) = PCI_CMD_STAT_VAL;
			*(PCI_CSR_BAR_REG) = force_pci_alloc_mem(&pci_base, &addr_ext, 0x100000);
			*(PCI_SRAM_BAR_REG) = force_pci_alloc_mem(&pci_base, &addr_ext, sram_bar);
			*(PCI_DRAM_BAR_REG) = force_pci_alloc_mem(&pci_base, &addr_ext, dram_bar);
			cyg_pci_set_memory_base(pci_base, addr_ext);
		}

		/* enable outbound pci int. from xscale */
		*(PCI_OUT_INT_MASK_REG) &= XSIM;

		*(IXP_RESET0_REG) |= INIT_COMP;

		// if this is master npu then init bus
		if(strap_options_val() & CFG_PCI_BOOT_HOST)
		{
			// Initialize Primary PCI bus (bus 0)
			cyg_pci_configure_bus(0, &next_bus);

            // prepare dev_id so that we skip slave
			master_dev_id = CYG_PCI_DEV_MAKE_ID(0, CYG_PCI_DEV_MAKE_DEVFN(6, 0));
			cyg_pci_find_device(IXP2400_VENDOR_ID, IXP2400_DEVICE_ID, &master_dev_id);

			// first npu would be slave
			dev_id = CYG_PCI_NULL_DEVID;
			// configure slave npu
			if(cyg_pci_find_device(IXP2400_VENDOR_ID, IXP2400_DEVICE_ID, &dev_id))
			{
				if(dev_id != master_dev_id)
				{
					cyg_pci_get_device_info(dev_id, &slave_dev_info);
					slave_found = 1;
				}
			}
			
			if(slave_found)
			{
#ifndef DONT_INIT_SLAVE
				slave_ixp_init();
#else
                printf("Warning - Slave will remain in reset in single flash system\n");
#endif
			}
			else
			{
				printf("Can't find slave NPU\n");
			}
		}
		else
		{
			int i = 0;

			printf("Waiting for master to copy config data.");
			// wait till master copies the config data and assigns BAR
			while(board_config_data->config_valid != CONFIG_DATA_VALID)
			{
				if(i > 30)
				{
					printf("\nMaster hasn't copied the config data");
					break;
				}
				// wait for 1 sec.
				hal_delay_us(1000000);
				printf(".");
				i++;		
			}
			printf("\n");
		}
	}

    // setup non transparent bridge
    ntb_init();

}

// Use "naked" attribute to suppress C prologue/epilogue
static 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 *paddr;
    cyg_uint32 dev = CYG_PCI_DEV_GET_DEV(devfn);
    cyg_uint32 fn  = CYG_PCI_DEV_GET_FN(devfn);
	
	if(bus == PRIMARY_BUS_NUM)
	{
		paddr = (cyg_uint32 *)XSCALE_PCI_TYPE_0_CONFIG_BASE;
	}
	else
	{
		paddr = (cyg_uint32 *)XSCALE_PCI_TYPE_1_CONFIG_BASE;
	}

    /* Offsets must be dword-aligned */
    offset &= ~3;

	if(bus == PRIMARY_BUS_NUM)
	{ /* Type 0 config */
		(cyg_uint32)paddr |= ((1 << (dev + 16)) | (fn << 8) | offset | 0);
	}
	else
	{ /* Type 1 config */
		(cyg_uint32)paddr |= ((bus << 16) | (dev << 11) | (fn << 8) | offset | 0);
	}

	orig_abort_vec = ((volatile cyg_uint32 *)0x20)[4];
    ((volatile unsigned *)0x20)[4] = (unsigned)__pci_abort_handler;
    HAL_ICACHE_SYNC();

    return paddr;
}

static int clear_master_aborts(void)
{
	cyg_uint32 temp;
	int err = 0;

	temp = *(PCI_CONTROL_REG);
	if(temp & 0x120)
	{
		err = 1;
		*(PCI_CONTROL_REG) = temp;
	}
	temp = *(PCI_CMD_STAT_REG);
	if(temp & 0x20000000)
	{
		err = 1;
#ifdef A0_REV
		while(temp & 0x20000000)
		{
			*(PCI_CMD_STAT_REG) = temp;
			temp = *(PCI_CMD_STAT_REG);
		}
#else
		*(PCI_CMD_STAT_REG) = temp;
#endif
	}

	((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(clear_master_aborts())
		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;

	clear_master_aborts();
}


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(clear_master_aborts())
		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; 

	clear_master_aborts();
}

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(clear_master_aborts())
		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; 

	clear_master_aborts();
}

⌨️ 快捷键说明

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