Patchwork add ThinkPad T60

login
register
about
Submitter Sven Schnelle
Date 2011-04-17 13:07:45
Message ID <871v1181r2.fsf@begreifnix.stackframe.org>
Download mbox | patch
Permalink /patch/2882/
State Superseded
Headers show

Comments

Sven Schnelle - 2011-04-17 13:07:45
Hi List,

the attached patch adds support for the ThinkPad T60 to
coreboot. it is diffed against the existing X60 port.

Signed-off-by: Sven Schnelle <svens@stackframe.org>
Stefan Reinauer - 2011-04-18 00:09:58
On 4/17/11 6:07 AM, Sven Schnelle wrote:
> Hi List,
>
> the attached patch adds support for the ThinkPad T60 to
> coreboot. it is diffed against the existing X60 port.
>
> Signed-off-by: Sven Schnelle<svens@stackframe.org>
>

> Index: t60/Kconfig
> ===================================================================
> --- t60/Kconfig	(revision 6509)
> +++ t60/Kconfig	(working copy)
>
> @@ -56,4 +56,28 @@
>   	int
>   	default 1
>
> +config TI_PCMCIA_CARDBUS_CMDR
> +	hex
> +	default 0x0107
> +
> +config TI_PCMCIA_CARDBUS_CLSR
> +	hex
> +	default 0x00
> +
> +config TI_PCMCIA_CARDBUS_CLTR
> +	hex
> +	default 0x40
> +
> +config TI_PCMCIA_CARDBUS_BCR
> +	hex
> +	default 0x07C0
> +
> +config TI_PCMCIA_CARDBUS_SCR
> +	hex
> +	default 0x08449060
> +
> +config TI_PCMCIA_CARDBUS_MRR
> +	hex
> +	default 0x00007522
> +
>   endif

Can you please put these in a .c or .h file in the mainboard directory? 
I don't think we should add configuration variables for single registers 
in Kconfig.


> Index: t60/dock.c
> ===================================================================
> --- t60/dock.c	(revision 6509)
> +++ t60/dock.c	(working copy)
> @@ -26,8 +26,9 @@
>   #include<delay.h>
>   #include<arch/io.h>
>   #include "dock.h"
> +#include "superio/nsc/pc87384/pc87384.h"
> +#include "ec/acpi/ec.h"
>   #include "southbridge/intel/i82801gx/i82801gx.h"
> -#include "superio/nsc/pc87392/pc87392.h"
>
>   static void dlpc_write_register(int reg, int value)
>   {
> @@ -59,6 +60,7 @@
>   	dlpc_write_register(0xf1, mode);
>   }
>
> +
drop new line?

> +	/* no GPIO events enabled for PORT0 */
> +	outb(0x00, 0x1622);
> +	/* clear GPIO events on PORT0 */
> +	outb(0xff, 0x1623);
> +	outb(0xff, 0x1624);
> +	/* no GPIO events enabled for PORT1 */
> +	outb(0x00, 0x1626);
Are you properly preventing the resource allocator from putting other 
resources on top of 0x16xx?


> +	outb(0x61, 0x15ec);
> +	return inb(0x15ee)&  1;
>   }
> +

... and 0x15xx


> Index: t60/mptable.c
> ===================================================================
> --- t60/mptable.c	(revision 6509)
> +++ t60/mptable.c	(working copy)
> @@ -62,9 +62,7 @@
>   	smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1f<<  2)       , 0x02, 0x17); /* LPC       0:1f.0 */
>   	smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1f<<  2) | 0x01, 0x02, 0x10); /* IDE       0:1f.1 */
>   	smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1f<<  2) | 0x02, 0x02, 0x10); /* SATA      0:1f.2 */
> -	smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x05, (0x00<<  2) | 0x00, 0x02, 0x10); /* Cardbus   5:00.0 */
> -	smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x05, (0x00<<  2) | 0x01, 0x02, 0x11); /* Firewire  5:00.1 */
> -	smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x05, (0x00<<  2) | 0x02, 0x02, 0x12); /* SDHC      5:00.2 */
> +	smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x06, (0x00<<  2) | 0x00, 0x02, 0x10); /* Cardbus   5:00.0 */
>
>   	smp_write_lintsrc(mc, mp_ExtINT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_HIGH, isa_bus, 0, MP_APIC_ALL, 0);
>   	smp_write_lintsrc(mc, mp_NMI,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_HIGH, isa_bus, 0, MP_APIC_ALL, 1);

