Lines Matching +full:sp7021 +full:- +full:mmc

1 // SPDX-License-Identifier: GPL-2.0-only
5 * Author: Li-hao Kuo <lhjeff911@gmail.com>
11 #include <linux/dma-mapping.h>
14 #include <linux/mmc/core.h>
15 #include <linux/mmc/host.h>
16 #include <linux/mmc/mmc.h>
17 #include <linux/mmc/sdio.h>
18 #include <linux/mmc/slot-gpio.h>
167 struct mmc_host *mmc; member
180 return readl_poll_timeout(host->base + SPMMC_SD_STATE_REG, state, in spmmc_wait_finish()
189 return readl_poll_timeout(host->base + SPMMC_SD_STATUS_REG, status, in spmmc_wait_sdstatus()
202 if (!(cmd->flags & MMC_RSP_PRESENT)) in spmmc_get_rsp()
204 if (cmd->flags & MMC_RSP_136) { in spmmc_get_rsp()
207 value0_3 = readl(host->base + SPMMC_SD_RSPBUF0_3_REG); in spmmc_get_rsp()
208 value4_5 = readl(host->base + SPMMC_SD_RSPBUF4_5_REG) & 0xffff; in spmmc_get_rsp()
209 cmd->resp[0] = (value0_3 << 8) | (value4_5 >> 8); in spmmc_get_rsp()
210 cmd->resp[1] = value4_5 << 24; in spmmc_get_rsp()
211 value0_3 = readl(host->base + SPMMC_SD_RSPBUF0_3_REG); in spmmc_get_rsp()
212 value4_5 = readl(host->base + SPMMC_SD_RSPBUF4_5_REG) & 0xffff; in spmmc_get_rsp()
213 cmd->resp[1] |= value0_3 >> 8; in spmmc_get_rsp()
214 cmd->resp[2] = value0_3 << 24; in spmmc_get_rsp()
215 cmd->resp[2] |= value4_5 << 8; in spmmc_get_rsp()
216 value0_3 = readl(host->base + SPMMC_SD_RSPBUF0_3_REG); in spmmc_get_rsp()
217 value4_5 = readl(host->base + SPMMC_SD_RSPBUF4_5_REG) & 0xffff; in spmmc_get_rsp()
218 cmd->resp[2] |= value0_3 >> 24; in spmmc_get_rsp()
219 cmd->resp[3] = value0_3 << 8; in spmmc_get_rsp()
220 cmd->resp[3] |= value4_5 >> 8; in spmmc_get_rsp()
224 value0_3 = readl(host->base + SPMMC_SD_RSPBUF0_3_REG); in spmmc_get_rsp()
225 value4_5 = readl(host->base + SPMMC_SD_RSPBUF4_5_REG) & 0xffff; in spmmc_get_rsp()
226 cmd->resp[0] = (value0_3 << 8) | (value4_5 >> 8); in spmmc_get_rsp()
227 cmd->resp[1] = value4_5 << 24; in spmmc_get_rsp()
234 int f_min = host->mmc->f_min; in spmmc_set_bus_clk()
235 int f_max = host->mmc->f_max; in spmmc_set_bus_clk()
236 u32 value = readl(host->base + SPMMC_SD_CONFIG0_REG); in spmmc_set_bus_clk()
243 clkdiv = (clk_get_rate(host->clk) + clk) / clk - 1; in spmmc_set_bus_clk()
248 writel(value, host->base + SPMMC_SD_CONFIG0_REG); in spmmc_set_bus_clk()
253 u32 value = readl(host->base + SPMMC_SD_CONFIG1_REG); in spmmc_set_bus_timing()
254 int clkdiv = FIELD_GET(SPMMC_CLOCK_DIVISION, readl(host->base + SPMMC_SD_CONFIG0_REG)); in spmmc_set_bus_timing()
282 writel(value, host->base + SPMMC_SD_CONFIG1_REG); in spmmc_set_bus_timing()
283 value = readl(host->base + SPMMC_SD_TIMING_CONFIG0_REG); in spmmc_set_bus_timing()
288 writel(value, host->base + SPMMC_SD_TIMING_CONFIG0_REG); in spmmc_set_bus_timing()
291 writel(value, host->base + SPMMC_SD_CONFIG1_REG); in spmmc_set_bus_timing()
294 value = readl(host->base + SPMMC_SD_CONFIG0_REG); in spmmc_set_bus_timing()
296 writel(value, host->base + SPMMC_SD_CONFIG0_REG); in spmmc_set_bus_timing()
298 value = readl(host->base + SPMMC_SD_CONFIG0_REG); in spmmc_set_bus_timing()
300 writel(value, host->base + SPMMC_SD_CONFIG0_REG); in spmmc_set_bus_timing()
306 u32 value = readl(host->base + SPMMC_SD_CONFIG0_REG); in spmmc_set_bus_width()
322 writel(value, host->base + SPMMC_SD_CONFIG0_REG); in spmmc_set_bus_width()
330 u32 value = readl(host->base + SPMMC_SD_CONFIG0_REG); in spmmc_set_sdmmc_mode()
334 writel(value, host->base + SPMMC_SD_CONFIG0_REG); in spmmc_set_sdmmc_mode()
346 value = readl(host->base + SPMMC_HW_DMA_CTRL_REG); in spmmc_sw_reset()
348 writel(value, host->base + SPMMC_HW_DMA_CTRL_REG); in spmmc_sw_reset()
350 writel(value, host->base + SPMMC_HW_DMA_CTRL_REG); in spmmc_sw_reset()
351 value = readl(host->base + SPMMC_HW_DMA_CTRL_REG); in spmmc_sw_reset()
353 writel(value, host->base + SPMMC_HW_DMA_CTRL_REG); in spmmc_sw_reset()
354 writel(0x7, host->base + SPMMC_SD_RST_REG); in spmmc_sw_reset()
355 readl_poll_timeout_atomic(host->base + SPMMC_SD_HW_STATE_REG, value, in spmmc_sw_reset()
364 value = ((cmd->opcode | 0x40) << 24) | (cmd->arg >> 8); in spmmc_prepare_cmd()
365 writel(value, host->base + SPMMC_SD_CMDBUF0_3_REG); in spmmc_prepare_cmd()
366 writeb(cmd->arg & 0xff, host->base + SPMMC_SD_CMDBUF4_REG); in spmmc_prepare_cmd()
369 value = readl(host->base + SPMMC_SD_INT_REG); in spmmc_prepare_cmd()
372 writel(value, host->base + SPMMC_SD_INT_REG); in spmmc_prepare_cmd()
374 value = readl(host->base + SPMMC_SD_CONFIG0_REG); in spmmc_prepare_cmd()
377 if (cmd->flags & MMC_RSP_PRESENT) { in spmmc_prepare_cmd()
381 writel(value, host->base + SPMMC_SD_CONFIG0_REG); in spmmc_prepare_cmd()
389 if (cmd->flags & MMC_RSP_CRC && !(cmd->flags & MMC_RSP_136)) in spmmc_prepare_cmd()
394 if (cmd->flags & MMC_RSP_136) in spmmc_prepare_cmd()
398 writel(value, host->base + SPMMC_SD_CONFIG0_REG); in spmmc_prepare_cmd()
405 writel(data->blocks - 1, host->base + SPMMC_SD_PAGE_NUM_REG); in spmmc_prepare_data()
406 writel(data->blksz - 1, host->base + SPMMC_SD_BLOCKSIZE_REG); in spmmc_prepare_data()
407 value = readl(host->base + SPMMC_SD_CONFIG0_REG); in spmmc_prepare_data()
408 if (data->flags & MMC_DATA_READ) { in spmmc_prepare_data()
413 srcdst = readl(host->base + SPMMC_CARD_MEDIATYPE_SRCDST_REG); in spmmc_prepare_data()
418 writel(srcdst, host->base + SPMMC_CARD_MEDIATYPE_SRCDST_REG); in spmmc_prepare_data()
422 srcdst = readl(host->base + SPMMC_CARD_MEDIATYPE_SRCDST_REG); in spmmc_prepare_data()
427 writel(srcdst, host->base + SPMMC_CARD_MEDIATYPE_SRCDST_REG); in spmmc_prepare_data()
431 if (host->dmapio_mode == SPMMC_DMA_MODE) { in spmmc_prepare_data()
437 count = dma_map_sg(host->mmc->parent, data->sg, data->sg_len, in spmmc_prepare_data()
440 data->error = -EINVAL; in spmmc_prepare_data()
444 for_each_sg(data->sg, sg, count, i) { in spmmc_prepare_data()
446 dma_size = sg_dma_len(sg) / data->blksz - 1; in spmmc_prepare_data()
448 writel(dma_addr, host->base + SPMMC_DMA_BASE_ADDR_REG); in spmmc_prepare_data()
449 writel(dma_size, host->base + SPMMC_SDRAM_SECTOR_0_SIZE_REG); in spmmc_prepare_data()
451 writel(dma_addr, host->base + SPMMC_SDRAM_SECTOR_1_ADDR_REG); in spmmc_prepare_data()
452 writel(dma_size, host->base + SPMMC_SDRAM_SECTOR_1_LENG_REG); in spmmc_prepare_data()
454 writel(dma_addr, host->base + SPMMC_SDRAM_SECTOR_2_ADDR_REG); in spmmc_prepare_data()
455 writel(dma_size, host->base + SPMMC_SDRAM_SECTOR_2_LENG_REG); in spmmc_prepare_data()
457 writel(dma_addr, host->base + SPMMC_SDRAM_SECTOR_3_ADDR_REG); in spmmc_prepare_data()
458 writel(dma_size, host->base + SPMMC_SDRAM_SECTOR_3_LENG_REG); in spmmc_prepare_data()
460 writel(dma_addr, host->base + SPMMC_SDRAM_SECTOR_4_ADDR_REG); in spmmc_prepare_data()
461 writel(dma_size, host->base + SPMMC_SDRAM_SECTOR_4_LENG_REG); in spmmc_prepare_data()
463 writel(dma_addr, host->base + SPMMC_SDRAM_SECTOR_5_ADDR_REG); in spmmc_prepare_data()
464 writel(dma_size, host->base + SPMMC_SDRAM_SECTOR_5_LENG_REG); in spmmc_prepare_data()
466 writel(dma_addr, host->base + SPMMC_SDRAM_SECTOR_6_ADDR_REG); in spmmc_prepare_data()
467 writel(dma_size, host->base + SPMMC_SDRAM_SECTOR_6_LENG_REG); in spmmc_prepare_data()
469 writel(dma_addr, host->base + SPMMC_SDRAM_SECTOR_7_ADDR_REG); in spmmc_prepare_data()
470 writel(dma_size, host->base + SPMMC_SDRAM_SECTOR_7_LENG_REG); in spmmc_prepare_data()
474 writel(value, host->base + SPMMC_SD_CONFIG0_REG); in spmmc_prepare_data()
476 if (data->blksz * data->blocks > host->dma_int_threshold) { in spmmc_prepare_data()
477 host->dma_use_int = 1; in spmmc_prepare_data()
478 value = readl(host->base + SPMMC_SD_INT_REG); in spmmc_prepare_data()
481 writel(value, host->base + SPMMC_SD_INT_REG); in spmmc_prepare_data()
486 writel(value, host->base + SPMMC_SD_CONFIG0_REG); in spmmc_prepare_data()
492 u32 value = readl(host->base + SPMMC_SD_CTRL_REG); in spmmc_trigger_transaction()
495 writel(value, host->base + SPMMC_SD_CTRL_REG); in spmmc_trigger_transaction()
507 value = readl(host->base + SPMMC_SD_INT_REG); in spmmc_send_stop_cmd()
510 writel(value, host->base + SPMMC_SD_INT_REG); in spmmc_send_stop_cmd()
512 readl_poll_timeout(host->base + SPMMC_SD_STATE_REG, value, in spmmc_send_stop_cmd()
519 struct mmc_command *cmd = mrq->cmd; in spmmc_check_error()
520 struct mmc_data *data = mrq->data; in spmmc_check_error()
522 u32 value = readl(host->base + SPMMC_SD_STATE_REG); in spmmc_check_error()
528 value = readl(host->base + SPMMC_SD_STATUS_REG); in spmmc_check_error()
530 if (host->tuning_info.enable_tuning) { in spmmc_check_error()
531 timing_cfg0 = readl(host->base + SPMMC_SD_TIMING_CONFIG0_REG); in spmmc_check_error()
532 host->tuning_info.rd_crc_dly = FIELD_GET(SPMMC_SD_READ_CRC_DELAY, in spmmc_check_error()
534 host->tuning_info.rd_dat_dly = FIELD_GET(SPMMC_SD_READ_DATA_DELAY, in spmmc_check_error()
536 host->tuning_info.rd_rsp_dly = FIELD_GET(SPMMC_SD_READ_RESPONSE_DELAY, in spmmc_check_error()
538 host->tuning_info.wr_cmd_dly = FIELD_GET(SPMMC_SD_WRITE_COMMAND_DELAY, in spmmc_check_error()
540 host->tuning_info.wr_dat_dly = FIELD_GET(SPMMC_SD_WRITE_DATA_DELAY, in spmmc_check_error()
545 ret = -ETIMEDOUT; in spmmc_check_error()
546 host->tuning_info.wr_cmd_dly++; in spmmc_check_error()
548 ret = -EILSEQ; in spmmc_check_error()
549 host->tuning_info.rd_rsp_dly++; in spmmc_check_error()
552 ret = -ETIMEDOUT; in spmmc_check_error()
553 host->tuning_info.rd_dat_dly++; in spmmc_check_error()
555 ret = -EILSEQ; in spmmc_check_error()
556 host->tuning_info.rd_dat_dly++; in spmmc_check_error()
558 ret = -ETIMEDOUT; in spmmc_check_error()
559 host->tuning_info.rd_crc_dly++; in spmmc_check_error()
561 ret = -EILSEQ; in spmmc_check_error()
563 host->tuning_info.wr_dat_dly++; in spmmc_check_error()
565 host->tuning_info.rd_crc_dly++; in spmmc_check_error()
568 cmd->error = ret; in spmmc_check_error()
570 data->error = ret; in spmmc_check_error()
571 data->bytes_xfered = 0; in spmmc_check_error()
573 if (!host->tuning_info.need_tuning && host->tuning_info.enable_tuning) in spmmc_check_error()
574 cmd->retries = SPMMC_MAX_RETRIES; in spmmc_check_error()
577 if (host->tuning_info.enable_tuning) { in spmmc_check_error()
580 host->tuning_info.rd_crc_dly); in spmmc_check_error()
583 host->tuning_info.rd_dat_dly); in spmmc_check_error()
586 host->tuning_info.rd_rsp_dly); in spmmc_check_error()
589 host->tuning_info.wr_cmd_dly); in spmmc_check_error()
592 host->tuning_info.wr_dat_dly); in spmmc_check_error()
593 writel(timing_cfg0, host->base + SPMMC_SD_TIMING_CONFIG0_REG); in spmmc_check_error()
596 data->error = 0; in spmmc_check_error()
597 data->bytes_xfered = data->blocks * data->blksz; in spmmc_check_error()
599 host->tuning_info.need_tuning = ret; in spmmc_check_error()
615 f = ffs(candidate_dly) - 1; in spmmc_find_best_delay()
617 value = ((1 << w) - 1) << f; in spmmc_find_best_delay()
627 int data_left = data->blocks * data->blksz; in spmmc_xfer_data_pio()
633 if (data->flags & MMC_DATA_WRITE) in spmmc_xfer_data_pio()
637 sg_miter_start(&sg_miter, data->sg, data->sg_len, flags); in spmmc_xfer_data_pio()
645 if (data->flags & MMC_DATA_WRITE) { in spmmc_xfer_data_pio()
648 writel(*buf, host->base + SPMMC_SD_PIODATATX_REG); in spmmc_xfer_data_pio()
652 *buf = readl(host->base + SPMMC_SD_PIODATARX_REG); in spmmc_xfer_data_pio()
657 remain -= 4; in spmmc_xfer_data_pio()
660 data_left -= consumed; in spmmc_xfer_data_pio()
669 int ret = reset_control_assert(host->rstc); in spmmc_controller_init()
673 ret = reset_control_deassert(host->rstc); in spmmc_controller_init()
676 value = readl(host->base + SPMMC_CARD_MEDIATYPE_SRCDST_REG); in spmmc_controller_init()
679 writel(value, host->base + SPMMC_CARD_MEDIATYPE_SRCDST_REG); in spmmc_controller_init()
685 * 3. notify mmc layer the request is done
695 cmd = mrq->cmd; in spmmc_finish_request()
696 data = mrq->data; in spmmc_finish_request()
698 if (data && SPMMC_DMA_MODE == host->dmapio_mode) { in spmmc_finish_request()
699 dma_unmap_sg(host->mmc->parent, data->sg, data->sg_len, mmc_get_dma_dir(data)); in spmmc_finish_request()
700 host->dma_use_int = 0; in spmmc_finish_request()
705 if (mrq->stop) in spmmc_finish_request()
708 host->mrq = NULL; in spmmc_finish_request()
709 mmc_request_done(host->mmc, mrq); in spmmc_finish_request()
716 u32 value = readl(host->base + SPMMC_SD_INT_REG); in spmmc_irq()
721 writel(value, host->base + SPMMC_SD_INT_REG); in spmmc_irq()
727 static void spmmc_request(struct mmc_host *mmc, struct mmc_request *mrq) in spmmc_request() argument
729 struct spmmc_host *host = mmc_priv(mmc); in spmmc_request()
733 host->mrq = mrq; in spmmc_request()
734 data = mrq->data; in spmmc_request()
735 cmd = mrq->cmd; in spmmc_request()
739 if (cmd->flags & MMC_RSP_136) { in spmmc_request()
744 host->mrq = NULL; in spmmc_request()
745 mmc_request_done(host->mmc, mrq); in spmmc_request()
750 if (host->dmapio_mode == SPMMC_PIO_MODE && data) { in spmmc_request()
753 value = readl(host->base + SPMMC_SD_INT_REG); in spmmc_request()
755 writel(value, host->base + SPMMC_SD_INT_REG); in spmmc_request()
761 if (host->dma_use_int) { in spmmc_request()
772 static void spmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) in spmmc_set_ios() argument
774 struct spmmc_host *host = (struct spmmc_host *)mmc_priv(mmc); in spmmc_set_ios()
776 spmmc_set_bus_clk(host, ios->clock); in spmmc_set_ios()
777 spmmc_set_bus_timing(host, ios->timing); in spmmc_set_ios()
778 spmmc_set_bus_width(host, ios->bus_width); in spmmc_set_ios()
787 * -ENOSYS when not supported (equal to NULL callback)
790 static int spmmc_get_cd(struct mmc_host *mmc) in spmmc_get_cd() argument
794 if (mmc_can_gpio_cd(mmc)) in spmmc_get_cd()
795 ret = mmc_gpio_get_cd(mmc); in spmmc_get_cd()
803 static int spmmc_execute_tuning(struct mmc_host *mmc, u32 opcode) in spmmc_execute_tuning() argument
805 struct spmmc_host *host = mmc_priv(mmc); in spmmc_execute_tuning()
809 host->tuning_info.enable_tuning = 0; in spmmc_execute_tuning()
811 value = readl(host->base + SPMMC_SD_TIMING_CONFIG0_REG); in spmmc_execute_tuning()
818 writel(value, host->base + SPMMC_SD_TIMING_CONFIG0_REG); in spmmc_execute_tuning()
820 if (!mmc_send_tuning(mmc, opcode, NULL)) { in spmmc_execute_tuning()
825 host->tuning_info.enable_tuning = 1; in spmmc_execute_tuning()
829 value = readl(host->base + SPMMC_SD_TIMING_CONFIG0_REG); in spmmc_execute_tuning()
836 writel(value, host->base + SPMMC_SD_TIMING_CONFIG0_REG); in spmmc_execute_tuning()
840 return -EIO; in spmmc_execute_tuning()
854 spmmc_finish_request(host, host->mrq); in spmmc_func_finish_req()
861 struct mmc_host *mmc; in spmmc_drv_probe() local
866 mmc = devm_mmc_alloc_host(&pdev->dev, sizeof(struct spmmc_host)); in spmmc_drv_probe()
867 if (!mmc) in spmmc_drv_probe()
868 return -ENOMEM; in spmmc_drv_probe()
870 host = mmc_priv(mmc); in spmmc_drv_probe()
871 host->mmc = mmc; in spmmc_drv_probe()
872 host->dmapio_mode = SPMMC_DMA_MODE; in spmmc_drv_probe()
873 host->dma_int_threshold = 1024; in spmmc_drv_probe()
875 host->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); in spmmc_drv_probe()
876 if (IS_ERR(host->base)) in spmmc_drv_probe()
877 return PTR_ERR(host->base); in spmmc_drv_probe()
879 host->clk = devm_clk_get(&pdev->dev, NULL); in spmmc_drv_probe()
880 if (IS_ERR(host->clk)) in spmmc_drv_probe()
881 return dev_err_probe(&pdev->dev, PTR_ERR(host->clk), "clk get fail\n"); in spmmc_drv_probe()
883 host->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL); in spmmc_drv_probe()
884 if (IS_ERR(host->rstc)) in spmmc_drv_probe()
885 return dev_err_probe(&pdev->dev, PTR_ERR(host->rstc), "rst get fail\n"); in spmmc_drv_probe()
887 host->irq = platform_get_irq(pdev, 0); in spmmc_drv_probe()
888 if (host->irq < 0) in spmmc_drv_probe()
889 return host->irq; in spmmc_drv_probe()
891 ret = devm_request_threaded_irq(&pdev->dev, host->irq, in spmmc_drv_probe()
897 ret = clk_prepare_enable(host->clk); in spmmc_drv_probe()
899 return dev_err_probe(&pdev->dev, ret, "failed to enable clk\n"); in spmmc_drv_probe()
901 ret = mmc_of_parse(mmc); in spmmc_drv_probe()
905 mmc->ops = &spmmc_ops; in spmmc_drv_probe()
906 mmc->f_min = SPMMC_MIN_CLK; in spmmc_drv_probe()
907 if (mmc->f_max > SPMMC_MAX_CLK) in spmmc_drv_probe()
908 mmc->f_max = SPMMC_MAX_CLK; in spmmc_drv_probe()
910 ret = mmc_regulator_get_supply(mmc); in spmmc_drv_probe()
914 if (!mmc->ocr_avail) in spmmc_drv_probe()
915 mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; in spmmc_drv_probe()
916 mmc->max_seg_size = SPMMC_MAX_BLK_COUNT * 512; in spmmc_drv_probe()
917 mmc->max_segs = SPMMC_MAX_DMA_MEMORY_SECTORS; in spmmc_drv_probe()
918 mmc->max_req_size = SPMMC_MAX_BLK_COUNT * 512; in spmmc_drv_probe()
919 mmc->max_blk_size = 512; in spmmc_drv_probe()
920 mmc->max_blk_count = SPMMC_MAX_BLK_COUNT; in spmmc_drv_probe()
922 dev_set_drvdata(&pdev->dev, host); in spmmc_drv_probe()
925 host->tuning_info.enable_tuning = 1; in spmmc_drv_probe()
926 pm_runtime_set_active(&pdev->dev); in spmmc_drv_probe()
927 pm_runtime_enable(&pdev->dev); in spmmc_drv_probe()
928 ret = mmc_add_host(mmc); in spmmc_drv_probe()
935 pm_runtime_disable(&pdev->dev); in spmmc_drv_probe()
938 clk_disable_unprepare(host->clk); in spmmc_drv_probe()
946 mmc_remove_host(host->mmc); in spmmc_drv_remove()
947 pm_runtime_get_sync(&dev->dev); in spmmc_drv_remove()
948 clk_disable_unprepare(host->clk); in spmmc_drv_remove()
949 pm_runtime_put_noidle(&dev->dev); in spmmc_drv_remove()
950 pm_runtime_disable(&dev->dev); in spmmc_drv_remove()
958 clk_disable_unprepare(host->clk); in spmmc_pm_runtime_suspend()
969 return clk_prepare_enable(host->clk); in spmmc_pm_runtime_resume()
977 .compatible = "sunplus,sp7021-mmc",
995 MODULE_AUTHOR("Li-hao Kuo <lhjeff911@gmail.com>");
996 MODULE_DESCRIPTION("Sunplus MMC controller driver");