Lines Matching refs:host

74 #define mmc_readl(host, reg) \  argument
75 readl((host)->reg_base + SDXC_##reg)
76 #define mmc_writel(host, reg, value) \ argument
77 writel((value), (host)->reg_base + SDXC_##reg)
250 static int sunxi_mmc_reset_host(struct sunxi_mmc_host *host) in sunxi_mmc_reset_host() argument
255 mmc_writel(host, REG_GCTRL, SDXC_HARDWARE_RESET); in sunxi_mmc_reset_host()
257 rval = mmc_readl(host, REG_GCTRL); in sunxi_mmc_reset_host()
261 dev_err(mmc_dev(host->mmc), "fatal err reset timeout\n"); in sunxi_mmc_reset_host()
271 struct sunxi_mmc_host *host = mmc_priv(mmc); in sunxi_mmc_init_host() local
273 if (sunxi_mmc_reset_host(host)) in sunxi_mmc_init_host()
276 mmc_writel(host, REG_FTRGL, 0x20070008); in sunxi_mmc_init_host()
277 mmc_writel(host, REG_TMOUT, 0xffffffff); in sunxi_mmc_init_host()
278 mmc_writel(host, REG_IMASK, host->sdio_imask); in sunxi_mmc_init_host()
279 mmc_writel(host, REG_RINTR, 0xffffffff); in sunxi_mmc_init_host()
280 mmc_writel(host, REG_DBGC, 0xdeb); in sunxi_mmc_init_host()
281 mmc_writel(host, REG_FUNS, SDXC_CEATA_ON); in sunxi_mmc_init_host()
282 mmc_writel(host, REG_DLBA, host->sg_dma); in sunxi_mmc_init_host()
284 rval = mmc_readl(host, REG_GCTRL); in sunxi_mmc_init_host()
287 mmc_writel(host, REG_GCTRL, rval); in sunxi_mmc_init_host()
292 static void sunxi_mmc_init_idma_des(struct sunxi_mmc_host *host, in sunxi_mmc_init_idma_des() argument
295 struct sunxi_idma_des *pdes = (struct sunxi_idma_des *)host->sg_cpu; in sunxi_mmc_init_idma_des()
296 dma_addr_t next_desc = host->sg_dma; in sunxi_mmc_init_idma_des()
297 int i, max_len = (1 << host->idma_des_size_bits); in sunxi_mmc_init_idma_des()
333 static int sunxi_mmc_map_dma(struct sunxi_mmc_host *host, in sunxi_mmc_map_dma() argument
339 dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, in sunxi_mmc_map_dma()
342 dev_err(mmc_dev(host->mmc), "dma_map_sg failed\n"); in sunxi_mmc_map_dma()
348 dev_err(mmc_dev(host->mmc), in sunxi_mmc_map_dma()
358 static void sunxi_mmc_start_dma(struct sunxi_mmc_host *host, in sunxi_mmc_start_dma() argument
363 sunxi_mmc_init_idma_des(host, data); in sunxi_mmc_start_dma()
365 rval = mmc_readl(host, REG_GCTRL); in sunxi_mmc_start_dma()
367 mmc_writel(host, REG_GCTRL, rval); in sunxi_mmc_start_dma()
369 mmc_writel(host, REG_GCTRL, rval); in sunxi_mmc_start_dma()
371 mmc_writel(host, REG_DMAC, SDXC_IDMAC_SOFT_RESET); in sunxi_mmc_start_dma()
374 mmc_writel(host, REG_IDIE, SDXC_IDMAC_RECEIVE_INTERRUPT); in sunxi_mmc_start_dma()
376 mmc_writel(host, REG_DMAC, in sunxi_mmc_start_dma()
380 static void sunxi_mmc_send_manual_stop(struct sunxi_mmc_host *host, in sunxi_mmc_send_manual_stop() argument
398 mmc_writel(host, REG_CARG, arg); in sunxi_mmc_send_manual_stop()
399 mmc_writel(host, REG_CMDR, cmd_val); in sunxi_mmc_send_manual_stop()
402 ri = mmc_readl(host, REG_RINTR); in sunxi_mmc_send_manual_stop()
407 dev_err(mmc_dev(host->mmc), "send stop command failed\n"); in sunxi_mmc_send_manual_stop()
412 req->stop->resp[0] = mmc_readl(host, REG_RESP0); in sunxi_mmc_send_manual_stop()
415 mmc_writel(host, REG_RINTR, 0xffff); in sunxi_mmc_send_manual_stop()
418 static void sunxi_mmc_dump_errinfo(struct sunxi_mmc_host *host) in sunxi_mmc_dump_errinfo() argument
420 struct mmc_command *cmd = host->mrq->cmd; in sunxi_mmc_dump_errinfo()
421 struct mmc_data *data = host->mrq->data; in sunxi_mmc_dump_errinfo()
424 if ((host->int_sum & SDXC_INTERRUPT_ERROR_BIT) == in sunxi_mmc_dump_errinfo()
429 dev_err(mmc_dev(host->mmc), in sunxi_mmc_dump_errinfo()
431 host->mmc->index, cmd->opcode, in sunxi_mmc_dump_errinfo()
433 host->int_sum & SDXC_RESP_ERROR ? " RE" : "", in sunxi_mmc_dump_errinfo()
434 host->int_sum & SDXC_RESP_CRC_ERROR ? " RCE" : "", in sunxi_mmc_dump_errinfo()
435 host->int_sum & SDXC_DATA_CRC_ERROR ? " DCE" : "", in sunxi_mmc_dump_errinfo()
436 host->int_sum & SDXC_RESP_TIMEOUT ? " RTO" : "", in sunxi_mmc_dump_errinfo()
437 host->int_sum & SDXC_DATA_TIMEOUT ? " DTO" : "", in sunxi_mmc_dump_errinfo()
438 host->int_sum & SDXC_FIFO_RUN_ERROR ? " FE" : "", in sunxi_mmc_dump_errinfo()
439 host->int_sum & SDXC_HARD_WARE_LOCKED ? " HL" : "", in sunxi_mmc_dump_errinfo()
440 host->int_sum & SDXC_START_BIT_ERROR ? " SBE" : "", in sunxi_mmc_dump_errinfo()
441 host->int_sum & SDXC_END_BIT_ERROR ? " EBE" : "" in sunxi_mmc_dump_errinfo()
446 static irqreturn_t sunxi_mmc_finalize_request(struct sunxi_mmc_host *host) in sunxi_mmc_finalize_request() argument
448 struct mmc_request *mrq = host->mrq; in sunxi_mmc_finalize_request()
452 mmc_writel(host, REG_IMASK, host->sdio_imask); in sunxi_mmc_finalize_request()
453 mmc_writel(host, REG_IDIE, 0); in sunxi_mmc_finalize_request()
455 if (host->int_sum & SDXC_INTERRUPT_ERROR_BIT) { in sunxi_mmc_finalize_request()
456 sunxi_mmc_dump_errinfo(host); in sunxi_mmc_finalize_request()
461 host->manual_stop_mrq = mrq; in sunxi_mmc_finalize_request()
468 mrq->cmd->resp[0] = mmc_readl(host, REG_RESP3); in sunxi_mmc_finalize_request()
469 mrq->cmd->resp[1] = mmc_readl(host, REG_RESP2); in sunxi_mmc_finalize_request()
470 mrq->cmd->resp[2] = mmc_readl(host, REG_RESP1); in sunxi_mmc_finalize_request()
471 mrq->cmd->resp[3] = mmc_readl(host, REG_RESP0); in sunxi_mmc_finalize_request()
473 mrq->cmd->resp[0] = mmc_readl(host, REG_RESP0); in sunxi_mmc_finalize_request()
481 mmc_writel(host, REG_IDST, 0x337); in sunxi_mmc_finalize_request()
482 mmc_writel(host, REG_DMAC, 0); in sunxi_mmc_finalize_request()
483 rval = mmc_readl(host, REG_GCTRL); in sunxi_mmc_finalize_request()
485 mmc_writel(host, REG_GCTRL, rval); in sunxi_mmc_finalize_request()
487 mmc_writel(host, REG_GCTRL, rval); in sunxi_mmc_finalize_request()
489 mmc_writel(host, REG_GCTRL, rval); in sunxi_mmc_finalize_request()
490 dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, in sunxi_mmc_finalize_request()
494 mmc_writel(host, REG_RINTR, 0xffff); in sunxi_mmc_finalize_request()
496 host->mrq = NULL; in sunxi_mmc_finalize_request()
497 host->int_sum = 0; in sunxi_mmc_finalize_request()
498 host->wait_dma = false; in sunxi_mmc_finalize_request()
500 return host->manual_stop_mrq ? IRQ_WAKE_THREAD : IRQ_HANDLED; in sunxi_mmc_finalize_request()
505 struct sunxi_mmc_host *host = dev_id; in sunxi_mmc_irq() local
512 spin_lock(&host->lock); in sunxi_mmc_irq()
514 idma_int = mmc_readl(host, REG_IDST); in sunxi_mmc_irq()
515 msk_int = mmc_readl(host, REG_MISTA); in sunxi_mmc_irq()
517 dev_dbg(mmc_dev(host->mmc), "irq: rq %p mi %08x idi %08x\n", in sunxi_mmc_irq()
518 host->mrq, msk_int, idma_int); in sunxi_mmc_irq()
520 mrq = host->mrq; in sunxi_mmc_irq()
523 host->wait_dma = false; in sunxi_mmc_irq()
525 host->int_sum |= msk_int; in sunxi_mmc_irq()
528 if ((host->int_sum & SDXC_RESP_TIMEOUT) && in sunxi_mmc_irq()
529 !(host->int_sum & SDXC_COMMAND_DONE)) in sunxi_mmc_irq()
530 mmc_writel(host, REG_IMASK, in sunxi_mmc_irq()
531 host->sdio_imask | SDXC_COMMAND_DONE); in sunxi_mmc_irq()
533 else if (host->int_sum & SDXC_INTERRUPT_ERROR_BIT) in sunxi_mmc_irq()
535 else if ((host->int_sum & SDXC_INTERRUPT_DONE_BIT) && in sunxi_mmc_irq()
536 !host->wait_dma) in sunxi_mmc_irq()
543 mmc_writel(host, REG_RINTR, msk_int); in sunxi_mmc_irq()
544 mmc_writel(host, REG_IDST, idma_int); in sunxi_mmc_irq()
547 ret = sunxi_mmc_finalize_request(host); in sunxi_mmc_irq()
549 spin_unlock(&host->lock); in sunxi_mmc_irq()
552 mmc_request_done(host->mmc, mrq); in sunxi_mmc_irq()
555 mmc_signal_sdio_irq(host->mmc); in sunxi_mmc_irq()
562 struct sunxi_mmc_host *host = dev_id; in sunxi_mmc_handle_manual_stop() local
566 spin_lock_irqsave(&host->lock, iflags); in sunxi_mmc_handle_manual_stop()
567 mrq = host->manual_stop_mrq; in sunxi_mmc_handle_manual_stop()
568 spin_unlock_irqrestore(&host->lock, iflags); in sunxi_mmc_handle_manual_stop()
571 dev_err(mmc_dev(host->mmc), "no request for manual stop\n"); in sunxi_mmc_handle_manual_stop()
575 dev_err(mmc_dev(host->mmc), "data error, sending stop command\n"); in sunxi_mmc_handle_manual_stop()
585 sunxi_mmc_send_manual_stop(host, mrq); in sunxi_mmc_handle_manual_stop()
587 spin_lock_irqsave(&host->lock, iflags); in sunxi_mmc_handle_manual_stop()
588 host->manual_stop_mrq = NULL; in sunxi_mmc_handle_manual_stop()
589 spin_unlock_irqrestore(&host->lock, iflags); in sunxi_mmc_handle_manual_stop()
591 mmc_request_done(host->mmc, mrq); in sunxi_mmc_handle_manual_stop()
596 static int sunxi_mmc_oclk_onoff(struct sunxi_mmc_host *host, u32 oclk_en) in sunxi_mmc_oclk_onoff() argument
601 rval = mmc_readl(host, REG_CLKCR); in sunxi_mmc_oclk_onoff()
607 mmc_writel(host, REG_CLKCR, rval); in sunxi_mmc_oclk_onoff()
610 mmc_writel(host, REG_CMDR, rval); in sunxi_mmc_oclk_onoff()
613 rval = mmc_readl(host, REG_CMDR); in sunxi_mmc_oclk_onoff()
617 mmc_writel(host, REG_RINTR, in sunxi_mmc_oclk_onoff()
618 mmc_readl(host, REG_RINTR) & ~SDXC_SDIO_INTERRUPT); in sunxi_mmc_oclk_onoff()
621 dev_err(mmc_dev(host->mmc), "fatal err update clk timeout\n"); in sunxi_mmc_oclk_onoff()
628 static int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host, in sunxi_mmc_clk_set_rate() argument
634 rate = clk_round_rate(host->clk_mmc, ios->clock); in sunxi_mmc_clk_set_rate()
635 dev_dbg(mmc_dev(host->mmc), "setting clk to %d, rounded %d\n", in sunxi_mmc_clk_set_rate()
639 ret = clk_set_rate(host->clk_mmc, rate); in sunxi_mmc_clk_set_rate()
641 dev_err(mmc_dev(host->mmc), "error setting clk to %d: %d\n", in sunxi_mmc_clk_set_rate()
646 ret = sunxi_mmc_oclk_onoff(host, 0); in sunxi_mmc_clk_set_rate()
651 rval = mmc_readl(host, REG_CLKCR); in sunxi_mmc_clk_set_rate()
653 mmc_writel(host, REG_CLKCR, rval); in sunxi_mmc_clk_set_rate()
680 clk_set_phase(host->clk_sample, sclk_dly); in sunxi_mmc_clk_set_rate()
681 clk_set_phase(host->clk_output, oclk_dly); in sunxi_mmc_clk_set_rate()
683 return sunxi_mmc_oclk_onoff(host, 1); in sunxi_mmc_clk_set_rate()
688 struct sunxi_mmc_host *host = mmc_priv(mmc); in sunxi_mmc_set_ios() local
699 host->ferror = sunxi_mmc_init_host(mmc); in sunxi_mmc_set_ios()
700 if (host->ferror) in sunxi_mmc_set_ios()
708 sunxi_mmc_reset_host(host); in sunxi_mmc_set_ios()
716 mmc_writel(host, REG_WIDTH, SDXC_WIDTH1); in sunxi_mmc_set_ios()
719 mmc_writel(host, REG_WIDTH, SDXC_WIDTH4); in sunxi_mmc_set_ios()
722 mmc_writel(host, REG_WIDTH, SDXC_WIDTH8); in sunxi_mmc_set_ios()
727 rval = mmc_readl(host, REG_GCTRL); in sunxi_mmc_set_ios()
732 mmc_writel(host, REG_GCTRL, rval); in sunxi_mmc_set_ios()
736 host->ferror = sunxi_mmc_clk_set_rate(host, ios); in sunxi_mmc_set_ios()
743 struct sunxi_mmc_host *host = mmc_priv(mmc); in sunxi_mmc_enable_sdio_irq() local
747 spin_lock_irqsave(&host->lock, flags); in sunxi_mmc_enable_sdio_irq()
749 imask = mmc_readl(host, REG_IMASK); in sunxi_mmc_enable_sdio_irq()
751 host->sdio_imask = SDXC_SDIO_INTERRUPT; in sunxi_mmc_enable_sdio_irq()
754 host->sdio_imask = 0; in sunxi_mmc_enable_sdio_irq()
757 mmc_writel(host, REG_IMASK, imask); in sunxi_mmc_enable_sdio_irq()
758 spin_unlock_irqrestore(&host->lock, flags); in sunxi_mmc_enable_sdio_irq()
763 struct sunxi_mmc_host *host = mmc_priv(mmc); in sunxi_mmc_hw_reset() local
764 mmc_writel(host, REG_HWRST, 0); in sunxi_mmc_hw_reset()
766 mmc_writel(host, REG_HWRST, 1); in sunxi_mmc_hw_reset()
772 struct sunxi_mmc_host *host = mmc_priv(mmc); in sunxi_mmc_request() local
778 bool wait_dma = host->wait_dma; in sunxi_mmc_request()
782 if (host->ferror) { in sunxi_mmc_request()
783 mrq->cmd->error = host->ferror; in sunxi_mmc_request()
789 ret = sunxi_mmc_map_dma(host, data); in sunxi_mmc_request()
841 spin_lock_irqsave(&host->lock, iflags); in sunxi_mmc_request()
843 if (host->mrq || host->manual_stop_mrq) { in sunxi_mmc_request()
844 spin_unlock_irqrestore(&host->lock, iflags); in sunxi_mmc_request()
857 mmc_writel(host, REG_BLKSZ, data->blksz); in sunxi_mmc_request()
858 mmc_writel(host, REG_BCNTR, data->blksz * data->blocks); in sunxi_mmc_request()
859 sunxi_mmc_start_dma(host, data); in sunxi_mmc_request()
862 host->mrq = mrq; in sunxi_mmc_request()
863 host->wait_dma = wait_dma; in sunxi_mmc_request()
864 mmc_writel(host, REG_IMASK, host->sdio_imask | imask); in sunxi_mmc_request()
865 mmc_writel(host, REG_CARG, cmd->arg); in sunxi_mmc_request()
866 mmc_writel(host, REG_CMDR, cmd_val); in sunxi_mmc_request()
868 spin_unlock_irqrestore(&host->lock, iflags); in sunxi_mmc_request()
887 static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host, in sunxi_mmc_resource_request() argument
894 host->idma_des_size_bits = 13; in sunxi_mmc_resource_request()
896 host->idma_des_size_bits = 16; in sunxi_mmc_resource_request()
898 ret = mmc_regulator_get_supply(host->mmc); in sunxi_mmc_resource_request()
905 host->reg_base = devm_ioremap_resource(&pdev->dev, in sunxi_mmc_resource_request()
907 if (IS_ERR(host->reg_base)) in sunxi_mmc_resource_request()
908 return PTR_ERR(host->reg_base); in sunxi_mmc_resource_request()
910 host->clk_ahb = devm_clk_get(&pdev->dev, "ahb"); in sunxi_mmc_resource_request()
911 if (IS_ERR(host->clk_ahb)) { in sunxi_mmc_resource_request()
913 return PTR_ERR(host->clk_ahb); in sunxi_mmc_resource_request()
916 host->clk_mmc = devm_clk_get(&pdev->dev, "mmc"); in sunxi_mmc_resource_request()
917 if (IS_ERR(host->clk_mmc)) { in sunxi_mmc_resource_request()
919 return PTR_ERR(host->clk_mmc); in sunxi_mmc_resource_request()
922 host->clk_output = devm_clk_get(&pdev->dev, "output"); in sunxi_mmc_resource_request()
923 if (IS_ERR(host->clk_output)) { in sunxi_mmc_resource_request()
925 return PTR_ERR(host->clk_output); in sunxi_mmc_resource_request()
928 host->clk_sample = devm_clk_get(&pdev->dev, "sample"); in sunxi_mmc_resource_request()
929 if (IS_ERR(host->clk_sample)) { in sunxi_mmc_resource_request()
931 return PTR_ERR(host->clk_sample); in sunxi_mmc_resource_request()
934 host->reset = devm_reset_control_get_optional(&pdev->dev, "ahb"); in sunxi_mmc_resource_request()
935 if (PTR_ERR(host->reset) == -EPROBE_DEFER) in sunxi_mmc_resource_request()
936 return PTR_ERR(host->reset); in sunxi_mmc_resource_request()
938 ret = clk_prepare_enable(host->clk_ahb); in sunxi_mmc_resource_request()
944 ret = clk_prepare_enable(host->clk_mmc); in sunxi_mmc_resource_request()
950 ret = clk_prepare_enable(host->clk_output); in sunxi_mmc_resource_request()
956 ret = clk_prepare_enable(host->clk_sample); in sunxi_mmc_resource_request()
962 if (!IS_ERR(host->reset)) { in sunxi_mmc_resource_request()
963 ret = reset_control_deassert(host->reset); in sunxi_mmc_resource_request()
974 ret = sunxi_mmc_reset_host(host); in sunxi_mmc_resource_request()
978 host->irq = platform_get_irq(pdev, 0); in sunxi_mmc_resource_request()
979 return devm_request_threaded_irq(&pdev->dev, host->irq, sunxi_mmc_irq, in sunxi_mmc_resource_request()
980 sunxi_mmc_handle_manual_stop, 0, "sunxi-mmc", host); in sunxi_mmc_resource_request()
983 if (!IS_ERR(host->reset)) in sunxi_mmc_resource_request()
984 reset_control_assert(host->reset); in sunxi_mmc_resource_request()
986 clk_disable_unprepare(host->clk_sample); in sunxi_mmc_resource_request()
988 clk_disable_unprepare(host->clk_output); in sunxi_mmc_resource_request()
990 clk_disable_unprepare(host->clk_mmc); in sunxi_mmc_resource_request()
992 clk_disable_unprepare(host->clk_ahb); in sunxi_mmc_resource_request()
998 struct sunxi_mmc_host *host; in sunxi_mmc_probe() local
1008 host = mmc_priv(mmc); in sunxi_mmc_probe()
1009 host->mmc = mmc; in sunxi_mmc_probe()
1010 spin_lock_init(&host->lock); in sunxi_mmc_probe()
1012 ret = sunxi_mmc_resource_request(host, pdev); in sunxi_mmc_probe()
1016 host->sg_cpu = dma_alloc_coherent(&pdev->dev, PAGE_SIZE, in sunxi_mmc_probe()
1017 &host->sg_dma, GFP_KERNEL); in sunxi_mmc_probe()
1018 if (!host->sg_cpu) { in sunxi_mmc_probe()
1028 mmc->max_seg_size = (1 << host->idma_des_size_bits); in sunxi_mmc_probe()
1044 dev_info(&pdev->dev, "base:0x%p irq:%u\n", host->reg_base, host->irq); in sunxi_mmc_probe()
1049 dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma); in sunxi_mmc_probe()
1058 struct sunxi_mmc_host *host = mmc_priv(mmc); in sunxi_mmc_remove() local
1061 disable_irq(host->irq); in sunxi_mmc_remove()
1062 sunxi_mmc_reset_host(host); in sunxi_mmc_remove()
1064 if (!IS_ERR(host->reset)) in sunxi_mmc_remove()
1065 reset_control_assert(host->reset); in sunxi_mmc_remove()
1067 clk_disable_unprepare(host->clk_mmc); in sunxi_mmc_remove()
1068 clk_disable_unprepare(host->clk_ahb); in sunxi_mmc_remove()
1070 dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma); in sunxi_mmc_remove()