In general it would be better to look for the appropriate devices in the 
system, because someone might plug in a device with a bridge on the 
lower buses, effectively rendering your mptable useless.

MP table automation ftw!



Looks great otherwise.

Stefan
Sven Schnelle - 2011-04-18 08:00:53
Hi Stefan,

Stefan Reinauer <stefan.reinauer@coreboot.org> writes:

> On 4/17/11 6:07 AM, Sven Schnelle wrote:
>
>     Index: t60/Kconfig
>     ===================================================================
>     --- t60/Kconfig (revision 6509)
>     +++ t60/Kconfig (working copy)
>
>     @@ -56,4 +56,28 @@
>             int
>             default 1
>      
>     +config TI_PCMCIA_CARDBUS_CMDR
>     +       hex
>     +       default 0x0107
>     +
>     +config TI_PCMCIA_CARDBUS_CLSR
>     +       hex
>     +       default 0x00
>     +
>     +config TI_PCMCIA_CARDBUS_CLTR
>     +       hex
>     +       default 0x40
>     +
>     +config TI_PCMCIA_CARDBUS_BCR
>     +       hex
>     +       default 0x07C0
>     +
>     +config TI_PCMCIA_CARDBUS_SCR
>     +       hex
>     +       default 0x08449060
>     +
>     +config TI_PCMCIA_CARDBUS_MRR
>     +       hex
>     +       default 0x00007522
>     +
>      endif
>
> Can you please put these in a .c or .h file in the mainboard
> directory? I don't think we should add configuration variables
> for single registers in Kconfig.

Actually i've copied that from another Board using the pci1x2x cardbus
controller, and was quite surprised that these settings are located in
Kconfig. IMHO they should be configured in devicetree.cb via chip.h config.
What do you think about this solution? Maybe we should do that in an
extra patch, which moves those setting to chip config and converts all
pci1x2x users?

>     Index: t60/dock.c
>     ===================================================================
>     --- t60/dock.c  (revision 6509)
>     +++ t60/dock.c  (working copy)
>     @@ -26,8 +26,9 @@
>      #include <delay.h>
>      #include <arch/io.h>
>      #include "dock.h"
>     +#include "superio/nsc/pc87384/pc87384.h"
>     +#include "ec/acpi/ec.h"
>      #include "southbridge/intel/i82801gx/i82801gx.h"
>     -#include "superio/nsc/pc87392/pc87392.h"
>      
>      static void dlpc_write_register(int reg, int value)
>      {
>     @@ -59,6 +60,7 @@
>             dlpc_write_register(0xf1, mode);
>      }
>      
>     +
>     
> drop new line?

Yes ;)

>     +       /* no GPIO events enabled for PORT0 */
>     +       outb(0x00, 0x1622);
>     +       /* clear GPIO events on PORT0 */
>     +       outb(0xff, 0x1623);
>     +       outb(0xff, 0x1624);
>     +       /* no GPIO events enabled for PORT1 */
>     +       outb(0x00, 0x1626);
>     
> Are you properly preventing the resource allocator from putting other resources on top of 0x16xx?

Yes, it's listed in devicetree.cb (which should prevent
allocation). Debug log from boot:

PNP: 002e.7 60 <- [0x0000001620 - 0x000000162f] size 0x00000010 gran 0x04 io

>     +       outb(0x61, 0x15ec);
>     +       return inb(0x15ee) & 1;
>      }
>     +
> ... and 0x15xx

