Re: [PATCH v2 04/12] PCI: brcmstb: Use swinit reset if available

From: Jim Quinlan
Date: Mon Jul 08 2024 - 10:38:56 EST


On Mon, Jul 8, 2024 at 9:26 AM Philipp Zabel <p.zabel@xxxxxxxxxxxxxx> wrote:
>
> Hi Stanimir,
>
> On Mo, 2024-07-08 at 14:14 +0300, Stanimir Varbanov wrote:
> > Hi Philipp,
> >
> > On 7/8/24 12:37, Philipp Zabel wrote:
> > > On Fr, 2024-07-05 at 13:46 -0400, Jim Quinlan wrote:
> > > > On Thu, Jul 4, 2024 at 8:56 AM Stanimir Varbanov <svarbanov@xxxxxxx> wrote:
> > > > >
> > > > > Hi Jim,
> > > > >
> > > > > On 7/3/24 21:02, Jim Quinlan wrote:
> > > > > > The 7712 SOC adds a software init reset device for the PCIe HW.
> > > > > > If found in the DT node, use it.
> > > > > >
> > > > > > Signed-off-by: Jim Quinlan <james.quinlan@xxxxxxxxxxxx>
> > > > > > ---
> > > > > > drivers/pci/controller/pcie-brcmstb.c | 19 +++++++++++++++++++
> > > > > > 1 file changed, 19 insertions(+)
> > > > > >
> > > > > > diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c
> > > > > > index 4104c3668fdb..69926ee5c961 100644
> > > > > > --- a/drivers/pci/controller/pcie-brcmstb.c
> > > > > > +++ b/drivers/pci/controller/pcie-brcmstb.c
> > > > > > @@ -266,6 +266,7 @@ struct brcm_pcie {
> > > > > > struct reset_control *rescal;
> > > > > > struct reset_control *perst_reset;
> > > > > > struct reset_control *bridge;
> > > > > > + struct reset_control *swinit;
> > > > > > int num_memc;
> > > > > > u64 memc_size[PCIE_BRCM_MAX_MEMC];
> > > > > > u32 hw_rev;
> > > > > > @@ -1626,6 +1627,13 @@ static int brcm_pcie_probe(struct platform_device *pdev)
> > > > > > dev_err(&pdev->dev, "could not enable clock\n");
> > > > > > return ret;
> > > > > > }
> > > > > > +
> > > > > > + pcie->swinit = devm_reset_control_get_optional_exclusive(&pdev->dev, "swinit");
> > > > > > + if (IS_ERR(pcie->swinit)) {
> > > > > > + ret = dev_err_probe(&pdev->dev, PTR_ERR(pcie->swinit),
> > > > > > + "failed to get 'swinit' reset\n");
> > > > > > + goto clk_out;
> > > > > > + }
> > > > > > pcie->rescal = devm_reset_control_get_optional_shared(&pdev->dev, "rescal");
> > > > > > if (IS_ERR(pcie->rescal)) {
> > > > > > ret = PTR_ERR(pcie->rescal);
> > > > > > @@ -1637,6 +1645,17 @@ static int brcm_pcie_probe(struct platform_device *pdev)
> > > > > > goto clk_out;
> > > > > > }
> > > > > >
> > > > > > + ret = reset_control_assert(pcie->swinit);
> > > > > > + if (ret) {
> > > > > > + dev_err_probe(&pdev->dev, ret, "could not assert reset 'swinit'\n");
> > > > > > + goto clk_out;
> > > > > > + }
> > > > > > + ret = reset_control_deassert(pcie->swinit);
> > > > > > + if (ret) {
> > > > > > + dev_err(&pdev->dev, "could not de-assert reset 'swinit' after asserting\n");
> > > > > > + goto clk_out;
> > > > > > + }
> > > > >
> > > > > why not call reset_control_reset(pcie->swinit) directly?
> > > > Hi Stan,
> > > >
> > > > There is no reset_control_reset() method defined for reset-brcmstb.c.
> > > > The only reason I can
> > > > think of for this is that it allows the callers of assert/deassert to
> > > > insert a delay if desired.
> > >
> > > The main reason for the existence of reset_control_reset() is that
> > > there are reset controllers that can only be triggered (e.g. by writing
> > > a bit to a self-clearing register) to produce a complete reset pulse,
> > > with assertion, delay, and deassertion all handled by the reset
> > > controller.
> >
> > Got it. Thank you for explanation.
> >
> > But, IMO that means that the consumer driver should have knowledge of
> > low-level reset implementation, which is not generic API?
>
> Kind of. If the reset controller hardware has self-clearing resets, it
> is impossible to implement manual reset_control_assert/deassert() on
> top. So if a reset consumer requires that level of control, it just
> can't work with a self-deasserting controller. The other way around, a
> reset controller driver can emulate self-deasserting resets, iff it
> knows the timing requirements of all consumers.
>
> If the reset consumer only needs to see a pulse on the reset line, and
> there are no ordering requirements with other resets or clocks, and the
> device either doesn't care about timing or the reset controller knows
> how to produce the required delay, then using reset_control_reset()
> would be semantically correct.
>
> > Otherwise, I don't see a problem to implement asset/deassert sequence in
> > .reset op in this particular reset-brcmstb.c low-level driver.
>
> When reset_control_reset() is used, every reset controller that can be
> paired with this consumer needs to implement the .reset method,
> requiring to know the delay requirements for all of their consumers.
> The reset-simple driver implements this with a configurable worst-case
> delay, for example. As far as I can see, that has never been used.
>
> So yes, in this particular case, pcie-brcmstb only ever being paired
> with reset-brcmstb, it might be no problem to implement .reset in
> reset-brcmstb correctly, if all its consumers and their required delays
> are known.

This will not work. reset-brcmstb.c is a reset provider; it provides
resets for dozens of different HW blocks. Forcing dozens of the
resets to operate at the worst-case delay of the slowest one of them
is unacceptable, especially if a particular HW block uses its reset
often and/or requires timely execution.

Regards,
Jim Quinlan
Broadcom STB/CM


>
> regards
> Philipp

Attachment: smime.p7s
Description: S/MIME Cryptographic Signature