[PATCH v3 9/9] reset: amlogic: add auxiliary reset driver support

Neil Armstrong neil.armstrong at linaro.org
Mon Aug 19 09:35:23 PDT 2024


On 08/08/2024 12:27, 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


I thing the header name should be include/soc/amlogic/reset-meson-aux.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"
> +	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 ea4fc562f7e6..774902527d17 100644
> --- a/drivers/reset/amlogic/reset-meson-core.c
> +++ b/drivers/reset/amlogic/reset-meson-core.c
> @@ -85,12 +85,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)
> @@ -105,7 +126,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 */




More information about the linux-amlogic mailing list