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
,
22 struct acpi_resource_address32
*addr32
)
26 size
= addr32
->max_address_range
- addr32
->min_address_range
+ 1;
27 req
->iomap_base
= addr32
->min_address_range
;
28 req
->iomem_base
= ioremap(req
->iomap_base
, size
);
29 req
->io_type
= SERIAL_IO_MEM
;
32 static void acpi_serial_irq(struct serial_struct
*req
,
33 struct acpi_resource_ext_irq
*ext_irq
)
35 if (ext_irq
->number_of_interrupts
> 0) {
37 req
->irq
= acpi_register_irq(ext_irq
->interrupts
[0],
38 ext_irq
->active_high_low
, ext_irq
->edge_level
);
40 req
->irq
= ext_irq
->interrupts
[0];
45 static int acpi_serial_add(struct acpi_device
*device
)
48 struct acpi_buffer buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
49 struct serial_struct serial_req
;
52 memset(&serial_req
, 0, sizeof(serial_req
));
53 result
= acpi_get_current_resources(device
->handle
, &buffer
);
54 if (ACPI_FAILURE(result
)) {
59 while (offset
<= buffer
.length
) {
60 struct acpi_resource
*res
= buffer
.pointer
+ offset
;
63 offset
+= res
->length
;
64 if (res
->id
== ACPI_RSTYPE_ADDRESS32
) {
65 acpi_serial_address(&serial_req
, &res
->data
.address32
);
66 } else if (res
->id
== ACPI_RSTYPE_EXT_IRQ
) {
67 acpi_serial_irq(&serial_req
, &res
->data
.extended_irq
);
71 serial_req
.baud_base
= BASE_BAUD
;
72 serial_req
.flags
= ASYNC_SKIP_TEST
|ASYNC_BOOT_AUTOCONF
|ASYNC_AUTO_IRQ
;
75 line
= register_serial(&serial_req
);
80 acpi_os_free(buffer
.pointer
);
84 static int acpi_serial_remove(struct acpi_device
*device
, int type
)
89 static struct acpi_driver acpi_serial_driver
= {
94 .add
= acpi_serial_add
,
95 .remove
= acpi_serial_remove
,
99 static int __init
acpi_serial_init(void)
101 return acpi_bus_register_driver(&acpi_serial_driver
);
104 static void __exit
acpi_serial_exit(void)
106 acpi_bus_unregister_driver(&acpi_serial_driver
);
109 module_init(acpi_serial_init
);
110 module_exit(acpi_serial_exit
);