Lines Matching +full:orion +full:- +full:sdio

1 // SPDX-License-Identifier: GPL-2.0-only
3 * Marvell MMC/SD/SDIO driver
6 * Copyright (C) 2008-2009 Marvell Ltd.
16 #include <linux/dma-mapping.h>
22 #include <linux/mmc/slot-gpio.h>
58 void __iomem *iobase = host->base; in mvsd_setup_data()
77 dev_warn(host->dev, "FIFO_EMPTY bit missing\n"); in mvsd_setup_data()
82 dev_dbg(host->dev, "*** wait for FIFO_EMPTY bit " in mvsd_setup_data()
84 hw_state, count, jiffies - (t - HZ)); in mvsd_setup_data()
88 tmout = DIV_ROUND_UP(data->timeout_ns, host->ns_per_clk); in mvsd_setup_data()
89 tmout += data->timeout_clks; in mvsd_setup_data()
90 tmout_index = fls(tmout - 1) - 12; in mvsd_setup_data()
96 dev_dbg(host->dev, "data %s at 0x%08x: blocks=%d blksz=%d tmout=%u (%d)\n", in mvsd_setup_data()
97 (data->flags & MMC_DATA_READ) ? "read" : "write", in mvsd_setup_data()
98 (u32)sg_virt(data->sg), data->blocks, data->blksz, in mvsd_setup_data()
101 host->ctrl &= ~MVSD_HOST_CTRL_TMOUT_MASK; in mvsd_setup_data()
102 host->ctrl |= MVSD_HOST_CTRL_TMOUT(tmout_index); in mvsd_setup_data()
103 mvsd_write(MVSD_HOST_CTRL, host->ctrl); in mvsd_setup_data()
104 mvsd_write(MVSD_BLK_COUNT, data->blocks); in mvsd_setup_data()
105 mvsd_write(MVSD_BLK_SIZE, data->blksz); in mvsd_setup_data()
107 if (nodma || (data->blksz | data->sg->offset) & 3 || in mvsd_setup_data()
108 ((!(data->flags & MMC_DATA_READ) && data->sg->offset & 0x3f))) { in mvsd_setup_data()
111 * is not aligned on a 4-byte boundary. in mvsd_setup_data()
117 host->pio_size = data->blocks * data->blksz; in mvsd_setup_data()
118 host->pio_ptr = sg_virt(data->sg); in mvsd_setup_data()
120 dev_dbg(host->dev, "fallback to PIO for data at 0x%p size %d\n", in mvsd_setup_data()
121 host->pio_ptr, host->pio_size); in mvsd_setup_data()
126 host->sg_frags = dma_map_sg(mmc_dev(host->mmc), in mvsd_setup_data()
127 data->sg, data->sg_len, in mvsd_setup_data()
129 phys_addr = sg_dma_address(data->sg); in mvsd_setup_data()
139 void __iomem *iobase = host->base; in mvsd_request()
140 struct mmc_command *cmd = mrq->cmd; in mvsd_request()
145 BUG_ON(host->mrq != NULL); in mvsd_request()
146 host->mrq = mrq; in mvsd_request()
148 dev_dbg(host->dev, "cmd %d (hw state 0x%04x)\n", in mvsd_request()
149 cmd->opcode, mvsd_read(MVSD_HW_STATE)); in mvsd_request()
151 cmdreg = MVSD_CMD_INDEX(cmd->opcode); in mvsd_request()
153 if (cmd->flags & MMC_RSP_BUSY) in mvsd_request()
155 else if (cmd->flags & MMC_RSP_136) in mvsd_request()
157 else if (cmd->flags & MMC_RSP_PRESENT) in mvsd_request()
162 if (cmd->flags & MMC_RSP_CRC) in mvsd_request()
165 if (cmd->flags & MMC_RSP_OPCODE) in mvsd_request()
168 if (cmd->flags & MMC_RSP_PRESENT) { in mvsd_request()
173 if (mrq->data) { in mvsd_request()
174 struct mmc_data *data = mrq->data; in mvsd_request()
179 if (data->flags & MMC_DATA_READ) in mvsd_request()
186 if (data->flags & MMC_DATA_WRITE) in mvsd_request()
188 else if (host->pio_size > 32) in mvsd_request()
194 if (data->stop) { in mvsd_request()
195 struct mmc_command *stop = data->stop; in mvsd_request()
198 mvsd_write(MVSD_AUTOCMD12_ARG_LOW, stop->arg & 0xffff); in mvsd_request()
199 mvsd_write(MVSD_AUTOCMD12_ARG_HI, stop->arg >> 16); in mvsd_request()
201 if (stop->flags & MMC_RSP_BUSY) in mvsd_request()
203 if (stop->flags & MMC_RSP_OPCODE) in mvsd_request()
205 cmd12reg |= MVSD_AUTOCMD12_INDEX(stop->opcode); in mvsd_request()
217 mvsd_write(MVSD_ARG_LOW, cmd->arg & 0xffff); in mvsd_request()
218 mvsd_write(MVSD_ARG_HI, cmd->arg >> 16); in mvsd_request()
220 spin_lock_irqsave(&host->lock, flags); in mvsd_request()
222 host->xfer_mode &= MVSD_XFER_MODE_INT_CHK_EN; in mvsd_request()
223 host->xfer_mode |= xfer; in mvsd_request()
224 mvsd_write(MVSD_XFER_MODE, host->xfer_mode); in mvsd_request()
230 host->intr_en &= MVSD_NOR_CARD_INT; in mvsd_request()
231 host->intr_en |= intr | MVSD_NOR_ERROR; in mvsd_request()
232 mvsd_write(MVSD_NOR_INTR_EN, host->intr_en); in mvsd_request()
235 timeout = cmd->busy_timeout ? cmd->busy_timeout : 5000; in mvsd_request()
236 mod_timer(&host->timer, jiffies + msecs_to_jiffies(timeout)); in mvsd_request()
238 spin_unlock_irqrestore(&host->lock, flags); in mvsd_request()
244 void __iomem *iobase = host->base; in mvsd_finish_cmd()
246 if (cmd->flags & MMC_RSP_136) { in mvsd_finish_cmd()
250 cmd->resp[0] = ((response[0] & 0x03ff) << 22) | in mvsd_finish_cmd()
253 cmd->resp[1] = ((response[2] & 0x03ff) << 22) | in mvsd_finish_cmd()
256 cmd->resp[2] = ((response[4] & 0x03ff) << 22) | in mvsd_finish_cmd()
259 cmd->resp[3] = ((response[6] & 0x03ff) << 22) | in mvsd_finish_cmd()
261 } else if (cmd->flags & MMC_RSP_PRESENT) { in mvsd_finish_cmd()
265 cmd->resp[0] = ((response[2] & 0x003f) << (8 - 8)) | in mvsd_finish_cmd()
266 ((response[1] & 0xffff) << (14 - 8)) | in mvsd_finish_cmd()
267 ((response[0] & 0x03ff) << (30 - 8)); in mvsd_finish_cmd()
268 cmd->resp[1] = ((response[0] & 0xfc00) >> 10); in mvsd_finish_cmd()
269 cmd->resp[2] = 0; in mvsd_finish_cmd()
270 cmd->resp[3] = 0; in mvsd_finish_cmd()
274 cmd->error = -ETIMEDOUT; in mvsd_finish_cmd()
277 cmd->error = -EILSEQ; in mvsd_finish_cmd()
289 void __iomem *iobase = host->base; in mvsd_finish_data()
291 if (host->pio_ptr) { in mvsd_finish_data()
292 host->pio_ptr = NULL; in mvsd_finish_data()
293 host->pio_size = 0; in mvsd_finish_data()
295 dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->sg_frags, in mvsd_finish_data()
300 data->error = -ETIMEDOUT; in mvsd_finish_data()
302 data->error = -EILSEQ; in mvsd_finish_data()
304 data->error = -EBADE; in mvsd_finish_data()
308 dev_dbg(host->dev, "data done: blocks_left=%d, bytes_left=%d\n", in mvsd_finish_data()
310 data->bytes_xfered = in mvsd_finish_data()
311 (data->blocks - mvsd_read(MVSD_CURR_BLK_LEFT)) * data->blksz; in mvsd_finish_data()
313 if (data->bytes_xfered && data->error) in mvsd_finish_data()
314 data->bytes_xfered -= data->blksz; in mvsd_finish_data()
317 if (data->stop) { in mvsd_finish_data()
321 data->stop->resp[0] = ((response[2] & 0x003f) << (8 - 8)) | in mvsd_finish_data()
322 ((response[1] & 0xffff) << (14 - 8)) | in mvsd_finish_data()
323 ((response[0] & 0x03ff) << (30 - 8)); in mvsd_finish_data()
324 data->stop->resp[1] = ((response[0] & 0xfc00) >> 10); in mvsd_finish_data()
325 data->stop->resp[2] = 0; in mvsd_finish_data()
326 data->stop->resp[3] = 0; in mvsd_finish_data()
330 dev_dbg(host->dev, "c12err 0x%04x\n", err_cmd12); in mvsd_finish_data()
332 data->stop->error = -ENOEXEC; in mvsd_finish_data()
334 data->stop->error = -ETIMEDOUT; in mvsd_finish_data()
336 data->stop->error = -EILSEQ; in mvsd_finish_data()
347 void __iomem *iobase = host->base; in mvsd_irq()
352 dev_dbg(host->dev, "intr 0x%04x intr_en 0x%04x hw_state 0x%04x\n", in mvsd_irq()
357 * It looks like, SDIO IP can issue one late, spurious irq in mvsd_irq()
362 …dev_dbg(host->dev, "spurious irq detected intr 0x%04x intr_en 0x%04x erri 0x%04x erri_en 0x%04x\n", in mvsd_irq()
370 spin_lock(&host->lock); in mvsd_irq()
373 if (host->pio_size && in mvsd_irq()
374 (intr_status & host->intr_en & in mvsd_irq()
376 u16 *p = host->pio_ptr; in mvsd_irq()
377 int s = host->pio_size; in mvsd_irq()
381 s -= 32; in mvsd_irq()
393 s -= 4; in mvsd_irq()
400 memcpy(p, ((void *)&val) + 4 - s, s); in mvsd_irq()
405 host->intr_en &= in mvsd_irq()
407 mvsd_write(MVSD_NOR_INTR_EN, host->intr_en); in mvsd_irq()
408 } else if (host->intr_en & MVSD_NOR_RX_FIFO_8W) { in mvsd_irq()
409 host->intr_en &= ~MVSD_NOR_RX_FIFO_8W; in mvsd_irq()
410 host->intr_en |= MVSD_NOR_RX_READY; in mvsd_irq()
411 mvsd_write(MVSD_NOR_INTR_EN, host->intr_en); in mvsd_irq()
414 dev_dbg(host->dev, "pio %d intr 0x%04x hw_state 0x%04x\n", in mvsd_irq()
416 host->pio_ptr = p; in mvsd_irq()
417 host->pio_size = s; in mvsd_irq()
419 } else if (host->pio_size && in mvsd_irq()
420 (intr_status & host->intr_en & in mvsd_irq()
422 u16 *p = host->pio_ptr; in mvsd_irq()
423 int s = host->pio_size; in mvsd_irq()
433 s -= 4; in mvsd_irq()
439 memcpy(((void *)&val) + 4 - s, p, s); in mvsd_irq()
446 host->intr_en &= in mvsd_irq()
448 mvsd_write(MVSD_NOR_INTR_EN, host->intr_en); in mvsd_irq()
451 dev_dbg(host->dev, "pio %d intr 0x%04x hw_state 0x%04x\n", in mvsd_irq()
453 host->pio_ptr = p; in mvsd_irq()
454 host->pio_size = s; in mvsd_irq()
462 if (intr_status & host->intr_en & ~intr_done_mask) { in mvsd_irq()
463 struct mmc_request *mrq = host->mrq; in mvsd_irq()
464 struct mmc_command *cmd = mrq->cmd; in mvsd_irq()
467 del_timer(&host->timer); in mvsd_irq()
468 host->mrq = NULL; in mvsd_irq()
470 host->intr_en &= MVSD_NOR_CARD_INT; in mvsd_irq()
471 mvsd_write(MVSD_NOR_INTR_EN, host->intr_en); in mvsd_irq()
474 spin_unlock(&host->lock); in mvsd_irq()
477 cmd->error = -EPROTO; in mvsd_irq()
480 dev_dbg(host->dev, "err 0x%04x\n", err_status); in mvsd_irq()
484 if (mrq->data) in mvsd_irq()
485 err_status = mvsd_finish_data(host, mrq->data, err_status); in mvsd_irq()
487 dev_err(host->dev, "unhandled error status %#04x\n", in mvsd_irq()
489 cmd->error = -ENOMSG; in mvsd_irq()
492 mmc_request_done(host->mmc, mrq); in mvsd_irq()
495 spin_unlock(&host->lock); in mvsd_irq()
498 mmc_signal_sdio_irq(host->mmc); in mvsd_irq()
505 dev_err(host->dev, "unhandled interrupt status=0x%04x en=0x%04x pio=%d\n", in mvsd_irq()
506 intr_status, host->intr_en, host->pio_size); in mvsd_irq()
513 void __iomem *iobase = host->base; in mvsd_timeout_timer()
517 spin_lock_irqsave(&host->lock, flags); in mvsd_timeout_timer()
518 mrq = host->mrq; in mvsd_timeout_timer()
520 dev_err(host->dev, "Timeout waiting for hardware interrupt.\n"); in mvsd_timeout_timer()
521 dev_err(host->dev, "hw_state=0x%04x, intr_status=0x%04x intr_en=0x%04x\n", in mvsd_timeout_timer()
526 host->mrq = NULL; in mvsd_timeout_timer()
530 host->xfer_mode &= MVSD_XFER_MODE_INT_CHK_EN; in mvsd_timeout_timer()
531 mvsd_write(MVSD_XFER_MODE, host->xfer_mode); in mvsd_timeout_timer()
533 host->intr_en &= MVSD_NOR_CARD_INT; in mvsd_timeout_timer()
534 mvsd_write(MVSD_NOR_INTR_EN, host->intr_en); in mvsd_timeout_timer()
538 mrq->cmd->error = -ETIMEDOUT; in mvsd_timeout_timer()
539 mvsd_finish_cmd(host, mrq->cmd, 0); in mvsd_timeout_timer()
540 if (mrq->data) { in mvsd_timeout_timer()
541 mrq->data->error = -ETIMEDOUT; in mvsd_timeout_timer()
542 mvsd_finish_data(host, mrq->data, 0); in mvsd_timeout_timer()
545 spin_unlock_irqrestore(&host->lock, flags); in mvsd_timeout_timer()
548 mmc_request_done(host->mmc, mrq); in mvsd_timeout_timer()
554 void __iomem *iobase = host->base; in mvsd_enable_sdio_irq()
557 spin_lock_irqsave(&host->lock, flags); in mvsd_enable_sdio_irq()
559 host->xfer_mode |= MVSD_XFER_MODE_INT_CHK_EN; in mvsd_enable_sdio_irq()
560 host->intr_en |= MVSD_NOR_CARD_INT; in mvsd_enable_sdio_irq()
562 host->xfer_mode &= ~MVSD_XFER_MODE_INT_CHK_EN; in mvsd_enable_sdio_irq()
563 host->intr_en &= ~MVSD_NOR_CARD_INT; in mvsd_enable_sdio_irq()
565 mvsd_write(MVSD_XFER_MODE, host->xfer_mode); in mvsd_enable_sdio_irq()
566 mvsd_write(MVSD_NOR_INTR_EN, host->intr_en); in mvsd_enable_sdio_irq()
567 spin_unlock_irqrestore(&host->lock, flags); in mvsd_enable_sdio_irq()
572 void __iomem *iobase = host->base; in mvsd_power_up()
573 dev_dbg(host->dev, "power up\n"); in mvsd_power_up()
586 void __iomem *iobase = host->base; in mvsd_power_down()
587 dev_dbg(host->dev, "power down\n"); in mvsd_power_down()
601 void __iomem *iobase = host->base; in mvsd_set_ios()
604 if (ios->power_mode == MMC_POWER_UP) in mvsd_set_ios()
607 if (ios->clock == 0) { in mvsd_set_ios()
610 host->clock = 0; in mvsd_set_ios()
611 dev_dbg(host->dev, "clock off\n"); in mvsd_set_ios()
612 } else if (ios->clock != host->clock) { in mvsd_set_ios()
613 u32 m = DIV_ROUND_UP(host->base_clock, ios->clock) - 1; in mvsd_set_ios()
617 host->clock = ios->clock; in mvsd_set_ios()
618 host->ns_per_clk = 1000000000 / (host->base_clock / (m+1)); in mvsd_set_ios()
619 dev_dbg(host->dev, "clock=%d (%d), div=0x%04x\n", in mvsd_set_ios()
620 ios->clock, host->base_clock / (m+1), m); in mvsd_set_ios()
631 if (ios->bus_mode == MMC_BUSMODE_PUSHPULL) in mvsd_set_ios()
634 if (ios->bus_width == MMC_BUS_WIDTH_4) in mvsd_set_ios()
639 * high speed SD, SDHC and SDIO cards. Not enabling that bit in mvsd_set_ios()
645 if (ios->timing == MMC_TIMING_MMC_HS || in mvsd_set_ios()
646 ios->timing == MMC_TIMING_SD_HS) in mvsd_set_ios()
650 host->ctrl = ctrl_reg; in mvsd_set_ios()
652 dev_dbg(host->dev, "ctrl 0x%04x: %s %s %s\n", ctrl_reg, in mvsd_set_ios()
654 "push-pull" : "open-drain", in mvsd_set_ios()
656 "4bit-width" : "1bit-width", in mvsd_set_ios()
658 "high-speed" : ""); in mvsd_set_ios()
660 if (ios->power_mode == MMC_POWER_OFF) in mvsd_set_ios()
675 void __iomem *iobase = host->base; in mv_conf_mbus_windows()
683 for (i = 0; i < dram->num_cs; i++) { in mv_conf_mbus_windows()
684 const struct mbus_dram_window *cs = dram->cs + i; in mv_conf_mbus_windows()
685 writel(((cs->size - 1) & 0xffff0000) | in mv_conf_mbus_windows()
686 (cs->mbus_attr << 8) | in mv_conf_mbus_windows()
687 (dram->mbus_dram_target_id << 4) | 1, in mv_conf_mbus_windows()
689 writel(cs->base, iobase + MVSD_WINDOW_BASE(i)); in mv_conf_mbus_windows()
695 struct device_node *np = pdev->dev.of_node; in mvsd_probe()
702 dev_err(&pdev->dev, "no DT node\n"); in mvsd_probe()
703 return -ENODEV; in mvsd_probe()
709 mmc = mmc_alloc_host(sizeof(struct mvsd_host), &pdev->dev); in mvsd_probe()
711 ret = -ENOMEM; in mvsd_probe()
716 host->mmc = mmc; in mvsd_probe()
717 host->dev = &pdev->dev; in mvsd_probe()
720 * Some non-DT platforms do not pass a clock, and the clock in mvsd_probe()
723 * clock associated to the SDIO interface (it can simply be a in mvsd_probe()
726 host->clk = devm_clk_get(&pdev->dev, NULL); in mvsd_probe()
727 if (IS_ERR(host->clk)) { in mvsd_probe()
728 dev_err(&pdev->dev, "no clock associated\n"); in mvsd_probe()
729 ret = -EINVAL; in mvsd_probe()
732 clk_prepare_enable(host->clk); in mvsd_probe()
734 mmc->ops = &mvsd_ops; in mvsd_probe()
736 mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; in mvsd_probe()
738 mmc->f_min = DIV_ROUND_UP(host->base_clock, MVSD_BASE_DIV_MAX); in mvsd_probe()
739 mmc->f_max = MVSD_CLOCKRATE_MAX; in mvsd_probe()
741 mmc->max_blk_size = 2048; in mvsd_probe()
742 mmc->max_blk_count = 65535; in mvsd_probe()
744 mmc->max_segs = 1; in mvsd_probe()
745 mmc->max_seg_size = mmc->max_blk_size * mmc->max_blk_count; in mvsd_probe()
746 mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; in mvsd_probe()
748 host->base_clock = clk_get_rate(host->clk) / 2; in mvsd_probe()
753 mmc->f_max = maxfreq; in mvsd_probe()
755 spin_lock_init(&host->lock); in mvsd_probe()
757 host->base = devm_platform_ioremap_resource(pdev, 0); in mvsd_probe()
758 if (IS_ERR(host->base)) { in mvsd_probe()
759 ret = PTR_ERR(host->base); in mvsd_probe()
763 /* (Re-)program MBUS remapping windows if we are asked to. */ in mvsd_probe()
770 ret = devm_request_irq(&pdev->dev, irq, mvsd_irq, 0, DRIVER_NAME, host); in mvsd_probe()
772 dev_err(&pdev->dev, "cannot assign irq %d\n", irq); in mvsd_probe()
776 timer_setup(&host->timer, mvsd_timeout_timer, 0); in mvsd_probe()
782 if (!(mmc->caps & MMC_CAP_NEEDS_POLL)) in mvsd_probe()
783 dev_dbg(&pdev->dev, "using GPIO for card detection\n"); in mvsd_probe()
785 dev_dbg(&pdev->dev, "lacking card detect (fall back to polling)\n"); in mvsd_probe()
791 if (!IS_ERR(host->clk)) in mvsd_probe()
792 clk_disable_unprepare(host->clk); in mvsd_probe()
806 del_timer_sync(&host->timer); in mvsd_remove()
809 if (!IS_ERR(host->clk)) in mvsd_remove()
810 clk_disable_unprepare(host->clk); in mvsd_remove()
815 { .compatible = "marvell,orion-sdio" },
839 MODULE_DESCRIPTION("Marvell MMC,SD,SDIO Host Controller driver");