Lines Matching full:host
22 * and is based on drivers/mmc/host/bcm2835.c in Linux which is written by
56 #define SDHSTS 0x20 /* SD host status - 11 R/W */
59 #define SDHCFG 0x38 /* Host configuration - 2 R/W */
60 #define SDHBCT 0x3c /* Host byte count (debug) - 32 R/W */
62 #define SDHBLC 0x50 /* Host block count (SDIO/SDHC) - 9 R/W */
182 static void bcm2835_dumpregs(struct bcm2835_host *host) in bcm2835_dumpregs() argument
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()
202 static void bcm2835_reset_internal(struct bcm2835_host *host) in bcm2835_reset_internal() argument
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()
235 static int bcm2835_wait_transfer_complete(struct bcm2835_host *host) in bcm2835_wait_transfer_complete() argument
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()
262 bcm2835_dumpregs(host); in bcm2835_wait_transfer_complete()
270 static int bcm2835_transfer_block_pio(struct bcm2835_host *host, bool is_read) in bcm2835_transfer_block_pio() argument
272 struct mmc_data *data = host->data; in bcm2835_transfer_block_pio()
299 edm = readl(host->ioaddr + SDEDM); in bcm2835_transfer_block_pio()
319 hsts = readl(host->ioaddr + SDHSTS); 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()
345 static int bcm2835_transfer_pio(struct bcm2835_host *host) in bcm2835_transfer_pio() argument
351 is_read = (host->data->flags & MMC_DATA_READ) != 0; in bcm2835_transfer_pio()
352 ret = bcm2835_transfer_block_pio(host, is_read); in bcm2835_transfer_pio()
356 sdhsts = readl(host->ioaddr + SDHSTS); in bcm2835_transfer_pio()
373 static void bcm2835_prepare_data(struct bcm2835_host *host, struct mmc_cmd *cmd, in bcm2835_prepare_data() argument
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()
389 static u32 bcm2835_read_wait_sdcmd(struct bcm2835_host *host) in bcm2835_read_wait_sdcmd() argument
395 ret = readl_poll_timeout(host->ioaddr + SDCMD, value, in bcm2835_read_wait_sdcmd()
403 static int bcm2835_send_command(struct bcm2835_host *host, struct mmc_cmd *cmd, in bcm2835_send_command() argument
408 WARN_ON(host->cmd); in bcm2835_send_command()
415 sdcmd = bcm2835_read_wait_sdcmd(host); in bcm2835_send_command()
418 bcm2835_dumpregs(host); 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()
429 bcm2835_prepare_data(host, cmd, data); in bcm2835_send_command()
431 writel(cmd->cmdarg, host->ioaddr + SDARG); in bcm2835_send_command()
435 host->use_busy = false; in bcm2835_send_command()
443 host->use_busy = true; in bcm2835_send_command()
454 writel(sdcmd | SDCMD_NEW_FLAG, host->ioaddr + SDCMD); in bcm2835_send_command()
459 static int bcm2835_finish_command(struct bcm2835_host *host) in bcm2835_finish_command() argument
461 struct mmc_cmd *cmd = host->cmd; in bcm2835_finish_command()
465 sdcmd = bcm2835_read_wait_sdcmd(host); in bcm2835_finish_command()
470 bcm2835_dumpregs(host); 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()
484 host->cmd->cmdidx); in bcm2835_finish_command()
485 bcm2835_dumpregs(host); 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()
512 static int bcm2835_check_cmd_error(struct bcm2835_host *host, u32 intmask) in bcm2835_check_cmd_error() argument
519 if (!host->cmd) in bcm2835_check_cmd_error()
531 bcm2835_dumpregs(host); in bcm2835_check_cmd_error()
535 static int bcm2835_check_data_error(struct bcm2835_host *host, u32 intmask) in bcm2835_check_data_error() argument
539 if (!host->data) in bcm2835_check_data_error()
552 static int bcm2835_transmit(struct bcm2835_host *host) in bcm2835_transmit() argument
554 u32 intmask = readl(host->ioaddr + SDHSTS); in bcm2835_transmit()
558 ret = bcm2835_check_data_error(host, intmask); in bcm2835_transmit()
562 ret = bcm2835_check_cmd_error(host, intmask); 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()
570 bcm2835_finish_command(host); in bcm2835_transmit()
574 if (host->data) { in bcm2835_transmit()
575 ret = bcm2835_transfer_pio(host); in bcm2835_transmit()
578 host->blocks--; in bcm2835_transmit()
579 if (host->blocks == 0) { in bcm2835_transmit()
581 ret = bcm2835_wait_transfer_complete(host); in bcm2835_transmit()
585 host->data = NULL; in bcm2835_transmit()
592 static void bcm2835_set_clock(struct bcm2835_host *host, unsigned int clock) in bcm2835_set_clock() argument
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()
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()
659 struct bcm2835_host *host = dev_get_priv(dev); in bcm2835_send_cmd() local
670 edm = readl(host->ioaddr + SDEDM); in bcm2835_send_cmd()
677 readl(host->ioaddr + SDCMD) & SDCMD_CMD_MASK, edm); in bcm2835_send_cmd()
678 bcm2835_dumpregs(host); in bcm2835_send_cmd()
687 ret = bcm2835_send_command(host, cmd, data); in bcm2835_send_cmd()
688 if (!ret && !host->use_busy) in bcm2835_send_cmd()
689 ret = bcm2835_finish_command(host); in bcm2835_send_cmd()
693 while (host->use_busy || host->data) { in bcm2835_send_cmd()
694 ret = bcm2835_transmit(host); in bcm2835_send_cmd()
704 struct bcm2835_host *host = dev_get_priv(dev); in bcm2835_set_ios() local
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()
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()
727 static void bcm2835_add_host(struct bcm2835_host *host) in bcm2835_add_host() argument
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()
738 /* host controller capabilities */ in bcm2835_add_host()
745 host->hcfg = SDHCFG_BUSY_IRPT_EN; in bcm2835_add_host()
747 bcm2835_reset_internal(host); in bcm2835_add_host()
753 struct bcm2835_host *host = dev_get_priv(dev); in bcm2835_probe() local
757 host->dev = dev; in bcm2835_probe()
758 host->mmc = mmc; in bcm2835_probe()
759 host->plat = plat; 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()
767 host->ioaddr = devm_ioremap(dev, host->phys_addr, SZ_256); in bcm2835_probe()
768 if (!host->ioaddr) in bcm2835_probe()
771 host->max_clk = bcm2835_get_mmc_clock(BCM2835_MBOX_CLOCK_ID_CORE); in bcm2835_probe()
773 bcm2835_add_host(host); in bcm2835_probe()