same here, the 15e0 range is allocated in ec/lenovo/pmh7 (i'm not using
the pmh7 function here because i don't want to have all the PMH7 code in
SMM just for one register read) 

>
>     Index: t60/mptable.c
>     ===================================================================
>     --- t60/mptable.c       (revision 6509)
>     +++ t60/mptable.c       (working copy)
>     @@ -62,9 +62,7 @@
>             smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1f << 2)       , 0x02, 0x17); /* LPC       0:1f.0 */
>             smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1f << 2) | 0x01, 0x02, 0x10); /* IDE       0:1f.1 */
>             smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1f << 2) | 0x02, 0x02, 0x10); /* SATA      0:1f.2 */
>     -       smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x05, (0x00 << 2) | 0x00, 0x02, 0x10); /* Cardbus   5:00.0 */
>     -       smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x05, (0x00 << 2) | 0x01, 0x02, 0x11); /* Firewire  5:00.1 */
>     -       smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x05, (0x00 << 2) | 0x02, 0x02, 0x12); /* SDHC      5:00.2 */
>     +       smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x06, (0x00 << 2) | 0x00, 0x02, 0x10); /* Cardbus   5:00.0 */
>      
>             smp_write_lintsrc(mc, mp_ExtINT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_HIGH, isa_bus, 0, MP_APIC_ALL, 0);
>             smp_write_lintsrc(mc, mp_NMI,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_HIGH, isa_bus, 0, MP_APIC_ALL, 1);
>
> In general it would be better to look for the appropriate devices in the system, because someone might plug in a device with a bridge on the
> lower buses, effectively rendering your mptable useless.
>
> MP table automation ftw!

Hmm, have to look how to do automatic generation of mptable. Thanks
for the hint.

Sven.
Stefan Reinauer - 2011-04-18 19:32:15
* Sven Schnelle <svens@stackframe.org> [110418 10:00]:
> Stefan Reinauer <stefan.reinauer@coreboot.org> writes:
> > Can you please put these in a .c or .h file in the mainboard
> > directory? I don't think we should add configuration variables
> > for single registers in Kconfig.
> 
> Actually i've copied that from another Board using the pci1x2x cardbus
> controller, and was quite surprised that these settings are located in
> Kconfig. IMHO they should be configured in devicetree.cb via chip.h config.
> What do you think about this solution? Maybe we should do that in an
> extra patch, which moves those setting to chip config and converts all
> pci1x2x users?
 
Oh, that sounds like a much better thing to do. 

> >     -       smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x05, (0x00 << 2) | 0x00, 0x02, 0x10); /* Cardbus   5:00.0 */
> >     -       smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x05, (0x00 << 2) | 0x01, 0x02, 0x11); /* Firewire  5:00.1 */
> >     -       smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x05, (0x00 << 2) | 0x02, 0x02, 0x12); /* SDHC      5:00.2 */
> >     +       smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x06, (0x00 << 2) | 0x00, 0x02, 0x10); /* Cardbus   5:00.0 */
> >      
> >             smp_write_lintsrc(mc, mp_ExtINT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_HIGH, isa_bus, 0, MP_APIC_ALL, 0);
> >             smp_write_lintsrc(mc, mp_NMI,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_HIGH, isa_bus, 0, MP_APIC_ALL, 1);
> >
> > In general it would be better to look for the appropriate devices in the system, because someone might plug in a device with a bridge on the
> > lower buses, effectively rendering your mptable useless.
> >
> > MP table automation ftw!
> 
> Hmm, have to look how to do automatic generation of mptable. Thanks
> for the hint.

Well, there is this (unimplemented) idea of adding the IO Apics to the
device tree (ie. let each southbridge create an extra device) and then
create proper mp tables and pirq tables by walking the device tree.

However, as a quick fix you can look at the kontron 986lcd-m. It probes
for certain bridges and fixes up the bus numbers according to their
subordinate buses.

