diff options
author | Wolfgang Denk <wd@denx.de> | 2010-10-05 14:31:48 +0200 |
---|---|---|
committer | Wolfgang Denk <wd@denx.de> | 2010-10-05 14:31:48 +0200 |
commit | bbf2abc0f5a5be0b8081ae8587fa90b376160444 (patch) | |
tree | 3bbade787e2f3b791118990bb716cb962b386566 /board/freescale | |
parent | dd09985499ac95484974eb0f832fe47b33369952 (diff) | |
parent | cdfcedbf250ba2ec01b2555cffde83e9947e9fbf (diff) | |
download | u-boot-imx-bbf2abc0f5a5be0b8081ae8587fa90b376160444.zip u-boot-imx-bbf2abc0f5a5be0b8081ae8587fa90b376160444.tar.gz u-boot-imx-bbf2abc0f5a5be0b8081ae8587fa90b376160444.tar.bz2 |
Merge branch 'next' of git://git.denx.de/u-boot-video
Diffstat (limited to 'board/freescale')
-rw-r--r-- | board/freescale/common/fsl_diu_fb.c | 41 | ||||
-rw-r--r-- | board/freescale/common/fsl_diu_fb.h | 59 | ||||
-rw-r--r-- | board/freescale/mpc8610hpcd/mpc8610hpcd_diu.c | 74 | ||||
-rw-r--r-- | board/freescale/p1022ds/Makefile | 2 | ||||
-rw-r--r-- | board/freescale/p1022ds/diu.c | 304 |
5 files changed, 357 insertions, 123 deletions
diff --git a/board/freescale/common/fsl_diu_fb.c b/board/freescale/common/fsl_diu_fb.c index 394b71f..35ed938 100644 --- a/board/freescale/common/fsl_diu_fb.c +++ b/board/freescale/common/fsl_diu_fb.c @@ -28,7 +28,7 @@ #include <malloc.h> #include <asm/io.h> -#include "fsl_diu_fb.h" +#include <fsl_diu_fb.h> struct fb_videomode { const char *name; /* optional */ @@ -472,3 +472,42 @@ static int allocate_buf(struct diu_addr *buf, u32 size, u32 bytes_align) buf->offset = 0; return 0; } + +#if defined(CONFIG_VIDEO) || defined(CONFIG_CFB_CONSOLE) +#include <stdio_dev.h> +#include <video_fb.h> +/* + * The Graphic Device + */ +static GraphicDevice ctfb; + +void *video_hw_init(void) +{ + struct fb_info *info; + + if (platform_diu_init(&ctfb.winSizeX, &ctfb.winSizeY) < 0) + return NULL; + + /* fill in Graphic device struct */ + sprintf(ctfb.modeIdent, "%ix%ix%i %ikHz %iHz", + ctfb.winSizeX, ctfb.winSizeY, 32, 64, 60); + + ctfb.frameAdrs = (unsigned int)fsl_fb_open(&info); + ctfb.plnSizeX = ctfb.winSizeX; + ctfb.plnSizeY = ctfb.winSizeY; + + ctfb.gdfBytesPP = 4; + ctfb.gdfIndex = GDF_32BIT_X888RGB; + + ctfb.isaBase = 0; + ctfb.pciBase = 0; + ctfb.memSize = info->screen_size; + + /* Cursor Start Address */ + ctfb.dprBase = 0; + ctfb.vprBase = 0; + ctfb.cprBase = 0; + + return &ctfb; +} +#endif /* defined(CONFIG_VIDEO) || defined(CONFIG_CFB_CONSOLE) */ diff --git a/board/freescale/common/fsl_diu_fb.h b/board/freescale/common/fsl_diu_fb.h deleted file mode 100644 index 3a5fc9f..0000000 --- a/board/freescale/common/fsl_diu_fb.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2007 Freescale Semiconductor, Inc. - * York Sun <yorksun@freescale.com> - * - * FSL DIU Framebuffer driver - * - * See file CREDITS for list of people who contributed to this - * project. - * - * 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 - */ - -struct fb_var_screeninfo { - unsigned int xres; /* visible resolution */ - unsigned int yres; - - unsigned int bits_per_pixel; /* guess what */ - - /* Timing: All values in pixclocks, except pixclock (of course) */ - unsigned int pixclock; /* pixel clock in ps (pico seconds) */ - unsigned int left_margin; /* time from sync to picture */ - unsigned int right_margin; /* time from picture to sync */ - unsigned int upper_margin; /* time from sync to picture */ - unsigned int lower_margin; - unsigned int hsync_len; /* length of horizontal sync */ - unsigned int vsync_len; /* length of vertical sync */ - unsigned int sync; /* see FB_SYNC_* */ - unsigned int vmode; /* see FB_VMODE_* */ - unsigned int rotate; /* angle we rotate counter clockwise */ -}; - -struct fb_info { - struct fb_var_screeninfo var; /* Current var */ - unsigned long smem_start; /* Start of frame buffer mem */ - /* (physical address) */ - unsigned int smem_len; /* Length of frame buffer mem */ - unsigned int type; /* see FB_TYPE_* */ - unsigned int line_length; /* length of a line in bytes */ - - char *screen_base; - unsigned long screen_size; -}; - - -extern char *fsl_fb_open(struct fb_info **info); -int fsl_diu_init(int xres, unsigned int pixel_format, int gamma_fix); diff --git a/board/freescale/mpc8610hpcd/mpc8610hpcd_diu.c b/board/freescale/mpc8610hpcd/mpc8610hpcd_diu.c index 960c8ed..81e53e7 100644 --- a/board/freescale/mpc8610hpcd/mpc8610hpcd_diu.c +++ b/board/freescale/mpc8610hpcd/mpc8610hpcd_diu.c @@ -26,17 +26,7 @@ #include <common.h> #include <command.h> #include <asm/io.h> - -#ifdef CONFIG_FSL_DIU_FB - -#include "../common/fsl_diu_fb.h" - -#if defined(CONFIG_VIDEO) || defined(CONFIG_CFB_CONSOLE) -#include <stdio_dev.h> -#include <video_fb.h> -#endif - -static int xres, yres; +#include <fsl_diu_fb.h> void diu_set_pixel_clock(unsigned int pixclock) { @@ -59,7 +49,7 @@ void diu_set_pixel_clock(unsigned int pixclock) debug("DIU: Modified value of CLKDVDR = 0x%08x\n", *guts_clkdvdr); } -int mpc8610hpcd_diu_init(void) +int platform_diu_init(unsigned int *xres, unsigned int *yres) { char *monitor_port; int gamma_fix; @@ -73,8 +63,8 @@ int mpc8610hpcd_diu_init(void) monitor_port = getenv("monitor"); if (!strncmp(monitor_port, "0", 1)) { /* 0 - DVI */ - xres = 1280; - yres = 1024; + *xres = 1280; + *yres = 1024; if (pixis_arch == 0x01) pixel_format = 0x88882317; else @@ -83,68 +73,26 @@ int mpc8610hpcd_diu_init(void) out_8(pixis_base + PIXIS_BRDCFG0, tmp_val | 0x08); } else if (!strncmp(monitor_port, "1", 1)) { /* 1 - Single link LVDS */ - xres = 1024; - yres = 768; + *xres = 1024; + *yres = 768; pixel_format = 0x88883316; gamma_fix = 0; out_8(pixis_base + PIXIS_BRDCFG0, (tmp_val & 0xf7) | 0x10); } else if (!strncmp(monitor_port, "2", 1)) { /* 2 - Double link LVDS */ - xres = 1280; - yres = 1024; + *xres = 1280; + *yres = 1024; pixel_format = 0x88883316; gamma_fix = 1; out_8(pixis_base + PIXIS_BRDCFG0, tmp_val & 0xe7); } else { /* DVI */ - xres = 1280; - yres = 1024; + *xres = 1280; + *yres = 1024; pixel_format = 0x88882317; gamma_fix = 0; out_8(pixis_base + PIXIS_BRDCFG0, tmp_val | 0x08); } - return fsl_diu_init(xres, pixel_format, gamma_fix); -} - -#if defined(CONFIG_VIDEO) || defined(CONFIG_CFB_CONSOLE) - -/* - * The Graphic Device - */ -static GraphicDevice ctfb; - -void *video_hw_init(void) -{ - struct fb_info *info; - - if (mpc8610hpcd_diu_init() < 0) - return NULL; - - /* fill in Graphic device struct */ - sprintf(ctfb.modeIdent, "%ix%ix%i %ikHz %iHz", xres, yres, 32, 64, 60); - - ctfb.frameAdrs = (unsigned int)fsl_fb_open(&info); - ctfb.winSizeX = xres; - ctfb.winSizeY = yres; - ctfb.plnSizeX = ctfb.winSizeX; - ctfb.plnSizeY = ctfb.winSizeY; - - ctfb.gdfBytesPP = 4; - ctfb.gdfIndex = GDF_32BIT_X888RGB; - - ctfb.isaBase = 0; - ctfb.pciBase = 0; - ctfb.memSize = info->screen_size; - - /* Cursor Start Address */ - ctfb.dprBase = 0; - ctfb.vprBase = 0; - ctfb.cprBase = 0; - - return &ctfb; + return fsl_diu_init(*xres, pixel_format, gamma_fix); } - -#endif /* defined(CONFIG_VIDEO) || defined(CONFIG_CFB_CONSOLE) */ - -#endif /* CONFIG_FSL_DIU_FB */ diff --git a/board/freescale/p1022ds/Makefile b/board/freescale/p1022ds/Makefile index 8ede2d6..678eb2a 100644 --- a/board/freescale/p1022ds/Makefile +++ b/board/freescale/p1022ds/Makefile @@ -16,6 +16,8 @@ COBJS-y += ddr.o COBJS-y += law.o COBJS-y += tlb.o +COBJS-$(CONFIG_FSL_DIU_FB) += diu.o + SRCS := $(SOBJS:.o=.S) $(COBJS-y:.o=.c) OBJS := $(addprefix $(obj),$(COBJS-y)) SOBJS := $(addprefix $(obj),$(SOBJS)) diff --git a/board/freescale/p1022ds/diu.c b/board/freescale/p1022ds/diu.c new file mode 100644 index 0000000..12b40a0 --- /dev/null +++ b/board/freescale/p1022ds/diu.c @@ -0,0 +1,304 @@ +/* + * Copyright 2010 Freescale Semiconductor, Inc. + * Authors: Timur Tabi <timur@freescale.com> + * + * FSL DIU Framebuffer driver + * + * 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. + */ + +#include <common.h> +#include <command.h> +#include <asm/io.h> +#include <stdio_dev.h> +#include <video_fb.h> +#include "../common/ngpixis.h" +#include <fsl_diu_fb.h> + +/* The CTL register is called 'csr' in the ngpixis_t structure */ +#define PX_CTL_ALTACC 0x80 + +#define PX_BRDCFG0_ELBC_SPI_MASK 0xc0 +#define PX_BRDCFG0_ELBC_SPI_ELBC 0x00 +#define PX_BRDCFG0_ELBC_SPI_NULL 0xc0 +#define PX_BRDCFG0_ELBC_DIU 0x02 + +#define PX_BRDCFG1_DVIEN 0x80 +#define PX_BRDCFG1_DFPEN 0x40 +#define PX_BRDCFG1_BACKLIGHT 0x20 + +#define PMUXCR_ELBCDIU_MASK 0xc0000000 +#define PMUXCR_ELBCDIU_NOR16 0x80000000 + +/* + * DIU Area Descriptor + * + * Note that we need to byte-swap the value before it's written to the AD + * register. So even though the registers don't look like they're in the same + * bit positions as they are on the MPC8610, the same value is written to the + * AD register on the MPC8610 and on the P1022. + */ +#define AD_BYTE_F 0x10000000 +#define AD_ALPHA_C_SHIFT 25 +#define AD_BLUE_C_SHIFT 23 +#define AD_GREEN_C_SHIFT 21 +#define AD_RED_C_SHIFT 19 +#define AD_PIXEL_S_SHIFT 16 +#define AD_COMP_3_SHIFT 12 +#define AD_COMP_2_SHIFT 8 +#define AD_COMP_1_SHIFT 4 +#define AD_COMP_0_SHIFT 0 + +/* + * Variables used by the DIU/LBC switching code. It's safe to makes these + * global, because the DIU requires DDR, so we'll only run this code after + * relocation. + */ +static u8 px_brdcfg0; +static u32 pmuxcr; +static void *lbc_lcs0_ba; +static void *lbc_lcs1_ba; + +void diu_set_pixel_clock(unsigned int pixclock) +{ + ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); + unsigned long speed_ccb, temp; + u32 pixval; + + speed_ccb = get_bus_freq(0); + temp = 1000000000 / pixclock; + temp *= 1000; + pixval = speed_ccb / temp; + debug("DIU pixval = %lu\n", pixval); + + /* Modify PXCLK in GUTS CLKDVDR */ + temp = in_be32(&gur->clkdvdr) & 0x2000FFFF; + out_be32(&gur->clkdvdr, temp); /* turn off clock */ + out_be32(&gur->clkdvdr, temp | 0x80000000 | ((pixval & 0x1F) << 16)); +} + +int platform_diu_init(unsigned int *xres, unsigned int *yres) +{ + ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); + char *monitor_port; + u32 pixel_format; + u8 temp; + + /* Save the LBC LCS0 and LCS1 addresses for the DIU mux functions */ + lbc_lcs0_ba = (void *)(get_lbc_br(0) & get_lbc_or(0) & 0xFFFF8000); + lbc_lcs1_ba = (void *)(get_lbc_br(1) & get_lbc_or(1) & 0xFFFF8000); + + pixel_format = cpu_to_le32(AD_BYTE_F | (3 << AD_ALPHA_C_SHIFT) | + (0 << AD_BLUE_C_SHIFT) | (1 << AD_GREEN_C_SHIFT) | + (2 << AD_RED_C_SHIFT) | (8 << AD_COMP_3_SHIFT) | + (8 << AD_COMP_2_SHIFT) | (8 << AD_COMP_1_SHIFT) | + (8 << AD_COMP_0_SHIFT) | (3 << AD_PIXEL_S_SHIFT)); + + temp = in_8(&pixis->brdcfg1); + + monitor_port = getenv("monitor"); + if (!strncmp(monitor_port, "1", 1)) { /* 1 - Single link LVDS */ + *xres = 1024; + *yres = 768; + /* Enable the DFP port, disable the DVI and the backlight */ + temp &= ~(PX_BRDCFG1_DVIEN | PX_BRDCFG1_BACKLIGHT); + temp |= PX_BRDCFG1_DFPEN; + } else { /* DVI */ + *xres = 1280; + *yres = 1024; + /* Enable the DVI port, disable the DFP and the backlight */ + temp &= ~(PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT); + temp |= PX_BRDCFG1_DVIEN; + } + + out_8(&pixis->brdcfg1, temp); + + /* + * Enable PIXIS indirect access mode. This is a hack that allows us to + * access PIXIS registers even when the LBC pins have been muxed to the + * DIU. + */ + setbits_8(&pixis->csr, PX_CTL_ALTACC); + + /* + * Route the LAD pins to the DIU. This will disable access to the eLBC, + * which means we won't be able to read/write any NOR flash addresses! + */ + out_8(lbc_lcs0_ba, offsetof(ngpixis_t, brdcfg0)); + px_brdcfg0 = in_8(lbc_lcs1_ba); + out_8(lbc_lcs1_ba, px_brdcfg0 | PX_BRDCFG0_ELBC_DIU); + + /* Setting PMUXCR to switch to DVI from ELBC */ + clrsetbits_be32(&gur->pmuxcr, + PMUXCR_ELBCDIU_MASK, PMUXCR_ELBCDIU_NOR16); + pmuxcr = in_be32(&gur->pmuxcr); + + return fsl_diu_init(*xres, pixel_format, 0); +} + +#ifdef CONFIG_CFI_FLASH_USE_WEAK_ACCESSORS + +/* + * set_mux_to_lbc - disable the DIU so that we can read/write to elbc + * + * On the Freescale P1022, the DIU video signal and the LBC address/data lines + * share the same pins, which means that when the DIU is active (e.g. the + * console is on the DVI display), NOR flash cannot be accessed. So we use the + * weak accessor feature of the CFI flash code to temporarily switch the pin + * mux from DIU to LBC whenever we want to read or write flash. This has a + * significant performance penalty, but it's the only way to make it work. + * + * There are two muxes: one on the chip, and one on the board. The chip mux + * controls whether the pins are used for the DIU or the LBC, and it is + * set via PMUXCR. The board mux controls whether those signals go to + * the video connector or the NOR flash chips, and it is set via the ngPIXIS. + */ +static int set_mux_to_lbc(void) +{ + ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR; + + /* Switch the muxes only if they're currently set to DIU mode */ + if ((in_be32(&gur->pmuxcr) & PMUXCR_ELBCDIU_MASK) == + PMUXCR_ELBCDIU_NOR16) { + /* + * In DIU mode, the PIXIS can only be accessed indirectly + * since we can't read/write the LBC directly. + */ + + /* Set the board mux to LBC. This will disable the display. */ + out_8(lbc_lcs0_ba, offsetof(ngpixis_t, brdcfg0)); + px_brdcfg0 = in_8(lbc_lcs1_ba); + out_8(lbc_lcs1_ba, (px_brdcfg0 & ~(PX_BRDCFG0_ELBC_SPI_MASK + | PX_BRDCFG0_ELBC_DIU)) | PX_BRDCFG0_ELBC_SPI_ELBC); + + /* Disable indirect PIXIS mode */ + out_8(lbc_lcs0_ba, offsetof(ngpixis_t, csr)); + clrbits_8(lbc_lcs1_ba, PX_CTL_ALTACC); + + /* Set the chip mux to LBC mode, so that writes go to flash. */ + out_be32(&gur->pmuxcr, (pmuxcr & ~PMUXCR_ELBCDIU_MASK) | + PMUXCR_ELBCDIU_NOR16); + in_be32(&gur->pmuxcr); + + return 1; + } + + return 0; +} + +/* + * set_mux_to_diu - re-enable the DIU muxing + * + * This function restores the chip and board muxing to point to the DIU. + */ +static void set_mux_to_diu(void) +{ + ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR; + + /* Enable indirect PIXIS mode */ + setbits_8(&pixis->csr, PX_CTL_ALTACC); + + /* Set the board mux to DIU. This will enable the display. */ + out_8(lbc_lcs0_ba, offsetof(ngpixis_t, brdcfg0)); + out_8(lbc_lcs1_ba, px_brdcfg0); + in_8(lbc_lcs1_ba); + + /* Set the chip mux to DIU mode. */ + out_be32(&gur->pmuxcr, pmuxcr); + in_be32(&gur->pmuxcr); +} + +void flash_write8(u8 value, void *addr) +{ + int sw = set_mux_to_lbc(); + + __raw_writeb(value, addr); + if (sw) + set_mux_to_diu(); +} + +void flash_write16(u16 value, void *addr) +{ + int sw = set_mux_to_lbc(); + + __raw_writew(value, addr); + if (sw) + set_mux_to_diu(); +} + +void flash_write32(u32 value, void *addr) +{ + int sw = set_mux_to_lbc(); + + __raw_writel(value, addr); + if (sw) + set_mux_to_diu(); +} + +void flash_write64(u64 value, void *addr) +{ + int sw = set_mux_to_lbc(); + + /* There is no __raw_writeq(), so do the write manually */ + *(volatile u64 *)addr = value; + if (sw) + set_mux_to_diu(); +} + +u8 flash_read8(void *addr) +{ + u8 ret; + + int sw = set_mux_to_lbc(); + + ret = __raw_readb(addr); + if (sw) + set_mux_to_diu(); + + return ret; +} + +u16 flash_read16(void *addr) +{ + u16 ret; + + int sw = set_mux_to_lbc(); + + ret = __raw_readw(addr); + if (sw) + set_mux_to_diu(); + + return ret; +} + +u32 flash_read32(void *addr) +{ + u32 ret; + + int sw = set_mux_to_lbc(); + + ret = __raw_readl(addr); + if (sw) + set_mux_to_diu(); + + return ret; +} + +u64 flash_read64(void *addr) +{ + u64 ret; + + int sw = set_mux_to_lbc(); + + /* There is no __raw_readq(), so do the read manually */ + ret = *(volatile u64 *)addr; + if (sw) + set_mux_to_diu(); + + return ret; +} + +#endif |