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:
Bjorn Helgaas 2016-12-12 11:25:11 -06:00
commit 44b83b32e7
9 changed files with 239 additions and 102 deletions

View File

@ -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";

View File

@ -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

View File

@ -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

View File

@ -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))

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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",