[linux-yocto] [PATCH 03/17] axxia: generalize driver support for multi-controller PCI/SRIO/SATA
Daniel Dragomir
daniel.dragomir at windriver.com
Tue May 16 11:38:55 PDT 2017
From: Gary McGee <gary.mcgee at intel.com>
Signed-off-by: Gary McGee <gary.mcgee at 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
More information about the linux-yocto
mailing list