]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge current mainline tree into linux-omap tree
authorTony Lindgren <tony@atomide.com>
Thu, 15 Jan 2009 15:25:27 +0000 (17:25 +0200)
committerTony Lindgren <tony@atomide.com>
Thu, 15 Jan 2009 15:25:27 +0000 (17:25 +0200)
Merge branches 'master' and 'linus'

Conflicts:

arch/arm/Kconfig
arch/arm/configs/omap3_pandora_defconfig
arch/arm/mach-omap1/board-h2.c
arch/arm/mach-omap1/board-h3.c
arch/arm/mach-omap1/board-innovator.c
arch/arm/mach-omap1/board-osk.c
arch/arm/mach-omap1/board-sx1.c
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/Makefile
arch/arm/mach-omap2/board-2430sdp.c
arch/arm/mach-omap2/board-apollon.c
arch/arm/mach-omap2/board-generic.c
arch/arm/mach-omap2/board-h4.c
arch/arm/mach-omap2/board-ldp.c
arch/arm/mach-omap2/board-omap3beagle.c
arch/arm/mach-omap2/board-omap3pandora.c
arch/arm/mach-omap2/board-overo.c
arch/arm/mach-omap2/devices.c
arch/arm/mach-omap2/id.c
arch/arm/mach-omap2/mux.c
arch/arm/plat-omap/devices.c
arch/arm/plat-omap/include/mach/control.h
arch/arm/plat-omap/include/mach/mux.h
drivers/i2c/busses/i2c-omap.c
drivers/i2c/chips/Kconfig
drivers/i2c/chips/Makefile
drivers/i2c/chips/menelaus.c
drivers/input/keyboard/gpio_keys.c
drivers/input/touchscreen/Makefile
drivers/leds/Kconfig
drivers/leds/Makefile
drivers/misc/Kconfig
drivers/misc/Makefile
drivers/mtd/onenand/omap2.c
drivers/usb/gadget/Kconfig
drivers/usb/musb/musbhsdma.h
drivers/usb/otg/Kconfig
include/linux/i2c/twl4030.h
sound/soc/codecs/Kconfig
sound/soc/codecs/Makefile
sound/soc/codecs/twl4030.c
sound/soc/codecs/twl4030.h
sound/soc/omap/Kconfig
sound/soc/omap/Makefile
sound/soc/omap/omap3beagle.c
sound/soc/omap/overo.c

46 files changed:
1  2 
Makefile
arch/arm/Kconfig
arch/arm/boot/compressed/Makefile
arch/arm/include/asm/setup.h
arch/arm/mach-omap1/Kconfig
arch/arm/mach-omap1/mcbsp.c
arch/arm/mach-omap2/mcbsp.c
arch/arm/mach-omap2/timer-gp.c
arch/arm/plat-omap/Kconfig
arch/arm/plat-omap/dma.c
arch/arm/plat-omap/include/mach/io.h
arch/arm/plat-omap/include/mach/mcbsp.h
drivers/Makefile
drivers/bluetooth/Kconfig
drivers/bluetooth/Makefile
drivers/hwmon/Kconfig
drivers/hwmon/Makefile
drivers/i2c/chips/Kconfig
drivers/i2c/chips/Makefile
drivers/input/keyboard/Kconfig
drivers/input/keyboard/Makefile
drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/ads7846.c
drivers/mfd/Kconfig
drivers/mfd/Makefile
drivers/mfd/twl4030-core.c
drivers/misc/Kconfig
drivers/misc/Makefile
drivers/mmc/host/Makefile
drivers/mmc/host/omap_hsmmc.c
drivers/mtd/maps/Kconfig
drivers/mtd/maps/omap_nor.c
drivers/mtd/nand/Kconfig
drivers/net/smc911x.h
drivers/net/smc91x.c
drivers/power/Kconfig
drivers/power/Makefile
drivers/rtc/rtc-twl4030.c
drivers/serial/8250.c
drivers/spi/Kconfig
drivers/spi/Makefile
drivers/usb/host/Kconfig
drivers/watchdog/Kconfig
include/linux/i2c/twl4030.h
kernel/printk.c
security/Kconfig

diff --cc Makefile
Simple merge
index 72b45cdfea53a5635d9bcbad1b0a9e3734814afb,dbfdf87f993f8849b44e16e0000384bb24d116f6..7b180ac738974501430635b069defcb03944b6c4
@@@ -1276,11 -1325,8 +1325,13 @@@ source "drivers/regulator/Kconfig
  
  source "drivers/uio/Kconfig"
  
+ source "drivers/staging/Kconfig"
 +if ARCH_OMAP
 +source "drivers/cbus/Kconfig"
 +source "drivers/dsp/dspgateway/Kconfig"
 +endif
 +
  endmenu
  
  source "fs/Kconfig"
Simple merge
Simple merge
Simple merge
index 7de7c69155840f2e84fddc23574bb9d74546afe5,4474da7bc88a0f613f2e4a544491b44bf6e889dd..ca7a0cc1707c29779bf3b6d9c279da4d558682c7
@@@ -17,7 -17,8 +17,9 @@@
  #include <linux/io.h>
  #include <linux/platform_device.h>
  
++#include <mach/irqs.h>
  #include <mach/dma.h>
+ #include <mach/irqs.h>
  #include <mach/mux.h>
  #include <mach/cpu.h>
  #include <mach/mcbsp.h>
index b40b29a2d791b8248891cc1976b9f2a6b3439c6b,acdc709901cd1ca55f231ac79be495e1e0e67dc7..1785d7a590c53b584a403a4e3e477dae2cbfd20c
@@@ -17,7 -17,8 +17,9 @@@
  #include <linux/io.h>
  #include <linux/platform_device.h>
  
++#include <mach/irqs.h>
  #include <mach/dma.h>
+ #include <mach/irqs.h>
  #include <mach/mux.h>
  #include <mach/cpu.h>
  #include <mach/mcbsp.h>
index 3e66a9a1519c23339567b5ef3b5ba0e08a9b2789,ae6036300f603521ce2b59267fee71d5f668e589..8351a34f3e19c1568c6cb64acf724c2068e1d206
@@@ -121,10 -118,9 +121,10 @@@ static void __init omap2_gp_clockevent_
        clockevent_gpt.max_delta_ns =
                clockevent_delta2ns(0xffffffff, &clockevent_gpt);
        clockevent_gpt.min_delta_ns =
 -              clockevent_delta2ns(1, &clockevent_gpt);
 +              clockevent_delta2ns(3, &clockevent_gpt);
 +              /* Timer internal resynch latency. */
  
-       clockevent_gpt.cpumask = cpumask_of_cpu(0);
+       clockevent_gpt.cpumask = cpumask_of(0);
        clockevents_register_device(&clockevent_gpt);
  }
  
Simple merge
Simple merge
Simple merge
index cc48f2f33d606310838539c4bdc1feb738f13cdd,6a0d1a0a24a7d86f2f767130de8ed9ea95073e3c..eef873db3d48f54f420da4b2840cf717b58b9aae
  #define OMAP_MCBSP_REG_XCERG  0x3A
  #define OMAP_MCBSP_REG_XCERH  0x3C
  
++/* Dummy defines, these are not available on omap1 */
++#define OMAP_MCBSP_REG_XCCR   0x00
++#define OMAP_MCBSP_REG_RCCR   0x00
++
  #define AUDIO_MCBSP_DATAWRITE (OMAP1510_MCBSP1_BASE + OMAP_MCBSP_REG_DXR1)
  #define AUDIO_MCBSP_DATAREAD  (OMAP1510_MCBSP1_BASE + OMAP_MCBSP_REG_DRR1)
  
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 2ca170bc7e0d2c4ec82d8e40ac9fadf4093c9184,59c3d23f5bdccdf54e0dbc7d5099e136ad7768e8..744ecbcc450cc6b690e22f19c35239fa90fd1f07
@@@ -1,4 -1,4 +1,4 @@@
--#
++
  # Miscellaneous I2C chip drivers configuration
  #
  # *** DEPRECATED! Do not add new entries! See Makefile ***
@@@ -114,48 -114,6 +114,35 @@@ config SENSORS_PCF859
          These devices are hard to detect and rarely found on mainstream
          hardware.  If unsure, say N.
  
