3 * Copyright (c) 2002-2003 Matthew Wilcox for Hewlett-Packard
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
11 #include <linux/acpi.h>
12 #include <linux/init.h>
13 #include <linux/module.h>
14 #include <linux/serial.h>
16 #include <acpi/acpi_bus.h>
19 #include <asm/serial.h>
21 static void acpi_serial_address(struct serial_struct *req, struct acpi_resource_address32 *addr32)
25 size = addr32->max_address_range - addr32->min_address_range + 1;
26 req->iomap_base = addr32->min_address_range;
27 req->iomem_base = ioremap(req->iomap_base, size);
28 req->io_type = SERIAL_IO_MEM;
31 static void acpi_serial_irq(struct serial_struct *req, struct acpi_resource_ext_irq *ext_irq)
33 if (ext_irq->number_of_interrupts > 0) {
35 req->irq = acpi_register_irq(ext_irq->interrupts[0],
36 ext_irq->active_high_low, ext_irq->edge_level);
38 req->irq = ext_irq->interrupts[0];
43 static int acpi_serial_add(struct acpi_device *device)
46 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
47 struct serial_struct serial_req;
50 memset(&serial_req, 0, sizeof(serial_req));
51 result = acpi_get_current_resources(device->handle, &buffer);
52 if (ACPI_FAILURE(result)) {
57 while (offset <= buffer.length) {
58 struct acpi_resource *res = buffer.pointer + offset;
61 offset += res->length;
62 if (res->id == ACPI_RSTYPE_ADDRESS32) {
63 acpi_serial_address(&serial_req, &res->data.address32);
64 } else if (res->id == ACPI_RSTYPE_EXT_IRQ) {
65 acpi_serial_irq(&serial_req, &res->data.extended_irq);
69 serial_req.baud_base = BASE_BAUD;
70 serial_req.flags = ASYNC_SKIP_TEST|ASYNC_BOOT_AUTOCONF|ASYNC_AUTO_IRQ;
73 line = register_serial(&serial_req);
78 acpi_os_free(buffer.pointer);
82 static int acpi_serial_remove(struct acpi_device *device, int type)
87 static struct acpi_driver acpi_serial_driver = {
92 .add = acpi_serial_add,
93 .remove = acpi_serial_remove,
97 static int __init acpi_serial_init(void)
99 acpi_bus_register_driver(&acpi_serial_driver);
103 static void __exit acpi_serial_exit(void)
105 acpi_bus_unregister_driver(&acpi_serial_driver);
108 module_init(acpi_serial_init);
109 module_exit(acpi_serial_exit);