[U-Boot] [PATCH 1/4] arm: mxs: Add LCDIF clock configuration function

This function turns on the LCDIF clock and configures it's frequency. The dividers settings are calculated within the function and the current implementation should be fast and accurate.
Signed-off-by: Marek Vasut marex@denx.de Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Otavio Salvador otavio@ossystems.com.br Cc: Stefano Babic sbabic@denx.de --- arch/arm/cpu/arm926ejs/mxs/clock.c | 93 +++++++++++++++++++++++++++++++++ arch/arm/include/asm/arch-mxs/clock.h | 1 + 2 files changed, 94 insertions(+)
diff --git a/arch/arm/cpu/arm926ejs/mxs/clock.c b/arch/arm/cpu/arm926ejs/mxs/clock.c index 43e7663..f94107f 100644 --- a/arch/arm/cpu/arm926ejs/mxs/clock.c +++ b/arch/arm/cpu/arm926ejs/mxs/clock.c @@ -325,6 +325,99 @@ void mxs_set_ssp_busclock(unsigned int bus, uint32_t 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) { switch (clk) { diff --git a/arch/arm/include/asm/arch-mxs/clock.h b/arch/arm/include/asm/arch-mxs/clock.h index 3f7d3f0..9be53f0 100644 --- a/arch/arm/include/asm/arch-mxs/clock.h +++ b/arch/arm/include/asm/arch-mxs/clock.h @@ -59,6 +59,7 @@ uint32_t mxc_get_clock(enum mxc_clock clk); void mxs_set_ioclk(enum mxs_ioclock io, uint32_t freq); void mxs_set_sspclk(enum mxs_sspclock ssp, uint32_t freq, int xtal); void mxs_set_ssp_busclock(unsigned int bus, uint32_t freq); +void mxs_set_lcdclk(uint32_t freq);
/* Compatibility with the FEC Ethernet driver */ #define imx_get_fecclk() mxc_get_clock(MXC_AHB_CLK)

Extend the regs-lcdif.h with registers for i.MX233.
Signed-off-by: Marek Vasut marex@denx.de Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Otavio Salvador otavio@ossystems.com.br Cc: Stefano Babic sbabic@denx.de --- arch/arm/include/asm/arch-mxs/regs-lcdif.h | 36 +++++++++++++++++++++------- 1 file changed, 27 insertions(+), 9 deletions(-)
diff --git a/arch/arm/include/asm/arch-mxs/regs-lcdif.h b/arch/arm/include/asm/arch-mxs/regs-lcdif.h index b90b2d4..1aa1498 100644 --- a/arch/arm/include/asm/arch-mxs/regs-lcdif.h +++ b/arch/arm/include/asm/arch-mxs/regs-lcdif.h @@ -32,10 +32,17 @@ struct mxs_lcdif_regs { mxs_reg_32(hw_lcdif_ctrl) /* 0x00 */ mxs_reg_32(hw_lcdif_ctrl1) /* 0x10 */ +#if defined(CONFIG_MX28) mxs_reg_32(hw_lcdif_ctrl2) /* 0x20 */ - mxs_reg_32(hw_lcdif_transfer_count) /* 0x30 */ - mxs_reg_32(hw_lcdif_cur_buf) /* 0x40 */ - mxs_reg_32(hw_lcdif_next_buf) /* 0x50 */ +#endif + mxs_reg_32(hw_lcdif_transfer_count) /* 0x20/0x30 */ + mxs_reg_32(hw_lcdif_cur_buf) /* 0x30/0x40 */ + mxs_reg_32(hw_lcdif_next_buf) /* 0x40/0x50 */ + +#if defined(CONFIG_MX23) + uint32_t reserved1[4]; +#endif + mxs_reg_32(hw_lcdif_timing) /* 0x60 */ mxs_reg_32(hw_lcdif_vdctrl0) /* 0x70 */ mxs_reg_32(hw_lcdif_vdctrl1) /* 0x80 */ @@ -54,13 +61,19 @@ struct mxs_lcdif_regs { mxs_reg_32(hw_lcdif_csc_coeffctrl4) /* 0x150 */ mxs_reg_32(hw_lcdif_csc_offset) /* 0x160 */ mxs_reg_32(hw_lcdif_csc_limit) /* 0x170 */ - mxs_reg_32(hw_lcdif_data) /* 0x180 */ - mxs_reg_32(hw_lcdif_bm_error_stat) /* 0x190 */ + +#if defined(CONFIG_MX23) + uint32_t reserved2[12]; +#endif + mxs_reg_32(hw_lcdif_data) /* 0x1b0/0x180 */ + mxs_reg_32(hw_lcdif_bm_error_stat) /* 0x1c0/0x190 */ +#if defined(CONFIG_MX28) mxs_reg_32(hw_lcdif_crc_stat) /* 0x1a0 */ - mxs_reg_32(hw_lcdif_lcdif_stat) /* 0x1b0 */ - mxs_reg_32(hw_lcdif_version) /* 0x1c0 */ - mxs_reg_32(hw_lcdif_debug0) /* 0x1d0 */ - mxs_reg_32(hw_lcdif_debug1) /* 0x1e0 */ +#endif + mxs_reg_32(hw_lcdif_lcdif_stat) /* 0x1d0/0x1b0 */ + mxs_reg_32(hw_lcdif_version) /* 0x1e0/0x1c0 */ + mxs_reg_32(hw_lcdif_debug0) /* 0x1f0/0x1d0 */ + mxs_reg_32(hw_lcdif_debug1) /* 0x200/0x1e0 */ mxs_reg_32(hw_lcdif_debug2) /* 0x1f0 */ }; #endif @@ -191,8 +204,13 @@ struct mxs_lcdif_regs { #define LCDIF_VDCTRL1_VSYNC_PERIOD_MASK 0xffffffff #define LCDIF_VDCTRL1_VSYNC_PERIOD_OFFSET 0
+#if defined(CONFIG_MX23) +#define LCDIF_VDCTRL2_HSYNC_PULSE_WIDTH_MASK (0xff << 24) +#define LCDIF_VDCTRL2_HSYNC_PULSE_WIDTH_OFFSET 24 +#elif defined(CONFIG_MX28) #define LCDIF_VDCTRL2_HSYNC_PULSE_WIDTH_MASK (0x3fff << 18) #define LCDIF_VDCTRL2_HSYNC_PULSE_WIDTH_OFFSET 18 +#endif #define LCDIF_VDCTRL2_HSYNC_PERIOD_MASK 0x3ffff #define LCDIF_VDCTRL2_HSYNC_PERIOD_OFFSET 0

On 28/04/2013 21:20, Marek Vasut wrote:
Extend the regs-lcdif.h with registers for i.MX233.
Signed-off-by: Marek Vasut marex@denx.de Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Otavio Salvador otavio@ossystems.com.br Cc: Stefano Babic sbabic@denx.de
Applied to u-boot-imx, thanks. Best regards, Stefano Babic

Add basic LCD driver for i.MX233 and i.MX28. This driver allows framebuffer console and framebuffer logo.
Signed-off-by: Marek Vasut marex@denx.de Cc: Anatolij Gustschin agust@denx.de Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Otavio Salvador otavio@ossystems.com.br Cc: Stefano Babic sbabic@denx.de --- drivers/video/Makefile | 1 + drivers/video/cfb_console.c | 4 + drivers/video/mxsfb.c | 189 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 194 insertions(+) create mode 100644 drivers/video/mxsfb.c
diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 53952ab..68ff34b 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -49,6 +49,7 @@ COBJS-$(CONFIG_VIDEO_MB862xx) += mb862xx.o videomodes.o COBJS-$(CONFIG_VIDEO_MB86R0xGDC) += mb86r0xgdc.o videomodes.o COBJS-$(CONFIG_VIDEO_MX3) += mx3fb.o videomodes.o COBJS-$(CONFIG_VIDEO_IPUV3) += mxc_ipuv3_fb.o ipu_common.o ipu_disp.o +COBJS-$(CONFIG_VIDEO_MXS) += mxsfb.o videomodes.o COBJS-$(CONFIG_VIDEO_OMAP3) += omap3_dss.o COBJS-$(CONFIG_VIDEO_SED13806) += sed13806.o COBJS-$(CONFIG_VIDEO_SM501) += sm501.o diff --git a/drivers/video/cfb_console.c b/drivers/video/cfb_console.c index 61e1058..0793f07 100644 --- a/drivers/video/cfb_console.c +++ b/drivers/video/cfb_console.c @@ -151,6 +151,10 @@ #endif #endif
+#ifdef CONFIG_VIDEO_MXS +#define VIDEO_FB_16BPP_WORD_SWAP +#endif + /* * Defines for the MB862xx driver */ diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c new file mode 100644 index 0000000..461ff6e --- /dev/null +++ b/drivers/video/mxsfb.c @@ -0,0 +1,189 @@ +/* + * Freescale i.MX23/i.MX28 LCDIF driver + * + * Copyright (C) 2011-2013 Marek Vasut marex@denx.de + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +#include <common.h> +#include <malloc.h> +#include <video_fb.h> + +#include <asm/arch/imx-regs.h> +#include <asm/arch/clock.h> +#include <asm/arch/sys_proto.h> +#include <asm/errno.h> +#include <asm/io.h> + +#include "videomodes.h" + +#define PS2KHZ(ps) (1000000000UL / (ps)) + +static GraphicDevice panel; + +/* + * DENX M28EVK: + * setenv videomode + * video=ctfb:x:800,y:480,depth:18,mode:0,pclk:30066, + * le:0,ri:256,up:0,lo:45,hs:1,vs:1,sync:100663296,vmode:0 + */ + +static void mxs_lcd_init(GraphicDevice *panel, + struct ctfb_res_modes *mode, int bpp) +{ + struct mxs_lcdif_regs *regs = (struct mxs_lcdif_regs *)MXS_LCDIF_BASE; + uint32_t word_len = 0, bus_width = 0; + uint8_t valid_data = 0; + + /* Kick in the LCDIF clock */ + mxs_set_lcdclk(PS2KHZ(mode->pixclock)); + + /* Restart the LCDIF block */ + mxs_reset_block(®s->hw_lcdif_ctrl_reg); + + switch (bpp) { + case 24: + word_len = LCDIF_CTRL_WORD_LENGTH_24BIT; + bus_width = LCDIF_CTRL_LCD_DATABUS_WIDTH_24BIT; + valid_data = 0x7; + break; + case 18: + word_len = LCDIF_CTRL_WORD_LENGTH_24BIT; + bus_width = LCDIF_CTRL_LCD_DATABUS_WIDTH_18BIT; + valid_data = 0x7; + break; + case 16: + word_len = LCDIF_CTRL_WORD_LENGTH_16BIT; + bus_width = LCDIF_CTRL_LCD_DATABUS_WIDTH_16BIT; + valid_data = 0xf; + break; + case 8: + word_len = LCDIF_CTRL_WORD_LENGTH_8BIT; + bus_width = LCDIF_CTRL_LCD_DATABUS_WIDTH_8BIT; + valid_data = 0xf; + break; + } + + writel(bus_width | word_len | LCDIF_CTRL_DOTCLK_MODE | + LCDIF_CTRL_BYPASS_COUNT | LCDIF_CTRL_LCDIF_MASTER, + ®s->hw_lcdif_ctrl); + + writel(valid_data << LCDIF_CTRL1_BYTE_PACKING_FORMAT_OFFSET, + ®s->hw_lcdif_ctrl1); + writel((mode->yres << LCDIF_TRANSFER_COUNT_V_COUNT_OFFSET) | mode->xres, + ®s->hw_lcdif_transfer_count); + + writel(LCDIF_VDCTRL0_ENABLE_PRESENT | LCDIF_VDCTRL0_ENABLE_POL | + LCDIF_VDCTRL0_VSYNC_PERIOD_UNIT | + LCDIF_VDCTRL0_VSYNC_PULSE_WIDTH_UNIT | + mode->vsync_len, ®s->hw_lcdif_vdctrl0); + writel(mode->upper_margin + mode->lower_margin + + mode->vsync_len + mode->yres, + ®s->hw_lcdif_vdctrl1); + writel((mode->hsync_len << LCDIF_VDCTRL2_HSYNC_PULSE_WIDTH_OFFSET) | + (mode->left_margin + mode->right_margin + + mode->hsync_len + mode->xres), + ®s->hw_lcdif_vdctrl2); + writel(((mode->left_margin + mode->hsync_len) << + LCDIF_VDCTRL3_HORIZONTAL_WAIT_CNT_OFFSET) | + (mode->upper_margin + mode->vsync_len), + ®s->hw_lcdif_vdctrl3); + writel((0 << LCDIF_VDCTRL4_DOTCLK_DLY_SEL_OFFSET) | mode->xres, + ®s->hw_lcdif_vdctrl4); + + writel(panel->frameAdrs, ®s->hw_lcdif_cur_buf); + writel(panel->frameAdrs, ®s->hw_lcdif_next_buf); + + /* Flush FIFO first */ + writel(LCDIF_CTRL1_FIFO_CLEAR, ®s->hw_lcdif_ctrl1_set); + + /* Sync signals ON */ + setbits_le32(®s->hw_lcdif_vdctrl4, LCDIF_VDCTRL4_SYNC_SIGNALS_ON); + + /* FIFO cleared */ + writel(LCDIF_CTRL1_FIFO_CLEAR, ®s->hw_lcdif_ctrl1_clr); + + /* RUN! */ + writel(LCDIF_CTRL_RUN, ®s->hw_lcdif_ctrl_set); +} + +void *video_hw_init(void) +{ + int bpp = -1; + char *penv; + void *fb; + struct ctfb_res_modes mode; + + puts("Video: "); + + /* Suck display configuration from "videomode" variable */ + penv = getenv("videomode"); + if (!penv) { + printf("MXSFB: 'videomode' variable not set!"); + return NULL; + } + + bpp = video_get_params(&mode, penv); + + /* fill in Graphic device struct */ + sprintf(panel.modeIdent, "%dx%dx%d", + mode.xres, mode.yres, bpp); + + panel.winSizeX = mode.xres; + panel.winSizeY = mode.yres; + panel.plnSizeX = mode.xres; + panel.plnSizeY = mode.yres; + + switch (bpp) { + case 24: + case 18: + panel.gdfBytesPP = 4; + panel.gdfIndex = GDF_32BIT_X888RGB; + break; + case 16: + panel.gdfBytesPP = 2; + panel.gdfIndex = GDF_16BIT_565RGB; + break; + case 8: + panel.gdfBytesPP = 1; + panel.gdfIndex = GDF__8BIT_INDEX; + break; + default: + printf("MXSFB: Invalid BPP specified! (bpp = %i)\n", bpp); + return NULL; + } + + panel.memSize = mode.xres * mode.yres * panel.gdfBytesPP; + + /* Allocate framebuffer */ + fb = malloc(panel.memSize); + if (!fb) { + printf("MXSFB: Error allocating framebuffer!\n"); + return NULL; + } + + /* Wipe framebuffer */ + memset(fb, 0, panel.memSize); + + panel.frameAdrs = (u32)fb; + + printf("%s\n", panel.modeIdent); + + /* Start framebuffer */ + mxs_lcd_init(&panel, &mode, bpp); + + return (void *)&panel; +}

On Sun, 28 Apr 2013 21:20:03 +0200 Marek Vasut marex@denx.de wrote:
Add basic LCD driver for i.MX233 and i.MX28. This driver allows framebuffer console and framebuffer logo.
Signed-off-by: Marek Vasut marex@denx.de Cc: Anatolij Gustschin agust@denx.de Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Otavio Salvador otavio@ossystems.com.br Cc: Stefano Babic sbabic@denx.de
Acked-by: Anatolij Gustschin agust@denx.de

On 06/05/2013 17:04, Anatolij Gustschin wrote:
On Sun, 28 Apr 2013 21:20:03 +0200 Marek Vasut marex@denx.de wrote:
Add basic LCD driver for i.MX233 and i.MX28. This driver allows framebuffer console and framebuffer logo.
Signed-off-by: Marek Vasut marex@denx.de Cc: Anatolij Gustschin agust@denx.de Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Otavio Salvador otavio@ossystems.com.br Cc: Stefano Babic sbabic@denx.de
Acked-by: Anatolij Gustschin agust@denx.de
Thanks, Anatolji
Marek, also this patchset will flow now.
Regards, Stefano

On 28/04/2013 21:20, Marek Vasut wrote:
Add basic LCD driver for i.MX233 and i.MX28. This driver allows framebuffer console and framebuffer logo.
Signed-off-by: Marek Vasut marex@denx.de Cc: Anatolij Gustschin agust@denx.de Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Otavio Salvador otavio@ossystems.com.br Cc: Stefano Babic sbabic@denx.de
Applied to u-boot-imx, thanks. Best regards, Stefano Babic

Enable LCD output support on M28EVK.
Signed-off-by: Marek Vasut marex@denx.de Cc: Anatolij Gustschin agust@denx.de Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Otavio Salvador otavio@ossystems.com.br Cc: Stefano Babic sbabic@denx.de --- include/configs/m28evk.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)
diff --git a/include/configs/m28evk.h b/include/configs/m28evk.h index f2725cc..a7d3ae6 100644 --- a/include/configs/m28evk.h +++ b/include/configs/m28evk.h @@ -76,6 +76,7 @@ #define CONFIG_CMD_SF #define CONFIG_CMD_SPI #define CONFIG_CMD_USB +#define CONFIG_VIDEO
/* * Memory configurations @@ -268,6 +269,24 @@ #endif
/* + * LCD + */ +#ifdef CONFIG_VIDEO +#define CONFIG_CFB_CONSOLE +#define CONFIG_VIDEO_MXS +#define CONFIG_VIDEO_LOGO +#define CONFIG_VIDEO_SW_CURSOR +#define CONFIG_VGA_AS_SINGLE_DEVICE +#define CONFIG_SYS_CONSOLE_IS_IN_ENV +#define CONFIG_SPLASH_SCREEN +#define CONFIG_CMD_BMP +#define CONFIG_BMP_16BPP +#define CONFIG_VIDEO_BMP_RLE8 +#define CONFIG_VIDEO_BMP_GZIP +#define CONFIG_SYS_VIDEO_LOGO_MAX_SIZE (512 << 10) +#endif + +/* * Boot Linux */ #define CONFIG_CMDLINE_TAG

On Sun, 28 Apr 2013 21:20:04 +0200 Marek Vasut marex@denx.de wrote:
Enable LCD output support on M28EVK.
Signed-off-by: Marek Vasut marex@denx.de Cc: Anatolij Gustschin agust@denx.de Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Otavio Salvador otavio@ossystems.com.br Cc: Stefano Babic sbabic@denx.de
Acked-by: Anatolij Gustschin agust@denx.de

On 28/04/2013 21:20, Marek Vasut wrote:
Enable LCD output support on M28EVK.
Signed-off-by: Marek Vasut marex@denx.de Cc: Anatolij Gustschin agust@denx.de Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Otavio Salvador otavio@ossystems.com.br Cc: Stefano Babic sbabic@denx.de
Applied to u-boot-imx, thanks. Best regards, Stefano Babic

Hi Stefano,
you missed these.
This function turns on the LCDIF clock and configures it's frequency. The dividers settings are calculated within the function and the current implementation should be fast and accurate.
Signed-off-by: Marek Vasut marex@denx.de Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Otavio Salvador otavio@ossystems.com.br Cc: Stefano Babic sbabic@denx.de
arch/arm/cpu/arm926ejs/mxs/clock.c | 93 +++++++++++++++++++++++++++++++++ arch/arm/include/asm/arch-mxs/clock.h | 1 + 2 files changed, 94 insertions(+)
diff --git a/arch/arm/cpu/arm926ejs/mxs/clock.c b/arch/arm/cpu/arm926ejs/mxs/clock.c index 43e7663..f94107f 100644 --- a/arch/arm/cpu/arm926ejs/mxs/clock.c +++ b/arch/arm/cpu/arm926ejs/mxs/clock.c @@ -325,6 +325,99 @@ void mxs_set_ssp_busclock(unsigned int bus, uint32_t 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) { switch (clk) { diff --git a/arch/arm/include/asm/arch-mxs/clock.h b/arch/arm/include/asm/arch-mxs/clock.h index 3f7d3f0..9be53f0 100644 --- a/arch/arm/include/asm/arch-mxs/clock.h +++ b/arch/arm/include/asm/arch-mxs/clock.h @@ -59,6 +59,7 @@ uint32_t mxc_get_clock(enum mxc_clock clk); void mxs_set_ioclk(enum mxs_ioclock io, uint32_t freq); void mxs_set_sspclk(enum mxs_sspclock ssp, uint32_t freq, int xtal); void mxs_set_ssp_busclock(unsigned int bus, uint32_t freq); +void mxs_set_lcdclk(uint32_t freq);
/* Compatibility with the FEC Ethernet driver */ #define imx_get_fecclk() mxc_get_clock(MXC_AHB_CLK)
Best regards, Marek Vasut

On 28/04/2013 21:20, Marek Vasut wrote:
This function turns on the LCDIF clock and configures it's frequency. The dividers settings are calculated within the function and the current implementation should be fast and accurate.
Signed-off-by: Marek Vasut marex@denx.de Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Otavio Salvador otavio@ossystems.com.br Cc: Stefano Babic sbabic@denx.de
Applied to u-boot-imx, thanks. Best regards, Stefano Babic
participants (3)
-
Anatolij Gustschin
-
Marek Vasut
-
Stefano Babic