[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