[kernel] r13107 - in dists/trunk/linux-2.6/debian: . patches/features/arm patches/series

Martin Michlmayr tbm at alioth.debian.org
Sat Mar 14 10:03:39 UTC 2009


Author: tbm
Date: Sat Mar 14 10:03:37 2009
New Revision: 13107

Log:
Add patches from git.marvell.com to improve Kirkwood support


Added:
   dists/trunk/linux-2.6/debian/patches/features/arm/kw-mpp.patch
   dists/trunk/linux-2.6/debian/patches/features/arm/kw-register-internal-devices.patch
   dists/trunk/linux-2.6/debian/patches/features/arm/kw-register-sdio.patch
   dists/trunk/linux-2.6/debian/patches/features/arm/kw-sheevaplug-led.patch
   dists/trunk/linux-2.6/debian/patches/features/arm/kw-sheevaplug-usb-power.patch
   dists/trunk/linux-2.6/debian/patches/features/arm/kw-sheevaplug.patch
   dists/trunk/linux-2.6/debian/patches/features/arm/mv-sdio.patch
   dists/trunk/linux-2.6/debian/patches/features/arm/orion-gpio-input-output.patch
Modified:
   dists/trunk/linux-2.6/debian/changelog
   dists/trunk/linux-2.6/debian/patches/series/1~experimental.1

