Lines Matching +full:no +full:- +full:mmc

1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2018 Oleksij Rempel <linux@rempel-privat.de>
10 * As soon as some one with documentation or more experience in SD/MMC, or
12 * thing what I did. 2018 Oleksij Rempel <linux@rempel-privat.de>
24 #include <linux/mmc/host.h>
25 #include <linux/mmc/mmc.h>
75 struct alcor_pci_priv *priv = host->alcor_pci; in alcor_rmw8()
89 struct alcor_pci_priv *priv = host->alcor_pci; in alcor_mask_sd_irqs()
96 struct alcor_pci_priv *priv = host->alcor_pci; in alcor_unmask_sd_irqs()
106 struct alcor_pci_priv *priv = host->alcor_pci; in alcor_reset()
116 dev_err(host->dev, "%s: timeout\n", __func__); in alcor_reset()
124 struct alcor_pci_priv *priv = host->alcor_pci; in alcor_data_set_dma()
127 if (!host->sg_count) in alcor_data_set_dma()
130 if (!host->sg) { in alcor_data_set_dma()
131 dev_err(host->dev, "have blocks, but no SG\n"); in alcor_data_set_dma()
135 if (!sg_dma_len(host->sg)) { in alcor_data_set_dma()
136 dev_err(host->dev, "DMA SG len == 0\n"); in alcor_data_set_dma()
141 addr = (u32)sg_dma_address(host->sg); in alcor_data_set_dma()
144 host->sg = sg_next(host->sg); in alcor_data_set_dma()
145 host->sg_count--; in alcor_data_set_dma()
150 struct alcor_pci_priv *priv = host->alcor_pci; in alcor_trigger_data_transfer()
151 struct mmc_data *data = host->data; in alcor_trigger_data_transfer()
154 if (data->flags & MMC_DATA_WRITE) in alcor_trigger_data_transfer()
157 if (data->host_cookie == COOKIE_MAPPED) { in alcor_trigger_data_transfer()
164 * indicating that the single-page DMA was completed. in alcor_trigger_data_transfer()
168 host->dma_on = 1; in alcor_trigger_data_transfer()
169 alcor_write32(priv, data->sg_count * 0x1000, in alcor_trigger_data_transfer()
174 * into several sector-sized transfers. When one sector has in alcor_trigger_data_transfer()
178 alcor_write32(priv, data->blksz, AU6601_REG_BLOCK_SIZE); in alcor_trigger_data_transfer()
187 struct alcor_pci_priv *priv = host->alcor_pci; in alcor_trf_block_pio()
191 if (!host->blocks) in alcor_trf_block_pio()
194 if (host->dma_on) { in alcor_trf_block_pio()
195 dev_err(host->dev, "configured DMA but got PIO request.\n"); in alcor_trf_block_pio()
199 if (!!(host->data->flags & MMC_DATA_READ) != read) { in alcor_trf_block_pio()
200 dev_err(host->dev, "got unexpected direction %i != %i\n", in alcor_trf_block_pio()
201 !!(host->data->flags & MMC_DATA_READ), read); in alcor_trf_block_pio()
204 if (!sg_miter_next(&host->sg_miter)) in alcor_trf_block_pio()
207 blksize = host->data->blksz; in alcor_trf_block_pio()
208 len = min(host->sg_miter.length, blksize); in alcor_trf_block_pio()
210 dev_dbg(host->dev, "PIO, %s block size: 0x%zx\n", in alcor_trf_block_pio()
213 host->sg_miter.consumed = len; in alcor_trf_block_pio()
214 host->blocks--; in alcor_trf_block_pio()
216 buf = host->sg_miter.addr; in alcor_trf_block_pio()
219 ioread32_rep(priv->iobase + AU6601_REG_BUFFER, buf, len >> 2); in alcor_trf_block_pio()
221 iowrite32_rep(priv->iobase + AU6601_REG_BUFFER, buf, len >> 2); in alcor_trf_block_pio()
223 sg_miter_stop(&host->sg_miter); in alcor_trf_block_pio()
229 struct mmc_data *data = host->data; in alcor_prepare_sg_miter()
231 if (data->flags & MMC_DATA_READ) in alcor_prepare_sg_miter()
235 sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags); in alcor_prepare_sg_miter()
241 struct alcor_pci_priv *priv = host->alcor_pci; in alcor_prepare_data()
242 struct mmc_data *data = cmd->data; in alcor_prepare_data()
248 host->data = data; in alcor_prepare_data()
249 host->data->bytes_xfered = 0; in alcor_prepare_data()
250 host->blocks = data->blocks; in alcor_prepare_data()
251 host->sg = data->sg; in alcor_prepare_data()
252 host->sg_count = data->sg_count; in alcor_prepare_data()
253 dev_dbg(host->dev, "prepare DATA: sg %i, blocks: %i\n", in alcor_prepare_data()
254 host->sg_count, host->blocks); in alcor_prepare_data()
256 if (data->host_cookie != COOKIE_MAPPED) in alcor_prepare_data()
265 struct alcor_pci_priv *priv = host->alcor_pci; in alcor_send_cmd()
269 host->cmd = cmd; in alcor_send_cmd()
272 dev_dbg(host->dev, "send CMD. opcode: 0x%02x, arg; 0x%08x\n", in alcor_send_cmd()
273 cmd->opcode, cmd->arg); in alcor_send_cmd()
274 alcor_write8(priv, cmd->opcode | 0x40, AU6601_REG_CMD_OPCODE); in alcor_send_cmd()
275 alcor_write32be(priv, cmd->arg, AU6601_REG_CMD_ARG); in alcor_send_cmd()
294 dev_err(host->dev, "%s: cmd->flag (0x%02x) is not valid\n", in alcor_send_cmd()
300 if (!cmd->data && cmd->busy_timeout) in alcor_send_cmd()
301 timeout = cmd->busy_timeout; in alcor_send_cmd()
305 schedule_delayed_work(&host->timeout_work, in alcor_send_cmd()
309 dev_dbg(host->dev, "xfer ctrl: 0x%02x; timeout: %lu\n", ctrl, timeout); in alcor_send_cmd()
323 if (!host->mrq) in alcor_request_complete()
327 cancel_delayed_work(&host->timeout_work); in alcor_request_complete()
329 mrq = host->mrq; in alcor_request_complete()
331 host->mrq = NULL; in alcor_request_complete()
332 host->cmd = NULL; in alcor_request_complete()
333 host->data = NULL; in alcor_request_complete()
334 host->dma_on = 0; in alcor_request_complete()
343 data = host->data; in alcor_finish_data()
344 host->data = NULL; in alcor_finish_data()
345 host->dma_on = 0; in alcor_finish_data()
354 if (data->error) in alcor_finish_data()
355 data->bytes_xfered = 0; in alcor_finish_data()
357 data->bytes_xfered = data->blksz * data->blocks; in alcor_finish_data()
360 * Need to send CMD12 if - in alcor_finish_data()
361 * a) open-ended multiblock transfer (no CMD23) in alcor_finish_data()
364 if (data->stop && in alcor_finish_data()
365 (data->error || in alcor_finish_data()
366 !host->mrq->sbc)) { in alcor_finish_data()
372 if (data->error) in alcor_finish_data()
376 alcor_send_cmd(host, data->stop, false); in alcor_finish_data()
385 dev_dbg(host->dev, "ERR IRQ %x\n", intmask); in alcor_err_irq()
387 if (host->cmd) { in alcor_err_irq()
389 host->cmd->error = -ETIMEDOUT; in alcor_err_irq()
391 host->cmd->error = -EILSEQ; in alcor_err_irq()
394 if (host->data) { in alcor_err_irq()
396 host->data->error = -ETIMEDOUT; in alcor_err_irq()
398 host->data->error = -EILSEQ; in alcor_err_irq()
400 host->data->bytes_xfered = 0; in alcor_err_irq()
409 struct alcor_pci_priv *priv = host->alcor_pci; in alcor_cmd_irq_done()
416 /* got CMD_END but no CMD is in progress, wake thread an process the in alcor_cmd_irq_done()
419 if (!host->cmd) in alcor_cmd_irq_done()
422 if (host->cmd->flags & MMC_RSP_PRESENT) { in alcor_cmd_irq_done()
423 struct mmc_command *cmd = host->cmd; in alcor_cmd_irq_done()
425 cmd->resp[0] = alcor_read32be(priv, AU6601_REG_CMD_RSP0); in alcor_cmd_irq_done()
426 dev_dbg(host->dev, "RSP0: 0x%04x\n", cmd->resp[0]); in alcor_cmd_irq_done()
427 if (host->cmd->flags & MMC_RSP_136) { in alcor_cmd_irq_done()
428 cmd->resp[1] = in alcor_cmd_irq_done()
430 cmd->resp[2] = in alcor_cmd_irq_done()
432 cmd->resp[3] = in alcor_cmd_irq_done()
434 dev_dbg(host->dev, "RSP1,2,3: 0x%04x 0x%04x 0x%04x\n", in alcor_cmd_irq_done()
435 cmd->resp[1], cmd->resp[2], cmd->resp[3]); in alcor_cmd_irq_done()
440 host->cmd->error = 0; in alcor_cmd_irq_done()
443 if (!host->data) in alcor_cmd_irq_done()
447 host->cmd = NULL; in alcor_cmd_irq_done()
458 if (!host->cmd && intmask & AU6601_INT_CMD_END) { in alcor_cmd_irq_thread()
459 …dev_dbg(host->dev, "Got command interrupt 0x%08x even though no command operation was in progress.… in alcor_cmd_irq_thread()
464 if (!host->data) in alcor_cmd_irq_thread()
468 host->cmd = NULL; in alcor_cmd_irq_thread()
484 if (!host->data && intmask == AU6601_INT_DATA_END) in alcor_data_irq_done()
488 if (!host->data) in alcor_data_irq_done()
503 if (!host->sg_count) in alcor_data_irq_done()
509 dev_err(host->dev, "Got READ_BUF_RDY and WRITE_BUF_RDY at same time\n"); in alcor_data_irq_done()
514 if (!host->dma_on && host->blocks) { in alcor_data_irq_done()
532 if (!host->data) { in alcor_data_irq_thread()
533 dev_dbg(host->dev, "Got data interrupt 0x%08x even though no data operation was in progress.\n", in alcor_data_irq_thread()
542 if ((intmask & AU6601_INT_DATA_END) || !host->blocks || in alcor_data_irq_thread()
543 (host->dma_on && !host->sg_count)) in alcor_data_irq_thread()
549 dev_dbg(host->dev, "card %s\n", in alcor_cd_irq()
552 if (host->mrq) { in alcor_cd_irq()
553 dev_dbg(host->dev, "cancel all pending tasks.\n"); in alcor_cd_irq()
555 if (host->data) in alcor_cd_irq()
556 host->data->error = -ENOMEDIUM; in alcor_cd_irq()
558 if (host->cmd) in alcor_cd_irq()
559 host->cmd->error = -ENOMEDIUM; in alcor_cd_irq()
561 host->mrq->cmd->error = -ENOMEDIUM; in alcor_cd_irq()
575 mutex_lock(&host->cmd_mutex); in alcor_irq_thread()
577 intmask = host->irq_status_sd; in alcor_irq_thread()
581 dev_dbg(host->dev, "unexpected IRQ: 0x%04x\n", intmask); in alcor_irq_thread()
603 dev_warn(host->dev, in alcor_irq_thread()
609 dev_dbg(host->dev, "got not handled IRQ: 0x%04x\n", intmask); in alcor_irq_thread()
612 mutex_unlock(&host->cmd_mutex); in alcor_irq_thread()
621 struct alcor_pci_priv *priv = host->alcor_pci; in alcor_irq()
645 host->irq_status_sd = status; in alcor_irq()
654 struct alcor_pci_priv *priv = host->alcor_pci; in alcor_set_clock()
668 tmp_div = DIV_ROUND_UP(cfg->clk_src_freq, clock); in alcor_set_clock()
669 if (cfg->min_div > tmp_div || tmp_div > cfg->max_div) in alcor_set_clock()
672 tmp_clock = DIV_ROUND_UP(cfg->clk_src_freq, tmp_div); in alcor_set_clock()
673 tmp_diff = abs(clock - tmp_clock); in alcor_set_clock()
677 clk_src = cfg->clk_src_reg; in alcor_set_clock()
682 clk_src |= ((clk_div - 1) << 8); in alcor_set_clock()
685 dev_dbg(host->dev, "set freq %d cal freq %d, use div %d, mod %x\n", in alcor_set_clock()
692 static void alcor_set_timing(struct mmc_host *mmc, struct mmc_ios *ios) in alcor_set_timing() argument
694 struct alcor_sdmmc_host *host = mmc_priv(mmc); in alcor_set_timing()
696 if (ios->timing == MMC_TIMING_LEGACY) { in alcor_set_timing()
705 static void alcor_set_bus_width(struct mmc_host *mmc, struct mmc_ios *ios) in alcor_set_bus_width() argument
707 struct alcor_sdmmc_host *host = mmc_priv(mmc); in alcor_set_bus_width()
708 struct alcor_pci_priv *priv = host->alcor_pci; in alcor_set_bus_width()
710 if (ios->bus_width == MMC_BUS_WIDTH_1) { in alcor_set_bus_width()
712 } else if (ios->bus_width == MMC_BUS_WIDTH_4) { in alcor_set_bus_width()
716 dev_err(host->dev, "Unknown BUS mode\n"); in alcor_set_bus_width()
720 static int alcor_card_busy(struct mmc_host *mmc) in alcor_card_busy() argument
722 struct alcor_sdmmc_host *host = mmc_priv(mmc); in alcor_card_busy()
723 struct alcor_pci_priv *priv = host->alcor_pci; in alcor_card_busy()
732 static int alcor_get_cd(struct mmc_host *mmc) in alcor_get_cd() argument
734 struct alcor_sdmmc_host *host = mmc_priv(mmc); in alcor_get_cd()
735 struct alcor_pci_priv *priv = host->alcor_pci; in alcor_get_cd()
744 static int alcor_get_ro(struct mmc_host *mmc) in alcor_get_ro() argument
746 struct alcor_sdmmc_host *host = mmc_priv(mmc); in alcor_get_ro()
747 struct alcor_pci_priv *priv = host->alcor_pci; in alcor_get_ro()
756 static void alcor_request(struct mmc_host *mmc, struct mmc_request *mrq) in alcor_request() argument
758 struct alcor_sdmmc_host *host = mmc_priv(mmc); in alcor_request()
760 mutex_lock(&host->cmd_mutex); in alcor_request()
762 host->mrq = mrq; in alcor_request()
765 if (alcor_get_cd(mmc)) in alcor_request()
766 alcor_send_cmd(host, mrq->cmd, true); in alcor_request()
768 mrq->cmd->error = -ENOMEDIUM; in alcor_request()
772 mutex_unlock(&host->cmd_mutex); in alcor_request()
775 static void alcor_pre_req(struct mmc_host *mmc, in alcor_pre_req() argument
778 struct alcor_sdmmc_host *host = mmc_priv(mmc); in alcor_pre_req()
779 struct mmc_data *data = mrq->data; in alcor_pre_req()
780 struct mmc_command *cmd = mrq->cmd; in alcor_pre_req()
787 data->host_cookie = COOKIE_UNMAPPED; in alcor_pre_req()
790 if (cmd->opcode != MMC_READ_MULTIPLE_BLOCK in alcor_pre_req()
791 && cmd->opcode != MMC_WRITE_MULTIPLE_BLOCK) in alcor_pre_req()
795 * non-word-aligned buffers or lengths. A future improvement in alcor_pre_req()
796 * could be made to use temporary DMA bounce-buffers when these in alcor_pre_req()
802 if (data->blocks * data->blksz < AU6601_MAX_DMA_BLOCK_SIZE) in alcor_pre_req()
805 if (data->blksz & 3) in alcor_pre_req()
808 for_each_sg(data->sg, sg, data->sg_len, i) { in alcor_pre_req()
809 if (sg->length != AU6601_MAX_DMA_BLOCK_SIZE) in alcor_pre_req()
811 if (sg->offset != 0) in alcor_pre_req()
817 sg_len = dma_map_sg(host->dev, data->sg, data->sg_len, in alcor_pre_req()
820 data->host_cookie = COOKIE_MAPPED; in alcor_pre_req()
822 data->sg_count = sg_len; in alcor_pre_req()
825 static void alcor_post_req(struct mmc_host *mmc, in alcor_post_req() argument
829 struct alcor_sdmmc_host *host = mmc_priv(mmc); in alcor_post_req()
830 struct mmc_data *data = mrq->data; in alcor_post_req()
835 if (data->host_cookie == COOKIE_MAPPED) { in alcor_post_req()
836 dma_unmap_sg(host->dev, in alcor_post_req()
837 data->sg, in alcor_post_req()
838 data->sg_len, in alcor_post_req()
842 data->host_cookie = COOKIE_UNMAPPED; in alcor_post_req()
845 static void alcor_set_power_mode(struct mmc_host *mmc, struct mmc_ios *ios) in alcor_set_power_mode() argument
847 struct alcor_sdmmc_host *host = mmc_priv(mmc); in alcor_set_power_mode()
848 struct alcor_pci_priv *priv = host->alcor_pci; in alcor_set_power_mode()
850 switch (ios->power_mode) { in alcor_set_power_mode()
852 alcor_set_clock(host, ios->clock); in alcor_set_power_mode()
873 /* no documentation about clk delay, for now just try to mimic in alcor_set_power_mode()
880 alcor_set_clock(host, ios->clock); in alcor_set_power_mode()
887 alcor_set_clock(host, ios->clock); in alcor_set_power_mode()
902 dev_err(host->dev, "Unknown power parameter\n"); in alcor_set_power_mode()
906 static void alcor_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) in alcor_set_ios() argument
908 struct alcor_sdmmc_host *host = mmc_priv(mmc); in alcor_set_ios()
910 mutex_lock(&host->cmd_mutex); in alcor_set_ios()
912 dev_dbg(host->dev, "set ios. bus width: %x, power mode: %x\n", in alcor_set_ios()
913 ios->bus_width, ios->power_mode); in alcor_set_ios()
915 if (ios->power_mode != host->cur_power_mode) { in alcor_set_ios()
916 alcor_set_power_mode(mmc, ios); in alcor_set_ios()
917 host->cur_power_mode = ios->power_mode; in alcor_set_ios()
919 alcor_set_timing(mmc, ios); in alcor_set_ios()
920 alcor_set_bus_width(mmc, ios); in alcor_set_ios()
921 alcor_set_clock(host, ios->clock); in alcor_set_ios()
924 mutex_unlock(&host->cmd_mutex); in alcor_set_ios()
927 static int alcor_signal_voltage_switch(struct mmc_host *mmc, in alcor_signal_voltage_switch() argument
930 struct alcor_sdmmc_host *host = mmc_priv(mmc); in alcor_signal_voltage_switch()
932 mutex_lock(&host->cmd_mutex); in alcor_signal_voltage_switch()
934 switch (ios->signal_voltage) { in alcor_signal_voltage_switch()
942 /* No signal voltage switch required */ in alcor_signal_voltage_switch()
946 mutex_unlock(&host->cmd_mutex); in alcor_signal_voltage_switch()
966 mutex_lock(&host->cmd_mutex); in alcor_timeout_timer()
968 dev_dbg(host->dev, "triggered timeout\n"); in alcor_timeout_timer()
969 if (host->mrq) { in alcor_timeout_timer()
970 dev_err(host->dev, "Timeout waiting for hardware interrupt.\n"); in alcor_timeout_timer()
972 if (host->data) { in alcor_timeout_timer()
973 host->data->error = -ETIMEDOUT; in alcor_timeout_timer()
975 if (host->cmd) in alcor_timeout_timer()
976 host->cmd->error = -ETIMEDOUT; in alcor_timeout_timer()
978 host->mrq->cmd->error = -ETIMEDOUT; in alcor_timeout_timer()
985 mutex_unlock(&host->cmd_mutex); in alcor_timeout_timer()
990 struct alcor_pci_priv *priv = host->alcor_pci; in alcor_hw_init()
991 struct alcor_dev_cfg *cfg = priv->cfg; in alcor_hw_init()
1019 /* for 6601 - dma_boundary; for 6621 - dma_page_cnt in alcor_hw_init()
1022 alcor_write8(priv, cfg->dma, AU6601_DMA_BOUNDARY); in alcor_hw_init()
1035 struct alcor_pci_priv *priv = host->alcor_pci; in alcor_hw_uninit()
1050 struct mmc_host *mmc = mmc_from_priv(host); in alcor_init_mmc() local
1052 mmc->f_min = AU6601_MIN_CLOCK; in alcor_init_mmc()
1053 mmc->f_max = AU6601_MAX_CLOCK; in alcor_init_mmc()
1054 mmc->ocr_avail = MMC_VDD_33_34; in alcor_init_mmc()
1055 mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SD_HIGHSPEED in alcor_init_mmc()
1058 mmc->caps2 = MMC_CAP2_NO_SDIO; in alcor_init_mmc()
1059 mmc->ops = &alcor_sdc_ops; in alcor_init_mmc()
1072 mmc->max_segs = AU6601_MAX_DMA_SEGMENTS; in alcor_init_mmc()
1073 mmc->max_seg_size = AU6601_MAX_DMA_BLOCK_SIZE; in alcor_init_mmc()
1074 mmc->max_blk_count = 240; in alcor_init_mmc()
1075 mmc->max_req_size = mmc->max_blk_count * mmc->max_blk_size; in alcor_init_mmc()
1076 dma_set_max_seg_size(host->dev, mmc->max_seg_size); in alcor_init_mmc()
1081 struct alcor_pci_priv *priv = pdev->dev.platform_data; in alcor_pci_sdmmc_drv_probe()
1082 struct mmc_host *mmc; in alcor_pci_sdmmc_drv_probe() local
1086 mmc = mmc_alloc_host(sizeof(*host), &pdev->dev); in alcor_pci_sdmmc_drv_probe()
1087 if (!mmc) { in alcor_pci_sdmmc_drv_probe()
1088 dev_err(&pdev->dev, "Can't allocate MMC\n"); in alcor_pci_sdmmc_drv_probe()
1089 return -ENOMEM; in alcor_pci_sdmmc_drv_probe()
1092 host = mmc_priv(mmc); in alcor_pci_sdmmc_drv_probe()
1093 host->dev = &pdev->dev; in alcor_pci_sdmmc_drv_probe()
1094 host->cur_power_mode = MMC_POWER_UNDEFINED; in alcor_pci_sdmmc_drv_probe()
1095 host->alcor_pci = priv; in alcor_pci_sdmmc_drv_probe()
1101 ret = devm_request_threaded_irq(&pdev->dev, priv->irq, in alcor_pci_sdmmc_drv_probe()
1106 dev_err(&pdev->dev, "Failed to get irq for data line\n"); in alcor_pci_sdmmc_drv_probe()
1110 mutex_init(&host->cmd_mutex); in alcor_pci_sdmmc_drv_probe()
1111 INIT_DELAYED_WORK(&host->timeout_work, alcor_timeout_timer); in alcor_pci_sdmmc_drv_probe()
1116 dev_set_drvdata(&pdev->dev, host); in alcor_pci_sdmmc_drv_probe()
1117 ret = mmc_add_host(mmc); in alcor_pci_sdmmc_drv_probe()
1124 mmc_free_host(mmc); in alcor_pci_sdmmc_drv_probe()
1130 struct alcor_sdmmc_host *host = dev_get_drvdata(&pdev->dev); in alcor_pci_sdmmc_drv_remove()
1131 struct mmc_host *mmc = mmc_from_priv(host); in alcor_pci_sdmmc_drv_remove() local
1133 if (cancel_delayed_work_sync(&host->timeout_work)) in alcor_pci_sdmmc_drv_remove()
1137 mmc_remove_host(mmc); in alcor_pci_sdmmc_drv_remove()
1138 mmc_free_host(mmc); in alcor_pci_sdmmc_drv_remove()
1146 if (cancel_delayed_work_sync(&host->timeout_work)) in alcor_pci_sdmmc_suspend()
1188 MODULE_AUTHOR("Oleksij Rempel <linux@rempel-privat.de>");