diff options
Diffstat (limited to 'qemu/roms/u-boot/board/freescale/p1022ds/diu.c')
-rw-r--r-- | qemu/roms/u-boot/board/freescale/p1022ds/diu.c | 477 |
1 files changed, 0 insertions, 477 deletions
diff --git a/qemu/roms/u-boot/board/freescale/p1022ds/diu.c b/qemu/roms/u-boot/board/freescale/p1022ds/diu.c deleted file mode 100644 index 6fd4d953b..000000000 --- a/qemu/roms/u-boot/board/freescale/p1022ds/diu.c +++ /dev/null @@ -1,477 +0,0 @@ -/* - * Copyright 2010-2011 Freescale Semiconductor, Inc. - * Authors: Timur Tabi <timur@freescale.com> - * - * FSL DIU Framebuffer driver - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <command.h> -#include <linux/ctype.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 -#define PMUXCR_ELBCDIU_DIU 0x40000000 - -/* - * 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; -static u32 old_br0, old_or0, old_br1, old_or1; -static u32 new_br0, new_or0, new_br1, new_or1; - -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 = %u\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, const char *port) -{ - ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); - const char *name; - u32 pixel_format; - u8 temp; - phys_addr_t phys0, phys1; /* BR0/BR1 physical addresses */ - - /* - * Indirect mode requires both BR0 and BR1 to be set to "GPCM", - * otherwise writes to these addresses won't actually appear on the - * local bus, and so the PIXIS won't see them. - * - * In FCM mode, writes go to the NAND controller, which does not pass - * them to the localbus directly. So we force BR0 and BR1 into GPCM - * mode, since we don't care about what's behind the localbus any - * more. However, we save those registers first, so that we can - * restore them when necessary. - */ - new_br0 = old_br0 = get_lbc_br(0); - new_br1 = old_br1 = get_lbc_br(1); - new_or0 = old_or0 = get_lbc_or(0); - new_or1 = old_or1 = get_lbc_or(1); - - /* - * Use the existing BRx/ORx values if it's already GPCM. Otherwise, - * force the values to simple 32KB GPCM windows with the most - * conservative timing. - */ - if ((old_br0 & BR_MSEL) != BR_MS_GPCM) { - new_br0 = (get_lbc_br(0) & BR_BA) | BR_V; - new_or0 = OR_AM_32KB | 0xFF7; - set_lbc_br(0, new_br0); - set_lbc_or(0, new_or0); - } - if ((old_br1 & BR_MSEL) != BR_MS_GPCM) { - new_br1 = (get_lbc_br(1) & BR_BA) | BR_V; - new_or1 = OR_AM_32KB | 0xFF7; - set_lbc_br(1, new_br1); - set_lbc_or(1, new_or1); - } - - /* - * Determine the physical addresses for Chip Selects 0 and 1. The - * BR0/BR1 registers contain the truncated physical addresses for the - * chip selects, mapped via the localbus LAW. Since the BRx registers - * only contain the lower 32 bits of the address, we have to determine - * the upper 4 bits some other way. The proper way is to scan the LAW - * table looking for a matching localbus address. Instead, we cheat. - * We know that the upper bits are 0 for 32-bit addressing, or 0xF for - * 36-bit addressing. - */ -#ifdef CONFIG_PHYS_64BIT - phys0 = 0xf00000000ULL | (old_br0 & old_or0 & BR_BA); - phys1 = 0xf00000000ULL | (old_br1 & old_or1 & BR_BA); -#else - phys0 = old_br0 & old_or0 & BR_BA; - phys1 = old_br1 & old_or1 & BR_BA; -#endif - - /* Save the LBC LCS0 and LCS1 addresses for the DIU mux functions */ - lbc_lcs0_ba = map_physmem(phys0, 1, 0); - lbc_lcs1_ba = map_physmem(phys1, 1, 0); - - 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); - - if (strncmp(port, "lvds", 4) == 0) { - /* Single link LVDS */ - temp &= ~PX_BRDCFG1_DVIEN; - /* - * LVDS also needs backlight enabled, otherwise the display - * will be blank. - */ - temp |= (PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT); - name = "Single-Link LVDS"; - } else { /* DVI */ - /* Enable the DVI port, disable the DFP and the backlight */ - temp &= ~(PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT); - temp |= PX_BRDCFG1_DVIEN; - name = "DVI"; - } - - printf("DIU: Switching to %s monitor @ %ux%u\n", name, xres, yres); - 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); - in_8(lbc_lcs1_ba); - - /* Set PMUXCR to switch the muxed pins from the LBC to the DIU */ - clrsetbits_be32(&gur->pmuxcr, PMUXCR_ELBCDIU_MASK, PMUXCR_ELBCDIU_DIU); - pmuxcr = in_be32(&gur->pmuxcr); - - return fsl_diu_init(xres, yres, pixel_format, 0); -} - -/* - * 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)); - out_8(lbc_lcs1_ba, px_brdcfg0); - in_8(lbc_lcs1_ba); - - /* 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); - - /* Restore the BR0 and BR1 settings */ - set_lbc_br(0, old_br0); - set_lbc_or(0, old_or0); - set_lbc_br(1, old_br1); - set_lbc_or(1, old_or1); - - 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; - - /* Set BR0 and BR1 to GPCM mode */ - set_lbc_br(0, new_br0); - set_lbc_or(0, new_or0); - set_lbc_br(1, new_br1); - set_lbc_or(1, new_or1); - - /* 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 | PX_BRDCFG0_ELBC_DIU); - in_8(lbc_lcs1_ba); - - /* Set the chip mux to DIU mode. */ - out_be32(&gur->pmuxcr, pmuxcr); - in_be32(&gur->pmuxcr); -} - -/* - * pixis_read - board-specific function to read from the PIXIS - * - * This function overrides the generic pixis_read() function, so that it can - * use PIXIS indirect mode if necessary. - */ -u8 pixis_read(unsigned int reg) -{ - ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR; - - /* Use indirect mode if the mux is currently set to DIU mode */ - if ((in_be32(&gur->pmuxcr) & PMUXCR_ELBCDIU_MASK) != - PMUXCR_ELBCDIU_NOR16) { - out_8(lbc_lcs0_ba, reg); - return in_8(lbc_lcs1_ba); - } else { - void *p = (void *)PIXIS_BASE; - - return in_8(p + reg); - } -} - -/* - * pixis_write - board-specific function to write to the PIXIS - * - * This function overrides the generic pixis_write() function, so that it can - * use PIXIS indirect mode if necessary. - */ -void pixis_write(unsigned int reg, u8 value) -{ - ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR; - - /* Use indirect mode if the mux is currently set to DIU mode */ - if ((in_be32(&gur->pmuxcr) & PMUXCR_ELBCDIU_MASK) != - PMUXCR_ELBCDIU_NOR16) { - out_8(lbc_lcs0_ba, reg); - out_8(lbc_lcs1_ba, value); - /* Do a read-back to ensure the write completed */ - in_8(lbc_lcs1_ba); - } else { - void *p = (void *)PIXIS_BASE; - - out_8(p + reg, value); - } -} - -void pixis_bank_reset(void) -{ - /* - * For some reason, a PIXIS bank reset does not work if the PIXIS is - * in indirect mode, so switch to direct mode first. - */ - set_mux_to_lbc(); - - out_8(&pixis->vctl, 0); - out_8(&pixis->vctl, 1); - - while (1); -} - -#ifdef CONFIG_CFI_FLASH_USE_WEAK_ACCESSORS - -void flash_write8(u8 value, void *addr) -{ - int sw = set_mux_to_lbc(); - - __raw_writeb(value, addr); - if (sw) { - /* - * To ensure the post-write is completed to eLBC, software must - * perform a dummy read from one valid address from eLBC space - * before changing the eLBC_DIU from NOR mode to DIU mode. - * set_mux_to_diu() includes a sync that will ensure the - * __raw_readb() completes before it switches the mux. - */ - __raw_readb(addr); - set_mux_to_diu(); - } -} - -void flash_write16(u16 value, void *addr) -{ - int sw = set_mux_to_lbc(); - - __raw_writew(value, addr); - if (sw) { - /* - * To ensure the post-write is completed to eLBC, software must - * perform a dummy read from one valid address from eLBC space - * before changing the eLBC_DIU from NOR mode to DIU mode. - * set_mux_to_diu() includes a sync that will ensure the - * __raw_readb() completes before it switches the mux. - */ - __raw_readb(addr); - set_mux_to_diu(); - } -} - -void flash_write32(u32 value, void *addr) -{ - int sw = set_mux_to_lbc(); - - __raw_writel(value, addr); - if (sw) { - /* - * To ensure the post-write is completed to eLBC, software must - * perform a dummy read from one valid address from eLBC space - * before changing the eLBC_DIU from NOR mode to DIU mode. - * set_mux_to_diu() includes a sync that will ensure the - * __raw_readb() completes before it switches the mux. - */ - __raw_readb(addr); - set_mux_to_diu(); - } -} - -void flash_write64(u64 value, void *addr) -{ - int sw = set_mux_to_lbc(); - uint32_t *p = addr; - - /* - * There is no __raw_writeq(), so do the write manually. We don't trust - * the compiler, so we use inline assembly. - */ - __asm__ __volatile__( - "stw%U0%X0 %2,%0;\n" - "stw%U1%X1 %3,%1;\n" - : "=m" (*p), "=m" (*(p + 1)) - : "r" ((uint32_t) (value >> 32)), "r" ((uint32_t) (value))); - - if (sw) { - /* - * To ensure the post-write is completed to eLBC, software must - * perform a dummy read from one valid address from eLBC space - * before changing the eLBC_DIU from NOR mode to DIU mode. We - * read addr+4 because we just wrote to addr+4, so that's how we - * maintain execution order. set_mux_to_diu() includes a sync - * that will ensure the __raw_readb() completes before it - * switches the mux. - */ - __raw_readb(addr + 4); - 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 |