8250-pci.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2022-11-09 GuEe-GUI first version
  9. */
  10. #include <rtthread.h>
  11. #include "8250.h"
  12. #define IO_PORT_BAR 0
  13. enum
  14. {
  15. PCI_SERIAL = 0,
  16. PCI_SERIAL2 = 2,
  17. PCI_SERIAL4 = 4,
  18. };
  19. enum
  20. {
  21. SERIAL_8250 = 0,
  22. SERIAL_16450,
  23. SERIAL_16550,
  24. SERIAL_16650,
  25. SERIAL_16750,
  26. SERIAL_16850,
  27. SERIAL_16950,
  28. };
  29. struct pci_serial
  30. {
  31. struct serial8250 parent;
  32. struct rt_spinlock spinlock;
  33. struct rt_pci_device *pci_dev;
  34. rt_uint8_t type;
  35. rt_uint8_t compat;
  36. };
  37. #define to_pci_serial(raw) rt_container_of(raw, struct pci_serial, parent)
  38. static rt_err_t pci_serial_isr(struct serial8250 *serial, int irq)
  39. {
  40. rt_uint32_t iir;
  41. void *base = serial->base;
  42. iir = HWREG8(base + UART_IIR);
  43. if (!(iir & UART_IIR_NO_INT))
  44. {
  45. rt_hw_serial_isr(&serial->parent, RT_SERIAL_EVENT_RX_IND);
  46. }
  47. return RT_EOK;
  48. }
  49. static rt_ubase_t pci_serial_clock(struct pci_serial *pci_serial)
  50. {
  51. rt_ubase_t clock = 1843200;
  52. return clock;
  53. }
  54. static void pci_serial_free_resource(struct pci_serial *pci_serial)
  55. {
  56. struct serial8250 *serial = &pci_serial->parent;
  57. if (serial->base)
  58. {
  59. rt_iounmap(serial->base);
  60. }
  61. rt_free(pci_serial);
  62. }
  63. static void pci_8250serial_remove(struct serial8250 *serial)
  64. {
  65. struct pci_serial *pci_serial = to_pci_serial(serial);
  66. rt_pci_irq_mask(pci_serial->pci_dev);
  67. pci_serial_free_resource(pci_serial);
  68. }
  69. static rt_err_t pci_serial_probe(struct rt_pci_device *pdev)
  70. {
  71. rt_err_t err;
  72. struct serial8250 *serial;
  73. struct pci_serial *pci_serial = serial8250_alloc(pci_serial);
  74. struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
  75. if (!pci_serial)
  76. {
  77. return -RT_ENOMEM;
  78. }
  79. serial = &pci_serial->parent;
  80. serial->size = pdev->resource[IO_PORT_BAR].size;
  81. serial->base = rt_pci_iomap(pdev, IO_PORT_BAR);
  82. if (!serial->base)
  83. {
  84. err = -RT_EIO;
  85. goto _free_res;
  86. }
  87. pdev->parent.user_data = serial;
  88. serial->irq = pdev->irq;
  89. serial->parent.ops = &serial8250_uart_ops;
  90. serial->parent.config = config;
  91. serial->freq = pci_serial_clock(pci_serial);
  92. serial->handle_irq = &pci_serial_isr;
  93. serial->iotype = PORT_MMIO;
  94. serial->remove = &pci_8250serial_remove;
  95. serial->data = pci_serial;
  96. pci_serial->pci_dev = pdev;
  97. pci_serial->type = (rt_ubase_t)pdev->id->data;
  98. rt_spin_lock_init(&pci_serial->spinlock);
  99. rt_pci_read_config_u8(pdev, PCIR_PROGIF, &pci_serial->compat);
  100. if ((err = serial8250_setup(serial)))
  101. {
  102. goto _free_res;
  103. }
  104. rt_pci_irq_unmask(pci_serial->pci_dev);
  105. return RT_EOK;
  106. _free_res:
  107. pci_serial_free_resource(pci_serial);
  108. return err;
  109. }
  110. static rt_err_t pci_serial_remove(struct rt_pci_device *pdev)
  111. {
  112. struct serial8250 *serial = pdev->parent.user_data;
  113. return serial8250_remove(serial);
  114. }
  115. static const struct rt_pci_device_id pci_serial_pci_ids[] =
  116. {
  117. { RT_PCI_DEVICE_ID(PCI_VENDOR_ID_REDHAT, 0x0002), .data = (void *)PCI_SERIAL, },
  118. { RT_PCI_DEVICE_ID(PCI_VENDOR_ID_REDHAT, 0x0003), .data = (void *)PCI_SERIAL2, },
  119. { RT_PCI_DEVICE_ID(PCI_VENDOR_ID_REDHAT, 0x0004), .data = (void *)PCI_SERIAL4, },
  120. { /* sentinel */ }
  121. };
  122. static struct rt_pci_driver pci_serial_driver =
  123. {
  124. .name = "serial-pci",
  125. .ids = pci_serial_pci_ids,
  126. .probe = pci_serial_probe,
  127. .remove = pci_serial_remove,
  128. };
  129. RT_PCI_DRIVER_EXPORT(pci_serial_driver);