Message ID | 1492514488-27385-5-git-send-email-vivek.gautam@codeaurora.org |
---|---|
State | Superseded |
Headers | show |
On Tue, 2017-04-18 at 16:51 +0530, Vivek Gautam wrote: > Make use of reset_control_array_*() set of APIs to manage > an array of reset controllers available with the device. > > Cc: Thierry Reding <treding@nvidia.com> > Cc: Philipp Zabel <p.zabel@pengutronix.de> > Signed-off-by: Vivek Gautam <vivek.gautam@codeaurora.org> > --- > drivers/soc/tegra/pmc.c | 99 ++++++++++++++++++------------------------------- > 1 file changed, 36 insertions(+), 63 deletions(-) > > diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c > index e233dd5dcab3..4d039fa3db1b 100644 > --- a/drivers/soc/tegra/pmc.c > +++ b/drivers/soc/tegra/pmc.c > @@ -124,8 +124,7 @@ struct tegra_powergate { > unsigned int id; > struct clk **clks; > unsigned int num_clks; > - struct reset_control **resets; > - unsigned int num_resets; > + struct reset_control_array *resets; > }; > > struct tegra_io_pad_soc { > @@ -348,32 +347,14 @@ static int tegra_powergate_enable_clocks(struct tegra_powergate *pg) > return err; > } > > -static int tegra_powergate_reset_assert(struct tegra_powergate *pg) > +static inline int tegra_powergate_reset_assert(struct tegra_powergate *pg) > { > - unsigned int i; > - int err; > - > - for (i = 0; i < pg->num_resets; i++) { > - err = reset_control_assert(pg->resets[i]); > - if (err) > - return err; > - } > - > - return 0; > + return reset_control_array_assert(pg->resets); > } > > -static int tegra_powergate_reset_deassert(struct tegra_powergate *pg) > +static inline int tegra_powergate_reset_deassert(struct tegra_powergate *pg) > { > - unsigned int i; > - int err; > - > - for (i = 0; i < pg->num_resets; i++) { > - err = reset_control_deassert(pg->resets[i]); > - if (err) > - return err; > - } > - > - return 0; > + return reset_control_array_deassert(pg->resets); > } > > static int tegra_powergate_power_up(struct tegra_powergate *pg, > @@ -558,6 +539,7 @@ int tegra_powergate_sequence_power_up(unsigned int id, struct clk *clk, > struct reset_control *rst) > { > struct tegra_powergate pg; > + struct reset_control_array *resets; > int err; > > if (!tegra_powergate_is_available(id)) > @@ -566,12 +548,25 @@ int tegra_powergate_sequence_power_up(unsigned int id, struct clk *clk, > pg.id = id; > pg.clks = &clk; > pg.num_clks = 1; > - pg.resets = &rst; > - pg.num_resets = 1; Oh, I didn't notice that the resets array is often used for a single reset. I think in this case instead of wrapping a reset_control_array around the passed reset, you could store it as an additional pointer in tegra_powergate->reset and add if (pg->reset) return reset_control_(de)assert(pg->resets); to the tegra_powergate_reset_(de)assert functions ... > + > + resets = kzalloc(sizeof(*resets) + sizeof(resets->rstc[0]) * 1, > + GFP_KERNEL); > + if (!resets) > + return -ENOMEM; > + > + resets->rstc[0] = rst; > + pg.resets = resets; > > err = tegra_powergate_power_up(&pg, false); > - if (err) > + if (err) { > pr_err("failed to turn on partition %d: %d\n", id, err); > + goto free_reset; > + } > + > + return 0; > + > +free_reset: > + kfree(resets); > ... as having to open code this handling of struct reset_control_array internals completely negates its convenience. > return err; > } > @@ -755,45 +750,26 @@ static int tegra_powergate_of_get_clks(struct tegra_powergate *pg, > static int tegra_powergate_of_get_resets(struct tegra_powergate *pg, > struct device_node *np, bool off) > { > - struct reset_control *rst; > - unsigned int i, count; > int err; > > - count = of_count_phandle_with_args(np, "resets", "#reset-cells"); > - if (count == 0) > - return -ENODEV; > - > - pg->resets = kcalloc(count, sizeof(rst), GFP_KERNEL); > - if (!pg->resets) > - return -ENOMEM; > - > - for (i = 0; i < count; i++) { > - pg->resets[i] = of_reset_control_get_by_index(np, i); > - if (IS_ERR(pg->resets[i])) { > - err = PTR_ERR(pg->resets[i]); > - goto error; > - } > - > - if (off) > - err = reset_control_assert(pg->resets[i]); > - else > - err = reset_control_deassert(pg->resets[i]); > - > - if (err) { > - reset_control_put(pg->resets[i]); > - goto error; > - } > + pg->resets = of_reset_control_array_get_exclusive(np); > + if (IS_ERR(pg->resets)) { > + pr_err("failed to get device resets\n"); > + return PTR_ERR(pg->resets); > } > > - pg->num_resets = count; > + if (off) > + err = reset_control_array_assert(pg->resets); > + else > + err = reset_control_array_deassert(pg->resets); > > - return 0; > + if (err) > + goto put_reset; > > -error: > - while (i--) > - reset_control_put(pg->resets[i]); > + return 0; > > - kfree(pg->resets); > +put_reset: > + reset_control_array_put(pg->resets); > > return err; > } > @@ -885,10 +861,7 @@ static void tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np) > pm_genpd_remove(&pg->genpd); > > remove_resets: > - while (pg->num_resets--) > - reset_control_put(pg->resets[pg->num_resets]); > - > - kfree(pg->resets); > + reset_control_array_put(pg->resets); > > remove_clks: > while (pg->num_clks--) regards Philipp -- To unsubscribe from this list: send the line "unsubscribe linux-tegra" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 18/04/17 12:21, Vivek Gautam wrote: > Make use of reset_control_array_*() set of APIs to manage > an array of reset controllers available with the device. Before we apply this patch, I need to check to see if the order of the resets managed by the PMC driver matter. Today the order of the resets is determined by the order they appear in the DT node and although the new APIs work in the same way they do not guarantee this. So let me check to see if we can any concerns about ordering here. Otherwise would be nice to use these APIs. Cheers Jon
On 04/24/2017 06:15 PM, Jon Hunter wrote: > On 18/04/17 12:21, Vivek Gautam wrote: >> Make use of reset_control_array_*() set of APIs to manage >> an array of reset controllers available with the device. > Before we apply this patch, I need to check to see if the order of the > resets managed by the PMC driver matter. Today the order of the resets > is determined by the order they appear in the DT node and although the > new APIs work in the same way they do not guarantee this. So let me > check to see if we can any concerns about ordering here. Otherwise would > be nice to use these APIs. Right, that will be perfect. Best regards Vivek > > Cheers > Jon >
On 25/04/17 05:15, Vivek Gautam wrote: > On 04/24/2017 06:15 PM, Jon Hunter wrote: >> On 18/04/17 12:21, Vivek Gautam wrote: >>> Make use of reset_control_array_*() set of APIs to manage >>> an array of reset controllers available with the device. >> Before we apply this patch, I need to check to see if the order of the >> resets managed by the PMC driver matter. Today the order of the resets >> is determined by the order they appear in the DT node and although the >> new APIs work in the same way they do not guarantee this. So let me >> check to see if we can any concerns about ordering here. Otherwise would >> be nice to use these APIs. > > Right, that will be perfect. So I don't see any restrictions here and so I think this change is fine. BTW, for the DT case, is there any reason why we don't just say the order will be determine by the order the resets are list in the DT node? Cheers Jon
On Tue, 2017-04-25 at 11:05 +0100, Jon Hunter wrote: > On 25/04/17 05:15, Vivek Gautam wrote: > > On 04/24/2017 06:15 PM, Jon Hunter wrote: > >> On 18/04/17 12:21, Vivek Gautam wrote: > >>> Make use of reset_control_array_*() set of APIs to manage > >>> an array of reset controllers available with the device. > >> Before we apply this patch, I need to check to see if the order of the > >> resets managed by the PMC driver matter. Today the order of the resets > >> is determined by the order they appear in the DT node and although the > >> new APIs work in the same way they do not guarantee this. So let me > >> check to see if we can any concerns about ordering here. Otherwise would > >> be nice to use these APIs. > > > > Right, that will be perfect. > > So I don't see any restrictions here and so I think this change is fine. Thank you for checking. > BTW, for the DT case, is there any reason why we don't just say the > order will be determine by the order the resets are list in the DT node? I'd rather not make any promises, so I don't have to care about keeping them. This makes it easier to think about and allows for more freedom in changing the core code if needed. What if in the future there is a use case for enabling a bunch of resets by flipping a number of bits in a single register at the same time? Or if people accidentally depend on the ordering when in reality there is a small delay necessary between assertions that just happens to be hidden by the framework overhead? If there is a use case for an array of reset controls that must be (de)asserted in a fixed order and doesn't need any delay between the steps and is not suitable to be described by named resets for some reason, we can discuss this. Until then, I'm happy that tegra pmc can handle arrays without any particular ordering. regards Philipp -- To unsubscribe from this list: send the line "unsubscribe linux-tegra" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 25/04/17 11:33, Philipp Zabel wrote: > On Tue, 2017-04-25 at 11:05 +0100, Jon Hunter wrote: >> On 25/04/17 05:15, Vivek Gautam wrote: >>> On 04/24/2017 06:15 PM, Jon Hunter wrote: >>>> On 18/04/17 12:21, Vivek Gautam wrote: >>>>> Make use of reset_control_array_*() set of APIs to manage >>>>> an array of reset controllers available with the device. >>>> Before we apply this patch, I need to check to see if the order of the >>>> resets managed by the PMC driver matter. Today the order of the resets >>>> is determined by the order they appear in the DT node and although the >>>> new APIs work in the same way they do not guarantee this. So let me >>>> check to see if we can any concerns about ordering here. Otherwise would >>>> be nice to use these APIs. >>> >>> Right, that will be perfect. >> >> So I don't see any restrictions here and so I think this change is fine. > > Thank you for checking. > >> BTW, for the DT case, is there any reason why we don't just say the >> order will be determine by the order the resets are list in the DT node? > > I'd rather not make any promises, so I don't have to care about keeping > them. This makes it easier to think about and allows for more freedom in > changing the core code if needed. > > What if in the future there is a use case for enabling a bunch of resets > by flipping a number of bits in a single register at the same time? Or > if people accidentally depend on the ordering when in reality there is a > small delay necessary between assertions that just happens to be hidden > by the framework overhead? > > If there is a use case for an array of reset controls that must be > (de)asserted in a fixed order and doesn't need any delay between the > steps and is not suitable to be described by named resets for some > reason, we can discuss this. Until then, I'm happy that tegra pmc can > handle arrays without any particular ordering. OK, makes sense. Thanks Jon
On 04/25/2017 04:24 PM, Jon Hunter wrote: > On 25/04/17 11:33, Philipp Zabel wrote: >> On Tue, 2017-04-25 at 11:05 +0100, Jon Hunter wrote: >>> On 25/04/17 05:15, Vivek Gautam wrote: >>>> On 04/24/2017 06:15 PM, Jon Hunter wrote: >>>>> On 18/04/17 12:21, Vivek Gautam wrote: >>>>>> Make use of reset_control_array_*() set of APIs to manage >>>>>> an array of reset controllers available with the device. >>>>> Before we apply this patch, I need to check to see if the order of the >>>>> resets managed by the PMC driver matter. Today the order of the resets >>>>> is determined by the order they appear in the DT node and although the >>>>> new APIs work in the same way they do not guarantee this. So let me >>>>> check to see if we can any concerns about ordering here. Otherwise would >>>>> be nice to use these APIs. >>>> Right, that will be perfect. >>> So I don't see any restrictions here and so I think this change is fine. >> Thank you for checking. >> >>> BTW, for the DT case, is there any reason why we don't just say the >>> order will be determine by the order the resets are list in the DT node? >> I'd rather not make any promises, so I don't have to care about keeping >> them. This makes it easier to think about and allows for more freedom in >> changing the core code if needed. >> >> What if in the future there is a use case for enabling a bunch of resets >> by flipping a number of bits in a single register at the same time? Or >> if people accidentally depend on the ordering when in reality there is a >> small delay necessary between assertions that just happens to be hidden >> by the framework overhead? >> >> If there is a use case for an array of reset controls that must be >> (de)asserted in a fixed order and doesn't need any delay between the >> steps and is not suitable to be described by named resets for some >> reason, we can discuss this. Until then, I'm happy that tegra pmc can >> handle arrays without any particular ordering. > OK, makes sense. Thanks Jon for testing this. Best Regards Vivek > > Thanks > Jon >
On 25/04/17 12:06, Vivek Gautam wrote: > On 04/25/2017 04:24 PM, Jon Hunter wrote: >> On 25/04/17 11:33, Philipp Zabel wrote: >>> On Tue, 2017-04-25 at 11:05 +0100, Jon Hunter wrote: >>>> On 25/04/17 05:15, Vivek Gautam wrote: >>>>> On 04/24/2017 06:15 PM, Jon Hunter wrote: >>>>>> On 18/04/17 12:21, Vivek Gautam wrote: >>>>>>> Make use of reset_control_array_*() set of APIs to manage >>>>>>> an array of reset controllers available with the device. >>>>>> Before we apply this patch, I need to check to see if the order of >>>>>> the >>>>>> resets managed by the PMC driver matter. Today the order of the >>>>>> resets >>>>>> is determined by the order they appear in the DT node and although >>>>>> the >>>>>> new APIs work in the same way they do not guarantee this. So let me >>>>>> check to see if we can any concerns about ordering here. Otherwise >>>>>> would >>>>>> be nice to use these APIs. >>>>> Right, that will be perfect. >>>> So I don't see any restrictions here and so I think this change is >>>> fine. >>> Thank you for checking. >>> >>>> BTW, for the DT case, is there any reason why we don't just say the >>>> order will be determine by the order the resets are list in the DT >>>> node? >>> I'd rather not make any promises, so I don't have to care about keeping >>> them. This makes it easier to think about and allows for more freedom in >>> changing the core code if needed. >>> >>> What if in the future there is a use case for enabling a bunch of resets >>> by flipping a number of bits in a single register at the same time? Or >>> if people accidentally depend on the ordering when in reality there is a >>> small delay necessary between assertions that just happens to be hidden >>> by the framework overhead? >>> >>> If there is a use case for an array of reset controls that must be >>> (de)asserted in a fixed order and doesn't need any delay between the >>> steps and is not suitable to be described by named resets for some >>> reason, we can discuss this. Until then, I'm happy that tegra pmc can >>> handle arrays without any particular ordering. >> OK, makes sense. > > Thanks Jon for testing this. Not tested yet :-) However, I will test this just to confirm. Are you planning on sending out a v4 soon? Jon
On Tue, Apr 25, 2017 at 4:41 PM, Jon Hunter <jonathanh@nvidia.com> wrote: > > On 25/04/17 12:06, Vivek Gautam wrote: >> On 04/25/2017 04:24 PM, Jon Hunter wrote: >>> On 25/04/17 11:33, Philipp Zabel wrote: >>>> On Tue, 2017-04-25 at 11:05 +0100, Jon Hunter wrote: >>>>> On 25/04/17 05:15, Vivek Gautam wrote: >>>>>> On 04/24/2017 06:15 PM, Jon Hunter wrote: >>>>>>> On 18/04/17 12:21, Vivek Gautam wrote: >>>>>>>> Make use of reset_control_array_*() set of APIs to manage >>>>>>>> an array of reset controllers available with the device. >>>>>>> Before we apply this patch, I need to check to see if the order of >>>>>>> the >>>>>>> resets managed by the PMC driver matter. Today the order of the >>>>>>> resets >>>>>>> is determined by the order they appear in the DT node and although >>>>>>> the >>>>>>> new APIs work in the same way they do not guarantee this. So let me >>>>>>> check to see if we can any concerns about ordering here. Otherwise >>>>>>> would >>>>>>> be nice to use these APIs. >>>>>> Right, that will be perfect. >>>>> So I don't see any restrictions here and so I think this change is >>>>> fine. >>>> Thank you for checking. >>>> >>>>> BTW, for the DT case, is there any reason why we don't just say the >>>>> order will be determine by the order the resets are list in the DT >>>>> node? >>>> I'd rather not make any promises, so I don't have to care about keeping >>>> them. This makes it easier to think about and allows for more freedom in >>>> changing the core code if needed. >>>> >>>> What if in the future there is a use case for enabling a bunch of resets >>>> by flipping a number of bits in a single register at the same time? Or >>>> if people accidentally depend on the ordering when in reality there is a >>>> small delay necessary between assertions that just happens to be hidden >>>> by the framework overhead? >>>> >>>> If there is a use case for an array of reset controls that must be >>>> (de)asserted in a fixed order and doesn't need any delay between the >>>> steps and is not suitable to be described by named resets for some >>>> reason, we can discuss this. Until then, I'm happy that tegra pmc can >>>> handle arrays without any particular ordering. >>> OK, makes sense. >> >> Thanks Jon for testing this. > > Not tested yet :-) > > However, I will test this just to confirm. Are you planning on sending > out a v4 soon? Yes, I will send a v4 soon this week. Thanks Vivek
diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index e233dd5dcab3..4d039fa3db1b 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -124,8 +124,7 @@ struct tegra_powergate { unsigned int id; struct clk **clks; unsigned int num_clks; - struct reset_control **resets; - unsigned int num_resets; + struct reset_control_array *resets; }; struct tegra_io_pad_soc { @@ -348,32 +347,14 @@ static int tegra_powergate_enable_clocks(struct tegra_powergate *pg) return err; } -static int tegra_powergate_reset_assert(struct tegra_powergate *pg) +static inline int tegra_powergate_reset_assert(struct tegra_powergate *pg) { - unsigned int i; - int err; - - for (i = 0; i < pg->num_resets; i++) { - err = reset_control_assert(pg->resets[i]); - if (err) - return err; - } - - return 0; + return reset_control_array_assert(pg->resets); } -static int tegra_powergate_reset_deassert(struct tegra_powergate *pg) +static inline int tegra_powergate_reset_deassert(struct tegra_powergate *pg) { - unsigned int i; - int err; - - for (i = 0; i < pg->num_resets; i++) { - err = reset_control_deassert(pg->resets[i]); - if (err) - return err; - } - - return 0; + return reset_control_array_deassert(pg->resets); } static int tegra_powergate_power_up(struct tegra_powergate *pg, @@ -558,6 +539,7 @@ int tegra_powergate_sequence_power_up(unsigned int id, struct clk *clk, struct reset_control *rst) { struct tegra_powergate pg; + struct reset_control_array *resets; int err; if (!tegra_powergate_is_available(id)) @@ -566,12 +548,25 @@ int tegra_powergate_sequence_power_up(unsigned int id, struct clk *clk, pg.id = id; pg.clks = &clk; pg.num_clks = 1; - pg.resets = &rst; - pg.num_resets = 1; + + resets = kzalloc(sizeof(*resets) + sizeof(resets->rstc[0]) * 1, + GFP_KERNEL); + if (!resets) + return -ENOMEM; + + resets->rstc[0] = rst; + pg.resets = resets; err = tegra_powergate_power_up(&pg, false); - if (err) + if (err) { pr_err("failed to turn on partition %d: %d\n", id, err); + goto free_reset; + } + + return 0; + +free_reset: + kfree(resets); return err; } @@ -755,45 +750,26 @@ static int tegra_powergate_of_get_clks(struct tegra_powergate *pg, static int tegra_powergate_of_get_resets(struct tegra_powergate *pg, struct device_node *np, bool off) { - struct reset_control *rst; - unsigned int i, count; int err; - count = of_count_phandle_with_args(np, "resets", "#reset-cells"); - if (count == 0) - return -ENODEV; - - pg->resets = kcalloc(count, sizeof(rst), GFP_KERNEL); - if (!pg->resets) - return -ENOMEM; - - for (i = 0; i < count; i++) { - pg->resets[i] = of_reset_control_get_by_index(np, i); - if (IS_ERR(pg->resets[i])) { - err = PTR_ERR(pg->resets[i]); - goto error; - } - - if (off) - err = reset_control_assert(pg->resets[i]); - else - err = reset_control_deassert(pg->resets[i]); - - if (err) { - reset_control_put(pg->resets[i]); - goto error; - } + pg->resets = of_reset_control_array_get_exclusive(np); + if (IS_ERR(pg->resets)) { + pr_err("failed to get device resets\n"); + return PTR_ERR(pg->resets); } - pg->num_resets = count; + if (off) + err = reset_control_array_assert(pg->resets); + else + err = reset_control_array_deassert(pg->resets); - return 0; + if (err) + goto put_reset; -error: - while (i--) - reset_control_put(pg->resets[i]); + return 0; - kfree(pg->resets); +put_reset: + reset_control_array_put(pg->resets); return err; } @@ -885,10 +861,7 @@ static void tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np) pm_genpd_remove(&pg->genpd); remove_resets: - while (pg->num_resets--) - reset_control_put(pg->resets[pg->num_resets]); - - kfree(pg->resets); + reset_control_array_put(pg->resets); remove_clks: while (pg->num_clks--)
Make use of reset_control_array_*() set of APIs to manage an array of reset controllers available with the device. Cc: Thierry Reding <treding@nvidia.com> Cc: Philipp Zabel <p.zabel@pengutronix.de> Signed-off-by: Vivek Gautam <vivek.gautam@codeaurora.org> --- drivers/soc/tegra/pmc.c | 99 ++++++++++++++++++------------------------------- 1 file changed, 36 insertions(+), 63 deletions(-)