LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] Driver for Freescale 8610 and 5121 DIU
From: York Sun @ 2008-03-12 21:43 UTC (permalink / raw)
  To: linux-kernel; +Cc: linuxppc-dev, York Sun
In-Reply-To: <12053582234100-git-send-email-yorksun@freescale.com>

The following features are supported:
plane 0 works as a regular frame buffer, can be accessed by /dev/fb0
plane 1 has two AOIs (area of interest), can be accessed by /dev/fb1 and /dev/fb2
plane 2 has two AOIs, can be accessed by /dev/fb3 and /dev/fb4
Special ioctls support AOIs

All /dev/fb* can be used as regular frame buffer devices, except hardware change can
only be made through /dev/fb0. Changing pixel clock has no effect on other fbs.

Limitation of usage of AOIs:
AOIs on the same plane can not be horizonally overlapped
AOIs have horizonal order, i.e. AOI0 should be always on top of AOI1
AOIs can not beyond phisical display area. Application should check AOI geometry
before changing physical resolution on /dev/fb0

required command line parameters to preallocate memory for frame buffer
diufb=15M

optional command line parameters to set modes and monitor
video=fslfb:[resolution][,bpp][,monitor]
Syntax:

Resolution
xres x yres-bpp@refresh_rate, the -bpp and @refresh_rate are optional
eg, 1024x768, 1280x1024, 1280x1024-32, 1280x1024@60, 1280x1024-32@60, 1280x480-32@60

Bpp
bpp=32, bpp=24, or bpp=16

Monitor
monitor=0, monitor=1, monitor=2
0 is DVI
1 is Single link LVDS
2 is Double link LVDS

Note: switching monitor is a board feather, not DIU feather. MPC8610HPCD has three
monitor ports to swtich to. MPC5121ADS doesn't have additional monitor port. So switching
monirot port for MPC5121ADS has no effect.

Signed-off-by: York Sun <yorksun@freescale.com>
---

This patch is targeting 2.6.26, adding new feature.

 Documentation/powerpc/booting-without-of.txt |   34 +
 arch/powerpc/boot/dts/mpc8610_hpcd.dts       |   13 +
 drivers/video/Kconfig                        |   10 +
 drivers/video/Makefile                       |    1 +
 drivers/video/fsl-diu-fb.c                   | 1634 ++++++++++++++++++++++++++
 drivers/video/fsl-diu-fb.h                   |  388 ++++++
 6 files changed, 2080 insertions(+), 0 deletions(-)
 create mode 100644 drivers/video/fsl-diu-fb.c
 create mode 100644 drivers/video/fsl-diu-fb.h

diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index 7b4e8a7..f7ae14a 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -2816,6 +2816,40 @@ platforms are moved over to use the flattened-device-tree model.
 		   big-endian;
 	   };
 
+    r) Freescale Display Interface Unit
+
+    The Freescale DIU is a LCD controller, with proper hardware, it can also
+    drive DVI monitors.
+
+    Required properties:
+    - compatible : should be "fsl-diu".
+    - reg : should contain at least address and length of the DIU register
+      set.
+    - Interrupts : one DIU interrupt should be describe here.
+
+    Example (MPC8610HPCD)
+	diu@2c000 {
+		device_type = "lcd";
+		compatible = "fsl-diu";
+		reg = <0x2c000 100>;
+		interrupts = <72 2>;
+		interrupt-parent = <&mpic>;
+	};
+
+    s) Freescale on board FPGA
+
+    This is the memory-mapped registers for on board FPGA.
+
+    Required properities:
+    - compatible : should be "fsl,fpga-pixis".
+    - reg : should contain the address and the lenght of the FPPGA register
+      set.
+
+    Example (MPC8610HPCD)
+	fpga {
+		compatible = "fsl,fpga-pixis";
+		reg = <0xe8000000 20>;
+	};
 
    More devices will be defined as this spec matures.
 
diff --git a/arch/powerpc/boot/dts/mpc8610_hpcd.dts b/arch/powerpc/boot/dts/mpc8610_hpcd.dts
index 16c947b..78c67ee 100644
--- a/arch/powerpc/boot/dts/mpc8610_hpcd.dts
+++ b/arch/powerpc/boot/dts/mpc8610_hpcd.dts
@@ -45,6 +45,11 @@
 		reg = <0x00000000 0x20000000>;	// 512M at 0x0
 	};
 
+	fpga {
+		compatible = "fsl,fpga-pixis";
+		reg = <0xe8000000 20>;		// pixis at 0xe8000000
+	};
+
 	soc@e0000000 {
 		#address-cells = <1>;
 		#size-cells = <1>;
@@ -104,6 +109,14 @@
 			interrupt-parent = <&mpic>;
 		};
 
