1 #include <lunaix/device.h>
2 #include <asm-generic/isrm.h>
3 #include <lunaix/syslog.h>
4 #include <lunaix/mm/mmio.h>
10 #define PCI_DEVICE_16x50_UART 0x070000
12 LOG_MODULE("16x50-pci")
14 static DEFINE_LLIST(pci_ports);
18 uart_msi_irq_handler(const struct hart_state* hstate)
21 struct uart16550* uart;
23 vector = hart_vector_stamp(hstate);
24 uart = (struct uart16550*)isrm_get_payload(hstate);
27 uart_handle_irq(vector, uart);
31 uart_intx_irq_handler(const struct hart_state* hstate)
33 int vector = hart_vector_stamp(hstate);
34 uart_handle_irq_overlap(vector, &pci_ports);
38 pci16x50_check_compat(struct pci_probe* probe)
41 classid = pci_device_class(probe);
43 return (classid & 0xffff00) == PCI_DEVICE_16x50_UART;
47 pci16x50_pci_register(struct device_def* def)
49 return !pci_register_driver(def, pci16x50_check_compat);
53 pci16x50_pci_create(struct device_def* def, morph_t* obj)
55 struct pci_base_addr* bar;
56 struct pci_probe* probe;
57 struct uart16550* uart;
58 struct serial_dev* sdev;
61 probe = changeling_reveal(obj, pci_probe_morpher);
65 for (int i = 0; i < PCI_BAR_COUNT; i++)
68 pci_cmd_set_msi(&cmd);
70 bar = pci_device_bar(probe, i);
75 if (!pci_bar_mmio_space(bar)) {
76 #ifdef CONFIG_PCI_PMIO
77 pci_cmd_set_pmio(&cmd);
78 pci_apply_command(probe, cmd);
80 uart = uart16x50_pmio_create(bar->start);
82 WARN("plaform configured to not support pmio access.");
87 pci_cmd_set_mmio(&cmd);
88 pci_apply_command(probe, cmd);
90 uart = uart16x50_mmio_create(bar->start, bar->size);
94 WARN("not accessible (BAR #%d)", i);
98 if (!pci_capability_msi(probe)) {
99 WARN("failed to fallback to legacy INTx: not supported.");
103 sdev = uart_create_serial(uart, &def->class, &pci_ports, "PCI");
105 msiv = pci_msi_setup_simple(probe, uart_msi_irq_handler);
106 isrm_set_payload(msi_vect(msiv), __ptr(uart));
108 INFO("base: 0x%x (%s), irq=%d (%s)",
110 pci_bar_mmio_space(bar) ? "mmio" : "pmio",
112 pci_capability_msi(probe) ? "msi" : "intx, re-routed");
114 uart->iv = msi_vect(msiv);
116 pci_bind_instance(probe, sdev->dev);