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
This commit is contained in:
parent
1aba096789
commit
fea6bd1690
|
@ -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
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
|
||||
int mainboard_io_trap_handler(int smif)
|
||||
static void mainboard_smm_init(void)
|
||||
{
|
||||
switch (smif) {
|
||||
case 0x99:
|
||||
printk(BIOS_DEBUG, "Sample\n");
|
||||
//gnvs->smif = 0;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
printk(BIOS_DEBUG, "initializing SMI\n");
|
||||
/* Enable 0x1600/0x1600 register pair */
|
||||
ec_set_bit(0x00, 0x05);
|
||||
ec_set_ports(0x1604, 0x1600);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
int mainboard_io_trap_handler(int smif)
|
||||
{
|
||||
static int smm_initialized;
|
||||
|
||||
if (!smm_initialized) {
|
||||
mainboard_smm_init();
|
||||
smm_initialized = 1;
|
||||
}
|
||||
|
||||
switch (smif) {
|
||||
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 1;
|
||||
}
|
||||
|
||||
/* On success, the IO Trap Handler returns 0
|
||||
* On failure, the IO Trap Handler returns a value != 0 */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
/* 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);
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue