diff mbox

[U-Boot,2/5] sun6i: clock: Add support for the mipi pll

Message ID 1439043904-31492-3-git-send-email-hdegoede@redhat.com
State Accepted
Delegated to: Hans de Goede
Headers show

Commit Message

Hans de Goede Aug. 8, 2015, 2:25 p.m. UTC
Add support for the mipi pll, this is necessary for getting higher dotclocks
with lcd panels.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 arch/arm/cpu/armv7/sunxi/clock_sun6i.c        | 55 +++++++++++++++++++++++++++
 arch/arm/include/asm/arch-sunxi/clock_sun4i.h |  1 +
 arch/arm/include/asm/arch-sunxi/clock_sun6i.h | 14 +++++++
 3 files changed, 70 insertions(+)

Comments

Ian Campbell Aug. 11, 2015, 7:51 a.m. UTC | #1
On Sat, 2015-08-08 at 16:25 +0200, Hans de Goede wrote:
> Add support for the mipi pll, this is necessary for getting higher 
> dotclocks
> with lcd panels.
> 
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>

Acked-by: Ian Campbell <ijc@hellion.org.uk>
Chen-Yu Tsai Aug. 11, 2015, 7:57 a.m. UTC | #2
On Sat, Aug 8, 2015 at 10:25 PM, Hans de Goede <hdegoede@redhat.com> wrote:
> Add support for the mipi pll, this is necessary for getting higher dotclocks
> with lcd panels.

Do you plan on adding this to the kernel (both the clock driver and reference
in the simplefb node) as well?

ChenYu

> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> ---
>  arch/arm/cpu/armv7/sunxi/clock_sun6i.c        | 55 +++++++++++++++++++++++++++
>  arch/arm/include/asm/arch-sunxi/clock_sun4i.h |  1 +
>  arch/arm/include/asm/arch-sunxi/clock_sun6i.h | 14 +++++++
>  3 files changed, 70 insertions(+)
Hans de Goede Aug. 11, 2015, 9:39 a.m. UTC | #3
Hi,

On 11-08-15 09:57, Chen-Yu Tsai wrote:
> On Sat, Aug 8, 2015 at 10:25 PM, Hans de Goede <hdegoede@redhat.com> wrote:
>> Add support for the mipi pll, this is necessary for getting higher dotclocks
>> with lcd panels.
>
> Do you plan on adding this to the kernel (both the clock driver and reference
> in the simplefb node) as well?

Not at this time, once we have a kms driver in the kernel, and figured out
how to add support for bridge chips like these, we are going to need support
for this to support high res lcd panels though.

Regards,

Hans
diff mbox

Patch

diff --git a/arch/arm/cpu/armv7/sunxi/clock_sun6i.c b/arch/arm/cpu/armv7/sunxi/clock_sun6i.c
index 1d6f839..3ab3b31 100644
--- a/arch/arm/cpu/armv7/sunxi/clock_sun6i.c
+++ b/arch/arm/cpu/armv7/sunxi/clock_sun6i.c
@@ -170,6 +170,47 @@  void clock_set_pll5(unsigned int clk, bool sigma_delta_enable)
 	udelay(5500);
 }
 
+#ifdef CONFIG_MACH_SUN6I
+void clock_set_mipi_pll(unsigned int clk)
+{
+	struct sunxi_ccm_reg * const ccm =
+		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+	unsigned int k, m, n, value, diff;
+	unsigned best_k = 0, best_m = 0, best_n = 0, best_diff = 0xffffffff;
+	unsigned int src = clock_get_pll3();
+
+	/* All calculations are in KHz to avoid overflows */
+	clk /= 1000;
+	src /= 1000;
+
+	/* Pick the closest lower clock */
+	for (k = 1; k <= 4; k++) {
+		for (m = 1; m <= 16; m++) {
+			for (n = 1; n <= 16; n++) {
+				value = src * n * k / m;
+				if (value > clk)
+					continue;
+
+				diff = clk - value;
+				if (diff < best_diff) {
+					best_diff = diff;
+					best_k = k;
+					best_m = m;
+					best_n = n;
+				}
+				if (diff == 0)
+					goto done;
+			}
+		}
+	}
+
+done:
+	writel(CCM_MIPI_PLL_CTRL_EN | CCM_MIPI_PLL_CTRL_LDO_EN |
+	       CCM_MIPI_PLL_CTRL_N(best_n) | CCM_MIPI_PLL_CTRL_K(best_k) |
+	       CCM_MIPI_PLL_CTRL_M(best_m), &ccm->mipi_pll_cfg);
+}
+#endif
+
 #ifdef CONFIG_MACH_SUN8I_A33
 void clock_set_pll11(unsigned int clk, bool sigma_delta_enable)
 {
@@ -210,6 +251,20 @@  unsigned int clock_get_pll6(void)
 	return 24000000 * n * k / 2;
 }
 