Anyways, with the pci1x2x fix in place, the code is
Acked-by: Stefan Reinauer <stefan.reinauer@coreboot.org>

Everything else will possibly need another round of thoughts/patches.

Stefan

Patch

Index: Kconfig
===================================================================
--- Kconfig	(revision 6509)
+++ Kconfig	(working copy)
@@ -11,9 +11,14 @@ 
 
 	    ThinkPad X60s (Model 1703)
 
+config BOARD_LENOVO_T60
+	bool "ThinkPad T60 / T60p"
+	help
+
 endchoice
 
 source "src/mainboard/lenovo/x60/Kconfig"
+source "src/mainboard/lenovo/t60/Kconfig"
 
 config MAINBOARD_VENDOR
 	string
Index: t60/Kconfig
===================================================================
--- t60/Kconfig	(revision 6509)
+++ t60/Kconfig	(working copy)
@@ -1,4 +1,4 @@ 
-if BOARD_LENOVO_X60
+if BOARD_LENOVO_T60
 
 config BOARD_SPECIFIC_OPTIONS # dummy
 	def_bool y
@@ -7,9 +7,9 @@ 
 	select CPU_INTEL_SOCKET_MFCPGA478
 	select NORTHBRIDGE_INTEL_I945GM
 	select SOUTHBRIDGE_INTEL_I82801GX
-	select SOUTHBRIDGE_RICOH_RL5C476
 	select SUPERIO_NSC_PC87382
-	select SUPERIO_NSC_PC87392
+	select SUPERIO_NSC_PC87384
+	select SOUTHBRIDGE_TI_PCI1X2X
 	select EC_LENOVO_PMH7
 	select EC_LENOVO_H8
 	select BOARD_HAS_FADT
@@ -26,7 +26,7 @@ 
 
 config MAINBOARD_DIR
 	string
-	default lenovo/x60
+	default lenovo/t60
 
 config DCACHE_RAM_BASE
 	hex
@@ -38,7 +38,7 @@ 
 
 config MAINBOARD_PART_NUMBER
 	string
-	default "ThinkPad X60 / X60s"
+	default "ThinkPad T60 / T60p"
 
 config MMCONF_BASE_ADDRESS
 	hex
@@ -56,4 +56,28 @@ 
 	int
 	default 1
 
+config TI_PCMCIA_CARDBUS_CMDR
+	hex
+	default 0x0107
+
+config TI_PCMCIA_CARDBUS_CLSR
+	hex
+	default 0x00
+
+config TI_PCMCIA_CARDBUS_CLTR
+	hex
+	default 0x40
+
+config TI_PCMCIA_CARDBUS_BCR
+	hex
+	default 0x07C0
+
+config TI_PCMCIA_CARDBUS_SCR
+	hex
+	default 0x08449060
+
+config TI_PCMCIA_CARDBUS_MRR
+	hex
+	default 0x00007522
+
 endif
Index: t60/dock.c
===================================================================
--- t60/dock.c	(revision 6509)
+++ t60/dock.c	(working copy)
@@ -26,8 +26,9 @@ 
 #include <delay.h>
 #include <arch/io.h>
 #include "dock.h"
+#include "superio/nsc/pc87384/pc87384.h"
+#include "ec/acpi/ec.h"
 #include "southbridge/intel/i82801gx/i82801gx.h"
-#include "superio/nsc/pc87392/pc87392.h"
 
 static void dlpc_write_register(int reg, int value)
 {
@@ -59,6 +60,7 @@ 
 	dlpc_write_register(0xf1, mode);
 }
 