- config TPS65010
-       tristate "TPS6501x Power Management chips"
-       depends on GPIOLIB
-       default y if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_OSK
-       help
-         If you say yes here you get support for the TPS6501x series of
-         Power Management chips.  These include voltage regulators,
-         lithium ion/polymer battery charging, and other features that
-         are often used in portable devices like cell phones and cameras.
-         This driver can also be built as a module.  If so, the module
-         will be called tps65010.
 +config TWL4030_MADC
 +      tristate "TWL4030 MADC Driver"
 +      depends on TWL4030_CORE
 +      help
 +        The TWL4030 Monitoring ADC driver enables the host
 +        processor to monitor analog signals using analog-to-digital
 +        conversions on the input source. TWL4030 MADC provides the
 +        following features:
 +         - Single 10-bit ADC with successive approximation register (SAR) conversion;
 +         - Analog multiplexer for 16 inputs;
 +         - Seven (of the 16) inputs are freely available;
 +         - Battery voltage monitoring;
 +         - Concurrent conversion request management;
 +         - Interrupt signal to Primary Interrupt Handler;
 +         - Averaging feature;
 +         - Selective enable/disable of the averaging feature.
 +
 +        Say 'y' here to statically link this module into the kernel or 'm'
 +        to build it as a dinamically loadable module. The module will be
 +        called twl4030-madc.ko
 +
 +config TWL4030_PWRBUTTON
 +      tristate "TWL4030 Power button Driver"
 +      depends on TWL4030_CORE
 +
 +config TWL4030_POWEROFF
 +      tristate "TWL4030 device poweroff"
 +      depends on TWL4030_CORE
 +
  config SENSORS_MAX6875
        tristate "Maxim MAX6875 Power supply supervisor"
        depends on EXPERIMENTAL
index 417e7fb7f7d29370cafe8e726c66d0e32a7089aa,83accaaf8164bfcc81397da82e363ee25e20434d..ffd8d0d1909dc9b5559b4e31d329d18834ebdfbe
@@@ -18,15 -18,8 +18,14 @@@ obj-$(CONFIG_SENSORS_PCA9539)       += pca953
  obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o
  obj-$(CONFIG_PCF8575)         += pcf8575.o
  obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
- obj-$(CONFIG_TPS65010)                += tps65010.o
 +obj-$(CONFIG_MENELAUS)                += menelaus.o
  obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o
  obj-$(CONFIG_MCU_MPC8349EMITX)        += mcu_mpc8349emitx.o
 +obj-$(CONFIG_TWL4030_POWEROFF)        += twl4030-poweroff.o
 +obj-$(CONFIG_TWL4030_PWRBUTTON)       += twl4030-pwrbutton.o
 +obj-$(CONFIG_TWL4030_MADC)    += twl4030-madc.o
 +obj-$(CONFIG_RTC_X1205_I2C)   += x1205.o
 +obj-$(CONFIG_LP5521)          += lp5521.o
  
  ifeq ($(CONFIG_I2C_DEBUG_CHIP),y)
  EXTRA_CFLAGS += -DDEBUG
Simple merge
index ae47fffacc6852798d0f094b078cb71d780125fc,36351e1190f9e2db8d49da0ac1b6a941c8b547d1..27c4f1dc4b20c3285b93ed11f57b0e9d4834c79f
@@@ -19,11 -19,8 +19,12 @@@ obj-$(CONFIG_KEYBOARD_TOSA)         += tosakbd
  obj-$(CONFIG_KEYBOARD_HIL)            += hil_kbd.o
  obj-$(CONFIG_KEYBOARD_HIL_OLD)                += hilkbd.o
  obj-$(CONFIG_KEYBOARD_OMAP)           += omap-keypad.o
 +obj-$(CONFIG_OMAP_PS2)                        += innovator_ps2.o
 +obj-$(CONFIG_KEYBOARD_TSC2301)                += tsc2301_kp.o
 +obj-$(CONFIG_KEYBOARD_LM8323)         += lm8323.o
 +obj-$(CONFIG_KEYBOARD_TWL4030)                += omap-twl4030keypad.o
  obj-$(CONFIG_KEYBOARD_PXA27x)         += pxa27x_keypad.o
+ obj-$(CONFIG_KEYBOARD_PXA930_ROTARY)  += pxa930_rotary.o
  obj-$(CONFIG_KEYBOARD_AAED2000)               += aaed2000_kbd.o
  obj-$(CONFIG_KEYBOARD_GPIO)           += gpio_keys.o
  obj-$(CONFIG_KEYBOARD_HP6XX)          += jornada680_kbd.o
Simple merge
Simple merge
Simple merge
index 6c1236d2a56315e709b21d56ca5d04a173261a3d,0c9418b36c2692a8c700f9f7f69222a4de774419..7ca14f45771025168a1199ab4a15b738f5eee0d5
@@@ -17,8 -19,10 +19,11 @@@ wm8350-objs                 := wm8350-core.o wm8350-r
  obj-$(CONFIG_MFD_WM8350)      += wm8350.o
  obj-$(CONFIG_MFD_WM8350_I2C)  += wm8350-i2c.o
  
+ obj-$(CONFIG_TPS65010)                += tps65010.o
+ obj-$(CONFIG_MENELAUS)                += menelaus.o
  obj-$(CONFIG_TWL4030_CORE)    += twl4030-core.o twl4030-irq.o
 +obj-$(CONFIG_TWL4030_POWER)    += twl4030-power.o
  
  obj-$(CONFIG_MFD_CORE)                += mfd-core.o
  
index 1b178cd40131899a33c5c3049cc1b890af0e2c79,b59c385cbc12f98bc319845d719fc83e518c8dc0..7e7f0db2005d74bef2450ccea9923e733f62b8a8
@@@ -38,6 -38,6 +38,9 @@@
  #include <linux/i2c.h>
  #include <linux/i2c/twl4030.h>
  
