Skip to contentSkip to conversation

clk: qcom: Add DSI clocks for MSM8960/APQ8064

PATCH Applied Archit Taneja 2 participants 6 messages Oct 14, 2015 – Oct 19, 2015

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

cover clk: qcom: Add DSI clocks for MSM8960/APQ8064

Add DSI related clocks 8960/8064. The changes are similar to what we have for newer chipsets(clk-rcg2), with some minor differences.

Archit Taneja (2):
clk: qcom: clk-rcg: Add customized clk_ops for DSI RCGs
clk: qcom: mmcc-8960: Add DSI related clocks

 drivers/clk/qcom/clk-rcg.c      | 233 +++++++++++++++++++++++
 drivers/clk/qcom/clk-rcg.h      |   3 +
 drivers/clk/qcom/mmcc-msm8960.c | 404 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 640 insertions(+)
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
#1 lore raw

PATCH 1/2 clk: qcom: clk-rcg: Add customized clk_ops for DSI RCGs

DSI specific RCG clocks required customized clk_ops. There are a total of 4 RCGs per DSI block: DSI, BYTE, ESC and PIXEL.

There are a total of 2 clocks coming from the DSI PLL, which serve as inputs to these RCGs. The BYTE and ESC RCGs are fed by one of the post dividers of DSI1 or DSI2 PLLs, and the DSI and PIXEL RCGs are fed by another divider of the PLL.

In each of the 2 groups above, only one of the clocks sets its parent. These are BYTE RCG and DSI RCG for each of the groups respectively, as shown in the diagram below.

The DSI and BYTE RCGs serve as bypass clocks. We create a new set of ops clk_rcg_bypass2_ops, which are like the regular bypass ops, but don't take in a freq table, since the DSI driver using these clocks is parent-able.

The PIXEL RCG needs to derive the required pixel clock using dsixpll. It parses a m/n frac table to retrieve the correct clock.

