summaryrefslogtreecommitdiff
path: root/src/mainboard/lenovo/t400/dock.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mainboard/lenovo/t400/dock.c')
-rw-r--r--src/mainboard/lenovo/t400/dock.c82
1 files changed, 42 insertions, 40 deletions
diff --git a/src/mainboard/lenovo/t400/dock.c b/src/mainboard/lenovo/t400/dock.c
index 3d92a796de..6d1a80c1c1 100644
--- a/src/mainboard/lenovo/t400/dock.c
+++ b/src/mainboard/lenovo/t400/dock.c
@@ -34,10 +34,8 @@ struct pin_config {
u8 mode;
};
-static int poll_clk_stable(pnp_devfn_t dev)
+static int poll_clk_stable(pnp_devfn_t dev, int timeout)
{
- int timeout = 1000;
-
/* Enable 14.318MHz CLK on CLKIN */
pnp_write_config(dev, 0x29, 0xa0);
while(!(pnp_read_config(dev, 0x29) & 0x10) && timeout--)
@@ -69,20 +67,10 @@ static int gpio_init(pnp_devfn_t gpio, u16 gpio_base,
static const pnp_devfn_t l_dlpc = PNP_DEV(0x164e, PC87382_DOCK);
static const pnp_devfn_t l_gpio = PNP_DEV(0x164e, PC87382_GPIO);
-#define DLPC_CONTROL 0x164c
-#define DLPC_GPIO_BASE 0x1680
-
-#define DLPC_GPDO0 (DLPC_GPIO_BASE + 0x0)
-#define DLPC_GPDI0 (DLPC_GPIO_BASE + 0x1)
-#define D_PLTRST 0x01
-#define D_LPCPD 0x02
-
-#define DLPC_GPDO2 (DLPC_GPIO_BASE + 0x8)
-#define DLPC_GPDI2 (DLPC_GPIO_BASE + 0x9)
-
static int pc87382_init(pnp_devfn_t dlpc, u16 dlpc_base)
{
- int timeout = 1000;
+ /* Maximum 3300 LCLKs at 14.318MHz */
+ int timeout = 230;
/* Enable LPC bridge LDN. */
pnp_set_logical_device(dlpc);
@@ -93,7 +81,7 @@ static int pc87382_init(pnp_devfn_t dlpc, u16 dlpc_base)
outb(0x00, dlpc_base);
outb(0x07, dlpc_base);
while (!(inb(dlpc_base) & 8) && timeout--)
- udelay(1000);
+ udelay(1);
if (!timeout)
return 1;
@@ -106,8 +94,10 @@ static void pc87382_close(pnp_devfn_t dlpc)
/* Disconnect LPC bus */
u16 dlpc_base = pnp_read_iobase(dlpc, PNP_IDX_IO0);
- outb(0x00, dlpc_base);
- pnp_set_enable(dlpc, 0);
+ if (dlpc_base) {
+ outb(0x00, dlpc_base);
+ pnp_set_enable(dlpc, 0);
+ }
}
static const struct pin_config local_gpio[] = {
@@ -115,18 +105,26 @@ static const struct pin_config local_gpio[] = {
{0x04, 4}, {0x20, 4}, {0x21, 4}, {0x23, 4},
};
-static int pc87382_connect(void)
+/* Enable internal clock and configure GPIO LDN */
+int pc87382_early(void)
{
- u8 reg;
-
- if (poll_clk_stable(l_gpio) != 0)
+ /* Wake-up time is 33 msec (maximum). */
+ if (poll_clk_stable(l_gpio, 33) != 0)
return 1;
+ /* Set up GPIOs */
if (gpio_init(l_gpio, DLPC_GPIO_BASE,
local_gpio, ARRAY_SIZE(local_gpio)) != 0) {
return 1;
}
+ return 0;
+}
+
+static int pc87382_connect(void)
+{
+ u8 reg;
+
reg = inb(DLPC_GPDO0);
reg |= D_PLTRST | D_LPCPD;
/* Deassert D_PLTRST# and D_LPCPD# */
@@ -158,10 +156,12 @@ static void pc87382_disconnect(void)
outb(reg, DLPC_GPDO0);
}
+/* Returns 3bit dock id */
static u8 dock_identify(void)
{
u8 id;
+ /* Make sure GPIO LDN is configured first ! */
id = (inb(DLPC_GPDI0) >> 4) & 1;
id |= (inb(DLPC_GPDI2) & 3) << 1;
@@ -172,10 +172,8 @@ static u8 dock_identify(void)
#include <superio/nsc/pc87384/pc87384.h>
-static const pnp_devfn_t r_gpio = PNP_DEV(0x2e, PC87384_GPIO);
-static const pnp_devfn_t r_serial = PNP_DEV(0x2e, PC87384_SP1);
-
-#define DOCK_GPIO_BASE 0x1620
+static const pnp_devfn_t r_gpio = PNP_DEV(SUPERIO_DEV, PC87384_GPIO);
+static const pnp_devfn_t r_serial = PNP_DEV(SUPERIO_DEV, PC87384_SP1);
static const struct pin_config remote_gpio[] = {
{0x00, PC87384_GPIO_PIN_DEBOUNCE | PC87384_GPIO_PIN_PULLUP},
@@ -190,7 +188,7 @@ static const struct pin_config remote_gpio[] = {
static int pc87384_init(void)
{
- if (poll_clk_stable(r_gpio) != 0)
+ if (poll_clk_stable(r_gpio, 1000) != 0)
return 1;
/* set GPIO pins to Serial/Parallel Port
@@ -199,9 +197,12 @@ static int pc87384_init(void)
pnp_write_config(r_gpio, 0x22, 0xa9);
/* enable serial port */
- pnp_set_logical_device(r_serial);
- pnp_set_iobase(r_serial, PNP_IDX_IO0, 0x3f8);
- pnp_set_enable(r_serial, 1);
+
+ if (CONFIG_TTYS0_BASE > 0) {
+ pnp_set_logical_device(r_serial);
+ pnp_set_iobase(r_serial, PNP_IDX_IO0, CONFIG_TTYS0_BASE);
+ pnp_set_enable(r_serial, 1);
+ }
if (gpio_init(r_gpio, DOCK_GPIO_BASE,
remote_gpio, ARRAY_SIZE(remote_gpio)) != 0)
@@ -228,14 +229,16 @@ static int pc87384_init(void)
void dock_connect(void)
{
- if (dock_identify() == 0)
+ const u8 id = dock_identify();
+
+ /* Dock type 2505 doesn't have serial, LPT port or LEDs */
+ if (id == DOCK_TYPE_NONE || id == DOCK_TYPE_2505)
return;
- if (pc87382_connect() != 0) {
+ if (pc87382_connect() != 0 || pc87384_init() != 0) {
pc87382_disconnect();
return;
}
- pc87384_init();
ec_write(H8_LED_CONTROL,
H8_LED_CONTROL_OFF | H8_LED_CONTROL_DOCK_LED1);
@@ -253,13 +256,12 @@ void dock_disconnect(void)
H8_LED_CONTROL_OFF | H8_LED_CONTROL_DOCK_LED2);
}
-void h8_mainboard_init_dock(void)
+void dock_info(void)
{
- u8 id = dock_identify();
+ const u8 id = dock_identify();
- if (id != 0) {
- printk(BIOS_DEBUG, "dock (id=%d) is present\n", id);
- dock_connect();
- } else
- printk(BIOS_DEBUG, "dock is not connected\n");
+ if (id != DOCK_TYPE_NONE)
+ printk(BIOS_DEBUG, "DOCK: is present: id=%d\n", id);
+ else
+ printk(BIOS_DEBUG, "DOCK: not connected\n");
}