+		diu@2c000 {
+			device_type = "lcd";
+			compatible = "fsl-diu";
+			reg = <0x2c000 100>;
+			interrupts = <72 2>;
+			interrupt-parent = <&mpic>;
+		};
+
 		mpic: interrupt-controller@40000 {
 			clock-frequency = <0>;
 			interrupt-controller;
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 758435f..8923327 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -1766,6 +1766,16 @@ config FB_MBX_DEBUG
 
          If unsure, say N.
 
+config FB_FSL_DIU
+	tristate "Freescale MPC8610/MPC5121 DIU framebuffer support"
+	depends on FB && (MPC8610 || MPC5121)
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select PPC_LIB_RHEAP
+	---help---
+	  Framebuffer driver for the MPC8610/MPC5121 chip from Freescale
+
 config FB_W100
 	tristate "W100 frame buffer support"
 	depends on FB && PXA_SHARPSL
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 83e02b3..fb09b5e 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -113,6 +113,7 @@ obj-$(CONFIG_FB_PS3)		  += ps3fb.o
 obj-$(CONFIG_FB_SM501)            += sm501fb.o
 obj-$(CONFIG_FB_XILINX)           += xilinxfb.o
 obj-$(CONFIG_FB_OMAP)             += omap/
+obj-$(CONFIG_FB_FSL_DIU)	  += fsl-diu-fb.o
 
 # Platform or fallback drivers go here
 obj-$(CONFIG_FB_UVESA)            += uvesafb.o
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
new file mode 100644
index 0000000..4dd1990
--- /dev/null
+++ b/drivers/video/fsl-diu-fb.c
@@ -0,0 +1,1634 @@
+/*
+ * Copyright 2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ *  Freescale DIU Frame Buffer device driver
+ *
+ *  Authors: Hongjun Chen <hong-jun.chen@freescale.com>
+ *           Paul Widmer <paul.widmer@freescale.com>
+ *           Srikanth Srinivasan <srikanth.srinivasan@freescale.com>
+ *           York Sun <yorksun@freescale.com>
+ *  Copyright (C) Freescale Semicondutor, Inc. 2007. All rights reserved.
+ *
+ *   Based on imxfb.c Copyright (C) 2004 S.Hauer, Pengutronix
+ *
+ * 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 <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <asm/uaccess.h>
+
+#include <asm/of_platform.h>
+
+#include <sysdev/fsl_soc.h>
+#undef DEBUG
+#include "fsl-diu-fb.h"
+
+static int irq;
+static char *fb_mode = "1024x768-32@60";
+static int fb_enabled;
+static unsigned long default_bpp = 32;
+static ATOMIC_NOTIFIER_HEAD(fsl_diu_notifier_list);
+static int monitor_port;
+static struct diu_ad *dummy_ad;
+void *dummy_aoi_virt;
+
+#if defined(CONFIG_NOT_COHERENT_CACHE)
+unsigned int *coherence_data;
+unsigned long *coherence_data_phy;
+#endif
+
+static DEFINE_SPINLOCK(diu_lock);
+
+struct mfb_info {
+	int index;
+	int type;
+	char *id;
+	int registered;
+	int blank;
+	unsigned long pseudo_palette[16];
+	struct diu_ad *ad;
+	int cursor_reset;
+	unsigned char g_alpha;
+	unsigned int count;
+	int x_aoi_d;		/* aoi display x offset to physical screen */
+	int y_aoi_d;		/* aoi display y offset to physical screen */
+};
+
+
+struct mfb_info mfbi_p0 = {
+	.index = 0,
+	.type = MFB_TYPE_OUTPUT,
+	.id = "Panel0",
+	.registered = 0,
+	.count = 0,
+	.x_aoi_d = 0,
+	.y_aoi_d = 0,
+};
+
+struct mfb_info mfbi_p1_0 = {
+	.index = 1,
+	.type = MFB_TYPE_OUTPUT,
+	.id = "Panel1 AOI0",
+	.registered = 0,
+	.g_alpha = 0xff,
+	.count = 0,
+	.x_aoi_d = 0,
+	.y_aoi_d = 0,
+};
+
+struct mfb_info mfbi_p1_1 = {
+	.index = 2,
+	.type = MFB_TYPE_OUTPUT,
+	.id = "Panel1 AOI1",
+	.registered = 0,
+	.g_alpha = 0xff,
+	.count = 0,
+	.x_aoi_d = 0,
+	.y_aoi_d = 480,
+};
+
+struct mfb_info mfbi_p2_0 = {
+	.index = 3,
+	.type = MFB_TYPE_OUTPUT,
+	.id = "Panel2 AOI0",
+	.registered = 0,
+	.g_alpha = 0xff,
+	.count = 0,
+	.x_aoi_d = 640,
+	.y_aoi_d = 0,
+};
+
+struct mfb_info mfbi_p2_1 = {
+	.index = 4,
+	.type = MFB_TYPE_OUTPUT,
+	.id = "Panel2 AOI1",
+	.registered = 0,
+	.g_alpha = 0xff,
+	.count = 0,
+	.x_aoi_d = 640,
+	.y_aoi_d = 480,
+};
+
+static struct diu_hw dr = {
+	.mode = MFB_MODE1,
+	.reg_lock = __SPIN_LOCK_UNLOCKED(old_style_spin_init),
+};
+
+struct diu_pool pool;
+
+static struct fb_info fsl_diu_info[] = {
+	{.par = &mfbi_p0},
+	{.par = &mfbi_p1_0},
+	{.par = &mfbi_p1_1},
+	{.par = &mfbi_p2_0},
+	{.par = &mfbi_p2_1},
+};
+
+static void write_reg(u32 *reg, u32 value)
+{
+	unsigned long flag;
+
+	spin_lock_irqsave(&dr.reg_lock, flag);
+	*reg = value;
+	spin_unlock_irqrestore(&dr.reg_lock, flag);
+}
+
+static u32 read_reg(u32 *reg)
+{
+	u32 value;
+	unsigned long flag;
+
+	spin_lock_irqsave(&dr.reg_lock, flag);
+	value = *reg;
+	spin_unlock_irqrestore(&dr.reg_lock, flag);
+	return value;
+}
+
+static int fsl_diu_enable_panel(struct fb_info *info)
+{
+	struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par;
+	struct diu *hw = dr.diu_reg;
+	struct diu_ad *ad = mfbi->ad;
+	int res = 0;
+
+	DPRINTK("Entered: enable_panel index %d\n", mfbi->index);
+	if (mfbi->type != MFB_TYPE_OFF) {
+		switch (mfbi->index) {
+		case 0:				/* plane 0 */
+			if (hw->desc[0] != ad->paddr)
+				write_reg(&(hw->desc[0]), ad->paddr);
+			break;
+		case 1:				/* plane 1 AOI 0 */
+			cmfbi = fsl_diu_info[2].par;
+			if (hw->desc[1] != ad->paddr) {	/* AOI0 closed */
+				if (cmfbi->count > 0)	/* AOI1 open */
+					ad->next_ad =
+						cpu_to_le32(cmfbi->ad->paddr);
+				else
+					ad->next_ad = 0;
+				write_reg(&(hw->desc[1]), ad->paddr);
+			}
+			break;
+		case 3:				/* plane 2 AOI 0 */
+			cmfbi = fsl_diu_info[4].par;
+			if (hw->desc[2] != ad->paddr) {	/* AOI0 closed */
+				if (cmfbi->count > 0)	/* AOI1 open */
+					ad->next_ad =
+						cpu_to_le32(cmfbi->ad->paddr);
+				else
+					ad->next_ad = 0;
+				write_reg(&(hw->desc[2]), ad->paddr);
+			}
+			break;
+		case 2:				/* plane 1 AOI 1 */
+			pmfbi = fsl_diu_info[1].par;
+			ad->next_ad = 0;
+			if (hw->desc[1] == dummy_ad->paddr) /* AOI0 closed */
+				write_reg(&(hw->desc[1]), ad->paddr);
+			else					/* AOI0 open */
+				pmfbi->ad->next_ad = cpu_to_le32(ad->paddr);
+			break;
+		case 4:				/* plane 2 AOI 1 */
+			pmfbi = fsl_diu_info[3].par;
+			ad->next_ad = 0;
+			if (hw->desc[2] == dummy_ad->paddr) /* AOI0 closed */
+				write_reg(&(hw->desc[2]), ad->paddr);
+			else				/* AOI0 was open */
+				pmfbi->ad->next_ad = cpu_to_le32(ad->paddr);
+			break;
+		default:
+			res = -EINVAL;
+			break;
+		}
+	} else
+		res = -EINVAL;
+	return res;
+}
+
+static int fsl_diu_disable_panel(struct fb_info *info)
+{
+	struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par;
+	struct diu *hw = dr.diu_reg;
+	struct diu_ad *ad = mfbi->ad;
+	int res = 0;
+
+	DPRINTK("Entered: disable_panel\n");
+	switch (mfbi->index) {
+	case 0:					/* plane 0 */
+		if (hw->desc[0] != dummy_ad->paddr)
+			write_reg(&(hw->desc[0]), dummy_ad->paddr);
+		break;
+	case 1:					/* plane 1 AOI 0 */
+		cmfbi = fsl_diu_info[2].par;
+		if (cmfbi->count > 0)	/* AOI1 is open */
+			write_reg(&(hw->desc[1]), cmfbi->ad->paddr);
+					/* move AOI1 to the first */
+		else			/* AOI1 was closed */
+			write_reg(&(hw->desc[1]), dummy_ad->paddr);
+					/* close AOI 0 */
+		break;
+	case 3:					/* plane 2 AOI 0 */
+		cmfbi = fsl_diu_info[4].par;
+		if (cmfbi->count > 0)	/* AOI1 is open */
+			write_reg(&(hw->desc[2]), cmfbi->ad->paddr);
+					/* move AOI1 to the first */
+		else			/* AOI1 was closed */
+			write_reg(&(hw->desc[2]), dummy_ad->paddr);
+					/* close AOI 0 */
+		break;
+	case 2:					/* plane 1 AOI 1 */
+		pmfbi = fsl_diu_info[1].par;
+		if (hw->desc[1] != ad->paddr) {
+					/* AOI1 is not the first in the chain */
+			if (pmfbi->count > 0)
+					/* AOI0 is open, must be the first */
+				pmfbi->ad->next_ad = 0;
+		} else			/* AOI1 is the first in the chain */
+			write_reg(&(hw->desc[1]), dummy_ad->paddr);
+					/* close AOI 1 */
+		break;
+	case 4:					/* plane 2 AOI 1 */
+		pmfbi = fsl_diu_info[3].par;
+		if (hw->desc[2] != ad->paddr) {
+				/* AOI1 is not the first in the chain */
+			if (pmfbi->count > 0)
+				/* AOI0 is open, must be the first */
+				pmfbi->ad->next_ad = 0;
+		} else		/* AOI1 is the first in the chain */
+			write_reg(&(hw->desc[2]), dummy_ad->paddr);
+				/* close AOI 1 */
+		break;
+	default:
+		res = -EINVAL;
+		break;
+	}
+
+	return res;
+}
+
+static void enable_lcdc(struct fb_info *info)
+{
+	struct diu *hw = dr.diu_reg;
+
+	DPRINTK("Entered: enable_lcdc\n");
+	if (!fb_enabled) {
+		write_reg(&(hw->diu_mode), dr.mode);
+		fb_enabled++;
+	}
+}
+
+static void disable_lcdc(struct fb_info *info)
+{
+	struct diu *hw = dr.diu_reg;
+
+	DPRINTK("Entered: disable_lcdc\n");
+	if (fb_enabled) {
+		write_reg(&(hw->diu_mode), 0);
+		fb_enabled = 0;
+	}
+}
+
+/*
+ * Checks to see if the hardware supports the state requested by var passed
+ * in. This function does not alter the hardware state! If the var passed in
+ * is slightly off by what the hardware can support then we alter the var
+ * PASSED in to what we can do. If the hardware doesn't support mode change
+ * a -EINVAL will be returned by the upper layers.
+ */
+static int fsl_diu_check_var
+	(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	unsigned long htotal, vtotal;
+	struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par;
+	int index = mfbi->index;
+
+	DPRINTK("Entered: fsl_diu_check_var\n");
+	DPRINTK("check_var xres: %d\n", var->xres);
+	DPRINTK("check_var yres: %d\n", var->yres);
+
+	if (var->xres_virtual < var->xres)
+		var->xres_virtual = var->xres;
+	if (var->yres_virtual < var->yres)
+		var->yres_virtual = var->yres;
+
+	if (var->xoffset < 0)
+		var->xoffset = 0;
+
+	if (var->yoffset < 0)
+		var->yoffset = 0;
+
+	if (var->xoffset + info->var.xres > info->var.xres_virtual)
+		var->xoffset = info->var.xres_virtual - info->var.xres;
+
+	if (var->yoffset + info->var.yres > info->var.yres_virtual)
+		var->yoffset = info->var.yres_virtual - info->var.yres;
+
+	if ((var->bits_per_pixel != 32) && (var->bits_per_pixel != 24) &&
+	    (var->bits_per_pixel != 16))
+		var->bits_per_pixel = default_bpp;
+
+	switch (var->bits_per_pixel) {
+	case 16:
+		var->red.length = 5;
+		var->red.offset = 11;
+		var->red.msb_right = 0;
+
+		var->green.length = 6;
+		var->green.offset = 5;
+		var->green.msb_right = 0;
+
+		var->blue.length = 5;
+		var->blue.offset = 0;
+		var->blue.msb_right = 0;
+
+		var->transp.length = 0;
+		var->transp.offset = 0;
+		var->transp.msb_right = 0;
+		break;
+	case 24:
+		var->red.length = 8;
+		var->red.offset = 0;
+		var->red.msb_right = 0;
+
+		var->green.length = 8;
+		var->green.offset = 8;
+		var->green.msb_right = 0;
+
+		var->blue.length = 8;
+		var->blue.offset = 16;
+		var->blue.msb_right = 0;
+
+		var->transp.length = 0;
+		var->transp.offset = 0;
+		var->transp.msb_right = 0;
+		break;
+	case 32:
+		var->red.length = 8;
+		var->red.offset = 16;
+		var->red.msb_right = 0;
+
+		var->green.length = 8;
+		var->green.offset = 8;
+		var->green.msb_right = 0;
+
+		var->blue.length = 8;
+		var->blue.offset = 0;
+		var->blue.msb_right = 0;
+
+		var->transp.length = 8;
+		var->transp.offset = 24;
+		var->transp.msb_right = 0;
+
+		break;
+	}
+	/* If the pixclock is below the minimum spec'd value then set to
+	 * refresh rate for 60Hz since this is supported by most monitors.
+	 * Refer to Documentation/fb/ for calculations.
+	 */
+	if ((var->pixclock < MIN_PIX_CLK) || (var->pixclock > MAX_PIX_CLK)) {
+		htotal = var->xres + var->right_margin + var->hsync_len +
+		    var->left_margin;
+		vtotal = var->yres + var->lower_margin + var->vsync_len +
+		    var->upper_margin;
+		var->pixclock = (vtotal * htotal * 6UL) / 100UL;
+		var->pixclock = KHZ2PICOS(var->pixclock);
+		DPRINTK("pixclock set for 60Hz refresh = %u ps\n",
+			var->pixclock);
+	}
+
+	var->height = -1;
+	var->width = -1;
+	var->grayscale = 0;
+
+	/* Copy nonstd field to/from sync for fbset usage */
+	var->sync |= var->nonstd;
+	var->nonstd |= var->sync;
+
+	/* check AOI position */
+	switch (index) {
+	case 0:
+		if (mfbi->x_aoi_d != 0)
+			mfbi->x_aoi_d = 0;
+		if (mfbi->y_aoi_d != 0)
+			mfbi->y_aoi_d = 0;
+		break;
+	case 1:			/* AOI 0 */
+	case 3:
+		cmfbi = fsl_diu_info[index+1].par;
+		if ((mfbi->x_aoi_d + var->xres) > fsl_diu_info[0].var.xres)
+			mfbi->x_aoi_d = fsl_diu_info[0].var.xres - var->xres;
+		if (mfbi->x_aoi_d < 0)
+			mfbi->x_aoi_d = 0;
+		if ((var->xres + mfbi->x_aoi_d) > fsl_diu_info[0].var.xres)
+			var->xres = fsl_diu_info[0].var.xres - mfbi->x_aoi_d;
+
+		if (cmfbi->count > 0) {		/* AOI1 is open */
+			if ((mfbi->y_aoi_d + var->yres) > cmfbi->y_aoi_d)
+				mfbi->y_aoi_d = cmfbi->y_aoi_d - var->yres;
+			if (mfbi->y_aoi_d < 0)
+				mfbi->y_aoi_d = 0;
+			if ((var->yres + mfbi->y_aoi_d) > cmfbi->y_aoi_d)
+				var->yres = cmfbi->y_aoi_d - mfbi->y_aoi_d;
+		} else {				/* AOI1 is close */
+			if ((mfbi->y_aoi_d + var->yres) >
+						fsl_diu_info[0].var.yres)
+				mfbi->y_aoi_d =
+					fsl_diu_info[0].var.yres - var->yres;
+			if (mfbi->y_aoi_d < 0)
+				mfbi->y_aoi_d = 0;
+			if ((var->yres + mfbi->y_aoi_d) >
+					fsl_diu_info[0].var.yres)
+				var->yres =
+				fsl_diu_info[0].var.yres - mfbi->y_aoi_d;
+		}
+		break;
+	case 2:			/* AOI 1 */
+	case 4:
+		pmfbi = fsl_diu_info[index-1].par;
+		if ((mfbi->x_aoi_d + var->xres) > fsl_diu_info[0].var.xres)
+			mfbi->x_aoi_d = fsl_diu_info[0].var.xres - var->xres;
+		if (mfbi->x_aoi_d < 0)
+			mfbi->x_aoi_d = 0;
+		if ((var->xres + mfbi->x_aoi_d) > fsl_diu_info[0].var.xres)
+			var->xres = fsl_diu_info[0].var.xres - mfbi->x_aoi_d;
+
+		if (pmfbi->count > 0) {		/* AOI0 is open */
+			if ((mfbi->y_aoi_d + var->yres) >
+						fsl_diu_info[0].var.yres)
+				mfbi->y_aoi_d =
+					fsl_diu_info[0].var.yres - var->yres;
+			if (mfbi->y_aoi_d <
+				(pmfbi->y_aoi_d+fsl_diu_info[index-1].var.yres))
+				mfbi->y_aoi_d =
+				pmfbi->y_aoi_d+fsl_diu_info[index-1].var.yres;
+			if ((var->yres + mfbi->y_aoi_d) >
+						fsl_diu_info[0].var.yres)
+				var->yres =  fsl_diu_info[0].var.yres
+						- mfbi->y_aoi_d;
+		} else {				/* AOI0 is close */
+			if ((mfbi->y_aoi_d + var->yres) >
+					fsl_diu_info[0].var.yres)
+				mfbi->y_aoi_d =
+					fsl_diu_info[0].var.yres - var->yres;
+			if (mfbi->y_aoi_d < 0)
+				mfbi->y_aoi_d = 0;
+			if ((var->yres + mfbi->y_aoi_d) >
+					fsl_diu_info[0].var.yres)
+				var->yres =
+				fsl_diu_info[0].var.yres - mfbi->y_aoi_d;
+		}
+		break;
+	}
+	return 0;
+}
+
+static void hide_cursor(struct fb_info *info)
+{
+	struct diu *pdiu = dr.diu_reg;
+	pdiu->cursor = 0;
+}
+
+static void show_cursor(struct fb_info *info)
+{
+	struct diu *pdiu = dr.diu_reg;
+	pdiu->cursor = pool.cursor.paddr + pool.cursor.offset;
+}
+
+/*
+ * Copies a cursor image from user space to the proper place in driver
+ * memory so that the hardware can display the cursor image *
+ */
+static void load_cursor_image(struct fb_info *info, u8 *data8,
+				     u16 bg, u16 fg, u32 w, u32 h)
+{
+	u16 *dst = (u16 *)(pool.cursor.vaddr + pool.cursor.offset);
+	int i, j;
+	u32 b;
+	u16 tmp;
+	u32 *data = (u32 *)data8;
+
+	w = (w + 1) & ~1;
+
+	for (i = 0; i < 32; i++) {
+		for (j = 0; j < 32; j++) {
+			b = *data++;
+			tmp = (b & (1 << 31)) ? b : bg;
+			*dst = cpu_to_be16(tmp);
+			dst++;
+		}
+	}
+}
+
+/*
+ * A cursor function that supports displaying a cursor image via hardware.
+ * Within the kernel, copy and invert rops are supported.  If exported
+ * to user space, only the copy rop will be supported.
+ */
+static int fsl_diu_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+	struct mfb_info *mfbi = info->par;
+	struct diu *pdiu = dr.diu_reg;
+	u8 data[MAX_CURS * MAX_CURS/8];
+	int i, set = cursor->set;
+	u16 fg, bg;
+
+	if (cursor->image.width > MAX_CURS || cursor->image.height > MAX_CURS)
+		return -EINVAL;
+
+	hide_cursor(info);
+
+	if (mfbi->cursor_reset) {
+		set = FB_CUR_SETALL;
+		mfbi->cursor_reset = 0;
+	}
+
+	if (set & FB_CUR_SETSIZE)
+		memset_io(pool.cursor.vaddr + pool.cursor.offset,
+				0, MAX_CURS * MAX_CURS * 2);
+
+	if (set & FB_CUR_SETPOS) {
+		u32 xx, yy, temp;
+
+		yy = cursor->image.dy - info->var.yoffset;
+		xx = cursor->image.dx - info->var.xoffset;
+		temp = xx & 0xFFFF;
+		temp |= yy << 16;
+
+		write_reg(&(pdiu->curs_pos), temp);
+	}
+
+	if (set & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP | FB_CUR_SETIMAGE)) {
+		u32 bg_idx = cursor->image.bg_color;
+		u32 fg_idx = cursor->image.fg_color;
+		u32 s_pitch = (cursor->image.width+7) >> 3;
+		u32 d_pitch = MAX_CURS/8;
+		u8 *dat = (u8 *) cursor->image.data;
+		u8 *msk = (u8 *) cursor->mask;
+		u8 *src;
+
+		src = kmalloc(s_pitch * cursor->image.height, GFP_ATOMIC);
+
+		switch (cursor->rop) {
+		case ROP_XOR:
+			for (i = 0; i < s_pitch * cursor->image.height; i++)
+				src[i] = dat[i] ^ msk[i];
+			break;
+		case ROP_COPY:
+		default:
+			for (i = 0; i < s_pitch * cursor->image.height; i++)
+				src[i] = dat[i] & msk[i];
+			break;
+		}
+
+		fb_pad_aligned_buffer(data, d_pitch, src, s_pitch,
+						cursor->image.height);
+		bg = ((info->cmap.red[bg_idx] & 0xe0) << 10) |
+			((info->cmap.green[bg_idx] & 0xe0) << 5) |
+			((info->cmap.blue[bg_idx] & 0xe0) >> 5) |
+			1 << 15;
+
+		fg = ((info->cmap.red[fg_idx] & 0xe0) << 10) |
+			((info->cmap.green[fg_idx] & 0xe0) << 5) |
+			((info->cmap.blue[fg_idx] & 0xe0) >> 5) |
+			1 << 15;
+
+		load_cursor_image(info, data, bg, fg,
+					 cursor->image.width,
+					 cursor->image.height);
+		kfree(src);
+	}
+
+	if (cursor->enable)
+		show_cursor(info);
+
+	return 0;
+}
+
+static void set_fix(struct fb_info *info)
+{
+	struct fb_fix_screeninfo *fix = &info->fix;
+	struct fb_var_screeninfo *var = &info->var;
+	struct mfb_info *mfbi = info->par;
+
+	DPRINTK("Entered: set_fix\n");
+	strncpy(fix->id, mfbi->id, strlen(mfbi->id));
+	fix->line_length = var->xres_virtual * var->bits_per_pixel / 8;
+	fix->type = FB_TYPE_PACKED_PIXELS;
+	fix->accel = FB_ACCEL_NONE;
+	fix->visual = FB_VISUAL_TRUECOLOR;
+	fix->xpanstep = 1;
+	fix->ypanstep = 1;
+}
+
+static void update_lcdc(struct fb_info *info)
+{
+	struct fb_var_screeninfo *var = &info->var;
+	struct mfb_info *mfbi = info->par;
+	struct diu *hw;
+	int i, j;
+	char __iomem *cursor_base, *gamma_table_base;
+
+	u32 temp;
+
+	DPRINTK("Entered: update_lcdc\n");
+
+	spin_lock_init(&dr.reg_lock);
+	hw = dr.diu_reg;
+
+	if (mfbi->type == MFB_TYPE_OFF) {
+		fsl_diu_disable_panel(info);
+		return;
+	}
+
+	platform_set_monitor_port(monitor_port);
+	gamma_table_base = pool.gamma.vaddr;
+	cursor_base = pool.cursor.vaddr;
+	/* Prep for DIU init  - gamma table, cursor table */
+
+	for (i = 0; i <= 2; i++)
+	   for (j = 0; j <= 255; j++)
+	      *gamma_table_base++ = j;
+
+	platform_set_gamma_table(monitor_port, pool.gamma.vaddr);
+
+	DPRINTK("update-lcdc: HW - %p\n Disabling DIU\n", hw);
+	disable_lcdc(info);
+
+	/* Program DIU registers */
+
+	write_reg(&(hw->gamma), pool.gamma.paddr);
+	write_reg(&(hw->cursor), pool.cursor.paddr);
+
+	write_reg(&(hw->bgnd), 0x007F7F7F); 	/* BGND */
+	write_reg(&(hw->bgnd_wb), 0); 		/* BGND_WB */
+	write_reg(&(hw->disp_size), (var->yres << 16 | var->xres));
+						/* DISP SIZE */
+	DPRINTK("DIU xres: %d\n", var->xres);
+	DPRINTK("DIU yres: %d\n", var->yres);
+
+	write_reg(&(hw->wb_size), 0); /* WB SIZE */
+	write_reg(&(hw->wb_mem_addr), 0); /* WB MEM ADDR */
+
+	/* Horizontal and vertical configuration register */
+	temp = var->left_margin << 22 | /* BP_H */
+	       var->hsync_len << 11 |   /* PW_H */
+	       var->right_margin;       /* FP_H */
+
+	write_reg(&(hw->hsyn_para), temp);
+
+	temp = var->upper_margin << 22 | /* BP_V */
+	       var->vsync_len << 11 |    /* PW_V  */
+	       var->lower_margin;        /* FP_V  */
+
+	write_reg(&(hw->vsyn_para), temp);
+
+	DPRINTK("DIU right_margin - %d\n", var->right_margin);
+	DPRINTK("DIU left_margin - %d\n", var->left_margin);
+	DPRINTK("DIU hsync_len - %d\n", var->hsync_len);
+	DPRINTK("DIU upper_margin - %d\n", var->upper_margin);
+	DPRINTK("DIU lower_margin - %d\n", var->lower_margin);
+	DPRINTK("DIU vsync_len - %d\n", var->vsync_len);
+	DPRINTK("DIU HSYNC - 0x%08x\n", hw->hsyn_para);
+	DPRINTK("DIU VSYNC - 0x%08x\n", hw->vsyn_para);
+
+	platform_set_pixel_clock(var->pixclock);
+
+	write_reg(&(hw->syn_pol), 0);	/* SYNC SIGNALS POLARITY */
+	write_reg(&(hw->thresholds), 0x00037800); /* The Thresholds */
+	write_reg(&(hw->int_status), 0);	/* INTERRUPT STATUS */
+	write_reg(&(hw->plut), 0x01F5F666);
+
+	/* Enable the DIU */
+	enable_lcdc(info);
+}
+
+static int map_video_memory(struct fb_info *info)
+{
+	DPRINTK("Entered: map_video_memory\n");
+	DPRINTK("info->var.xres_virtual = %d\n", info->var.xres_virtual);
+	DPRINTK("info->var.yres_virtual = %d\n", info->var.yres_virtual);
+	DPRINTK("info->fix.line_length  = %d\n", info->fix.line_length);
+
+	info->fix.smem_len = info->fix.line_length * info->var.yres_virtual;
+	DPRINTK("MAP_VIDEO_MEMORY: smem_len = %d\n", info->fix.smem_len);
+	info->screen_base = fsl_diu_alloc(info->fix.smem_len,
+					&info->fix.smem_start);
+	if (info->screen_base == 0) {
+		printk(KERN_ERR "Unable to allocate fb memory\n");
+		return -EBUSY;
+	}
+
+	info->screen_size = info->fix.smem_len;
+
+	DPRINTK("Allocated fb @ paddr=0x%08lx, size=%d.\n",
+				info->fix.smem_start,
+		info->fix.smem_len);
+	DPRINTK("screen base 0x%08lx\n", (long unsigned int) info->screen_base);
+
+	return 0;
+}
+
+static void unmap_video_memory(struct fb_info *info)
+{
+	DPRINTK("Entered: unmap_video_memory\n");
+	fsl_diu_free(info->screen_base, info->fix.smem_len);
+	info->screen_base = 0;
+	info->fix.smem_start = 0;
+	info->fix.smem_len = 0;
+}
+
+/*
+ * Using the fb_var_screeninfo in fb_info we set the resolution of this
+ * particular framebuffer. This function alters the fb_fix_screeninfo stored
+ * in fb_info. It does not alter var in fb_info since we are using that
+ * data. This means we depend on the data in var inside fb_info to be
+ * supported by the hardware. fsl_diu_check_var is always called before
+ * fsl_diu_set_par to ensure this.
+ */
+static int fsl_diu_set_par(struct fb_info *info)
+{
+	unsigned long len;
+	struct fb_var_screeninfo *var = &info->var;
+	struct mfb_info *mfbi = info->par;
+	struct diu_ad *ad = mfbi->ad;
+	struct diu *hw;
+
+	DPRINTK("Entered: fsl_diu_set_par\n");
+	hw = dr.diu_reg;
+
+	set_fix(info);
+	mfbi->cursor_reset = 1;
+
+	len = info->var.yres_virtual * info->fix.line_length;
+	/* Alloc & dealloc each time resolution/bpp change */
+	if (len != info->fix.smem_len) {
+		if (info->fix.smem_start)
+			unmap_video_memory(info);
+		DPRINTK("SET PAR: smem_len = %d\n", info->fix.smem_len);
+
+		/* Memory allocation for framebuffer */
+		if (map_video_memory(info)) {
+			printk(KERN_ERR "Unable to allocate fb memory 1\n");
+			return -ENOMEM;
+		}
+	}
+
+	ad->pix_fmt =
+		platform_get_pixel_format(var->bits_per_pixel, monitor_port);
+	ad->addr    = cpu_to_le32(info->fix.smem_start);
+	ad->src_size_g_alpha = cpu_to_le32((var->yres << 12) |
+				var->xres) | mfbi->g_alpha;
+	/* fix me. AOI should not be greater than display size */
+	ad->aoi_size 	= cpu_to_le32((var->yres << 16) | var->xres);
+	ad->offset_xyi = 0;
+	ad->offset_xyd = cpu_to_le32((mfbi->y_aoi_d << 16) | mfbi->x_aoi_d);
+
+	/* Disable chroma keying function */
+	ad->ckmax_r = 0;
+	ad->ckmax_g = 0;
+	ad->ckmax_b = 0;
+
+	ad->ckmin_r = 255;
+	ad->ckmin_g = 255;
+	ad->ckmin_b = 255;
+
+	if (mfbi->index == 0)
+		update_lcdc(info);
+	return 0;
+}
+
+/*
+ * Set a single color register. The values supplied have a 16 bit magnitude
+ * which needs to be scaled in this function for the hardware. Things to take
+ * into consideration are how many color registers, if any, are supported with
+ * the current color visual. With truecolor mode no color palettes are
+ * supported. Here a psuedo palette is created which we store the value in
+ * pseudo_palette in struct fb_info. For pseudocolor mode we have a limited
+ * color palette.
+ */
+static int fsl_diu_setcolreg(unsigned regno, unsigned red, unsigned green,
+			   unsigned blue, unsigned transp, struct fb_info *info)
+{
+	int ret = 1;
+
+	/*
+	 * If greyscale is true, then we convert the RGB value
+	 * to greyscale no matter what visual we are using.
+	 */
+	if (info->var.grayscale)
+		red = green = blue = (19595 * red + 38470 * green +
+				      7471 * blue) >> 16;
+	switch (info->fix.visual) {
+	case FB_VISUAL_TRUECOLOR:
+		/*
+		 * 16-bit True Colour.  We encode the RGB value
+		 * according to the RGB bitfield information.
+		 */
+		if (regno < 16) {
+			u32 *pal = info->pseudo_palette;
+			u32 v;
+
+#define CNVT_TOHW(val, width) ((((val)<<(width))+0x7FFF-(val))>>16)
+			red = CNVT_TOHW(red, info->var.red.length);
+			green = CNVT_TOHW(green, info->var.green.length);
+			blue = CNVT_TOHW(blue, info->var.blue.length);
+			transp = CNVT_TOHW(transp, info->var.transp.length);
+#undef CNVT_TOHW
+			v = (red << info->var.red.offset) |
+			    (green << info->var.green.offset) |
+			    (blue << info->var.blue.offset) |
+			    (transp << info->var.transp.offset);
+
+			pal[regno] = v;
+			ret = 0;
+		}
+		break;
+	case FB_VISUAL_STATIC_PSEUDOCOLOR:
+	case FB_VISUAL_PSEUDOCOLOR:
+		break;
+	}
+
+	return ret;
+}
+
+/*
+ * Pan (or wrap, depending on the `vmode' field) the display using the
+ * 'xoffset' and 'yoffset' fields of the 'var' structure. If the values
+ * don't fit, return -EINVAL.
+ */
+static int fsl_diu_pan_display(struct fb_var_screeninfo *var,
+			     struct fb_info *info)
+{
+	DPRINTK("Entered: fsl_diu_pan_display\n");
+	if ((info->var.xoffset == var->xoffset) &&
+	    (info->var.yoffset == var->yoffset))
+		return 0;	/* No change, do nothing */
+
+	if (var->xoffset < 0 || var->yoffset < 0
+	    || var->xoffset + info->var.xres > info->var.xres_virtual
+	    || var->yoffset + info->var.yres > info->var.yres_virtual)
+		return -EINVAL;
+
+	info->var.xoffset = var->xoffset;
+	info->var.yoffset = var->yoffset;
+
+	if (var->vmode & FB_VMODE_YWRAP)
+		info->var.vmode |= FB_VMODE_YWRAP;
+	else
+		info->var.vmode &= ~FB_VMODE_YWRAP;
+
+	return 0;
+}
+
+/*
+ * Blank the screen if blank_mode != 0, else unblank. Return 0 if blanking
+ * succeeded, != 0 if un-/blanking failed.
+ * blank_mode == 2: suspend vsync
+ * blank_mode == 3: suspend hsync
+ * blank_mode == 4: powerdown
+ */
+static int fsl_diu_blank(int blank_mode, struct fb_info *info)
+{
+	struct mfb_info *mfbi = info->par;
+
+	DPRINTK("Entered: fsl_diu_blank\n");
+	mfbi->blank = blank_mode;
+
+	switch (blank_mode) {
+	case FB_BLANK_VSYNC_SUSPEND:
+	case FB_BLANK_HSYNC_SUSPEND:
+	/* FIXME: fixes to enable_panel and enable lcdc needed */
+	case FB_BLANK_NORMAL:
+	/*	fsl_diu_disable_panel(info);*/
+		break;
+	case FB_BLANK_POWERDOWN:
+	/*	disable_lcdc(info);	*/
+		break;
+	case FB_BLANK_UNBLANK:
+	/*	fsl_diu_enable_panel(info);*/
+		break;
+	}
+
+	return 0;
+}
+
+static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd,
+		       unsigned long arg)
+{
+	struct mfb_info *mfbi = info->par;
+	struct diu_ad *ad = mfbi->ad;
+	struct mfb_chroma_key ck;
+	unsigned char global_alpha;
+	struct aoi_display_offset aoi_d;
+	__u32 pix_fmt;
+
+	DPRINTK("Entered: fsl_diu_ioctl\n");
+	switch (cmd) {
+	case MFB_SET_PIXFMT:
+		if (!arg)
+			return -EINVAL;
+		if (copy_from_user((void *)&pix_fmt, (void *)arg,
+				sizeof(pix_fmt)))
+			return -EFAULT;
+		ad->pix_fmt = pix_fmt;
+		DPRINTK("Set pixel format to 0x%08x\n", ad->pix_fmt);
+		break;
+	case MFB_GET_PIXFMT:
+		if (!arg)
+			return -EINVAL;
+		pix_fmt = ad->pix_fmt;
+		if (copy_to_user((void *)arg, (void *)&pix_fmt,
+				sizeof(pix_fmt)))
+			return -EFAULT;
+		DPRINTK("get pixel format 0x%08x\n", ad->pix_fmt);
+		break;
+	case MFB_SET_AOID:
+		if (!arg)
+			return -EINVAL;
+		if (copy_from_user((void *)&aoi_d, (void *)arg, sizeof(aoi_d)))
+			return -EFAULT;
+		mfbi->x_aoi_d = aoi_d.x_aoi_d;
+		mfbi->y_aoi_d = aoi_d.y_aoi_d;
+		DPRINTK("set AOI display offset of index %d to (%d,%d)\n",
+				 mfbi->index, aoi_d.x_aoi_d, aoi_d.y_aoi_d);
+		fsl_diu_check_var(&info->var, info);
+		fsl_diu_set_par(info);
+		break;
+	case MFB_GET_AOID:
+		if (!arg)
+			return -EINVAL;
+		aoi_d.x_aoi_d = mfbi->x_aoi_d;
+		aoi_d.y_aoi_d = mfbi->y_aoi_d;
+		if (copy_to_user((void *)arg, (void *)&aoi_d, sizeof(aoi_d)))
+			return -EFAULT;
+		DPRINTK("get AOI display offset of index %d (%d,%d)\n",
+				mfbi->index, aoi_d.x_aoi_d, aoi_d.y_aoi_d);
+		break;
+	case MFB_GET_ALPHA:
+		if (!arg)
+			return -EINVAL;
+		global_alpha = mfbi->g_alpha;
+		if (copy_to_user((void *)arg, (void *)&global_alpha,
+						sizeof(global_alpha)))
+			return -EFAULT;
+		DPRINTK("get global alpha of index %d\n", mfbi->index);
+		break;
+	case MFB_SET_ALPHA:
+		if (!arg)
+			return -EINVAL;
+
+		/* set panel information */
+		if (copy_from_user((void *)&global_alpha, (void *)arg,
+			sizeof(global_alpha)))
+			return -EFAULT;
+		ad->src_size_g_alpha = (ad->src_size_g_alpha & (~0xff)) |
+							(global_alpha & 0xff);
+		mfbi->g_alpha = global_alpha;
+		DPRINTK("set global alpha for index %d\n", mfbi->index);
+		break;
+	case MFB_SET_CHROMA_KEY:
+		if (!arg)
+			return -EINVAL;
+
+		/* set panel winformation */
+		if (copy_from_user((void *)&ck, (void *)arg, sizeof(ck)))
+			return -EFAULT;
+
+		if (ck.enable &&
+		   (ck.red_max < ck.red_min ||
+		    ck.green_max < ck.green_min ||
+		    ck.blue_max < ck.blue_min))
+			return -EINVAL;
+
+		if (!ck.enable) {
+			ad->ckmax_r = 0;
+			ad->ckmax_g = 0;
+			ad->ckmax_b = 0;
+			ad->ckmin_r = 255;
+			ad->ckmin_g = 255;
+			ad->ckmin_b = 255;
+		} else {
+			ad->ckmax_r = ck.red_max;
+			ad->ckmax_g = ck.green_max;
+			ad->ckmax_b = ck.blue_max;
+			ad->ckmin_r = ck.red_min;
+			ad->ckmin_g = ck.green_min;
+			ad->ckmin_b = ck.blue_min;
+		}
+		DPRINTK("set chroma key\n");
+		break;
+	case FBIOGET_GWINFO:
+		if (mfbi->type == MFB_TYPE_OFF)
+			return -ENODEV;
+
+		if (!arg)
+			return -EINVAL;
+
+		/* get graphic window information */
+		if (copy_to_user((void *)arg, (void *)ad, sizeof(*ad)))
+			return -EFAULT;
+		break;
+	case FBIOGET_HWCINFO:
+		DPRINTK("FBIOGET_HWCINFO:0x%08x\n", FBIOGET_HWCINFO);
+		break;
+	case FBIOPUT_MODEINFO:
+		DPRINTK("FBIOPUT_MODEINFO:0x%08x\n", FBIOPUT_MODEINFO);
+		break;
+	case FBIOGET_DISPINFO:
+		DPRINTK("FBIOGET_DISPINFO:0x%08x\n", FBIOGET_DISPINFO);
+		break;
+
+	default:
+		printk(KERN_ERR "Unknown ioctl command (0x%08X)\n", cmd);
+		return 0;
+	}
+
+	return 0;
+}
+
+/* turn on fb if count == 1
+ */
+static int fsl_diu_open(struct fb_info *info, int user)
+{
+	struct mfb_info *mfbi = info->par;
+	int res = 0;
+
+	spin_lock(&diu_lock);
+	mfbi->count++;
+	if (mfbi->count == 1) {
+		DPRINTK("open plane index %d\n", mfbi->index);
+		fsl_diu_check_var(&info->var, info);
+		fsl_diu_set_par(info);
+		res = fsl_diu_enable_panel(info);
+		if (res < 0)
+			mfbi->count--;
+	}
+
+	spin_unlock(&diu_lock);
+	return res;
+}
+
+/* turn off fb if count == 0
+ */
+static int fsl_diu_release(struct fb_info *info, int user)
+{
+	struct mfb_info *mfbi = info->par;
+	int res = 0;
+
+	spin_lock(&diu_lock);
+	mfbi->count--;
+	if (mfbi->count == 0) {
+		DPRINTK("release plane index %d\n", mfbi->index);
+		res = fsl_diu_disable_panel(info);
+		if (res < 0)
+			mfbi->count++;
+	}
+	spin_unlock(&diu_lock);
+	return res;
+}
+
+static struct fb_ops fsl_diu_ops = {
+	.owner = THIS_MODULE,
+	.fb_check_var = fsl_diu_check_var,
+	.fb_set_par = fsl_diu_set_par,
+	.fb_setcolreg = fsl_diu_setcolreg,
+	.fb_blank = fsl_diu_blank,
+	.fb_pan_display = fsl_diu_pan_display,
+	.fb_fillrect = cfb_fillrect,
+	.fb_copyarea = cfb_copyarea,
+	.fb_imageblit = cfb_imageblit,
+	.fb_ioctl = fsl_diu_ioctl,
+	.fb_open = fsl_diu_open,
+	.fb_release = fsl_diu_release,
+};
+
+static int init_fbinfo(struct fb_info *info,
+			       struct platform_device *pdev)
+{
+	struct mfb_info *mfbi = info->par;
+
+	DPRINTK("Entered: init_fbinfo\n");
+	info->device = NULL;
+	info->var.activate = FB_ACTIVATE_NOW;
+	info->fbops = &fsl_diu_ops;
+	info->flags = FBINFO_FLAG_DEFAULT;
+	info->pseudo_palette = &mfbi->pseudo_palette;
+
+	/* Allocate colormap */
+	fb_alloc_cmap(&info->cmap, 16, 0);
+	return 0;
+}
+
+static int install_fb(struct fb_info *info,
+			      struct platform_device *pdev)
+{
+	int rc;
+	struct mfb_info *mfbi = info->par;
+	const char *aoi_mode, *init_aoi_mode = "320x240";
+
+	DPRINTK("Entered: install_fb\n");
+	if (init_fbinfo(info, pdev))
+		return -EINVAL;
+
+	if (mfbi->index == 0)	/* plane 0 */
+		aoi_mode = fb_mode;
+	else
+		aoi_mode = init_aoi_mode;
+	DPRINTK("mode used = %s\n", aoi_mode);
+	rc = fb_find_mode(&info->var, info, aoi_mode, fsl_diu_mode_db,
+	     ARRAY_SIZE(fsl_diu_mode_db), &fsl_diu_default_mode, default_bpp);
+
+	switch (rc) {
+	case 1:
+		DPRINTK("using mode specified in @mode\n");
+		break;
+	case 2:
+		DPRINTK("using mode specified in @mode "
+			"with ignored refresh rate\n");
+		break;
+	case 3:
+		DPRINTK("using mode default mode\n");
+		break;
+	case 4:
+		DPRINTK("using mode from list\n");
+		break;
+	default:
+		DPRINTK("rc = %d\n", rc);
+		DPRINTK("failed to find mode\n");
+		return -EBUSY;
+		break;
+	}
+
+	DPRINTK("xres_virtual %d\n", info->var.xres_virtual);
+	DPRINTK("bits_per_pixel %d\n", info->var.bits_per_pixel);
+
+	DPRINTK("info->var.yres_virtual = %d\n", info->var.yres_virtual);
+	DPRINTK("info->fix.line_length = %d\n", info->fix.line_length);
+
+	if (mfbi->type == MFB_TYPE_OFF)
+		mfbi->blank = FB_BLANK_NORMAL;
+	else
+		mfbi->blank = FB_BLANK_UNBLANK;
+
+	if (fsl_diu_check_var(&info->var, info)) {
+		printk(KERN_ERR "fb_check_var failed");
+		fb_dealloc_cmap(&info->cmap);
+		return -EINVAL;
+	}
+
+	if (fsl_diu_set_par(info)) {
+		printk(KERN_ERR "fb_set_par failed");
+		fb_dealloc_cmap(&info->cmap);
+		return -EINVAL;
+	}
+
+	if (register_framebuffer(info) < 0) {
+		printk(KERN_ERR "register_framebuffer failed");
+		unmap_video_memory(info);
+		fb_dealloc_cmap(&info->cmap);
+		return -EINVAL;
+	}
+
+	mfbi->registered = 1;
+	printk(KERN_INFO "fb%d: %s fb device registered successfully.\n",
+		 info->node, info->fix.id);
+
+	return 0;
+}
+
+static void __exit uninstall_fb(struct fb_info *info)
+{
+	struct mfb_info *mfbi = info->par;
+
+	DPRINTK("Entered: uninstall_fb\n");
+	if (!mfbi->registered)
+		return;
+
+	unregister_framebuffer(info);
+	unmap_video_memory(info);
+	if (&info->cmap)
+		fb_dealloc_cmap(&info->cmap);
+
+	mfbi->registered = 0;
+}
+
+static irqreturn_t fsl_diu_isr(int irq, void *dev_id)
+{
+	struct diu *hw = dr.diu_reg;
+	unsigned int status = read_reg(&(hw->int_status));
+
+	if (status) {
+		/* This is the workaround for underrun */
+		if (status & INT_UNDRUN) {
+			out_be32(&(hw->diu_mode), 0);
+			DPRINTK("Err: DIU occurs underrun!\n");
+			udelay(1);
+			out_be32(&(hw->diu_mode), 1);
+		}
+#if defined(CONFIG_NOT_COHERENT_CACHE)
+		else if (status & INT_VSYNC) {
+			int i;
+			unsigned int *ptr;
+			ptr  = coherence_data;
+			for (i = 0; i < 1024*8; i++)
+				*ptr++ = 0;
+		}
+#endif
+		return IRQ_HANDLED;
+	}
+	return IRQ_NONE;
+}
+
+static void request_irq_local(void)
+{
+	unsigned long status, flags, ints;
+	struct diu *hw;
+	struct device_node *np;
+
+	DPRINTK("Entered: request_irq_local\n");
+	hw = dr.diu_reg;
+
+	/* Read to clear the status */
+	status = read_reg(&(hw->int_status));
+
+	np = of_find_compatible_node(NULL, NULL, "fsl-diu");
+	if (!np) {
+		printk(KERN_ERR "Err: can't find device node 'fsl-diu'\n");
+		return;
+	}
+
+	irq = irq_of_parse_and_map(np, 0);
+	of_node_put(np);
+	if (request_irq(irq, fsl_diu_isr, 0, "LCDC", 0))
+		pr_info("Request LCDC IRQ failed.\n");
+	else {
+		spin_lock_irqsave(&fsl_diu_notifier_list.lock, flags);
+		ints = INT_PARERR | INT_LS_BF_VS;
+#if !defined(CONFIG_NOT_COHERENT_CACHE)
+		ints |=	INT_VSYNC;
+#endif
+		if (dr.mode == MFB_MODE2 || dr.mode == MFB_MODE3)
+			ints |= INT_VSYNC_WB;
+
+		/* Read to clear the status */
+		status = read_reg(&(hw->int_status));
+		write_reg(&(hw->int_mask), ints);
+		spin_unlock_irqrestore(&fsl_diu_notifier_list.lock, flags);
+	}
+}
+
+static void free_irq_local(void)
+{
+	struct diu *hw = dr.diu_reg;
+
+	DPRINTK("Entered: free_irq_local\n");
+	/* Disable all LCDC interrupt */
+	write_reg(&(hw->int_mask), 0x1f);
+
+	free_irq(irq, 0);
+}
+
+int fsl_diu_register_client(struct notifier_block *nb)
+{
+	unsigned long flags;
+	int ret;
+	struct diu *hw = dr.diu_reg;
+	DPRINTK("Entered: fsl_diu_register_client\n");
+
+	ret = atomic_notifier_chain_register(&fsl_diu_notifier_list, nb);
+
+	spin_lock_irqsave(&fsl_diu_notifier_list.lock, flags);
+
+	/* Enable interrupt in case client has registered */
+	if (fsl_diu_notifier_list.head != NULL) {
+		unsigned long status;
+		unsigned long ints = INT_PARERR | INT_LS_BF_VS;
+
+#if !defined(CONFIG_NOT_COHERENT_CACHE)
+			ints |= INT_VSYNC;
+#endif
+
+		if (dr.mode == MFB_MODE2 || dr.mode == MFB_MODE3)
+			ints |= INT_VSYNC_WB;
+
+		/* Read to clear the status */
+		status = read_reg(&(hw->int_status));
+		write_reg(&(hw->int_mask), ints);
+	}
+
+	spin_unlock_irqrestore(&fsl_diu_notifier_list.lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL(fsl_diu_register_client);
+
+int fsl_diu_unregister_client(struct notifier_block *nb)
+{
+	unsigned long flags;
+	int ret;
+	struct diu *hw = dr.diu_reg;
+
+	DPRINTK("Entered: fsl_diu_unregister_client\n");
+	ret = atomic_notifier_chain_unregister(&fsl_diu_notifier_list, nb);
+
+	spin_lock_irqsave(&fsl_diu_notifier_list.lock, flags);
+
+	/* Mask interrupt in case no client registered */
+	if (fsl_diu_notifier_list.head == NULL)
+		write_reg(&(hw->int_mask), 0x1f);
+
+	spin_unlock_irqrestore(&fsl_diu_notifier_list.lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL(fsl_diu_unregister_client);
+
+#ifdef CONFIG_PM
+/*
+ * Power management hooks. Note that we won't be called from IRQ context,
+ * unlike the blank functions above, so we may sleep.
+ */
+static int fsl_diu_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	DPRINTK("Entered: fsl_diu_suspend\n");
+	disable_lcdc(&fsl_diu_info[0]);
+
+	return 0;
+}
+
+static int fsl_diu_resume(struct platform_device *pdev)
+{
+	DPRINTK("Entered: fsl_diu_resume\n");
+	enable_lcdc(&fsl_diu_info[0]);
+
+	return 0;
+}
+#endif				/* CONFIG_PM */
+
+/* Align to 64-bit(8-byte), 32-byte, etc. */
+static int allocate_buf(struct diu_addr *buf, u32 size, u32 bytes_align)
+{
+	u32 offset, ssize;
+	u32 mask;
+
+	DPRINTK("Entered: allocate_buf\n");
+	ssize = size + bytes_align;
+	buf->vaddr = dma_alloc_coherent(0, ssize,
+					(dma_addr_t *) &(buf->paddr),
+					GFP_DMA | GFP_KERNEL);
+	if (!buf->vaddr)
+		return -ENOMEM;
+
+	memset(buf->vaddr, 0, ssize);
+
+	mask = bytes_align - 1;
+	offset = (u32)buf->paddr & mask;
+	if (offset) {
+		buf->offset = bytes_align - offset;
+		buf->paddr = (u32)buf->paddr + offset;
+	} else
+		buf->offset = 0;
+	return 0;
+}
+
+static void free_buf(struct diu_addr *buf, u32 size, u32 bytes_align)
+{
+	DPRINTK("Entered: free_buf\n");
+	dma_free_coherent(0, size + bytes_align,
+				buf->vaddr, (buf->paddr - buf->offset));
+	return;
+}
+
+static ssize_t store_monitor(struct device *device,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	char **last = NULL;
+	int val, old_monitor_port;
+
+	val = simple_strtoul(buf, last, 0);
+
+	old_monitor_port = monitor_port;
+
+	monitor_port = platform_set_sysfs_monitor_port(val);
+
+	if (old_monitor_port != monitor_port) {
+				/* All AOIs need adjust pixel format */
+		fsl_diu_set_par(&fsl_diu_info[0]);
+		fsl_diu_set_par(&fsl_diu_info[1]);
+		fsl_diu_set_par(&fsl_diu_info[2]);
+		fsl_diu_set_par(&fsl_diu_info[3]);
+		fsl_diu_set_par(&fsl_diu_info[4]);
+	}
+	return count;
+}
+
+static ssize_t show_monitor(struct device *device,
+	struct device_attribute *attr, char *buf)
+{
+	return platform_show_monitor_port(monitor_port, buf);
+}
+
+static struct device_attribute device_attrs[] = {
+	__ATTR(monitor, S_IRUGO|S_IWUSR, show_monitor, store_monitor),
+};
+
+static int fsl_diu_probe(struct platform_device *pdev)
+{
+	struct mfb_info *mfbi;
+	unsigned long dummy_ad_addr;
+	int ret, i, error = 0;
+
+	DPRINTK("Entered: fsl_diu_probe\n");
+
+	/* Area descriptor memory pool aligns to 64-bit boundary */
+	allocate_buf(&pool.ad, sizeof(struct diu_ad) * FSL_AOI_NUM, 8);
+
+	/* Get memory for Gamma Table  - 32-byte aligned memory */
+	allocate_buf(&pool.gamma, 768, 32);
+
+	/* For performance, cursor bitmap buffer aligns to 32-byte boundary */
+	allocate_buf(&pool.cursor, MAX_CURS * MAX_CURS * 2, 32);
+
+	i = sizeof(fsl_diu_info) / sizeof(struct fb_info);
+	dummy_ad = (struct diu_ad *)((u32)pool.ad.vaddr + pool.ad.offset) + i;
+	dummy_ad->paddr = pool.ad.paddr + i * sizeof(struct diu_ad);
+	dummy_aoi_virt = fsl_diu_alloc(64, &dummy_ad_addr);
+	dummy_ad->addr = cpu_to_le32(dummy_ad_addr);
+	dummy_ad->pix_fmt = 0x88882317;
+	dummy_ad->src_size_g_alpha = cpu_to_le32((4 << 12) | 4);
+	dummy_ad->aoi_size = cpu_to_le32((4 << 16) |  2);
+	dummy_ad->offset_xyi = 0;
+	dummy_ad->offset_xyd = 0;
+	dummy_ad->next_ad = 0;
+	memset(dummy_aoi_virt, 0x00, 64);
+	write_reg(&(dr.diu_reg->desc[0]), dummy_ad->paddr);
+	write_reg(&(dr.diu_reg->desc[1]), dummy_ad->paddr);
+	write_reg(&(dr.diu_reg->desc[2]), dummy_ad->paddr);
+
+	for (i = 0; i < sizeof(fsl_diu_info) / sizeof(struct fb_info); i++) {
+		fsl_diu_info[i].fix.smem_start = 0;
+		mfbi = fsl_diu_info[i].par;
+		mfbi->ad = (struct diu_ad *)((u32)pool.ad.vaddr
+					+ pool.ad.offset) + i;
+		mfbi->ad->paddr = pool.ad.paddr + i * sizeof(struct diu_ad);
+		ret = install_fb(&fsl_diu_info[i], pdev);
+		if (ret) {
+			printk(KERN_ERR "Failed to register framebuffer %d\n",
+					i);
+			return ret;
+		}
+	}
+	for (i = 0; i < ARRAY_SIZE(device_attrs); i++) {
+		error = device_create_file(fsl_diu_info[0].dev,
+						&device_attrs[i]);
+
+		if (error)
+			break;
+	}
+
+	if (error) {
+		while (--i >= 0)
+			device_remove_file(fsl_diu_info[0].dev,
+						&device_attrs[i]);
+	}
+
+#if defined(CONFIG_NOT_COHERENT_CACHE)
+	coherence_data = fsl_diu_alloc(32*1024, &coherence_data_phy);
+#endif
+
+	request_irq_local();
+	return 0;
+}
+
+static struct platform_driver fsl_diu_driver = {
+	.driver = {
+		   .name = "fsl_diu",
+		   .owner = THIS_MODULE,
+		   },
+	.probe = fsl_diu_probe,
+#ifdef CONFIG_PM
+	.suspend = fsl_diu_suspend,
+	.resume = fsl_diu_resume,
+#endif
+};
+
+#ifndef MODULE
+static int __init fsl_diu_setup(char *options)
+{
+	char *opt;
+	int val;
+
+	DPRINTK("Entered: fsl_diu_setup\n");
+	if (!options || !*options)
+		return 0;
+
+	while ((opt = strsep(&options, ",")) != NULL) {
+		if (!*opt)
+			continue;
+		if (!strncmp(opt, "monitor=", 8)) {
+			val = simple_strtoul(opt + 8, NULL, 0);
+			if ((val == 0) || (val == 1) || (val == 2))
+				monitor_port = val;
+		} else if (!strncmp(opt, "bpp=", 4))
+			default_bpp = simple_strtoul(opt + 4, NULL, 0);
+		else
+			fb_mode = opt;
+	}
+
+	return 0;
+}
+#endif
+
+static struct platform_device fsl_diu_device = {
+	.name   = "fsl_diu",
+};
+
+int __init fsl_diu_init(void)
+{
+	struct device_node *np;
+	struct resource r;
+	int error;
+	DPRINTK("Entered: fsl_diu_init\n");
+	np = of_find_compatible_node(NULL, NULL, "fsl-diu");
+	if (!np) {
+		printk(KERN_ERR "Err: can't find device node 'fsl-diu'\n");
+		return -ENODEV;
+	}
+
+	of_address_to_resource(np, 0, &r);
+	of_node_put(np);
+
+	DPRINTK("%s, r.start: 0x%08x\n", __func__, r.start);
+
+	dr.diu_reg = ioremap(r.start, sizeof(struct diu));
+
+	write_reg(&(dr.diu_reg->diu_mode), 0);		/* disable DIU anyway*/
+
+	spin_lock_init(&dr.reg_lock);
+
+
+	/*
+	 * For kernel boot options (in 'video=xxxfb:<options>' format)
+	 */
+#ifndef MODULE
+	{
+		char *option;
+
+		if (fb_get_options("fslfb", &option))
+			return -ENODEV;
+		fsl_diu_setup(option);
+	}
+#endif
+	error = platform_driver_register(&fsl_diu_driver);
+
+	if (!error) {
+		error = platform_device_register(&fsl_diu_device);
+		if (error) {
+			printk(KERN_ERR "Err: "
+					"can't register FB device driver!\n");
+			platform_driver_unregister(&fsl_diu_driver);
+		}
+		printk(KERN_INFO "FSL_DIU_FB: registed FB device driver!\n");
+	}
+
+	return error;
+}
+
+void __exit fsl_diu_exit(void)
+{
+	int i;
+
+	DPRINTK("Entered: fsl_diu_exit\n");
+	free_irq_local();
+	for (i = sizeof(fsl_diu_info) / sizeof(struct fb_info); i > 0; i--)
+		uninstall_fb(&fsl_diu_info[i - 1]);
+
+	platform_driver_unregister(&fsl_diu_driver);
+	iounmap(dr.diu_reg);
+
+	free_buf(&pool.ad, sizeof(struct diu_ad) * FSL_AOI_NUM, 8);
+	free_buf(&pool.cursor, MAX_CURS * MAX_CURS * 2, 32);
+	fsl_diu_free(dummy_aoi_virt, 64);
+	return;
+}
+
+module_init(fsl_diu_init);
+module_exit(fsl_diu_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("FSL DIU framebuffer driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fsl-diu-fb.h b/drivers/video/fsl-diu-fb.h
new file mode 100644
index 0000000..294d0bf
--- /dev/null
+++ b/drivers/video/fsl-diu-fb.h
@@ -0,0 +1,388 @@
+/*
+ * Copyright 2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ *  Freescale DIU Frame Buffer device driver
+ *
+ *  Authors: Hongjun Chen <hong-jun.chen@freescale.com>
+ *           Paul Widmer <paul.widmer@freescale.com>
+ *           Srikanth Srinivasan <srikanth.srinivasan@freescale.com>
+ *           York Sun <yorksun@freescale.com>
+ *  Copyright (C) Freescale Semicondutor, Inc. 2007. All rights reserved.
+ *
+ *   Based on imxfb.c Copyright (C) 2004 S.Hauer, Pengutronix
+ *
+ * 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.
+ *
+ */
+
+#ifndef __FSL_DIU_FB_H__
+#define __FSL_DIU_FB_H__
+
+/* FIXME: This should be changed to dev_dbg this will be done as soon as
+ * we can obtain dev through the dts setup
+ */
+#ifdef DEBUG
+#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__, ## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+
+
+/* Arbitrary threshold to determine the allocation method
+ * See mpc8610fb_set_par(), map_video_memory(), and unmap_video_memory()
+ */
+#define MEM_ALLOC_THRESHOLD (1024*768*4+32)
+/* Minimum value that the pixel clock can be set to in pico seconds
+ * This is determined by platform clock/3 where the minimum platform
+ * clock is 533MHz. This gives 5629 pico seconds.
+ */
+#define MIN_PIX_CLK 5629
+#define MAX_PIX_CLK 96096
+
+#include <linux/types.h>
+
+struct mfb_alpha {
+	int enable;
+	int alpha;
+};
+
+struct mfb_chroma_key {
+	int enable;
+	__u8  red_max;
+	__u8  green_max;
+	__u8  blue_max;
+	__u8  red_min;
+	__u8  green_min;
+	__u8  blue_min;
+};
+
+struct aoi_display_offset {
+	int x_aoi_d;
+	int y_aoi_d;
+};
+
+#define MFB_SET_CHROMA_KEY	_IOW('M', 1, struct mfb_chroma_key)
+#define MFB_WAIT_FOR_VSYNC	_IOW('F', 0x20, u_int32_t)
+#define MFB_SET_BRIGHTNESS	_IOW('M', 3, __u8)
+
+#define MFB_SET_ALPHA		0x80014d00
+#define MFB_GET_ALPHA		0x40014d00
+#define MFB_SET_AOID		0x80084d04
+#define MFB_GET_AOID		0x40084d04
+#define MFB_SET_PIXFMT		0x80014d08
+#define MFB_GET_PIXFMT		0x40014d08
+
+#define FBIOGET_GWINFO		0x46E0
+#define FBIOPUT_GWINFO		0x46E1
+
+#ifdef __KERNEL__
+#include <linux/spinlock.h>
+
+/*
+ * These parameters give default parameters
+ * for video output 1024x768,
+ * FIXME - change timing to proper amounts
+ * hsync 31.5kHz, vsync 60Hz
+ */
+static struct fb_videomode __devinitdata fsl_diu_default_mode = {
+	.refresh	= 60,
+	.xres		= 1024,
+	.yres		= 768,
+	.pixclock	= 15385,
+	.left_margin	= 160,
+	.right_margin	= 24,
+	.upper_margin	= 29,
+	.lower_margin	= 3,
+	.hsync_len	= 136,
+	.vsync_len	= 6,
+	.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	.vmode		= FB_VMODE_NONINTERLACED
+};
+
+static struct fb_videomode __devinitdata fsl_diu_mode_db[] = {
+	{
+		.name		= "1024x768-60",
+		.refresh	= 60,
+		.xres		= 1024,
+		.yres		= 768,
+		.pixclock	= 15385,
+		.left_margin	= 160,
+		.right_margin	= 24,
+		.upper_margin	= 29,
+		.lower_margin	= 3,
+		.hsync_len	= 136,
+		.vsync_len	= 6,
+		.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		.vmode		= FB_VMODE_NONINTERLACED
+	},
+	{
+		.name		= "1024x768-70",
+		.refresh	= 70,
+		.xres		= 1024,
+		.yres		= 768,
+		.pixclock	= 16886,
+		.left_margin	= 3,
+		.right_margin	= 3,
+		.upper_margin	= 2,
+		.lower_margin	= 2,
+		.hsync_len	= 40,
+		.vsync_len	= 18,
+		.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		.vmode		= FB_VMODE_NONINTERLACED
+	},
+	{
+		.name		= "1024x768-75",
+		.refresh	= 75,
+		.xres		= 1024,
+		.yres		= 768,
+		.pixclock	= 15009,
+		.left_margin	= 3,
+		.right_margin	= 3,
+		.upper_margin	= 2,
+		.lower_margin	= 2,
+		.hsync_len	= 80,
+		.vsync_len	= 32,
+		.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		.vmode		= FB_VMODE_NONINTERLACED
+	},
+	{
+		.name		= "1280x1024-60",
+		.refresh	= 60,
+		.xres		= 1280,
+		.yres		= 1024,
+		.pixclock	= 9375,
+		.left_margin	= 38,
+		.right_margin	= 128,
+		.upper_margin	= 2,
+		.lower_margin	= 7,
+		.hsync_len	= 216,
+		.vsync_len	= 37,
+		.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		.vmode		= FB_VMODE_NONINTERLACED
+	},
+	{
+		.name		= "1280x1024-70",
+		.refresh	= 70,
+		.xres		= 1280,
+		.yres		= 1024,
+		.pixclock	= 9380,
+		.left_margin	= 6,
+		.right_margin	= 6,
+		.upper_margin	= 4,
+		.lower_margin	= 4,
+		.hsync_len	= 60,
+		.vsync_len	= 94,
+		.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		.vmode		= FB_VMODE_NONINTERLACED
+	},
+	{
+		.name		= "1280x1024-75",
+		.refresh	= 75,
+		.xres		= 1280,
+		.yres		= 1024,
+		.pixclock	= 9380,
+		.left_margin	= 6,
+		.right_margin	= 6,
+		.upper_margin	= 4,
+		.lower_margin	= 4,
+		.hsync_len	= 60,
+		.vsync_len	= 15,
+		.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		.vmode		= FB_VMODE_NONINTERLACED
+	},
+	{
+		.name		= "320x240",		/* for AOI only */
+		.refresh	= 60,
+		.xres		= 320,
+		.yres		= 240,
+		.pixclock	= 15385,
+		.left_margin	= 0,
+		.right_margin	= 0,
+		.upper_margin	= 0,
+		.lower_margin	= 0,
+		.hsync_len	= 0,
+		.vsync_len	= 0,
+		.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		.vmode		= FB_VMODE_NONINTERLACED
+	},
+	{
+		.name		= "1280x480-60",
+		.refresh	= 60,
+		.xres		= 1280,
+		.yres		= 480,
+		.pixclock	= 18939,
+		.left_margin	= 353,
+		.right_margin	= 47,
+		.upper_margin	= 39,
+		.lower_margin	= 4,
+		.hsync_len	= 8,
+		.vsync_len	= 2,
+		.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		.vmode		= FB_VMODE_NONINTERLACED
+	},
+};
+/*
+ * These are the fields of area descriptor(in DDR memory) for every plane
+ */
+struct diu_ad {
+	/* Word 0(32-bit) in DDR memory */
+/* 	__u16 comp; */
+/* 	__u16 pixel_s:2; */
+/* 	__u16 pallete:1; */
+/* 	__u16 red_c:2; */
+/* 	__u16 green_c:2; */
+/* 	__u16 blue_c:2; */
+/* 	__u16 alpha_c:3; */
+/* 	__u16 byte_f:1; */
+/* 	__u16 res0:3; */
+
+	__u32 pix_fmt; /* hard coding pixel format */
+
+	/* Word 1(32-bit) in DDR memory */
+	__u32 addr;
+
+	/* Word 2(32-bit) in DDR memory */
+/* 	__u32 delta_xs:11; */
+/* 	__u32 res1:1; */
+/* 	__u32 delta_ys:11; */
+/* 	__u32 res2:1; */
+/* 	__u32 g_alpha:8; */
+	__u32 src_size_g_alpha;
+
+	/* Word 3(32-bit) in DDR memory */
+/* 	__u32 delta_xi:11; */
+/* 	__u32 res3:5; */
+/* 	__u32 delta_yi:11; */
+/* 	__u32 res4:3; */
+/* 	__u32 flip:2; */
+	__u32 aoi_size;
+
+	/* Word 4(32-bit) in DDR memory */
+	/*__u32 offset_xi:11;
+	__u32 res5:5;
+	__u32 offset_yi:11;
+	__u32 res6:5;
+	*/
+	__u32 offset_xyi;
+
+	/* Word 5(32-bit) in DDR memory */
+	/*__u32 offset_xd:11;
+	__u32 res7:5;
+	__u32 offset_yd:11;
+	__u32 res8:5; */
+	__u32 offset_xyd;
+
+
+	/* Word 6(32-bit) in DDR memory */
+	__u32 ckmax_r:8;
+	__u32 ckmax_g:8;
+	__u32 ckmax_b:8;
+	__u32 res9:8;
+
+	/* Word 7(32-bit) in DDR memory */
+	__u32 ckmin_r:8;
+	__u32 ckmin_g:8;
+	__u32 ckmin_b:8;
+	__u32 res10:8;
+/* 	__u32 res10:8; */
+
+	/* Word 8(32-bit) in DDR memory */
+	__u32 next_ad;
+
+	/* Word 9(32-bit) in DDR memory, just for 64-bit aligned */
+	__u32 paddr;
+} __attribute__ ((packed));
+
+/* DIU register map */
+struct diu {
+	__be32 desc[3];
+	__be32 gamma;
+	__be32 pallete;
+	__be32 cursor;
+	__be32 curs_pos;
+	__be32 diu_mode;
+	__be32 bgnd;
+	__be32 bgnd_wb;
+	__be32 disp_size;
+	__be32 wb_size;
+	__be32 wb_mem_addr;
+	__be32 hsyn_para;
+	__be32 vsyn_para;
+	__be32 syn_pol;
+	__be32 thresholds;
+	__be32 int_status;
+	__be32 int_mask;
+	__be32 colorbar[8];
+	__be32 filling;
+	__be32 plut;
+} __attribute__ ((packed));
+
+struct diu_hw {
+	struct diu *diu_reg;
+	spinlock_t reg_lock;
+
+	__u32 mode;		/* DIU operation mode */
+};
+
+struct diu_addr {
+	__u8 __iomem *vaddr;	/* Virtual address */
+	dma_addr_t paddr;	/* Physical address */
+	__u32 	   offset;
+};
+
+struct diu_pool {
+	struct diu_addr ad;
+	struct diu_addr gamma;
+	struct diu_addr pallete;
+	struct diu_addr cursor;
+};
+
+#define FSL_DIU_BASE_OFFSET	0x2C000	/* Offset of DIU */
+#define INT_LCDC		64	/* DIU interrupt number */
+
+#define FSL_AOI_NUM	6	/* 5 AOIs and one dummy AOI */
+				/* 1 for plane 0, 2 for plane 1&2 each */
+
+/* Minimum X and Y resolutions */
+#define MIN_XRES	64
+#define MIN_YRES	64
+
+/* HW cursor parameters */
+#define MAX_CURS		32
+
+/* Modes of operation of DIU */
+#define MFB_MODE0	0	/* DIU off */
+#define MFB_MODE1	1	/* All three planes output to display */
+#define MFB_MODE2	2	/* Plane 1 to display, planes 2+3 written back*/
+#define MFB_MODE3	3	/* All three planes written back to memory */
+#define MFB_MODE4	4	/* Color bar generation */
+
+/* INT_STATUS/INT_MASK field descriptions */
+#define INT_VSYNC	0x01	/* Vsync interrupt  */
+#define INT_VSYNC_WB	0x02	/* Vsync interrupt for write back operation */
+#define INT_UNDRUN	0x04	/* Under run exception interrupt */
+#define INT_PARERR	0x08	/* Display parameters error interrupt */
+#define INT_LS_BF_VS	0x10	/* Lines before vsync. interrupt */
+
+/* Panels'operation modes */
+#define MFB_TYPE_OUTPUT	0	/* Panel output to display */
+#define MFB_TYPE_OFF	1	/* Panel off */
+#define MFB_TYPE_WB	2	/* Panel written back to memory */
+#define MFB_TYPE_TEST	3	/* Panel generate color bar */
+
+void *fsl_diu_alloc(unsigned long size, unsigned long *phys);
+void fsl_diu_free(void *p, unsigned long size);
+unsigned int platform_get_pixel_format(unsigned int bits_per_pixel,
+						int monitor_port);
+void platform_set_gamma_table(int monitor_port, char *gamma_table_base);
+void platform_set_pixel_clock(unsigned int pixclock);
+ssize_t platform_show_monitor_port(int monitor_port, char *buf);
+int platform_set_monitor_port(int val);
+int platform_set_sysfs_monitor_port(int val);
+
+#endif /* __KERNEL__ */
+#endif /* __FSL_DIU_FB_H__ */
-- 
1.5.2.2

^ permalink raw reply related

* Re: [PATCH 1/2] Driver for Freescale 8610 and 5121 DIU
From: Jiri Slaby @ 2008-03-12 22:20 UTC (permalink / raw)
  To: York Sun; +Cc: linuxppc-dev, linux-kernel
In-Reply-To: <12053582231281-git-send-email-yorksun@freescale.com>

On 03/12/2008 10:43 PM, York Sun wrote:
> +static int fsl_diu_open(struct fb_info *info, int user)
> +{
> +	struct mfb_info *mfbi = info->par;
> +	int res = 0;
> +
> +	spin_lock(&diu_lock);
> +	mfbi->count++;
> +	if (mfbi->count == 1) {
> +		DPRINTK("open plane index %d\n", mfbi->index);
> +		fsl_diu_check_var(&info->var, info);
> +		fsl_diu_set_par(info);

Please retest your code (at least) with sleep-inside spinlock debug option. If I 
see correctly you call GFP_KERNEL allocation somewhere deeper in this function, 
which might sleep.

> +		res = fsl_diu_enable_panel(info);
> +		if (res < 0)
> +			mfbi->count--;
> +	}
> +
> +	spin_unlock(&diu_lock);
> +	return res;
> +}

> +static void __exit uninstall_fb(struct fb_info *info)
> +{
> +	struct mfb_info *mfbi = info->par;
> +
> +	DPRINTK("Entered: uninstall_fb\n");

You don't need this stuff everywhere (kprobes).

> +	if (!mfbi->registered)
> +		return;
> +
> +	unregister_framebuffer(info);
> +	unmap_video_memory(info);
> +	if (&info->cmap)
> +		fb_dealloc_cmap(&info->cmap);
> +
> +	mfbi->registered = 0;
> +}
[...]
> +static int fsl_diu_probe(struct platform_device *pdev)
> +{
> +	struct mfb_info *mfbi;
> +	unsigned long dummy_ad_addr;
> +	int ret, i, error = 0;
> +
> +	DPRINTK("Entered: fsl_diu_probe\n");
> +
> +	/* Area descriptor memory pool aligns to 64-bit boundary */
> +	allocate_buf(&pool.ad, sizeof(struct diu_ad) * FSL_AOI_NUM, 8);
> +
> +	/* Get memory for Gamma Table  - 32-byte aligned memory */
> +	allocate_buf(&pool.gamma, 768, 32);
> +
> +	/* For performance, cursor bitmap buffer aligns to 32-byte boundary */
> +	allocate_buf(&pool.cursor, MAX_CURS * MAX_CURS * 2, 32);
> +
> +	i = sizeof(fsl_diu_info) / sizeof(struct fb_info);
> +	dummy_ad = (struct diu_ad *)((u32)pool.ad.vaddr + pool.ad.offset) + i;
> +	dummy_ad->paddr = pool.ad.paddr + i * sizeof(struct diu_ad);
> +	dummy_aoi_virt = fsl_diu_alloc(64, &dummy_ad_addr);
> +	dummy_ad->addr = cpu_to_le32(dummy_ad_addr);
> +	dummy_ad->pix_fmt = 0x88882317;
> +	dummy_ad->src_size_g_alpha = cpu_to_le32((4 << 12) | 4);
> +	dummy_ad->aoi_size = cpu_to_le32((4 << 16) |  2);
> +	dummy_ad->offset_xyi = 0;
> +	dummy_ad->offset_xyd = 0;
> +	dummy_ad->next_ad = 0;
> +	memset(dummy_aoi_virt, 0x00, 64);
> +	write_reg(&(dr.diu_reg->desc[0]), dummy_ad->paddr);
> +	write_reg(&(dr.diu_reg->desc[1]), dummy_ad->paddr);
> +	write_reg(&(dr.diu_reg->desc[2]), dummy_ad->paddr);
> +
> +	for (i = 0; i < sizeof(fsl_diu_info) / sizeof(struct fb_info); i++) {
> +		fsl_diu_info[i].fix.smem_start = 0;
> +		mfbi = fsl_diu_info[i].par;
> +		mfbi->ad = (struct diu_ad *)((u32)pool.ad.vaddr
> +					+ pool.ad.offset) + i;
> +		mfbi->ad->paddr = pool.ad.paddr + i * sizeof(struct diu_ad);
> +		ret = install_fb(&fsl_diu_info[i], pdev);
> +		if (ret) {
> +			printk(KERN_ERR "Failed to register framebuffer %d\n",
> +					i);
> +			return ret;

some kind of free here

> +		}
> +	}
[...]
> +int __init fsl_diu_init(void)
> +{
> +	struct device_node *np;
> +	struct resource r;
> +	int error;
> +	DPRINTK("Entered: fsl_diu_init\n");
> +	np = of_find_compatible_node(NULL, NULL, "fsl-diu");
> +	if (!np) {
> +		printk(KERN_ERR "Err: can't find device node 'fsl-diu'\n");
> +		return -ENODEV;
> +	}
> +
> +	of_address_to_resource(np, 0, &r);
> +	of_node_put(np);
> +
> +	DPRINTK("%s, r.start: 0x%08x\n", __func__, r.start);
> +
> +	dr.diu_reg = ioremap(r.start, sizeof(struct diu));

The arch never fails with remapping?

> +
> +	write_reg(&(dr.diu_reg->diu_mode), 0);		/* disable DIU anyway*/
> +
> +	spin_lock_init(&dr.reg_lock);
> +
> +
> +	/*
> +	 * For kernel boot options (in 'video=xxxfb:<options>' format)
> +	 */
> +#ifndef MODULE
> +	{
> +		char *option;
> +
> +		if (fb_get_options("fslfb", &option))
> +			return -ENODEV;
> +		fsl_diu_setup(option);
> +	}
> +#endif
> +	error = platform_driver_register(&fsl_diu_driver);
> +
> +	if (!error) {
> +		error = platform_device_register(&fsl_diu_device);
> +		if (error) {
> +			printk(KERN_ERR "Err: "
> +					"can't register FB device driver!\n");
> +			platform_driver_unregister(&fsl_diu_driver);

iounmap

> +		}
> +		printk(KERN_INFO "FSL_DIU_FB: registed FB device driver!\n");
> +	}

else iounmap

> +
> +	return error;
> +}
[...]
> diff --git a/drivers/video/fsl-diu-fb.h b/drivers/video/fsl-diu-fb.h
> new file mode 100644
> index 0000000..294d0bf
> --- /dev/null
> +++ b/drivers/video/fsl-diu-fb.h
> @@ -0,0 +1,388 @@
[...]
> +#ifndef __FSL_DIU_FB_H__
> +#define __FSL_DIU_FB_H__
> +
> +/* FIXME: This should be changed to dev_dbg this will be done as soon as
> + * we can obtain dev through the dts setup

then use at least pr_debug() here:

> + */
> +#ifdef DEBUG
> +#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__, ## args)
> +#else
> +#define DPRINTK(fmt, args...)
> +#endif

regards,
-- 
Jiri Slaby
Faculty of Informatics, Masaryk University
Suse Labs

^ permalink raw reply

* Re: [BUG] 2.6.25-rc5-mm1 kernel panic with "Exception: 501 " on powerpc
From: Michael Ellerman @ 2008-03-12 22:26 UTC (permalink / raw)
  To: Matthew Wilcox
  Cc: linuxppc-dev, Andrew Morton, linux-kernel, Kamalesh Babulal
In-Reply-To: <20080312175102.GC613@parisc-linux.org>

[-- Attachment #1: Type: text/plain, Size: 934 bytes --]

On Wed, 2008-03-12 at 11:51 -0600, Matthew Wilcox wrote:
> On Wed, Mar 12, 2008 at 10:46:45AM -0700, Andrew Morton wrote:
> > On Wed, 12 Mar 2008 18:25:37 +0530 Kamalesh Babulal <kamalesh@linux.vnet.ibm.com> wrote:
> > Beats me.  Maybe we're still enabling interrupts too early.  But the new
> > semaphore code got fixed (didn't it?)
> 
> On the 7th, according to my records.  Easy to check -- look in
> kernel/semaphore.c and see whether down() is using spin_lock_irqsave
> (good) or spin_lock_irq (bad).

down() looks OK, but there's still a spin_lock_irq() in __down_common(),
although I don't know if it makes sense for us to be in __down() at that
stage.

cheers

-- 
Michael Ellerman
OzLabs, IBM Australia Development Lab

wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)

We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* Re: PPC upstream kernel ignored DABR bug
From: Jens Osterkamp @ 2008-03-12 22:30 UTC (permalink / raw)
  To: luisgpm
  Cc: linuxppc-dev, Paul Mackerras, Roland McGrath, Arnd Bergmann,
	Jan Kratochvil
In-Reply-To: <1205344272.2272.45.camel@gargoyle>


> Just to make sure, i tested the binary against the 2.6.25-rc4 kernel. It
> still fails. So this is really an open bug for PPC.

On a Cell- or 970-based machine ?

Gruß,
	Jens

IBM Deutschland Entwicklung GmbH
Vorsitzender des Aufsichtsrats: Martin Jetter
Geschäftsführung: Herbert Kircher 
Sitz der Gesellschaft: Böblingen
Registergericht: Amtsgericht Stuttgart, HRB 243294

^ permalink raw reply

* Re: [BUG] 2.6.25-rc5-mm1 kernel panic with "Exception: 501 " on powerpc
From: Matthew Wilcox @ 2008-03-12 22:33 UTC (permalink / raw)
  To: Michael Ellerman
  Cc: linuxppc-dev, Andrew Morton, linux-kernel, Kamalesh Babulal
In-Reply-To: <1205360769.7436.8.camel@concordia.ozlabs.ibm.com>

On Thu, Mar 13, 2008 at 09:26:09AM +1100, Michael Ellerman wrote:
> down() looks OK, but there's still a spin_lock_irq() in __down_common(),
> although I don't know if it makes sense for us to be in __down() at that
> stage.

The spin_lock_irq in __down_common is correct.  We're going to schedule(),
so we spin_unlock_irq() to save us passing the flags into the helper
function.  If we had interrupts disabled on entry, there's an Aieee
for that.

-- 
Intel are signing my paycheques ... these opinions are still mine
"Bill, look, we understand that you're interested in selling us this
operating system, but compare it to ours.  We can't possibly take such
a retrograde step."

^ permalink raw reply

* Re: [PATCH] Always define pmu_sys_suspended
From: Paul Mackerras @ 2008-03-12 22:54 UTC (permalink / raw)
  To: Guido Günther; +Cc: linuxppc-dev
In-Reply-To: <20080227141452.GA10345@bogon.ms20.nix>

Guido G=FCnther writes:

> diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.=
c
> index ebec663..296edcb 100644
> --- a/drivers/macintosh/via-pmu.c
> +++ b/drivers/macintosh/via-pmu.c
> @@ -2437,8 +2437,8 @@ void pmu=5Fblink(int n)
>  }
>  #endif /* DEBUG=5FSLEEP */
> =20
> -#if defined(CONFIG=5FSUSPEND) && defined(CONFIG=5FPPC32)
>  int pmu=5Fsys=5Fsuspended;
> +#if defined(CONFIG=5FSUSPEND) && defined(CONFIG=5FPPC32)

I don't think this is quite right, since pmu.h currently defines
pmu=5Fsys=5Fsuspended to be 0 if CONFIG=5FPM=5FSLEEP is not defined.  T=
hus
with your patch we will get a syntax error in that case.

Paul.

^ permalink raw reply

* [PATCH 1/3] maple: use platform name in define_machine()
From: Nathan Lynch @ 2008-03-12 23:43 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1205365385-28315-1-git-send-email-ntl@pobox.com>

Prevailing practice for define_machine() in powerpc is to use the
platform name when the platform has only one define_machine()
statement, but maple uses "maple_md".  This caused me some
head-scratching when writing some new code that uses
machine_is(maple).

Use "maple" instead of "maple_md".  There should not be any behavioral
change -- fixup_maple_ide() calls machine_is(maple) but the body of
the function is ifdef'd out.

Signed-off-by: Nathan Lynch <ntl@pobox.com>
---
 arch/powerpc/platforms/maple/setup.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c
index 3ce2d73..3b32e07 100644
--- a/arch/powerpc/platforms/maple/setup.c
+++ b/arch/powerpc/platforms/maple/setup.c
@@ -319,7 +319,7 @@ static int __init maple_probe(void)
 	return 1;
 }
 
-define_machine(maple_md) {
+define_machine(maple) {
 	.name			= "Maple",
 	.probe			= maple_probe,
 	.setup_arch		= maple_setup_arch,
-- 
1.5.4.4

^ permalink raw reply related

* maple: minor updates
From: Nathan Lynch @ 2008-03-12 23:43 UTC (permalink / raw)
  To: linuxppc-dev


Please consider the following mostly-trivial patches for 2.6.26.

 arch/powerpc/configs/maple_defconfig |  133 ++++++++++++++++++++++++++++++++--
 arch/powerpc/platforms/maple/pci.c   |   47 ------------
 arch/powerpc/platforms/maple/setup.c |    2 +-
 3 files changed, 129 insertions(+), 53 deletions(-)

^ permalink raw reply

* [PATCH 2/3] maple: kill fixup_maple_ide
From: Nathan Lynch @ 2008-03-12 23:43 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1205365385-28315-1-git-send-email-ntl@pobox.com>

This function has been a no-op for about 18 months; it's there in
the history should anyone need to resurrect it.

Signed-off-by: Nathan Lynch <ntl@pobox.com>
---
 arch/powerpc/platforms/maple/pci.c |   47 ------------------------------------
 1 files changed, 0 insertions(+), 47 deletions(-)

diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c
index 3ffa0ac..3018552 100644
--- a/arch/powerpc/platforms/maple/pci.c
+++ b/arch/powerpc/platforms/maple/pci.c
@@ -592,50 +592,3 @@ int maple_pci_get_legacy_ide_irq(struct pci_dev *pdev, int channel)
 	}
 	return irq;
 }
-
-/* XXX: To remove once all firmwares are ok */
-static void fixup_maple_ide(struct pci_dev* dev)
-{
-	if (!machine_is(maple))
-		return;
-
-#if 0 /* Enable this to enable IDE port 0 */
-	{
-		u8 v;
-
-		pci_read_config_byte(dev, 0x40, &v);
-		v |= 2;
-		pci_write_config_byte(dev, 0x40, v);
-	}
-#endif
-#if 0 /* fix bus master base */
-	pci_write_config_dword(dev, 0x20, 0xcc01);
-	printk("old ide resource: %lx -> %lx \n",
-	       dev->resource[4].start, dev->resource[4].end);
-	dev->resource[4].start = 0xcc00;
-	dev->resource[4].end = 0xcc10;
-#endif
-#if 0 /* Enable this to fixup IDE sense/polarity of irqs in IO-APICs */
-	{
-		struct pci_dev *apicdev;
-		u32 v;
-
-		apicdev = pci_get_slot (dev->bus, PCI_DEVFN(5,0));
-		if (apicdev == NULL)
-			printk("IDE Fixup IRQ: Can't find IO-APIC !\n");
-		else {
-			pci_write_config_byte(apicdev, 0xf2, 0x10 + 2*14);
-			pci_read_config_dword(apicdev, 0xf4, &v);
-			v &= ~0x00000022;
-			pci_write_config_dword(apicdev, 0xf4, v);
-			pci_write_config_byte(apicdev, 0xf2, 0x10 + 2*15);
-			pci_read_config_dword(apicdev, 0xf4, &v);
-			v &= ~0x00000022;
-			pci_write_config_dword(apicdev, 0xf4, v);
-			pci_dev_put(apicdev);
-		}
-	}
-#endif
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_IDE,
-			 fixup_maple_ide);
-- 
1.5.4.4

^ permalink raw reply related

* [PATCH 3/3] maple: enable ipr driver in defconfig
From: Nathan Lynch @ 2008-03-12 23:43 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1205365385-28315-1-git-send-email-ntl@pobox.com>

Some machines supported by the maple platform have an Obsidian
controller which can't be used without enabling CONFIG_IPR and the
options on which it depends.

Signed-off-by: Nathan Lynch <ntl@pobox.com>
---
 arch/powerpc/configs/maple_defconfig |  133 ++++++++++++++++++++++++++++++++--
 1 files changed, 128 insertions(+), 5 deletions(-)

diff --git a/arch/powerpc/configs/maple_defconfig b/arch/powerpc/configs/maple_defconfig
index 8b810d0..25be62b 100644
--- a/arch/powerpc/configs/maple_defconfig
+++ b/arch/powerpc/configs/maple_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.24-rc4
-# Thu Dec  6 16:48:26 2007
+# Wed Mar 12 16:21:48 2008
 #
 CONFIG_PPC64=y
 
@@ -333,7 +333,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=y
 # CONFIG_DEBUG_DRIVER is not set
 # CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
@@ -374,6 +374,7 @@ CONFIG_BLK_DEV_IDEDISK=y
 CONFIG_BLK_DEV_IDECD=y
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
 CONFIG_IDE_TASK_IOCTL=y
 CONFIG_IDE_PROC_FS=y
 
@@ -427,10 +428,129 @@ CONFIG_IDE_ARCH_OBSOLETE_INIT=y
 # SCSI device support
 #
 # CONFIG_RAID_ATTRS is not set
-# CONFIG_SCSI is not set
-# CONFIG_SCSI_DMA is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
 # CONFIG_SCSI_NETLINK is not set
-# CONFIG_ATA is not set
+# CONFIG_SCSI_PROC_FS is not set
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+CONFIG_SCSI_IPR=y
+CONFIG_SCSI_IPR_TRACE=y
+CONFIG_SCSI_IPR_DUMP=y
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+CONFIG_ATA=y
+CONFIG_ATA_NONSTANDARD=y
+# CONFIG_SATA_AHCI is not set
+# CONFIG_SATA_SVW is not set
+# CONFIG_ATA_PIIX is not set
+# CONFIG_SATA_MV is not set
+# CONFIG_SATA_NV is not set
+# CONFIG_PDC_ADMA is not set
+# CONFIG_SATA_QSTOR is not set
+# CONFIG_SATA_PROMISE is not set
+# CONFIG_SATA_SX4 is not set
+# CONFIG_SATA_SIL is not set
+# CONFIG_SATA_SIL24 is not set
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_ULI is not set
+# CONFIG_SATA_VIA is not set
+# CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
+# CONFIG_PATA_ALI is not set
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_CS5530 is not set
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+# CONFIG_ATA_GENERIC is not set
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_NS87415 is not set
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RZ1000 is not set
+# CONFIG_PATA_SC1200 is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+# CONFIG_PATA_VIA is not set
+# CONFIG_PATA_WINBOND is not set
 # CONFIG_MD is not set
 # CONFIG_FUSION is not set
 
@@ -536,6 +656,7 @@ CONFIG_USB_PEGASUS=y
 # CONFIG_HIPPI is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
 # CONFIG_NETPOLL is not set
@@ -783,12 +904,14 @@ CONFIG_USB_UHCI_HCD=y
 #
 # may also be needed; see USB_STORAGE Help for more information
 #
+# CONFIG_USB_STORAGE is not set
 # CONFIG_USB_LIBUSUAL is not set
 
 #
 # USB Imaging devices
 #
 # CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
 CONFIG_USB_MON=y
 
 #
-- 
1.5.4.4

^ permalink raw reply related

* Please pull powerpc.git merge branch
From: Paul Mackerras @ 2008-03-12 23:51 UTC (permalink / raw)
  To: torvalds; +Cc: linuxppc-dev, akpm, linux-kernel

Linus,

Please do:

git pull \
git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc.git merge

to get some more bug-fixes for various powerpc platforms.

Thanks,
Paul.

 arch/powerpc/Makefile                           |    2 
 arch/powerpc/boot/Makefile                      |   18 -
 arch/powerpc/boot/dts/mpc8377_mds.dts           |   70 ++
 arch/powerpc/boot/dts/mpc8378_mds.dts           |   70 ++
 arch/powerpc/boot/dts/mpc8379_mds.dts           |   70 ++
 arch/powerpc/boot/dts/sbc8548.dts               |   16 
 arch/powerpc/boot/wrapper                       |    6 
 arch/powerpc/configs/adder875-uboot_defconfig   |  798 -----------------------
 arch/powerpc/configs/adder875_defconfig         |   61 +-
 arch/powerpc/kernel/head_8xx.S                  |   30 +
 arch/powerpc/kernel/misc_32.S                   |   15 
 arch/powerpc/kernel/pci-common.c                |    8 
 arch/powerpc/kernel/ppc_ksyms.c                 |    3 
 arch/powerpc/mm/hash_utils_64.c                 |    4 
 arch/powerpc/platforms/83xx/mpc837x_mds.c       |    8 
 arch/powerpc/platforms/Kconfig                  |    1 
 arch/powerpc/platforms/Kconfig.cputype          |    7 
 arch/powerpc/platforms/cell/spufs/context.c     |    3 
 arch/powerpc/platforms/cell/spufs/run.c         |    3 
 arch/powerpc/platforms/cell/spufs/sched.c       |    4 
 arch/powerpc/platforms/cell/spufs/spufs.h       |    1 
 arch/powerpc/platforms/powermac/pic.c           |    2 
 arch/powerpc/sysdev/qe_lib/qe.c                 |    7 
 arch/ppc/kernel/head_8xx.S                      |   30 +
 drivers/block/viodasd.c                         |    3 
 drivers/macintosh/via-pmu-backlight.c           |    5 
 drivers/macintosh/via-pmu.c                     |    2 
 include/asm-powerpc/pgtable-ppc32.h             |    8 
 include/asm-ppc/pgtable.h                       |    8 
 include/linux/pmu.h                             |    9 
 30 files changed, 389 insertions(+), 883 deletions(-)
 delete mode 100644 arch/powerpc/configs/adder875-uboot_defconfig
 rename arch/powerpc/configs/{adder875-redboot_defconfig => adder875_defconfig} (95%)

Andy Fleming (1):
      [POWERPC] 83xx: Make 83xx perfmon support selectable

Benjamin Herrenschmidt (3):
      [POWERPC] Fix bogus test for unassigned PCI resources
      [POWERPC] Fix sleep on some powerbooks
      [POWERPC] Fix viodasd driver with scatterlist debug

Grant Likely (1):
      [POWERPC] Fix zImage-dtb.initrd build error

Guido Guenther (1):
      [POWERPC] Fix build of modular drivers/macintosh/apm_emu.c

Ionut Nicu (1):
      [POWERPC] QE: Make qe_get_firmware_info reentrant

Jeremy Kerr (2):
      [POWERPC] spufs: don't (ab)use SCHED_IDLE
      [POWERPC] spufs: fix rescheduling of non-runnable contexts

Jeremy McNicoll (1):
      [POWERPC] 85xx: sbc8548 - Fix incorrect PCI-X and PCI interrupt map

Li Yang (2):
      [POWERPC] 83xx: Fix wrong USB phy type in mpc837xmds dts
      [POWERPC] 83xx: Add local bus device nodes to MPC837xMDS device trees.

Michael Ellerman (1):
      [POWERPC] Fix large hash table allocation on Cell blades

Paul Mackerras (1):
      [POWERPC] Add __ucmpdi2 for 64-bit comparisons in 32-bit kernels

Scott Wood (1):
      [POWERPC] 8xx: Fix wrapper platform for adder875, and combine defconfigs.

Theodore Ts'o (1):
      [POWERPC] Export empty_zero_page

Timur Tabi (1):
      [POWERPC] QE: Fix QE firmware uploading limit

Tony Breeds (3):
      [POWERPC] Fix undefined pmu_sys_suspended compilation error
      [POWERPC] Fix drivers/macintosh/mediabay.c when !CONFIG_ADB_PMU
      [POWERPC] Fix arch/powerpc/platforms/powermac/pic.c when !CONFIG_ADB_PMU

Vitaly Bordug (1):
      [POWERPC] 8xx: fix swap

Yuri Tikhonov (1):
      [PPC] 8xx: swap bug-fix

^ permalink raw reply

* Re: [PATCH 1/2] Driver for Freescale 8610 and 5121 DIU
From: Stephen Rothwell @ 2008-03-13  0:10 UTC (permalink / raw)
  To: York Sun; +Cc: linuxppc-dev, linux-kernel
In-Reply-To: <12053582231281-git-send-email-yorksun@freescale.com>

[-- Attachment #1: Type: text/plain, Size: 889 bytes --]

Hi York,

Just a few things from a first pass.

On Wed, 12 Mar 2008 16:43:42 -0500 York Sun <yorksun@freescale.com> wrote:
>
> +++ b/drivers/video/fsl-diu-fb.c
>
> +#include <asm/of_platform.h>

Please include <linux/of_platform.h> instead.

> +/* Align to 64-bit(8-byte), 32-byte, etc. */
> +static int allocate_buf(struct diu_addr *buf, u32 size, u32 bytes_align)
> +{
>
> +	buf->vaddr = dma_alloc_coherent(0, ssize,
> +					(dma_addr_t *) &(buf->paddr),

This cast is unnecessary as buf->paddr is a dma_addr_t ...

> +++ b/drivers/video/fsl-diu-fb.h
>
> +static struct fb_videomode __devinitdata fsl_diu_default_mode = {
> +static struct fb_videomode __devinitdata fsl_diu_mode_db[] = {

Why are these in the .h file?  They should be in the .c file.

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* Re: PPC upstream kernel ignored DABR bug
From: Roland McGrath @ 2008-03-13  1:47 UTC (permalink / raw)
  To: Jens Osterkamp
  Cc: linuxppc-dev, Jan Kratochvil, Paul Mackerras, Arnd Bergmann
In-Reply-To: <200803122330.36905.jens@de.ibm.com>

AFAICT the DABRX register just has two global bits that enable paying
attention to the DABR register.  It only needs to be set once at boot time
(as the cell code does).  I don't see how missing that initialization could
ever have explained the behavior we see where DABR matches are intermittent.
If those DABRX bits weren't set then no DABR match would have happened.
(Apparently they are set before boot on an Apple G5.)

What we actually see is that DABR matches seem to be reliable when things
are slow, and get intermittent when there are enough threads with DABR set.

I searched the web trying to figure out what a DABRX register does so I
could just go try it myself rather than waiting another n months for powerpc
folks to forget about it again.  (I did try it, and 
	mtspr(SPRN_DABRX, DABRX_KERNEL | DABRX_USER);
makes no difference to the test on my machine, even done in set_dabr every
time we set SPRN_DABR.)

I happened across:

http://www-01.ibm.com/chips/techlib/techlib.nsf/techdocs/79B6E24422AA101287256E93006C957E/$file/PowerPC_970FX_errata_DD3.X_V1.7.pdf

which is "IBM PowerPC 970FX RISC Microprocessor Errata List for DD3.X"
and contains "Erratum #8: DABRX register might not always be updated correctly":

	Projected Impact
	      The data address breakpoint function might not always work.
	Workaround
	      None.
	Status
	      A fix is not planned at this time for the PowerPC 970FX.

The only machine I have at home for testing powerpc is an Apple G5,
supplied to me by IBM.  It says:
	cpu             : PPC970FX, altivec supported
	revision        : 3.0 (pvr 003c 0300)
so I am guessing this document applies to the chips I have.  Since I can't
test on other chips myself, it is plausible from what I've seen that there
is no mysterious kernel problem and only this hardware problem.  The
description of the hardware problem would not make me think that it would
behave this way, but it is not very detailed or precise, or at least does
not seem so to a reader not expert on powerpc.

So, uh, go IBM!

I'm in the minority in this conversation as someone not expert on powerpc,
and as someone not employed by IBM.  (I don't really mind finding public IBM
documents about powerpc on the web and telling IBM powerpc folks about them.
But, well.)

I don't know what I can do next to tell whether this processor erratum is in
fact what's happening in the test case.  If it is, I don't know if there
might be some arcane way to work around it despite "None" cited above.


Thanks,
Roland

^ permalink raw reply

* Re:The question about the QUICC ENGINE microcode for freescale
From: 郭劲 @ 2008-03-13  2:05 UTC (permalink / raw)
  To: rmcguire; +Cc: linuxppc-embedded

Hi,Russell,
My MPC8360 is 533/266/400MHZ(core/ddr/QE), I have 2Gbytes DDR-1 memory, not
DDR-II. I found that the DDR affected the speed if some ddr is not good. I used
the linux-2.6.22 with enable the NAPI driver. I will update my cpu to
667/333/400MHZ.

I written the email to the support.asis@freescale.com, I do not know who will
response this email. Nobody in freescale teach me how to deal with this problem. 

I do not know whether or not each QUICC ENGINE in charge of each GETH? How to
config to make each QE in charge of each GETH?

Thank you very much.


>From: "Russell McGuire" <rmcguire@videopresence.com>
>Reply-To: <rmcguire@videopresence.com>
>To: <guojin02@tsinghua.org.cn>
>Subject: The question about the QUICC ENGINE microcode for freescale
>Date:Tue, 11 Mar 2008 17:20:25 -0700
>
>Couple of thoughts, is that according to Freescale specs, the QE can only
>support TWO 1000Mbit end points. And that is assuming RAW traffic, not
>protocol layer processing. Since the 8360E has two QUICC Engines, that is
>only 1000Mbits data per Engine. Are you intending to get 1000Mbits TX and RX
>on each engine? I think in reality you will be capped at 1000Mbit aggregate
>in the RX and TX. I could be wrong, but you might want to run that past a
>Freescale FAE, do you have the name of your contact for your area?
>
>This is assuming that you are running at the full speed of the MPC8360E, i.e
>both QUICC engines probably pushing 500Mhz. You'll also need to probably be
>running DDR2 RAM at MAX speed to achieve these rates, as each skbuf will
>have to be dma'd out to external memory. All the early dev boards by
>Freescale only used DDR1. As well you'll want to be sure your Coherent
>System Bus <CSB> speed is as near max, i.e. 300-333Mhz.
>
>What clock speeds / Frequency of chip are you using to test this?  As well
>which driver are you using with this test?
>
>As a HW designer for these boards and driver programmer I am just curious
>what your HW is looking / configured like?
>
>-Russ
>
>
>
>
>
>Hi,friends,
>
>I want to realize the high speed TCP package on GETH of MPC8360E,I would
>like the speed on both UCC1 and UCC2 for both send and receive TCP
>package(big package) up to 1000M bits/sec, so the total internet speed is
>4000M bits/sec for MPC8360E.
>
>I tested the internet performance by IPERF test software with the condition
>that the core cpu deal with the TCP package,without microcode. I config the
>UCC2 down, config UCC1 to send package out to an server PC,no receive,the
>speed for UCC1 just only sending package is about 300M bits/sec, and CPU is
>100% used. This speed is so slow, is too slow. If I send and recieve at the
>same time, the speed is much slower, if I make the UCC2 up, the speed is
>much slower and slower.
>I do not know how to incrase the internet speed for MPC8360E, somebody told
>me, we must use the microcode for QUICC ENGINE.  
>
>My question is that where can I download the microcode for QUICC ENGINE and
>how to use it?  Whether or not this microcode can help me to realize the
>4000M bits/sec for TCP package?
>
>
>
>
> 

^ permalink raw reply

* Re: [PATCH 2/8] pseries: phyp dump: reserve-release proof-of-concept
From: Manish Ahuja @ 2008-03-13  4:29 UTC (permalink / raw)
  To: linasvepstas; +Cc: linuxppc-dev, paulus, mahuja
In-Reply-To: <3ae3aa420803121052g6ded9c94xd23823a4e81f4bbf@mail.gmail.com>

If Mike and Paul are okay, then I will leave this bit as is and fix all 
other issues and comments.

Thanks,
Manish



Linas Vepstas wrote:
> On 10/03/2008, Michael Ellerman <michael@ellerman.id.au> wrote:
>> On Thu, 2008-02-28 at 18:24 -0600, Manish Ahuja wrote:
> 
>>  > +
>>  > +/* Global, used to communicate data between early boot and late boot */
>>  > +static struct phyp_dump phyp_dump_global;
>>  > +struct phyp_dump *phyp_dump_info = &phyp_dump_global;
>>
>> I don't see the point of this. You have a static (ie. non-global) struct
>>  called phyp_dump_global, then you create a pointer to it and pass that
>>  around.
> 
> I did this. This is a style used to minimize disruption due to future
> design changes. Basically, the idea is that, at some later time, for
> some unknown reason, we decide that this structure shouldn't
> be global, or maybe shouldn't be statically allocated, or maybe
> should be per-cpu, or who knows.  By creating a pointer, and
> just passing that around, you isolate other code from this change.
> 
> I learned this trick after spending too many months of my life hunting
> down globals and replacing them by dynamically allocated structs.
> Its a long and painful process, on many levels, often requiring major
> code restructuring.  Code that touches globals directly is often
> poorly thought out, designed.  But going in the opposite direction
> is easy: if your code always passes everything it needs as args
> to subroutines,  then you are free & clear ... if one of those args
> just happens to be a pointer to a global, there's no loss (not even
> a performance loss -- the arg passing overhead is about the same
> as a global TOC lookup!)
> 
> So it may look weird if you're not used to seeing it; but the alternative
> is almost always worse.
> 
> --linas

^ permalink raw reply

* [PATCH] [POWERPC] really export empty_zero_page
From: Stephen Rothwell @ 2008-03-13  5:20 UTC (permalink / raw)
  To: paulus; +Cc: ppc-dev, linux-next, Theodore Tso

It was being protected by CONFIG_PPC32.

Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
 arch/powerpc/kernel/ppc_ksyms.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

I have applied this to today's linux-next tree.

diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
index 9c98424..a722ede 100644
--- a/arch/powerpc/kernel/ppc_ksyms.c
+++ b/arch/powerpc/kernel/ppc_ksyms.c
@@ -58,7 +58,6 @@ extern void program_check_exception(struct pt_regs *regs);
 extern void single_step_exception(struct pt_regs *regs);
 extern int sys_sigreturn(struct pt_regs *regs);
 
-EXPORT_SYMBOL(empty_zero_page);
 EXPORT_SYMBOL(clear_pages);
 EXPORT_SYMBOL(copy_page);
 EXPORT_SYMBOL(ISA_DMA_THRESHOLD);
@@ -192,3 +191,4 @@ EXPORT_SYMBOL(intercept_table);
 EXPORT_SYMBOL(__mtdcr);
 EXPORT_SYMBOL(__mfdcr);
 #endif
+EXPORT_SYMBOL(empty_zero_page);
-- 
1.5.4.3

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/

^ permalink raw reply related

* Re: [PATCH 10/11] celleb: add support for PCI Express
From: Ishizaki Kou @ 2008-03-13  5:51 UTC (permalink / raw)
  To: arnd; +Cc: linuxppc-dev, paulus
In-Reply-To: <200803051249.28739.arnd@arndb.de>

Arnd Bergmann <arnd@arndb.de> wrote:
> On Wednesday 05 March 2008, Ishizaki Kou wrote:
> > This patch adds support for PCI Express port on Celleb. I/O space
> > of this PCI Express port is not mapped in memory space. So we use
> > the io-workaround mechanism to make accesses indirect.
> > 
> > Signed-off-by: Kou Ishizaki <kou.ishizaki@toshiba.co.jp>
> 
> Acked-by: Arnd Bergmann <arnd@arndb.de>
> 
> This one looks good, but I wonder if we should make it possible to
> also use it on QS20, which the current code doesn't allow.
> 
> It's a rather hypothetical question, because QS20 has been replaced
> by QS21 as a product and it never supported PCIe cards with I/O space
> mappings, but it would be the "right" thing to do.
> 
> Since you don't have the QS20 hardware to test that, and I currently
> doubt anyone at IBM has the energy to do the work, it will probably
> never get done. If you send another version of the patch, maybe you
> can add comments to hint that this is actually possible, just hasn't
> been implemented.

Sorry, I don't know about QS20 and its chipset. However, if anyone
changes the code to work also on QS20, I'll welcome the change and
test it on Celleb.

Though I don't know it helps you, I explain a little about Celleb.

The way to access SCC PCIe I/O port is the same as the way to access
its config space.
 - Write an address to the address register.
 - Write an 'I/O port write' or 'I/O port read' command with byte
   enable bits to the command register.
 - Write or Read the data register.
That's all, and you can find this in my code.


By the way, I found a minor bug in my patch. I'll send fixed one.

> +	dummy_page_da = dma_map_single(bus->phb->parent, dummy_page_va,
> +			PAGE_SIZE, DMA_FROM_DEVICE);
> +	if (dummy_page_da == DMA_FROM_DEVICE) {

Comparing with DMA_FROM_DEVICE is wrong. We should compare with
DMA_ERROR_CODE. And using dma_mapping_error() is the right way.


Best regards,
Kou Ishizaki

^ permalink raw reply

* Hi, friends, the question about the core frequency on u-boot and device tree?
From: 郭劲 @ 2008-03-13  6:38 UTC (permalink / raw)
  To: support.asia, linuxppc-embedded, u-boot-users

HI,friends,

The core frequency and bus frequency and QE frequency on MPC8360 are configed
during the loading of HRCW and the CLKIN or PCI_CLKIN, in the u-boot-1.2.0, I can
use the "clocks" command to show all kind of frequecy,at this time the core
frequency is 528MHZ. please see follow:
 => clocks
Clock configuration Guo Jing:
  Core:                 528 MHz
  Coherent System Bus:  264 MHz
  QE:                   396 MHz
  BRG:                  198 MHz
  Local Bus Controller: 264 MHz
  Local Bus:             66 MHz
  DDR:                  264 MHz
  DDR Secondary:        264 MHz
  SEC:                   88 MHz
  I2C1:                 264 MHz
  I2C2:                 264 MHz

Then, I modified the device tree source code to make the core frequency is 660MHZ.
		
PowerPC,8360@0 {
			device_type = "cpu";
			reg = <0>;
			d-cache-line-size = <20>;	// 32 bytes
			i-cache-line-size = <20>;	// 32 bytes
			d-cache-size = <8000>;		// L1, 32K
			i-cache-size = <8000>;		// L1, 32K
			timebase-frequency = <3EF1480>; //66MHZ
			bus-frequency = <FBC5200>;    //264MHZ 
			clock-frequency = <2756CD00>; //660MHZ
			32-bit;
		};
The device tree will send the core frequency information to linux kernel. Then I
bootm the linux by above dtb blob. follow is the dmesg information. we can see
that:
time_init: decrementer frequency = 66.000000 MHz
time_init: processor frequency   = 660.000000 MHz

I am so confused with the core frequency. I think the dmesg show the wrong core
frequency because the actual core freqyency is decided by the power on of cpu. The
device tree just only send a false frequency to the linux kernel.
My question is which frequency, 660MHZ or the 528MHZ, is the actual core
frequency?  
Which one, the HRCW or the device tree, decide the actual frequency of core?
If we can use the device tree to re-assign the core frequency, how this process is
finished?



~ # dmesg
Using MPC836x MDS machine description
Linux version 2.6.22 (dpim@localhost.localdomain) (gcc version 4.0.2 20060628
(Wasabi)) #2 Mon Mar 10 01:02:46 EST 2008
Found initrd at 0xcfc39000:0xcffa4fa3
Found legacy serial port 0 for /soc8360@e0000000/serial@4500
  mem=e0004500, taddr=e0004500, irq=0, clk=264000000, speed=0
Found legacy serial port 1 for /soc8360@e0000000/serial@4600
  mem=e0004600, taddr=e0004600, irq=0, clk=264000000, speed=0
Entering add_active_range(0, 0, 524288) 0 entries of 256 used
Found MPC83xx PCI host bridge at 0x00000000e0008500. Firmware bus number: 0->0
Bad clock source for time stamp 1
Bad clock source for time stamp 2
pio-handle not available 
Top of RAM: 0x80000000, Total RAM: 0x80000000
Memory hole size: 0MB
Zone PFN ranges:
  DMA             0 ->   196608
  Normal     196608 ->   196608
  HighMem    196608 ->   524288
early_node_map[1] active PFN ranges
    0:        0 ->   524288
On node 0 totalpages: 524288
  DMA zone: 1536 pages used for memmap
  DMA zone: 0 pages reserved
  DMA zone: 195072 pages, LIFO batch:31
  Normal zone: 0 pages used for memmap
  HighMem zone: 2560 pages used for memmap
  HighMem zone: 325120 pages, LIFO batch:31
Built 1 zonelists.  Total pages: 520192
Kernel command line: console=ttyS0,115200 root=/dev/ram rw
IPIC (128 IRQ sources) at fddf3700
QEIC (64 IRQ sources) at fddf2080
PID hash table entries: 4096 (order: 12, 16384 bytes)
time_init: decrementer frequency = 66.000000 MHz
time_init: processor frequency   = 660.000000 MHz
Dentry cache hash table entries: 131072 (order: 7, 524288 bytes)
Inode-cache hash table entries: 65536 (order: 6, 262144 bytes)
High memory: 1310720k
Memory: 2072044k/2097152k available (2692k kernel code, 1334664k reserved, 112k
data, 122k bss, 144k init)
Calibrating delay loop... 131.58 BogoMIPS (lpj=263168)
Mount-cache hash table entries: 512
NET: Registered protocol family 16
fsl_sec2_of_init: start
PCI: Probing PCI hardware
Registering qe_ic with sysfs...
Registering ipic with sysfs...
Generic PHY: Registered new driver
SCSI subsystem initialized
NET: Registered protocol family 2
IP route cache hash table entries: 32768 (order: 5, 131072 bytes)
TCP established hash table entries: 131072 (order: 8, 1048576 bytes)
TCP bind hash table entries: 65536 (order: 6, 262144 bytes)
TCP: Hash tables configured (established 131072 bind 65536)
TCP reno registered
checking if image is initramfs...it isn't (no cpio magic); looks like an initrd
Freeing initrd memory: 3503k freed
highmem bounce pool size: 64 pages
JFFS2 version 2.2. (NAND) © 2001-2006 Red Hat, Inc.
cryptodev_init(c02921e8)
cryptosoft: registered as device: 0
talitos: des/3des aes md5 sha1
io scheduler noop registered
io scheduler anticipatory registered (default)
io scheduler deadline registered
io scheduler cfq registered
Generic RTC Driver v1.07
WDT driver for MPC83xx initialized. mode:reset timeout=65535 (16 seconds)
Serial: 8250/16550 driver $Revision: 1.90 $ 4 ports, IRQ sharing disabled
serial8250.0: ttyS0 at MMIO 0xe0004500 (irq = 16) is a 16550A
console handover: boot [udbg0] -> real [ttyS0]
serial8250.0: ttyS1 at MMIO 0xe0004600 (irq = 17) is a 16550A
RAMDISK driver initialized: 16 RAM disks of 32768K size 1024 blocksize
loop: module loaded
UCC Ethernet Controller MII Bus: probed
ucc_geth: QE UCC Gigabit Ethernet Controller
ucc_geth: UCC1 at 0xe0102000 (irq = 23) 
eth0: MTU=1500 (frame size=1518,rx_buffer_size=1536,truesize=1792,sk_buff=160)
ucc_geth: UCC2 at 0xe0103000 (irq = 24) 
eth1: MTU=1500 (frame size=1518,rx_buffer_size=1536,truesize=1792,sk_buff=160)
SKB Handler initialized(max=64)
Marvell 88E1101: Registered new driver
Marvell 88E1111: Registered new driver
Marvell 88E1145: Registered new driver
MPC8360E MDS flash device: 2000000 at fe000000 Partition number 6
MPC8360E MDS Flash Map Info: Found 1 x16 devices at 0x0 in 16-bit bank
MPC8360E MDS Flash Map Info: Found an alias at 0x1000000 for the chip at 0x0
Support for command set 0001 not present
gen_probe: No supported Vendor Command Set found
i2c /dev entries driver
ds1374 0-0068: rtc core: registered ds1374 as rtc0
TCP cubic registered
NET: Registered protocol family 1
NET: Registered protocol family 17
ds1374 0-0068: setting the system clock to 1972-02-18 11:35:36 (67260936)
RAMDISK: Compressed image found at block 0
VFS: Mounted root (ext2 filesystem).
Freeing unused kernel memory: 144k init
PHY: e0102120:00 - Link is Up - 1000/Full

^ permalink raw reply

* RE: fsldma seems to be buggy, noticed in loop mode
From: Zhang Wei @ 2008-03-13  7:03 UTC (permalink / raw)
  To: Sebastian Siewior, linuxppc-embedded
In-Reply-To: <20080312180421.GC7255@Chamillionaire.breakpoint.cc>

Hi, Sebastian

Could you please apply these two patches and test again?

http://lkml.org/lkml/2008/3/10/64
http://lkml.org/lkml/2008/3/13/36

Thanks!
Wei.

> -----Original Message-----
> From: Sebastian Siewior [mailto:linuxppc-embedded@ml.breakpoint.cc]=20
> Sent: Thursday, March 13, 2008 2:04 AM
> To: linuxppc-embedded@ozlabs.org
> Cc: Zhang Wei
> Subject: fsldma seems to be buggy, noticed in loop mode
>=20
> Hello,
>=20
> I have a little kmod where I dma data from one place to another (can
> post it if someone wants to see it). It works in general according to
> memcmp :)
>=20
> If I set the DAHE flag (DAHTS =3D 0, for one byte transfers) =
everything
> seems to work as well (I see only the last byte which has the correct
> value).
> Now if I change the destination address to my FIFO I get the requested
> transfer size plus some extra bytes. The extra bytes are looking like
> exactly the same DMA transfer once again. Then my FIFO overruns.
> Enabling some printks in the kernel gave me the following log:
>=20
> |of-fsl-dma-channel e0021100.dma-channe: new link desc alloc df32a000
> |of-fsl-dma-channel e0021100.dma-channe: --memcpy issue--
> |of-fsl-dma-channel e0021100.dma-channe: Ch 0, LD 1f32a000
> |of-fsl-dma-channel e0021100.dma-channe: LD offset 0: 00050000
> |of-fsl-dma-channel e0021100.dma-channe: LD offset 1: 1f0be000
> |of-fsl-dma-channel e0021100.dma-channe: LD offset 2: 00050000
> |of-fsl-dma-channel e0021100.dma-channe: LD offset 3: 1f36c000
> |of-fsl-dma-channel e0021100.dma-channe: LD offset 4: 00000000
> |of-fsl-dma-channel e0021100.dma-channe: LD offset 5: 00000001
> |of-fsl-dma-channel e0021100.dma-channe: LD offset 6: 00000100
> |of-fsl-dma-channel e0021100.dma-channe: LD offset 7: 00000000
> |of-fsl-dma-channel e0021100.dma-channe: ----------------
> |of-fsl-dma-channel e0021100.dma-channe: xfer LDs staring=20
> from 0x000000001f32a000
> |of-fsl-dma-channel e0021100.dma-channe: xfer LDs staring=20
> from 0x000000001f32a000
> |of-fsl-dma-channel e0021100.dma-channe: xfer LDs staring=20
> from 0x000000001f32a000
> |of-fsl-dma-channel e0021100.dma-channe: xfer LDs staring=20
> from 0x000000001f32a000
> |of-fsl-dma-channel e0021100.dma-channe: xfer LDs staring=20
> from 0x000000001f32a000
> |of-fsl-dma-channel e0021100.dma-channe: xfer LDs staring=20
> from 0x000000001f32a000
> |of-fsl-dma-channel e0021100.dma-channe: xfer LDs staring=20
> from 0x000000001f32a000
> |of-fsl-dma-channel e0021100.dma-channe: xfer LDs staring=20
> from 0x000000001f32a000
> |of-fsl-dma-channel e0021100.dma-channe: xfer LDs staring=20
> from 0x000000001f32a000
> |of-fsl-dma-channel e0021100.dma-channe: xfer LDs staring=20
> from 0x000000001f32a000
> |of-fsl-dma-channel e0021100.dma-channe: xfer LDs staring=20
> from 0x000000001f32a000
> |of-fsl-dma-channel e0021100.dma-channe: xfer LDs staring=20
> from 0x000000001f32a000
> |of-fsl-dma-channel e0021100.dma-channe: xfer LDs staring=20
> from 0x000000001f32a000
> |of-fsl-dma-channel e0021100.dma-channe: chan completed_cookie =3D 1
> |of-fsl-dma-channel e0021100.dma-channe: link descriptor=20
> df32a000 will be recycle.
> |of-fsl-dma-channel e0021100.dma-channe: chan completed_cookie =3D 1
> |of-fsl-dma-channel e0021100.dma-channe: chan completed_cookie =3D 1
>=20
> done.=20
> I have one list entry which is df32a000. According to the output that
> single request gets started a couple of times what would=20
> explain why the
> FIFO overruns.
> Is it possible that the driver does not properly recognize that the
> transfer is finished _and_ that is the last one in line? Enabling the
> dma self test Kconfig option shows no error message but the number of
> interrupts that have been generated differ from channel to channel,
> from boot to boot.
>=20
> btw: It is a MPC8544 DS with -rc5.
>=20
> thanks,
>  Sebastian
>=20

^ permalink raw reply

* [PATCH] powerpc: user_regset PTRACE_SETREGS regression fix
From: Roland McGrath @ 2008-03-13  8:25 UTC (permalink / raw)
  To: Paul Mackerras, Anton Blanchard; +Cc: linuxppc-dev, linux-kernel


The PTRACE_SETREGS request was only recently added on powerpc,
and gdb does not use it.  So it slipped through without getting
all the testing it should have had.

The user_regset changes had a simple bug in storing to all of
the 32-bit general registers block on 64-bit kernels.  This bug
only comes up with PTRACE_SETREGS, not PPC_PTRACE_SETREGS.
It causes a BUG_ON to hit, so this fix needs to go in ASAP.

Signed-off-by: Roland McGrath <roland@redhat.com>
---
 arch/powerpc/kernel/ptrace.c |   10 ++++++++--
 1 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index 7673e98..2a9fe97 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -530,15 +530,21 @@ static int gpr32_set(struct task_struct *target,
 		--count;
 	}
 
-	if (kbuf)
+	if (kbuf) {
 		for (; count > 0 && pos <= PT_MAX_PUT_REG; --count)
 			regs[pos++] = *k++;
-	else
+		for (; count > 0 && pos < PT_TRAP; --count, ++pos)
+			++k;
+	} else {
 		for (; count > 0 && pos <= PT_MAX_PUT_REG; --count) {
 			if (__get_user(reg, u++))
 				return -EFAULT;
 			regs[pos++] = reg;
 		}
+		for (; count > 0 && pos < PT_TRAP; --count, ++pos)
+			if (__get_user(reg, u++))
+				return -EFAULT;
+	}
 
 	if (count > 0 && pos == PT_TRAP) {
 		if (kbuf)

^ permalink raw reply related

* Re: [PATCH 1/4] Ensure that pmu_sys_suspended exists in appropriate configs.
From: Guido Günther @ 2008-03-13  8:30 UTC (permalink / raw)
  To: Tony Breeds; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <20080312212005.GU6887@bakeyournoodle.com>

Hi Tony,
On Thu, Mar 13, 2008 at 08:20:05AM +1100, Tony Breeds wrote:
[..snip..] 
> where pmu_sys_suspended is referenced and I'm having difficulty
> understanding how CONFIG_HIBERNATION is affecting that.
I mangled the filenames and didn't notice that you fixed the header file
instead of via-pmu.c. Yes, this should work. Thanks for fixing this 
and the apm-emu stuff as well.
Cheers,
 -- Guido

^ permalink raw reply

* [PATCH -mm 1/4] powerpc copy_siginfo_from_user32
From: Roland McGrath @ 2008-03-13  8:31 UTC (permalink / raw)
  To: Paul Mackerras, Anton Blanchard
  Cc: linuxppc-dev, Ingo Molnar, Thomas Gleixner, Andrew Morton,
	linux-kernel


Define the copy_siginfo_from_user32 entry point for powerpc, so
that generic CONFIG_COMPAT code can call it.  We already had the
code rolled into compat_sys_rt_sigqueueinfo, this just moves it
out into the canonical function that other arch's define.

Signed-off-by: Roland McGrath <roland@redhat.com>
---
 arch/powerpc/kernel/signal_32.c |   19 ++++++++++++++++---
 1 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index d840bc7..ad69434 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -621,6 +621,18 @@ int copy_siginfo_to_user32(struct compat_siginfo __user *d, siginfo_t *s)
 
 #define copy_siginfo_to_user	copy_siginfo_to_user32
 
+int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from)
+{
+	memset(to, 0, sizeof *to);
+
+	if (copy_from_user(to, from, 3*sizeof(int)) ||
+	    copy_from_user(to->_sifields._pad,
+			   from->_sifields._pad, SI_PAD_SIZE32))
+		return -EFAULT;
+
+	return 0;
+}
+
 /*
  * Note: it is necessary to treat pid and sig as unsigned ints, with the
  * corresponding cast to a signed int to insure that the proper conversion
@@ -634,9 +646,10 @@ long compat_sys_rt_sigqueueinfo(u32 pid, u32 sig, compat_siginfo_t __user *uinfo
 	int ret;
 	mm_segment_t old_fs = get_fs();
 
-	if (copy_from_user (&info, uinfo, 3*sizeof(int)) ||
-	    copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE32))
-		return -EFAULT;
+	ret = copy_siginfo_from_user32(&info, uinfo);
+	if (unlikely(ret))
+		return ret;
+
 	set_fs (KERNEL_DS);
 	/* The __user pointer cast is valid becasuse of the set_fs() */
 	ret = sys_rt_sigqueueinfo((int)pid, (int)sig, (siginfo_t __user *) &info);

^ permalink raw reply related

* [PATCH -mm 2/4] ptrace: compat_ptrace_request siginfo
From: Roland McGrath @ 2008-03-13  8:32 UTC (permalink / raw)
  To: Paul Mackerras, Anton Blanchard
  Cc: linuxppc-dev, Ingo Molnar, Thomas Gleixner, Andrew Morton,
	linux-kernel
In-Reply-To: <20080313083107.8BDE926F992@magilla.localdomain>


This adds support for PTRACE_GETSIGINFO and PTRACE_SETSIGINFO in
compat_ptrace_request.  It relies on existing arch definitions for
copy_siginfo_to_user32 and copy_siginfo_from_user32.

On powerpc, this fixes a longstanding regression of 32-bit ptrace
calls on 64-bit kernels vs native calls (64-bit calls or 32-bit
kernels).  This can be seen in a 32-bit call using PTRACE_GETSIGINFO
to examine e.g. siginfo_t.si_addr from a signal that sets it.
(This was broken as of 2.6.24 and, I presume, many or all prior versions.)

Signed-off-by: Roland McGrath <roland@redhat.com>
---
 kernel/ptrace.c |   48 +++++++++++++++++++++++++++++++++++-------------
 1 files changed, 35 insertions(+), 13 deletions(-)

diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index fdb34e8..67e392e 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -323,9 +323,8 @@ static int ptrace_setoptions(struct task_struct *child, long data)
 	return (data & ~PTRACE_O_MASK) ? -EINVAL : 0;
 }
 
-static int ptrace_getsiginfo(struct task_struct *child, siginfo_t __user * data)
+static int ptrace_getsiginfo(struct task_struct *child, siginfo_t *info)
 {
-	siginfo_t lastinfo;
 	int error = -ESRCH;
 
 	read_lock(&tasklist_lock);
@@ -333,31 +332,25 @@ static int ptrace_getsiginfo(struct task_struct *child, siginfo_t __user * data)
 		error = -EINVAL;
 		spin_lock_irq(&child->sighand->siglock);
 		if (likely(child->last_siginfo != NULL)) {
-			lastinfo = *child->last_siginfo;
+			*info = *child->last_siginfo;
 			error = 0;
 		}
 		spin_unlock_irq(&child->sighand->siglock);
 	}
 	read_unlock(&tasklist_lock);
-	if (!error)
-		return copy_siginfo_to_user(data, &lastinfo);
 	return error;
 }
 
-static int ptrace_setsiginfo(struct task_struct *child, siginfo_t __user * data)
+static int ptrace_setsiginfo(struct task_struct *child, const siginfo_t *info)
 {
-	siginfo_t newinfo;
 	int error = -ESRCH;
 
-	if (copy_from_user(&newinfo, data, sizeof (siginfo_t)))
-		return -EFAULT;
-
 	read_lock(&tasklist_lock);
 	if (likely(child->sighand != NULL)) {
 		error = -EINVAL;
 		spin_lock_irq(&child->sighand->siglock);
 		if (likely(child->last_siginfo != NULL)) {
-			*child->last_siginfo = newinfo;
+			*child->last_siginfo = *info;
 			error = 0;
 		}
 		spin_unlock_irq(&child->sighand->siglock);
@@ -424,6 +417,7 @@ int ptrace_request(struct task_struct *child, long request,
 		   long addr, long data)
 {
 	int ret = -EIO;
+	siginfo_t siginfo;
 
 	switch (request) {
 	case PTRACE_PEEKTEXT:
@@ -442,12 +436,22 @@ int ptrace_request(struct task_struct *child, long request,
 	case PTRACE_GETEVENTMSG:
 		ret = put_user(child->ptrace_message, (unsigned long __user *) data);
 		break;
+
 	case PTRACE_GETSIGINFO:
-		ret = ptrace_getsiginfo(child, (siginfo_t __user *) data);
+		ret = ptrace_getsiginfo(child, &siginfo);
+		if (!ret)
+			ret = copy_siginfo_to_user((siginfo_t __user *) data,
+						   &siginfo);
 		break;
+
 	case PTRACE_SETSIGINFO:
-		ret = ptrace_setsiginfo(child, (siginfo_t __user *) data);
+		if (copy_from_user(&siginfo, (siginfo_t __user *) data,
+				   sizeof siginfo))
+			ret = -EFAULT;
+		else
+			ret = ptrace_setsiginfo(child, &siginfo);
 		break;
+
 	case PTRACE_DETACH:	 /* detach a process that was attached. */
 		ret = ptrace_detach(child, data);
 		break;
@@ -616,6 +620,7 @@ int compat_ptrace_request(struct task_struct *child, compat_long_t request,
 {
 	compat_ulong_t __user *datap = compat_ptr(data);
 	compat_ulong_t word;
+	siginfo_t siginfo;
 	int ret;
 
 	switch (request) {
@@ -638,6 +643,23 @@ int compat_ptrace_request(struct task_struct *child, compat_long_t request,
 		ret = put_user((compat_ulong_t) child->ptrace_message, datap);
 		break;
 
+	case PTRACE_GETSIGINFO:
+		ret = ptrace_getsiginfo(child, &siginfo);
+		if (!ret)
+			ret = copy_siginfo_to_user32(
+				(struct compat_siginfo __user *) datap,
+				&siginfo);
+		break;
+
+	case PTRACE_SETSIGINFO:
+		memset(&siginfo, 0, sizeof siginfo);
+		if (copy_siginfo_from_user32(
+			    &siginfo, (struct compat_siginfo __user *) datap))
+			ret = -EFAULT;
+		else
+			ret = ptrace_setsiginfo(child, &siginfo);
+		break;
+
 	default:
 		ret = ptrace_request(child, request, addr, data);
 	}

^ permalink raw reply related

* RE: [PATCH] Ported Xilinx GPIO driver to OpenFirmware.
From: Magnus Hjorth @ 2008-03-13  8:33 UTC (permalink / raw)
  To: 'Stephen Neuendorffer', 'git'; +Cc: linuxppc-embedded
In-Reply-To: <20080311173602.8E61C728093@mail209-sin.bigfish.com>

Hi,

Thanks for the feedback. I'll have a look into refining the patch in a few weeks when I get some
more time. 

I have also been tinkering a little with the SPI driver, and that got me thinking. Wouldn't it be
great if SPI controllers and devices could be specified in the OF device tree and registered on boot
time? Even better if SPI worked as a true bus in EDK, with placeholder IP-cores for each slave
device, so such device entries could be autogenerated.

Cheers,
Magnus

> -----Original Message-----
> From: Stephen Neuendorffer [mailto:stephen.neuendorffer@xilinx.com]
> Sent: den 11 mars 2008 18:36
> To: Magnus Hjorth; git
> Cc: linuxppc-embedded@ozlabs.org; Grant Likely
> Subject: RE: [PATCH] Ported Xilinx GPIO driver to OpenFirmware.
> 
> 
> Thanks Magnus!
> 
> Generally speaking this looks reasonable.  Some comments:
> 
> >  struct xgpio_instance {
> >  	struct list_head link;
> >  	unsigned long base_phys;	/* GPIO base address - physical
> */
> >  	unsigned long remap_size;
> > -	u32 device_id;
> > +	u32 device_id;		/* Dev ID for platform devices, 0 for OF
> devices */
> > +	void *of_id;		/* of_dev pointer for OF devices, NULL
> for plat devices */
> 
> Why have separate ids?  I don't think the of_dev needs to be kept around
> here.  This driver seems seems awkwardly written to have a local list of
> all the devices, rather than simply attaching the xgpio_instance as the
> private data of the file.
> 
> For instance, in drivers/char/xilinx_hwicap.c:
> 
> static ssize_t
> hwicap_read(struct file *file, char __user *buf, size_t count, loff_t
> *ppos)
> {
> 	struct hwicap_drvdata *drvdata = file->private_data;
> 
> and the drvdata is set in open:
> 
> static int hwicap_open(struct inode *inode, struct file *file)
> {
> 	struct hwicap_drvdata *drvdata;
> 	int status;
> 
> 	drvdata = container_of(inode->i_cdev, struct hwicap_drvdata,
> cdev);
> 	...
> 	file->private_data = drvdata;
> 
> Which would work if xgpio_instance directly contains the struct
> miscdevice.
> I think this is a much cleaner pattern (although it took me a while to
> figure out the magic that makes it work... )
> 
> > +static struct of_device_id xgpio_of_match[] = {
> > +	{.compatible = "xlnx,xps-gpio-1.00.a"},
> 
> This should also probably contain the corresponding strings for the
> following as well:
>       opb_gpio_v1_00_a
>       opb_gpio_v2_00_a
>       opb_gpio_v3_01_a
>       opb_gpio_v3_01_b
> 	plb_gpio_v1_00_b
> 
> This would seem to be a relatively easy driver to clean up (by pulling
> it all into one file and converting the other code to the kernel style)
> and submit to mainline, if you're interested?
> 
> Steve

^ permalink raw reply

* [PATCH -mm 3/4] x86_64 ia32 ptrace: use compat_ptrace_request for siginfo
From: Roland McGrath @ 2008-03-13  8:33 UTC (permalink / raw)
  To: Paul Mackerras, Anton Blanchard
  Cc: linuxppc-dev, Ingo Molnar, Thomas Gleixner, Andrew Morton,
	linux-kernel
In-Reply-To: <20080313083107.8BDE926F992@magilla.localdomain>


This removes the special-case handling for PTRACE_GETSIGINFO
and PTRACE_SETSIGINFO from x86_64's sys32_ptrace.  The generic
compat_ptrace_request code handles these.

Signed-off-by: Roland McGrath <roland@redhat.com>
---
 arch/x86/kernel/ptrace.c |   30 +-----------------------------
 1 files changed, 1 insertions(+), 29 deletions(-)

diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
index 77d9ddd..42305fa 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -1184,32 +1184,6 @@ static int genregs32_set(struct task_struct *target,
 	return ret;
 }
 
-static long ptrace32_siginfo(unsigned request, u32 pid, u32 addr, u32 data)
-{
-	siginfo_t __user *si = compat_alloc_user_space(sizeof(siginfo_t));
-	compat_siginfo_t __user *si32 = compat_ptr(data);
-	siginfo_t ssi;
-	int ret;
-
-	if (request == PTRACE_SETSIGINFO) {
-		memset(&ssi, 0, sizeof(siginfo_t));
-		ret = copy_siginfo_from_user32(&ssi, si32);
-		if (ret)
-			return ret;
-		if (copy_to_user(si, &ssi, sizeof(siginfo_t)))
-			return -EFAULT;
-	}
-	ret = sys_ptrace(request, pid, addr, (unsigned long)si);
-	if (ret)
-		return ret;
-	if (request == PTRACE_GETSIGINFO) {
-		if (copy_from_user(&ssi, si, sizeof(siginfo_t)))
-			return -EFAULT;
-		ret = copy_siginfo_to_user32(si32, &ssi);
-	}
-	return ret;
-}
-
 asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data)
 {
 	struct task_struct *child;
@@ -1255,11 +1229,9 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data)
 	case PTRACE_SETFPXREGS:
 	case PTRACE_GETFPXREGS:
 	case PTRACE_GETEVENTMSG:
-		break;
-
 	case PTRACE_SETSIGINFO:
 	case PTRACE_GETSIGINFO:
-		return ptrace32_siginfo(request, pid, addr, data);
+		break;
 	}
 
 	child = ptrace_get_task_struct(pid);

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox