clk: starfive: jh7100: Make hw clock implementation reusable
The JH7100 has additional audio and video clocks at different memory ranges, but they use the same register layout. Add a header and export the starfive_jh7100_clk_ops function so the clock implementation can be reused by drivers handling these clocks. Signed-off-by: Emil Renner Berthing <kernel@esmil.dk> Link: https://lore.kernel.org/r/20220126173953.1016706-6-kernel@esmil.dk Signed-off-by: Stephen Boyd <sboyd@kernel.org>
This commit is contained in:
parent
c31b32fef8
commit
26ad971faa
@ -20,83 +20,15 @@
|
||||
|
||||
#include <dt-bindings/clock/starfive-jh7100.h>
|
||||
|
||||
#include "clk-starfive-jh7100.h"
|
||||
|
||||
/* external clocks */
|
||||
#define JH7100_CLK_OSC_SYS (JH7100_CLK_END + 0)
|
||||
#define JH7100_CLK_OSC_AUD (JH7100_CLK_END + 1)
|
||||
#define JH7100_CLK_GMAC_RMII_REF (JH7100_CLK_END + 2)
|
||||
#define JH7100_CLK_GMAC_GR_MII_RX (JH7100_CLK_END + 3)
|
||||
|
||||
/* register fields */
|
||||
#define JH7100_CLK_ENABLE BIT(31)
|
||||
#define JH7100_CLK_INVERT BIT(30)
|
||||
#define JH7100_CLK_MUX_MASK GENMASK(27, 24)
|
||||
#define JH7100_CLK_MUX_SHIFT 24
|
||||
#define JH7100_CLK_DIV_MASK GENMASK(23, 0)
|
||||
#define JH7100_CLK_FRAC_MASK GENMASK(15, 8)
|
||||
#define JH7100_CLK_FRAC_SHIFT 8
|
||||
#define JH7100_CLK_INT_MASK GENMASK(7, 0)
|
||||
|
||||
/* fractional divider min/max */
|
||||
#define JH7100_CLK_FRAC_MIN 100UL
|
||||
#define JH7100_CLK_FRAC_MAX 25599UL
|
||||
|
||||
/* clock data */
|
||||
#define JH7100_GATE(_idx, _name, _flags, _parent) [_idx] = { \
|
||||
.name = _name, \
|
||||
.flags = CLK_SET_RATE_PARENT | (_flags), \
|
||||
.max = JH7100_CLK_ENABLE, \
|
||||
.parents = { [0] = _parent }, \
|
||||
}
|
||||
|
||||
#define JH7100__DIV(_idx, _name, _max, _parent) [_idx] = { \
|
||||
.name = _name, \
|
||||
.flags = 0, \
|
||||
.max = _max, \
|
||||
.parents = { [0] = _parent }, \
|
||||
}
|
||||
|
||||
#define JH7100_GDIV(_idx, _name, _flags, _max, _parent) [_idx] = { \
|
||||
.name = _name, \
|
||||
.flags = _flags, \
|
||||
.max = JH7100_CLK_ENABLE | (_max), \
|
||||
.parents = { [0] = _parent }, \
|
||||
}
|
||||
|
||||
#define JH7100_FDIV(_idx, _name, _parent) [_idx] = { \
|
||||
.name = _name, \
|
||||
.flags = 0, \
|
||||
.max = JH7100_CLK_FRAC_MAX, \
|
||||
.parents = { [0] = _parent }, \
|
||||
}
|
||||
|
||||
#define JH7100__MUX(_idx, _name, _nparents, ...) [_idx] = { \
|
||||
.name = _name, \
|
||||
.flags = 0, \
|
||||
.max = ((_nparents) - 1) << JH7100_CLK_MUX_SHIFT, \
|
||||
.parents = { __VA_ARGS__ }, \
|
||||
}
|
||||
|
||||
#define JH7100_GMUX(_idx, _name, _flags, _nparents, ...) [_idx] = { \
|
||||
.name = _name, \
|
||||
.flags = _flags, \
|
||||
.max = JH7100_CLK_ENABLE | \
|
||||
(((_nparents) - 1) << JH7100_CLK_MUX_SHIFT), \
|
||||
.parents = { __VA_ARGS__ }, \
|
||||
}
|
||||
|
||||
#define JH7100__INV(_idx, _name, _parent) [_idx] = { \
|
||||
.name = _name, \
|
||||
.flags = CLK_SET_RATE_PARENT, \
|
||||
.max = JH7100_CLK_INVERT, \
|
||||
.parents = { [0] = _parent }, \
|
||||
}
|
||||
|
||||
static const struct {
|
||||
const char *name;
|
||||
unsigned long flags;
|
||||
u32 max;
|
||||
u8 parents[4];
|
||||
} jh7100_clk_data[] __initconst = {
|
||||
static const struct jh7100_clk_data jh7100_clk_data[] __initconst = {
|
||||
JH7100__MUX(JH7100_CLK_CPUNDBUS_ROOT, "cpundbus_root", 4,
|
||||
JH7100_CLK_OSC_SYS,
|
||||
JH7100_CLK_PLL0_OUT,
|
||||
@ -337,21 +269,6 @@ static const struct {
|
||||
JH7100_GATE(JH7100_CLK_SYSERR_APB, "syserr_apb", 0, JH7100_CLK_APB2_BUS),
|
||||
};
|
||||
|
||||
struct jh7100_clk {
|
||||
struct clk_hw hw;
|
||||
unsigned int idx;
|
||||
unsigned int max_div;
|
||||
};
|
||||
|
||||
struct jh7100_clk_priv {
|
||||
/* protect clk enable and set rate/parent from happening at the same time */
|
||||
spinlock_t rmw_lock;
|
||||
struct device *dev;
|
||||
void __iomem *base;
|
||||
struct clk_hw *pll[3];
|
||||
struct jh7100_clk reg[JH7100_CLK_PLL0_OUT];
|
||||
};
|
||||
|
||||
static struct jh7100_clk *jh7100_clk_from(struct clk_hw *hw)
|
||||
{
|
||||
return container_of(hw, struct jh7100_clk, hw);
|
||||
@ -623,7 +540,7 @@ static const struct clk_ops jh7100_clk_inv_ops = {
|
||||
.debug_init = jh7100_clk_debug_init,
|
||||
};
|
||||
|
||||
static const struct clk_ops *__init jh7100_clk_ops(u32 max)
|
||||
const struct clk_ops *starfive_jh7100_clk_ops(u32 max)
|
||||
{
|
||||
if (max & JH7100_CLK_DIV_MASK) {
|
||||
if (max & JH7100_CLK_ENABLE)
|
||||
@ -644,6 +561,7 @@ static const struct clk_ops *__init jh7100_clk_ops(u32 max)
|
||||
|
||||
return &jh7100_clk_inv_ops;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(starfive_jh7100_clk_ops);
|
||||
|
||||
static struct clk_hw *jh7100_clk_get(struct of_phandle_args *clkspec, void *data)
|
||||
{
|
||||
@ -665,7 +583,7 @@ static int __init clk_starfive_jh7100_probe(struct platform_device *pdev)
|
||||
unsigned int idx;
|
||||
int ret;
|
||||
|
||||
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||
priv = devm_kzalloc(&pdev->dev, struct_size(priv, reg, JH7100_CLK_PLL0_OUT), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -695,7 +613,7 @@ static int __init clk_starfive_jh7100_probe(struct platform_device *pdev)
|
||||
struct clk_parent_data parents[4] = {};
|
||||
struct clk_init_data init = {
|
||||
.name = jh7100_clk_data[idx].name,
|
||||
.ops = jh7100_clk_ops(max),
|
||||
.ops = starfive_jh7100_clk_ops(max),
|
||||
.parent_data = parents,
|
||||
.num_parents = ((max & JH7100_CLK_MUX_MASK) >> JH7100_CLK_MUX_SHIFT) + 1,
|
||||
.flags = jh7100_clk_data[idx].flags,
|
||||
|
97
drivers/clk/starfive/clk-starfive-jh7100.h
Normal file
97
drivers/clk/starfive/clk-starfive-jh7100.h
Normal file
@ -0,0 +1,97 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __CLK_STARFIVE_JH7100_H
|
||||
#define __CLK_STARFIVE_JH7100_H
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/clk-provider.h>
|
||||
|
||||
/* register fields */
|
||||
#define JH7100_CLK_ENABLE BIT(31)
|
||||
#define JH7100_CLK_INVERT BIT(30)
|
||||
#define JH7100_CLK_MUX_MASK GENMASK(27, 24)
|
||||
#define JH7100_CLK_MUX_SHIFT 24
|
||||
#define JH7100_CLK_DIV_MASK GENMASK(23, 0)
|
||||
#define JH7100_CLK_FRAC_MASK GENMASK(15, 8)
|
||||
#define JH7100_CLK_FRAC_SHIFT 8
|
||||
#define JH7100_CLK_INT_MASK GENMASK(7, 0)
|
||||
|
||||
/* fractional divider min/max */
|
||||
#define JH7100_CLK_FRAC_MIN 100UL
|
||||
#define JH7100_CLK_FRAC_MAX 25599UL
|
||||
|
||||
/* clock data */
|
||||
struct jh7100_clk_data {
|
||||
const char *name;
|
||||
unsigned long flags;
|
||||
u32 max;
|
||||
u8 parents[4];
|
||||
};
|
||||
|
||||
#define JH7100_GATE(_idx, _name, _flags, _parent) [_idx] = { \
|
||||
.name = _name, \
|
||||
.flags = CLK_SET_RATE_PARENT | (_flags), \
|
||||
.max = JH7100_CLK_ENABLE, \
|
||||
.parents = { [0] = _parent }, \
|
||||
}
|
||||
|
||||
#define JH7100__DIV(_idx, _name, _max, _parent) [_idx] = { \
|
||||
.name = _name, \
|
||||
.flags = 0, \
|
||||
.max = _max, \
|
||||
.parents = { [0] = _parent }, \
|
||||
}
|
||||
|
||||
#define JH7100_GDIV(_idx, _name, _flags, _max, _parent) [_idx] = { \
|
||||
.name = _name, \
|
||||
.flags = _flags, \
|
||||
.max = JH7100_CLK_ENABLE | (_max), \
|
||||
.parents = { [0] = _parent }, \
|
||||
}
|
||||
|
||||
#define JH7100_FDIV(_idx, _name, _parent) [_idx] = { \
|
||||
.name = _name, \
|
||||
.flags = 0, \
|
||||
.max = JH7100_CLK_FRAC_MAX, \
|
||||
.parents = { [0] = _parent }, \
|
||||
}
|
||||
|
||||
#define JH7100__MUX(_idx, _name, _nparents, ...) [_idx] = { \
|
||||
.name = _name, \
|
||||
.flags = 0, \
|
||||
.max = ((_nparents) - 1) << JH7100_CLK_MUX_SHIFT, \
|
||||
.parents = { __VA_ARGS__ }, \
|
||||
}
|
||||
|
||||
#define JH7100_GMUX(_idx, _name, _flags, _nparents, ...) [_idx] = { \
|
||||
.name = _name, \
|
||||
.flags = _flags, \
|
||||
.max = JH7100_CLK_ENABLE | \
|
||||
(((_nparents) - 1) << JH7100_CLK_MUX_SHIFT), \
|
||||
.parents = { __VA_ARGS__ }, \
|
||||
}
|
||||
|
||||
#define JH7100__INV(_idx, _name, _parent) [_idx] = { \
|
||||
.name = _name, \
|
||||
.flags = CLK_SET_RATE_PARENT, \
|
||||
.max = JH7100_CLK_INVERT, \
|
||||
.parents = { [0] = _parent }, \
|
||||
}
|
||||
|
||||
struct jh7100_clk {
|
||||
struct clk_hw hw;
|
||||
unsigned int idx;
|
||||
unsigned int max_div;
|
||||
};
|
||||
|
||||
struct jh7100_clk_priv {
|
||||
/* protect clk enable and set rate/parent from happening at the same time */
|
||||
spinlock_t rmw_lock;
|
||||
struct device *dev;
|
||||
void __iomem *base;
|
||||
struct clk_hw *pll[3];
|
||||
struct jh7100_clk reg[];
|
||||
};
|
||||
|
||||
const struct clk_ops *starfive_jh7100_clk_ops(u32 max);
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user