8250_pericom.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. // SPDX-License-Identifier: GPL-2.0
  2. /* Driver for Pericom UART */
  3. #include <linux/bits.h>
  4. #include <linux/module.h>
  5. #include <linux/overflow.h>
  6. #include <linux/pci.h>
  7. #include "8250.h"
  8. #define PCI_DEVICE_ID_ACCESSIO_PCIE_COM_2SDB 0x1051
  9. #define PCI_DEVICE_ID_ACCESSIO_MPCIE_COM_2S 0x1053
  10. #define PCI_DEVICE_ID_ACCESSIO_PCIE_COM422_4 0x105a
  11. #define PCI_DEVICE_ID_ACCESSIO_PCIE_COM485_4 0x105b
  12. #define PCI_DEVICE_ID_ACCESSIO_PCIE_COM_4SDB 0x105c
  13. #define PCI_DEVICE_ID_ACCESSIO_MPCIE_COM_4S 0x105e
  14. #define PCI_DEVICE_ID_ACCESSIO_PCIE_COM422_8 0x106a
  15. #define PCI_DEVICE_ID_ACCESSIO_PCIE_COM485_8 0x106b
  16. #define PCI_DEVICE_ID_ACCESSIO_PCIE_COM232_2DB 0x1091
  17. #define PCI_DEVICE_ID_ACCESSIO_MPCIE_COM232_2 0x1093
  18. #define PCI_DEVICE_ID_ACCESSIO_PCIE_COM232_4 0x1098
  19. #define PCI_DEVICE_ID_ACCESSIO_PCIE_COM232_4DB 0x1099
  20. #define PCI_DEVICE_ID_ACCESSIO_MPCIE_COM232_4 0x109b
  21. #define PCI_DEVICE_ID_ACCESSIO_PCIE_COM232_8 0x10a9
  22. #define PCI_DEVICE_ID_ACCESSIO_PCIE_COM_2SMDB 0x10d1
  23. #define PCI_DEVICE_ID_ACCESSIO_MPCIE_COM_2SM 0x10d3
  24. #define PCI_DEVICE_ID_ACCESSIO_PCIE_COM_4SM 0x10d9
  25. #define PCI_DEVICE_ID_ACCESSIO_PCIE_COM_4SMDB 0x10da
  26. #define PCI_DEVICE_ID_ACCESSIO_MPCIE_COM_4SM 0x10dc
  27. #define PCI_DEVICE_ID_ACCESSIO_PCIE_COM_8SM 0x10e9
  28. #define PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM485_1 0x1108
  29. #define PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM422_2 0x1110
  30. #define PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM485_2 0x1111
  31. #define PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM422_4 0x1118
  32. #define PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM485_4 0x1119
  33. #define PCI_DEVICE_ID_ACCESSIO_PCIE_ICM_2S 0x1152
  34. #define PCI_DEVICE_ID_ACCESSIO_PCIE_ICM_4S 0x115a
  35. #define PCI_DEVICE_ID_ACCESSIO_PCIE_ICM232_2 0x1190
  36. #define PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM232_2 0x1191
  37. #define PCI_DEVICE_ID_ACCESSIO_PCIE_ICM232_4 0x1198
  38. #define PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM232_4 0x1199
  39. #define PCI_DEVICE_ID_ACCESSIO_PCIE_ICM_2SM 0x11d0
  40. #define PCI_DEVICE_ID_ACCESSIO_PCIE_ICM_4SM 0x11d8
  41. struct pericom8250 {
  42. void __iomem *virt;
  43. unsigned int nr;
  44. int line[];
  45. };
  46. static void pericom_do_set_divisor(struct uart_port *port, unsigned int baud,
  47. unsigned int quot, unsigned int quot_frac)
  48. {
  49. int scr;
  50. for (scr = 16; scr > 4; scr--) {
  51. unsigned int maxrate = port->uartclk / scr;
  52. unsigned int divisor = max(maxrate / baud, 1U);
  53. int delta = maxrate / divisor - baud;
  54. if (baud > maxrate + baud / 50)
  55. continue;
  56. if (delta > baud / 50)
  57. divisor++;
  58. if (divisor > 0xffff)
  59. continue;
  60. /* Update delta due to possible divisor change */
  61. delta = maxrate / divisor - baud;
  62. if (abs(delta) < baud / 50) {
  63. struct uart_8250_port *up = up_to_u8250p(port);
  64. int lcr = serial_port_in(port, UART_LCR);
  65. serial_port_out(port, UART_LCR, lcr | UART_LCR_DLAB);
  66. serial_dl_write(up, divisor);
  67. serial_port_out(port, 2, 16 - scr);
  68. serial_port_out(port, UART_LCR, lcr);
  69. return;
  70. }
  71. }
  72. }
  73. static int pericom8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
  74. {
  75. unsigned int nr, i, bar = 0, maxnr;
  76. struct pericom8250 *pericom;
  77. struct uart_8250_port uart;
  78. int ret;
  79. ret = pcim_enable_device(pdev);
  80. if (ret)
  81. return ret;
  82. maxnr = pci_resource_len(pdev, bar) >> 3;
  83. if (pdev->vendor == PCI_VENDOR_ID_PERICOM)
  84. nr = pdev->device & 0x0f;
  85. else if (pdev->vendor == PCI_VENDOR_ID_ACCESSIO)
  86. nr = BIT(((pdev->device & 0x38) >> 3) - 1);
  87. else
  88. nr = 1;
  89. pericom = devm_kzalloc(&pdev->dev, struct_size(pericom, line, nr), GFP_KERNEL);
  90. if (!pericom)
  91. return -ENOMEM;
  92. pericom->virt = pcim_iomap(pdev, bar, 0);
  93. if (!pericom->virt)
  94. return -ENOMEM;
  95. memset(&uart, 0, sizeof(uart));
  96. uart.port.dev = &pdev->dev;
  97. uart.port.irq = pdev->irq;
  98. uart.port.private_data = pericom;
  99. uart.port.iotype = UPIO_PORT;
  100. uart.port.uartclk = 921600 * 16;
  101. uart.port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
  102. uart.port.set_divisor = pericom_do_set_divisor;
  103. for (i = 0; i < nr && i < maxnr; i++) {
  104. unsigned int offset = (i == 3 && nr == 4) ? 0x38 : i * 0x8;
  105. uart.port.iobase = pci_resource_start(pdev, bar) + offset;
  106. dev_dbg(&pdev->dev, "Setup PCI port: port %lx, irq %d, type %d\n",
  107. uart.port.iobase, uart.port.irq, uart.port.iotype);
  108. pericom->line[i] = serial8250_register_8250_port(&uart);
  109. if (pericom->line[i] < 0) {
  110. dev_err(&pdev->dev,
  111. "Couldn't register serial port %lx, irq %d, type %d, error %d\n",
  112. uart.port.iobase, uart.port.irq,
  113. uart.port.iotype, pericom->line[i]);
  114. break;
  115. }
  116. }
  117. pericom->nr = i;
  118. pci_set_drvdata(pdev, pericom);
  119. return 0;
  120. }
  121. static void pericom8250_remove(struct pci_dev *pdev)
  122. {
  123. struct pericom8250 *pericom = pci_get_drvdata(pdev);
  124. unsigned int i;
  125. for (i = 0; i < pericom->nr; i++)
  126. serial8250_unregister_port(pericom->line[i]);
  127. }
  128. static const struct pci_device_id pericom8250_pci_ids[] = {
  129. /*
  130. * Pericom PI7C9X795[1248] Uno/Dual/Quad/Octal UART
  131. * (Only 7954 has an offset jump for port 4)
  132. */
  133. { PCI_VDEVICE(PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7951) },
  134. { PCI_VDEVICE(PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7952) },
  135. { PCI_VDEVICE(PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7954) },
  136. { PCI_VDEVICE(PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7958) },
  137. /*
  138. * ACCES I/O Products quad
  139. * (Only 7954 has an offset jump for port 4)
  140. */
  141. { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM_2SDB) },
  142. { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_COM_2S) },
  143. { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM422_4) },
  144. { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM485_4) },
  145. { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM_4SDB) },
  146. { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_COM_4S) },
  147. { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM422_8) },
  148. { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM485_8) },
  149. { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM232_2DB) },
  150. { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_COM232_2) },
  151. { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM232_4) },
  152. { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM232_4DB) },
  153. { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_COM232_4) },
  154. { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM232_8) },
  155. { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM_2SMDB) },
  156. { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_COM_2SM) },
  157. { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM_4SM) },
  158. { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM_4SMDB) },
  159. { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_COM_4SM) },
  160. { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM_8SM) },
  161. { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM485_1) },
  162. { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM422_2) },
  163. { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM485_2) },
  164. { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM422_4) },
  165. { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM485_4) },
  166. { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_ICM_2S) },
  167. { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_ICM_4S) },
  168. { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_ICM232_2) },
  169. { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM232_2) },
  170. { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_ICM232_4) },
  171. { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM232_4) },
  172. { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_ICM_2SM) },
  173. { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_ICM_4SM) },
  174. { }
  175. };
  176. MODULE_DEVICE_TABLE(pci, pericom8250_pci_ids);
  177. static struct pci_driver pericom8250_pci_driver = {
  178. .name = "8250_pericom",
  179. .id_table = pericom8250_pci_ids,
  180. .probe = pericom8250_probe,
  181. .remove = pericom8250_remove,
  182. };
  183. module_pci_driver(pericom8250_pci_driver);
  184. MODULE_LICENSE("GPL v2");
  185. MODULE_DESCRIPTION("Pericom UART driver");