+
 static void dock_gpio_set_mode(int port, int mode, int irq)
 {
 	dock_write_register(0xf0, port);
@@ -107,132 +109,99 @@ 
 	/* 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)
+static int dock_superio_init(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);
+	dock_write_register(0x29, 0xa0);
 	/* wait until clock is settled */
-	while(!(dock_read_register(0x29) & 0x08) && timeout--)
+	while(!(dock_read_register(0x29) & 0x10) && timeout--)
 		udelay(1000);
 
 	if (!timeout)
 		return 1;
 
-	/* Pin  6: CLKRUN
-	 * Pin 72:  #DR1
-	 * Pin 19: #SMI
-	 * Pin 73: #MTR
+	/* set GPIO pins to Serial/Parallel Port
+	 * functions
 	 */
-	dock_write_register(0x24, 0x37);
+	dock_write_register(0x22, 0xeb);
 
-	/* PNF active HIGH */
-	dock_write_register(0x25, 0xa0);
+	dock_write_register(0x07, PC87384_GPIO);
+	dock_write_register(0x60, 0x16);
+	dock_write_register(0x61, 0x20);
 
-	/* disable FDC */
-	dock_write_register(0x26, 0x01);
+	dock_gpio_set_mode(0x00, PC87384_GPIO_PIN_DEBOUNCE |
+			   PC87384_GPIO_PIN_PULLUP, 0x00);
 
-	/* Enable GPIO IRQ to #SMI */
-	dock_write_register(0x28, 0x02);
+	dock_gpio_set_mode(0x01, PC87384_GPIO_PIN_TYPE_PUSH_PULL |
+			   PC87384_GPIO_PIN_OE, 0x00);
 
-	/* select GPIO */
-	dock_write_register(0x07, 0x07);
+	dock_gpio_set_mode(0x02, PC87384_GPIO_PIN_TYPE_PUSH_PULL |
+			   PC87384_GPIO_PIN_OE, 0x00);
 
-	/* set base address */
-	dock_write_register(0x60, 0x16);
-	dock_write_register(0x61, 0x20);
+	dock_gpio_set_mode(0x03, PC87384_GPIO_PIN_DEBOUNCE |
+			   PC87384_GPIO_PIN_PULLUP, 0x00);
 
-	/* init GPIO pins */
-	dock_gpio_set_mode(0x00, PC87392_GPIO_PIN_DEBOUNCE |
-				 PC87392_GPIO_PIN_PULLUP, 0x00);
+	dock_gpio_set_mode(0x04, PC87384_GPIO_PIN_DEBOUNCE |
+			   PC87384_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(0x05, PC87384_GPIO_PIN_DEBOUNCE |
+			   PC87384_GPIO_PIN_PULLUP, 0x00);
 
-	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(0x06, PC87384_GPIO_PIN_DEBOUNCE |
+			   PC87384_GPIO_PIN_PULLUP, 0x00);
 
-	dock_gpio_set_mode(0x10, PC87392_GPIO_PIN_DEBOUNCE |
-				 PC87392_GPIO_PIN_PULLUP,
-				 PC87392_GPIO_PIN_TRIGGERS_SMI);
+	dock_gpio_set_mode(0x07, PC87384_GPIO_PIN_DEBOUNCE |
+			   PC87384_GPIO_PIN_PULLUP, 0x00);
 
-	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);
+	outb(0xfd, 0x1620);
 
-	dock_gpio_set_mode(0x17, PC87392_GPIO_PIN_PULLUP, 0x00);
+	/* no GPIO events enabled for PORT0 */
+	outb(0x00, 0x1622);
+	/* clear GPIO events on PORT0 */
+	outb(0xff, 0x1623);
+	outb(0xff, 0x1624);
+	/* no GPIO events enabled for PORT1 */
+	outb(0x00, 0x1626);
 
-	dock_gpio_set_mode(0x20, PC87392_GPIO_PIN_TYPE_PUSH_PULL |
-				 PC87392_GPIO_PIN_OE, 0x00);
+	/* clear GPIO events on PORT1*/
+	outb(0xff, 0x1627);
+	outb(0x1F, 0x1628);
+	/* enable GPIO */
+	dock_write_register(0x30, 0x01);
+	return 0;
+}
 
