All of lore.kernel.org
 help / color / mirror / Atom feed
From: "周琰杰 (Zhou Yanjie)" <zhouyanjie@wanyeetech.com>
To: mturquette@baylibre.com, sboyd@kernel.org, robh+dt@kernel.org
Cc: linux-mips@vger.kernel.org, linux-clk@vger.kernel.org,
	linux-kernel@vger.kernel.org, devicetree@vger.kernel.org,
	paul@crapouillou.net, dongsheng.qiu@ingenic.com,
	aric.pzqi@ingenic.com, rick.tyliu@ingenic.com,
	sihui.liu@ingenic.com, jun.jiang@ingenic.com,
	sernia.zhou@foxmail.com
Subject: [PATCH v5 02/11] clk: Ingenic: Adjust cgu code to make it compatible with I2S PLL.
Date: Tue, 29 Jun 2021 02:20:35 +0800	[thread overview]
Message-ID: <1624904444-2618-3-git-send-email-zhouyanjie@wanyeetech.com> (raw)
In-Reply-To: <1624904444-2618-1-git-send-email-zhouyanjie@wanyeetech.com>

I2S PLL is different from the APLL/MPLL, which have no OD bits,
no stable bit, but have parent clock selection bits, therefore,
it is necessary to modify the CGU PLL correlation code to make
it compatible with I2S PLL.

Signed-off-by: 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
---

Notes:
    v5:
    New patch.

 drivers/clk/ingenic/cgu.c | 118 ++++++++++++++++++++++++++++++++++++++++------
 drivers/clk/ingenic/cgu.h |   1 +
 2 files changed, 104 insertions(+), 15 deletions(-)

diff --git a/drivers/clk/ingenic/cgu.c b/drivers/clk/ingenic/cgu.c
index 266c759..391bf50 100644
--- a/drivers/clk/ingenic/cgu.c
+++ b/drivers/clk/ingenic/cgu.c
@@ -76,6 +76,85 @@ ingenic_cgu_gate_set(struct ingenic_cgu *cgu,
  * PLL operations
  */
 
+static u8 ingenic_pll_get_parent(struct clk_hw *hw)
+{
+	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
+	const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);
+	struct ingenic_cgu *cgu = ingenic_clk->cgu;
+	const struct ingenic_cgu_pll_info *pll_info;
+	u32 reg;
+	u8 i, hw_idx, idx = 0;
+
+	BUG_ON(clk_info->type != CGU_CLK_PLL);
+	pll_info = &clk_info->pll;
+
+	if (pll_info->mux_bits <= 0)
+		return 1;
+
+	reg = readl(cgu->base + pll_info->reg);
+	hw_idx = (reg >> pll_info->mux_shift) &
+		 GENMASK(pll_info->mux_bits - 1, 0);
+
+	/*
+	 * Convert the hardware index to the parent index by skipping
+	 * over any -1's in the parents array.
+	 */
+	for (i = 0; i < hw_idx; i++) {
+		if (clk_info->parents[i] != -1)
+			idx++;
+	}
+
+	return idx;
+}
+
+static int ingenic_pll_set_parent(struct clk_hw *hw, u8 idx)
+{
+	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
+	const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);
+	struct ingenic_cgu *cgu = ingenic_clk->cgu;
+	const struct ingenic_cgu_pll_info *pll_info;
+	unsigned long flags;
+	u32 reg;
+	u8 curr_idx, hw_idx, num_poss;
+
+	BUG_ON(clk_info->type != CGU_CLK_PLL);
+	pll_info = &clk_info->pll;
+
+	if (pll_info->mux_bits <= 0)
+		return 0;
+
+	/*
+	 * Convert the parent index to the hardware index by adding
+	 * 1 for any -1 in the parents array preceding the given
+	 * index. That is, we want the index of idx'th entry in
+	 * clk_info->parents which does not equal -1.
+	 */
+	hw_idx = curr_idx = 0;
+	num_poss = 1 << pll_info->mux_bits;
+	for (; hw_idx < num_poss; hw_idx++) {
+		if (clk_info->parents[hw_idx] == -1)
+			continue;
+		if (curr_idx == idx)
+			break;
+		curr_idx++;
+	}
+
+	/* idx should always be a valid parent */
+	BUG_ON(curr_idx != idx);
+
+	spin_lock_irqsave(&cgu->lock, flags);
+
+	/* write the register */
+	reg = readl(cgu->base + pll_info->reg);
+	reg &= ~(GENMASK(pll_info->mux_bits - 1, 0) << pll_info->mux_shift);
+	reg |= hw_idx << pll_info->mux_shift;
+	writel(reg, cgu->base + pll_info->reg);
+
+	spin_unlock_irqrestore(&cgu->lock, flags);
+
+	return 0;
+}
+
 static unsigned long
 ingenic_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
 {
@@ -96,8 +175,20 @@ ingenic_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
 	m += pll_info->m_offset;
 	n = (ctl >> pll_info->n_shift) & GENMASK(pll_info->n_bits - 1, 0);
 	n += pll_info->n_offset;
-	od_enc = ctl >> pll_info->od_shift;
-	od_enc &= GENMASK(pll_info->od_bits - 1, 0);
+
+	if (pll_info->od_encoding) {
+		od_enc = ctl >> pll_info->od_shift;
+		od_enc &= GENMASK(pll_info->od_bits - 1, 0);
+
+		for (od = 0; od < pll_info->od_max; od++) {
+			if (pll_info->od_encoding[od] == od_enc)
+				break;
+		}
+		BUG_ON(od == pll_info->od_max);
+		od++;
+	} else {
+		od = 1;
+	}
 
 	if (pll_info->bypass_bit >= 0) {
 		ctl = readl(cgu->base + pll_info->bypass_reg);
@@ -108,15 +199,7 @@ ingenic_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
 			return parent_rate;
 	}
 
-	for (od = 0; od < pll_info->od_max; od++) {
-		if (pll_info->od_encoding[od] == od_enc)
-			break;
-	}
-	BUG_ON(od == pll_info->od_max);
-	od++;
-
-	return div_u64((u64)parent_rate * m * pll_info->rate_multiplier,
-		n * od);
+	return div_u64((u64)parent_rate * m * pll_info->rate_multiplier, n * od);
 }
 
 static void
