Author: svens Date: Fri Apr 1 09:28:56 2011 New Revision: 6473 URL: https://tracker.coreboot.org/trac/coreboot/changeset/6473
Log: 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
Added: trunk/src/mainboard/lenovo/x60/acpi/.ec.asl.swp trunk/src/mainboard/lenovo/x60/acpi/.gpe.asl.swp trunk/src/mainboard/lenovo/x60/acpi/dock.asl - copied, changed from r6472, trunk/src/mainboard/lenovo/x60/mainboard_smi.c trunk/src/mainboard/lenovo/x60/dock.c trunk/src/mainboard/lenovo/x60/dock.h trunk/src/mainboard/lenovo/x60/smi.h Modified: trunk/src/mainboard/lenovo/x60/Makefile.inc trunk/src/mainboard/lenovo/x60/acpi/ec.asl trunk/src/mainboard/lenovo/x60/acpi/gpe.asl trunk/src/mainboard/lenovo/x60/mainboard_smi.c trunk/src/mainboard/lenovo/x60/romstage.c
Modified: trunk/src/mainboard/lenovo/x60/Makefile.inc ============================================================================== --- trunk/src/mainboard/lenovo/x60/Makefile.inc Fri Apr 1 09:28:50 2011 (r6472) +++ trunk/src/mainboard/lenovo/x60/Makefile.inc Fri Apr 1 09:28:56 2011 (r6473) @@ -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
Added: trunk/src/mainboard/lenovo/x60/acpi/.ec.asl.swp ============================================================================== Files /dev/null 00:00:00 1970 (empty, because file is newly added) and trunk/src/mainboard/lenovo/x60/acpi/.ec.asl.swp Fri Apr 1 09:28:56 2011 (r6473) differ
Added: trunk/src/mainboard/lenovo/x60/acpi/.gpe.asl.swp ============================================================================== Files /dev/null 00:00:00 1970 (empty, because file is newly added) and trunk/src/mainboard/lenovo/x60/acpi/.gpe.asl.swp Fri Apr 1 09:28:56 2011 (r6473) differ
Copied and modified: trunk/src/mainboard/lenovo/x60/acpi/dock.asl (from r6472, trunk/src/mainboard/lenovo/x60/mainboard_smi.c) ============================================================================== --- trunk/src/mainboard/lenovo/x60/mainboard_smi.c Fri Apr 1 09:28:50 2011 (r6472, copy source) +++ trunk/src/mainboard/lenovo/x60/acpi/dock.asl Fri Apr 1 09:28:56 2011 (r6473) @@ -1,7 +1,7 @@ /* * This file is part of the coreboot project. * - * Copyright (C) 2008-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 @@ -19,35 +19,37 @@ * MA 02110-1301 USA */
-#include <arch/io.h> -#include <arch/romcc_io.h> -#include <console/console.h> -#include <cpu/x86/smm.h> -#include "southbridge/intel/i82801gx/nvs.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; - -int mainboard_io_trap_handler(int smif) +OperationRegion (DLPC, SystemIO, 0x164c, 1) +Field(DLPC, ByteAcc, NoLock, Preserve) +{ + , 3, + DSTA, 1, +} +Device(DOCK) { - switch (smif) { - case 0x99: - printk(BIOS_DEBUG, "Sample\n"); - //gnvs->smif = 0; - break; - default: - return 0; + 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) }
- /* 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; + Method(_STA, 0, NotSerialized) + { + Return (DSTA) + } } -
Modified: trunk/src/mainboard/lenovo/x60/acpi/ec.asl ============================================================================== --- trunk/src/mainboard/lenovo/x60/acpi/ec.asl Fri Apr 1 09:28:50 2011 (r6472) +++ trunk/src/mainboard/lenovo/x60/acpi/ec.asl Fri Apr 1 09:28:56 2011 (r6473) @@ -19,6 +19,7 @@ * MA 02110-1301 USA */
+#include "smi.h" Device(EC) { Name (_HID, EISAID("PNP0C09")) @@ -83,6 +84,11 @@ \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 @@ #include "sleepbutton.asl" #include "lid.asl" #include "beep.asl" +#include "dock.asl" }
Modified: trunk/src/mainboard/lenovo/x60/acpi/gpe.asl ============================================================================== --- trunk/src/mainboard/lenovo/x60/acpi/gpe.asl Fri Apr 1 09:28:50 2011 (r6472) +++ trunk/src/mainboard/lenovo/x60/acpi/gpe.asl Fri Apr 1 09:28:56 2011 (r6473) @@ -1,3 +1,4 @@ +#include "smi.h" Scope (_GPE) { Method(_L18, 0, NotSerialized) @@ -5,4 +6,16 @@ /* 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) + } + } }
Added: trunk/src/mainboard/lenovo/x60/dock.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ trunk/src/mainboard/lenovo/x60/dock.c Fri Apr 1 09:28:56 2011 (r6473) @@ -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); +}
Added: trunk/src/mainboard/lenovo/x60/dock.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ trunk/src/mainboard/lenovo/x60/dock.h Fri Apr 1 09:28:56 2011 (r6473) @@ -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
Modified: trunk/src/mainboard/lenovo/x60/mainboard_smi.c ============================================================================== --- trunk/src/mainboard/lenovo/x60/mainboard_smi.c Fri Apr 1 09:28:50 2011 (r6472) +++ trunk/src/mainboard/lenovo/x60/mainboard_smi.c Fri Apr 1 09:28:56 2011 (r6473) @@ -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; }
Modified: trunk/src/mainboard/lenovo/x60/romstage.c ============================================================================== --- trunk/src/mainboard/lenovo/x60/romstage.c Fri Apr 1 09:28:50 2011 (r6472) +++ trunk/src/mainboard/lenovo/x60/romstage.c Fri Apr 1 09:28:56 2011 (r6473) @@ -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 @@ 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 @@
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);
Added: trunk/src/mainboard/lenovo/x60/smi.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ trunk/src/mainboard/lenovo/x60/smi.h Fri Apr 1 09:28:56 2011 (r6473) @@ -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