-	dock_gpio_set_mode(0x21, PC87392_GPIO_PIN_TYPE_PUSH_PULL |
-				 PC87392_GPIO_PIN_OE, 0x00);
+int dock_connect(void)
+{
+	int timeout = 1000;
 
-	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);
+	outb(0x07, 0x164c);
 
-	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);
+	timeout = 1000;
 
-	dock_gpio_set_mode(0x35, PC87392_GPIO_PIN_PULLUP |
-				 PC87392_GPIO_PIN_OE, 0x00);
+	while(!(inb(0x164c) & 8) && timeout--)
+		udelay(1000);
 
-	dock_gpio_set_mode(0x36, PC87392_GPIO_PIN_PULLUP, 0x00);
-	dock_gpio_set_mode(0x37, PC87392_GPIO_PIN_PULLUP, 0x00);
+	if (!timeout) {
+		/* docking failed, disable DLPC switch */
+		outb(0x00, 0x164c);
+		dlpc_write_register(0x30, 0x00);
+		return 1;
+	}
 
-	/* enable GPIO */
-	dock_write_register(0x30, 0x01);
+	/* Assert D_PLTRST# */
+	outb(0xfe, 0x1680);
+	udelay(1000);
+	/* Deassert D_PLTRST# */
+	outb(0xff, 0x1680);
+	udelay(10000);
 
-	outb(0x00, 0x1628);
-	outb(0x00, 0x1623);
-	outb(0x82, 0x1622);
-	outb(0xff, 0x1624);
-
-	/* Enable USB and Ultrabay power */
-	outb(0x03, 0x1628);
-	return 0;
+	return dock_superio_init();
 }
 
 void dock_disconnect(void)
@@ -245,5 +214,7 @@ 
 
 int dock_present(void)
 {
-	return !((inb(DEFAULT_GPIOBASE + 0x0c) >> 13) & 1);
+	outb(0x61, 0x15ec);
+	return inb(0x15ee) & 1;
 }
+
Index: t60/romstage.c
===================================================================
--- t60/romstage.c	(revision 6509)
+++ t60/romstage.c	(working copy)
@@ -43,40 +43,16 @@ 
 {
 	printk(BIOS_DEBUG, " GPIOS...");
 
-	/* X60 GPIO:
-	    1: HDD_PRESENCE#
-	    6: Unknown (Pulled high by R215 to VCC3B)
-	    7: BDC_PRESENCE#
-	    8: H8_WAKE#
-	    9: RTC_BAT_IN#
-	   10: Unknown (Pulled high by R700 to VCC3M
-	   12: H8SCI#
-	   13: SLICE_ON_3M#
-	   14: Unknown (Pulled high by R321 to VCC3)
-	   15: Unknown (Pulled high by R258 to VCC3)
-	   19: Unknown (Pulled low  by R594)
-	   21: Unknown (Pulled high by R145 to VCC3)
-	   22: FWH_WP#
-	   25: MDC_KILL#
-	   33: HDD_PRESENCE_2#
-	   35: CLKREQ_SATA#
-	   36: PLANARID0
-	   37: PLANARID1
-	   38: PLANARID2
-	   39: PLANARID3
-	   48: FWH_TBL#
-	*/
-
-	outl(0x1f40f7c2, DEFAULT_GPIOBASE + 0x00);	/* GPIO_USE_SEL */
-	outl(0xe0e8ffc3, DEFAULT_GPIOBASE + 0x04);	/* GP_IO_SEL */
-	outl(0xfbf6ddfd, DEFAULT_GPIOBASE + 0x0c);	/* GP_LVL */
+	outl(0x1f48f7c2, DEFAULT_GPIOBASE + 0x00);	/* GPIO_USE_SEL */
+	outl(0xe0e0ffc3, DEFAULT_GPIOBASE + 0x04);	/* GP_IO_SEL */
+	outl(0xfbfefb7d, DEFAULT_GPIOBASE + 0x0c);	/* GP_LVL */
 	/* Output Control Registers */
 	outl(0x00040000, DEFAULT_GPIOBASE + 0x18);	/* GPO_BLINK */
 	/* Input Control Registers */
 	outl(0x000039ff, DEFAULT_GPIOBASE + 0x2c);	/* GPI_INV */
-	outl(0x000100f2, DEFAULT_GPIOBASE + 0x30);	/* GPIO_USE_SEL2 */
-	outl(0x000000f0, DEFAULT_GPIOBASE + 0x34);	/* GP_IO_SEL2 */
-	outl(0x00030043, DEFAULT_GPIOBASE + 0x38);	/* GP_LVL */
+	outl(0x000100f0, DEFAULT_GPIOBASE + 0x30);	/* GPIO_USE_SEL2 */
+	outl(0x000000f1, DEFAULT_GPIOBASE + 0x34);	/* GP_IO_SEL2 */
+	outl(0x000300a3, DEFAULT_GPIOBASE + 0x38);	/* GP_LVL2 */
 }
 
 static void ich7_enable_lpc(void)
