[PATCH v2 0/5] Add missing reset controls to NVIDIA Tegra ASoC drivers
Hi,
This series adds missing hardware reset controls to I2S and AC97 drivers. Currently drivers happen to work properly because reset is implicitly deasserted by tegra-clk driver, but clk driver shouldn't touch the resets and we need to fix it because this breaks other Tegra drivers. Previously we fixed the resets of the AHUB and HDMI codec drivers, but turned out that we missed the I2C and AC97 drivers.
Thanks to Paul Fertser for testing the pending clk patches and finding that audio got broken on Tegra20 AC100 netbook because of the missing I2S reset.
Changelog:
v2: - After some more testing I found that I2S control logic doesn't require I2S clock to be enabled for resetting. Hence it's fine to have I2S to be reset by parent AHUB driver, so I dropped "tegra30: i2s: Add reset control" patch.
- While I was double-checking resets on Tegra30, I found that that Tegra30 I2S driver has a broken runtime PM which doesn't restore hardware state on resume and it's lost after AHUB RPM-resume. Thus, added this new patch "tegra30: i2s: Restore hardware state on runtime PM resume".
- Added new patches which switch AHUB driver to use reset-bulk API. I took the RFC patch from Philipp Zabel, fixed it and added devm_reset_control_bulk_optional_get_exclusive_released() that will be useful for further Tegra GPU patches. This is a minor improvement which makes code cleaner.
Dmitry Osipenko (4): ASoC: tegra20: ac97: Add reset control ASoC: tegra20: i2s: Add reset control ASoC: tegra30: i2s: Restore hardware state on runtime PM resume ASoC: tegra: ahub: Switch to use reset-bulk API
Philipp Zabel (1): reset: Add reset_control_bulk API
drivers/reset/core.c | 215 +++++++++++++++++++++++++ include/linux/reset.h | 279 +++++++++++++++++++++++++++++++++ sound/soc/tegra/tegra20_ac97.c | 21 +++ sound/soc/tegra/tegra20_ac97.h | 1 + sound/soc/tegra/tegra20_i2s.c | 31 ++++ sound/soc/tegra/tegra20_i2s.h | 1 + sound/soc/tegra/tegra30_ahub.c | 104 +++++------- sound/soc/tegra/tegra30_ahub.h | 5 +- sound/soc/tegra/tegra30_i2s.c | 41 ++--- 9 files changed, 600 insertions(+), 98 deletions(-)
Tegra20 AC97 driver doesn't manage the AC97 controller reset, relying on implicit deassertion of the reset by tegra-clk driver, which needs to be fixed since this behaviour is unacceptable by other Tegra drivers. Add explicit reset control to the Tegra20 AC97 driver.
Note that AC97 reset was always specified in Tegra20 device-tree, hence DTB ABI changes aren't required.
Signed-off-by: Dmitry Osipenko digetx@gmail.com --- sound/soc/tegra/tegra20_ac97.c | 21 +++++++++++++++++++++ sound/soc/tegra/tegra20_ac97.h | 1 + 2 files changed, 22 insertions(+)
diff --git a/sound/soc/tegra/tegra20_ac97.c b/sound/soc/tegra/tegra20_ac97.c index 06c728ae17ed..c454a34c15c4 100644 --- a/sound/soc/tegra/tegra20_ac97.c +++ b/sound/soc/tegra/tegra20_ac97.c @@ -21,6 +21,7 @@ #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/regmap.h> +#include <linux/reset.h> #include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> @@ -313,6 +314,12 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev) } dev_set_drvdata(&pdev->dev, ac97);
+ ac97->reset = devm_reset_control_get_exclusive(&pdev->dev, "ac97"); + if (IS_ERR(ac97->reset)) { + dev_err(&pdev->dev, "Can't retrieve ac97 reset\n"); + return PTR_ERR(ac97->reset); + } + ac97->clk_ac97 = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(ac97->clk_ac97)) { dev_err(&pdev->dev, "Can't retrieve ac97 clock\n"); @@ -364,12 +371,26 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev) ac97->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; ac97->playback_dma_data.maxburst = 4;
+ ret = reset_control_assert(ac97->reset); + if (ret) { + dev_err(&pdev->dev, "Failed to assert AC'97 reset: %d\n", ret); + goto err_clk_put; + } + ret = clk_prepare_enable(ac97->clk_ac97); if (ret) { dev_err(&pdev->dev, "clk_enable failed: %d\n", ret); goto err_clk_put; }
+ usleep_range(10, 100); + + ret = reset_control_deassert(ac97->reset); + if (ret) { + dev_err(&pdev->dev, "Failed to deassert AC'97 reset: %d\n", ret); + goto err_clk_disable_unprepare; + } + ret = snd_soc_set_ac97_ops(&tegra20_ac97_ops); if (ret) { dev_err(&pdev->dev, "Failed to set AC'97 ops: %d\n", ret); diff --git a/sound/soc/tegra/tegra20_ac97.h b/sound/soc/tegra/tegra20_ac97.h index e467cd1ff2ca..870ea09ff301 100644 --- a/sound/soc/tegra/tegra20_ac97.h +++ b/sound/soc/tegra/tegra20_ac97.h @@ -78,6 +78,7 @@ struct tegra20_ac97 { struct clk *clk_ac97; struct snd_dmaengine_dai_dma_data capture_dma_data; struct snd_dmaengine_dai_dma_data playback_dma_data; + struct reset_control *reset; struct regmap *regmap; int reset_gpio; int sync_gpio;
The I2S reset may be asserted at a boot time, in particular this is the case on Tegra20 AC100 netbook. Tegra20 I2S driver doesn't manage the reset control and currently it happens to work because reset is implicitly deasserted by the tegra-clk driver when I2S clock is enabled. The I2S permanently stays in a reset once tegra-clk is fixed to not touch the resets, which it shouldn't be doing. Add reset control to the Tegra20 I2S driver.
Note that I2S reset was always specified in Tegra20 device-tree, hence DTB ABI changes aren't required.
Tested-by: Paul Fertser fercerpav@gmail.com # T20 AC100 Reported-by: Paul Fertser fercerpav@gmail.com Signed-off-by: Dmitry Osipenko digetx@gmail.com --- sound/soc/tegra/tegra20_i2s.c | 31 +++++++++++++++++++++++++++++++ sound/soc/tegra/tegra20_i2s.h | 1 + 2 files changed, 32 insertions(+)
diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c index d7a3d046c8f8..c0af5352b483 100644 --- a/sound/soc/tegra/tegra20_i2s.c +++ b/sound/soc/tegra/tegra20_i2s.c @@ -22,6 +22,7 @@ #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/regmap.h> +#include <linux/reset.h> #include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> @@ -37,6 +38,8 @@ static int tegra20_i2s_runtime_suspend(struct device *dev) { struct tegra20_i2s *i2s = dev_get_drvdata(dev);
+ regcache_cache_only(i2s->regmap, true); + clk_disable_unprepare(i2s->clk_i2s);
return 0; @@ -47,13 +50,35 @@ static int tegra20_i2s_runtime_resume(struct device *dev) struct tegra20_i2s *i2s = dev_get_drvdata(dev); int ret;
+ ret = reset_control_assert(i2s->reset); + if (ret) + return ret; + ret = clk_prepare_enable(i2s->clk_i2s); if (ret) { dev_err(dev, "clk_enable failed: %d\n", ret); return ret; }
+ usleep_range(10, 100); + + ret = reset_control_deassert(i2s->reset); + if (ret) + goto disable_clocks; + + regcache_cache_only(i2s->regmap, false); + regcache_mark_dirty(i2s->regmap); + + ret = regcache_sync(i2s->regmap); + if (ret) + goto disable_clocks; + return 0; + +disable_clocks: + clk_disable_unprepare(i2s->clk_i2s); + + return ret; }
static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai, @@ -339,6 +364,12 @@ static int tegra20_i2s_platform_probe(struct platform_device *pdev) i2s->dai = tegra20_i2s_dai_template; i2s->dai.name = dev_name(&pdev->dev);
+ i2s->reset = devm_reset_control_get_exclusive(&pdev->dev, "i2s"); + if (IS_ERR(i2s->reset)) { + dev_err(&pdev->dev, "Can't retrieve i2s reset\n"); + return PTR_ERR(i2s->reset); + } + i2s->clk_i2s = clk_get(&pdev->dev, NULL); if (IS_ERR(i2s->clk_i2s)) { dev_err(&pdev->dev, "Can't retrieve i2s clock\n"); diff --git a/sound/soc/tegra/tegra20_i2s.h b/sound/soc/tegra/tegra20_i2s.h index 628d3ca09f42..8233e5fa2eff 100644 --- a/sound/soc/tegra/tegra20_i2s.h +++ b/sound/soc/tegra/tegra20_i2s.h @@ -144,6 +144,7 @@ struct tegra20_i2s { struct snd_dmaengine_dai_dma_data capture_dma_data; struct snd_dmaengine_dai_dma_data playback_dma_data; struct regmap *regmap; + struct reset_control *reset; };
#endif
Tegra30 I2S driver syncs regmap cache only on resume from system suspend, but hardware is reset across the runtime suspend because RPM of the parent AHUB driver resets the I2S hardware, hence h/w state is lost after each RPM resume. The problem isn't visible because hardware happens to be fully reprogrammed after each RPM resume. Move hardware syncing to RPM resume in order to restore h/w state properly.
Fixes: ed9ce1ed2239 ("ASoC: tegra: ahub: Reset hardware properly") Signed-off-by: Dmitry Osipenko digetx@gmail.com --- sound/soc/tegra/tegra30_i2s.c | 40 +++++++++++------------------------ 1 file changed, 12 insertions(+), 28 deletions(-)
diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c index 6740df541508..3d22c1be6f3d 100644 --- a/sound/soc/tegra/tegra30_i2s.c +++ b/sound/soc/tegra/tegra30_i2s.c @@ -58,8 +58,18 @@ static int tegra30_i2s_runtime_resume(struct device *dev) }
regcache_cache_only(i2s->regmap, false); + regcache_mark_dirty(i2s->regmap); + + ret = regcache_sync(i2s->regmap); + if (ret) + goto disable_clocks;
return 0; + +disable_clocks: + clk_disable_unprepare(i2s->clk_i2s); + + return ret; }
static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai, @@ -551,37 +561,11 @@ static int tegra30_i2s_platform_remove(struct platform_device *pdev) return 0; }
-#ifdef CONFIG_PM_SLEEP -static int tegra30_i2s_suspend(struct device *dev) -{ - struct tegra30_i2s *i2s = dev_get_drvdata(dev); - - regcache_mark_dirty(i2s->regmap); - - return 0; -} - -static int tegra30_i2s_resume(struct device *dev) -{ - struct tegra30_i2s *i2s = dev_get_drvdata(dev); - int ret; - - ret = pm_runtime_get_sync(dev); - if (ret < 0) { - pm_runtime_put(dev); - return ret; - } - ret = regcache_sync(i2s->regmap); - pm_runtime_put(dev); - - return ret; -} -#endif - static const struct dev_pm_ops tegra30_i2s_pm_ops = { SET_RUNTIME_PM_OPS(tegra30_i2s_runtime_suspend, tegra30_i2s_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(tegra30_i2s_suspend, tegra30_i2s_resume) + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) };
static struct platform_driver tegra30_i2s_driver = {
From: Philipp Zabel p.zabel@pengutronix.de
Follow the clock and regulator subsystems' lead and add a bulk API for reset controls.
Signed-off-by: Philipp Zabel p.zabel@pengutronix.de Tested-by: Dmitry Osipenko digetx@gmail.com Signed-off-by: Dmitry Osipenko digetx@gmail.com --- drivers/reset/core.c | 215 ++++++++++++++++++++++++++++++++ include/linux/reset.h | 279 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 494 insertions(+)
diff --git a/drivers/reset/core.c b/drivers/reset/core.c index dbf881b586d9..71c1c8264b2d 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -358,6 +358,30 @@ int reset_control_reset(struct reset_control *rstc) } EXPORT_SYMBOL_GPL(reset_control_reset);
+/** + * reset_control_bulk_reset - reset the controlled devices in order + * @num_rstcs: number of entries in rstcs array + * @rstcs: array of struct reset_control_bulk_data with reset controls set + * + * Issue a reset on all provided reset controls, in order. + * + * See also: reset_control_reset() + */ +int reset_control_bulk_reset(int num_rstcs, + struct reset_control_bulk_data *rstcs) +{ + int ret, i; + + for (i = 0; i < num_rstcs; i++) { + ret = reset_control_reset(rstcs[i].rstc); + if (ret) + return ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(reset_control_bulk_reset); + /** * reset_control_rearm - allow shared reset line to be re-triggered" * @rstc: reset controller @@ -461,6 +485,36 @@ int reset_control_assert(struct reset_control *rstc) } EXPORT_SYMBOL_GPL(reset_control_assert);
+/** + * reset_control_bulk_assert - asserts the reset lines in order + * @num_rstcs: number of entries in rstcs array + * @rstcs: array of struct reset_control_bulk_data with reset controls set + * + * Assert the reset lines for all provided reset controls, in order. + * If an assertion fails, already asserted resets are deasserted again. + * + * See also: reset_control_assert() + */ +int reset_control_bulk_assert(int num_rstcs, + struct reset_control_bulk_data *rstcs) +{ + int ret, i; + + for (i = 0; i < num_rstcs; i++) { + ret = reset_control_assert(rstcs[i].rstc); + if (ret) + goto err; + } + + return 0; + +err: + while (i--) + reset_control_deassert(rstcs[i].rstc); + return ret; +} +EXPORT_SYMBOL_GPL(reset_control_bulk_assert); + /** * reset_control_deassert - deasserts the reset line * @rstc: reset controller @@ -511,6 +565,36 @@ int reset_control_deassert(struct reset_control *rstc) } EXPORT_SYMBOL_GPL(reset_control_deassert);
+/** + * reset_control_bulk_deassert - deasserts the reset lines in reverse order + * @num_rstcs: number of entries in rstcs array + * @rstcs: array of struct reset_control_bulk_data with reset controls set + * + * Deassert the reset lines for all provided reset controls, in reverse order. + * If a deassertion fails, already deasserted resets are asserted again. + * + * See also: reset_control_deassert() + */ +int reset_control_bulk_deassert(int num_rstcs, + struct reset_control_bulk_data *rstcs) +{ + int ret, i; + + for (i = num_rstcs - 1; i >= 0; i--) { + ret = reset_control_deassert(rstcs[i].rstc); + if (ret) + goto err; + } + + return 0; + +err: + while (i < num_rstcs) + reset_control_assert(rstcs[i++].rstc); + return ret; +} +EXPORT_SYMBOL_GPL(reset_control_bulk_deassert); + /** * reset_control_status - returns a negative errno if not supported, a * positive value if the reset line is asserted, or zero if the reset @@ -588,6 +672,36 @@ int reset_control_acquire(struct reset_control *rstc) } EXPORT_SYMBOL_GPL(reset_control_acquire);
+/** + * reset_control_bulk_acquire - acquires reset controls for exclusive use + * @num_rstcs: number of entries in rstcs array + * @rstcs: array of struct reset_control_bulk_data with reset controls set + * + * This is used to explicitly acquire reset controls requested with + * reset_control_bulk_get_exclusive_release() for temporary exclusive use. + * + * See also: reset_control_acquire(), reset_control_bulk_release() + */ +int reset_control_bulk_acquire(int num_rstcs, + struct reset_control_bulk_data *rstcs) +{ + int ret, i; + + for (i = 0; i < num_rstcs; i++) { + ret = reset_control_acquire(rstcs[i].rstc); + if (ret) + goto err; + } + + return 0; + +err: + while (i--) + reset_control_release(rstcs[i].rstc); + return ret; +} +EXPORT_SYMBOL_GPL(reset_control_bulk_acquire); + /** * reset_control_release() - releases exclusive access to a reset control * @rstc: reset control @@ -610,6 +724,26 @@ void reset_control_release(struct reset_control *rstc) } EXPORT_SYMBOL_GPL(reset_control_release);
+/** + * reset_control_bulk_release() - releases exclusive access to reset controls + * @num_rstcs: number of entries in rstcs array + * @rstcs: array of struct reset_control_bulk_data with reset controls set + * + * Releases exclusive access right to reset controls previously obtained by a + * call to reset_control_bulk_acquire(). + * + * See also: reset_control_release(), reset_control_bulk_acquire() + */ +void reset_control_bulk_release(int num_rstcs, + struct reset_control_bulk_data *rstcs) +{ + int i; + + for (i = 0; i < num_rstcs; i++) + reset_control_release(rstcs[i].rstc); +} +EXPORT_SYMBOL_GPL(reset_control_bulk_release); + static struct reset_control *__reset_control_get_internal( struct reset_controller_dev *rcdev, unsigned int index, bool shared, bool acquired) @@ -814,6 +948,32 @@ struct reset_control *__reset_control_get(struct device *dev, const char *id, } EXPORT_SYMBOL_GPL(__reset_control_get);
+int __reset_control_bulk_get(struct device *dev, int num_rstcs, + struct reset_control_bulk_data *rstcs, + bool shared, bool optional, bool acquired) +{ + int ret, i; + + for (i = 0; i < num_rstcs; i++) { + rstcs[i].rstc = __reset_control_get(dev, rstcs[i].id, 0, + shared, optional, acquired); + if (IS_ERR(rstcs[i].rstc)) { + ret = PTR_ERR(rstcs[i].rstc); + goto err; + } + } + + return 0; + +err: + mutex_lock(&reset_list_mutex); + while (i--) + __reset_control_put_internal(rstcs[i].rstc); + mutex_unlock(&reset_list_mutex); + return ret; +} +EXPORT_SYMBOL_GPL(__reset_control_bulk_get); + static void reset_control_array_put(struct reset_control_array *resets) { int i; @@ -845,6 +1005,23 @@ void reset_control_put(struct reset_control *rstc) } EXPORT_SYMBOL_GPL(reset_control_put);
+/** + * reset_control_bulk_put - free the reset controllers + * @num_rstcs: number of entries in rstcs array + * @rstcs: array of struct reset_control_bulk_data with reset controls set + */ +void reset_control_bulk_put(int num_rstcs, struct reset_control_bulk_data *rstcs) +{ + mutex_lock(&reset_list_mutex); + while (num_rstcs--) { + if (IS_ERR_OR_NULL(rstcs[num_rstcs].rstc)) + continue; + __reset_control_put_internal(rstcs[num_rstcs].rstc); + } + mutex_unlock(&reset_list_mutex); +} +EXPORT_SYMBOL_GPL(reset_control_bulk_put); + static void devm_reset_control_release(struct device *dev, void *res) { reset_control_put(*(struct reset_control **)res); @@ -874,6 +1051,44 @@ struct reset_control *__devm_reset_control_get(struct device *dev, } EXPORT_SYMBOL_GPL(__devm_reset_control_get);
+struct reset_control_bulk_devres { + int num_rstcs; + struct reset_control_bulk_data *rstcs; +}; + +static void devm_reset_control_bulk_release(struct device *dev, void *res) +{ + struct reset_control_bulk_devres *devres = res; + + reset_control_bulk_put(devres->num_rstcs, devres->rstcs); +} + +int __devm_reset_control_bulk_get(struct device *dev, int num_rstcs, + struct reset_control_bulk_data *rstcs, + bool shared, bool optional, bool acquired) +{ + struct reset_control_bulk_devres *ptr; + int ret; + + ptr = devres_alloc(devm_reset_control_bulk_release, sizeof(*ptr), + GFP_KERNEL); + if (!ptr) + return -ENOMEM; + + ret = __reset_control_bulk_get(dev, num_rstcs, rstcs, shared, optional, acquired); + if (ret < 0) { + devres_free(ptr); + return ret; + } + + ptr->num_rstcs = num_rstcs; + ptr->rstcs = rstcs; + devres_add(dev, ptr); + + return 0; +} +EXPORT_SYMBOL_GPL(__devm_reset_control_bulk_get); + /** * __device_reset - find reset controller associated with the device * and perform reset diff --git a/include/linux/reset.h b/include/linux/reset.h index b9109efa2a5c..bca087fe2a0f 100644 --- a/include/linux/reset.h +++ b/include/linux/reset.h @@ -10,6 +10,21 @@ struct device; struct device_node; struct reset_control;
+/** + * struct reset_control_bulk_data - Data used for bulk reset control operations. + * + * @id: reset control consumer ID + * @rstc: struct reset_control * to store the associated reset control + * + * The reset APIs provide a series of reset_control_bulk_*() API calls as + * a convenience to consumers which require multiple reset controls. + * This structure is used to manage data for these calls. + */ +struct reset_control_bulk_data { + const char *id; + struct reset_control *rstc; +}; + #ifdef CONFIG_RESET_CONTROLLER
int reset_control_reset(struct reset_control *rstc); @@ -20,17 +35,29 @@ int reset_control_status(struct reset_control *rstc); int reset_control_acquire(struct reset_control *rstc); void reset_control_release(struct reset_control *rstc);
+int reset_control_bulk_reset(int num_rstcs, struct reset_control_bulk_data *rstcs); +int reset_control_bulk_assert(int num_rstcs, struct reset_control_bulk_data *rstcs); +int reset_control_bulk_deassert(int num_rstcs, struct reset_control_bulk_data *rstcs); +int reset_control_bulk_acquire(int num_rstcs, struct reset_control_bulk_data *rstcs); +void reset_control_bulk_release(int num_rstcs, struct reset_control_bulk_data *rstcs); + struct reset_control *__of_reset_control_get(struct device_node *node, const char *id, int index, bool shared, bool optional, bool acquired); struct reset_control *__reset_control_get(struct device *dev, const char *id, int index, bool shared, bool optional, bool acquired); +int __reset_control_bulk_get(struct device *dev, int num_rstcs, + struct reset_control_bulk_data *rstcs, + bool shared, bool optional, bool acquired); void reset_control_put(struct reset_control *rstc); int __device_reset(struct device *dev, bool optional); struct reset_control *__devm_reset_control_get(struct device *dev, const char *id, int index, bool shared, bool optional, bool acquired); +int __devm_reset_control_bulk_get(struct device *dev, int num_rstcs, + struct reset_control_bulk_data *rstcs, + bool shared, bool optional, bool acquired);
struct reset_control *devm_reset_control_array_get(struct device *dev, bool shared, bool optional); @@ -96,6 +123,14 @@ static inline struct reset_control *__reset_control_get( return optional ? NULL : ERR_PTR(-ENOTSUPP); }
+static inline struct reset_control * +__reset_control_bulk_get(struct device *dev, int num_rstcs, + struct reset_control_bulk_data *rstcs, + bool shared, bool optional, bool acquired) +{ + return optional ? NULL : ERR_PTR(-ENOTSUPP); +} + static inline struct reset_control *__devm_reset_control_get( struct device *dev, const char *id, int index, bool shared, bool optional, @@ -104,6 +139,14 @@ static inline struct reset_control *__devm_reset_control_get( return optional ? NULL : ERR_PTR(-ENOTSUPP); }
+static inline struct reset_control * +__devm_reset_control_bulk_get(struct device *dev, int num_rstcs, + struct reset_control_bulk_data *rstcs, + bool shared, bool optional, bool acquired) +{ + return optional ? NULL : ERR_PTR(-ENOTSUPP); +} + static inline struct reset_control * devm_reset_control_array_get(struct device *dev, bool shared, bool optional) { @@ -155,6 +198,23 @@ __must_check reset_control_get_exclusive(struct device *dev, const char *id) return __reset_control_get(dev, id, 0, false, false, true); }
+/** + * reset_control_bulk_get_exclusive - Lookup and obtain exclusive references to + * multiple reset controllers. + * @dev: device to be reset by the controller + * @num_rstcs: number of entries in rstcs array + * @rstcs: array of struct reset_control_bulk_data with reset line names set + * + * Fills the rstcs array with pointers to exclusive reset controls and + * returns 0, or an IS_ERR() condition containing errno. + */ +static inline int __must_check +reset_control_bulk_get_exclusive(struct device *dev, int num_rstcs, + struct reset_control_bulk_data *rstcs) +{ + return __reset_control_bulk_get(dev, num_rstcs, rstcs, false, false, true); +} + /** * reset_control_get_exclusive_released - Lookup and obtain a temoprarily * exclusive reference to a reset @@ -176,6 +236,48 @@ __must_check reset_control_get_exclusive_released(struct device *dev, return __reset_control_get(dev, id, 0, false, false, false); }
+/** + * reset_control_bulk_get_exclusive_released - Lookup and obtain temporarily + * exclusive references to multiple reset + * controllers. + * @dev: device to be reset by the controller + * @num_rstcs: number of entries in rstcs array + * @rstcs: array of struct reset_control_bulk_data with reset line names set + * + * Fills the rstcs array with pointers to exclusive reset controls and + * returns 0, or an IS_ERR() condition containing errno. + * reset-controls returned by this function must be acquired via + * reset_control_bulk_acquire() before they can be used and should be released + * via reset_control_bulk_release() afterwards. + */ +static inline int __must_check +reset_control_bulk_get_exclusive_released(struct device *dev, int num_rstcs, + struct reset_control_bulk_data *rstcs) +{ + return __reset_control_bulk_get(dev, num_rstcs, rstcs, false, false, false); +} + +/** + * reset_control_bulk_get_optional_exclusive_released - Lookup and obtain optional + * temporarily exclusive references to multiple + * reset controllers. + * @dev: device to be reset by the controller + * @num_rstcs: number of entries in rstcs array + * @rstcs: array of struct reset_control_bulk_data with reset line names set + * + * Optional variant of reset_control_bulk_get_exclusive_released(). If the + * requested reset is not specified in the device tree, this function returns 0 + * instead of an error and missing rtsc is set to NULL. + * + * See reset_control_bulk_get_exclusive_released() for more information. + */ +static inline int __must_check +reset_control_bulk_get_optional_exclusive_released(struct device *dev, int num_rstcs, + struct reset_control_bulk_data *rstcs) +{ + return __reset_control_bulk_get(dev, num_rstcs, rstcs, false, true, false); +} + /** * reset_control_get_shared - Lookup and obtain a shared reference to a * reset controller. @@ -204,6 +306,23 @@ static inline struct reset_control *reset_control_get_shared( return __reset_control_get(dev, id, 0, true, false, false); }
+/** + * reset_control_bulk_get_shared - Lookup and obtain shared references to + * multiple reset controllers. + * @dev: device to be reset by the controller + * @num_rstcs: number of entries in rstcs array + * @rstcs: array of struct reset_control_bulk_data with reset line names set + * + * Fills the rstcs array with pointers to shared reset controls and + * returns 0, or an IS_ERR() condition containing errno. + */ +static inline int __must_check +reset_control_bulk_get_shared(struct device *dev, int num_rstcs, + struct reset_control_bulk_data *rstcs) +{ + return __reset_control_bulk_get(dev, num_rstcs, rstcs, true, false, false); +} + /** * reset_control_get_optional_exclusive - optional reset_control_get_exclusive() * @dev: device to be reset by the controller @@ -221,6 +340,26 @@ static inline struct reset_control *reset_control_get_optional_exclusive( return __reset_control_get(dev, id, 0, false, true, true); }
+/** + * reset_control_bulk_get_optional_exclusive - optional + * reset_control_bulk_get_exclusive() + * @dev: device to be reset by the controller + * @num_rstcs: number of entries in rstcs array + * @rstcs: array of struct reset_control_bulk_data with reset line names set + * + * Optional variant of reset_control_bulk_get_exclusive(). If any of the + * requested resets are not specified in the device tree, this function sets + * them to NULL instead of returning an error. + * + * See reset_control_bulk_get_exclusive() for more information. + */ +static inline int __must_check +reset_control_bulk_get_optional_exclusive(struct device *dev, int num_rstcs, + struct reset_control_bulk_data *rstcs) +{ + return __reset_control_bulk_get(dev, num_rstcs, rstcs, false, true, true); +} + /** * reset_control_get_optional_shared - optional reset_control_get_shared() * @dev: device to be reset by the controller @@ -238,6 +377,26 @@ static inline struct reset_control *reset_control_get_optional_shared( return __reset_control_get(dev, id, 0, true, true, false); }
+/** + * reset_control_bulk_get_optional_shared - optional + * reset_control_bulk_get_shared() + * @dev: device to be reset by the controller + * @num_rstcs: number of entries in rstcs array + * @rstcs: array of struct reset_control_bulk_data with reset line names set + * + * Optional variant of reset_control_bulk_get_shared(). If the requested resets + * are not specified in the device tree, this function sets them to NULL + * instead of returning an error. + * + * See reset_control_bulk_get_shared() for more information. + */ +static inline int __must_check +reset_control_bulk_get_optional_shared(struct device *dev, int num_rstcs, + struct reset_control_bulk_data *rstcs) +{ + return __reset_control_bulk_get(dev, num_rstcs, rstcs, true, true, false); +} + /** * of_reset_control_get_exclusive - Lookup and obtain an exclusive reference * to a reset controller. @@ -343,6 +502,26 @@ __must_check devm_reset_control_get_exclusive(struct device *dev, return __devm_reset_control_get(dev, id, 0, false, false, true); }
+/** + * devm_reset_control_bulk_get_exclusive - resource managed + * reset_control_bulk_get_exclusive() + * @dev: device to be reset by the controller + * @num_rstcs: number of entries in rstcs array + * @rstcs: array of struct reset_control_bulk_data with reset line names set + * + * Managed reset_control_bulk_get_exclusive(). For reset controllers returned + * from this function, reset_control_put() is called automatically on driver + * detach. + * + * See reset_control_bulk_get_exclusive() for more information. + */ +static inline int __must_check +devm_reset_control_bulk_get_exclusive(struct device *dev, int num_rstcs, + struct reset_control_bulk_data *rstcs) +{ + return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, false, false, true); +} + /** * devm_reset_control_get_exclusive_released - resource managed * reset_control_get_exclusive_released() @@ -362,6 +541,26 @@ __must_check devm_reset_control_get_exclusive_released(struct device *dev, return __devm_reset_control_get(dev, id, 0, false, false, false); }
+/** + * devm_reset_control_bulk_get_exclusive_released - resource managed + * reset_control_bulk_get_exclusive_released() + * @dev: device to be reset by the controller + * @num_rstcs: number of entries in rstcs array + * @rstcs: array of struct reset_control_bulk_data with reset line names set + * + * Managed reset_control_bulk_get_exclusive_released(). For reset controllers + * returned from this function, reset_control_put() is called automatically on + * driver detach. + * + * See reset_control_bulk_get_exclusive_released() for more information. + */ +static inline int __must_check +devm_reset_control_bulk_get_exclusive_released(struct device *dev, int num_rstcs, + struct reset_control_bulk_data *rstcs) +{ + return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, false, false, false); +} + /** * devm_reset_control_get_optional_exclusive_released - resource managed * reset_control_get_optional_exclusive_released() @@ -381,6 +580,26 @@ __must_check devm_reset_control_get_optional_exclusive_released(struct device *d return __devm_reset_control_get(dev, id, 0, false, true, false); }
+/** + * devm_reset_control_bulk_get_optional_exclusive_released - resource managed + * reset_control_bulk_optional_get_exclusive_released() + * @dev: device to be reset by the controller + * @num_rstcs: number of entries in rstcs array + * @rstcs: array of struct reset_control_bulk_data with reset line names set + * + * Managed reset_control_bulk_optional_get_exclusive_released(). For reset + * controllers returned from this function, reset_control_put() is called + * automatically on driver detach. + * + * See reset_control_bulk_optional_get_exclusive_released() for more information. + */ +static inline int __must_check +devm_reset_control_bulk_get_optional_exclusive_released(struct device *dev, int num_rstcs, + struct reset_control_bulk_data *rstcs) +{ + return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, false, true, false); +} + /** * devm_reset_control_get_shared - resource managed reset_control_get_shared() * @dev: device to be reset by the controller @@ -396,6 +615,26 @@ static inline struct reset_control *devm_reset_control_get_shared( return __devm_reset_control_get(dev, id, 0, true, false, false); }
+/** + * devm_reset_control_bulk_get_shared - resource managed + * reset_control_bulk_get_shared() + * @dev: device to be reset by the controller + * @num_rstcs: number of entries in rstcs array + * @rstcs: array of struct reset_control_bulk_data with reset line names set + * + * Managed reset_control_bulk_get_shared(). For reset controllers returned + * from this function, reset_control_put() is called automatically on driver + * detach. + * + * See reset_control_bulk_get_shared() for more information. + */ +static inline int __must_check +devm_reset_control_bulk_get_shared(struct device *dev, int num_rstcs, + struct reset_control_bulk_data *rstcs) +{ + return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, true, false, false); +} + /** * devm_reset_control_get_optional_exclusive - resource managed * reset_control_get_optional_exclusive() @@ -414,6 +653,26 @@ static inline struct reset_control *devm_reset_control_get_optional_exclusive( return __devm_reset_control_get(dev, id, 0, false, true, true); }
+/** + * devm_reset_control_bulk_get_optional_exclusive - resource managed + * reset_control_bulk_get_optional_exclusive() + * @dev: device to be reset by the controller + * @num_rstcs: number of entries in rstcs array + * @rstcs: array of struct reset_control_bulk_data with reset line names set + * + * Managed reset_control_bulk_get_optional_exclusive(). For reset controllers + * returned from this function, reset_control_put() is called automatically on + * driver detach. + * + * See reset_control_bulk_get_optional_exclusive() for more information. + */ +static inline int __must_check +devm_reset_control_bulk_get_optional_exclusive(struct device *dev, int num_rstcs, + struct reset_control_bulk_data *rstcs) +{ + return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, true, false, true); +} + /** * devm_reset_control_get_optional_shared - resource managed * reset_control_get_optional_shared() @@ -432,6 +691,26 @@ static inline struct reset_control *devm_reset_control_get_optional_shared( return __devm_reset_control_get(dev, id, 0, true, true, false); }
+/** + * devm_reset_control_bulk_get_optional_shared - resource managed + * reset_control_bulk_get_optional_shared() + * @dev: device to be reset by the controller + * @num_rstcs: number of entries in rstcs array + * @rstcs: array of struct reset_control_bulk_data with reset line names set + * + * Managed reset_control_bulk_get_optional_shared(). For reset controllers + * returned from this function, reset_control_put() is called automatically on + * driver detach. + * + * See reset_control_bulk_get_optional_shared() for more information. + */ +static inline int __must_check +devm_reset_control_bulk_get_optional_shared(struct device *dev, int num_rstcs, + struct reset_control_bulk_data *rstcs) +{ + return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, true, true, false); +} + /** * devm_reset_control_get_exclusive_by_index - resource managed * reset_control_get_exclusive()
Hi Dmitry,
I love your patch! Perhaps something to improve:
[auto build test WARNING on pza/reset/next] [also build test WARNING on asoc/for-next linus/master v5.12-rc2 next-20210311] [cannot apply to tegra/for-next] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch]
url: https://github.com/0day-ci/linux/commits/Dmitry-Osipenko/Add-missing-reset-c... base: https://git.pengutronix.de/git/pza/linux reset/next config: m68k-defconfig (attached as .config) compiler: m68k-linux-gcc (GCC) 9.3.0 reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # https://github.com/0day-ci/linux/commit/082cad3274c4566ac97502fd137479791c31... git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Dmitry-Osipenko/Add-missing-reset-controls-to-NVIDIA-Tegra-ASoC-drivers/20210311-231938 git checkout 082cad3274c4566ac97502fd137479791c318300 # save the attached .config to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=m68k
If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot lkp@intel.com
All warnings (new ones prefixed by >>):
In file included from drivers/net/phy/mdio_bus.c:30: include/linux/reset.h: In function 'reset_control_bulk_get_exclusive':
include/linux/reset.h:215:9: warning: returning 'struct reset_control *' from a function with return type 'int' makes integer from pointer without a cast [-Wint-conversion]
215 | return __reset_control_bulk_get(dev, num_rstcs, rstcs, false, false, true); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/reset.h: In function 'reset_control_bulk_get_exclusive_released': include/linux/reset.h:257:9: warning: returning 'struct reset_control *' from a function with return type 'int' makes integer from pointer without a cast [-Wint-conversion] 257 | return __reset_control_bulk_get(dev, num_rstcs, rstcs, false, false, false); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/reset.h: In function 'reset_control_bulk_get_optional_exclusive_released': include/linux/reset.h:278:9: warning: returning 'struct reset_control *' from a function with return type 'int' makes integer from pointer without a cast [-Wint-conversion] 278 | return __reset_control_bulk_get(dev, num_rstcs, rstcs, false, true, false); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/reset.h: In function 'reset_control_bulk_get_shared': include/linux/reset.h:323:9: warning: returning 'struct reset_control *' from a function with return type 'int' makes integer from pointer without a cast [-Wint-conversion] 323 | return __reset_control_bulk_get(dev, num_rstcs, rstcs, true, false, false); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/reset.h: In function 'reset_control_bulk_get_optional_exclusive': include/linux/reset.h:360:9: warning: returning 'struct reset_control *' from a function with return type 'int' makes integer from pointer without a cast [-Wint-conversion] 360 | return __reset_control_bulk_get(dev, num_rstcs, rstcs, false, true, true); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/reset.h: In function 'reset_control_bulk_get_optional_shared': include/linux/reset.h:397:9: warning: returning 'struct reset_control *' from a function with return type 'int' makes integer from pointer without a cast [-Wint-conversion] 397 | return __reset_control_bulk_get(dev, num_rstcs, rstcs, true, true, false); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/reset.h: In function 'devm_reset_control_bulk_get_exclusive': include/linux/reset.h:522:9: warning: returning 'struct reset_control *' from a function with return type 'int' makes integer from pointer without a cast [-Wint-conversion] 522 | return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, false, false, true); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/reset.h: In function 'devm_reset_control_bulk_get_exclusive_released': include/linux/reset.h:561:9: warning: returning 'struct reset_control *' from a function with return type 'int' makes integer from pointer without a cast [-Wint-conversion] 561 | return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, false, false, false); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/reset.h: In function 'devm_reset_control_bulk_get_optional_exclusive_released': include/linux/reset.h:600:9: warning: returning 'struct reset_control *' from a function with return type 'int' makes integer from pointer without a cast [-Wint-conversion] 600 | return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, false, true, false); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/reset.h: In function 'devm_reset_control_bulk_get_shared': include/linux/reset.h:635:9: warning: returning 'struct reset_control *' from a function with return type 'int' makes integer from pointer without a cast [-Wint-conversion] 635 | return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, true, false, false); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/reset.h: In function 'devm_reset_control_bulk_get_optional_exclusive': include/linux/reset.h:673:9: warning: returning 'struct reset_control *' from a function with return type 'int' makes integer from pointer without a cast [-Wint-conversion] 673 | return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, true, false, true); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/reset.h: In function 'devm_reset_control_bulk_get_optional_shared': include/linux/reset.h:711:9: warning: returning 'struct reset_control *' from a function with return type 'int' makes integer from pointer without a cast [-Wint-conversion] 711 | return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, true, true, false); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
vim +215 include/linux/reset.h
200 201 /** 202 * reset_control_bulk_get_exclusive - Lookup and obtain exclusive references to 203 * multiple reset controllers. 204 * @dev: device to be reset by the controller 205 * @num_rstcs: number of entries in rstcs array 206 * @rstcs: array of struct reset_control_bulk_data with reset line names set 207 * 208 * Fills the rstcs array with pointers to exclusive reset controls and 209 * returns 0, or an IS_ERR() condition containing errno. 210 */ 211 static inline int __must_check 212 reset_control_bulk_get_exclusive(struct device *dev, int num_rstcs, 213 struct reset_control_bulk_data *rstcs) 214 {
215 return __reset_control_bulk_get(dev, num_rstcs, rstcs, false, false, true);
216 } 217
--- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
11.03.2021 19:32, kernel test robot пишет:
Hi Dmitry,
I love your patch! Perhaps something to improve:
[auto build test WARNING on pza/reset/next] [also build test WARNING on asoc/for-next linus/master v5.12-rc2 next-20210311] [cannot apply to tegra/for-next] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch]
url: https://github.com/0day-ci/linux/commits/Dmitry-Osipenko/Add-missing-reset-c... base: https://git.pengutronix.de/git/pza/linux reset/next config: m68k-defconfig (attached as .config) compiler: m68k-linux-gcc (GCC) 9.3.0 reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # https://github.com/0day-ci/linux/commit/082cad3274c4566ac97502fd137479791c31... git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Dmitry-Osipenko/Add-missing-reset-controls-to-NVIDIA-Tegra-ASoC-drivers/20210311-231938 git checkout 082cad3274c4566ac97502fd137479791c318300 # save the attached .config to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=m68k
If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot lkp@intel.com
All warnings (new ones prefixed by >>):
In file included from drivers/net/phy/mdio_bus.c:30: include/linux/reset.h: In function 'reset_control_bulk_get_exclusive':
include/linux/reset.h:215:9: warning: returning 'struct reset_control *' from a function with return type 'int' makes integer from pointer without a cast [-Wint-conversion]
215 | return __reset_control_bulk_get(dev, num_rstcs, rstcs, false, false, true); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/reset.h: In function 'reset_control_bulk_get_exclusive_released': include/linux/reset.h:257:9: warning: returning 'struct reset_control *' from a function with return type 'int' makes integer from pointer without a cast [-Wint-conversion] 257 | return __reset_control_bulk_get(dev, num_rstcs, rstcs, false, false, false); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/reset.h: In function 'reset_control_bulk_get_optional_exclusive_released': include/linux/reset.h:278:9: warning: returning 'struct reset_control *' from a function with return type 'int' makes integer from pointer without a cast [-Wint-conversion] 278 | return __reset_control_bulk_get(dev, num_rstcs, rstcs, false, true, false); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/reset.h: In function 'reset_control_bulk_get_shared': include/linux/reset.h:323:9: warning: returning 'struct reset_control *' from a function with return type 'int' makes integer from pointer without a cast [-Wint-conversion] 323 | return __reset_control_bulk_get(dev, num_rstcs, rstcs, true, false, false); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/reset.h: In function 'reset_control_bulk_get_optional_exclusive': include/linux/reset.h:360:9: warning: returning 'struct reset_control *' from a function with return type 'int' makes integer from pointer without a cast [-Wint-conversion] 360 | return __reset_control_bulk_get(dev, num_rstcs, rstcs, false, true, true); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/reset.h: In function 'reset_control_bulk_get_optional_shared': include/linux/reset.h:397:9: warning: returning 'struct reset_control *' from a function with return type 'int' makes integer from pointer without a cast [-Wint-conversion] 397 | return __reset_control_bulk_get(dev, num_rstcs, rstcs, true, true, false); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/reset.h: In function 'devm_reset_control_bulk_get_exclusive': include/linux/reset.h:522:9: warning: returning 'struct reset_control *' from a function with return type 'int' makes integer from pointer without a cast [-Wint-conversion] 522 | return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, false, false, true); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/reset.h: In function 'devm_reset_control_bulk_get_exclusive_released': include/linux/reset.h:561:9: warning: returning 'struct reset_control *' from a function with return type 'int' makes integer from pointer without a cast [-Wint-conversion] 561 | return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, false, false, false); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/reset.h: In function 'devm_reset_control_bulk_get_optional_exclusive_released': include/linux/reset.h:600:9: warning: returning 'struct reset_control *' from a function with return type 'int' makes integer from pointer without a cast [-Wint-conversion] 600 | return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, false, true, false); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/reset.h: In function 'devm_reset_control_bulk_get_shared': include/linux/reset.h:635:9: warning: returning 'struct reset_control *' from a function with return type 'int' makes integer from pointer without a cast [-Wint-conversion] 635 | return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, true, false, false); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/reset.h: In function 'devm_reset_control_bulk_get_optional_exclusive': include/linux/reset.h:673:9: warning: returning 'struct reset_control *' from a function with return type 'int' makes integer from pointer without a cast [-Wint-conversion] 673 | return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, true, false, true); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/reset.h: In function 'devm_reset_control_bulk_get_optional_shared': include/linux/reset.h:711:9: warning: returning 'struct reset_control *' from a function with return type 'int' makes integer from pointer without a cast [-Wint-conversion] 711 | return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, true, true, false); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
vim +215 include/linux/reset.h
200 201 /** 202 * reset_control_bulk_get_exclusive - Lookup and obtain exclusive references to 203 * multiple reset controllers. 204 * @dev: device to be reset by the controller 205 * @num_rstcs: number of entries in rstcs array 206 * @rstcs: array of struct reset_control_bulk_data with reset line names set 207 * 208 * Fills the rstcs array with pointers to exclusive reset controls and 209 * returns 0, or an IS_ERR() condition containing errno. 210 */ 211 static inline int __must_check 212 reset_control_bulk_get_exclusive(struct device *dev, int num_rstcs, 213 struct reset_control_bulk_data *rstcs) 214 {
215 return __reset_control_bulk_get(dev, num_rstcs, rstcs, false, false, true);
216 } 217
0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
I missed to check the !CONFIG_RESET_CONTROLLER case, will make a v3.
Hi Dmitry,
I love your patch! Perhaps something to improve:
[auto build test WARNING on pza/reset/next] [also build test WARNING on asoc/for-next linus/master v5.12-rc2 next-20210311] [cannot apply to tegra/for-next] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch]
url: https://github.com/0day-ci/linux/commits/Dmitry-Osipenko/Add-missing-reset-c... base: https://git.pengutronix.de/git/pza/linux reset/next config: x86_64-randconfig-a011-20210311 (attached as .config) compiler: clang version 13.0.0 (https://github.com/llvm/llvm-project 574a9dabc63ba1e7a04c08d4bde2eacd61b44ce1) reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # install x86_64 cross compiling tool for clang build # apt-get install binutils-x86-64-linux-gnu # https://github.com/0day-ci/linux/commit/082cad3274c4566ac97502fd137479791c31... git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Dmitry-Osipenko/Add-missing-reset-controls-to-NVIDIA-Tegra-ASoC-drivers/20210311-231938 git checkout 082cad3274c4566ac97502fd137479791c318300 # save the attached .config to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=x86_64
If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot lkp@intel.com
All warnings (new ones prefixed by >>):
drivers/reset/core.c:1013:6: warning: no previous prototype for function 'reset_control_bulk_put' [-Wmissing-prototypes]
void reset_control_bulk_put(int num_rstcs, struct reset_control_bulk_data *rstcs) ^ drivers/reset/core.c:1013:1: note: declare 'static' if the function is not intended to be used outside of this translation unit void reset_control_bulk_put(int num_rstcs, struct reset_control_bulk_data *rstcs) ^ static 1 warning generated.
vim +/reset_control_bulk_put +1013 drivers/reset/core.c
1007 1008 /** 1009 * reset_control_bulk_put - free the reset controllers 1010 * @num_rstcs: number of entries in rstcs array 1011 * @rstcs: array of struct reset_control_bulk_data with reset controls set 1012 */
1013 void reset_control_bulk_put(int num_rstcs, struct reset_control_bulk_data *rstcs)
1014 { 1015 mutex_lock(&reset_list_mutex); 1016 while (num_rstcs--) { 1017 if (IS_ERR_OR_NULL(rstcs[num_rstcs].rstc)) 1018 continue; 1019 __reset_control_put_internal(rstcs[num_rstcs].rstc); 1020 } 1021 mutex_unlock(&reset_list_mutex); 1022 } 1023 EXPORT_SYMBOL_GPL(reset_control_bulk_put); 1024
--- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
Switch to use reset-bulk API in order to make code cleaner.
Signed-off-by: Dmitry Osipenko digetx@gmail.com --- sound/soc/tegra/tegra30_ahub.c | 104 ++++++++++++--------------------- sound/soc/tegra/tegra30_ahub.h | 5 +- sound/soc/tegra/tegra30_i2s.c | 1 + 3 files changed, 40 insertions(+), 70 deletions(-)
diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c index 9ef05ca4f6c4..d24c26f4960d 100644 --- a/sound/soc/tegra/tegra30_ahub.c +++ b/sound/soc/tegra/tegra30_ahub.c @@ -65,7 +65,7 @@ static int tegra30_ahub_runtime_resume(struct device *dev) { int ret;
- ret = reset_control_assert(ahub->reset); + ret = reset_control_bulk_assert(ahub->nresets, ahub->resets); if (ret) return ret;
@@ -75,7 +75,7 @@ static int tegra30_ahub_runtime_resume(struct device *dev)
usleep_range(10, 100);
- ret = reset_control_deassert(ahub->reset); + ret = reset_control_bulk_deassert(ahub->nresets, ahub->resets); if (ret) goto disable_clocks;
@@ -339,41 +339,28 @@ int tegra30_ahub_unset_rx_cif_source(enum tegra30_ahub_rxcif rxcif) } EXPORT_SYMBOL_GPL(tegra30_ahub_unset_rx_cif_source);
-#define MOD_LIST_MASK_TEGRA30 BIT(0) -#define MOD_LIST_MASK_TEGRA114 BIT(1) -#define MOD_LIST_MASK_TEGRA124 BIT(2) - -#define MOD_LIST_MASK_TEGRA30_OR_LATER \ - (MOD_LIST_MASK_TEGRA30 | MOD_LIST_MASK_TEGRA114 | \ - MOD_LIST_MASK_TEGRA124) -#define MOD_LIST_MASK_TEGRA114_OR_LATER \ - (MOD_LIST_MASK_TEGRA114 | MOD_LIST_MASK_TEGRA124) - -static const struct { - const char *rst_name; - u32 mod_list_mask; -} configlink_mods[] = { - { "d_audio", MOD_LIST_MASK_TEGRA30_OR_LATER }, - { "apbif", MOD_LIST_MASK_TEGRA30_OR_LATER }, - { "i2s0", MOD_LIST_MASK_TEGRA30_OR_LATER }, - { "i2s1", MOD_LIST_MASK_TEGRA30_OR_LATER }, - { "i2s2", MOD_LIST_MASK_TEGRA30_OR_LATER }, - { "i2s3", MOD_LIST_MASK_TEGRA30_OR_LATER }, - { "i2s4", MOD_LIST_MASK_TEGRA30_OR_LATER }, - { "dam0", MOD_LIST_MASK_TEGRA30_OR_LATER }, - { "dam1", MOD_LIST_MASK_TEGRA30_OR_LATER }, - { "dam2", MOD_LIST_MASK_TEGRA30_OR_LATER }, - { "spdif", MOD_LIST_MASK_TEGRA30_OR_LATER }, - { "amx", MOD_LIST_MASK_TEGRA114_OR_LATER }, - { "adx", MOD_LIST_MASK_TEGRA114_OR_LATER }, - { "amx1", MOD_LIST_MASK_TEGRA124 }, - { "adx1", MOD_LIST_MASK_TEGRA124 }, - { "afc0", MOD_LIST_MASK_TEGRA124 }, - { "afc1", MOD_LIST_MASK_TEGRA124 }, - { "afc2", MOD_LIST_MASK_TEGRA124 }, - { "afc3", MOD_LIST_MASK_TEGRA124 }, - { "afc4", MOD_LIST_MASK_TEGRA124 }, - { "afc5", MOD_LIST_MASK_TEGRA124 }, +static const struct reset_control_bulk_data tegra30_ahub_resets_data[] = { + { "d_audio" }, + { "apbif" }, + { "i2s0" }, + { "i2s1" }, + { "i2s2" }, + { "i2s3" }, + { "i2s4" }, + { "dam0" }, + { "dam1" }, + { "dam2" }, + { "spdif" }, + { "amx" }, /* Tegra114+ */ + { "adx" }, /* Tegra114+ */ + { "amx1" }, /* Tegra124 */ + { "adx1" }, /* Tegra124 */ + { "afc0" }, /* Tegra124 */ + { "afc1" }, /* Tegra124 */ + { "afc2" }, /* Tegra124 */ + { "afc3" }, /* Tegra124 */ + { "afc4" }, /* Tegra124 */ + { "afc5" }, /* Tegra124 */ };
#define LAST_REG(name) \ @@ -502,17 +489,17 @@ static const struct regmap_config tegra30_ahub_ahub_regmap_config = { };
static struct tegra30_ahub_soc_data soc_data_tegra30 = { - .mod_list_mask = MOD_LIST_MASK_TEGRA30, + .num_resets = 11, .set_audio_cif = tegra30_ahub_set_cif, };
static struct tegra30_ahub_soc_data soc_data_tegra114 = { - .mod_list_mask = MOD_LIST_MASK_TEGRA114, + .num_resets = 13, .set_audio_cif = tegra30_ahub_set_cif, };
static struct tegra30_ahub_soc_data soc_data_tegra124 = { - .mod_list_mask = MOD_LIST_MASK_TEGRA124, + .num_resets = 21, .set_audio_cif = tegra124_ahub_set_cif, };
@@ -527,8 +514,6 @@ static int tegra30_ahub_probe(struct platform_device *pdev) { const struct of_device_id *match; const struct tegra30_ahub_soc_data *soc_data; - struct reset_control *rst; - int i; struct resource *res0; void __iomem *regs_apbif, *regs_ahub; int ret = 0; @@ -541,34 +526,16 @@ static int tegra30_ahub_probe(struct platform_device *pdev) return -EINVAL; soc_data = match->data;
- /* - * The AHUB hosts a register bus: the "configlink". For this to - * operate correctly, all devices on this bus must be out of reset. - */ - for (i = 0; i < ARRAY_SIZE(configlink_mods); i++) { - if (!(configlink_mods[i].mod_list_mask & - soc_data->mod_list_mask)) - continue; - - rst = reset_control_get_exclusive(&pdev->dev, - configlink_mods[i].rst_name); - if (IS_ERR(rst)) { - dev_err(&pdev->dev, "Can't get reset %s\n", - configlink_mods[i].rst_name); - ret = PTR_ERR(rst); - return ret; - } - - /* just check presence of the reset control in DT */ - reset_control_put(rst); - } - ahub = devm_kzalloc(&pdev->dev, sizeof(struct tegra30_ahub), GFP_KERNEL); if (!ahub) return -ENOMEM; dev_set_drvdata(&pdev->dev, ahub);
+ BUILD_BUG_ON(sizeof(ahub->resets) != sizeof(tegra30_ahub_resets_data)); + memcpy(ahub->resets, tegra30_ahub_resets_data, sizeof(ahub->resets)); + + ahub->nresets = soc_data->num_resets; ahub->soc_data = soc_data; ahub->dev = &pdev->dev;
@@ -579,10 +546,11 @@ static int tegra30_ahub_probe(struct platform_device *pdev) if (ret) return ret;
- ahub->reset = devm_reset_control_array_get_exclusive(&pdev->dev); - if (IS_ERR(ahub->reset)) { - dev_err(&pdev->dev, "Can't get resets: %pe\n", ahub->reset); - return PTR_ERR(ahub->reset); + ret = devm_reset_control_bulk_get_exclusive(&pdev->dev, ahub->nresets, + ahub->resets); + if (ret) { + dev_err(&pdev->dev, "Can't get resets: %d\n", ret); + return ret; }
res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0); diff --git a/sound/soc/tegra/tegra30_ahub.h b/sound/soc/tegra/tegra30_ahub.h index 3b85244f87f1..c9eaf4ec8f6e 100644 --- a/sound/soc/tegra/tegra30_ahub.h +++ b/sound/soc/tegra/tegra30_ahub.h @@ -491,7 +491,7 @@ void tegra124_ahub_set_cif(struct regmap *regmap, unsigned int reg, struct tegra30_ahub_cif_conf *conf);
struct tegra30_ahub_soc_data { - u32 mod_list_mask; + unsigned int num_resets; void (*set_audio_cif)(struct regmap *regmap, unsigned int reg, struct tegra30_ahub_cif_conf *conf); @@ -511,7 +511,8 @@ struct tegra30_ahub_soc_data { struct tegra30_ahub { const struct tegra30_ahub_soc_data *soc_data; struct device *dev; - struct reset_control *reset; + struct reset_control_bulk_data resets[21]; + unsigned int nresets; struct clk_bulk_data clocks[2]; unsigned int nclocks; resource_size_t apbif_addr; diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c index 3d22c1be6f3d..614b67be1dd9 100644 --- a/sound/soc/tegra/tegra30_i2s.c +++ b/sound/soc/tegra/tegra30_i2s.c @@ -23,6 +23,7 @@ #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/regmap.h> +#include <linux/reset.h> #include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h>
participants (2)
-
Dmitry Osipenko
-
kernel test robot