Phaneendra, The patch description should be
[PATCH] DaVinci: DM355 SDIO support You use a printk in your patch. That should be replaced I believe with an appropriate dev_dbg or dev_warn. BTW you use dev_dbg in another part of your patch. Thanks, Sandeep > -----Original Message----- > From: [email protected] > [mailto:[email protected]] On Behalf > Of Phaneendra kumar > Sent: Wednesday, July 29, 2009 8:57 AM > To: [email protected] > Subject: DM355 SDIO support > > > Hi all, > > This patch will add SDIO support to the DM355 host controller driver. > > I have verified this on DM355 EVM board in both DMA and PIO modes. And i > have used open source libertas driver for verifying the SDIO > functionality. > > Signed-off-by: Phaneendra Kumar <[email protected]> > ----- > diff --git a/drivers/mmc/host/davinci_mmc.c > b/drivers/mmc/host/davinci_mmc.c > index 8907b72..0744059 100644 > --- a/drivers/mmc/host/davinci_mmc.c > +++ b/drivers/mmc/host/davinci_mmc.c > @@ -31,6 +31,8 @@ > #include <linux/delay.h> > #include <linux/dma-mapping.h> > #include <linux/mmc/mmc.h> > +#include <linux/timer.h> > +#include <linux/mmc/card.h> > > #include <mach/mmc.h> > #include <mach/edma.h> > @@ -65,8 +67,8 @@ > #define DAVINCI_MMCBLNC 0x60 > #define DAVINCI_SDIOCTL 0x64 > #define DAVINCI_SDIOST0 0x68 > -#define DAVINCI_SDIOEN 0x6C > -#define DAVINCI_SDIOST 0x70 > +#define DAVINCI_SDIOIEN 0x6C > +#define DAVINCI_SDIOIST 0x70 > #define DAVINCI_MMCFIFOCTL 0x74 /* FIFO Control Register */ > > /* DAVINCI_MMCCTL definitions */ > @@ -133,6 +135,23 @@ > /* MMCSD Init clock in Hz in opendrain mode */ > #define MMCSD_INIT_CLOCK 200000 > > +/* DAVINCI_SDIOCTL definitions */ > +#define SDIOCTL_RDWTRQ_SET (1 << 0) > +#define SDIOCTL_RDWTCR_SET (1 << 0) > + > +/* DAVINCI_SDIOST0 definitions */ > +#define SDIOST0_DAT1_HI (1 << 0) > +#define SDIOST0_INTPRD (1 << 1) > +#define SDIOST0_RDWTST (1 << 2) > + > +/* DAVINCI_SDIOIEN definitions */ > +#define SDIOIEN_IOINTEN (1 << 0) > +#define SDIOIEN_RWSEN (1 << 1) > + > +/* DAVINCI_SDIOIST definitions */ > +#define SDIOIST_IOINT (1 << 0) > +#define SDIOIST_RWS (1 << 1) > + > /* > * One scatterlist dma "segment" is at most MAX_CCNT rw_threshold units, > * and we handle up to NR_SG segments. MMC_BLOCK_BOUNCE kicks in only > @@ -181,6 +200,10 @@ struct mmc_davinci_host { > u32 rxdma, txdma; > bool use_dma; > bool do_dma; > + struct timer_list sdio_timer; > + u32 sdioInt; > + /* For sdio irq enabling and disabling */ > + spinlock_t sdio_lock; > > /* Scatterlist DMA uses one or more parameter RAM entries: > * the main one (associated with rxdma or txdma) plus zero or > @@ -202,6 +225,41 @@ struct mmc_davinci_host { > unsigned ns_in_one_cycle; > }; > > +static void mmc_enable_sdio_irq(struct mmc_host *mmc, int enable); > + > +static inline void davinci_sdio_intr_chck(struct mmc_davinci_host *host) > +{ > + if (host->mmc->caps & MMC_CAP_SDIO_IRQ) { > + if (!((readl(host->base + DAVINCI_SDIOST0)) & SDIOST0_DAT1_HI) > + && host->sdioInt) { > + writel(SDIOIST_IOINT, host->base + DAVINCI_SDIOIST); > + mmc_signal_sdio_irq(host->mmc); > + } > + } > +} > + > +static inline void davinci_cmd_dat_reset(struct mmc_davinci_host *host) > +{ > + u32 temp = 0; > + > + if (host->mmc->card) { > + if (mmc_card_sdio(host->mmc->card)) { > + temp = readl(host->base + DAVINCI_MMCCTL); > + writel(temp | MMCCTL_CMDRST | MMCCTL_DATRST, > + host->base + DAVINCI_MMCCTL); > + > + temp &= ~(MMCCTL_CMDRST | MMCCTL_DATRST); > + writel(temp, host->base + DAVINCI_MMCCTL); > + } > + } > +} > + > +static void davinci_sdio_timer(unsigned long data) > +{ > + struct mmc_davinci_host *host = (struct mmc_davinci_host *)data; > + > + davinci_sdio_intr_chck(host); > +} > > /* PIO only */ > static void mmc_davinci_sg_to_buf(struct mmc_davinci_host *host) > @@ -387,6 +445,15 @@ static void mmc_davinci_dma_cb(unsigned channel, u16 > ch_status, void *data) > if (DMA_COMPLETE != ch_status) { > struct mmc_davinci_host *host = data; > > + if (!(host->data)) { > + printk(KERN_ERR "DMA Event Miss / NULL Transfr\n"); > + edma_stop(host->txdma); > + edma_clean_channel(host->txdma); > + edma_stop(host->rxdma); > + edma_clean_channel(host->rxdma); > + return; > + } > + > /* Currently means: DMA Event Missed, or "null" transfer > * request was seen. In the future, TC errors (like bad > * addresses) might be presented too. > @@ -664,6 +731,14 @@ mmc_davinci_prepare_data(struct mmc_davinci_host > *host, struct mmc_request *req) > host->buffer = NULL; > host->bytes_left = data->blocks * data->blksz; > > + if (host->mmc->card) { > + if (mmc_card_sdio(host->mmc->card)) { > + if (data->blksz == 64) { > + mdelay(5); > + } > + } > + } > + > /* For now we try to use DMA whenever we won't need partial FIFO > * reads or writes, either for the whole transfer (as tested here) > * or for any individual scatterlist segment (tested when we call > @@ -706,6 +781,8 @@ static void mmc_davinci_request(struct mmc_host *mmc, > struct mmc_request *req) > return; > } > > + davinci_cmd_dat_reset(host); > + > host->do_dma = 0; > mmc_davinci_prepare_data(host, req); > mmc_davinci_start_command(host, req->cmd); > @@ -826,12 +903,9 @@ static void mmc_davinci_set_ios(struct mmc_host *mmc, > struct mmc_ios *ios) > static void > mmc_davinci_xfer_done(struct mmc_davinci_host *host, struct mmc_data > *data) > { > - host->data = NULL; > - host->data_dir = DAVINCI_MMC_DATADIR_NONE; > + davinci_abort_dma(host); > > if (host->do_dma) { > - davinci_abort_dma(host); > - > dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, > (data->flags & MMC_DATA_WRITE) > ? DMA_TO_DEVICE > @@ -839,11 +913,18 @@ mmc_davinci_xfer_done(struct mmc_davinci_host *host, > struct mmc_data *data) > host->do_dma = false; > } > > + host->data = NULL; > + host->data_dir = DAVINCI_MMC_DATADIR_NONE; > + > + davinci_cmd_dat_reset(host); > + > if (!data->stop || (host->cmd && host->cmd->error)) { > mmc_request_done(host->mmc, data->mrq); > writel(0, host->base + DAVINCI_MMCIM); > } else > mmc_davinci_start_command(host, data->stop); > + > + davinci_sdio_intr_chck(host); > } > > static void mmc_davinci_cmd_done(struct mmc_davinci_host *host, > @@ -870,6 +951,7 @@ static void mmc_davinci_cmd_done(struct > mmc_davinci_host *host, > mmc_request_done(host->mmc, cmd->mrq); > writel(0, host->base + DAVINCI_MMCIM); > } > + davinci_sdio_intr_chck(host); > } > > static void > @@ -895,6 +977,17 @@ static irqreturn_t mmc_davinci_irq(int irq, void > *dev_id) > int end_transfer = 0; > struct mmc_data *data = host->data; > > + if (host->mmc->caps & MMC_CAP_SDIO_IRQ) { > + status = readl(host->base + DAVINCI_SDIOIST); > + if (status & SDIOIST_IOINT) { > + dev_dbg(mmc_dev(host->mmc), > + "SDIO interrupt status %x\n", status); > + writel(status | SDIOIST_IOINT, > + host->base + DAVINCI_SDIOIST); > + mmc_signal_sdio_irq(host->mmc); > + } > + } > + > if (host->cmd == NULL && host->data == NULL) { > status = readl(host->base + DAVINCI_MMCST0); > dev_dbg(mmc_dev(host->mmc), > @@ -904,6 +997,7 @@ static irqreturn_t mmc_davinci_irq(int irq, void > *dev_id) > return IRQ_NONE; > } > > + davinci_sdio_intr_chck(host); > status = readl(host->base + DAVINCI_MMCST0); > qstatus = status; > > @@ -1031,11 +1125,41 @@ static int mmc_davinci_get_ro(struct mmc_host > *mmc) > return config->get_ro(pdev->id); > } > > +static void mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) > +{ > + struct mmc_davinci_host *host = mmc_priv(mmc); > + unsigned long flags; > + > + spin_lock_irqsave(&host->sdio_lock, flags); > + > + if (enable) { > + if (!((readl(host->base + DAVINCI_SDIOST0)) > + & SDIOST0_DAT1_HI)) { > + writel(SDIOIST_IOINT, > + host->base + DAVINCI_SDIOIST); > + mmc_signal_sdio_irq(host->mmc); > + }else { > + host->sdioInt = 1; > + mod_timer(&host->sdio_timer, jiffies + (HZ/100)); > + writel(readl(host->base + DAVINCI_SDIOIEN) | > + SDIOIEN_IOINTEN, host->base + DAVINCI_SDIOIEN); > + } > + } else { > + host->sdioInt = 0; > + del_timer(&host->sdio_timer); > + writel(readl(host->base + DAVINCI_SDIOIEN) & ~SDIOIEN_IOINTEN, > + host->base + DAVINCI_SDIOIEN); > + } > + > + spin_unlock_irqrestore(&host->sdio_lock, flags); > +} > + > static struct mmc_host_ops mmc_davinci_ops = { > .request = mmc_davinci_request, > .set_ios = mmc_davinci_set_ios, > .get_cd = mmc_davinci_get_cd, > .get_ro = mmc_davinci_get_ro, > + .enable_sdio_irq = mmc_enable_sdio_irq, > }; > > /*---------------------------------------------------------------------- > */ > @@ -1132,6 +1256,12 @@ static int __init davinci_mmcsd_probe(struct > platform_device *pdev) > /* REVISIT: someday, support IRQ-driven card detection. */ > mmc->caps |= MMC_CAP_NEEDS_POLL; > > + mmc->caps |= MMC_CAP_SDIO_IRQ; > + spin_lock_init(&host->sdio_lock); > + setup_timer(&host->sdio_timer, davinci_sdio_timer, > + (unsigned long)host); > + host->sdioInt = 0; > + > if (!pdata || pdata->wires == 4 || pdata->wires == 0) > mmc->caps |= MMC_CAP_4_BIT_DATA; > > _______________________________________________ > Davinci-linux-open-source mailing list > [email protected] > http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source _______________________________________________ Davinci-linux-open-source mailing list [email protected] http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source
