diff options
author | Robby Cai <R63905@freescale.com> | 2010-03-08 20:53:40 +0800 |
---|---|---|
committer | Alejandro Gonzalez <alex.gonzalez@digi.com> | 2010-05-25 11:17:19 +0200 |
commit | 6b353f5d2891f9d5e7c2e9e3d87f4adf5fe45807 (patch) | |
tree | 650ffb8a5a69865003943e63dfd5237d403d03a6 /arch | |
parent | 96cd175aeacfb56fdcba3be792b4c78a2d50511a (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.c | 215 | ||||
-rw-r--r-- | arch/arm/mach-mx23/device.c | 5 | ||||
-rw-r--r-- | arch/arm/mach-mx23/mx23evk_pins.c | 40 |
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, |