From: Gary McGee <gary.mc...@intel.com> Signed-off-by: Gary McGee <gary.mc...@intel.com> --- drivers/misc/axxia-pei.c | 1465 +++++++++++++++++++++++------------------ drivers/pci/host/pcie-axxia.c | 146 ++-- include/linux/axxia-pei.h | 6 +- 3 files changed, 917 insertions(+), 700 deletions(-)
diff --git a/drivers/misc/axxia-pei.c b/drivers/misc/axxia-pei.c index 7a5b255..7996e9c 100644 --- a/drivers/misc/axxia-pei.c +++ b/drivers/misc/axxia-pei.c @@ -31,17 +31,29 @@ #include <linux/delay.h> #include <linux/of.h> #include <linux/lsi-ncr.h> +#include <linux/mutex.h> static int is_5500; static int is_5600; static int is_6700; static void __iomem *pcie_gpreg0; +static void __iomem *pcie_gpreg1; +static void __iomem *pcie_gpreg2; static void __iomem *pcie_rc; +static int pcie_cc_gpreg_offset = 0x8000; static int is_pei_control_available; static int is_pei_control_v2; +DEFINE_MUTEX(axxia_pei_mux); + +struct axxia_pei { + unsigned int control; + int control_set; + unsigned int initialized; +}; + struct pei_coefficients { unsigned version; unsigned control; @@ -57,6 +69,7 @@ struct pei_coefficients { unsigned lane_1_vboost; }; +static struct axxia_pei axxia_pei; static struct pei_coefficients coefficients; enum SataMode { @@ -79,6 +92,12 @@ enum SrioSpeed { SRIO_SPEED_5G, SRIO_SPEED_6_25G }; + +enum PCIMode { + PEI0, + PEI1, + PEI2 +}; enum PLLMode { PLLA, PLLB @@ -94,6 +113,37 @@ enum Dir { RX }; +/* PEI0x8 000/010 which is valid? */ +enum port_config0 { + pc0_PEI0x8 = 0x0, + pc0_PEI0x4 = 0x1, + pc0_PEI0x8_alt = 0x2, + pc0_PEI0x2_PEI2x2 = 0x3, + pc0_SRIO1x2_SRIO0x2 = 0x4, + pc0_PEI0x2_SRIO0x2 = 0x7, +}; + +enum port_config1 { + pc1_PEI0x8 = 0x0, + pc1_PEI1x4 = 0x1, + pc1_PEI1x2_SATA0x1_SATA1x1 = 0x2, + pc1_PEI1x2_PEI2x2 = 0x3, +}; + +enum pipe_port { + pp_disable = 0x0, + pp_0 = 0x1, + pp_0_1 = 0x2, + pp_0_1_2_3 = 0x3, +}; + +enum pipe_nphy { + one_phy = 0x0, + two_phy = 0x1, + three_phy = 0x2, + four_phy = 0x3, +}; + /****************************************************************************** * PCIe/SRIO/SATA parameters * Supported configs: @@ -185,7 +235,7 @@ enum Dir { * Bit 2: PEI2 enabled * Bit 1: PEI1 enabled * Bit 0: PEI0 enabled - *******************************************************************************/ + ******************************************************************************/ void setup_sata_mode(enum SataMode mode, enum SataSpeed speed) { @@ -369,6 +419,7 @@ void setup_srio_mode(enum SrioMode mode, enum SrioSpeed speed) u32 regVal; u32 phy, lane, rate, width, pll; int i = 0; + if (mode == SRIO0) { phy = 1; lane = 2; @@ -566,69 +617,172 @@ void setup_srio_mode(enum SrioMode mode, enum SrioSpeed speed) } } +void disable_ltssm(enum PCIMode mode) +{ + u32 val; + + if (!is_5600 && !is_6700) + return; + + switch (mode) { + case PEI0: + /* LTSSM Disable for PEI0 */ + val = readl(pcie_gpreg0 + pcie_cc_gpreg_offset + 0x38); + val &= (~(0x1)); + writel(val, pcie_gpreg0 + pcie_cc_gpreg_offset + 0x38); + break; + case PEI1: + /* LTSSM Disable for PEI1 */ + if (!is_5600) + break; + val = readl(pcie_gpreg1 + pcie_cc_gpreg_offset + 0x38); + val &= (~(0x1)); + writel(val, pcie_gpreg1 + pcie_cc_gpreg_offset + 0x38); + break; + case PEI2: + /* LTSSM Disable for PEI2 */ + if (!is_5600) + break; + val = readl(pcie_gpreg2 + pcie_cc_gpreg_offset + 0x38); + val &= (~(0x1)); + writel(val, pcie_gpreg2 + pcie_cc_gpreg_offset + 0x38); + break; + default: + pr_err("%s Unsupported PEI %d\n", __func__, mode); + }; + + mdelay(100); /* TODO: Why is this needed? */ +} + +void set_sw_port_config0(enum port_config0 mode) +{ + u32 regVal; + + ncr_read32(NCP_REGION_ID(0x115, 0), 0, ®Val); + regVal &= ~(0x7 << 26); + regVal |= ((mode & 0x7) << 26); + ncr_write32(NCP_REGION_ID(0x115, 0), 0, regVal); +} + +void set_sw_port_config1(enum port_config1 mode) +{ + u32 regVal; + + ncr_read32(NCP_REGION_ID(0x115, 0), 0x4, ®Val); + regVal &= ~(0x3 << 22); + regVal |= ((mode & 0x3) << 22); + ncr_write32(NCP_REGION_ID(0x115, 0), 0x4, regVal); +} + +static void set_pipe_port_sel(enum pipe_port pp) +{ + u32 regVal; + + ncr_read32(NCP_REGION_ID(0x115, 0), 0x4, ®Val); + regVal &= ~(0x3 << 24); + regVal |= ((pp & 0x3) << 24); + ncr_write32(NCP_REGION_ID(0x115, 0), 0x4, regVal); +} + +static void set_pipe_nphy(enum pipe_nphy nphy) +{ + u32 regVal; + + ncr_read32(NCP_REGION_ID(0x115, 0), 0x4, ®Val); + regVal &= ~(0x3 << 20); + regVal |= ((nphy & 0x3) << 20); + ncr_write32(NCP_REGION_ID(0x115, 0), 0x4, regVal); +} + +static void set_srio_mode(enum SrioMode mode, unsigned int ctrl) +{ + u32 regVal; + + ncr_read32(NCP_REGION_ID(0x115, 0), 0, ®Val); + if (SRIO0 == mode) { + regVal &= ~(0x3 << 20); + regVal |= ((ctrl & 0x3) << 20); + } else { + regVal &= ~(0x3 << 24); + regVal |= ((ctrl & 0x3) << 24); + } + ncr_write32(NCP_REGION_ID(0x115, 0), 0, regVal); +} + +static void set_srio_speed(enum SrioMode mode, enum SrioSpeed speed) +{ + u32 regVal; + + ncr_read32(NCP_REGION_ID(0x115, 0x0), 0x4, ®Val); + if (SRIO0 == mode) { + regVal &= ~(0x7 << 12); + regVal |= ((speed & 0x7) << 12); + } else { + regVal &= ~(0x7 << 16); + regVal |= ((speed & 0x7) << 16); + } + ncr_write32(NCP_REGION_ID(0x115, 0), 0x4, regVal); +} + +static void set_pei0_rc_mode(u32 rc) +{ + u32 regVal; + + ncr_read32(NCP_REGION_ID(0x115, 0x0), 0x0, ®Val); + if (rc) + regVal |= (0x1 << 22); + else + regVal &= ~(0x1 << 22); + ncr_write32(NCP_REGION_ID(0x115, 0x0), 0x0, regVal); +} + void enable_reset(u32 phy) { u32 regVal; if (phy == 0) { - ncr_read32(NCP_REGION_ID(0x115, 0), 0, - ®Val); + ncr_read32(NCP_REGION_ID(0x115, 0), 0, ®Val); regVal |= (1 << 5); - ncr_write32(NCP_REGION_ID(0x115, 0), 0, - regVal); + ncr_write32(NCP_REGION_ID(0x115, 0), 0, regVal); } else if (phy == 1) { - ncr_read32(NCP_REGION_ID(0x115, 0), 0, - ®Val); + ncr_read32(NCP_REGION_ID(0x115, 0), 0, ®Val); regVal |= (1 << 14); - ncr_write32(NCP_REGION_ID(0x115, 0), 0, - regVal); + ncr_write32(NCP_REGION_ID(0x115, 0), 0, regVal); } else if (phy == 2) { - ncr_read32(NCP_REGION_ID(0x115, 0), 0x4, - ®Val); + ncr_read32(NCP_REGION_ID(0x115, 0), 0x4, ®Val); regVal |= (1 << 19); - ncr_write32(NCP_REGION_ID(0x115, 0), 0x4, - regVal); + ncr_write32(NCP_REGION_ID(0x115, 0), 0x4, regVal); } else if (phy == 3) { - ncr_read32(NCP_REGION_ID(0x115, 0), 0x4, - ®Val); + ncr_read32(NCP_REGION_ID(0x115, 0), 0x4, ®Val); regVal |= (1 << 29); - ncr_write32(NCP_REGION_ID(0x115, 0), 0x4, - regVal); + ncr_write32(NCP_REGION_ID(0x115, 0), 0x4, regVal); } } -void release_reset(u32 phy) +static void release_reset(u32 phy) { u32 regVal; if (phy == 0) { - ncr_read32(NCP_REGION_ID(0x115, 0), 0, - ®Val); + ncr_read32(NCP_REGION_ID(0x115, 0), 0, ®Val); regVal &= (~(1 << 5)); - ncr_write32(NCP_REGION_ID(0x115, 0), 0, - regVal); + ncr_write32(NCP_REGION_ID(0x115, 0), 0, regVal); } else if (phy == 1) { - ncr_read32(NCP_REGION_ID(0x115, 0), 0, - ®Val); + ncr_read32(NCP_REGION_ID(0x115, 0), 0, ®Val); regVal &= (~(1 << 14)); - ncr_write32(NCP_REGION_ID(0x115, 0), 0, - regVal); + ncr_write32(NCP_REGION_ID(0x115, 0), 0, regVal); } else if (phy == 2) { - ncr_read32(NCP_REGION_ID(0x115, 0), 0x4, - ®Val); + ncr_read32(NCP_REGION_ID(0x115, 0), 0x4, ®Val); regVal &= (~(1 << 19)); - ncr_write32(NCP_REGION_ID(0x115, 0), 0x4, - regVal); + ncr_write32(NCP_REGION_ID(0x115, 0), 0x4, regVal); } else if (phy == 3) { - ncr_read32(NCP_REGION_ID(0x115, 0), 0x4, - ®Val); + ncr_read32(NCP_REGION_ID(0x115, 0), 0x4, ®Val); regVal &= (~(1 << 29)); - ncr_write32(NCP_REGION_ID(0x115, 0), 0x4, - regVal); + ncr_write32(NCP_REGION_ID(0x115, 0), 0x4, regVal); } } -int check_pll_lock(enum PLLMode mode, u32 phy) +static int check_pll_lock(enum PLLMode mode, u32 phy) { u32 regVal; int count = 0; @@ -647,7 +801,36 @@ int check_pll_lock(enum PLLMode mode, u32 phy) return regVal; } -int check_ack(u32 phy, u32 lane, enum Dir dir) +static int release_srio_reset(enum SrioMode mode, enum SrioSpeed speed) +{ + u32 phy; + enum PLLMode pll; + + switch (mode) { + case SRIO0: + phy = 1; + break; + case SRIO1: + phy = 0; + break; + default: + pr_err("Wrong SRIO%d\n", mode); + return 1; + } + + release_reset(phy); + pll = PLLA; + if ((SRIO_SPEED_3_125G == speed) || + (SRIO_SPEED_6_25G == speed)) + pll = PLLB; + if (!check_pll_lock(pll, phy)) { + pr_err("%s didn't lock\n", pll == PLLA ? "PLLA" : "PLLB"); + return 1; + } + return 0; +} + +static int check_ack(u32 phy, u32 lane, enum Dir dir) { u32 regVal; int count = 0; @@ -672,6 +855,33 @@ int check_ack(u32 phy, u32 lane, enum Dir dir) return regVal; } +static int check_srio_ack(enum SrioMode mode) +{ + unsigned int phy; + unsigned int lane; + + switch (mode) { + case SRIO0: + phy = 1; + break; + case SRIO1: + phy = 0; + break; + default: + pr_err("Wrong SRIO%d\n", mode); + return 1; + } + + for (lane = 0; lane < 2; lane++) { + if (!check_ack(phy, lane, RX)) { + pr_err("RX ACK not set for PHY%d LANE%d\n", phy, lane); + return 1; + } + } + + return 0; +} + void set_tx_clk_ready(void) { u32 regVal; @@ -733,6 +943,40 @@ powerup_lane(u32 phy, u32 lane, enum PowerState state, enum Dir dir) return ret; } +static int +powerup_srio_lanes(enum SrioMode mode, enum PowerState state) +{ + u32 lane; + u32 phy; + + switch (mode) { + case SRIO0: + phy = 1; + break; + case SRIO1: + phy = 0; + break; + default: + pr_err("Wrong SRIO%d\n", mode); + return 1; + } + + /* Power up TX/RX lanes */ + for (lane = 0; lane < 2; lane++) { + if (!powerup_lane(phy, lane, state, TX)) { + pr_err("TX powerup failed for PHY%d LANE%d\n", + phy, lane); + return 1; + } + if (!powerup_lane(phy, lane, state, RX)) { + pr_err("RX powerup failed for PHY%d LANE%d\n", + phy, lane); + return 1; + } + } + return 0; +} + /* ------------------------------------------------------------------------------ enable_lane @@ -757,8 +1001,29 @@ enable_lane(u32 phy, u32 lane, enum Dir dir) regVal |= (1 << 21); ncr_write32(NCP_REGION_ID(0x115, 0), offset, regVal); +} - return; +static void enable_srio_lanes(enum SrioMode mode) +{ + u32 lane; + u32 phy; + + switch (mode) { + case SRIO0: + phy = 1; + break; + case SRIO1: + phy = 0; + break; + default: + pr_err("Wrong SRIO%d\n", mode); + return; + } + + for (lane = 0; lane < 2; lane++) { + enable_lane(phy, lane, TX); + enable_lane(phy, lane, RX); + } } /* @@ -900,7 +1165,6 @@ update_settings(void) ncr_write32(region, offset, value); } - return; } @@ -909,15 +1173,11 @@ update_settings(void) pei_setup */ -int -pei_setup(void) +static int +pei_setup(unsigned int control) { - unsigned int control; unsigned int pci_srio_sata_mode; - unsigned int val; unsigned int rc_mode; - unsigned int phyVal0; - unsigned int phyVal1; unsigned int srio0_mode; unsigned int srio1_mode; unsigned int srio0_speed; @@ -928,19 +1188,18 @@ pei_setup(void) unsigned int sata1_mode; unsigned int srio0_ctrl; unsigned int srio1_ctrl; - unsigned int reg_val = 0; - enum PLLMode pll; + unsigned int pei0_mode; + unsigned int pei1_mode; + unsigned int pei2_mode; + u32 reg_val = 0; int phy, lane; - if (!is_pei_control_available) { - pr_err("Control value is NOT available!\n"); - - return 1; - } - - control = coefficients.control; - pci_srio_sata_mode = (control & 0x03c00000) >> 22; + /* + pr_debug("YYY: pei_setup control=0x%08x pci_srio_sata_mode=%d\n", + control, pci_srio_sata_mode); + */ + sata0_mode = (control & 0x20) >> 5; sata1_mode = (control & 0x40) >> 6; @@ -953,749 +1212,578 @@ pei_setup(void) srio0_speed = (control & 0x7000) >> 12; srio1_speed = (control & 0x38000) >> 15; - /* LTSSM Disable for PEI0 */ - val = readl(pcie_gpreg0 + 0x8038); - val &= (~(0x1)); - writel(val, pcie_gpreg0 + 0x8038); - msleep(100); + srio0_ctrl = (control & 0x300) >> 8; + srio1_ctrl = (control & 0xc00) >> 10; + + pei0_mode = (control & 0x1); + pei1_mode = (control & 0x2) >> 1; + pei2_mode = (control & 0x4) >> 2; + + rc_mode = (control & 0x80) >> 7; + + disable_ltssm(PEI0); + disable_ltssm(PEI1); + disable_ltssm(PEI2); for (phy = 0; phy < 4; phy++) enable_reset(phy); - ncr_read32(NCP_REGION_ID(0x115, 0), 0, &phyVal0); - phyVal0 &= ~1; - ncr_write32(NCP_REGION_ID(0x115, 0), 0, phyVal0); + /* Disable all interfaces */ + ncr_read32(NCP_REGION_ID(0x115, 0), 0, ®_val); + reg_val &= ~(0xf | (0x1 << 10) | (0x3 << 29)); + ncr_write32(NCP_REGION_ID(0x115, 0), 0, reg_val); mdelay(100); /* TODO: Why is this needed? */ switch (pci_srio_sata_mode) { case 0: - /* PEI0x8 */ - rc_mode = (control & 0x80)<<15; - /* Enable PEI0, PEI0 RC mode */ - phyVal0 = (control & 0x1) | rc_mode; - ncr_write32(NCP_REGION_ID(0x115, 0), 0, phyVal0); - /* PIPE port select -- Enable PIPE0 interface */ - ncr_write32(NCP_REGION_ID(0x115, 0), 0x4, (0x1<<24)); + set_sw_port_config0(pc0_PEI0x8); + set_sw_port_config1(pc1_PEI0x8); + set_pei0_rc_mode(rc_mode); + set_pipe_port_sel(pp_0); + set_pipe_nphy(four_phy); + + if (pei0_mode) + for (phy = 0; phy < 4; phy++) + release_reset(phy); + + /* Enable PEI0 */ + ncr_read32(NCP_REGION_ID(0x115, 0), 0x0, ®_val); + reg_val |= (pei0_mode << 0); + ncr_write32(NCP_REGION_ID(0x115, 0), 0x0, reg_val); break; case 1: /* PEI0x4, PEI1x4 */ - phyVal1 = 0x0e7001ac; - ncr_write32(NCP_REGION_ID(0x115, 0), 0x4, phyVal1); - - phyVal0 = 0x84400040; - ncr_write32(NCP_REGION_ID(0x115, 0), 0, phyVal0); + set_sw_port_config0(pc0_PEI0x4); + set_sw_port_config1(pc1_PEI1x4); + set_pei0_rc_mode(rc_mode); + set_pipe_port_sel(pp_0_1); + set_pipe_nphy(four_phy); + + if (pei0_mode) + for (phy = 0; phy < 2; phy++) + release_reset(phy); + if (pei1_mode) + for (phy = 2; phy < 4; phy++) + release_reset(phy); + + /* Enable PEI0/PEI1 */ + ncr_read32(NCP_REGION_ID(0x115, 0), 0x0, ®_val); + reg_val |= + (pei0_mode << 0) | + (pei1_mode << 1); + ncr_write32(NCP_REGION_ID(0x115, 0), 0x0, reg_val); break; case 2: /* PEI0x4_PEI1x2_SATA0x1_SATA1x1 */ - rc_mode = (control & 0x80)<<15; /* Enable PEI0/PEI1, PEI0 RC mode */ - phyVal0 = (control & 0x3) | rc_mode; - /* PEI0x4 */ - phyVal0 |= (0x1 << 26); - ncr_write32(NCP_REGION_ID(0x115, 0), 0, phyVal0); - /* PEI1x2_SATA0_SATA1 */ - phyVal1 = (0x1 << 23); - /* PIPE port select -- Enable PIPE0/PIPE1 interface */ - phyVal1 |= (0x2 << 24); - ncr_write32(NCP_REGION_ID(0x115, 0), 0x4, phyVal1); + set_sw_port_config0(pc0_PEI0x4); + set_sw_port_config1(pc1_PEI1x2_SATA0x1_SATA1x1); + set_pei0_rc_mode(rc_mode); + set_pipe_port_sel(pp_0_1); + + if (pei0_mode) + for (phy = 0; phy < 2; phy++) + release_reset(phy); + if (pei1_mode) + release_reset(2); + + /* Enable PEI0/PEI1 */ + ncr_read32(NCP_REGION_ID(0x115, 0), 0, ®_val); + reg_val |= (pei0_mode << 0) | (pei1_mode << 1); + ncr_write32(NCP_REGION_ID(0x115, 0), 0, reg_val); + if (sata0_mode) setup_sata_mode(SATA0, sata0_speed); if (sata1_mode) setup_sata_mode(SATA1, sata1_speed); - if (!check_pll_lock(PLLA, 1)) { - printk("PLLA didn't lock\n"); - return 1; - } - for (lane = 0; lane < 2; lane++) { - if (!check_ack(3, lane, TX)) { - printk("TX ACK not set for PHY3 LANE%d\n", lane); - return 1; - } - if (!check_ack(3, lane, RX)) { - printk("RX ACK not set for PHY3 LANE%d\n", lane); - return 1; + if (sata0_mode || sata1_mode) { + release_reset(3); + for (lane = 0; lane < 2; lane++) { + if (!check_ack(3, lane, TX)) { + pr_err("TX ACK not set for PHY3 LANE%d\n", + lane); + return 1; + } + if (!check_ack(3, lane, RX)) { + pr_err("RX ACK not set for PHY3 LANE%d\n", + lane); + return 1; + } } - } - /* Set TX clock ready */ - set_tx_clk_ready(); + /* Set TX clock ready */ + set_tx_clk_ready(); + } /* Enable SATA0/SATA1 */ - ncr_read32(NCP_REGION_ID(0x115, 0), 0x4, &phyVal0); - phyVal0 |= (control & 0x20) << 24; - phyVal0 |= (control & 0x40) << 24; - ncr_write32(NCP_REGION_ID(0x115, 0), 0, phyVal0); + ncr_read32(NCP_REGION_ID(0x115, 0), 0, ®_val); + reg_val |= (sata0_mode << 29) | (sata1_mode << 30); + ncr_write32(NCP_REGION_ID(0x115, 0), 0, reg_val); - if (!check_rx_valid(3, 0)) { - printk("RX clock/data recovery not asserted for PHY3 LANE0\n"); - return 1; - } - if (!check_rx_valid(3, 1)) { - printk("RX clock/data recovery not asserted for PHY3 LANE1\n"); - return 1; + if (sata0_mode || sata1_mode) { + if (!check_rx_valid(3, 0)) { + pr_err("RX clock/data recovery not asserted for PHY3 LANE0\n"); + return 1; + } + if (!check_rx_valid(3, 1)) { + pr_err("RX clock/data recovery not asserted for PHY3 LANE1\n"); + return 1; + } } break; case 3: - /* PEI0x2_PEI2x2_PEI1x2_SATA0x1_SATA1x1 */ - rc_mode = (control & 0x80)<<15; - /* Enable PEI0/PEI1/PEI2, PEI0 RC mode */ - phyVal0 = (control & 0x7) | rc_mode; /* PEI0x2_PEI2x2 */ - phyVal0 |= (0x3 << 26); - ncr_write32(NCP_REGION_ID(0x115, 0), 0, phyVal0); /* PEI1x2_SATA0_SATA1 */ - phyVal1 = (0x1 << 23); - /* PIPE port select -- Enable PIPE0, PIPE1 - * and PIPE2 interface */ - phyVal1 |= (0x3 << 24); - ncr_write32(NCP_REGION_ID(0x115, 0), 0x4, phyVal1); + set_sw_port_config0(pc0_PEI0x2_PEI2x2); + set_sw_port_config1(pc1_PEI1x2_SATA0x1_SATA1x1); + set_pei0_rc_mode(rc_mode); + set_pipe_port_sel(pp_0_1_2_3); + + if (pei0_mode) + release_reset(0); + if (pei1_mode) + release_reset(1); + if (pei2_mode) + release_reset(2); + + /* Enable PEI0/PEI1/PEI2 */ + ncr_read32(NCP_REGION_ID(0x115, 0), 0, ®_val); + reg_val |= (pei0_mode << 0) | (pei1_mode << 1) | + (pei2_mode << 2); + ncr_write32(NCP_REGION_ID(0x115, 0), 0, reg_val); + if (sata0_mode) setup_sata_mode(SATA0, sata0_speed); if (sata1_mode) setup_sata_mode(SATA1, sata1_speed); - - if (!check_pll_lock(PLLA, 1)) { - printk("PLLA didn't lock\n"); - return 1; - } - for (lane = 0; lane < 2; lane++) { - if (!check_ack(3, lane, TX)) { - printk("TX ACK not set for PHY3 LANE%d\n", lane); - return 1; - } - if (!check_ack(3, lane, RX)) { - printk("RX ACK not set for PHY3 LANE%d\n", lane); - return 1; + if (sata0_mode || sata1_mode) { + release_reset(3); + for (lane = 0; lane < 2; lane++) { + if (!check_ack(3, lane, TX)) { + pr_err("TX ACK not set for PHY3 LANE%d\n", + lane); + return 1; + } + if (!check_ack(3, lane, RX)) { + pr_err("RX ACK not set for PHY3 LANE%d\n", + lane); + return 1; + } } + /* Set TX clock ready */ + set_tx_clk_ready(); } - /* Set TX clock ready */ - set_tx_clk_ready(); /* Enable SATA0/SATA1 */ - ncr_read32(NCP_REGION_ID(0x115, 0), 0, &phyVal0); - phyVal0 |= (control & 0x20) << 24; - phyVal0 |= (control & 0x40) << 24; - ncr_write32(NCP_REGION_ID(0x115, 0), 0, phyVal0); + ncr_read32(NCP_REGION_ID(0x115, 0), 0, ®_val); + reg_val |= (sata0_mode << 29) | (sata1_mode << 30); + ncr_write32(NCP_REGION_ID(0x115, 0), 0, reg_val); - if (!check_rx_valid(3, 0)) { - printk("RX clock/data recovery not asserted for PHY3 LANE0\n"); - return 1; - } - if (!check_rx_valid(3, 1)) { - printk("RX clock/data recovery not asserted for PHY3 LANE1\n"); - return 1; + if (sata0_mode || sata1_mode) { + if (!check_rx_valid(3, 0)) { + pr_err("RX clock/data recovery not asserted for PHY3 LANE0\n"); + return 1; + } + if (!check_rx_valid(3, 1)) { + pr_err("RX clock/data recovery not asserted for PHY3 LANE1\n"); + return 1; + } } break; case 4: /* PEI0x2_SRIO0x2_PEI1x4 */ - rc_mode = (control & 0x80)<<15; /* Enable PEI0/PEI1/SRIO0, PEI0 RC mode */ - phyVal0 = (control & 0x3) | rc_mode; - /* PEI0x2_SRI0x2 */ - phyVal0 |= (0x7 << 26); - /* SRIO0 mode */ - srio0_ctrl = ((control & 0x300) << 12); + set_sw_port_config0(pc0_PEI0x2_SRIO0x2); + set_sw_port_config1(pc1_PEI1x4); + set_pei0_rc_mode(rc_mode); + set_pipe_port_sel(pp_0_1); + + if (pei0_mode) + release_reset(0); + if (pei1_mode) + for (phy = 2; phy < 4; phy++) + release_reset(phy); + + /* Enable PEI0/PEI1 */ ncr_read32(NCP_REGION_ID(0x115, 0), 0, ®_val); - reg_val &= ~(0xf | (0x1 << 22) | (0x7<<26) | (0x3 << 20)); - reg_val |= phyVal0 | srio0_ctrl; + reg_val |= (pei0_mode << 0) | (pei1_mode << 1); ncr_write32(NCP_REGION_ID(0x115, 0), 0, reg_val); - /* PEI1x4 */ - phyVal1 = (0x1 << 22); - /* PIPE port select -- Enable PIPE0/PIPE1 interface */ - phyVal1 |= (0x2 << 24); - /* SRIO0 speed */ - srio0_speed = (control & 0x7000); - ncr_read32(NCP_REGION_ID(0x115, 0), 0x4, ®_val); - reg_val &= ~((0x3<<24) | (0x3 << 22) | (0x7 << 12)); - reg_val |= (phyVal1 | srio0_speed); - ncr_write32(NCP_REGION_ID(0x115, 0), 0x4, reg_val); - srio0_speed = srio0_speed >> 12; - if (srio0_mode) - setup_srio_mode(SRIO0, srio0_speed); - printk("Set up sRIO0 -- %d\n", srio0_speed); - for (phy = 0; phy < 4; phy++) - release_reset(phy); - - pll = PLLA; - if ((srio0_speed == SRIO_SPEED_3_125G) - || (srio0_speed == SRIO_SPEED_6_25G)) - pll = PLLB; - if (!check_pll_lock(pll, 1)) { - printk("%s didn't lock\n", - pll == PLLA ? "PLLA" : "PLLB"); - return 1; - } - printk("Enabling sRIO ."); - for (lane = 0; lane < 2; lane++) { - if (!check_ack(3, lane, RX)) { - printk("RX ACK not set for PHY1 LANE%d\n", lane); - return 1; - } - } - /* Power up TX/RX lanes */ - for (lane = 0; lane < 2; lane++) { - if (!powerup_lane(1, lane, P1, TX)) { - printk("TX powerup failed for PHY1 LANE%d\n", lane); - return 1; - } - if (!powerup_lane(1, lane, P1, RX)) { - printk("RX powerup failed for PHY1 LANE%d\n", lane); - return 1; - } - } - - /* Set TX clock ready */ - set_tx_clk_ready(); + set_srio_mode(SRIO0, srio0_ctrl); + set_srio_speed(SRIO0, srio0_speed); + pr_debug("Set up sRIO0 -- %d\n", srio0_speed); + if (srio0_mode && release_srio_reset(SRIO0, srio0_speed)) + srio0_mode = 0; + pr_debug("Enabling sRIO ."); + if (srio0_mode && check_srio_ack(SRIO0)) + srio0_mode = 0; /* Power up TX/RX lanes */ - for (lane = 0; lane < 2; lane++) { - if (!powerup_lane(1, lane, P0, TX)) { - printk("TX powerup failed for PHY1 LANE%d\n", lane); - return 1; - } - if (!powerup_lane(1, lane, P0, RX)) { - printk("RX powerup failed for PHY1 LANE%d\n", lane); - return 1; - } - } - - for (lane = 0; lane < 2; lane++) { - enable_lane(1, lane, TX); - enable_lane(1, lane, RX); - } + if (srio0_mode && powerup_srio_lanes(SRIO0, P1)) + srio0_mode = 0; + /* Set TX clock ready */ + if (srio0_mode) + set_tx_clk_ready(); + if (srio0_mode && powerup_srio_lanes(SRIO0, P0)) + srio0_mode = 0; + if (srio0_mode) + enable_srio_lanes(SRIO0); /* Enable SRIO0 */ - ncr_read32(NCP_REGION_ID(0x115, 0), 0, &phyVal0); - ncr_write32(NCP_REGION_ID(0x115, 0), 0, - phyVal0 | 0x8); - printk("Done\n"); + ncr_read32(NCP_REGION_ID(0x115, 0), 0, ®_val); + reg_val |= (srio0_mode << 3); + ncr_write32(NCP_REGION_ID(0x115, 0), 0, reg_val); + pr_debug("Done\n"); break; case 5: /* PEI0x2_SRIO0x2_PEI1x2_SATA0x1_SATA1x1 */ - rc_mode = (control & 0x80)<<15; /* Enable PEI0/PEI1/SRIO0, PEI0 RC mode */ - phyVal0 = (control & 0x3) | rc_mode; - /* PEI0x2_SRI0x2 */ - phyVal0 |= (0x7 << 26); - /* SRIO0 mode */ - srio0_ctrl = ((control & 0x300) << 12); + set_sw_port_config0(pc0_PEI0x2_SRIO0x2); + set_sw_port_config1(pc1_PEI1x2_SATA0x1_SATA1x1); + set_pei0_rc_mode(rc_mode); + set_pipe_port_sel(pp_0_1); + set_pipe_nphy(three_phy); + + if (pei0_mode) + release_reset(0); + if (pei1_mode) + release_reset(2); + + /* Enable PEI0/PEI1 */ ncr_read32(NCP_REGION_ID(0x115, 0), 0, ®_val); - reg_val &= ~(0xf | (0x1 << 22) | (0x7<<26) | (0x3 << 20)); - reg_val |= phyVal0 | srio0_ctrl; + reg_val |= (pei0_mode << 0) | (pei1_mode << 1); ncr_write32(NCP_REGION_ID(0x115, 0), 0, reg_val); - /* PEI1x2_SATA0x1_SATA1x1 */ - phyVal1 = (0x1 << 23); - /* PIPE port select -- Enable PIPE0/PIPE1 interface */ - phyVal1 |= (0x2 << 24); - /* SRIO0 speed */ - srio0_speed = (control & 0x7000); - ncr_read32(NCP_REGION_ID(0x115, 0), 0x4, ®_val); - reg_val &= ~((0x3<<24) | (0x3 << 22) | (0x7 << 12)); - reg_val |= (phyVal1 | srio0_speed); - ncr_write32(NCP_REGION_ID(0x115, 0), 0x4, reg_val); - srio0_speed = srio0_speed >> 12; + + set_srio_mode(SRIO0, srio0_ctrl); + set_srio_speed(SRIO0, srio0_speed); + if (sata0_mode) setup_sata_mode(SATA0, sata0_speed); if (sata1_mode) setup_sata_mode(SATA1, sata1_speed); if (srio0_mode) setup_srio_mode(SRIO0, srio0_speed); - printk("Set up sRIO0 -- %d\n", srio0_speed); - for (phy = 0; phy < 4; phy++) - release_reset(phy); - pll = PLLA; - if ((srio0_speed == SRIO_SPEED_3_125G) - || (srio0_speed == SRIO_SPEED_6_25G)) - pll = PLLB; - if (!check_pll_lock(pll, 1)) { - printk("%s didn't lock\n", - pll == PLLA ? "PLLA" : "PLLB"); - return 1; - } - for (lane = 0; lane < 2; lane++) { - if (!check_ack(3, lane, TX)) { - printk("TX ACK not set for PHY3 LANE%d\n", lane); - return 1; - } - if (!check_ack(3, lane, RX)) { - printk("RX ACK not set for PHY3 LANE%d\n", lane); - return 1; - } - } - printk("Enabling sRIO/SATA ."); - /* Power up TX/RX lanes */ - for (lane = 0; lane < 2; lane++) { - if (!powerup_lane(1, lane, P1, TX)) { - printk("TX powerup failed for PHY1 LANE%d\n", lane); - return 1; - } - if (!powerup_lane(1, lane, P1, RX)) { - printk("RX powerup failed for PHY1 LANE%d\n", lane); - return 1; + pr_debug("Set up sRIO0 -- %d\n", srio0_speed); + if (srio0_mode && release_srio_reset(SRIO0, srio0_speed)) + srio0_mode = 0; + if (sata0_mode || sata1_mode) + release_reset(3); + if (sata0_mode || sata1_mode) { + for (lane = 0; lane < 2; lane++) { + if (!check_ack(3, lane, TX)) { + pr_err("TX ACK not set for PHY3 LANE%d\n", + lane); + return 1; + } + if (!check_ack(3, lane, RX)) { + pr_err("RX ACK not set for PHY3 LANE%d\n", + lane); + return 1; + } } } + pr_debug("Enabling sRIO/SATA ."); + if (srio0_mode && check_srio_ack(SRIO0)) + srio0_mode = 0; + if (srio0_mode && powerup_srio_lanes(SRIO0, P1)) + srio0_mode = 0; /* Set TX clock ready */ - set_tx_clk_ready(); + if (srio0_mode || sata0_mode || sata1_mode) + set_tx_clk_ready(); - /* Power up TX/RX lanes */ - for (lane = 0; lane < 2; lane++) { - if (!powerup_lane(1, lane, P0, TX)) { - printk("TX powerup failed for PHY1 LANE%d\n", lane); + if (srio0_mode && powerup_srio_lanes(SRIO0, P0)) + srio0_mode = 0; + if (srio0_mode) + enable_srio_lanes(SRIO0); + + /* Enable SATA0/SATA1 */ + ncr_read32(NCP_REGION_ID(0x115, 0), 0, ®_val); + reg_val |= (sata0_mode << 29) | (sata1_mode << 30); + ncr_write32(NCP_REGION_ID(0x115, 0), 0, reg_val); + + if (sata0_mode || sata1_mode) { + if (!check_rx_valid(3, 0)) { + pr_err("RX clock/data recovery not asserted for PHY3 LANE0\n"); return 1; } - if (!powerup_lane(1, lane, P0, RX)) { - printk("RX powerup failed for PHY1 LANE%d\n", lane); + if (!check_rx_valid(3, 1)) { + pr_err("RX clock/data recovery not asserted for PHY3 LANE1\n"); return 1; } } - printk("."); - for (lane = 0; lane < 2; lane++) { - enable_lane(1, lane, TX); - enable_lane(1, lane, RX); - } - /* Enable SATA0/SATA1 */ - ncr_read32(NCP_REGION_ID(0x115, 0), 0, &phyVal0); - phyVal0 |= (control & 0x20) << 24; - phyVal0 |= (control & 0x40) << 24; - ncr_write32(NCP_REGION_ID(0x115, 0), 0, phyVal0); - - if (!check_rx_valid(3, 0)) { - printk("RX clock/data recovery not asserted for PHY3 LANE0\n"); - return 1; - } - if (!check_rx_valid(3, 1)) { - printk("RX clock/data recovery not asserted for PHY3 LANE1\n"); - return 1; - } /* Enable SRIO0 */ - ncr_read32(NCP_REGION_ID(0x115, 0), 0, &phyVal0); - ncr_write32(NCP_REGION_ID(0x115, 0), 0, - phyVal0 | 0x8); - printk("Done\n"); + ncr_read32(NCP_REGION_ID(0x115, 0), 0, ®_val); + reg_val |= (srio0_mode << 3); + ncr_write32(NCP_REGION_ID(0x115, 0), 0, reg_val); + pr_debug("Done\n"); break; case 6: /* PEI0x2_SRIO0x2_PEI1x2_PEI2x2 */ - rc_mode = (control & 0x80)<<15; /* Enable PEI0/PEI1/PEI2/SRIO0, PEI0 RC mode */ - phyVal0 = (control & 0x7) | rc_mode; - /* PEI0x2_SRIO0x2 */ - phyVal0 |= (0x7 << 26); - /* SRIO0 mode */ - srio0_ctrl = ((control & 0x300) << 12); + set_pei0_rc_mode(rc_mode); + set_sw_port_config0(pc0_PEI0x2_SRIO0x2); + set_sw_port_config1(pc1_PEI1x2_PEI2x2); + set_pipe_port_sel(pp_0_1_2_3); + set_pipe_nphy(three_phy); + + if (pei0_mode) + release_reset(0); + if (pei1_mode) + release_reset(2); + if (pei2_mode) + release_reset(3); + + /* Enable PEI0/PEI1/PEI2 */ ncr_read32(NCP_REGION_ID(0x115, 0), 0, ®_val); - reg_val &= ~(0xf | (0x1 << 22) | (0x7<<26) | (0x3 << 20)); - reg_val |= phyVal0 | srio0_ctrl; + reg_val |= (pei0_mode << 0) | (pei1_mode << 1) | + (pei2_mode << 2); ncr_write32(NCP_REGION_ID(0x115, 0), 0, reg_val); - /* PEI1x2_PEI2x2 */ - phyVal1 = (0x3 << 22); - /* PIPE port select -- Enable PIPE0, PIPE1 - * and PIPE2 interface */ - phyVal1 |= (0x3 << 24); - /* SRIO0 speed */ - srio0_speed = (control & 0x7000); - ncr_read32(NCP_REGION_ID(0x115, 0), 0x4, ®_val); - reg_val &= ~((0x3<<24) | (0x3 << 22) | (0x7 << 12)); - reg_val |= (phyVal1 | srio0_speed); - ncr_write32(NCP_REGION_ID(0x115, 0), 0x4, reg_val); - srio0_speed = srio0_speed >> 12; - if (srio0_mode) + + set_srio_mode(SRIO0, srio0_ctrl); + set_srio_speed(SRIO0, srio0_speed); + if (srio0_mode) { + pr_err("Set up sRIO0 -- %d\n", srio0_speed); setup_srio_mode(SRIO0, srio0_speed); - printk("Set up sRIO0 -- %d\n", srio0_speed); - for (phy = 0; phy < 4; phy++) - release_reset(phy); - - pll = PLLA; - if ((srio0_speed == SRIO_SPEED_3_125G) - || (srio0_speed == SRIO_SPEED_6_25G)) - pll = PLLB; - if (!check_pll_lock(pll, 1)) { - printk("%s didn't lock\n", - pll == PLLA ? "PLLA" : "PLLB"); - return 1; + if (release_srio_reset(SRIO0, srio0_speed)) + srio0_mode = 0; } - printk("Enabling sRIO ."); - /* Power up TX/RX lanes */ - for (lane = 0; lane < 2; lane++) { - if (!powerup_lane(1, lane, P1, TX)) { - printk("TX powerup failed for PHY1 LANE%d\n", lane); - return 1; - } - if (!powerup_lane(1, lane, P1, RX)) { - printk("RX powerup failed for PHY1 LANE%d\n", lane); - return 1; - } - } + if (srio0_mode && powerup_srio_lanes(SRIO0, P1)) + srio0_mode = 0; /* Set TX clock ready */ - set_tx_clk_ready(); + if (srio0_mode) { + set_tx_clk_ready(); - /* Power up TX/RX lanes */ - for (lane = 0; lane < 2; lane++) { - if (!powerup_lane(1, lane, P0, TX)) { - printk("TX powerup failed for PHY1 LANE%d\n", lane); - return 1; - } - if (!powerup_lane(1, lane, P0, RX)) { - printk("RX powerup failed for PHY1 LANE%d\n", lane); - return 1; - } + if (powerup_srio_lanes(SRIO0, P0)) + srio0_mode = 0; } + if (srio0_mode) + enable_srio_lanes(SRIO0); - for (lane = 0; lane < 2; lane++) { - enable_lane(1, lane, TX); - enable_lane(1, lane, RX); - } /* Enable SRIO0 */ - ncr_read32(NCP_REGION_ID(0x115, 0), 0, &phyVal0); - ncr_write32(NCP_REGION_ID(0x115, 0), 0, - phyVal0 | 0x8); - printk("Done\n"); + ncr_read32(NCP_REGION_ID(0x115, 0), 0, ®_val); + reg_val |= (srio0_mode << 3); + ncr_write32(NCP_REGION_ID(0x115, 0), 0, reg_val); + pr_debug("Done\n"); break; case 7: /* SRIO1x2_SRIO0x2_PEI1x4 */ /* Enable PEI1/SRIO0/SRIO1 */ - phyVal0 = (control & 0x2); - /* SRIO1x2_SRIO0x2 */ - phyVal0 |= (0x4 << 26); - /* SRIO0 mode */ - srio0_ctrl = ((control & 0x300) << 12); - /* SRIO1 mode */ - srio1_ctrl = ((control & 0xC00) << 14); + set_sw_port_config0(pc0_SRIO1x2_SRIO0x2); + set_sw_port_config1(pc1_PEI1x4); + set_pipe_port_sel(pp_0_1); + set_pipe_nphy(four_phy); + + if (pei1_mode) + for (phy = 2; phy < 4; phy++) + release_reset(phy); + /* Enable PEI1 */ ncr_read32(NCP_REGION_ID(0x115, 0), 0, ®_val); - reg_val &= ~(0xf | (0x7<<26) | (0x3 << 20) | (0x3 << 24)); - reg_val |= (phyVal0 | srio0_ctrl | srio1_ctrl); + reg_val |= (pei1_mode << 1); ncr_write32(NCP_REGION_ID(0x115, 0), 0, reg_val); - /* PEI1x4 */ - phyVal1 = (0x1 << 22); - /* PIPE port select -- Enable PIPE0/PIPE1 interface */ - phyVal1 |= (0x2 << 24); - /* SRIO0 speed */ - srio0_speed = (control & 0x7000); - /* SRIO1 speed */ - srio1_speed = (control & 0x38000) << 1; - ncr_read32(NCP_REGION_ID(0x115, 0), 0x4, ®_val); - reg_val &= ~((0x3 << 24) | (0x3 << 22) | (0x7 << 12) | - (0x7 << 16)); - reg_val |= (phyVal1 | srio0_speed | srio1_speed); - ncr_write32(NCP_REGION_ID(0x115, 0), 0x4, reg_val); - srio0_speed = srio0_speed >> 12; - srio1_speed = srio1_speed >> 16; - if (srio0_mode) + + set_srio_mode(SRIO0, srio0_ctrl); + set_srio_mode(SRIO1, srio1_ctrl); + set_srio_speed(SRIO0, srio0_speed); + set_srio_speed(SRIO1, srio1_speed); + pr_debug("Set up sRIO0 -- %d\n", srio0_speed); + if (srio0_mode) { setup_srio_mode(SRIO0, srio0_speed); - printk("Set up sRIO0 -- %d\n", srio0_speed); - if (srio1_mode) + if (release_srio_reset(SRIO0, srio0_speed)) + srio0_mode = 0; + } + pr_debug("Set up sRIO1 -- %d\n", srio1_speed); + if (srio1_mode) { setup_srio_mode(SRIO1, srio1_speed); - printk("Set up sRIO1 -- %d\n", srio1_speed); - for (phy = 0; phy < 4; phy++) - release_reset(phy); - - for (phy = 0; phy < 2; phy++) { - pll = PLLA; - if ((phy == 0) && - ((srio1_speed == SRIO_SPEED_3_125G) || - (srio1_speed == SRIO_SPEED_6_25G))) - pll = PLLB; - else if ((phy == 1) && - ((srio0_speed == SRIO_SPEED_3_125G) || - (srio0_speed == SRIO_SPEED_6_25G))) - pll = PLLB; - if (!check_pll_lock(pll, phy)) { - printk("%s didn't lock\n", - pll == PLLA ? "PLLA" : "PLLB"); - return 1; - } + if (release_srio_reset(SRIO1, srio1_speed)) + srio1_mode = 0; } - printk("Enabling sRIO ."); + pr_debug("Enabling sRIO ."); /* Power up TX/RX lanes */ - for (phy = 0; phy < 2; phy++) { - for (lane = 0; lane < 2; lane++) { - if (!powerup_lane(phy, lane, P1, TX)) { - printk("TX powerup failed for PHY%d LANE%d\n", phy, lane); - return 1; - } - if (!powerup_lane(phy, lane, P1, RX)) { - printk("RX powerup failed for PHY%d LANE%d\n", phy, lane); - return 1; - } - } + if (srio0_mode) { + pr_debug("0 ."); + if (powerup_srio_lanes(SRIO0, P1)) + srio0_mode = 0; + } + if (srio1_mode) { + pr_debug("1 ."); + if (powerup_srio_lanes(SRIO1, P1)) + srio1_mode = 0; } - printk("."); + pr_debug("."); /* Set TX clock ready */ - set_tx_clk_ready(); + if (srio0_mode || srio1_mode) + set_tx_clk_ready(); + /* Power up TX/RX lanes */ - for (phy = 0; phy < 2; phy++) { - for (lane = 0; lane < 2; lane++) { - if (!powerup_lane(phy, lane, P0, TX)) { - printk("TX powerup failed for PHY%d LANE%d\n", phy, lane); - return 1; - } - if (!powerup_lane(phy, lane, P0, RX)) { - printk("RX powerup failed for PHY%d LANE%d\n", phy, lane); - return 1; - } - } - } - printk("."); - for (phy = 0; phy < 2; phy++) { - for (lane = 0; lane < 2; lane++) { - enable_lane(phy, lane, TX); - enable_lane(phy, lane, RX); - } - } - printk("."); + if (srio0_mode && powerup_srio_lanes(SRIO0, P0)) + srio0_mode = 0; + if (srio1_mode && powerup_srio_lanes(SRIO1, P0)) + srio1_mode = 0; + pr_debug("."); + if (srio0_mode) + enable_srio_lanes(SRIO0); + if (srio1_mode) + enable_srio_lanes(SRIO1); + pr_debug("."); /* Enable SRIO0/SRIO1 */ - ncr_read32(NCP_REGION_ID(0x115, 0), 0, &phyVal0); - ncr_write32(NCP_REGION_ID(0x115, 0), 0, - phyVal0 | 0x408); - printk("Done\n"); + ncr_read32(NCP_REGION_ID(0x115, 0), 0, ®_val); + reg_val |= (srio0_mode << 3) | (srio1_mode << 10); + ncr_write32(NCP_REGION_ID(0x115, 0), 0, reg_val); + pr_debug("Done\n"); break; case 8: /* SRIO1x2_SRIO0x2_PEI1x2_SATA0x1_SATA1x1 */ /* Enable PEI1 */ - phyVal0 = (control & 0x2); - /* SRIO1x2_SRIO0x2 */ - phyVal0 |= (0x4 << 26); - /* SRIO0 mode */ - srio0_ctrl = ((control & 0x300) << 12); - /* SRIO1 mode */ - srio1_ctrl = ((control & 0xC00) << 14); + set_sw_port_config0(pc0_SRIO1x2_SRIO0x2); + set_sw_port_config1(pc1_PEI1x2_SATA0x1_SATA1x1); + set_pipe_port_sel(pp_0_1); + set_pipe_nphy(two_phy); + + if (pei1_mode) + release_reset(2); + + /* Enable PEI1 */ ncr_read32(NCP_REGION_ID(0x115, 0), 0, ®_val); - reg_val &= ~(0xf | (0x7 << 26) | (0x3 << 20) | (0x3 << 24)); - reg_val |= (phyVal0 | srio0_ctrl | srio1_ctrl); + reg_val |= (pei1_mode << 1); ncr_write32(NCP_REGION_ID(0x115, 0), 0, reg_val); - /* PEI1x2_SATA0x1_SATA1x1 */ - phyVal1 = (0x1 << 23); - /* PIPE port select -- Enable PIPE0/PIPE1 interface */ - phyVal1 |= (0x2 << 24); - /* SRIO0 speed */ - srio0_speed = (control & 0x7000); - /* SRIO1 speed */ - srio1_speed = (control & 0x38000) << 1; - ncr_read32(NCP_REGION_ID(0x115, 0), 0x4, ®_val); - reg_val &= ~((0x3 << 24) | (0x3 << 22) | (0x7 << 12) | - (0x7 << 16)); - reg_val |= (phyVal1 | srio0_speed | srio1_speed); - ncr_write32(NCP_REGION_ID(0x115, 0), 0x4, reg_val); - srio0_speed = srio0_speed >> 12; - srio1_speed = srio1_speed >> 16; + + set_srio_mode(SRIO0, srio0_ctrl); + set_srio_mode(SRIO1, srio1_ctrl); + set_srio_speed(SRIO0, srio0_speed); + set_srio_speed(SRIO1, srio1_speed); if (sata0_mode) setup_sata_mode(SATA0, sata0_speed); if (sata1_mode) setup_sata_mode(SATA1, sata1_speed); - if (srio0_mode) + pr_debug("Set up sRIO0 -- %d\n", srio0_speed); + if (srio0_mode) { setup_srio_mode(SRIO0, srio0_speed); - printk("Set up sRIO0 -- %d\n", srio0_speed); - if (srio1_mode) + if (release_srio_reset(SRIO0, srio0_speed)) + srio0_mode = 0; + } + pr_debug("Set up sRIO1 -- %d\n", srio1_speed); + if (srio1_mode) { setup_srio_mode(SRIO1, srio1_speed); - printk("Set up sRIO1 -- %d\n", srio1_speed); - for (phy = 0; phy < 4; phy++) - release_reset(phy); - - for (phy = 0; phy < 2; phy++) { - pll = PLLA; - if ((phy == 0) && ((srio1_speed == SRIO_SPEED_3_125G) - || (srio1_speed == SRIO_SPEED_6_25G))) - pll = PLLB; - else if ((phy == 1) && - ((srio0_speed == SRIO_SPEED_3_125G) - || (srio0_speed == SRIO_SPEED_6_25G))) - pll = PLLB; - if (!check_pll_lock(pll, phy)) { - printk("%s didn't lock\n", - pll == PLLA ? "PLLA" : "PLLB"); - return 1; - } + if (release_srio_reset(SRIO1, srio1_speed)) + srio1_mode = 0; } - printk("Enabling sRIO/SATA ."); + if (sata0_mode || sata1_mode) + release_reset(3); + + pr_debug("Enabling sRIO/SATA ."); /* Power up TX/RX lanes */ - for (phy = 0; phy < 2; phy++) { - for (lane = 0; lane < 2; lane++) { - if (!powerup_lane(phy, lane, P1, TX)) { - printk("TX powerup failed for PHY%d LANE%d\n", phy, lane); - return 1; - } - if (!powerup_lane(phy, lane, P1, RX)) { - printk("RX powerup failed for PHY%d LANE%d\n", phy, lane); - return 1; - } - } - } + if (srio0_mode && powerup_srio_lanes(SRIO0, P1)) + srio0_mode = 0; + if (srio1_mode && powerup_srio_lanes(SRIO1, P1)) + srio1_mode = 0; - printk("."); + pr_debug("."); /* Set TX clock ready */ - set_tx_clk_ready(); + if (srio0_mode || srio1_mode || sata0_mode || sata1_mode) + set_tx_clk_ready(); /* Power up TX/RX lanes */ - for (phy = 0; phy < 2; phy++) { - for (lane = 0; lane < 2; lane++) { - if (!powerup_lane(phy, lane, P0, TX)) { - printk("TX powerup failed for PHY%d LANE%d\n", phy, lane); - return 1; - } - if (!powerup_lane(phy, lane, P0, RX)) { - printk("RX powerup failed for PHY%d LANE%d\n", phy, lane); - return 1; - } - } - } - printk("."); + if (srio0_mode && powerup_srio_lanes(SRIO0, P0)) + srio0_mode = 0; + if (srio1_mode && powerup_srio_lanes(SRIO1, P0)) + srio1_mode = 0; + pr_debug("."); - for (phy = 0; phy < 2; phy++) { - for (lane = 0; lane < 2; lane++) { - enable_lane(phy, lane, TX); - enable_lane(phy, lane, RX); - } - } - printk("."); + if (srio0_mode) + enable_srio_lanes(SRIO0); + if (srio1_mode) + enable_srio_lanes(SRIO1); + pr_debug("."); /* Enable SATA0/SATA1 */ - ncr_read32(NCP_REGION_ID(0x115, 0), 0, &phyVal0); - phyVal0 |= (control & 0x20) << 24; - phyVal0 |= (control & 0x40) << 24; - ncr_write32(NCP_REGION_ID(0x115, 0), 0, phyVal0); + ncr_read32(NCP_REGION_ID(0x115, 0), 0, ®_val); + reg_val |= (sata0_mode << 29) | (sata1_mode << 30); + ncr_write32(NCP_REGION_ID(0x115, 0), 0, reg_val); - if (!check_rx_valid(3, 0)) { - printk("RX clock/data recovery not asserted for PHY3 LANE0\n"); - return 1; - } - if (!check_rx_valid(3, 1)) { - printk("RX clock/data recovery not asserted for PHY3 LANE1\n"); - return 1; - } + if (sata0_mode && !check_rx_valid(3, 0)) + pr_err("RX clock/data recovery not asserted for PHY3 LANE0\n"); + if (sata1_mode && !check_rx_valid(3, 1)) + pr_err("RX clock/data recovery not asserted for PHY3 LANE1\n"); /* Enable SRIO0/SRIO1 */ - ncr_read32(NCP_REGION_ID(0x115, 0), 0, &phyVal0); - ncr_write32(NCP_REGION_ID(0x115, 0), 0, - phyVal0 | 0x408); - printk("Done\n"); + ncr_read32(NCP_REGION_ID(0x115, 0), 0, ®_val); + reg_val |= (srio0_mode << 3) | (srio1_mode << 10); + ncr_write32(NCP_REGION_ID(0x115, 0), 0, reg_val); + pr_debug("Done\n"); break; case 9: /* SRIO1x2_SRIO0x2_PEI1x2_PEI2x2 */ /* Enable PEI2/PEI1 */ - phyVal0 = (control & 0x6); - /* SRIO1x2_SRIO0x2 */ - phyVal0 |= (0x4 << 26); - /* SRIO0 mode */ - srio0_ctrl = ((control & 0x300) << 12); - /* SRIO1 mode */ - srio1_ctrl = ((control & 0xC00) << 14); + set_sw_port_config0(pc0_SRIO1x2_SRIO0x2); + set_sw_port_config1(pc1_PEI1x2_PEI2x2); + set_pipe_port_sel(pp_0_1_2_3); + + if (pei1_mode) + release_reset(2); + if (pei2_mode) + release_reset(3); + + /* Enable PEI1/PEI2 */ ncr_read32(NCP_REGION_ID(0x115, 0), 0, ®_val); - reg_val &= ~(0xf | (0x7 << 26) | (0x3 << 20) | (0x3 << 24)); - reg_val |= (phyVal0 | srio0_ctrl | srio1_ctrl); + reg_val |= (pei1_mode << 1) | (pei2_mode << 2); ncr_write32(NCP_REGION_ID(0x115, 0), 0, reg_val); - /* PEI1x2_PEI2x2 */ - phyVal1 = (0x3 << 22); - /* PIPE port select -- Enable PIPE0, PIPE1 - * and PIPE2 interface */ - phyVal1 |= (0x3 << 24); - /* SRIO0 speed */ - srio0_speed = (control & 0x7000); - /* SRIO1 speed */ - srio1_speed = (control & 0x38000) << 1; - ncr_read32(NCP_REGION_ID(0x115, 0), 0x4, ®_val); - reg_val &= ~((0x3 << 24) | (0x3 << 22) | (0x7 << 12) | - (0x7 << 16)); - reg_val |= (phyVal1 | srio0_speed | srio1_speed); - ncr_write32(NCP_REGION_ID(0x115, 0), 0x4, reg_val); - srio0_speed = srio0_speed >> 12; - srio1_speed = srio1_speed >> 16; - if (srio0_mode) + + set_srio_mode(SRIO0, srio0_ctrl); + set_srio_mode(SRIO1, srio1_ctrl); + set_srio_speed(SRIO0, srio0_speed); + set_srio_speed(SRIO1, srio1_speed); + if (srio0_mode) { + pr_debug("Set up sRIO0 -- %d\n", srio0_speed); setup_srio_mode(SRIO0, srio0_speed); - printk("Set up sRIO0 -- %d\n", srio0_speed); - if (srio1_mode) + if (release_srio_reset(SRIO0, srio0_speed)) + srio0_mode = 0; + } + if (srio1_mode) { + pr_debug("Set up sRIO1 -- %d\n", srio1_speed); setup_srio_mode(SRIO1, srio1_speed); - printk("Set up sRIO1 -- %d\n", srio1_speed); - for (phy = 0; phy < 4; phy++) - release_reset(phy); - - for (phy = 0; phy < 2; phy++) { - pll = PLLA; - if ((phy == 0) && - ((srio1_speed == SRIO_SPEED_3_125G) || - (srio1_speed == SRIO_SPEED_6_25G))) - pll = PLLB; - else if ((phy == 1) && - ((srio0_speed == SRIO_SPEED_3_125G) || - (srio0_speed == SRIO_SPEED_6_25G))) - pll = PLLB; - if (!check_pll_lock(pll, phy)) { - printk("%s didn't lock\n", - pll == PLLA ? "PLLA" : "PLLB"); - return 1; - } + if (release_srio_reset(SRIO1, srio1_speed)) + srio1_mode = 0; } - printk("Enabling sRIO ."); + pr_debug("Enabling sRIO ."); /* Power up TX/RX lanes */ - for (phy = 0; phy < 2; phy++) { - for (lane = 0; lane < 2; lane++) { - if (!powerup_lane(phy, lane, P1, TX)) { - printk("TX powerup failed for PHY%d LANE%d\n", phy, lane); - return 1; - } - if (!powerup_lane(phy, lane, P1, RX)) { - printk("RX powerup failed for PHY%d LANE%d\n", phy, lane); - return 1; - } - } - } + if (srio0_mode && powerup_srio_lanes(SRIO0, P1)) + srio0_mode = 0; + if (srio1_mode && powerup_srio_lanes(SRIO1, P1)) + srio1_mode = 0; - printk("."); + pr_debug("."); /* Set TX clock ready */ - set_tx_clk_ready(); + if (srio0_mode || srio1_mode) + set_tx_clk_ready(); /* Power up TX/RX lanes */ - for (phy = 0; phy < 2; phy++) { - for (lane = 0; lane < 2; lane++) { - if (!powerup_lane(phy, lane, P0, TX)) { - printk("TX powerup failed for PHY%d LANE%d\n", phy, lane); - return 1; - } - if (!powerup_lane(phy, lane, P0, RX)) { - printk("RX powerup failed for PHY%d LANE%d\n", phy, lane); - return 1; - } - } - } - printk("."); + if (srio0_mode && powerup_srio_lanes(SRIO0, P0)) + srio0_mode = 0; + if (srio1_mode && powerup_srio_lanes(SRIO1, P0)) + srio1_mode = 0; + pr_debug("."); - for (phy = 0; phy < 2; phy++) { - for (lane = 0; lane < 2; lane++) { - enable_lane(phy, lane, TX); - enable_lane(phy, lane, RX); - } - } - printk("."); + if (srio0_mode) + enable_srio_lanes(SRIO0); + if (srio1_mode) + enable_srio_lanes(SRIO1); + pr_debug("."); /* Enable SRIO0/SRIO1 */ - ncr_read32(NCP_REGION_ID(0x115, 0), 0, &phyVal0); - ncr_write32(NCP_REGION_ID(0x115, 0), 0, - phyVal0 | 0x408); - printk("Done\n"); + ncr_read32(NCP_REGION_ID(0x115, 0), 0, ®_val); + reg_val |= (srio0_mode << 3) | (srio1_mode << 10); + ncr_write32(NCP_REGION_ID(0x115, 0), 0, reg_val); + pr_debug("Done\n"); break; } - ncr_read32(NCP_REGION_ID(0x115, 0), 0, &phyVal0); - phyVal0 |= 1; - ncr_write32(NCP_REGION_ID(0x115, 0), 0, phyVal0); - msleep(100); - - switch (pci_srio_sata_mode) { - case 1: - writel(0x70120, pcie_rc + 0x710); - writel(0x104be, pcie_rc + 0x80c); - writel(0x1017201, pcie_rc + 0x8a8); - break; - default: - break; - } update_settings(); return 0; } - EXPORT_SYMBOL(pei_setup); /* @@ -1703,12 +1791,7 @@ EXPORT_SYMBOL(pei_setup); get_v2_coefficients */ -static int -get_v2_coefficients(struct device_node *pei_control) -{ - int i; - unsigned *lvalue; - char *names[] = { +static char *names[] = { "primary_input_clock", "input_ref_clock_range", "lane_0_eq_main", @@ -1719,7 +1802,13 @@ get_v2_coefficients(struct device_node *pei_control) "lane_1_eq_pre", "lane_1_eq_post", "lane_1_vboost" - }; +}; + +static int +get_v2_coefficients(struct device_node *pei_control) +{ + int i; + unsigned *lvalue; lvalue = &coefficients.primary_input_clock; @@ -1740,6 +1829,70 @@ get_v2_coefficients(struct device_node *pei_control) return 0; } +int axxia_pei_setup(unsigned int control, unsigned int force) +{ + int ret = 0; + + mutex_lock(&axxia_pei_mux); + + pr_debug("axxia_pei_setup: control=0x%08x, force = 0x%08x\n", + control, force); + axxia_pei.control = control; + axxia_pei.control_set = 1; + + if (1 == force) + axxia_pei.initialized = 0; + + if (axxia_pei.initialized) + goto cleanup; + + /* + Previously, if the boot loader set 'control', it did + not initialized the PEI. Start with that + assumption. + */ + if (0 == axxia_pei.initialized) { + if (0 != pei_setup(control)) { + pr_err("pcie-axxia: PEI setup failed!\n"); + + ret = -EINVAL; + goto cleanup; + } else { + axxia_pei.initialized = 1; + } + + msleep(100); + } + +cleanup: + mutex_unlock(&axxia_pei_mux); + return ret; +} +EXPORT_SYMBOL(axxia_pei_setup); + +unsigned int axxia_pei_get_control(void) +{ + unsigned int ret; + + mutex_lock(&axxia_pei_mux); + ret = axxia_pei.control; + mutex_unlock(&axxia_pei_mux); + return ret; +} +EXPORT_SYMBOL(axxia_pei_get_control); + +int axxia_pei_is_control_set(void) +{ + int ret; + + mutex_lock(&axxia_pei_mux); + ret = axxia_pei.control_set; + mutex_unlock(&axxia_pei_mux); + return ret; +} +EXPORT_SYMBOL(axxia_pei_is_control_set); + + /* ------------------------------------------------------------------------------ pei_init @@ -1755,9 +1908,13 @@ pei_init(void) } else if (of_find_compatible_node(NULL, NULL, "lsi,axm5616")) { is_5600 = 1; pcie_gpreg0 = ioremap(0xa003000000, 0x10000); + pcie_gpreg1 = ioremap(0xa005000000, 0x10000); + pcie_gpreg2 = ioremap(0xa007000000, 0x10000); pcie_rc = ioremap(0xa002000000, 0x1000); } else if (of_find_compatible_node(NULL, NULL, "lsi,axc6732")) { is_6700 = 1; + pcie_gpreg0 = ioremap(0xa003000000, 0x10000); + pcie_rc = ioremap(0xa002000000, 0x1000); } else { pr_err("No Valid Compatible String Found for PEI!\n"); diff --git a/drivers/pci/host/pcie-axxia.c b/drivers/pci/host/pcie-axxia.c index 247838e..7bc54e0 100644 --- a/drivers/pci/host/pcie-axxia.c +++ b/drivers/pci/host/pcie-axxia.c @@ -43,13 +43,15 @@ #define PORT_LINK_MODE_1_LANES (0x1 << 16) #define PORT_LINK_MODE_2_LANES (0x3 << 16) #define PORT_LINK_MODE_4_LANES (0x7 << 16) +#define PORT_LINK_MODE_8_LANES (0xf << 16) #define PCIE_LINK_WIDTH_SPEED_CONTROL 0x80C #define PORT_LOGIC_SPEED_CHANGE (0x1 << 17) -#define PORT_LOGIC_LINK_WIDTH_MASK (0x1ff << 8) +#define PORT_LOGIC_LINK_WIDTH_MASK (0x1f << 8) #define PORT_LOGIC_LINK_WIDTH_1_LANES (0x1 << 8) #define PORT_LOGIC_LINK_WIDTH_2_LANES (0x2 << 8) #define PORT_LOGIC_LINK_WIDTH_4_LANES (0x4 << 8) +#define PORT_LOGIC_LINK_WIDTH_8_LANES (0x8 << 8) #define PCIE_GEN3_EQ_CONTROL_OFF 0x8a8 @@ -106,9 +108,6 @@ /* SYSCON */ #define AXXIA_SYSCON_BASE 0x8002C00000 -static int control_set; -static unsigned int control_value; -static struct pcie_port *_pp; static inline uint32_t axxia_mmio_read_32(uintptr_t addr) { @@ -126,10 +125,11 @@ axxia_is_x9(void) struct axxia_pcie { struct pcie_port pp; - unsigned int control; - unsigned int initialized; + struct axxia_pcie *next; }; +static struct axxia_pcie *axxia_pcie_controllers; + static unsigned long global_io_offset; static inline void axxia_pcie_readl_rc(struct pcie_port *pp, u32 reg, u32 *val) @@ -457,16 +457,16 @@ irqreturn_t axxia_dw_handle_msi_irq(struct pcie_port *pp) for (i = 0; i < MAX_MSI_CTRLS; i++) { axxia_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_STATUS + i * 12, 4, - (u32 *)&val); + (u32 *)&val); if (val) { ret = IRQ_HANDLED; pos = 0; while ((pos = find_next_bit(&val, 32, pos)) != 32) { irq = irq_find_mapping(pp->irq_domain, - i * 32 + pos); + i * 32 + pos); axxia_pcie_wr_own_conf(pp, - PCIE_MSI_INTR0_STATUS + i * 12, - 4, 1 << pos); + PCIE_MSI_INTR0_STATUS + i * 12, + 4, 1 << pos); generic_handle_irq(irq); pos++; } @@ -509,9 +509,10 @@ int axxia_pcie_link_up(struct pcie_port *pp) axxia_cc_gpreg_readl(pp, PEI_SII_PWR_MGMT_REG, &smlh_state); smlh_state = (smlh_state & PEI_SMLH_LINK_STATE) >> 4; + if ((smlh_state != 0x11) && (smlh_state != 0x23)) { - pr_info("smlh_state = 0x%x\n", smlh_state); - pr_err("PCIe LINK IS NOT UP\n"); + dev_err(pp->dev, "PCIe LINK IS NOT UP: smlh_state = %x\n", + smlh_state); return 0; } return 1; @@ -523,8 +524,26 @@ void axxia_pcie_setup_rc(struct pcie_port *pp) u32 membase; u32 memlimit; + axxia_pcie_rd_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, &val); + val &= ~PORT_LOGIC_LINK_WIDTH_MASK; + switch (pp->lanes) { + case 2: + val |= PORT_LOGIC_LINK_WIDTH_2_LANES; + break; + case 4: + val |= PORT_LOGIC_LINK_WIDTH_4_LANES; + break; + case 8: + val |= PORT_LOGIC_LINK_WIDTH_8_LANES; + break; + case 1: + default: + val |= PORT_LOGIC_LINK_WIDTH_1_LANES; + } + axxia_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val); + /* Set the number of lanes based on the device tree. */ - axxia_pcie_readl_rc(pp, PCIE_PORT_LINK_CONTROL, &val); + axxia_pcie_rd_own_conf(pp, PCIE_PORT_LINK_CONTROL, 4, &val); val &= ~PORT_LINK_MODE_MASK; switch (pp->lanes) { @@ -537,11 +556,13 @@ void axxia_pcie_setup_rc(struct pcie_port *pp) case 4: val |= PORT_LINK_MODE_4_LANES; break; + case 8: + val |= PORT_LINK_MODE_8_LANES; + break; default: break; } - - axxia_pcie_writel_rc(pp, val, PCIE_PORT_LINK_CONTROL); + axxia_pcie_wr_own_conf(pp, PCIE_PORT_LINK_CONTROL, 4, val); /* Add Mikes tweak for GEN3_EQ_CONTROL */ axxia_pcie_writel_rc(pp, 0x1017201, PCIE_GEN3_EQ_CONTROL_OFF); @@ -569,10 +590,11 @@ void axxia_pcie_setup_rc(struct pcie_port *pp) axxia_cc_gpreg_readl(pp, PEI_GENERAL_CORE_CTL_REG, &val); msleep(100); val |= 0x1; - axxia_cc_gpreg_writel(pp, 0x1, PEI_GENERAL_CORE_CTL_REG); + axxia_cc_gpreg_writel(pp, val, PEI_GENERAL_CORE_CTL_REG); msleep(100); } + static int axxia_pcie_establish_link(struct pcie_port *pp) { /* setup root complex */ @@ -586,6 +608,20 @@ static int axxia_pcie_establish_link(struct pcie_port *pp) return 0; } +static void pci_axxia_program_rc_class(struct pcie_port *pp) +{ + u32 dbi_ro_wr_en; + /* program correct class for RC */ + axxia_pcie_readl_rc(pp, 0x8bc, &dbi_ro_wr_en); + /* DBI_RO_WR_EN */ + if (!(dbi_ro_wr_en & 0x1)) + axxia_pcie_writel_rc(pp, (dbi_ro_wr_en | 0x1), 0x8bc); + axxia_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2, PCI_CLASS_BRIDGE_PCI); + /* DBI_RO_WR_EN */ + if (!(dbi_ro_wr_en & 0x1)) + axxia_pcie_writel_rc(pp, dbi_ro_wr_en, 0x8bc); +} + static irqreturn_t axxia_pcie_irq_handler(int irq, void *arg) { struct pcie_port *pp = arg; @@ -845,6 +881,8 @@ int axxia_pcie_host_init(struct pcie_port *pp) return -EINVAL; } + /* program correct class for RC */ + pci_axxia_program_rc_class(pp); if (axxia_pcie_establish_link(pp)) dev_warn(pp->dev, "axxia_pcie_establish_link failed\n"); @@ -864,8 +902,8 @@ int axxia_pcie_host_init(struct pcie_port *pp) if (IS_ENABLED(CONFIG_PCI_MSI)) { pp->irq_domain = irq_domain_add_linear(pp->dev->of_node, - MAX_MSI_IRQS, &axxia_msi_domain_ops, - &axxia_dw_pcie_msi_chip); + MAX_MSI_IRQS, &axxia_msi_domain_ops, + &axxia_dw_pcie_msi_chip); if (!pp->irq_domain) { dev_err(pp->dev, "irq domain init failed\n"); return -ENXIO; @@ -877,9 +915,6 @@ int axxia_pcie_host_init(struct pcie_port *pp) axxia_pcie_enable_interrupts(pp); - /* program correct class for RC */ - axxia_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2, PCI_CLASS_BRIDGE_PCI); - bus = pci_create_root_bus(&pdev->dev, pp->root_bus_nr, &axxia_pciex_pci_ops, pp, &res); if (!bus) @@ -898,7 +933,6 @@ int axxia_pcie_host_init(struct pcie_port *pp) return 0; } - static int axxia_pcie_probe(struct platform_device *pdev) { struct axxia_pcie *axxia_pcie; @@ -907,15 +941,21 @@ static int axxia_pcie_probe(struct platform_device *pdev) int ret; struct device_node *pei_control; const unsigned int *control; + unsigned int control_value; const unsigned int *initialized; + unsigned int initialized_value; + u32 val; axxia_pcie = devm_kzalloc(&pdev->dev, sizeof(*axxia_pcie), GFP_KERNEL); if (!axxia_pcie) return -ENOMEM; - pp = &axxia_pcie->pp; + /* add this instance to the list */ + axxia_pcie->next = axxia_pcie_controllers; + axxia_pcie_controllers = axxia_pcie; + pp = &axxia_pcie->pp; pp->dev = &pdev->dev; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi"); @@ -934,40 +974,45 @@ static int axxia_pcie_probe(struct platform_device *pdev) return PTR_ERR(pp->cc_gpreg_base); pp->root_bus_nr = 0; - _pp = pp; pei_control = of_find_node_by_name(NULL, "pei_control"); + /* LTSSM disable */ + axxia_cc_gpreg_readl(pp, PEI_GENERAL_CORE_CTL_REG, &val); + msleep(100); + val &= ~(0x1); + axxia_cc_gpreg_writel(pp, val, PEI_GENERAL_CORE_CTL_REG); + msleep(100); + if (pei_control) { control = of_get_property(pei_control, "control", NULL); if (NULL == control) { pr_err("pcie-axxia: 'control' NOT set!!!\n"); - return -EINVAL; } - axxia_pcie->control = be32_to_cpu(*control); - control_value = axxia_pcie->control; - control_set = 1; + control_value = be32_to_cpu(*control); + + initialized = of_get_property(pei_control, "initialized", NULL); /* Previously, if the boot loader set 'control', it did - not initialized the PEI. Start with that - assumption. + not initialized the PEI. Start with that assumption. */ - - axxia_pcie->initialized = 1; - initialized = of_get_property(pei_control, "initialized", NULL); - + initialized_value = 1; if (NULL != initialized) - axxia_pcie->initialized = be32_to_cpu(*initialized); - - if (0 == axxia_pcie->initialized) - if (0 != pei_setup()) { - pr_err("pcie-axxia: PEI setup failed!\n"); + initialized_value = be32_to_cpu(*initialized); - return -EINVAL; - } + /* + * always call pei_setup regardless of the 'initialized' value. + * this is needed to save the control_value. + * the axxia_pei setup will only be done once + */ + ret = axxia_pei_setup(control_value, 0); + if (0 != ret) { + pr_err("pcie-axxia: PEI setup failed!\n"); + return ret; + } } ret = axxia_pcie_host_init(pp); @@ -1010,15 +1055,26 @@ axxia_pcie_reset(void) { struct pci_bus *pci_bus = NULL; int sub_buses; + unsigned int control; + struct pcie_port *_pp = NULL; + struct axxia_pcie *axx_pcie = axxia_pcie_controllers; + - if (0 == control_set || NULL == _pp) + if (0 == axxia_pei_is_control_set()) return -1; + + control = axxia_pei_get_control(); + /* Re-initialize the PEIs */ - pei_setup(); + axxia_pei_setup(control, 1); /* Re-configure the root complex */ - axxia_pcie_setup_rc(_pp); + while (axx_pcie) { + _pp = &axx_pcie->pp; + axxia_pcie_setup_rc(_pp); + axx_pcie = axx_pcie->next; + } /* Re-scan the Bus */ while (NULL != (pci_bus = pci_find_next_bus(pci_bus))) { @@ -1029,7 +1085,6 @@ axxia_pcie_reset(void) return 0; } - EXPORT_SYMBOL(axxia_pcie_reset); static ssize_t @@ -1045,6 +1100,7 @@ axxia_pcie_reset_trigger(struct file *file, const char __user *buf, static int pcie_init(void) { + axxia_pcie_controllers = NULL; return platform_driver_register(&axxia_pcie_driver); } subsys_initcall(pcie_init); diff --git a/include/linux/axxia-pei.h b/include/linux/axxia-pei.h index abbe9d6..9744945 100644 --- a/include/linux/axxia-pei.h +++ b/include/linux/axxia-pei.h @@ -18,7 +18,11 @@ #ifndef __AXXIA_PEI_H #define __AXXIA_PEI_H -int pei_setup(void); +int axxia_pei_setup(unsigned int, unsigned int); int axxia_pcie_reset(void); +unsigned int axxia_pei_get_control(void); +int axxia_pei_is_control_set(void); + + #endif /* __AXXIA_PEI_H */ -- 2.7.4 -- _______________________________________________ linux-yocto mailing list linux-yocto@yoctoproject.org https://lists.yoctoproject.org/listinfo/linux-yocto