Lines Matching +full:mmc +full:-
2 * MOXA ART MMC host driver.
23 #include <linux/dma-mapping.h>
25 #include <linux/mmc/host.h>
26 #include <linux/mmc/sd.h>
82 /* 1-10 below can be sent to either registers, interrupt or clear. */
119 #define MIN_POWER (MMC_VDD_360 - SD_POWER_MASK)
132 struct mmc_host *mmc; member
154 host->cur_sg = data->sg; in moxart_init_sg()
155 host->num_sg = data->sg_len; in moxart_init_sg()
156 host->data_remain = host->cur_sg->length; in moxart_init_sg()
158 if (host->data_remain > host->data_len) in moxart_init_sg()
159 host->data_remain = host->data_len; in moxart_init_sg()
165 struct mmc_data *data = host->mrq->cmd->data; in moxart_next_sg()
167 host->cur_sg++; in moxart_next_sg()
168 host->num_sg--; in moxart_next_sg()
170 if (host->num_sg > 0) { in moxart_next_sg()
171 host->data_remain = host->cur_sg->length; in moxart_next_sg()
172 remain = host->data_len - data->bytes_xfered; in moxart_next_sg()
173 if (remain > 0 && remain < host->data_remain) in moxart_next_sg()
174 host->data_remain = remain; in moxart_next_sg()
177 return host->num_sg; in moxart_next_sg()
183 int ret = -ETIMEDOUT; in moxart_wait_for_status()
187 *status = readl(host->base + REG_STATUS); in moxart_wait_for_status()
192 writel(*status & mask, host->base + REG_CLEAR); in moxart_wait_for_status()
198 dev_err(mmc_dev(host->mmc), "timed out waiting for status\n"); in moxart_wait_for_status()
210 RSP_CRC_FAIL | CMD_SENT, host->base + REG_CLEAR); in moxart_send_command()
211 writel(cmd->arg, host->base + REG_ARGUMENT); in moxart_send_command()
213 cmdctrl = cmd->opcode & CMD_IDX_MASK; in moxart_send_command()
219 if (cmd->flags & MMC_RSP_PRESENT) in moxart_send_command()
222 if (cmd->flags & MMC_RSP_136) in moxart_send_command()
225 writel(cmdctrl | CMD_EN, host->base + REG_COMMAND); in moxart_send_command()
227 if (moxart_wait_for_status(host, MASK_RSP, &status) == -ETIMEDOUT) in moxart_send_command()
228 cmd->error = -ETIMEDOUT; in moxart_send_command()
231 cmd->error = -ETIMEDOUT; in moxart_send_command()
235 cmd->error = -EIO; in moxart_send_command()
239 if (cmd->flags & MMC_RSP_136) { in moxart_send_command()
240 cmd->resp[3] = readl(host->base + REG_RESPONSE0); in moxart_send_command()
241 cmd->resp[2] = readl(host->base + REG_RESPONSE1); in moxart_send_command()
242 cmd->resp[1] = readl(host->base + REG_RESPONSE2); in moxart_send_command()
243 cmd->resp[0] = readl(host->base + REG_RESPONSE3); in moxart_send_command()
245 cmd->resp[0] = readl(host->base + REG_RESPONSE0); in moxart_send_command()
254 complete(&host->dma_complete); in moxart_dma_complete()
259 return (host->data_len > host->fifo_width) && host->have_dma; in moxart_use_dma()
268 if (host->data_len == data->bytes_xfered) in moxart_transfer_dma()
271 if (data->flags & MMC_DATA_WRITE) { in moxart_transfer_dma()
272 dma_chan = host->dma_chan_tx; in moxart_transfer_dma()
275 dma_chan = host->dma_chan_rx; in moxart_transfer_dma()
279 len = dma_map_sg(dma_chan->device->dev, data->sg, in moxart_transfer_dma()
280 data->sg_len, mmc_get_dma_dir(data)); in moxart_transfer_dma()
283 desc = dmaengine_prep_slave_sg(dma_chan, data->sg, in moxart_transfer_dma()
288 dev_err(mmc_dev(host->mmc), "dma_map_sg returned zero length\n"); in moxart_transfer_dma()
292 host->tx_desc = desc; in moxart_transfer_dma()
293 desc->callback = moxart_dma_complete; in moxart_transfer_dma()
294 desc->callback_param = host; in moxart_transfer_dma()
299 wait_for_completion_interruptible_timeout(&host->dma_complete, in moxart_transfer_dma()
300 host->timeout); in moxart_transfer_dma()
302 data->bytes_xfered = host->data_len; in moxart_transfer_dma()
304 dma_unmap_sg(dma_chan->device->dev, in moxart_transfer_dma()
305 data->sg, data->sg_len, in moxart_transfer_dma()
312 struct mmc_data *data = host->mrq->cmd->data; in moxart_transfer_pio()
315 if (host->data_len == data->bytes_xfered) in moxart_transfer_pio()
318 sgp = sg_virt(host->cur_sg); in moxart_transfer_pio()
319 remain = host->data_remain; in moxart_transfer_pio()
321 if (data->flags & MMC_DATA_WRITE) { in moxart_transfer_pio()
324 == -ETIMEDOUT) { in moxart_transfer_pio()
325 data->error = -ETIMEDOUT; in moxart_transfer_pio()
326 complete(&host->pio_complete); in moxart_transfer_pio()
329 for (len = 0; len < remain && len < host->fifo_width;) { in moxart_transfer_pio()
330 iowrite32(*sgp, host->base + REG_DATA_WINDOW); in moxart_transfer_pio()
334 remain -= len; in moxart_transfer_pio()
340 == -ETIMEDOUT) { in moxart_transfer_pio()
341 data->error = -ETIMEDOUT; in moxart_transfer_pio()
342 complete(&host->pio_complete); in moxart_transfer_pio()
345 for (len = 0; len < remain && len < host->fifo_width;) { in moxart_transfer_pio()
346 *sgp = ioread32(host->base + REG_DATA_WINDOW); in moxart_transfer_pio()
350 remain -= len; in moxart_transfer_pio()
354 data->bytes_xfered += host->data_remain - remain; in moxart_transfer_pio()
355 host->data_remain = remain; in moxart_transfer_pio()
357 if (host->data_len != data->bytes_xfered) in moxart_transfer_pio()
360 complete(&host->pio_complete); in moxart_transfer_pio()
365 struct mmc_data *data = host->mrq->cmd->data; in moxart_prepare_data()
372 host->data_len = data->blocks * data->blksz; in moxart_prepare_data()
373 blksz_bits = ffs(data->blksz) - 1; in moxart_prepare_data()
374 BUG_ON(1 << blksz_bits != data->blksz); in moxart_prepare_data()
380 if (data->flags & MMC_DATA_WRITE) in moxart_prepare_data()
386 writel(DCR_DATA_FIFO_RESET, host->base + REG_DATA_CONTROL); in moxart_prepare_data()
387 writel(MASK_DATA | FIFO_URUN | FIFO_ORUN, host->base + REG_CLEAR); in moxart_prepare_data()
388 writel(host->rate, host->base + REG_DATA_TIMER); in moxart_prepare_data()
389 writel(host->data_len, host->base + REG_DATA_LENGTH); in moxart_prepare_data()
390 writel(datactrl, host->base + REG_DATA_CONTROL); in moxart_prepare_data()
393 static void moxart_request(struct mmc_host *mmc, struct mmc_request *mrq) in moxart_request() argument
395 struct moxart_host *host = mmc_priv(mmc); in moxart_request()
399 spin_lock_irqsave(&host->lock, flags); in moxart_request()
401 init_completion(&host->dma_complete); in moxart_request()
402 init_completion(&host->pio_complete); in moxart_request()
404 host->mrq = mrq; in moxart_request()
406 if (readl(host->base + REG_STATUS) & CARD_DETECT) { in moxart_request()
407 mrq->cmd->error = -ETIMEDOUT; in moxart_request()
412 moxart_send_command(host, host->mrq->cmd); in moxart_request()
414 if (mrq->cmd->data) { in moxart_request()
417 writel(CARD_CHANGE, host->base + REG_INTERRUPT_MASK); in moxart_request()
419 spin_unlock_irqrestore(&host->lock, flags); in moxart_request()
421 moxart_transfer_dma(mrq->cmd->data, host); in moxart_request()
423 spin_lock_irqsave(&host->lock, flags); in moxart_request()
426 writel(MASK_INTR_PIO, host->base + REG_INTERRUPT_MASK); in moxart_request()
428 spin_unlock_irqrestore(&host->lock, flags); in moxart_request()
431 wait_for_completion_interruptible_timeout(&host->pio_complete, in moxart_request()
432 host->timeout); in moxart_request()
434 spin_lock_irqsave(&host->lock, flags); in moxart_request()
437 if (host->is_removed) { in moxart_request()
438 dev_err(mmc_dev(host->mmc), "card removed\n"); in moxart_request()
439 mrq->cmd->error = -ETIMEDOUT; in moxart_request()
444 == -ETIMEDOUT) { in moxart_request()
445 mrq->cmd->data->error = -ETIMEDOUT; in moxart_request()
450 mrq->cmd->data->error = -ETIMEDOUT; in moxart_request()
452 if (mrq->cmd->data->stop) in moxart_request()
453 moxart_send_command(host, mrq->cmd->data->stop); in moxart_request()
457 spin_unlock_irqrestore(&host->lock, flags); in moxart_request()
458 mmc_request_done(host->mmc, mrq); in moxart_request()
466 spin_lock(&host->lock); in moxart_irq()
468 status = readl(host->base + REG_STATUS); in moxart_irq()
470 host->is_removed = status & CARD_DETECT; in moxart_irq()
471 if (host->is_removed && host->have_dma) { in moxart_irq()
472 dmaengine_terminate_all(host->dma_chan_tx); in moxart_irq()
473 dmaengine_terminate_all(host->dma_chan_rx); in moxart_irq()
475 host->mrq = NULL; in moxart_irq()
476 writel(MASK_INTR_PIO, host->base + REG_CLEAR); in moxart_irq()
477 writel(CARD_CHANGE, host->base + REG_INTERRUPT_MASK); in moxart_irq()
478 mmc_detect_change(host->mmc, 0); in moxart_irq()
480 if (status & (FIFO_ORUN | FIFO_URUN) && host->mrq) in moxart_irq()
483 spin_unlock(&host->lock); in moxart_irq()
488 static void moxart_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) in moxart_set_ios() argument
490 struct moxart_host *host = mmc_priv(mmc); in moxart_set_ios()
495 spin_lock_irqsave(&host->lock, flags); in moxart_set_ios()
497 if (ios->clock) { in moxart_set_ios()
499 if (ios->clock >= host->sysclk / (2 * (div + 1))) in moxart_set_ios()
503 host->rate = host->sysclk / (2 * (div + 1)); in moxart_set_ios()
504 if (host->rate > host->sysclk) in moxart_set_ios()
506 writel(ctrl, host->base + REG_CLOCK_CONTROL); in moxart_set_ios()
509 if (ios->power_mode == MMC_POWER_OFF) { in moxart_set_ios()
510 writel(readl(host->base + REG_POWER_CONTROL) & ~SD_POWER_ON, in moxart_set_ios()
511 host->base + REG_POWER_CONTROL); in moxart_set_ios()
513 if (ios->vdd < MIN_POWER) in moxart_set_ios()
516 power = ios->vdd - MIN_POWER; in moxart_set_ios()
519 host->base + REG_POWER_CONTROL); in moxart_set_ios()
522 switch (ios->bus_width) { in moxart_set_ios()
524 writel(BUS_WIDTH_4, host->base + REG_BUS_WIDTH); in moxart_set_ios()
527 writel(BUS_WIDTH_1, host->base + REG_BUS_WIDTH); in moxart_set_ios()
531 spin_unlock_irqrestore(&host->lock, flags); in moxart_set_ios()
535 static int moxart_get_ro(struct mmc_host *mmc) in moxart_get_ro() argument
537 struct moxart_host *host = mmc_priv(mmc); in moxart_get_ro()
539 return !!(readl(host->base + REG_STATUS) & WRITE_PROT); in moxart_get_ro()
550 struct device *dev = &pdev->dev; in moxart_probe()
551 struct device_node *node = dev->of_node; in moxart_probe()
553 struct mmc_host *mmc; in moxart_probe() local
561 mmc = devm_mmc_alloc_host(dev, sizeof(*host)); in moxart_probe()
562 if (!mmc) { in moxart_probe()
564 return -ENOMEM; in moxart_probe()
574 return dev_err_probe(dev, -EINVAL, in moxart_probe()
585 ret = mmc_of_parse(mmc); in moxart_probe()
589 host = mmc_priv(mmc); in moxart_probe()
590 host->mmc = mmc; in moxart_probe()
591 host->base = reg_mmc; in moxart_probe()
592 host->reg_phys = res_mmc.start; in moxart_probe()
593 host->timeout = msecs_to_jiffies(1000); in moxart_probe()
594 host->sysclk = clk_get_rate(clk); in moxart_probe()
595 host->fifo_width = readl(host->base + REG_FEATURE) << 2; in moxart_probe()
596 host->dma_chan_tx = dma_request_chan(dev, "tx"); in moxart_probe()
597 host->dma_chan_rx = dma_request_chan(dev, "rx"); in moxart_probe()
599 spin_lock_init(&host->lock); in moxart_probe()
601 mmc->ops = &moxart_ops; in moxart_probe()
602 mmc->f_max = DIV_ROUND_CLOSEST(host->sysclk, 2); in moxart_probe()
603 mmc->f_min = DIV_ROUND_CLOSEST(host->sysclk, CLK_DIV_MASK * 2); in moxart_probe()
604 mmc->ocr_avail = 0xffff00; /* Support 2.0v - 3.6v power. */ in moxart_probe()
605 mmc->max_blk_size = 2048; /* Max. block length in REG_DATA_CONTROL */ in moxart_probe()
606 mmc->max_req_size = DATA_LEN_MASK; /* bits 0-23 in REG_DATA_LENGTH */ in moxart_probe()
607 mmc->max_blk_count = mmc->max_req_size / 512; in moxart_probe()
609 if (IS_ERR(host->dma_chan_tx) || IS_ERR(host->dma_chan_rx)) { in moxart_probe()
610 if (PTR_ERR(host->dma_chan_tx) == -EPROBE_DEFER || in moxart_probe()
611 PTR_ERR(host->dma_chan_rx) == -EPROBE_DEFER) { in moxart_probe()
612 ret = -EPROBE_DEFER; in moxart_probe()
615 if (!IS_ERR(host->dma_chan_tx)) { in moxart_probe()
616 dma_release_channel(host->dma_chan_tx); in moxart_probe()
617 host->dma_chan_tx = NULL; in moxart_probe()
619 if (!IS_ERR(host->dma_chan_rx)) { in moxart_probe()
620 dma_release_channel(host->dma_chan_rx); in moxart_probe()
621 host->dma_chan_rx = NULL; in moxart_probe()
624 host->have_dma = false; in moxart_probe()
626 mmc->max_seg_size = mmc->max_req_size; in moxart_probe()
629 host->dma_chan_tx, host->dma_chan_rx); in moxart_probe()
630 host->have_dma = true; in moxart_probe()
638 cfg.dst_addr = host->reg_phys + REG_DATA_WINDOW; in moxart_probe()
639 dmaengine_slave_config(host->dma_chan_tx, &cfg); in moxart_probe()
642 cfg.src_addr = host->reg_phys + REG_DATA_WINDOW; in moxart_probe()
644 dmaengine_slave_config(host->dma_chan_rx, &cfg); in moxart_probe()
646 mmc->max_seg_size = min3(mmc->max_req_size, in moxart_probe()
647 dma_get_max_seg_size(host->dma_chan_rx->device->dev), in moxart_probe()
648 dma_get_max_seg_size(host->dma_chan_tx->device->dev)); in moxart_probe()
651 if (readl(host->base + REG_BUS_WIDTH) & BUS_WIDTH_4_SUPPORT) in moxart_probe()
652 mmc->caps |= MMC_CAP_4_BIT_DATA; in moxart_probe()
654 writel(0, host->base + REG_INTERRUPT_MASK); in moxart_probe()
656 writel(CMD_SDC_RESET, host->base + REG_COMMAND); in moxart_probe()
658 if (!(readl(host->base + REG_COMMAND) & CMD_SDC_RESET)) in moxart_probe()
663 ret = devm_request_irq(dev, irq, moxart_irq, 0, "moxart-mmc", host); in moxart_probe()
667 dev_set_drvdata(dev, mmc); in moxart_probe()
668 ret = mmc_add_host(mmc); in moxart_probe()
672 dev_dbg(dev, "IRQ=%d, FIFO is %d bytes\n", irq, host->fifo_width); in moxart_probe()
677 if (!IS_ERR_OR_NULL(host->dma_chan_tx)) in moxart_probe()
678 dma_release_channel(host->dma_chan_tx); in moxart_probe()
679 if (!IS_ERR_OR_NULL(host->dma_chan_rx)) in moxart_probe()
680 dma_release_channel(host->dma_chan_rx); in moxart_probe()
686 struct mmc_host *mmc = dev_get_drvdata(&pdev->dev); in moxart_remove() local
687 struct moxart_host *host = mmc_priv(mmc); in moxart_remove()
689 if (!IS_ERR_OR_NULL(host->dma_chan_tx)) in moxart_remove()
690 dma_release_channel(host->dma_chan_tx); in moxart_remove()
691 if (!IS_ERR_OR_NULL(host->dma_chan_rx)) in moxart_remove()
692 dma_release_channel(host->dma_chan_rx); in moxart_remove()
693 mmc_remove_host(mmc); in moxart_remove()
695 writel(0, host->base + REG_INTERRUPT_MASK); in moxart_remove()
696 writel(0, host->base + REG_POWER_CONTROL); in moxart_remove()
697 writel(readl(host->base + REG_CLOCK_CONTROL) | CLK_OFF, in moxart_remove()
698 host->base + REG_CLOCK_CONTROL); in moxart_remove()
702 { .compatible = "moxa,moxart-mmc" },
712 .name = "mmc-moxart",
719 MODULE_ALIAS("platform:mmc-moxart");
720 MODULE_DESCRIPTION("MOXA ART MMC driver");