Lines Matching +full:bcm2835 +full:- +full:mbox

1 // SPDX-License-Identifier: GPL-2.0
3 * bcm2835 sdhost driver.
20 * This code was ported to U-Boot by
22 * and is based on drivers/mmc/host/bcm2835.c in Linux which is written by
24 * Copyright (C) 2015-2016 Raspberry Pi (Trading) Ltd.
26 * mmc-bcm2835.c by Gellert Weisz
28 * sdhci-bcm2708.c by Broadcom
29 * sdhci-bcm2835.c by Stephen Warren and Oleksandr Tymoshenko
30 * sdhci.c and sdhci-pci.c by Pierre Ossman
37 #include <asm/arch/mbox.h>
48 #define SDCMD 0x00 /* Command to SD card - 16 R/W */
49 #define SDARG 0x04 /* Argument to SD card - 32 R/W */
50 #define SDTOUT 0x08 /* Start value for timeout counter - 32 R/W */
51 #define SDCDIV 0x0c /* Start value for clock divider - 11 R/W */
52 #define SDRSP0 0x10 /* SD card response (31:0) - 32 R */
53 #define SDRSP1 0x14 /* SD card response (63:32) - 32 R */
54 #define SDRSP2 0x18 /* SD card response (95:64) - 32 R */
55 #define SDRSP3 0x1c /* SD card response (127:96) - 32 R */
56 #define SDHSTS 0x20 /* SD host status - 11 R/W */
57 #define SDVDD 0x30 /* SD card power control - 1 R/W */
58 #define SDEDM 0x34 /* Emergency Debug Mode - 13 R/W */
59 #define SDHCFG 0x38 /* Host configuration - 2 R/W */
60 #define SDHBCT 0x3c /* Host byte count (debug) - 32 R/W */
61 #define SDDATA 0x40 /* Data to/from SD card - 32 R/W */
62 #define SDHBLC 0x50 /* Host block count (SDIO/SDHC) - 9 R/W */
185 dev_dbg(dev, "SDCMD 0x%08x\n", readl(host->ioaddr + SDCMD)); in bcm2835_dumpregs()
186 dev_dbg(dev, "SDARG 0x%08x\n", readl(host->ioaddr + SDARG)); in bcm2835_dumpregs()
187 dev_dbg(dev, "SDTOUT 0x%08x\n", readl(host->ioaddr + SDTOUT)); in bcm2835_dumpregs()
188 dev_dbg(dev, "SDCDIV 0x%08x\n", readl(host->ioaddr + SDCDIV)); in bcm2835_dumpregs()
189 dev_dbg(dev, "SDRSP0 0x%08x\n", readl(host->ioaddr + SDRSP0)); in bcm2835_dumpregs()
190 dev_dbg(dev, "SDRSP1 0x%08x\n", readl(host->ioaddr + SDRSP1)); in bcm2835_dumpregs()
191 dev_dbg(dev, "SDRSP2 0x%08x\n", readl(host->ioaddr + SDRSP2)); in bcm2835_dumpregs()
192 dev_dbg(dev, "SDRSP3 0x%08x\n", readl(host->ioaddr + SDRSP3)); in bcm2835_dumpregs()
193 dev_dbg(dev, "SDHSTS 0x%08x\n", readl(host->ioaddr + SDHSTS)); in bcm2835_dumpregs()
194 dev_dbg(dev, "SDVDD 0x%08x\n", readl(host->ioaddr + SDVDD)); in bcm2835_dumpregs()
195 dev_dbg(dev, "SDEDM 0x%08x\n", readl(host->ioaddr + SDEDM)); in bcm2835_dumpregs()
196 dev_dbg(dev, "SDHCFG 0x%08x\n", readl(host->ioaddr + SDHCFG)); in bcm2835_dumpregs()
197 dev_dbg(dev, "SDHBCT 0x%08x\n", readl(host->ioaddr + SDHBCT)); in bcm2835_dumpregs()
198 dev_dbg(dev, "SDHBLC 0x%08x\n", readl(host->ioaddr + SDHBLC)); in bcm2835_dumpregs()
206 writel(SDVDD_POWER_OFF, host->ioaddr + SDVDD); in bcm2835_reset_internal()
207 writel(0, host->ioaddr + SDCMD); in bcm2835_reset_internal()
208 writel(0, host->ioaddr + SDARG); in bcm2835_reset_internal()
210 writel(0xf00000, host->ioaddr + SDTOUT); in bcm2835_reset_internal()
211 writel(0, host->ioaddr + SDCDIV); in bcm2835_reset_internal()
213 writel(SDHSTS_CLEAR_MASK, host->ioaddr + SDHSTS); in bcm2835_reset_internal()
214 writel(0, host->ioaddr + SDHCFG); in bcm2835_reset_internal()
215 writel(0, host->ioaddr + SDHBCT); in bcm2835_reset_internal()
216 writel(0, host->ioaddr + SDHBLC); in bcm2835_reset_internal()
219 temp = readl(host->ioaddr + SDEDM); in bcm2835_reset_internal()
224 writel(temp, host->ioaddr + SDEDM); in bcm2835_reset_internal()
227 writel(SDVDD_POWER_ON, host->ioaddr + SDVDD); in bcm2835_reset_internal()
230 host->clock = 0; in bcm2835_reset_internal()
231 writel(host->hcfg, host->ioaddr + SDHCFG); in bcm2835_reset_internal()
232 writel(host->cdiv, host->ioaddr + SDCDIV); in bcm2835_reset_internal()
242 edm = readl(host->ioaddr + SDEDM); in bcm2835_wait_transfer_complete()
253 host->ioaddr + SDEDM); in bcm2835_wait_transfer_complete()
259 dev_err(host->dev, in bcm2835_wait_transfer_complete()
260 "wait_transfer_complete - still waiting after %d retries\n", in bcm2835_wait_transfer_complete()
263 return -ETIMEDOUT; in bcm2835_wait_transfer_complete()
272 struct mmc_data *data = host->data; in bcm2835_transfer_block_pio()
273 size_t blksize = data->blocksize; in bcm2835_transfer_block_pio()
279 return -EINVAL; in bcm2835_transfer_block_pio()
281 buf = is_read ? (u32 *)data->dest : (u32 *)data->src; in bcm2835_transfer_block_pio()
284 data->dest += blksize; in bcm2835_transfer_block_pio()
286 data->src += blksize; in bcm2835_transfer_block_pio()
299 edm = readl(host->ioaddr + SDEDM); in bcm2835_transfer_block_pio()
303 words = SDDATA_FIFO_WORDS - edm_fifo_fill(edm); in bcm2835_transfer_block_pio()
319 hsts = readl(host->ioaddr + SDHSTS); in bcm2835_transfer_block_pio()
330 copy_words -= words; in bcm2835_transfer_block_pio()
335 *(buf++) = readl(host->ioaddr + SDDATA); in bcm2835_transfer_block_pio()
337 writel(*(buf++), host->ioaddr + SDDATA); in bcm2835_transfer_block_pio()
338 words--; in bcm2835_transfer_block_pio()
351 is_read = (host->data->flags & MMC_DATA_READ) != 0; in bcm2835_transfer_pio()
356 sdhsts = readl(host->ioaddr + SDHSTS); in bcm2835_transfer_pio()
360 printf("%s transfer error - HSTS %08x\n", in bcm2835_transfer_pio()
362 ret = -EILSEQ; in bcm2835_transfer_pio()
365 printf("%s timeout error - HSTS %08x\n", in bcm2835_transfer_pio()
367 ret = -ETIMEDOUT; in bcm2835_transfer_pio()
376 WARN_ON(host->data); in bcm2835_prepare_data()
378 host->data = data; in bcm2835_prepare_data()
383 host->blocks = data->blocks; in bcm2835_prepare_data()
385 writel(data->blocksize, host->ioaddr + SDHBCT); in bcm2835_prepare_data()
386 writel(data->blocks, host->ioaddr + SDHBLC); in bcm2835_prepare_data()
395 ret = readl_poll_timeout(host->ioaddr + SDCMD, value, in bcm2835_read_wait_sdcmd()
397 if (ret == -ETIMEDOUT) in bcm2835_read_wait_sdcmd()
408 WARN_ON(host->cmd); in bcm2835_send_command()
410 if ((cmd->resp_type & MMC_RSP_136) && (cmd->resp_type & MMC_RSP_BUSY)) { in bcm2835_send_command()
412 return -EINVAL; in bcm2835_send_command()
419 return -EBUSY; in bcm2835_send_command()
422 host->cmd = cmd; in bcm2835_send_command()
425 sdhsts = readl(host->ioaddr + SDHSTS); in bcm2835_send_command()
427 writel(sdhsts, host->ioaddr + SDHSTS); in bcm2835_send_command()
431 writel(cmd->cmdarg, host->ioaddr + SDARG); in bcm2835_send_command()
433 sdcmd = cmd->cmdidx & SDCMD_CMD_MASK; in bcm2835_send_command()
435 host->use_busy = false; in bcm2835_send_command()
436 if (!(cmd->resp_type & MMC_RSP_PRESENT)) { in bcm2835_send_command()
439 if (cmd->resp_type & MMC_RSP_136) in bcm2835_send_command()
441 if (cmd->resp_type & MMC_RSP_BUSY) { in bcm2835_send_command()
443 host->use_busy = true; in bcm2835_send_command()
448 if (data->flags & MMC_DATA_WRITE) in bcm2835_send_command()
450 if (data->flags & MMC_DATA_READ) in bcm2835_send_command()
454 writel(sdcmd | SDCMD_NEW_FLAG, host->ioaddr + SDCMD); in bcm2835_send_command()
461 struct mmc_cmd *cmd = host->cmd; in bcm2835_finish_command()
471 return -EIO; in bcm2835_finish_command()
473 u32 sdhsts = readl(host->ioaddr + SDHSTS); in bcm2835_finish_command()
476 writel(SDHSTS_ERROR_MASK, host->ioaddr + SDHSTS); in bcm2835_finish_command()
479 (host->cmd->cmdidx != MMC_CMD_SEND_OP_COND)) { in bcm2835_finish_command()
481 ret = -ETIMEDOUT; in bcm2835_finish_command()
484 host->cmd->cmdidx); in bcm2835_finish_command()
486 ret = -EILSEQ; in bcm2835_finish_command()
493 if (cmd->resp_type & MMC_RSP_PRESENT) { in bcm2835_finish_command()
494 if (cmd->resp_type & MMC_RSP_136) { in bcm2835_finish_command()
498 cmd->response[3 - i] = in bcm2835_finish_command()
499 readl(host->ioaddr + SDRSP0 + i * 4); in bcm2835_finish_command()
502 cmd->response[0] = readl(host->ioaddr + SDRSP0); in bcm2835_finish_command()
507 host->cmd = NULL; in bcm2835_finish_command()
514 int ret = -EINVAL; in bcm2835_check_cmd_error()
519 if (!host->cmd) in bcm2835_check_cmd_error()
520 return -EINVAL; in bcm2835_check_cmd_error()
524 ret = -EILSEQ; in bcm2835_check_cmd_error()
527 ret = -EILSEQ; in bcm2835_check_cmd_error()
529 ret = -ETIMEDOUT; in bcm2835_check_cmd_error()
539 if (!host->data) in bcm2835_check_data_error()
542 ret = -EILSEQ; in bcm2835_check_data_error()
544 ret = -ETIMEDOUT; in bcm2835_check_data_error()
554 u32 intmask = readl(host->ioaddr + SDHSTS); in bcm2835_transmit()
567 if (host->use_busy && (intmask & SDHSTS_BUSY_IRPT)) { in bcm2835_transmit()
568 writel(SDHSTS_BUSY_IRPT, host->ioaddr + SDHSTS); in bcm2835_transmit()
569 host->use_busy = false; in bcm2835_transmit()
574 if (host->data) { in bcm2835_transmit()
578 host->blocks--; in bcm2835_transmit()
579 if (host->blocks == 0) { in bcm2835_transmit()
585 host->data = NULL; in bcm2835_transmit()
596 /* The SDCDIV register has 11 bits, and holds (div - 2). But in bcm2835_set_clock()
601 * must be 100-400KHz, so can range check the requested in bcm2835_set_clock()
605 * clock 250MHz -> 0->125MHz, 1->83.3MHz, 2->62.5MHz, 3->50.0MHz in bcm2835_set_clock()
606 * 4->41.7MHz, 5->35.7MHz, 6->31.3MHz, 7->27.8MHz in bcm2835_set_clock()
608 * 623->400KHz/27.8MHz in bcm2835_set_clock()
609 * reset value (507)->491159/50MHz in bcm2835_set_clock()
611 * BUT, the 3-bit clock divisor in data mode is too small if in bcm2835_set_clock()
621 host->cdiv = SDCDIV_MAX_CDIV; in bcm2835_set_clock()
622 writel(host->cdiv, host->ioaddr + SDCDIV); in bcm2835_set_clock()
626 div = host->max_clk / clock; in bcm2835_set_clock()
629 if ((host->max_clk / div) > clock) in bcm2835_set_clock()
631 div -= 2; in bcm2835_set_clock()
636 clock = host->max_clk / (div + 2); in bcm2835_set_clock()
637 host->mmc->clock = clock; in bcm2835_set_clock()
641 host->ns_per_fifo_word = (1000000000 / clock) * in bcm2835_set_clock()
642 ((host->mmc->card_caps & MMC_MODE_4BIT) ? 8 : 32); in bcm2835_set_clock()
644 host->cdiv = div; in bcm2835_set_clock()
645 writel(host->cdiv, host->ioaddr + SDCDIV); in bcm2835_set_clock()
648 writel(host->mmc->clock / 2, host->ioaddr + SDTOUT); in bcm2835_set_clock()
653 return !(x & (x - 1)); in is_power_of_2()
663 if (data && !is_power_of_2(data->blocksize)) { in bcm2835_send_cmd()
664 printf("unsupported block size (%d bytes)\n", data->blocksize); in bcm2835_send_cmd()
667 return -EINVAL; in bcm2835_send_cmd()
670 edm = readl(host->ioaddr + SDEDM); in bcm2835_send_cmd()
675 (cmd && cmd->cmdidx != MMC_CMD_STOP_TRANSMISSION)) { in bcm2835_send_cmd()
677 readl(host->ioaddr + SDCMD) & SDCMD_CMD_MASK, edm); in bcm2835_send_cmd()
681 return -EILSEQ; in bcm2835_send_cmd()
688 if (!ret && !host->use_busy) in bcm2835_send_cmd()
693 while (host->use_busy || host->data) { in bcm2835_send_cmd()
707 if (!mmc->clock || mmc->clock != host->clock) { in bcm2835_set_ios()
708 bcm2835_set_clock(host, mmc->clock); in bcm2835_set_ios()
709 host->clock = mmc->clock; in bcm2835_set_ios()
713 host->hcfg &= ~SDHCFG_WIDE_EXT_BUS; in bcm2835_set_ios()
714 if (mmc->bus_width == 4) in bcm2835_set_ios()
715 host->hcfg |= SDHCFG_WIDE_EXT_BUS; in bcm2835_set_ios()
717 host->hcfg |= SDHCFG_WIDE_INT_BUS; in bcm2835_set_ios()
720 host->hcfg |= SDHCFG_SLOW_CARD; in bcm2835_set_ios()
722 writel(host->hcfg, host->ioaddr + SDHCFG); in bcm2835_set_ios()
729 struct mmc_config *cfg = &host->plat->cfg; in bcm2835_add_host()
731 cfg->f_max = host->max_clk; in bcm2835_add_host()
732 cfg->f_min = host->max_clk / SDCDIV_MAX_CDIV; in bcm2835_add_host()
733 cfg->b_max = 65535; in bcm2835_add_host()
736 cfg->f_max, cfg->f_min); in bcm2835_add_host()
739 cfg->host_caps = MMC_MODE_4BIT | MMC_MODE_HS | MMC_MODE_HS_52MHz; in bcm2835_add_host()
742 cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; in bcm2835_add_host()
745 host->hcfg = SDHCFG_BUSY_IRPT_EN; in bcm2835_add_host()
757 host->dev = dev; in bcm2835_probe()
758 host->mmc = mmc; in bcm2835_probe()
759 host->plat = plat; in bcm2835_probe()
760 upriv->mmc = &plat->mmc; in bcm2835_probe()
761 plat->cfg.name = dev->name; in bcm2835_probe()
763 host->phys_addr = devfdt_get_addr(dev); in bcm2835_probe()
764 if (host->phys_addr == FDT_ADDR_T_NONE) in bcm2835_probe()
765 return -EINVAL; in bcm2835_probe()
767 host->ioaddr = devm_ioremap(dev, host->phys_addr, SZ_256); in bcm2835_probe()
768 if (!host->ioaddr) in bcm2835_probe()
769 return -ENOMEM; in bcm2835_probe()
771 host->max_clk = bcm2835_get_mmc_clock(BCM2835_MBOX_CLOCK_ID_CORE); in bcm2835_probe()
775 dev_dbg(dev, "%s -> OK\n", __func__); in bcm2835_probe()
781 { .compatible = "brcm,bcm2835-sdhost" },
794 return mmc_bind(dev, &plat->mmc, &plat->cfg); in bcm2835_bind()
798 .name = "bcm2835-sdhost",