diff options
author | Sven Schnelle <svens@stackframe.org> | 2011-04-01 07:28:56 +0000 |
---|---|---|
committer | Sven Schnelle <svens@stackframe.org> | 2011-04-01 07:28:56 +0000 |
commit | fea6bd16909a29854539c431497ccc460f3cdf7a (patch) | |
tree | 6cb1ecc72deb3ec1edfaff4f98dcb4dc45ba220e /src | |
parent | 1aba09678913404826d7581f329bfa75d26cbdca (diff) |
X60: add dock code for Ultrabase X6
Move the old docking code from romstage.c to dock.c, and use that code
both in romstage and SMM code.
Signed-off-by: Sven Schnelle <svens@stackframe.org>
Acked-by: Peter Stuge <peter@stuge.se>
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@6473 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src')
-rw-r--r-- | src/mainboard/lenovo/x60/Makefile.inc | 3 | ||||
-rw-r--r-- | src/mainboard/lenovo/x60/acpi/.ec.asl.swp | bin | 0 -> 12288 bytes | |||
-rw-r--r-- | src/mainboard/lenovo/x60/acpi/.gpe.asl.swp | bin | 0 -> 12288 bytes | |||
-rw-r--r-- | src/mainboard/lenovo/x60/acpi/dock.asl | 55 | ||||
-rw-r--r-- | src/mainboard/lenovo/x60/acpi/ec.asl | 7 | ||||
-rw-r--r-- | src/mainboard/lenovo/x60/acpi/gpe.asl | 13 | ||||
-rw-r--r-- | src/mainboard/lenovo/x60/dock.c | 249 | ||||
-rw-r--r-- | src/mainboard/lenovo/x60/dock.h | 8 | ||||
-rw-r--r-- | src/mainboard/lenovo/x60/mainboard_smi.c | 47 | ||||
-rw-r--r-- | src/mainboard/lenovo/x60/romstage.c | 88 | ||||
-rw-r--r-- | src/mainboard/lenovo/x60/smi.h | 7 |
11 files changed, 388 insertions, 89 deletions
diff --git a/src/mainboard/lenovo/x60/Makefile.inc b/src/mainboard/lenovo/x60/Makefile.inc index fb78b3d83f..75152586f8 100644 --- a/src/mainboard/lenovo/x60/Makefile.inc +++ b/src/mainboard/lenovo/x60/Makefile.inc @@ -17,4 +17,5 @@ ## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ## -smm-$(CONFIG_HAVE_SMI_HANDLER) += mainboard_smi.c +smm-$(CONFIG_HAVE_SMI_HANDLER) += mainboard_smi.c dock.c +romstage-y += dock.c diff --git a/src/mainboard/lenovo/x60/acpi/.ec.asl.swp b/src/mainboard/lenovo/x60/acpi/.ec.asl.swp Binary files differnew file mode 100644 index 0000000000..2930ae88cd --- /dev/null +++ b/src/mainboard/lenovo/x60/acpi/.ec.asl.swp diff --git a/src/mainboard/lenovo/x60/acpi/.gpe.asl.swp b/src/mainboard/lenovo/x60/acpi/.gpe.asl.swp Binary files differnew file mode 100644 index 0000000000..f5f0cc8d1a --- /dev/null +++ b/src/mainboard/lenovo/x60/acpi/.gpe.asl.swp diff --git a/src/mainboard/lenovo/x60/acpi/dock.asl b/src/mainboard/lenovo/x60/acpi/dock.asl new file mode 100644 index 0000000000..db61e059a8 --- /dev/null +++ b/src/mainboard/lenovo/x60/acpi/dock.asl @@ -0,0 +1,55 @@ +/* + * This file is part of the coreboot project. + * + * 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 + */ + +#include "smi.h" + +OperationRegion (DLPC, SystemIO, 0x164c, 1) +Field(DLPC, ByteAcc, NoLock, Preserve) +{ + , 3, + DSTA, 1, +} +Device(DOCK) +{ + Name(_HID, "ACPI0003") + Name(_UID, 0x00) + Name(_PCL, Package() { \_SB } ) + + Method(_DCK, 1, NotSerialized) + { + if (Arg0) { + Sleep(250) + /* connect dock */ + TRAP(SMI_DOCK_CONNECT) + } else { + /* disconnect dock */ + TRAP(SMI_DOCK_DISCONNECT) + } + + Xor(Arg0, DSTA, Local0) + Return (Local0) + } + + Method(_STA, 0, NotSerialized) + { + Return (DSTA) + } +} diff --git a/src/mainboard/lenovo/x60/acpi/ec.asl b/src/mainboard/lenovo/x60/acpi/ec.asl index 81532b86db..043b72ef56 100644 --- a/src/mainboard/lenovo/x60/acpi/ec.asl +++ b/src/mainboard/lenovo/x60/acpi/ec.asl @@ -19,6 +19,7 @@ * MA 02110-1301 USA */ +#include "smi.h" Device(EC) { Name (_HID, EISAID("PNP0C09")) @@ -83,6 +84,11 @@ Device(EC) \DSPC.BRTD() } + Method(_Q18, 0, NotSerialized) + { + Notify(\_SB.PCI0.LPCB.EC.DOCK, 3) + } + /* AC status change: present */ Method(_Q26, 0, NotSerialized) { @@ -111,4 +117,5 @@ Device(EC) #include "sleepbutton.asl" #include "lid.asl" #include "beep.asl" +#include "dock.asl" } diff --git a/src/mainboard/lenovo/x60/acpi/gpe.asl b/src/mainboard/lenovo/x60/acpi/gpe.asl index 1c5d1bdfd8..64e8e31e66 100644 --- a/src/mainboard/lenovo/x60/acpi/gpe.asl +++ b/src/mainboard/lenovo/x60/acpi/gpe.asl @@ -1,3 +1,4 @@ +#include "smi.h" Scope (\_GPE) { Method(_L18, 0, NotSerialized) @@ -5,4 +6,16 @@ Scope (\_GPE) /* Read EC register to clear wake status */ Store(\_SB.PCI0.LPCB.EC.WAKE, Local0) } + + /* SLICE_ON_3M GPE (Dock status) */ + Method(_L1D, 0, NotSerialized) + { + if (GP13) { + Or(GIV1, 0x20, GIV1) + Notify(\_SB.PCI0.LPCB.EC.DOCK, 3) + } else { + And(GIV1, 0xdf, GIV1) + Notify(\_SB.PCI0.LPCB.EC.DOCK, 0) + } + } } diff --git a/src/mainboard/lenovo/x60/dock.c b/src/mainboard/lenovo/x60/dock.c new file mode 100644 index 0000000000..b64d864f49 --- /dev/null +++ b/src/mainboard/lenovo/x60/dock.c @@ -0,0 +1,249 @@ +/* + * This file is part of the coreboot project. + * + * 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 + */ + +#include <console/console.h> +#include <device/device.h> +#include <arch/io.h> +#include <boot/tables.h> +#include <delay.h> +#include <arch/io.h> +#include "dock.h" +#include "southbridge/intel/i82801gx/i82801gx.h" +#include "superio/nsc/pc87392/pc87392.h" + +static void dlpc_write_register(int reg, int value) +{ + outb(reg, 0x164e); + outb(value, 0x164f); +} + +static u8 dlpc_read_register(int reg) +{ + outb(reg, 0x164e); + return inb(0x164f); +} + +static void dock_write_register(int reg, int value) +{ + outb(reg, 0x2e); + outb(value, 0x2f); +} + +static u8 dock_read_register(int reg) +{ + outb(reg, 0x2e); + return inb(0x2f); +} + +static void dlpc_gpio_set_mode(int port, int mode) +{ + dlpc_write_register(0xf0, port); + dlpc_write_register(0xf1, mode); +} + +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); +} + +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); +} + +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); + + 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; + } + + dlpc_gpio_init(); + + return 0; +} + +int dock_connect(void) +{ + int timeout = 1000; + + /* Assert D_PLTRST# */ + outb(0xfe, 0x1680); + udelay(1000); + /* Deassert D_PLTRST# */ + outb(0xff, 0x1680); + + /* startup 14.318MHz Clock */ + dock_write_register(0x29, 0x06); + /* wait until clock is settled */ + 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); + return 0; +} + +void dock_disconnect(void) +{ + /* disconnect LPC bus */ + outb(0x00, 0x164c); + /* Assert PLTRST and DLPCPD */ + outb(0xfc, 0x1680); +} + +int dock_present(void) +{ + return !((inb(DEFAULT_GPIOBASE + 0x0c) >> 13) & 1); +} diff --git a/src/mainboard/lenovo/x60/dock.h b/src/mainboard/lenovo/x60/dock.h new file mode 100644 index 0000000000..05c5cc4764 --- /dev/null +++ b/src/mainboard/lenovo/x60/dock.h @@ -0,0 +1,8 @@ +#ifndef THINKPAD_X60_DOCK_H +#define THINKPAD_X60_DOCK_H + +extern int dock_connect(void); +extern void dock_disconnect(void); +extern int dock_present(void); +extern int dlpc_init(void); +#endif diff --git a/src/mainboard/lenovo/x60/mainboard_smi.c b/src/mainboard/lenovo/x60/mainboard_smi.c index 6736ace09a..5e0f6a98b0 100644 --- a/src/mainboard/lenovo/x60/mainboard_smi.c +++ b/src/mainboard/lenovo/x60/mainboard_smi.c @@ -24,30 +24,55 @@ #include <console/console.h> #include <cpu/x86/smm.h> #include "southbridge/intel/i82801gx/nvs.h" +#include <ec/acpi/ec.h> +#include "dock.h" +#include "smi.h" /* The southbridge SMI handler checks whether gnvs has a * valid pointer before calling the trap handler */ extern global_nvs_t *gnvs; +static void mainboard_smm_init(void) +{ + printk(BIOS_DEBUG, "initializing SMI\n"); + /* Enable 0x1600/0x1600 register pair */ + ec_set_bit(0x00, 0x05); + ec_set_ports(0x1604, 0x1600); +} + int mainboard_io_trap_handler(int smif) { + static int smm_initialized; + + if (!smm_initialized) { + mainboard_smm_init(); + smm_initialized = 1; + } + switch (smif) { - case 0x99: - printk(BIOS_DEBUG, "Sample\n"); - //gnvs->smif = 0; + case SMI_DOCK_CONNECT: + dlpc_init(); + if (!dock_connect()) { + /* set dock LED to indicate status */ + ec_write(0x0c, 0x88); + } else { + /* blink dock LED to indicate failure */ + ec_write(0x0c, 0xc8); + } + break; + + case SMI_DOCK_DISCONNECT: + dock_disconnect(); + ec_write(0x0c, 0x08); break; + default: - return 0; + return 1; } /* On success, the IO Trap Handler returns 0 - * On failure, the IO Trap Handler returns a value != 0 - * - * For now, we force the return value to 0 and log all traps to - * see what's going on. - */ - //gnvs->smif = 0; - return 1; + * On failure, the IO Trap Handler returns a value != 0 */ + return 0; } diff --git a/src/mainboard/lenovo/x60/romstage.c b/src/mainboard/lenovo/x60/romstage.c index e2b4a402a5..bdc2200b55 100644 --- a/src/mainboard/lenovo/x60/romstage.c +++ b/src/mainboard/lenovo/x60/romstage.c @@ -37,6 +37,7 @@ #include "northbridge/intel/i945/i945.h" #include "northbridge/intel/i945/raminit.h" #include "southbridge/intel/i82801gx/i82801gx.h" +#include "dock.h" void setup_ich7_gpios(void) { @@ -107,78 +108,6 @@ static void pnp_write_register(device_t dev, int reg, int val) outb(val, port+1); } -static void dock_write_register(int reg, int value) -{ - outb(reg, 0x164e); - outb(value, 0x164f); - /* original software reads the chip id after every - I/O operation. Not sure if they are doing it for - some code switching depending on hardware or just - to have a delay after every operation. - - Do it the same way for now, we may remove it later - if it isn't needed - */ - outb(0x20, 0x164e); - inb(0x164f); -} - -static void dock_dlpc_init(void) -{ - /* Select DLPC module */ - dock_write_register(0x07, 0x19); - /* DLPC Base Address 0x164c */ - dock_write_register(0x60, 0x16); - dock_write_register(0x61, 0x4c); - /* Activate DLPC */ - dock_write_register(0x30, 0x01); - outb(0x07, 0x164c); - - while(!(inb(0x164c) & 8)) - udelay(100 * 100); -} - -static void dock_gpio_set_mode(int port, int mode) -{ - dock_write_register(0xf0, port); - dock_write_register(0xf1, mode); - -} - -static void dock_gpio_init(void) -{ - /* Select GPIO module */ - dock_write_register(0x07, 0x07); - /* GPIO Base Address 0x1680 */ - dock_write_register(0x60, 0x16); - dock_write_register(0x61, 0x80); - - /* Activate GPIO */ - dock_write_register(0x30, 0x01); - - dock_gpio_set_mode(0x00, 3); - dock_gpio_set_mode(0x01, 3); - dock_gpio_set_mode(0x02, 0); - dock_gpio_set_mode(0x03, 3); - dock_gpio_set_mode(0x04, 4); - dock_gpio_set_mode(0x20, 4); - dock_gpio_set_mode(0x21, 4); - dock_gpio_set_mode(0x23, 4); -} - -static void connect_dock(void) -{ - /* Enable 14.318MHz CLK on CLKIN */ - dock_write_register(0x29, 0x00); - dock_write_register(0x29, 0xa0); - dock_gpio_init(); - /* Assert D_PLTRST# */ - outb(0xfe, 0x1680); - dock_dlpc_init(); - /* Deassert D_PLTRST# */ - outb(0xff, 0x1680); -} - static void early_superio_config(void) { device_t dev; @@ -306,12 +235,17 @@ void main(unsigned long bist) ich7_enable_lpc(); - connect_dock(); - - early_superio_config(); - /* Set up the console */ - uart_init(); + /* dock_init initializes the DLPC switch on + * thinpad side, so this is required even + * if we're undocked. + */ + if (!dlpc_init() && dock_present()) { + dock_connect(); + early_superio_config(); + /* Set up the console */ + uart_init(); + } #if CONFIG_USBDEBUG i82801gx_enable_usbdebug(1); diff --git a/src/mainboard/lenovo/x60/smi.h b/src/mainboard/lenovo/x60/smi.h new file mode 100644 index 0000000000..6eb840256a --- /dev/null +++ b/src/mainboard/lenovo/x60/smi.h @@ -0,0 +1,7 @@ +#ifndef MAINBOARD_LENOVO_X60_SMI_H +#define MAINBOARD_LENOVO_X60_SMI_H + +#define SMI_DOCK_CONNECT 0x01 +#define SMI_DOCK_DISCONNECT 0x02 + +#endif |