Modified: dists/trunk/linux-2.6/debian/changelog
==============================================================================
--- dists/trunk/linux-2.6/debian/changelog	(original)
+++ dists/trunk/linux-2.6/debian/changelog	Sat Mar 14 10:03:37 2009
@@ -57,6 +57,15 @@
   * [arm, armel] Enable various V4L USB devices. (Closes: #518582)
   * [arm/orion5x] Build the SENSORS_LM75 module since it's needed on the
     D-Link DNS-323.
+  * Add patches from git.marvell.com to improve Kirkwood support:
+    - Orion: make gpio /input/output validation separate
+    - Kirkwood: MPP initialization code
+    - SDIO driver for Marvell SoCs
+    - Kirkwood: SDIO driver registration for DB6281 and RD6281
+    - Kirkwood: register internal devices in a common place
+    - Kirkwood: Marvell SheevaPlug support
+    - Kirkwood: SheevaPlug USB Power Enable setup
+    - Kirkwood: SheevaPlug LED support
 
   [ Ben Hutchings ]
   * Remove firmware from drivers and make them use request_firmware():

Added: dists/trunk/linux-2.6/debian/patches/features/arm/kw-mpp.patch
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/features/arm/kw-mpp.patch	Sat Mar 14 10:03:37 2009
@@ -0,0 +1,436 @@
+From: Nicolas Pitre <nico at cam.org>
+Date: Sat, 31 Jan 2009 03:44:20 +0000 (-0500)
+Subject: [ARM] Kirkwood: MPP initialization code
+X-Git-Url: http://git.marvell.com/?p=orion.git;a=commitdiff_plain;h=0100defd2803f6c3df6bfd400a10af0cf9b8536a
+
+[ARM] Kirkwood: MPP initialization code
+
+This allows for board support code to set up their MPP config if the
+bootloader didn't do it all or did it wrong.  This also allows to
+register usable GPIOs.
+
+Signed-off-by: Nicolas Pitre <nico at marvell.com>
+---
+
+diff --git a/arch/arm/mach-kirkwood/Makefile b/arch/arm/mach-kirkwood/Makefile
+index b96c55d..fdff35c 100644
+--- a/arch/arm/mach-kirkwood/Makefile
++++ b/arch/arm/mach-kirkwood/Makefile
+@@ -1,4 +1,4 @@
+-obj-y				+= common.o addr-map.o irq.o pcie.o
++obj-y				+= common.o addr-map.o irq.o pcie.o mpp.o
+ 
+ obj-$(CONFIG_MACH_DB88F6281_BP)		+= db88f6281-bp-setup.o
+ obj-$(CONFIG_MACH_RD88F6192_NAS)	+= rd88f6192-nas-setup.o
+diff --git a/arch/arm/mach-kirkwood/mpp.c b/arch/arm/mach-kirkwood/mpp.c
+new file mode 100644
+index 0000000..63c4493
+--- /dev/null
++++ b/arch/arm/mach-kirkwood/mpp.c
+@@ -0,0 +1,97 @@
++/*
++ * arch/arm/mach-kirkwood/mpp.c
++ *
++ * MPP functions for Marvell Kirkwood SoCs
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2.  This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/mbus.h>
++#include <linux/io.h>
++#include <asm/gpio.h>
++#include <mach/hardware.h>
++#include "common.h"
++#include "mpp.h"
++
++static unsigned int __init kirkwood_variant(void)
++{
++	u32 dev, rev;
++
++	kirkwood_pcie_id(&dev, &rev);
++
++	if (dev == MV88F6281_DEV_ID && rev >= MV88F6281_REV_A0)
++		return MPP_F6281_MASK;
++	if (dev == MV88F6192_DEV_ID && rev >= MV88F6192_REV_A0)
++		return MPP_F6192_MASK;
++	if (dev == MV88F6180_DEV_ID)
++		return MPP_F6180_MASK;
++
++	printk(KERN_ERR "MPP setup: unknown kirkwood variant "
++			"(dev %#x rev %#x)\n", dev, rev);
++	return 0;
++}
++
++#define MPP_CTRL(i)	(DEV_BUS_VIRT_BASE + (i) * 4)
++#define MPP_NR_REGS	(1 + MPP_MAX/8)
++
++void __init kirkwood_mpp_conf(unsigned int *mpp_list)
++{
++	u32 mpp_ctrl[MPP_NR_REGS];
++	unsigned int variant_mask;
++	int i;
++
++	variant_mask = kirkwood_variant();
++	if (!variant_mask)
++		return;
++
++	printk(KERN_DEBUG "initial MPP regs:");
++	for (i = 0; i < MPP_NR_REGS; i++) {
++		mpp_ctrl[i] = readl(MPP_CTRL(i));
++		printk(" %08x", mpp_ctrl[i]);
++	}
++	printk("\n");
++
++	while (*mpp_list) {
++		unsigned int num = MPP_NUM(*mpp_list);
++		unsigned int sel = MPP_SEL(*mpp_list);
++		int shift, gpio_mode;
++
++		if (num > MPP_MAX) {
++			printk(KERN_ERR "kirkwood_mpp_conf: invalid MPP "
++					"number (%u)\n", num);
++			continue;
++		}
++		if (!(*mpp_list & variant_mask)) {
++			printk(KERN_WARNING
++			       "kirkwood_mpp_conf: requested MPP%u config "
++			       "unavailable on this hardware\n", num);
++			continue;
++		}
++
++		shift = (num & 7) << 2;
++		mpp_ctrl[num / 8] &= ~(0xf << shift);
++		mpp_ctrl[num / 8] |= sel << shift;
++
++		gpio_mode = 0;
++		if (*mpp_list & MPP_INPUT_MASK)
++			gpio_mode |= GPIO_INPUT_OK;
++		if (*mpp_list & MPP_OUTPUT_MASK)
++			gpio_mode |= GPIO_OUTPUT_OK;
++		if (sel != 0)
++			gpio_mode = 0;
++		orion_gpio_set_valid(num, gpio_mode);
++
++		mpp_list++;
++	}
++
++	printk(KERN_DEBUG "  final MPP regs:");
++	for (i = 0; i < MPP_NR_REGS; i++) {
++		writel(mpp_ctrl[i], MPP_CTRL(i));
++		printk(" %08x", mpp_ctrl[i]);
++	}
++	printk("\n");
++}
+diff --git a/arch/arm/mach-kirkwood/mpp.h b/arch/arm/mach-kirkwood/mpp.h
+new file mode 100644
+index 0000000..45cccb7
+--- /dev/null
++++ b/arch/arm/mach-kirkwood/mpp.h
+@@ -0,0 +1,303 @@
++/*
++ * linux/arch/arm/mach-kirkwood/mpp.h -- Multi Purpose Pins
++ *
++ * Copyright 2009: Marvell Technology Group Ltd.
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2.  This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#ifndef __KIRKWOOD_MPP_H
++#define __KIRKWOOD_MPP_H
++
++#define MPP(_num, _sel, _in, _out, _F6180, _F6190, _F6192, _F6281) ( \
++	/* MPP number */		((_num) & 0xff) | \
++	/* MPP select value */		(((_sel) & 0xf) << 8) | \
++	/* may be input signal */	((!!(_in)) << 12) | \
++	/* may be output signal */	((!!(_out)) << 13) | \
++	/* available on F6180 */	((!!(_F6180)) << 14) | \
++	/* available on F6190 */	((!!(_F6190)) << 15) | \
++	/* available on F6192 */	((!!(_F6192)) << 16) | \
++	/* available on F6281 */	((!!(_F6281)) << 17))
++
++#define MPP_NUM(x)	((x) & 0xff)
++#define MPP_SEL(x)	(((x) >> 8) & 0xf)
++
++				/*   num sel  i  o  6180 6190 6192 6281 */
++
++#define MPP_INPUT_MASK		MPP(  0, 0x0, 1, 0, 0,   0,   0,   0    )
++#define MPP_OUTPUT_MASK		MPP(  0, 0x0, 0, 1, 0,   0,   0,   0    )
++
++#define MPP_F6180_MASK		MPP(  0, 0x0, 0, 0, 1,   0,   0,   0    )
++#define MPP_F6190_MASK		MPP(  0, 0x0, 0, 0, 0,   1,   0,   0    )
++#define MPP_F6192_MASK		MPP(  0, 0x0, 0, 0, 0,   0,   1,   0    )
++#define MPP_F6281_MASK		MPP(  0, 0x0, 0, 0, 0,   0,   0,   1    )
++
++#define MPP0_GPIO		MPP(  0, 0x0, 1, 1, 1,   1,   1,   1    )
++#define MPP0_NF_IO2		MPP(  0, 0x1, 1, 1, 1,   1,   1,   1    )
++#define MPP0_SPI_SCn		MPP(  0, 0x2, 0, 1, 1,   1,   1,   1    )
++
++#define MPP1_GPO		MPP(  1, 0x0, 0, 1, 1,   1,   1,   1    )
++#define MPP1_NF_IO3		MPP(  1, 0x1, 1, 1, 1,   1,   1,   1    )
++#define MPP1_SPI_MOSI		MPP(  1, 0x2, 0, 1, 1,   1,   1,   1    )
++
++#define MPP2_GPO		MPP(  2, 0x0, 0, 1, 1,   1,   1,   1    )
++#define MPP2_NF_IO4		MPP(  2, 0x1, 1, 1, 1,   1,   1,   1    )
++#define MPP2_SPI_SCK		MPP(  2, 0x2, 0, 1, 1,   1,   1,   1    )
++
++#define MPP3_GPO		MPP(  3, 0x0, 0, 1, 1,   1,   1,   1    )
++#define MPP3_NF_IO5		MPP(  3, 0x1, 1, 1, 1,   1,   1,   1    )
++#define MPP3_SPI_MISO		MPP(  3, 0x2, 1, 0, 1,   1,   1,   1    )
++
++#define MPP4_GPIO		MPP(  4, 0x0, 1, 1, 1,   1,   1,   1    )
++#define MPP4_NF_IO6		MPP(  4, 0x1, 1, 1, 1,   1,   1,   1    )
++#define MPP4_UART0_RXD		MPP(  4, 0x2, 1, 0, 1,   1,   1,   1    )
++#define MPP4_SATA1_ACTn		MPP(  4, 0x5, 0, 1, 0,   0,   1,   1    )
++#define MPP4_PTP_CLK		MPP(  4, 0xd, 1, 0, 1,   1,   1,   1    )
++
++#define MPP5_GPO		MPP(  5, 0x0, 0, 1, 1,   1,   1,   1    )
++#define MPP5_NF_IO7		MPP(  5, 0x1, 1, 1, 1,   1,   1,   1    )
++#define MPP5_UART0_TXD		MPP(  5, 0x2, 0, 1, 1,   1,   1,   1    )
++#define MPP5_PTP_TRIG_GEN	MPP(  5, 0x4, 0, 1, 1,   1,   1,   1    )
++#define MPP5_SATA0_ACTn		MPP(  5, 0x5, 0, 1, 0,   1,   1,   1    )
++
++#define MPP6_SYSRST_OUTn	MPP(  6, 0x1, 0, 1, 1,   1,   1,   1    )
++#define MPP6_SPI_MOSI		MPP(  6, 0x2, 0, 1, 1,   1,   1,   1    )
++#define MPP6_PTP_TRIG_GEN	MPP(  6, 0x3, 0, 1, 1,   1,   1,   1    )
++
++#define MPP7_GPO		MPP(  7, 0x0, 0, 1, 1,   1,   1,   1    )
++#define MPP7_PEX_RST_OUTn	MPP(  7, 0x1, 0, 1, 1,   1,   1,   1    )
++#define MPP7_SPI_SCn		MPP(  7, 0x2, 0, 1, 1,   1,   1,   1    )
++#define MPP7_PTP_TRIG_GEN	MPP(  7, 0x3, 0, 1, 1,   1,   1,   1    )
++
++#define MPP8_GPIO		MPP(  8, 0x0, 1, 1, 1,    1,  1,   1    )
++#define MPP8_TW_SDA		MPP(  8, 0x1, 1, 1, 1,   1,   1,   1    )
++#define MPP8_UART0_RTS		MPP(  8, 0x2, 0, 1, 1,   1,   1,   1    )
++#define MPP8_UART1_RTS		MPP(  8, 0x3, 0, 1, 1,   1,   1,   1    )
++#define MPP8_MII0_RXERR		MPP(  8, 0x4, 1, 0, 0,   1,   1,   1    )
++#define MPP8_SATA1_PRESENTn	MPP(  8, 0x5, 0, 1, 0,   0,   1,   1    )
++#define MPP8_PTP_CLK		MPP(  8, 0xc, 1, 0, 1,   1,   1,   1    )
++#define MPP8_MII0_COL		MPP(  8, 0xd, 1, 0, 1,   1,   1,   1    )
++
++#define MPP9_GPIO		MPP(  9, 0x0, 1, 1, 1,   1,   1,   1    )
++#define MPP9_TW_SCK		MPP(  9, 0x1, 1, 1, 1,   1,   1,   1    )
++#define MPP9_UART0_CTS		MPP(  9, 0x2, 1, 0, 1,   1,   1,   1    )
++#define MPP9_UART1_CTS		MPP(  9, 0x3, 1, 0, 1,   1,   1,   1    )
++#define MPP9_SATA0_PRESENTn	MPP(  9, 0x5, 0, 1, 0,   1,   1,   1    )
++#define MPP9_PTP_EVENT_REQ	MPP(  9, 0xc, 1, 0, 1,   1,   1,   1    )
++#define MPP9_MII0_CRS		MPP(  9, 0xd, 1, 0, 1,   1,   1,   1    )
++
++#define MPP10_GPO		MPP( 10, 0x0, 0, 1, 1,   1,   1,   1    )
++#define MPP10_SPI_SCK		MPP( 10, 0x2, 0, 1, 1,   1,   1,   1    )
++#define MPP10_UArt0_TXD		MPP( 10, 0X3, 0, 1, 1,   1,   1,   1    )
++#define MPP10_SATA1_ACTn	MPP( 10, 0x5, 0, 1, 0,   0,   1,   1    )
++#define MPP10_PTP_TRIG_GEN	MPP( 10, 0xc, 0, 1, 1,   1,   1,   1    )
++
++#define MPP11_GPIO		MPP( 11, 0x0, 1, 1, 1,   1,   1,   1    )
++#define MPP11_SPI_MISO		MPP( 11, 0x2, 1, 0, 1,   1,   1,   1    )
++#define MPP11_UArt0_RXD		MPP( 11, 0x3, 1, 0, 1,   1,   1,   1    )
++#define MPP11_PTP_EVENT_REQ	MPP( 11, 0x4, 1, 0, 1,   1,   1,   1    )
++#define MPP11_PTP_TRIG_GEN	MPP( 11, 0xc, 0, 1, 1,   1,   1,   1    )
++#define MPP11_PTP_CLK		MPP( 11, 0xd, 1, 0, 1,   1,   1,   1    )
++#define MPP11_SATA0_ACTn	MPP( 11, 0x5, 0, 1, 0,   1,   1,   1    )
++
++#define MPP12_GPO		MPP( 12, 0x0, 0, 1, 1,   1,   1,   1    )
++#define MPP12_SD_CLK		MPP( 12, 0x1, 0, 1, 1,   1,   1,   1    )
++
++#define MPP13_GPIO		MPP( 13, 0x0, 1, 1, 1,   1,   1,   1    )
++#define MPP13_SD_CMD		MPP( 13, 0x1, 1, 1, 1,   1,   1,   1    )
++#define MPP13_UART1_TXD		MPP( 13, 0x3, 0, 1, 1,   1,   1,   1    )
++
++#define MPP14_GPIO		MPP( 14, 0x0, 1, 1, 1,   1,   1,   1    )
++#define MPP14_SD_D0		MPP( 14, 0x1, 1, 1, 1,   1,   1,   1    )
++#define MPP14_UART1_RXD		MPP( 14, 0x3, 1, 0, 1,   1,   1,   1    )
++#define MPP14_SATA1_PRESENTn	MPP( 14, 0x4, 0, 1, 0,   0,   1,   1    )
++#define MPP14_MII0_COL		MPP( 14, 0xd, 1, 0, 1,   1,   1,   1    )
++
++#define MPP15_GPIO		MPP( 15, 0x0, 1, 1, 1,   1,   1,   1    )
++#define MPP15_SD_D1		MPP( 15, 0x1, 1, 1, 1,   1,   1,   1    )
++#define MPP15_UART0_RTS		MPP( 15, 0x2, 0, 1, 1,   1,   1,   1    )
++#define MPP15_UART1_TXD		MPP( 15, 0x3, 0, 1, 1,   1,   1,   1    )
++#define MPP15_SATA0_ACTn	MPP( 15, 0x4, 0, 1, 0,   1,   1,   1    )
++
++#define MPP16_GPIO		MPP( 16, 0x0, 1, 1, 1,   1,   1,   1    )
++#define MPP16_SD_D2		MPP( 16, 0x1, 1, 1, 1,   1,   1,   1    )
++#define MPP16_UART0_CTS		MPP( 16, 0x2, 1, 0, 1,   1,   1,   1    )
++#define MPP16_UART1_RXD		MPP( 16, 0x3, 1, 0, 1,   1,   1,   1    )
++#define MPP16_SATA1_ACTn	MPP( 16, 0x4, 0, 1, 0,   0,   1,   1    )
++#define MPP16_MII0_CRS		MPP( 16, 0xd, 1, 0, 1,   1,   1,   1    )
++
++#define MPP17_GPIO		MPP( 17, 0x0, 1, 1, 1,   1,   1,   1    )
++#define MPP17_SD_D3		MPP( 17, 0x1, 1, 1, 1,   1,   1,   1    )
++#define MPP17_SATA0_PRESENTn	MPP( 17, 0x4, 0, 1, 0,   1,   1,   1    )
++
++#define MPP18_GPO		MPP( 18, 0x0, 0, 1, 1,   1,   1,   1    )
++#define MPP18_NF_IO0		MPP( 18, 0x1, 1, 1, 1,   1,   1,   1    )
++
++#define MPP19_GPO		MPP( 19, 0x0, 0, 1, 1,   1,   1,   1    )
++#define MPP19_NF_IO1		MPP( 19, 0x1, 1, 1, 1,   1,   1,   1    )
++
++#define MPP20_GPIO		MPP( 20, 0x0, 1, 1, 0,   1,   1,   1    )
++#define MPP20_TSMP0		MPP( 20, 0x1, 1, 1, 0,   0,   1,   1    )
++#define MPP20_TDM_CH0_TX_QL	MPP( 20, 0x2, 0, 1, 0,   0,   1,   1    )
++#define MPP20_GE1_0		MPP( 20, 0x3, 0, 0, 0,   1,   1,   1    )
++#define MPP20_AUDIO_SPDIFI	MPP( 20, 0x4, 1, 0, 0,   0,   1,   1    )
++#define MPP20_SATA1_ACTn	MPP( 20, 0x5, 0, 1, 0,   0,   1,   1    )
++
++#define MPP21_GPIO		MPP( 21, 0x0, 1, 1, 0,   1,   1,   1    )
++#define MPP21_TSMP1		MPP( 21, 0x1, 1, 1, 0,   0,   1,   1    )
++#define MPP21_TDM_CH0_RX_QL	MPP( 21, 0x2, 0, 1, 0,   0,   1,   1    )
++#define MPP21_GE1_1		MPP( 21, 0x3, 0, 0, 0,   1,   1,   1    )
++#define MPP21_AUDIO_SPDIFO	MPP( 21, 0x4, 0, 1, 0,   0,   1,   1    )
++#define MPP21_SATA0_ACTn	MPP( 21, 0x5, 0, 1, 0,   1,   1,   1    )
++
++#define MPP22_GPIO		MPP( 22, 0x0, 1, 1, 0,   1,   1,   1    )
++#define MPP22_TSMP2		MPP( 22, 0x1, 1, 1, 0,   0,   1,   1    )
++#define MPP22_TDM_CH2_TX_QL	MPP( 22, 0x2, 0, 1, 0,   0,   1,   1    )
++#define MPP22_GE1_2		MPP( 22, 0x3, 0, 0, 0,   1,   1,   1    )
++#define MPP22_AUDIO_SPDIFRMKCLK	MPP( 22, 0x4, 0, 1, 0,   0,   1,   1    )
++#define MPP22_SATA1_PRESENTn	MPP( 22, 0x5, 0, 1, 0,   0,   1,   1    )
++
++#define MPP23_GPIO		MPP( 23, 0x0, 1, 1, 0,   1,   1,   1    )
++#define MPP23_TSMP3		MPP( 23, 0x1, 1, 1, 0,   0,   1,   1    )
++#define MPP23_TDM_CH2_RX_QL	MPP( 23, 0x2, 1, 0, 0,   0,   1,   1    )
++#define MPP23_GE1_3		MPP( 23, 0x3, 0, 0, 0,   1,   1,   1    )
++#define MPP23_AUDIO_I2SBCLK	MPP( 23, 0x4, 0, 1, 0,   0,   1,   1    )
++#define MPP23_SATA0_PRESENTn	MPP( 23, 0x5, 0, 1, 0,   1,   1,   1    )
++
++#define MPP24_GPIO		MPP( 24, 0x0, 1, 1, 0,   1,   1,   1    )
++#define MPP24_TSMP4		MPP( 24, 0x1, 1, 1, 0,   0,   1,   1    )
++#define MPP24_TDM_SPI_CS0	DEV( 24, 0x2, 0, 1, 0,   0,   1,   1    )
++#define MPP24_GE1_4		MPP( 24, 0x3, 0, 0, 0,   1,   1,   1    )
++#define MPP24_AUDIO_I2SDO	MPP( 24, 0x4, 0, 1, 0,   0,   1,   1    )
++
++#define MPP25_GPIO		MPP( 25, 0x0, 1, 1, 0,   1,   1,   1    )
++#define MPP25_TSMP5		MPP( 25, 0x1, 1, 1, 0,   0,   1,   1    )
++#define MPP25_TDM_SPI_SCK	MPP( 25, 0x2, 0, 1, 0,   0,   1,   1    )
++#define MPP25_GE1_5		MPP( 25, 0x3, 0, 0, 0,   1,   1,   1    )
++#define MPP25_AUDIO_I2SLRCLK	MPP( 25, 0x4, 0, 1, 0,   0,   1,   1    )
++
++#define MPP26_GPIO		MPP( 26, 0x0, 1, 1, 0,   1,   1,   1    )
++#define MPP26_TSMP6		MPP( 26, 0x1, 1, 1, 0,   0,   1,   1    )
++#define MPP26_TDM_SPI_MISO	MPP( 26, 0x2, 1, 0, 0,   0,   1,   1    )
++#define MPP26_GE1_6		MPP( 26, 0x3, 0, 0, 0,   1,   1,   1    )
++#define MPP26_AUDIO_I2SMCLK	MPP( 26, 0x4, 0, 1, 0,   0,   1,   1    )
++
++#define MPP27_GPIO		MPP( 27, 0x0, 1, 1, 0,   1,   1,   1    )
++#define MPP27_TSMP7		MPP( 27, 0x1, 1, 1, 0,   0,   1,   1    )
++#define MPP27_TDM_SPI_MOSI	MPP( 27, 0x2, 0, 1, 0,   0,   1,   1    )
++#define MPP27_GE1_7		MPP( 27, 0x3, 0, 0, 0,   1,   1,   1    )
++#define MPP27_AUDIO_I2SDI	MPP( 27, 0x4, 1, 0, 0,   0,   1,   1    )
++
++#define MPP28_GPIO		MPP( 28, 0x0, 1, 1, 0,   1,   1,   1    )
++#define MPP28_TSMP8		MPP( 28, 0x1, 1, 1, 0,   0,   1,   1    )
++#define MPP28_TDM_CODEC_INTn	MPP( 28, 0x2, 0, 0, 0,   0,   1,   1    )
++#define MPP28_GE1_8		MPP( 28, 0x3, 0, 0, 0,   1,   1,   1    )
++#define MPP28_AUDIO_EXTCLK	MPP( 28, 0x4, 1, 0, 0,   0,   1,   1    )
++
++#define MPP29_GPIO		MPP( 29, 0x0, 1, 1, 0,   1,   1,   1    )
++#define MPP29_TSMP9		MPP( 29, 0x1, 1, 1, 0,   0,   1,   1    )
++#define MPP29_TDM_CODEC_RSTn	MPP( 29, 0x2, 0, 0, 0,   0,   1,   1    )
++#define MPP29_GE1_9		MPP( 29, 0x3, 0, 0, 0,   1,   1,   1    )
++
++#define MPP30_GPIO		MPP( 30, 0x0, 1, 1, 0,   1,   1,   1    )
++#define MPP30_TSMP10		MPP( 30, 0x1, 1, 1, 0,   0,   1,   1    )
++#define MPP30_TDM_PCLK		MPP( 30, 0x2, 1, 1, 0,   0,   1,   1    )
++#define MPP30_GE1_10		MPP( 30, 0x3, 0, 0, 0,   1,   1,   1    )
++
++#define MPP31_GPIO		MPP( 31, 0x0, 1, 1, 0,   1,   1,   1    )
++#define MPP31_TSMP11		MPP( 31, 0x1, 1, 1, 0,   0,   1,   1    )
++#define MPP31_TDM_FS		MPP( 31, 0x2, 1, 1, 0,   0,   1,   1    )
++#define MPP31_GE1_11		MPP( 31, 0x3, 0, 0, 0,   1,   1,   1    )
++
++#define MPP32_GPIO		MPP( 32, 0x0, 1, 1, 0,   1,   1,   1    )
++#define MPP32_TSMP12		MPP( 32, 0x1, 1, 1, 0,   0,   1,   1    )
++#define MPP32_TDM_DRX		MPP( 32, 0x2, 1, 0, 0,   0,   1,   1    )
++#define MPP32_GE1_12		MPP( 32, 0x3, 0, 0, 0,   1,   1,   1    )
++
++#define MPP33_GPIO		MPP( 33, 0x0, 1, 1, 0,   1,   1,   1    )
++#define MPP33_TDM_DTX		MPP( 33, 0x2, 0, 1, 0,   0,   1,   1    )
++#define MPP33_GE1_13		MPP( 33, 0x3, 0, 0, 0,   1,   1,   1    )
++
++#define MPP34_GPIO		MPP( 34, 0x0, 1, 1, 0,   1,   1,   1    )
++#define MPP34_TDM_SPI_CS1	MPP( 34, 0x2, 0, 1, 0,   0,   1,   1    )
++#define MPP34_GE1_14		MPP( 34, 0x3, 0, 0, 0,   1,   1,   1    )
++
++#define MPP35_GPIO		MPP( 35, 0x0, 1, 1, 1,   1,   1,   1    )
++#define MPP35_TDM_CH0_TX_QL	MPP( 35, 0x2, 0, 1, 0,   0,   1,   1    )
++#define MPP35_GE1_15		MPP( 35, 0x3, 0, 0, 0,   1,   1,   1    )
++#define MPP35_SATA0_ACTn	MPP( 35, 0x5, 0, 1, 0,   1,   1,   1    )
++#define MPP35_MII0_RXERR	MPP( 35, 0xc, 1, 0, 1,   1,   1,   1    )
++
++#define MPP36_GPIO		MPP( 36, 0x0, 1, 1, 1,   0,   0,   1    )
++#define MPP36_TSMP0		MPP( 36, 0x1, 1, 1, 0,   0,   0,   1    )
++#define MPP36_TDM_SPI_CS1	MPP( 36, 0x2, 0, 1, 0,   0,   0,   1    )
++#define MPP36_AUDIO_SPDIFI	MPP( 36, 0x4, 1, 0, 1,   0,   0,   1    )
++
++#define MPP37_GPIO		MPP( 37, 0x0, 1, 1, 1,   0,   0,   1    )
++#define MPP37_TSMP1		MPP( 37, 0x1, 1, 1, 0,   0,   0,   1    )
++#define MPP37_TDM_CH2_TX_QL	MPP( 37, 0x2, 0, 1, 0,   0,   0,   1    )
++#define MPP37_AUDIO_SPDIFO	MPP( 37, 0x4, 0, 1, 1,   0,   0,   1    )
++
++#define MPP38_GPIO		MPP( 38, 0x0, 1, 1, 1,   0,   0,   1    )
++#define MPP38_TSMP2		MPP( 38, 0x1, 1, 1, 0,   0,   0,   1    )
++#define MPP38_TDM_CH2_RX_QL	MPP( 38, 0x2, 0, 1, 0,   0,   0,   1    )
++#define MPP38_AUDIO_SPDIFRMLCLK	MPP( 38, 0x4, 0, 1, 1,   0,   0,   1    )
++
++#define MPP39_GPIO		MPP( 39, 0x0, 1, 1, 1,   0,   0,   1    )
++#define MPP39_TSMP3		MPP( 39, 0x1, 1, 1, 0,   0,   0,   1    )
++#define MPP39_TDM_SPI_CS0	MPP( 39, 0x2, 0, 1, 0,   0,   0,   1    )
++#define MPP39_AUDIO_I2SBCLK	MPP( 39, 0x4, 0, 1, 1,   0,   0,   1    )
++
++#define MPP40_GPIO		MPP( 40, 0x0, 1, 1, 1,   0,   0,   1    )
++#define MPP40_TSMP4		MPP( 40, 0x1, 1, 1, 0,   0,   0,   1    )
++#define MPP40_TDM_SPI_SCK	MPP( 40, 0x2, 0, 1, 0,   0,   0,   1    )
++#define MPP40_AUDIO_I2SDO	MPP( 40, 0x4, 0, 1, 1,   0,   0,   1    )
++
++#define MPP41_GPIO		MPP( 41, 0x0, 1, 1, 1,   0,   0,   1    )
++#define MPP41_TSMP5		MPP( 41, 0x1, 1, 1, 0,   0,   0,   1    )
++#define MPP41_TDM_SPI_MISO	MPP( 41, 0x2, 1, 0, 0,   0,   0,   1    )
++#define MPP41_AUDIO_I2SLRC	MPP( 41, 0x4, 0, 1, 1,   0,   0,   1    )
++
++#define MPP42_GPIO		MPP( 42, 0x0, 1, 1, 1,   0,   0,   1    )
++#define MPP42_TSMP6		MPP( 42, 0x1, 1, 1, 0,   0,   0,   1    )
++#define MPP42_TDM_SPI_MOSI	MPP( 42, 0x2, 0, 1, 0,   0,   0,   1    )
++#define MPP42_AUDIO_I2SMCLK	MPP( 42, 0x4, 0, 1, 1,   0,   0,   1    )
++
++#define MPP43_GPIO		MPP( 43, 0x0, 1, 1, 1,   0,   0,   1    )
++#define MPP43_TSMP7		MPP( 43, 0x1, 1, 1, 0,   0,   0,   1    )
++#define MPP43_TDM_CODEC_INTn	MPP( 43, 0x2, 0, 0, 0,   0,   0,   1    )
++#define MPP43_AUDIO_I2SDI	MPP( 43, 0x4, 1, 0, 1,   0,   0,   1    )
++
++#define MPP44_GPIO		MPP( 44, 0x0, 1, 1, 1,   0,   0,   1    )
++#define MPP44_TSMP8		MPP( 44, 0x1, 1, 1, 0,   0,   0,   1    )
++#define MPP44_TDM_CODEC_RSTn	MPP( 44, 0x2, 0, 0, 0,   0,   0,   1    )
++#define MPP44_AUDIO_EXTCLK	MPP( 44, 0x4, 1, 0, 1,   0,   0,   1    )
++
++#define MPP45_GPIO		MPP( 45, 0x0, 1, 1, 0,   0,   0,   1    )
++#define MPP45_TSMP9		MPP( 45, 0x1, 1, 1, 0,   0,   0,   1    )
++#define MPP45_TDM_PCLK		MPP( 45, 0x2, 1, 1, 0,   0,   0,   1    )
++
++#define MPP46_GPIO		MPP( 46, 0x0, 1, 1, 0,   0,   0,   1    )
++#define MPP46_TSMP10		MPP( 46, 0x1, 1, 1, 0,   0,   0,   1    )
++#define MPP46_TDM_FS		MPP( 46, 0x2, 1, 1, 0,   0,   0,   1    )
++
++#define MPP47_GPIO		MPP( 47, 0x0, 1, 1, 0,   0,   0,   1    )
++#define MPP47_TSMP11		MPP( 47, 0x1, 1, 1, 0,   0,   0,   1    )
++#define MPP47_TDM_DRX		MPP( 47, 0x2, 1, 0, 0,   0,   0,   1    )
++
++#define MPP48_GPIO		MPP( 48, 0x0, 1, 1, 0,   0,   0,   1    )
++#define MPP48_TSMP12		MPP( 48, 0x1, 1, 1, 0,   0,   0,   1    )
++#define MPP48_TDM_DTX		MPP( 48. 0x2, 0, 1, 0,   0,   0,   1    )
++
++#define MPP49_GPIO		MPP( 49, 0x0, 1, 1, 0,   0,   0,   1    )
++#define MPP49_TSMP9		MPP( 49, 0x1, 1, 1, 0,   0,   0,   1    )
++#define MPP49_TDM_CH0_RX_QL	MPP( 49, 0x2, 0, 1, 0,   0,   0,   1    )
++#define MPP49_PTP_CLK		MPP( 49, 0x5, 1, 0, 0,   0,   0,   1    )
++
++#define MPP_MAX			49
++
++void kirkwood_mpp_conf(unsigned int *mpp_list);
++
++#endif

