diff options
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/common/sys_eeprom.c | 44 | ||||
-rw-r--r-- | board/freescale/corenet_ds/pci.c | 28 | ||||
-rw-r--r-- | board/freescale/mpc8569mds/ddr.c | 16 | ||||
-rw-r--r-- | board/freescale/mpc8569mds/mpc8569mds.c | 26 | ||||
-rw-r--r-- | board/freescale/mpc8569mds/tlb.c | 15 | ||||
-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 | ||||
-rw-r--r-- | board/freescale/p1022ds/p1022ds.c | 67 |
11 files changed, 525 insertions, 151 deletions
diff --git a/board/freescale/common/fsl_diu_fb.c b/board/freescale/common/fsl_diu_fb.c index 394b71f32f..35ed938bef 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 3a5fc9ff82..0000000000 --- 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/common/sys_eeprom.c b/board/freescale/common/sys_eeprom.c index 3929ad0aac..11dfd84fe6 100644 --- a/board/freescale/common/sys_eeprom.c +++ b/board/freescale/common/sys_eeprom.c @@ -28,13 +28,21 @@ #include <i2c.h> #include <linux/ctype.h> +#ifdef CONFIG_SYS_I2C_EEPROM_CCID #include "../common/eeprom.h" +#define MAX_NUM_PORTS 8 +#endif -#if !defined(CONFIG_SYS_I2C_EEPROM_CCID) && !defined(CONFIG_SYS_I2C_EEPROM_NXID) -#error "Please define either CONFIG_SYS_I2C_EEPROM_CCID or CONFIG_SYS_I2C_EEPROM_NXID" +#ifdef CONFIG_SYS_I2C_EEPROM_NXID +#define MAX_NUM_PORTS 8 +#define NXID_VERSION 0 #endif -#define MAX_NUM_PORTS 8 /* This value must be 8 as defined in doc */ +#ifdef CONFIG_SYS_I2C_EEPROM_NXID_1 +#define CONFIG_SYS_I2C_EEPROM_NXID +#define MAX_NUM_PORTS 23 +#define NXID_VERSION 1 +#endif /** * static eeprom: EEPROM layout for CCID or NXID formats @@ -68,8 +76,8 @@ static struct __attribute__ ((__packed__)) eeprom { u8 res_1[21]; /* 0x2b - 0x3f Reserved */ u8 mac_count; /* 0x40 Number of MAC addresses */ u8 mac_flag; /* 0x41 MAC table flags */ - u8 mac[MAX_NUM_PORTS][6]; /* 0x42 - 0x71 MAC addresses */ - u32 crc; /* 0x72 CRC32 checksum */ + u8 mac[MAX_NUM_PORTS][6]; /* 0x42 - x MAC addresses */ + u32 crc; /* x+1 CRC32 checksum */ #endif } e; @@ -204,7 +212,7 @@ static void update_crc(void) */ static int prog_eeprom(void) { - int ret = 0; /* shut up gcc */ + int ret = 0; int i; void *p; #ifdef CONFIG_SYS_EEPROM_BUS_NUM @@ -225,6 +233,11 @@ static int prog_eeprom(void) i2c_set_bus_num(CONFIG_SYS_EEPROM_BUS_NUM); #endif + /* + * The AT24C02 datasheet says that data can only be written in page + * mode, which means 8 bytes at a time, and it takes up to 5ms to + * complete a given write. + */ for (i = 0, p = &e; i < sizeof(e); i += 8, p += 8) { ret = i2c_write(CONFIG_SYS_I2C_EEPROM_ADDR, i, CONFIG_SYS_I2C_EEPROM_ADDR_LEN, p, min((sizeof(e) - i), 8)); @@ -233,12 +246,23 @@ static int prog_eeprom(void) udelay(5000); /* 5ms write cycle timing */ } + if (!ret) { + /* Verify the write by reading back the EEPROM and comparing */ + struct eeprom e2; + + ret = i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, 0, + CONFIG_SYS_I2C_EEPROM_ADDR_LEN, (void *)&e2, sizeof(e2)); + if (!ret && memcmp(&e, &e2, sizeof(e))) + ret = -1; + } + #ifdef CONFIG_SYS_EEPROM_BUS_NUM i2c_set_bus_num(bus); #endif if (ret) { printf("Programming failed.\n"); + has_been_read = 0; return -1; } @@ -300,7 +324,7 @@ static void set_mac_address(unsigned int index, const char *string) char *p = (char *) string; unsigned int i; - if (!string) { + if ((index >= MAX_NUM_PORTS) || !string) { printf("Usage: mac <n> XX:XX:XX:XX:XX:XX\n"); return; } @@ -333,7 +357,7 @@ int do_mac(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (cmd == 'i') { #ifdef CONFIG_SYS_I2C_EEPROM_NXID memcpy(e.id, "NXID", sizeof(e.id)); - e.version = 0; + e.version = NXID_VERSION; #else memcpy(e.id, "CCID", sizeof(e.id)); #endif @@ -382,8 +406,8 @@ int do_mac(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) e.mac_count = simple_strtoul(argv[2], NULL, 16); update_crc(); break; - case '0' ... '7': /* "mac 0" through "mac 7" */ - set_mac_address(cmd - '0', argv[2]); + case '0' ... '9': /* "mac 0" through "mac 22" */ + set_mac_address(simple_strtoul(argv[1], NULL, 10), argv[2]); break; case 'h': /* help */ default: diff --git a/board/freescale/corenet_ds/pci.c b/board/freescale/corenet_ds/pci.c index 2994e366c2..e1bca1984c 100644 --- a/board/freescale/corenet_ds/pci.c +++ b/board/freescale/corenet_ds/pci.c @@ -40,10 +40,14 @@ static struct pci_controller pcie2_hose; static struct pci_controller pcie3_hose; #endif +#ifdef CONFIG_PCIE4 +static struct pci_controller pcie4_hose; +#endif + void pci_init_board(void) { volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); - struct fsl_pci_info pci_info[3]; + struct fsl_pci_info pci_info[4]; u32 devdisr; int first_free_busno = 0; int num = 0; @@ -119,6 +123,28 @@ void pci_init_board(void) #else setbits_be32(&gur->devdisr, FSL_CORENET_DEVDISR_PCIE3); /* disable */ #endif + +#ifdef CONFIG_PCIE4 + pcie_configured = is_serdes_configured(PCIE4); + + if (pcie_configured && !(devdisr & FSL_CORENET_DEVDISR_PCIE4)) { + set_next_law(CONFIG_SYS_PCIE4_MEM_PHYS, LAW_SIZE_512M, + LAW_TRGT_IF_PCIE_4); + set_next_law(CONFIG_SYS_PCIE4_IO_PHYS, LAW_SIZE_64K, + LAW_TRGT_IF_PCIE_4); + SET_STD_PCIE_INFO(pci_info[num], 4); + pcie_ep = fsl_setup_hose(&pcie4_hose, pci_info[num].regs); + printf(" PCIE4 connected to as %s (base addr %lx)\n", + pcie_ep ? "End Point" : "Root Complex", + pci_info[num].regs); + first_free_busno = fsl_pci_init_port(&pci_info[num++], + &pcie4_hose, first_free_busno); + } else { + printf (" PCIE4: disabled\n"); + } +#else + setbits_be32(&gur->devdisr, FSL_CORENET_DEVDISR_PCIE4); /* disable */ +#endif } void pci_of_setup(void *blob, bd_t *bd) diff --git a/board/freescale/mpc8569mds/ddr.c b/board/freescale/mpc8569mds/ddr.c index e938788f07..e3f5b4aa21 100644 --- a/board/freescale/mpc8569mds/ddr.c +++ b/board/freescale/mpc8569mds/ddr.c @@ -77,8 +77,18 @@ void fsl_ddr_board_options(memctl_options_t *popts, popts->write_data_delay = 2; /* - * Factors to consider for half-strength driver enable: - * - number of DIMMs installed + * Enable half drive strength */ - popts->half_strength_driver_enable = 0; + popts->half_strength_driver_enable = 1; + + /* Write leveling override */ + popts->wrlvl_en = 1; + popts->wrlvl_override = 1; + popts->wrlvl_sample = 0xa; + popts->wrlvl_start = 0x4; + + /* Rtt and Rtt_W override */ + popts->rtt_override = 1; + popts->rtt_override_value = DDR3_RTT_60_OHM; + popts->rtt_wr_override_value = 0; /* Rtt_WR= dynamic ODT off */ } diff --git a/board/freescale/mpc8569mds/mpc8569mds.c b/board/freescale/mpc8569mds/mpc8569mds.c index 01b7dcb70c..795e5654e8 100644 --- a/board/freescale/mpc8569mds/mpc8569mds.c +++ b/board/freescale/mpc8569mds/mpc8569mds.c @@ -27,6 +27,7 @@ #include <pci.h> #include <asm/processor.h> #include <asm/mmu.h> +#include <asm/cache.h> #include <asm/immap_85xx.h> #include <asm/fsl_pci.h> #include <asm/fsl_ddr_sdram.h> @@ -211,6 +212,31 @@ int board_early_init_f (void) return 0; } +int board_early_init_r(void) +{ + const unsigned int flashbase = CONFIG_SYS_NAND_BASE; + const u8 flash_esel = 0; + + /* + * Remap Boot flash to caching-inhibited + * so that flash can be erased properly. + */ + + /* Flush d-cache and invalidate i-cache of any FLASH data */ + flush_dcache(); + invalidate_icache(); + + /* invalidate existing TLB entry for flash */ + disable_tlb(flash_esel); + + set_tlb(1, flashbase, CONFIG_SYS_NAND_BASE, /* tlb, epn, rpn */ + MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G, /* perms, wimge */ + 0, flash_esel, /* ts, esel */ + BOOKE_PAGESZ_64M, 1); /* tsize, iprot */ + + return 0; +} + int checkboard (void) { printf ("Board: 8569 MDS\n"); diff --git a/board/freescale/mpc8569mds/tlb.c b/board/freescale/mpc8569mds/tlb.c index 73dcc3e66c..f852fc35c3 100644 --- a/board/freescale/mpc8569mds/tlb.c +++ b/board/freescale/mpc8569mds/tlb.c @@ -1,5 +1,5 @@ /* - * Copyright 2009 Freescale Semiconductor, Inc. + * Copyright 2009-2010 Freescale Semiconductor, Inc. * * (C) Copyright 2000 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. @@ -46,15 +46,20 @@ struct fsl_e_tlb_entry tlb_table[] = { /* TLB 1 Initializations */ /* - * TLBe 0: 64M Non-cacheable, guarded + * TLBe 0: 64M write-through, guarded * Out of reset this entry is only 4K. - * 0xfc000000 256K NAND FLASH (CS3) - * 0xfe000000 32M NOR FLASH (CS0) + * 0xfc000000 32MB NAND FLASH (CS3) + * 0xfe000000 32MB NOR FLASH (CS0) */ +#ifdef CONFIG_NAND_SPL SET_TLB_ENTRY(1, CONFIG_SYS_NAND_BASE, CONFIG_SYS_NAND_BASE, MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G, + 0, 0, BOOKE_PAGESZ_1M, 1), +#else + SET_TLB_ENTRY(1, CONFIG_SYS_NAND_BASE, CONFIG_SYS_NAND_BASE, + MAS3_SX|MAS3_SW|MAS3_SR, MAS2_W|MAS2_G, 0, 0, BOOKE_PAGESZ_64M, 1), - +#endif /* * TLBe 1: 256KB Non-cacheable, guarded * 0xf8000000 32K BCSR diff --git a/board/freescale/mpc8610hpcd/mpc8610hpcd_diu.c b/board/freescale/mpc8610hpcd/mpc8610hpcd_diu.c index 960c8eda7d..81e53e734f 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 8ede2d6055..678eb2ae06 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 0000000000..12b40a01ed --- /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 diff --git a/board/freescale/p1022ds/p1022ds.c b/board/freescale/p1022ds/p1022ds.c index 5cdee9ff70..ee93e8b815 100644 --- a/board/freescale/p1022ds/p1022ds.c +++ b/board/freescale/p1022ds/p1022ds.c @@ -27,6 +27,7 @@ #include <asm/mp.h> #include <netdev.h> #include <i2c.h> +#include <hwconfig.h> #include "../common/ngpixis.h" @@ -90,34 +91,58 @@ phys_size_t initdram(int board_type) #define CONFIG_TFP410_I2C_ADDR 0x38 +/* Masks for the SSI_TDM and AUDCLK bits of the ngPIXIS BRDCFG1 register. */ +#define CONFIG_PIXIS_BRDCFG1_SSI_TDM_MASK 0x0c +#define CONFIG_PIXIS_BRDCFG1_AUDCLK_MASK 0x03 + +/* Route the I2C1 pins to the SSI port instead. */ +#define CONFIG_PIXIS_BRDCFG1_SSI_TDM_SSI 0x08 + +/* Choose the 12.288Mhz codec reference clock */ +#define CONFIG_PIXIS_BRDCFG1_AUDCLK_12 0x02 + +/* Choose the 11.2896Mhz codec reference clock */ +#define CONFIG_PIXIS_BRDCFG1_AUDCLK_11 0x01 + int misc_init_r(void) { u8 temp; + const char *audclk; + size_t arglen; - /* Enable the TFP410 Encoder */ + /* For DVI, enable the TFP410 Encoder. */ temp = 0xBF; if (i2c_write(CONFIG_TFP410_I2C_ADDR, 0x08, 1, &temp, sizeof(temp)) < 0) return -1; - - /* Verify if enabled */ - temp = 0; if (i2c_read(CONFIG_TFP410_I2C_ADDR, 0x08, 1, &temp, sizeof(temp)) < 0) return -1; - debug("DVI Encoder Read: 0x%02x\n", temp); temp = 0x10; if (i2c_write(CONFIG_TFP410_I2C_ADDR, 0x0A, 1, &temp, sizeof(temp)) < 0) return -1; - - /* Verify if enabled */ - temp = 0; if (i2c_read(CONFIG_TFP410_I2C_ADDR, 0x0A, 1, &temp, sizeof(temp)) < 0) return -1; - debug("DVI Encoder Read: 0x%02x\n",temp); + /* + * Enable the reference clock for the WM8776 codec, and route the MUX + * pins for SSI. The default is the 12.288 MHz clock + */ + + temp = in_8(&pixis->brdcfg1) & ~(CONFIG_PIXIS_BRDCFG1_SSI_TDM_MASK | + CONFIG_PIXIS_BRDCFG1_AUDCLK_MASK); + temp |= CONFIG_PIXIS_BRDCFG1_SSI_TDM_SSI; + + audclk = hwconfig_arg("audclk", &arglen); + /* Check the first two chars only */ + if (audclk && (strncmp(audclk, "11", 2) == 0)) + temp |= CONFIG_PIXIS_BRDCFG1_AUDCLK_11; + else + temp |= CONFIG_PIXIS_BRDCFG1_AUDCLK_12; + out_8(&pixis->brdcfg1, temp); + return 0; } @@ -310,6 +335,27 @@ int board_eth_init(bd_t *bis) } #ifdef CONFIG_OF_BOARD_SETUP +/** + * ft_codec_setup - fix up the clock-frequency property of the codec node + * + * Update the clock-frequency property based on the value of the 'audclk' + * hwconfig option. If audclk is not specified, then default to 12.288MHz. + */ +static void ft_codec_setup(void *blob, const char *compatible) +{ + const char *audclk; + size_t arglen; + u32 freq; + + audclk = hwconfig_arg("audclk", &arglen); + if (audclk && (strncmp(audclk, "11", 2) == 0)) + freq = 11289600; + else + freq = 12288000; + + do_fixup_by_compat_u32(blob, compatible, "clock-frequency", freq, 1); +} + void ft_board_setup(void *blob, bd_t *bd) { phys_addr_t base; @@ -327,6 +373,9 @@ void ft_board_setup(void *blob, bd_t *bd) #ifdef CONFIG_FSL_SGMII_RISER fsl_sgmii_riser_fdt_fixup(blob); #endif + + /* Update the WM8776 node's clock frequency property */ + ft_codec_setup(blob, "wlf,wm8776"); } #endif |