mirror of
https://github.com/genesi/linux-legacy.git
synced 2026-10-23 05:21:28 +00:00
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:
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user