Skip to content

Commit

Permalink
PCI: rockchip: Simplify reset control handling by using reset_control…
Browse files Browse the repository at this point in the history
…_bulk*() function

Currently, the driver acquires and asserts/deasserts the resets
individually thereby making the driver complex to read.

This can be simplified by using the reset_control_bulk() APIs.

Use devm_reset_control_bulk_get_exclusive() API to acquire all the resets
and use reset_control_bulk_{assert/deassert}() APIs to assert/deassert them
in bulk.

Following the recommendations in 'Rockchip RK3399 TRM v1.3 Part2':

  1. Split the reset controls into two groups as per section '17.5.8.1.1
     PCIe as Root Complex'.

  2. Deassert the 'Pipe, MGMT Sticky, MGMT, Core' resets in groups as per
     section '17.5.8.1.1 PCIe as Root Complex'. This is accomplished using
     the reset_control_bulk APIs.

Link: https://lore.kernel.org/r/20241202151150.7393-3-linux.amoon@gmail.com
Co-developed-by: Dan Carpenter <dan.carpenter@linaro.org>
Signed-off-by: Anand Moon <linux.amoon@gmail.com>
Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
[kwilczynski: squash error handling fix from https://lore.kernel.org/r/7da6ac56-af55-4436-9597-6af24df8122c@stanley.mountain]
Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
  • Loading branch information
Anand Moon authored and Krzysztof Wilczyński committed Jan 15, 2025
1 parent abdd4c8 commit 1871593
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 129 deletions.
150 changes: 28 additions & 122 deletions drivers/pci/controller/pcie-rockchip.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ int rockchip_pcie_parse_dt(struct rockchip_pcie *rockchip)
struct platform_device *pdev = to_platform_device(dev);
struct device_node *node = dev->of_node;
struct resource *regs;
int err;
int err, i;

if (rockchip->is_rc) {
regs = platform_get_resource_byname(pdev,
Expand Down Expand Up @@ -69,55 +69,23 @@ int rockchip_pcie_parse_dt(struct rockchip_pcie *rockchip)
if (rockchip->link_gen < 0 || rockchip->link_gen > 2)
rockchip->link_gen = 2;

rockchip->core_rst = devm_reset_control_get_exclusive(dev, "core");
if (IS_ERR(rockchip->core_rst)) {
if (PTR_ERR(rockchip->core_rst) != -EPROBE_DEFER)
dev_err(dev, "missing core reset property in node\n");
return PTR_ERR(rockchip->core_rst);
}

rockchip->mgmt_rst = devm_reset_control_get_exclusive(dev, "mgmt");
if (IS_ERR(rockchip->mgmt_rst)) {
if (PTR_ERR(rockchip->mgmt_rst) != -EPROBE_DEFER)
dev_err(dev, "missing mgmt reset property in node\n");
return PTR_ERR(rockchip->mgmt_rst);
}

rockchip->mgmt_sticky_rst = devm_reset_control_get_exclusive(dev,
"mgmt-sticky");
if (IS_ERR(rockchip->mgmt_sticky_rst)) {
if (PTR_ERR(rockchip->mgmt_sticky_rst) != -EPROBE_DEFER)
dev_err(dev, "missing mgmt-sticky reset property in node\n");
return PTR_ERR(rockchip->mgmt_sticky_rst);
}
for (i = 0; i < ROCKCHIP_NUM_PM_RSTS; i++)
rockchip->pm_rsts[i].id = rockchip_pci_pm_rsts[i];

rockchip->pipe_rst = devm_reset_control_get_exclusive(dev, "pipe");
if (IS_ERR(rockchip->pipe_rst)) {
if (PTR_ERR(rockchip->pipe_rst) != -EPROBE_DEFER)
dev_err(dev, "missing pipe reset property in node\n");
return PTR_ERR(rockchip->pipe_rst);
}

rockchip->pm_rst = devm_reset_control_get_exclusive(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);
}
err = devm_reset_control_bulk_get_exclusive(dev,
ROCKCHIP_NUM_PM_RSTS,
rockchip->pm_rsts);
if (err)
return dev_err_probe(dev, err, "Cannot get the PM reset\n");

rockchip->pclk_rst = devm_reset_control_get_exclusive(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);
}
for (i = 0; i < ROCKCHIP_NUM_CORE_RSTS; i++)
rockchip->core_rsts[i].id = rockchip_pci_core_rsts[i];

rockchip->aclk_rst = devm_reset_control_get_exclusive(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);
}
err = devm_reset_control_bulk_get_exclusive(dev,
ROCKCHIP_NUM_CORE_RSTS,
rockchip->core_rsts);
if (err)
return dev_err_probe(dev, err, "Cannot get the Core resets\n");

