blob: 288ab2281ef418314f093305cda0d9d9e9725e5e (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
|
@page page_device_pci_ofw PCI and device tree
# PCI Open Firmware integration
Implementation: **`components/drivers/pci/ofw.c`**. Requires **`RT_USING_OFW`**.
Host controllers probe as **platform** devices; this file connects enumerated **`rt_pci_device`** instances to DT **`ranges`** and **INTx** routing.
---
## INTx: `pci_ofw_irq_parse`
Resolves **legacy PCI INTx**:
1. Device node has **`interrupts`** → **`rt_ofw_parse_irq_cells`**
2. Else read **`INTPIN`** from config; **`pin == 0`** → **`-RT_ENOSYS`**
3. Walk bus tree:
- Device-local **`interrupt-map`** if present
- Else P2P bridge or **host bridge** node → **`rt_ofw_parse_irq_map`** with key:
```text
map_addr[0] = (bus->number << 16) | (devfn << 8)
map_addr[3] = swizzled INTx pin /* rt_pci_irq_intx */
```
Missing **`interrupt-map`** on root → **`-RT_EEMPTY`** (logged).
---
## `rt_pci_ofw_irq_parse_and_map`
```c
int rt_pci_ofw_irq_parse_and_map(struct rt_pci_device *pdev,
rt_uint8_t slot, rt_uint8_t pin);
```
Calls **`pci_ofw_irq_parse`**, then **`rt_ofw_map_irq`**. Sets **`pdev->intx_pic`** from **`rt_ofw_data(irq_args.data)`**.
Host bridge may wire **`host_bridge->irq_map`** to this helper during init.
---
## `ranges` parsing
**`pci_ofw_parse_ranges`** / **`rt_pci_ofw_parse_ranges`**:
- Decodes PCI address **`space_code`** (config / I/O / 32-bit mem / 64-bit mem)
- Fills **`host_bridge->bus_regions`**: CPU phys, PCI bus addr, size, prefetch flags
- Used before **`rt_pci_region_setup`**
**`rt_pci_ofw_host_bridge_init`**, **`rt_pci_ofw_bus_init`**, **`rt_pci_ofw_device_init`** — per-node OFW hooks during probe.
---
## DT artifacts
| Property | Use |
| --- | --- |
| Host **`compatible`** | Select host driver (@ref page_device_pci_host) |
| **`reg`** | ECAM MMIO |
| **`ranges` / `dma-ranges`** | MEM/IO windows |
| **`interrupt-map` / `interrupt-map-mask`** | INTx → PIC |
| Endpoint **`reg`** (optional) | Direct **`interrupts`** on slot |
BAR values still come from config space after enumeration.
---
## MSI/MSI-X
MSI message address/data from **PIC** (**`pdev->msi_pic`**), not **`interrupts`** cells. Ensure PIC/MSI parent in DT matches host setup (@ref page_device_pci_msi).
---
## Pitfalls
| Issue | Mitigation |
| --- | --- |
| Missing root **`interrupt-map`** | Use MSI or fix DTS |
| Wrong swizzling | Use **`rt_pci_irq_intx`** for map key |
| Empty **`ranges`** | BAR assignment fails |
## See also
- @ref page_device_pci
- @ref page_device_pci_host
- @ref page_device_pci_irq
- @ref page_device_pci_msi
- @ref page_device_ofw_irq
- `components/drivers/pci/ofw.c`
|