The ESC RCG doesn't have a frac M/N block, it can just apply a pre- divider. Its ops simply check if the required clock rate can be achieved by the pre-divider.

      +-------------------+
      |                   |---dsixpllbyte---o---> To byte RCG
      |                   |                 | (sets parent rate)
      |                   |                 |
      |                   |                 |
      |    DSI 1/2 PLL    |                 |
      |                   |                 o---> To esc RCG
      |                   |                 (doesn't set parent rate)
      |                   |
      |                   |----dsixpll-----o---> To dsi RCG
      +-------------------+                | (sets parent rate)
                             ( x = 1, 2 )  |
                                           |

o---> To pixel rcg (doesn't set parent rate)

---
 drivers/clk/qcom/clk-rcg.c | 233 +++++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/qcom/clk-rcg.h |   3 +
 2 files changed, 236 insertions(+)
drivers/clk/qcom/clk-rcg.c +233 -0
index bccedc4..46ff9f2 100644
@@ -542,6 +542,203 @@ static int clk_rcg_bypass_set_rate(struct clk_hw *hw, unsigned long rate,
 	return __clk_rcg_set_rate(rcg, rcg->freq_tbl);
 }
 
+static int clk_rcg_bypass2_determine_rate(struct clk_hw *hw,
+				struct clk_rate_request *req)
+{
+	struct clk_hw *p;
+
+	p = req->best_parent_hw;
+	req->best_parent_rate = clk_hw_round_rate(p, req->rate);
+	req->rate = req->best_parent_rate;
+
+	return 0;
+}
+
+static int clk_rcg_bypass2_set_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long parent_rate)
+{
+	struct clk_rcg *rcg = to_clk_rcg(hw);
+	struct freq_tbl f = { 0 };
+	u32 ns, src;
+	int i, ret, num_parents = clk_hw_get_num_parents(hw);
+
+	ret = regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns);
+	if (ret)
+		goto err;
+
+	src = ns_to_src(&rcg->s, ns);
+	f.pre_div = ns_to_pre_div(&rcg->p, ns) + 1;
+
+	for (i = 0; i < num_parents; i++) {
+		if (src == rcg->s.parent_map[i].cfg) {
+			f.src = rcg->s.parent_map[i].src;
+			return __clk_rcg_set_rate(rcg, &f);
+		}
+	}
+
+err:
+	return -EINVAL;
+}
+
+static int clk_rcg_bypass2_set_rate_and_parent(struct clk_hw *hw,
+		unsigned long rate, unsigned long parent_rate, u8 index)
+{
+	/* Read the hardware to determine parent during set_rate */
+	return clk_rcg_bypass2_set_rate(hw, rate, parent_rate);
+}
+
+struct frac_entry {
+	int num;
+	int den;
+};
+
+static const struct frac_entry pixel_table[] = {
+	{ 1, 2 },
+	{ 1, 3 },
+	{ 3, 16 },
+	{ }
+};
+
+static int clk_rcg_pixel_determine_rate(struct clk_hw *hw,
+		struct clk_rate_request *req)
+{
+	int delta = 100000;
+	const struct frac_entry *frac = pixel_table;
+	unsigned long request, src_rate;
+
+	for (; frac->num; frac++) {
+		request = (req->rate * frac->den) / frac->num;
+
+		src_rate = clk_hw_round_rate(req->best_parent_hw, request);
+
+		if ((src_rate < (request - delta)) ||
+			(src_rate > (request + delta)))
+			continue;
+
+		req->best_parent_rate = src_rate;
+		req->rate = (src_rate * frac->num) / frac->den;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static int clk_rcg_pixel_set_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long parent_rate)
+{
+	struct clk_rcg *rcg = to_clk_rcg(hw);
+	int delta = 100000;
+	const struct frac_entry *frac = pixel_table;
+	unsigned long request;
+	struct freq_tbl f = { 0 };
+	u32 ns, src;
+	int i, ret, num_parents = clk_hw_get_num_parents(hw);
+
+	ret = regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns);
+	if (ret)
+		goto err;
+
+	src = ns_to_src(&rcg->s, ns);
+	f.pre_div = ns_to_pre_div(&rcg->p, ns) + 1;
+
+	for (i = 0; i < num_parents; i++) {
+		if (src == rcg->s.parent_map[i].cfg) {
+			f.src = rcg->s.parent_map[i].src;
+			break;
+		}
+	}
+
+	/* let us find appropriate m/n values for this */
+	for (; frac->num; frac++) {
+		request = (rate * frac->den) / frac->num;
+
+		if ((parent_rate < (request - delta)) ||
+			(parent_rate > (request + delta)))
+			continue;
+
+		f.m = frac->num;
+		f.n = frac->den;
+
+		return __clk_rcg_set_rate(rcg, &f);
+	}
+
+err:
+	return -EINVAL;
+}
+
+static int clk_rcg_pixel_set_rate_and_parent(struct clk_hw *hw,
+		unsigned long rate, unsigned long parent_rate, u8 index)
+{
+	return clk_rcg_pixel_set_rate(hw, rate, parent_rate);
+}
+
+static int clk_rcg_esc_determine_rate(struct clk_hw *hw,
+		struct clk_rate_request *req)
+{
+	struct clk_rcg *rcg = to_clk_rcg(hw);
+	int pre_div_max = BIT(rcg->p.pre_div_width);
+	int div;
+	unsigned long src_rate;
+
+	if (req->rate == 0)
+		return -EINVAL;
+
+	src_rate = clk_hw_get_rate(req->best_parent_hw);
+
+	div = src_rate / req->rate;
+
+	if (div >= 1 && div <= pre_div_max) {
+		req->best_parent_rate = src_rate;
+		req->rate = src_rate / div;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static int clk_rcg_esc_set_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long parent_rate)
+{
+	struct clk_rcg *rcg = to_clk_rcg(hw);
+	struct freq_tbl f = { 0 };
+	int pre_div_max = BIT(rcg->p.pre_div_width);
+	int div;
+	u32 ns;
+	int i, ret, num_parents = clk_hw_get_num_parents(hw);
+
+	if (rate == 0)
+		return -EINVAL;
+
+	ret = regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns);
+	if (ret)
+		goto err;
+
+	ns = ns_to_src(&rcg->s, ns);
+
+	for (i = 0; i < num_parents; i++) {
+		if (ns == rcg->s.parent_map[i].cfg) {
+			f.src = rcg->s.parent_map[i].src;
+			break;
+		}
+	}
+
+	div = parent_rate / rate;
+
+	if (div >= 1 && div <= pre_div_max) {
+		f.pre_div = div;
+		return __clk_rcg_set_rate(rcg, &f);
+	}
+
+err:
+	return -EINVAL;
+}
+
+static int clk_rcg_esc_set_rate_and_parent(struct clk_hw *hw,
+		unsigned long rate, unsigned long parent_rate, u8 index)
+{
+	return clk_rcg_esc_set_rate(hw, rate, parent_rate);
+}
+
 /*
  * This type of clock has a glitch-free mux that switches between the output of
  * the M/N counter and an always on clock source (XO). When clk_set_rate() is
@@ -639,6 +836,42 @@ const struct clk_ops clk_rcg_bypass_ops = {
 };
 EXPORT_SYMBOL_GPL(clk_rcg_bypass_ops);
 
+const struct clk_ops clk_rcg_bypass2_ops = {
+	.enable = clk_enable_regmap,
+	.disable = clk_disable_regmap,
+	.get_parent = clk_rcg_get_parent,
+	.set_parent = clk_rcg_set_parent,
+	.recalc_rate = clk_rcg_recalc_rate,
+	.determine_rate = clk_rcg_bypass2_determine_rate,
+	.set_rate = clk_rcg_bypass2_set_rate,
+	.set_rate_and_parent = clk_rcg_bypass2_set_rate_and_parent,
+};
+EXPORT_SYMBOL_GPL(clk_rcg_bypass2_ops);
+
+const struct clk_ops clk_rcg_pixel_ops = {
+	.enable = clk_enable_regmap,
+	.disable = clk_disable_regmap,
+	.get_parent = clk_rcg_get_parent,
+	.set_parent = clk_rcg_set_parent,
+	.recalc_rate = clk_rcg_recalc_rate,
+	.determine_rate = clk_rcg_pixel_determine_rate,
+	.set_rate = clk_rcg_pixel_set_rate,
+	.set_rate_and_parent = clk_rcg_pixel_set_rate_and_parent,
+};
+EXPORT_SYMBOL_GPL(clk_rcg_pixel_ops);
+
+const struct clk_ops clk_rcg_esc_ops = {
+	.enable = clk_enable_regmap,
+	.disable = clk_disable_regmap,
+	.get_parent = clk_rcg_get_parent,
+	.set_parent = clk_rcg_set_parent,
+	.recalc_rate = clk_rcg_recalc_rate,
+	.determine_rate = clk_rcg_esc_determine_rate,
+	.set_rate = clk_rcg_esc_set_rate,
+	.set_rate_and_parent = clk_rcg_esc_set_rate_and_parent,
+};
+EXPORT_SYMBOL_GPL(clk_rcg_esc_ops);
+
 const struct clk_ops clk_rcg_lcc_ops = {
 	.enable = clk_rcg_lcc_enable,
 	.disable = clk_rcg_lcc_disable,
drivers/clk/qcom/clk-rcg.h +3 -0
index 56028bb..cfe59b8 100644
@@ -106,6 +106,9 @@ struct clk_rcg {
 
 extern const struct clk_ops clk_rcg_ops;
 extern const struct clk_ops clk_rcg_bypass_ops;
+extern const struct clk_ops clk_rcg_bypass2_ops;
+extern const struct clk_ops clk_rcg_pixel_ops;
+extern const struct clk_ops clk_rcg_esc_ops;
 extern const struct clk_ops clk_rcg_lcc_ops;
 
 #define to_clk_rcg(_hw) container_of(to_clk_regmap(_hw), struct clk_rcg, clkr)
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
Applied
#2 lore raw

Re: [PATCH 1/2] clk: qcom: clk-rcg: Add customized clk_ops for DSI RCGs

Quoted 37 lines · Archit Taneja

DSI specific RCG clocks required customized clk_ops. There are a total of 4 RCGs per DSI block: DSI, BYTE, ESC and PIXEL.

There are a total of 2 clocks coming from the DSI PLL, which serve as inputs to these RCGs. The BYTE and ESC RCGs are fed by one of the post dividers of DSI1 or DSI2 PLLs, and the DSI and PIXEL RCGs are fed by another divider of the PLL.

In each of the 2 groups above, only one of the clocks sets its parent. These are BYTE RCG and DSI RCG for each of the groups respectively, as shown in the diagram below.

The DSI and BYTE RCGs serve as bypass clocks. We create a new set of ops clk_rcg_bypass2_ops, which are like the regular bypass ops, but don't take in a freq table, since the DSI driver using these clocks is parent-able.

The PIXEL RCG needs to derive the required pixel clock using dsixpll. It parses a m/n frac table to retrieve the correct clock.

The ESC RCG doesn't have a frac M/N block, it can just apply a pre- divider. Its ops simply check if the required clock rate can be achieved by the pre-divider.

      +-------------------+
      |                   |---dsixpllbyte---o---> To byte RCG
      |                   |                 | (sets parent rate)
      |                   |                 |
      |                   |                 |
      |    DSI 1/2 PLL    |                 |
      |                   |                 o---> To esc RCG
      |                   |                 (doesn't set parent rate)
      |                   |
      |                   |----dsixpll-----o---> To dsi RCG
      +-------------------+                | (sets parent rate)
                             ( x = 1, 2 )  |
                                           |
Quoted 5 lines

o---> To pixel rcg (doesn't set parent rate)

---

Applied to clk-next +

----8<----

drivers/clk/qcom/clk-rcg.c +3 -6
index 46ff9f25cd97..bfbb28f450c2 100644
@@ -564,7 +564,7 @@ static int clk_rcg_bypass2_set_rate(struct clk_hw *hw, unsigned long rate,
 
 	ret = regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns);
 	if (ret)
-		goto err;
+		return ret;
 
 	src = ns_to_src(&rcg->s, ns);
 	f.pre_div = ns_to_pre_div(&rcg->p, ns) + 1;
@@ -576,7 +576,6 @@ static int clk_rcg_bypass2_set_rate(struct clk_hw *hw, unsigned long rate,
 		}
 	}
 
-err:
 	return -EINVAL;
 }
 
@@ -636,7 +635,7 @@ static int clk_rcg_pixel_set_rate(struct clk_hw *hw, unsigned long rate,
 
 	ret = regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns);
 	if (ret)
-		goto err;
+		return ret;
 
 	src = ns_to_src(&rcg->s, ns);
 	f.pre_div = ns_to_pre_div(&rcg->p, ns) + 1;
@@ -662,7 +661,6 @@ static int clk_rcg_pixel_set_rate(struct clk_hw *hw, unsigned long rate,
 		return __clk_rcg_set_rate(rcg, &f);
 	}
 
-err:
 	return -EINVAL;
 }
 
@@ -711,7 +709,7 @@ static int clk_rcg_esc_set_rate(struct clk_hw *hw, unsigned long rate,
 
 	ret = regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns);
 	if (ret)
-		goto err;
+		return ret;
 
 	ns = ns_to_src(&rcg->s, ns);
 
@@ -729,7 +727,6 @@ static int clk_rcg_esc_set_rate(struct clk_hw *hw, unsigned long rate,
 		return __clk_rcg_set_rate(rcg, &f);
 	}
 
-err:
 	return -EINVAL;
 }
 
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
#3 lore raw

Re: [PATCH 1/2] clk: qcom: clk-rcg: Add customized clk_ops for DSI RCGs

Quoted 41 lines · Stephen Boyd
Quoted 40 lines · Archit Taneja

DSI specific RCG clocks required customized clk_ops. There are a total of 4 RCGs per DSI block: DSI, BYTE, ESC and PIXEL.

There are a total of 2 clocks coming from the DSI PLL, which serve as inputs to these RCGs. The BYTE and ESC RCGs are fed by one of the post dividers of DSI1 or DSI2 PLLs, and the DSI and PIXEL RCGs are fed by another divider of the PLL.

In each of the 2 groups above, only one of the clocks sets its parent. These are BYTE RCG and DSI RCG for each of the groups respectively, as shown in the diagram below.

The DSI and BYTE RCGs serve as bypass clocks. We create a new set of ops clk_rcg_bypass2_ops, which are like the regular bypass ops, but don't take in a freq table, since the DSI driver using these clocks is parent-able.

The PIXEL RCG needs to derive the required pixel clock using dsixpll. It parses a m/n frac table to retrieve the correct clock.

The ESC RCG doesn't have a frac M/N block, it can just apply a pre- divider. Its ops simply check if the required clock rate can be achieved by the pre-divider.

       +-------------------+
       |                   |---dsixpllbyte---o---> To byte RCG
       |                   |                 | (sets parent rate)
       |                   |                 |
       |                   |                 |
       |    DSI 1/2 PLL    |                 |
       |                   |                 o---> To esc RCG
       |                   |                 (doesn't set parent rate)
       |                   |
       |                   |----dsixpll-----o---> To dsi RCG
       +-------------------+                | (sets parent rate)
                              ( x = 1, 2 )  |
                                            |

o---> To pixel rcg (doesn't set parent rate)

Quoted 4 lines
Quoted 2 lines

---

Applied to clk-next +

Thanks for the clean up!

Archit

Quoted 58 lines

----8<----

drivers/clk/qcom/clk-rcg.c +3 -6
index 46ff9f25cd97..bfbb28f450c2 100644
@@ -564,7 +564,7 @@ static int clk_rcg_bypass2_set_rate(struct clk_hw *hw, unsigned long rate,
 
  	ret = regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns);
  	if (ret)
-		goto err;
+		return ret;
 
  	src = ns_to_src(&rcg->s, ns);
  	f.pre_div = ns_to_pre_div(&rcg->p, ns) + 1;
@@ -576,7 +576,6 @@ static int clk_rcg_bypass2_set_rate(struct clk_hw *hw, unsigned long rate,
  		}
  	}
 
-err:
  	return -EINVAL;
  }
 
@@ -636,7 +635,7 @@ static int clk_rcg_pixel_set_rate(struct clk_hw *hw, unsigned long rate,
 
  	ret = regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns);
  	if (ret)
-		goto err;
+		return ret;
 
  	src = ns_to_src(&rcg->s, ns);
  	f.pre_div = ns_to_pre_div(&rcg->p, ns) + 1;
@@ -662,7 +661,6 @@ static int clk_rcg_pixel_set_rate(struct clk_hw *hw, unsigned long rate,
  		return __clk_rcg_set_rate(rcg, &f);
  	}
 
-err:
  	return -EINVAL;
  }
 
@@ -711,7 +709,7 @@ static int clk_rcg_esc_set_rate(struct clk_hw *hw, unsigned long rate,
 
  	ret = regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns);
  	if (ret)
-		goto err;
+		return ret;
 
  	ns = ns_to_src(&rcg->s, ns);
 
@@ -729,7 +727,6 @@ static int clk_rcg_esc_set_rate(struct clk_hw *hw, unsigned long rate,
  		return __clk_rcg_set_rate(rcg, &f);
  	}
 
-err:
  	return -EINVAL;
  }
 
Signature · 1 line
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
#4 lore raw

PATCH 2/2 clk: qcom: mmcc-8960: Add DSI related clocks

In reply to Archit Taneja

Add rcg and branch clk structs for DSI1 and DSI2 blocks found in MSM8960 and APQ8064. Each DSI instance has 4 pairs of rcg and branch clocks. Populate arrays mmcc_msm8960_clks and mmcc_apq8064_clks with these clocks.

---
 drivers/clk/qcom/mmcc-msm8960.c | 404 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 404 insertions(+)
drivers/clk/qcom/mmcc-msm8960.c +404 -0
index bad02ae..c564755 100644
@@ -41,6 +41,10 @@ enum {
 	P_PLL3,
 	P_PLL15,
 	P_HDMI_PLL,
+	P_DSI1_PLL_DSICLK,
+	P_DSI2_PLL_DSICLK,
+	P_DSI1_PLL_BYTECLK,
+	P_DSI2_PLL_BYTECLK,
 };
 
 #define F_MN(f, s, _m, _n) { .freq = f, .src = s, .m = _m, .n = _n }
@@ -85,6 +89,30 @@ static const char * const mmcc_pxo_pll8_pll2_pll3[] = {
 	"pll3",
 };
 
+static const struct parent_map mmcc_pxo_dsi2_dsi1_map[] = {
+	{ P_PXO, 0 },
+	{ P_DSI2_PLL_DSICLK, 1 },
+	{ P_DSI1_PLL_DSICLK, 3 },
+};
+
+static const char * const mmcc_pxo_dsi2_dsi1[] = {
+	"pxo",
+	"dsi2pll",
+	"dsi1pll",
+};
+
+static const struct parent_map mmcc_pxo_dsi1_dsi2_byte_map[] = {
+	{ P_PXO, 0 },
+	{ P_DSI1_PLL_BYTECLK, 1 },
+	{ P_DSI2_PLL_BYTECLK, 2 },
+};
+
+static const char * const mmcc_pxo_dsi1_dsi2_byte[] = {
+	"pxo",
+	"dsi1pllbyte",
+	"dsi2pllbyte",
+};
+
 static struct clk_pll pll2 = {
 	.l_reg = 0x320,
 	.m_reg = 0x324,
@@ -2042,6 +2070,350 @@ static struct clk_branch dsi2_s_ahb_clk = {
 	},
 };
 
+static struct clk_rcg dsi1_src = {
+	.ns_reg = 0x0054,
+	.md_reg = 0x0050,
+	.mn = {
+		.mnctr_en_bit = 5,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 6,
+		.n_val_shift = 24,
+		.m_val_shift = 8,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 14,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = mmcc_pxo_dsi2_dsi1_map,
+	},
+	.clkr = {
+		.enable_reg = 0x004c,
+		.enable_mask = BIT(2),
+		.hw.init = &(struct clk_init_data){
+			.name = "dsi1_src",
+			.parent_names = mmcc_pxo_dsi2_dsi1,
+			.num_parents = 3,
+			.ops = &clk_rcg_bypass2_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch dsi1_clk = {
+	.halt_reg = 0x01d0,
+	.halt_bit = 1,
+	.clkr = {
+		.enable_reg = 0x004c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "dsi1_clk",
+			.parent_names = (const char *[]){ "dsi1_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg dsi2_src = {
+	.ns_reg = 0x012c,
+	.md_reg = 0x00a8,
+	.mn = {
+		.mnctr_en_bit = 5,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 6,
+		.n_val_shift = 24,
+		.m_val_shift = 8,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 14,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = mmcc_pxo_dsi2_dsi1_map,
+	},
+	.clkr = {
+		.enable_reg = 0x003c,
+		.enable_mask = BIT(2),
+		.hw.init = &(struct clk_init_data){
+			.name = "dsi2_src",
+			.parent_names = mmcc_pxo_dsi2_dsi1,
+			.num_parents = 3,
+			.ops = &clk_rcg_bypass2_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch dsi2_clk = {
+	.halt_reg = 0x01d0,
+	.halt_bit = 2,
+	.clkr = {
+		.enable_reg = 0x003c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "dsi2_clk",
+			.parent_names = (const char *[]){ "dsi2_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg dsi1_byte_src = {
+	.ns_reg = 0x00b0,
+	.p = {
+		.pre_div_shift = 12,
+		.pre_div_width = 4,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = mmcc_pxo_dsi1_dsi2_byte_map,
+	},
+	.clkr = {
+		.enable_reg = 0x0090,
+		.enable_mask = BIT(2),
+		.hw.init = &(struct clk_init_data){
+			.name = "dsi1_byte_src",
+			.parent_names = mmcc_pxo_dsi1_dsi2_byte,
+			.num_parents = 3,
+			.ops = &clk_rcg_bypass2_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch dsi1_byte_clk = {
+	.halt_reg = 0x01cc,
+	.halt_bit = 21,
+	.clkr = {
+		.enable_reg = 0x0090,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "dsi1_byte_clk",
+			.parent_names = (const char *[]){ "dsi1_byte_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg dsi2_byte_src = {
+	.ns_reg = 0x012c,
+	.p = {
+		.pre_div_shift = 12,
+		.pre_div_width = 4,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = mmcc_pxo_dsi1_dsi2_byte_map,
+	},
+	.clkr = {
+		.enable_reg = 0x0130,
+		.enable_mask = BIT(2),
+		.hw.init = &(struct clk_init_data){
+			.name = "dsi2_byte_src",
+			.parent_names = mmcc_pxo_dsi1_dsi2_byte,
+			.num_parents = 3,
+			.ops = &clk_rcg_bypass2_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch dsi2_byte_clk = {
+	.halt_reg = 0x01cc,
+	.halt_bit = 20,
+	.clkr = {
+		.enable_reg = 0x00b4,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "dsi2_byte_clk",
+			.parent_names = (const char *[]){ "dsi2_byte_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg dsi1_esc_src = {
+	.ns_reg = 0x0011c,
+	.p = {
+		.pre_div_shift = 12,
+		.pre_div_width = 4,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = mmcc_pxo_dsi1_dsi2_byte_map,
+	},
+	.clkr = {
+		.enable_reg = 0x00cc,
+		.enable_mask = BIT(2),
+		.hw.init = &(struct clk_init_data){
+			.name = "dsi1_esc_src",
+			.parent_names = mmcc_pxo_dsi1_dsi2_byte,
+			.num_parents = 3,
+			.ops = &clk_rcg_esc_ops,
+		},
+	},
+};
+
+static struct clk_branch dsi1_esc_clk = {
+	.halt_reg = 0x01e8,
+	.halt_bit = 1,
+	.clkr = {
+		.enable_reg = 0x00cc,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "dsi1_esc_clk",
+			.parent_names = (const char *[]){ "dsi1_esc_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg dsi2_esc_src = {
+	.ns_reg = 0x00150,
+	.p = {
+		.pre_div_shift = 12,
+		.pre_div_width = 4,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = mmcc_pxo_dsi1_dsi2_byte_map,
+	},
+	.clkr = {
+		.enable_reg = 0x013c,
+		.enable_mask = BIT(2),
+		.hw.init = &(struct clk_init_data){
+			.name = "dsi2_esc_src",
+			.parent_names = mmcc_pxo_dsi1_dsi2_byte,
+			.num_parents = 3,
+			.ops = &clk_rcg_esc_ops,
+		},
+	},
+};
+
+static struct clk_branch dsi2_esc_clk = {
+	.halt_reg = 0x01e8,
+	.halt_bit = 3,
+	.clkr = {
+		.enable_reg = 0x013c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "dsi2_esc_clk",
+			.parent_names = (const char *[]){ "dsi2_esc_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg dsi1_pixel_src = {
+	.ns_reg = 0x0138,
+	.md_reg = 0x0134,
+	.mn = {
+		.mnctr_en_bit = 5,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 6,
+		.n_val_shift = 16,
+		.m_val_shift = 8,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 12,
+		.pre_div_width = 4,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = mmcc_pxo_dsi2_dsi1_map,
+	},
+	.clkr = {
+		.enable_reg = 0x0130,
+		.enable_mask = BIT(2),
+		.hw.init = &(struct clk_init_data){
+			.name = "dsi1_pixel_src",
+			.parent_names = mmcc_pxo_dsi2_dsi1,
+			.num_parents = 3,
+			.ops = &clk_rcg_pixel_ops,
+		},
+	},
+};
+
+static struct clk_branch dsi1_pixel_clk = {
+	.halt_reg = 0x01d0,
+	.halt_bit = 6,
+	.clkr = {
+		.enable_reg = 0x0130,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mdp_pclk1_clk",
+			.parent_names = (const char *[]){ "dsi1_pixel_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg dsi2_pixel_src = {
+	.ns_reg = 0x00e4,
+	.md_reg = 0x00b8,
+	.mn = {
+		.mnctr_en_bit = 5,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 6,
+		.n_val_shift = 16,
+		.m_val_shift = 8,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 12,
+		.pre_div_width = 4,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = mmcc_pxo_dsi2_dsi1_map,
+	},
+	.clkr = {
+		.enable_reg = 0x0094,
+		.enable_mask = BIT(2),
+		.hw.init = &(struct clk_init_data){
+			.name = "dsi2_pixel_src",
+			.parent_names = mmcc_pxo_dsi2_dsi1,
+			.num_parents = 3,
+			.ops = &clk_rcg_pixel_ops,
+		},
+	},
+};
+
+static struct clk_branch dsi2_pixel_clk = {
+	.halt_reg = 0x01d0,
+	.halt_bit = 19,
+	.clkr = {
+		.enable_reg = 0x0094,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mdp_pclk2_clk",
+			.parent_names = (const char *[]){ "dsi2_pixel_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
 static struct clk_branch gfx2d0_ahb_clk = {
 	.hwcg_reg = 0x0038,
 	.hwcg_bit = 28,
@@ -2325,6 +2697,8 @@ static struct clk_regmap *mmcc_msm8960_clks[] = {
 	[CSI2_SRC] = &csi2_src.clkr,
 	[CSI2_CLK] = &csi2_clk.clkr,
 	[CSI2_PHY_CLK] = &csi2_phy_clk.clkr,
+	[DSI_SRC] = &dsi1_src.clkr,
+	[DSI_CLK] = &dsi1_clk.clkr,
 	[CSI_PIX_CLK] = &csi_pix_clk.clkr,
 	[CSI_RDI_CLK] = &csi_rdi_clk.clkr,
 	[MDP_VSYNC_CLK] = &mdp_vsync_clk.clkr,
@@ -2345,6 +2719,18 @@ static struct clk_regmap *mmcc_msm8960_clks[] = {
 	[MDP_SRC] = &mdp_src.clkr,
 	[MDP_CLK] = &mdp_clk.clkr,
 	[MDP_LUT_CLK] = &mdp_lut_clk.clkr,
+	[DSI2_PIXEL_SRC] = &dsi2_pixel_src.clkr,
+	[DSI2_PIXEL_CLK] = &dsi2_pixel_clk.clkr,
+	[DSI2_SRC] = &dsi2_src.clkr,
+	[DSI2_CLK] = &dsi2_clk.clkr,
+	[DSI1_BYTE_SRC] = &dsi1_byte_src.clkr,
+	[DSI1_BYTE_CLK] = &dsi1_byte_clk.clkr,
+	[DSI2_BYTE_SRC] = &dsi2_byte_src.clkr,
+	[DSI2_BYTE_CLK] = &dsi2_byte_clk.clkr,
+	[DSI1_ESC_SRC] = &dsi1_esc_src.clkr,
+	[DSI1_ESC_CLK] = &dsi1_esc_clk.clkr,
+	[DSI2_ESC_SRC] = &dsi2_esc_src.clkr,
+	[DSI2_ESC_CLK] = &dsi2_esc_clk.clkr,
 	[ROT_SRC] = &rot_src.clkr,
 	[ROT_CLK] = &rot_clk.clkr,
 	[TV_ENC_CLK] = &tv_enc_clk.clkr,
@@ -2359,6 +2745,8 @@ static struct clk_regmap *mmcc_msm8960_clks[] = {
 	[VFE_CSI_CLK] = &vfe_csi_clk.clkr,
 	[VPE_SRC] = &vpe_src.clkr,
 	[VPE_CLK] = &vpe_clk.clkr,
+	[DSI_PIXEL_SRC] = &dsi1_pixel_src.clkr,
+	[DSI_PIXEL_CLK] = &dsi1_pixel_clk.clkr,
 	[CAMCLK0_SRC] = &camclk0_src.clkr,
 	[CAMCLK0_CLK] = &camclk0_clk.clkr,
 	[CAMCLK1_SRC] = &camclk1_src.clkr,
@@ -2490,6 +2878,8 @@ static struct clk_regmap *mmcc_apq8064_clks[] = {
 	[CSI2_SRC] = &csi2_src.clkr,
 	[CSI2_CLK] = &csi2_clk.clkr,
 	[CSI2_PHY_CLK] = &csi2_phy_clk.clkr,
+	[DSI_SRC] = &dsi1_src.clkr,
+	[DSI_CLK] = &dsi1_clk.clkr,
 	[CSI_PIX_CLK] = &csi_pix_clk.clkr,
 	[CSI_RDI_CLK] = &csi_rdi_clk.clkr,
 	[MDP_VSYNC_CLK] = &mdp_vsync_clk.clkr,
@@ -2506,6 +2896,18 @@ static struct clk_regmap *mmcc_apq8064_clks[] = {
 	[MDP_SRC] = &mdp_src.clkr,
 	[MDP_CLK] = &mdp_clk.clkr,
 	[MDP_LUT_CLK] = &mdp_lut_clk.clkr,
+	[DSI2_PIXEL_SRC] = &dsi2_pixel_src.clkr,
+	[DSI2_PIXEL_CLK] = &dsi2_pixel_clk.clkr,
+	[DSI2_SRC] = &dsi2_src.clkr,
+	[DSI2_CLK] = &dsi2_clk.clkr,
+	[DSI1_BYTE_SRC] = &dsi1_byte_src.clkr,
+	[DSI1_BYTE_CLK] = &dsi1_byte_clk.clkr,
+	[DSI2_BYTE_SRC] = &dsi2_byte_src.clkr,
+	[DSI2_BYTE_CLK] = &dsi2_byte_clk.clkr,
+	[DSI1_ESC_SRC] = &dsi1_esc_src.clkr,
+	[DSI1_ESC_CLK] = &dsi1_esc_clk.clkr,
+	[DSI2_ESC_SRC] = &dsi2_esc_src.clkr,
+	[DSI2_ESC_CLK] = &dsi2_esc_clk.clkr,
 	[ROT_SRC] = &rot_src.clkr,
 	[ROT_CLK] = &rot_clk.clkr,
 	[TV_DAC_CLK] = &tv_dac_clk.clkr,
@@ -2519,6 +2921,8 @@ static struct clk_regmap *mmcc_apq8064_clks[] = {
 	[VFE_CSI_CLK] = &vfe_csi_clk.clkr,
 	[VPE_SRC] = &vpe_src.clkr,
 	[VPE_CLK] = &vpe_clk.clkr,
+	[DSI_PIXEL_SRC] = &dsi1_pixel_src.clkr,
+	[DSI_PIXEL_CLK] = &dsi1_pixel_clk.clkr,
 	[CAMCLK0_SRC] = &camclk0_src.clkr,
 	[CAMCLK0_CLK] = &camclk0_clk.clkr,
 	[CAMCLK1_SRC] = &camclk1_src.clkr,
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
Applied
#5 lore raw

Re: [PATCH 2/2] clk: qcom: mmcc-8960: Add DSI related clocks

Quoted 6 lines · Archit Taneja

Add rcg and branch clk structs for DSI1 and DSI2 blocks found in MSM8960 and APQ8064. Each DSI instance has 4 pairs of rcg and branch clocks. Populate arrays mmcc_msm8960_clks and mmcc_apq8064_clks with these clocks.

---

Applied to clk-next

Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project