Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+159 -110
+1 -1
drivers/clk/clk.c
··· 2530 2530 rate = clk_core_req_round_rate_nolock(core, req_rate); 2531 2531 2532 2532 /* bail early if nothing to do */ 2533 - if (rate == clk_core_get_rate_recalc(core)) 2533 + if (rate == clk_core_get_rate_nolock(core)) 2534 2534 return 0; 2535 2535 2536 2536 /* fail on a direct rate set of a protected provider */
+1 -1
drivers/clk/meson/Kconfig
··· 106 106 select COMMON_CLK_MESON_SCLK_DIV 107 107 select COMMON_CLK_MESON_CLKC_UTILS 108 108 select REGMAP_MMIO 109 - depends on RESET_MESON_AUX 109 + select RESET_CONTROLLER 110 110 help 111 111 Support for the audio clock controller on AmLogic A113D devices, 112 112 aka axg, Say Y if you want audio subsystem to work.
+100 -9
drivers/clk/meson/axg-audio.c
··· 15 15 #include <linux/reset-controller.h> 16 16 #include <linux/slab.h> 17 17 18 - #include <soc/amlogic/reset-meson-aux.h> 19 - 20 18 #include "meson-clkc-utils.h" 21 19 #include "axg-audio.h" 22 20 #include "clk-regmap.h" ··· 1678 1680 &sm1_earcrx_dmac_clk, 1679 1681 }; 1680 1682 1683 + struct axg_audio_reset_data { 1684 + struct reset_controller_dev rstc; 1685 + struct regmap *map; 1686 + unsigned int offset; 1687 + }; 1688 + 1689 + static void axg_audio_reset_reg_and_bit(struct axg_audio_reset_data *rst, 1690 + unsigned long id, 1691 + unsigned int *reg, 1692 + unsigned int *bit) 1693 + { 1694 + unsigned int stride = regmap_get_reg_stride(rst->map); 1695 + 1696 + *reg = (id / (stride * BITS_PER_BYTE)) * stride; 1697 + *reg += rst->offset; 1698 + *bit = id % (stride * BITS_PER_BYTE); 1699 + } 1700 + 1701 + static int axg_audio_reset_update(struct reset_controller_dev *rcdev, 1702 + unsigned long id, bool assert) 1703 + { 1704 + struct axg_audio_reset_data *rst = 1705 + container_of(rcdev, struct axg_audio_reset_data, rstc); 1706 + unsigned int offset, bit; 1707 + 1708 + axg_audio_reset_reg_and_bit(rst, id, &offset, &bit); 1709 + 1710 + regmap_update_bits(rst->map, offset, BIT(bit), 1711 + assert ? BIT(bit) : 0); 1712 + 1713 + return 0; 1714 + } 1715 + 1716 + static int axg_audio_reset_status(struct reset_controller_dev *rcdev, 1717 + unsigned long id) 1718 + { 1719 + struct axg_audio_reset_data *rst = 1720 + container_of(rcdev, struct axg_audio_reset_data, rstc); 1721 + unsigned int val, offset, bit; 1722 + 1723 + axg_audio_reset_reg_and_bit(rst, id, &offset, &bit); 1724 + 1725 + regmap_read(rst->map, offset, &val); 1726 + 1727 + return !!(val & BIT(bit)); 1728 + } 1729 + 1730 + static int axg_audio_reset_assert(struct reset_controller_dev *rcdev, 1731 + unsigned long id) 1732 + { 1733 + return axg_audio_reset_update(rcdev, id, true); 1734 + } 1735 + 1736 + static int axg_audio_reset_deassert(struct reset_controller_dev *rcdev, 1737 + unsigned long id) 1738 + { 1739 + return axg_audio_reset_update(rcdev, id, false); 1740 + } 1741 + 1742 + static int axg_audio_reset_toggle(struct reset_controller_dev *rcdev, 1743 + unsigned long id) 1744 + { 1745 + int ret; 1746 + 1747 + ret = axg_audio_reset_assert(rcdev, id); 1748 + if (ret) 1749 + return ret; 1750 + 1751 + return axg_audio_reset_deassert(rcdev, id); 1752 + } 1753 + 1754 + static const struct reset_control_ops axg_audio_rstc_ops = { 1755 + .assert = axg_audio_reset_assert, 1756 + .deassert = axg_audio_reset_deassert, 1757 + .reset = axg_audio_reset_toggle, 1758 + .status = axg_audio_reset_status, 1759 + }; 1760 + 1681 1761 static struct regmap_config axg_audio_regmap_cfg = { 1682 1762 .reg_bits = 32, 1683 1763 .val_bits = 32, ··· 1766 1690 struct clk_regmap *const *regmap_clks; 1767 1691 unsigned int regmap_clk_num; 1768 1692 struct meson_clk_hw_data hw_clks; 1693 + unsigned int reset_offset; 1694 + unsigned int reset_num; 1769 1695 unsigned int max_register; 1770 - const char *rst_drvname; 1771 1696 }; 1772 1697 1773 1698 static int axg_audio_clkc_probe(struct platform_device *pdev) 1774 1699 { 1775 1700 struct device *dev = &pdev->dev; 1776 1701 const struct audioclk_data *data; 1702 + struct axg_audio_reset_data *rst; 1777 1703 struct regmap *map; 1778 1704 void __iomem *regs; 1779 1705 struct clk_hw *hw; ··· 1834 1756 if (ret) 1835 1757 return ret; 1836 1758 1837 - /* Register auxiliary reset driver when applicable */ 1838 - if (data->rst_drvname) 1839 - ret = devm_meson_rst_aux_register(dev, map, data->rst_drvname); 1759 + /* Stop here if there is no reset */ 1760 + if (!data->reset_num) 1761 + return 0; 1840 1762 1841 - return ret; 1763 + rst = devm_kzalloc(dev, sizeof(*rst), GFP_KERNEL); 1764 + if (!rst) 1765 + return -ENOMEM; 1766 + 1767 + rst->map = map; 1768 + rst->offset = data->reset_offset; 1769 + rst->rstc.nr_resets = data->reset_num; 1770 + rst->rstc.ops = &axg_audio_rstc_ops; 1771 + rst->rstc.of_node = dev->of_node; 1772 + rst->rstc.owner = THIS_MODULE; 1773 + 1774 + return devm_reset_controller_register(dev, &rst->rstc); 1842 1775 } 1843 1776 1844 1777 static const struct audioclk_data axg_audioclk_data = { ··· 1869 1780 .hws = g12a_audio_hw_clks, 1870 1781 .num = ARRAY_SIZE(g12a_audio_hw_clks), 1871 1782 }, 1783 + .reset_offset = AUDIO_SW_RESET, 1784 + .reset_num = 26, 1872 1785 .max_register = AUDIO_CLK_SPDIFOUT_B_CTRL, 1873 - .rst_drvname = "rst-g12a", 1874 1786 }; 1875 1787 1876 1788 static const struct audioclk_data sm1_audioclk_data = { ··· 1881 1791 .hws = sm1_audio_hw_clks, 1882 1792 .num = ARRAY_SIZE(sm1_audio_hw_clks), 1883 1793 }, 1794 + .reset_offset = AUDIO_SM1_SW_RESET0, 1795 + .reset_num = 39, 1884 1796 .max_register = AUDIO_EARCRX_DMAC_CLK_CTRL, 1885 - .rst_drvname = "rst-sm1", 1886 1797 }; 1887 1798 1888 1799 static const struct of_device_id clkc_match_table[] = {
+21 -76
drivers/reset/amlogic/reset-meson-aux.c
··· 11 11 #include <linux/auxiliary_bus.h> 12 12 #include <linux/regmap.h> 13 13 #include <linux/reset-controller.h> 14 - #include <linux/slab.h> 15 14 16 15 #include "reset-meson.h" 17 - #include <soc/amlogic/reset-meson-aux.h> 18 16 19 - static DEFINE_IDA(meson_rst_aux_ida); 20 - 21 - struct meson_reset_adev { 22 - struct auxiliary_device adev; 23 - struct regmap *map; 17 + static const struct meson_reset_param meson_a1_audio_param = { 18 + .reset_ops = &meson_reset_toggle_ops, 19 + .reset_num = 32, 20 + .level_offset = 0x28, 24 21 }; 25 22 26 - #define to_meson_reset_adev(_adev) \ 27 - container_of((_adev), struct meson_reset_adev, adev) 23 + static const struct meson_reset_param meson_a1_audio_vad_param = { 24 + .reset_ops = &meson_reset_toggle_ops, 25 + .reset_num = 6, 26 + .level_offset = 0x8, 27 + }; 28 28 29 29 static const struct meson_reset_param meson_g12a_audio_param = { 30 30 .reset_ops = &meson_reset_toggle_ops, ··· 40 40 41 41 static const struct auxiliary_device_id meson_reset_aux_ids[] = { 42 42 { 43 + .name = "a1-audio-clkc.rst-a1", 44 + .driver_data = (kernel_ulong_t)&meson_a1_audio_param, 45 + }, { 46 + .name = "a1-audio-clkc.rst-a1-vad", 47 + .driver_data = (kernel_ulong_t)&meson_a1_audio_vad_param, 48 + }, { 43 49 .name = "axg-audio-clkc.rst-g12a", 44 50 .driver_data = (kernel_ulong_t)&meson_g12a_audio_param, 45 51 }, { ··· 60 54 { 61 55 const struct meson_reset_param *param = 62 56 (const struct meson_reset_param *)(id->driver_data); 63 - struct meson_reset_adev *raux = 64 - to_meson_reset_adev(adev); 57 + struct regmap *map; 65 58 66 - return meson_reset_controller_register(&adev->dev, raux->map, param); 59 + map = dev_get_regmap(adev->dev.parent, NULL); 60 + if (!map) 61 + return -EINVAL; 62 + 63 + return meson_reset_controller_register(&adev->dev, map, param); 67 64 } 68 65 69 66 static struct auxiliary_driver meson_reset_aux_driver = { ··· 74 65 .id_table = meson_reset_aux_ids, 75 66 }; 76 67 module_auxiliary_driver(meson_reset_aux_driver); 77 - 78 - static void meson_rst_aux_release(struct device *dev) 79 - { 80 - struct auxiliary_device *adev = to_auxiliary_dev(dev); 81 - struct meson_reset_adev *raux = 82 - to_meson_reset_adev(adev); 83 - 84 - ida_free(&meson_rst_aux_ida, adev->id); 85 - kfree(raux); 86 - } 87 - 88 - static void meson_rst_aux_unregister_adev(void *_adev) 89 - { 90 - struct auxiliary_device *adev = _adev; 91 - 92 - auxiliary_device_delete(adev); 93 - auxiliary_device_uninit(adev); 94 - } 95 - 96 - int devm_meson_rst_aux_register(struct device *dev, 97 - struct regmap *map, 98 - const char *adev_name) 99 - { 100 - struct meson_reset_adev *raux; 101 - struct auxiliary_device *adev; 102 - int ret; 103 - 104 - raux = kzalloc(sizeof(*raux), GFP_KERNEL); 105 - if (!raux) 106 - return -ENOMEM; 107 - 108 - ret = ida_alloc(&meson_rst_aux_ida, GFP_KERNEL); 109 - if (ret < 0) 110 - goto raux_free; 111 - 112 - raux->map = map; 113 - 114 - adev = &raux->adev; 115 - adev->id = ret; 116 - adev->name = adev_name; 117 - adev->dev.parent = dev; 118 - adev->dev.release = meson_rst_aux_release; 119 - device_set_of_node_from_dev(&adev->dev, dev); 120 - 121 - ret = auxiliary_device_init(adev); 122 - if (ret) 123 - goto ida_free; 124 - 125 - ret = __auxiliary_device_add(adev, dev->driver->name); 126 - if (ret) { 127 - auxiliary_device_uninit(adev); 128 - return ret; 129 - } 130 - 131 - return devm_add_action_or_reset(dev, meson_rst_aux_unregister_adev, 132 - adev); 133 - 134 - ida_free: 135 - ida_free(&meson_rst_aux_ida, adev->id); 136 - raux_free: 137 - kfree(raux); 138 - return ret; 139 - } 140 - EXPORT_SYMBOL_GPL(devm_meson_rst_aux_register); 141 68 142 69 MODULE_DESCRIPTION("Amlogic Meson Reset Auxiliary driver"); 143 70 MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
+36
include/dt-bindings/reset/amlogic,meson-a1-audio-reset.h
··· 1 + /* SPDX-License-Identifier: (GPL-2.0 OR MIT) */ 2 + /* 3 + * Copyright (c) 2024, SaluteDevices. All Rights Reserved. 4 + * 5 + * Author: Jan Dakinevich <jan.dakinevich@salutedevices.com> 6 + */ 7 + 8 + #ifndef _DT_BINDINGS_AMLOGIC_MESON_A1_AUDIO_RESET_H 9 + #define _DT_BINDINGS_AMLOGIC_MESON_A1_AUDIO_RESET_H 10 + 11 + #define AUD_RESET_DDRARB 0 12 + #define AUD_RESET_TDMIN_A 1 13 + #define AUD_RESET_TDMIN_B 2 14 + #define AUD_RESET_TDMIN_LB 3 15 + #define AUD_RESET_LOOPBACK 4 16 + #define AUD_RESET_TDMOUT_A 5 17 + #define AUD_RESET_TDMOUT_B 6 18 + #define AUD_RESET_FRDDR_A 7 19 + #define AUD_RESET_FRDDR_B 8 20 + #define AUD_RESET_TODDR_A 9 21 + #define AUD_RESET_TODDR_B 10 22 + #define AUD_RESET_SPDIFIN 11 23 + #define AUD_RESET_RESAMPLE 12 24 + #define AUD_RESET_EQDRC 13 25 + #define AUD_RESET_LOCKER 14 26 + #define AUD_RESET_TOACODEC 30 27 + #define AUD_RESET_CLKTREE 31 28 + 29 + #define AUD_VAD_RESET_DDRARB 0 30 + #define AUD_VAD_RESET_PDM 1 31 + #define AUD_VAD_RESET_TDMIN_VAD 2 32 + #define AUD_VAD_RESET_TODDR_VAD 3 33 + #define AUD_VAD_RESET_TOVAD 4 34 + #define AUD_VAD_RESET_CLKTREE 5 35 + 36 + #endif /* _DT_BINDINGS_AMLOGIC_MESON_A1_AUDIO_RESET_H */
-23
include/soc/amlogic/reset-meson-aux.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0 */ 2 - #ifndef __SOC_RESET_MESON_AUX_H 3 - #define __SOC_RESET_MESON_AUX_H 4 - 5 - #include <linux/err.h> 6 - 7 - struct device; 8 - struct regmap; 9 - 10 - #if IS_ENABLED(CONFIG_RESET_MESON_AUX) 11 - int devm_meson_rst_aux_register(struct device *dev, 12 - struct regmap *map, 13 - const char *adev_name); 14 - #else 15 - static inline int devm_meson_rst_aux_register(struct device *dev, 16 - struct regmap *map, 17 - const char *adev_name) 18 - { 19 - return 0; 20 - } 21 - #endif 22 - 23 - #endif /* __SOC_RESET_MESON_AUX_H */