@@ -215,13 +298,15 @@ ingenic_pll_set_rate(struct clk_hw *hw, unsigned long req_rate,
 	ctl &= ~(GENMASK(pll_info->n_bits - 1, 0) << pll_info->n_shift);
 	ctl |= (n - pll_info->n_offset) << pll_info->n_shift;
 
-	ctl &= ~(GENMASK(pll_info->od_bits - 1, 0) << pll_info->od_shift);
-	ctl |= pll_info->od_encoding[od - 1] << pll_info->od_shift;
+	if (pll_info->od_encoding) {
+		ctl &= ~(GENMASK(pll_info->od_bits - 1, 0) << pll_info->od_shift);
+		ctl |= pll_info->od_encoding[od - 1] << pll_info->od_shift;
+	}
 
 	writel(ctl, cgu->base + pll_info->reg);
 
 	/* If the PLL is enabled, verify that it's stable */
-	if (ctl & BIT(pll_info->enable_bit))
+	if ((pll_info->stable_bit >= 0) && (ctl & BIT(pll_info->enable_bit)))
 		ret = ingenic_pll_check_stable(cgu, pll_info);
 
 	spin_unlock_irqrestore(&cgu->lock, flags);
@@ -292,6 +377,9 @@ static int ingenic_pll_is_enabled(struct clk_hw *hw)
 }
 
 static const struct clk_ops ingenic_pll_ops = {
+	.get_parent = ingenic_pll_get_parent,
+	.set_parent = ingenic_pll_set_parent,
+
 	.recalc_rate = ingenic_pll_recalc_rate,
 	.round_rate = ingenic_pll_round_rate,
 	.set_rate = ingenic_pll_set_rate,
@@ -672,7 +760,7 @@ static int ingenic_register_clock(struct ingenic_cgu *cgu, unsigned idx)
 		clk_init.flags |= CLK_SET_RATE_PARENT;
 	}
 
