I have code, called from the probe() function of my PCIe driver (loosely based on this post):
EDIT: Based on Andreas Bombe's response, I changed the code to use pci_iomap()
, but I'm still experience the system hang
static my_pci_dev pci_dev; /* local structure */
static int pci_setup_region(struct pci_dev *dev)
{
int bar = 0;
pci_dev.physical.addr = pci_resource_start(dev, bar);
pci_dev.physical.size = pci_resource_len(dev, bar);
pci_dev.virtual.addr = pci_iomap(dev, bar, pci_dev.physical.size);
if (NULL == pci_dev.virtual.addr) {
return -ENOMEM;
} else {
pci_dev.virtual.size = pci_dev.physical.size;
}
printk(KERN_ALERT "Virtual address: %p", pci_dev.virtual.addr);
if (request_mem_region(pci_dev.physical.addr, pci_dev.physical.size, DEVICE_NAME) == NULL) {
pci_release_resources();
return -EBUSY;
} else {
pci_dev.physical.allocated = 1;
}
/* Test it out! */
printk(KERN_ALERT "Trying to read data.\n");
printk(KERN_ALERT "Copied chip-id data:%08x", ioread8(pci_dev.virtual.addr));
return 0;
}
But the kernel just hangs at the call to ioread8()
.
Am I doing something wrong? Or do I need to look to hardware?
Here is the output on a clean boot of the system for lspci -v
and cat /proc/iomem
:
root@socfpga:~# lspci -v
00:00.0 PCI bridge: Altera Corporation Device e000 (rev 01) (prog-if 00 [Normal decode])
Flags: fast devsel
Bus: primary=00, secondary=01, subordinate=01, sec-latency=0
I/O behind bridge: 00000000-00000fff
Memory behind bridge: c0000000-c00fffff
Prefetchable memory behind bridge: 00000000-000fffff
Capabilities: [50] MSI: Enable- Count=1/4 Maskable- 64bit+
Capabilities: [78] Power Management version 3
Capabilities: [80] Express Root Port (Slot-), MSI 00
Capabilities: [100] Virtual Channel
Capabilities: [200] Vendor Specific Information: ID=1172 Rev=0 Len=044 <?>
01:00.0 Multimedia audio controller: Altera Corporation Device e002 (rev 01)
Subsystem: Altera Corporation Device e002
Flags: fast devsel, IRQ 75
Memory at c0000000 (32-bit, non-prefetchable) [disabled] [size=128K]
Capabilities: [50] MSI: Enable- Count=1/4 Maskable- 64bit+
Capabilities: [78] Power Management version 3
Capabilities: [80] Express Endpoint, MSI 00
Capabilities: [100] Virtual Channel
Capabilities: [200] Vendor Specific Information: ID=1172 Rev=0 Len=044 <?>
Kernel modules: test-pci
The memory comes up [disabled]
: do I have to enable it?
root@socfpga:~# cat /proc/iomem
00000000-3fffffff : System RAM
00008000-006fa7d3 : Kernel code
00754000-007d8c23 : Kernel data
c0000000-cfffffff : ALTERA PCIE RP MEM
c0000000-c00fffff : PCI Bus 0000:01
c0000000-c001ffff : 0000:01:00.0
d0000000-dfffffff : ALTERA PCIE RP PREF MEM
ff200000-ff20000f : csr
ff200010-ff20008f : vector_slave
ff210000-ff21003f : ff210000.chipidbridge0
ff280000-ff283fff : Cra
ff702000-ff703fff : /soc/ethernet@ff702000
ff704000-ff704fff : /soc/dwmmc0@ff704000
ff705000-ff705fff : ff705000.spi
ffa00000-ffa00fff : ff705000.spi
ffb40000-ffb4fffe : /soc/usb@ffb40000
ffc00000-ffc00fff : c_can_platform
ffc02000-ffc0201f : serial
ffc04000-ffc04fff : /soc/i2c@ffc04000
ffd02000-ffd02fff : /soc/wd@ffd02000
ffe01000-ffe01fff : /soc/amba/pdma@ffe01000
fff00000-fff00fff : fff00000.spi
ffff0000-ffffffff : /soc/sram@ffff0000
root@socfpga:~#
You definitely have to enable it. These are the basic steps:
pci_enable_device(dev);
pci_request_regions(dev, "driver/device name");
bar0 = pci_iomap(dev, 0, 0);
x = ioread(bar0 + offset); /* there you are */
Error checking is required for all the pci_*
calls. If the device needs to do DMA you also need to call pci_set_master
and pci_set_dma_mask
.
To elaborate, bypassing the PCI kernel code and directly ioremapping the BARs may have worked a long time ago. I'm not sure if it is even legal anymore in current code but it certainly isn't advisable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With