Allow libpayload to use an OXPCIe 952 card on systems without

onboard serial port                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                         
Signed-off-by: Stefan Reinauer <reinauer@google.com>                                                                                                                                                                                                                     
Acked-by:  Marc Jones <marcj303@gmail.com>                                                                                                                                                                                                                               



git-svn-id: svn://svn.coreboot.org/coreboot/trunk@6508 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
Stefan Reinauer 2011-04-16 00:13:17 +00:00 committed by Stefan Reinauer
parent a7163f1eb9
commit 4e67731011
3 changed files with 87 additions and 7 deletions

View File

@ -32,9 +32,11 @@
#include <libpayload.h> #include <libpayload.h>
#define IOBASE lib_sysinfo.ser_ioport #define IOBASE lib_sysinfo.ser_ioport
#define MEMBASE (phys_to_virt(lib_sysinfo.ser_base))
#define DIVISOR(x) (115200 / x) #define DIVISOR(x) (115200 / x)
void serial_hardware_init(int port, int speed, int word_bits, int parity, int stop_bits) #ifdef CONFIG_SERIAL_SET_SPEED
static void serial_io_hardware_init(int port, int speed, int word_bits, int parity, int stop_bits)
{ {
unsigned char reg; unsigned char reg;
@ -58,6 +60,31 @@ void serial_hardware_init(int port, int speed, int word_bits, int parity, int st
outb(reg & ~0x80, port + 0x03); outb(reg & ~0x80, port + 0x03);
} }
static void serial_mem_hardware_init(int port, int speed, int word_bits, int parity, int stop_bits)
{
unsigned char reg;
/* We will assume 8n1 for now. Does anyone use anything else these days? */
/* Disable interrupts. */
writeb(0, MEMBASE + 0x01);
/* Assert RTS and DTR. */
writeb(3, MEMBASE + 0x04);
/* Set the divisor latch. */
reg = readb(MEMBASE + 0x03);
writeb(reg | 0x80, MEMBASE + 0x03);
/* Write the divisor. */
writeb(DIVISOR(speed) & 0xFF, MEMBASE);
writeb(DIVISOR(speed) >> 8 & 0xFF, MEMBASE + 1);
/* Restore the previous value of the divisor. */
writeb(reg & ~0x80, MEMBASE + 0x03);
}
#endif
static struct console_input_driver consin = { static struct console_input_driver consin = {
.havekey = serial_havechar, .havekey = serial_havechar,
.getchar = serial_getchar .getchar = serial_getchar
@ -69,29 +96,82 @@ static struct console_output_driver consout = {
void serial_init(void) void serial_init(void)
{ {
pcidev_t oxpcie_dev;
if (pci_find_device(0x1415, 0xc158, &oxpcie_dev)) {
lib_sysinfo.ser_base = pci_read_resource(oxpcie_dev, 0) + 0x1000;
} else {
lib_sysinfo.ser_base = 0;
}
#ifdef CONFIG_SERIAL_SET_SPEED #ifdef CONFIG_SERIAL_SET_SPEED
serial_hardware_init(IOBASE, CONFIG_SERIAL_BAUD_RATE, 8, 0, 1); if (lib_sysinfo.ser_base)
serial_mem_hardware_init(IOBASE, CONFIG_SERIAL_BAUD_RATE, 8, 0, 1);
else
serial_io_hardware_init(IOBASE, CONFIG_SERIAL_BAUD_RATE, 8, 0, 1);
#endif #endif
console_add_input_driver(&consin); console_add_input_driver(&consin);
console_add_output_driver(&consout); console_add_output_driver(&consout);
} }
void serial_putchar(unsigned int c) static void serial_io_putchar(unsigned int c)
{ {
c &= 0xff; c &= 0xff;
while ((inb(IOBASE + 0x05) & 0x20) == 0) ; while ((inb(IOBASE + 0x05) & 0x20) == 0) ;
outb(c, IOBASE); outb(c, IOBASE);
} }
int serial_havechar(void) static int serial_io_havechar(void)
{ {
return inb(IOBASE + 0x05) & 0x01; return inb(IOBASE + 0x05) & 0x01;
} }
static int serial_io_getchar(void)
{
while (!serial_io_havechar()) ;
return (int)inb(IOBASE);
}
static void serial_mem_putchar(unsigned int c)
{
c &= 0xff;
while ((readb(MEMBASE + 0x05) & 0x20) == 0) ;
writeb(c, MEMBASE);
}
static int serial_mem_havechar(void)
{
return readb(MEMBASE + 0x05) & 0x01;
}
static int serial_mem_getchar(void)
{
while (!serial_mem_havechar()) ;
return (int)readb(MEMBASE);
}
void serial_putchar(unsigned int c)
{
if (lib_sysinfo.ser_base)
serial_mem_putchar(c);
else
serial_io_putchar(c);
}
int serial_havechar(void)
{
if (lib_sysinfo.ser_base)
return serial_mem_havechar();
else
return serial_io_havechar();
}
int serial_getchar(void) int serial_getchar(void)
{ {
while (!serial_havechar()) ; if (lib_sysinfo.ser_base)
return (int)inb(IOBASE); return serial_mem_getchar();
else
return serial_io_getchar();
} }
/* These are thinly veiled vt100 functions used by curses */ /* These are thinly veiled vt100 functions used by curses */

View File

@ -153,7 +153,6 @@ int keyboard_set_layout(char *country);
* @{ * @{
*/ */
void serial_init(void); void serial_init(void);
void serial_hardware_init(int port, int speed, int word_bits, int parity, int stop_bits);
void serial_putchar(unsigned int c); void serial_putchar(unsigned int c);
int serial_havechar(void); int serial_havechar(void);
int serial_getchar(void); int serial_getchar(void);

View File

@ -36,6 +36,7 @@
struct sysinfo_t { struct sysinfo_t {
unsigned int cpu_khz; unsigned int cpu_khz;
unsigned short ser_ioport; unsigned short ser_ioport;
unsigned long ser_base; // for mmapped serial
int n_memranges; int n_memranges;