if (rockchip->is_rc)
rockchip->perst_gpio = devm_gpiod_get_optional(dev, "ep",
Expand Down Expand Up @@ -150,23 +118,10 @@ int rockchip_pcie_init_port(struct rockchip_pcie *rockchip)
int err, i;
u32 regs;

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 = reset_control_bulk_assert(ROCKCHIP_NUM_PM_RSTS,
rockchip->pm_rsts);
if (err)
return dev_err_probe(dev, err, "Couldn't assert PM resets\n");

for (i = 0; i < MAX_LANE_NUM; i++) {
err = phy_init(rockchip->phys[i]);
Expand All @@ -176,47 +131,19 @@ int rockchip_pcie_init_port(struct rockchip_pcie *rockchip)
}
}

err = reset_control_assert(rockchip->core_rst);
if (err) {
dev_err(dev, "assert core_rst err %d\n", err);
goto err_exit_phy;
}

err = reset_control_assert(rockchip->mgmt_rst);
if (err) {
dev_err(dev, "assert mgmt_rst err %d\n", err);
goto err_exit_phy;
}

err = reset_control_assert(rockchip->mgmt_sticky_rst);
err = reset_control_bulk_assert(ROCKCHIP_NUM_CORE_RSTS,
rockchip->core_rsts);
if (err) {
dev_err(dev, "assert mgmt_sticky_rst err %d\n", err);
goto err_exit_phy;
}

err = reset_control_assert(rockchip->pipe_rst);
if (err) {
dev_err(dev, "assert pipe_rst err %d\n", err);
dev_err_probe(dev, err, "Couldn't assert Core resets\n");
goto err_exit_phy;
}

udelay(10);

err = reset_control_deassert(rockchip->pm_rst);
err = reset_control_bulk_deassert(ROCKCHIP_NUM_PM_RSTS,
rockchip->pm_rsts);
if (err) {
dev_err(dev, "deassert pm_rst err %d\n", err);
goto err_exit_phy;
}

err = reset_control_deassert(rockchip->aclk_rst);
if (err) {
dev_err(dev, "deassert aclk_rst err %d\n", err);
goto err_exit_phy;
}

err = reset_control_deassert(rockchip->pclk_rst);
if (err) {
dev_err(dev, "deassert pclk_rst err %d\n", err);
dev_err(dev, "Couldn't deassert PM resets %d\n", err);
goto err_exit_phy;
}

Expand Down Expand Up @@ -256,31 +183,10 @@ int rockchip_pcie_init_port(struct rockchip_pcie *rockchip)
goto err_power_off_phy;
}

/*
* Please don't reorder the deassert sequence of the following
* four reset pins.
*/
err = reset_control_deassert(rockchip->mgmt_sticky_rst);
if (err) {
dev_err(dev, "deassert mgmt_sticky_rst err %d\n", err);
goto err_power_off_phy;
}

err = reset_control_deassert(rockchip->core_rst);
if (err) {
dev_err(dev, "deassert core_rst err %d\n", err);
goto err_power_off_phy;
}

err = reset_control_deassert(rockchip->mgmt_rst);
if (err) {
dev_err(dev, "deassert mgmt_rst err %d\n", err);
goto err_power_off_phy;
}

err = reset_control_deassert(rockchip->pipe_rst);
err = reset_control_bulk_deassert(ROCKCHIP_NUM_CORE_RSTS,
rockchip->core_rsts);
if (err) {
dev_err(dev, "deassert pipe_rst err %d\n", err);
dev_err(dev, "Couldn't deassert Core reset %d\n", err);
goto err_power_off_phy;
}

Expand Down
26 changes: 19 additions & 7 deletions drivers/pci/controller/pcie-rockchip.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/pci-ecam.h>
#include <linux/reset.h>

/*
* The upper 16 bits of PCIE_CLIENT_CONFIG are a write mask for the lower 16
Expand Down Expand Up @@ -310,18 +311,29 @@
(((c) << ((b) * 8 + 5)) & \
ROCKCHIP_PCIE_CORE_EP_FUNC_BAR_CFG_BAR_CTRL_MASK(b))

#define ROCKCHIP_NUM_PM_RSTS ARRAY_SIZE(rockchip_pci_pm_rsts)
#define ROCKCHIP_NUM_CORE_RSTS ARRAY_SIZE(rockchip_pci_core_rsts)

static const char * const rockchip_pci_pm_rsts[] = {
"pm",
"pclk",
"aclk",
};

static const char * const rockchip_pci_core_rsts[] = {
"mgmt-sticky",
"core",
"mgmt",
"pipe",
};

struct rockchip_pcie {
void __iomem *reg_base; /* DT axi-base */
void __iomem *apb_base; /* DT apb-base */
bool legacy_phy;
struct phy *phys[MAX_LANE_NUM];
struct reset_control *core_rst;
struct reset_control *mgmt_rst;
struct reset_control *mgmt_sticky_rst;
struct reset_control *pipe_rst;
struct reset_control *pm_rst;
struct reset_control *aclk_rst;
struct reset_control *pclk_rst;
struct reset_control_bulk_data pm_rsts[ROCKCHIP_NUM_PM_RSTS];
struct reset_control_bulk_data core_rsts[ROCKCHIP_NUM_CORE_RSTS];
struct clk_bulk_data *clks;
int num_clks;
struct regulator *vpcie12v; /* 12V power supply */
Expand Down

0 comments on commit 1871593

Please sign in to comment.