++#ifdef CONFIG_ARM
++#include <mach/cpu.h>
++#endif
  
  /*
   * The TWL4030 "Triton 2" is one of a family of a multi-function "Power
index a11e2a0a823b4077a61ed08ac45d095f45691cd3,419c378bd24b334d5645fa6a35ef5a3b8c158dd0..f1c5f83612aa0f62b1ecf45d207a1903ce0ecf4e
@@@ -413,43 -158,6 +158,20 @@@ config ATMEL_SS
  
          If unsure, say N.
  
- config INTEL_MENLOW
-       tristate "Thermal Management driver for Intel menlow platform"
-       depends on ACPI_THERMAL
-       select THERMAL
-       depends on X86
-       ---help---
-         ACPI thermal management enhancement driver on
-         Intel Menlow platform.
-         If unsure, say N.
- config EEEPC_LAPTOP
-       tristate "Eee PC Hotkey Driver (EXPERIMENTAL)"
-       depends on X86
-       depends on ACPI
-       depends on BACKLIGHT_CLASS_DEVICE
-       depends on HWMON
-       depends on EXPERIMENTAL
-       depends on RFKILL
-       ---help---
-         This driver supports the Fn-Fx keys on Eee PC laptops.
-         It also adds the ability to switch camera/wlan on/off.
 +config OMAP_STI
 +      bool "Serial Trace Interface support"
 +      depends on ARCH_OMAP16XX || ARCH_OMAP24XX || ARCH_OMAP34XX
 +      default n
 +      help
 +        Serial Trace Interface. The protocols suported for OMAP1/2/3 are
 +        STI/CSTI/XTIv2 correspondingly.
 +
 +config OMAP_STI_CONSOLE
 +      bool "STI console support"
 +      depends on OMAP_STI
 +      help
 +        This enables a console driver by way of STI/XTI.
 +
  config ENCLOSURE_SERVICES
        tristate "Enclosure Services"
        default n
index 78be134a80914feba6d6be5181079bfb3cd20519,9cf8ae6e4b39f53107cf46887ee4b70633ccd5db..9f066265f30bc2a8e53902af2f4ebbfd3405624d
@@@ -22,12 -14,7 +14,8 @@@ obj-$(CONFIG_DELL_LAPTOP)    += dell-lapto
  obj-$(CONFIG_TIFM_7XX1)               += tifm_7xx1.o
  obj-$(CONFIG_PHANTOM)         += phantom.o
  obj-$(CONFIG_SGI_IOC4)                += ioc4.o
- obj-$(CONFIG_SONY_LAPTOP)     += sony-laptop.o
- obj-$(CONFIG_THINKPAD_ACPI)   += thinkpad_acpi.o
- obj-$(CONFIG_FUJITSU_LAPTOP)  += fujitsu-laptop.o
- obj-$(CONFIG_PANASONIC_LAPTOP)        += panasonic-laptop.o
  obj-$(CONFIG_EEPROM_93CX6)    += eeprom_93cx6.o
- obj-$(CONFIG_INTEL_MENLOW)    += intel_menlow.o
++obj-$(CONFIG_OMAP_STI)                += sti/
  obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o
  obj-$(CONFIG_KGDB_TESTS)      += kgdbts.o
  obj-$(CONFIG_SGI_XP)          += sgi-xp/
Simple merge
index d5c1e9d7e6bd45d1436b7099d8e1b2a459e164da,0000000000000000000000000000000000000000..70d8d78a2a468837a887d99210e642866ae01b4b
mode 100644,000000..100644
--- /dev/null
@@@ -1,1302 -1,0 +1,1302 @@@
- #include <asm/dma.h>
 +/*
 + * drivers/mmc/host/omap_hsmmc.c
 + *
 + * Driver for OMAP2430/3430 MMC controller.
 + *
 + * Copyright (C) 2007 Texas Instruments.
 + *
 + * Authors:
 + *    Syed Mohammed Khasim    <x0khasim@ti.com>
 + *    Madhusudhan             <madhu.cr@ti.com>
 + *    Mohit Jalori            <mjalori@ti.com>
 + *
 + * 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/module.h>
 +#include <linux/init.h>
 +#include <linux/interrupt.h>
 +#include <linux/delay.h>
 +#include <linux/dma-mapping.h>
 +#include <linux/platform_device.h>
 +#include <linux/workqueue.h>
 +#include <linux/timer.h>
 +#include <linux/clk.h>
 +#include <linux/mmc/host.h>
 +#include <linux/io.h>
 +#include <linux/semaphore.h>
++#include <mach/dma.h>
 +#include <mach/hardware.h>
 +#include <mach/board.h>
 +#include <mach/mmc.h>
 +#include <mach/cpu.h>
 +
 +/* OMAP HSMMC Host Controller Registers */
 +#define OMAP_HSMMC_SYSCONFIG  0x0010
 +#define OMAP_HSMMC_CON                0x002C
 +#define OMAP_HSMMC_BLK                0x0104
 +#define OMAP_HSMMC_ARG                0x0108
 +#define OMAP_HSMMC_CMD                0x010C
 +#define OMAP_HSMMC_RSP10      0x0110
 +#define OMAP_HSMMC_RSP32      0x0114
 +#define OMAP_HSMMC_RSP54      0x0118
 +#define OMAP_HSMMC_RSP76      0x011C
 +#define OMAP_HSMMC_DATA               0x0120
 +#define OMAP_HSMMC_HCTL               0x0128
 +#define OMAP_HSMMC_SYSCTL     0x012C
 +#define OMAP_HSMMC_STAT               0x0130
 +#define OMAP_HSMMC_IE         0x0134
 +#define OMAP_HSMMC_ISE                0x0138
 +#define OMAP_HSMMC_CAPA               0x0140
 +
 +#define VS18                  (1 << 26)
 +#define VS30                  (1 << 25)
 +#define SDVS18                        (0x5 << 9)
 +#define SDVS30                        (0x6 << 9)
 +#define SDVSCLR                       0xFFFFF1FF
 +#define SDVSDET                       0x00000400
 +#define AUTOIDLE              0x1
 +#define SDBP                  (1 << 8)
 +#define DTO                   0xe
 +#define ICE                   0x1
 +#define ICS                   0x2
 +#define CEN                   (1 << 2)
 +#define CLKD_MASK             0x0000FFC0
 +#define CLKD_SHIFT            6
 +#define DTO_MASK              0x000F0000
 +#define DTO_SHIFT             16
 +#define INT_EN_MASK           0x307F0033
 +#define INIT_STREAM           (1 << 1)
 +#define DP_SELECT             (1 << 21)
 +#define DDIR                  (1 << 4)
 +#define DMA_EN                        0x1
 +#define MSBS                  (1 << 5)
 +#define BCE                   (1 << 1)
 +#define FOUR_BIT              (1 << 1)
 +#define CC                    0x1
 +#define TC                    0x02
 +#define OD                    0x1
 +#define ERR                   (1 << 15)
 +#define CMD_TIMEOUT           (1 << 16)
 +#define DATA_TIMEOUT          (1 << 20)
 +#define CMD_CRC                       (1 << 17)
 +#define DATA_CRC              (1 << 21)
 +#define CARD_ERR              (1 << 28)
 +#define STAT_CLEAR            0xFFFFFFFF
 +#define INIT_STREAM_CMD               0x00000000
 +#define DUAL_VOLT_OCR_BIT     7
 +#define SRC                   (1 << 25)
 +#define SRD                   (1 << 26)
 +
 +/*
 + * FIXME: Most likely all the data using these _DEVID defines should come
 + * from the platform_data, or implemented in controller and slot specific
 + * functions.
 + */
 +#define OMAP_MMC1_DEVID               0
 +#define OMAP_MMC2_DEVID               1
 +
 +#define OMAP_MMC_DATADIR_NONE 0
 +#define OMAP_MMC_DATADIR_READ 1
 +#define OMAP_MMC_DATADIR_WRITE        2
 +#define MMC_TIMEOUT_MS                20
 +#define OMAP_MMC_MASTER_CLOCK 96000000
 +#define DRIVER_NAME           "mmci-omap-hs"
 +
 +/*
 + * One controller can have multiple slots, like on some omap boards using
 + * omap.c controller driver. Luckily this is not currently done on any known
 + * omap_hsmmc.c device.
 + */
 +#define mmc_slot(host)                (host->pdata->slots[host->slot_id])
 +
 +/*
 + * MMC Host controller read/write API's
 + */
 +#define OMAP_HSMMC_READ(base, reg)    \
 +      __raw_readl((base) + OMAP_HSMMC_##reg)
 +
 +#define OMAP_HSMMC_WRITE(base, reg, val) \
 +      __raw_writel((val), (base) + OMAP_HSMMC_##reg)
 +
 +enum {OFF = 0, ON};
 +#define IDLE_TIMEOUT (jiffies_to_msecs(10))
 +
 +struct mmc_omap_host {
 +      struct  device          *dev;
 +      struct  mmc_host        *mmc;
 +      struct  mmc_request     *mrq;
 +      struct  mmc_command     *cmd;
 +      struct  mmc_data        *data;
 +      struct  clk             *fclk;
 +      struct  clk             *iclk;
 +      struct  clk             *dbclk;
 +      struct  semaphore       sem;
 +      struct  work_struct     mmc_carddetect_work;
 +      void    __iomem         *base;
 +      resource_size_t         mapbase;
 +      unsigned int            id;
 +      unsigned int            dma_len;
 +      unsigned int            dma_dir;
 +      unsigned char           bus_mode;
 +      unsigned char           datadir;
 +      u32                     *buffer;
 +      u32                     bytesleft;
 +      int                     suspended;
 +      int                     irq;
 +      int                     carddetect;
 +      int                     use_dma, dma_ch;
 +      int                     initstr;
 +      int                     slot_id;
 +      int                     dbclk_enabled;
 +
 +      struct timer_list       idle_timer;
 +      spinlock_t              clk_lock;     /* for changing enabled state */
 +      unsigned int            fclk_enabled:1;
 +
 +      struct  omap_mmc_platform_data  *pdata;
 +};
 +
 +static int mmc_omap_fclk_state(struct mmc_omap_host *host, unsigned int state)
 +{
 +      unsigned long flags;
 +      int ret = 0;
 +
 +      spin_lock_irqsave(&host->clk_lock, flags);
 +      del_timer(&host->idle_timer);
 +      if (host->fclk_enabled != state) {
 +              if (state == ON) {
 +                      ret = clk_enable(host->fclk);
 +                      if (ret != 0)
 +                              goto err_out;
 +
 +                      dev_dbg(mmc_dev(host->mmc), "mmc_fclk: enabled\n");
 +              } else {
 +                      clk_disable(host->fclk);
 +                      dev_dbg(mmc_dev(host->mmc), "mmc_fclk: disabled\n");
 +              }
 +              host->fclk_enabled = state;
 +      }
 +
 +err_out:
 +      spin_unlock_irqrestore(&host->clk_lock, flags);
 +      return ret;
 +}
 +
 +static void mmc_omap_idle_timer(unsigned long data)
 +{
 +      struct mmc_omap_host *host = (struct mmc_omap_host *) data;
 +
 +      mmc_omap_fclk_state(host, OFF);
 +}
 +
 +static void mmc_omap_fclk_lazy_disable(struct mmc_omap_host *host)
 +{
 +      mod_timer(&host->idle_timer, jiffies + IDLE_TIMEOUT);
 +}
 +
 +/*
 + * Stop clock to the card
 + */
 +static void omap_mmc_stop_clock(struct mmc_omap_host *host)
 +{
 +      OMAP_HSMMC_WRITE(host->base, SYSCTL,
 +              OMAP_HSMMC_READ(host->base, SYSCTL) & ~CEN);
 +      if ((OMAP_HSMMC_READ(host->base, SYSCTL) & CEN) != 0x0)
 +              dev_dbg(mmc_dev(host->mmc), "MMC Clock is not stoped\n");
 +}
 +
 +/*
 + * Send init stream sequence to card
 + * before sending IDLE command
 + */
 +static void send_init_stream(struct mmc_omap_host *host)
 +{
 +      int reg = 0;
 +      unsigned long timeout;
 +
 +      disable_irq(host->irq);
 +      OMAP_HSMMC_WRITE(host->base, CON,
 +              OMAP_HSMMC_READ(host->base, CON) | INIT_STREAM);
 +      OMAP_HSMMC_WRITE(host->base, CMD, INIT_STREAM_CMD);
 +
 +      timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS);
 +      while ((reg != CC) && time_before(jiffies, timeout))
 +              reg = OMAP_HSMMC_READ(host->base, STAT) & CC;
 +
 +      OMAP_HSMMC_WRITE(host->base, CON,
 +              OMAP_HSMMC_READ(host->base, CON) & ~INIT_STREAM);
 +      enable_irq(host->irq);
 +}
 +
 +static inline
 +int mmc_omap_cover_is_closed(struct mmc_omap_host *host)
 +{
 +      int r = 1;
 +
 +      if (host->pdata->slots[host->slot_id].get_cover_state)
 +              r = host->pdata->slots[host->slot_id].get_cover_state(host->dev,
 +                      host->slot_id);
 +      return r;
 +}
 +
 +static ssize_t
 +mmc_omap_show_cover_switch(struct device *dev, struct device_attribute *attr,
 +                         char *buf)
 +{
 +      struct mmc_host *mmc = container_of(dev, struct mmc_host, class_dev);
 +      struct mmc_omap_host *host = mmc_priv(mmc);
 +
 +      return sprintf(buf, "%s\n", mmc_omap_cover_is_closed(host) ? "closed" :
 +                     "open");
 +}
 +
 +static DEVICE_ATTR(cover_switch, S_IRUGO, mmc_omap_show_cover_switch, NULL);
 +
 +static ssize_t
 +mmc_omap_show_slot_name(struct device *dev, struct device_attribute *attr,
 +                      char *buf)
 +{
 +      struct mmc_host *mmc = container_of(dev, struct mmc_host, class_dev);
 +      struct mmc_omap_host *host = mmc_priv(mmc);
 +      struct omap_mmc_slot_data slot = host->pdata->slots[host->slot_id];
 +
 +      return sprintf(buf, "slot:%s\n", slot.name);
 +}
 +
 +static DEVICE_ATTR(slot_name, S_IRUGO, mmc_omap_show_slot_name, NULL);
 +
 +/*
 + * Configure the response type and send the cmd.
 + */
 +static void
 +mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd,
 +      struct mmc_data *data)
 +{
 +      int cmdreg = 0, resptype = 0, cmdtype = 0;
 +
 +      dev_dbg(mmc_dev(host->mmc), "%s: CMD%d, argument 0x%08x\n",
 +              mmc_hostname(host->mmc), cmd->opcode, cmd->arg);
 +      host->cmd = cmd;
 +
 +      /*
 +       * Clear status bits and enable interrupts
 +       */
 +      OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
 +      OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK);
 +      OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK);
 +
 +      if (cmd->flags & MMC_RSP_PRESENT) {
 +              if (cmd->flags & MMC_RSP_136)
 +                      resptype = 1;
 +              else
 +                      resptype = 2;
 +      }
 +
 +      /*
 +       * Unlike OMAP1 controller, the cmdtype does not seem to be based on
 +       * ac, bc, adtc, bcr. Only commands ending an open ended transfer need
 +       * a val of 0x3, rest 0x0.
 +       */
 +      if (cmd == host->mrq->stop)
 +              cmdtype = 0x3;
 +
 +      cmdreg = (cmd->opcode << 24) | (resptype << 16) | (cmdtype << 22);
 +
 +      if (data) {
 +              cmdreg |= DP_SELECT | MSBS | BCE;
 +              if (data->flags & MMC_DATA_READ)
 +                      cmdreg |= DDIR;
 +              else
 +                      cmdreg &= ~(DDIR);
 +      }
 +
 +      if (host->use_dma)
 +              cmdreg |= DMA_EN;
 +
 +      OMAP_HSMMC_WRITE(host->base, ARG, cmd->arg);
 +      OMAP_HSMMC_WRITE(host->base, CMD, cmdreg);
 +}
 +
 +/*
 + * Notify the transfer complete to MMC core
 + */
 +static void
 +mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data)
 +{
 +      host->data = NULL;
 +
 +      if (host->use_dma && host->dma_ch != -1)
 +              dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_len,
 +                      host->dma_dir);
 +
 +      host->datadir = OMAP_MMC_DATADIR_NONE;
 +
 +      if (!data->error)
 +              data->bytes_xfered += data->blocks * (data->blksz);
 +      else
 +              data->bytes_xfered = 0;
 +
 +      if (!data->stop) {
 +              host->mrq = NULL;
 +              mmc_omap_fclk_lazy_disable(host);
 +              mmc_request_done(host->mmc, data->mrq);
 +              return;
 +      }
 +      mmc_omap_start_command(host, data->stop, NULL);
 +}
 +
 +/*
 + * Notify the core about command completion
 + */
 +static void
 +mmc_omap_cmd_done(struct mmc_omap_host *host, struct mmc_command *cmd)
 +{
 +      host->cmd = NULL;
 +
 +      if (cmd->flags & MMC_RSP_PRESENT) {
 +              if (cmd->flags & MMC_RSP_136) {
 +                      /* response type 2 */
 +                      cmd->resp[3] = OMAP_HSMMC_READ(host->base, RSP10);
 +                      cmd->resp[2] = OMAP_HSMMC_READ(host->base, RSP32);
 +                      cmd->resp[1] = OMAP_HSMMC_READ(host->base, RSP54);
 +                      cmd->resp[0] = OMAP_HSMMC_READ(host->base, RSP76);
 +              } else {
 +                      /* response types 1, 1b, 3, 4, 5, 6 */
 +                      cmd->resp[0] = OMAP_HSMMC_READ(host->base, RSP10);
 +              }
 +      }
 +      if (host->data == NULL || cmd->error) {
 +              host->mrq = NULL;
 +              mmc_omap_fclk_lazy_disable(host);
 +              mmc_request_done(host->mmc, cmd->mrq);
 +      }
 +}
 +
 +/*
 + * DMA clean up for command errors
 + */
 +static void mmc_dma_cleanup(struct mmc_omap_host *host)
 +{
 +      host->data->error = -ETIMEDOUT;
 +
 +      if (host->use_dma && host->dma_ch != -1) {
 +              dma_unmap_sg(mmc_dev(host->mmc), host->data->sg, host->dma_len,
 +                      host->dma_dir);
 +              omap_free_dma(host->dma_ch);
 +              host->dma_ch = -1;
 +              up(&host->sem);
 +      }
 +      host->data = NULL;
 +      host->datadir = OMAP_MMC_DATADIR_NONE;
 +}
 +
 +/*
 + * Readable error output
 + */
 +#ifdef CONFIG_MMC_DEBUG
 +static void mmc_omap_report_irq(struct mmc_omap_host *host, u32 status)
 +{
 +      /* --- means reserved bit without definition at documentation */
 +      static const char *mmc_omap_status_bits[] = {
 +              "CC", "TC", "BGE", "---", "BWR", "BRR", "---", "---", "CIRQ",
 +              "OBI", "---", "---", "---", "---", "---", "ERRI", "CTO", "CCRC",
 +              "CEB", "CIE", "DTO", "DCRC", "DEB", "---", "ACE", "---",
 +              "---", "---", "---", "CERR", "CERR", "BADA", "---", "---", "---"
 +      };
 +      char res[256];
 +      char *buf = res;
 +      int len, i;
 +
 +      len = sprintf(buf, "MMC IRQ 0x%x :", status);
 +      buf += len;
 +
 +      for (i = 0; i < ARRAY_SIZE(mmc_omap_status_bits); i++)
 +              if (status & (1 << i)) {
 +                      len = sprintf(buf, " %s", mmc_omap_status_bits[i]);
 +                      buf += len;
 +              }
 +
 +      dev_dbg(mmc_dev(host->mmc), "%s\n", res);
 +}
 +#endif  /* CONFIG_MMC_DEBUG */
 +
 +
 +/*
 + * MMC controller IRQ handler
 + */
 +static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
 +{
 +      struct mmc_omap_host *host = dev_id;
 +      struct mmc_data *data;
 +      int end_cmd = 0, end_trans = 0, status;
 +
 +      if (host->cmd == NULL && host->data == NULL) {
 +              OMAP_HSMMC_WRITE(host->base, STAT,
 +                      OMAP_HSMMC_READ(host->base, STAT));
 +              return IRQ_HANDLED;
 +      }
 +
 +      data = host->data;
 +      status = OMAP_HSMMC_READ(host->base, STAT);
 +      dev_dbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status);
 +
 +      if (status & ERR) {
 +#ifdef CONFIG_MMC_DEBUG
 +              mmc_omap_report_irq(host, status);
 +#endif
 +              if ((status & CMD_TIMEOUT) ||
 +                      (status & CMD_CRC)) {
 +                      if (host->cmd) {
 +                              if (status & CMD_TIMEOUT) {
 +                                      OMAP_HSMMC_WRITE(host->base, SYSCTL,
 +                                              OMAP_HSMMC_READ(host->base,
 +                                                              SYSCTL) | SRC);
 +                                      while (OMAP_HSMMC_READ(host->base,
 +                                                      SYSCTL) & SRC)
 +                                              ;
 +
 +                                      host->cmd->error = -ETIMEDOUT;
 +                              } else {
 +                                      host->cmd->error = -EILSEQ;
 +                              }
 +                              end_cmd = 1;
 +                      }
 +                      if (host->data)
 +                              mmc_dma_cleanup(host);
 +              }
 +              if ((status & DATA_TIMEOUT) ||
 +                      (status & DATA_CRC)) {
 +                      if (host->data) {
 +                              if (status & DATA_TIMEOUT)
 +                                      mmc_dma_cleanup(host);
 +                              else
 +                                      host->data->error = -EILSEQ;
 +                              OMAP_HSMMC_WRITE(host->base, SYSCTL,
 +                                      OMAP_HSMMC_READ(host->base,
 +                                                      SYSCTL) | SRD);
 +                              while (OMAP_HSMMC_READ(host->base,
 +                                              SYSCTL) & SRD)
 +                                      ;
 +                              end_trans = 1;
 +                      }
 +              }
 +              if (status & CARD_ERR) {
 +                      dev_dbg(mmc_dev(host->mmc),
 +                              "Ignoring card err CMD%d\n", host->cmd->opcode);
 +                      if (host->cmd)
 +                              end_cmd = 1;
 +                      if (host->data)
 +                              end_trans = 1;
 +              }
 +      }
 +
 +      OMAP_HSMMC_WRITE(host->base, STAT, status);
 +
 +      if (end_cmd || (status & CC))
 +              mmc_omap_cmd_done(host, host->cmd);
 +      if (end_trans || (status & TC))
 +              mmc_omap_xfer_done(host, data);
 +
 +      return IRQ_HANDLED;
 +}
 +
 +/*
 + * Switch MMC operating voltage
 + */
 +static int omap_mmc_switch_opcond(struct mmc_omap_host *host, int vdd)
 +{
 +      u32 reg_val = 0;
 +      int ret;
 +
 +      /* Disable the clocks */
 +      mmc_omap_fclk_state(host, OFF);
 +      clk_disable(host->iclk);
 +      clk_disable(host->dbclk);
 +
 +      /* Turn the power off */
 +      ret = mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0);
 +      if (ret != 0)
 +              goto err;
 +
 +      /* Turn the power ON with given VDD 1.8 or 3.0v */
 +      ret = mmc_slot(host).set_power(host->dev, host->slot_id, 1, vdd);
 +      if (ret != 0)
 +              goto err;
 +
 +      mmc_omap_fclk_state(host, ON);
 +      clk_enable(host->iclk);
 +      clk_enable(host->dbclk);
 +
 +      OMAP_HSMMC_WRITE(host->base, HCTL,
 +              OMAP_HSMMC_READ(host->base, HCTL) & SDVSCLR);
 +      reg_val = OMAP_HSMMC_READ(host->base, HCTL);
 +      /*
 +       * If a MMC dual voltage card is detected, the set_ios fn calls
 +       * this fn with VDD bit set for 1.8V. Upon card removal from the
 +       * slot, omap_mmc_set_ios sets the VDD back to 3V on MMC_POWER_OFF.
 +       *
 +       * Only MMC1 supports 3.0V.  MMC2 will not function if SDVS30 is
 +       * set in HCTL.
 +       */
 +      if (host->id == OMAP_MMC1_DEVID) {
 +              if (((1 << vdd) == MMC_VDD_32_33) ||
 +                  ((1 << vdd) == MMC_VDD_33_34))
 +                      reg_val |= SDVS30;
 +              else if ((1 << vdd) == MMC_VDD_165_195)
 +                      reg_val |= SDVS18;
 +      } else
 +              reg_val |= SDVS18;
 +
 +      OMAP_HSMMC_WRITE(host->base, HCTL, reg_val);
 +
 +      OMAP_HSMMC_WRITE(host->base, HCTL,
 +              OMAP_HSMMC_READ(host->base, HCTL) | SDBP);
 +
 +      return 0;
 +err:
 +      dev_dbg(mmc_dev(host->mmc), "Unable to switch operating voltage\n");
 +      return ret;
 +}
 +
 +/*
 + * Work Item to notify the core about card insertion/removal
 + */
 +static void mmc_omap_detect(struct work_struct *work)
 +{
 +      struct mmc_omap_host *host = container_of(work, struct mmc_omap_host,
 +                                              mmc_carddetect_work);
 +
 +      sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch");
 +      mmc_omap_fclk_state(host, ON);
 +      if (host->carddetect) {
 +              mmc_detect_change(host->mmc, (HZ * 200) / 1000);
 +      } else {
 +              OMAP_HSMMC_WRITE(host->base, SYSCTL,
 +                      OMAP_HSMMC_READ(host->base, SYSCTL) | SRD);
 +              while (OMAP_HSMMC_READ(host->base, SYSCTL) & SRD)
 +                      ;
 +
 +              mmc_detect_change(host->mmc, (HZ * 50) / 1000);
 +      }
 +      mmc_omap_fclk_lazy_disable(host);
 +}
 +
 +/*
 + * ISR for handling card insertion and removal
 + */
 +static irqreturn_t omap_mmc_cd_handler(int irq, void *dev_id)
 +{
 +      struct mmc_omap_host *host = (struct mmc_omap_host *)dev_id;
 +
 +      host->carddetect = mmc_slot(host).card_detect(irq);
 +      schedule_work(&host->mmc_carddetect_work);
 +
 +      return IRQ_HANDLED;
 +}
 +
 +/*
 + * DMA call back function
 + */
 +static void mmc_omap_dma_cb(int lch, u16 ch_status, void *data)
 +{
 +      struct mmc_omap_host *host = data;
 +
 +      if (ch_status & OMAP2_DMA_MISALIGNED_ERR_IRQ)
 +              dev_dbg(mmc_dev(host->mmc), "MISALIGNED_ADRS_ERR\n");
 +
 +      if (host->dma_ch < 0)
 +              return;
 +
 +      omap_free_dma(host->dma_ch);
 +      host->dma_ch = -1;
 +      /*
 +       * DMA Callback: run in interrupt context.
 +       * mutex_unlock will through a kernel warning if used.
 +       */
 +      up(&host->sem);
 +}
 +
 +/*
 + * Configure dma src and destination parameters
 + */
 +static int mmc_omap_config_dma_param(int sync_dir, struct mmc_omap_host *host,
 +                              struct mmc_data *data)
 +{
 +      if (sync_dir == 0) {
 +              omap_set_dma_dest_params(host->dma_ch, 0,
 +                      OMAP_DMA_AMODE_CONSTANT,
 +                      (host->mapbase + OMAP_HSMMC_DATA), 0, 0);
 +              omap_set_dma_src_params(host->dma_ch, 0,
 +                      OMAP_DMA_AMODE_POST_INC,
 +                      sg_dma_address(&data->sg[0]), 0, 0);
 +      } else {
 +              omap_set_dma_src_params(host->dma_ch, 0,
 +                      OMAP_DMA_AMODE_CONSTANT,
 +                      (host->mapbase + OMAP_HSMMC_DATA), 0, 0);
 +              omap_set_dma_dest_params(host->dma_ch, 0,
 +                      OMAP_DMA_AMODE_POST_INC,
 +                      sg_dma_address(&data->sg[0]), 0, 0);
 +      }
 +      return 0;
 +}
 +/*
 + * Routine to configure and start DMA for the MMC card
 + */
 +static int
 +mmc_omap_start_dma_transfer(struct mmc_omap_host *host, struct mmc_request *req)
 +{
 +      int sync_dev, sync_dir = 0;
 +      int dma_ch = 0, ret = 0, err = 1;
 +      struct mmc_data *data = req->data;
 +
 +      /*
 +       * If for some reason the DMA transfer is still active,
 +       * we wait for timeout period and free the dma
 +       */
 +      if (host->dma_ch != -1) {
 +              set_current_state(TASK_UNINTERRUPTIBLE);
 +              schedule_timeout(100);
 +              if (down_trylock(&host->sem)) {
 +                      omap_free_dma(host->dma_ch);
 +                      host->dma_ch = -1;
 +                      up(&host->sem);
 +                      return err;
 +              }
 +      } else {
 +              if (down_trylock(&host->sem))
 +                      return err;
 +      }
 +
 +      if (!(data->flags & MMC_DATA_WRITE)) {
 +              host->dma_dir = DMA_FROM_DEVICE;
 +              if (host->id == OMAP_MMC1_DEVID)
 +                      sync_dev = OMAP24XX_DMA_MMC1_RX;
 +              else
 +                      sync_dev = OMAP24XX_DMA_MMC2_RX;
 +      } else {
 +              host->dma_dir = DMA_TO_DEVICE;
 +              if (host->id == OMAP_MMC1_DEVID)
 +                      sync_dev = OMAP24XX_DMA_MMC1_TX;
 +              else
 +                      sync_dev = OMAP24XX_DMA_MMC2_TX;
 +      }
 +
 +      ret = omap_request_dma(sync_dev, "MMC/SD", mmc_omap_dma_cb,
 +                      host, &dma_ch);
 +      if (ret != 0) {
 +              dev_dbg(mmc_dev(host->mmc),
 +                      "%s: omap_request_dma() failed with %d\n",
 +                      mmc_hostname(host->mmc), ret);
 +              return ret;
 +      }
 +
 +      host->dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg,
 +                      data->sg_len, host->dma_dir);
 +      host->dma_ch = dma_ch;
 +
 +      if (!(data->flags & MMC_DATA_WRITE))
 +              mmc_omap_config_dma_param(1, host, data);
 +      else
 +              mmc_omap_config_dma_param(0, host, data);
 +
 +      if ((data->blksz % 4) == 0)
 +              omap_set_dma_transfer_params(dma_ch, OMAP_DMA_DATA_TYPE_S32,
 +                      (data->blksz / 4), data->blocks, OMAP_DMA_SYNC_FRAME,
 +                      sync_dev, sync_dir);
 +      else
 +              /* REVISIT: The MMC buffer increments only when MSB is written.
 +               * Return error for blksz which is non multiple of four.
 +               */
 +              return -EINVAL;
 +
 +      omap_start_dma(dma_ch);
 +      return 0;
 +}
 +
 +static void set_data_timeout(struct mmc_omap_host *host,
 +                           struct mmc_request *req)
 +{
 +      unsigned int timeout, cycle_ns;
 +      uint32_t reg, clkd, dto = 0;
 +
 +      reg = OMAP_HSMMC_READ(host->base, SYSCTL);
 +      clkd = (reg & CLKD_MASK) >> CLKD_SHIFT;
 +      if (clkd == 0)
 +              clkd = 1;
 +
 +      cycle_ns = 1000000000 / (clk_get_rate(host->fclk) / clkd);
 +      timeout = req->data->timeout_ns / cycle_ns;
 +      timeout += req->data->timeout_clks;
 +      if (timeout) {
 +              while ((timeout & 0x80000000) == 0) {
 +                      dto += 1;
 +                      timeout <<= 1;
 +              }
 +              dto = 31 - dto;
 +              timeout <<= 1;
 +              if (timeout && dto)
 +                      dto += 1;
 +              if (dto >= 13)
 +                      dto -= 13;
 +              else
 +                      dto = 0;
 +              if (dto > 14)
 +                      dto = 14;
 +      }
 +
 +      reg &= ~DTO_MASK;
 +      reg |= dto << DTO_SHIFT;
 +      OMAP_HSMMC_WRITE(host->base, SYSCTL, reg);
 +}
 +
 +/*
 + * Configure block length for MMC/SD cards and initiate the transfer.
 + */
 +static int
 +mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req)
 +{
 +      int ret;
 +      host->data = req->data;
 +
 +      if (req->data == NULL) {
 +              host->datadir = OMAP_MMC_DATADIR_NONE;
 +              OMAP_HSMMC_WRITE(host->base, BLK, 0);
 +              return 0;
 +      }
 +
 +      OMAP_HSMMC_WRITE(host->base, BLK, (req->data->blksz)
 +                                      | (req->data->blocks << 16));
 +      set_data_timeout(host, req);
 +
 +      host->datadir = (req->data->flags & MMC_DATA_WRITE) ?
 +                      OMAP_MMC_DATADIR_WRITE : OMAP_MMC_DATADIR_READ;
 +
 +      if (host->use_dma) {
 +              ret = mmc_omap_start_dma_transfer(host, req);
 +              if (ret != 0) {
 +                      dev_dbg(mmc_dev(host->mmc), "MMC start dma failure\n");
 +                      return ret;
 +              }
 +      }
 +      return 0;
 +}
 +
 +/*
 + * Request function. for read/write operation
 + */
 +static void omap_mmc_request(struct mmc_host *mmc, struct mmc_request *req)
 +{
 +      struct mmc_omap_host *host = mmc_priv(mmc);
 +
 +      WARN_ON(host->mrq != NULL);
 +      host->mrq = req;
 +      mmc_omap_fclk_state(host, ON);
 +      mmc_omap_prepare_data(host, req);
 +      mmc_omap_start_command(host, req->cmd, req->data);
 +}
 +
 +/* Routine to configure clock values. Exposed API to core */
 +static void omap_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 +{
 +      struct mmc_omap_host *host = mmc_priv(mmc);
 +      u16 dsor = 0;
 +      unsigned long regval;
 +      unsigned long timeout;
 +
 +      mmc_omap_fclk_state(host, ON);
 +
 +      switch (ios->power_mode) {
 +      case MMC_POWER_OFF:
 +              mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0);
 +              /*
 +               * Reset bus voltage to 3V if it got set to 1.8V earlier.
 +               * REVISIT: If we are able to detect cards after unplugging
 +               * a 1.8V card, this code should not be needed.
 +               */
 +              if (!(OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET)) {
 +                      int vdd = fls(host->mmc->ocr_avail) - 1;
 +                      if (omap_mmc_switch_opcond(host, vdd) != 0)
 +                              host->mmc->ios.vdd = vdd;
 +              }
 +              break;
 +      case MMC_POWER_UP:
 +              mmc_slot(host).set_power(host->dev, host->slot_id, 1, ios->vdd);
 +              break;
 +      }
 +
 +      switch (mmc->ios.bus_width) {
 +      case MMC_BUS_WIDTH_4:
 +              OMAP_HSMMC_WRITE(host->base, HCTL,
 +                      OMAP_HSMMC_READ(host->base, HCTL) | FOUR_BIT);
 +              break;
 +      case MMC_BUS_WIDTH_1:
 +              OMAP_HSMMC_WRITE(host->base, HCTL,
 +                      OMAP_HSMMC_READ(host->base, HCTL) & ~FOUR_BIT);
 +              break;
 +      }
 +
 +      if (host->id == OMAP_MMC1_DEVID) {
 +              /* Only MMC1 can operate at 3V/1.8V */
 +              if ((OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET) &&
 +                      (ios->vdd == DUAL_VOLT_OCR_BIT)) {
 +                              /*
 +                               * The mmc_select_voltage fn of the core does
 +                               * not seem to set the power_mode to
 +                               * MMC_POWER_UP upon recalculating the voltage.
 +                               * vdd 1.8v.
 +                               */
 +                              if (omap_mmc_switch_opcond(host, ios->vdd) != 0)
 +                                      dev_dbg(mmc_dev(host->mmc),
 +                                              "Switch operation failed\n");
 +              }
 +      }
 +
 +      if (ios->clock) {
 +              dsor = OMAP_MMC_MASTER_CLOCK / ios->clock;
 +              if (dsor < 1)
 +                      dsor = 1;
 +
 +              if (OMAP_MMC_MASTER_CLOCK / dsor > ios->clock)
 +                      dsor++;
 +
 +              if (dsor > 250)
 +                      dsor = 250;
 +      }
 +      omap_mmc_stop_clock(host);
 +      regval = OMAP_HSMMC_READ(host->base, SYSCTL);
 +      regval = regval & ~(CLKD_MASK);
 +      regval = regval | (dsor << 6) | (DTO << 16);
 +      OMAP_HSMMC_WRITE(host->base, SYSCTL, regval);
 +      OMAP_HSMMC_WRITE(host->base, SYSCTL,
 +              OMAP_HSMMC_READ(host->base, SYSCTL) | ICE);
 +
 +      /* Wait till the ICS bit is set */
 +      timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS);
 +      while ((OMAP_HSMMC_READ(host->base, SYSCTL) & ICS) != 0x2
 +              && time_before(jiffies, timeout))
 +              msleep(1);
 +
 +      OMAP_HSMMC_WRITE(host->base, SYSCTL,
 +              OMAP_HSMMC_READ(host->base, SYSCTL) | CEN);
 +
 +      if (ios->power_mode == MMC_POWER_ON)
 +              send_init_stream(host);
 +
 +      if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)
 +              OMAP_HSMMC_WRITE(host->base, CON,
 +                              OMAP_HSMMC_READ(host->base, CON) | OD);
 +
 +      mmc_omap_fclk_lazy_disable(host);
 +}
 +
 +static int omap_hsmmc_get_cd(struct mmc_host *mmc)
 +{
 +      struct mmc_omap_host *host = mmc_priv(mmc);
 +      struct omap_mmc_platform_data *pdata = host->pdata;
 +
 +      if (!pdata->slots[0].card_detect)
 +              return -ENOSYS;
 +      return pdata->slots[0].card_detect(pdata->slots[0].card_detect_irq);
 +}
 +
 +static int omap_hsmmc_get_ro(struct mmc_host *mmc)
 +{
 +      struct mmc_omap_host *host = mmc_priv(mmc);
 +      struct omap_mmc_platform_data *pdata = host->pdata;
 +
 +      if (!pdata->slots[0].get_ro)
 +              return -ENOSYS;
 +      return pdata->slots[0].get_ro(host->dev, 0);
 +}
 +
 +static struct mmc_host_ops mmc_omap_ops = {
 +      .request = omap_mmc_request,
 +      .set_ios = omap_mmc_set_ios,
 +      .get_cd = omap_hsmmc_get_cd,
 +      .get_ro = omap_hsmmc_get_ro,
 +      /* NYET -- enable_sdio_irq */
 +};
 +
 +static int __init omap_mmc_probe(struct platform_device *pdev)
 +{
 +      struct omap_mmc_platform_data *pdata = pdev->dev.platform_data;
 +      struct mmc_host *mmc;
 +      struct mmc_omap_host *host = NULL;
 +      struct resource *res;
 +      int ret = 0, irq;
 +      u32 hctl, capa;
 +
 +      if (pdata == NULL) {
 +              dev_err(&pdev->dev, "Platform Data is missing\n");
 +              return -ENXIO;
 +      }
 +
 +      if (pdata->nr_slots == 0) {
 +              dev_err(&pdev->dev, "No Slots\n");
 +              return -ENXIO;
 +      }
 +
 +      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 +      irq = platform_get_irq(pdev, 0);
 +      if (res == NULL || irq < 0)
 +              return -ENXIO;
 +
 +      res = request_mem_region(res->start, res->end - res->start + 1,
 +                                                      pdev->name);
 +      if (res == NULL)
 +              return -EBUSY;
 +
 +      mmc = mmc_alloc_host(sizeof(struct mmc_omap_host), &pdev->dev);
 +      if (!mmc) {
 +              ret = -ENOMEM;
 +              goto err;
 +      }
 +
 +      host            = mmc_priv(mmc);
 +      host->mmc       = mmc;
 +      host->pdata     = pdata;
 +      host->dev       = &pdev->dev;
 +      host->use_dma   = 1;
 +      host->dev->dma_mask = &pdata->dma_mask;
 +      host->dma_ch    = -1;
 +      host->irq       = irq;
 +      host->id        = pdev->id;
 +      host->slot_id   = 0;
 +      host->mapbase   = res->start;
 +      host->base      = ioremap(host->mapbase, SZ_4K);
 +
 +      platform_set_drvdata(pdev, host);
 +      INIT_WORK(&host->mmc_carddetect_work, mmc_omap_detect);
 +
 +      mmc->ops        = &mmc_omap_ops;
 +      mmc->f_min      = 400000;
 +      mmc->f_max      = 52000000;
 +
 +      sema_init(&host->sem, 1);
 +
 +      host->iclk = clk_get(&pdev->dev, "mmchs_ick");
 +      if (IS_ERR(host->iclk)) {
 +              ret = PTR_ERR(host->iclk);
 +              host->iclk = NULL;
 +              goto err1;
 +      }
 +      host->fclk = clk_get(&pdev->dev, "mmchs_fck");
 +      if (IS_ERR(host->fclk)) {
 +              ret = PTR_ERR(host->fclk);
 +              host->fclk = NULL;
 +              clk_put(host->iclk);
 +              goto err1;
 +      }
 +
 +      spin_lock_init(&host->clk_lock);
 +      setup_timer(&host->idle_timer, mmc_omap_idle_timer,
 +                  (unsigned long) host);
 +
 +      if (mmc_omap_fclk_state(host, ON) != 0) {
 +              clk_put(host->iclk);
 +              clk_put(host->fclk);
 +              goto err1;
 +      }
 +      if (clk_enable(host->iclk) != 0) {
 +              mmc_omap_fclk_state(host, OFF);
 +              clk_put(host->iclk);
 +              clk_put(host->fclk);
 +              goto err1;
 +      }
 +
 +      host->dbclk = clk_get(&pdev->dev, "mmchsdb_fck");
 +      /*
 +       * MMC can still work without debounce clock.
 +       */
 +      if (IS_ERR(host->dbclk))
 +              dev_warn(mmc_dev(host->mmc), "Failed to get debounce clock\n");
 +      else
 +              if (clk_enable(host->dbclk) != 0)
 +                      dev_dbg(mmc_dev(host->mmc), "Enabling debounce"
 +                                                      " clk failed\n");
 +              else
 +                      host->dbclk_enabled = 1;
 +
 +#ifdef CONFIG_MMC_BLOCK_BOUNCE
 +      mmc->max_phys_segs = 1;
 +      mmc->max_hw_segs = 1;
 +#endif
 +      mmc->max_blk_size = 512;       /* Block Length at max can be 1024 */
 +      mmc->max_blk_count = 0xFFFF;    /* No. of Blocks is 16 bits */
 +      mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
 +      mmc->max_seg_size = mmc->max_req_size;
 +
 +      mmc->ocr_avail = mmc_slot(host).ocr_mask;
 +      mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED;
 +
 +      if (pdata->slots[host->slot_id].wires >= 4)
 +              mmc->caps |= MMC_CAP_4_BIT_DATA;
 +
 +      /* Only MMC1 supports 3.0V */
 +      if (host->id == OMAP_MMC1_DEVID) {
 +              hctl = SDVS30;
 +              capa = VS30 | VS18;
 +      } else {
 +              hctl = SDVS18;
 +              capa = VS18;
 +      }
 +
 +      OMAP_HSMMC_WRITE(host->base, HCTL,
 +                      OMAP_HSMMC_READ(host->base, HCTL) | hctl);
 +
 +      OMAP_HSMMC_WRITE(host->base, CAPA,
 +                      OMAP_HSMMC_READ(host->base, CAPA) | capa);
 +
 +      /* Set the controller to AUTO IDLE mode */
 +      OMAP_HSMMC_WRITE(host->base, SYSCONFIG,
 +                      OMAP_HSMMC_READ(host->base, SYSCONFIG) | AUTOIDLE);
 +
 +      /* Set SD bus power bit */
 +      OMAP_HSMMC_WRITE(host->base, HCTL,
 +                      OMAP_HSMMC_READ(host->base, HCTL) | SDBP);
 +
 +      /* Request IRQ for MMC operations */
 +      ret = request_irq(host->irq, mmc_omap_irq, IRQF_DISABLED,
 +                      mmc_hostname(mmc), host);
 +      if (ret) {
 +              dev_dbg(mmc_dev(host->mmc), "Unable to grab HSMMC IRQ\n");
 +              goto err_irq;
 +      }
 +
 +      if (pdata->init != NULL) {
 +              if (pdata->init(&pdev->dev) != 0) {
 +                      dev_dbg(mmc_dev(host->mmc),
 +                              "Unable to configure MMC IRQs\n");
 +                      goto err_irq_cd_init;
 +              }
 +      }
 +
 +      /* Request IRQ for card detect */
 +      if ((mmc_slot(host).card_detect_irq) && (mmc_slot(host).card_detect)) {
 +              ret = request_irq(mmc_slot(host).card_detect_irq,
 +                                omap_mmc_cd_handler,
 +                                IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
 +                                        | IRQF_DISABLED,
 +                                mmc_hostname(mmc), host);
 +              if (ret) {
 +                      dev_dbg(mmc_dev(host->mmc),
 +                              "Unable to grab MMC CD IRQ\n");
 +                      goto err_irq_cd;
 +              }
 +      }
 +
 +      OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK);
 +      OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK);
 +
 +      mmc_add_host(mmc);
 +
 +      if (host->pdata->slots[host->slot_id].name != NULL) {
 +              ret = device_create_file(&mmc->class_dev, &dev_attr_slot_name);
 +              if (ret < 0)
 +                      goto err_slot_name;
 +      }
 +      if (mmc_slot(host).card_detect_irq && mmc_slot(host).card_detect &&
 +                      host->pdata->slots[host->slot_id].get_cover_state) {
 +              ret = device_create_file(&mmc->class_dev,
 +                                      &dev_attr_cover_switch);
 +              if (ret < 0)
 +                      goto err_cover_switch;
 +      }
 +      mmc_omap_fclk_lazy_disable(host);
 +
 +      return 0;
 +
 +err_cover_switch:
 +      device_remove_file(&mmc->class_dev, &dev_attr_cover_switch);
 +err_slot_name:
 +      mmc_remove_host(mmc);
 +err_irq_cd:
 +      free_irq(mmc_slot(host).card_detect_irq, host);
 +err_irq_cd_init:
 +      free_irq(host->irq, host);
 +err_irq:
 +      mmc_omap_fclk_state(host, OFF);
 +      clk_disable(host->iclk);
 +      clk_put(host->fclk);
 +      clk_put(host->iclk);
 +      if (host->dbclk_enabled) {
 +              clk_disable(host->dbclk);
 +              clk_put(host->dbclk);
 +      }
 +
 +err1:
 +      iounmap(host->base);
 +err:
 +      dev_dbg(mmc_dev(host->mmc), "Probe Failed\n");
 +      release_mem_region(res->start, res->end - res->start + 1);
 +      if (host)
 +              mmc_free_host(mmc);
 +      return ret;
 +}
 +
 +static int omap_mmc_remove(struct platform_device *pdev)
 +{
 +      struct mmc_omap_host *host = platform_get_drvdata(pdev);
 +      struct resource *res;
 +
 +      if (host) {
 +              mmc_remove_host(host->mmc);
 +              if (host->pdata->cleanup)
 +                      host->pdata->cleanup(&pdev->dev);
 +              free_irq(host->irq, host);
 +              if (mmc_slot(host).card_detect_irq)
 +                      free_irq(mmc_slot(host).card_detect_irq, host);
 +              flush_scheduled_work();
 +
 +              mmc_omap_fclk_state(host, OFF);
 +              clk_disable(host->iclk);
 +              clk_put(host->fclk);
 +              clk_put(host->iclk);
 +              if (host->dbclk_enabled) {
 +                      clk_disable(host->dbclk);
 +                      clk_put(host->dbclk);
 +              }
 +
 +              mmc_free_host(host->mmc);
 +              iounmap(host->base);
 +      }
 +
 +      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 +      if (res)
 +              release_mem_region(res->start, res->end - res->start + 1);
 +      platform_set_drvdata(pdev, NULL);
 +
 +      return 0;
 +}
 +
 +#ifdef CONFIG_PM
 +static int omap_mmc_suspend(struct platform_device *pdev, pm_message_t state)
 +{
 +      int ret = 0;
 +      struct mmc_omap_host *host = platform_get_drvdata(pdev);
 +
 +      if (host && host->suspended)
 +              return 0;
 +
 +      if (host) {
 +              ret = mmc_suspend_host(host->mmc, state);
 +              if (ret == 0) {
 +                      host->suspended = 1;
 +
 +                      mmc_omap_fclk_state(host, ON);
 +                      OMAP_HSMMC_WRITE(host->base, ISE, 0);
 +                      OMAP_HSMMC_WRITE(host->base, IE, 0);
 +
 +                      if (host->pdata->suspend) {
 +                              ret = host->pdata->suspend(&pdev->dev,
 +                                                              host->slot_id);
 +                              if (ret)
 +                                      dev_dbg(mmc_dev(host->mmc),
 +                                              "Unable to handle MMC board"
 +                                              " level suspend\n");
 +                      }
 +
 +                      OMAP_HSMMC_WRITE(host->base, HCTL,
 +                                       OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP);
 +                      mmc_omap_fclk_state(host, OFF);
 +                      clk_disable(host->iclk);
 +                      clk_disable(host->dbclk);
 +              }
 +
 +      }
 +      return ret;
 +}
 +
 +/* Routine to resume the MMC device */
 +static int omap_mmc_resume(struct platform_device *pdev)
 +{
 +      int ret = 0;
 +      struct mmc_omap_host *host = platform_get_drvdata(pdev);
 +
 +      if (host && !host->suspended)
 +              return 0;
 +
 +      if (host) {
 +              int i;
 +              if (mmc_omap_fclk_state(host, ON) != 0)
 +                      goto clk_en_err;
 +
 +              ret = clk_enable(host->iclk);
 +              if (ret) {
 +                      mmc_omap_fclk_state(host, OFF);
 +                      clk_put(host->fclk);
 +                      goto clk_en_err;
 +              }
 +
 +              if (clk_enable(host->dbclk) != 0)
 +                      dev_dbg(mmc_dev(host->mmc),
 +                                      "Enabling debounce clk failed\n");
 +
 +              OMAP_HSMMC_WRITE(host->base, HCTL,
 +                               OMAP_HSMMC_READ(host->base, HCTL) | SDBP);
 +
 +              for (i = 0; i < 100; i++)
 +                      if (OMAP_HSMMC_READ(host->base, HCTL) & SDBP)
 +                              break;
 +
 +              if (host->pdata->resume) {
 +                      ret = host->pdata->resume(&pdev->dev, host->slot_id);
 +                      if (ret)
 +                              dev_dbg(mmc_dev(host->mmc),
 +                                      "Unmask interrupt failed\n");
 +              }
 +
 +              /* Notify the core to resume the host */
 +              ret = mmc_resume_host(host->mmc);
 +              if (ret == 0)
 +                      host->suspended = 0;
 +
 +              mmc_omap_fclk_lazy_disable(host);
 +      }
 +
 +      return ret;
 +
 +clk_en_err:
 +      dev_dbg(mmc_dev(host->mmc),
 +              "Failed to enable MMC clocks during resume\n");
 +      return ret;
 +}
 +
 +#else
 +#define omap_mmc_suspend      NULL
 +#define omap_mmc_resume               NULL
 +#endif
 +
 +static struct platform_driver omap_mmc_driver = {
 +      .probe          = omap_mmc_probe,
 +      .remove         = omap_mmc_remove,
 +      .suspend        = omap_mmc_suspend,
 +      .resume         = omap_mmc_resume,
 +      .driver         = {
 +              .name = DRIVER_NAME,
 +              .owner = THIS_MODULE,
 +      },
 +};
 +
 +static int __init omap_mmc_init(void)
 +{
 +      /* Register the MMC driver */
 +      return platform_driver_register(&omap_mmc_driver);
 +}
 +
 +static void __exit omap_mmc_cleanup(void)
 +{
 +      /* Unregister MMC driver */
 +      platform_driver_unregister(&omap_mmc_driver);
 +}
 +
 +module_init(omap_mmc_init);
 +module_exit(omap_mmc_cleanup);
 +
 +MODULE_DESCRIPTION("OMAP High Speed Multimedia Card driver");
 +MODULE_LICENSE("GPL");
 +MODULE_ALIAS("platform:" DRIVER_NAME);
 +MODULE_AUTHOR("Texas Instruments Inc");
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc kernel/printk.c
Simple merge
Simple merge