Lines Matching +full:mmci +full:- +full:gpio +full:- +full:supply
1 // SPDX-License-Identifier: GPL-2.0-only
3 * linux/drivers/mmc/host/pxa.c - PXA MMCI driver
8 * - No way to clear interrupts.
9 * - Have to turn off the clock whenever we touch the device.
10 * - Doesn't tell you how many data blocks were transferred.
23 #include <linux/dma-mapping.h>
27 #include <linux/mmc/slot-gpio.h>
30 #include <linux/gpio/consumer.h>
38 #include <linux/platform_data/mmc-pxamci.h>
42 #define DRIVER_NAME "pxa2xx-mci"
79 struct mmc_host *mmc = host->mmc; in pxamci_init_ocr()
86 if (IS_ERR(mmc->supply.vmmc)) { in pxamci_init_ocr()
87 /* fall-back to platform data */ in pxamci_init_ocr()
88 mmc->ocr_avail = host->pdata ? in pxamci_init_ocr()
89 host->pdata->ocr_mask : in pxamci_init_ocr()
100 struct mmc_host *mmc = host->mmc; in pxamci_set_power()
101 struct regulator *supply = mmc->supply.vmmc; in pxamci_set_power() local
103 if (!IS_ERR(supply)) in pxamci_set_power()
104 return mmc_regulator_set_ocr(mmc, supply, vdd); in pxamci_set_power()
106 if (host->power) { in pxamci_set_power()
107 bool on = !!((1 << vdd) & host->pdata->ocr_mask); in pxamci_set_power()
108 gpiod_set_value(host->power, on); in pxamci_set_power()
111 if (host->pdata && host->pdata->setpower) in pxamci_set_power()
112 return host->pdata->setpower(mmc_dev(host->mmc), vdd); in pxamci_set_power()
119 if (readl(host->base + MMC_STAT) & STAT_CLK_EN) { in pxamci_stop_clock()
123 writel(STOP_CLOCK, host->base + MMC_STRPCL); in pxamci_stop_clock()
126 v = readl(host->base + MMC_STAT); in pxamci_stop_clock()
130 } while (timeout--); in pxamci_stop_clock()
133 dev_err(mmc_dev(host->mmc), "unable to stop clock\n"); in pxamci_stop_clock()
141 spin_lock_irqsave(&host->lock, flags); in pxamci_enable_irq()
142 host->imask &= ~mask; in pxamci_enable_irq()
143 writel(host->imask, host->base + MMC_I_MASK); in pxamci_enable_irq()
144 spin_unlock_irqrestore(&host->lock, flags); in pxamci_enable_irq()
151 spin_lock_irqsave(&host->lock, flags); in pxamci_disable_irq()
152 host->imask |= mask; in pxamci_disable_irq()
153 writel(host->imask, host->base + MMC_I_MASK); in pxamci_disable_irq()
154 spin_unlock_irqrestore(&host->lock, flags); in pxamci_disable_irq()
165 unsigned int nob = data->blocks; in pxamci_setup_data()
170 host->data = data; in pxamci_setup_data()
172 writel(nob, host->base + MMC_NOB); in pxamci_setup_data()
173 writel(data->blksz, host->base + MMC_BLKLEN); in pxamci_setup_data()
175 clks = (unsigned long long)data->timeout_ns * host->clkrate; in pxamci_setup_data()
177 timeout = (unsigned int)clks + (data->timeout_clks << host->clkrt); in pxamci_setup_data()
178 writel((timeout + 255) / 256, host->base + MMC_RDTO); in pxamci_setup_data()
183 config.src_addr = host->res->start + MMC_RXFIFO; in pxamci_setup_data()
184 config.dst_addr = host->res->start + MMC_TXFIFO; in pxamci_setup_data()
188 if (data->flags & MMC_DATA_READ) { in pxamci_setup_data()
189 host->dma_dir = DMA_FROM_DEVICE; in pxamci_setup_data()
191 chan = host->dma_chan_rx; in pxamci_setup_data()
193 host->dma_dir = DMA_TO_DEVICE; in pxamci_setup_data()
195 chan = host->dma_chan_tx; in pxamci_setup_data()
202 dev_err(mmc_dev(host->mmc), "dma slave config failed\n"); in pxamci_setup_data()
206 host->dma_len = dma_map_sg(chan->device->dev, data->sg, data->sg_len, in pxamci_setup_data()
207 host->dma_dir); in pxamci_setup_data()
209 tx = dmaengine_prep_slave_sg(chan, data->sg, host->dma_len, direction, in pxamci_setup_data()
212 dev_err(mmc_dev(host->mmc), "prep_slave_sg() failed\n"); in pxamci_setup_data()
216 if (!(data->flags & MMC_DATA_READ)) { in pxamci_setup_data()
217 tx->callback = pxamci_dma_irq; in pxamci_setup_data()
218 tx->callback_param = host; in pxamci_setup_data()
221 host->dma_cookie = dmaengine_submit(tx); in pxamci_setup_data()
229 if (!cpu_is_pxa27x() || data->flags & MMC_DATA_READ) in pxamci_setup_data()
235 WARN_ON(host->cmd != NULL); in pxamci_start_cmd()
236 host->cmd = cmd; in pxamci_start_cmd()
238 if (cmd->flags & MMC_RSP_BUSY) in pxamci_start_cmd()
256 writel(cmd->opcode, host->base + MMC_CMD); in pxamci_start_cmd()
257 writel(cmd->arg >> 16, host->base + MMC_ARGH); in pxamci_start_cmd()
258 writel(cmd->arg & 0xffff, host->base + MMC_ARGL); in pxamci_start_cmd()
259 writel(cmdat, host->base + MMC_CMDAT); in pxamci_start_cmd()
260 writel(host->clkrt, host->base + MMC_CLKRT); in pxamci_start_cmd()
262 writel(START_CLOCK, host->base + MMC_STRPCL); in pxamci_start_cmd()
269 host->mrq = NULL; in pxamci_finish_request()
270 host->cmd = NULL; in pxamci_finish_request()
271 host->data = NULL; in pxamci_finish_request()
272 mmc_request_done(host->mmc, mrq); in pxamci_finish_request()
277 struct mmc_command *cmd = host->cmd; in pxamci_cmd_done()
284 host->cmd = NULL; in pxamci_cmd_done()
288 * discard the upper 8 bits of the first 16-bit word. in pxamci_cmd_done()
290 v = readl(host->base + MMC_RES) & 0xffff; in pxamci_cmd_done()
292 u32 w1 = readl(host->base + MMC_RES) & 0xffff; in pxamci_cmd_done()
293 u32 w2 = readl(host->base + MMC_RES) & 0xffff; in pxamci_cmd_done()
294 cmd->resp[i] = v << 24 | w1 << 8 | w2 >> 8; in pxamci_cmd_done()
299 cmd->error = -ETIMEDOUT; in pxamci_cmd_done()
300 } else if (stat & STAT_RES_CRC_ERR && cmd->flags & MMC_RSP_CRC) { in pxamci_cmd_done()
308 (cmd->flags & MMC_RSP_136 && cmd->resp[0] & 0x80000000)) in pxamci_cmd_done()
309 pr_debug("ignoring CRC from command %d - *risky*\n", cmd->opcode); in pxamci_cmd_done()
311 cmd->error = -EILSEQ; in pxamci_cmd_done()
315 if (host->data && !cmd->error) { in pxamci_cmd_done()
321 if (cpu_is_pxa27x() && host->data->flags & MMC_DATA_WRITE) in pxamci_cmd_done()
322 dma_async_issue_pending(host->dma_chan_tx); in pxamci_cmd_done()
324 pxamci_finish_request(host, host->mrq); in pxamci_cmd_done()
332 struct mmc_data *data = host->data; in pxamci_data_done()
338 if (data->flags & MMC_DATA_READ) in pxamci_data_done()
339 chan = host->dma_chan_rx; in pxamci_data_done()
341 chan = host->dma_chan_tx; in pxamci_data_done()
342 dma_unmap_sg(chan->device->dev, in pxamci_data_done()
343 data->sg, data->sg_len, host->dma_dir); in pxamci_data_done()
346 data->error = -ETIMEDOUT; in pxamci_data_done()
348 data->error = -EILSEQ; in pxamci_data_done()
356 if (!data->error) in pxamci_data_done()
357 data->bytes_xfered = data->blocks * data->blksz; in pxamci_data_done()
359 data->bytes_xfered = 0; in pxamci_data_done()
363 host->data = NULL; in pxamci_data_done()
364 if (host->mrq->stop) { in pxamci_data_done()
366 pxamci_start_cmd(host, host->mrq->stop, host->cmdat); in pxamci_data_done()
368 pxamci_finish_request(host, host->mrq); in pxamci_data_done()
380 ireg = readl(host->base + MMC_I_REG) & ~readl(host->base + MMC_I_MASK); in pxamci_irq()
383 unsigned stat = readl(host->base + MMC_STAT); in pxamci_irq()
392 mmc_signal_sdio_irq(host->mmc); in pxamci_irq()
405 WARN_ON(host->mrq != NULL); in pxamci_request()
407 host->mrq = mrq; in pxamci_request()
411 cmdat = host->cmdat; in pxamci_request()
412 host->cmdat &= ~CMDAT_INIT; in pxamci_request()
414 if (mrq->data) { in pxamci_request()
415 pxamci_setup_data(host, mrq->data); in pxamci_request()
419 if (mrq->data->flags & MMC_DATA_WRITE) in pxamci_request()
423 pxamci_start_cmd(host, mrq->cmd, cmdat); in pxamci_request()
430 if (host->use_ro_gpio) in pxamci_get_ro()
432 if (host->pdata && host->pdata->get_ro) in pxamci_get_ro()
433 return !!host->pdata->get_ro(mmc_dev(mmc)); in pxamci_get_ro()
438 return -ENOSYS; in pxamci_get_ro()
445 if (ios->clock) { in pxamci_set_ios()
446 unsigned long rate = host->clkrate; in pxamci_set_ios()
447 unsigned int clk = rate / ios->clock; in pxamci_set_ios()
449 if (host->clkrt == CLKRT_OFF) in pxamci_set_ios()
450 clk_prepare_enable(host->clk); in pxamci_set_ios()
452 if (ios->clock == 26000000) { in pxamci_set_ios()
454 host->clkrt = 7; in pxamci_set_ios()
465 if (rate / clk > ios->clock) in pxamci_set_ios()
467 host->clkrt = fls(clk) - 1; in pxamci_set_ios()
475 if (host->clkrt != CLKRT_OFF) { in pxamci_set_ios()
476 host->clkrt = CLKRT_OFF; in pxamci_set_ios()
477 clk_disable_unprepare(host->clk); in pxamci_set_ios()
481 if (host->power_mode != ios->power_mode) { in pxamci_set_ios()
484 host->power_mode = ios->power_mode; in pxamci_set_ios()
486 ret = pxamci_set_power(host, ios->power_mode, ios->vdd); in pxamci_set_ios()
498 if (ios->power_mode == MMC_POWER_ON) in pxamci_set_ios()
499 host->cmdat |= CMDAT_INIT; in pxamci_set_ios()
502 if (ios->bus_width == MMC_BUS_WIDTH_4) in pxamci_set_ios()
503 host->cmdat |= CMDAT_SD_4DAT; in pxamci_set_ios()
505 host->cmdat &= ~CMDAT_SD_4DAT; in pxamci_set_ios()
508 host->clkrt, host->cmdat); in pxamci_set_ios()
537 spin_lock_irqsave(&host->lock, flags); in pxamci_dma_irq()
539 if (!host->data) in pxamci_dma_irq()
542 if (host->data->flags & MMC_DATA_READ) in pxamci_dma_irq()
543 chan = host->dma_chan_rx; in pxamci_dma_irq()
545 chan = host->dma_chan_tx; in pxamci_dma_irq()
547 status = dmaengine_tx_status(chan, host->dma_cookie, &state); in pxamci_dma_irq()
550 writel(BUF_PART_FULL, host->base + MMC_PRTBUF); in pxamci_dma_irq()
552 pr_err("%s: DMA error on %s channel\n", mmc_hostname(host->mmc), in pxamci_dma_irq()
553 host->data->flags & MMC_DATA_READ ? "rx" : "tx"); in pxamci_dma_irq()
554 host->data->error = -EIO; in pxamci_dma_irq()
559 spin_unlock_irqrestore(&host->lock, flags); in pxamci_dma_irq()
566 mmc_detect_change(devid, msecs_to_jiffies(host->detect_delay_ms)); in pxamci_detect_irq()
572 { .compatible = "marvell,pxa-mmc" },
581 struct device_node *np = pdev->dev.of_node; in pxamci_of_init()
589 /* pxa-mmc specific */ in pxamci_of_init()
590 if (of_property_read_u32(np, "pxa-mmc,detect-delay-ms", &tmp) == 0) in pxamci_of_init()
591 host->detect_delay_ms = tmp; in pxamci_of_init()
611 struct device *dev = &pdev->dev; in pxamci_probe()
622 ret = -ENOMEM; in pxamci_probe()
626 mmc->ops = &pxamci_ops; in pxamci_probe()
629 * We can do SG-DMA, but we don't because we never know how much in pxamci_probe()
632 mmc->max_segs = NR_SG; in pxamci_probe()
637 mmc->max_seg_size = PAGE_SIZE; in pxamci_probe()
642 mmc->max_blk_size = cpu_is_pxa25x() ? 1023 : 2048; in pxamci_probe()
647 mmc->max_blk_count = 65535; in pxamci_probe()
654 host->mmc = mmc; in pxamci_probe()
655 host->pdata = pdev->dev.platform_data; in pxamci_probe()
656 host->clkrt = CLKRT_OFF; in pxamci_probe()
658 host->clk = devm_clk_get(dev, NULL); in pxamci_probe()
659 if (IS_ERR(host->clk)) { in pxamci_probe()
660 ret = PTR_ERR(host->clk); in pxamci_probe()
661 host->clk = NULL; in pxamci_probe()
665 host->clkrate = clk_get_rate(host->clk); in pxamci_probe()
670 mmc->f_min = (host->clkrate + 63) / 64; in pxamci_probe()
671 mmc->f_max = (mmc_has_26MHz()) ? 26000000 : host->clkrate; in pxamci_probe()
677 mmc->caps = 0; in pxamci_probe()
678 host->cmdat = 0; in pxamci_probe()
680 mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ; in pxamci_probe()
681 host->cmdat |= CMDAT_SDIO_INT_EN; in pxamci_probe()
683 mmc->caps |= MMC_CAP_MMC_HIGHSPEED | in pxamci_probe()
687 spin_lock_init(&host->lock); in pxamci_probe()
688 host->res = r; in pxamci_probe()
689 host->imask = MMC_I_MASK_ALL; in pxamci_probe()
691 host->base = devm_ioremap_resource(dev, r); in pxamci_probe()
692 if (IS_ERR(host->base)) { in pxamci_probe()
693 ret = PTR_ERR(host->base); in pxamci_probe()
702 writel(0, host->base + MMC_SPI); in pxamci_probe()
703 writel(64, host->base + MMC_RESTO); in pxamci_probe()
704 writel(host->imask, host->base + MMC_I_MASK); in pxamci_probe()
713 host->dma_chan_rx = dma_request_chan(dev, "rx"); in pxamci_probe()
714 if (IS_ERR(host->dma_chan_rx)) { in pxamci_probe()
716 ret = PTR_ERR(host->dma_chan_rx); in pxamci_probe()
717 host->dma_chan_rx = NULL; in pxamci_probe()
721 host->dma_chan_tx = dma_request_chan(dev, "tx"); in pxamci_probe()
722 if (IS_ERR(host->dma_chan_tx)) { in pxamci_probe()
724 ret = PTR_ERR(host->dma_chan_tx); in pxamci_probe()
725 host->dma_chan_tx = NULL; in pxamci_probe()
729 if (host->pdata) { in pxamci_probe()
730 host->detect_delay_ms = host->pdata->detect_delay_ms; in pxamci_probe()
732 host->power = devm_gpiod_get_optional(dev, "power", GPIOD_OUT_LOW); in pxamci_probe()
733 if (IS_ERR(host->power)) { in pxamci_probe()
740 if (ret && ret != -ENOENT) { in pxamci_probe()
745 if (!host->pdata->gpio_card_ro_invert) in pxamci_probe()
746 mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; in pxamci_probe()
749 if (ret && ret != -ENOENT) { in pxamci_probe()
754 host->use_ro_gpio = true; in pxamci_probe()
756 if (host->pdata->init) in pxamci_probe()
757 host->pdata->init(dev, pxamci_detect_irq, mmc); in pxamci_probe()
759 if (host->power && host->pdata->setpower) in pxamci_probe()
761 if (host->use_ro_gpio && host->pdata->get_ro) in pxamci_probe()
771 if (host->dma_chan_rx) in pxamci_probe()
772 dma_release_channel(host->dma_chan_rx); in pxamci_probe()
773 if (host->dma_chan_tx) in pxamci_probe()
774 dma_release_channel(host->dma_chan_tx); in pxamci_probe()
790 if (host->pdata && host->pdata->exit) in pxamci_remove()
791 host->pdata->exit(&pdev->dev, mmc); in pxamci_remove()
796 host->base + MMC_I_MASK); in pxamci_remove()
798 dmaengine_terminate_all(host->dma_chan_rx); in pxamci_remove()
799 dmaengine_terminate_all(host->dma_chan_tx); in pxamci_remove()
800 dma_release_channel(host->dma_chan_rx); in pxamci_remove()
801 dma_release_channel(host->dma_chan_tx); in pxamci_remove()
823 MODULE_ALIAS("platform:pxa2xx-mci");