@@ -106,9 +82,9 @@ 
 	int timeout = 100000;
 	device_t dev = PNP_DEV(0x2e, 3);
 
-	pnp_write_config(dev, 0x29, 0x06);
+	pnp_write_config(dev, 0x29, 0xa0);
 
-	while(!(pnp_read_config(dev, 0x29) & 0x08) && timeout--)
+	while(!(pnp_read_config(dev, 0x29) & 0x10) && timeout--)
 		udelay(1000);
 
 	/* Enable COM1 */
Index: t60/devicetree.cb
===================================================================
--- t60/devicetree.cb	(revision 6509)
+++ t60/devicetree.cb	(working copy)
@@ -30,14 +30,21 @@ 
 
 	device pci_domain 0 on
 		device pci 00.0 on # Host bridge
-			subsystemid 0x17aa 0x2017
+			subsystemid 0x17aa 0x2015
 		end
-		device pci 02.0 on # VGA controller
+		device pci 01.0 on # PCI-e
+			device pci 00.0 on # VGA
+				subsystemid 0x17aa 0x20a4
+			end
+		end
+
+		device pci 02.0 on # GMA Graphics controller
 			subsystemid 0x17aa 0x201a
 		end
 		device pci 02.1 on # display controller
 			subsystemid 0x17aa 0x201a
 		end
+
 		chip southbridge/intel/i82801gx
 			register "pirqa_routing" = "0x0b"
 			register "pirqb_routing" = "0x0b"
@@ -63,8 +70,10 @@ 
 			device pci 1b.0 on # Audio Cnotroller
 				subsystemid 0x17aa 0x2010
 			end
-			device pci 1c.0 on end # Ethernet
-			device pci 1c.1 on end # Atheros WLAN
+			device pci 1c.0 on # Ethernet
+				subsystemid 0x17aa 0x2001
+			end
+			device pci 1c.1 on end # WLAN
 			device pci 1d.0 on # USB UHCI
 				subsystemid 0x17aa 0x200a
 			end
@@ -80,12 +89,21 @@ 
 			device pci 1d.7 on # USB2 EHCI
 				subsystemid 0x17aa 0x200b
 			end
+			device pci 1e.0 on # PCI Bridge
+				chip southbridge/ti/pci1x2x
+					device pci 00.0 on
+						subsystemid 0x17aa 0x2012
+					end
+				end
+			end
 			device pci 1f.0 on # PCI-LPC bridge
 				subsystemid 0x17aa 0x2009
 				chip ec/lenovo/pmh7
 					device pnp ff.1 on # dummy
 					end
+
 					register "backlight_enable" = "0x01"
+					register "dock_event_enable" = "0x01"
 				end
 				chip ec/lenovo/h8
 					device pnp ff.2 on # dummy
