8250_acpi.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /*
  2. * Copyright (c) 2002-2003 Matthew Wilcox for Hewlett-Packard
  3. * Copyright (C) 2004 Hewlett-Packard Co
  4. * Bjorn Helgaas <bjorn.helgaas@hp.com>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. */
  11. #include <linux/acpi.h>
  12. #include <linux/init.h>
  13. #include <linux/module.h>
  14. #include <linux/serial_core.h>
  15. #include <acpi/acpi_bus.h>
  16. #include <asm/io.h>
  17. #include "8250.h"
  18. struct serial_private {
  19. int line;
  20. };
  21. static acpi_status acpi_serial_mmio(struct uart_port *port,
  22. struct acpi_resource_address64 *addr)
  23. {
  24. port->mapbase = addr->minimum;
  25. port->iotype = UPIO_MEM;
  26. port->flags |= UPF_IOREMAP;
  27. return AE_OK;
  28. }
  29. static acpi_status acpi_serial_port(struct uart_port *port,
  30. struct acpi_resource_io *io)
  31. {
  32. if (io->address_length) {
  33. port->iobase = io->minimum;
  34. port->iotype = UPIO_PORT;
  35. } else
  36. printk(KERN_ERR "%s: zero-length IO port range?\n", __FUNCTION__);
  37. return AE_OK;
  38. }
  39. static acpi_status acpi_serial_ext_irq(struct uart_port *port,
  40. struct acpi_resource_extended_irq *ext_irq)
  41. {
  42. int rc;
  43. if (ext_irq->interrupt_count > 0) {
  44. rc = acpi_register_gsi(ext_irq->interrupts[0],
  45. ext_irq->triggering, ext_irq->polarity);
  46. if (rc < 0)
  47. return AE_ERROR;
  48. port->irq = rc;
  49. }
  50. return AE_OK;
  51. }
  52. static acpi_status acpi_serial_irq(struct uart_port *port,
  53. struct acpi_resource_irq *irq)
  54. {
  55. int rc;
  56. if (irq->interrupt_count > 0) {
  57. rc = acpi_register_gsi(irq->interrupts[0],
  58. irq->triggering, irq->polarity);
  59. if (rc < 0)
  60. return AE_ERROR;
  61. port->irq = rc;
  62. }
  63. return AE_OK;
  64. }
  65. static acpi_status acpi_serial_resource(struct acpi_resource *res, void *data)
  66. {
  67. struct uart_port *port = (struct uart_port *) data;
  68. struct acpi_resource_address64 addr;
  69. acpi_status status;
  70. status = acpi_resource_to_address64(res, &addr);
  71. if (ACPI_SUCCESS(status))
  72. return acpi_serial_mmio(port, &addr);
  73. else if (res->type == ACPI_RESOURCE_TYPE_IO)
  74. return acpi_serial_port(port, &res->data.io);
  75. else if (res->type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ)
  76. return acpi_serial_ext_irq(port, &res->data.extended_irq);
  77. else if (res->type == ACPI_RESOURCE_TYPE_IRQ)
  78. return acpi_serial_irq(port, &res->data.irq);
  79. return AE_OK;
  80. }
  81. static int acpi_serial_add(struct acpi_device *device)
  82. {
  83. struct serial_private *priv;
  84. acpi_status status;
  85. struct uart_port port;
  86. int result;
  87. memset(&port, 0, sizeof(struct uart_port));
  88. port.uartclk = 1843200;
  89. port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
  90. priv = kmalloc(sizeof(struct serial_private), GFP_KERNEL);
  91. if (!priv) {
  92. result = -ENOMEM;
  93. goto fail;
  94. }
  95. memset(priv, 0, sizeof(*priv));
  96. status = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
  97. acpi_serial_resource, &port);
  98. if (ACPI_FAILURE(status)) {
  99. result = -ENODEV;
  100. goto fail;
  101. }
  102. if (!port.mapbase && !port.iobase) {
  103. printk(KERN_ERR "%s: no iomem or port address in %s _CRS\n",
  104. __FUNCTION__, device->pnp.bus_id);
  105. result = -ENODEV;
  106. goto fail;
  107. }
  108. priv->line = serial8250_register_port(&port);
  109. if (priv->line < 0) {
  110. printk(KERN_WARNING "Couldn't register serial port %s: %d\n",
  111. device->pnp.bus_id, priv->line);
  112. result = -ENODEV;
  113. goto fail;
  114. }
  115. acpi_driver_data(device) = priv;
  116. return 0;
  117. fail:
  118. kfree(priv);
  119. return result;
  120. }
  121. static int acpi_serial_remove(struct acpi_device *device, int type)
  122. {
  123. struct serial_private *priv;
  124. if (!device || !acpi_driver_data(device))
  125. return -EINVAL;
  126. priv = acpi_driver_data(device);
  127. serial8250_unregister_port(priv->line);
  128. kfree(priv);
  129. return 0;
  130. }
  131. static struct acpi_driver acpi_serial_driver = {
  132. .name = "serial",
  133. .class = "",
  134. .ids = "PNP0501",
  135. .ops = {
  136. .add = acpi_serial_add,
  137. .remove = acpi_serial_remove,
  138. },
  139. };
  140. static int __init acpi_serial_init(void)
  141. {
  142. return acpi_bus_register_driver(&acpi_serial_driver);
  143. }
  144. static void __exit acpi_serial_exit(void)
  145. {
  146. acpi_bus_unregister_driver(&acpi_serial_driver);
  147. }
  148. module_init(acpi_serial_init);
  149. module_exit(acpi_serial_exit);
  150. MODULE_LICENSE("GPL");
  151. MODULE_DESCRIPTION("Generic 8250/16x50 ACPI serial driver");