Lines Matching +full:mmc +full:- +full:host
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>
26 #include <linux/mmc/host.h>
27 #include <linux/mmc/slot-gpio.h>
37 #include <linux/platform_data/mmc-pxamci.h>
41 #define DRIVER_NAME "pxa2xx-mci"
50 struct mmc_host *mmc; member
76 static int pxamci_init_ocr(struct pxamci_host *host) in pxamci_init_ocr() argument
78 struct mmc_host *mmc = host->mmc; in pxamci_init_ocr() local
81 ret = mmc_regulator_get_supply(mmc); in pxamci_init_ocr()
85 if (IS_ERR(mmc->supply.vmmc)) { in pxamci_init_ocr()
86 /* fall-back to platform data */ in pxamci_init_ocr()
87 mmc->ocr_avail = host->pdata ? in pxamci_init_ocr()
88 host->pdata->ocr_mask : in pxamci_init_ocr()
95 static inline int pxamci_set_power(struct pxamci_host *host, in pxamci_set_power() argument
99 struct mmc_host *mmc = host->mmc; in pxamci_set_power() local
100 struct regulator *supply = mmc->supply.vmmc; in pxamci_set_power()
103 return mmc_regulator_set_ocr(mmc, supply, vdd); in pxamci_set_power()
105 if (host->power) { in pxamci_set_power()
106 bool on = !!((1 << vdd) & host->pdata->ocr_mask); in pxamci_set_power()
107 gpiod_set_value(host->power, on); in pxamci_set_power()
110 if (host->pdata && host->pdata->setpower) in pxamci_set_power()
111 return host->pdata->setpower(mmc_dev(host->mmc), vdd); in pxamci_set_power()
116 static void pxamci_stop_clock(struct pxamci_host *host) in pxamci_stop_clock() argument
118 if (readl(host->base + MMC_STAT) & STAT_CLK_EN) { in pxamci_stop_clock()
122 writel(STOP_CLOCK, host->base + MMC_STRPCL); in pxamci_stop_clock()
125 v = readl(host->base + MMC_STAT); in pxamci_stop_clock()
129 } while (timeout--); in pxamci_stop_clock()
132 dev_err(mmc_dev(host->mmc), "unable to stop clock\n"); in pxamci_stop_clock()
136 static void pxamci_enable_irq(struct pxamci_host *host, unsigned int mask) in pxamci_enable_irq() argument
140 spin_lock_irqsave(&host->lock, flags); in pxamci_enable_irq()
141 host->imask &= ~mask; in pxamci_enable_irq()
142 writel(host->imask, host->base + MMC_I_MASK); in pxamci_enable_irq()
143 spin_unlock_irqrestore(&host->lock, flags); in pxamci_enable_irq()
146 static void pxamci_disable_irq(struct pxamci_host *host, unsigned int mask) in pxamci_disable_irq() argument
150 spin_lock_irqsave(&host->lock, flags); in pxamci_disable_irq()
151 host->imask |= mask; in pxamci_disable_irq()
152 writel(host->imask, host->base + MMC_I_MASK); in pxamci_disable_irq()
153 spin_unlock_irqrestore(&host->lock, flags); in pxamci_disable_irq()
158 static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data) in pxamci_setup_data() argument
164 unsigned int nob = data->blocks; in pxamci_setup_data()
169 host->data = data; in pxamci_setup_data()
171 writel(nob, host->base + MMC_NOB); in pxamci_setup_data()
172 writel(data->blksz, host->base + MMC_BLKLEN); in pxamci_setup_data()
174 clks = (unsigned long long)data->timeout_ns * host->clkrate; in pxamci_setup_data()
176 timeout = (unsigned int)clks + (data->timeout_clks << host->clkrt); in pxamci_setup_data()
177 writel((timeout + 255) / 256, host->base + MMC_RDTO); in pxamci_setup_data()
182 config.src_addr = host->res->start + MMC_RXFIFO; in pxamci_setup_data()
183 config.dst_addr = host->res->start + MMC_TXFIFO; in pxamci_setup_data()
187 if (data->flags & MMC_DATA_READ) { in pxamci_setup_data()
188 host->dma_dir = DMA_FROM_DEVICE; in pxamci_setup_data()
190 chan = host->dma_chan_rx; in pxamci_setup_data()
192 host->dma_dir = DMA_TO_DEVICE; in pxamci_setup_data()
194 chan = host->dma_chan_tx; in pxamci_setup_data()
201 dev_err(mmc_dev(host->mmc), "dma slave config failed\n"); in pxamci_setup_data()
205 host->dma_len = dma_map_sg(chan->device->dev, data->sg, data->sg_len, in pxamci_setup_data()
206 host->dma_dir); in pxamci_setup_data()
208 tx = dmaengine_prep_slave_sg(chan, data->sg, host->dma_len, direction, in pxamci_setup_data()
211 dev_err(mmc_dev(host->mmc), "prep_slave_sg() failed\n"); in pxamci_setup_data()
215 if (!(data->flags & MMC_DATA_READ)) { in pxamci_setup_data()
216 tx->callback = pxamci_dma_irq; in pxamci_setup_data()
217 tx->callback_param = host; in pxamci_setup_data()
220 host->dma_cookie = dmaengine_submit(tx); in pxamci_setup_data()
228 if (!cpu_is_pxa27x() || data->flags & MMC_DATA_READ) in pxamci_setup_data()
232 static void pxamci_start_cmd(struct pxamci_host *host, struct mmc_command *cmd, unsigned int cmdat) in pxamci_start_cmd() argument
234 WARN_ON(host->cmd != NULL); in pxamci_start_cmd()
235 host->cmd = cmd; in pxamci_start_cmd()
237 if (cmd->flags & MMC_RSP_BUSY) in pxamci_start_cmd()
255 writel(cmd->opcode, host->base + MMC_CMD); in pxamci_start_cmd()
256 writel(cmd->arg >> 16, host->base + MMC_ARGH); in pxamci_start_cmd()
257 writel(cmd->arg & 0xffff, host->base + MMC_ARGL); in pxamci_start_cmd()
258 writel(cmdat, host->base + MMC_CMDAT); in pxamci_start_cmd()
259 writel(host->clkrt, host->base + MMC_CLKRT); in pxamci_start_cmd()
261 writel(START_CLOCK, host->base + MMC_STRPCL); in pxamci_start_cmd()
263 pxamci_enable_irq(host, END_CMD_RES); in pxamci_start_cmd()
266 static void pxamci_finish_request(struct pxamci_host *host, struct mmc_request *mrq) in pxamci_finish_request() argument
268 host->mrq = NULL; in pxamci_finish_request()
269 host->cmd = NULL; in pxamci_finish_request()
270 host->data = NULL; in pxamci_finish_request()
271 mmc_request_done(host->mmc, mrq); in pxamci_finish_request()
274 static int pxamci_cmd_done(struct pxamci_host *host, unsigned int stat) in pxamci_cmd_done() argument
276 struct mmc_command *cmd = host->cmd; in pxamci_cmd_done()
283 host->cmd = NULL; in pxamci_cmd_done()
287 * discard the upper 8 bits of the first 16-bit word. in pxamci_cmd_done()
289 v = readl(host->base + MMC_RES) & 0xffff; in pxamci_cmd_done()
291 u32 w1 = readl(host->base + MMC_RES) & 0xffff; in pxamci_cmd_done()
292 u32 w2 = readl(host->base + MMC_RES) & 0xffff; in pxamci_cmd_done()
293 cmd->resp[i] = v << 24 | w1 << 8 | w2 >> 8; in pxamci_cmd_done()
298 cmd->error = -ETIMEDOUT; in pxamci_cmd_done()
299 } else if (stat & STAT_RES_CRC_ERR && cmd->flags & MMC_RSP_CRC) { in pxamci_cmd_done()
307 (cmd->flags & MMC_RSP_136 && cmd->resp[0] & 0x80000000)) in pxamci_cmd_done()
308 pr_debug("ignoring CRC from command %d - *risky*\n", cmd->opcode); in pxamci_cmd_done()
310 cmd->error = -EILSEQ; in pxamci_cmd_done()
313 pxamci_disable_irq(host, END_CMD_RES); in pxamci_cmd_done()
314 if (host->data && !cmd->error) { in pxamci_cmd_done()
315 pxamci_enable_irq(host, DATA_TRAN_DONE); in pxamci_cmd_done()
320 if (cpu_is_pxa27x() && host->data->flags & MMC_DATA_WRITE) in pxamci_cmd_done()
321 dma_async_issue_pending(host->dma_chan_tx); in pxamci_cmd_done()
323 pxamci_finish_request(host, host->mrq); in pxamci_cmd_done()
329 static int pxamci_data_done(struct pxamci_host *host, unsigned int stat) in pxamci_data_done() argument
331 struct mmc_data *data = host->data; in pxamci_data_done()
337 if (data->flags & MMC_DATA_READ) in pxamci_data_done()
338 chan = host->dma_chan_rx; in pxamci_data_done()
340 chan = host->dma_chan_tx; in pxamci_data_done()
341 dma_unmap_sg(chan->device->dev, in pxamci_data_done()
342 data->sg, data->sg_len, host->dma_dir); in pxamci_data_done()
345 data->error = -ETIMEDOUT; in pxamci_data_done()
347 data->error = -EILSEQ; in pxamci_data_done()
355 if (!data->error) in pxamci_data_done()
356 data->bytes_xfered = data->blocks * data->blksz; in pxamci_data_done()
358 data->bytes_xfered = 0; in pxamci_data_done()
360 pxamci_disable_irq(host, DATA_TRAN_DONE); in pxamci_data_done()
362 host->data = NULL; in pxamci_data_done()
363 if (host->mrq->stop) { in pxamci_data_done()
364 pxamci_stop_clock(host); in pxamci_data_done()
365 pxamci_start_cmd(host, host->mrq->stop, host->cmdat); in pxamci_data_done()
367 pxamci_finish_request(host, host->mrq); in pxamci_data_done()
375 struct pxamci_host *host = devid; in pxamci_irq() local
379 ireg = readl(host->base + MMC_I_REG) & ~readl(host->base + MMC_I_MASK); in pxamci_irq()
382 unsigned stat = readl(host->base + MMC_STAT); in pxamci_irq()
387 handled |= pxamci_cmd_done(host, stat); in pxamci_irq()
389 handled |= pxamci_data_done(host, stat); in pxamci_irq()
391 mmc_signal_sdio_irq(host->mmc); in pxamci_irq()
399 static void pxamci_request(struct mmc_host *mmc, struct mmc_request *mrq) in pxamci_request() argument
401 struct pxamci_host *host = mmc_priv(mmc); in pxamci_request() local
404 WARN_ON(host->mrq != NULL); in pxamci_request()
406 host->mrq = mrq; in pxamci_request()
408 pxamci_stop_clock(host); in pxamci_request()
410 cmdat = host->cmdat; in pxamci_request()
411 host->cmdat &= ~CMDAT_INIT; in pxamci_request()
413 if (mrq->data) { in pxamci_request()
414 pxamci_setup_data(host, mrq->data); in pxamci_request()
418 if (mrq->data->flags & MMC_DATA_WRITE) in pxamci_request()
422 pxamci_start_cmd(host, mrq->cmd, cmdat); in pxamci_request()
425 static int pxamci_get_ro(struct mmc_host *mmc) in pxamci_get_ro() argument
427 struct pxamci_host *host = mmc_priv(mmc); in pxamci_get_ro() local
429 if (host->use_ro_gpio) in pxamci_get_ro()
430 return mmc_gpio_get_ro(mmc); in pxamci_get_ro()
431 if (host->pdata && host->pdata->get_ro) in pxamci_get_ro()
432 return !!host->pdata->get_ro(mmc_dev(mmc)); in pxamci_get_ro()
434 * Board doesn't support read only detection; let the mmc core in pxamci_get_ro()
437 return -ENOSYS; in pxamci_get_ro()
440 static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) in pxamci_set_ios() argument
442 struct pxamci_host *host = mmc_priv(mmc); in pxamci_set_ios() local
444 if (ios->clock) { in pxamci_set_ios()
445 unsigned long rate = host->clkrate; in pxamci_set_ios()
446 unsigned int clk = rate / ios->clock; in pxamci_set_ios()
448 if (host->clkrt == CLKRT_OFF) in pxamci_set_ios()
449 clk_prepare_enable(host->clk); in pxamci_set_ios()
451 if (ios->clock == 26000000) { in pxamci_set_ios()
453 host->clkrt = 7; in pxamci_set_ios()
464 if (rate / clk > ios->clock) in pxamci_set_ios()
466 host->clkrt = fls(clk) - 1; in pxamci_set_ios()
473 pxamci_stop_clock(host); in pxamci_set_ios()
474 if (host->clkrt != CLKRT_OFF) { in pxamci_set_ios()
475 host->clkrt = CLKRT_OFF; in pxamci_set_ios()
476 clk_disable_unprepare(host->clk); in pxamci_set_ios()
480 if (host->power_mode != ios->power_mode) { in pxamci_set_ios()
483 host->power_mode = ios->power_mode; in pxamci_set_ios()
485 ret = pxamci_set_power(host, ios->power_mode, ios->vdd); in pxamci_set_ios()
487 dev_err(mmc_dev(mmc), "unable to set power\n"); in pxamci_set_ios()
497 if (ios->power_mode == MMC_POWER_ON) in pxamci_set_ios()
498 host->cmdat |= CMDAT_INIT; in pxamci_set_ios()
501 if (ios->bus_width == MMC_BUS_WIDTH_4) in pxamci_set_ios()
502 host->cmdat |= CMDAT_SD_4DAT; in pxamci_set_ios()
504 host->cmdat &= ~CMDAT_SD_4DAT; in pxamci_set_ios()
506 dev_dbg(mmc_dev(mmc), "PXAMCI: clkrt = %x cmdat = %x\n", in pxamci_set_ios()
507 host->clkrt, host->cmdat); in pxamci_set_ios()
510 static void pxamci_enable_sdio_irq(struct mmc_host *host, int enable) in pxamci_enable_sdio_irq() argument
512 struct pxamci_host *pxa_host = mmc_priv(host); in pxamci_enable_sdio_irq()
530 struct pxamci_host *host = param; in pxamci_dma_irq() local
536 spin_lock_irqsave(&host->lock, flags); in pxamci_dma_irq()
538 if (!host->data) in pxamci_dma_irq()
541 if (host->data->flags & MMC_DATA_READ) in pxamci_dma_irq()
542 chan = host->dma_chan_rx; in pxamci_dma_irq()
544 chan = host->dma_chan_tx; in pxamci_dma_irq()
546 status = dmaengine_tx_status(chan, host->dma_cookie, &state); in pxamci_dma_irq()
549 writel(BUF_PART_FULL, host->base + MMC_PRTBUF); in pxamci_dma_irq()
551 pr_err("%s: DMA error on %s channel\n", mmc_hostname(host->mmc), in pxamci_dma_irq()
552 host->data->flags & MMC_DATA_READ ? "rx" : "tx"); in pxamci_dma_irq()
553 host->data->error = -EIO; in pxamci_dma_irq()
554 pxamci_data_done(host, 0); in pxamci_dma_irq()
558 spin_unlock_irqrestore(&host->lock, flags); in pxamci_dma_irq()
563 struct pxamci_host *host = mmc_priv(devid); in pxamci_detect_irq() local
565 mmc_detect_change(devid, msecs_to_jiffies(host->detect_delay_ms)); in pxamci_detect_irq()
571 { .compatible = "marvell,pxa-mmc" },
578 struct mmc_host *mmc) in pxamci_of_init() argument
580 struct device_node *np = pdev->dev.of_node; in pxamci_of_init()
581 struct pxamci_host *host = mmc_priv(mmc); in pxamci_of_init() local
588 /* pxa-mmc specific */ in pxamci_of_init()
589 if (of_property_read_u32(np, "pxa-mmc,detect-delay-ms", &tmp) == 0) in pxamci_of_init()
590 host->detect_delay_ms = tmp; in pxamci_of_init()
592 ret = mmc_of_parse(mmc); in pxamci_of_init()
600 struct mmc_host *mmc) in pxamci_of_init() argument
608 struct mmc_host *mmc; in pxamci_probe() local
609 struct pxamci_host *host = NULL; in pxamci_probe() local
610 struct device *dev = &pdev->dev; in pxamci_probe()
618 mmc = mmc_alloc_host(sizeof(struct pxamci_host), dev); in pxamci_probe()
619 if (!mmc) { in pxamci_probe()
620 ret = -ENOMEM; in pxamci_probe()
624 mmc->ops = &pxamci_ops; in pxamci_probe()
627 * We can do SG-DMA, but we don't because we never know how much in pxamci_probe()
630 mmc->max_segs = NR_SG; in pxamci_probe()
635 mmc->max_seg_size = PAGE_SIZE; in pxamci_probe()
640 mmc->max_blk_size = cpu_is_pxa25x() ? 1023 : 2048; in pxamci_probe()
645 mmc->max_blk_count = 65535; in pxamci_probe()
647 ret = pxamci_of_init(pdev, mmc); in pxamci_probe()
651 host = mmc_priv(mmc); in pxamci_probe()
652 host->mmc = mmc; in pxamci_probe()
653 host->pdata = pdev->dev.platform_data; in pxamci_probe()
654 host->clkrt = CLKRT_OFF; in pxamci_probe()
656 host->clk = devm_clk_get(dev, NULL); in pxamci_probe()
657 if (IS_ERR(host->clk)) { in pxamci_probe()
658 ret = PTR_ERR(host->clk); in pxamci_probe()
659 host->clk = NULL; in pxamci_probe()
663 host->clkrate = clk_get_rate(host->clk); in pxamci_probe()
668 mmc->f_min = (host->clkrate + 63) / 64; in pxamci_probe()
669 mmc->f_max = (mmc_has_26MHz()) ? 26000000 : host->clkrate; in pxamci_probe()
671 ret = pxamci_init_ocr(host); in pxamci_probe()
675 mmc->caps = 0; in pxamci_probe()
676 host->cmdat = 0; in pxamci_probe()
678 mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ; in pxamci_probe()
679 host->cmdat |= CMDAT_SDIO_INT_EN; in pxamci_probe()
681 mmc->caps |= MMC_CAP_MMC_HIGHSPEED | in pxamci_probe()
685 spin_lock_init(&host->lock); in pxamci_probe()
686 host->imask = MMC_I_MASK_ALL; in pxamci_probe()
688 host->base = devm_platform_get_and_ioremap_resource(pdev, 0, &r); in pxamci_probe()
689 if (IS_ERR(host->base)) { in pxamci_probe()
690 ret = PTR_ERR(host->base); in pxamci_probe()
693 host->res = r; in pxamci_probe()
696 * Ensure that the host controller is shut down, and setup in pxamci_probe()
699 pxamci_stop_clock(host); in pxamci_probe()
700 writel(0, host->base + MMC_SPI); in pxamci_probe()
701 writel(64, host->base + MMC_RESTO); in pxamci_probe()
702 writel(host->imask, host->base + MMC_I_MASK); in pxamci_probe()
705 DRIVER_NAME, host); in pxamci_probe()
709 platform_set_drvdata(pdev, mmc); in pxamci_probe()
711 host->dma_chan_rx = dma_request_chan(dev, "rx"); in pxamci_probe()
712 if (IS_ERR(host->dma_chan_rx)) { in pxamci_probe()
714 ret = PTR_ERR(host->dma_chan_rx); in pxamci_probe()
715 host->dma_chan_rx = NULL; in pxamci_probe()
719 host->dma_chan_tx = dma_request_chan(dev, "tx"); in pxamci_probe()
720 if (IS_ERR(host->dma_chan_tx)) { in pxamci_probe()
722 ret = PTR_ERR(host->dma_chan_tx); in pxamci_probe()
723 host->dma_chan_tx = NULL; in pxamci_probe()
727 if (host->pdata) { in pxamci_probe()
728 host->detect_delay_ms = host->pdata->detect_delay_ms; in pxamci_probe()
730 host->power = devm_gpiod_get_optional(dev, "power", GPIOD_OUT_LOW); in pxamci_probe()
731 if (IS_ERR(host->power)) { in pxamci_probe()
732 ret = PTR_ERR(host->power); in pxamci_probe()
738 ret = mmc_gpiod_request_cd(mmc, "cd", 0, false, 0); in pxamci_probe()
739 if (ret && ret != -ENOENT) { in pxamci_probe()
744 if (!host->pdata->gpio_card_ro_invert) in pxamci_probe()
745 mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; in pxamci_probe()
747 ret = mmc_gpiod_request_ro(mmc, "wp", 0, 0); in pxamci_probe()
748 if (ret && ret != -ENOENT) { in pxamci_probe()
753 host->use_ro_gpio = true; in pxamci_probe()
755 if (host->pdata->init) in pxamci_probe()
756 host->pdata->init(dev, pxamci_detect_irq, mmc); in pxamci_probe()
758 if (host->power && host->pdata->setpower) in pxamci_probe()
760 if (host->use_ro_gpio && host->pdata->get_ro) in pxamci_probe()
764 ret = mmc_add_host(mmc); in pxamci_probe()
766 if (host->pdata && host->pdata->exit) in pxamci_probe()
767 host->pdata->exit(dev, mmc); in pxamci_probe()
774 if (host) { in pxamci_probe()
775 if (host->dma_chan_rx) in pxamci_probe()
776 dma_release_channel(host->dma_chan_rx); in pxamci_probe()
777 if (host->dma_chan_tx) in pxamci_probe()
778 dma_release_channel(host->dma_chan_tx); in pxamci_probe()
780 if (mmc) in pxamci_probe()
781 mmc_free_host(mmc); in pxamci_probe()
787 struct mmc_host *mmc = platform_get_drvdata(pdev); in pxamci_remove() local
789 if (mmc) { in pxamci_remove()
790 struct pxamci_host *host = mmc_priv(mmc); in pxamci_remove() local
792 mmc_remove_host(mmc); in pxamci_remove()
794 if (host->pdata && host->pdata->exit) in pxamci_remove()
795 host->pdata->exit(&pdev->dev, mmc); in pxamci_remove()
797 pxamci_stop_clock(host); in pxamci_remove()
800 host->base + MMC_I_MASK); in pxamci_remove()
802 dmaengine_terminate_all(host->dma_chan_rx); in pxamci_remove()
803 dmaengine_terminate_all(host->dma_chan_tx); in pxamci_remove()
804 dma_release_channel(host->dma_chan_rx); in pxamci_remove()
805 dma_release_channel(host->dma_chan_tx); in pxamci_remove()
807 mmc_free_host(mmc); in pxamci_remove()
825 MODULE_ALIAS("platform:pxa2xx-mci");