Added: dists/trunk/linux-2.6/debian/patches/features/arm/kw-register-internal-devices.patch
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/features/arm/kw-register-internal-devices.patch	Sat Mar 14 10:03:37 2009
@@ -0,0 +1,114 @@
+From: Nicolas Pitre <nico at cam.org>
+Date: Fri, 27 Feb 2009 03:55:59 +0000 (-0500)
+Subject: [ARM] Kirkwood: register internal devices in a common place
+X-Git-Url: http://git.marvell.com/?p=orion.git;a=commitdiff_plain;h=5b99d5348304a32dfca92238d27ac4de2b365175
+
+[ARM] Kirkwood: register internal devices in a common place
+
+The RTC and the two XOR engines are internal to the chip, and therefore
+always available since they don't depend on a particular board layout.
+
+Signed-off-by: Nicolas Pitre <nico at marvell.com>
+---
+
+
+--- a/arch/arm/mach-kirkwood/rd88f6281-setup.c~	2009-03-14 08:03:45.000000000 +0000
++++ b/arch/arm/mach-kirkwood/rd88f6281-setup.c	2009-03-14 08:03:54.000000000 +0000
+@@ -124,7 +124,6 @@
+ 	}
+ 	kirkwood_ge00_switch_init(&rd88f6281_switch_data, NO_IRQ);
+ 
+-	kirkwood_rtc_init();
+ 	kirkwood_sata_init(&rd88f6281_sata_data);
+ 	kirkwood_sdio_init(&rd88f6281_mvsdio_data);
+ 	kirkwood_uart0_init();
+--- a/arch/arm/mach-kirkwood/db88f6281-bp-setup.c~	2009-03-14 08:03:32.000000000 +0000
++++ b/arch/arm/mach-kirkwood/db88f6281-bp-setup.c	2009-03-14 08:03:54.000000000 +0000
+@@ -55,7 +55,6 @@
+ 
+ 	kirkwood_ehci_init();
+ 	kirkwood_ge00_init(&db88f6281_ge00_data);
+-	kirkwood_rtc_init();
+ 	kirkwood_sata_init(&db88f6281_sata_data);
+ 	kirkwood_uart0_init();
+ 	kirkwood_sdio_init(&db88f6281_mvsdio_data);
+diff --git a/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c b/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c
+index b1d1a87..913ea94 100644
+--- a/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c
++++ b/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c
+@@ -61,14 +61,11 @@ static void __init rd88f6192_init(void)
+ 
+ 	kirkwood_ehci_init();
+ 	kirkwood_ge00_init(&rd88f6192_ge00_data);
+-	kirkwood_rtc_init();
+ 	kirkwood_sata_init(&rd88f6192_sata_data);
+ 	spi_register_board_info(rd88F6192_spi_slave_info,
+ 				ARRAY_SIZE(rd88F6192_spi_slave_info));
+ 	kirkwood_spi_init();
+ 	kirkwood_uart0_init();
+-	kirkwood_xor0_init();
+-	kirkwood_xor1_init();
+ }
+ 
+ static int __init rd88f6192_pci_init(void)
+
+diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c
+index e5076aa..9f01255 100644
+--- a/arch/arm/mach-kirkwood/common.c
++++ b/arch/arm/mach-kirkwood/common.c
+@@ -255,7 +255,7 @@ static struct resource kirkwood_rtc_resource = {
+ 	.flags	= IORESOURCE_MEM,
+ };
+ 
+-void __init kirkwood_rtc_init(void)
++static void __init kirkwood_rtc_init(void)
+ {
+ 	platform_device_register_simple("rtc-mv", -1, &kirkwood_rtc_resource, 1);
+ }
+@@ -547,7 +547,7 @@ static struct platform_device kirkwood_xor01_channel = {
+ 	},
+ };
+ 
+-void __init kirkwood_xor0_init(void)
++static void __init kirkwood_xor0_init(void)
+ {
+ 	platform_device_register(&kirkwood_xor0_shared);
+ 
+@@ -645,7 +645,7 @@ static struct platform_device kirkwood_xor11_channel = {
+ 	},
+ };
+ 
+-void __init kirkwood_xor1_init(void)
++static void __init kirkwood_xor1_init(void)
+ {
+ 	platform_device_register(&kirkwood_xor1_shared);
+ 
+@@ -753,4 +753,9 @@ void __init kirkwood_init(void)
+ #ifdef CONFIG_CACHE_FEROCEON_L2
+ 	kirkwood_l2_init();
+ #endif
++
++	/* internal devices that every board has */
++	kirkwood_rtc_init();
++	kirkwood_xor0_init();
++	kirkwood_xor1_init();
+ }
+diff --git a/arch/arm/mach-kirkwood/common.h b/arch/arm/mach-kirkwood/common.h
+index 5827940..9e52826 100644
+--- a/arch/arm/mach-kirkwood/common.h
++++ b/arch/arm/mach-kirkwood/common.h
+@@ -34,14 +34,11 @@ void kirkwood_ge00_init(struct mv643xx_eth_platform_data *eth_data);
+ void kirkwood_ge01_init(struct mv643xx_eth_platform_data *eth_data);
+ void kirkwood_ge00_switch_init(struct dsa_platform_data *d, int irq);
+ void kirkwood_pcie_init(void);
+-void kirkwood_rtc_init(void);
+ void kirkwood_sata_init(struct mv_sata_platform_data *sata_data);
+ void kirkwood_sdio_init(struct mvsdio_platform_data *mvsdio_data);
+ void kirkwood_spi_init(void);
+ void kirkwood_uart0_init(void);
+ void kirkwood_uart1_init(void);
+-void kirkwood_xor0_init(void);
+-void kirkwood_xor1_init(void);
+ 
+ extern struct sys_timer kirkwood_timer;
+ 

