Lines Matching +full:clock +full:- +full:error +full:- +full:detect
1 // SPDX-License-Identifier: GPL-2.0+
3 * (C) Copyright 2007-2011
18 #include <asm/arch/clock.h>
22 #include <asm-generic/gpio.h>
39 struct gpio_desc cd_gpio; /* Change Detect GPIO */
40 int cd_inverted; /* Inverted Card Detect */
60 return -EINVAL; in sunxi_mmc_getcd_gpio()
73 priv->reg = (struct sunxi_mmc *)SUNXI_MMC0_BASE; in mmc_resource_init()
74 priv->mclkreg = &ccm->sd0_clk_cfg; in mmc_resource_init()
77 priv->reg = (struct sunxi_mmc *)SUNXI_MMC1_BASE; in mmc_resource_init()
78 priv->mclkreg = &ccm->sd1_clk_cfg; in mmc_resource_init()
81 priv->reg = (struct sunxi_mmc *)SUNXI_MMC2_BASE; in mmc_resource_init()
82 priv->mclkreg = &ccm->sd2_clk_cfg; in mmc_resource_init()
86 priv->reg = (struct sunxi_mmc *)SUNXI_MMC3_BASE; in mmc_resource_init()
87 priv->mclkreg = &ccm->sd3_clk_cfg; in mmc_resource_init()
92 return -1; in mmc_resource_init()
94 priv->mmc_no = sdc_no; in mmc_resource_init()
120 if (IS_ENABLED(CONFIG_MACH_SUN8I_A83T) && priv->mmc_no != 2) in mmc_set_mod_clk()
154 printf("mmc %u error cannot set clock to %u\n", priv->mmc_no, in mmc_set_mod_clk()
156 return -1; in mmc_set_mod_clk()
190 setbits_le32(&priv->reg->ntsr, SUNXI_MMC_NTSR_MODE_SEL_NEW); in mmc_set_mod_clk()
202 CCM_MMC_CTRL_M(div) | val, priv->mclkreg); in mmc_set_mod_clk()
204 debug("mmc %u set mod-clk req %u parent %u n %u m %u rate %u\n", in mmc_set_mod_clk()
205 priv->mmc_no, hz, pll_hz, 1u << n, div, pll_hz / (1u << n) / div); in mmc_set_mod_clk()
220 writel(cmd, &priv->reg->cmd); in mmc_update_clk()
221 while (readl(&priv->reg->cmd) & SUNXI_MMC_CMD_START) { in mmc_update_clk()
223 return -1; in mmc_update_clk()
226 /* clock update sets various irq status bits, clear these */ in mmc_update_clk()
227 writel(readl(&priv->reg->rint), &priv->reg->rint); in mmc_update_clk()
234 unsigned rval = readl(&priv->reg->clkcr); in mmc_config_clock()
236 /* Disable Clock */ in mmc_config_clock()
238 writel(rval, &priv->reg->clkcr); in mmc_config_clock()
240 return -1; in mmc_config_clock()
243 if (mmc_set_mod_clk(priv, mmc->clock)) in mmc_config_clock()
244 return -1; in mmc_config_clock()
248 writel(rval, &priv->reg->clkcr); in mmc_config_clock()
254 * using HS400 which is not supported by mainline U-Boot or in mmc_config_clock()
257 writel(SUNXI_MMC_CAL_DL_SW_EN, &priv->reg->samp_dl); in mmc_config_clock()
260 /* Re-enable Clock */ in mmc_config_clock()
262 writel(rval, &priv->reg->clkcr); in mmc_config_clock()
264 return -1; in mmc_config_clock()
272 debug("set ios: bus_width: %x, clock: %d\n", in sunxi_mmc_set_ios_common()
273 mmc->bus_width, mmc->clock); in sunxi_mmc_set_ios_common()
275 /* Change clock first */ in sunxi_mmc_set_ios_common()
276 if (mmc->clock && mmc_config_clock(priv, mmc) != 0) { in sunxi_mmc_set_ios_common()
277 priv->fatal_err = 1; in sunxi_mmc_set_ios_common()
278 return -EINVAL; in sunxi_mmc_set_ios_common()
282 if (mmc->bus_width == 8) in sunxi_mmc_set_ios_common()
283 writel(0x2, &priv->reg->width); in sunxi_mmc_set_ios_common()
284 else if (mmc->bus_width == 4) in sunxi_mmc_set_ios_common()
285 writel(0x1, &priv->reg->width); in sunxi_mmc_set_ios_common()
287 writel(0x0, &priv->reg->width); in sunxi_mmc_set_ios_common()
295 struct sunxi_mmc_priv *priv = mmc->priv; in sunxi_mmc_core_init()
298 writel(SUNXI_MMC_GCTRL_RESET, &priv->reg->gctrl); in sunxi_mmc_core_init()
308 const int reading = !!(data->flags & MMC_DATA_READ); in mmc_trans_data_by_cpu()
312 unsigned *buff = (unsigned int *)(reading ? data->dest : data->src); in mmc_trans_data_by_cpu()
313 unsigned byte_cnt = data->blocksize * data->blocks; in mmc_trans_data_by_cpu()
321 setbits_le32(&priv->reg->gctrl, SUNXI_MMC_GCTRL_ACCESS_BY_AHB); in mmc_trans_data_by_cpu()
326 while (readl(&priv->reg->status) & status_bit) { in mmc_trans_data_by_cpu()
328 return -1; in mmc_trans_data_by_cpu()
332 buff[i] = readl(&priv->reg->fifo); in mmc_trans_data_by_cpu()
334 writel(buff[i], &priv->reg->fifo); in mmc_trans_data_by_cpu()
347 status = readl(&priv->reg->rint); in mmc_rint_wait()
352 return -ETIMEDOUT; in mmc_rint_wait()
365 int error = 0; in sunxi_mmc_send_cmd_common() local
369 if (priv->fatal_err) in sunxi_mmc_send_cmd_common()
370 return -1; in sunxi_mmc_send_cmd_common()
371 if (cmd->resp_type & MMC_RSP_BUSY) in sunxi_mmc_send_cmd_common()
372 debug("mmc cmd %d check rsp busy\n", cmd->cmdidx); in sunxi_mmc_send_cmd_common()
373 if (cmd->cmdidx == 12) in sunxi_mmc_send_cmd_common()
376 if (!cmd->cmdidx) in sunxi_mmc_send_cmd_common()
378 if (cmd->resp_type & MMC_RSP_PRESENT) in sunxi_mmc_send_cmd_common()
380 if (cmd->resp_type & MMC_RSP_136) in sunxi_mmc_send_cmd_common()
382 if (cmd->resp_type & MMC_RSP_CRC) in sunxi_mmc_send_cmd_common()
386 if ((u32)(long)data->dest & 0x3) { in sunxi_mmc_send_cmd_common()
387 error = -1; in sunxi_mmc_send_cmd_common()
392 if (data->flags & MMC_DATA_WRITE) in sunxi_mmc_send_cmd_common()
394 if (data->blocks > 1) in sunxi_mmc_send_cmd_common()
396 writel(data->blocksize, &priv->reg->blksz); in sunxi_mmc_send_cmd_common()
397 writel(data->blocks * data->blocksize, &priv->reg->bytecnt); in sunxi_mmc_send_cmd_common()
400 debug("mmc %d, cmd %d(0x%08x), arg 0x%08x\n", priv->mmc_no, in sunxi_mmc_send_cmd_common()
401 cmd->cmdidx, cmdval | cmd->cmdidx, cmd->cmdarg); in sunxi_mmc_send_cmd_common()
402 writel(cmd->cmdarg, &priv->reg->arg); in sunxi_mmc_send_cmd_common()
405 writel(cmdval | cmd->cmdidx, &priv->reg->cmd); in sunxi_mmc_send_cmd_common()
415 bytecnt = data->blocksize * data->blocks; in sunxi_mmc_send_cmd_common()
417 writel(cmdval | cmd->cmdidx, &priv->reg->cmd); in sunxi_mmc_send_cmd_common()
420 error = readl(&priv->reg->rint) & in sunxi_mmc_send_cmd_common()
422 error = -ETIMEDOUT; in sunxi_mmc_send_cmd_common()
427 error = mmc_rint_wait(priv, mmc, 1000, SUNXI_MMC_RINT_COMMAND_DONE, in sunxi_mmc_send_cmd_common()
429 if (error) in sunxi_mmc_send_cmd_common()
435 error = mmc_rint_wait(priv, mmc, timeout_msecs, in sunxi_mmc_send_cmd_common()
436 data->blocks > 1 ? in sunxi_mmc_send_cmd_common()
440 if (error) in sunxi_mmc_send_cmd_common()
444 if (cmd->resp_type & MMC_RSP_BUSY) { in sunxi_mmc_send_cmd_common()
449 status = readl(&priv->reg->status); in sunxi_mmc_send_cmd_common()
452 error = -ETIMEDOUT; in sunxi_mmc_send_cmd_common()
458 if (cmd->resp_type & MMC_RSP_136) { in sunxi_mmc_send_cmd_common()
459 cmd->response[0] = readl(&priv->reg->resp3); in sunxi_mmc_send_cmd_common()
460 cmd->response[1] = readl(&priv->reg->resp2); in sunxi_mmc_send_cmd_common()
461 cmd->response[2] = readl(&priv->reg->resp1); in sunxi_mmc_send_cmd_common()
462 cmd->response[3] = readl(&priv->reg->resp0); in sunxi_mmc_send_cmd_common()
464 cmd->response[3], cmd->response[2], in sunxi_mmc_send_cmd_common()
465 cmd->response[1], cmd->response[0]); in sunxi_mmc_send_cmd_common()
467 cmd->response[0] = readl(&priv->reg->resp0); in sunxi_mmc_send_cmd_common()
468 debug("mmc resp 0x%08x\n", cmd->response[0]); in sunxi_mmc_send_cmd_common()
471 if (error < 0) { in sunxi_mmc_send_cmd_common()
472 writel(SUNXI_MMC_GCTRL_RESET, &priv->reg->gctrl); in sunxi_mmc_send_cmd_common()
475 writel(0xffffffff, &priv->reg->rint); in sunxi_mmc_send_cmd_common()
476 writel(readl(&priv->reg->gctrl) | SUNXI_MMC_GCTRL_FIFO_RESET, in sunxi_mmc_send_cmd_common()
477 &priv->reg->gctrl); in sunxi_mmc_send_cmd_common()
479 return error; in sunxi_mmc_send_cmd_common()
485 struct sunxi_mmc_priv *priv = mmc->priv; in sunxi_mmc_set_ios_legacy()
493 struct sunxi_mmc_priv *priv = mmc->priv; in sunxi_mmc_send_cmd_legacy()
500 struct sunxi_mmc_priv *priv = mmc->priv; in sunxi_mmc_getcd_legacy()
503 cd_pin = sunxi_mmc_getcd_gpio(priv->mmc_no); in sunxi_mmc_getcd_legacy()
521 struct mmc_config *cfg = &priv->cfg; in sunxi_mmc_init()
526 cfg->name = "SUNXI SD/MMC"; in sunxi_mmc_init()
527 cfg->ops = &sunxi_mmc_ops; in sunxi_mmc_init()
529 cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; in sunxi_mmc_init()
530 cfg->host_caps = MMC_MODE_4BIT; in sunxi_mmc_init()
533 cfg->host_caps = MMC_MODE_8BIT; in sunxi_mmc_init()
535 cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS; in sunxi_mmc_init()
536 cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; in sunxi_mmc_init()
538 cfg->f_min = 400000; in sunxi_mmc_init()
539 cfg->f_max = 52000000; in sunxi_mmc_init()
544 /* config ahb clock */ in sunxi_mmc_init()
545 debug("init mmc %d clock and io\n", sdc_no); in sunxi_mmc_init()
547 setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MMC(sdc_no)); in sunxi_mmc_init()
551 setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_MMC(sdc_no)); in sunxi_mmc_init()
554 /* sun9i has a mmc-common module, also set the gate and reset there */ in sunxi_mmc_init()
559 setbits_le32(&ccm->sd_gate_reset, 1 << sdc_no); in sunxi_mmc_init()
561 setbits_le32(&ccm->sd_gate_reset, 1 << (RESET_SHIFT + sdc_no)); in sunxi_mmc_init()
576 return sunxi_mmc_set_ios_common(priv, &plat->mmc); in sunxi_mmc_set_ios()
585 return sunxi_mmc_send_cmd_common(priv, &plat->mmc, cmd, data); in sunxi_mmc_send_cmd()
592 if (dm_gpio_is_valid(&priv->cd_gpio)) { in sunxi_mmc_getcd()
593 int cd_state = dm_gpio_get_value(&priv->cd_gpio); in sunxi_mmc_getcd()
595 return cd_state ^ priv->cd_inverted; in sunxi_mmc_getcd()
613 struct mmc_config *cfg = &plat->cfg; in sunxi_mmc_probe()
618 cfg->name = dev->name; in sunxi_mmc_probe()
619 bus_width = dev_read_u32_default(dev, "bus-width", 1); in sunxi_mmc_probe()
621 cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; in sunxi_mmc_probe()
622 cfg->host_caps = 0; in sunxi_mmc_probe()
624 cfg->host_caps |= MMC_MODE_8BIT; in sunxi_mmc_probe()
626 cfg->host_caps |= MMC_MODE_4BIT; in sunxi_mmc_probe()
627 cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS; in sunxi_mmc_probe()
628 cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; in sunxi_mmc_probe()
630 cfg->f_min = 400000; in sunxi_mmc_probe()
631 cfg->f_max = 52000000; in sunxi_mmc_probe()
633 priv->reg = (void *)dev_read_addr(dev); in sunxi_mmc_probe()
634 priv->variant = in sunxi_mmc_probe()
637 /* We don't have a sunxi clock driver so find the clock address here */ in sunxi_mmc_probe()
638 ret = dev_read_phandle_with_args(dev, "clocks", "#clock-cells", 0, in sunxi_mmc_probe()
644 priv->mmc_no = ((uintptr_t)priv->reg - SUNXI_MMC0_BASE) / 0x1000; in sunxi_mmc_probe()
645 priv->mclkreg = (void *)ccu_reg + in sunxi_mmc_probe()
646 (priv->variant->mclk_offset + (priv->mmc_no * 4)); in sunxi_mmc_probe()
661 if (!dev_read_bool(dev, "non-removable") && in sunxi_mmc_probe()
662 !gpio_request_by_name(dev, "cd-gpios", 0, &priv->cd_gpio, in sunxi_mmc_probe()
664 int cd_pin = gpio_get_number(&priv->cd_gpio); in sunxi_mmc_probe()
669 /* Check if card detect is inverted */ in sunxi_mmc_probe()
670 priv->cd_inverted = dev_read_bool(dev, "cd-inverted"); in sunxi_mmc_probe()
672 upriv->mmc = &plat->mmc; in sunxi_mmc_probe()
675 writel(SUNXI_MMC_GCTRL_RESET, &priv->reg->gctrl); in sunxi_mmc_probe()
685 return mmc_bind(dev, &plat->mmc, &plat->cfg); in sunxi_mmc_bind()
702 .compatible = "allwinner,sun4i-a10-mmc",
706 .compatible = "allwinner,sun5i-a13-mmc",
710 .compatible = "allwinner,sun7i-a20-mmc",
714 .compatible = "allwinner,sun8i-a83t-emmc",
718 .compatible = "allwinner,sun9i-a80-mmc",
722 .compatible = "allwinner,sun50i-a64-mmc",
726 .compatible = "allwinner,sun50i-a64-emmc",
730 .compatible = "allwinner,sun50i-h6-mmc",
734 .compatible = "allwinner,sun50i-h6-emmc",