aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/southbridge/intel/lynxpoint/pch.c26
-rw-r--r--src/southbridge/intel/lynxpoint/pch.h6
-rw-r--r--src/southbridge/intel/lynxpoint/serialio.c31
3 files changed, 56 insertions, 7 deletions
diff --git a/src/southbridge/intel/lynxpoint/pch.c b/src/southbridge/intel/lynxpoint/pch.c
index cc3718d444..58c68cdf05 100644
--- a/src/southbridge/intel/lynxpoint/pch.c
+++ b/src/southbridge/intel/lynxpoint/pch.c
@@ -83,10 +83,18 @@ u16 get_gpiobase(void)
#ifndef __SMM__
+/* Put device in D3Hot Power State */
+static void pch_enable_d3hot(device_t dev)
+{
+ u32 reg32 = pci_read_config32(dev, PCH_PCS);
+ reg32 |= PCH_PCS_PS_D3HOT;
+ pci_write_config32(dev, PCH_PCS, reg32);
+}
+
/* Set bit in Function Disble register to hide this device */
-static void pch_hide_devfn(unsigned devfn)
+static void pch_hide_devfn(device_t dev)
{
- switch (devfn) {
+ switch (dev->path.pci.devfn) {
case PCI_DEVFN(19, 0): /* Audio DSP */
RCBA32_OR(FD, PCH_DISABLE_ADSPD);
break;
@@ -94,24 +102,31 @@ static void pch_hide_devfn(unsigned devfn)
RCBA32_OR(FD, PCH_DISABLE_XHCI);
break;
case PCI_DEVFN(21, 0): /* DMA */
+ pch_enable_d3hot(dev);
pch_iobp_update(SIO_IOBP_FUNCDIS0, ~0UL, SIO_IOBP_FUNCDIS_DIS);
break;
case PCI_DEVFN(21, 1): /* I2C0 */
+ pch_enable_d3hot(dev);
pch_iobp_update(SIO_IOBP_FUNCDIS1, ~0UL, SIO_IOBP_FUNCDIS_DIS);
break;
case PCI_DEVFN(21, 2): /* I2C1 */
+ pch_enable_d3hot(dev);
pch_iobp_update(SIO_IOBP_FUNCDIS2, ~0UL, SIO_IOBP_FUNCDIS_DIS);
break;
case PCI_DEVFN(21, 3): /* SPI0 */
+ pch_enable_d3hot(dev);
pch_iobp_update(SIO_IOBP_FUNCDIS3, ~0UL, SIO_IOBP_FUNCDIS_DIS);
break;
case PCI_DEVFN(21, 4): /* SPI1 */
+ pch_enable_d3hot(dev);
pch_iobp_update(SIO_IOBP_FUNCDIS4, ~0UL, SIO_IOBP_FUNCDIS_DIS);
break;
case PCI_DEVFN(21, 5): /* UART0 */
+ pch_enable_d3hot(dev);
pch_iobp_update(SIO_IOBP_FUNCDIS5, ~0UL, SIO_IOBP_FUNCDIS_DIS);
break;
case PCI_DEVFN(21, 6): /* UART1 */
+ pch_enable_d3hot(dev);
pch_iobp_update(SIO_IOBP_FUNCDIS6, ~0UL, SIO_IOBP_FUNCDIS_DIS);
break;
case PCI_DEVFN(22, 0): /* MEI #1 */
@@ -127,6 +142,7 @@ static void pch_hide_devfn(unsigned devfn)
RCBA32_OR(FD2, PCH_DISABLE_KT);
break;
case PCI_DEVFN(23, 0): /* SDIO */
+ pch_enable_d3hot(dev);
pch_iobp_update(SIO_IOBP_FUNCDIS7, ~0UL, SIO_IOBP_FUNCDIS_DIS);
break;
case PCI_DEVFN(25, 0): /* Gigabit Ethernet */
@@ -146,7 +162,7 @@ static void pch_hide_devfn(unsigned devfn)
case PCI_DEVFN(28, 5): /* PCI Express Root Port 6 */
case PCI_DEVFN(28, 6): /* PCI Express Root Port 7 */
case PCI_DEVFN(28, 7): /* PCI Express Root Port 8 */
- RCBA32_OR(FD, PCH_DISABLE_PCIE(PCI_FUNC(devfn)));
+ RCBA32_OR(FD, PCH_DISABLE_PCIE(PCI_FUNC(dev->path.pci.devfn)));
break;
case PCI_DEVFN(29, 0): /* EHCI #1 */
RCBA32_OR(FD, PCH_DISABLE_EHCI1);
@@ -404,7 +420,7 @@ static void pch_pcie_enable(device_t dev)
new_rpfn |= RPFN_HIDE(PCI_FUNC(dev->path.pci.devfn));
/* Hide this device if possible */
- pch_hide_devfn(dev->path.pci.devfn);
+ pch_hide_devfn(dev);
} else {
int fn;
@@ -463,7 +479,7 @@ void pch_enable(device_t dev)
pci_write_config32(dev, PCI_COMMAND, reg32);
/* Hide this device if possible */
- pch_hide_devfn(dev->path.pci.devfn);
+ pch_hide_devfn(dev);
} else {
/* Enable SERR */
reg32 = pci_read_config32(dev, PCI_COMMAND);
diff --git a/src/southbridge/intel/lynxpoint/pch.h b/src/southbridge/intel/lynxpoint/pch.h
index ca1d8b1b68..b01fdc04cb 100644
--- a/src/southbridge/intel/lynxpoint/pch.h
+++ b/src/southbridge/intel/lynxpoint/pch.h
@@ -218,6 +218,10 @@ void set_gpio(int gpio_num, int value);
#define SEE (1 << 1)
#define PERE (1 << 0)
+/* Power Management Control and Status */
+#define PCH_PCS 0x84
+#define PCH_PCS_PS_D3HOT 3
+
#define PCH_EHCI1_DEV PCI_DEV(0, 0x1d, 0)
#define PCH_EHCI2_DEV PCI_DEV(0, 0x1a, 0)
#define PCH_ME_DEV PCI_DEV(0, 0x16, 0)
@@ -377,6 +381,8 @@ void set_gpio(int gpio_num, int value);
#define SIO_ID_UART1 6 /* D21:F6 */
#define SIO_ID_SDIO 7 /* D23:F0 */
+#define SIO_REG_PPR_CLOCK 0x800
+#define SIO_REG_PPR_CLOCK_EN (1 << 0)
#define SIO_REG_PPR_RST 0x804
#define SIO_REG_PPR_RST_ASSERT 0x3
#define SIO_REG_PPR_GEN 0x808
diff --git a/src/southbridge/intel/lynxpoint/serialio.c b/src/southbridge/intel/lynxpoint/serialio.c
index 11d6a36b44..8257cc2f6f 100644
--- a/src/southbridge/intel/lynxpoint/serialio.c
+++ b/src/southbridge/intel/lynxpoint/serialio.c
@@ -29,6 +29,22 @@
#include "pch.h"
#include "nvs.h"
+/* Set D3Hot Power State in ACPI mode */
+static void serialio_enable_d3hot(struct device *dev)
+{
+ u32 reg32 = pci_read_config32(dev, PCH_PCS);
+ reg32 |= PCH_PCS_PS_D3HOT;
+ pci_write_config32(dev, PCH_PCS, reg32);
+}
+
+/* Enable clock in PCI mode */
+static void serialio_enable_clock(struct resource *bar0)
+{
+ u32 reg32 = read32(bar0->base + SIO_REG_PPR_CLOCK);
+ reg32 |= SIO_REG_PPR_CLOCK_EN;
+ write32(bar0->base + SIO_REG_PPR_CLOCK, reg32);
+}
+
/* Put Serial IO D21:F0-F6 device into desired mode. */
static void serialio_d21_mode(int sio_index, int int_pin, int acpi_mode)
{
@@ -143,9 +159,15 @@ static void serialio_init(struct device *dev)
struct southbridge_intel_lynxpoint_config *config = dev->chip_info;
struct resource *bar0, *bar1;
int sio_index = -1;
+ u32 reg32;
printk(BIOS_DEBUG, "Initializing Serial IO device\n");
+ /* Ensure memory and bus master are enabled */
+ reg32 = pci_read_config32(dev, PCI_COMMAND);
+ reg32 |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+ pci_write_config32(dev, PCI_COMMAND, reg32);
+
/* Find BAR0 and BAR1 */
bar0 = find_resource(dev, PCI_BASE_ADDRESS_0);
if (!bar0)
@@ -154,6 +176,11 @@ static void serialio_init(struct device *dev)
if (!bar1)
return;
+ if (!config->sio_acpi_mode)
+ serialio_enable_clock(bar0);
+ else if (dev->path.pci.devfn != PCI_DEVFN(21, 0))
+ serialio_enable_d3hot(dev); /* all but SDMA */
+
switch (dev->path.pci.devfn) {
case PCI_DEVFN(21, 0): /* SDMA */
sio_index = SIO_ID_SDMA;
@@ -241,9 +268,9 @@ static struct pci_operations pci_ops = {
};
static struct device_operations device_ops = {
- .read_resources = pci_bus_read_resources,
+ .read_resources = pci_dev_read_resources,
.set_resources = pci_dev_set_resources,
- .enable_resources = pci_bus_enable_resources,
+ .enable_resources = pci_dev_enable_resources,
.init = serialio_init,
.ops_pci = &pci_ops,
};