本帖最后由 devhuan 于 2015-1-14 10:43 编辑
大家好,我们在调试飞思卡尔的4in1编码器TW6865时遇到了难以解决的问题,希望大家给个意见和帮助; 在通过
内核中 System Type->Freescale MXC Implementations下的PCI Express选项
PCI Express support
[ ] PCI Express EP mode in the IMX6 RC/EP interconnection system [ ] PCI Express RC mode in the IMX6 RC/EP interconnection system 在内核中通过补丁pcie_cap_patch.patch 向kernel中添加TW6865相关的驱动和配置;并在内核的选项选上tw68系列的encoder的编码器 <*> Multimedia support --->
Video capture adapters --->
Encoders, decoders, sensors and other helper chips ---> <*> pcie TW68 video encoder 启动之后,我们的log中可以看到pcie可以link up,也就是说link上pcie; PMU: registered new PMU device of type 0 Static Power Management for Freescale i.MX6 wait mode is enabled for i.MX6 cpaddr = c0880000 suspend_iram_base=c091c000 PM driver module loaded iMX6 PCIe PCIe RC mode imx_pcie_pltfm_probe entering. PCIE: imx_pcie_pltfm_probe start link up. IMX PCIe port: link up. PCI: bus0: Fast back to back transfers disabled liutest start fixup imx6dq pcie tw6869 pci 0000:01:00.0: Setting PCI class for tw6868 PCIe device liutest END fixup imx6dq pcie tw6869 PCI: bus1: Fast back to back transfers disabled pci 0000:00:00.0: BAR 0: assigned [mem 0x01000000-0x010fffff 64bit pref] pci 0000:00:00.0: BAR 0: set to [mem 0x01000000-0x010fffff 64bit pref] (PCI address [0x1000000-0x10fffff]) pci 0000:00:00.0: BAR 9: assigned [mem 0x01100000-0x011fffff pref] pci 0000:00:00.0: BAR 6: assigned [mem 0x01200000-0x0120ffff pref] pci 0000:01:00.0: BAR 0: assigned [mem 0x01100000-0x01100fff pref] pci 0000:01:00.0: BAR 0: set to [mem 0x01100000-0x01100fff pref] (PCI address [0x1100000-0x1100fff]) pci 0000:00:00.0: PCI bridge to [bus 01-01] pci 0000:00:00.0: bridge window [io disabled] pci 0000:00:00.0: bridge window [mem disabled] pci 0000:00:00.0: bridge window [mem 0x01100000-0x011fffff pref] liutest PCI: r->start =0x1000000 r->end =0x10fffff IMX usb wakeup probe add wake up source irq 75 IMX usb wakeup probe 从这段log中可以看到pcie在探测插槽上的设备时是找到了设备的,并且成功连接,但是我们在这之后,CPU却在运行到如下log的地方停住了; ....... ARC USBOTG Device Controller driver (1 August 2005) mousedev: PS/2 mouse device common for all mice i2c-core: driver [isl29023] using legacy suspend method i2c-core: driver [isl29023] using legacy resume method snvs_rtc snvs_rtc.0: rtc core: registered snvs_rtc as rtc0 i2c /dev entries driver Linux video capture interface: v2.00 TW6868_: v4l2 driver version 2.0.1 loaded PCI register init called //【死在了这里,没有继续往下启动了】 跟踪内核中的运行到函数__pci_enable_device_flags(struct pci_dev *dev,resource_size_t flags)时在里面调用函数pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr);时没有返回一直停留在这个函数里面了,但是CPU没有”死掉“,就是停在里面了,因为在我注释掉这个函数之后,程序可以正确的跑到printk(KERN_INFO "pos 4 : after PCI register init called\n");函数; File:pci.c static int __pci_enable_device_flags(struct pci_dev *dev,resource_size_t flags) { int err; int i, bars = 0; /* * Power state could be unknown at this point, either due to a fresh * boot or a device removal call. So get the current power state * so that things like MSI message writing will behave as expected * (e.g. if the device really is in D0 at enable time). */ if (dev->pm_cap) { u16 pmcsr; // add by huan.gong @ 2015-01-13 printk(KERN_INFO "pos 3 : after PCI register init called\n"); pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr); dev->current_state = (pmcsr & PCI_PM_CTRL_STATE_MASK); } // add by huan.gong @ 2015-01-13 printk(KERN_INFO "pos 4 : after PCI register init called\n"); if (atomic_add_return(1, &dev->enable_cnt) > 1) { // add by huan.gong @ 2015-01-13 printk(KERN_INFO "pos 5 : after PCI register init called\n"); return 0; /* already enabled */ }
之后我又跟踪了函数pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr);内联函数 static inline int pci_read_config_word(struct pci_dev *dev, int where, u16 *val) { return pci_bus_read_config_word(dev->bus, dev->devfn, where, val); } EXPORT_SYMBOL(pci_bus_read_config_word); 为了提高性能这个函数最终的实现时宏 #define PCI_OP_READ(size,type,len) \ int pci_bus_read_config_##size \ (struct pci_bus *bus, unsigned int devfn, int pos, type *value) \ { \ int res; \ unsigned long flags; \ u32 data = 0; \ if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \ printk(KERN_INFO "::::lock irq\n");\ raw_spin_lock_irqsave(&pci_lock, flags); \ printk(KERN_INFO "::::read before\n");\ res = bus->ops->read(bus, devfn, pos, len, &data); \ printk(KERN_INFO "::::read after\n");\ *value = (type)data; \ raw_spin_unlock_irqrestore(&pci_lock, flags); \ printk(KERN_INFO "::::unlock irq\n");\ return res; \ } 最终,cpu是挂在了第39行的read函数里面,而这个是一个函数指针,是在驱动开发的过程中通过.read = XXXX()来指定的,如果结合我们前面分析的那部分应该是read(dev->bus, dev->devfn,dev->pm_cap + PCI_PM_CTRL,&pmcsr)其中dev就是pcie设备;也就是说在读取pcie的PCI_PM_CTRL控制字(16bit)时进去就没能出来,而原本读出来是要存入pmcsr的。
通过测试我们还看到了其他的log,在“挂起”之前,也有调用这个函数,只不过传进来的位置和要读取的长度不一样而已。 这可能是目前遇到的最难处理的问题,也不知道如何下手去处理,我们前期功能验证和测试的时候用的是成都嵌智捷科技的板子,后来我们的工程师开发的定制的板子,嵌智捷的板子上我们没有测试过PCIE,希望有相关经验的来帮忙分析一些,不胜感激.....提前来个万分感谢....
|