summaryrefslogtreecommitdiffstats
path: root/drivers/clk
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk')
-rw-r--r--drivers/clk/clk-en7523.c9
-rw-r--r--drivers/clk/clk.c2
-rw-r--r--drivers/clk/meson/Kconfig2
-rw-r--r--drivers/clk/meson/axg-audio.c109
4 files changed, 107 insertions, 15 deletions
diff --git a/drivers/clk/clk-en7523.c b/drivers/clk/clk-en7523.c
index e52c5460e927..495c0d607c7d 100644
--- a/drivers/clk/clk-en7523.c
+++ b/drivers/clk/clk-en7523.c
@@ -87,6 +87,7 @@ static const u32 slic_base[] = { 100000000, 3125000 };
static const u32 npu_base[] = { 333000000, 400000000, 500000000 };
/* EN7581 */
static const u32 emi7581_base[] = { 540000000, 480000000, 400000000, 300000000 };
+static const u32 bus7581_base[] = { 600000000, 540000000 };
static const u32 npu7581_base[] = { 800000000, 750000000, 720000000, 600000000 };
static const u32 crypto_base[] = { 540000000, 480000000 };
@@ -222,8 +223,8 @@ static const struct en_clk_desc en7581_base_clks[] = {
.base_reg = REG_BUS_CLK_DIV_SEL,
.base_bits = 1,
.base_shift = 8,
- .base_values = bus_base,
- .n_base_values = ARRAY_SIZE(bus_base),
+ .base_values = bus7581_base,
+ .n_base_values = ARRAY_SIZE(bus7581_base),
.div_bits = 3,
.div_shift = 0,
@@ -503,6 +504,8 @@ static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_dat
u32 rate;
int i;
+ clk_data->num = EN7523_NUM_CLOCKS;
+
for (i = 0; i < ARRAY_SIZE(en7523_base_clks); i++) {
const struct en_clk_desc *desc = &en7523_base_clks[i];
u32 reg = desc->div_reg ? desc->div_reg : desc->base_reg;
@@ -524,8 +527,6 @@ static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_dat
hw = en7523_register_pcie_clk(dev, np_base);
clk_data->hws[EN7523_CLK_PCIE] = hw;
-
- clk_data->num = EN7523_NUM_CLOCKS;
}
static int en7523_clk_hw_init(struct platform_device *pdev,
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index bdc6e5b90da5..9b45fa005030 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -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 */
diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig
index febb5d7348ff..be2e3a5f8336 100644
--- a/drivers/clk/meson/Kconfig
+++ b/drivers/clk/meson/Kconfig
@@ -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.
diff --git a/drivers/clk/meson/axg-audio.c b/drivers/clk/meson/axg-audio.c
index 7a3460804424..9df627b142f8 100644
--- a/drivers/clk/meson/axg-audio.c
+++ b/drivers/clk/meson/axg-audio.c
@@ -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;
+
+ 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 ret;
+ 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[] = {