2011-04-01 09:28:56 +02:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <console/console.h>
|
|
|
|
#include <device/device.h>
|
|
|
|
#include <arch/io.h>
|
|
|
|
#include <delay.h>
|
|
|
|
#include <arch/io.h>
|
|
|
|
#include "dock.h"
|
|
|
|
#include "southbridge/intel/i82801gx/i82801gx.h"
|
2015-01-03 18:17:35 +01:00
|
|
|
#include <superio/nsc/pc87392/pc87392.h>
|
2011-04-01 09:28:56 +02:00
|
|
|
|
|
|
|
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);
|
|
|
|
|
2012-01-10 14:44:12 +01:00
|
|
|
dlpc_gpio_init();
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int dock_connect(void)
|
|
|
|
{
|
|
|
|
int timeout = 1000;
|
|
|
|
|
2011-04-01 09:28:56 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Assert D_PLTRST# */
|
|
|
|
outb(0xfe, 0x1680);
|
2011-07-11 18:36:16 +02:00
|
|
|
udelay(100000);
|
2011-04-01 09:28:56 +02:00
|
|
|
/* Deassert D_PLTRST# */
|
|
|
|
outb(0xff, 0x1680);
|
|
|
|
|
2012-01-10 14:44:12 +01:00
|
|
|
udelay(100000);
|
2011-07-11 18:36:16 +02:00
|
|
|
|
2011-04-01 09:28:56 +02:00
|
|
|
/* startup 14.318MHz Clock */
|
|
|
|
dock_write_register(0x29, 0x06);
|
|
|
|
/* wait until clock is settled */
|
2012-01-10 14:44:12 +01:00
|
|
|
timeout = 1000;
|
2011-04-01 09:28:56 +02:00
|
|
|
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);
|
2011-07-11 18:36:16 +02:00
|
|
|
|
|
|
|
dock_write_register(0x07, 0x03);
|
|
|
|
dock_write_register(0x30, 0x01);
|
2011-04-01 09:28:56 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void dock_disconnect(void)
|
|
|
|
{
|
2012-01-10 14:44:12 +01:00
|
|
|
printk(BIOS_DEBUG, "%s enter\n", __func__);
|
2011-04-01 09:28:56 +02:00
|
|
|
/* disconnect LPC bus */
|
|
|
|
outb(0x00, 0x164c);
|
2012-01-10 14:44:12 +01:00
|
|
|
udelay(10000);
|
|
|
|
|
2011-04-01 09:28:56 +02:00
|
|
|
/* Assert PLTRST and DLPCPD */
|
|
|
|
outb(0xfc, 0x1680);
|
2012-01-10 14:44:12 +01:00
|
|
|
udelay(10000);
|
|
|
|
|
|
|
|
/* disable Ultrabay and USB Power */
|
|
|
|
outb(0x00, 0x1628);
|
|
|
|
udelay(10000);
|
|
|
|
|
|
|
|
printk(BIOS_DEBUG, "%s finish\n", __func__);
|
2011-04-01 09:28:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
int dock_present(void)
|
|
|
|
{
|
2016-08-02 14:28:49 +02:00
|
|
|
return !((inw(DEFAULT_GPIOBASE + 0x0c) >> 13) & 1);
|
2011-04-01 09:28:56 +02:00
|
|
|
}
|
2011-04-27 21:48:05 +02:00
|
|
|
|
|
|
|
int dock_ultrabay_device_present(void)
|
|
|
|
{
|
|
|
|
return inb(0x1621) & 0x02 ? 0 : 1;
|
|
|
|
}
|