Reset controller updates for v6.14 (v2)
* Add support for A1 SoC in amlogic reset driver. * Drop aux registration helper from amlogic reset driver. -----BEGIN PGP SIGNATURE----- iI0EABYIADUWIQRRO6F6WdpH1R0vGibVhaclGDdiwAUCZ4fp4xcccC56YWJlbEBw ZW5ndXRyb25peC5kZQAKCRDVhaclGDdiwPZeAQC49hnPkGyg3ju+M3ZGxkVVkCUE ytv2GDykOGkM/Dz9AgD+J3x9+L1T2OqhpMc90nhZxMRouWtPJztMLzFqIcTa1Ac= =Mivr -----END PGP SIGNATURE----- gpgsig -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEiK/NIGsWEZVxh/FrYKtH/8kJUicFAmeH6uUACgkQYKtH/8kJ UicJQQ//dKaFiMHfBqbw3edNbsL2/U5rCJmvxRitiKOavMm5w3npH9gl1bi/XZVA H3uiJDum6OBQpRAXHmwltSqNZJKtPumQ2xf6hiX6KRYlxlAyLwJK5RkmOXl7Ccil rCTaqajSWaqadUhZUljRhqcI1dpdFG1Adb4lPoxDxgFYLs/vNeJDBJgI3rIvA8aE XNc+HL4LXSQfo7XKZVwpgti/FAg3uXJqSdN2LLJA/MFjqqXaP1Ky2K5khuqUYY+q bbfEGg62UU199GEkNGzynRO5STpIFwlu/vLtc91a+97/9gYCmD6Y5SNJL4MgEi8K ZQGBGBSHLF2EVSGrW5dKXhcX/Ra4hhKqxNE/AeWMBrvCTehuzF4CpZ1zLdUuSt3r l+xMfoWh91ot/DDFut87kGEfKsXypiCrZGSJ5eUtzuWmyjAcYRNZ87qTD3uGlKG/ 7tEVb4RpXTjAKVZnIPS55ACf/sChiAk3hf02Iki5JMNspE8bXeXCSNVszTomQGL+ XhlQoDxBWn6cyei6c5Asfu5guhPAI5NIMli80dutYT9ZxYI7CA1nuqCqRQ+uJ6n3 xe2d98ISMRTUCahto/1QefT14c2tZF2AI6joSbMdz13F9N/64hrl3jrS2242IN0K Yj8n8LPdtBPjEjZlfQu47nH0SMGlUUwIVynGMXiTNyTG9khNJL8= =MjNd -----END PGP SIGNATURE----- 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: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
commit
f51df260e8
|
@ -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 */
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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[] = {
|
||||
|
|
|
@ -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;
|
||||
|
||||
return meson_reset_controller_register(&adev->dev, raux->map, param);
|
||||
map = dev_get_regmap(adev->dev.parent, NULL);
|
||||
if (!map)
|
||||
return -EINVAL;
|
||||
|
||||
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");
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/* 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 */
|
|
@ -1,23 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __SOC_RESET_MESON_AUX_H
|
||||
#define __SOC_RESET_MESON_AUX_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_RESET_MESON_AUX_H */
|
Loading…
Reference in New Issue