/*
* 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 SDVS33 (0x7 << 9)
#define SDVS_MASK 0x00000E00
#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)
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 omap_mmc_platform_data *pdata;
};
/*
* Stop clock to the card
*/
static void omap_mmc_stop_clock(struct mmc_omap_host *host)
{
OMAP_HSMMC_WRITE(host->base,