Added: dists/trunk/linux-2.6/debian/patches/features/arm/kw-register-sdio.patch
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/features/arm/kw-register-sdio.patch	Sat Mar 14 10:03:37 2009
@@ -0,0 +1,198 @@
+From: Nicolas Pitre <nico at cam.org>
+Date: Sat, 14 Feb 2009 08:15:55 +0000 (-0500)
+Subject: [ARM] Kirkwood: SDIO driver registration for DB6281 and RD6281
+X-Git-Url: http://git.marvell.com/?p=orion.git;a=commitdiff_plain;h=8235ee009cd839265f5dc2dace2758471a823e68
+
+[ARM] Kirkwood: SDIO driver registration for DB6281 and RD6281
+
+Signed-off-by: Nicolas Pitre <nico at marvell.com>
+---
+
+diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c
+index b3404b7..e5076aa 100644
+--- a/arch/arm/mach-kirkwood/common.c
++++ b/arch/arm/mach-kirkwood/common.c
+@@ -24,6 +24,7 @@
+ #include <mach/kirkwood.h>
+ #include <plat/cache-feroceon-l2.h>
+ #include <plat/ehci-orion.h>
++#include <plat/mvsdio.h>
+ #include <plat/mv_xor.h>
+ #include <plat/orion_nand.h>
+ #include <plat/time.h>
+@@ -296,6 +297,50 @@ void __init kirkwood_sata_init(struct mv_sata_platform_data *sata_data)
+ 
+ 
+ /*****************************************************************************
++ * SD/SDIO/MMC
++ ****************************************************************************/
++static struct resource mvsdio_resources[] = {
++	[0] = {
++		.start	= SDIO_PHYS_BASE,
++		.end	= SDIO_PHYS_BASE + SZ_1K - 1,
++		.flags	= IORESOURCE_MEM,
++	},
++	[1] = {
++		.start	= IRQ_KIRKWOOD_SDIO,
++		.end	= IRQ_KIRKWOOD_SDIO,
++		.flags	= IORESOURCE_IRQ,
++	},
++};
++
++static u64 mvsdio_dmamask = 0xffffffffUL;
++
++static struct platform_device kirkwood_sdio = {
++	.name		= "mvsdio",
++	.id		= -1,
++	.dev		= {
++		.dma_mask = &mvsdio_dmamask,
++		.coherent_dma_mask = 0xffffffff,
++	},
++	.num_resources	= ARRAY_SIZE(mvsdio_resources),
++	.resource	= mvsdio_resources,
++};
++
++void __init kirkwood_sdio_init(struct mvsdio_platform_data *mvsdio_data)
++{
++	u32 dev, rev;
++
++	kirkwood_pcie_id(&dev, &rev);
++	if (rev == 0)  /* catch all Kirkwood Z0's */
++		mvsdio_data->clock = 100000000;
++	else
++		mvsdio_data->clock = 200000000;
++	mvsdio_data->dram = &kirkwood_mbus_dram_info;
++	kirkwood_sdio.dev.platform_data = mvsdio_data;
++	platform_device_register(&kirkwood_sdio);
++}
++
++
++/*****************************************************************************
+  * SPI
+  ****************************************************************************/
+ static struct orion_spi_info kirkwood_spi_plat_data = {
+diff --git a/arch/arm/mach-kirkwood/common.h b/arch/arm/mach-kirkwood/common.h
+index fe367c1..5827940 100644
+--- a/arch/arm/mach-kirkwood/common.h
++++ b/arch/arm/mach-kirkwood/common.h
+@@ -14,6 +14,7 @@
+ struct dsa_platform_data;
+ struct mv643xx_eth_platform_data;
+ struct mv_sata_platform_data;
++struct mvsdio_platform_data;
+ 
+ /*
+  * Basic Kirkwood init functions used early by machine-setup.
+@@ -35,6 +36,7 @@ void kirkwood_ge00_switch_init(struct dsa_platform_data *d, int irq);
+ void kirkwood_pcie_init(void);
+ void kirkwood_rtc_init(void);
+ void kirkwood_sata_init(struct mv_sata_platform_data *sata_data);
++void kirkwood_sdio_init(struct mvsdio_platform_data *mvsdio_data);
+ void kirkwood_spi_init(void);
+ void kirkwood_uart0_init(void);
+ void kirkwood_uart1_init(void);
+diff --git a/arch/arm/mach-kirkwood/db88f6281-bp-setup.c b/arch/arm/mach-kirkwood/db88f6281-bp-setup.c
+index a14c294..5c3b40d 100644
+--- a/arch/arm/mach-kirkwood/db88f6281-bp-setup.c
++++ b/arch/arm/mach-kirkwood/db88f6281-bp-setup.c
+@@ -22,7 +22,9 @@
+ #include <asm/mach/arch.h>
+ #include <asm/mach/pci.h>
+ #include <mach/kirkwood.h>
++#include <plat/mvsdio.h>
+ #include "common.h"
++#include "mpp.h"
+ 
+ static struct mv643xx_eth_platform_data db88f6281_ge00_data = {
+ 	.phy_addr	= MV643XX_ETH_PHY_ADDR(8),
+@@ -32,18 +34,31 @@ static struct mv_sata_platform_data db88f6281_sata_data = {
+ 	.n_ports	= 2,
+ };
+ 
++static struct mvsdio_platform_data db88f6281_mvsdio_data = {
++	.gpio_write_protect	= 37,
++	.gpio_card_detect	= 38,
++};
++
++static unsigned int db88f6281_mpp_config[] __initdata = {
++	MPP37_GPIO,
++	MPP38_GPIO,
++	0
++};
++
+ static void __init db88f6281_init(void)
+ {
+ 	/*
+ 	 * Basic setup. Needs to be called early.
+ 	 */
+ 	kirkwood_init();
++	kirkwood_mpp_conf(db88f6281_mpp_config);
+ 
+ 	kirkwood_ehci_init();
+ 	kirkwood_ge00_init(&db88f6281_ge00_data);
+ 	kirkwood_rtc_init();
+ 	kirkwood_sata_init(&db88f6281_sata_data);
+ 	kirkwood_uart0_init();
++	kirkwood_sdio_init(&db88f6281_mvsdio_data);
+ }
+ 
+ static int __init db88f6281_pci_init(void)
+diff --git a/arch/arm/mach-kirkwood/include/mach/kirkwood.h b/arch/arm/mach-kirkwood/include/mach/kirkwood.h
+index ada480c..d3db30f 100644
+--- a/arch/arm/mach-kirkwood/include/mach/kirkwood.h
++++ b/arch/arm/mach-kirkwood/include/mach/kirkwood.h
+@@ -116,5 +116,7 @@
+ 
+ #define SATA_PHYS_BASE		(KIRKWOOD_REGS_PHYS_BASE | 0x80000)
+ 
++#define SDIO_PHYS_BASE		(KIRKWOOD_REGS_PHYS_BASE | 0x90000)
++
+ 
+ #endif
+diff --git a/arch/arm/mach-kirkwood/rd88f6281-setup.c b/arch/arm/mach-kirkwood/rd88f6281-setup.c
+index a1ef8a9..a8b88a5 100644
+--- a/arch/arm/mach-kirkwood/rd88f6281-setup.c
++++ b/arch/arm/mach-kirkwood/rd88f6281-setup.c
+@@ -24,8 +24,10 @@
+ #include <asm/mach/arch.h>
+ #include <asm/mach/pci.h>
+ #include <mach/kirkwood.h>
++#include <plat/mvsdio.h>
+ #include <plat/orion_nand.h>
+ #include "common.h"
++#include "mpp.h"
+ 
+ static struct mtd_partition rd88f6281_nand_parts[] = {
+ 	{
+@@ -91,6 +93,15 @@ static struct mv_sata_platform_data rd88f6281_sata_data = {
+ 	.n_ports	= 2,
+ };
+ 
++static struct mvsdio_platform_data rd88f6281_mvsdio_data = {
++	.gpio_card_detect = 28,
++};
++
++static unsigned int rd88f6281_mpp_config[] __initdata = {
++	MPP28_GPIO,
++	0
++};
++
+ static void __init rd88f6281_init(void)
+ {
+ 	u32 dev, rev;
+@@ -99,6 +110,7 @@ static void __init rd88f6281_init(void)
+ 	 * Basic setup. Needs to be called early.
+ 	 */
+ 	kirkwood_init();
++	kirkwood_mpp_conf(rd88f6281_mpp_config);
+ 
+ 	kirkwood_ehci_init();
+ 
+@@ -114,6 +126,7 @@
+ 
+ 	kirkwood_rtc_init();
+ 	kirkwood_sata_init(&rd88f6281_sata_data);
++	kirkwood_sdio_init(&rd88f6281_mvsdio_data);
+ 	kirkwood_uart0_init();
+ 
+ 	platform_device_register(&rd88f6281_nand_flash);

Added: dists/trunk/linux-2.6/debian/patches/features/arm/kw-sheevaplug-led.patch
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/features/arm/kw-sheevaplug-led.patch	Sat Mar 14 10:03:37 2009
@@ -0,0 +1,62 @@
+From: Nicolas Pitre <nico at cam.org>
+Date: Tue, 3 Mar 2009 06:16:07 +0000 (-0500)
+Subject: [ARM] Kirkwood: SheevaPlug LED support
+X-Git-Url: http://git.marvell.com/?p=orion.git;a=commitdiff_plain;h=efd8c1bb08a981f0e6581aedb7a842924816a78c
+
+[ARM] Kirkwood: SheevaPlug LED support
+
+Signed-off-by: Nicolas Pitre <nico at marvell.com>
+---
+
+diff --git a/arch/arm/mach-kirkwood/sheevaplug-setup.c b/arch/arm/mach-kirkwood/sheevaplug-setup.c
+index c1cb9f4..831e4a5 100644
+--- a/arch/arm/mach-kirkwood/sheevaplug-setup.c
++++ b/arch/arm/mach-kirkwood/sheevaplug-setup.c
+@@ -15,6 +15,7 @@
+ #include <linux/mtd/partitions.h>
+ #include <linux/mv643xx_eth.h>
+ #include <linux/gpio.h>
++#include <linux/leds.h>
+ #include <asm/mach-types.h>
+ #include <asm/mach/arch.h>
+ #include <mach/kirkwood.h>
+@@ -73,8 +74,31 @@ static struct mvsdio_platform_data sheevaplug_mvsdio_data = {
+ 	// unfortunately the CD signal has not been connected */
+ };
+ 
++static struct gpio_led sheevaplug_led_pins[] = {
++	{
++		.name			= "plug:green:health",
++		.default_trigger	= "default-on",
++		.gpio			= 49,
++		.active_low		= 1,
++	},
++};
++
++static struct gpio_led_platform_data sheevaplug_led_data = {
++	.leds		= sheevaplug_led_pins,
++	.num_leds	= ARRAY_SIZE(sheevaplug_led_pins),
++};
++
++static struct platform_device sheevaplug_leds = {
++	.name	= "leds-gpio",
++	.id	= -1,
++	.dev	= {
++		.platform_data	= &sheevaplug_led_data,
++	}
++};
++
+ static unsigned int sheevaplug_mpp_config[] __initdata = {
+ 	MPP29_GPIO,	/* USB Power Enable */
++	MPP49_GPIO,	/* LED */
+ 	0
+ };
+ 
+@@ -97,6 +121,7 @@ static void __init sheevaplug_init(void)
+ 	kirkwood_sdio_init(&sheevaplug_mvsdio_data);
+ 
+ 	platform_device_register(&sheevaplug_nand_flash);
++	platform_device_register(&sheevaplug_leds);
+ }
+ 
+ MACHINE_START(SHEEVAPLUG, "Marvell SheevaPlug Reference Board")

Added: dists/trunk/linux-2.6/debian/patches/features/arm/kw-sheevaplug-usb-power.patch
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/features/arm/kw-sheevaplug-usb-power.patch	Sat Mar 14 10:03:37 2009
@@ -0,0 +1,59 @@
+From: Nicolas Pitre <nico at cam.org>
+Date: Tue, 3 Mar 2009 04:44:41 +0000 (-0500)
+Subject: [ARM] Kirkwood: SheevaPlug USB Power Enable setup
+X-Git-Url: http://git.marvell.com/?p=orion.git;a=commitdiff_plain;h=3361de48dd360be04f02f0ebda969b15835ed39f
+
+[ARM] Kirkwood: SheevaPlug USB Power Enable setup
+
+Ideally, the default should be set to 0 and let the EHCI driver turn
+it on as needed.  This makes USB usable in the mean time.
+
+Signed-off-by: Nicolas Pitre <nico at marvell.com>
+---
+
+diff --git a/arch/arm/mach-kirkwood/sheevaplug-setup.c b/arch/arm/mach-kirkwood/sheevaplug-setup.c
+index d48989d..c1cb9f4 100644
+--- a/arch/arm/mach-kirkwood/sheevaplug-setup.c
++++ b/arch/arm/mach-kirkwood/sheevaplug-setup.c
+@@ -14,12 +14,14 @@
+ #include <linux/mtd/nand.h>
+ #include <linux/mtd/partitions.h>
+ #include <linux/mv643xx_eth.h>
++#include <linux/gpio.h>
+ #include <asm/mach-types.h>
+ #include <asm/mach/arch.h>
+ #include <mach/kirkwood.h>
+ #include <plat/mvsdio.h>
+ #include <plat/orion_nand.h>
+ #include "common.h"
++#include "mpp.h"
+ 
+ static struct mtd_partition sheevaplug_nand_parts[] = {
+ 	{
+@@ -71,15 +73,26 @@ static struct mvsdio_platform_data sheevaplug_mvsdio_data = {
+ 	// unfortunately the CD signal has not been connected */
+ };
+ 
++static unsigned int sheevaplug_mpp_config[] __initdata = {
++	MPP29_GPIO,	/* USB Power Enable */
++	0
++};
++
+ static void __init sheevaplug_init(void)
+ {
+ 	/*
+ 	 * Basic setup. Needs to be called early.
+ 	 */
+ 	kirkwood_init();
++	kirkwood_mpp_conf(sheevaplug_mpp_config);
+ 
+ 	kirkwood_uart0_init();
++
++	if (gpio_request(29, "USB Power Enable") != 0 ||
++	    gpio_direction_output(29, 1) != 0)
++		printk(KERN_ERR "can't set up GPIO 29 (USB Power Enable)\n");
+ 	kirkwood_ehci_init();
++
+ 	kirkwood_ge00_init(&sheevaplug_ge00_data);
+ 	kirkwood_sdio_init(&sheevaplug_mvsdio_data);
+ 

Added: dists/trunk/linux-2.6/debian/patches/features/arm/kw-sheevaplug.patch
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/features/arm/kw-sheevaplug.patch	Sat Mar 14 10:03:37 2009
@@ -0,0 +1,149 @@
+From: Shadi Ammouri <shadi at marvell.com>
+Date: Tue, 24 Feb 2009 20:26:23 +0000 (-0500)
+Subject: [ARM] Kirkwood: Marvell SheevaPlug support
+X-Git-Url: http://git.marvell.com/?p=orion.git;a=commitdiff_plain;h=cb418a5633f257755359347055f8b76e1524f585
+
+[ARM] Kirkwood: Marvell SheevaPlug support
+
+Signed-off-by: Nicolas Pitre <nico at marvell.com>
+---
+
+diff --git a/arch/arm/mach-kirkwood/Kconfig b/arch/arm/mach-kirkwood/Kconfig
+index 3600cd9..5324436 100644
+--- a/arch/arm/mach-kirkwood/Kconfig
++++ b/arch/arm/mach-kirkwood/Kconfig
+@@ -20,6 +20,12 @@ config MACH_RD88F6281
+ 	  Say 'Y' here if you want your kernel to support the
+ 	  Marvell RD-88F6281 Reference Board.
+ 
++config MACH_SHEEVAPLUG
++	bool "Marvell SheevaPlug Reference Board"
++	help
++	  Say 'Y' here if you want your kernel to support the
++	  Marvell SheevaPlug Reference Board.
++
+ endmenu
+ 
+ endif
+diff --git a/arch/arm/mach-kirkwood/Makefile b/arch/arm/mach-kirkwood/Makefile
+index fdff35c..de81b4b 100644
+--- a/arch/arm/mach-kirkwood/Makefile
++++ b/arch/arm/mach-kirkwood/Makefile
+@@ -3,3 +3,4 @@ obj-y				+= common.o addr-map.o irq.o pcie.o mpp.o
+ obj-$(CONFIG_MACH_DB88F6281_BP)		+= db88f6281-bp-setup.o
+ obj-$(CONFIG_MACH_RD88F6192_NAS)	+= rd88f6192-nas-setup.o
+ obj-$(CONFIG_MACH_RD88F6281)		+= rd88f6281-setup.o
++obj-$(CONFIG_MACH_SHEEVAPLUG)		+= sheevaplug-setup.o
+diff --git a/arch/arm/mach-kirkwood/sheevaplug-setup.c b/arch/arm/mach-kirkwood/sheevaplug-setup.c
+new file mode 100644
+index 0000000..d48989d
+--- /dev/null
++++ b/arch/arm/mach-kirkwood/sheevaplug-setup.c
+@@ -0,0 +1,98 @@
++/*
++ * arch/arm/mach-kirkwood/sheevaplug-setup.c
++ *
++ * Marvell SheevaPlug Reference Board Setup
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2.  This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/mtd/nand.h>
++#include <linux/mtd/partitions.h>
++#include <linux/mv643xx_eth.h>
++#include <asm/mach-types.h>
++#include <asm/mach/arch.h>
++#include <mach/kirkwood.h>
++#include <plat/mvsdio.h>
++#include <plat/orion_nand.h>
++#include "common.h"
++
++static struct mtd_partition sheevaplug_nand_parts[] = {
++	{
++		.name = "u-boot",
++		.offset = 0,
++		.size = SZ_1M
++	}, {
++		.name = "uImage",
++		.offset = MTDPART_OFS_NXTBLK,
++		.size = SZ_4M
++	}, {
++		.name = "root",
++		.offset = MTDPART_OFS_NXTBLK,
++		.size = MTDPART_SIZ_FULL
++	},
++};
++
++static struct resource sheevaplug_nand_resource = {
++	.flags		= IORESOURCE_MEM,
++	.start		= KIRKWOOD_NAND_MEM_PHYS_BASE,
++	.end		= KIRKWOOD_NAND_MEM_PHYS_BASE +
++			  KIRKWOOD_NAND_MEM_SIZE - 1,
++};
++
++static struct orion_nand_data sheevaplug_nand_data = {
++	.parts		= sheevaplug_nand_parts,
++	.nr_parts	= ARRAY_SIZE(sheevaplug_nand_parts),
++	.cle		= 0,
++	.ale		= 1,
++	.width		= 8,
++	.chip_delay	= 25,
++};
++
++static struct platform_device sheevaplug_nand_flash = {
++	.name		= "orion_nand",
++	.id		= -1,
++	.dev		= {
++		.platform_data	= &sheevaplug_nand_data,
++	},
++	.resource	= &sheevaplug_nand_resource,
++	.num_resources	= 1,
++};
++
++static struct mv643xx_eth_platform_data sheevaplug_ge00_data = {
++	.phy_addr	= MV643XX_ETH_PHY_ADDR(0),
++};
++
++static struct mvsdio_platform_data sheevaplug_mvsdio_data = {
++	// unfortunately the CD signal has not been connected */
++};
++
++static void __init sheevaplug_init(void)
++{
++	/*
++	 * Basic setup. Needs to be called early.
++	 */
++	kirkwood_init();
++
++	kirkwood_uart0_init();
++	kirkwood_ehci_init();
++	kirkwood_ge00_init(&sheevaplug_ge00_data);
++	kirkwood_sdio_init(&sheevaplug_mvsdio_data);
++
++	platform_device_register(&sheevaplug_nand_flash);
++}
++
++MACHINE_START(SHEEVAPLUG, "Marvell SheevaPlug Reference Board")
++	/* Maintainer: shadi Ammouri <shadi at marvell.com> */
++	.phys_io	= KIRKWOOD_REGS_PHYS_BASE,
++	.io_pg_offst	= ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
++	.boot_params	= 0x00000100,
++	.init_machine	= sheevaplug_init,
++	.map_io		= kirkwood_map_io,
++	.init_irq	= kirkwood_init_irq,
++	.timer		= &kirkwood_timer,
++MACHINE_END
+diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
+index fd23c0e..1fbfcac 100644
+--- a/arch/arm/tools/mach-types
++++ b/arch/arm/tools/mach-types
+@@ -1994,3 +1994,4 @@ benzina			MACH_BENZINA		BENZINA			2003
+ blaze			MACH_BLAZE		BLAZE			2004
+ linkstation_ls_hgl	MACH_LINKSTATION_LS_HGL	LINKSTATION_LS_HGL	2005
+ htcvenus		MACH_HTCVENUS		HTCVENUS		2006
++sheevaplug		MACH_SHEEVAPLUG		SHEEVAPLUG		2097

Added: dists/trunk/linux-2.6/debian/patches/features/arm/mv-sdio.patch
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/features/arm/mv-sdio.patch	Sat Mar 14 10:03:37 2009
@@ -0,0 +1,1158 @@
+From: Maen Suleiman <maen at marvell.com>
+Date: Sat, 14 Feb 2009 08:07:26 +0000 (-0500)
+Subject: [MMC] SDIO driver for Marvell SoCs
+X-Git-Url: http://git.marvell.com/?p=orion.git;a=commitdiff_plain;h=4c4f07fb0d12809cdc6a1e3ebf948c00188d8cf9
+
+[MMC] SDIO driver for Marvell SoCs
+
+This supports MMC/SD/SDIO currently found on the Kirkwood 88F6281 and
+88F6192 SoC controllers.
+
+Signed-off-by: Nicolas Pitre <nico at marvell.com>
+---
+
+diff --git a/arch/arm/plat-orion/include/plat/mvsdio.h b/arch/arm/plat-orion/include/plat/mvsdio.h
+new file mode 100644
+index 0000000..14ca886
+--- /dev/null
++++ b/arch/arm/plat-orion/include/plat/mvsdio.h
+@@ -0,0 +1,21 @@
++/*
++ * arch/arm/plat-orion/include/plat/mvsdio.h
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2.  This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#ifndef __MACH_MVSDIO_H
++#define __MACH_MVSDIO_H
++
++#include <linux/mbus.h>
++
++struct mvsdio_platform_data {
++	struct mbus_dram_target_info *dram;
++	unsigned int clock;
++	int gpio_card_detect;
++	int gpio_write_protect;
++};
++
++#endif
+diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
+index 99d4b28..092baf6 100644
+--- a/drivers/mmc/host/Kconfig
++++ b/drivers/mmc/host/Kconfig
+@@ -171,6 +171,17 @@ config MMC_TIFM_SD
+           To compile this driver as a module, choose M here: the
+ 	  module will be called tifm_sd.
+ 
++config MMC_MVSDIO
++	tristate "Marvell MMC/SD/SDIO host driver"
++	depends on PLAT_ORION
++	---help---
++	  This selects the Marvell SDIO host driver.
++	  SDIO may currently be found on the Kirkwood 88F6281 and 88F6192
++	  SoC controllers.
++
++	  To compile this driver as a module, choose M here: the
++	  module will be called mvsdio.
++
+ config MMC_SPI
+ 	tristate "MMC/SD/SDIO over SPI"
+ 	depends on SPI_MASTER && !HIGHMEM && HAS_DMA
+diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
+index dedec55..c006eb4 100644
+--- a/drivers/mmc/host/Makefile
++++ b/drivers/mmc/host/Makefile
+@@ -20,6 +20,7 @@ obj-$(CONFIG_MMC_OMAP_HS)	+= omap_hsmmc.o
+ obj-$(CONFIG_MMC_AT91)		+= at91_mci.o
+ obj-$(CONFIG_MMC_ATMELMCI)	+= atmel-mci.o
+ obj-$(CONFIG_MMC_TIFM_SD)	+= tifm_sd.o
++obj-$(CONFIG_MMC_MVSDIO)	+= mvsdio.o
+ obj-$(CONFIG_MMC_SPI)		+= mmc_spi.o
+ ifeq ($(CONFIG_OF),y)
+ obj-$(CONFIG_MMC_SPI)		+= of_mmc_spi.o
+diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c
+new file mode 100644
+index 0000000..e4d69d8
+--- /dev/null
++++ b/drivers/mmc/host/mvsdio.c
+@@ -0,0 +1,882 @@
++/*
++ * Marvell MMC/SD/SDIO driver
++ *
++ * Authors: Maen Suleiman, Nicolas Pitre
++ * Copyright (C) 2008-2009 Marvell Ltd.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/io.h>
++#include <linux/platform_device.h>
++#include <linux/mbus.h>
++#include <linux/delay.h>
++#include <linux/interrupt.h>
++#include <linux/dma-mapping.h>
++#include <linux/scatterlist.h>
++#include <linux/irq.h>
++#include <linux/gpio.h>
++#include <linux/mmc/host.h>
++
++#include <asm/sizes.h>
++#include <asm/unaligned.h>
++#include <plat/mvsdio.h>
++
++#include "mvsdio.h"
++
++#define DRIVER_NAME	"mvsdio"
++
++static int maxfreq = MVSD_CLOCKRATE_MAX;
++static int nodma;
++
++struct mvsd_host {
++	void __iomem *base;
++	struct mmc_request *mrq;
++	spinlock_t lock;
++	unsigned int xfer_mode;
++	unsigned int intr_en;
++	unsigned int ctrl;
++	unsigned int pio_size;
++	void *pio_ptr;
++	unsigned int sg_frags;
++	unsigned int ns_per_clk;
++	unsigned int clock;
++	unsigned int base_clock;
++	struct timer_list timer;
++	struct mmc_host *mmc;
++	struct device *dev;
++	struct resource *res;
++	int irq;
++	int gpio_card_detect;
++	int gpio_write_protect;
++};
++
++#define mvsd_write(offs, val)	writel(val, iobase + (offs))
++#define mvsd_read(offs)		readl(iobase + (offs))
++
++static int mvsd_setup_data(struct mvsd_host *host, struct mmc_data *data)
++{
++	void __iomem *iobase = host->base;
++	unsigned int tmout;
++	int tmout_index;
++
++	/* If timeout=0 then maximum timeout index is used. */
++	tmout = DIV_ROUND_UP(data->timeout_ns, host->ns_per_clk);
++	tmout += data->timeout_clks;
++	tmout_index = fls(tmout - 1) - 12;
++	if (tmout_index < 0)
++		tmout_index = 0;
++	if (tmout_index > MVSD_HOST_CTRL_TMOUT_MAX)
++		tmout_index = MVSD_HOST_CTRL_TMOUT_MAX;
++
++	dev_dbg(host->dev, "data %s at 0x%08x: blocks=%d blksz=%d tmout=%u (%d)\n",
++		(data->flags & MMC_DATA_READ) ? "read" : "write",
++		(u32)sg_virt(data->sg), data->blocks, data->blksz,
++		tmout, tmout_index);
++
++	host->ctrl &= ~MVSD_HOST_CTRL_TMOUT_MASK;
++	host->ctrl |= MVSD_HOST_CTRL_TMOUT(tmout_index);
++	mvsd_write(MVSD_HOST_CTRL, host->ctrl);
++	mvsd_write(MVSD_BLK_COUNT, data->blocks);
++	mvsd_write(MVSD_BLK_SIZE, data->blksz);
++
++	if (nodma || (data->blksz | data->sg->offset) & 3) {
++		/*
++		 * We cannot do DMA on a buffer which offset or size
++		 * is not aligned on a 4-byte boundary.
++		 */
++		host->pio_size = data->blocks * data->blksz;
++		host->pio_ptr = sg_virt(data->sg);
++		if (!nodma)
++			printk(KERN_DEBUG "%s: fallback to PIO for data "
++					  "at 0x%p size %d\n",
++					  mmc_hostname(host->mmc),
++					  host->pio_ptr, host->pio_size);
++		return 1;
++	} else {
++		dma_addr_t phys_addr;
++		int dma_dir = (data->flags & MMC_DATA_READ) ?
++			DMA_FROM_DEVICE : DMA_TO_DEVICE;
++		host->sg_frags = dma_map_sg(mmc_dev(host->mmc), data->sg,
++					    data->sg_len, dma_dir);
++		phys_addr = sg_dma_address(data->sg);
++		mvsd_write(MVSD_SYS_ADDR_LOW, (u32)phys_addr & 0xffff);
++		mvsd_write(MVSD_SYS_ADDR_HI,  (u32)phys_addr >> 16);
++		return 0;
++	}
++}
++
++static void mvsd_request(struct mmc_host *mmc, struct mmc_request *mrq)
++{
++	struct mvsd_host *host = mmc_priv(mmc);
++	void __iomem *iobase = host->base;
++	struct mmc_command *cmd = mrq->cmd;
++	u32 cmdreg = 0, xfer = 0, intr = 0;
++	unsigned long flags;
++
++	BUG_ON(host->mrq != NULL);
++	host->mrq = mrq;
++
++	dev_dbg(host->dev, "cmd %d (hw state 0x%04x)\n",
++		cmd->opcode, mvsd_read(MVSD_HW_STATE));
++
++	cmdreg = MVSD_CMD_INDEX(cmd->opcode);
++
++	if (cmd->flags & MMC_RSP_BUSY)
++		cmdreg |= MVSD_CMD_RSP_48BUSY;
++	else if (cmd->flags & MMC_RSP_136)
++		cmdreg |= MVSD_CMD_RSP_136;
++	else if (cmd->flags & MMC_RSP_PRESENT)
++		cmdreg |= MVSD_CMD_RSP_48;
++	else
++		cmdreg |= MVSD_CMD_RSP_NONE;
++
++	if (cmd->flags & MMC_RSP_CRC)
++		cmdreg |= MVSD_CMD_CHECK_CMDCRC;
++
++	if (cmd->flags & MMC_RSP_OPCODE)
++		cmdreg |= MVSD_CMD_INDX_CHECK;
++
++	if (cmd->flags & MMC_RSP_PRESENT) {
++		cmdreg |= MVSD_UNEXPECTED_RESP;
++		intr |= MVSD_NOR_UNEXP_RSP;
++	}
++
++	if (mrq->data) {
++		struct mmc_data *data = mrq->data;
++		int pio;
++
++		cmdreg |= MVSD_CMD_DATA_PRESENT | MVSD_CMD_CHECK_DATACRC16;
++		xfer |= MVSD_XFER_MODE_HW_WR_DATA_EN;
++		if (data->flags & MMC_DATA_READ)
++			xfer |= MVSD_XFER_MODE_TO_HOST;
++
++		pio = mvsd_setup_data(host, data);
++		if (pio) {
++			xfer |= MVSD_XFER_MODE_PIO;
++			/* PIO section of mvsd_irq has comments on those bits */
++			if (data->flags & MMC_DATA_WRITE)
++				intr |= MVSD_NOR_TX_AVAIL;
++			else if (host->pio_size > 32)
++				intr |= MVSD_NOR_RX_FIFO_8W;
++			else
++				intr |= MVSD_NOR_RX_READY;
++		}
++
++		if (data->stop) {
++			struct mmc_command *stop = data->stop;
++			u32 cmd12reg = 0;
++
++			mvsd_write(MVSD_AUTOCMD12_ARG_LOW, stop->arg & 0xffff);
++			mvsd_write(MVSD_AUTOCMD12_ARG_HI,  stop->arg >> 16);
++
++			if (stop->flags & MMC_RSP_BUSY)
++				cmd12reg |= MVSD_AUTOCMD12_BUSY;
++			if (stop->flags & MMC_RSP_OPCODE)
++				cmd12reg |= MVSD_AUTOCMD12_INDX_CHECK;
++			cmd12reg |= MVSD_AUTOCMD12_INDEX(stop->opcode);
++			mvsd_write(MVSD_AUTOCMD12_CMD, cmd12reg);
++
++			xfer |= MVSD_XFER_MODE_AUTO_CMD12;
++			intr |= MVSD_NOR_AUTOCMD12_DONE;
++		} else {
++			intr |= MVSD_NOR_XFER_DONE;
++		}
++	} else {
++		intr |= MVSD_NOR_CMD_DONE;
++	}
++
++	mvsd_write(MVSD_ARG_LOW, cmd->arg & 0xffff);
++	mvsd_write(MVSD_ARG_HI,  cmd->arg >> 16);
++
++	spin_lock_irqsave(&host->lock, flags);
++
++	host->xfer_mode &= MVSD_XFER_MODE_INT_CHK_EN;
++	host->xfer_mode |= xfer;
++	mvsd_write(MVSD_XFER_MODE, host->xfer_mode);
++
++	mvsd_write(MVSD_NOR_INTR_STATUS, ~MVSD_NOR_CARD_INT);
++	mvsd_write(MVSD_ERR_INTR_STATUS, 0xffff);
++	mvsd_write(MVSD_CMD, cmdreg);
++
++	host->intr_en &= MVSD_NOR_CARD_INT;
++	host->intr_en |= intr | MVSD_NOR_ERROR;
++	mvsd_write(MVSD_NOR_INTR_EN, host->intr_en);
++	mvsd_write(MVSD_ERR_INTR_EN, 0xffff);
++
++	mod_timer(&host->timer, jiffies + 5 * HZ);
++
++	spin_unlock_irqrestore(&host->lock, flags);
++}
++
++static u32 mvsd_finish_cmd(struct mvsd_host *host, struct mmc_command *cmd,
++			   u32 err_status)
++{
++	void __iomem *iobase = host->base;
++
++	if (cmd->flags & MMC_RSP_136) {
++		unsigned int response[8], i;
++		for (i = 0; i < 8; i++)
++			response[i] = mvsd_read(MVSD_RSP(i));
++		cmd->resp[0] =		((response[0] & 0x03ff) << 22) |
++					((response[1] & 0xffff) << 6) |
++					((response[2] & 0xfc00) >> 10);
++		cmd->resp[1] =		((response[2] & 0x03ff) << 22) |
++					((response[3] & 0xffff) << 6) |
++					((response[4] & 0xfc00) >> 10);
++		cmd->resp[2] =		((response[4] & 0x03ff) << 22) |
++					((response[5] & 0xffff) << 6) |
++					((response[6] & 0xfc00) >> 10);
++		cmd->resp[3] =		((response[6] & 0x03ff) << 22) |
++					((response[7] & 0x3fff) << 8);
++	} else if (cmd->flags & MMC_RSP_PRESENT) {
++		unsigned int response[3], i;
++		for (i = 0; i < 3; i++)
++			response[i] = mvsd_read(MVSD_RSP(i));
++		cmd->resp[0] =		((response[2] & 0x003f) << (8 - 8)) |
++					((response[1] & 0xffff) << (14 - 8)) |
++					((response[0] & 0x03ff) << (30 - 8));
++		cmd->resp[1] =		((response[0] & 0xfc00) >> 10);
++		cmd->resp[2] = 0;
++		cmd->resp[3] = 0;
++	}
++
++	if (err_status & MVSD_ERR_CMD_TIMEOUT) {
++		cmd->error = -ETIMEDOUT;
++	} else if (err_status & (MVSD_ERR_CMD_CRC | MVSD_ERR_CMD_ENDBIT |
++				 MVSD_ERR_CMD_INDEX | MVSD_ERR_CMD_STARTBIT)) {
++		cmd->error = -EILSEQ;
++	}
++	err_status &= ~(MVSD_ERR_CMD_TIMEOUT | MVSD_ERR_CMD_CRC |
++			MVSD_ERR_CMD_ENDBIT | MVSD_ERR_CMD_INDEX |
++			MVSD_ERR_CMD_STARTBIT);
++
++	return err_status;
++}
++
++static u32 mvsd_finish_data(struct mvsd_host *host, struct mmc_data *data,
++			    u32 err_status)
++{
++	void __iomem *iobase = host->base;
++
++	if (host->pio_ptr) {
++		host->pio_ptr = NULL;
++		host->pio_size = 0;
++	} else {
++		dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->sg_frags,
++			     (data->flags & MMC_DATA_READ) ?
++				DMA_FROM_DEVICE : DMA_TO_DEVICE);
++	}
++
++	if (err_status & MVSD_ERR_DATA_TIMEOUT)
++		data->error = -ETIMEDOUT;
++	else if (err_status & (MVSD_ERR_DATA_CRC | MVSD_ERR_DATA_ENDBIT))
++		data->error = -EILSEQ;
++	else if (err_status & MVSD_ERR_XFER_SIZE)
++		data->error = -EBADE;
++	err_status &= ~(MVSD_ERR_DATA_TIMEOUT | MVSD_ERR_DATA_CRC |
++			MVSD_ERR_DATA_ENDBIT | MVSD_ERR_XFER_SIZE);
++
++	data->bytes_xfered =
++		(data->blocks - mvsd_read(MVSD_CURR_BLK_LEFT)) * data->blksz;
++	dev_dbg(host->dev, "data done: blocks_left=%d, bytes_left=%d\n",
++		mvsd_read(MVSD_CURR_BLK_LEFT), mvsd_read(MVSD_CURR_BYTE_LEFT));
++
++	/* Handle Auto cmd 12 response */
++	if (data->stop) {
++		unsigned int response[3], i;
++		for (i = 0; i < 3; i++)
++			response[i] = mvsd_read(MVSD_AUTO_RSP(i));
++		data->stop->resp[0] =	((response[2] & 0x003f) << (8 - 8)) |
++					((response[1] & 0xffff) << (14 - 8)) |
++					((response[0] & 0x03ff) << (30 - 8));
++		data->stop->resp[1] =	((response[0] & 0xfc00) >> 10);
++		data->stop->resp[2] = 0;
++		data->stop->resp[3] = 0;
++
++		if (err_status & MVSD_ERR_AUTOCMD12) {
++			u32 err_cmd12 = mvsd_read(MVSD_AUTOCMD12_ERR_STATUS);
++			dev_dbg(host->dev, "c12err 0x%04x\n", err_cmd12);
++			if (err_cmd12 & MVSD_AUTOCMD12_ERR_NOTEXE)
++				data->stop->error = -ENOEXEC;
++			else if (err_cmd12 & MVSD_AUTOCMD12_ERR_TIMEOUT)
++				data->stop->error = -ETIMEDOUT;
++			else if (err_cmd12)
++				data->stop->error = -EILSEQ;
++			err_status &= ~MVSD_ERR_AUTOCMD12;
++		}
++	}
++
++	return err_status;
++}
++
++static irqreturn_t mvsd_irq(int irq, void *dev)
++{
++	struct mvsd_host *host = dev;
++	void __iomem *iobase = host->base;
++	u32 intr_status, intr_done_mask;
++	int irq_handled = 0;
++
++	intr_status = mvsd_read(MVSD_NOR_INTR_STATUS);
++	dev_dbg(host->dev, "intr 0x%04x intr_en 0x%04x hw_state 0x%04x\n",
++		intr_status, mvsd_read(MVSD_NOR_INTR_EN),
++		mvsd_read(MVSD_HW_STATE));
++
++	spin_lock(&host->lock);
++
++	/* PIO handling, if needed. Messy business... */
++	if (host->pio_size &&
++	    (intr_status & host->intr_en &
++	     (MVSD_NOR_RX_READY | MVSD_NOR_RX_FIFO_8W))) {
++		u16 *p = host->pio_ptr;
++		int s = host->pio_size;
++		while (s >= 32 && (intr_status & MVSD_NOR_RX_FIFO_8W)) {
++			readsw(iobase + MVSD_FIFO, p, 16);
++			p += 16;
++			s -= 32;
++			intr_status = mvsd_read(MVSD_NOR_INTR_STATUS);
++		}
++		/*
++		 * Normally we'd use < 32 here, but the RX_FIFO_8W bit
++		 * doesn't appear to assert when there is exactly 32 bytes
++		 * (8 words) left to fetch in a transfer.
++		 */
++		if (s <= 32) {
++			while (s >= 4 && (intr_status & MVSD_NOR_RX_READY)) {
++				put_unaligned(mvsd_read(MVSD_FIFO), p++);
++				put_unaligned(mvsd_read(MVSD_FIFO), p++);
++				s -= 4;
++				intr_status = mvsd_read(MVSD_NOR_INTR_STATUS);
++			}
++			if (s && s < 4 && (intr_status & MVSD_NOR_RX_READY)) {
++				u16 val[2] = {0, 0};
++				val[0] = mvsd_read(MVSD_FIFO);
++				val[1] = mvsd_read(MVSD_FIFO);
++				memcpy(p, &val, s);
++				s = 0;
++				intr_status = mvsd_read(MVSD_NOR_INTR_STATUS);
++			}
++			if (s == 0) {
++				host->intr_en &=
++				     ~(MVSD_NOR_RX_READY | MVSD_NOR_RX_FIFO_8W);
++				mvsd_write(MVSD_NOR_INTR_EN, host->intr_en);
++			} else if (host->intr_en & MVSD_NOR_RX_FIFO_8W) {
++				host->intr_en &= ~MVSD_NOR_RX_FIFO_8W;
++				host->intr_en |= MVSD_NOR_RX_READY;
++				mvsd_write(MVSD_NOR_INTR_EN, host->intr_en);
++			}
++		}
++		dev_dbg(host->dev, "pio %d intr 0x%04x hw_state 0x%04x\n",
++			s, intr_status, mvsd_read(MVSD_HW_STATE));
++		host->pio_ptr = p;
++		host->pio_size = s;
++		irq_handled = 1;
++	} else if (host->pio_size &&
++		   (intr_status & host->intr_en &
++		    (MVSD_NOR_TX_AVAIL | MVSD_NOR_TX_FIFO_8W))) {
++		u16 *p = host->pio_ptr;
++		int s = host->pio_size;
++		/*
++		 * The TX_FIFO_8W bit is unreliable. When set, bursting
++		 * 16 halfwords all at once in the FIFO drops data. Actually
++		 * TX_AVAIL does go off after only one word is pushed even if
++		 * TX_FIFO_8W remains set.
++		 */
++		while (s >= 4 && (intr_status & MVSD_NOR_TX_AVAIL)) {
++			mvsd_write(MVSD_FIFO, get_unaligned(p++));
++			mvsd_write(MVSD_FIFO, get_unaligned(p++));
++			s -= 4;
++			intr_status = mvsd_read(MVSD_NOR_INTR_STATUS);
++		}
++		if (s < 4) {
++			if (s && (intr_status & MVSD_NOR_TX_AVAIL)) {
++				u16 val[2] = {0, 0};
++				memcpy(&val, p, s);
++				mvsd_write(MVSD_FIFO, val[0]);
++				mvsd_write(MVSD_FIFO, val[1]);
++				s = 0;
++				intr_status = mvsd_read(MVSD_NOR_INTR_STATUS);
++			}
++			if (s == 0) {
++				host->intr_en &=
++				     ~(MVSD_NOR_TX_AVAIL | MVSD_NOR_TX_FIFO_8W);
++				mvsd_write(MVSD_NOR_INTR_EN, host->intr_en);
++			}
++		}
++		dev_dbg(host->dev, "pio %d intr 0x%04x hw_state 0x%04x\n",
++			s, intr_status, mvsd_read(MVSD_HW_STATE));
++		host->pio_ptr = p;
++		host->pio_size = s;
++		irq_handled = 1;
++	}
++
++	mvsd_write(MVSD_NOR_INTR_STATUS, intr_status);
++
++	intr_done_mask = MVSD_NOR_CARD_INT | MVSD_NOR_RX_READY |
++			 MVSD_NOR_RX_FIFO_8W | MVSD_NOR_TX_FIFO_8W;
++	if (intr_status & host->intr_en & ~intr_done_mask) {
++		struct mmc_request *mrq = host->mrq;
++		struct mmc_command *cmd = mrq->cmd;
++		u32 err_status = 0;
++
++		del_timer(&host->timer);
++		host->mrq = NULL;
++
++		host->intr_en &= MVSD_NOR_CARD_INT;
++		mvsd_write(MVSD_NOR_INTR_EN, host->intr_en);
++		mvsd_write(MVSD_ERR_INTR_EN, 0);
++
++		spin_unlock(&host->lock);
++
++		if (intr_status & MVSD_NOR_UNEXP_RSP) {
++			cmd->error = -EPROTO;
++		} else if (intr_status & MVSD_NOR_ERROR) {
++			err_status = mvsd_read(MVSD_ERR_INTR_STATUS);
++			dev_dbg(host->dev, "err 0x%04x\n", err_status);
++		}
++
++		err_status = mvsd_finish_cmd(host, cmd, err_status);
++		if (mrq->data)
++			err_status = mvsd_finish_data(host, mrq->data, err_status);
++		if (err_status) {
++			printk(KERN_ERR "%s: unhandled error status %#04x\n",
++					mmc_hostname(host->mmc), err_status);
++			cmd->error = -ENOMSG;
++		}
++
++		mmc_request_done(host->mmc, mrq);
++		irq_handled = 1;
++	} else
++		spin_unlock(&host->lock);
++
++	if (intr_status & MVSD_NOR_CARD_INT) {
++		mmc_signal_sdio_irq(host->mmc);
++		irq_handled = 1;
++	}
++
++	if (irq_handled)
++		return IRQ_HANDLED;
++
++	printk(KERN_ERR "%s: unhandled interrupt status=0x%04x en=0x%04x "
++			"pio=%d\n", mmc_hostname(host->mmc), intr_status,
++			host->intr_en, host->pio_size);
++	return IRQ_NONE;
++}
++
++static void mvsd_timeout_timer(unsigned long data)
++{
++	struct mvsd_host *host = (struct mvsd_host *)data;
++	void __iomem *iobase = host->base;
++	struct mmc_request *mrq;
++	unsigned long flags;
++
++	spin_lock_irqsave(&host->lock, flags);
++	mrq = host->mrq;
++	if (mrq) {
++		printk(KERN_ERR "%s: Timeout waiting for hardware interrupt.\n",
++				mmc_hostname(host->mmc));
++		printk(KERN_ERR "%s: hw_state=0x%04x, intr_status=0x%04x "
++				"intr_en=0x%04x\n", mmc_hostname(host->mmc),
++				mvsd_read(MVSD_HW_STATE),
++				mvsd_read(MVSD_NOR_INTR_STATUS),
++				mvsd_read(MVSD_NOR_INTR_EN));
++
++		host->mrq = NULL;
++
++		mvsd_write(MVSD_SW_RESET, MVSD_SW_RESET_NOW);
++
++		host->xfer_mode &= MVSD_XFER_MODE_INT_CHK_EN;
++		mvsd_write(MVSD_XFER_MODE, host->xfer_mode);
++
++		host->intr_en &= MVSD_NOR_CARD_INT;
++		mvsd_write(MVSD_NOR_INTR_EN, host->intr_en);
++		mvsd_write(MVSD_ERR_INTR_EN, 0);
++		mvsd_write(MVSD_ERR_INTR_STATUS, 0xffff);
++
++		mrq->cmd->error = -ETIMEDOUT;
++		mvsd_finish_cmd(host, mrq->cmd, 0);
++		if (mrq->data) {
++			mrq->data->error = -ETIMEDOUT;
++			mvsd_finish_data(host, mrq->data, 0);
++		}
++	}
++	spin_unlock_irqrestore(&host->lock, flags);
++
++	if (mrq)
++		mmc_request_done(host->mmc, mrq);
++}
++
++static irqreturn_t mvsd_card_detect_irq(int irq, void *dev)
++{
++	struct mvsd_host *host = dev;
++	mmc_detect_change(host->mmc, msecs_to_jiffies(100));
++	return IRQ_HANDLED;
++}
++
++static void mvsd_enable_sdio_irq(struct mmc_host *mmc, int enable)
++{
++	struct mvsd_host *host = mmc_priv(mmc);
++	void __iomem *iobase = host->base;
++	unsigned long flags;
++
++	spin_lock_irqsave(&host->lock, flags);
++	if (enable) {
++		host->xfer_mode |= MVSD_XFER_MODE_INT_CHK_EN;
++		host->intr_en |= MVSD_NOR_CARD_INT;
++	} else {
++		host->xfer_mode &= ~MVSD_XFER_MODE_INT_CHK_EN;
++		host->intr_en &= ~MVSD_NOR_CARD_INT;
++	}
++	mvsd_write(MVSD_XFER_MODE, host->xfer_mode);
++	mvsd_write(MVSD_NOR_INTR_EN, host->intr_en);
++	spin_unlock_irqrestore(&host->lock, flags);
++}
++
++static int mvsd_get_ro(struct mmc_host *mmc)
++{
++	struct mvsd_host *host = mmc_priv(mmc);
++
++	if (host->gpio_write_protect)
++		return gpio_get_value(host->gpio_write_protect);
++
++	/*
++	 * Board doesn't support read only detection; let the mmc core
++	 * decide what to do.
++	 */
++	return -ENOSYS;
++}
++
++static void mvsd_power_up(struct mvsd_host *host)
++{
++	void __iomem *iobase = host->base;
++	dev_dbg(host->dev, "power up\n");
++	mvsd_write(MVSD_NOR_INTR_EN, 0);
++	mvsd_write(MVSD_ERR_INTR_EN, 0);
++	mvsd_write(MVSD_SW_RESET, MVSD_SW_RESET_NOW);
++	mvsd_write(MVSD_XFER_MODE, 0);
++	mvsd_write(MVSD_NOR_STATUS_EN, 0xffff);
++	mvsd_write(MVSD_ERR_STATUS_EN, 0xffff);
++	mvsd_write(MVSD_NOR_INTR_STATUS, 0xffff);
++	mvsd_write(MVSD_ERR_INTR_STATUS, 0xffff);
++}
++
++static void mvsd_power_down(struct mvsd_host *host)
++{
++	void __iomem *iobase = host->base;
++	dev_dbg(host->dev, "power down\n");
++	mvsd_write(MVSD_NOR_INTR_EN, 0);
++	mvsd_write(MVSD_ERR_INTR_EN, 0);
++	mvsd_write(MVSD_SW_RESET, MVSD_SW_RESET_NOW);
++	mvsd_write(MVSD_XFER_MODE, MVSD_XFER_MODE_STOP_CLK);
++	mvsd_write(MVSD_NOR_STATUS_EN, 0);
++	mvsd_write(MVSD_ERR_STATUS_EN, 0);
++	mvsd_write(MVSD_NOR_INTR_STATUS, 0xffff);
++	mvsd_write(MVSD_ERR_INTR_STATUS, 0xffff);
++}
++
++static void mvsd_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
++{
++	struct mvsd_host *host = mmc_priv(mmc);
++	void __iomem *iobase = host->base;
++	u32 ctrl_reg = 0;
++
++	if (ios->power_mode == MMC_POWER_UP)
++		mvsd_power_up(host);
++
++	if (ios->clock == 0) {
++		mvsd_write(MVSD_XFER_MODE, MVSD_XFER_MODE_STOP_CLK);
++		mvsd_write(MVSD_CLK_DIV, MVSD_BASE_DIV_MAX);
++		host->clock = 0;
++		dev_dbg(host->dev, "clock off\n");
++	} else if (ios->clock != host->clock) {
++		u32 m = DIV_ROUND_UP(host->base_clock, ios->clock) - 1;
++		if (m > MVSD_BASE_DIV_MAX)
++			m = MVSD_BASE_DIV_MAX;
++		mvsd_write(MVSD_CLK_DIV, m);
++		host->clock = ios->clock;
++		host->ns_per_clk = 1000000000 / (host->base_clock / (m+1));
++		dev_dbg(host->dev, "clock=%d (%d), div=0x%04x\n",
++			ios->clock, host->base_clock / (m+1), m);
++	}
++
++	/* default transfer mode */
++	ctrl_reg |= MVSD_HOST_CTRL_BIG_ENDIAN;
++	ctrl_reg &= ~MVSD_HOST_CTRL_LSB_FIRST;
++
++	/* default to maximum timeout */
++	ctrl_reg |= MVSD_HOST_CTRL_TMOUT_MASK;
++	ctrl_reg |= MVSD_HOST_CTRL_TMOUT_EN;
++
++	if (ios->bus_mode == MMC_BUSMODE_PUSHPULL)
++		ctrl_reg |= MVSD_HOST_CTRL_PUSH_PULL_EN;
++
++	if (ios->bus_width == MMC_BUS_WIDTH_4)
++		ctrl_reg |= MVSD_HOST_CTRL_DATA_WIDTH_4_BITS;
++
++	if (ios->timing == MMC_TIMING_MMC_HS ||
++	    ios->timing == MMC_TIMING_SD_HS)
++		ctrl_reg |= MVSD_HOST_CTRL_HI_SPEED_EN;
++
++	host->ctrl = ctrl_reg;
++	mvsd_write(MVSD_HOST_CTRL, ctrl_reg);
++	dev_dbg(host->dev, "ctrl 0x%04x: %s %s %s\n", ctrl_reg,
++		(ctrl_reg & MVSD_HOST_CTRL_PUSH_PULL_EN) ?
++			"push-pull" : "open-drain",
++		(ctrl_reg & MVSD_HOST_CTRL_DATA_WIDTH_4_BITS) ?
++			"4bit-width" : "1bit-width",
++		(ctrl_reg & MVSD_HOST_CTRL_HI_SPEED_EN) ?
++			"high-speed" : "");
++
++	if (ios->power_mode == MMC_POWER_OFF)
++		mvsd_power_down(host);
++}
++
++static const struct mmc_host_ops mvsd_ops = {
++	.request		= mvsd_request,
++	.get_ro			= mvsd_get_ro,
++	.set_ios		= mvsd_set_ios,
++	.enable_sdio_irq	= mvsd_enable_sdio_irq,
++};
++
++static void __init mv_conf_mbus_windows(struct mvsd_host *host,
++					struct mbus_dram_target_info *dram)
++{
++	void __iomem *iobase = host->base;
++	int i;
++
++	for (i = 0; i < 4; i++) {
++		writel(0, iobase + MVSD_WINDOW_CTRL(i));
++		writel(0, iobase + MVSD_WINDOW_BASE(i));
++	}
++
++	for (i = 0; i < dram->num_cs; i++) {
++		struct mbus_dram_window *cs = dram->cs + i;
++		writel(((cs->size - 1) & 0xffff0000) |
++		       (cs->mbus_attr << 8) |
++		       (dram->mbus_dram_target_id << 4) | 1,
++		       iobase + MVSD_WINDOW_CTRL(i));
++		writel(cs->base, iobase + MVSD_WINDOW_BASE(i));
++	}
++}
++
++static int __init mvsd_probe(struct platform_device *pdev)
++{
++	struct mmc_host *mmc = NULL;
++	struct mvsd_host *host = NULL;
++	const struct mvsdio_platform_data *mvsd_data;
++	struct resource *r;
++	int ret, irq;
++
++	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	irq = platform_get_irq(pdev, 0);
++	mvsd_data = pdev->dev.platform_data;
++	if (!r || irq < 0 || !mvsd_data)
++		return -ENXIO;
++
++	r = request_mem_region(r->start, SZ_1K, DRIVER_NAME);
++	if (!r)
++		return -EBUSY;
++
++	mmc = mmc_alloc_host(sizeof(struct mvsd_host), &pdev->dev);
++	if (!mmc) {
++		ret = -ENOMEM;
++		goto out;
++	}
++
++	host = mmc_priv(mmc);
++	host->mmc = mmc;
++	host->dev = &pdev->dev;
++	host->res = r;
++	host->base_clock = mvsd_data->clock / 2;
++
++	mmc->ops = &mvsd_ops;
++
++	mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
++	mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ |
++		    MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED;
++
++	mmc->f_min = DIV_ROUND_UP(host->base_clock, MVSD_BASE_DIV_MAX);
++	mmc->f_max = maxfreq;
++
++	mmc->max_blk_size = 2048;
++	mmc->max_blk_count = 65535;
++
++	mmc->max_hw_segs = 1;
++	mmc->max_phys_segs = 1;
++	mmc->max_seg_size = mmc->max_blk_size * mmc->max_blk_count;
++	mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
++
++	spin_lock_init(&host->lock);
++
++	host->base = ioremap(r->start, SZ_4K);
++	if (!host->base) {
++		ret = -ENOMEM;
++		goto out;
++	}
++
++	/* (Re-)program MBUS remapping windows if we are asked to. */
++	if (mvsd_data->dram != NULL)
++		mv_conf_mbus_windows(host, mvsd_data->dram);
++
++	mvsd_power_down(host);
++
++	ret = request_irq(irq, mvsd_irq, 0, DRIVER_NAME, host);
++	if (ret) {
++		printk(KERN_ERR "%s: cannot assign irq %d\n", DRIVER_NAME, irq);
++		goto out;
++	} else
++		host->irq = irq;
++
++	if (mvsd_data->gpio_card_detect) {
++		ret = gpio_request(mvsd_data->gpio_card_detect,
++				   DRIVER_NAME " cd");
++		if (ret == 0) {
++			gpio_direction_input(mvsd_data->gpio_card_detect);
++			irq = gpio_to_irq(mvsd_data->gpio_card_detect);
++			ret = request_irq(irq, mvsd_card_detect_irq,
++					  IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING,
++					  DRIVER_NAME " cd", host);
++			if (ret == 0)
++				host->gpio_card_detect =
++					mvsd_data->gpio_card_detect;
++			else
++				gpio_free(mvsd_data->gpio_card_detect);
++		}
++	}
++	if (!host->gpio_card_detect)
++		mmc->caps |= MMC_CAP_NEEDS_POLL;
++
++	if (mvsd_data->gpio_write_protect) {
++		ret = gpio_request(mvsd_data->gpio_write_protect,
++				   DRIVER_NAME " wp");
++		if (ret == 0) {
++			gpio_direction_input(mvsd_data->gpio_write_protect);
++			host->gpio_write_protect =
++				mvsd_data->gpio_write_protect;
++		}
++	}
++
++	setup_timer(&host->timer, mvsd_timeout_timer, (unsigned long)host);
++	platform_set_drvdata(pdev, mmc);
++	ret = mmc_add_host(mmc);
++	if (ret)
++		goto out;
++
++	printk(KERN_NOTICE "%s: %s driver initialized, ",
++			   mmc_hostname(mmc), DRIVER_NAME);
++	if (host->gpio_card_detect)
++		printk("using GPIO %d for card detection\n",
++		       host->gpio_card_detect);
++	else
++		printk("lacking card detect (fall back to polling)\n");
++	return 0;
++
++out:
++	if (host) {
++		if (host->irq)
++			free_irq(host->irq, host);
++		if (host->gpio_card_detect) {
++			free_irq(gpio_to_irq(host->gpio_card_detect), host);
++			gpio_free(host->gpio_card_detect);
++		}
++		if (host->gpio_write_protect)
++			gpio_free(host->gpio_write_protect);
++		if (host->base)
++			iounmap(host->base);
++	}
++	if (r)
++		release_resource(r);
++	if (mmc)
++		mmc_free_host(mmc);
++
++	return ret;
++}
++
++static int __exit mvsd_remove(struct platform_device *pdev)
++{
++	struct mmc_host *mmc = platform_get_drvdata(pdev);
++
++	if (mmc) {
++		struct mvsd_host *host = mmc_priv(mmc);
++
++		if (host->gpio_card_detect) {
++			free_irq(gpio_to_irq(host->gpio_card_detect), host);
++			gpio_free(host->gpio_card_detect);
++		}
++		mmc_remove_host(mmc);
++		free_irq(host->irq, host);
++		if (host->gpio_write_protect)
++			gpio_free(host->gpio_write_protect);
++		del_timer_sync(&host->timer);
++		mvsd_power_down(host);
++		iounmap(host->base);
++		release_resource(host->res);
++		mmc_free_host(mmc);
++	}
++	platform_set_drvdata(pdev, NULL);
++	return 0;
++}
++
++#ifdef CONFIG_PM
++static int mvsd_suspend(struct platform_device *dev, pm_message_t state,
++			   u32 level)
++{
++	struct mmc_host *mmc = platform_get_drvdata(dev);
++	int ret = 0;
++
++	if (mmc && level == SUSPEND_DISABLE)
++		ret = mmc_suspend_host(mmc, state);
++
++	return ret;
++}
++
++static int mvsd_resume(struct platform_device *dev, u32 level)
++{
++	struct mmc_host *mmc = platform_dev_get_drvdata(dev);
++	int ret = 0;
++
++	if (mmc && level == RESUME_ENABLE)
++		ret = mmc_resume_host(mmc);
++
++	return ret;
++}
++#else
++#define mvsd_suspend	NULL
++#define mvsd_resume	NULL
++#endif
++
++static struct platform_driver mvsd_driver = {
++	.remove		= __exit_p(mvsd_remove),
++	.suspend	= mvsd_suspend,
++	.resume		= mvsd_resume,
++	.driver		= {
++		.name	= DRIVER_NAME,
++	},
++};
++
++static int __init mvsd_init(void)
++{
++	return platform_driver_probe(&mvsd_driver, mvsd_probe);
++}
++
++static void __exit mvsd_exit(void)
++{
++	platform_driver_unregister(&mvsd_driver);
++}
++
++module_init(mvsd_init);
++module_exit(mvsd_exit);
++
++/* maximum card clock frequency (default 50MHz) */
++module_param(maxfreq, int, 0);
++
++/* force PIO transfers all the time */
++module_param(nodma, int, 0);
++
++MODULE_AUTHOR("Maen Suleiman, Nicolas Pitre");
++MODULE_DESCRIPTION("Marvell MMC,SD,SDIO Host Controller driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/mmc/host/mvsdio.h b/drivers/mmc/host/mvsdio.h
+new file mode 100644
+index 0000000..7d9727b
+--- /dev/null
++++ b/drivers/mmc/host/mvsdio.h
+@@ -0,0 +1,190 @@
++/*
++ *  Copyright (C) 2008 Marvell Semiconductors, All Rights Reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef __MVSDIO_H
++#define __MVSDIO_H
++
++/*
++ * Clock rates
++ */
++
++#define MVSD_CLOCKRATE_MAX			50000000
++#define MVSD_BASE_DIV_MAX			0x7ff
++
++
++/*
++ * Register offsets
++ */
++
++#define MVSD_SYS_ADDR_LOW			0x000
++#define MVSD_SYS_ADDR_HI			0x004
++#define MVSD_BLK_SIZE				0x008
++#define MVSD_BLK_COUNT				0x00c
++#define MVSD_ARG_LOW				0x010
++#define MVSD_ARG_HI				0x014
++#define MVSD_XFER_MODE				0x018
++#define MVSD_CMD				0x01c
++#define MVSD_RSP(i)				(0x020 + ((i)<<2))
++#define MVSD_RSP0				0x020
++#define MVSD_RSP1				0x024
++#define MVSD_RSP2				0x028
++#define MVSD_RSP3				0x02c
++#define MVSD_RSP4				0x030
++#define MVSD_RSP5				0x034
++#define MVSD_RSP6				0x038
++#define MVSD_RSP7				0x03c
++#define MVSD_FIFO				0x040
++#define MVSD_RSP_CRC7				0x044
++#define MVSD_HW_STATE				0x048
++#define MVSD_HOST_CTRL				0x050
++#define MVSD_BLK_GAP_CTRL			0x054
++#define MVSD_CLK_CTRL				0x058
++#define MVSD_SW_RESET				0x05c
++#define MVSD_NOR_INTR_STATUS			0x060
++#define MVSD_ERR_INTR_STATUS			0x064
++#define MVSD_NOR_STATUS_EN			0x068
++#define MVSD_ERR_STATUS_EN			0x06c
++#define MVSD_NOR_INTR_EN			0x070
++#define MVSD_ERR_INTR_EN			0x074
++#define MVSD_AUTOCMD12_ERR_STATUS		0x078
++#define MVSD_CURR_BYTE_LEFT			0x07c
++#define MVSD_CURR_BLK_LEFT			0x080
++#define MVSD_AUTOCMD12_ARG_LOW			0x084
++#define MVSD_AUTOCMD12_ARG_HI			0x088
++#define MVSD_AUTOCMD12_CMD			0x08c
++#define MVSD_AUTO_RSP(i)			(0x090 + ((i)<<2))
++#define MVSD_AUTO_RSP0				0x090
++#define MVSD_AUTO_RSP1				0x094
++#define MVSD_AUTO_RSP2				0x098
++#define MVSD_CLK_DIV				0x128
++
++#define MVSD_WINDOW_CTRL(i)			(0x108 + ((i) << 3))
++#define MVSD_WINDOW_BASE(i)			(0x10c + ((i) << 3))
++
++
++/*
++ * MVSD_CMD
++ */
++
++#define MVSD_CMD_RSP_NONE			(0 << 0)
++#define MVSD_CMD_RSP_136			(1 << 0)
++#define MVSD_CMD_RSP_48				(2 << 0)
++#define MVSD_CMD_RSP_48BUSY			(3 << 0)
++
++#define MVSD_CMD_CHECK_DATACRC16		(1 << 2)
++#define MVSD_CMD_CHECK_CMDCRC			(1 << 3)
++#define MVSD_CMD_INDX_CHECK			(1 << 4)
++#define MVSD_CMD_DATA_PRESENT			(1 << 5)
++#define MVSD_UNEXPECTED_RESP			(1 << 7)
++#define MVSD_CMD_INDEX(x)			((x) << 8)
++
++
++/*
++ * MVSD_AUTOCMD12_CMD
++ */
++
++#define MVSD_AUTOCMD12_BUSY			(1 << 0)
++#define MVSD_AUTOCMD12_INDX_CHECK		(1 << 1)
++#define MVSD_AUTOCMD12_INDEX(x)			((x) << 8)
++
++/*
++ * MVSD_XFER_MODE
++ */
++
++#define MVSD_XFER_MODE_WR_DATA_START		(1 << 0)
++#define MVSD_XFER_MODE_HW_WR_DATA_EN		(1 << 1)
++#define MVSD_XFER_MODE_AUTO_CMD12		(1 << 2)
++#define MVSD_XFER_MODE_INT_CHK_EN		(1 << 3)
++#define MVSD_XFER_MODE_TO_HOST			(1 << 4)
++#define MVSD_XFER_MODE_STOP_CLK			(1 << 5)
++#define MVSD_XFER_MODE_PIO			(1 << 6)
++
++
++/*
++ * MVSD_HOST_CTRL
++ */
++
++#define MVSD_HOST_CTRL_PUSH_PULL_EN 		(1 << 0)
++
++#define MVSD_HOST_CTRL_CARD_TYPE_MEM_ONLY 	(0 << 1)
++#define MVSD_HOST_CTRL_CARD_TYPE_IO_ONLY 	(1 << 1)
++#define MVSD_HOST_CTRL_CARD_TYPE_IO_MEM_COMBO 	(2 << 1)
++#define MVSD_HOST_CTRL_CARD_TYPE_IO_MMC 	(3 << 1)
++#define MVSD_HOST_CTRL_CARD_TYPE_MASK	 	(3 << 1)
++
++#define MVSD_HOST_CTRL_BIG_ENDIAN 		(1 << 3)
++#define MVSD_HOST_CTRL_LSB_FIRST 		(1 << 4)
++#define MVSD_HOST_CTRL_DATA_WIDTH_4_BITS 	(1 << 9)
++#define MVSD_HOST_CTRL_HI_SPEED_EN 		(1 << 10)
++
++#define MVSD_HOST_CTRL_TMOUT_MAX 		0xf
++#define MVSD_HOST_CTRL_TMOUT_MASK 		(0xf << 11)
++#define MVSD_HOST_CTRL_TMOUT(x) 		((x) << 11)
++#define MVSD_HOST_CTRL_TMOUT_EN 		(1 << 15)
++
++
++/*
++ * MVSD_SW_RESET
++ */
++
++#define MVSD_SW_RESET_NOW			(1 << 8)
++
++
++/*
++ * Normal interrupt status bits
++ */
++
++#define MVSD_NOR_CMD_DONE			(1 << 0)
++#define MVSD_NOR_XFER_DONE			(1 << 1)
++#define MVSD_NOR_BLK_GAP_EVT			(1 << 2)
++#define MVSD_NOR_DMA_DONE			(1 << 3)
++#define MVSD_NOR_TX_AVAIL			(1 << 4)
++#define MVSD_NOR_RX_READY			(1 << 5)
++#define MVSD_NOR_CARD_INT			(1 << 8)
++#define MVSD_NOR_READ_WAIT_ON			(1 << 9)
++#define MVSD_NOR_RX_FIFO_8W			(1 << 10)
++#define MVSD_NOR_TX_FIFO_8W			(1 << 11)
++#define MVSD_NOR_SUSPEND_ON			(1 << 12)
++#define MVSD_NOR_AUTOCMD12_DONE			(1 << 13)
++#define MVSD_NOR_UNEXP_RSP			(1 << 14)
++#define MVSD_NOR_ERROR				(1 << 15)
++
++
++/*
++ * Error status bits
++ */
++
++#define MVSD_ERR_CMD_TIMEOUT			(1 << 0)
++#define MVSD_ERR_CMD_CRC			(1 << 1)
++#define MVSD_ERR_CMD_ENDBIT			(1 << 2)
++#define MVSD_ERR_CMD_INDEX			(1 << 3)
++#define MVSD_ERR_DATA_TIMEOUT			(1 << 4)
++#define MVSD_ERR_DATA_CRC			(1 << 5)
++#define MVSD_ERR_DATA_ENDBIT			(1 << 6)
++#define MVSD_ERR_AUTOCMD12			(1 << 8)
++#define MVSD_ERR_CMD_STARTBIT			(1 << 9)
++#define MVSD_ERR_XFER_SIZE			(1 << 10)
++#define MVSD_ERR_RESP_T_BIT			(1 << 11)
++#define MVSD_ERR_CRC_ENDBIT			(1 << 12)
++#define MVSD_ERR_CRC_STARTBIT			(1 << 13)
++#define MVSD_ERR_CRC_STATUS			(1 << 14)
++
++
++/*
++ * CMD12 error status bits
++ */
++
++#define MVSD_AUTOCMD12_ERR_NOTEXE		(1 << 0)
++#define MVSD_AUTOCMD12_ERR_TIMEOUT		(1 << 1)
++#define MVSD_AUTOCMD12_ERR_CRC			(1 << 2)
++#define MVSD_AUTOCMD12_ERR_ENDBIT		(1 << 3)
++#define MVSD_AUTOCMD12_ERR_INDEX		(1 << 4)
++#define MVSD_AUTOCMD12_ERR_RESP_T_BIT		(1 << 5)
++#define MVSD_AUTOCMD12_ERR_RESP_STARTBIT	(1 << 6)
++
++#endif

Added: dists/trunk/linux-2.6/debian/patches/features/arm/orion-gpio-input-output.patch
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/features/arm/orion-gpio-input-output.patch	Sat Mar 14 10:03:37 2009
@@ -0,0 +1,110 @@
+From: Nicolas Pitre <nico at cam.org>
+Date: Mon, 2 Feb 2009 20:27:55 +0000 (-0500)
+Subject: [ARM] Orion: make gpio /input/output validation separate
+X-Git-Url: http://git.marvell.com/?p=orion.git;a=commitdiff_plain;h=28d27cf4ce8378180eda32aa7d8e778c9e72a54f
+
+[ARM] Orion: make gpio /input/output validation separate
+
+Especially on Kirkwood, a couple GPIOs are actually only output capable.
+Let's separate the ability to configure a GPIO as input or output to
+accommodate this restriction.
+
+Signed-off-by: Nicolas Pitre <nico at marvell.com>
+---
+
+diff --git a/arch/arm/plat-orion/gpio.c b/arch/arm/plat-orion/gpio.c
+index 0d12c21..32eb9e3 100644
+--- a/arch/arm/plat-orion/gpio.c
++++ b/arch/arm/plat-orion/gpio.c
+@@ -19,7 +19,8 @@
+ 
+ static DEFINE_SPINLOCK(gpio_lock);
+ static const char *gpio_label[GPIO_MAX];  /* non null for allocated GPIOs */
+-static unsigned long gpio_valid[BITS_TO_LONGS(GPIO_MAX)];
++static unsigned long gpio_valid_input[BITS_TO_LONGS(GPIO_MAX)];
++static unsigned long gpio_valid_output[BITS_TO_LONGS(GPIO_MAX)];
+ 
+ static inline void __set_direction(unsigned pin, int input)
+ {
+@@ -53,7 +54,7 @@ int gpio_direction_input(unsigned pin)
+ {
+ 	unsigned long flags;
+ 
+-	if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
++	if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid_input)) {
+ 		pr_debug("%s: invalid GPIO %d\n", __func__, pin);
+ 		return -EINVAL;
+ 	}
+@@ -83,7 +84,7 @@ int gpio_direction_output(unsigned pin, int value)
+ 	unsigned long flags;
+ 	u32 u;
+ 
+-	if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
++	if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid_output)) {
+ 		pr_debug("%s: invalid GPIO %d\n", __func__, pin);
+ 		return -EINVAL;
+ 	}
+@@ -161,7 +162,9 @@ int gpio_request(unsigned pin, const char *label)
+ 	unsigned long flags;
+ 	int ret;
+ 
+-	if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
++	if (pin >= GPIO_MAX ||
++	    !(test_bit(pin, gpio_valid_input) ||
++	      test_bit(pin, gpio_valid_output))) {
+ 		pr_debug("%s: invalid GPIO %d\n", __func__, pin);
+ 		return -EINVAL;
+ 	}
+@@ -183,7 +186,9 @@ EXPORT_SYMBOL(gpio_request);
+ 
+ void gpio_free(unsigned pin)
+ {
+-	if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
++	if (pin >= GPIO_MAX ||
++	    !(test_bit(pin, gpio_valid_input) ||
++	      test_bit(pin, gpio_valid_output))) {
+ 		pr_debug("%s: invalid GPIO %d\n", __func__, pin);
+ 		return;
+ 	}
+@@ -208,12 +213,18 @@ void __init orion_gpio_set_unused(unsigned pin)
+ 	__set_direction(pin, 0);
+ }
+ 
+-void __init orion_gpio_set_valid(unsigned pin, int valid)
++void __init orion_gpio_set_valid(unsigned pin, int mode)
+ {
+-	if (valid)
+-		__set_bit(pin, gpio_valid);
++	if (mode == 1)
++		mode = GPIO_INPUT_OK | GPIO_OUTPUT_OK;
++	if (mode & GPIO_INPUT_OK)
++		__set_bit(pin, gpio_valid_input);
+ 	else
+-		__clear_bit(pin, gpio_valid);
++		__clear_bit(pin, gpio_valid_input);
++	if (mode & GPIO_OUTPUT_OK)
++		__set_bit(pin, gpio_valid_output);
++	else
++		__clear_bit(pin, gpio_valid_output);
+ }
+ 
+ void orion_gpio_set_blink(unsigned pin, int blink)
+diff --git a/arch/arm/plat-orion/include/plat/gpio.h b/arch/arm/plat-orion/include/plat/gpio.h
+index ec743e8..33f6c6a 100644
+--- a/arch/arm/plat-orion/include/plat/gpio.h
++++ b/arch/arm/plat-orion/include/plat/gpio.h
+@@ -25,9 +25,13 @@ void gpio_set_value(unsigned pin, int value);
+  * Orion-specific GPIO API extensions.
+  */
+ void orion_gpio_set_unused(unsigned pin);
+-void orion_gpio_set_valid(unsigned pin, int valid);
+ void orion_gpio_set_blink(unsigned pin, int blink);
+ 
++#define GPIO_BIDI_OK		(1 << 0)
++#define GPIO_INPUT_OK		(1 << 1)
++#define GPIO_OUTPUT_OK		(1 << 2)
++void orion_gpio_set_valid(unsigned pin, int mode);
++
+ /*
+  * GPIO interrupt handling.
+  */

Modified: dists/trunk/linux-2.6/debian/patches/series/1~experimental.1
==============================================================================
--- dists/trunk/linux-2.6/debian/patches/series/1~experimental.1	(original)
+++ dists/trunk/linux-2.6/debian/patches/series/1~experimental.1	Sat Mar 14 10:03:37 2009
@@ -26,3 +26,12 @@
 + bugfix/powerpc/lpar-console.patch
 #+ bugfix/all/wireless-regulatory-default-EU.patch
 + features/sparc/video-sunxvr500-intergraph.patch
+# Kirkwood support, will be in 2.6.30
++ features/arm/orion-gpio-input-output.patch
++ features/arm/kw-mpp.patch
++ features/arm/mv-sdio.patch
++ features/arm/kw-register-sdio.patch
++ features/arm/kw-register-internal-devices.patch
++ features/arm/kw-sheevaplug.patch
++ features/arm/kw-sheevaplug-usb-power.patch
++ features/arm/kw-sheevaplug-led.patch



More information about the Kernel-svn-changes mailing list