]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
clk: mediatek: add support for GATEs for APMIXED OPs
authorChristian Marangi <ansuelsmth@gmail.com>
Fri, 28 Jun 2024 17:40:56 +0000 (19:40 +0200)
committerTom Rini <trini@konsulko.com>
Thu, 1 Aug 2024 21:32:18 +0000 (15:32 -0600)
Add support for GATEs for APMIXED OPs. It's possible that some APMIXED
have also gates on top of PLL. This is the case for mt7622. Add support
for this.

Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
drivers/clk/mediatek/clk-mtk.c

index c11c9918e5187bbfa9921bb11fc67d7539dae529..cdc00837bab81b233477cbc3dc86ed220567ca1c 100644 (file)
@@ -48,6 +48,56 @@ static int mtk_clk_get_id(struct clk *clk)
        return id;
 }
 
+static int mtk_gate_enable(void __iomem *base, const struct mtk_gate *gate)
+{
+       u32 bit = BIT(gate->shift);
+
+       switch (gate->flags & CLK_GATE_MASK) {
+       case CLK_GATE_SETCLR:
+               writel(bit, base + gate->regs->clr_ofs);
+               break;
+       case CLK_GATE_SETCLR_INV:
+               writel(bit, base + gate->regs->set_ofs);
+               break;
+       case CLK_GATE_NO_SETCLR:
+               clrsetbits_le32(base + gate->regs->sta_ofs, bit, 0);
+               break;
+       case CLK_GATE_NO_SETCLR_INV:
+               clrsetbits_le32(base + gate->regs->sta_ofs, bit, bit);
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int mtk_gate_disable(void __iomem *base, const struct mtk_gate *gate)
+{
+       u32 bit = BIT(gate->shift);
+
+       switch (gate->flags & CLK_GATE_MASK) {
+       case CLK_GATE_SETCLR:
+               writel(bit, base + gate->regs->set_ofs);
+               break;
+       case CLK_GATE_SETCLR_INV:
+               writel(bit, base + gate->regs->clr_ofs);
+               break;
+       case CLK_GATE_NO_SETCLR:
+               clrsetbits_le32(base + gate->regs->sta_ofs, bit, bit);
+               break;
+       case CLK_GATE_NO_SETCLR_INV:
+               clrsetbits_le32(base + gate->regs->sta_ofs, bit, 0);
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 /*
  * In case the rate change propagation to parent clocks is undesirable,
  * this function is recursively called to find the parent to calculate
@@ -144,11 +194,10 @@ static unsigned long __mtk_pll_recalc_rate(const struct mtk_pll_data *pll,
  * for the integer part and the remaining bits (if present) for the
  * fractional part. Also they have a 3 bit power-of-two post divider.
  */
-static void mtk_pll_set_rate_regs(struct clk *clk, u32 pcw, int postdiv)
+static void mtk_pll_set_rate_regs(struct mtk_clk_priv *priv, u32 id,
+                                 u32 pcw, int postdiv)
 {
-       struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
        const struct mtk_pll_data *pll;
-       int id = mtk_clk_get_id(clk);
        u32 val, chg;
 
        pll = &priv->tree->plls[id];
@@ -183,17 +232,16 @@ static void mtk_pll_set_rate_regs(struct clk *clk, u32 pcw, int postdiv)
 
 /**
  * mtk_pll_calc_values - calculate good values for a given input frequency.
- * @clk:       The clk
+ * @priv:      The mtk priv struct
+ * @id:                The clk id
  * @pcw:       The pcw value (output)
  * @postdiv:   The post divider (output)
  * @freq:      The desired target frequency
  */
-static void mtk_pll_calc_values(struct clk *clk, u32 *pcw, u32 *postdiv,
-                               u32 freq)
+static void mtk_pll_calc_values(struct mtk_clk_priv *priv, u32 id,
+                               u32 *pcw, u32 *postdiv, u32 freq)
 {
-       struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
        const struct mtk_pll_data *pll;
-       int id = mtk_clk_get_id(clk);
        unsigned long fmin;
        u64 _pcw;
        int ibits;
@@ -221,11 +269,16 @@ static void mtk_pll_calc_values(struct clk *clk, u32 *pcw, u32 *postdiv,
 
 static ulong mtk_apmixedsys_set_rate(struct clk *clk, ulong rate)
 {
+       struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
+       int id = mtk_clk_get_id(clk);
        u32 pcw = 0;
        u32 postdiv;
 
-       mtk_pll_calc_values(clk, &pcw, &postdiv, rate);
-       mtk_pll_set_rate_regs(clk, pcw, postdiv);
+       if (priv->tree->gates && id >= priv->tree->gates_offs)
+               return -EINVAL;
+
+       mtk_pll_calc_values(priv, id, &pcw, &postdiv, rate);
+       mtk_pll_set_rate_regs(priv, id, pcw, postdiv);
 
        return 0;
 }
@@ -235,9 +288,16 @@ static ulong mtk_apmixedsys_get_rate(struct clk *clk)
        struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
        const struct mtk_pll_data *pll;
        int id = mtk_clk_get_id(clk);
+       const struct mtk_gate *gate;
        u32 postdiv;
        u32 pcw;
 
+       /* GATE handling */
+       if (priv->tree->gates && id >= priv->tree->gates_offs) {
+               gate = &priv->tree->gates[id - priv->tree->gates_offs];
+               return mtk_clk_find_parent_rate(clk, gate->parent, NULL);
+       }
+
        pll = &priv->tree->plls[id];
 
        postdiv = (readl(priv->base + pll->pd_reg) >> pll->pd_shift) &
@@ -256,8 +316,15 @@ static int mtk_apmixedsys_enable(struct clk *clk)
        struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
        const struct mtk_pll_data *pll;
        int id = mtk_clk_get_id(clk);
+       const struct mtk_gate *gate;
        u32 r;
 
+       /* GATE handling */
+       if (priv->tree->gates && id >= priv->tree->gates_offs) {
+               gate = &priv->tree->gates[id - priv->tree->gates_offs];
+               return mtk_gate_enable(priv->base, gate);
+       }
+
        pll = &priv->tree->plls[id];
 
        r = readl(priv->base + pll->pwr_reg) | CON0_PWR_ON;
@@ -288,8 +355,15 @@ static int mtk_apmixedsys_disable(struct clk *clk)
        struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
        const struct mtk_pll_data *pll;
        int id = mtk_clk_get_id(clk);
+       const struct mtk_gate *gate;
        u32 r;
 
+       /* GATE handling */
+       if (priv->tree->gates && id >= priv->tree->gates_offs) {
+               gate = &priv->tree->gates[id - priv->tree->gates_offs];
+               return mtk_gate_disable(priv->base, gate);
+       }
+
        pll = &priv->tree->plls[id];
 
        if (pll->flags & HAVE_RST_BAR) {
@@ -581,31 +655,6 @@ static int mtk_common_clk_set_parent(struct clk *clk, struct clk *parent)
 
 /* CG functions */
 
-static int mtk_gate_enable(void __iomem *base, const struct mtk_gate *gate)
-{
-       u32 bit = BIT(gate->shift);
-
-       switch (gate->flags & CLK_GATE_MASK) {
-       case CLK_GATE_SETCLR:
-               writel(bit, base + gate->regs->clr_ofs);
-               break;
-       case CLK_GATE_SETCLR_INV:
-               writel(bit, base + gate->regs->set_ofs);
-               break;
-       case CLK_GATE_NO_SETCLR:
-               clrsetbits_le32(base + gate->regs->sta_ofs, bit, 0);
-               break;
-       case CLK_GATE_NO_SETCLR_INV:
-               clrsetbits_le32(base + gate->regs->sta_ofs, bit, bit);
-               break;
-
-       default:
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
 static int mtk_clk_gate_enable(struct clk *clk)
 {
        struct mtk_cg_priv *priv = dev_get_priv(clk->dev);
@@ -633,31 +682,6 @@ static int mtk_clk_infrasys_enable(struct clk *clk)
        return mtk_gate_enable(priv->base, gate);
 }
 
-static int mtk_gate_disable(void __iomem *base, const struct mtk_gate *gate)
-{
-       u32 bit = BIT(gate->shift);
-
-       switch (gate->flags & CLK_GATE_MASK) {
-       case CLK_GATE_SETCLR:
-               writel(bit, base + gate->regs->set_ofs);
-               break;
-       case CLK_GATE_SETCLR_INV:
-               writel(bit, base + gate->regs->clr_ofs);
-               break;
-       case CLK_GATE_NO_SETCLR:
-               clrsetbits_le32(base + gate->regs->sta_ofs, bit, bit);
-               break;
-       case CLK_GATE_NO_SETCLR_INV:
-               clrsetbits_le32(base + gate->regs->sta_ofs, bit, 0);
-               break;
-
-       default:
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
 static int mtk_clk_gate_disable(struct clk *clk)
 {
        struct mtk_cg_priv *priv = dev_get_priv(clk->dev);