mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
PCI: rcar-gen4: Handle PERST# via reset subsystem
Handle PERST# via both GPIO and reset subsystem. On R-Car Gen4, the PERST# signal is operated as a GPIO, on R-Car Gen5 it might only be accessible via SCMI reset via reset subsystem. Support both options. This is a preparatory work for R-Car Gen5 support. Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org> Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Link: https://patch.msgid.link/20260921202823.72620-6-marek.vasut+renesas@mailbox.org
This commit is contained in:
parent
bb0cf158cf
commit
487a731517
|
|
@ -99,6 +99,7 @@ struct rcar_gen4_pcie {
|
|||
void __iomem *base;
|
||||
void __iomem *phy_base;
|
||||
struct platform_device *pdev;
|
||||
struct reset_control *perst;
|
||||
const struct rcar_gen4_pcie_drvdata *drvdata;
|
||||
};
|
||||
#define to_rcar_gen4_pcie(_dw) container_of(_dw, struct rcar_gen4_pcie, dw)
|
||||
|
|
@ -317,12 +318,25 @@ static void rcar_gen4_pcie_unprepare(struct rcar_gen4_pcie *rcar)
|
|||
|
||||
static int rcar_gen4_pcie_get_resources(struct rcar_gen4_pcie *rcar)
|
||||
{
|
||||
struct device *dev = rcar->dw.dev;
|
||||
struct device_node *root_port;
|
||||
|
||||
rcar->phy_base = devm_platform_ioremap_resource_byname(rcar->pdev, "phy");
|
||||
if (IS_ERR(rcar->phy_base))
|
||||
return PTR_ERR(rcar->phy_base);
|
||||
|
||||
root_port = of_get_next_available_child(dev->of_node, NULL);
|
||||
if (root_port) {
|
||||
rcar->perst = of_reset_control_get_optional_exclusive(root_port, "perst");
|
||||
of_node_put(root_port);
|
||||
if (IS_ERR(rcar->perst))
|
||||
return dev_err_probe(dev, PTR_ERR(rcar->perst), "Failed to get PERST#\n");
|
||||
}
|
||||
|
||||
/* Renesas-specific registers */
|
||||
rcar->base = devm_platform_ioremap_resource_byname(rcar->pdev, "app");
|
||||
if (IS_ERR(rcar->base))
|
||||
reset_control_put(rcar->perst);
|
||||
|
||||
return PTR_ERR_OR_ZERO(rcar->base);
|
||||
}
|
||||
|
|
@ -494,6 +508,21 @@ static int rcar_gen4_pcie_enable_device(struct pci_host_bridge *bridge,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void rcar_gen4_pcie_host_perst_assert(struct dw_pcie_rp *pp, bool assert)
|
||||
{
|
||||
struct dw_pcie *dw = to_dw_pcie_from_pp(pp);
|
||||
struct rcar_gen4_pcie *rcar = to_rcar_gen4_pcie(dw);
|
||||
|
||||
if (dw->pe_rst) {
|
||||
gpiod_set_value_cansleep(dw->pe_rst, assert);
|
||||
} else {
|
||||
if (assert)
|
||||
reset_control_assert(rcar->perst);
|
||||
else
|
||||
reset_control_deassert(rcar->perst);
|
||||
}
|
||||
}
|
||||
|
||||
/* Host mode */
|
||||
static int rcar_gen4_pcie_host_init(struct dw_pcie_rp *pp)
|
||||
{
|
||||
|
|
@ -504,7 +533,7 @@ static int rcar_gen4_pcie_host_init(struct dw_pcie_rp *pp)
|
|||
if (pp->bridge)
|
||||
pp->bridge->enable_device = rcar_gen4_pcie_enable_device;
|
||||
|
||||
gpiod_set_value_cansleep(dw->pe_rst, 1);
|
||||
rcar_gen4_pcie_host_perst_assert(pp, true);
|
||||
|
||||
ret = rcar->drvdata->init(rcar);
|
||||
if (ret)
|
||||
|
|
@ -525,7 +554,7 @@ static int rcar_gen4_pcie_host_init(struct dw_pcie_rp *pp)
|
|||
|
||||
msleep(PCIE_T_PVPERL_MS); /* pe_rst requires 100msec delay */
|
||||
|
||||
gpiod_set_value_cansleep(dw->pe_rst, 0);
|
||||
rcar_gen4_pcie_host_perst_assert(pp, false);
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
@ -539,7 +568,7 @@ static void rcar_gen4_pcie_host_deinit(struct dw_pcie_rp *pp)
|
|||
struct dw_pcie *dw = to_dw_pcie_from_pp(pp);
|
||||
struct rcar_gen4_pcie *rcar = to_rcar_gen4_pcie(dw);
|
||||
|
||||
gpiod_set_value_cansleep(dw->pe_rst, 1);
|
||||
rcar_gen4_pcie_host_perst_assert(pp, true);
|
||||
rcar->drvdata->deinit(rcar);
|
||||
}
|
||||
|
||||
|
|
@ -713,7 +742,7 @@ static int rcar_gen4_pcie_probe(struct platform_device *pdev)
|
|||
|
||||
err = rcar_gen4_pcie_prepare(rcar);
|
||||
if (err)
|
||||
return err;
|
||||
goto err_prepare;
|
||||
|
||||
err = rcar_gen4_add_dw_pcie(rcar);
|
||||
if (err)
|
||||
|
|
@ -724,6 +753,9 @@ static int rcar_gen4_pcie_probe(struct platform_device *pdev)
|
|||
err_unprepare:
|
||||
rcar_gen4_pcie_unprepare(rcar);
|
||||
|
||||
err_prepare:
|
||||
reset_control_put(rcar->perst);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -747,6 +779,7 @@ static void rcar_gen4_pcie_remove(struct platform_device *pdev)
|
|||
|
||||
rcar_gen4_remove_dw_pcie(rcar);
|
||||
rcar_gen4_pcie_unprepare(rcar);
|
||||
reset_control_put(rcar->perst);
|
||||
}
|
||||
|
||||
static int r8a779f0_pcie_ltssm_control(struct rcar_gen4_pcie *rcar, bool enable)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user