1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
|
/*
* linux/drivers/char/acpi_serial.c
*
* Copyright (C) 2000 Hewlett-Packard Co.
* Copyright (C) 2000 Khalid Aziz <khalid_aziz@hp.com>
*
* Detect and initialize the headless console serial port defined in
* SPCR table and debug serial port defined in DBGP table
*
*/
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/pm.h>
#include <linux/acpi.h>
#include <linux/init.h>
#include <linux/serial.h>
#include <asm/serial.h>
#include <asm/io.h>
#include <linux/acpi_serial.h>
/*#include <asm/acpi-ext.h>*/
#undef SERIAL_DEBUG_ACPI
/*
* Query ACPI tables for a debug and a headless console serial
* port. If found, add them to rs_table[]. A pointer to either SPCR
* or DBGP table is passed as parameter. This function should be called
* before serial_console_init() is called to make sure the SPCR serial
* console will be available for use. IA-64 kernel calls this function
* from within acpi.c when it encounters SPCR or DBGP tables as it parses
* the ACPI 2.0 tables during bootup.
*
*/
void __init setup_serial_acpi(void *tablep)
{
acpi_ser_t *acpi_ser_p;
struct serial_struct serial_req;
unsigned long iobase;
int global_sys_irq;
#ifdef SERIAL_DEBUG_ACPI
printk("Entering setup_serial_acpi()\n");
#endif
/* Now get the table */
if (tablep == NULL) {
return;
}
acpi_ser_p = (acpi_ser_t *)tablep;
/*
* Perform a sanity check on the table. Table should have a
* signature of "SPCR" or "DBGP" and it should be atleast 52 bytes
* long.
*/
if ((strncmp(acpi_ser_p->signature, ACPI_SPCRT_SIGNATURE,
ACPI_SIG_LEN) != 0) &&
(strncmp(acpi_ser_p->signature, ACPI_DBGPT_SIGNATURE,
ACPI_SIG_LEN) != 0)) {
return;
}
if (acpi_ser_p->length < 52) {
return;
}
iobase = (((u64) acpi_ser_p->base_addr.addrh) << 32) | acpi_ser_p->base_addr.addrl;
global_sys_irq = (acpi_ser_p->global_int[3] << 24) |
(acpi_ser_p->global_int[2] << 16) |
(acpi_ser_p->global_int[1] << 8) |
acpi_ser_p->global_int[0];
#ifdef SERIAL_DEBUG_ACPI
printk("setup_serial_acpi(): table pointer = 0x%p\n", acpi_ser_p);
printk(" sig = '%c%c%c%c'\n",
acpi_ser_p->signature[0],
acpi_ser_p->signature[1],
acpi_ser_p->signature[2],
acpi_ser_p->signature[3]);
printk(" length = %d\n", acpi_ser_p->length);
printk(" Rev = %d\n", acpi_ser_p->rev);
printk(" Interface type = %d\n", acpi_ser_p->intfc_type);
printk(" Base address = 0x%lX\n", iobase);
printk(" IRQ = %d\n", acpi_ser_p->irq);
printk(" Global System Int = %d\n", global_sys_irq);
printk(" Baud rate = ");
switch (acpi_ser_p->baud) {
case ACPI_SERIAL_BAUD_9600:
printk("9600\n");
break;
case ACPI_SERIAL_BAUD_19200:
printk("19200\n");
break;
case ACPI_SERIAL_BAUD_57600:
printk("57600\n");
break;
case ACPI_SERIAL_BAUD_115200:
printk("115200\n");
break;
default:
printk("Huh (%d)\n", acpi_ser_p->baud);
break;
}
if (acpi_ser_p->base_addr.space_id == ACPI_SERIAL_PCICONF_SPACE) {
printk(" PCI serial port:\n");
printk(" Bus %d, Device %d, Vendor ID 0x%x, Dev ID 0x%x\n",
acpi_ser_p->pci_bus, acpi_ser_p->pci_dev,
acpi_ser_p->pci_vendor_id, acpi_ser_p->pci_dev_id);
}
#endif
/*
* Now build a serial_req structure to update the entry in
* rs_table for the headless console port.
*/
switch (acpi_ser_p->intfc_type) {
case ACPI_SERIAL_INTFC_16550:
serial_req.type = PORT_16550;
serial_req.baud_base = BASE_BAUD;
break;
case ACPI_SERIAL_INTFC_16450:
serial_req.type = PORT_16450;
serial_req.baud_base = BASE_BAUD;
break;
default:
serial_req.type = PORT_UNKNOWN;
break;
}
if (strncmp(acpi_ser_p->signature, ACPI_SPCRT_SIGNATURE,
ACPI_SIG_LEN) == 0) {
serial_req.line = ACPI_SERIAL_CONSOLE_PORT;
}
else if (strncmp(acpi_ser_p->signature, ACPI_DBGPT_SIGNATURE,
ACPI_SIG_LEN) == 0) {
serial_req.line = ACPI_SERIAL_DEBUG_PORT;
}
/*
* Check if this is an I/O mapped address or a memory mapped address
*/
if (acpi_ser_p->base_addr.space_id == ACPI_SERIAL_MEM_SPACE) {
serial_req.port = 0;
serial_req.port_high = 0;
serial_req.iomem_base = (void *)ioremap(iobase, 64);
serial_req.io_type = SERIAL_IO_MEM;
}
else if (acpi_ser_p->base_addr.space_id == ACPI_SERIAL_IO_SPACE) {
serial_req.port = (unsigned long) iobase & 0xffffffff;
serial_req.port_high = (unsigned long)(((u64)iobase) >> 32);
serial_req.iomem_base = NULL;
serial_req.io_type = SERIAL_IO_PORT;
}
else if (acpi_ser_p->base_addr.space_id == ACPI_SERIAL_PCICONF_SPACE) {
printk("WARNING: No support for PCI serial console\n");
return;
}
/*
* If the table does not have IRQ information, use 0 for IRQ.
* This will force rs_init() to probe for IRQ.
*/
if (acpi_ser_p->length < 53) {
serial_req.irq = 0;
}
else {
serial_req.flags = ASYNC_SKIP_TEST | ASYNC_BOOT_AUTOCONF |
ASYNC_AUTO_IRQ;
if (acpi_ser_p->int_type &
(ACPI_SERIAL_INT_APIC | ACPI_SERIAL_INT_SAPIC)) {
serial_req.irq = global_sys_irq;
}
else if (acpi_ser_p->int_type & ACPI_SERIAL_INT_PCAT) {
serial_req.irq = acpi_ser_p->irq;
}
else {
/*
* IRQ type not being set would mean UART will
* run in polling mode. Do not probe for IRQ in
* that case.
*/
serial_req.flags = ASYNC_SKIP_TEST|ASYNC_BOOT_AUTOCONF;
}
}
serial_req.xmit_fifo_size = serial_req.custom_divisor = 0;
serial_req.close_delay = serial_req.hub6 = serial_req.closing_wait = 0;
serial_req.iomem_reg_shift = 0;
if (early_serial_setup(&serial_req) < 0) {
printk("early_serial_setup() for ACPI serial console port failed\n");
return;
}
#ifdef SERIAL_DEBUG_ACPI
printk("Leaving setup_serial_acpi()\n");
#endif
}
|