[PATCH v2 9/9] reset: amlogic: add auxiliary reset driver support
Jan Dakinevich
jan.dakinevich at salutedevices.com
Tue Jul 23 18:18:51 PDT 2024
On 7/18/24 12:57, Jerome Brunet wrote:
> Add support for the reset controller present in the audio clock
> controller of the g12 and sm1 SoC families, using the auxiliary bus.
>
> This is expected to replace the driver currently present directly
> within the related clock driver.
>
> Signed-off-by: Jerome Brunet <jbrunet at baylibre.com>
> ---
> drivers/reset/amlogic/Kconfig | 8 ++
> drivers/reset/amlogic/Makefile | 1 +
> drivers/reset/amlogic/reset-meson-aux.c | 136 ++++++++++++++++++++
> drivers/reset/amlogic/reset-meson-core.c | 25 +++-
> drivers/reset/amlogic/reset-meson-pltf.c | 3 +
> drivers/reset/amlogic/reset-meson.h | 4 +
> include/soc/amlogic/meson-auxiliary-reset.h | 23 ++++
> 7 files changed, 198 insertions(+), 2 deletions(-)
> create mode 100644 drivers/reset/amlogic/reset-meson-aux.c
> create mode 100644 include/soc/amlogic/meson-auxiliary-reset.h
>
> diff --git a/drivers/reset/amlogic/Kconfig b/drivers/reset/amlogic/Kconfig
> index 04c7be0f3165..ee1c7620a2b1 100644
> --- a/drivers/reset/amlogic/Kconfig
> +++ b/drivers/reset/amlogic/Kconfig
> @@ -11,6 +11,14 @@ config RESET_MESON
> help
> This enables the reset platform driver for Amlogic SoCs.
>
> +config RESET_MESON_AUX
> + tristate "Meson Reset Platform Driver"
Is it correct? I suppose you mean "... Auxiliary Driver", because there
is another "Meson Reset Platform Driver" several lines above.
> + depends on ARCH_MESON || COMPILE_TEST
> + select AUXILIARY_BUS
> + select RESET_MESON_CORE
> + help
> + This enables the reset auxiliary driver for Amlogic SoCs.
> +
> config RESET_MESON_AUDIO_ARB
> tristate "Meson Audio Memory Arbiter Reset Driver"
> depends on ARCH_MESON || COMPILE_TEST
> diff --git a/drivers/reset/amlogic/Makefile b/drivers/reset/amlogic/Makefile
> index 0f8f9121b566..5d53a4b11ed9 100644
> --- a/drivers/reset/amlogic/Makefile
> +++ b/drivers/reset/amlogic/Makefile
> @@ -1,3 +1,4 @@
> obj-$(CONFIG_RESET_MESON) += reset-meson-pltf.o
> +obj-$(CONFIG_RESET_MESON_AUX) += reset-meson-aux.o
> obj-$(CONFIG_RESET_MESON_CORE) += reset-meson-core.o
> obj-$(CONFIG_RESET_MESON_AUDIO_ARB) += reset-meson-audio-arb.o
> diff --git a/drivers/reset/amlogic/reset-meson-aux.c b/drivers/reset/amlogic/reset-meson-aux.c
> new file mode 100644
> index 000000000000..caf26eb67c14
> --- /dev/null
> +++ b/drivers/reset/amlogic/reset-meson-aux.c
> @@ -0,0 +1,136 @@
> +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
> +/*
> + * Amlogic Meson Reset Auxiliary driver
> + *
> + * Copyright (c) 2024 BayLibre, SAS.
> + * Author: Jerome Brunet <jbrunet at baylibre.com>
> + */
> +
> +#include <linux/err.h>
> +#include <linux/module.h>
> +#include <linux/auxiliary_bus.h>
> +#include <linux/regmap.h>
> +#include <linux/reset-controller.h>
> +#include <linux/slab.h>
> +
> +#include "reset-meson.h"
> +#include <soc/amlogic/meson-auxiliary-reset.h>
> +
> +static DEFINE_IDA(meson_rst_aux_ida);
> +
> +struct meson_reset_adev {
> + struct auxiliary_device adev;
> + struct regmap *map;
> +};
> +
> +#define to_meson_reset_adev(_adev) \
> + container_of((_adev), struct meson_reset_adev, adev)
> +
> +static const struct meson_reset_param meson_g12a_audio_param = {
> + .reset_ops = &meson_reset_toggle_ops,
> + .reset_num = 26,
> + .level_offset = 0x24,
> +};
> +
> +static const struct meson_reset_param meson_sm1_audio_param = {
> + .reset_ops = &meson_reset_toggle_ops,
> + .reset_num = 39,
> + .level_offset = 0x28,
> +};
> +
> +static const struct auxiliary_device_id meson_reset_aux_ids[] = {
> + {
> + .name = "axg-audio-clkc.rst-g12a",
> + .driver_data = (kernel_ulong_t)&meson_g12a_audio_param,
> + }, {
> + .name = "axg-audio-clkc.rst-sm1",
> + .driver_data = (kernel_ulong_t)&meson_sm1_audio_param,
> + }, {}
> +};
> +MODULE_DEVICE_TABLE(auxiliary, meson_reset_aux_ids);
> +
> +static int meson_reset_aux_probe(struct auxiliary_device *adev,
> + const struct auxiliary_device_id *id)
> +{
> + const struct meson_reset_param *param =
> + (const struct meson_reset_param *)(id->driver_data);
> + struct meson_reset_adev *raux =
> + to_meson_reset_adev(adev);
> +
> + return meson_reset_probe(&adev->dev, raux->map, param);
> +}
> +
> +static struct auxiliary_driver meson_reset_aux_driver = {
> + .probe = meson_reset_aux_probe,
> + .id_table = meson_reset_aux_ids,
> +};
> +module_auxiliary_driver(meson_reset_aux_driver);
> +
> +static void meson_rst_aux_release(struct device *dev)
> +{
> + struct auxiliary_device *adev = to_auxiliary_dev(dev);
> + struct meson_reset_adev *raux =
> + to_meson_reset_adev(adev);
> +
> + ida_free(&meson_rst_aux_ida, adev->id);
> + kfree(raux);
> +}
> +
> +static void meson_rst_aux_unregister_adev(void *_adev)
> +{
> + struct auxiliary_device *adev = _adev;
> +
> + auxiliary_device_delete(adev);
> + auxiliary_device_uninit(adev);
> +}
> +
> +int devm_meson_rst_aux_register(struct device *dev,
> + struct regmap *map,
> + const char *adev_name)
> +{
> + struct meson_reset_adev *raux;
> + struct auxiliary_device *adev;
> + int ret;
> +
> + raux = kzalloc(sizeof(*raux), GFP_KERNEL);
> + if (!raux)
> + return -ENOMEM;
> +
> + ret = ida_alloc(&meson_rst_aux_ida, GFP_KERNEL);
> + if (ret < 0)
> + goto raux_free;
> +
> + raux->map = map;
> +
> + adev = &raux->adev;
> + adev->id = ret;
> + adev->name = adev_name;
> + adev->dev.parent = dev;
> + adev->dev.release = meson_rst_aux_release;
> + device_set_of_node_from_dev(&adev->dev, dev);
> +
> + ret = auxiliary_device_init(adev);
> + if (ret)
> + goto ida_free;
> +
> + ret = __auxiliary_device_add(adev, dev->driver->name);
> + if (ret) {
> + auxiliary_device_uninit(adev);
> + return ret;
> + }
> +
> + return devm_add_action_or_reset(dev, meson_rst_aux_unregister_adev,
> + adev);
> +
> +ida_free:
> + ida_free(&meson_rst_aux_ida, adev->id);
> +raux_free:
> + kfree(raux);
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(devm_meson_rst_aux_register);
> +
> +MODULE_DESCRIPTION("Amlogic Meson Reset Auxiliary driver");
> +MODULE_AUTHOR("Jerome Brunet <jbrunet at baylibre.com>");
> +MODULE_LICENSE("Dual BSD/GPL");
> +MODULE_IMPORT_NS(MESON_RESET);
> diff --git a/drivers/reset/amlogic/reset-meson-core.c b/drivers/reset/amlogic/reset-meson-core.c
> index 5e23f3212e6d..1e5883b27c30 100644
> --- a/drivers/reset/amlogic/reset-meson-core.c
> +++ b/drivers/reset/amlogic/reset-meson-core.c
> @@ -86,12 +86,33 @@ static int meson_reset_deassert(struct reset_controller_dev *rcdev,
> return meson_reset_level(rcdev, id, false);
> }
>
> -static const struct reset_control_ops meson_reset_ops = {
> +static int meson_reset_level_toggle(struct reset_controller_dev *rcdev,
> + unsigned long id)
> +{
> + int ret;
> +
> + ret = meson_reset_assert(rcdev, id);
> + if (ret)
> + return ret;
> +
> + return meson_reset_deassert(rcdev, id);
> +}
> +
> +const struct reset_control_ops meson_reset_ops = {
> .reset = meson_reset_reset,
> .assert = meson_reset_assert,
> .deassert = meson_reset_deassert,
> .status = meson_reset_status,
> };
> +EXPORT_SYMBOL_NS_GPL(meson_reset_ops, MESON_RESET);
> +
> +const struct reset_control_ops meson_reset_toggle_ops = {
> + .reset = meson_reset_level_toggle,
> + .assert = meson_reset_assert,
> + .deassert = meson_reset_deassert,
> + .status = meson_reset_status,
> +};
> +EXPORT_SYMBOL_NS_GPL(meson_reset_toggle_ops, MESON_RESET);
>
> int meson_reset_probe(struct device *dev, struct regmap *map,
> const struct meson_reset_param *param)
> @@ -106,7 +127,7 @@ int meson_reset_probe(struct device *dev, struct regmap *map,
> data->map = map;
> data->rcdev.owner = dev->driver->owner;
> data->rcdev.nr_resets = param->reset_num;
> - data->rcdev.ops = &meson_reset_ops;
> + data->rcdev.ops = data->param->reset_ops;
> data->rcdev.of_node = dev->of_node;
>
> return devm_reset_controller_register(dev, &data->rcdev);
> diff --git a/drivers/reset/amlogic/reset-meson-pltf.c b/drivers/reset/amlogic/reset-meson-pltf.c
> index 97e933b4aa34..2bc3ea42c6ec 100644
> --- a/drivers/reset/amlogic/reset-meson-pltf.c
> +++ b/drivers/reset/amlogic/reset-meson-pltf.c
> @@ -16,6 +16,7 @@
> #include "reset-meson.h"
>
> static const struct meson_reset_param meson8b_param = {
> + .reset_ops = &meson_reset_ops,
> .reset_num = 256,
> .reset_offset = 0x0,
> .level_offset = 0x7c,
> @@ -23,6 +24,7 @@ static const struct meson_reset_param meson8b_param = {
> };
>
> static const struct meson_reset_param meson_a1_param = {
> + .reset_ops = &meson_reset_ops,
> .reset_num = 96,
> .reset_offset = 0x0,
> .level_offset = 0x40,
> @@ -30,6 +32,7 @@ static const struct meson_reset_param meson_a1_param = {
> };
>
> static const struct meson_reset_param meson_s4_param = {
> + .reset_ops = &meson_reset_ops,
> .reset_num = 192,
> .reset_offset = 0x0,
> .level_offset = 0x40,
> diff --git a/drivers/reset/amlogic/reset-meson.h b/drivers/reset/amlogic/reset-meson.h
> index c2e8a5cf2e46..5ab2ac9ab2e5 100644
> --- a/drivers/reset/amlogic/reset-meson.h
> +++ b/drivers/reset/amlogic/reset-meson.h
> @@ -12,6 +12,7 @@
> #include <linux/reset-controller.h>
>
> struct meson_reset_param {
> + const struct reset_control_ops *reset_ops;
> unsigned int reset_num;
> unsigned int reset_offset;
> unsigned int level_offset;
> @@ -21,4 +22,7 @@ struct meson_reset_param {
> int meson_reset_probe(struct device *dev, struct regmap *map,
> const struct meson_reset_param *param);
>
> +extern const struct reset_control_ops meson_reset_ops;
> +extern const struct reset_control_ops meson_reset_toggle_ops;
> +
> #endif /* __MESON_RESET_CORE_H */
> diff --git a/include/soc/amlogic/meson-auxiliary-reset.h b/include/soc/amlogic/meson-auxiliary-reset.h
> new file mode 100644
> index 000000000000..f70dd864ef6a
> --- /dev/null
> +++ b/include/soc/amlogic/meson-auxiliary-reset.h
> @@ -0,0 +1,23 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef __SOC_AMLOGIC_MESON_AUX_RESET_H
> +#define __SOC_AMLOGIC_MESON_AUX_RESET_H
> +
> +#include <linux/err.h>
> +
> +struct device;
> +struct regmap;
> +
> +#if IS_ENABLED(CONFIG_RESET_MESON_AUX)
> +int devm_meson_rst_aux_register(struct device *dev,
> + struct regmap *map,
> + const char *adev_name);
> +#else
> +static inline int devm_meson_rst_aux_register(struct device *dev,
> + struct regmap *map,
> + const char *adev_name)
> +{
> + return 0;
> +}
> +#endif
> +
> +#endif /* __SOC_AMLOGIC_MESON_AUX_RESET_H */
--
Best regards
Jan Dakinevich
More information about the linux-amlogic
mailing list