aboutsummaryrefslogtreecommitdiff
path: root/drivers/mmc
diff options
context:
space:
mode:
authorSebastian Rasmussen <sebastian.rasmussen@stericsson.com>2011-03-11 02:18:53 +0100
committerJonas ABERG <jonas.aberg@stericsson.com>2011-03-14 10:10:21 +0100
commit853d6466132b9c13d8bcaef4facfe643d203c80a (patch)
tree815586418956ebb16270d06877f58747495a8bd4 /drivers/mmc
parent510f32f682337c4897b19001ab4392dc628a4c9d (diff)
mmc-u8500: Remove driver
The mmc-u8500 driver is replaced by the MMCI driver nowadays, so remove the old mmc-u8500 driver completely. Signed-off-by: Sebastian Rasmussen <sebastian.rasmussen@stericsson.com> Change-Id: I0dc9ad9262c719b7f53f648aaebb413b689eb2a6 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/18118 Reviewed-by: Jonas ABERG <jonas.aberg@stericsson.com>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/host/mmc-u8500.c1888
-rw-r--r--drivers/mmc/host/mmc-u8500.h25
2 files changed, 0 insertions, 1913 deletions
diff --git a/drivers/mmc/host/mmc-u8500.c b/drivers/mmc/host/mmc-u8500.c
deleted file mode 100644
index d142a7d369b..00000000000
--- a/drivers/mmc/host/mmc-u8500.c
+++ /dev/null
@@ -1,1888 +0,0 @@
-/*
- * Overview:
- * SD/EMMC driver for u8500 platform
- *
- * Copyright (C) 2009 ST-Ericsson SA
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-/*-------------------------------------------------------------------------
- * SDI controller configuration
- * Kernel entry point for sdmmc/emmc chip
- *-------------------------------------------------------------------------
- * <VERSION>v1.0.0
- *-------------------------------------------------------------------------
- */
-
-/** @file mmc-u8500.c
- * @brief This file contains the sdmmc/emmc chip initialization with default
- * as DMA mode.Polling/Interrupt mode support could be enabled in the kernel
- * menuconfig. Read and write function definitions to configure the read and
- * write functionality was implemented.
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/device.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/highmem.h>
-#include <linux/mmc/host.h>
-#include <linux/mmc/card.h>
-#include <linux/mmc/sdio.h>
-#include <linux/mmc/sdio_func.h>
-#include <linux/amba/bus.h>
-#include <linux/clk.h>
-#include <linux/dma-mapping.h>
-#include <linux/vmalloc.h>
-#include <linux/completion.h>
-#include <linux/regulator/consumer.h>
-
-#include <asm/cacheflush.h>
-#include <asm/div64.h>
-#include <asm/io.h>
-#include <asm/scatterlist.h>
-#include <asm/sizes.h>
-#include <mach/hardware.h>
-#include <mach/mmc.h>
-#include <asm/bitops.h>
-#include <mach/mmc.h>
-#include "mmc-u8500.h"
-
-/* Workaround for SDIO Multibyte mode, not suuported in H/W */
-#ifdef SDIO_MULTIBYTE_WORKAROUND
-#undef SDIO_MULTIBYTE_WORKAROUND
-/* Not fully validated, to be enabled from menuconfig later */
-#endif
-
-/*
- * Global variables
- */
-
-#define DRIVER_NAME "DRIVER MMC"
-
-#define CONFIG_STM_MMC_DEBUG
-#define DRIVER_DEBUG CONFIG_STM_MMC_DEBUG
-#define DRIVER_DEBUG_PFX DRIVER_NAME
-#define DRIVER_DBG KERN_ERR
-extern struct driver_debug_st DBG_ST;
-#define DMA_SCATERGATHER
-
-#if defined CONFIG_U8500_MMC_POLL
-const int mmc_mode = MCI_POLLINGMODE;
-#elif defined CONFIG_U8500_MMC_INTR
-const int mmc_mode = MCI_INTERRUPTMODE;
-#elif defined CONFIG_U8500_MMC_DMA
-const int mmc_mode = MCI_DMAMODE;
-#endif
-
-#if defined CONFIG_U8500_SDIO_POLL
-const int sdio_mode = MCI_POLLINGMODE;
-#elif defined CONFIG_U8500_SDIO_INTR
-const int sdio_mode = MCI_INTERRUPTMODE;
-#elif defined CONFIG_U8500_SDIO_DMA
-const int sdio_mode = MCI_DMAMODE;
-#else
-const int sdio_mode = 0xFFFF;
-#endif
-
-#if !defined CONFIG_U8500_MMC_INTR
-static unsigned int fmax = MMC_HOST_CLK_MAX;
-#else
-static unsigned int fmax = MMC_HOST_CLK_MAX / 8;
-#endif
-
-static void u8500_mmci_start_command(struct u8500_mmci_host *host,
- struct mmc_command *cmd);
-
-static void u8500_mmci_data_irq(struct u8500_mmci_host *host,
- u32 hoststatus);
-
-static void u8500_mmci_cmd_irq(struct u8500_mmci_host *host,
- u32 hoststatus);
-
-#define U8500_MMC_DISABLED_TIMEOUT 500
-
-/*
- * Pointer to save SDIO host data structure.
- * Required for sysfs inplementation for card detection
- */
-static struct u8500_mmci_host *sdio_host_ptr;
-#define CARD_DETECT_DELAY_MSEC (10)
-
-/* For SDIO host DMA mode, min data transfer size in bytes */
-#define MIN_DATA_SIZE_DMA 32
-/* DMA element size in bytes */
-#define DMA_ELEMENT_SZ 4
-/**
- * u8500_sdio_detect_card() - Initiates card scan for sdio host
- *
- * this function will scan for insertion/removal of sdio card.
- * This is required to initiate card rescan from sdio client device driver.
- */
-void u8500_sdio_detect_card(void)
-{
- struct u8500_mmci_host *host = sdio_host_ptr;
- if (sdio_host_ptr && host->mmc)
- mmc_detect_change(host->mmc,
- msecs_to_jiffies(CARD_DETECT_DELAY_MSEC));
-
- return;
-}
-EXPORT_SYMBOL(u8500_sdio_detect_card);
-
-static ssize_t sdio_detect_card_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- unsigned int scan_val;
-
- if (sscanf(buf, "%u", &scan_val) != 1)
- return -EINVAL;
- /*
- * unsigned integer is valid entry.
- * mmc_detect_change is called when scan_val == 1.
- */
- if (scan_val != 1)
- return -EINVAL;
-
- /* call card scan */
- u8500_sdio_detect_card();
-
- return strnlen(buf, count);
-}
-
-static DEVICE_ATTR(detect_card, S_IWUSR, NULL, sdio_detect_card_store);
-
-
-/**
- * u8500_mmci_init_sg() - initializing the host scatterlist
- * @host: pointer to the u8500_mmci_host structure
- * @data: pointer to the mmc_data structure
- *
- * this function assigns the scattelist of the mmc_data structure
- * to the host scatterlist.
- */
-static inline void
-u8500_mmci_init_sg(struct u8500_mmci_host *host, struct mmc_data *data)
-{
- /*
- * Ideally, we want the higher levels to pass us a scatter list
- */
- host->sg_len = data->sg_len;
- host->sg_ptr = data->sg;
- host->sg_off = 0;
-}
-
-/**
- * u8500_mmc_clearirqsrc() - Clearing the interrupts of the host
- * @base: pointer to the base address of the host
- * @irqsrc: irqsrc number.
- *
- * this function clears the corresponding interrupt of the source of the
- * SD controller by writing to interrupt clear register
- */
-static inline void u8500_mmc_clearirqsrc(void *base, u32 irqsrc)
-{
- irqsrc &= ~(MCI_SDIOIT);
- writel(irqsrc, (base + MMCICLEAR));
-}
-
-/**
- * u8500_mmc_disableirqsrc() - Disabling the interrupts of the host
- * @base: pointer to the base address of the host
- * @irqsrc: irqsrc number.
- *
- * this function disables the corresponding interrupt source
- */
-static inline void u8500_mmc_disableirqsrc(void *base, u32 irqsrc)
-{
- u32 temp_reg;
- irqsrc &= ~(MCI_SDIOIT);
- temp_reg = readl(base + MMCIMASK0);
- temp_reg &= ~irqsrc;
- writel(temp_reg, (base + MMCIMASK0));
-}
-
-/**
- * u8500_mmc_enableirqsrc() - Enabeling the interrupts of the host
- * @base: pointer to the base address of the host
- * @irqsrc: irqsrc number
- *
- * this function enables the corresponding interrupt source
- */
-static inline void u8500_mmc_enableirqsrc(void *base, u32 irqsrc)
-{
- u32 temp_reg;
- irqsrc &= ~(MCI_SDIOIT);
- temp_reg = readl(base + MMCIMASK0);
- temp_reg |= irqsrc;
- writel(temp_reg, (base + MMCIMASK0));
-}
-
-/**
- * u8500_mmci_request_end() - Informs the stack regarding the completion of the request
- * @host: pointer to the u8500_mmci_host structure
- * @mrq: pointer to the mmc_request structure
- *
- * this function will be called after servicing the request sent from the
- * stack.And this function will inform the stack that the request is done
- */
-static void
-u8500_mmci_request_end(struct u8500_mmci_host *host,
- struct mmc_request *mrq)
-{
- unsigned long flag_lock = 0;
- spin_lock_irqsave(&host->lock, flag_lock);
- host->mrq = NULL;
- host->cmd = NULL;
- if (mrq->data)
- mrq->data->bytes_xfered = host->data_xfered;
- /*
- * Need to drop the host lock here; mmc_request_done may call
- * back into the driver...
- */
- spin_unlock_irqrestore(&host->lock, flag_lock);
- mmc_request_done(host->mmc, mrq);
-}
-
-/**
- * u8500_mmci_stop_data() - clears the data control registers
- * @host: pointer to the u8500_mmci_host structure
- *
- * this function clears the data control register after the end of
- * data transfer or when an error occured in the data transfer
- */
-static void u8500_mmci_stop_data(struct u8500_mmci_host *host)
-{
- unsigned long flag_lock = 0;
- u32 temp = 0;
- spin_lock_irqsave(&host->lock, flag_lock);
- temp = readl(host->base + MMCIDATACTRL) & ~(MCI_DPSM_ENABLE);
- writel(temp, host->base + MMCIDATACTRL);
- writel(0, host->base + MMCIMASK1);
- host->data = NULL;
- spin_unlock_irqrestore(&host->lock, flag_lock);
-}
-
-/**
- * u8500_mmc_send_cmd() - configures the cmd and arg control registers
- * @base: pointer to the base address of the host
- * @cmd: cmd number to be sent
- * @arg: arg value need to be paased along with command
- * @flags: flags need to be set for the cmd
- * @devicemode: devicemode for the data transfer
- *
- * this function will send the cmd to the card by enabling the
- * command path state machine and writing the cmd number and arg to the
- * corresponding command and arguement registers
- */
-static void u8500_mmc_send_cmd(void *base, u32 cmd, u32 arg, u32 flags,
- int devicemode)
-{
- u32 c, irqmask;
- /* stm_dbg2(DBG_ST.mmc,"Sending CMD%d, arg=%08x\n", cmd, arg);*/
- /* Clear any previous command */
- if ((readl(base + MMCICOMMAND) & MCI_CPSM_ENABLE)) {
- writel(0, (base + MMCICOMMAND));
- udelay(1);
- }
- c = cmd | MCI_CPSM_ENABLE;
- irqmask = MCI_CMDCRCFAIL | MCI_CMDTIMEOUT;
- if (flags & MMC_RSP_PRESENT) {
- if (flags & MMC_RSP_136)
- c |= MCI_CPSM_LONGRSP;
- c |= MCI_CPSM_RESPONSE;
- irqmask |= MCI_CMDRESPEND;
- } else {
- irqmask |= MCI_CMDSENT;
- }
- writel(arg, (base + MMCIARGUMENT));
- writel(c, (base + MMCICOMMAND));
-
- if (devicemode != MCI_POLLINGMODE)
- u8500_mmc_enableirqsrc(base, irqmask);
-}
-
-/**
- * process_command_end() - read the response for the corresponding cmd sent
- * @host: pointer to the u8500_mmci_host
- * @hoststatus: status register value
- *
- * this function will read the response of the corresponding command by
- * reading the response registers
- */
-static void process_command_end(struct u8500_mmci_host *host, u32 hoststatus)
-{
- struct mmc_command *cmd;
- void __iomem *base;
-
- base = host->base;
- cmd = host->cmd;
-
- u8500_mmc_disableirqsrc(base, MCI_CMD_IRQ);
- u8500_mmc_clearirqsrc(base, MCI_CMD_IRQ);
-
- cmd->resp[0] = readl(base + MMCIRESPONSE0);
- cmd->resp[1] = readl(base + MMCIRESPONSE1);
- cmd->resp[2] = readl(base + MMCIRESPONSE2);
- cmd->resp[3] = readl(base + MMCIRESPONSE3);
-
- if ((hoststatus & MCI_CMDTIMEOUT)) {
- /* printk(KERN_ERR "Command Timeout: %d\n", cmd->opcode); */
- cmd->error = -ETIMEDOUT;
- } else if ((hoststatus & MCI_CMDCRCFAIL) && (cmd->flags & MMC_RSP_CRC)) {
- printk(KERN_ERR "Command CRC Fail\n");
- cmd->error = -EILSEQ;
- } else if ((cmd->flags & MMC_RSP_OPCODE) &&
- readl(base + MMCIRESPCMD) != cmd->opcode) {
- printk(KERN_ERR "Command failed opcode check\n");
- cmd->error = -EILSEQ;
- } else {
- cmd->error = MMC_ERR_NONE;
- }
- /* stm_dbg2(DBG_ST.mmc,"CMD%d error=%d response:0x%08x 0x%08x 0x%08x 0x%08x\n",
- cmd->opcode, cmd->error, cmd->resp[0], cmd->resp[1], cmd->resp[2],
- cmd->resp[3]);
- */
-}
-
-/**
- * wait_for_command_end() - waiting for the command completion
- * @host: pointer to the u8500_mmci_host
- *
- * this function will wait for whether the command completion has
- * happened or any error generated by reading the status register
- */
-static void wait_for_command_end(struct u8500_mmci_host *host)
-{
- u32 hoststatus, statusmask;
- struct mmc_command *cmd;
- void __iomem *base;
-
- base = host->base;
- cmd = host->cmd;
-
- statusmask = MCI_CMDTIMEOUT | MCI_CMDCRCFAIL;
- if ((cmd->flags & MMC_RSP_PRESENT)) {
- statusmask |= MCI_CMDRESPEND;
- } else {
- statusmask |= MCI_CMDSENT;
- }
- do {
- hoststatus = readl(base + MMCISTATUS) & statusmask;
- } while (!hoststatus);
-
- u8500_mmci_cmd_irq(host, hoststatus);
-}
-
-/**
- * check_for_data_err() - checks the status register value for the error
- * @hoststatus: value of the host status register
- *
- * this function will read the status register and will return the
- * error if any generated during the operation
- */
-static int check_for_data_err(u32 hoststatus)
-{
- int error = MMC_ERR_NONE;
- if (hoststatus &
- (MCI_DATACRCFAIL | MCI_DATATIMEOUT | MCI_TXUNDERRUN | MCI_RXOVERRUN
- | MCI_STBITERR)) {
- if ((hoststatus & MCI_DATATIMEOUT)) {
- printk(KERN_ERR "MMC: data timeout\n");
- error = -ETIMEDOUT;
- } else if (hoststatus & MCI_DATACRCFAIL) {
- error = -EILSEQ;
- printk(KERN_ERR "MMC: data CRC fail\n");
- } else if (hoststatus & MCI_RXOVERRUN) {
- error = -EIO;
- printk(KERN_ERR "MMC: Rx overrun\n");
- } else if (hoststatus & MCI_TXUNDERRUN) {
- printk(KERN_ERR "MMC: Tx underrun\n");
- error = -EIO;
- } else if (hoststatus & MCI_STBITERR) {
- printk(KERN_ERR "MMC: stbiterr\n");
- error = -EILSEQ;
- }
- }
- return error;
-}
-/**
- * u8500_mmc_dma_transfer_done() - called after the DMA tarnsfer completion
- * @host: pointer to the u8500_mmci_host
- *
- * this function will update the stack with the data read and about
- * the request completion
- */
-static void u8500_mmc_dma_transfer_done(struct u8500_mmci_host *host)
-{
- struct mmc_data *data;
- struct mmc_host *mmc;
- void __iomem *base;
- unsigned long flags;
- u32 temp_reg;
- int retry;
- base = host->base;
- data = host->data;
- mmc = host->mmc;
- host->dma_done = NULL;
- if (data == NULL) {
- printk(KERN_ERR "mmc-u8500: what? data is null, go back\n");
- u8500_mmci_request_end(host, host->mrq);
- return;
- }
- /*
- * Need to wait for end of transfer, i.e.,
- * DATAEND bit to be set in SDI STATUS register
- */
- temp_reg = readl(base + MMCISTATUS);
- retry = 200*100; /* Max wait for 100 usec */
- while (!(temp_reg & MCI_DATAEND) && (retry > 0)) {
- ndelay(5);
- retry--;
- temp_reg = readl(host->base + MMCISTATUS);
- }
-
-#ifndef DMA_SCATERGATHER
- spin_lock_irqsave(&host->lock, flags);
- if (!data->error) {
- if ((data->flags & MMC_DATA_READ)) {
- u32 *buffer_local, *buffer;
- u8500_mmci_init_sg(host, data);
- buffer_local = host->dma_buffer;
- while (host->sg_len--) {
- buffer = (u32 *) (page_address(sg_page(host->sg_ptr)) +
- host->sg_ptr->offset);
- memcpy(buffer, buffer_local, host->sg_ptr->length);
- buffer_local += host->sg_ptr->length / 4;
- host->sg_ptr++;
- host->sg_off = 0;
- }
- }
- }
- spin_unlock_irqrestore(&host->lock, flags);
-#endif
- if (data->error) {
- if (data->flags & MMC_DATA_READ)
- host->dmach_mmc2mem->device->
- device_control(host->dmach_mmc2mem,
- DMA_TERMINATE_ALL, 0);
- else
- host->dmach_mem2mmc->device->
- device_control(host->dmach_mem2mmc,
- DMA_TERMINATE_ALL, 0);
-#ifdef DMA_SCATERGATHER
- dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
- ((data->flags & MMC_DATA_READ) ?
- DMA_FROM_DEVICE : DMA_TO_DEVICE));
-#endif
- u8500_mmc_clearirqsrc(base, MMCCLRSTATICFLAGS);
- u8500_mmci_stop_data(host);
- goto out;
- }
- spin_lock_irqsave(&host->lock, flags);
- host->data_xfered += host->size;
- spin_unlock_irqrestore(&host->lock, flags);
- u8500_mmc_clearirqsrc(base, MMCCLRSTATICFLAGS);
- u8500_mmci_stop_data(host);
-#ifdef DMA_SCATERGATHER
- dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
- ((data->flags & MMC_DATA_READ) ?
- DMA_FROM_DEVICE : DMA_TO_DEVICE));
-#endif
- if (!data->stop)
- u8500_mmci_request_end(host, data->mrq);
- else
- u8500_mmci_start_command(host, data->stop);
- return;
-out:
- if (data->error != MMC_ERR_NONE) {
- if (!data->stop)
- u8500_mmci_request_end(host, data->mrq);
- else
- u8500_mmci_start_command(host, data->stop);
- }
-}
-/**
- * u8500_mmc_dmaclbk() - callback handler for DMA
- * @data: pointer to the host
- * @event: event value for checking the completion status
- *
- * this function is the callback which will be called upon the completion of any DMA
- * request regarding read/write.
- */
-void u8500_mmc_dmaclbk(void *data)
-{
- struct u8500_mmci_host *host = data;
- if (host->dma_done == NULL) {
- /* Removing this print */
- /* stm_info("MMC: host->dma_done is found tobe null ! \n"); */
- return;
- }
- u8500_mmc_dma_transfer_done(host);
- return;
-}
-
-/**
- * u8500_mmc_set_dma() - initiates the DMA transfer
- * @host: pointer to the u8500_mmci_host register
- *
- * configures the DMA channel and selects the burst size depending on the
- * data size and enables the dma transfer for the corresponding device
- * either sdmmc or emmc
- */
-static void u8500_mmc_set_dma(struct u8500_mmci_host *host)
-{
- struct dma_async_tx_descriptor *dmach_desc;
- struct mmc_data *data;
-#ifndef DMA_SCATERGATHER
- u32 *buffer, *ptr, *buffer1;
- unsigned long flag_lock = 0;
- u32 sg_len;
-#endif
- enum dma_data_direction direction;
- data = host->data;
-
- direction = (data->flags & MMC_DATA_READ)
- ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
-
-#ifdef DMA_SCATERGATHER
-/* #warning " scatter gather is compiled " */
- data->sg_len = dma_map_sg(mmc_dev(host->mmc), data->sg,
- data->sg_len, direction);
-#else
- spin_lock_irqsave(&host->lock, flag_lock);
- if (data->flags & MMC_DATA_READ) {
- buffer = (u32 *)host->dma;
- } else {
- ptr = (u32 *) host->dma_buffer;
- buffer1 = (u32 *) (page_address(sg_page(host->sg_ptr)) +
- host->sg_ptr->offset) + host->sg_off;
- memcpy(ptr, buffer1, host->size);
- buffer = (u32 *)host->dma;
- }
- spin_unlock_irqrestore(&host->lock, flag_lock);
-#endif
-
- if (data->flags & MMC_DATA_READ) {
- dmach_desc = host->dmach_mmc2mem->device->
- device_prep_slave_sg(host->dmach_mmc2mem,
- data->sg, data->sg_len,
- direction,
- DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
- if (!dmach_desc) {
- dev_err(mmc_dev(host->mmc),
- "could not get DMA descriptor");
- return;
- }
-
- dmach_desc->callback = u8500_mmc_dmaclbk;
- dmach_desc->callback_param = host;
- dmach_desc->tx_submit(dmach_desc);
- dma_async_issue_pending(host->dmach_mmc2mem);
- } else {
- dmach_desc = host->dmach_mem2mmc->device->
- device_prep_slave_sg(host->dmach_mem2mmc,
- data->sg, data->sg_len,
- direction,
- DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
- if (!dmach_desc) {
- dev_err(mmc_dev(host->mmc),
- "could not get DMA descriptor");
- return;
- }
-
- dmach_desc->callback = u8500_mmc_dmaclbk;
- dmach_desc->callback_param = host;
- dmach_desc->tx_submit(dmach_desc);
- dma_async_issue_pending(host->dmach_mem2mmc);
- }
-}
-/**
- * u8500_mmci_read() - data read function in polling mode
- * @host: pointer to the u8500_mmci_host structure
- * @buffer: pointer to the host buffer
- * @remain: size of the remaining data to be transferred
- * @hoststatus: value of the host status register
- *
- * the function will read the data from the fifo and copies to the host buffer
- * in case of polling mode and returns the data transfered
- */
-static int u8500_mmci_read(struct u8500_mmci_host *host, u32 * buffer,
- unsigned int remain, u32 hoststatus)
-{
- void __iomem *base;
- int count, max_count;
- unsigned int data_xfered = 0;
- u8 *char_buf;
- u16 *word_buf;
- unsigned int temp;
- u32 flag = MCI_DATA_IRQ;
-
- base = host->base;
- if (host->cmd && host->cmd->opcode == SD_IO_RW_EXTENDED)
- flag = MCI_DATA_ERR; /* required for SDIO CMD53 */
-
- while ((remain > 0) && !(hoststatus & flag)) {
- if ((hoststatus & MCI_RXFIFOHALFFULL) && (remain >= 32))
- max_count = MCI_FIFOHALFSIZE;
- else if ((hoststatus & MCI_RXDATAAVLBL) && (remain < 32))
- max_count = 1;
- else
- max_count = 0;
- for (count = 0; count < max_count; count++) {
- if (remain == 2) { /* half word aligned, read 16bit half words */
- word_buf = (u16 *)buffer;
- *word_buf = readw((u16 *)(base + MMCIFIFO));
- word_buf++;
- buffer = (u32 *)word_buf;
- data_xfered += 2;
- remain = 0;
- } else if (remain < 4) {/* not word aligned, read byte by byte */
- char_buf = (u8 *)buffer;
- for (temp = 0; temp < remain; temp++) {
- *char_buf = readb((u8 *)(base + MMCIFIFO));
- char_buf++;
- }
- data_xfered += remain;
- buffer = (u32 *)char_buf;
- remain = 0;
- } else {
- *buffer = readl(base + MMCIFIFO);
- buffer++;
- data_xfered += 4;
- remain -= 4;
- }
- }
- hoststatus = readl(base + MMCISTATUS);
- }
-
- if (remain) {
- /* stm_dbg2(DBG_ST.mmc,"While READ, Remain is %d, hoststatus is %x, data_xfered is %d\n",
- * remain, hoststatus, data_xfered);
- */
- }
- return data_xfered;
-}
-/**
- * u8500_mmci_write() - data write function in polling mode
- * @host: pointer to the u8500_mmci_host structure
- * @buffer: pointer to the host buffer
- * @remain: size of the remaining data to be transfered
- * @hoststatus: value of the host status register
- *
- * the function will write the data from the host buffer to the fifo
- * in case of polling mode and returns the data transfered
- */
-static int u8500_mmci_write(struct u8500_mmci_host *host, u32 * buffer,
- unsigned int remain, u32 hoststatus)
-{
- void __iomem *base;
- int count, max_count;
- unsigned int data_xfered = 0, temp;
- u16 *buf16;
- u8 *buf8;
- u32 flag = MCI_DATA_IRQ;
-
- base = host->base;
- if (host->cmd && host->cmd->opcode == SD_IO_RW_EXTENDED)
- flag = MCI_DATA_ERR; /* required for SDIO CMD53 */
-
- while ((remain > 0) && !(hoststatus & flag)) {
- if ((hoststatus & MCI_TXFIFOEMPTY) && (remain >= 64))
- max_count = MCI_FIFOSIZE;
- else if ((hoststatus & MCI_TXFIFOHALFEMPTY) && (remain >= 32))
- max_count = MCI_FIFOHALFSIZE;
- else if (remain < 32)
- max_count = 1;
- else
- max_count = 0;
- for (count = 0; count < max_count; count++) {
- if (remain == 2) { /* half word aligned, read 16bit half words */
- buf16 = (u16 *)buffer;
- writew(*buf16, (u16 *)(base + MMCIFIFO));
- buf16++;
- buffer = (u32 *)buf16;
- data_xfered += 2;
- remain = 0;
- } else if (remain < 4) /* not word aligned, read byte by byte */ {
- buf8 = (u8 *)buffer;
- for (temp = 0; temp < remain; temp++) {
- writew(*buf8, (u8 *)(base + MMCIFIFO));
- buf8++;
- }
- data_xfered += remain;
- buffer = (u32 *)buf8;
- remain = 0;
- } else {
- writel(*buffer, (base + MMCIFIFO));
- buffer++;
- data_xfered += 4;
- remain -= 4;
- }
- }
-
- hoststatus = readl(base + MMCISTATUS);
- }
- if (remain) {
- printk(KERN_INFO "While WRITE, Remain is %d, hoststatus is %x, data_xfered is %d\n",
- remain, hoststatus, data_xfered);
- }
- return data_xfered;
-}
-/**
- * u8500_mmci_read_write() - the function calls corresponding read/write function
- * @host: pointer to the u8500_mmci_host structure
- *
- * this function will call the corresponding read or write function of the polling mode depending
- * on the flag set in the status register
- */
-static void u8500_mmci_read_write(struct u8500_mmci_host *host)
-{
- void __iomem *base;
- u32 *buffer;
- u32 hoststatus;
- struct mmc_data *data;
- unsigned int remain, len;
- unsigned long flags = 0;
-
- u32 temp_flag = MCI_TXFIFOHALFEMPTY | MCI_RXDATAAVLBL;
- base = host->base;
- data = host->data;
-
- hoststatus = readl(base + MMCISTATUS);
- if (host->cmd && host->cmd->opcode == SD_IO_RW_EXTENDED)
- temp_flag |= MCI_DATAEND | MCI_DATABLOCKEND; /* Required for SDIO CMD53 */
-
- while (host->data_xfered < host->size &&
- (hoststatus & temp_flag)) {
- /* Do not add any printk or DEBUG at this location */
- if (data->flags & MMC_DATA_READ) {
- buffer = host->buffer;
- remain = host->size;
- } else {
- buffer =
- (u32 *) (page_address(sg_page(host->sg_ptr)) +
- host->sg_ptr->offset) + host->sg_off;
- remain = host->sg_ptr->length - host->sg_off;
- }
- if (host->devicemode == MCI_POLLINGMODE)
- local_irq_save(flags);
- len = 0;
- if (hoststatus & MCI_RXACTIVE) {
- len =
- u8500_mmci_read(host, buffer, remain, hoststatus);
- } else if (hoststatus & MCI_TXACTIVE) {
- len =
- u8500_mmci_write(host, buffer, remain,
- hoststatus);
- }
- if (host->devicemode == MCI_POLLINGMODE)
- local_irq_restore(flags);
- spin_lock_irqsave(&host->lock, flags);
- host->sg_off += len;
- host->data_xfered += len;
- remain -= len;
- if (remain) {
- printk(KERN_INFO "Remain is %d, hoststatus is %x, host->size is %d, host->data_xfered is %d\n",
- remain, readl(base + MMCISTATUS), host->size,
- host->data_xfered);
- spin_unlock_irqrestore(&host->lock, flags);
- break;
- }
- if ((--host->sg_len) && (data->flags & MMC_DATA_WRITE)) {
- host->sg_ptr++;
- host->sg_off = 0;
- } else {
- spin_unlock_irqrestore(&host->lock, flags);
- break;
- }
- spin_unlock_irqrestore(&host->lock, flags);
-
- hoststatus = readl(base + MMCISTATUS);
- }
-
- if (host->devicemode == MCI_INTERRUPTMODE) {
- /** If we're nearing the end of the read, switch to
- * "any data available" mode
- */
- if ((hoststatus & MCI_RXACTIVE) &&
- (host->size - host->data_xfered) < MCI_FIFOSIZE) {
- u8500_mmc_enableirqsrc(base, MCI_RXDATAAVLBL);
- }
- /*
- * If we run out of data, disable the data IRQs; this
- * prevents a race where the FIFO becomes empty before
- * the chip itself has disabled the data path, and
- * stops us racing with our data end IRQ
- */
- if (host->size == host->data_xfered) {
- u8500_mmc_disableirqsrc(base, MCI_XFER_IRQ_MASK);
- }
- } else if (host->devicemode == MCI_POLLINGMODE) {
-
- u8500_mmci_cmd_irq(host, hoststatus);
- u8500_mmci_data_irq(host, hoststatus);
- }
-}
-
-/**
- * start_data_xfer() - configures the data control registers
- * @host: pointer to the u8500_mmci_host
- *
- * this function configures the data control registers for enabling the data path,
- * and direction of data transfer and configures the data length register with
- * the data size to be transfered and configures the data timer register
- */
-static void start_data_xfer(struct u8500_mmci_host *host)
-{
- void __iomem *base;
- struct mmc_data *data;
- unsigned int size;
- u32 temp_reg;
- u32 clk_reg;
- unsigned int temp;
- data = host->data;
- base = host->base;
- size = host->size;
-
- BUG_ON(!data);
- BUG_ON(!(data->flags & (MMC_DATA_READ | MMC_DATA_WRITE)));
- BUG_ON((data->flags & MMC_DATA_READ) && (data->flags & MMC_DATA_WRITE));
- BUG_ON(!host->cmd);
-
- /**
- * Required for SDIo CMD53, for transfer sizes <8, H/W flow
- * control should be disabled
- */
- if (host->cmd->opcode == SD_IO_RW_EXTENDED) {
- clk_reg = readl(host->base + MMCICLOCK);
- if (host->size < 8)
- clk_reg &= ~(MCI_HWFC_EN);
- else
- clk_reg |= (MCI_HWFC_EN);
- writel(clk_reg, host->base + MMCICLOCK);
- }
-
- writel(0x0FFFFFFF, (base + MMCIDATATIMER));
-
- /**
- * Work around for SDIO multibyte mode, required for H/W
- * limitation, as byte mode is not supported in host controller
- */
-#ifdef SDIO_MULTIBYTE_WORKAROUND
- if (host->cmd && (host->cmd->opcode == SD_IO_RW_EXTENDED) && !(host->cmd->arg & 0x08000000)) {
- temp = __fls(host->aligned_blksz);
- writel(host->aligned_size, (base + MMCIDATALENGTH));
- } else {
- writel(size, (base + MMCIDATALENGTH));
- temp = __fls(data->blksz);
- /* Get the last set bit position i.e power of two */
- }
-#else
- writel(size, (base + MMCIDATALENGTH));
- temp = __fls(data->blksz); /* Get the last set bit position, i.e., power of two */
-#endif /* End of SDIO_MULTIBYTE_WORKAROUND */
-
- /*
- * On DB8500v2, the block size is moved to a different offset, and it
- * takes the direct value instead of a power of two.
- */
- if (cpu_is_u8500v2())
- temp_reg = MCI_DPSM_ENABLE | (data->blksz << 16);
- else
- temp_reg = MCI_DPSM_ENABLE | ((temp & 0xF) << 4);
-
- if (host->devicemode == MCI_DMAMODE) {
- /* Enable the DMA mode of the MMC Host Controller */
- temp_reg |= MCI_DPSM_DMAENABLE;
- temp_reg |= MCI_DPSM_DMAreqctl;
- }
- if ((data->flags & MMC_DATA_READ)) {
- temp_reg |= MCI_DPSM_DIRECTION;
- }
-
- if (host->devicemode == MCI_DMAMODE)
- u8500_mmc_enableirqsrc(base, MCI_DATA_ERR);
- else if (host->devicemode == MCI_INTERRUPTMODE) {
- u8500_mmc_enableirqsrc(base, (MCI_DATA_IRQ | MCI_XFER_IRQ));
- if (host->size < MCI_FIFOSIZE) {
- u8500_mmc_enableirqsrc(base, MCI_RXDATAAVLBL);
- }
- }
- /* Required for SDIO CMD53 and SDIO interrupt */
- if (host->cmd->opcode == SD_IO_RW_EXTENDED)
- temp_reg |= MCI_SDIO_ENABLE;
-
- writel(temp_reg, (base + MMCIDATACTRL));
-
-}
-static void u8500_mmci_xfer_irq(struct u8500_mmci_host *host,
- u32 hoststatus)
-{
- hoststatus &= MCI_XFER_IRQ_MASK;
- if (!hoststatus)
- return;
- BUG_ON(host->devicemode != MCI_INTERRUPTMODE);
- u8500_mmci_read_write(host);
-}
-/**
- * u8500_mmci_cmd_irq() - called to service the command status interrupt
- * @host: pointer to the u8500_mmci_host
- * @hoststatus: value of the hoststatus register
- *
- * this function processes the command request end in the interrupt mode and will
- * inform the stack about the request end
- */
-static void u8500_mmci_cmd_irq(struct u8500_mmci_host *host, u32 hoststatus)
-{
- void __iomem *base;
- struct mmc_command *cmd;
- struct mmc_data *data;
- u32 cmdstatusmask;
- cmd = host->cmd;
- data = host->data;
- base = host->base;
- if (cmd) {
- cmdstatusmask = MCI_CMDTIMEOUT | MCI_CMDCRCFAIL;
- if ((cmd->flags & MMC_RSP_PRESENT))
- cmdstatusmask |= MCI_CMDRESPEND;
- else
- cmdstatusmask |= MCI_CMDSENT;
- } else
- cmdstatusmask = 0;
- hoststatus &= cmdstatusmask;
- if (!hoststatus)
- return;
- process_command_end(host, hoststatus);
-
- if (!cmd->data || cmd->error != MMC_ERR_NONE) {
- if (cmd->error != MMC_ERR_NONE && data) {
- /* printk("The COMMCND NUMBER IS : %d status register value is : %d\n",
- cmd->opcode, hoststatus); */
- if (host->devicemode == MCI_POLLINGMODE) {
- u8500_mmci_stop_data(host);
- if (!data->stop)
- u8500_mmci_request_end(host, data->mrq);
- else
- u8500_mmci_start_command(host, data->stop);
- } else {
- data->error = cmd->error;
- u8500_mmc_dma_transfer_done(host);
- return;
- }
- } else {
- u8500_mmci_request_end(host, cmd->mrq);
- }
- } else if (!(cmd->data->flags & MMC_DATA_READ)) {
- start_data_xfer(host);
- }
- hoststatus &= ~(MCI_SDIOIT);
- u8500_mmc_clearirqsrc(base, hoststatus);
-}
-/**
- * u8500_mmci_data_irq() - called to service the data transfer status interrupt
- * @host: pointer to the u8500_mmci_host
- * @hoststatus: value of the hoststatus register
- *
- * this function processes the command with data request end in the interrupt mode and will
- * inform the stack about the request end
- */
-static void u8500_mmci_data_irq(struct u8500_mmci_host *host,
- u32 hoststatus)
-{
- struct mmc_data *data;
- struct mmc_command *cmd;
- struct mmc_host *mmc;
- hoststatus &= MCI_DATA_IRQ;
-
- if (!hoststatus) {
- return;
- }
- cmd = host->cmd;
- data = host->data;
- mmc = host->mmc;
-
- if (!data) {
- goto clear_data_irq;
- }
- data->error = check_for_data_err(hoststatus);
-
- if (data->error != MMC_ERR_NONE)
- printk(KERN_ERR "mmc-u8500: In %d Cmd, data_irq, data->error"
- " is %d, data_xfered is %d, hoststatus = %x",
- cmd->opcode, data->error, host->data_xfered,
- hoststatus);
-
- if (host->devicemode == MCI_DMAMODE && data->error != MMC_ERR_NONE) {
- u8500_mmc_dma_transfer_done(host);
- return;
- }
- if (!data->error) {
- if ((data->flags & MMC_DATA_READ)
- && (host->devicemode != MCI_DMAMODE)) {
- u32 *buffer_local, *buffer;
- u8500_mmci_init_sg(host, data);
- buffer_local = host->buffer;
- while (host->sg_len--) {
- buffer =
- (u32 *) (page_address(sg_page(host->sg_ptr)) + host->sg_ptr->offset);
- memcpy(buffer, buffer_local,
- host->sg_ptr->length);
- buffer_local += host->sg_ptr->length / 4;
- flush_dcache_page(sg_page(host->sg_ptr));
- host->sg_ptr++;
- host->sg_off = 0;
- }
- }
- }
-
- u8500_mmci_stop_data(host);
-
- if (!data->stop)
- u8500_mmci_request_end(host, data->mrq);
- else
- u8500_mmci_start_command(host, data->stop);
-clear_data_irq:
- hoststatus &= ~(MCI_SDIOIT);
- u8500_mmc_clearirqsrc(host->base, hoststatus);
-}
-
-/**
- * u8500_mmci_irq() - interrupt handler registred for sd controller interrupt
- * @irq: irq interrupt source number
- * @dev_id: dev_id pointer to the current device id
- *
- * this function is the interrupt handler registered for sdmmc interrupt and this
- * will be invoked on any interrupt from mmc
- */
-static irqreturn_t u8500_mmci_irq(int irq, void *dev_id)
-{
- struct u8500_mmci_host *host = dev_id;
- void __iomem *base;
- u32 hoststatus;
-
- base = host->base;
-
- hoststatus = readl(base + MMCISTATUS);
- hoststatus &= readl(base + MMCIMASK0);
-
- while (hoststatus) {
- if ((hoststatus & MCI_XFER_IRQ_MASK))
- u8500_mmci_xfer_irq(host, hoststatus);
- if ((hoststatus & MCI_CMD_IRQ))
- u8500_mmci_cmd_irq(host, hoststatus);
- if ((hoststatus & MCI_DATA_IRQ))
- u8500_mmci_data_irq(host, hoststatus);
- if (hoststatus & MCI_SDIOIT) {
- /* Explicitly clear SDIOIT */
- writel(MCI_SDIOIT, (base + MMCICLEAR));
- /* printk("\n START SDIO IRQ handler"); */
- if (host->mmc->card && host->mmc->card->sdio_func[0] &&
- host->mmc->card->sdio_func[0]->irq_handler) {
- struct sdio_func *func = host->mmc->card->sdio_func[0];
- host->mmc->card->sdio_func[0]->irq_handler(func);
- /* printk("\n END SDIO IRQ handler"); */
- }
- }
- u8500_mmc_clearirqsrc(base, hoststatus);
- hoststatus = readl(base + MMCISTATUS);
- hoststatus &= readl(base + MMCIMASK0);
- }
-
- return IRQ_HANDLED;
-}
-
-/**
- * u8500_mmci_start_data() - Processes the command with data request recieved from MMC framework
- * @host: Pointer to the host structure for MMC
- * @data: Pointer to the mmc data structure
- * @cmd: Pointer to the mmc comand structure
- */
-static void u8500_mmci_start_data(struct u8500_mmci_host *host,
- struct mmc_data *data,
- struct mmc_command *cmd)
-{
- DECLARE_COMPLETION_ONSTACK(complete);
- void __iomem *base;
- unsigned long flag_lock = 0;
- unsigned int mem_addr;
-
- spin_lock_irqsave(&host->lock, flag_lock);
- host->data = data;
- host->cmd = cmd;
- host->size = data->blocks * data->blksz;
- host->data_xfered = 0;
- base = host->base;
-
- spin_unlock_irqrestore(&host->lock, flag_lock);
-
- u8500_mmci_init_sg(host, data);
-
- /**
- * Required for SDIO DMA mode, dynamic switching between polling
- * and DMA mode, depending on transfer size, and address alignment.
- * For transfer size < 32 and for element size unaligned address
- * SDIO host is configured in polling mode.
- */
- if ((host->cmd->opcode == SD_IO_RW_EXTENDED) &&
- (sdio_mode == MCI_DMAMODE)) {
- mem_addr = (unsigned int)(page_address(sg_page(host->sg_ptr)) +
- host->sg_ptr->offset) + host->sg_off;
-
- if ((mem_addr % DMA_ELEMENT_SZ) ||
- (host->size < MIN_DATA_SIZE_DMA))
- host->devicemode = MCI_POLLINGMODE;
- else
- host->devicemode = MCI_DMAMODE;
-
- }
-#ifdef SDIO_MULTIBYTE_WORKAROUND
- /**
- * Work around for multibyte mode, required for SDIO CMD 53
- * size alignment required as host controller H/W does not
- * support byte mode
- */
- if (host->cmd && (host->cmd->opcode == SD_IO_RW_EXTENDED) && !(host->cmd->arg & 0x08000000)) {
- host->aligned_blksz = (1 << __fls(data->blksz));
- if (host->aligned_blksz < data->blksz) /* If the no. is not power of two, get next power of two */
- host->aligned_blksz = host->aligned_blksz << 1;
- if (host->aligned_blksz > 4096) /* Error handling, not sure if this will ever occur */
- host->aligned_blksz = data->blksz;
- host->cmd->arg &= ~(0x1FF); /* reset block size in command args to zero */
- if (host->aligned_blksz < 512)
- host->cmd->arg |= host->aligned_blksz;
- host->aligned_size = data->blocks * host->aligned_blksz;
- /* else blksz in arg will be zero. */
-#if 0
- else { /* 512 MULTI BYET not working , so always send 512 as block mode */
- host->cmd->arg |= data->blocks;
- host->cmd->arg |= 0x08000000;
- }
-#endif
- }
-#endif /* End of SDIO_MULTIBYTE_WORKAROUND */
- cmd->error = MMC_ERR_NONE;
- data->error = MMC_ERR_NONE;
-
- if (host->devicemode == MCI_DMAMODE)
- u8500_mmc_set_dma(host);
- /**
- * For a read we need to write to the data ctrl register first, then
- * send the command. For writes, the order is reversed.
- */
- if ((data->flags & MMC_DATA_READ))
- start_data_xfer(host);
- if (host->devicemode == MCI_DMAMODE)
- host->dma_done = &complete;
- u8500_mmc_send_cmd(base, cmd->opcode, cmd->arg, cmd->flags, host->devicemode);
-
- /**
- * Required for SDIO interrupt from card , always enable SDIOIT ,
- * even if MMC_CAP_SDIO_IRQ is not set
- */
- if ((host->is_sdio == 1) /* && (host->mmc->caps & MMC_CAP_SDIO_IRQ) */) {
- /* Explicitly enable SDIOIT */
- if (host->sdio_setirq && !(host->sdio_irqstatus)) {
- /* If nterrupt is not already enabled then enable SDIOIT MASK */
- writel(MCI_SDIOIT, (base + MMCICLEAR));
- writel((readl(base + MMCIMASK0) | MCI_SDIOIT), (base + MMCIMASK0));
- host->sdio_irqstatus = 1;
- } else if (!(host->sdio_setirq) && (host->sdio_irqstatus)) {
- /* If SDIO is not already disabled then disable SDIOIT */
- u32 temp = readl(base + MMCIMASK0);
- temp &= ~(MCI_SDIOIT);
- writel(temp, (base + MMCIMASK0));
- host->sdio_irqstatus = 0;
- }
- }
-
- if (host->devicemode == MCI_POLLINGMODE) {
- if (!(data->flags & MMC_DATA_READ))
- wait_for_command_end(host);
- while (data->error == MMC_ERR_NONE && host->data) {
- u8500_mmci_read_write(host);
- schedule();
- }
- }
- return ;
-}
-/**
- * u8500_mmci_start_command() - Processes the command request recieved from MMC framework
- * @host: Pointer to the host structure for MMC
- * @cmd: Pointer to the mmc command structure
- */
-static void
-u8500_mmci_start_command(struct u8500_mmci_host *host,
- struct mmc_command *cmd)
-{
- void __iomem *base = host->base;
-
- host->cmd = cmd;
- u8500_mmc_send_cmd(base, cmd->opcode, cmd->arg, cmd->flags, host->devicemode);
- if (host->devicemode == MCI_POLLINGMODE) {
- wait_for_command_end(host);
- }
- return;
-}
-
-/**
- * u8500_mmci_request() - Processes the request recieved from MMC framework
- * @mmc: Pointer to the host structure for MMC
- * @mrq: Pointer to the mmc request structure
- */
-static void u8500_mmci_request(struct mmc_host *mmc, struct mmc_request *mrq)
-{
- struct u8500_mmci_host *host = mmc_priv(mmc);
- WARN_ON(host->mrq != NULL);
- if (host->mrq != NULL) {
- mrq->cmd->error = -EIO;
- if (mrq->data)
- mrq->data->bytes_xfered = 0;
- return;
- }
- host->mrq = mrq;
- if (mrq->data && mrq->data->flags & (MMC_DATA_READ | MMC_DATA_WRITE))
- u8500_mmci_start_data(host, mrq->data, mrq->cmd);
- else
- u8500_mmci_start_command(host, mrq->cmd);
-}
-
-/**
- * u8500_mmci_set_ios() - Perform configuration related settings for MMC host
- * @mmc: the pointer to the host structure for MMC
- * @ios: pointer to the configuration settings to be done
- */
-static void u8500_mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
-{
- struct u8500_mmci_host *host = mmc_priv(mmc);
- u32 clk = 0;
-
- /**
- * Make sure we aren't changing the control registers too soon after
- * writing data.
- */
- udelay(10);
- /* Set the bus and power modes */
- switch (ios->power_mode) {
- case MMC_POWER_OFF:
- if (!host->level_shifter) {
- writel(0x40, host->base + MMCIPOWER);
- } else {
- writel(0xBC, host->base + MMCIPOWER);
- }
-
- if (host->board->set_power)
- host->board->set_power(mmc_dev(mmc), 0);
-#ifdef CONFIG_REGULATOR
- /* we disable the supplies for the SD */
- if (host->level_shifter) {
- if (regulator_is_enabled(host->regulator))
- regulator_disable(host->regulator);
- }
-#endif
- break;
- case MMC_POWER_UP:
- if (!host->level_shifter) {
- writel(0x42, host->base + MMCIPOWER);
- } else {
- writel(0xBE, host->base + MMCIPOWER);
- }
-
- if (host->board->set_power)
- host->board->set_power(mmc_dev(mmc), 1);
- if ((host->is_sdio == 1) && (!host->level_shifter))
- writel(0xBE, host->base + MMCIPOWER);
-#ifdef CONFIG_REGULATOR
- if (host->level_shifter) {
- if (!regulator_is_enabled(host->regulator))
- regulator_enable(host->regulator);
- }
-#endif
- break;
- case MMC_POWER_ON:
- if (!host->level_shifter)
- writel(0x43, host->base + MMCIPOWER);
- else
- writel(0xBF, host->base + MMCIPOWER);
- if ((host->is_sdio == 1) && (!host->level_shifter))
- writel(0x3, host->base + MMCIPOWER);
- break;
- }
- if (ios->clock) {
- if (ios->clock >= (host->mclk / 2))
- clk = 0;
- else {
- u32 div = host->mclk / ios->clock;
- if (div > 2) {
- clk = div - 2;
- if (clk > 255)
- clk = 255;
- } else
- clk = 0;
-
- host->cclk = host->mclk / (clk + 2);
- if (host->cclk > ios->clock) {
- clk += 1;
- host->cclk = host->mclk / (clk + 2);
- }
- }
- if ((host->devicemode == MCI_DMAMODE)
- && !host->is_sdio && !host->level_shifter)
- clk |= MCI_CLK_PWRSAVE;
- clk |= (MCI_HWFC_EN | MCI_CLK_ENABLE);
- writel(clk, host->base + MMCICLOCK);
- }
-
- if (!host->level_shifter) {
- if (ios->bus_mode == MMC_BUSMODE_PUSHPULL)
- writel(0x03, host->base + MMCIPOWER);
- }
- switch (ios->bus_width) {
- case MMC_BUS_WIDTH_1:
- break;
- case MMC_BUS_WIDTH_4:
- clk = readl(host->base + MMCICLOCK);
- clk |= MCI_BUS_WIDTH_4;
- writel(clk, host->base + MMCICLOCK);
- break;
- case MMC_BUS_WIDTH_8:
- clk = readl(host->base + MMCICLOCK);
- clk |= MCI_BUS_WIDTH_8;
- writel(clk, host->base + MMCICLOCK);
- break;
- default:
- printk(KERN_INFO "u8500_mmci_setios(): whats going on ??");
- break;
- }
-}
-
-/**
- * u8500_mmci_enable() - Perform enable, according to the mmc
- * enable/disable framework to exit power saveing state.
- * @mmc: the pointer to the host structure for MMC
- */
-static int u8500_mmci_enable(struct mmc_host *mmc)
-{
- struct u8500_mmci_host *host = mmc_priv(mmc);
- if (host->host_reg)
- regulator_enable(host->host_reg);
- clk_enable(host->clk);
- mmc_power_restore_host(host->mmc);
- return 0;
-}
-
-/**
- * u8500_mmci_disable() - Perform disable, according to the mmc
- * enable/disable framework to enter power saveing state.
- * @mmc: the pointer to the host structure for MMC
- * @lazy: indicates if the host should be claimed and thus
- * handles recursion
- */
-static int u8500_mmci_disable(struct mmc_host *mmc, int lazy)
-{
- struct u8500_mmci_host *host = mmc_priv(mmc);
-
- if (lazy && !mmc_try_claim_host(host->mmc))
- return U8500_MMC_DISABLED_TIMEOUT;
- mmc_power_save_host(host->mmc);
- clk_disable(host->clk);
- if (host->host_reg)
- regulator_disable(host->host_reg);
- if (lazy)
- mmc_release_host(host->mmc);
- return 0;
-}
-
-static void sdio_enableirq(struct mmc_host *mmc, int enable)
-{
- struct u8500_mmci_host *host = mmc_priv(mmc);
- printk(KERN_INFO "mmc-u8500: sdio_enableirq= %d", enable);
- if (host && host->is_sdio)
- host->sdio_setirq = enable;
-}
-
-static struct mmc_host_ops u8500_mmci_ops = {
- .request = u8500_mmci_request,
- .set_ios = u8500_mmci_set_ios,
- .enable_sdio_irq = sdio_enableirq,
- .enable = u8500_mmci_enable,
- .disable = u8500_mmci_disable,
-};
-
-/**
- * u8500_mmci_check_status() - checks the status of the card on every interval
- * @data: pointer to the current host
- *
- * this function will check the status of the card on every interval
- * of the time configured and inform the status to the mmc stack
- */
-static void u8500_mmci_check_status(void *data)
-{
- struct u8500_mmci_host *host = (struct u8500_mmci_host *) data;
- mdelay(50);
- mmc_detect_change(host->mmc, 30);
- return;
-}
-
-/**
- * u8500_mmci_probe() - intilaizing the mmc device
- * @dev: mmc device pointer
- * @id: bus_id
- *
- * this function will use the current mmc device pointer, initialize and configure
- * the device, allocate the memory for the device,request the memory region with the
- * device name and scan the device
- */
-static int u8500_mmci_probe(struct amba_device *dev, struct amba_id *id)
-{
- struct u8500_mmci_host *host;
- struct mmc_host *mmc;
- int ret;
- int devicemode = mmc_mode;
- struct mmc_board *board = dev->dev.platform_data;
- printk(KERN_INFO
- "MMC: operating mode is set to %d [where 1=dma,2=poll,3=intr]",
- devicemode);
- if (!board) {
- printk(KERN_ERR "mmc: Platform data not set");
- return -EINVAL;
- }
- if (board->is_sdio)
- devicemode = sdio_mode;
- else
- devicemode = mmc_mode;
-
- if (board->init) {
- ret = board->init(dev);
- if (ret) {
- printk(KERN_ERR
- "mmc-u8500: Error in configuring MMC\n");
- goto out;
- }
- }
-
- ret = amba_request_regions(dev, DRIVER_NAME);
- if (ret) {
- printk(KERN_ERR "mmc-u8500: Error in amba_request_region\n");
- goto configure_mmc;
- }
- mmc = mmc_alloc_host(sizeof(struct u8500_mmci_host), &dev->dev);
- if (!mmc) {
- ret = -ENOMEM;
- goto rel_regions;
- }
- host = mmc_priv(mmc);
- host->oldstat = -1;
- host->mclk = MMC_HOST_CLK_MAX;
- host->mmc = mmc;
- host->board = board;
- if (board->bus_resume_flags) {
- host->bus_resume_flags = board->bus_resume_flags;
- mmc->bus_resume_flags = host->bus_resume_flags;
- }
-
- if (board->level_shifter)
- host->level_shifter = board->level_shifter;
- /**
- * For SDIO , as DMA to polling switching happens dynamically , always need to allocate buffer
- */
- if (board->is_sdio || (devicemode == MCI_POLLINGMODE)) {
- host->buffer = vmalloc(MAX_DATA);
- if (!host->buffer) {
- ret = -ENOMEM;
- goto free_mmc;
- }
- }
- host->base = ioremap(dev->res.start, SZ_4K);
- if (!host->base) {
- ret = -ENOMEM;
- goto host_free;
- }
- mmc->ops = &u8500_mmci_ops;
- mmc->f_max = min(host->mclk, fmax);
- mmc->f_min = MMC_HOST_CLK_MAX / (MMC_CLK_DIV + 2);
- if (devicemode == MCI_DMAMODE)
- mmc->caps = host->board->caps;
- host->host_reg = regulator_get(&dev->dev, "v-mmc");
- if (IS_ERR(host->host_reg)) {
- dev_warn(&dev->dev, "could not get mmc host regulator");
- host->host_reg = NULL;
- }
-
- host->is_sdio = board->is_sdio;
- if (host->is_sdio) {
- if (host->board->caps & MMC_CAP_SDIO_IRQ)
- host->sdio_setirq = 0;
- else
- host->sdio_setirq = 1;
- /* Make IRQ enable even when SDIO_IRQ is not supported in capability */
-
- host->sdio_irqstatus = 0;
- mmc->caps = host->board->caps;
- }
-
- host->devicemode = devicemode;
- /*
- * We can do SGIO
- */
- if (devicemode == MCI_DMAMODE) {
- /* scatter/gather DMA */
- mmc->max_hw_segs = MMC_MAX_HW_SEGMENTS;
- mmc->max_phys_segs = MMC_MAX_PHY_SEGMENTS;
- } else {
- mmc->max_hw_segs = 1;
- mmc->max_phys_segs = 1;
- }
- mmc->ocr_avail = OCR_AVAIL;
- /**
- * XXX No errors in Tx/Rx but writes garbage data with mmc->max_req_size = 32768;
- */
-#ifdef DMA_SCATERGATHER
- mmc->max_req_size = MMC_MAX_REQ_SIZE;
-#else
- mmc->max_req_size = 4096;
-#endif
- mmc->max_seg_size = MMC_MAX_SEG_SIZE;
-
- mmc->max_blk_size = 4096;
- if (devicemode == MCI_DMAMODE)
- mmc->max_blk_count = mmc->max_req_size / MMC_HOST_BLK_SIZE;
- else
- mmc->max_blk_count = 64;
- spin_lock_init(&host->lock);
-
-#ifdef CONFIG_REGULATOR
- /* attach regulator for on board emmc */
- if (board->supply) {
- host->regulator = regulator_get(&dev->dev, board->supply);
- if (IS_ERR(host->regulator)) {
- ret = PTR_ERR(host->regulator);
- goto host_free;
- }
- regulator_set_voltage(host->regulator,
- board->min_supply_voltage,
- board->max_supply_voltage);
- regulator_enable(host->regulator);
- }
-#endif
- host->clk = clk_get(&dev->dev, NULL);
- if (IS_ERR(host->clk)) {
- ret = PTR_ERR(host->clk);
-#ifdef CONFIG_REGULATOR
- goto put_regulator;
-#else
- goto unmap;
-#endif
- }
-
- if (host->host_reg) {
- mmc->caps |= MMC_CAP_DISABLE;
- mmc_set_disable_delay(mmc, U8500_MMC_DISABLED_TIMEOUT);
- regulator_enable(host->host_reg);
- }
- clk_enable(host->clk);
- writel(0, host->base + MMCIMASK0);
- writel(0xfff, host->base + MMCICLEAR);
- if ((devicemode != MCI_POLLINGMODE) || (host->is_sdio == 1)) {
- /* interrupt should always be enabled for I/O cards */
- ret = request_irq(dev->irq[0], u8500_mmci_irq,
- IRQF_DISABLED/* SA_INTERRUPT */, DRIVER_NAME, host);
- if (ret)
- goto put_clk;
- }
- amba_set_drvdata(dev, mmc);
- if (board->card_detect) {
- board->card_detect(u8500_mmci_check_status, (void *)host);
- host->card_detect_intr_value = board->card_detect_intr_value;
- }
- printk(KERN_INFO
- "mmc-u8500: %s: MMCI rev %x cfg %02x at 0x%08x irq %d",
- mmc_hostname(mmc), amba_rev(dev), amba_config(dev),
- dev->res.start, dev->irq[0]);
- if (devicemode == MCI_DMAMODE) {
- dma_cap_mask_t mask;
-
-#ifndef DMA_SCATERGATHER
- host->dma_buffer = (u32 *)dma_alloc_coherent(NULL, 4096, &host->dma, (GFP_KERNEL | GFP_DMA));
-#endif
-
- dma_cap_zero(mask);
- dma_cap_set(DMA_SLAVE, mask);
-
- host->dmach_mmc2mem
- = dma_request_channel(mask, host->board->dma_filter,
- host->board->dma_mmc2mem);
- if (host->dmach_mmc2mem == NULL) {
- printk(KERN_ERR "mmc-u8500: RX pipe request failed\n");
- goto irq0_free;
- }
-
- dma_cap_zero(mask);
- dma_cap_set(DMA_SLAVE, mask);
-
- host->dmach_mem2mmc
- = dma_request_channel(mask, host->board->dma_filter,
- host->board->dma_mem2mmc);
- if (host->dmach_mmc2mem == NULL) {
- printk(KERN_ERR "mmc-u8500: TX pipe request failed\n");
- goto mem2mmc_dmareq_failed;
- }
-
- }
- /*
- * SDIO host structure is saved into global pointer
- * Used for sysfs implementation for dynamic detection of I/O cards
- * Also create sysfs file for detect_card
- */
- if (host->is_sdio) {
- ret = device_create_file(&dev->dev, &dev_attr_detect_card);
- if (ret < 0) {
- printk(KERN_ERR "mmc-u8500: Could not create sysfs"
- "file for SDIO detect_card\n");
- goto create_file_failed;
- }
- sdio_host_ptr = host;
- }
-
- ret = mmc_add_host(mmc);
- if (ret)
- goto add_host_failed;
-
- if (host->host_reg)
- regulator_disable(host->host_reg);
- return 0;
-add_host_failed:
- if (host->is_sdio)
- device_remove_file(&dev->dev, &dev_attr_detect_card);
-create_file_failed:
- if (host->dmach_mem2mmc)
- dma_release_channel(host->dmach_mem2mmc);
-mem2mmc_dmareq_failed:
- if (host->dmach_mmc2mem)
- dma_release_channel(host->dmach_mmc2mem);
-irq0_free:
- if (devicemode != MCI_POLLINGMODE || host->is_sdio)
- free_irq(dev->irq[0], host);
-put_clk:
- clk_disable(host->clk);
- clk_put(host->clk);
-#ifdef CONFIG_REGULATOR
-put_regulator:
- if (host->regulator) {
- if (regulator_is_enabled(host->regulator))
- regulator_disable(host->regulator);
- regulator_put(host->regulator);
- }
-#else
-unmap:
-#endif
- iounmap(host->base);
-host_free:
- vfree(host->buffer);
-free_mmc:
- mmc_free_host(mmc);
-rel_regions:
- amba_release_regions(dev);
-configure_mmc:
- if (board->exit)
- board->exit(dev);
-out:
- return ret;
-}
-/**
- * u8500_mmci_remove() - Remove the mmc by freeing all resources
- * @dev: current mmc device pointer
- *
- * this function will remove the mmc by freeing all resources used by the device by using
- * the current mmc device pointer
- */
-static int u8500_mmci_remove(struct amba_device *dev)
-{
- struct mmc_board *board = dev->dev.platform_data;
- struct mmc_host *mmc = amba_get_drvdata(dev);
-
- printk(KERN_INFO "MMC module removed\n");
- if (!board)
- return -EINVAL;
- amba_set_drvdata(dev, NULL);
- if (mmc) {
- struct u8500_mmci_host *host = mmc_priv(mmc);
-
- /*
- * global pointer for storing SDIO host structure is cleared
- * Used for sysfs implementation for dynamic detection of
- * I/O cards. Also remove sysfs file for detect_card
- */
- if (host->is_sdio) {
- sdio_host_ptr = NULL;
- device_remove_file(&dev->dev, &dev_attr_detect_card);
- }
- mmc_remove_host(mmc);
- dma_release_channel(host->dmach_mmc2mem);
- dma_release_channel(host->dmach_mem2mmc);
- host->dmach_mmc2mem = NULL;
- host->dmach_mem2mmc = NULL;
- if (host->host_reg)
- regulator_enable(host->host_reg);
- writel(0, host->base + MMCIMASK0);
- writel(0, host->base + MMCICOMMAND);
- writel(0, host->base + MMCIDATACTRL);
- free_irq(dev->irq[0], host);
- iounmap(host->base);
- if (host->host_reg) {
- regulator_disable(host->host_reg);
- regulator_put(host->host_reg);
- }
- vfree(host->buffer);
- mmc_free_host(mmc);
- amba_release_regions(dev);
- if (board->exit)
- board->exit(dev);
- clk_disable(host->clk);
- clk_put(host->clk);
-#ifdef CONFIG_REGULATOR
- if (host->regulator) {
- if (regulator_is_enabled(host->regulator))
- regulator_disable(host->regulator);
- regulator_put(host->regulator);
- }
-#endif
- }
- return 0;
-}
-#ifdef CONFIG_PM
-/**
- * u8500_mmci_suspend() - Use the current mmc device pointer and called the mmc suspend function
- * @dev: current mmc device pointer
- * @state: state suspend state
- */
-static int u8500_mmci_suspend(struct amba_device *dev, pm_message_t state)
-{
- struct mmc_host *mmc = amba_get_drvdata(dev);
- int ret = 0;
-
- if (mmc) {
- struct u8500_mmci_host *host = mmc_priv(mmc);
- mmc_host_enable(host->mmc);
- ret = mmc_suspend_host(mmc, state);
- if (ret)
- dev_err(mmc_dev(host->mmc),
- "Failed to suspend mmci host during suspend");
- if (host->level_shifter)
- host->board->card_detect_intr_conf(0);
-#ifdef CONFIG_REGULATOR
- if (host->board->supply) {
- if (!host->level_shifter) {
- if (regulator_is_enabled(host->regulator))
- regulator_disable(host->regulator);
- }
- }
-#endif
- ret = mmc_host_disable(host->mmc);
- if (ret) {
- dev_err(mmc_dev(host->mmc),
- "Failed to disable mmci host during suspend");
- return ret;
- }
- }
- return ret;
-}
-/**
- * u8500_mmci_resume() - Use the current mmc device pointer and called the mmc resume function
- * @dev: mmc device pointer
- */
-static int u8500_mmci_resume(struct amba_device *dev)
-{
- struct mmc_host *mmc = amba_get_drvdata(dev);
- int ret = 0;
-
- if (mmc) {
- struct u8500_mmci_host *host = mmc_priv(mmc);
- if (host->level_shifter)
- host->board->card_detect_intr_conf(1);
-#ifdef CONFIG_REGULATOR
- if (host->board->supply) {
- if (!host->level_shifter) {
- if (!regulator_is_enabled(host->regulator))
- regulator_enable(host->regulator);
- }
- }
-#endif
- ret = mmc_host_enable(host->mmc);
- if (ret) {
- clk_disable(host->clk);
- dev_err(mmc_dev(host->mmc),
- "Failed to enable mmci host during resume");
- return ret;
- }
- ret = mmc_resume_host(mmc);
- if (ret)
- dev_err(mmc_dev(host->mmc),
- "Failed to resume mmci host during resume");
- mmc_host_lazy_disable(host->mmc);
- }
- return ret;
-}
-#else
-#define u8500_mmci_suspend NULL
-#define u8500_mmci_resume NULL
-#endif
-
-
-static struct amba_id u8500_mmci_ids[] = {
- {
- .id = SDI_PER_ID,
- .mask = SDI_PER_MASK,
- },
- {0, 0, 0},
-};
-
-static struct amba_driver u8500_mmci_driver = {
- .drv = {
- .name = DRIVER_NAME,
- },
- .probe = u8500_mmci_probe,
- .remove = u8500_mmci_remove,
- .suspend = u8500_mmci_suspend,
- .resume = u8500_mmci_resume,
- .id_table = u8500_mmci_ids,
-};
-/**
- * u8500_mmci_init() - register the mmc driver as amba driver
- * @void: No arguments
- */
-static int __init u8500_mmci_init(void)
-{
- return amba_driver_register(&u8500_mmci_driver);
-}
-/**
- * u8500_mmci_exit() - unregister the amba mmc driver
- * @void: No arguments
- */
-static void __exit u8500_mmci_exit(void)
-{
- amba_driver_unregister(&u8500_mmci_driver);
-}
-/**
- * module_init - register the amba mmc driver to the kernel
- * @u8500_mmci_init: mmc init function call
- */
-module_init(u8500_mmci_init);
-/**
- * module_exit() - unregister the amba mmc driver to the kernel
- * @u8500_mmci_exit: mmc exit function call
- */
-module_exit(u8500_mmci_exit);
-
-MODULE_AUTHOR("Hanumath Prasad(hanumath.prasad@stericcson.com)");
-MODULE_DESCRIPTION("ARM PrimeCell PL180 Multimedia Card Interface driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/host/mmc-u8500.h b/drivers/mmc/host/mmc-u8500.h
deleted file mode 100644
index ae084288c0b..00000000000
--- a/drivers/mmc/host/mmc-u8500.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2008 STMicroelectronics
- *
- * 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 __MMC_NOMADIK
-#define __MMC_NOMADIK
-
-#define MMC_ERR_NONE 0
-#define MMC_ERR_TIMEOUT 1
-#define MMC_ERR_BADCRC 2
-#define MMC_ERR_FIFO 3
-#define MMC_ERR_FAILED 4
-#define MMC_ERR_INVALID 5
-
-#define MMC_VDD_18_19 0x00000040 /* VDD voltage 1.8 - 1.9 */
-#define MMC_VDD_17_18 0x00000020 /* VDD voltage 1.7 - 1.8 */
-#define MMC_VDD_32_33 0x00100000 /* VDD voltage 3.2 ~ 3.3 */
-#define MMC_VDD_33_34 0x00200000 /* VDD voltage 3.3 ~ 3.4 */
-
-#endif
-