-	if (caps & (CGU_CLK_MUX | CGU_CLK_CUSTOM)) {
+	if (caps & (CGU_CLK_PLL | CGU_CLK_MUX | CGU_CLK_CUSTOM)) {
 		clk_init.num_parents = 0;
 
 		if (caps & CGU_CLK_MUX)
diff --git a/drivers/clk/ingenic/cgu.h b/drivers/clk/ingenic/cgu.h
index bfc2b9c..87d716e 100644
--- a/drivers/clk/ingenic/cgu.h
+++ b/drivers/clk/ingenic/cgu.h
@@ -48,6 +48,7 @@ struct ingenic_cgu_pll_info {
 	unsigned reg;
 	unsigned rate_multiplier;
 	const s8 *od_encoding;
+	u8 mux_shift, mux_bits;
 	u8 m_shift, m_bits, m_offset;
 	u8 n_shift, n_bits, n_offset;
 	u8 od_shift, od_bits, od_max;
-- 
2.7.4


  parent reply	other threads:[~2021-06-28 18:21 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-06-28 18:20 [PATCH v5 00/11] Add new clocks and fix bugs for Ingenic SoCs 周琰杰 (Zhou Yanjie)
2021-06-28 18:20 ` [PATCH v5 01/11] clk: JZ4780: Add function for disable the second core 周琰杰 (Zhou Yanjie)
2021-06-28 18:20 ` 周琰杰 (Zhou Yanjie) [this message]
2021-06-28 22:32   ` [PATCH v5 02/11] clk: Ingenic: Adjust cgu code to make it compatible with I2S PLL kernel test robot
2021-06-28 22:32     ` kernel test robot
2021-06-28 18:20 ` [PATCH v5 03/11] dt-bindings: clock: Add missing clocks for Ingenic SoCs 周琰杰 (Zhou Yanjie)
2021-06-28 18:20 ` [PATCH v5 04/11] clk: Ingenic: Fix problem of MAC clock in Ingenic X1000 and X1830 周琰杰 (Zhou Yanjie)
2021-06-28 18:20 ` [PATCH v5 05/11] clk: Ingenic: Add missing clocks for Ingenic SoCs 周琰杰 (Zhou Yanjie)
2021-06-28 18:20 ` [PATCH v5 06/11] clk: Ingenic: Clean up and reformat the code 周琰杰 (Zhou Yanjie)
2021-06-28 18:20 ` [PATCH v5 07/11] dt-bindings: clock: Add documentation for JZ4775 and X2000 bindings 周琰杰 (Zhou Yanjie)
2021-06-28 18:20 ` [PATCH v5 08/11] dt-bindings: clock: Add JZ4775 clock bindings 周琰杰 (Zhou Yanjie)
2021-06-28 18:20 ` [PATCH v5 09/11] dt-bindings: clock: Add X2000 " 周琰杰 (Zhou Yanjie)
2021-06-28 18:20 ` [PATCH v5 10/11] clk: Ingenic: Add CGU driver for JZ4775 周琰杰 (Zhou Yanjie)
2021-06-28 18:20 ` [PATCH v5 11/11] clk: Ingenic: Add CGU driver for X2000 周琰杰 (Zhou Yanjie)

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1624904444-2618-3-git-send-email-zhouyanjie@wanyeetech.com \
    --to=zhouyanjie@wanyeetech.com \
    --cc=aric.pzqi@ingenic.com \
    --cc=devicetree@vger.kernel.org \
    --cc=dongsheng.qiu@ingenic.com \
    --cc=jun.jiang@ingenic.com \
    --cc=linux-clk@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mips@vger.kernel.org \
    --cc=mturquette@baylibre.com \
    --cc=paul@crapouillou.net \
    --cc=rick.tyliu@ingenic.com \
    --cc=robh+dt@kernel.org \
    --cc=sboyd@kernel.org \
    --cc=sernia.zhou@foxmail.com \
    --cc=sihui.liu@ingenic.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.