summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSven Schnelle <svens@stackframe.org>2011-04-01 07:28:56 +0000
committerSven Schnelle <svens@stackframe.org>2011-04-01 07:28:56 +0000
commitfea6bd16909a29854539c431497ccc460f3cdf7a (patch)
tree6cb1ecc72deb3ec1edfaff4f98dcb4dc45ba220e
parent1aba09678913404826d7581f329bfa75d26cbdca (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
-rw-r--r--src/mainboard/lenovo/x60/Makefile.inc3
-rw-r--r--src/mainboard/lenovo/x60/acpi/.ec.asl.swpbin0 -> 12288 bytes
-rw-r--r--src/mainboard/lenovo/x60/acpi/.gpe.asl.swpbin0 -> 12288 bytes
-rw-r--r--src/mainboard/lenovo/x60/acpi/dock.asl55
-rw-r--r--src/mainboard/lenovo/x60/acpi/ec.asl7
-rw-r--r--src/mainboard/lenovo/x60/acpi/gpe.asl13
-rw-r--r--src/mainboard/lenovo/x60/dock.c249
-rw-r--r--src/mainboard/lenovo/x60/dock.h8
-rw-r--r--src/mainboard/lenovo/x60/mainboard_smi.c47
-rw-r--r--src/mainboard/lenovo/x60/romstage.c88
-rw-r--r--src/mainboard/lenovo/x60/smi.h7
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
new file mode 100644
index 0000000000..2930ae88cd
--- /dev/null
+++ b/src/mainboard/lenovo/x60/acpi/.ec.asl.swp
Binary files differ
diff --git a/src/mainboard/lenovo/x60/acpi/.gpe.asl.swp b/src/mainboard/lenovo/x60/acpi/.gpe.asl.swp
new file mode 100644
index 0000000000..f5f0cc8d1a
--- /dev/null
+++ b/src/mainboard/lenovo/x60/acpi/.gpe.asl.swp
Binary files differ
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