summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabriele Paoloni <gabriele.paoloni@huawei.com>2015-09-29 10:38:37 +0800
committerSherlock Wang <sherlock.wang@139.com>2015-11-06 15:51:17 +0800
commit14694f79fe049c580081aaa0dafbddd628fc8903 (patch)
tree70b799fe032c3781643474afd383ef4ba9b1df4b
parent8f91a42914035c290100e38fb633d218af4cf817 (diff)
PCI: hisi:add link function
1. add pcie link function 2. enable DFE when pcie link to GEN3 3. Fix gen3 equalization configure error Signed-off-by: liudongdong <liudongdong3@huawei.com> Signed-off-by: zhangjukuo <zhangjukuo@huawei.com> Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com> Signed-off-by: Zhenfa Qiu <qiuzhenfa@hisilicon.com> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
-rw-r--r--drivers/pci/host/pcie-hisi.c523
1 files changed, 507 insertions, 16 deletions
diff --git a/drivers/pci/host/pcie-hisi.c b/drivers/pci/host/pcie-hisi.c
index 5f1949682606..f2ad00bcf012 100644
--- a/drivers/pci/host/pcie-hisi.c
+++ b/drivers/pci/host/pcie-hisi.c
@@ -10,6 +10,7 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
+#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/irqdomain.h>
#include <linux/module.h>
@@ -43,12 +44,74 @@
#define PCIE_DBI_CS2_ENABLE 0x1
#define PCIE_DBI_CS2_DISABLE 0x0
+#define PCIE_CTRL_7_REG 0x114
+#define PCIE_LTSSM_ENABLE_SHIFT BIT(11)
+#define PCIE_SUBCTRL_RESET_REQ_REG 0xA00
+#define PCIE0_2_SUBCTRL_RESET_REQ_REG(port_id) \
+ (PCIE_SUBCTRL_RESET_REQ_REG + (port_id << 3))
+#define PCIE3_SUBCTRL_RESET_REQ_REG 0xA68
+
+#define PCIE_SUBCTRL_DRESET_REQ_REG 0xA04
+#define PCIE0_2_SUBCTRL_DRESET_REQ_REG(port_id) \
+ (PCIE_SUBCTRL_DRESET_REQ_REG + (port_id << 3))
+#define PCIE3_SUBCTRL_DRESET_REQ_REG 0xA6C
+
+#define PCIE_SUBCTRL_RESET_ST_REG 0x5A00
+#define PCIE0_2_SUBCTRL_RESET_ST_REG(port_id) \
+ (PCIE_SUBCTRL_RESET_ST_REG + (port_id << 2))
+#define PCIE3_SUBCTRL_RESET_ST_REG 0x5A34
+
+#define PCIE_SUBCTRL_SC_PCIE0_CLK_DIS_REG 0x304
+#define PCIE_SUBCTRL_SC_PCIE0_2_CLK_DIS_REG(port_id) \
+ (PCIE_SUBCTRL_SC_PCIE0_CLK_DIS_REG + (port_id << 3))
+#define PCIE_SUBCTRL_SC_PCIE3_CLK_DIS_REG 0x324
+
+#define PCIE_SUBCTRL_SC_PCIE0_CLK_ST_REG 0x5300
+#define PCIE_SUBCTRL_SC_PCIE0_2_CLK_ST_REG(port_id) \
+ (PCIE_SUBCTRL_SC_PCIE0_CLK_ST_REG + (port_id << 2))
+#define PCIE_SUBCTRL_SC_PCIE3_CLK_ST_REG 0x5310
+
+#define PCIE_SUBCTRL_SC_PCIE0_CLK_EN_REG 0x300
+#define PCIE_SUBCTRL_SC_PCIE0_2_CLK_EN_REG(port_id) \
+ (PCIE_SUBCTRL_SC_PCIE0_CLK_EN_REG + (port_id << 3))
+#define PCIE_SUBCTRL_SC_PCIE3_CLK_EN_REG 0x320
+
+#define PCIE_ASSERT_RESET_ON 1
+#define PCIE_DEASSERT_RESET_ON 0
+#define PCIE_CLOCK_ON 1
+#define PCIE_CLOCK_OFF 0
+
+#define PCIE_PCS_LOCAL_RESET_REQ 0xAC0
+#define PCIE_PCS_LOCAL_DRESET_REQ 0xAC4
+#define PCIE_PCS_RESET_REQ_REG 0xA60
+#define PCIE_PCS_RESET_REG_ST 0x5A30
+#define PCIE_PCS_LOCAL_DRESET_ST 0x5A60
+#define PCIE_PCS_LOCAL_RESET_ST 0x5A60
+#define PCIE_PCS_DRESET_REQ_REG 0xA64
+#define PCIE_M_PCS_IN15_CFG 0x74
+#define PCIE_M_PCS_IN13_CFG 0x34
+#define PCIE_PCS_RXDETECTED 0xE4
+#define PCIE_PCS_SERDES_STATUS 0x8108
+#define HIP05_PCIE_CORE_IS_RESET 0x1
+#define PCIE_CORE_MODE_REG 0xF8
+#define PCIE_LINK_WIDTH_SPEED_CONTROL 0x80C
+#define PORT_LOGIC_SPEED_CHANGE (0x1 << 17)
+
+#define DS_API(lane) ((0x1FF6c + 8 * (15 - lane)) * 2)
+#define PCIE_DFE_ENABLE_VAL 0x3851
+enum pcie_mac_phy_rate_e {
+ PCIE_GEN1 = 0, /* PCIE 1.0 */
+ PCIE_GEN2 = 1, /* PCIE 2.0 */
+ PCIE_GEN3 = 2 /* PCIE 3.0 */
+};
+
#define to_hisi_pcie(x) container_of(x, struct hisi_pcie, pp)
struct hisi_pcie {
void __iomem *subctrl_base;
void __iomem *reg_base;
- struct msi_controller *msi;
+ void __iomem *phy_base;
+ void __iomem *serdes_base;
u32 port_id;
struct pcie_port pp;
};
@@ -74,6 +137,22 @@ static inline u32 hisi_pcie_apb_readl(struct hisi_pcie *pcie, u32 reg)
{
return readl(pcie->reg_base + reg);
}
+static inline void hisi_pcie_pcs_writel(struct hisi_pcie *pcie,
+ u32 val, u32 reg)
+{
+ writel(val, pcie->phy_base + reg);
+}
+
+static inline u32 hisi_pcie_pcs_readl(struct hisi_pcie *pcie, u32 reg)
+{
+ return readl(pcie->phy_base + reg);
+}
+
+static inline void hisi_pcie_serdes_writel(struct hisi_pcie *pcie,
+ u32 val, u32 reg)
+{
+ writel(val, pcie->serdes_base + reg);
+}
/*
* Change mode to indicate the same reg_base to base of PCIe host configure
@@ -106,9 +185,7 @@ static void hisi_pcie_config_context(struct hisi_pcie *pcie)
int i;
u32 val;
- /*
- * enable to clean vmid and asid tables though apb bus
- * */
+ /* enable to clean vmid and asid tables though apb bus */
hisi_pcie_change_apb_mode(pcie, PCIE_SLV_SYSCTRL_MODE);
val = hisi_pcie_apb_readl(pcie, PCIE_SYS_CTRL20_REG);
@@ -166,6 +243,399 @@ static int hisi_pcie_link_up(struct pcie_port *pp)
return ((val & PCIE_LTSSM_STATE_MASK) == PCIE_LTSSM_LINKUP_STATE);
}
+static void hisi_pcie_enable_ltssm(struct hisi_pcie *pcie, bool on)
+{
+ u32 val;
+
+ hisi_pcie_change_apb_mode(pcie, PCIE_SLV_SYSCTRL_MODE);
+
+ val = hisi_pcie_apb_readl(pcie, PCIE_CTRL_7_REG);
+ if (on)
+ val |= PCIE_LTSSM_ENABLE_SHIFT;
+ else
+ val &= ~(PCIE_LTSSM_ENABLE_SHIFT);
+ hisi_pcie_apb_writel(pcie, val, PCIE_CTRL_7_REG);
+
+ hisi_pcie_change_apb_mode(pcie, PCIE_SLV_DBI_MODE);
+}
+
+static void hisi_pcie_gen3_dfe_enable(struct hisi_pcie *pcie)
+{
+ u32 val;
+ u32 lane;
+ u32 current_speed;
+ u32 port_id = pcie->port_id;
+
+ if (port_id == 3)
+ return;
+
+ val = hisi_pcie_subctrl_readl(pcie,
+ PCIE_SUBCTRL_SYS_STATE4_REG +
+ 0x100 * port_id);
+ current_speed = (val >> 6) & 0x3;
+
+ if (current_speed != PCIE_GEN3)
+ return;
+
+ for (lane = 0; lane < 8; lane++)
+ hisi_pcie_serdes_writel(pcie,
+ PCIE_DFE_ENABLE_VAL, DS_API(lane) + 4);
+
+ dev_info(pcie->pp.dev, "enable DFE success!\n");
+}
+
+
+static void hisi_pcie_core_reset_ctrl(struct hisi_pcie *pcie,
+ bool reset_on)
+{
+ u32 reg_reset_ctrl;
+ u32 reg_dereset_ctrl;
+ u32 reg_reset_status;
+ u32 reset_status;
+ u32 reset_status_checked;
+ unsigned long timeout;
+ u32 port_id = pcie->port_id;
+
+ if (port_id == 3) {
+ reg_reset_ctrl = PCIE3_SUBCTRL_RESET_REQ_REG;
+ reg_dereset_ctrl = PCIE3_SUBCTRL_DRESET_REQ_REG;
+ reg_reset_status = PCIE3_SUBCTRL_RESET_ST_REG;
+ } else {
+ reg_reset_ctrl = PCIE0_2_SUBCTRL_RESET_REQ_REG(port_id);
+ reg_dereset_ctrl = PCIE0_2_SUBCTRL_DRESET_REQ_REG(port_id);
+ reg_reset_status = PCIE0_2_SUBCTRL_RESET_ST_REG(port_id);
+ }
+
+ if (reset_on) {
+ /* if core is link up, stop the ltssm state machine first */
+ if (hisi_pcie_link_up(&pcie->pp))
+ hisi_pcie_enable_ltssm(pcie, 0);
+
+ hisi_pcie_subctrl_writel(pcie, 0x1, reg_reset_ctrl);
+ } else
+ hisi_pcie_subctrl_writel(pcie, 0x1, reg_dereset_ctrl);
+
+ timeout = jiffies + HZ * 1;
+ do {
+ reset_status = hisi_pcie_subctrl_readl(pcie, reg_reset_status);
+ if (reset_on)
+ reset_status_checked = ((reset_status & 0x01) !=
+ HIP05_PCIE_CORE_IS_RESET);
+ else
+ reset_status_checked = ((reset_status & 0x01) != 0);
+
+ } while ((reset_status_checked) && (time_before(jiffies, timeout)));
+
+ /* get a timeout error */
+ if (reset_status_checked)
+ dev_err(pcie->pp.dev, "pcie core reset or dereset failed!\n");
+}
+
+static void hisi_pcie_clock_ctrl(struct hisi_pcie *pcie, bool clock_on)
+{
+ u32 reg_clock_disable;
+ u32 reg_clock_enable;
+ u32 reg_clock_status;
+ u32 clock_status;
+ u32 clock_status_checked;
+ unsigned long timeout;
+ u32 port_id = pcie->port_id;
+
+ if (port_id == 3) {
+ reg_clock_disable = PCIE_SUBCTRL_SC_PCIE3_CLK_DIS_REG;
+ reg_clock_enable = PCIE_SUBCTRL_SC_PCIE3_CLK_EN_REG;
+ reg_clock_status = PCIE_SUBCTRL_SC_PCIE3_CLK_ST_REG;
+ } else {
+ reg_clock_disable =
+ PCIE_SUBCTRL_SC_PCIE0_2_CLK_DIS_REG(port_id);
+ reg_clock_enable = PCIE_SUBCTRL_SC_PCIE0_2_CLK_EN_REG(port_id);
+ reg_clock_status = PCIE_SUBCTRL_SC_PCIE0_2_CLK_ST_REG(port_id);
+ }
+
+ if (clock_on)
+ hisi_pcie_subctrl_writel(pcie, 0x3, reg_clock_enable);
+ else
+ hisi_pcie_subctrl_writel(pcie, 0x3, reg_clock_disable);
+
+ timeout = jiffies + HZ * 1;
+ do {
+ clock_status = hisi_pcie_subctrl_readl(pcie, reg_clock_status);
+ if (clock_on)
+ clock_status_checked = ((clock_status & 0x03) != 0x3);
+ else
+ clock_status_checked = ((clock_status & 0x03) != 0);
+
+ } while ((clock_status_checked) && (time_before(jiffies, timeout)));
+
+ /* get a timeout error */
+ if (clock_status_checked)
+ dev_err(pcie->pp.dev, "clock operation failed!\n");
+}
+
+static void hisi_pcie_assert_core_reset(struct hisi_pcie *pcie)
+{
+ hisi_pcie_core_reset_ctrl(pcie, PCIE_ASSERT_RESET_ON);
+ hisi_pcie_clock_ctrl(pcie, PCIE_CLOCK_OFF);
+}
+
+static void hisi_pcie_deassert_core_reset(struct hisi_pcie *pcie)
+{
+ hisi_pcie_core_reset_ctrl(pcie, PCIE_DEASSERT_RESET_ON);
+}
+
+static void hisi_pcie_deassert_pcs_reset(struct hisi_pcie *pcie)
+{
+ u32 val;
+ u32 hilink_reset_status;
+ u32 pcs_local_status;
+ u32 hilink_status_checked;
+ u32 pcs_local_status_checked;
+ unsigned long timeout;
+ u32 port_id = pcie->port_id;
+
+ val = 1 << port_id;
+ hisi_pcie_subctrl_writel(pcie, val, PCIE_PCS_LOCAL_DRESET_REQ);
+
+ val = 0xff << (port_id << 3);
+ hisi_pcie_subctrl_writel(pcie, val, PCIE_PCS_DRESET_REQ_REG);
+
+ timeout = jiffies + HZ * 1;
+ /* read reset status, make sure pcs is deassert */
+ do {
+ pcs_local_status = hisi_pcie_subctrl_readl(pcie,
+ PCIE_PCS_LOCAL_RESET_ST);
+ pcs_local_status_checked = (pcs_local_status & (1 << port_id));
+ } while ((pcs_local_status_checked) && (time_before(jiffies, timeout)));
+
+ /* get a timeout error */
+ if (pcs_local_status_checked)
+ dev_err(pcie->pp.dev, "pcs deassert reset failed!\n");
+
+ timeout = jiffies + HZ * 1;
+
+ do {
+ hilink_reset_status = hisi_pcie_subctrl_readl(pcie,
+ PCIE_PCS_RESET_REG_ST);
+ hilink_status_checked = (hilink_reset_status &
+ (0xff << (port_id << 3)));
+ } while ((hilink_status_checked) && (time_before(jiffies, timeout)));
+
+ if (hilink_status_checked)
+ dev_err(pcie->pp.dev, "pcs deassert reset failed!\n");
+}
+
+static void hisi_pcie_assert_pcs_reset(struct hisi_pcie *pcie)
+{
+ u32 reg;
+ u32 hilink_reset_status;
+ u32 pcs_local_reset_status;
+ u32 hilink_status_checked;
+ u32 pcs_local_status_checked;
+ unsigned long timeout;
+ u32 port_id = pcie->port_id;
+
+ reg = 1 << port_id;
+ hisi_pcie_subctrl_writel(pcie, reg, PCIE_PCS_LOCAL_RESET_REQ);
+
+ reg = 0xff << (port_id << 3);
+ hisi_pcie_subctrl_writel(pcie, reg, PCIE_PCS_RESET_REQ_REG);
+
+ timeout = jiffies + HZ * 1;
+ /* read reset status, make sure pcs is reset */
+ do {
+ pcs_local_reset_status = hisi_pcie_subctrl_readl(pcie,
+ PCIE_PCS_LOCAL_RESET_ST);
+ pcs_local_status_checked =
+ ((pcs_local_reset_status & (1 << port_id)) !=
+ (1 << port_id));
+
+ } while ((pcs_local_status_checked) && (time_before(jiffies, timeout)));
+
+ if (pcs_local_status_checked)
+ dev_err(pcie->pp.dev, "pcs local reset status read failed\n");
+
+ timeout = jiffies + HZ * 1;
+ do {
+ hilink_reset_status = hisi_pcie_subctrl_readl(pcie,
+ PCIE_PCS_RESET_REG_ST);
+ hilink_status_checked =
+ ((hilink_reset_status & (0xff << (port_id << 3))) !=
+ (0xff << (port_id << 3)));
+ } while ((hilink_status_checked) && (time_before(jiffies, timeout)));
+
+ if (hilink_status_checked)
+ dev_err(pcie->pp.dev, "error:pcs assert reset failed\n");
+}
+
+static void hisi_pcie_init_pcs(struct hisi_pcie *pcie)
+{
+ u32 i;
+ u32 lane_num = pcie->pp.lanes;
+
+ if (pcie->port_id <= 2) {
+ hisi_pcie_serdes_writel(pcie, 0x212, 0xc088);
+
+ hisi_pcie_pcs_writel(pcie, 0x2026044, 0x8020);
+ hisi_pcie_pcs_writel(pcie, 0x2126044, 0x8060);
+ hisi_pcie_pcs_writel(pcie, 0x2126044, 0x80c4);
+ hisi_pcie_pcs_writel(pcie, 0x2026044, 0x80e4);
+ hisi_pcie_pcs_writel(pcie, 0x4018, 0x80a0);
+ hisi_pcie_pcs_writel(pcie, 0x804018, 0x80a4);
+ hisi_pcie_pcs_writel(pcie, 0x11201100, 0x80c0);
+ hisi_pcie_pcs_writel(pcie, 0x3, 0x15c);
+ hisi_pcie_pcs_writel(pcie, 0x0, 0x158);
+ } else {
+ for (i = 0; i < lane_num; i++)
+ hisi_pcie_pcs_writel(pcie, 0x46e000,
+ PCIE_M_PCS_IN15_CFG + (i << 2));
+ for (i = 0; i < lane_num; i++)
+ hisi_pcie_pcs_writel(pcie, 0x1001,
+ PCIE_M_PCS_IN13_CFG + (i << 2));
+
+ hisi_pcie_pcs_writel(pcie, 0xffff, PCIE_PCS_RXDETECTED);
+ }
+}
+
+/*
+ * In p660, pcie 3 do not support the 8Gbps speed we have no need to
+ * use the equalization, but it has not affected to the funcion.
+ */
+void pcie_equalization(struct hisi_pcie *pcie)
+{
+
+ u32 val;
+
+ hisi_pcie_apb_writel(pcie, 0x1400, 0x890);
+ hisi_pcie_apb_writel(pcie, 0xfd7, 0x894);
+
+ hisi_pcie_apb_writel(pcie, 0x0, 0x89c);
+ hisi_pcie_apb_writel(pcie, 0xfc00, 0x898);
+ hisi_pcie_apb_writel(pcie, 0x1, 0x89c);
+ hisi_pcie_apb_writel(pcie, 0xbd00, 0x898);
+ hisi_pcie_apb_writel(pcie, 0x2, 0x89c);
+ hisi_pcie_apb_writel(pcie, 0xccc0, 0x898);
+ hisi_pcie_apb_writel(pcie, 0x3, 0x89c);
+ hisi_pcie_apb_writel(pcie, 0x8dc0, 0x898);
+ hisi_pcie_apb_writel(pcie, 0x4, 0x89c);
+ hisi_pcie_apb_writel(pcie, 0xfc0, 0x898);
+ hisi_pcie_apb_writel(pcie, 0x5, 0x89c);
+ hisi_pcie_apb_writel(pcie, 0xe46, 0x898);
+ hisi_pcie_apb_writel(pcie, 0x6, 0x89c);
+ hisi_pcie_apb_writel(pcie, 0xdc8, 0x898);
+ hisi_pcie_apb_writel(pcie, 0x7, 0x89c);
+ hisi_pcie_apb_writel(pcie, 0xcb46, 0x898);
+ hisi_pcie_apb_writel(pcie, 0x8, 0x89c);
+ hisi_pcie_apb_writel(pcie, 0x8c07, 0x898);
+ hisi_pcie_apb_writel(pcie, 0x9, 0x89c);
+ hisi_pcie_apb_writel(pcie, 0xd0b, 0x898);
+ hisi_pcie_apb_writel(pcie, 0x103ff21, 0x8a8);
+
+ val = hisi_pcie_apb_readl(pcie, 0x80);
+ val |= 0x80;
+ hisi_pcie_apb_writel(pcie, val, 0x80);
+
+ hisi_pcie_apb_writel(pcie, 0x44444444, 0x184);
+ hisi_pcie_apb_writel(pcie, 0x44444444, 0x188);
+ hisi_pcie_apb_writel(pcie, 0x44444444, 0x18c);
+ hisi_pcie_apb_writel(pcie, 0x44444444, 0x190);
+}
+
+static void hisi_pcie_mode_set(struct hisi_pcie *pcie)
+{
+ hisi_pcie_change_apb_mode(pcie, PCIE_SLV_SYSCTRL_MODE);
+ hisi_pcie_apb_writel(pcie, 0x4 << 28, PCIE_CORE_MODE_REG);
+ hisi_pcie_change_apb_mode(pcie, PCIE_SLV_DBI_MODE);
+}
+
+static void hisi_pcie_spd_set(struct hisi_pcie *pcie, u32 spd)
+{
+ u32 val;
+
+ val = hisi_pcie_apb_readl(pcie, 0xa0);
+ val &= ~(0xf);
+ val |= spd;
+ hisi_pcie_apb_writel(pcie, val, 0xa0);
+}
+
+static void hisi_pcie_spd_control(struct hisi_pcie *pcie)
+{
+ u32 val;
+
+ /* set link width speed control register */
+ val = hisi_pcie_apb_readl(pcie, PCIE_LINK_WIDTH_SPEED_CONTROL);
+ /*
+ * set the Directed Speed Change field of the Link Width and Speed
+ * Change Control register
+ */
+ val |= PORT_LOGIC_SPEED_CHANGE;
+ hisi_pcie_apb_writel(pcie, val, PCIE_LINK_WIDTH_SPEED_CONTROL);
+}
+
+void hisi_pcie_establish_link(struct hisi_pcie *pcie)
+{
+ u32 val;
+ int count = 0;
+
+ if (dw_pcie_link_up(&pcie->pp)) {
+ dev_info(pcie->pp.dev, "already Link up\n");
+ return;
+ }
+ /* assert reset signals */
+ hisi_pcie_assert_core_reset(pcie);
+ hisi_pcie_assert_pcs_reset(pcie);
+
+ /* de-assert phy reset */
+ hisi_pcie_deassert_pcs_reset(pcie);
+
+ /* de-assert core reset */
+ hisi_pcie_deassert_core_reset(pcie);
+
+ /* enable clock */
+ hisi_pcie_clock_ctrl(pcie, PCIE_CLOCK_ON);
+
+ /* initialize phy */
+ hisi_pcie_init_pcs(pcie);
+
+ /* set controller to RC mode */
+ hisi_pcie_mode_set(pcie);
+
+ /* set target link speed */
+ hisi_pcie_spd_set(pcie, 3);
+
+ /* set link speed control*/
+ hisi_pcie_spd_control(pcie);
+
+ /* setup root complex */
+ dw_pcie_setup_rc(&pcie->pp);
+
+ pcie_equalization(pcie);
+
+ /* assert LTSSM enable */
+ hisi_pcie_enable_ltssm(pcie, 1);
+
+ /* check if the link is up or not */
+ while (!dw_pcie_link_up(&pcie->pp)) {
+ mdelay(100);
+ count++;
+ if (count == 10) {
+ val = hisi_pcie_pcs_readl(pcie, PCIE_PCS_SERDES_STATUS);
+ dev_info(pcie->pp.dev,
+ "PCIe Link Failed! PLL Locked: 0x%x\n", val);
+ return;
+ }
+ }
+
+ dev_info(pcie->pp.dev, "Link up\n");
+
+ /* dfe enable is just for 660 */
+ hisi_pcie_gen3_dfe_enable(pcie);
+ /*
+ * add a 1s delay between linkup and enumeration, make sure
+ * the EP device's configuration registers are prepared well
+ */
+ mdelay(1000);
+}
+
static void hisi_pcie_set_db2_enable(struct hisi_pcie *pcie, u32 enable)
{
u32 dbi_ctrl;
@@ -189,8 +659,8 @@ static void hisi_pcie_disabled_bar0(struct hisi_pcie *pcie)
hisi_pcie_set_db2_enable(pcie, PCIE_DBI_CS2_DISABLE);
}
-static
-int hisi_pcie_msi_host_init(struct pcie_port *pp, struct msi_controller *chip)
+static int hisi_pcie_msi_host_init(struct pcie_port *pp,
+ struct msi_controller *chip)
{
struct device_node *msi_node;
struct irq_domain *irq_domain;
@@ -213,6 +683,21 @@ int hisi_pcie_msi_host_init(struct pcie_port *pp, struct msi_controller *chip)
return 0;
}
+static void hisi_pcie_host_init(struct pcie_port *pp)
+{
+ struct hisi_pcie *pcie = to_hisi_pcie(pp);
+
+ hisi_pcie_establish_link(pcie);
+ hisi_pcie_config_context(pcie);
+ /*
+ * The default size of BAR0 in p660 host bridge is 0x10000000,
+ * which will bring problem when most resource has been allocated
+ * to BAR0 in host bridge.However, we need not use BAR0 in host bridge
+ * in RC mode. Here we just disable it
+ */
+ hisi_pcie_disabled_bar0(pcie);
+}
+
static int hisi_pcie_cfg_write(struct pcie_port *pp, int where, int size,
u32 val)
{
@@ -242,6 +727,7 @@ static int hisi_pcie_cfg_write(struct pcie_port *pp, int where, int size,
static struct pcie_host_ops hisi_pcie_host_ops = {
.link_up = hisi_pcie_link_up,
.msi_host_init = hisi_pcie_msi_host_init,
+ .host_init = hisi_pcie_host_init,
.wr_own_conf = hisi_pcie_cfg_write,
};
@@ -262,18 +748,8 @@ static int hisi_add_pcie_port(struct pcie_port *pp,
}
hisi_pcie->port_id = port_id;
- /*
- * The default size of BAR0 in p660 host bridge is 0x10000000,
- * which will bring problem when most resource has been allocated
- * to BAR0 in host bridge.However, we need not use BAR0 in host bridge
- * in RC mode. Here we just disable it
- */
- hisi_pcie_disabled_bar0(hisi_pcie);
-
pp->ops = &hisi_pcie_host_ops;
- hisi_pcie_config_context(hisi_pcie);
-
ret = dw_pcie_host_init(pp);
if (ret) {
dev_err(&pdev->dev, "failed to initialize host\n");
@@ -289,6 +765,8 @@ static int hisi_pcie_probe(struct platform_device *pdev)
struct pcie_port *pp;
struct resource *reg;
struct resource *subctrl;
+ struct resource *phy;
+ struct resource *serdes;
int ret;
hisi_pcie = devm_kzalloc(&pdev->dev, sizeof(*hisi_pcie), GFP_KERNEL);
@@ -315,6 +793,19 @@ static int hisi_pcie_probe(struct platform_device *pdev)
hisi_pcie->pp.dbi_base = hisi_pcie->reg_base;
+ phy = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcs");
+ hisi_pcie->phy_base = devm_ioremap_resource(&pdev->dev, phy);
+ if (IS_ERR(hisi_pcie->phy_base)) {
+ dev_err(pp->dev, "cannot get phy base\n");
+ return PTR_ERR(hisi_pcie->phy_base);
+ }
+
+ serdes = platform_get_resource_byname(pdev, IORESOURCE_MEM, "serdes");
+ hisi_pcie->serdes_base = devm_ioremap_resource(&pdev->dev, serdes);
+ if (IS_ERR(hisi_pcie->serdes_base)) {
+ dev_err(pp->dev, "cannot get serdes base\n");
+ return PTR_ERR(hisi_pcie->serdes_base);
+ }
ret = hisi_add_pcie_port(pp, pdev);
if (ret)
return ret;