Lines Matching refs:host

2  *  linux/drivers/mmc/host/mxcmmc.c - Freescale i.MX MMCI driver
28 #include <linux/mmc/host.h>
197 static inline int is_imx31_mmc(struct mxcmci_host *host)
199 return host->devtype == IMX31_MMC;
202 static inline int is_mpc512x_mmc(struct mxcmci_host *host)
204 return host->devtype == MPC512X_MMC;
207 static inline u32 mxcmci_readl(struct mxcmci_host *host, int reg)
210 return ioread32be(host->base + reg);
212 return readl(host->base + reg);
215 static inline void mxcmci_writel(struct mxcmci_host *host, u32 val, int reg)
218 iowrite32be(val, host->base + reg);
220 writel(val, host->base + reg);
223 static inline u16 mxcmci_readw(struct mxcmci_host *host, int reg)
226 return ioread32be(host->base + reg);
228 return readw(host->base + reg);
231 static inline void mxcmci_writew(struct mxcmci_host *host, u16 val, int reg)
234 iowrite32be(val, host->base + reg);
236 writew(val, host->base + reg);
239 static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios);
241 static void mxcmci_set_power(struct mxcmci_host *host, unsigned int vdd)
243 if (!IS_ERR(host->mmc->supply.vmmc)) {
244 if (host->power_mode == MMC_POWER_UP)
245 mmc_regulator_set_ocr(host->mmc,
246 host->mmc->supply.vmmc, vdd);
247 else if (host->power_mode == MMC_POWER_OFF)
248 mmc_regulator_set_ocr(host->mmc,
249 host->mmc->supply.vmmc, 0);
252 if (host->pdata && host->pdata->setpower)
253 host->pdata->setpower(mmc_dev(host->mmc), vdd);
256 static inline int mxcmci_use_dma(struct mxcmci_host *host)
258 return host->do_dma;
261 static void mxcmci_softreset(struct mxcmci_host *host)
265 dev_dbg(mmc_dev(host->mmc), "mxcmci_softreset\n");
268 mxcmci_writew(host, STR_STP_CLK_RESET, MMC_REG_STR_STP_CLK);
269 mxcmci_writew(host, STR_STP_CLK_RESET | STR_STP_CLK_START_CLK,
273 mxcmci_writew(host, STR_STP_CLK_START_CLK, MMC_REG_STR_STP_CLK);
275 mxcmci_writew(host, 0xff, MMC_REG_RES_TO);
301 static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
313 host->data = data;
316 mxcmci_writew(host, nob, MMC_REG_NOB);
317 mxcmci_writew(host, blksz, MMC_REG_BLK_LEN);
318 host->datasize = datasize;
320 if (!mxcmci_use_dma(host))
325 host->do_dma = 0;
331 host->dma_dir = DMA_FROM_DEVICE;
334 host->dma_dir = DMA_TO_DEVICE;
340 nents = dma_map_sg(host->dma->device->dev, data->sg,
341 data->sg_len, host->dma_dir);
345 host->desc = dmaengine_prep_slave_sg(host->dma,
349 if (!host->desc) {
350 dma_unmap_sg(host->dma->device->dev, data->sg, data->sg_len,
351 host->dma_dir);
352 host->do_dma = 0;
357 dmaengine_submit(host->desc);
358 dma_async_issue_pending(host->dma);
360 mod_timer(&host->watchdog, jiffies + msecs_to_jiffies(MXCMCI_TIMEOUT_MS));
365 static void mxcmci_cmd_done(struct mxcmci_host *host, unsigned int stat);
366 static void mxcmci_data_done(struct mxcmci_host *host, unsigned int stat);
370 struct mxcmci_host *host = data;
373 del_timer(&host->watchdog);
375 stat = mxcmci_readl(host, MMC_REG_STATUS);
376 mxcmci_writel(host, stat & ~STATUS_DATA_TRANS_DONE, MMC_REG_STATUS);
378 dev_dbg(mmc_dev(host->mmc), "%s: 0x%08x\n", __func__, stat);
381 mxcmci_writel(host, STATUS_READ_OP_DONE, MMC_REG_STATUS);
383 mxcmci_data_done(host, stat);
386 static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd,
389 u32 int_cntr = host->default_irq_mask;
392 WARN_ON(host->cmd != NULL);
393 host->cmd = cmd;
409 dev_err(mmc_dev(host->mmc), "unhandled response type 0x%x\n",
417 if (mxcmci_use_dma(host)) {
418 if (host->dma_dir == DMA_FROM_DEVICE) {
419 host->desc->callback = mxcmci_dma_callback;
420 host->desc->callback_param = host;
426 spin_lock_irqsave(&host->lock, flags);
427 if (host->use_sdio)
429 mxcmci_writel(host, int_cntr, MMC_REG_INT_CNTR);
430 spin_unlock_irqrestore(&host->lock, flags);
432 mxcmci_writew(host, cmd->opcode, MMC_REG_CMD);
433 mxcmci_writel(host, cmd->arg, MMC_REG_ARG);
434 mxcmci_writew(host, cmdat, MMC_REG_CMD_DAT_CONT);
439 static void mxcmci_finish_request(struct mxcmci_host *host,
442 u32 int_cntr = host->default_irq_mask;
445 spin_lock_irqsave(&host->lock, flags);
446 if (host->use_sdio)
448 mxcmci_writel(host, int_cntr, MMC_REG_INT_CNTR);
449 spin_unlock_irqrestore(&host->lock, flags);
451 host->req = NULL;
452 host->cmd = NULL;
453 host->data = NULL;
455 mmc_request_done(host->mmc, req);
458 static int mxcmci_finish_data(struct mxcmci_host *host, unsigned int stat)
460 struct mmc_data *data = host->data;
463 if (mxcmci_use_dma(host)) {
464 dma_unmap_sg(host->dma->device->dev, data->sg, data->sg_len,
465 host->dma_dir);
470 dev_dbg(mmc_dev(host->mmc), "request failed. status: 0x%08x\n",
473 dev_err(mmc_dev(host->mmc), "%s: -EILSEQ\n", __func__);
478 dev_err(mmc_dev(host->mmc),
482 dev_err(mmc_dev(host->mmc),
487 dev_err(mmc_dev(host->mmc),
491 dev_err(mmc_dev(host->mmc), "%s: -EIO\n", __func__);
495 data->bytes_xfered = host->datasize;
500 host->data = NULL;
505 static void mxcmci_read_response(struct mxcmci_host *host, unsigned int stat)
507 struct mmc_command *cmd = host->cmd;
515 dev_dbg(mmc_dev(host->mmc), "CMD TIMEOUT\n");
518 dev_dbg(mmc_dev(host->mmc), "cmd crc error\n");
525 a = mxcmci_readw(host, MMC_REG_RES_FIFO);
526 b = mxcmci_readw(host, MMC_REG_RES_FIFO);
530 a = mxcmci_readw(host, MMC_REG_RES_FIFO);
531 b = mxcmci_readw(host, MMC_REG_RES_FIFO);
532 c = mxcmci_readw(host, MMC_REG_RES_FIFO);
538 static int mxcmci_poll_status(struct mxcmci_host *host, u32 mask)
544 stat = mxcmci_readl(host, MMC_REG_STATUS);
548 mxcmci_softreset(host);
549 mxcmci_set_clk_rate(host, host->clock);
558 static int mxcmci_pull(struct mxcmci_host *host, void *_buf, int bytes)
564 stat = mxcmci_poll_status(host,
568 *buf++ = cpu_to_le32(mxcmci_readl(host, MMC_REG_BUFFER_ACCESS));
576 stat = mxcmci_poll_status(host,
580 tmp = cpu_to_le32(mxcmci_readl(host, MMC_REG_BUFFER_ACCESS));
587 static int mxcmci_push(struct mxcmci_host *host, void *_buf, int bytes)
593 stat = mxcmci_poll_status(host, STATUS_BUF_WRITE_RDY);
596 mxcmci_writel(host, cpu_to_le32(*buf++), MMC_REG_BUFFER_ACCESS);
604 stat = mxcmci_poll_status(host, STATUS_BUF_WRITE_RDY);
609 mxcmci_writel(host, cpu_to_le32(tmp), MMC_REG_BUFFER_ACCESS);
612 stat = mxcmci_poll_status(host, STATUS_BUF_WRITE_RDY);
619 static int mxcmci_transfer_data(struct mxcmci_host *host)
621 struct mmc_data *data = host->req->data;
625 host->data = data;
626 host->datasize = 0;
630 stat = mxcmci_pull(host, sg_virt(sg), sg->length);
633 host->datasize += sg->length;
637 stat = mxcmci_push(host, sg_virt(sg), sg->length);
640 host->datasize += sg->length;
642 stat = mxcmci_poll_status(host, STATUS_WRITE_OP_DONE);
651 struct mxcmci_host *host = container_of(work, struct mxcmci_host,
653 int datastat = mxcmci_transfer_data(host);
655 mxcmci_writel(host, STATUS_READ_OP_DONE | STATUS_WRITE_OP_DONE,
657 mxcmci_finish_data(host, datastat);
659 if (host->req->stop) {
660 if (mxcmci_start_cmd(host, host->req->stop, 0)) {
661 mxcmci_finish_request(host, host->req);
665 mxcmci_finish_request(host, host->req);
669 static void mxcmci_data_done(struct mxcmci_host *host, unsigned int stat)
675 spin_lock_irqsave(&host->lock, flags);
677 if (!host->data) {
678 spin_unlock_irqrestore(&host->lock, flags);
682 if (!host->req) {
683 spin_unlock_irqrestore(&host->lock, flags);
687 req = host->req;
689 host->req = NULL; /* we will handle finish req below */
691 data_error = mxcmci_finish_data(host, stat);
693 spin_unlock_irqrestore(&host->lock, flags);
695 mxcmci_read_response(host, stat);
696 host->cmd = NULL;
699 if (mxcmci_start_cmd(host, req->stop, 0)) {
700 mxcmci_finish_request(host, req);
704 mxcmci_finish_request(host, req);
708 static void mxcmci_cmd_done(struct mxcmci_host *host, unsigned int stat)
710 mxcmci_read_response(host, stat);
711 host->cmd = NULL;
713 if (!host->data && host->req) {
714 mxcmci_finish_request(host, host->req);
722 if (!mxcmci_use_dma(host) && host->data)
723 schedule_work(&host->datawork);
729 struct mxcmci_host *host = devid;
734 stat = mxcmci_readl(host, MMC_REG_STATUS);
735 mxcmci_writel(host,
740 dev_dbg(mmc_dev(host->mmc), "%s: 0x%08x\n", __func__, stat);
742 spin_lock_irqsave(&host->lock, flags);
743 sdio_irq = (stat & STATUS_SDIO_INT_ACTIVE) && host->use_sdio;
744 spin_unlock_irqrestore(&host->lock, flags);
746 if (mxcmci_use_dma(host) &&
748 mxcmci_writel(host, STATUS_READ_OP_DONE | STATUS_WRITE_OP_DONE,
752 mxcmci_writel(host, STATUS_SDIO_INT_ACTIVE, MMC_REG_STATUS);
753 mmc_signal_sdio_irq(host->mmc);
757 mxcmci_cmd_done(host, stat);
759 if (mxcmci_use_dma(host) &&
761 del_timer(&host->watchdog);
762 mxcmci_data_done(host, stat);
765 if (host->default_irq_mask &&
767 mmc_detect_change(host->mmc, msecs_to_jiffies(200));
774 struct mxcmci_host *host = mmc_priv(mmc);
775 unsigned int cmdat = host->cmdat;
778 WARN_ON(host->req != NULL);
780 host->req = req;
781 host->cmdat &= ~CMD_DAT_CONT_INIT;
783 if (host->dma)
784 host->do_dma = 1;
787 error = mxcmci_setup_data(host, req->data);
800 error = mxcmci_start_cmd(host, req->cmd, cmdat);
804 mxcmci_finish_request(host, req);
807 static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios)
811 unsigned int clk_in = clk_get_rate(host->clk_per);
834 mxcmci_writew(host, (prescaler << 4) | divider, MMC_REG_CLK_RATE);
836 dev_dbg(mmc_dev(host->mmc), "scaler: %d divider: %d in: %d out: %d\n",
842 struct mxcmci_host *host = mmc_priv(mmc);
843 struct dma_slave_config *config = &host->dma_slave_config;
845 config->dst_addr = host->phys_base + MMC_REG_BUFFER_ACCESS;
846 config->src_addr = host->phys_base + MMC_REG_BUFFER_ACCESS;
849 config->dst_maxburst = host->burstlen;
850 config->src_maxburst = host->burstlen;
853 return dmaengine_slave_config(host->dma, config);
858 struct mxcmci_host *host = mmc_priv(mmc);
870 if (mxcmci_use_dma(host) && burstlen != host->burstlen) {
871 host->burstlen = burstlen;
874 dev_err(mmc_dev(host->mmc),
876 dma_release_channel(host->dma);
877 host->do_dma = 0;
878 host->dma = NULL;
883 host->cmdat |= CMD_DAT_CONT_BUS_WIDTH_4;
885 host->cmdat &= ~CMD_DAT_CONT_BUS_WIDTH_4;
887 if (host->power_mode != ios->power_mode) {
888 host->power_mode = ios->power_mode;
889 mxcmci_set_power(host, ios->vdd);
892 host->cmdat |= CMD_DAT_CONT_INIT;
896 mxcmci_set_clk_rate(host, ios->clock);
897 mxcmci_writew(host, STR_STP_CLK_START_CLK, MMC_REG_STR_STP_CLK);
899 mxcmci_writew(host, STR_STP_CLK_STOP_CLK, MMC_REG_STR_STP_CLK);
902 host->clock = ios->clock;
917 struct mxcmci_host *host = mmc_priv(mmc);
919 if (host->pdata && host->pdata->get_ro)
920 return !!host->pdata->get_ro(mmc_dev(mmc));
931 struct mxcmci_host *host = mmc_priv(mmc);
935 spin_lock_irqsave(&host->lock, flags);
936 host->use_sdio = enable;
937 int_cntr = mxcmci_readl(host, MMC_REG_INT_CNTR);
944 mxcmci_writel(host, int_cntr, MMC_REG_INT_CNTR);
945 spin_unlock_irqrestore(&host->lock, flags);
948 static void mxcmci_init_card(struct mmc_host *host, struct mmc_card *card)
950 struct mxcmci_host *mxcmci = mmc_priv(host);
960 host->caps &= ~MMC_CAP_4_BIT_DATA;
962 host->caps |= MMC_CAP_4_BIT_DATA;
967 struct mxcmci_host *host = param;
972 chan->private = &host->dma_data;
980 struct mxcmci_host *host = mmc_priv(mmc);
981 struct mmc_request *req = host->req;
982 unsigned int stat = mxcmci_readl(host, MMC_REG_STATUS);
984 if (host->dma_dir == DMA_FROM_DEVICE) {
985 dmaengine_terminate_all(host->dma);
986 dev_err(mmc_dev(host->mmc),
990 dev_err(mmc_dev(host->mmc),
993 mxcmci_softreset(host);
998 if (host->data)
999 host->data->error = -ETIMEDOUT;
1000 host->req = NULL;
1001 host->cmd = NULL;
1002 host->data = NULL;
1003 mmc_request_done(host->mmc, req);
1017 struct mxcmci_host *host;
1034 mmc = mmc_alloc_host(sizeof(*host), &pdev->dev);
1038 host = mmc_priv(mmc);
1040 host->base = devm_ioremap_resource(&pdev->dev, res);
1041 if (IS_ERR(host->base)) {
1042 ret = PTR_ERR(host->base);
1046 host->phys_base = res->start;
1067 host->devtype = id_entry->driver_data;
1069 host->devtype = pdev->id_entry->driver_data;
1073 if (!is_mpc512x_mmc(host))
1076 host->mmc = mmc;
1077 host->pdata = pdata;
1078 spin_lock_init(&host->lock);
1096 host->default_irq_mask =
1099 host->default_irq_mask = 0;
1101 host->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
1102 if (IS_ERR(host->clk_ipg)) {
1103 ret = PTR_ERR(host->clk_ipg);
1107 host->clk_per = devm_clk_get(&pdev->dev, "per");
1108 if (IS_ERR(host->clk_per)) {
1109 ret = PTR_ERR(host->clk_per);
1113 clk_prepare_enable(host->clk_per);
1114 clk_prepare_enable(host->clk_ipg);
1116 mxcmci_softreset(host);
1118 host->rev_no = mxcmci_readw(host, MMC_REG_REV_NO);
1119 if (host->rev_no != 0x400) {
1121 dev_err(mmc_dev(host->mmc), "wrong rev.no. 0x%08x. aborting.\n",
1122 host->rev_no);
1126 mmc->f_min = clk_get_rate(host->clk_per) >> 16;
1127 mmc->f_max = clk_get_rate(host->clk_per) >> 1;
1130 mxcmci_writew(host, 0x2db4, MMC_REG_READ_TO);
1132 mxcmci_writel(host, host->default_irq_mask, MMC_REG_INT_CNTR);
1134 if (!host->pdata) {
1135 host->dma = dma_request_slave_channel(&pdev->dev, "rx-tx");
1139 host->dmareq = res->start;
1140 host->dma_data.peripheral_type = IMX_DMATYPE_SDHC;
1141 host->dma_data.priority = DMA_PRIO_LOW;
1142 host->dma_data.dma_request = host->dmareq;
1145 host->dma = dma_request_channel(mask, filter, host);
1148 if (host->dma)
1150 host->dma->device->dev);
1152 dev_info(mmc_dev(host->mmc), "dma not available. Using PIO\n");
1154 INIT_WORK(&host->datawork, mxcmci_datawork);
1157 dev_name(&pdev->dev), host);
1163 if (host->pdata && host->pdata->init) {
1164 ret = host->pdata->init(&pdev->dev, mxcmci_detect_irq,
1165 host->mmc);
1170 init_timer(&host->watchdog);
1171 host->watchdog.function = &mxcmci_watchdog;
1172 host->watchdog.data = (unsigned long)mmc;
1179 if (host->dma)
1180 dma_release_channel(host->dma);
1183 clk_disable_unprepare(host->clk_per);
1184 clk_disable_unprepare(host->clk_ipg);
1195 struct mxcmci_host *host = mmc_priv(mmc);
1199 if (host->pdata && host->pdata->exit)
1200 host->pdata->exit(&pdev->dev, mmc);
1202 if (host->dma)
1203 dma_release_channel(host->dma);
1205 clk_disable_unprepare(host->clk_per);
1206 clk_disable_unprepare(host->clk_ipg);
1216 struct mxcmci_host *host = mmc_priv(mmc);
1218 clk_disable_unprepare(host->clk_per);
1219 clk_disable_unprepare(host->clk_ipg);
1226 struct mxcmci_host *host = mmc_priv(mmc);
1228 clk_prepare_enable(host->clk_per);
1229 clk_prepare_enable(host->clk_ipg);