Lines Matching +full:mmci +full:- +full:gpio +full:- +full:supply
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>
36 #include <linux/mmc/slot-gpio.h>
40 #include <linux/platform_data/mmc-mxcmmc.h>
42 #include <linux/platform_data/dma-imx.h>
44 #define DRIVER_NAME "mxc-mmc"
162 .name = "imx21-mmc",
165 .name = "imx31-mmc",
168 .name = "mpc512x-sdhc",
178 .compatible = "fsl,imx21-mmc",
181 .compatible = "fsl,imx31-mmc",
184 .compatible = "fsl,mpc5121-sdhc",
194 return host->devtype == IMX31_MMC; in is_imx31_mmc()
199 return host->devtype == MPC512X_MMC; in is_mpc512x_mmc()
205 return ioread32be(host->base + reg); in mxcmci_readl()
207 return readl(host->base + reg); in mxcmci_readl()
213 iowrite32be(val, host->base + reg); in mxcmci_writel()
215 writel(val, host->base + reg); in mxcmci_writel()
221 return ioread32be(host->base + reg); in mxcmci_readw()
223 return readw(host->base + reg); in mxcmci_readw()
229 iowrite32be(val, host->base + reg); in mxcmci_writew()
231 writew(val, host->base + reg); in mxcmci_writew()
238 if (!IS_ERR(host->mmc->supply.vmmc)) { in mxcmci_set_power()
239 if (host->power_mode == MMC_POWER_UP) in mxcmci_set_power()
240 mmc_regulator_set_ocr(host->mmc, in mxcmci_set_power()
241 host->mmc->supply.vmmc, vdd); in mxcmci_set_power()
242 else if (host->power_mode == MMC_POWER_OFF) in mxcmci_set_power()
243 mmc_regulator_set_ocr(host->mmc, in mxcmci_set_power()
244 host->mmc->supply.vmmc, 0); in mxcmci_set_power()
247 if (host->pdata && host->pdata->setpower) in mxcmci_set_power()
248 host->pdata->setpower(mmc_dev(host->mmc), vdd); in mxcmci_set_power()
253 return host->do_dma; in mxcmci_use_dma()
260 dev_dbg(mmc_dev(host->mmc), "mxcmci_softreset\n"); in mxcmci_softreset()
289 for_each_sg(data->sg, sg, data->sg_len, i) in mxcmci_swap_buffers()
290 buffer_swap32(sg_virt(sg), sg->length); in mxcmci_swap_buffers()
298 unsigned int nob = data->blocks; in mxcmci_setup_data()
299 unsigned int blksz = data->blksz; in mxcmci_setup_data()
305 host->data = data; in mxcmci_setup_data()
306 data->bytes_xfered = 0; in mxcmci_setup_data()
310 host->datasize = datasize; in mxcmci_setup_data()
315 for_each_sg(data->sg, sg, data->sg_len, i) { in mxcmci_setup_data()
316 if (sg->offset & 3 || sg->length & 3 || sg->length < 512) { in mxcmci_setup_data()
317 host->do_dma = 0; in mxcmci_setup_data()
322 if (data->flags & MMC_DATA_READ) { in mxcmci_setup_data()
323 host->dma_dir = DMA_FROM_DEVICE; in mxcmci_setup_data()
326 host->dma_dir = DMA_TO_DEVICE; in mxcmci_setup_data()
332 nents = dma_map_sg(host->dma->device->dev, data->sg, in mxcmci_setup_data()
333 data->sg_len, host->dma_dir); in mxcmci_setup_data()
334 if (nents != data->sg_len) in mxcmci_setup_data()
335 return -EINVAL; in mxcmci_setup_data()
337 host->desc = dmaengine_prep_slave_sg(host->dma, in mxcmci_setup_data()
338 data->sg, data->sg_len, slave_dirn, in mxcmci_setup_data()
341 if (!host->desc) { in mxcmci_setup_data()
342 dma_unmap_sg(host->dma->device->dev, data->sg, data->sg_len, in mxcmci_setup_data()
343 host->dma_dir); in mxcmci_setup_data()
344 host->do_dma = 0; in mxcmci_setup_data()
349 dmaengine_submit(host->desc); in mxcmci_setup_data()
350 dma_async_issue_pending(host->dma); in mxcmci_setup_data()
352 mod_timer(&host->watchdog, jiffies + msecs_to_jiffies(MXCMCI_TIMEOUT_MS)); in mxcmci_setup_data()
365 del_timer(&host->watchdog); in mxcmci_dma_callback()
369 dev_dbg(mmc_dev(host->mmc), "%s: 0x%08x\n", __func__, stat); in mxcmci_dma_callback()
377 u32 int_cntr = host->default_irq_mask; in mxcmci_start_cmd()
380 WARN_ON(host->cmd != NULL); in mxcmci_start_cmd()
381 host->cmd = cmd; in mxcmci_start_cmd()
397 dev_err(mmc_dev(host->mmc), "unhandled response type 0x%x\n", in mxcmci_start_cmd()
399 cmd->error = -EINVAL; in mxcmci_start_cmd()
400 return -EINVAL; in mxcmci_start_cmd()
406 if (host->dma_dir == DMA_FROM_DEVICE) { in mxcmci_start_cmd()
407 host->desc->callback = mxcmci_dma_callback; in mxcmci_start_cmd()
408 host->desc->callback_param = host; in mxcmci_start_cmd()
414 spin_lock_irqsave(&host->lock, flags); in mxcmci_start_cmd()
415 if (host->use_sdio) in mxcmci_start_cmd()
418 spin_unlock_irqrestore(&host->lock, flags); in mxcmci_start_cmd()
420 mxcmci_writew(host, cmd->opcode, MMC_REG_CMD); in mxcmci_start_cmd()
421 mxcmci_writel(host, cmd->arg, MMC_REG_ARG); in mxcmci_start_cmd()
430 u32 int_cntr = host->default_irq_mask; in mxcmci_finish_request()
433 spin_lock_irqsave(&host->lock, flags); in mxcmci_finish_request()
434 if (host->use_sdio) in mxcmci_finish_request()
437 spin_unlock_irqrestore(&host->lock, flags); in mxcmci_finish_request()
439 host->req = NULL; in mxcmci_finish_request()
440 host->cmd = NULL; in mxcmci_finish_request()
441 host->data = NULL; in mxcmci_finish_request()
443 mmc_request_done(host->mmc, req); in mxcmci_finish_request()
448 struct mmc_data *data = host->data; in mxcmci_finish_data()
452 dma_unmap_sg(host->dma->device->dev, data->sg, data->sg_len, in mxcmci_finish_data()
453 host->dma_dir); in mxcmci_finish_data()
458 dev_dbg(mmc_dev(host->mmc), "request failed. status: 0x%08x\n", in mxcmci_finish_data()
461 dev_err(mmc_dev(host->mmc), "%s: -EILSEQ\n", __func__); in mxcmci_finish_data()
462 data->error = -EILSEQ; in mxcmci_finish_data()
466 dev_err(mmc_dev(host->mmc), in mxcmci_finish_data()
467 "%s: No CRC -ETIMEDOUT\n", __func__); in mxcmci_finish_data()
468 data->error = -ETIMEDOUT; in mxcmci_finish_data()
470 dev_err(mmc_dev(host->mmc), in mxcmci_finish_data()
471 "%s: -EILSEQ\n", __func__); in mxcmci_finish_data()
472 data->error = -EILSEQ; in mxcmci_finish_data()
475 dev_err(mmc_dev(host->mmc), in mxcmci_finish_data()
476 "%s: read -ETIMEDOUT\n", __func__); in mxcmci_finish_data()
477 data->error = -ETIMEDOUT; in mxcmci_finish_data()
479 dev_err(mmc_dev(host->mmc), "%s: -EIO\n", __func__); in mxcmci_finish_data()
480 data->error = -EIO; in mxcmci_finish_data()
483 data->bytes_xfered = host->datasize; in mxcmci_finish_data()
486 data_error = data->error; in mxcmci_finish_data()
488 host->data = NULL; in mxcmci_finish_data()
495 struct mmc_command *cmd = host->cmd; in mxcmci_read_response()
503 dev_dbg(mmc_dev(host->mmc), "CMD TIMEOUT\n"); in mxcmci_read_response()
504 cmd->error = -ETIMEDOUT; in mxcmci_read_response()
505 } else if (stat & STATUS_RESP_CRC_ERR && cmd->flags & MMC_RSP_CRC) { in mxcmci_read_response()
506 dev_dbg(mmc_dev(host->mmc), "cmd crc error\n"); in mxcmci_read_response()
507 cmd->error = -EILSEQ; in mxcmci_read_response()
510 if (cmd->flags & MMC_RSP_PRESENT) { in mxcmci_read_response()
511 if (cmd->flags & MMC_RSP_136) { in mxcmci_read_response()
515 cmd->resp[i] = a << 16 | b; in mxcmci_read_response()
521 cmd->resp[0] = a << 24 | b << 8 | c >> 8; in mxcmci_read_response()
537 mxcmci_set_clk_rate(host, host->clock); in mxcmci_poll_status()
557 bytes -= 4; in mxcmci_pull()
585 bytes -= 4; in mxcmci_push()
605 struct mmc_data *data = host->req->data; in mxcmci_transfer_data()
609 host->data = data; in mxcmci_transfer_data()
610 host->datasize = 0; in mxcmci_transfer_data()
612 if (data->flags & MMC_DATA_READ) { in mxcmci_transfer_data()
613 for_each_sg(data->sg, sg, data->sg_len, i) { in mxcmci_transfer_data()
614 stat = mxcmci_pull(host, sg_virt(sg), sg->length); in mxcmci_transfer_data()
617 host->datasize += sg->length; in mxcmci_transfer_data()
620 for_each_sg(data->sg, sg, data->sg_len, i) { in mxcmci_transfer_data()
621 stat = mxcmci_push(host, sg_virt(sg), sg->length); in mxcmci_transfer_data()
624 host->datasize += sg->length; in mxcmci_transfer_data()
643 if (host->req->stop) { in mxcmci_datawork()
644 if (mxcmci_start_cmd(host, host->req->stop, 0)) { in mxcmci_datawork()
645 mxcmci_finish_request(host, host->req); in mxcmci_datawork()
649 mxcmci_finish_request(host, host->req); in mxcmci_datawork()
659 spin_lock_irqsave(&host->lock, flags); in mxcmci_data_done()
661 if (!host->data) { in mxcmci_data_done()
662 spin_unlock_irqrestore(&host->lock, flags); in mxcmci_data_done()
666 if (!host->req) { in mxcmci_data_done()
667 spin_unlock_irqrestore(&host->lock, flags); in mxcmci_data_done()
671 req = host->req; in mxcmci_data_done()
672 if (!req->stop) in mxcmci_data_done()
673 host->req = NULL; /* we will handle finish req below */ in mxcmci_data_done()
677 spin_unlock_irqrestore(&host->lock, flags); in mxcmci_data_done()
683 host->cmd = NULL; in mxcmci_data_done()
685 if (req->stop) { in mxcmci_data_done()
686 if (mxcmci_start_cmd(host, req->stop, 0)) { in mxcmci_data_done()
698 host->cmd = NULL; in mxcmci_cmd_done()
700 if (!host->data && host->req) { in mxcmci_cmd_done()
701 mxcmci_finish_request(host, host->req); in mxcmci_cmd_done()
709 if (!mxcmci_use_dma(host) && host->data) in mxcmci_cmd_done()
710 schedule_work(&host->datawork); in mxcmci_cmd_done()
726 dev_dbg(mmc_dev(host->mmc), "%s: 0x%08x\n", __func__, stat); in mxcmci_irq()
728 spin_lock(&host->lock); in mxcmci_irq()
729 sdio_irq = (stat & STATUS_SDIO_INT_ACTIVE) && host->use_sdio; in mxcmci_irq()
730 spin_unlock(&host->lock); in mxcmci_irq()
737 mmc_signal_sdio_irq(host->mmc); in mxcmci_irq()
744 del_timer(&host->watchdog); in mxcmci_irq()
748 if (host->default_irq_mask && in mxcmci_irq()
750 mmc_detect_change(host->mmc, msecs_to_jiffies(200)); in mxcmci_irq()
758 unsigned int cmdat = host->cmdat; in mxcmci_request()
761 WARN_ON(host->req != NULL); in mxcmci_request()
763 host->req = req; in mxcmci_request()
764 host->cmdat &= ~CMD_DAT_CONT_INIT; in mxcmci_request()
766 if (host->dma) in mxcmci_request()
767 host->do_dma = 1; in mxcmci_request()
769 if (req->data) { in mxcmci_request()
770 error = mxcmci_setup_data(host, req->data); in mxcmci_request()
772 req->cmd->error = error; in mxcmci_request()
779 if (req->data->flags & MMC_DATA_WRITE) in mxcmci_request()
783 error = mxcmci_start_cmd(host, req->cmd, cmdat); in mxcmci_request()
794 unsigned int clk_in = clk_get_rate(host->clk_per); in mxcmci_set_clk_rate()
819 dev_dbg(mmc_dev(host->mmc), "scaler: %d divider: %d in: %d out: %d\n", in mxcmci_set_clk_rate()
826 struct dma_slave_config *config = &host->dma_slave_config; in mxcmci_setup_dma()
828 config->dst_addr = host->phys_base + MMC_REG_BUFFER_ACCESS; in mxcmci_setup_dma()
829 config->src_addr = host->phys_base + MMC_REG_BUFFER_ACCESS; in mxcmci_setup_dma()
830 config->dst_addr_width = 4; in mxcmci_setup_dma()
831 config->src_addr_width = 4; in mxcmci_setup_dma()
832 config->dst_maxburst = host->burstlen; in mxcmci_setup_dma()
833 config->src_maxburst = host->burstlen; in mxcmci_setup_dma()
834 config->device_fc = false; in mxcmci_setup_dma()
836 return dmaengine_slave_config(host->dma, config); in mxcmci_setup_dma()
845 * use burstlen of 64 (16 words) in 4 bit mode (--> reg value 0) in mxcmci_set_ios()
846 * use burstlen of 16 (4 words) in 1 bit mode (--> reg value 16) in mxcmci_set_ios()
848 if (ios->bus_width == MMC_BUS_WIDTH_4) in mxcmci_set_ios()
853 if (mxcmci_use_dma(host) && burstlen != host->burstlen) { in mxcmci_set_ios()
854 host->burstlen = burstlen; in mxcmci_set_ios()
857 dev_err(mmc_dev(host->mmc), in mxcmci_set_ios()
859 dma_release_channel(host->dma); in mxcmci_set_ios()
860 host->do_dma = 0; in mxcmci_set_ios()
861 host->dma = NULL; in mxcmci_set_ios()
865 if (ios->bus_width == MMC_BUS_WIDTH_4) in mxcmci_set_ios()
866 host->cmdat |= CMD_DAT_CONT_BUS_WIDTH_4; in mxcmci_set_ios()
868 host->cmdat &= ~CMD_DAT_CONT_BUS_WIDTH_4; in mxcmci_set_ios()
870 if (host->power_mode != ios->power_mode) { in mxcmci_set_ios()
871 host->power_mode = ios->power_mode; in mxcmci_set_ios()
872 mxcmci_set_power(host, ios->vdd); in mxcmci_set_ios()
874 if (ios->power_mode == MMC_POWER_ON) in mxcmci_set_ios()
875 host->cmdat |= CMD_DAT_CONT_INIT; in mxcmci_set_ios()
878 if (ios->clock) { in mxcmci_set_ios()
879 mxcmci_set_clk_rate(host, ios->clock); in mxcmci_set_ios()
885 host->clock = ios->clock; in mxcmci_set_ios()
902 if (host->pdata && host->pdata->get_ro) in mxcmci_get_ro()
903 return !!host->pdata->get_ro(mmc_dev(mmc)); in mxcmci_get_ro()
906 * context or gpio is invalid), then let the mmc core decide in mxcmci_get_ro()
918 spin_lock_irqsave(&host->lock, flags); in mxcmci_enable_sdio_irq()
919 host->use_sdio = enable; in mxcmci_enable_sdio_irq()
928 spin_unlock_irqrestore(&host->lock, flags); in mxcmci_enable_sdio_irq()
937 * multi-block transfers when connected SDIO peripheral doesn't in mxcmci_init_card()
939 * One way to prevent this is to only allow 1-bit transfers. in mxcmci_init_card()
942 if (is_imx31_mmc(mxcmci) && card->type == MMC_TYPE_SDIO) in mxcmci_init_card()
943 host->caps &= ~MMC_CAP_4_BIT_DATA; in mxcmci_init_card()
945 host->caps |= MMC_CAP_4_BIT_DATA; in mxcmci_init_card()
955 chan->private = &host->dma_data; in filter()
963 struct mmc_request *req = host->req; in mxcmci_watchdog()
966 if (host->dma_dir == DMA_FROM_DEVICE) { in mxcmci_watchdog()
967 dmaengine_terminate_all(host->dma); in mxcmci_watchdog()
968 dev_err(mmc_dev(host->mmc), in mxcmci_watchdog()
972 dev_err(mmc_dev(host->mmc), in mxcmci_watchdog()
980 if (host->data) in mxcmci_watchdog()
981 host->data->error = -ETIMEDOUT; in mxcmci_watchdog()
982 host->req = NULL; in mxcmci_watchdog()
983 host->cmd = NULL; in mxcmci_watchdog()
984 host->data = NULL; in mxcmci_watchdog()
985 mmc_request_done(host->mmc, req); in mxcmci_watchdog()
1005 struct imxmmc_platform_data *pdata = pdev->dev.platform_data; in mxcmci_probe()
1009 of_id = of_match_device(mxcmci_of_match, &pdev->dev); in mxcmci_probe()
1016 mmc = mmc_alloc_host(sizeof(*host), &pdev->dev); in mxcmci_probe()
1018 return -ENOMEM; in mxcmci_probe()
1022 host->base = devm_ioremap_resource(&pdev->dev, res); in mxcmci_probe()
1023 if (IS_ERR(host->base)) { in mxcmci_probe()
1024 ret = PTR_ERR(host->base); in mxcmci_probe()
1028 host->phys_base = res->start; in mxcmci_probe()
1033 mmc->ops = &mxcmci_ops; in mxcmci_probe()
1037 mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ; in mxcmci_probe()
1039 mmc->caps |= MMC_CAP_SDIO_IRQ; in mxcmci_probe()
1042 mmc->max_blk_size = 2048; in mxcmci_probe()
1043 mmc->max_blk_count = 65535; in mxcmci_probe()
1044 mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; in mxcmci_probe()
1045 mmc->max_seg_size = mmc->max_req_size; in mxcmci_probe()
1048 const struct platform_device_id *id_entry = of_id->data; in mxcmci_probe()
1049 host->devtype = id_entry->driver_data; in mxcmci_probe()
1051 host->devtype = pdev->id_entry->driver_data; in mxcmci_probe()
1056 mmc->max_segs = 64; in mxcmci_probe()
1058 host->mmc = mmc; in mxcmci_probe()
1059 host->pdata = pdata; in mxcmci_probe()
1060 spin_lock_init(&host->lock); in mxcmci_probe()
1063 dat3_card_detect = pdata->dat3_card_detect; in mxcmci_probe()
1065 && !of_property_read_bool(pdev->dev.of_node, "cd-gpios")) in mxcmci_probe()
1072 if (!mmc->ocr_avail) { in mxcmci_probe()
1073 if (pdata && pdata->ocr_avail) in mxcmci_probe()
1074 mmc->ocr_avail = pdata->ocr_avail; in mxcmci_probe()
1076 mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; in mxcmci_probe()
1080 host->default_irq_mask = in mxcmci_probe()
1083 host->default_irq_mask = 0; in mxcmci_probe()
1085 host->clk_ipg = devm_clk_get(&pdev->dev, "ipg"); in mxcmci_probe()
1086 if (IS_ERR(host->clk_ipg)) { in mxcmci_probe()
1087 ret = PTR_ERR(host->clk_ipg); in mxcmci_probe()
1091 host->clk_per = devm_clk_get(&pdev->dev, "per"); in mxcmci_probe()
1092 if (IS_ERR(host->clk_per)) { in mxcmci_probe()
1093 ret = PTR_ERR(host->clk_per); in mxcmci_probe()
1097 ret = clk_prepare_enable(host->clk_per); in mxcmci_probe()
1101 ret = clk_prepare_enable(host->clk_ipg); in mxcmci_probe()
1107 host->rev_no = mxcmci_readw(host, MMC_REG_REV_NO); in mxcmci_probe()
1108 if (host->rev_no != 0x400) { in mxcmci_probe()
1109 ret = -ENODEV; in mxcmci_probe()
1110 dev_err(mmc_dev(host->mmc), "wrong rev.no. 0x%08x. aborting.\n", in mxcmci_probe()
1111 host->rev_no); in mxcmci_probe()
1115 mmc->f_min = clk_get_rate(host->clk_per) >> 16; in mxcmci_probe()
1116 mmc->f_max = clk_get_rate(host->clk_per) >> 1; in mxcmci_probe()
1121 mxcmci_writel(host, host->default_irq_mask, MMC_REG_INT_CNTR); in mxcmci_probe()
1123 if (!host->pdata) { in mxcmci_probe()
1124 host->dma = dma_request_chan(&pdev->dev, "rx-tx"); in mxcmci_probe()
1125 if (IS_ERR(host->dma)) { in mxcmci_probe()
1126 if (PTR_ERR(host->dma) == -EPROBE_DEFER) { in mxcmci_probe()
1127 ret = -EPROBE_DEFER; in mxcmci_probe()
1132 host->dma = NULL; in mxcmci_probe()
1137 host->dmareq = res->start; in mxcmci_probe()
1138 host->dma_data.peripheral_type = IMX_DMATYPE_SDHC; in mxcmci_probe()
1139 host->dma_data.priority = DMA_PRIO_LOW; in mxcmci_probe()
1140 host->dma_data.dma_request = host->dmareq; in mxcmci_probe()
1143 host->dma = dma_request_channel(mask, filter, host); in mxcmci_probe()
1146 if (host->dma) in mxcmci_probe()
1147 mmc->max_seg_size = dma_get_max_seg_size( in mxcmci_probe()
1148 host->dma->device->dev); in mxcmci_probe()
1150 dev_info(mmc_dev(host->mmc), "dma not available. Using PIO\n"); in mxcmci_probe()
1152 INIT_WORK(&host->datawork, mxcmci_datawork); in mxcmci_probe()
1154 ret = devm_request_irq(&pdev->dev, irq, mxcmci_irq, 0, in mxcmci_probe()
1155 dev_name(&pdev->dev), host); in mxcmci_probe()
1161 if (host->pdata && host->pdata->init) { in mxcmci_probe()
1162 ret = host->pdata->init(&pdev->dev, mxcmci_detect_irq, in mxcmci_probe()
1163 host->mmc); in mxcmci_probe()
1168 timer_setup(&host->watchdog, mxcmci_watchdog, 0); in mxcmci_probe()
1175 if (host->dma) in mxcmci_probe()
1176 dma_release_channel(host->dma); in mxcmci_probe()
1179 clk_disable_unprepare(host->clk_ipg); in mxcmci_probe()
1181 clk_disable_unprepare(host->clk_per); in mxcmci_probe()
1196 if (host->pdata && host->pdata->exit) in mxcmci_remove()
1197 host->pdata->exit(&pdev->dev, mmc); in mxcmci_remove()
1199 if (host->dma) in mxcmci_remove()
1200 dma_release_channel(host->dma); in mxcmci_remove()
1202 clk_disable_unprepare(host->clk_per); in mxcmci_remove()
1203 clk_disable_unprepare(host->clk_ipg); in mxcmci_remove()
1216 clk_disable_unprepare(host->clk_per); in mxcmci_suspend()
1217 clk_disable_unprepare(host->clk_ipg); in mxcmci_suspend()
1227 ret = clk_prepare_enable(host->clk_per); in mxcmci_resume()
1231 ret = clk_prepare_enable(host->clk_ipg); in mxcmci_resume()
1233 clk_disable_unprepare(host->clk_per); in mxcmci_resume()
1258 MODULE_ALIAS("platform:mxc-mmc");