diff options
Diffstat (limited to 'src/southbridge/intel/lynxpoint/pcie.c')
-rw-r--r-- | src/southbridge/intel/lynxpoint/pcie.c | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/src/southbridge/intel/lynxpoint/pcie.c b/src/southbridge/intel/lynxpoint/pcie.c index c4cde920ed..e133feb9c2 100644 --- a/src/southbridge/intel/lynxpoint/pcie.c +++ b/src/southbridge/intel/lynxpoint/pcie.c @@ -25,6 +25,9 @@ #include <device/pci_ids.h> #include "pch.h" +static void pcie_update_cfg8(device_t dev, int reg, u8 mask, u8 or); +static void pcie_update_cfg(device_t dev, int reg, u32 mask, u32 or); + /* LynxPoint-LP has 6 root ports while non-LP has 8. */ #define MAX_NUM_ROOT_PORTS 8 #define H_NUM_ROOT_PORTS MAX_NUM_ROOT_PORTS @@ -179,6 +182,90 @@ static void pch_pcie_device_set_func(int index, int pci_func) } } +static void pcie_enable_clock_gating(void) +{ + int i; + int is_lp; + int enabled_ports; + + is_lp = pch_is_lp(); + enabled_ports = 0; + + for (i = 0; i < rpc.num_ports; i++) { + device_t dev; + int rp; + + dev = rpc.ports[i]; + rp = root_port_number(dev); + + if (!dev->enabled) { + /* Configure shared resource clock gating. */ + if (rp == 1 || rp == 5 || (rp == 6 && is_lp)) + pcie_update_cfg8(dev, 0xe1, 0xc3, 0x3c); + + if (!is_lp) { + if (rp == 1 && !rpc.ports[1]->enabled && + !rpc.ports[2]->enabled && + !rpc.ports[3]->enabled) { + pcie_update_cfg8(dev, 0xe2, ~1, 1); + pcie_update_cfg8(dev, 0xe1, 0x7f, 0x80); + } + if (rp == 5 && !rpc.ports[5]->enabled && + !rpc.ports[6]->enabled && + !rpc.ports[7]->enabled) { + pcie_update_cfg8(dev, 0xe2, ~1, 1); + pcie_update_cfg8(dev, 0xe1, 0x7f, 0x80); + } + continue; + } + + pcie_update_cfg8(dev, 0xe2, ~(3 << 4), (3 << 4)); + pcie_update_cfg(dev, 0x420, ~(1 << 31), (1 << 31)); + + /* Per-Port CLKREQ# handling. */ + if (is_lp && gpio_is_native(18 + rp - 1)) + pcie_update_cfg(dev, 0x420, ~0, (3 << 29)); + + /* Enable static clock gating. */ + if (rp == 1 && !rpc.ports[1]->enabled && + !rpc.ports[2]->enabled && !rpc.ports[3]->enabled) { + pcie_update_cfg8(dev, 0xe2, ~1, 1); + pcie_update_cfg8(dev, 0xe1, 0x7f, 0x80); + } else if (rp == 5 || rp == 6) { + pcie_update_cfg8(dev, 0xe2, ~1, 1); + pcie_update_cfg8(dev, 0xe1, 0x7f, 0x80); + } + continue; + } + + enabled_ports++; + + /* Enable dynamic clock gating. */ + pcie_update_cfg8(dev, 0xe1, 0xfc, 0x03); + + if (is_lp) { + pcie_update_cfg8(dev, 0xe2, ~(1 << 6), (1 << 6)); + pcie_update_cfg8(dev, 0xe8, ~(3 << 2), (2 << 2)); + } + + /* Update PECR1 register. */ + pcie_update_cfg8(dev, 0xe8, ~0, 1); + + pcie_update_cfg8(dev, 0x324, ~(1 << 5), (1 < 5)); + + /* Per-Port CLKREQ# handling. */ + if (is_lp && gpio_is_native(18 + rp - 1)) + pcie_update_cfg(dev, 0x420, ~0, (3 << 29)); + + /* Configure shared resource clock gating. */ + if (rp == 1 || rp == 5 || (rp == 6 && is_lp)) + pcie_update_cfg8(dev, 0xe1, 0xc3, 0x3c); + } + + if (!enabled_ports && is_lp) + pcie_update_cfg8(rpc.ports[0], 0xe1, ~(1 << 6), (1 << 6)); +} + static void root_port_commit_config(void) { int i; @@ -187,6 +274,9 @@ static void root_port_commit_config(void) if (!rpc.ports[0]->enabled) rpc.coalesce = 1; + /* Perform clock gating configuration. */ + pcie_enable_clock_gating(); + for (i = 0; i < rpc.num_ports; i++) { device_t dev; u32 reg32; |