Denis Carikli (GNUtoo@no-log.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/3260
-gerrit
commit 6b8a7ddb359d8fcbc01a71cc0d9a3a2ac369a1a1 Author: Denis 'GNUtoo' Carikli GNUtoo@no-log.org Date: Thu May 16 23:40:24 2013 +0200
Add support for Lenovo X60.
Change-Id: I105c69ae53b3735fd60e7461f8f64078e8fef15c Signed-off-by: Denis 'GNUtoo' Carikli GNUtoo@no-log.org --- SerialICE/Kconfig | 4 + SerialICE/mainboard/lenovo_x60.c | 363 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 367 insertions(+)
diff --git a/SerialICE/Kconfig b/SerialICE/Kconfig index 089ac13..5837e09 100644 --- a/SerialICE/Kconfig +++ b/SerialICE/Kconfig @@ -130,6 +130,9 @@ config BOARD_ASROCK_775I65G config BOARD_COMMELL_LV_672 bool "Commell LV-672"
+config BOARD_LENOVO_X60 + bool "Lenovo X60" + endchoice
config BOARD_INIT @@ -163,6 +166,7 @@ config BOARD_INIT default "intel_d845gbv2.c" if BOARD_INTEL_D845GBV2 default "asrock_775i65g.c" if BOARD_ASROCK_775I65G default "commell_lv_672.c" if BOARD_COMMELL_LV_672 + default "lenovo_x60.c" if BOARD_LENOVO_X60
config SOUTHBRIDGE_INIT string diff --git a/SerialICE/mainboard/lenovo_x60.c b/SerialICE/mainboard/lenovo_x60.c new file mode 100644 index 0000000..f9ce792 --- /dev/null +++ b/SerialICE/mainboard/lenovo_x60.c @@ -0,0 +1,363 @@ +/* + * SerialICE + * + * Adapted by: + * Copyright (C) 2013 Denis 'GNUtoo' Carikli GNUtoo@no-log.org + * from Coreboot's src/mainboard/lenovo/x60/romstage.c which has: + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2011 Sven Schnelle svens@stackframe.org + * + * 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 + */ + +#define PC87392_GPIO_PIN_DEBOUNCE 0x40 +#define PC87392_GPIO_PIN_PULLUP 0x04 +#define PC87392_GPIO_PIN_TRIGGERS_SMI 0x02 +#define PC87392_GPIO_PIN_OE 0x01 +#define PC87392_GPIO_PIN_TYPE_PUSH_PULL 0x02 +#define PNP_IDX_IO0 0x60 +#define BCTRL 0x3e +#define SBR (1 << 6) +#define DEFAULT_GPIOBASE 0x0480 + +#define PNP_DEV(PORT, FUNC) (((PORT) << 8) | (FUNC)) + +typedef unsigned device_t; /* pci and pci_mmio need to have different ways to have dev */ +typedef unsigned char uint8_t; + +const char boardname[33]="Lenovo X60 "; + +void udelay(unsigned usecs) +{ + int i; + for(i = 0; i < usecs; i++) + inb(0x80); +} + +static u8 dock_read_register(int reg) +{ + outb(reg, 0x2e); + return inb(0x2f); +} + +static void dlpc_write_register(int reg, int value) +{ + outb(reg, 0x164e); + outb(value, 0x164f); +} + +static void dock_write_register(int reg, int value) +{ + outb(reg, 0x2e); + outb(value, 0x2f); +} + +static void dock_gpio_set_mode(int port, int mode, int irq) +{ + dock_write_register(0xf0, port); + dock_write_register(0xf1, mode); + dock_write_register(0xf2, irq); +} + +int dock_connect(void) +{ + int timeout = 1000; + + outb(0x07, 0x164c); + + timeout = 1000; + + while(!(inb(0x164c) & 8) && timeout--) + udelay(1000); + + if (!timeout) { + /* docking failed, disable DLPC switch */ + outb(0x00, 0x164c); + dlpc_write_register(0x30, 0x00); + return 1; + } + + /* Assert D_PLTRST# */ + outb(0xfe, 0x1680); + udelay(100000); + /* Deassert D_PLTRST# */ + outb(0xff, 0x1680); + + udelay(100000); + + /* startup 14.318MHz Clock */ + dock_write_register(0x29, 0x06); + /* wait until clock is settled */ + timeout = 1000; + while(!(dock_read_register(0x29) & 0x08) && timeout--) + udelay(1000); + + if (!timeout) + return 1; + + /* Pin 6: CLKRUN + * Pin 72: #DR1 + * Pin 19: #SMI + * Pin 73: #MTR + */ + dock_write_register(0x24, 0x37); + + /* PNF active HIGH */ + dock_write_register(0x25, 0xa0); + + /* disable FDC */ + dock_write_register(0x26, 0x01); + + /* Enable GPIO IRQ to #SMI */ + dock_write_register(0x28, 0x02); + + /* select GPIO */ + dock_write_register(0x07, 0x07); + + /* set base address */ + dock_write_register(0x60, 0x16); + dock_write_register(0x61, 0x20); + + /* init GPIO pins */ + dock_gpio_set_mode(0x00, PC87392_GPIO_PIN_DEBOUNCE | + PC87392_GPIO_PIN_PULLUP, 0x00); + + dock_gpio_set_mode(0x01, PC87392_GPIO_PIN_DEBOUNCE | + PC87392_GPIO_PIN_PULLUP, + PC87392_GPIO_PIN_TRIGGERS_SMI); + + dock_gpio_set_mode(0x02, PC87392_GPIO_PIN_PULLUP, 0x00); + dock_gpio_set_mode(0x03, PC87392_GPIO_PIN_PULLUP, 0x00); + dock_gpio_set_mode(0x04, PC87392_GPIO_PIN_PULLUP, 0x00); + dock_gpio_set_mode(0x05, PC87392_GPIO_PIN_PULLUP, 0x00); + dock_gpio_set_mode(0x06, PC87392_GPIO_PIN_PULLUP, 0x00); + dock_gpio_set_mode(0x07, PC87392_GPIO_PIN_PULLUP, 0x02); + + dock_gpio_set_mode(0x10, PC87392_GPIO_PIN_DEBOUNCE | + PC87392_GPIO_PIN_PULLUP, + PC87392_GPIO_PIN_TRIGGERS_SMI); + + dock_gpio_set_mode(0x11, PC87392_GPIO_PIN_PULLUP, 0x00); + dock_gpio_set_mode(0x12, PC87392_GPIO_PIN_PULLUP, 0x00); + dock_gpio_set_mode(0x13, PC87392_GPIO_PIN_PULLUP, 0x00); + dock_gpio_set_mode(0x14, PC87392_GPIO_PIN_PULLUP, 0x00); + dock_gpio_set_mode(0x15, PC87392_GPIO_PIN_PULLUP, 0x00); + dock_gpio_set_mode(0x16, PC87392_GPIO_PIN_PULLUP | + PC87392_GPIO_PIN_OE , 0x00); + + dock_gpio_set_mode(0x17, PC87392_GPIO_PIN_PULLUP, 0x00); + + dock_gpio_set_mode(0x20, PC87392_GPIO_PIN_TYPE_PUSH_PULL | + PC87392_GPIO_PIN_OE, 0x00); + + dock_gpio_set_mode(0x21, PC87392_GPIO_PIN_TYPE_PUSH_PULL | + PC87392_GPIO_PIN_OE, 0x00); + + dock_gpio_set_mode(0x22, PC87392_GPIO_PIN_PULLUP, 0x00); + dock_gpio_set_mode(0x23, PC87392_GPIO_PIN_PULLUP, 0x00); + dock_gpio_set_mode(0x24, PC87392_GPIO_PIN_PULLUP, 0x00); + dock_gpio_set_mode(0x25, PC87392_GPIO_PIN_PULLUP, 0x00); + dock_gpio_set_mode(0x26, PC87392_GPIO_PIN_PULLUP, 0x00); + dock_gpio_set_mode(0x27, PC87392_GPIO_PIN_PULLUP, 0x00); + + dock_gpio_set_mode(0x30, PC87392_GPIO_PIN_PULLUP, 0x00); + dock_gpio_set_mode(0x31, PC87392_GPIO_PIN_PULLUP, 0x00); + dock_gpio_set_mode(0x32, PC87392_GPIO_PIN_PULLUP, 0x00); + dock_gpio_set_mode(0x33, PC87392_GPIO_PIN_PULLUP, 0x00); + dock_gpio_set_mode(0x34, PC87392_GPIO_PIN_PULLUP, 0x00); + + dock_gpio_set_mode(0x35, PC87392_GPIO_PIN_PULLUP | + PC87392_GPIO_PIN_OE, 0x00); + + dock_gpio_set_mode(0x36, PC87392_GPIO_PIN_PULLUP, 0x00); + dock_gpio_set_mode(0x37, PC87392_GPIO_PIN_PULLUP, 0x00); + + /* enable GPIO */ + dock_write_register(0x30, 0x01); + + outb(0x00, 0x1628); + outb(0x00, 0x1623); + outb(0x82, 0x1622); + outb(0xff, 0x1624); + + /* Enable USB and Ultrabay power */ + outb(0x03, 0x1628); + + dock_write_register(0x07, 0x03); + dock_write_register(0x30, 0x01); + + return 0; +} + +void pnp_write_config(device_t dev, uint8_t reg, uint8_t value) +{ + unsigned port = dev >> 8; + outb(reg, port ); + outb(value, port +1); +} +uint8_t pnp_read_config(device_t dev, uint8_t reg) +{ + unsigned port = dev >> 8; + outb(reg, port); + return inb(port +1); +} + +void pnp_set_iobase(device_t dev, unsigned index, unsigned iobase) +{ + pnp_write_config(dev, index + 0, (iobase >> 8) & 0xff); + pnp_write_config(dev, index + 1, iobase & 0xff); +} + +#if 0 //TODO +void pnp_set_logical_device(device_t dev) +{ + unsigned device = dev & 0xff; + pnp_write_config(dev, 0x07, device); +} +#endif +static void early_superio_config(void) +{ + int timeout = 100000; + device_t dev = PNP_DEV(0x2e, 3); + + pnp_write_config(dev, 0x29, 0x06); + + while (!(pnp_read_config(dev, 0x29) & 0x08) && timeout--) + udelay(1000); + + /* Enable COM1 */ + pnp_set_logical_device(0x2e, 3); + pnp_set_iobase(dev, PNP_IDX_IO0, 0x3f8); + pnp_set_enable(dev, 1); +} + +static void ich7_enable_lpc(void) +{ + // Enable Serial IRQ + pci_write_config8(PCI_ADDR(0, 0x1f, 0, 0x64), 0xd0); + // decode range + pci_write_config16(PCI_ADDR(0, 0x1f, 0, 0x80), 0x0210); + // decode range + pci_write_config16(PCI_ADDR(0, 0x1f, 0, 0x82), 0x1f0d); + + /* range 0x1600 - 0x167f */ + pci_write_config16(PCI_ADDR(0, 0x1f, 0, 0x84), 0x1601); + pci_write_config16(PCI_ADDR(0, 0x1f, 0, 0x86), 0x007c); + + /* range 0x15e0 - 0x10ef */ + pci_write_config16(PCI_ADDR(0, 0x1f, 0, 0x88), 0x15e1); + pci_write_config16(PCI_ADDR(0, 0x1f, 0, 0x8a), 0x000c); + + /* range 0x1680 - 0x169f */ + pci_write_config16(PCI_ADDR(0, 0x1f, 0, 0x8c), 0x1681); + pci_write_config16(PCI_ADDR(0, 0x1f, 0, 0x8e), 0x001c); +} + +static void dlpc_gpio_set_mode(int port, int mode) +{ + dlpc_write_register(0xf0, port); + dlpc_write_register(0xf1, mode); +} + +static void dlpc_gpio_init(void) +{ + /* Select GPIO module */ + dlpc_write_register(0x07, 0x07); + /* GPIO Base Address 0x1680 */ + dlpc_write_register(0x60, 0x16); + dlpc_write_register(0x61, 0x80); + + /* Activate GPIO */ + dlpc_write_register(0x30, 0x01); + + dlpc_gpio_set_mode(0x00, 3); + dlpc_gpio_set_mode(0x01, 3); + dlpc_gpio_set_mode(0x02, 0); + dlpc_gpio_set_mode(0x03, 3); + dlpc_gpio_set_mode(0x04, 4); + dlpc_gpio_set_mode(0x20, 4); + dlpc_gpio_set_mode(0x21, 4); + dlpc_gpio_set_mode(0x23, 4); +} + + +static void southbridge_init(void) +{ +#if 0 //TODO + if (bist == 0) + enable_lapic(); +#endif + /* Force PCIRST# */ + pci_write_config16(PCI_ADDR(0, 0x1e, 0, BCTRL), SBR); + udelay(200 * 1000); + pci_write_config16(PCI_ADDR(0, 0x1e, 0, BCTRL), 0); + + ich7_enable_lpc(); +} + +int dock_present(void) +{ + return !((inb(DEFAULT_GPIOBASE + 0x0c) >> 13) & 1); +} + +static u8 dlpc_read_register(int reg) +{ + outb(reg, 0x164e); + return inb(0x164f); +} + +int dlpc_init(void) +{ + int timeout = 1000; + + /* Enable 14.318MHz CLK on CLKIN */ + dlpc_write_register(0x29, 0xa0); + while(!(dlpc_read_register(0x29) & 0x10) && timeout--) + udelay(1000); + + if (!timeout) + return 1; + + /* Select DLPC module */ + dlpc_write_register(0x07, 0x19); + /* DLPC Base Address 0x164c */ + dlpc_write_register(0x60, 0x16); + dlpc_write_register(0x61, 0x4c); + /* Activate DLPC */ + dlpc_write_register(0x30, 0x01); + + dlpc_gpio_init(); + + return 0; +} + +static void superio_init(void) +{ + dlpc_init(); + /* dock_init initializes the DLPC switch on + * thinpad side, so this is required even + * if we're undocked. + */ + if (dock_present()) { + dock_connect(); + early_superio_config(); + } +} + +static void chipset_init(void) +{ + southbridge_init(); + superio_init(); +} +