1 #include <lunaix/device.h>
2 #include <lunaix/syslog.h>
3 #include <lunaix/mm/mmio.h>
9 #define PCI_DEVICE_16x50_UART 0x070000
11 LOG_MODULE("16x50-pci")
13 static DEFINE_LLIST(pci_ports);
17 uart_msi_irq_handler(irq_t irq, const struct hart_state* hstate)
19 struct uart16550* uart;
21 uart = irq_payload(irq, struct uart16550);
24 uart_handle_irq(irq, uart);
28 pci16x50_check_compat(struct pci_probe* probe)
31 classid = pci_device_class(probe);
33 return (classid & 0xffff00) == PCI_DEVICE_16x50_UART;
37 pci16x50_pci_register(struct device_def* def)
39 return !pci_register_driver(def, pci16x50_check_compat);
43 pci16x50_pci_create(struct device_def* def, morph_t* obj)
45 struct pci_base_addr* bar;
46 struct pci_probe* probe;
47 struct uart16550* uart;
48 struct serial_dev* sdev;
51 probe = changeling_reveal(obj, pci_probe_morpher);
55 for (int i = 0; i < PCI_BAR_COUNT; i++)
58 pci_cmd_set_msi(&cmd);
60 bar = pci_device_bar(probe, i);
65 if (!pci_bar_mmio_space(bar)) {
66 #ifdef CONFIG_PCI_PMIO
67 pci_cmd_set_pmio(&cmd);
68 pci_apply_command(probe, cmd);
70 uart = uart16x50_pmio_create(bar->start);
72 WARN("plaform configured to not support pmio access.");
77 pci_cmd_set_mmio(&cmd);
78 pci_apply_command(probe, cmd);
80 uart = uart16x50_mmio_create(bar->start, bar->size);
84 WARN("not accessible (BAR #%d)", i);
88 if (!pci_capability_msi(probe)) {
89 WARN("failed to fallback to legacy INTx: not supported.");
93 sdev = uart_create_serial(uart, &def->class, &pci_ports, "PCI");
95 irq = pci_declare_msi_irq(uart_msi_irq_handler, probe);
96 irq_set_payload(irq, uart);
97 pci_assign_msi(probe, irq, NULL);
99 INFO("base: 0x%x (%s), %s",
101 pci_bar_mmio_space(bar) ? "mmio" : "pmio",
102 pci_capability_msi(probe) ? "msi" : "intx, re-routed");
106 pci_bind_instance(probe, sdev->dev);