summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorRobby Cai <R63905@freescale.com>2010-03-08 20:53:40 +0800
committerAlejandro Gonzalez <alex.gonzalez@digi.com>2010-05-25 11:17:19 +0200
commit6b353f5d2891f9d5e7c2e9e3d87f4adf5fe45807 (patch)
tree650ffb8a5a69865003943e63dfd5237d403d03a6 /arch
parent96cd175aeacfb56fdcba3be792b4c78a2d50511a (diff)
ENGR00121272-3 [MX23] porting lcdif and framebuffer driver to new MSL
Add MSL-reated code Signed-off-by: Robby Cai <R63905@freescale.com> Signed-off-by: Alejandro Gonzalez <alex.gonzalez@digi.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-mx23/clock.c215
-rw-r--r--arch/arm/mach-mx23/device.c5
-rw-r--r--arch/arm/mach-mx23/mx23evk_pins.c40
3 files changed, 182 insertions, 78 deletions
diff --git a/arch/arm/mach-mx23/clock.c b/arch/arm/mach-mx23/clock.c
index a3ff8aee15e5..242c7014fa62 100644
--- a/arch/arm/mach-mx23/clock.c
+++ b/arch/arm/mach-mx23/clock.c
@@ -197,7 +197,6 @@ static unsigned long ref_pix_get_rate(struct clk *clk)
return ref_clk_get_rate(clk->parent->get_rate(clk->parent), reg);
}
-
static struct clk ref_pix_clk = {
.parent = &pll_clk,
.get_rate = ref_pix_get_rate,
@@ -205,6 +204,161 @@ static struct clk ref_pix_clk = {
.enable_bits = BM_CLKCTRL_FRAC_CLKGATEPIX,
};
+static unsigned long lcdif_get_rate(struct clk *clk)
+{
+ long rate = clk->parent->get_rate(clk->parent);
+ long div;
+ const int mask = 0xff;
+
+ div = (__raw_readl(clk->scale_reg) >> clk->scale_bits) & mask;
+ if (div) {
+ rate /= div;
+ div = (__raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_FRAC) &
+ BM_CLKCTRL_FRAC_PIXFRAC) >> BP_CLKCTRL_FRAC_PIXFRAC;
+ rate /= div;
+ }
+
+ return rate;
+}
+
+static int lcdif_set_rate(struct clk *clk, u32 rate)
+{
+ int ret = 0;
+ /*
+ * ref_pix can be between 480e6*18/35=246.9MHz and 480e6*18/18=480MHz,
+ * which is between 18/(18*480e6)=2.084ns and 35/(18*480e6)=4.050ns.
+ *
+ * ns_cycle >= 2*18e3/(18*480) = 25/6
+ * ns_cycle <= 2*35e3/(18*480) = 875/108
+ *
+ * Multiply the ns_cycle by 'div' to lengthen it until it fits the
+ * bounds. This is the divider we'll use after ref_pix.
+ *
+ * 6 * ns_cycle >= 25 * div
+ * 108 * ns_cycle <= 875 * div
+ */
+ u32 ns_cycle = 1000000000 / rate;
+ ns_cycle *= 2; /* Fix calculate double frequency */
+ u32 div, reg_val;
+ u32 lowest_result = (u32) -1;
+ u32 lowest_div = 0, lowest_fracdiv = 0;
+
+ for (div = 1; div < 256; ++div) {
+ u32 fracdiv;
+ u32 ps_result;
+ int lower_bound = 6 * ns_cycle >= 25 * div;
+ int upper_bound = 108 * ns_cycle <= 875 * div;
+ if (!lower_bound)
+ break;
+ if (!upper_bound)
+ continue;
+ /*
+ * Found a matching div. Calculate fractional divider needed,
+ * rounded up.
+ */
+ fracdiv = ((clk->parent->get_rate(clk->parent) / 1000000 * 18 / 2) *
+ ns_cycle + 1000 * div - 1) /
+ (1000 * div);
+ if (fracdiv < 18 || fracdiv > 35) {
+ ret = -EINVAL;
+ goto out;
+ }
+ /* Calculate the actual cycle time this results in */
+ ps_result = 6250 * div * fracdiv / 27;
+
+ /* Use the fastest result that doesn't break ns_cycle */
+ if (ps_result <= lowest_result) {
+ lowest_result = ps_result;
+ lowest_div = div;
+ lowest_fracdiv = fracdiv;
+ }
+ }
+
+ if (div >= 256 || lowest_result == (u32) -1) {
+ ret = -EINVAL;
+ goto out;
+ }
+ pr_debug("Programming PFD=%u,DIV=%u ref_pix=%uMHz "
+ "PIXCLK=%uMHz cycle=%u.%03uns\n",
+ lowest_fracdiv, lowest_div,
+ 480*18/lowest_fracdiv, 480*18/lowest_fracdiv/lowest_div,
+ lowest_result / 1000, lowest_result % 1000);
+
+ /* Program ref_pix phase fractional divider */
+ reg_val = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_FRAC);
+ reg_val &= ~BM_CLKCTRL_FRAC_PIXFRAC;
+ reg_val |= BF_CLKCTRL_FRAC_PIXFRAC(lowest_fracdiv);
+ __raw_writel(reg_val, CLKCTRL_BASE_ADDR + HW_CLKCTRL_FRAC);
+
+ /* Ungate PFD */
+ __raw_writel(BM_CLKCTRL_FRAC_CLKGATEPIX,
+ CLKCTRL_BASE_ADDR + HW_CLKCTRL_FRAC_CLR);
+
+ /* Program pix divider */
+ reg_val = __raw_readl(clk->scale_reg);
+ reg_val &= ~(BM_CLKCTRL_PIX_DIV | BM_CLKCTRL_PIX_CLKGATE);
+ reg_val |= BF_CLKCTRL_PIX_DIV(lowest_div);
+ __raw_writel(reg_val, clk->scale_reg);
+
+ /* Wait for divider update */
+ if (clk->busy_reg) {
+ int i;
+ for (i = 10000; i; i--)
+ if (!clk_is_busy(clk))
+ break;
+ if (!i) {
+ ret = -ETIMEDOUT;
+ goto out;
+ }
+ }
+
+ /* Switch to ref_pix source */
+ reg_val = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_CLKSEQ);
+ reg_val &= ~BM_CLKCTRL_CLKSEQ_BYPASS_PIX;
+ __raw_writel(reg_val, CLKCTRL_BASE_ADDR + HW_CLKCTRL_CLKSEQ);
+
+out:
+ return ret;
+}
+
+static int lcdif_set_parent(struct clk *clk, struct clk *parent)
+{
+ int ret = -EINVAL;
+ if (clk->bypass_reg) {
+ if (parent == clk->parent)
+ return 0;
+ if (parent == &ref_xtal_clk) {
+ __raw_writel(1 << clk->bypass_bits,
+ clk->bypass_reg + SET_REGISTER);
+ ret = 0;
+ }
+ if (ret && (parent == &ref_pix_clk)) {
+ __raw_writel(1 << clk->bypass_bits,
+ clk->bypass_reg + CLR_REGISTER);
+ ret = 0;
+ }
+ if (!ret)
+ clk->parent = parent;
+ }
+ return ret;
+}
+
+static struct clk lcdif_clk = {
+ .parent = &pll_clk,
+ .enable = mx23_raw_enable,
+ .disable = mx23_raw_disable,
+ .scale_reg = CLKCTRL_BASE_ADDR + HW_CLKCTRL_PIX,
+ .busy_reg = CLKCTRL_BASE_ADDR + HW_CLKCTRL_PIX,
+ .busy_bits = 29,
+ .enable_reg = CLKCTRL_BASE_ADDR + HW_CLKCTRL_PIX,
+ .enable_bits = 31,
+ .bypass_reg = CLKCTRL_BASE_ADDR + HW_CLKCTRL_CLKSEQ,
+ .bypass_bits = 1,
+ .get_rate = lcdif_get_rate,
+ .set_rate = lcdif_set_rate,
+ .set_parent = lcdif_set_parent,
+};
+
static unsigned long cpu_get_rate(struct clk *clk)
{
unsigned long reg;
@@ -422,59 +576,6 @@ static unsigned long ssp_get_rate(struct clk *clk)
return clk->parent->get_rate(clk->parent) / reg;
}
-static unsigned long lcdif_get_rate(struct clk *clk)
-{
- long rate = clk->parent->get_rate(clk->parent);
- long div;
-
- div = (__raw_readl(clk->scale_reg) >> clk->scale_bits) &
- BM_CLKCTRL_PIX_DIV;
- if (div)
- rate /= div;
-
- return rate;
-}
-
-static int lcdif_set_rate(struct clk *clk, unsigned long rate)
-{
- int reg_val;
-
- reg_val = __raw_readl(clk->scale_reg);
- reg_val &= ~(BM_CLKCTRL_PIX_DIV | BM_CLKCTRL_PIX_CLKGATE);
- reg_val |= (1 << BP_CLKCTRL_PIX_DIV) & BM_CLKCTRL_PIX_DIV;
- __raw_writel(reg_val, clk->scale_reg);
- if (clk->busy_reg) {
- int i;
- for (i = 10000; i; i--)
- if (!clk_is_busy(clk))
- break;
- if (!i)
- return -ETIMEDOUT;
- }
-
- reg_val = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_CLKSEQ);
- reg_val |= BM_CLKCTRL_CLKSEQ_BYPASS_PIX;
- __raw_writel(reg_val, CLKCTRL_BASE_ADDR + HW_CLKCTRL_CLKSEQ);
-
- return 0;
-}
-
-static struct clk dis_lcdif_clk = {
- .parent = &pll_clk,
- .enable = mx23_raw_enable,
- .disable = mx23_raw_disable,
- .scale_reg = CLKCTRL_BASE_ADDR + HW_CLKCTRL_PIX,
- .scale_bits = 0,
- .busy_reg = CLKCTRL_BASE_ADDR + HW_CLKCTRL_PIX,
- .busy_bits = 29,
- .enable_reg = CLKCTRL_BASE_ADDR + HW_CLKCTRL_PIX,
- .enable_bits = 31,
- .bypass_reg = CLKCTRL_BASE_ADDR + HW_CLKCTRL_CLKSEQ,
- .bypass_bits = 14,
- .get_rate = lcdif_get_rate,
- .set_rate = lcdif_set_rate,
-};
-
/* usb_clk for usb0 */
static struct clk usb_clk = {
.parent = &pll_clk,
@@ -523,6 +624,10 @@ static struct clk_lookup onchip_clocks[] = {
.clk = &ref_pix_clk,
},
{
+ .con_id = "lcdif",
+ .clk = &lcdif_clk,
+ },
+ {
.con_id = "rtc",
.clk = &rtc_clk,
},
@@ -579,8 +684,6 @@ static void mx23_clock_scan(void)
reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_CLKSEQ);
if (reg & BM_CLKCTRL_CLKSEQ_BYPASS_CPU)
cpu_clk.parent = &ref_xtal_clk;
- if (reg & BM_CLKCTRL_CLKSEQ_BYPASS_PIX)
- dis_lcdif_clk.parent = &ref_xtal_clk;
if (reg & BM_CLKCTRL_CLKSEQ_BYPASS_EMI)
emi_clk.parent = &ref_xtal_clk;
if (reg & BM_CLKCTRL_CLKSEQ_BYPASS_SSP)
diff --git a/arch/arm/mach-mx23/device.c b/arch/arm/mach-mx23/device.c
index 488f0f46a64b..d74f8706c8a0 100644
--- a/arch/arm/mach-mx23/device.c
+++ b/arch/arm/mach-mx23/device.c
@@ -135,8 +135,8 @@ static struct resource framebuffer_resource[] = {
},
{
.flags = IORESOURCE_IRQ,
- .start = IRQ_LCDIF,
- .end = IRQ_LCDIF,
+ .start = IRQ_LCDIF_ERROR,
+ .end = IRQ_LCDIF_ERROR,
},
};
@@ -534,6 +534,7 @@ int __init mx23_device_init(void)
mx23_init_rtc();
mx23_init_dcp();
mx23_init_mmc();
+ mx23_init_lcdif();
return 0;
}
diff --git a/arch/arm/mach-mx23/mx23evk_pins.c b/arch/arm/mach-mx23/mx23evk_pins.c
index d4060ef35e2c..06de5389864d 100644
--- a/arch/arm/mach-mx23/mx23evk_pins.c
+++ b/arch/arm/mach-mx23/mx23evk_pins.c
@@ -226,48 +226,48 @@ static struct pin_desc mx23evk_fixed_pins[] = {
},
{
.name = "LCD_D18",
- .id = PINID_LCD_D18,
- .fun = PIN_FUN1,
+ .id = PINID_GPMI_D08,
+ .fun = PIN_FUN2,
.strength = PAD_8MA,
.voltage = PAD_3_3V,
.drive = 1,
},
{
.name = "LCD_D19",
- .id = PINID_LCD_D19,
- .fun = PIN_FUN1,
+ .id = PINID_GPMI_D09,
+ .fun = PIN_FUN2,
.strength = PAD_8MA,
.voltage = PAD_3_3V,
.drive = 1,
},
{
.name = "LCD_D20",
- .id = PINID_LCD_D20,
- .fun = PIN_FUN1,
+ .id = PINID_GPMI_D10,
+ .fun = PIN_FUN2,
.strength = PAD_8MA,
.voltage = PAD_3_3V,
.drive = 1,
},
{
.name = "LCD_D21",
- .id = PINID_LCD_D21,
- .fun = PIN_FUN1,
+ .id = PINID_GPMI_D11,
+ .fun = PIN_FUN2,
.strength = PAD_8MA,
.voltage = PAD_3_3V,
.drive = 1,
},
{
.name = "LCD_D22",
- .id = PINID_LCD_D22,
- .fun = PIN_FUN1,
+ .id = PINID_GPMI_D12,
+ .fun = PIN_FUN2,
.strength = PAD_8MA,
.voltage = PAD_3_3V,
.drive = 1,
},
{
.name = "LCD_D23",
- .id = PINID_LCD_D23,
- .fun = PIN_FUN1,
+ .id = PINID_GPMI_D13,
+ .fun = PIN_FUN2,
.strength = PAD_8MA,
.voltage = PAD_3_3V,
.drive = 1,
@@ -282,32 +282,32 @@ static struct pin_desc mx23evk_fixed_pins[] = {
},
{
.name = "LCD_VSYNC",
- .id = PINID_LCD_RD_E,
- .fun = PIN_FUN2,
+ .id = PINID_LCD_VSYNC,
+ .fun = PIN_FUN1,
.strength = PAD_8MA,
.voltage = PAD_3_3V,
.drive = 1,
},
{
.name = "LCD_HSYNC",
- .id = PINID_LCD_WR_RWN,
- .fun = PIN_FUN2,
+ .id = PINID_LCD_HSYNC,
+ .fun = PIN_FUN1,
.strength = PAD_8MA,
.voltage = PAD_3_3V,
.drive = 1,
},
{
.name = "LCD_ENABLE",
- .id = PINID_LCD_CS,
- .fun = PIN_FUN2,
+ .id = PINID_LCD_ENABLE,
+ .fun = PIN_FUN1,
.strength = PAD_8MA,
.voltage = PAD_3_3V,
.drive = 1,
},
{
.name = "LCD_DOTCLK",
- .id = PINID_LCD_RS,
- .fun = PIN_FUN2,
+ .id = PINID_LCD_DOTCK,
+ .fun = PIN_FUN1,
.strength = PAD_8MA,
.voltage = PAD_3_3V,
.drive = 1,