Lines Matching +full:auto +full:- +full:cmd12

5  * SPDX-License-Identifier:	GPL-2.0+
14 #include <linux/dma-direction.h>
22 #define UNIPHIER_SD_CMD_NOSTOP BIT(14) /* No automatic CMD12 issue */
27 #define UNIPHIER_SD_CMD_NORMAL (0 << 8)/* auto-detect of resp-type */
36 #define UNIPHIER_SD_STOP_STP BIT(0) /* issue CMD12 */
103 #define UNIPHIER_SD_DMA_CTL_START BIT(0) /* start DMA (auto cleared) */
160 u32 info2 = readl(priv->regbase + UNIPHIER_SD_INFO2); in uniphier_sd_check_error()
168 return -ETIMEDOUT; in uniphier_sd_check_error()
173 return -ETIMEDOUT; in uniphier_sd_check_error()
179 return -EILSEQ; in uniphier_sd_check_error()
185 return -EIO; in uniphier_sd_check_error()
198 while (!(readl(priv->regbase + reg) & flag)) { in uniphier_sd_wait_for_irq()
199 if (wait-- < 0) { in uniphier_sd_wait_for_irq()
201 return -ETIMEDOUT; in uniphier_sd_wait_for_irq()
228 * UNIPHIER_SD_INFO2_BRE is edge-triggered, not level-triggered. in uniphier_sd_pio_read_one_block()
230 writel(0, priv->regbase + UNIPHIER_SD_INFO2); in uniphier_sd_pio_read_one_block()
234 *(*pbuf)++ = readl(priv->regbase + UNIPHIER_SD_BUF); in uniphier_sd_pio_read_one_block()
237 put_unaligned(readl(priv->regbase + UNIPHIER_SD_BUF), in uniphier_sd_pio_read_one_block()
256 writel(0, priv->regbase + UNIPHIER_SD_INFO2); in uniphier_sd_pio_write_one_block()
260 writel(*(*pbuf)++, priv->regbase + UNIPHIER_SD_BUF); in uniphier_sd_pio_write_one_block()
264 priv->regbase + UNIPHIER_SD_BUF); in uniphier_sd_pio_write_one_block()
272 u32 *dest = (u32 *)data->dest; in uniphier_sd_pio_xfer()
273 const u32 *src = (const u32 *)data->src; in uniphier_sd_pio_xfer()
276 for (i = 0; i < data->blocks; i++) { in uniphier_sd_pio_xfer()
277 if (data->flags & MMC_DATA_READ) in uniphier_sd_pio_xfer()
279 data->blocksize); in uniphier_sd_pio_xfer()
282 data->blocksize); in uniphier_sd_pio_xfer()
295 writel(0, priv->regbase + UNIPHIER_SD_DMA_INFO1); in uniphier_sd_dma_start()
296 writel(0, priv->regbase + UNIPHIER_SD_DMA_INFO2); in uniphier_sd_dma_start()
299 tmp = readl(priv->regbase + UNIPHIER_SD_EXTMODE); in uniphier_sd_dma_start()
301 writel(tmp, priv->regbase + UNIPHIER_SD_EXTMODE); in uniphier_sd_dma_start()
303 writel(dma_addr & U32_MAX, priv->regbase + UNIPHIER_SD_DMA_ADDR_L); in uniphier_sd_dma_start()
308 writel(dma_addr & U32_MAX, priv->regbase + UNIPHIER_SD_DMA_ADDR_H); in uniphier_sd_dma_start()
310 writel(UNIPHIER_SD_DMA_CTL_START, priv->regbase + UNIPHIER_SD_DMA_CTL); in uniphier_sd_dma_start()
319 while (!(readl(priv->regbase + UNIPHIER_SD_DMA_INFO1) & flag)) { in uniphier_sd_dma_wait_for_irq()
320 if (wait-- < 0) { in uniphier_sd_dma_wait_for_irq()
322 return -ETIMEDOUT; in uniphier_sd_dma_wait_for_irq()
328 if (readl(priv->regbase + UNIPHIER_SD_DMA_INFO2)) { in uniphier_sd_dma_wait_for_irq()
330 return -EIO; in uniphier_sd_dma_wait_for_irq()
339 size_t len = data->blocks * data->blocksize; in uniphier_sd_dma_xfer()
346 tmp = readl(priv->regbase + UNIPHIER_SD_DMA_MODE); in uniphier_sd_dma_xfer()
348 if (data->flags & MMC_DATA_READ) { in uniphier_sd_dma_xfer()
349 buf = data->dest; in uniphier_sd_dma_xfer()
354 buf = (void *)data->src; in uniphier_sd_dma_xfer()
360 writel(tmp, priv->regbase + UNIPHIER_SD_DMA_MODE); in uniphier_sd_dma_xfer()
366 ret = uniphier_sd_dma_wait_for_irq(dev, poll_flag, data->blocks); in uniphier_sd_dma_xfer()
399 if (readl(priv->regbase + UNIPHIER_SD_INFO2) & UNIPHIER_SD_INFO2_CBSY) { in uniphier_sd_send_cmd()
401 return -EBUSY; in uniphier_sd_send_cmd()
405 writel(0, priv->regbase + UNIPHIER_SD_INFO1); in uniphier_sd_send_cmd()
406 writel(0, priv->regbase + UNIPHIER_SD_INFO2); in uniphier_sd_send_cmd()
409 tmp = readl(priv->regbase + UNIPHIER_SD_EXTMODE); in uniphier_sd_send_cmd()
411 writel(tmp, priv->regbase + UNIPHIER_SD_EXTMODE); in uniphier_sd_send_cmd()
413 writel(cmd->cmdarg, priv->regbase + UNIPHIER_SD_ARG); in uniphier_sd_send_cmd()
415 tmp = cmd->cmdidx; in uniphier_sd_send_cmd()
418 writel(data->blocksize, priv->regbase + UNIPHIER_SD_SIZE); in uniphier_sd_send_cmd()
419 writel(data->blocks, priv->regbase + UNIPHIER_SD_SECCNT); in uniphier_sd_send_cmd()
421 /* Do not send CMD12 automatically */ in uniphier_sd_send_cmd()
424 if (data->blocks > 1) in uniphier_sd_send_cmd()
427 if (data->flags & MMC_DATA_READ) in uniphier_sd_send_cmd()
432 * Do not use the response type auto-detection on this hardware. in uniphier_sd_send_cmd()
437 switch (cmd->resp_type) { in uniphier_sd_send_cmd()
455 return -EINVAL; in uniphier_sd_send_cmd()
459 cmd->cmdidx, tmp, cmd->cmdarg); in uniphier_sd_send_cmd()
460 writel(tmp, priv->regbase + UNIPHIER_SD_CMD); in uniphier_sd_send_cmd()
467 if (cmd->resp_type & MMC_RSP_136) { in uniphier_sd_send_cmd()
468 u32 rsp_127_104 = readl(priv->regbase + UNIPHIER_SD_RSP76); in uniphier_sd_send_cmd()
469 u32 rsp_103_72 = readl(priv->regbase + UNIPHIER_SD_RSP54); in uniphier_sd_send_cmd()
470 u32 rsp_71_40 = readl(priv->regbase + UNIPHIER_SD_RSP32); in uniphier_sd_send_cmd()
471 u32 rsp_39_8 = readl(priv->regbase + UNIPHIER_SD_RSP10); in uniphier_sd_send_cmd()
473 cmd->response[0] = ((rsp_127_104 & 0x00ffffff) << 8) | in uniphier_sd_send_cmd()
475 cmd->response[1] = ((rsp_103_72 & 0x00ffffff) << 8) | in uniphier_sd_send_cmd()
477 cmd->response[2] = ((rsp_71_40 & 0x00ffffff) << 8) | in uniphier_sd_send_cmd()
479 cmd->response[3] = (rsp_39_8 & 0xffffff) << 8; in uniphier_sd_send_cmd()
481 /* bit 39-8 */ in uniphier_sd_send_cmd()
482 cmd->response[0] = readl(priv->regbase + UNIPHIER_SD_RSP10); in uniphier_sd_send_cmd()
487 if (priv->caps & UNIPHIER_SD_CAP_DMA_INTERNAL && in uniphier_sd_send_cmd()
488 uniphier_sd_addr_is_dmaable((long)data->src)) in uniphier_sd_send_cmd()
507 switch (mmc->bus_width) { in uniphier_sd_set_bus_width()
518 return -EINVAL; in uniphier_sd_set_bus_width()
521 tmp = readl(priv->regbase + UNIPHIER_SD_OPTION); in uniphier_sd_set_bus_width()
524 writel(tmp, priv->regbase + UNIPHIER_SD_OPTION); in uniphier_sd_set_bus_width()
534 tmp = readl(priv->regbase + UNIPHIER_SD_IF_MODE); in uniphier_sd_set_ddr_mode()
539 writel(tmp, priv->regbase + UNIPHIER_SD_IF_MODE); in uniphier_sd_set_ddr_mode()
548 if (!mmc->clock) in uniphier_sd_set_clk_rate()
551 divisor = DIV_ROUND_UP(priv->mclk, mmc->clock); in uniphier_sd_set_clk_rate()
571 else if (divisor <= 512 || !(priv->caps & UNIPHIER_SD_CAP_DIV1024)) in uniphier_sd_set_clk_rate()
576 tmp = readl(priv->regbase + UNIPHIER_SD_CLKCTL); in uniphier_sd_set_clk_rate()
583 writel(tmp, priv->regbase + UNIPHIER_SD_CLKCTL); in uniphier_sd_set_clk_rate()
587 writel(tmp, priv->regbase + UNIPHIER_SD_CLKCTL); in uniphier_sd_set_clk_rate()
590 writel(tmp, priv->regbase + UNIPHIER_SD_CLKCTL); in uniphier_sd_set_clk_rate()
602 mmc->clock, mmc_card_ddr(mmc), mmc->bus_width); in uniphier_sd_set_ios()
617 if (priv->caps & UNIPHIER_SD_CAP_NONREMOVABLE) in uniphier_sd_get_cd()
620 return !!(readl(priv->regbase + UNIPHIER_SD_INFO1) & in uniphier_sd_get_cd()
635 tmp = readl(priv->regbase + UNIPHIER_SD_SOFT_RST); in uniphier_sd_host_init()
637 writel(tmp, priv->regbase + UNIPHIER_SD_SOFT_RST); in uniphier_sd_host_init()
639 writel(tmp, priv->regbase + UNIPHIER_SD_SOFT_RST); in uniphier_sd_host_init()
643 writel(UNIPHIER_SD_STOP_SEC, priv->regbase + UNIPHIER_SD_STOP); in uniphier_sd_host_init()
650 writel(priv->version >= 0x10 ? 0x00000101 : 0x00000000, in uniphier_sd_host_init()
651 priv->regbase + UNIPHIER_SD_HOST_MODE); in uniphier_sd_host_init()
653 if (priv->caps & UNIPHIER_SD_CAP_DMA_INTERNAL) { in uniphier_sd_host_init()
654 tmp = readl(priv->regbase + UNIPHIER_SD_DMA_MODE); in uniphier_sd_host_init()
656 writel(tmp, priv->regbase + UNIPHIER_SD_DMA_MODE); in uniphier_sd_host_init()
664 return mmc_bind(dev, &plat->mmc, &plat->cfg); in uniphier_sd_bind()
678 return -EINVAL; in uniphier_sd_probe()
680 priv->regbase = devm_ioremap(dev, base, SZ_2K); in uniphier_sd_probe()
681 if (!priv->regbase) in uniphier_sd_probe()
682 return -ENOMEM; in uniphier_sd_probe()
691 priv->mclk = clk_set_rate(&clk, ULONG_MAX); in uniphier_sd_probe()
692 if (IS_ERR_VALUE(priv->mclk)) { in uniphier_sd_probe()
695 return priv->mclk; in uniphier_sd_probe()
705 plat->cfg.name = dev->name; in uniphier_sd_probe()
706 plat->cfg.host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS; in uniphier_sd_probe()
708 switch (fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "bus-width", in uniphier_sd_probe()
711 plat->cfg.host_caps |= MMC_MODE_8BIT; in uniphier_sd_probe()
714 plat->cfg.host_caps |= MMC_MODE_4BIT; in uniphier_sd_probe()
719 dev_err(dev, "Invalid \"bus-width\" value\n"); in uniphier_sd_probe()
720 return -EINVAL; in uniphier_sd_probe()
723 if (fdt_get_property(gd->fdt_blob, dev_of_offset(dev), "non-removable", in uniphier_sd_probe()
725 priv->caps |= UNIPHIER_SD_CAP_NONREMOVABLE; in uniphier_sd_probe()
727 priv->version = readl(priv->regbase + UNIPHIER_SD_VERSION) & in uniphier_sd_probe()
729 dev_dbg(dev, "version %x\n", priv->version); in uniphier_sd_probe()
730 if (priv->version >= 0x10) { in uniphier_sd_probe()
731 priv->caps |= UNIPHIER_SD_CAP_DMA_INTERNAL; in uniphier_sd_probe()
732 priv->caps |= UNIPHIER_SD_CAP_DIV1024; in uniphier_sd_probe()
737 plat->cfg.voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34; in uniphier_sd_probe()
738 plat->cfg.f_min = priv->mclk / in uniphier_sd_probe()
739 (priv->caps & UNIPHIER_SD_CAP_DIV1024 ? 1024 : 512); in uniphier_sd_probe()
740 plat->cfg.f_max = priv->mclk; in uniphier_sd_probe()
741 plat->cfg.b_max = U32_MAX; /* max value of UNIPHIER_SD_SECCNT */ in uniphier_sd_probe()
743 upriv->mmc = &plat->mmc; in uniphier_sd_probe()
749 { .compatible = "socionext,uniphier-sdhc" },
754 .name = "uniphier-mmc",