Merge branch 'pci/host-rockchip' into next
* pci/host-rockchip: PCI: rockchip: Move the deassert of pm/aclk/pclk after phy_init() PCI: rockchip: Split out rockchip_cfg_atu() PCI: rockchip: Clean up bit definitions for PCIE_RC_CONFIG_LCS PCI: rockchip: Correct the use of FTS mask PCI: rockchip: Remove the pointer to L1 substate cap PCI: rockchip: Specify the link capability PCI: rockchip: Fix negotiated lanes calculation PCI: rockchip: Add Kconfig COMPILE_TEST PCI: rockchip: Mark RC as common clock architecture PCI: rockchip: Provide captured slot power limit and scale PCI: rockchip: Add three new resets as required properties PCI: Don't attempt to claim shadow copies of ROM PCI: designware: Check for iATU unroll support after initializing host PCI: qcom: Fix pp->dev usage before assignment PCI: designware-plat: Update author email address PCI: layerscape: Fix drvdata usage before assignment PCI: designware-plat: Change maintainer to Jose Abreu
This commit is contained in:
commit
44b83b32e7
|
@ -26,13 +26,16 @@ Required properties:
|
||||||
- "sys"
|
- "sys"
|
||||||
- "legacy"
|
- "legacy"
|
||||||
- "client"
|
- "client"
|
||||||
- resets: Must contain five entries for each entry in reset-names.
|
- resets: Must contain seven entries for each entry in reset-names.
|
||||||
See ../reset/reset.txt for details.
|
See ../reset/reset.txt for details.
|
||||||
- reset-names: Must include the following names
|
- reset-names: Must include the following names
|
||||||
- "core"
|
- "core"
|
||||||
- "mgmt"
|
- "mgmt"
|
||||||
- "mgmt-sticky"
|
- "mgmt-sticky"
|
||||||
- "pipe"
|
- "pipe"
|
||||||
|
- "pm"
|
||||||
|
- "aclk"
|
||||||
|
- "pclk"
|
||||||
- pinctrl-names : The pin control state names
|
- pinctrl-names : The pin control state names
|
||||||
- pinctrl-0: The "default" pinctrl state
|
- pinctrl-0: The "default" pinctrl state
|
||||||
- #interrupt-cells: specifies the number of cells needed to encode an
|
- #interrupt-cells: specifies the number of cells needed to encode an
|
||||||
|
@ -86,8 +89,10 @@ pcie0: pcie@f8000000 {
|
||||||
reg = <0x0 0xf8000000 0x0 0x2000000>, <0x0 0xfd000000 0x0 0x1000000>;
|
reg = <0x0 0xf8000000 0x0 0x2000000>, <0x0 0xfd000000 0x0 0x1000000>;
|
||||||
reg-names = "axi-base", "apb-base";
|
reg-names = "axi-base", "apb-base";
|
||||||
resets = <&cru SRST_PCIE_CORE>, <&cru SRST_PCIE_MGMT>,
|
resets = <&cru SRST_PCIE_CORE>, <&cru SRST_PCIE_MGMT>,
|
||||||
<&cru SRST_PCIE_MGMT_STICKY>, <&cru SRST_PCIE_PIPE>;
|
<&cru SRST_PCIE_MGMT_STICKY>, <&cru SRST_PCIE_PIPE> ,
|
||||||
reset-names = "core", "mgmt", "mgmt-sticky", "pipe";
|
<&cru SRST_PCIE_PM>, <&cru SRST_P_PCIE>, <&cru SRST_A_PCIE>;
|
||||||
|
reset-names = "core", "mgmt", "mgmt-sticky", "pipe",
|
||||||
|
"pm", "pclk", "aclk";
|
||||||
phys = <&pcie_phy>;
|
phys = <&pcie_phy>;
|
||||||
phy-names = "pcie-phy";
|
phy-names = "pcie-phy";
|
||||||
pinctrl-names = "default";
|
pinctrl-names = "default";
|
||||||
|
|
|
@ -9300,7 +9300,7 @@ S: Maintained
|
||||||
F: drivers/pci/host/*designware*
|
F: drivers/pci/host/*designware*
|
||||||
|
|
||||||
PCI DRIVER FOR SYNOPSYS PROTOTYPING DEVICE
|
PCI DRIVER FOR SYNOPSYS PROTOTYPING DEVICE
|
||||||
M: Joao Pinto <jpinto@synopsys.com>
|
M: Jose Abreu <Jose.Abreu@synopsys.com>
|
||||||
L: linux-pci@vger.kernel.org
|
L: linux-pci@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: Documentation/devicetree/bindings/pci/designware-pcie.txt
|
F: Documentation/devicetree/bindings/pci/designware-pcie.txt
|
||||||
|
|
|
@ -278,7 +278,7 @@ config PCIE_ARTPEC6
|
||||||
|
|
||||||
config PCIE_ROCKCHIP
|
config PCIE_ROCKCHIP
|
||||||
bool "Rockchip PCIe controller"
|
bool "Rockchip PCIe controller"
|
||||||
depends on ARCH_ROCKCHIP
|
depends on ARCH_ROCKCHIP || COMPILE_TEST
|
||||||
depends on OF
|
depends on OF
|
||||||
depends on PCI_MSI_IRQ_DOMAIN
|
depends on PCI_MSI_IRQ_DOMAIN
|
||||||
select MFD_SYSCON
|
select MFD_SYSCON
|
||||||
|
|
|
@ -255,6 +255,7 @@ static int __init ls_pcie_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
pp = &pcie->pp;
|
pp = &pcie->pp;
|
||||||
pp->dev = dev;
|
pp->dev = dev;
|
||||||
|
pcie->drvdata = match->data;
|
||||||
pp->ops = pcie->drvdata->ops;
|
pp->ops = pcie->drvdata->ops;
|
||||||
|
|
||||||
dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
|
dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
|
||||||
|
@ -262,7 +263,6 @@ static int __init ls_pcie_probe(struct platform_device *pdev)
|
||||||
if (IS_ERR(pcie->pp.dbi_base))
|
if (IS_ERR(pcie->pp.dbi_base))
|
||||||
return PTR_ERR(pcie->pp.dbi_base);
|
return PTR_ERR(pcie->pp.dbi_base);
|
||||||
|
|
||||||
pcie->drvdata = match->data;
|
|
||||||
pcie->lut = pcie->pp.dbi_base + pcie->drvdata->lut_offset;
|
pcie->lut = pcie->pp.dbi_base + pcie->drvdata->lut_offset;
|
||||||
|
|
||||||
if (!ls_pcie_is_bridge(pcie))
|
if (!ls_pcie_is_bridge(pcie))
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
*
|
*
|
||||||
* Copyright (C) 2015-2016 Synopsys, Inc. (www.synopsys.com)
|
* Copyright (C) 2015-2016 Synopsys, Inc. (www.synopsys.com)
|
||||||
*
|
*
|
||||||
* Authors: Joao Pinto <jpinto@synopsys.com>
|
* Authors: Joao Pinto <jpmpinto@gmail.com>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License version 2 as
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
|
|
@ -637,8 +637,6 @@ int dw_pcie_host_init(struct pcie_port *pp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pp->iatu_unroll_enabled = dw_pcie_iatu_unroll_enabled(pp);
|
|
||||||
|
|
||||||
if (pp->ops->host_init)
|
if (pp->ops->host_init)
|
||||||
pp->ops->host_init(pp);
|
pp->ops->host_init(pp);
|
||||||
|
|
||||||
|
@ -809,6 +807,11 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
|
||||||
{
|
{
|
||||||
u32 val;
|
u32 val;
|
||||||
|
|
||||||
|
/* get iATU unroll support */
|
||||||
|
pp->iatu_unroll_enabled = dw_pcie_iatu_unroll_enabled(pp);
|
||||||
|
dev_dbg(pp->dev, "iATU unroll: %s\n",
|
||||||
|
pp->iatu_unroll_enabled ? "enabled" : "disabled");
|
||||||
|
|
||||||
/* set the number of lanes */
|
/* set the number of lanes */
|
||||||
val = dw_pcie_readl_rc(pp, PCIE_PORT_LINK_CONTROL);
|
val = dw_pcie_readl_rc(pp, PCIE_PORT_LINK_CONTROL);
|
||||||
val &= ~PORT_LINK_MODE_MASK;
|
val &= ~PORT_LINK_MODE_MASK;
|
||||||
|
|
|
@ -699,11 +699,11 @@ static int qcom_pcie_probe(struct platform_device *pdev)
|
||||||
if (IS_ERR(pcie->phy))
|
if (IS_ERR(pcie->phy))
|
||||||
return PTR_ERR(pcie->phy);
|
return PTR_ERR(pcie->phy);
|
||||||
|
|
||||||
|
pp->dev = dev;
|
||||||
ret = pcie->ops->get_resources(pcie);
|
ret = pcie->ops->get_resources(pcie);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
pp->dev = dev;
|
|
||||||
pp->root_bus_nr = -1;
|
pp->root_bus_nr = -1;
|
||||||
pp->ops = &qcom_pcie_dw_ops;
|
pp->ops = &qcom_pcie_dw_ops;
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,7 @@
|
||||||
#define PCIE_CLIENT_ARI_ENABLE HIWORD_UPDATE_BIT(0x0008)
|
#define PCIE_CLIENT_ARI_ENABLE HIWORD_UPDATE_BIT(0x0008)
|
||||||
#define PCIE_CLIENT_CONF_LANE_NUM(x) HIWORD_UPDATE(0x0030, ENCODE_LANES(x))
|
#define PCIE_CLIENT_CONF_LANE_NUM(x) HIWORD_UPDATE(0x0030, ENCODE_LANES(x))
|
||||||
#define PCIE_CLIENT_MODE_RC HIWORD_UPDATE_BIT(0x0040)
|
#define PCIE_CLIENT_MODE_RC HIWORD_UPDATE_BIT(0x0040)
|
||||||
|
#define PCIE_CLIENT_GEN_SEL_1 HIWORD_UPDATE(0x0080, 0)
|
||||||
#define PCIE_CLIENT_GEN_SEL_2 HIWORD_UPDATE_BIT(0x0080)
|
#define PCIE_CLIENT_GEN_SEL_2 HIWORD_UPDATE_BIT(0x0080)
|
||||||
#define PCIE_CLIENT_BASIC_STATUS1 (PCIE_CLIENT_BASE + 0x48)
|
#define PCIE_CLIENT_BASIC_STATUS1 (PCIE_CLIENT_BASE + 0x48)
|
||||||
#define PCIE_CLIENT_LINK_STATUS_UP 0x00300000
|
#define PCIE_CLIENT_LINK_STATUS_UP 0x00300000
|
||||||
|
@ -135,13 +136,14 @@
|
||||||
#define PCIE_RC_CONFIG_VENDOR (PCIE_RC_CONFIG_BASE + 0x00)
|
#define PCIE_RC_CONFIG_VENDOR (PCIE_RC_CONFIG_BASE + 0x00)
|
||||||
#define PCIE_RC_CONFIG_RID_CCR (PCIE_RC_CONFIG_BASE + 0x08)
|
#define PCIE_RC_CONFIG_RID_CCR (PCIE_RC_CONFIG_BASE + 0x08)
|
||||||
#define PCIE_RC_CONFIG_SCC_SHIFT 16
|
#define PCIE_RC_CONFIG_SCC_SHIFT 16
|
||||||
|
#define PCIE_RC_CONFIG_DCR (PCIE_RC_CONFIG_BASE + 0xc4)
|
||||||
|
#define PCIE_RC_CONFIG_DCR_CSPL_SHIFT 18
|
||||||
|
#define PCIE_RC_CONFIG_DCR_CSPL_LIMIT 0xff
|
||||||
|
#define PCIE_RC_CONFIG_DCR_CPLS_SHIFT 26
|
||||||
#define PCIE_RC_CONFIG_LCS (PCIE_RC_CONFIG_BASE + 0xd0)
|
#define PCIE_RC_CONFIG_LCS (PCIE_RC_CONFIG_BASE + 0xd0)
|
||||||
#define PCIE_RC_CONFIG_LCS_RETRAIN_LINK BIT(5)
|
|
||||||
#define PCIE_RC_CONFIG_LCS_LBMIE BIT(10)
|
|
||||||
#define PCIE_RC_CONFIG_LCS_LABIE BIT(11)
|
|
||||||
#define PCIE_RC_CONFIG_LCS_LBMS BIT(30)
|
|
||||||
#define PCIE_RC_CONFIG_LCS_LAMS BIT(31)
|
|
||||||
#define PCIE_RC_CONFIG_L1_SUBSTATE_CTRL2 (PCIE_RC_CONFIG_BASE + 0x90c)
|
#define PCIE_RC_CONFIG_L1_SUBSTATE_CTRL2 (PCIE_RC_CONFIG_BASE + 0x90c)
|
||||||
|
#define PCIE_RC_CONFIG_THP_CAP (PCIE_RC_CONFIG_BASE + 0x274)
|
||||||
|
#define PCIE_RC_CONFIG_THP_CAP_NEXT_MASK GENMASK(31, 20)
|
||||||
|
|
||||||
#define PCIE_CORE_AXI_CONF_BASE 0xc00000
|
#define PCIE_CORE_AXI_CONF_BASE 0xc00000
|
||||||
#define PCIE_CORE_OB_REGION_ADDR0 (PCIE_CORE_AXI_CONF_BASE + 0x0)
|
#define PCIE_CORE_OB_REGION_ADDR0 (PCIE_CORE_AXI_CONF_BASE + 0x0)
|
||||||
|
@ -190,6 +192,9 @@ struct rockchip_pcie {
|
||||||
struct reset_control *mgmt_rst;
|
struct reset_control *mgmt_rst;
|
||||||
struct reset_control *mgmt_sticky_rst;
|
struct reset_control *mgmt_sticky_rst;
|
||||||
struct reset_control *pipe_rst;
|
struct reset_control *pipe_rst;
|
||||||
|
struct reset_control *pm_rst;
|
||||||
|
struct reset_control *aclk_rst;
|
||||||
|
struct reset_control *pclk_rst;
|
||||||
struct clk *aclk_pcie;
|
struct clk *aclk_pcie;
|
||||||
struct clk *aclk_perf_pcie;
|
struct clk *aclk_perf_pcie;
|
||||||
struct clk *hclk_pcie;
|
struct clk *hclk_pcie;
|
||||||
|
@ -200,8 +205,14 @@ struct rockchip_pcie {
|
||||||
struct gpio_desc *ep_gpio;
|
struct gpio_desc *ep_gpio;
|
||||||
u32 lanes;
|
u32 lanes;
|
||||||
u8 root_bus_nr;
|
u8 root_bus_nr;
|
||||||
|
int link_gen;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct irq_domain *irq_domain;
|
struct irq_domain *irq_domain;
|
||||||
|
u32 io_size;
|
||||||
|
int offset;
|
||||||
|
phys_addr_t io_bus_addr;
|
||||||
|
u32 mem_size;
|
||||||
|
phys_addr_t mem_bus_addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
static u32 rockchip_pcie_read(struct rockchip_pcie *rockchip, u32 reg)
|
static u32 rockchip_pcie_read(struct rockchip_pcie *rockchip, u32 reg)
|
||||||
|
@ -220,7 +231,7 @@ static void rockchip_pcie_enable_bw_int(struct rockchip_pcie *rockchip)
|
||||||
u32 status;
|
u32 status;
|
||||||
|
|
||||||
status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_LCS);
|
status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_LCS);
|
||||||
status |= (PCIE_RC_CONFIG_LCS_LBMIE | PCIE_RC_CONFIG_LCS_LABIE);
|
status |= (PCI_EXP_LNKCTL_LBMIE | PCI_EXP_LNKCTL_LABIE);
|
||||||
rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_LCS);
|
rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_LCS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,7 +240,7 @@ static void rockchip_pcie_clr_bw_int(struct rockchip_pcie *rockchip)
|
||||||
u32 status;
|
u32 status;
|
||||||
|
|
||||||
status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_LCS);
|
status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_LCS);
|
||||||
status |= (PCIE_RC_CONFIG_LCS_LBMS | PCIE_RC_CONFIG_LCS_LAMS);
|
status |= (PCI_EXP_LNKSTA_LBMS | PCI_EXP_LNKSTA_LABS) << 16;
|
||||||
rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_LCS);
|
rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_LCS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -395,6 +406,40 @@ static struct pci_ops rockchip_pcie_ops = {
|
||||||
.write = rockchip_pcie_wr_conf,
|
.write = rockchip_pcie_wr_conf,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void rockchip_pcie_set_power_limit(struct rockchip_pcie *rockchip)
|
||||||
|
{
|
||||||
|
u32 status, curr, scale, power;
|
||||||
|
|
||||||
|
if (IS_ERR(rockchip->vpcie3v3))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set RC's captured slot power limit and scale if
|
||||||
|
* vpcie3v3 available. The default values are both zero
|
||||||
|
* which means the software should set these two according
|
||||||
|
* to the actual power supply.
|
||||||
|
*/
|
||||||
|
curr = regulator_get_current_limit(rockchip->vpcie3v3);
|
||||||
|
if (curr > 0) {
|
||||||
|
scale = 3; /* 0.001x */
|
||||||
|
curr = curr / 1000; /* convert to mA */
|
||||||
|
power = (curr * 3300) / 1000; /* milliwatt */
|
||||||
|
while (power > PCIE_RC_CONFIG_DCR_CSPL_LIMIT) {
|
||||||
|
if (!scale) {
|
||||||
|
dev_warn(rockchip->dev, "invalid power supply\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
scale--;
|
||||||
|
power = power / 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_DCR);
|
||||||
|
status |= (power << PCIE_RC_CONFIG_DCR_CSPL_SHIFT) |
|
||||||
|
(scale << PCIE_RC_CONFIG_DCR_CPLS_SHIFT);
|
||||||
|
rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_DCR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* rockchip_pcie_init_port - Initialize hardware
|
* rockchip_pcie_init_port - Initialize hardware
|
||||||
* @rockchip: PCIe port information
|
* @rockchip: PCIe port information
|
||||||
|
@ -408,6 +453,24 @@ static int rockchip_pcie_init_port(struct rockchip_pcie *rockchip)
|
||||||
|
|
||||||
gpiod_set_value(rockchip->ep_gpio, 0);
|
gpiod_set_value(rockchip->ep_gpio, 0);
|
||||||
|
|
||||||
|
err = reset_control_assert(rockchip->aclk_rst);
|
||||||
|
if (err) {
|
||||||
|
dev_err(dev, "assert aclk_rst err %d\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = reset_control_assert(rockchip->pclk_rst);
|
||||||
|
if (err) {
|
||||||
|
dev_err(dev, "assert pclk_rst err %d\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = reset_control_assert(rockchip->pm_rst);
|
||||||
|
if (err) {
|
||||||
|
dev_err(dev, "assert pm_rst err %d\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
err = phy_init(rockchip->phy);
|
err = phy_init(rockchip->phy);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
dev_err(dev, "fail to init phy, err %d\n", err);
|
dev_err(dev, "fail to init phy, err %d\n", err);
|
||||||
|
@ -438,14 +501,40 @@ static int rockchip_pcie_init_port(struct rockchip_pcie *rockchip)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
udelay(10);
|
||||||
|
|
||||||
|
err = reset_control_deassert(rockchip->pm_rst);
|
||||||
|
if (err) {
|
||||||
|
dev_err(dev, "deassert pm_rst err %d\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = reset_control_deassert(rockchip->aclk_rst);
|
||||||
|
if (err) {
|
||||||
|
dev_err(dev, "deassert aclk_rst err %d\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = reset_control_deassert(rockchip->pclk_rst);
|
||||||
|
if (err) {
|
||||||
|
dev_err(dev, "deassert pclk_rst err %d\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rockchip->link_gen == 2)
|
||||||
|
rockchip_pcie_write(rockchip, PCIE_CLIENT_GEN_SEL_2,
|
||||||
|
PCIE_CLIENT_CONFIG);
|
||||||
|
else
|
||||||
|
rockchip_pcie_write(rockchip, PCIE_CLIENT_GEN_SEL_1,
|
||||||
|
PCIE_CLIENT_CONFIG);
|
||||||
|
|
||||||
rockchip_pcie_write(rockchip,
|
rockchip_pcie_write(rockchip,
|
||||||
PCIE_CLIENT_CONF_ENABLE |
|
PCIE_CLIENT_CONF_ENABLE |
|
||||||
PCIE_CLIENT_LINK_TRAIN_ENABLE |
|
PCIE_CLIENT_LINK_TRAIN_ENABLE |
|
||||||
PCIE_CLIENT_ARI_ENABLE |
|
PCIE_CLIENT_ARI_ENABLE |
|
||||||
PCIE_CLIENT_CONF_LANE_NUM(rockchip->lanes) |
|
PCIE_CLIENT_CONF_LANE_NUM(rockchip->lanes) |
|
||||||
PCIE_CLIENT_MODE_RC |
|
PCIE_CLIENT_MODE_RC,
|
||||||
PCIE_CLIENT_GEN_SEL_2,
|
PCIE_CLIENT_CONFIG);
|
||||||
PCIE_CLIENT_CONFIG);
|
|
||||||
|
|
||||||
err = phy_power_on(rockchip->phy);
|
err = phy_power_on(rockchip->phy);
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -481,21 +570,19 @@ static int rockchip_pcie_init_port(struct rockchip_pcie *rockchip)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* We need to read/write PCIE_RC_CONFIG_L1_SUBSTATE_CTRL2 before
|
|
||||||
* enabling ASPM. Otherwise L1PwrOnSc and L1PwrOnVal isn't
|
|
||||||
* reliable and enabling ASPM doesn't work. This is a controller
|
|
||||||
* bug we need to work around.
|
|
||||||
*/
|
|
||||||
status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_L1_SUBSTATE_CTRL2);
|
|
||||||
rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_L1_SUBSTATE_CTRL2);
|
|
||||||
|
|
||||||
/* Fix the transmitted FTS count desired to exit from L0s. */
|
/* Fix the transmitted FTS count desired to exit from L0s. */
|
||||||
status = rockchip_pcie_read(rockchip, PCIE_CORE_CTRL_PLC1);
|
status = rockchip_pcie_read(rockchip, PCIE_CORE_CTRL_PLC1);
|
||||||
status = (status & PCIE_CORE_CTRL_PLC1_FTS_MASK) |
|
status = (status & ~PCIE_CORE_CTRL_PLC1_FTS_MASK) |
|
||||||
(PCIE_CORE_CTRL_PLC1_FTS_CNT << PCIE_CORE_CTRL_PLC1_FTS_SHIFT);
|
(PCIE_CORE_CTRL_PLC1_FTS_CNT << PCIE_CORE_CTRL_PLC1_FTS_SHIFT);
|
||||||
rockchip_pcie_write(rockchip, status, PCIE_CORE_CTRL_PLC1);
|
rockchip_pcie_write(rockchip, status, PCIE_CORE_CTRL_PLC1);
|
||||||
|
|
||||||
|
rockchip_pcie_set_power_limit(rockchip);
|
||||||
|
|
||||||
|
/* Set RC's clock architecture as common clock */
|
||||||
|
status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_LCS);
|
||||||
|
status |= PCI_EXP_LNKCTL_CCC;
|
||||||
|
rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_LCS);
|
||||||
|
|
||||||
/* Enable Gen1 training */
|
/* Enable Gen1 training */
|
||||||
rockchip_pcie_write(rockchip, PCIE_CLIENT_LINK_TRAIN_ENABLE,
|
rockchip_pcie_write(rockchip, PCIE_CLIENT_LINK_TRAIN_ENABLE,
|
||||||
PCIE_CLIENT_CONFIG);
|
PCIE_CLIENT_CONFIG);
|
||||||
|
@ -522,35 +609,37 @@ static int rockchip_pcie_init_port(struct rockchip_pcie *rockchip)
|
||||||
msleep(20);
|
msleep(20);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
if (rockchip->link_gen == 2) {
|
||||||
* Enable retrain for gen2. This should be configured only after
|
/*
|
||||||
* gen1 finished.
|
* Enable retrain for gen2. This should be configured only after
|
||||||
*/
|
* gen1 finished.
|
||||||
status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_LCS);
|
*/
|
||||||
status |= PCIE_RC_CONFIG_LCS_RETRAIN_LINK;
|
status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_LCS);
|
||||||
rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_LCS);
|
status |= PCI_EXP_LNKCTL_RL;
|
||||||
|
rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_LCS);
|
||||||
|
|
||||||
timeout = jiffies + msecs_to_jiffies(500);
|
timeout = jiffies + msecs_to_jiffies(500);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
status = rockchip_pcie_read(rockchip, PCIE_CORE_CTRL);
|
status = rockchip_pcie_read(rockchip, PCIE_CORE_CTRL);
|
||||||
if ((status & PCIE_CORE_PL_CONF_SPEED_MASK) ==
|
if ((status & PCIE_CORE_PL_CONF_SPEED_MASK) ==
|
||||||
PCIE_CORE_PL_CONF_SPEED_5G) {
|
PCIE_CORE_PL_CONF_SPEED_5G) {
|
||||||
dev_dbg(dev, "PCIe link training gen2 pass!\n");
|
dev_dbg(dev, "PCIe link training gen2 pass!\n");
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (time_after(jiffies, timeout)) {
|
||||||
|
dev_dbg(dev, "PCIe link training gen2 timeout, fall back to gen1!\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
msleep(20);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (time_after(jiffies, timeout)) {
|
|
||||||
dev_dbg(dev, "PCIe link training gen2 timeout, fall back to gen1!\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
msleep(20);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check the final link width from negotiated lane counter from MGMT */
|
/* Check the final link width from negotiated lane counter from MGMT */
|
||||||
status = rockchip_pcie_read(rockchip, PCIE_CORE_CTRL);
|
status = rockchip_pcie_read(rockchip, PCIE_CORE_CTRL);
|
||||||
status = 0x1 << ((status & PCIE_CORE_PL_CONF_LANE_MASK) >>
|
status = 0x1 << ((status & PCIE_CORE_PL_CONF_LANE_MASK) >>
|
||||||
PCIE_CORE_PL_CONF_LANE_MASK);
|
PCIE_CORE_PL_CONF_LANE_SHIFT);
|
||||||
dev_dbg(dev, "current link width is x%d\n", status);
|
dev_dbg(dev, "current link width is x%d\n", status);
|
||||||
|
|
||||||
rockchip_pcie_write(rockchip, ROCKCHIP_VENDOR_ID,
|
rockchip_pcie_write(rockchip, ROCKCHIP_VENDOR_ID,
|
||||||
|
@ -558,6 +647,12 @@ static int rockchip_pcie_init_port(struct rockchip_pcie *rockchip)
|
||||||
rockchip_pcie_write(rockchip,
|
rockchip_pcie_write(rockchip,
|
||||||
PCI_CLASS_BRIDGE_PCI << PCIE_RC_CONFIG_SCC_SHIFT,
|
PCI_CLASS_BRIDGE_PCI << PCIE_RC_CONFIG_SCC_SHIFT,
|
||||||
PCIE_RC_CONFIG_RID_CCR);
|
PCIE_RC_CONFIG_RID_CCR);
|
||||||
|
|
||||||
|
/* Clear THP cap's next cap pointer to remove L1 substate cap */
|
||||||
|
status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_THP_CAP);
|
||||||
|
status &= ~PCIE_RC_CONFIG_THP_CAP_NEXT_MASK;
|
||||||
|
rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_THP_CAP);
|
||||||
|
|
||||||
rockchip_pcie_write(rockchip, 0x0, PCIE_RC_BAR_CONF);
|
rockchip_pcie_write(rockchip, 0x0, PCIE_RC_BAR_CONF);
|
||||||
|
|
||||||
rockchip_pcie_write(rockchip,
|
rockchip_pcie_write(rockchip,
|
||||||
|
@ -753,6 +848,10 @@ static int rockchip_pcie_parse_dt(struct rockchip_pcie *rockchip)
|
||||||
rockchip->lanes = 1;
|
rockchip->lanes = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rockchip->link_gen = of_pci_get_max_link_speed(node);
|
||||||
|
if (rockchip->link_gen < 0 || rockchip->link_gen > 2)
|
||||||
|
rockchip->link_gen = 2;
|
||||||
|
|
||||||
rockchip->core_rst = devm_reset_control_get(dev, "core");
|
rockchip->core_rst = devm_reset_control_get(dev, "core");
|
||||||
if (IS_ERR(rockchip->core_rst)) {
|
if (IS_ERR(rockchip->core_rst)) {
|
||||||
if (PTR_ERR(rockchip->core_rst) != -EPROBE_DEFER)
|
if (PTR_ERR(rockchip->core_rst) != -EPROBE_DEFER)
|
||||||
|
@ -781,6 +880,27 @@ static int rockchip_pcie_parse_dt(struct rockchip_pcie *rockchip)
|
||||||
return PTR_ERR(rockchip->pipe_rst);
|
return PTR_ERR(rockchip->pipe_rst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rockchip->pm_rst = devm_reset_control_get(dev, "pm");
|
||||||
|
if (IS_ERR(rockchip->pm_rst)) {
|
||||||
|
if (PTR_ERR(rockchip->pm_rst) != -EPROBE_DEFER)
|
||||||
|
dev_err(dev, "missing pm reset property in node\n");
|
||||||
|
return PTR_ERR(rockchip->pm_rst);
|
||||||
|
}
|
||||||
|
|
||||||
|
rockchip->pclk_rst = devm_reset_control_get(dev, "pclk");
|
||||||
|
if (IS_ERR(rockchip->pclk_rst)) {
|
||||||
|
if (PTR_ERR(rockchip->pclk_rst) != -EPROBE_DEFER)
|
||||||
|
dev_err(dev, "missing pclk reset property in node\n");
|
||||||
|
return PTR_ERR(rockchip->pclk_rst);
|
||||||
|
}
|
||||||
|
|
||||||
|
rockchip->aclk_rst = devm_reset_control_get(dev, "aclk");
|
||||||
|
if (IS_ERR(rockchip->aclk_rst)) {
|
||||||
|
if (PTR_ERR(rockchip->aclk_rst) != -EPROBE_DEFER)
|
||||||
|
dev_err(dev, "missing aclk reset property in node\n");
|
||||||
|
return PTR_ERR(rockchip->aclk_rst);
|
||||||
|
}
|
||||||
|
|
||||||
rockchip->ep_gpio = devm_gpiod_get(dev, "ep", GPIOD_OUT_HIGH);
|
rockchip->ep_gpio = devm_gpiod_get(dev, "ep", GPIOD_OUT_HIGH);
|
||||||
if (IS_ERR(rockchip->ep_gpio)) {
|
if (IS_ERR(rockchip->ep_gpio)) {
|
||||||
dev_err(dev, "missing ep-gpios property in node\n");
|
dev_err(dev, "missing ep-gpios property in node\n");
|
||||||
|
@ -1025,6 +1145,50 @@ static int rockchip_pcie_prog_ib_atu(struct rockchip_pcie *rockchip,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int rockchip_cfg_atu(struct rockchip_pcie *rockchip)
|
||||||
|
{
|
||||||
|
struct device *dev = rockchip->dev;
|
||||||
|
int offset;
|
||||||
|
int err;
|
||||||
|
int reg_no;
|
||||||
|
|
||||||
|
for (reg_no = 0; reg_no < (rockchip->mem_size >> 20); reg_no++) {
|
||||||
|
err = rockchip_pcie_prog_ob_atu(rockchip, reg_no + 1,
|
||||||
|
AXI_WRAPPER_MEM_WRITE,
|
||||||
|
20 - 1,
|
||||||
|
rockchip->mem_bus_addr +
|
||||||
|
(reg_no << 20),
|
||||||
|
0);
|
||||||
|
if (err) {
|
||||||
|
dev_err(dev, "program RC mem outbound ATU failed\n");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = rockchip_pcie_prog_ib_atu(rockchip, 2, 32 - 1, 0x0, 0);
|
||||||
|
if (err) {
|
||||||
|
dev_err(dev, "program RC mem inbound ATU failed\n");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = rockchip->mem_size >> 20;
|
||||||
|
for (reg_no = 0; reg_no < (rockchip->io_size >> 20); reg_no++) {
|
||||||
|
err = rockchip_pcie_prog_ob_atu(rockchip,
|
||||||
|
reg_no + 1 + offset,
|
||||||
|
AXI_WRAPPER_IO_WRITE,
|
||||||
|
20 - 1,
|
||||||
|
rockchip->io_bus_addr +
|
||||||
|
(reg_no << 20),
|
||||||
|
0);
|
||||||
|
if (err) {
|
||||||
|
dev_err(dev, "program RC io outbound ATU failed\n");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int rockchip_pcie_probe(struct platform_device *pdev)
|
static int rockchip_pcie_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct rockchip_pcie *rockchip;
|
struct rockchip_pcie *rockchip;
|
||||||
|
@ -1034,13 +1198,7 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
|
||||||
resource_size_t io_base;
|
resource_size_t io_base;
|
||||||
struct resource *mem;
|
struct resource *mem;
|
||||||
struct resource *io;
|
struct resource *io;
|
||||||
phys_addr_t io_bus_addr = 0;
|
|
||||||
u32 io_size;
|
|
||||||
phys_addr_t mem_bus_addr = 0;
|
|
||||||
u32 mem_size = 0;
|
|
||||||
int reg_no;
|
|
||||||
int err;
|
int err;
|
||||||
int offset;
|
|
||||||
|
|
||||||
LIST_HEAD(res);
|
LIST_HEAD(res);
|
||||||
|
|
||||||
|
@ -1107,14 +1265,13 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
|
||||||
goto err_vpcie;
|
goto err_vpcie;
|
||||||
|
|
||||||
/* Get the I/O and memory ranges from DT */
|
/* Get the I/O and memory ranges from DT */
|
||||||
io_size = 0;
|
|
||||||
resource_list_for_each_entry(win, &res) {
|
resource_list_for_each_entry(win, &res) {
|
||||||
switch (resource_type(win->res)) {
|
switch (resource_type(win->res)) {
|
||||||
case IORESOURCE_IO:
|
case IORESOURCE_IO:
|
||||||
io = win->res;
|
io = win->res;
|
||||||
io->name = "I/O";
|
io->name = "I/O";
|
||||||
io_size = resource_size(io);
|
rockchip->io_size = resource_size(io);
|
||||||
io_bus_addr = io->start - win->offset;
|
rockchip->io_bus_addr = io->start - win->offset;
|
||||||
err = pci_remap_iospace(io, io_base);
|
err = pci_remap_iospace(io, io_base);
|
||||||
if (err) {
|
if (err) {
|
||||||
dev_warn(dev, "error %d: failed to map resource %pR\n",
|
dev_warn(dev, "error %d: failed to map resource %pR\n",
|
||||||
|
@ -1125,8 +1282,8 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
|
||||||
case IORESOURCE_MEM:
|
case IORESOURCE_MEM:
|
||||||
mem = win->res;
|
mem = win->res;
|
||||||
mem->name = "MEM";
|
mem->name = "MEM";
|
||||||
mem_size = resource_size(mem);
|
rockchip->mem_size = resource_size(mem);
|
||||||
mem_bus_addr = mem->start - win->offset;
|
rockchip->mem_bus_addr = mem->start - win->offset;
|
||||||
break;
|
break;
|
||||||
case IORESOURCE_BUS:
|
case IORESOURCE_BUS:
|
||||||
rockchip->root_bus_nr = win->res->start;
|
rockchip->root_bus_nr = win->res->start;
|
||||||
|
@ -1136,45 +1293,9 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mem_size) {
|
err = rockchip_cfg_atu(rockchip);
|
||||||
for (reg_no = 0; reg_no < (mem_size >> 20); reg_no++) {
|
if (err)
|
||||||
err = rockchip_pcie_prog_ob_atu(rockchip, reg_no + 1,
|
|
||||||
AXI_WRAPPER_MEM_WRITE,
|
|
||||||
20 - 1,
|
|
||||||
mem_bus_addr +
|
|
||||||
(reg_no << 20),
|
|
||||||
0);
|
|
||||||
if (err) {
|
|
||||||
dev_err(dev, "program RC mem outbound ATU failed\n");
|
|
||||||
goto err_vpcie;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err = rockchip_pcie_prog_ib_atu(rockchip, 2, 32 - 1, 0x0, 0);
|
|
||||||
if (err) {
|
|
||||||
dev_err(dev, "program RC mem inbound ATU failed\n");
|
|
||||||
goto err_vpcie;
|
goto err_vpcie;
|
||||||
}
|
|
||||||
|
|
||||||
offset = mem_size >> 20;
|
|
||||||
|
|
||||||
if (io_size) {
|
|
||||||
for (reg_no = 0; reg_no < (io_size >> 20); reg_no++) {
|
|
||||||
err = rockchip_pcie_prog_ob_atu(rockchip,
|
|
||||||
reg_no + 1 + offset,
|
|
||||||
AXI_WRAPPER_IO_WRITE,
|
|
||||||
20 - 1,
|
|
||||||
io_bus_addr +
|
|
||||||
(reg_no << 20),
|
|
||||||
0);
|
|
||||||
if (err) {
|
|
||||||
dev_err(dev, "program RC io outbound ATU failed\n");
|
|
||||||
goto err_vpcie;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bus = pci_scan_root_bus(&pdev->dev, 0, &rockchip_pcie_ops, rockchip, &res);
|
bus = pci_scan_root_bus(&pdev->dev, 0, &rockchip_pcie_ops, rockchip, &res);
|
||||||
if (!bus) {
|
if (!bus) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
|
|
|
@ -141,6 +141,14 @@ int pci_claim_resource(struct pci_dev *dev, int resource)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we have a shadow copy in RAM, the PCI device doesn't respond
|
||||||
|
* to the shadow range, so we don't need to claim it, and upstream
|
||||||
|
* bridges don't need to route the range to the device.
|
||||||
|
*/
|
||||||
|
if (res->flags & IORESOURCE_ROM_SHADOW)
|
||||||
|
return 0;
|
||||||
|
|
||||||
root = pci_find_parent_resource(dev, res);
|
root = pci_find_parent_resource(dev, res);
|
||||||
if (!root) {
|
if (!root) {
|
||||||
dev_info(&dev->dev, "can't claim BAR %d %pR: no compatible bridge window\n",
|
dev_info(&dev->dev, "can't claim BAR %d %pR: no compatible bridge window\n",
|
||||||
|
|
Loading…
Reference in New Issue