summaryrefslogtreecommitdiff
path: root/drivers/clk/mediatek
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk/mediatek')
-rw-r--r--drivers/clk/mediatek/clk-mtk.c43
-rw-r--r--drivers/clk/mediatek/clk-mtk.h23
2 files changed, 55 insertions, 11 deletions
diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c
index 6c6b500d9b..450de981e9 100644
--- a/drivers/clk/mediatek/clk-mtk.c
+++ b/drivers/clk/mediatek/clk-mtk.c
@@ -67,12 +67,23 @@ static int mtk_clk_mux_set_parent(void __iomem *base, u32 parent,
if (++index == mux->num_parents)
return -EINVAL;
- /* switch mux to a select parent */
- val = readl(base + mux->mux_reg);
- val &= ~(mux->mux_mask << mux->mux_shift);
+ if (mux->flags & CLK_MUX_SETCLR_UPD) {
+ val = (mux->mux_mask << mux->mux_shift);
+ writel(val, base + mux->mux_clr_reg);
- val |= index << mux->mux_shift;
- writel(val, base + mux->mux_reg);
+ val = (index << mux->mux_shift);
+ writel(val, base + mux->mux_set_reg);
+
+ if (mux->upd_shift >= 0)
+ writel(BIT(mux->upd_shift), base + mux->upd_reg);
+ } else {
+ /* switch mux to a select parent */
+ val = readl(base + mux->mux_reg);
+ val &= ~(mux->mux_mask << mux->mux_shift);
+
+ val |= index << mux->mux_shift;
+ writel(val, base + mux->mux_reg);
+ }
return 0;
}
@@ -332,9 +343,14 @@ static int mtk_topckgen_enable(struct clk *clk)
return 0;
/* enable clock gate */
- val = readl(priv->base + mux->gate_reg);
- val &= ~BIT(mux->gate_shift);
- writel(val, priv->base + mux->gate_reg);
+ if (mux->flags & CLK_MUX_SETCLR_UPD) {
+ val = BIT(mux->gate_shift);
+ writel(val, priv->base + mux->mux_clr_reg);
+ } else {
+ val = readl(priv->base + mux->gate_reg);
+ val &= ~BIT(mux->gate_shift);
+ writel(val, priv->base + mux->gate_reg);
+ }
if (mux->flags & CLK_DOMAIN_SCPSYS) {
/* enable scpsys clock off control */
@@ -360,9 +376,14 @@ static int mtk_topckgen_disable(struct clk *clk)
return 0;
/* disable clock gate */
- val = readl(priv->base + mux->gate_reg);
- val |= BIT(mux->gate_shift);
- writel(val, priv->base + mux->gate_reg);
+ if (mux->flags & CLK_MUX_SETCLR_UPD) {
+ val = BIT(mux->gate_shift);
+ writel(val, priv->base + mux->mux_set_reg);
+ } else {
+ val = readl(priv->base + mux->gate_reg);
+ val |= BIT(mux->gate_shift);
+ writel(val, priv->base + mux->gate_reg);
+ }
return 0;
}
diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
index dce93253ad..7ea0042500 100644
--- a/drivers/clk/mediatek/clk-mtk.h
+++ b/drivers/clk/mediatek/clk-mtk.h
@@ -12,6 +12,7 @@
#define HAVE_RST_BAR BIT(0)
#define CLK_DOMAIN_SCPSYS BIT(0)
+#define CLK_MUX_SETCLR_UPD BIT(1)
#define CLK_GATE_SETCLR BIT(0)
#define CLK_GATE_SETCLR_INV BIT(1)
@@ -102,9 +103,13 @@ struct mtk_composite {
const int id;
const int *parent;
u32 mux_reg;
+ u32 mux_set_reg;
+ u32 mux_clr_reg;
+ u32 upd_reg;
u32 gate_reg;
u32 mux_mask;
signed char mux_shift;
+ signed char upd_shift;
signed char gate_shift;
signed char num_parents;
u16 flags;
@@ -137,6 +142,24 @@ struct mtk_composite {
.flags = 0, \
}
+#define MUX_CLR_SET_UPD_FLAGS(_id, _parents, _mux_ofs, _mux_set_ofs,\
+ _mux_clr_ofs, _shift, _width, _gate, \
+ _upd_ofs, _upd, _flags) { \
+ .id = _id, \
+ .mux_reg = _mux_ofs, \
+ .mux_set_reg = _mux_set_ofs, \
+ .mux_clr_reg = _mux_clr_ofs, \
+ .upd_reg = _upd_ofs, \
+ .upd_shift = _upd, \
+ .mux_shift = _shift, \
+ .mux_mask = BIT(_width) - 1, \
+ .gate_reg = _mux_ofs, \
+ .gate_shift = _gate, \
+ .parent = _parents, \
+ .num_parents = ARRAY_SIZE(_parents), \
+ .flags = _flags, \
+ }
+
struct mtk_gate_regs {
u32 sta_ofs;
u32 clr_ofs;