|
@@ -325,6 +325,99 @@ void mxs_set_ssp_busclock(unsigned int bus, uint32_t freq)
|
|
bus, tgtclk, freq);
|
|
bus, tgtclk, freq);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+void mxs_set_lcdclk(uint32_t freq)
|
|
|
|
+{
|
|
|
|
+ struct mxs_clkctrl_regs *clkctrl_regs =
|
|
|
|
+ (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
|
|
|
|
+ uint32_t fp, x, k_rest, k_best, x_best, tk;
|
|
|
|
+ int32_t k_best_l = 999, k_best_t = 0, x_best_l = 0xff, x_best_t = 0xff;
|
|
|
|
+
|
|
|
|
+ if (freq == 0)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+#if defined(CONFIG_MX23)
|
|
|
|
+ writel(CLKCTRL_CLKSEQ_BYPASS_PIX, &clkctrl_regs->hw_clkctrl_clkseq_clr);
|
|
|
|
+#elif defined(CONFIG_MX28)
|
|
|
|
+ writel(CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF, &clkctrl_regs->hw_clkctrl_clkseq_clr);
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * / 18 \ 1 1
|
|
|
|
+ * freq kHz = | 480000000 Hz * -- | * --- * ------
|
|
|
|
+ * \ x / k 1000
|
|
|
|
+ *
|
|
|
|
+ * 480000000 Hz 18
|
|
|
|
+ * ------------ * --
|
|
|
|
+ * freq kHz x
|
|
|
|
+ * k = -------------------
|
|
|
|
+ * 1000
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+ fp = ((PLL_FREQ_KHZ * 1000) / freq) * 18;
|
|
|
|
+
|
|
|
|
+ for (x = 18; x <= 35; x++) {
|
|
|
|
+ tk = fp / x;
|
|
|
|
+ if ((tk / 1000 == 0) || (tk / 1000 > 255))
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ k_rest = tk % 1000;
|
|
|
|
+
|
|
|
|
+ if (k_rest < (k_best_l % 1000)) {
|
|
|
|
+ k_best_l = tk;
|
|
|
|
+ x_best_l = x;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (k_rest > (k_best_t % 1000)) {
|
|
|
|
+ k_best_t = tk;
|
|
|
|
+ x_best_t = x;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (1000 - (k_best_t % 1000) > (k_best_l % 1000)) {
|
|
|
|
+ k_best = k_best_l;
|
|
|
|
+ x_best = x_best_l;
|
|
|
|
+ } else {
|
|
|
|
+ k_best = k_best_t;
|
|
|
|
+ x_best = x_best_t;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ k_best /= 1000;
|
|
|
|
+
|
|
|
|
+#if defined(CONFIG_MX23)
|
|
|
|
+ writeb(CLKCTRL_FRAC_CLKGATE,
|
|
|
|
+ &clkctrl_regs->hw_clkctrl_frac0_set[CLKCTRL_FRAC0_PIX]);
|
|
|
|
+ writeb(CLKCTRL_FRAC_CLKGATE | (x_best & CLKCTRL_FRAC_FRAC_MASK),
|
|
|
|
+ &clkctrl_regs->hw_clkctrl_frac0[CLKCTRL_FRAC0_PIX]);
|
|
|
|
+ writeb(CLKCTRL_FRAC_CLKGATE,
|
|
|
|
+ &clkctrl_regs->hw_clkctrl_frac0_clr[CLKCTRL_FRAC0_PIX]);
|
|
|
|
+
|
|
|
|
+ writel(CLKCTRL_PIX_CLKGATE,
|
|
|
|
+ &clkctrl_regs->hw_clkctrl_pix_set);
|
|
|
|
+ clrsetbits_le32(&clkctrl_regs->hw_clkctrl_pix,
|
|
|
|
+ CLKCTRL_PIX_DIV_MASK | CLKCTRL_PIX_CLKGATE,
|
|
|
|
+ k_best << CLKCTRL_PIX_DIV_OFFSET);
|
|
|
|
+
|
|
|
|
+ while (readl(&clkctrl_regs->hw_clkctrl_pix) & CLKCTRL_PIX_BUSY)
|
|
|
|
+ ;
|
|
|
|
+#elif defined(CONFIG_MX28)
|
|
|
|
+ writeb(CLKCTRL_FRAC_CLKGATE,
|
|
|
|
+ &clkctrl_regs->hw_clkctrl_frac1_set[CLKCTRL_FRAC1_PIX]);
|
|
|
|
+ writeb(CLKCTRL_FRAC_CLKGATE | (x_best & CLKCTRL_FRAC_FRAC_MASK),
|
|
|
|
+ &clkctrl_regs->hw_clkctrl_frac1[CLKCTRL_FRAC1_PIX]);
|
|
|
|
+ writeb(CLKCTRL_FRAC_CLKGATE,
|
|
|
|
+ &clkctrl_regs->hw_clkctrl_frac1_clr[CLKCTRL_FRAC1_PIX]);
|
|
|
|
+
|
|
|
|
+ writel(CLKCTRL_DIS_LCDIF_CLKGATE,
|
|
|
|
+ &clkctrl_regs->hw_clkctrl_lcdif_set);
|
|
|
|
+ clrsetbits_le32(&clkctrl_regs->hw_clkctrl_lcdif,
|
|
|
|
+ CLKCTRL_DIS_LCDIF_DIV_MASK | CLKCTRL_DIS_LCDIF_CLKGATE,
|
|
|
|
+ k_best << CLKCTRL_DIS_LCDIF_DIV_OFFSET);
|
|
|
|
+
|
|
|
|
+ while (readl(&clkctrl_regs->hw_clkctrl_lcdif) & CLKCTRL_DIS_LCDIF_BUSY)
|
|
|
|
+ ;
|
|
|
|
+#endif
|
|
|
|
+}
|
|
|
|
+
|
|
uint32_t mxc_get_clock(enum mxc_clock clk)
|
|
uint32_t mxc_get_clock(enum mxc_clock clk)
|
|
{
|
|
{
|
|
switch (clk) {
|
|
switch (clk) {
|