8250_acpi.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  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->min_address_range;
  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->range_length) {
  33. port->iobase = io->min_base_address;
  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_ext_irq *ext_irq)
  41. {
  42. if (ext_irq->number_of_interrupts > 0)
  43. port->irq = acpi_register_gsi(ext_irq->interrupts[0],
  44. ext_irq->edge_level, ext_irq->active_high_low);
  45. return AE_OK;
  46. }
  47. static acpi_status acpi_serial_irq(struct uart_port *port,
  48. struct acpi_resource_irq *irq)
  49. {
  50. if (irq->number_of_interrupts > 0)
  51. port->irq = acpi_register_gsi(irq->interrupts[0],
  52. irq->edge_level, irq->active_high_low);
  53. return AE_OK;
  54. }
  55. static acpi_status acpi_serial_resource(struct acpi_resource *res, void *data)
  56. {
  57. struct uart_port *port = (struct uart_port *) data;
  58. struct acpi_resource_address64 addr;
  59. acpi_status status;
  60. status = acpi_resource_to_address64(res, &addr);
  61. if (ACPI_SUCCESS(status))
  62. return acpi_serial_mmio(port, &addr);
  63. else if (res->id == ACPI_RSTYPE_IO)
  64. return acpi_serial_port(port, &res->data.io);
  65. else if (res->id == ACPI_RSTYPE_EXT_IRQ)
  66. return acpi_serial_ext_irq(port, &res->data.extended_irq);
  67. else if (res->id == ACPI_RSTYPE_IRQ)
  68. return acpi_serial_irq(port, &res->data.irq);
  69. return AE_OK;
  70. }
  71. static int acpi_serial_add(struct acpi_device *device)
  72. {
  73. struct serial_private *priv;
  74. acpi_status status;
  75. struct uart_port port;
  76. int result;
  77. memset(&port, 0, sizeof(struct uart_port));
  78. port.uartclk = 1843200;
  79. port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
  80. priv = kmalloc(sizeof(struct serial_private), GFP_KERNEL);
  81. if (!priv) {
  82. result = -ENOMEM;
  83. goto fail;
  84. }
  85. memset(priv, 0, sizeof(*priv));
  86. status = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
  87. acpi_serial_resource, &port);
  88. if (ACPI_FAILURE(status)) {
  89. result = -ENODEV;
  90. goto fail;
  91. }
  92. if (!port.mapbase && !port.iobase) {
  93. printk(KERN_ERR "%s: no iomem or port address in %s _CRS\n",
  94. __FUNCTION__, device->pnp.bus_id);
  95. result = -ENODEV;
  96. goto fail;
  97. }
  98. priv->line = serial8250_register_port(&port);
  99. if (priv->line < 0) {
  100. printk(KERN_WARNING "Couldn't register serial port %s: %d\n",
  101. device->pnp.bus_id, priv->line);
  102. result = -ENODEV;
  103. goto fail;
  104. }
  105. acpi_driver_data(device) = priv;
  106. return 0;
  107. fail:
  108. kfree(priv);
  109. return result;
  110. }
  111. static int acpi_serial_remove(struct acpi_device *device, int type)
  112. {
  113. struct serial_private *priv;
  114. if (!device || !acpi_driver_data(device))
  115. return -EINVAL;
  116. priv = acpi_driver_data(device);
  117. serial8250_unregister_port(priv->line);
  118. kfree(priv);
  119. return 0;
  120. }
  121. static struct acpi_driver acpi_serial_driver = {
  122. .name = "serial",
  123. .class = "",
  124. .ids = "PNP0501",
  125. .ops = {
  126. .add = acpi_serial_add,
  127. .remove = acpi_serial_remove,
  128. },
  129. };
  130. static int __init acpi_serial_init(void)
  131. {
  132. return acpi_bus_register_driver(&acpi_serial_driver);
  133. }
  134. static void __exit acpi_serial_exit(void)
  135. {
  136. acpi_bus_unregister_driver(&acpi_serial_driver);
  137. }
  138. module_init(acpi_serial_init);
  139. module_exit(acpi_serial_exit);
  140. MODULE_LICENSE("GPL");
  141. MODULE_DESCRIPTION("Generic 8250/16x50 ACPI serial driver");