P2020RDB-sata移植之U-BOOT篇

硬件确认OK后,U-BOOT应该可以看到预期的PCIE1控制器枚举到需要的设备

PCIe1: Root Complex of mini PCIe SLOT, x1, regs @ 0xffe0a000
  01:00.0     - 1095:3132 - Mass storage controller
PCIe1: Bus 00 - 01
PCIe2: Root Complex of PCIe SLOT, no link, regs @ 0xffe09000
PCIe2: Bus 02 - 02

U-BOOT是依靠头文件的宏配置,来确定初始化需要的基本信息的,不像内核要依赖设备树,所以U-BOOT对于硬件调试很重要。那么U-BOOT是如何枚举到PCIE1下面的sata控制器的呢。

首先看一下函数调用路线

board_init_r(board.c)

--->pci_init(drivers/pci/pci.c)

--->pci_init_board(boar/freescale/p1_p2_rdb/pci.c)

--->fsl_pcie_init_board(drivers/pci/fsl_pci_init.c)

--->fsl_pcie_init_ctrl(drivers/pci/fsl_pci_init.c)

-->fsl_configure_pcie(drivers/pci/fsl_pci_init.c)

关键的调用是fsl_pcie_init_ctrlfsl_configure_pcie

重点看一下这两个函数

int fsl_pcie_init_board(int busno)
{
	struct fsl_pci_info pci_info;
	ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC8xxx_GUTS_ADDR;
	u32 devdisr;
	u32 *addr;

#ifdef CONFIG_SYS_FSL_QORIQ_CHASSIS2
	addr = &gur->devdisr3;
#else
	addr = &gur->devdisr;
#endif
	devdisr = in_be32(addr);

#ifdef CONFIG_PCIE1
	SET_STD_PCIE_INFO(pci_info, 1);
	busno = fsl_pcie_init_ctrl(busno, devdisr, PCIE1, &pci_info);
#else
	setbits_be32(addr, _DEVDISR_PCIE1); /* disable */
#endif

#ifdef CONFIG_PCIE2
	SET_STD_PCIE_INFO(pci_info, 2);
	busno = fsl_pcie_init_ctrl(busno, devdisr, PCIE2, &pci_info);
#else
	setbits_be32(addr, _DEVDISR_PCIE2); /* disable */
#endif

#ifdef CONFIG_PCIE3
	SET_STD_PCIE_INFO(pci_info, 3);
	busno = fsl_pcie_init_ctrl(busno, devdisr, PCIE3, &pci_info);
#else
	setbits_be32(addr, _DEVDISR_PCIE3); /* disable */
#endif

#ifdef CONFIG_PCIE4
	SET_STD_PCIE_INFO(pci_info, 4);
	busno = fsl_pcie_init_ctrl(busno, devdisr, PCIE4, &pci_info);
#else
	setbits_be32(addr, _DEVDISR_PCIE4); /* disable */
#endif

 	return busno;
}

可以看到如果有需要的话,会对每个PCIE控制器进行初始化设置,

设置的开始首先是设定PCI控制器的基本寄存器位置,这些位置在U-BOOT里通过头文件宏来提供,linux使用DTB获取。

看一下宏SET_STD_PCIE_INFO就一目了然了

#define SET_STD_PCIE_INFO(x, num) \
{			\
	x.regs = CONFIG_SYS_PCIE##num##_ADDR;	\
	x.mem_bus = CONFIG_SYS_PCIE##num##_MEM_BUS; \
	x.mem_phys = CONFIG_SYS_PCIE##num##_MEM_PHYS; \
	x.mem_size = CONFIG_SYS_PCIE##num##_MEM_SIZE; \
	x.io_bus = CONFIG_SYS_PCIE##num##_IO_BUS; \
	x.io_phys = CONFIG_SYS_PCIE##num##_IO_PHYS; \
	x.io_size = CONFIG_SYS_PCIE##num##_IO_SIZE; \
	x.law = LAW_TRGT_IF_PCIE_##num; \
	x.pci_num = num; \
}


U-BOOT获取了相应的寄存器位置后,就会配置对应的PCIE控制器

