mmc: add atomic operation for register

This commit is contained in:
lintao
2014-09-22 10:14:03 +08:00
parent 27c40940f7
commit 1c912e0e91
2 changed files with 26 additions and 4 deletions

View File

@@ -872,6 +872,7 @@ disable:
static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data)
{
int sg_len;
unsigned long flags;
u32 temp;
host->using_dma = 0;
@@ -910,9 +911,11 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data)
mci_writel(host, CTRL, temp);
/* Disable RX/TX IRQs, let DMA handle it */
spin_lock_irqsave(&host->slock, flags);
temp = mci_readl(host, INTMASK);
temp &= ~(SDMMC_INT_RXDR | SDMMC_INT_TXDR);
mci_writel(host, INTMASK, temp);
spin_unlock_irqrestore(&host->slock, flags);
host->dma_ops->start(host, sg_len);
@@ -922,6 +925,7 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data)
static void dw_mci_submit_data(struct dw_mci *host, struct mmc_data *data)
{
u32 temp;
unsigned long flag;
data->error = -EINPROGRESS;
@@ -954,10 +958,12 @@ static void dw_mci_submit_data(struct dw_mci *host, struct mmc_data *data)
host->part_buf_start = 0;
host->part_buf_count = 0;
spin_lock_irqsave(&host->slock, flag);
mci_writel(host, RINTSTS, SDMMC_INT_TXDR | SDMMC_INT_RXDR);
temp = mci_readl(host, INTMASK);
temp |= SDMMC_INT_TXDR | SDMMC_INT_RXDR;
mci_writel(host, INTMASK, temp);
spin_unlock_irqrestore(&host->slock, flag);
temp = mci_readl(host, CTRL);
temp &= ~SDMMC_CTRL_DMA_ENABLE;
@@ -1704,11 +1710,11 @@ static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb)
{
struct dw_mci_slot *slot = mmc_priv(mmc);
struct dw_mci *host = slot->host;
//unsigned long flags;
unsigned long flags;
u32 int_mask;
u32 sdio_int;
//spin_lock_irqsave(&host->lock, flags);
spin_lock_irqsave(&host->slock, flags);
/* Enable/disable Slot Specific SDIO interrupt */
int_mask = mci_readl(host, INTMASK);
@@ -1734,7 +1740,7 @@ static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb)
(int_mask & ~sdio_int));
}
//spin_unlock_irqrestore(&host->lock, flags);
spin_unlock_irqrestore(&host->slock, flags);
}
#ifdef CONFIG_MMC_DW_ROCKCHIP_SWITCH_VOLTAGE
@@ -3700,6 +3706,7 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
static void dw_mci_dealwith_timeout(struct dw_mci *host)
{
u32 ret, i, regs;
u32 sdio_int;
switch(host->state){
case STATE_IDLE:
@@ -3734,7 +3741,18 @@ static void dw_mci_dealwith_timeout(struct dw_mci *host)
| SDMMC_INT_RXDR | SDMMC_INT_VSI | DW_MCI_ERROR_FLAGS;
if(!(host->mmc->restrict_caps & RESTRICT_CARD_TYPE_SDIO))
regs |= SDMMC_INT_CD;
mci_writel(host, INTMASK, regs);
if ((host->mmc->restrict_caps & RESTRICT_CARD_TYPE_SDIO)) {
if (host->verid < DW_MMC_240A)
sdio_int = SDMMC_INT_SDIO(0);
else
sdio_int = SDMMC_INT_SDIO(8);
if (mci_readl(host, INTMASK) & sdio_int)
regs |= sdio_int;
}
mci_writel(host, INTMASK, regs);
mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE);
for (i = 0; i < host->num_slots; i++) {
struct dw_mci_slot *slot = host->slot[i];
@@ -3758,6 +3776,7 @@ static void dw_mci_dto_timeout(unsigned long host_data)
disable_irq(host->irq);
dev_err(host->dev, "data_over interrupt timeout!\n");
host->data_status = SDMMC_INT_EBE;
mci_writel(host, RINTSTS, 0xFFFFFFFF);
dw_mci_dealwith_timeout(host);
@@ -3862,6 +3881,8 @@ int dw_mci_probe(struct dw_mci *host)
host->svi_flags = 0;
spin_lock_init(&host->lock);
spin_lock_init(&host->slock);
INIT_LIST_HEAD(&host->queue);
INIT_DELAYED_WORK(&host->resume_rescan, resume_rescan_enable);
/*

View File

@@ -128,6 +128,7 @@ struct mmc_data;
*/
struct dw_mci {
spinlock_t lock;
spinlock_t slock;
void __iomem *regs;
struct scatterlist *sg;