+unsigned int clock_get_mipi_pll(void)
+{
+	struct sunxi_ccm_reg *const ccm =
+		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+	uint32_t rval = readl(&ccm->mipi_pll_cfg);
+	unsigned int n = ((rval & CCM_MIPI_PLL_CTRL_N_MASK) >> CCM_MIPI_PLL_CTRL_N_SHIFT) + 1;
+	unsigned int k = ((rval & CCM_MIPI_PLL_CTRL_K_MASK) >> CCM_MIPI_PLL_CTRL_K_SHIFT) + 1;
+	unsigned int m = ((rval & CCM_MIPI_PLL_CTRL_M_MASK) >> CCM_MIPI_PLL_CTRL_M_SHIFT) + 1;
+	unsigned int src = clock_get_pll3();
+
+	/* Multiply by 1000 after dividing by m to avoid integer overflows */
+	return ((src / 1000) * n * k / m) * 1000;
+}
+
 void clock_set_de_mod_clock(u32 *clk_cfg, unsigned int hz)
 {
 	int pll = clock_get_pll6() * 2;
diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun4i.h b/arch/arm/include/asm/arch-sunxi/clock_sun4i.h
index 1a0b525..0088bb9 100644
--- a/arch/arm/include/asm/arch-sunxi/clock_sun4i.h
+++ b/arch/arm/include/asm/arch-sunxi/clock_sun4i.h
@@ -289,6 +289,7 @@  struct sunxi_ccm_reg {
 #define CCM_LCD_CH0_CTRL_PLL7		(1 << 24)
 #define CCM_LCD_CH0_CTRL_PLL3_2X	(2 << 24)
 #define CCM_LCD_CH0_CTRL_PLL7_2X	(3 << 24)
+#define CCM_LCD_CH0_CTRL_MIPI_PLL	0 /* No mipi pll on sun4i/5i/7i */
 #ifdef CONFIG_MACH_SUN5I
 #define CCM_LCD_CH0_CTRL_TVE_RST	(0x1 << 29)
 #else
diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
index a197345..9b7b90c 100644
--- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
+++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
@@ -202,6 +202,18 @@  struct sunxi_ccm_reg {
 #define CCM_PLL6_CTRL_K_SHIFT		4
 #define CCM_PLL6_CTRL_K_MASK		(0x3 << CCM_PLL6_CTRL_K_SHIFT)
 
+#define CCM_MIPI_PLL_CTRL_M_SHIFT	0
+#define CCM_MIPI_PLL_CTRL_M_MASK	(0xf << CCM_MIPI_PLL_CTRL_M_SHIFT)
+#define CCM_MIPI_PLL_CTRL_M(n)		((((n) - 1) & 0xf) << 0)
+#define CCM_MIPI_PLL_CTRL_K_SHIFT	4
+#define CCM_MIPI_PLL_CTRL_K_MASK	(0x3 << CCM_MIPI_PLL_CTRL_K_SHIFT)
+#define CCM_MIPI_PLL_CTRL_K(n)		((((n) - 1) & 0x3) << 4)
+#define CCM_MIPI_PLL_CTRL_N_SHIFT	8
+#define CCM_MIPI_PLL_CTRL_N_MASK	(0xf << CCM_MIPI_PLL_CTRL_N_SHIFT)
+#define CCM_MIPI_PLL_CTRL_N(n)		((((n) - 1) & 0xf) << 8)
+#define CCM_MIPI_PLL_CTRL_LDO_EN	(0x3 << 22)
+#define CCM_MIPI_PLL_CTRL_EN		(0x1 << 31)
+
 #define CCM_PLL11_CTRL_N(n)		((((n) - 1) & 0x3f) << 8)
 #define CCM_PLL11_CTRL_SIGMA_DELTA_EN	(0x1 << 24)
 #define CCM_PLL11_CTRL_UPD		(0x1 << 30)
@@ -364,8 +376,10 @@  void clock_set_pll1(unsigned int hz);
 void clock_set_pll3(unsigned int hz);
 void clock_set_pll5(unsigned int clk, bool sigma_delta_enable);
 void clock_set_pll11(unsigned int clk, bool sigma_delta_enable);
+void clock_set_mipi_pll(unsigned int hz);
 unsigned int clock_get_pll3(void);
 unsigned int clock_get_pll6(void);
+unsigned int clock_get_mipi_pll(void);
 #endif
 
 #endif /* _SUNXI_CLOCK_SUN6I_H */