ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / drivers / serial / 8250_hcdp.c
1 /*
2  * linux/drivers/char/hcdp_serial.c
3  *
4  * Copyright (C) 2002 Hewlett-Packard Co.
5  *      Khalid Aziz <khalid_aziz@hp.com>
6  *
7  * Parse the EFI HCDP table to locate serial console and debug ports and
8  * initialize them.
9  *
10  * 2002/08/29 davidm    Adjust it to new 2.5 serial driver infrastructure.
11  */
12
13 #include <linux/config.h>
14 #include <linux/console.h>
15 #include <linux/kernel.h>
16 #include <linux/efi.h>
17 #include <linux/init.h>
18 #include <linux/tty.h>
19 #include <linux/serial.h>
20 #include <linux/serial_core.h>
21 #include <linux/types.h>
22 #include <linux/acpi.h>
23
24 #include <asm/io.h>
25 #include <asm/serial.h>
26 #include <asm/acpi.h>
27
28 #include "8250_hcdp.h"
29
30 #undef SERIAL_DEBUG_HCDP
31
32 /*
33  * Parse the HCDP table to find descriptions for headless console and debug
34  * serial ports and add them to rs_table[]. A pointer to HCDP table is
35  * passed as parameter. This function should be called before
36  * serial_console_init() is called to make sure the HCDP serial console will
37  * be available for use. IA-64 kernel calls this function from setup_arch()
38  * after the EFI and ACPI tables have been parsed.
39  */
40 void __init
41 setup_serial_hcdp(void *tablep)
42 {
43         hcdp_dev_t *hcdp_dev;
44         struct uart_port port;
45         unsigned long iobase;
46         hcdp_t hcdp;
47         int gsi, nr;
48         static char options[16];
49 #if 0
50         static int shift_once = 1;
51 #endif
52
53 #ifdef SERIAL_DEBUG_HCDP
54         printk("Entering setup_serial_hcdp()\n");
55 #endif
56
57         /* Verify we have a valid table pointer */
58         if (!tablep)
59                 return;
60
61         memset(&port, 0, sizeof(port));
62
63         /*
64          * Don't trust firmware to give us a table starting at an aligned
65          * address. Make a local copy of the HCDP table with aligned
66          * structures.
67          */
68         memcpy(&hcdp, tablep, sizeof(hcdp));
69
70         /*
71          * Perform a sanity check on the table. Table should have a signature
72          * of "HCDP" and it should be atleast 82 bytes long to have any
73          * useful information.
74          */
75         if ((strncmp(hcdp.signature, HCDP_SIGNATURE, HCDP_SIG_LEN) != 0))
76                 return;
77         if (hcdp.len < 82)
78                 return;
79
80 #ifdef SERIAL_DEBUG_HCDP
81         printk("setup_serial_hcdp(): table pointer = 0x%p, sig = '%.4s'\n",
82                tablep, hcdp.signature);
83         printk(" length = %d, rev = %d, ", hcdp.len, hcdp.rev);
84         printk("OEM ID = %.6s, # of entries = %d\n", hcdp.oemid,
85                         hcdp.num_entries);
86 #endif
87
88         /*
89          * Parse each device entry
90          */
91         for (nr = 0; nr < hcdp.num_entries; nr++) {
92                 hcdp_dev = hcdp.hcdp_dev + nr;
93                 /*
94                  * We will parse only the primary console device which is
95                  * the first entry for these devices. We will ignore rest
96                  * of the entries for the same type device that has already
97                  * been parsed and initialized
98                  */
99                 if (hcdp_dev->type != HCDP_DEV_CONSOLE)
100                         continue;
101
102                 iobase = ((u64) hcdp_dev->base_addr.addrhi << 32) |
103                                         hcdp_dev->base_addr.addrlo;
104                 gsi = hcdp_dev->global_int;
105
106                 /* See PCI spec v2.2, Appendix D (Class Codes): */
107                 switch (hcdp_dev->pci_prog_intfc) {
108                 case 0x00:
109                         port.type = PORT_8250;
110                         break;
111                 case 0x01:
112                         port.type = PORT_16450;
113                         break;
114                 case 0x02:
115                         port.type = PORT_16550;
116                         break;
117                 case 0x03:
118                         port.type = PORT_16650;
119                         break;
120                 case 0x04:
121                         port.type = PORT_16750;
122                         break;
123                 case 0x05:
124                         port.type = PORT_16850;
125                         break;
126                 case 0x06:
127                         port.type = PORT_16C950;
128                         break;
129                 default:
130                         printk(KERN_WARNING "warning: EFI HCDP table reports "
131                                 "unknown serial programming interface 0x%02x; "
132                                 "will autoprobe.\n", hcdp_dev->pci_prog_intfc);
133                         port.type = PORT_UNKNOWN;
134                         break;
135                 }
136
137 #ifdef SERIAL_DEBUG_HCDP
138                 printk("  type = %s, uart = %d\n",
139                         ((hcdp_dev->type == HCDP_DEV_CONSOLE) ?
140                         "Headless Console" :
141                         ((hcdp_dev->type == HCDP_DEV_DEBUG) ?
142                         "Debug port" : "Huh????")), port.type);
143                 printk("  base address space = %s, base address = 0x%lx\n",
144                        ((hcdp_dev->base_addr.space_id == ACPI_MEM_SPACE) ?
145                        "Memory Space" :
146                         ((hcdp_dev->base_addr.space_id == ACPI_IO_SPACE) ?
147                         "I/O space" : "PCI space")),
148                        iobase);
149                 printk("  gsi = %d, baud rate = %lu, bits = %d, clock = %d\n",
150                        gsi, (unsigned long) hcdp_dev->baud, hcdp_dev->bits,
151                        hcdp_dev->clock_rate);
152                 if (HCDP_PCI_UART(hcdp_dev))
153                         printk(" PCI id: %02x:%02x:%02x, vendor ID=0x%x, "
154                                 "dev ID=0x%x\n", hcdp_dev->pci_seg,
155                                 hcdp_dev->pci_bus, hcdp_dev->pci_dev,
156                                 hcdp_dev->pci_vendor_id, hcdp_dev->pci_dev_id);
157 #endif
158                 /*
159                  * Now fill in a port structure to update the 8250 port table..
160                  */
161                 if (hcdp_dev->clock_rate)
162                         port.uartclk = hcdp_dev->clock_rate;
163                 else
164                         port.uartclk = BASE_BAUD * 16;
165
166                 /*
167                  * Check if this is an I/O mapped address or a memory mapped
168                  * address
169                  */
170                 if (hcdp_dev->base_addr.space_id == ACPI_MEM_SPACE) {
171                         port.iobase = 0;
172                         port.mapbase = iobase;
173                         port.membase = ioremap(iobase, 64);
174                         port.iotype = SERIAL_IO_MEM;
175                 } else if (hcdp_dev->base_addr.space_id == ACPI_IO_SPACE) {
176                         port.iobase = iobase;
177                         port.mapbase = 0;
178                         port.membase = NULL;
179                         port.iotype = SERIAL_IO_PORT;
180                 } else if (hcdp_dev->base_addr.space_id == ACPI_PCICONF_SPACE) {
181                         printk(KERN_WARNING"warning: No support for PCI serial console\n");
182                         return;
183                 }
184
185                 if (HCDP_IRQ_SUPPORTED(hcdp_dev)) {
186 #ifdef CONFIG_IA64
187                         if (HCDP_PCI_UART(hcdp_dev))
188                                 port.irq = acpi_register_irq(gsi,
189                                         ACPI_ACTIVE_LOW, ACPI_LEVEL_SENSITIVE);
190                         else
191                                 port.irq = acpi_register_irq(gsi,
192                                         ACPI_ACTIVE_HIGH, ACPI_EDGE_SENSITIVE);
193 #else
194                         port.irq = gsi;
195 #endif
196                         port.flags |= UPF_AUTO_IRQ;
197
198                         if (HCDP_PCI_UART(hcdp_dev))
199                                 port.flags |= UPF_SHARE_IRQ;
200                 }
201
202                 port.flags |= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_RESOURCES;
203
204                 /*
205                  * Note: the above memset() initializes port.line to 0,
206                  * so we register this port as ttyS0.
207                  */
208                 if (early_serial_setup(&port) < 0) {
209                         printk("setup_serial_hcdp(): early_serial_setup() "
210                                 "for HCDP serial console port failed. "
211                                 "Will try any additional consoles in HCDP.\n");
212                         memset(&port, 0, sizeof(port));
213                         continue;
214                 }
215
216                 if (efi_uart_console_only()) {
217                         snprintf(options, sizeof(options), "%lun%d",
218                                 hcdp_dev->baud, hcdp_dev->bits);
219                         add_preferred_console("ttyS", port.line, options);
220                 }
221                 break;
222         }
223
224 #ifdef SERIAL_DEBUG_HCDP
225         printk("Leaving setup_serial_hcdp()\n");
226 #endif
227 }
228
229 #ifdef CONFIG_IA64_EARLY_PRINTK_UART
230 unsigned long
231 hcdp_early_uart (void)
232 {
233         efi_system_table_t *systab;
234         efi_config_table_t *config_tables;
235         unsigned long addr = 0;
236         hcdp_t *hcdp = 0;
237         hcdp_dev_t *dev;
238         int i;
239
240         systab = (efi_system_table_t *) ia64_boot_param->efi_systab;
241         if (!systab)
242                 return 0;
243         systab = __va(systab);
244
245         config_tables = (efi_config_table_t *) systab->tables;
246         if (!config_tables)
247                 return 0;
248         config_tables = __va(config_tables);
249
250         for (i = 0; i < systab->nr_tables; i++) {
251                 if (efi_guidcmp(config_tables[i].guid, HCDP_TABLE_GUID) == 0) {
252                         hcdp = (hcdp_t *) config_tables[i].table;
253                         break;
254                 }
255         }
256         if (!hcdp)
257                 return 0;
258         hcdp = __va(hcdp);
259
260         for (i = 0, dev = hcdp->hcdp_dev; i < hcdp->num_entries; i++, dev++) {
261                 if (dev->type == HCDP_DEV_CONSOLE) {
262                         addr = (u64) dev->base_addr.addrhi << 32 | dev->base_addr.addrlo;
263                         break;
264                 }
265         }
266         return addr;
267 }
268 #endif /* CONFIG_IA64_EARLY_PRINTK_UART */