Stefan Reinauer (stefan.reinauer@coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/823
-gerrit
commit 56eca08e465dce889c18eba8020196fa41d3bfff Author: Stefan Reinauer reinauer@chromium.org Date: Fri Mar 30 15:06:04 2012 -0700
Add support for SMSC LPC47N207 SuperI/O chip
This includes only early serial support for now.
Change-Id: I9a2a439e1d17a989428033fdb4a4b813553dab6d Signed-off-by: Vadim Bendebury vbendeb@chromium.org Signed-off-by: Stefan Reinauer reinauer@google.com --- src/superio/smsc/lpc47n207/early_serial.c | 122 +++++++++++++++++++++++++++++ src/superio/smsc/lpc47n207/lpc47n207.h | 25 ++++++ 2 files changed, 147 insertions(+), 0 deletions(-)
diff --git a/src/superio/smsc/lpc47n207/early_serial.c b/src/superio/smsc/lpc47n207/early_serial.c new file mode 100644 index 0000000..41e1b10 --- /dev/null +++ b/src/superio/smsc/lpc47n207/early_serial.c @@ -0,0 +1,122 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 The ChromiumOS Authors. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * This code tries to discover the SMSC LPC47N207 superio chip which can be + * connected over an LPC dongle. The chip could be bootstrap mapped to one of + * four LPC addresses: 0x2e, 0x4e, 0x162e, and 0x164e. + * + * Initializing the UART requires accesses to a few control registers. This + * structure includes the register offset and the value to write (along with + * the mask). + */ +typedef struct { + u8 conf_reg; + u8 value; + u8 mask; +} uart_conf; + +/* All regs/values to write to initialize the LPC47N207 UART */ +static const uart_conf uart_conf_data [] = { + {2, (1 << 3), (1 << 3)}, /* cr02, enable Primary UART power */ + {0xc, (1 << 6), (1 << 6)}, /* cr0c, enable Primary UART high speed */ + {0x24, (CONFIG_TTYS0_BASE >> 3) << 1, 0xff}, /* cr24, base addr */ +}; + +void try_enabling_LPC47N207_uart(void) +{ + device_t dev = PCH_LPC_DEV; + u16 saved_basic_config; + u16 saved_extended_config; + u8 reg_value; + const uart_conf* conf_item; + u16 lpc_ports[] = {0x2e, 0x4e, 0x162e, 0x164e}; + u16 lpc_port; + int i, j; + + /* preserve the LPC controller conffguration */ + saved_basic_config = pci_read_config16(dev, LPC_EN); + saved_extended_config = pci_read_config32(dev, LPC_GEN1_DEC); + + /* enable COMA mapping and all possible LPC addresses of 47N207 */ + pci_write_config16(dev, LPC_EN, + saved_basic_config | + CNF1_LPC_EN | CNF2_LPC_EN | COMA_LPC_EN); + + /* map full 256 bytes at 0x1600 to the LPC bus */ + pci_write_config32(dev, LPC_GEN1_DEC, 0xfc1601); + + /* Set COM1/COM2 decode range */ + pci_write_config16(dev, LPC_IO_DEC, 0x0010); + +#define CONFIG_ENABLE 0x55 +#define CONFIG_DISABLE 0xaa + + for (j = 0; j < ARRAY_SIZE(lpc_ports); j++) { + lpc_port = lpc_ports[j]; + + /* enable CONFIG mode */ + outb(CONFIG_ENABLE, lpc_port); + reg_value=inb(lpc_port); + if (reg_value != CONFIG_ENABLE) { + continue; /* There is no LPC device at this address */ + } + + do { + /* + * Registers 12 and 13 hold config address, look for a + * match. + */ + outb(0x12, lpc_port); + reg_value=inb(lpc_port + 1); + if (reg_value != (lpc_port & 0xff)) + break; + + outb(0x13, lpc_port); + reg_value=inb(lpc_port + 1); + if (reg_value != (lpc_port >> 8)) + break; + + /* This must be the SMSC LPC 47N207, enable the UART. */ + for (i = 0; i < ARRAY_SIZE(uart_conf_data); i++) { + u8 reg, value, mask; + + conf_item = uart_conf_data + i; + + reg = conf_item->conf_reg; + value = conf_item->value; + mask = conf_item->mask; + + outb(reg, lpc_port); + reg_value = inb(lpc_port + 1); + reg_value &= ~mask; + reg_value |= (value & mask); + outb(reg_value, lpc_port + 1); + } + /* Keep COMA UART enable bit on */ + saved_basic_config |= COMA_LPC_EN; + } while (0); + outb(CONFIG_DISABLE, lpc_port); + } + + /* Restore PCH config state. */ + pci_write_config16(dev, LPC_EN, saved_basic_config); + pci_write_config32(dev, LPC_GEN1_DEC, saved_extended_config); + +} diff --git a/src/superio/smsc/lpc47n207/lpc47n207.h b/src/superio/smsc/lpc47n207/lpc47n207.h new file mode 100644 index 0000000..69689a4 --- /dev/null +++ b/src/superio/smsc/lpc47n207/lpc47n207.h @@ -0,0 +1,25 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 The ChromiumOS Authors. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SUPERIO_SMSC_LPC47N207_LPC47N207_H +#define SUPERIO_SMSC_LPC47N207_LPC47N207_H + +extern void try_enabling_LPC47N207_uart(void); + +#endif