2 * Copyright (C) 2002, 2003, 2004 Hewlett-Packard Co.
3 * Khalid Aziz <khalid_aziz@hp.com>
4 * Alex Williamson <alex.williamson@hp.com>
5 * Bjorn Helgaas <bjorn.helgaas@hp.com>
7 * Parse the EFI PCDP table to locate the console device.
10 #include <linux/acpi.h>
11 #include <linux/console.h>
12 #include <linux/efi.h>
13 #include <linux/tty.h>
14 #include <linux/serial.h>
15 #include <linux/serial_core.h>
17 #include <asm/serial.h>
21 uart_irq_supported(int rev, struct pcdp_uart *uart)
24 return uart->pci_func & PCDP_UART_IRQ;
25 return uart->flags & PCDP_UART_IRQ;
29 uart_pci(int rev, struct pcdp_uart *uart)
32 return uart->pci_func & PCDP_UART_PCI;
33 return uart->flags & PCDP_UART_PCI;
37 uart_active_high_low(int rev, struct pcdp_uart *uart)
39 if (uart_pci(rev, uart) || uart->flags & PCDP_UART_ACTIVE_LOW)
40 return ACPI_ACTIVE_LOW;
41 return ACPI_ACTIVE_HIGH;
45 uart_edge_level(int rev, struct pcdp_uart *uart)
47 if (uart_pci(rev, uart))
48 return ACPI_LEVEL_SENSITIVE;
49 if (rev < 3 || uart->flags & PCDP_UART_EDGE_SENSITIVE)
50 return ACPI_EDGE_SENSITIVE;
51 return ACPI_LEVEL_SENSITIVE;
55 setup_serial_console(int rev, struct pcdp_uart *uart)
57 #ifdef CONFIG_SERIAL_8250_CONSOLE
58 struct uart_port port;
59 static char options[16];
62 memset(&port, 0, sizeof(port));
63 port.uartclk = uart->clock_rate;
64 if (!port.uartclk) /* some FW doesn't supply this */
65 port.uartclk = BASE_BAUD * 16;
67 if (uart->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
68 port.mapbase = uart->addr.address;
69 port.membase = ioremap(port.mapbase, mapsize);
71 printk(KERN_ERR "%s: couldn't ioremap 0x%lx-0x%lx\n",
72 __FUNCTION__, port.mapbase, port.mapbase + mapsize);
75 port.iotype = UPIO_MEM;
76 } else if (uart->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
77 port.iobase = uart->addr.address;
78 port.iotype = UPIO_PORT;
82 switch (uart->pci_prog_intfc) {
83 case 0x0: port.type = PORT_8250; break;
84 case 0x1: port.type = PORT_16450; break;
85 case 0x2: port.type = PORT_16550; break;
86 case 0x3: port.type = PORT_16650; break;
87 case 0x4: port.type = PORT_16750; break;
88 case 0x5: port.type = PORT_16850; break;
89 case 0x6: port.type = PORT_16C950; break;
90 default: port.type = PORT_UNKNOWN; break;
93 port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
95 if (uart_irq_supported(rev, uart)) {
96 port.irq = acpi_register_gsi(uart->gsi,
97 uart_active_high_low(rev, uart),
98 uart_edge_level(rev, uart));
99 port.flags |= UPF_AUTO_IRQ; /* some FW reported wrong GSI */
100 if (uart_pci(rev, uart))
101 port.flags |= UPF_SHARE_IRQ;
104 if (early_serial_setup(&port) < 0)
107 snprintf(options, sizeof(options), "%lun%d", uart->baud,
108 uart->bits ? uart->bits : 8);
109 add_preferred_console("ttyS", port.line, options);
111 printk(KERN_INFO "PCDP: serial console at %s 0x%lx (ttyS%d, options %s)\n",
112 port.iotype == UPIO_MEM ? "MMIO" : "I/O",
113 uart->addr.address, port.line, options);
118 setup_vga_console(struct pcdp_vga *vga)
121 #ifdef CONFIG_VGA_CONSOLE
122 if (efi_mem_type(0xA0000) == EFI_CONVENTIONAL_MEMORY) {
123 printk(KERN_ERR "PCDP: VGA selected, but frame buffer is not MMIO!\n");
127 conswitchp = &vga_con;
128 printk(KERN_INFO "PCDP: VGA console\n");
134 efi_setup_pcdp_console(char *cmdline)
137 struct pcdp_uart *uart;
138 struct pcdp_device *dev, *end;
145 printk(KERN_INFO "PCDP: v%d at 0x%p\n", pcdp->rev, pcdp);
148 if (strstr(cmdline, "console=ttyS0") || efi_uart_console_only())
152 for (i = 0, uart = pcdp->uart; i < pcdp->num_uarts; i++, uart++) {
153 if (uart->flags & PCDP_UART_PRIMARY_CONSOLE || serial) {
154 if (uart->type == PCDP_CONSOLE_UART) {
155 setup_serial_console(pcdp->rev, uart);
161 end = (struct pcdp_device *) ((u8 *) pcdp + pcdp->length);
162 for (dev = (struct pcdp_device *) (pcdp->uart + pcdp->num_uarts);
164 dev = (struct pcdp_device *) ((u8 *) dev + dev->length)) {
165 if (dev->flags & PCDP_PRIMARY_CONSOLE) {
166 if (dev->type == PCDP_CONSOLE_VGA) {
167 setup_vga_console((struct pcdp_vga *) dev);
174 #ifdef CONFIG_IA64_EARLY_PRINTK_UART
176 hcdp_early_uart (void)
178 efi_system_table_t *systab;
179 efi_config_table_t *config_tables;
180 unsigned long addr = 0;
181 struct pcdp *pcdp = 0;
182 struct pcdp_uart *uart;
185 systab = (efi_system_table_t *) ia64_boot_param->efi_systab;
188 systab = __va(systab);
190 config_tables = (efi_config_table_t *) systab->tables;
193 config_tables = __va(config_tables);
195 for (i = 0; i < systab->nr_tables; i++) {
196 if (efi_guidcmp(config_tables[i].guid, HCDP_TABLE_GUID) == 0) {
197 pcdp = (struct pcdp *) config_tables[i].table;
205 for (i = 0, uart = pcdp->uart; i < pcdp->num_uarts; i++, uart++) {
206 if (uart->type == PCDP_CONSOLE_UART) {
207 addr = uart->addr.address;
213 #endif /* CONFIG_IA64_EARLY_PRINTK_UART */