diff options
author | Takashi Iwai <tiwai@suse.de> | 2010-10-25 10:00:30 +0200 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2010-10-25 10:00:30 +0200 |
commit | aa5c14d5c0d3e4c587db4a1b220b9c86415c538f (patch) | |
tree | 0114637e8be2b38176e7e91e6cea3501b22cb66a /arch/powerpc | |
parent | 79fc84c7e0d2fe89c4e82f3a26fd8b0d13c31703 (diff) | |
parent | b11bdb5254ff17cb63e4ae5088b73fdcd2cc2602 (diff) |
Merge branch 'topic/asoc' into for-linus
Conflicts:
arch/powerpc/platforms/85xx/p1022_ds.c
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/boot/dts/mpc8610_hpcd.dts | 1 | ||||
-rw-r--r-- | arch/powerpc/configs/mpc85xx_defconfig | 3 | ||||
-rw-r--r-- | arch/powerpc/configs/mpc85xx_smp_defconfig | 3 | ||||
-rw-r--r-- | arch/powerpc/include/asm/fsl_guts.h (renamed from arch/powerpc/include/asm/immap_86xx.h) | 111 | ||||
-rw-r--r-- | arch/powerpc/platforms/85xx/p1022_ds.c | 211 |
5 files changed, 292 insertions, 37 deletions
diff --git a/arch/powerpc/boot/dts/mpc8610_hpcd.dts b/arch/powerpc/boot/dts/mpc8610_hpcd.dts index 9535ce68caa..83c3218cb4d 100644 --- a/arch/powerpc/boot/dts/mpc8610_hpcd.dts +++ b/arch/powerpc/boot/dts/mpc8610_hpcd.dts @@ -286,6 +286,7 @@ ssi@16100 { compatible = "fsl,mpc8610-ssi"; + status = "disabled"; cell-index = <1>; reg = <0x16100 0x100>; interrupt-parent = <&mpic>; diff --git a/arch/powerpc/configs/mpc85xx_defconfig b/arch/powerpc/configs/mpc85xx_defconfig index c3b113b2ca3..3aeb5949cfe 100644 --- a/arch/powerpc/configs/mpc85xx_defconfig +++ b/arch/powerpc/configs/mpc85xx_defconfig @@ -124,6 +124,9 @@ CONFIG_I2C_CPM=m CONFIG_I2C_MPC=y # CONFIG_HWMON is not set CONFIG_VIDEO_OUTPUT_CONTROL=y +CONFIG_FB=y +CONFIG_FB_FSL_DIU=y +# CONFIG_VGA_CONSOLE is not set CONFIG_SOUND=y CONFIG_SND=y # CONFIG_SND_SUPPORT_OLD_API is not set diff --git a/arch/powerpc/configs/mpc85xx_smp_defconfig b/arch/powerpc/configs/mpc85xx_smp_defconfig index a075da2ea3f..d62c8016f4b 100644 --- a/arch/powerpc/configs/mpc85xx_smp_defconfig +++ b/arch/powerpc/configs/mpc85xx_smp_defconfig @@ -126,6 +126,9 @@ CONFIG_I2C_CPM=m CONFIG_I2C_MPC=y # CONFIG_HWMON is not set CONFIG_VIDEO_OUTPUT_CONTROL=y +CONFIG_FB=y +CONFIG_FB_FSL_DIU=y +# CONFIG_VGA_CONSOLE is not set CONFIG_SOUND=y CONFIG_SND=y # CONFIG_SND_SUPPORT_OLD_API is not set diff --git a/arch/powerpc/include/asm/immap_86xx.h b/arch/powerpc/include/asm/fsl_guts.h index 0f165e59c32..bebd12463ec 100644 --- a/arch/powerpc/include/asm/immap_86xx.h +++ b/arch/powerpc/include/asm/fsl_guts.h @@ -1,5 +1,5 @@ /** - * MPC86xx Internal Memory Map + * Freecale 85xx and 86xx Global Utilties register set * * Authors: Jeff Brown * Timur Tabi <timur@freescale.com> @@ -10,73 +10,112 @@ * 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 header file defines structures for various 86xx SOC devices that are - * used by multiple source files. */ -#ifndef __ASM_POWERPC_IMMAP_86XX_H__ -#define __ASM_POWERPC_IMMAP_86XX_H__ +#ifndef __ASM_POWERPC_FSL_GUTS_H__ +#define __ASM_POWERPC_FSL_GUTS_H__ #ifdef __KERNEL__ -/* Global Utility Registers */ -struct ccsr_guts { +/* + * These #ifdefs are safe because it's not possible to build a kernel that + * runs on e500 and e600 cores. + */ + +#if !defined(CONFIG_PPC_85xx) && !defined(CONFIG_PPC_86xx) +#error Only 85xx and 86xx SOCs are supported +#endif + +/** + * Global Utility Registers. + * + * Not all registers defined in this structure are available on all chips, so + * you are expected to know whether a given register actually exists on your + * chip before you access it. + * + * Also, some registers are similar on different chips but have slightly + * different names. In these cases, one name is chosen to avoid extraneous + * #ifdefs. + */ +#ifdef CONFIG_PPC_85xx +struct ccsr_guts_85xx { +#else +struct ccsr_guts_86xx { +#endif __be32 porpllsr; /* 0x.0000 - POR PLL Ratio Status Register */ __be32 porbmsr; /* 0x.0004 - POR Boot Mode Status Register */ __be32 porimpscr; /* 0x.0008 - POR I/O Impedance Status and Control Register */ __be32 pordevsr; /* 0x.000c - POR I/O Device Status Register */ __be32 pordbgmsr; /* 0x.0010 - POR Debug Mode Status Register */ - u8 res1[0x20 - 0x14]; + __be32 pordevsr2; /* 0x.0014 - POR device status register 2 */ + u8 res018[0x20 - 0x18]; __be32 porcir; /* 0x.0020 - POR Configuration Information Register */ - u8 res2[0x30 - 0x24]; + u8 res024[0x30 - 0x24]; __be32 gpiocr; /* 0x.0030 - GPIO Control Register */ - u8 res3[0x40 - 0x34]; + u8 res034[0x40 - 0x34]; __be32 gpoutdr; /* 0x.0040 - General-Purpose Output Data Register */ - u8 res4[0x50 - 0x44]; + u8 res044[0x50 - 0x44]; __be32 gpindr; /* 0x.0050 - General-Purpose Input Data Register */ - u8 res5[0x60 - 0x54]; + u8 res054[0x60 - 0x54]; __be32 pmuxcr; /* 0x.0060 - Alternate Function Signal Multiplex Control */ - u8 res6[0x70 - 0x64]; + __be32 pmuxcr2; /* 0x.0064 - Alternate function signal multiplex control 2 */ + __be32 dmuxcr; /* 0x.0068 - DMA Mux Control Register */ + u8 res06c[0x70 - 0x6c]; __be32 devdisr; /* 0x.0070 - Device Disable Control */ __be32 devdisr2; /* 0x.0074 - Device Disable Control 2 */ - u8 res7[0x80 - 0x78]; + u8 res078[0x7c - 0x78]; + __be32 pmjcr; /* 0x.007c - 4 Power Management Jog Control Register */ __be32 powmgtcsr; /* 0x.0080 - Power Management Status and Control Register */ - u8 res8[0x90 - 0x84]; + __be32 pmrccr; /* 0x.0084 - Power Management Reset Counter Configuration Register */ + __be32 pmpdccr; /* 0x.0088 - Power Management Power Down Counter Configuration Register */ + __be32 pmcdr; /* 0x.008c - 4Power management clock disable register */ __be32 mcpsumr; /* 0x.0090 - Machine Check Summary Register */ __be32 rstrscr; /* 0x.0094 - Reset Request Status and Control Register */ - u8 res9[0xA0 - 0x98]; + __be32 ectrstcr; /* 0x.0098 - Exception reset control register */ + __be32 autorstsr; /* 0x.009c - Automatic reset status register */ __be32 pvr; /* 0x.00a0 - Processor Version Register */ __be32 svr; /* 0x.00a4 - System Version Register */ - u8 res10[0xB0 - 0xA8]; + u8 res0a8[0xb0 - 0xa8]; __be32 rstcr; /* 0x.00b0 - Reset Control Register */ - u8 res11[0xC0 - 0xB4]; + u8 res0b4[0xc0 - 0xb4]; +#ifdef CONFIG_PPC_85xx + __be32 iovselsr; /* 0x.00c0 - I/O voltage select status register */ +#else __be32 elbcvselcr; /* 0x.00c0 - eLBC Voltage Select Ctrl Reg */ - u8 res12[0x800 - 0xC4]; +#endif + u8 res0c4[0x224 - 0xc4]; + __be32 iodelay1; /* 0x.0224 - IO delay control register 1 */ + __be32 iodelay2; /* 0x.0228 - IO delay control register 2 */ + u8 res22c[0x800 - 0x22c]; __be32 clkdvdr; /* 0x.0800 - Clock Divide Register */ - u8 res13[0x900 - 0x804]; + u8 res804[0x900 - 0x804]; __be32 ircr; /* 0x.0900 - Infrared Control Register */ - u8 res14[0x908 - 0x904]; + u8 res904[0x908 - 0x904]; __be32 dmacr; /* 0x.0908 - DMA Control Register */ - u8 res15[0x914 - 0x90C]; + u8 res90c[0x914 - 0x90c]; __be32 elbccr; /* 0x.0914 - eLBC Control Register */ - u8 res16[0xB20 - 0x918]; + u8 res918[0xb20 - 0x918]; __be32 ddr1clkdr; /* 0x.0b20 - DDR1 Clock Disable Register */ __be32 ddr2clkdr; /* 0x.0b24 - DDR2 Clock Disable Register */ __be32 ddrclkdr; /* 0x.0b28 - DDR Clock Disable Register */ - u8 res17[0xE00 - 0xB2C]; + u8 resb2c[0xe00 - 0xb2c]; __be32 clkocr; /* 0x.0e00 - Clock Out Select Register */ - u8 res18[0xE10 - 0xE04]; + u8 rese04[0xe10 - 0xe04]; __be32 ddrdllcr; /* 0x.0e10 - DDR DLL Control Register */ - u8 res19[0xE20 - 0xE14]; + u8 rese14[0xe20 - 0xe14]; __be32 lbcdllcr; /* 0x.0e20 - LBC DLL Control Register */ - u8 res20[0xF04 - 0xE24]; + __be32 cpfor; /* 0x.0e24 - L2 charge pump fuse override register */ + u8 rese28[0xf04 - 0xe28]; __be32 srds1cr0; /* 0x.0f04 - SerDes1 Control Register 0 */ __be32 srds1cr1; /* 0x.0f08 - SerDes1 Control Register 0 */ - u8 res21[0xF40 - 0xF0C]; - __be32 srds2cr0; /* 0x.0f40 - SerDes1 Control Register 0 */ - __be32 srds2cr1; /* 0x.0f44 - SerDes1 Control Register 0 */ + u8 resf0c[0xf2c - 0xf0c]; + __be32 itcr; /* 0x.0f2c - Internal transaction control register */ + u8 resf30[0xf40 - 0xf30]; + __be32 srds2cr0; /* 0x.0f40 - SerDes2 Control Register 0 */ + __be32 srds2cr1; /* 0x.0f44 - SerDes2 Control Register 0 */ } __attribute__ ((packed)); +#ifdef CONFIG_PPC_86xx + #define CCSR_GUTS_DMACR_DEV_SSI 0 /* DMA controller/channel set to SSI */ #define CCSR_GUTS_DMACR_DEV_IR 1 /* DMA controller/channel set to IR */ @@ -93,7 +132,7 @@ struct ccsr_guts { * ch: The channel on the DMA controller (0, 1, 2, or 3) * device: The device to set as the source (CCSR_GUTS_DMACR_DEV_xx) */ -static inline void guts_set_dmacr(struct ccsr_guts __iomem *guts, +static inline void guts_set_dmacr(struct ccsr_guts_86xx __iomem *guts, unsigned int co, unsigned int ch, unsigned int device) { unsigned int shift = 16 + (8 * (1 - co) + 2 * (3 - ch)); @@ -129,7 +168,7 @@ static inline void guts_set_dmacr(struct ccsr_guts __iomem *guts, * ch: The channel on the DMA controller (0, 1, 2, or 3) * value: the new value for the bit (0 or 1) */ -static inline void guts_set_pmuxcr_dma(struct ccsr_guts __iomem *guts, +static inline void guts_set_pmuxcr_dma(struct ccsr_guts_86xx __iomem *guts, unsigned int co, unsigned int ch, unsigned int value) { if ((ch == 0) || (ch == 3)) { @@ -152,5 +191,7 @@ static inline void guts_set_pmuxcr_dma(struct ccsr_guts __iomem *guts, #define CCSR_GUTS_CLKDVDR_SSICLK_MASK 0x000000FF #define CCSR_GUTS_CLKDVDR_SSICLK(x) ((x) & CCSR_GUTS_CLKDVDR_SSICLK_MASK) -#endif /* __ASM_POWERPC_IMMAP_86XX_H__ */ -#endif /* __KERNEL__ */ +#endif + +#endif +#endif diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c index 34e00902ce8..e15afdf1234 100644 --- a/arch/powerpc/platforms/85xx/p1022_ds.c +++ b/arch/powerpc/platforms/85xx/p1022_ds.c @@ -8,7 +8,6 @@ * Copyright 2010 Freescale Semiconductor, Inc. * * This file is taken from the Freescale P1022DS BSP, with modifications: - * 1) No DIU support (pending rewrite of DIU code) * 2) No AMP support * 3) No PCI endpoint support * @@ -20,12 +19,211 @@ #include <linux/pci.h> #include <linux/of_platform.h> #include <linux/memblock.h> - +#include <asm/div64.h> #include <asm/mpic.h> #include <asm/swiotlb.h> #include <sysdev/fsl_soc.h> #include <sysdev/fsl_pci.h> +#include <asm/fsl_guts.h> + +#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE) + +/* + * Board-specific initialization of the DIU. This code should probably be + * executed when the DIU is opened, rather than in arch code, but the DIU + * driver does not have a mechanism for this (yet). + * + * This is especially problematic on the P1022DS because the local bus (eLBC) + * and the DIU video signals share the same pins, which means that enabling the + * DIU will disable access to NOR flash. + */ + +/* DIU Pixel Clock bits of the CLKDVDR Global Utilities register */ +#define CLKDVDR_PXCKEN 0x80000000 +#define CLKDVDR_PXCKINV 0x10000000 +#define CLKDVDR_PXCKDLY 0x06000000 +#define CLKDVDR_PXCLK_MASK 0x00FF0000 + +/* Some ngPIXIS register definitions */ +#define PX_BRDCFG1_DVIEN 0x80 +#define PX_BRDCFG1_DFPEN 0x40 +#define PX_BRDCFG1_BACKLIGHT 0x20 +#define PX_BRDCFG1_DDCEN 0x10 + +/* + * 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_MASK 0x0E000000 +#define AD_ALPHA_C_SHIFT 25 +#define AD_BLUE_C_MASK 0x01800000 +#define AD_BLUE_C_SHIFT 23 +#define AD_GREEN_C_MASK 0x00600000 +#define AD_GREEN_C_SHIFT 21 +#define AD_RED_C_MASK 0x00180000 +#define AD_RED_C_SHIFT 19 +#define AD_PALETTE 0x00040000 +#define AD_PIXEL_S_MASK 0x00030000 +#define AD_PIXEL_S_SHIFT 16 +#define AD_COMP_3_MASK 0x0000F000 +#define AD_COMP_3_SHIFT 12 +#define AD_COMP_2_MASK 0x00000F00 +#define AD_COMP_2_SHIFT 8 +#define AD_COMP_1_MASK 0x000000F0 +#define AD_COMP_1_SHIFT 4 +#define AD_COMP_0_MASK 0x0000000F +#define AD_COMP_0_SHIFT 0 + +#define MAKE_AD(alpha, red, blue, green, size, c0, c1, c2, c3) \ + cpu_to_le32(AD_BYTE_F | (alpha << AD_ALPHA_C_SHIFT) | \ + (blue << AD_BLUE_C_SHIFT) | (green << AD_GREEN_C_SHIFT) | \ + (red << AD_RED_C_SHIFT) | (c3 << AD_COMP_3_SHIFT) | \ + (c2 << AD_COMP_2_SHIFT) | (c1 << AD_COMP_1_SHIFT) | \ + (c0 << AD_COMP_0_SHIFT) | (size << AD_PIXEL_S_SHIFT)) + +/** + * p1022ds_get_pixel_format: return the Area Descriptor for a given pixel depth + * + * The Area Descriptor is a 32-bit value that determine which bits in each + * pixel are to be used for each color. + */ +static unsigned int p1022ds_get_pixel_format(unsigned int bits_per_pixel, + int monitor_port) +{ + switch (bits_per_pixel) { + case 32: + /* 0x88883316 */ + return MAKE_AD(3, 2, 0, 1, 3, 8, 8, 8, 8); + case 24: + /* 0x88082219 */ + return MAKE_AD(4, 0, 1, 2, 2, 0, 8, 8, 8); + case 16: + /* 0x65053118 */ + return MAKE_AD(4, 2, 1, 0, 1, 5, 6, 5, 0); + default: + pr_err("fsl-diu: unsupported pixel depth %u\n", bits_per_pixel); + return 0; + } +} + +/** + * p1022ds_set_gamma_table: update the gamma table, if necessary + * + * On some boards, the gamma table for some ports may need to be modified. + * This is not the case on the P1022DS, so we do nothing. +*/ +static void p1022ds_set_gamma_table(int monitor_port, char *gamma_table_base) +{ +} + +/** + * p1022ds_set_monitor_port: switch the output to a different monitor port + * + */ +static void p1022ds_set_monitor_port(int monitor_port) +{ + struct device_node *pixis_node; + u8 __iomem *brdcfg1; + + pixis_node = of_find_compatible_node(NULL, NULL, "fsl,p1022ds-pixis"); + if (!pixis_node) { + pr_err("p1022ds: missing ngPIXIS node\n"); + return; + } + + brdcfg1 = of_iomap(pixis_node, 0); + if (!brdcfg1) { + pr_err("p1022ds: could not map ngPIXIS registers\n"); + return; + } + brdcfg1 += 9; /* BRDCFG1 is at offset 9 in the ngPIXIS */ + + switch (monitor_port) { + case 0: /* DVI */ + /* Enable the DVI port, disable the DFP and the backlight */ + clrsetbits_8(brdcfg1, PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT, + PX_BRDCFG1_DVIEN); + break; + case 1: /* Single link LVDS */ + /* Enable the DFP port, disable the DVI and the backlight */ + clrsetbits_8(brdcfg1, PX_BRDCFG1_DVIEN | PX_BRDCFG1_BACKLIGHT, + PX_BRDCFG1_DFPEN); + break; + default: + pr_err("p1022ds: unsupported monitor port %i\n", monitor_port); + } +} + +/** + * p1022ds_set_pixel_clock: program the DIU's clock + * + * @pixclock: the wavelength, in picoseconds, of the clock + */ +void p1022ds_set_pixel_clock(unsigned int pixclock) +{ + struct device_node *guts_np = NULL; + struct ccsr_guts_85xx __iomem *guts; + unsigned long freq; + u64 temp; + u32 pxclk; + + /* Map the global utilities registers. */ + guts_np = of_find_compatible_node(NULL, NULL, "fsl,p1022-guts"); + if (!guts_np) { + pr_err("p1022ds: missing global utilties device node\n"); + return; + } + + guts = of_iomap(guts_np, 0); + of_node_put(guts_np); + if (!guts) { + pr_err("p1022ds: could not map global utilties device\n"); + return; + } + + /* Convert pixclock from a wavelength to a frequency */ + temp = 1000000000000ULL; + do_div(temp, pixclock); + freq = temp; + + /* pixclk is the ratio of the platform clock to the pixel clock */ + pxclk = DIV_ROUND_CLOSEST(fsl_get_sys_freq(), freq); + + /* Disable the pixel clock, and set it to non-inverted and no delay */ + clrbits32(&guts->clkdvdr, + CLKDVDR_PXCKEN | CLKDVDR_PXCKDLY | CLKDVDR_PXCLK_MASK); + + /* Enable the clock and set the pxclk */ + setbits32(&guts->clkdvdr, CLKDVDR_PXCKEN | (pxclk << 16)); +} + +/** + * p1022ds_show_monitor_port: show the current monitor + * + * This function returns a string indicating whether the current monitor is + * set to DVI or LVDS. + */ +ssize_t p1022ds_show_monitor_port(int monitor_port, char *buf) +{ + return sprintf(buf, "%c0 - DVI\n%c1 - Single link LVDS\n", + monitor_port == 0 ? '*' : ' ', monitor_port == 1 ? '*' : ' '); +} + +/** + * p1022ds_set_sysfs_monitor_port: set the monitor port for sysfs + */ +int p1022ds_set_sysfs_monitor_port(int val) +{ + return val < 2 ? val : 0; +} + +#endif void __init p1022_ds_pic_init(void) { @@ -92,6 +290,15 @@ static void __init p1022_ds_setup_arch(void) } #endif +#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE) + diu_ops.get_pixel_format = p1022ds_get_pixel_format; + diu_ops.set_gamma_table = p1022ds_set_gamma_table; + diu_ops.set_monitor_port = p1022ds_set_monitor_port; + diu_ops.set_pixel_clock = p1022ds_set_pixel_clock; + diu_ops.show_monitor_port = p1022ds_show_monitor_port; + diu_ops.set_sysfs_monitor_port = p1022ds_set_sysfs_monitor_port; +#endif + #ifdef CONFIG_SMP mpc85xx_smp_init(); #endif |