NXP

P2020RDB-sata移植之U-BOOT篇

2019-07-12 12:22发布

硬件确认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 ", num + 1); } return busno; }
端口硬件禁能的会输出printf("PCIe%d: disabled ", 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 ", 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 ", 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; }