@@ -95,6 +113,7 @@ 
 						io 0x66 = 0x1604
 					end
 
+
 					register "config0" = "0xa6"
 					register "config1" = "0x05"
 					register "config2" = "0xa0"
@@ -107,9 +126,11 @@ 
 					register "event3_enable" = "0xff"
 					register "event4_enable" = "0xf4"
 					register "event5_enable" = "0x3c"
+					register "event6_enable" = "0x80"
 
 					register "wlan_enable" = "0x01"
 					register "trackpoint_enable" = "0x03"
+
 				end
 				chip superio/nsc/pc87382
 					device pnp 164e.2 on # IR
@@ -129,7 +150,7 @@ 
 					end
 				end
 
-				chip superio/nsc/pc87392
+				chip superio/nsc/pc87384
 					device pnp 2e.0 off #FDC
 					end
 
@@ -166,7 +187,5 @@ 
 				subsystemid 0x17aa 0x200f
 			end
 		end
-		chip southbridge/ricoh/rl5c476
-		end
 	end
 end
Index: t60/mptable.c
===================================================================
--- t60/mptable.c	(revision 6509)
+++ t60/mptable.c	(working copy)
@@ -62,9 +62,7 @@ 
 	smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1f << 2)       , 0x02, 0x17); /* LPC       0:1f.0 */
 	smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1f << 2) | 0x01, 0x02, 0x10); /* IDE       0:1f.1 */
 	smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1f << 2) | 0x02, 0x02, 0x10); /* SATA      0:1f.2 */
-	smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x05, (0x00 << 2) | 0x00, 0x02, 0x10); /* Cardbus   5:00.0 */
-	smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x05, (0x00 << 2) | 0x01, 0x02, 0x11); /* Firewire  5:00.1 */
-	smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x05, (0x00 << 2) | 0x02, 0x02, 0x12); /* SDHC      5:00.2 */
+	smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x06, (0x00 << 2) | 0x00, 0x02, 0x10); /* Cardbus   5:00.0 */
 
 	smp_write_lintsrc(mc, mp_ExtINT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_HIGH, isa_bus, 0, MP_APIC_ALL, 0);
 	smp_write_lintsrc(mc, mp_NMI,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_HIGH, isa_bus, 0, MP_APIC_ALL, 1);
Index: t60/acpi/gpe.asl
===================================================================
--- t60/acpi/gpe.asl	(revision 6509)
+++ t60/acpi/gpe.asl	(working copy)
@@ -6,16 +6,4 @@ 
 		/* 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.DOCK, 3)
-               } else {
-		       And(GIV1, 0xdf, GIV1)
-		       Notify(\_SB.DOCK, 0)
-               }
-	}
 }
Index: t60/acpi/dock.asl
===================================================================
--- t60/acpi/dock.asl	(revision 6509)
+++ t60/acpi/dock.asl	(working copy)
@@ -53,15 +53,39 @@ 
 
 		Method(_STA, 0, NotSerialized)
 		{
-		Return (DSTA)
+			Return (DSTA)
 		}
 	}
 }
 
 Scope(\_SB.PCI0.LPCB.EC)
 {
+	OperationRegion(PMH7, SystemIO, 0x15e0, 0x10)
+	Field(PMH7, ByteAcc, NoLock, Preserve)
+	{
+		Offset(0x0c),
+			PIDX, 8,
+		Offset(0x0e),
+			PDAT, 8,
+	}
+
+	IndexField(PIDX, PDAT, ByteAcc, NoLock, Preserve)
+	{
+		Offset (0x61),
+			DPWR, 1,
+	}
+
 	Method(_Q18, 0, NotSerialized)
 	{
 	       Notify(\_SB.DOCK, 3)
 	}
+
+	Method(_Q37, 0, NotSerialized)
+	{
+		if (DPWR) {
+			Notify(\_SB.DOCK, 0)
+		} else {
+			Notify(\_SB.DOCK, 3)
+		}
+	}
 }