2005-04-17 02:20:36 +04:00
/*
* Parse the EFI PCDP table to locate the console device .
*
* ( c ) Copyright 2002 , 2003 , 2004 Hewlett - Packard Development Company , L . P .
* Khalid Aziz < khalid . aziz @ hp . com >
* Alex Williamson < alex . williamson @ hp . com >
* Bjorn Helgaas < bjorn . helgaas @ hp . com >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*/
# include <linux/acpi.h>
# include <linux/console.h>
# include <linux/efi.h>
# include <linux/serial.h>
2015-03-09 23:27:22 +03:00
# include <linux/serial_core.h>
2005-04-26 00:51:00 +04:00
# include <asm/vga.h>
2005-04-17 02:20:36 +04:00
# include "pcdp.h"
static int __init
setup_serial_console ( struct pcdp_uart * uart )
{
# ifdef CONFIG_SERIAL_8250_CONSOLE
int mmio ;
2005-06-23 11:10:16 +04:00
static char options [ 64 ] , * p = options ;
2005-07-28 12:07:39 +04:00
char parity ;
2005-04-17 02:20:36 +04:00
2007-02-02 19:48:22 +03:00
mmio = ( uart - > addr . space_id = = ACPI_ADR_SPACE_SYSTEM_MEMORY ) ;
2009-05-23 00:49:49 +04:00
p + = sprintf ( p , " uart8250,%s,0x%llx " ,
2005-06-23 11:10:16 +04:00
mmio ? " mmio " : " io " , uart - > addr . address ) ;
2005-07-28 12:07:39 +04:00
if ( uart - > baud ) {
2009-05-23 00:49:49 +04:00
p + = sprintf ( p , " ,%llu " , uart - > baud ) ;
2005-07-28 12:07:39 +04:00
if ( uart - > bits ) {
switch ( uart - > parity ) {
case 0x2 : parity = ' e ' ; break ;
case 0x3 : parity = ' o ' ; break ;
default : parity = ' n ' ;
}
p + = sprintf ( p , " %c%d " , parity , uart - > bits ) ;
}
}
2005-04-17 02:20:36 +04:00
serial: convert early_uart to earlycon for 8250
Beacuse SERIAL_PORT_DFNS is removed from include/asm-i386/serial.h and
include/asm-x86_64/serial.h. the serial8250_ports need to be probed late in
serial initializing stage. the console_init=>serial8250_console_init=>
register_console=>serial8250_console_setup will return -ENDEV, and console
ttyS0 can not be enabled at that time. need to wait till uart_add_one_port in
drivers/serial/serial_core.c to call register_console to get console ttyS0.
that is too late.
Make early_uart to use early_param, so uart console can be used earlier. Make
it to be bootconsole with CON_BOOT flag, so can use console handover feature.
and it will switch to corresponding normal serial console automatically.
new command line will be:
console=uart8250,io,0x3f8,9600n8
console=uart8250,mmio,0xff5e0000,115200n8
or
earlycon=uart8250,io,0x3f8,9600n8
earlycon=uart8250,mmio,0xff5e0000,115200n8
it will print in very early stage:
Early serial console at I/O port 0x3f8 (options '9600n8')
console [uart0] enabled
later for console it will print:
console handover: boot [uart0] -> real [ttyS0]
Signed-off-by: <yinghai.lu@sun.com>
Cc: Andi Kleen <ak@suse.de>
Cc: Bjorn Helgaas <bjorn.helgaas@hp.com>
Cc: Russell King <rmk@arm.linux.org.uk>
Cc: Gerd Hoffmann <kraxel@suse.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-07-16 10:37:59 +04:00
add_preferred_console ( " uart " , 8250 , & options [ 9 ] ) ;
2015-03-09 23:27:22 +03:00
return setup_earlycon ( options ) ;
2005-04-17 02:20:36 +04:00
# else
return - ENODEV ;
# endif
}
static int __init
2005-04-26 00:51:00 +04:00
setup_vga_console ( struct pcdp_device * dev )
2005-04-17 02:20:36 +04:00
{
# if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE)
2005-04-26 00:51:00 +04:00
u8 * if_ptr ;
if_ptr = ( ( u8 * ) dev + sizeof ( struct pcdp_device ) ) ;
if ( if_ptr [ 0 ] = = PCDP_IF_PCI ) {
struct pcdp_if_pci if_pci ;
/* struct copy since ifptr might not be correctly aligned */
memcpy ( & if_pci , if_ptr , sizeof ( if_pci ) ) ;
if ( if_pci . trans & PCDP_PCI_TRANS_IOPORT )
vga_console_iobase = if_pci . ioport_tra ;
if ( if_pci . trans & PCDP_PCI_TRANS_MMIO )
vga_console_membase = if_pci . mmio_tra ;
}
if ( efi_mem_type ( vga_console_membase + 0xA0000 ) = = EFI_CONVENTIONAL_MEMORY ) {
2005-04-17 02:20:36 +04:00
printk ( KERN_ERR " PCDP: VGA selected, but frame buffer is not MMIO! \n " ) ;
return - ENODEV ;
}
conswitchp = & vga_con ;
printk ( KERN_INFO " PCDP: VGA console \n " ) ;
return 0 ;
# else
return - ENODEV ;
# endif
}
int __init
efi_setup_pcdp_console ( char * cmdline )
{
struct pcdp * pcdp ;
struct pcdp_uart * uart ;
struct pcdp_device * dev , * end ;
int i , serial = 0 ;
2006-03-26 13:37:08 +04:00
int rc = - ENODEV ;
2005-04-17 02:20:36 +04:00
2006-03-26 13:37:08 +04:00
if ( efi . hcdp = = EFI_INVALID_TABLE_ADDR )
2005-04-17 02:20:36 +04:00
return - ENODEV ;
2017-07-18 00:10:00 +03:00
pcdp = early_memremap ( efi . hcdp , 4096 ) ;
2006-03-26 13:37:08 +04:00
printk ( KERN_INFO " PCDP: v%d at 0x%lx \n " , pcdp - > rev , efi . hcdp ) ;
2005-04-17 02:20:36 +04:00
if ( strstr ( cmdline , " console=hcdp " ) ) {
if ( pcdp - > rev < 3 )
serial = 1 ;
} else if ( strstr ( cmdline , " console= " ) ) {
printk ( KERN_INFO " Explicit \" console= \" ; ignoring PCDP \n " ) ;
2006-03-26 13:37:08 +04:00
goto out ;
2005-04-17 02:20:36 +04:00
}
if ( pcdp - > rev < 3 & & efi_uart_console_only ( ) )
serial = 1 ;
for ( i = 0 , uart = pcdp - > uart ; i < pcdp - > num_uarts ; i + + , uart + + ) {
if ( uart - > flags & PCDP_UART_PRIMARY_CONSOLE | | serial ) {
if ( uart - > type = = PCDP_CONSOLE_UART ) {
2006-03-26 13:37:08 +04:00
rc = setup_serial_console ( uart ) ;
goto out ;
2005-04-17 02:20:36 +04:00
}
}
}
end = ( struct pcdp_device * ) ( ( u8 * ) pcdp + pcdp - > length ) ;
for ( dev = ( struct pcdp_device * ) ( pcdp - > uart + pcdp - > num_uarts ) ;
dev < end ;
dev = ( struct pcdp_device * ) ( ( u8 * ) dev + dev - > length ) ) {
if ( dev - > flags & PCDP_PRIMARY_CONSOLE ) {
if ( dev - > type = = PCDP_CONSOLE_VGA ) {
2006-03-26 13:37:08 +04:00
rc = setup_vga_console ( dev ) ;
goto out ;
2005-04-17 02:20:36 +04:00
}
}
}
2006-03-26 13:37:08 +04:00
out :
2017-07-18 00:10:00 +03:00
early_memunmap ( pcdp , 4096 ) ;
2006-03-26 13:37:08 +04:00
return rc ;
2005-04-17 02:20:36 +04:00
}