| 22 | #include <drivers/ofw_fdt.h> |
| 23 | |
| 24 | static rt_err_t pci_ofw_irq_parse(struct rt_pci_device *pdev, struct rt_ofw_cell_args *out_irq) |
| 25 | { |
| 26 | rt_err_t err = RT_EOK; |
| 27 | rt_uint8_t pin; |
| 28 | fdt32_t map_addr[4]; |
| 29 | struct rt_pci_device *p2pdev; |
| 30 | struct rt_ofw_node *dev_np, *p2pnode = RT_NULL; |
| 31 | |
| 32 | /* Parse device tree if dev have a device node */ |
| 33 | dev_np = pdev->parent.ofw_node; |
| 34 | |
| 35 | if (dev_np) |
| 36 | { |
| 37 | err = rt_ofw_parse_irq_cells(dev_np, 0, out_irq); |
| 38 | |
| 39 | if (err) |
| 40 | { |
| 41 | return err; |
| 42 | } |
| 43 | } |
| 44 | |
| 45 | /* Assume #interrupt-cells is 1 */ |
| 46 | if ((err = rt_pci_read_config_u8(pdev, PCIR_INTPIN, &pin))) |
| 47 | { |
| 48 | goto _err; |
| 49 | } |
| 50 | |
| 51 | /* No pin, exit with no error message. */ |
| 52 | if (pin == 0) |
| 53 | { |
| 54 | return -RT_ENOSYS; |
| 55 | } |
| 56 | |
| 57 | /* Try local interrupt-map in the device node */ |
| 58 | if (rt_ofw_prop_read_raw(dev_np, "interrupt-map", RT_NULL)) |
| 59 | { |
| 60 | pin = rt_pci_irq_intx(pdev, pin); |
| 61 | p2pnode = dev_np; |
| 62 | } |
| 63 | |
| 64 | /* Walk up the PCI tree */ |
| 65 | while (!p2pnode) |
| 66 | { |
| 67 | p2pdev = pdev->bus->self; |
| 68 | |
| 69 | /* Is the root bus -> host bridge */ |
| 70 | if (rt_pci_is_root_bus(pdev->bus)) |
| 71 | { |
| 72 | struct rt_pci_host_bridge *host_bridge = pdev->bus->host_bridge; |
| 73 | |
| 74 | p2pnode = host_bridge->parent.ofw_node; |
| 75 | |
| 76 | if (!p2pnode) |
| 77 | { |
| 78 | err = -RT_EINVAL; |
| 79 | |
| 80 | goto _err; |
| 81 | } |
no test coverage detected