mirror of
https://github.com/torvalds/linux.git
synced 2026-05-12 16:18:45 +02:00
clk: amlogic: get regmap with clk_regmap_init
Add clk_regmap_init() and use it with all clock types which derive from clk_regmap. This helps initialise clk_regmap clocks without requiring tables to keep track of the clock using this type. The way it is done couples clk_regmap with the controllers, which is not ideal. This is a temporary solution to get rid of the tables. The situation will eventually be improved. Link: https://lore.kernel.org/r/20250623-amlogic-clk-drop-clk-regmap-tables-v4-1-ff04918211cc@baylibre.com Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
This commit is contained in:
parent
328d4a7eb0
commit
21ed19d118
|
|
@ -5,6 +5,7 @@ menu "Clock support for Amlogic platforms"
|
|||
config COMMON_CLK_MESON_REGMAP
|
||||
tristate
|
||||
select REGMAP
|
||||
select MFD_SYSCON
|
||||
|
||||
config COMMON_CLK_MESON_DUALDIV
|
||||
tristate
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ static int meson_clk_cpu_dyndiv_set_rate(struct clk_hw *hw, unsigned long rate,
|
|||
};
|
||||
|
||||
const struct clk_ops meson_clk_cpu_dyndiv_ops = {
|
||||
.init = clk_regmap_init,
|
||||
.recalc_rate = meson_clk_cpu_dyndiv_recalc_rate,
|
||||
.determine_rate = meson_clk_cpu_dyndiv_determine_rate,
|
||||
.set_rate = meson_clk_cpu_dyndiv_set_rate,
|
||||
|
|
|
|||
|
|
@ -126,6 +126,7 @@ static int meson_clk_dualdiv_set_rate(struct clk_hw *hw, unsigned long rate,
|
|||
}
|
||||
|
||||
const struct clk_ops meson_clk_dualdiv_ops = {
|
||||
.init = clk_regmap_init,
|
||||
.recalc_rate = meson_clk_dualdiv_recalc_rate,
|
||||
.determine_rate = meson_clk_dualdiv_determine_rate,
|
||||
.set_rate = meson_clk_dualdiv_set_rate,
|
||||
|
|
@ -133,6 +134,7 @@ const struct clk_ops meson_clk_dualdiv_ops = {
|
|||
EXPORT_SYMBOL_NS_GPL(meson_clk_dualdiv_ops, "CLK_MESON");
|
||||
|
||||
const struct clk_ops meson_clk_dualdiv_ro_ops = {
|
||||
.init = clk_regmap_init,
|
||||
.recalc_rate = meson_clk_dualdiv_recalc_rate,
|
||||
};
|
||||
EXPORT_SYMBOL_NS_GPL(meson_clk_dualdiv_ro_ops, "CLK_MESON");
|
||||
|
|
|
|||
|
|
@ -128,6 +128,11 @@ static int mpll_init(struct clk_hw *hw)
|
|||
{
|
||||
struct clk_regmap *clk = to_clk_regmap(hw);
|
||||
struct meson_clk_mpll_data *mpll = meson_clk_mpll_data(clk);
|
||||
int ret;
|
||||
|
||||
ret = clk_regmap_init(hw);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (mpll->init_count)
|
||||
regmap_multi_reg_write(clk->map, mpll->init_regs,
|
||||
|
|
@ -151,6 +156,7 @@ static int mpll_init(struct clk_hw *hw)
|
|||
}
|
||||
|
||||
const struct clk_ops meson_clk_mpll_ro_ops = {
|
||||
.init = clk_regmap_init,
|
||||
.recalc_rate = mpll_recalc_rate,
|
||||
.determine_rate = mpll_determine_rate,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ static int meson_clk_phase_set_phase(struct clk_hw *hw, int degrees)
|
|||
}
|
||||
|
||||
const struct clk_ops meson_clk_phase_ops = {
|
||||
.init = clk_regmap_init,
|
||||
.get_phase = meson_clk_phase_get_phase,
|
||||
.set_phase = meson_clk_phase_set_phase,
|
||||
};
|
||||
|
|
@ -83,6 +84,11 @@ static int meson_clk_triphase_sync(struct clk_hw *hw)
|
|||
struct clk_regmap *clk = to_clk_regmap(hw);
|
||||
struct meson_clk_triphase_data *tph = meson_clk_triphase_data(clk);
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
ret = clk_regmap_init(hw);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Get phase 0 and sync it to phase 1 and 2 */
|
||||
val = meson_parm_read(clk->map, &tph->ph0);
|
||||
|
|
@ -142,6 +148,11 @@ static int meson_sclk_ws_inv_sync(struct clk_hw *hw)
|
|||
struct clk_regmap *clk = to_clk_regmap(hw);
|
||||
struct meson_sclk_ws_inv_data *tph = meson_sclk_ws_inv_data(clk);
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
ret = clk_regmap_init(hw);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Get phase and sync the inverted value to ws */
|
||||
val = meson_parm_read(clk->map, &tph->ph);
|
||||
|
|
|
|||
|
|
@ -311,6 +311,11 @@ static int meson_clk_pll_init(struct clk_hw *hw)
|
|||
{
|
||||
struct clk_regmap *clk = to_clk_regmap(hw);
|
||||
struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
|
||||
int ret;
|
||||
|
||||
ret = clk_regmap_init(hw);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Keep the clock running, which was already initialized and enabled
|
||||
|
|
@ -468,6 +473,7 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
|||
* the other ops except set_rate since the rate is fixed.
|
||||
*/
|
||||
const struct clk_ops meson_clk_pcie_pll_ops = {
|
||||
.init = clk_regmap_init,
|
||||
.recalc_rate = meson_clk_pll_recalc_rate,
|
||||
.determine_rate = meson_clk_pll_determine_rate,
|
||||
.is_enabled = meson_clk_pll_is_enabled,
|
||||
|
|
@ -488,6 +494,7 @@ const struct clk_ops meson_clk_pll_ops = {
|
|||
EXPORT_SYMBOL_NS_GPL(meson_clk_pll_ops, "CLK_MESON");
|
||||
|
||||
const struct clk_ops meson_clk_pll_ro_ops = {
|
||||
.init = clk_regmap_init,
|
||||
.recalc_rate = meson_clk_pll_recalc_rate,
|
||||
.is_enabled = meson_clk_pll_is_enabled,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -4,9 +4,52 @@
|
|||
* Author: Jerome Brunet <jbrunet@baylibre.com>
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include "clk-regmap.h"
|
||||
|
||||
int clk_regmap_init(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_regmap *clk = to_clk_regmap(hw);
|
||||
struct device_node *np, *parent_np;
|
||||
struct device *dev;
|
||||
|
||||
/* Allow regmap to be preset as it was historically done */
|
||||
if (clk->map)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* FIXME: what follows couples the controller implementation
|
||||
* and clk_regmap clock type. This situation is not desirable
|
||||
* but temporary, until the controller is able to register
|
||||
* a hook to initialize a clock type
|
||||
*/
|
||||
|
||||
/* Check the usual dev enabled controller with an basic IO regmap */
|
||||
dev = clk_hw_get_dev(hw);
|
||||
if (dev) {
|
||||
clk->map = dev_get_regmap(dev, NULL);
|
||||
if (clk->map)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Move on to early and syscon based controllers */
|
||||
np = clk_hw_get_of_node(hw);
|
||||
if (np) {
|
||||
parent_np = of_get_parent(np);
|
||||
clk->map = syscon_node_to_regmap(parent_np);
|
||||
of_node_put(parent_np);
|
||||
|
||||
if (!IS_ERR_OR_NULL(clk->map))
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Bail out if regmap can't be found */
|
||||
return -EINVAL;
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(clk_regmap_init, "CLK_MESON");
|
||||
|
||||
static int clk_regmap_gate_endisable(struct clk_hw *hw, int enable)
|
||||
{
|
||||
struct clk_regmap *clk = to_clk_regmap(hw);
|
||||
|
|
@ -45,6 +88,7 @@ static int clk_regmap_gate_is_enabled(struct clk_hw *hw)
|
|||
}
|
||||
|
||||
const struct clk_ops clk_regmap_gate_ops = {
|
||||
.init = clk_regmap_init,
|
||||
.enable = clk_regmap_gate_enable,
|
||||
.disable = clk_regmap_gate_disable,
|
||||
.is_enabled = clk_regmap_gate_is_enabled,
|
||||
|
|
@ -52,6 +96,7 @@ const struct clk_ops clk_regmap_gate_ops = {
|
|||
EXPORT_SYMBOL_NS_GPL(clk_regmap_gate_ops, "CLK_MESON");
|
||||
|
||||
const struct clk_ops clk_regmap_gate_ro_ops = {
|
||||
.init = clk_regmap_init,
|
||||
.is_enabled = clk_regmap_gate_is_enabled,
|
||||
};
|
||||
EXPORT_SYMBOL_NS_GPL(clk_regmap_gate_ro_ops, "CLK_MESON");
|
||||
|
|
@ -121,6 +166,7 @@ static int clk_regmap_div_set_rate(struct clk_hw *hw, unsigned long rate,
|
|||
/* Would prefer clk_regmap_div_ro_ops but clashes with qcom */
|
||||
|
||||
const struct clk_ops clk_regmap_divider_ops = {
|
||||
.init = clk_regmap_init,
|
||||
.recalc_rate = clk_regmap_div_recalc_rate,
|
||||
.determine_rate = clk_regmap_div_determine_rate,
|
||||
.set_rate = clk_regmap_div_set_rate,
|
||||
|
|
@ -128,6 +174,7 @@ const struct clk_ops clk_regmap_divider_ops = {
|
|||
EXPORT_SYMBOL_NS_GPL(clk_regmap_divider_ops, "CLK_MESON");
|
||||
|
||||
const struct clk_ops clk_regmap_divider_ro_ops = {
|
||||
.init = clk_regmap_init,
|
||||
.recalc_rate = clk_regmap_div_recalc_rate,
|
||||
.determine_rate = clk_regmap_div_determine_rate,
|
||||
};
|
||||
|
|
@ -170,6 +217,7 @@ static int clk_regmap_mux_determine_rate(struct clk_hw *hw,
|
|||
}
|
||||
|
||||
const struct clk_ops clk_regmap_mux_ops = {
|
||||
.init = clk_regmap_init,
|
||||
.get_parent = clk_regmap_mux_get_parent,
|
||||
.set_parent = clk_regmap_mux_set_parent,
|
||||
.determine_rate = clk_regmap_mux_determine_rate,
|
||||
|
|
@ -177,6 +225,7 @@ const struct clk_ops clk_regmap_mux_ops = {
|
|||
EXPORT_SYMBOL_NS_GPL(clk_regmap_mux_ops, "CLK_MESON");
|
||||
|
||||
const struct clk_ops clk_regmap_mux_ro_ops = {
|
||||
.init = clk_regmap_init,
|
||||
.get_parent = clk_regmap_mux_get_parent,
|
||||
};
|
||||
EXPORT_SYMBOL_NS_GPL(clk_regmap_mux_ro_ops, "CLK_MESON");
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#ifndef __CLK_REGMAP_H
|
||||
#define __CLK_REGMAP_H
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
|
|
@ -31,6 +32,9 @@ static inline struct clk_regmap *to_clk_regmap(struct clk_hw *hw)
|
|||
return container_of(hw, struct clk_regmap, hw);
|
||||
}
|
||||
|
||||
/* clk_regmap init op to get and cache regmap from the controllers */
|
||||
int clk_regmap_init(struct clk_hw *hw);
|
||||
|
||||
/**
|
||||
* struct clk_regmap_gate_data - regmap backed gate specific data
|
||||
*
|
||||
|
|
|
|||
|
|
@ -222,6 +222,11 @@ static int sclk_div_init(struct clk_hw *hw)
|
|||
struct clk_regmap *clk = to_clk_regmap(hw);
|
||||
struct meson_sclk_div_data *sclk = meson_sclk_div_data(clk);
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
ret = clk_regmap_init(hw);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
val = meson_parm_read(clk->map, &sclk->div);
|
||||
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ static int meson_vclk_gate_is_enabled(struct clk_hw *hw)
|
|||
}
|
||||
|
||||
const struct clk_ops meson_vclk_gate_ops = {
|
||||
.init = clk_regmap_init,
|
||||
.enable = meson_vclk_gate_enable,
|
||||
.disable = meson_vclk_gate_disable,
|
||||
.is_enabled = meson_vclk_gate_is_enabled,
|
||||
|
|
@ -127,6 +128,7 @@ static int meson_vclk_div_is_enabled(struct clk_hw *hw)
|
|||
}
|
||||
|
||||
const struct clk_ops meson_vclk_div_ops = {
|
||||
.init = clk_regmap_init,
|
||||
.recalc_rate = meson_vclk_div_recalc_rate,
|
||||
.determine_rate = meson_vclk_div_determine_rate,
|
||||
.set_rate = meson_vclk_div_set_rate,
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ static unsigned long meson_vid_pll_div_recalc_rate(struct clk_hw *hw,
|
|||
}
|
||||
|
||||
const struct clk_ops meson_vid_pll_div_ro_ops = {
|
||||
.init = clk_regmap_init,
|
||||
.recalc_rate = meson_vid_pll_div_recalc_rate,
|
||||
};
|
||||
EXPORT_SYMBOL_NS_GPL(meson_vid_pll_div_ro_ops, "CLK_MESON");
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user