ENGR00121272-3 [MX23] porting lcdif and framebuffer driver to new MSL

Add MSL-reated code

Signed-off-by: Robby Cai <R63905@freescale.com>
This commit is contained in:
Robby Cai
2010-03-08 20:53:40 +08:00
committed by Matt Sealey
parent 94b23ff390
commit f6a8b829ff
3 changed files with 182 additions and 78 deletions

View File

@@ -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,
@@ -522,6 +623,10 @@ static struct clk_lookup onchip_clocks[] = {
.con_id = "ref_pix",
.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)

View File

@@ -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;
}

View File

@@ -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,