Unverified Commit f51df260 authored by Arnd Bergmann's avatar Arnd Bergmann
Browse files

Merge tag 'reset-for-v6.14-2' of git://git.pengutronix.de/pza/linux into soc/drivers

Reset controller updates for v6.14 (v2)

* Add support for A1 SoC in amlogic reset driver.
* Drop aux registration helper from amlogic reset driver.

* tag 'reset-for-v6.14-2' of git://git.pengutronix.de/pza/linux:
  reset: amlogic: aux: drop aux registration helper
  reset: amlogic: aux: get regmap through parent device
  reset: amlogic: add support for A1 SoC in auxiliary reset driver
  dt-bindings: reset: add bindings for A1 SoC audio reset controller
  clk: amlogic: axg-audio: revert reset implementation
  Revert "clk: Fix invalid execution of clk_set_rate"

Link: https://lore.kernel.org/r/20250115170247.1303656-1-p.zabel@pengutronix.de


Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
parents 677184d6 72bb8275
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -2530,7 +2530,7 @@ static int clk_core_set_rate_nolock(struct clk_core *core,
	rate = clk_core_req_round_rate_nolock(core, req_rate);

	/* bail early if nothing to do */
	if (rate == clk_core_get_rate_recalc(core))
	if (rate == clk_core_get_rate_nolock(core))
		return 0;

	/* fail on a direct rate set of a protected provider */
+1 −1
Original line number Diff line number Diff line
@@ -106,7 +106,7 @@ config COMMON_CLK_AXG_AUDIO
	select COMMON_CLK_MESON_SCLK_DIV
	select COMMON_CLK_MESON_CLKC_UTILS
	select REGMAP_MMIO
	depends on RESET_MESON_AUX
	select RESET_CONTROLLER
	help
	  Support for the audio clock controller on AmLogic A113D devices,
	  aka axg, Say Y if you want audio subsystem to work.
+100 −9
Original line number Diff line number Diff line
@@ -15,8 +15,6 @@
#include <linux/reset-controller.h>
#include <linux/slab.h>

#include <soc/amlogic/reset-meson-aux.h>

#include "meson-clkc-utils.h"
#include "axg-audio.h"
#include "clk-regmap.h"
@@ -1680,6 +1678,84 @@ static struct clk_regmap *const sm1_clk_regmaps[] = {
	&sm1_earcrx_dmac_clk,
};

struct axg_audio_reset_data {
	struct reset_controller_dev rstc;
	struct regmap *map;
	unsigned int offset;
};

static void axg_audio_reset_reg_and_bit(struct axg_audio_reset_data *rst,
					unsigned long id,
					unsigned int *reg,
					unsigned int *bit)
{
	unsigned int stride = regmap_get_reg_stride(rst->map);

	*reg = (id / (stride * BITS_PER_BYTE)) * stride;
	*reg += rst->offset;
	*bit = id % (stride * BITS_PER_BYTE);
}

static int axg_audio_reset_update(struct reset_controller_dev *rcdev,
				unsigned long id, bool assert)
{
	struct axg_audio_reset_data *rst =
		container_of(rcdev, struct axg_audio_reset_data, rstc);
	unsigned int offset, bit;

	axg_audio_reset_reg_and_bit(rst, id, &offset, &bit);

	regmap_update_bits(rst->map, offset, BIT(bit),
			assert ? BIT(bit) : 0);

	return 0;
}

static int axg_audio_reset_status(struct reset_controller_dev *rcdev,
				unsigned long id)
{
	struct axg_audio_reset_data *rst =
		container_of(rcdev, struct axg_audio_reset_data, rstc);
	unsigned int val, offset, bit;

	axg_audio_reset_reg_and_bit(rst, id, &offset, &bit);

	regmap_read(rst->map, offset, &val);

	return !!(val & BIT(bit));
}

static int axg_audio_reset_assert(struct reset_controller_dev *rcdev,
				unsigned long id)
{
	return axg_audio_reset_update(rcdev, id, true);
}

static int axg_audio_reset_deassert(struct reset_controller_dev *rcdev,
				unsigned long id)
{
	return axg_audio_reset_update(rcdev, id, false);
}

static int axg_audio_reset_toggle(struct reset_controller_dev *rcdev,
				unsigned long id)
{
	int ret;

	ret = axg_audio_reset_assert(rcdev, id);
	if (ret)
		return ret;

	return axg_audio_reset_deassert(rcdev, id);
}

static const struct reset_control_ops axg_audio_rstc_ops = {
	.assert = axg_audio_reset_assert,
	.deassert = axg_audio_reset_deassert,
	.reset = axg_audio_reset_toggle,
	.status = axg_audio_reset_status,
};

static struct regmap_config axg_audio_regmap_cfg = {
	.reg_bits	= 32,
	.val_bits	= 32,
@@ -1690,14 +1766,16 @@ struct audioclk_data {
	struct clk_regmap *const *regmap_clks;
	unsigned int regmap_clk_num;
	struct meson_clk_hw_data hw_clks;
	unsigned int reset_offset;
	unsigned int reset_num;
	unsigned int max_register;
	const char *rst_drvname;
};

static int axg_audio_clkc_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	const struct audioclk_data *data;
	struct axg_audio_reset_data *rst;
	struct regmap *map;
	void __iomem *regs;
	struct clk_hw *hw;
@@ -1756,11 +1834,22 @@ static int axg_audio_clkc_probe(struct platform_device *pdev)
	if (ret)
		return ret;

	/* Register auxiliary reset driver when applicable */
	if (data->rst_drvname)
		ret = devm_meson_rst_aux_register(dev, map, data->rst_drvname);
	/* Stop here if there is no reset */
	if (!data->reset_num)
		return 0;

	return ret;
	rst = devm_kzalloc(dev, sizeof(*rst), GFP_KERNEL);
	if (!rst)
		return -ENOMEM;

	rst->map = map;
	rst->offset = data->reset_offset;
	rst->rstc.nr_resets = data->reset_num;
	rst->rstc.ops = &axg_audio_rstc_ops;
	rst->rstc.of_node = dev->of_node;
	rst->rstc.owner = THIS_MODULE;

	return devm_reset_controller_register(dev, &rst->rstc);
}

static const struct audioclk_data axg_audioclk_data = {
@@ -1780,8 +1869,9 @@ static const struct audioclk_data g12a_audioclk_data = {
		.hws = g12a_audio_hw_clks,
		.num = ARRAY_SIZE(g12a_audio_hw_clks),
	},
	.reset_offset = AUDIO_SW_RESET,
	.reset_num = 26,
	.max_register = AUDIO_CLK_SPDIFOUT_B_CTRL,
	.rst_drvname = "rst-g12a",
};

static const struct audioclk_data sm1_audioclk_data = {
@@ -1791,8 +1881,9 @@ static const struct audioclk_data sm1_audioclk_data = {
		.hws = sm1_audio_hw_clks,
		.num = ARRAY_SIZE(sm1_audio_hw_clks),
	},
	.reset_offset = AUDIO_SM1_SW_RESET0,
	.reset_num = 39,
	.max_register = AUDIO_EARCRX_DMAC_CLK_CTRL,
	.rst_drvname = "rst-sm1",
};

static const struct of_device_id clkc_match_table[] = {
+21 −76
Original line number Diff line number Diff line
@@ -11,20 +11,20 @@
#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/reset-meson-aux.h>

static DEFINE_IDA(meson_rst_aux_ida);

struct meson_reset_adev {
	struct auxiliary_device adev;
	struct regmap *map;
static const struct meson_reset_param meson_a1_audio_param = {
	.reset_ops	= &meson_reset_toggle_ops,
	.reset_num	= 32,
	.level_offset	= 0x28,
};

#define to_meson_reset_adev(_adev) \
	container_of((_adev), struct meson_reset_adev, adev)
static const struct meson_reset_param meson_a1_audio_vad_param = {
	.reset_ops	= &meson_reset_toggle_ops,
	.reset_num	= 6,
	.level_offset	= 0x8,
};

static const struct meson_reset_param meson_g12a_audio_param = {
	.reset_ops	= &meson_reset_toggle_ops,
@@ -40,6 +40,12 @@ static const struct meson_reset_param meson_sm1_audio_param = {

static const struct auxiliary_device_id meson_reset_aux_ids[] = {
	{
		.name = "a1-audio-clkc.rst-a1",
		.driver_data = (kernel_ulong_t)&meson_a1_audio_param,
	}, {
		.name = "a1-audio-clkc.rst-a1-vad",
		.driver_data = (kernel_ulong_t)&meson_a1_audio_vad_param,
	}, {
		.name = "axg-audio-clkc.rst-g12a",
		.driver_data = (kernel_ulong_t)&meson_g12a_audio_param,
	}, {
@@ -54,10 +60,13 @@ static int meson_reset_aux_probe(struct auxiliary_device *adev,
{
	const struct meson_reset_param *param =
		(const struct meson_reset_param *)(id->driver_data);
	struct meson_reset_adev *raux =
		to_meson_reset_adev(adev);
	struct regmap *map;

	map = dev_get_regmap(adev->dev.parent, NULL);
	if (!map)
		return -EINVAL;

	return meson_reset_controller_register(&adev->dev, raux->map, param);
	return meson_reset_controller_register(&adev->dev, map, param);
}

static struct auxiliary_driver meson_reset_aux_driver = {
@@ -66,70 +75,6 @@ static struct auxiliary_driver meson_reset_aux_driver = {
};
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@baylibre.com>");
MODULE_LICENSE("Dual BSD/GPL");
+36 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
/*
 * Copyright (c) 2024, SaluteDevices. All Rights Reserved.
 *
 * Author: Jan Dakinevich <jan.dakinevich@salutedevices.com>
 */

#ifndef _DT_BINDINGS_AMLOGIC_MESON_A1_AUDIO_RESET_H
#define _DT_BINDINGS_AMLOGIC_MESON_A1_AUDIO_RESET_H

#define AUD_RESET_DDRARB	0
#define AUD_RESET_TDMIN_A	1
#define AUD_RESET_TDMIN_B	2
#define AUD_RESET_TDMIN_LB	3
#define AUD_RESET_LOOPBACK	4
#define AUD_RESET_TDMOUT_A	5
#define AUD_RESET_TDMOUT_B	6
#define AUD_RESET_FRDDR_A	7
#define AUD_RESET_FRDDR_B	8
#define AUD_RESET_TODDR_A	9
#define AUD_RESET_TODDR_B	10
#define AUD_RESET_SPDIFIN	11
#define AUD_RESET_RESAMPLE	12
#define AUD_RESET_EQDRC		13
#define AUD_RESET_LOCKER	14
#define AUD_RESET_TOACODEC	30
#define AUD_RESET_CLKTREE	31

#define AUD_VAD_RESET_DDRARB	0
#define AUD_VAD_RESET_PDM	1
#define AUD_VAD_RESET_TDMIN_VAD	2
#define AUD_VAD_RESET_TODDR_VAD	3
#define AUD_VAD_RESET_TOVAD	4
#define AUD_VAD_RESET_CLKTREE	5

#endif /* _DT_BINDINGS_AMLOGIC_MESON_A1_AUDIO_RESET_H */
Loading