mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2026-06-13 15:03:58 +03:00
clk: mediatek: add support for parent mux from different source
There is a current limitation where parents for a mux can be all declared as they are from a common source. This is not true as there are some MUX that can have parent from both infracfg or from topckgen. To handle this, implement a new flag for the mux, CLK_PARENT_MIXED, and a new entry for the mux parent_flags. To use this, CLK_PARENT_MIXED must be used and parent_flags will be used instead of the parent variable. Entry in parent_flags are just a struct of ID and flags where it will be defined where that parent comes from with the usage of CLK_PARENT_INFRASYS or CLK_PARENT_TOPCKGEN. This permits to have MUX with parents from infracfg or topckgen. Notice that with CLK_PARENT_MIXED applied the CLK_BYPASS_XTAL is ignored. With CLK_PARENT_MIXED declare CLK_PARENT_XTAL for the relevant parent instead. Also alias for the CLK_PARENT macro are provided to better clear their usage. CLK_PARENT_MIXED require these alias that describe the clk type to be defined in the clk_tree flags to prevent clk ID clash from different subsystem that may have equal clk ID. Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
This commit is contained in:
committed by
Tom Rini
parent
a03174cbfa
commit
89eff11485
@@ -55,13 +55,27 @@ static ulong mtk_clk_find_parent_rate(struct clk *clk, int id,
|
||||
}
|
||||
|
||||
static int mtk_clk_mux_set_parent(void __iomem *base, u32 parent,
|
||||
u32 parent_type,
|
||||
const struct mtk_composite *mux)
|
||||
{
|
||||
u32 val, index = 0;
|
||||
|
||||
while (mux->parent[index] != parent)
|
||||
if (++index == mux->num_parents)
|
||||
return -EINVAL;
|
||||
if (mux->flags & CLK_PARENT_MIXED) {
|
||||
/*
|
||||
* Assume parent_type in clk_tree to be always set with
|
||||
* CLK_PARENT_MIXED implementation. If it's not, assume
|
||||
* not parent clk ID clash is possible.
|
||||
*/
|
||||
while (mux->parent_flags[index].id != parent ||
|
||||
(parent_type && (mux->parent_flags[index].flags & CLK_PARENT_MASK) !=
|
||||
parent_type))
|
||||
if (++index == mux->num_parents)
|
||||
return -EINVAL;
|
||||
} else {
|
||||
while (mux->parent[index] != parent)
|
||||
if (++index == mux->num_parents)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (mux->flags & CLK_MUX_SETCLR_UPD) {
|
||||
val = (mux->mux_mask << mux->mux_shift);
|
||||
@@ -353,6 +367,19 @@ static ulong mtk_topckgen_get_mux_rate(struct clk *clk, u32 off)
|
||||
return priv->tree->xtal_rate;
|
||||
}
|
||||
|
||||
static ulong mtk_find_parent_rate(struct mtk_clk_priv *priv, struct clk *clk,
|
||||
const int parent, u16 flags)
|
||||
{
|
||||
switch (flags & CLK_PARENT_MASK) {
|
||||
case CLK_PARENT_XTAL:
|
||||
return priv->tree->xtal_rate;
|
||||
case CLK_PARENT_TOPCKGEN:
|
||||
return mtk_clk_find_parent_rate(clk, parent, priv->parent);
|
||||
default:
|
||||
return mtk_clk_find_parent_rate(clk, parent, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static ulong mtk_infrasys_get_mux_rate(struct clk *clk, u32 off)
|
||||
{
|
||||
struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
|
||||
@@ -363,21 +390,21 @@ static ulong mtk_infrasys_get_mux_rate(struct clk *clk, u32 off)
|
||||
index &= mux->mux_mask << mux->mux_shift;
|
||||
index = index >> mux->mux_shift;
|
||||
|
||||
if (mux->parent[index] > 0 ||
|
||||
(mux->parent[index] == CLK_XTAL &&
|
||||
priv->tree->flags & CLK_BYPASS_XTAL)) {
|
||||
switch (mux->flags & CLK_PARENT_MASK) {
|
||||
case CLK_PARENT_TOPCKGEN:
|
||||
return mtk_clk_find_parent_rate(clk, mux->parent[index],
|
||||
priv->parent);
|
||||
break;
|
||||
default:
|
||||
return mtk_clk_find_parent_rate(clk, mux->parent[index],
|
||||
NULL);
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Parents can be either from TOPCKGEN or INFRACFG,
|
||||
* inspect the mtk_parent struct to check the source
|
||||
*/
|
||||
if (mux->flags & CLK_PARENT_MIXED) {
|
||||
const struct mtk_parent *parent = &mux->parent_flags[index];
|
||||
|
||||
return mtk_find_parent_rate(priv, clk, parent->id, parent->flags);
|
||||
}
|
||||
return priv->tree->xtal_rate;
|
||||
|
||||
if (mux->parent[index] == CLK_XTAL &&
|
||||
!(priv->tree->flags & CLK_BYPASS_XTAL))
|
||||
return priv->tree->xtal_rate;
|
||||
|
||||
return mtk_find_parent_rate(priv, clk, mux->parent[index], mux->flags);
|
||||
}
|
||||
|
||||
static ulong mtk_topckgen_get_rate(struct clk *clk)
|
||||
@@ -491,12 +518,18 @@ static int mtk_clk_mux_disable(struct clk *clk)
|
||||
|
||||
static int mtk_common_clk_set_parent(struct clk *clk, struct clk *parent)
|
||||
{
|
||||
struct mtk_clk_priv *parent_priv = dev_get_priv(parent->dev);
|
||||
struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
|
||||
u32 parent_type;
|
||||
|
||||
if (clk->id < priv->tree->muxes_offs)
|
||||
return 0;
|
||||
|
||||
return mtk_clk_mux_set_parent(priv->base, parent->id,
|
||||
if (!parent_priv)
|
||||
return 0;
|
||||
|
||||
parent_type = parent_priv->tree->flags & CLK_PARENT_MASK;
|
||||
return mtk_clk_mux_set_parent(priv->base, parent->id, parent_type,
|
||||
&priv->tree->muxes[clk->id - priv->tree->muxes_offs]);
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,11 @@
|
||||
|
||||
/* flags in struct mtk_clk_tree */
|
||||
|
||||
/* clk id == 0 doesn't mean it's xtal clk */
|
||||
/* clk id == 0 doesn't mean it's xtal clk
|
||||
* This doesn't apply when CLK_PARENT_MIXED is defined.
|
||||
* With CLK_PARENT_MIXED declare CLK_PARENT_XTAL for the
|
||||
* relevant parent.
|
||||
*/
|
||||
#define CLK_BYPASS_XTAL BIT(0)
|
||||
|
||||
#define HAVE_RST_BAR BIT(0)
|
||||
@@ -30,7 +34,17 @@
|
||||
#define CLK_PARENT_TOPCKGEN BIT(5)
|
||||
#define CLK_PARENT_INFRASYS BIT(6)
|
||||
#define CLK_PARENT_XTAL BIT(7)
|
||||
#define CLK_PARENT_MASK GENMASK(7, 4)
|
||||
/*
|
||||
* For CLK_PARENT_MIXED to correctly work, is required to
|
||||
* define in clk_tree flags the clk type using the alias.
|
||||
*/
|
||||
#define CLK_PARENT_MIXED BIT(8)
|
||||
#define CLK_PARENT_MASK GENMASK(8, 4)
|
||||
|
||||
/* alias to reference clk type */
|
||||
#define CLK_APMIXED CLK_PARENT_APMIXED
|
||||
#define CLK_TOPCKGEN CLK_PARENT_TOPCKGEN
|
||||
#define CLK_INFRASYS CLK_PARENT_INFRASYS
|
||||
|
||||
#define ETHSYS_HIFSYS_RST_CTRL_OFS 0x34
|
||||
|
||||
@@ -97,11 +111,31 @@ struct mtk_fixed_factor {
|
||||
.flags = _flags, \
|
||||
}
|
||||
|
||||
/**
|
||||
* struct mtk_parent - clock parent with flags. Needed for MUX that
|
||||
* parent with mixed infracfg and topckgen.
|
||||
*
|
||||
* @id: index of parent clocks
|
||||
* @flags: hardware-specific flags (parent location,
|
||||
* infracfg, topckgen, APMIXED, xtal ...)
|
||||
*/
|
||||
struct mtk_parent {
|
||||
const int id;
|
||||
u16 flags;
|
||||
};
|
||||
|
||||
#define PARENT(_id, _flags) { \
|
||||
.id = _id, \
|
||||
.flags = _flags, \
|
||||
}
|
||||
|
||||
/**
|
||||
* struct mtk_composite - aggregate clock of mux, divider and gate clocks
|
||||
*
|
||||
* @id: index of clocks
|
||||
* @parent: index of parnet clocks
|
||||
* @parent: index of parnet clocks
|
||||
* @parent_flags: table of parent clocks with flags
|
||||
* @mux_reg: hardware-specific mux register
|
||||
* @gate_reg: hardware-specific gate register
|
||||
* @mux_mask: mask to the mux bit field
|
||||
@@ -112,7 +146,10 @@ struct mtk_fixed_factor {
|
||||
*/
|
||||
struct mtk_composite {
|
||||
const int id;
|
||||
const int *parent;
|
||||
union {
|
||||
const int *parent;
|
||||
const struct mtk_parent *parent_flags;
|
||||
};
|
||||
u32 mux_reg;
|
||||
u32 mux_set_reg;
|
||||
u32 mux_clr_reg;
|
||||
|
||||
Reference in New Issue
Block a user