int fsl_pcie_init_ctrl(int busno, u32 devdisr, enum srds_prtcl dev,
			struct fsl_pci_info *pci_info)
{
	struct pci_controller *hose;
	int num = dev - PCIE1;

	hose = calloc(1, sizeof(struct pci_controller));
	if (!hose)
		return busno;

	if (is_serdes_configured(dev) && !(devdisr & devdisr_mask[num])) {
		busno = fsl_configure_pcie(pci_info, hose,
				board_serdes_name(dev), busno);
	} else {
		printf("PCIe%d: disabled\n", num + 1);
	}

	return busno;
}

端口硬件禁能的会输出printf("PCIe%d: disabled\n", num + 1);

硬件使能的,开始fsl_configure_pcie枚举控制器

int fsl_configure_pcie(struct fsl_pci_info *info,
			struct pci_controller *hose,
			const char *connected, int busno)
{
	int is_endpoint;

	set_next_law(info->mem_phys, law_size_bits(info->mem_size), info->law);
	set_next_law(info->io_phys, law_size_bits(info->io_size), info->law);

	is_endpoint = fsl_setup_hose(hose, info->regs);
	printf("PCIe%u: %s", info->pci_num,
		is_endpoint ? "Endpoint" : "Root Complex");
	if (connected)
		printf(" of %s", connected);
	puts(", ");

	return fsl_pci_init_port(info, hose, busno);
}

函数的最后调用,枚举总线。

fsl_pci_init_port

->fsl_pci_init

->pci_hose_scan_bus

int pci_hose_scan_bus(struct pci_controller *hose, int bus)
{
	unsigned int sub_bus, found_multi = 0;
	unsigned short vendor, device, class;
	unsigned char header_type;
#ifndef CONFIG_PCI_PNP
	struct pci_config_table *cfg;
#endif
	pci_dev_t dev;
#ifdef CONFIG_PCI_SCAN_SHOW
	static int indent = 0;
#endif

	sub_bus = bus;

	for (dev =  PCI_BDF(bus,0,0);
	     dev <  PCI_BDF(bus, PCI_MAX_PCI_DEVICES - 1,
				PCI_MAX_PCI_FUNCTIONS - 1);
	     dev += PCI_BDF(0, 0, 1)) {

		if (pci_skip_dev(hose, dev))
			continue;

		if (PCI_FUNC(dev) && !found_multi)
			continue;

		pci_hose_read_config_byte(hose, dev, PCI_HEADER_TYPE, &header_type);

		pci_hose_read_config_word(hose, dev, PCI_VENDOR_ID, &vendor);

		if (vendor == 0xffff || vendor == 0x0000)
			continue;

		if (!PCI_FUNC(dev))
			found_multi = header_type & 0x80;

		debug("PCI Scan: Found Bus %d, Device %d, Function %d\n",
			PCI_BUS(dev), PCI_DEV(dev), PCI_FUNC(dev));

		pci_hose_read_config_word(hose, dev, PCI_DEVICE_ID, &device);
		pci_hose_read_config_word(hose, dev, PCI_CLASS_DEVICE, &class);

#ifdef CONFIG_PCI_SCAN_SHOW
		indent++;

		/* Print leading space, including bus indentation */
		printf("%*c", indent + 1, ' ');

		if (pci_print_dev(hose, dev)) {
			printf("%02x:%02x.%-*x - %04x:%04x - %s\n",
			       PCI_BUS(dev), PCI_DEV(dev), 6 - indent, PCI_FUNC(dev),
			       vendor, device, pci_class_str(class >> 8));
		}
#endif

#ifdef CONFIG_PCI_PNP
		sub_bus = max(pciauto_config_device(hose, dev), sub_bus);
#else
		cfg = pci_find_config(hose, class, vendor, device,
				      PCI_BUS(dev), PCI_DEV(dev), PCI_FUNC(dev));
		if (cfg) {
			cfg->config_device(hose, dev, cfg);
			sub_bus = max(sub_bus, hose->current_busno);
		}
#endif

#ifdef CONFIG_PCI_SCAN_SHOW
		indent--;
#endif

		if (hose->fixup_irq)
			hose->fixup_irq(hose, dev);
	}

	return sub_bus;
}







  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值