Lines Matching +full:mmc +full:- +full:host

1 // SPDX-License-Identifier: GPL-2.0-only
3 * linux/drivers/mmc/host/mxcmmc.c - Freescale i.MX MMCI driver
24 #include <linux/dma-mapping.h>
25 #include <linux/mmc/host.h>
26 #include <linux/mmc/card.h>
35 #include <linux/mmc/slot-gpio.h>
39 #include <linux/platform_data/mmc-mxcmmc.h>
41 #include <linux/dma/imx-dma.h>
43 #define DRIVER_NAME "mxc-mmc"
120 struct mmc_host *mmc; member
161 .compatible = "fsl,imx21-mmc",
164 .compatible = "fsl,imx31-mmc",
167 .compatible = "fsl,mpc5121-sdhc",
175 static inline int is_imx31_mmc(struct mxcmci_host *host) in is_imx31_mmc() argument
177 return host->devtype == IMX31_MMC; in is_imx31_mmc()
180 static inline int is_mpc512x_mmc(struct mxcmci_host *host) in is_mpc512x_mmc() argument
182 return host->devtype == MPC512X_MMC; in is_mpc512x_mmc()
185 static inline u32 mxcmci_readl(struct mxcmci_host *host, int reg) in mxcmci_readl() argument
188 return ioread32be(host->base + reg); in mxcmci_readl()
190 return readl(host->base + reg); in mxcmci_readl()
193 static inline void mxcmci_writel(struct mxcmci_host *host, u32 val, int reg) in mxcmci_writel() argument
196 iowrite32be(val, host->base + reg); in mxcmci_writel()
198 writel(val, host->base + reg); in mxcmci_writel()
201 static inline u16 mxcmci_readw(struct mxcmci_host *host, int reg) in mxcmci_readw() argument
204 return ioread32be(host->base + reg); in mxcmci_readw()
206 return readw(host->base + reg); in mxcmci_readw()
209 static inline void mxcmci_writew(struct mxcmci_host *host, u16 val, int reg) in mxcmci_writew() argument
212 iowrite32be(val, host->base + reg); in mxcmci_writew()
214 writew(val, host->base + reg); in mxcmci_writew()
217 static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios);
219 static void mxcmci_set_power(struct mxcmci_host *host, unsigned int vdd) in mxcmci_set_power() argument
221 if (!IS_ERR(host->mmc->supply.vmmc)) { in mxcmci_set_power()
222 if (host->power_mode == MMC_POWER_UP) in mxcmci_set_power()
223 mmc_regulator_set_ocr(host->mmc, in mxcmci_set_power()
224 host->mmc->supply.vmmc, vdd); in mxcmci_set_power()
225 else if (host->power_mode == MMC_POWER_OFF) in mxcmci_set_power()
226 mmc_regulator_set_ocr(host->mmc, in mxcmci_set_power()
227 host->mmc->supply.vmmc, 0); in mxcmci_set_power()
230 if (host->pdata && host->pdata->setpower) in mxcmci_set_power()
231 host->pdata->setpower(mmc_dev(host->mmc), vdd); in mxcmci_set_power()
234 static inline int mxcmci_use_dma(struct mxcmci_host *host) in mxcmci_use_dma() argument
236 return host->do_dma; in mxcmci_use_dma()
239 static void mxcmci_softreset(struct mxcmci_host *host) in mxcmci_softreset() argument
243 dev_dbg(mmc_dev(host->mmc), "mxcmci_softreset\n"); in mxcmci_softreset()
246 mxcmci_writew(host, STR_STP_CLK_RESET, MMC_REG_STR_STP_CLK); in mxcmci_softreset()
247 mxcmci_writew(host, STR_STP_CLK_RESET | STR_STP_CLK_START_CLK, in mxcmci_softreset()
251 mxcmci_writew(host, STR_STP_CLK_START_CLK, MMC_REG_STR_STP_CLK); in mxcmci_softreset()
253 mxcmci_writew(host, 0xff, MMC_REG_RES_TO); in mxcmci_softreset()
272 sg_miter_start(&sgm, data->sg, data->sg_len, in mxcmci_swap_buffers()
286 static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data) in mxcmci_setup_data() argument
288 unsigned int nob = data->blocks; in mxcmci_setup_data()
289 unsigned int blksz = data->blksz; in mxcmci_setup_data()
295 host->data = data; in mxcmci_setup_data()
296 data->bytes_xfered = 0; in mxcmci_setup_data()
298 mxcmci_writew(host, nob, MMC_REG_NOB); in mxcmci_setup_data()
299 mxcmci_writew(host, blksz, MMC_REG_BLK_LEN); in mxcmci_setup_data()
300 host->datasize = datasize; in mxcmci_setup_data()
302 if (!mxcmci_use_dma(host)) in mxcmci_setup_data()
305 for_each_sg(data->sg, sg, data->sg_len, i) { in mxcmci_setup_data()
306 if (sg->offset & 3 || sg->length & 3 || sg->length < 512) { in mxcmci_setup_data()
307 host->do_dma = 0; in mxcmci_setup_data()
312 if (data->flags & MMC_DATA_READ) { in mxcmci_setup_data()
313 host->dma_dir = DMA_FROM_DEVICE; in mxcmci_setup_data()
316 host->dma_dir = DMA_TO_DEVICE; in mxcmci_setup_data()
322 nents = dma_map_sg(host->dma->device->dev, data->sg, in mxcmci_setup_data()
323 data->sg_len, host->dma_dir); in mxcmci_setup_data()
324 if (nents != data->sg_len) in mxcmci_setup_data()
325 return -EINVAL; in mxcmci_setup_data()
327 host->desc = dmaengine_prep_slave_sg(host->dma, in mxcmci_setup_data()
328 data->sg, data->sg_len, slave_dirn, in mxcmci_setup_data()
331 if (!host->desc) { in mxcmci_setup_data()
332 dma_unmap_sg(host->dma->device->dev, data->sg, data->sg_len, in mxcmci_setup_data()
333 host->dma_dir); in mxcmci_setup_data()
334 host->do_dma = 0; in mxcmci_setup_data()
339 dmaengine_submit(host->desc); in mxcmci_setup_data()
340 dma_async_issue_pending(host->dma); in mxcmci_setup_data()
342 mod_timer(&host->watchdog, jiffies + msecs_to_jiffies(MXCMCI_TIMEOUT_MS)); in mxcmci_setup_data()
347 static void mxcmci_cmd_done(struct mxcmci_host *host, unsigned int stat);
348 static void mxcmci_data_done(struct mxcmci_host *host, unsigned int stat);
352 struct mxcmci_host *host = data; in mxcmci_dma_callback() local
355 del_timer(&host->watchdog); in mxcmci_dma_callback()
357 stat = mxcmci_readl(host, MMC_REG_STATUS); in mxcmci_dma_callback()
359 dev_dbg(mmc_dev(host->mmc), "%s: 0x%08x\n", __func__, stat); in mxcmci_dma_callback()
361 mxcmci_data_done(host, stat); in mxcmci_dma_callback()
364 static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd, in mxcmci_start_cmd() argument
367 u32 int_cntr = host->default_irq_mask; in mxcmci_start_cmd()
370 WARN_ON(host->cmd != NULL); in mxcmci_start_cmd()
371 host->cmd = cmd; in mxcmci_start_cmd()
387 dev_err(mmc_dev(host->mmc), "unhandled response type 0x%x\n", in mxcmci_start_cmd()
389 cmd->error = -EINVAL; in mxcmci_start_cmd()
390 return -EINVAL; in mxcmci_start_cmd()
395 if (mxcmci_use_dma(host)) { in mxcmci_start_cmd()
396 if (host->dma_dir == DMA_FROM_DEVICE) { in mxcmci_start_cmd()
397 host->desc->callback = mxcmci_dma_callback; in mxcmci_start_cmd()
398 host->desc->callback_param = host; in mxcmci_start_cmd()
404 spin_lock_irqsave(&host->lock, flags); in mxcmci_start_cmd()
405 if (host->use_sdio) in mxcmci_start_cmd()
407 mxcmci_writel(host, int_cntr, MMC_REG_INT_CNTR); in mxcmci_start_cmd()
408 spin_unlock_irqrestore(&host->lock, flags); in mxcmci_start_cmd()
410 mxcmci_writew(host, cmd->opcode, MMC_REG_CMD); in mxcmci_start_cmd()
411 mxcmci_writel(host, cmd->arg, MMC_REG_ARG); in mxcmci_start_cmd()
412 mxcmci_writew(host, cmdat, MMC_REG_CMD_DAT_CONT); in mxcmci_start_cmd()
417 static void mxcmci_finish_request(struct mxcmci_host *host, in mxcmci_finish_request() argument
420 u32 int_cntr = host->default_irq_mask; in mxcmci_finish_request()
423 spin_lock_irqsave(&host->lock, flags); in mxcmci_finish_request()
424 if (host->use_sdio) in mxcmci_finish_request()
426 mxcmci_writel(host, int_cntr, MMC_REG_INT_CNTR); in mxcmci_finish_request()
427 spin_unlock_irqrestore(&host->lock, flags); in mxcmci_finish_request()
429 host->req = NULL; in mxcmci_finish_request()
430 host->cmd = NULL; in mxcmci_finish_request()
431 host->data = NULL; in mxcmci_finish_request()
433 mmc_request_done(host->mmc, req); in mxcmci_finish_request()
436 static int mxcmci_finish_data(struct mxcmci_host *host, unsigned int stat) in mxcmci_finish_data() argument
438 struct mmc_data *data = host->data; in mxcmci_finish_data()
441 if (mxcmci_use_dma(host)) { in mxcmci_finish_data()
442 dma_unmap_sg(host->dma->device->dev, data->sg, data->sg_len, in mxcmci_finish_data()
443 host->dma_dir); in mxcmci_finish_data()
448 dev_dbg(mmc_dev(host->mmc), "request failed. status: 0x%08x\n", in mxcmci_finish_data()
451 dev_err(mmc_dev(host->mmc), "%s: -EILSEQ\n", __func__); in mxcmci_finish_data()
452 data->error = -EILSEQ; in mxcmci_finish_data()
456 dev_err(mmc_dev(host->mmc), in mxcmci_finish_data()
457 "%s: No CRC -ETIMEDOUT\n", __func__); in mxcmci_finish_data()
458 data->error = -ETIMEDOUT; in mxcmci_finish_data()
460 dev_err(mmc_dev(host->mmc), in mxcmci_finish_data()
461 "%s: -EILSEQ\n", __func__); in mxcmci_finish_data()
462 data->error = -EILSEQ; in mxcmci_finish_data()
465 dev_err(mmc_dev(host->mmc), in mxcmci_finish_data()
466 "%s: read -ETIMEDOUT\n", __func__); in mxcmci_finish_data()
467 data->error = -ETIMEDOUT; in mxcmci_finish_data()
469 dev_err(mmc_dev(host->mmc), "%s: -EIO\n", __func__); in mxcmci_finish_data()
470 data->error = -EIO; in mxcmci_finish_data()
473 data->bytes_xfered = host->datasize; in mxcmci_finish_data()
476 data_error = data->error; in mxcmci_finish_data()
478 host->data = NULL; in mxcmci_finish_data()
483 static void mxcmci_read_response(struct mxcmci_host *host, unsigned int stat) in mxcmci_read_response() argument
485 struct mmc_command *cmd = host->cmd; in mxcmci_read_response()
493 dev_dbg(mmc_dev(host->mmc), "CMD TIMEOUT\n"); in mxcmci_read_response()
494 cmd->error = -ETIMEDOUT; in mxcmci_read_response()
495 } else if (stat & STATUS_RESP_CRC_ERR && cmd->flags & MMC_RSP_CRC) { in mxcmci_read_response()
496 dev_dbg(mmc_dev(host->mmc), "cmd crc error\n"); in mxcmci_read_response()
497 cmd->error = -EILSEQ; in mxcmci_read_response()
500 if (cmd->flags & MMC_RSP_PRESENT) { in mxcmci_read_response()
501 if (cmd->flags & MMC_RSP_136) { in mxcmci_read_response()
503 a = mxcmci_readw(host, MMC_REG_RES_FIFO); in mxcmci_read_response()
504 b = mxcmci_readw(host, MMC_REG_RES_FIFO); in mxcmci_read_response()
505 cmd->resp[i] = a << 16 | b; in mxcmci_read_response()
508 a = mxcmci_readw(host, MMC_REG_RES_FIFO); in mxcmci_read_response()
509 b = mxcmci_readw(host, MMC_REG_RES_FIFO); in mxcmci_read_response()
510 c = mxcmci_readw(host, MMC_REG_RES_FIFO); in mxcmci_read_response()
511 cmd->resp[0] = a << 24 | b << 8 | c >> 8; in mxcmci_read_response()
516 static int mxcmci_poll_status(struct mxcmci_host *host, u32 mask) in mxcmci_poll_status() argument
522 stat = mxcmci_readl(host, MMC_REG_STATUS); in mxcmci_poll_status()
526 mxcmci_softreset(host); in mxcmci_poll_status()
527 mxcmci_set_clk_rate(host, host->clock); in mxcmci_poll_status()
536 static int mxcmci_pull(struct mxcmci_host *host, u32 *buf, int bytes) in mxcmci_pull() argument
541 stat = mxcmci_poll_status(host, in mxcmci_pull()
545 *buf++ = cpu_to_le32(mxcmci_readl(host, MMC_REG_BUFFER_ACCESS)); in mxcmci_pull()
546 bytes -= 4; in mxcmci_pull()
553 stat = mxcmci_poll_status(host, in mxcmci_pull()
557 tmp = cpu_to_le32(mxcmci_readl(host, MMC_REG_BUFFER_ACCESS)); in mxcmci_pull()
564 static int mxcmci_push(struct mxcmci_host *host, u32 *buf, int bytes) in mxcmci_push() argument
569 stat = mxcmci_poll_status(host, STATUS_BUF_WRITE_RDY); in mxcmci_push()
572 mxcmci_writel(host, cpu_to_le32(*buf++), MMC_REG_BUFFER_ACCESS); in mxcmci_push()
573 bytes -= 4; in mxcmci_push()
580 stat = mxcmci_poll_status(host, STATUS_BUF_WRITE_RDY); in mxcmci_push()
585 mxcmci_writel(host, cpu_to_le32(tmp), MMC_REG_BUFFER_ACCESS); in mxcmci_push()
588 return mxcmci_poll_status(host, STATUS_BUF_WRITE_RDY); in mxcmci_push()
591 static int mxcmci_transfer_data(struct mxcmci_host *host) in mxcmci_transfer_data() argument
593 struct mmc_data *data = host->req->data; in mxcmci_transfer_data()
598 host->data = data; in mxcmci_transfer_data()
599 host->datasize = 0; in mxcmci_transfer_data()
600 sg_miter_start(&sgm, data->sg, data->sg_len, in mxcmci_transfer_data()
601 (data->flags & MMC_DATA_READ) ? SG_MITER_TO_SG : SG_MITER_FROM_SG); in mxcmci_transfer_data()
603 if (data->flags & MMC_DATA_READ) { in mxcmci_transfer_data()
606 stat = mxcmci_pull(host, buf, sgm.length); in mxcmci_transfer_data()
609 host->datasize += sgm.length; in mxcmci_transfer_data()
614 stat = mxcmci_push(host, buf, sgm.length); in mxcmci_transfer_data()
617 host->datasize += sgm.length; in mxcmci_transfer_data()
619 stat = mxcmci_poll_status(host, STATUS_WRITE_OP_DONE); in mxcmci_transfer_data()
631 struct mxcmci_host *host = container_of(work, struct mxcmci_host, in mxcmci_datawork() local
633 int datastat = mxcmci_transfer_data(host); in mxcmci_datawork()
635 mxcmci_writel(host, STATUS_READ_OP_DONE | STATUS_WRITE_OP_DONE, in mxcmci_datawork()
637 mxcmci_finish_data(host, datastat); in mxcmci_datawork()
639 if (host->req->stop) { in mxcmci_datawork()
640 if (mxcmci_start_cmd(host, host->req->stop, 0)) { in mxcmci_datawork()
641 mxcmci_finish_request(host, host->req); in mxcmci_datawork()
645 mxcmci_finish_request(host, host->req); in mxcmci_datawork()
649 static void mxcmci_data_done(struct mxcmci_host *host, unsigned int stat) in mxcmci_data_done() argument
655 spin_lock_irqsave(&host->lock, flags); in mxcmci_data_done()
657 if (!host->data) { in mxcmci_data_done()
658 spin_unlock_irqrestore(&host->lock, flags); in mxcmci_data_done()
662 if (!host->req) { in mxcmci_data_done()
663 spin_unlock_irqrestore(&host->lock, flags); in mxcmci_data_done()
667 req = host->req; in mxcmci_data_done()
668 if (!req->stop) in mxcmci_data_done()
669 host->req = NULL; /* we will handle finish req below */ in mxcmci_data_done()
671 data_error = mxcmci_finish_data(host, stat); in mxcmci_data_done()
673 spin_unlock_irqrestore(&host->lock, flags); in mxcmci_data_done()
678 mxcmci_read_response(host, stat); in mxcmci_data_done()
679 host->cmd = NULL; in mxcmci_data_done()
681 if (req->stop) { in mxcmci_data_done()
682 if (mxcmci_start_cmd(host, req->stop, 0)) { in mxcmci_data_done()
683 mxcmci_finish_request(host, req); in mxcmci_data_done()
687 mxcmci_finish_request(host, req); in mxcmci_data_done()
691 static void mxcmci_cmd_done(struct mxcmci_host *host, unsigned int stat) in mxcmci_cmd_done() argument
693 mxcmci_read_response(host, stat); in mxcmci_cmd_done()
694 host->cmd = NULL; in mxcmci_cmd_done()
696 if (!host->data && host->req) { in mxcmci_cmd_done()
697 mxcmci_finish_request(host, host->req); in mxcmci_cmd_done()
705 if (!mxcmci_use_dma(host) && host->data) in mxcmci_cmd_done()
706 schedule_work(&host->datawork); in mxcmci_cmd_done()
712 struct mxcmci_host *host = devid; in mxcmci_irq() local
716 stat = mxcmci_readl(host, MMC_REG_STATUS); in mxcmci_irq()
717 mxcmci_writel(host, in mxcmci_irq()
722 dev_dbg(mmc_dev(host->mmc), "%s: 0x%08x\n", __func__, stat); in mxcmci_irq()
724 spin_lock(&host->lock); in mxcmci_irq()
725 sdio_irq = (stat & STATUS_SDIO_INT_ACTIVE) && host->use_sdio; in mxcmci_irq()
726 spin_unlock(&host->lock); in mxcmci_irq()
728 if (mxcmci_use_dma(host) && (stat & (STATUS_WRITE_OP_DONE))) in mxcmci_irq()
729 mxcmci_writel(host, STATUS_WRITE_OP_DONE, MMC_REG_STATUS); in mxcmci_irq()
732 mxcmci_writel(host, STATUS_SDIO_INT_ACTIVE, MMC_REG_STATUS); in mxcmci_irq()
733 mmc_signal_sdio_irq(host->mmc); in mxcmci_irq()
737 mxcmci_cmd_done(host, stat); in mxcmci_irq()
739 if (mxcmci_use_dma(host) && (stat & STATUS_WRITE_OP_DONE)) { in mxcmci_irq()
740 del_timer(&host->watchdog); in mxcmci_irq()
741 mxcmci_data_done(host, stat); in mxcmci_irq()
744 if (host->default_irq_mask && in mxcmci_irq()
746 mmc_detect_change(host->mmc, msecs_to_jiffies(200)); in mxcmci_irq()
751 static void mxcmci_request(struct mmc_host *mmc, struct mmc_request *req) in mxcmci_request() argument
753 struct mxcmci_host *host = mmc_priv(mmc); in mxcmci_request() local
754 unsigned int cmdat = host->cmdat; in mxcmci_request()
757 WARN_ON(host->req != NULL); in mxcmci_request()
759 host->req = req; in mxcmci_request()
760 host->cmdat &= ~CMD_DAT_CONT_INIT; in mxcmci_request()
762 if (host->dma) in mxcmci_request()
763 host->do_dma = 1; in mxcmci_request()
765 if (req->data) { in mxcmci_request()
766 error = mxcmci_setup_data(host, req->data); in mxcmci_request()
768 req->cmd->error = error; in mxcmci_request()
775 if (req->data->flags & MMC_DATA_WRITE) in mxcmci_request()
779 error = mxcmci_start_cmd(host, req->cmd, cmdat); in mxcmci_request()
783 mxcmci_finish_request(host, req); in mxcmci_request()
786 static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios) in mxcmci_set_clk_rate() argument
790 unsigned int clk_in = clk_get_rate(host->clk_per); in mxcmci_set_clk_rate()
813 mxcmci_writew(host, (prescaler << 4) | divider, MMC_REG_CLK_RATE); in mxcmci_set_clk_rate()
815 dev_dbg(mmc_dev(host->mmc), "scaler: %d divider: %d in: %d out: %d\n", in mxcmci_set_clk_rate()
819 static int mxcmci_setup_dma(struct mmc_host *mmc) in mxcmci_setup_dma() argument
821 struct mxcmci_host *host = mmc_priv(mmc); in mxcmci_setup_dma() local
822 struct dma_slave_config *config = &host->dma_slave_config; in mxcmci_setup_dma()
824 config->dst_addr = host->phys_base + MMC_REG_BUFFER_ACCESS; in mxcmci_setup_dma()
825 config->src_addr = host->phys_base + MMC_REG_BUFFER_ACCESS; in mxcmci_setup_dma()
826 config->dst_addr_width = 4; in mxcmci_setup_dma()
827 config->src_addr_width = 4; in mxcmci_setup_dma()
828 config->dst_maxburst = host->burstlen; in mxcmci_setup_dma()
829 config->src_maxburst = host->burstlen; in mxcmci_setup_dma()
830 config->device_fc = false; in mxcmci_setup_dma()
832 return dmaengine_slave_config(host->dma, config); in mxcmci_setup_dma()
835 static void mxcmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) in mxcmci_set_ios() argument
837 struct mxcmci_host *host = mmc_priv(mmc); in mxcmci_set_ios() local
841 * use burstlen of 64 (16 words) in 4 bit mode (--> reg value 0) in mxcmci_set_ios()
842 * use burstlen of 16 (4 words) in 1 bit mode (--> reg value 16) in mxcmci_set_ios()
844 if (ios->bus_width == MMC_BUS_WIDTH_4) in mxcmci_set_ios()
849 if (mxcmci_use_dma(host) && burstlen != host->burstlen) { in mxcmci_set_ios()
850 host->burstlen = burstlen; in mxcmci_set_ios()
851 ret = mxcmci_setup_dma(mmc); in mxcmci_set_ios()
853 dev_err(mmc_dev(host->mmc), in mxcmci_set_ios()
855 dma_release_channel(host->dma); in mxcmci_set_ios()
856 host->do_dma = 0; in mxcmci_set_ios()
857 host->dma = NULL; in mxcmci_set_ios()
861 if (ios->bus_width == MMC_BUS_WIDTH_4) in mxcmci_set_ios()
862 host->cmdat |= CMD_DAT_CONT_BUS_WIDTH_4; in mxcmci_set_ios()
864 host->cmdat &= ~CMD_DAT_CONT_BUS_WIDTH_4; in mxcmci_set_ios()
866 if (host->power_mode != ios->power_mode) { in mxcmci_set_ios()
867 host->power_mode = ios->power_mode; in mxcmci_set_ios()
868 mxcmci_set_power(host, ios->vdd); in mxcmci_set_ios()
870 if (ios->power_mode == MMC_POWER_ON) in mxcmci_set_ios()
871 host->cmdat |= CMD_DAT_CONT_INIT; in mxcmci_set_ios()
874 if (ios->clock) { in mxcmci_set_ios()
875 mxcmci_set_clk_rate(host, ios->clock); in mxcmci_set_ios()
876 mxcmci_writew(host, STR_STP_CLK_START_CLK, MMC_REG_STR_STP_CLK); in mxcmci_set_ios()
878 mxcmci_writew(host, STR_STP_CLK_STOP_CLK, MMC_REG_STR_STP_CLK); in mxcmci_set_ios()
881 host->clock = ios->clock; in mxcmci_set_ios()
886 struct mmc_host *mmc = data; in mxcmci_detect_irq() local
888 dev_dbg(mmc_dev(mmc), "%s\n", __func__); in mxcmci_detect_irq()
890 mmc_detect_change(mmc, msecs_to_jiffies(250)); in mxcmci_detect_irq()
894 static int mxcmci_get_ro(struct mmc_host *mmc) in mxcmci_get_ro() argument
896 struct mxcmci_host *host = mmc_priv(mmc); in mxcmci_get_ro() local
898 if (host->pdata && host->pdata->get_ro) in mxcmci_get_ro()
899 return !!host->pdata->get_ro(mmc_dev(mmc)); in mxcmci_get_ro()
902 * context or gpio is invalid), then let the mmc core decide in mxcmci_get_ro()
905 return mmc_gpio_get_ro(mmc); in mxcmci_get_ro()
908 static void mxcmci_enable_sdio_irq(struct mmc_host *mmc, int enable) in mxcmci_enable_sdio_irq() argument
910 struct mxcmci_host *host = mmc_priv(mmc); in mxcmci_enable_sdio_irq() local
914 spin_lock_irqsave(&host->lock, flags); in mxcmci_enable_sdio_irq()
915 host->use_sdio = enable; in mxcmci_enable_sdio_irq()
916 int_cntr = mxcmci_readl(host, MMC_REG_INT_CNTR); in mxcmci_enable_sdio_irq()
923 mxcmci_writel(host, int_cntr, MMC_REG_INT_CNTR); in mxcmci_enable_sdio_irq()
924 spin_unlock_irqrestore(&host->lock, flags); in mxcmci_enable_sdio_irq()
927 static void mxcmci_init_card(struct mmc_host *host, struct mmc_card *card) in mxcmci_init_card() argument
929 struct mxcmci_host *mxcmci = mmc_priv(host); in mxcmci_init_card()
933 * multi-block transfers when connected SDIO peripheral doesn't in mxcmci_init_card()
935 * One way to prevent this is to only allow 1-bit transfers. in mxcmci_init_card()
939 host->caps &= ~MMC_CAP_4_BIT_DATA; in mxcmci_init_card()
941 host->caps |= MMC_CAP_4_BIT_DATA; in mxcmci_init_card()
946 struct mxcmci_host *host = param; in filter() local
951 chan->private = &host->dma_data; in filter()
958 struct mxcmci_host *host = from_timer(host, t, watchdog); in mxcmci_watchdog() local
959 struct mmc_request *req = host->req; in mxcmci_watchdog()
960 unsigned int stat = mxcmci_readl(host, MMC_REG_STATUS); in mxcmci_watchdog()
962 if (host->dma_dir == DMA_FROM_DEVICE) { in mxcmci_watchdog()
963 dmaengine_terminate_all(host->dma); in mxcmci_watchdog()
964 dev_err(mmc_dev(host->mmc), in mxcmci_watchdog()
968 dev_err(mmc_dev(host->mmc), in mxcmci_watchdog()
971 mxcmci_softreset(host); in mxcmci_watchdog()
976 if (host->data) in mxcmci_watchdog()
977 host->data->error = -ETIMEDOUT; in mxcmci_watchdog()
978 host->req = NULL; in mxcmci_watchdog()
979 host->cmd = NULL; in mxcmci_watchdog()
980 host->data = NULL; in mxcmci_watchdog()
981 mmc_request_done(host->mmc, req); in mxcmci_watchdog()
994 struct mmc_host *mmc; in mxcmci_probe() local
995 struct mxcmci_host *host; in mxcmci_probe() local
1000 struct imxmmc_platform_data *pdata = pdev->dev.platform_data; in mxcmci_probe()
1008 mmc = mmc_alloc_host(sizeof(*host), &pdev->dev); in mxcmci_probe()
1009 if (!mmc) in mxcmci_probe()
1010 return -ENOMEM; in mxcmci_probe()
1012 host = mmc_priv(mmc); in mxcmci_probe()
1014 host->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); in mxcmci_probe()
1015 if (IS_ERR(host->base)) { in mxcmci_probe()
1016 ret = PTR_ERR(host->base); in mxcmci_probe()
1020 host->phys_base = res->start; in mxcmci_probe()
1022 ret = mmc_of_parse(mmc); in mxcmci_probe()
1025 mmc->ops = &mxcmci_ops; in mxcmci_probe()
1029 mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ; in mxcmci_probe()
1031 mmc->caps |= MMC_CAP_SDIO_IRQ; in mxcmci_probe()
1033 /* MMC core transfer sizes tunable parameters */ in mxcmci_probe()
1034 mmc->max_blk_size = 2048; in mxcmci_probe()
1035 mmc->max_blk_count = 65535; in mxcmci_probe()
1036 mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; in mxcmci_probe()
1037 mmc->max_seg_size = mmc->max_req_size; in mxcmci_probe()
1039 host->devtype = (uintptr_t)of_device_get_match_data(&pdev->dev); in mxcmci_probe()
1042 if (!is_mpc512x_mmc(host)) in mxcmci_probe()
1043 mmc->max_segs = 64; in mxcmci_probe()
1045 host->mmc = mmc; in mxcmci_probe()
1046 host->pdata = pdata; in mxcmci_probe()
1047 spin_lock_init(&host->lock); in mxcmci_probe()
1050 dat3_card_detect = pdata->dat3_card_detect; in mxcmci_probe()
1051 else if (mmc_card_is_removable(mmc) in mxcmci_probe()
1052 && !of_property_read_bool(pdev->dev.of_node, "cd-gpios")) in mxcmci_probe()
1055 ret = mmc_regulator_get_supply(mmc); in mxcmci_probe()
1059 if (!mmc->ocr_avail) { in mxcmci_probe()
1060 if (pdata && pdata->ocr_avail) in mxcmci_probe()
1061 mmc->ocr_avail = pdata->ocr_avail; in mxcmci_probe()
1063 mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; in mxcmci_probe()
1067 host->default_irq_mask = in mxcmci_probe()
1070 host->default_irq_mask = 0; in mxcmci_probe()
1072 host->clk_ipg = devm_clk_get(&pdev->dev, "ipg"); in mxcmci_probe()
1073 if (IS_ERR(host->clk_ipg)) { in mxcmci_probe()
1074 ret = PTR_ERR(host->clk_ipg); in mxcmci_probe()
1078 host->clk_per = devm_clk_get(&pdev->dev, "per"); in mxcmci_probe()
1079 if (IS_ERR(host->clk_per)) { in mxcmci_probe()
1080 ret = PTR_ERR(host->clk_per); in mxcmci_probe()
1084 ret = clk_prepare_enable(host->clk_per); in mxcmci_probe()
1088 ret = clk_prepare_enable(host->clk_ipg); in mxcmci_probe()
1092 mxcmci_softreset(host); in mxcmci_probe()
1094 host->rev_no = mxcmci_readw(host, MMC_REG_REV_NO); in mxcmci_probe()
1095 if (host->rev_no != 0x400) { in mxcmci_probe()
1096 ret = -ENODEV; in mxcmci_probe()
1097 dev_err(mmc_dev(host->mmc), "wrong rev.no. 0x%08x. aborting.\n", in mxcmci_probe()
1098 host->rev_no); in mxcmci_probe()
1102 mmc->f_min = clk_get_rate(host->clk_per) >> 16; in mxcmci_probe()
1103 mmc->f_max = clk_get_rate(host->clk_per) >> 1; in mxcmci_probe()
1106 mxcmci_writew(host, 0x2db4, MMC_REG_READ_TO); in mxcmci_probe()
1108 mxcmci_writel(host, host->default_irq_mask, MMC_REG_INT_CNTR); in mxcmci_probe()
1110 if (!host->pdata) { in mxcmci_probe()
1111 host->dma = dma_request_chan(&pdev->dev, "rx-tx"); in mxcmci_probe()
1112 if (IS_ERR(host->dma)) { in mxcmci_probe()
1113 if (PTR_ERR(host->dma) == -EPROBE_DEFER) { in mxcmci_probe()
1114 ret = -EPROBE_DEFER; in mxcmci_probe()
1119 host->dma = NULL; in mxcmci_probe()
1124 host->dmareq = res->start; in mxcmci_probe()
1125 host->dma_data.peripheral_type = IMX_DMATYPE_SDHC; in mxcmci_probe()
1126 host->dma_data.priority = DMA_PRIO_LOW; in mxcmci_probe()
1127 host->dma_data.dma_request = host->dmareq; in mxcmci_probe()
1130 host->dma = dma_request_channel(mask, filter, host); in mxcmci_probe()
1133 if (host->dma) in mxcmci_probe()
1134 mmc->max_seg_size = dma_get_max_seg_size( in mxcmci_probe()
1135 host->dma->device->dev); in mxcmci_probe()
1137 dev_info(mmc_dev(host->mmc), "dma not available. Using PIO\n"); in mxcmci_probe()
1139 INIT_WORK(&host->datawork, mxcmci_datawork); in mxcmci_probe()
1141 ret = devm_request_irq(&pdev->dev, irq, mxcmci_irq, 0, in mxcmci_probe()
1142 dev_name(&pdev->dev), host); in mxcmci_probe()
1146 platform_set_drvdata(pdev, mmc); in mxcmci_probe()
1148 if (host->pdata && host->pdata->init) { in mxcmci_probe()
1149 ret = host->pdata->init(&pdev->dev, mxcmci_detect_irq, in mxcmci_probe()
1150 host->mmc); in mxcmci_probe()
1155 timer_setup(&host->watchdog, mxcmci_watchdog, 0); in mxcmci_probe()
1157 ret = mmc_add_host(mmc); in mxcmci_probe()
1164 if (host->dma) in mxcmci_probe()
1165 dma_release_channel(host->dma); in mxcmci_probe()
1168 clk_disable_unprepare(host->clk_ipg); in mxcmci_probe()
1170 clk_disable_unprepare(host->clk_per); in mxcmci_probe()
1173 mmc_free_host(mmc); in mxcmci_probe()
1180 struct mmc_host *mmc = platform_get_drvdata(pdev); in mxcmci_remove() local
1181 struct mxcmci_host *host = mmc_priv(mmc); in mxcmci_remove() local
1183 mmc_remove_host(mmc); in mxcmci_remove()
1185 if (host->pdata && host->pdata->exit) in mxcmci_remove()
1186 host->pdata->exit(&pdev->dev, mmc); in mxcmci_remove()
1188 if (host->dma) in mxcmci_remove()
1189 dma_release_channel(host->dma); in mxcmci_remove()
1191 clk_disable_unprepare(host->clk_per); in mxcmci_remove()
1192 clk_disable_unprepare(host->clk_ipg); in mxcmci_remove()
1194 mmc_free_host(mmc); in mxcmci_remove()
1199 struct mmc_host *mmc = dev_get_drvdata(dev); in mxcmci_suspend() local
1200 struct mxcmci_host *host = mmc_priv(mmc); in mxcmci_suspend() local
1202 clk_disable_unprepare(host->clk_per); in mxcmci_suspend()
1203 clk_disable_unprepare(host->clk_ipg); in mxcmci_suspend()
1209 struct mmc_host *mmc = dev_get_drvdata(dev); in mxcmci_resume() local
1210 struct mxcmci_host *host = mmc_priv(mmc); in mxcmci_resume() local
1213 ret = clk_prepare_enable(host->clk_per); in mxcmci_resume()
1217 ret = clk_prepare_enable(host->clk_ipg); in mxcmci_resume()
1219 clk_disable_unprepare(host->clk_per); in mxcmci_resume()
1242 MODULE_ALIAS("platform:mxc-mmc");