Lines Matching full:host

3  *  linux/drivers/mmc/host/pxa.c - PXA MMCI driver
26 #include <linux/mmc/host.h>
76 static int pxamci_init_ocr(struct pxamci_host *host) in pxamci_init_ocr() argument
78 struct mmc_host *mmc = host->mmc; in pxamci_init_ocr()
87 mmc->ocr_avail = host->pdata ? in pxamci_init_ocr()
88 host->pdata->ocr_mask : in pxamci_init_ocr()
95 static inline int pxamci_set_power(struct pxamci_host *host, in pxamci_set_power() argument
99 struct mmc_host *mmc = host->mmc; in pxamci_set_power()
105 if (host->power) { in pxamci_set_power()
106 bool on = !!((1 << vdd) & host->pdata->ocr_mask); in pxamci_set_power()
107 gpiod_set_value(host->power, on); in pxamci_set_power()
110 if (host->pdata && host->pdata->setpower) in pxamci_set_power()
111 return host->pdata->setpower(mmc_dev(host->mmc), vdd); in pxamci_set_power()
116 static void pxamci_stop_clock(struct pxamci_host *host) in pxamci_stop_clock() argument
118 if (readl(host->base + MMC_STAT) & STAT_CLK_EN) { in pxamci_stop_clock()
122 writel(STOP_CLOCK, host->base + MMC_STRPCL); in pxamci_stop_clock()
125 v = readl(host->base + MMC_STAT); in pxamci_stop_clock()
132 dev_err(mmc_dev(host->mmc), "unable to stop clock\n"); in pxamci_stop_clock()
136 static void pxamci_enable_irq(struct pxamci_host *host, unsigned int mask) in pxamci_enable_irq() argument
140 spin_lock_irqsave(&host->lock, flags); in pxamci_enable_irq()
141 host->imask &= ~mask; in pxamci_enable_irq()
142 writel(host->imask, host->base + MMC_I_MASK); in pxamci_enable_irq()
143 spin_unlock_irqrestore(&host->lock, flags); in pxamci_enable_irq()
146 static void pxamci_disable_irq(struct pxamci_host *host, unsigned int mask) in pxamci_disable_irq() argument
150 spin_lock_irqsave(&host->lock, flags); in pxamci_disable_irq()
151 host->imask |= mask; in pxamci_disable_irq()
152 writel(host->imask, host->base + MMC_I_MASK); in pxamci_disable_irq()
153 spin_unlock_irqrestore(&host->lock, flags); in pxamci_disable_irq()
158 static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data) in pxamci_setup_data() argument
169 host->data = data; in pxamci_setup_data()
171 writel(nob, host->base + MMC_NOB); in pxamci_setup_data()
172 writel(data->blksz, host->base + MMC_BLKLEN); in pxamci_setup_data()
174 clks = (unsigned long long)data->timeout_ns * host->clkrate; in pxamci_setup_data()
176 timeout = (unsigned int)clks + (data->timeout_clks << host->clkrt); in pxamci_setup_data()
177 writel((timeout + 255) / 256, host->base + MMC_RDTO); in pxamci_setup_data()
182 config.src_addr = host->res->start + MMC_RXFIFO; in pxamci_setup_data()
183 config.dst_addr = host->res->start + MMC_TXFIFO; in pxamci_setup_data()
188 host->dma_dir = DMA_FROM_DEVICE; in pxamci_setup_data()
190 chan = host->dma_chan_rx; in pxamci_setup_data()
192 host->dma_dir = DMA_TO_DEVICE; in pxamci_setup_data()
194 chan = host->dma_chan_tx; in pxamci_setup_data()
201 dev_err(mmc_dev(host->mmc), "dma slave config failed\n"); in pxamci_setup_data()
205 host->dma_len = dma_map_sg(chan->device->dev, data->sg, data->sg_len, in pxamci_setup_data()
206 host->dma_dir); in pxamci_setup_data()
208 tx = dmaengine_prep_slave_sg(chan, data->sg, host->dma_len, direction, in pxamci_setup_data()
211 dev_err(mmc_dev(host->mmc), "prep_slave_sg() failed\n"); in pxamci_setup_data()
217 tx->callback_param = host; in pxamci_setup_data()
220 host->dma_cookie = dmaengine_submit(tx); in pxamci_setup_data()
232 static void pxamci_start_cmd(struct pxamci_host *host, struct mmc_command *cmd, unsigned int cmdat) in pxamci_start_cmd() argument
234 WARN_ON(host->cmd != NULL); in pxamci_start_cmd()
235 host->cmd = cmd; in pxamci_start_cmd()
255 writel(cmd->opcode, host->base + MMC_CMD); in pxamci_start_cmd()
256 writel(cmd->arg >> 16, host->base + MMC_ARGH); in pxamci_start_cmd()
257 writel(cmd->arg & 0xffff, host->base + MMC_ARGL); in pxamci_start_cmd()
258 writel(cmdat, host->base + MMC_CMDAT); in pxamci_start_cmd()
259 writel(host->clkrt, host->base + MMC_CLKRT); in pxamci_start_cmd()
261 writel(START_CLOCK, host->base + MMC_STRPCL); in pxamci_start_cmd()
263 pxamci_enable_irq(host, END_CMD_RES); in pxamci_start_cmd()
266 static void pxamci_finish_request(struct pxamci_host *host, struct mmc_request *mrq) in pxamci_finish_request() argument
268 host->mrq = NULL; in pxamci_finish_request()
269 host->cmd = NULL; in pxamci_finish_request()
270 host->data = NULL; in pxamci_finish_request()
271 mmc_request_done(host->mmc, mrq); in pxamci_finish_request()
274 static int pxamci_cmd_done(struct pxamci_host *host, unsigned int stat) in pxamci_cmd_done() argument
276 struct mmc_command *cmd = host->cmd; in pxamci_cmd_done()
283 host->cmd = NULL; in pxamci_cmd_done()
289 v = readl(host->base + MMC_RES) & 0xffff; in pxamci_cmd_done()
291 u32 w1 = readl(host->base + MMC_RES) & 0xffff; in pxamci_cmd_done()
292 u32 w2 = readl(host->base + MMC_RES) & 0xffff; in pxamci_cmd_done()
313 pxamci_disable_irq(host, END_CMD_RES); in pxamci_cmd_done()
314 if (host->data && !cmd->error) { in pxamci_cmd_done()
315 pxamci_enable_irq(host, DATA_TRAN_DONE); in pxamci_cmd_done()
320 if (cpu_is_pxa27x() && host->data->flags & MMC_DATA_WRITE) in pxamci_cmd_done()
321 dma_async_issue_pending(host->dma_chan_tx); in pxamci_cmd_done()
323 pxamci_finish_request(host, host->mrq); in pxamci_cmd_done()
329 static int pxamci_data_done(struct pxamci_host *host, unsigned int stat) in pxamci_data_done() argument
331 struct mmc_data *data = host->data; in pxamci_data_done()
338 chan = host->dma_chan_rx; in pxamci_data_done()
340 chan = host->dma_chan_tx; in pxamci_data_done()
342 data->sg, data->sg_len, host->dma_dir); in pxamci_data_done()
360 pxamci_disable_irq(host, DATA_TRAN_DONE); in pxamci_data_done()
362 host->data = NULL; in pxamci_data_done()
363 if (host->mrq->stop) { in pxamci_data_done()
364 pxamci_stop_clock(host); in pxamci_data_done()
365 pxamci_start_cmd(host, host->mrq->stop, host->cmdat); in pxamci_data_done()
367 pxamci_finish_request(host, host->mrq); in pxamci_data_done()
375 struct pxamci_host *host = devid; in pxamci_irq() local
379 ireg = readl(host->base + MMC_I_REG) & ~readl(host->base + MMC_I_MASK); in pxamci_irq()
382 unsigned stat = readl(host->base + MMC_STAT); in pxamci_irq()
387 handled |= pxamci_cmd_done(host, stat); in pxamci_irq()
389 handled |= pxamci_data_done(host, stat); in pxamci_irq()
391 mmc_signal_sdio_irq(host->mmc); in pxamci_irq()
401 struct pxamci_host *host = mmc_priv(mmc); in pxamci_request() local
404 WARN_ON(host->mrq != NULL); in pxamci_request()
406 host->mrq = mrq; in pxamci_request()
408 pxamci_stop_clock(host); in pxamci_request()
410 cmdat = host->cmdat; in pxamci_request()
411 host->cmdat &= ~CMDAT_INIT; in pxamci_request()
414 pxamci_setup_data(host, mrq->data); in pxamci_request()
422 pxamci_start_cmd(host, mrq->cmd, cmdat); in pxamci_request()
427 struct pxamci_host *host = mmc_priv(mmc); in pxamci_get_ro() local
429 if (host->use_ro_gpio) in pxamci_get_ro()
431 if (host->pdata && host->pdata->get_ro) in pxamci_get_ro()
432 return !!host->pdata->get_ro(mmc_dev(mmc)); in pxamci_get_ro()
442 struct pxamci_host *host = mmc_priv(mmc); in pxamci_set_ios() local
445 unsigned long rate = host->clkrate; in pxamci_set_ios()
448 if (host->clkrt == CLKRT_OFF) in pxamci_set_ios()
449 clk_prepare_enable(host->clk); in pxamci_set_ios()
453 host->clkrt = 7; in pxamci_set_ios()
466 host->clkrt = fls(clk) - 1; in pxamci_set_ios()
473 pxamci_stop_clock(host); in pxamci_set_ios()
474 if (host->clkrt != CLKRT_OFF) { in pxamci_set_ios()
475 host->clkrt = CLKRT_OFF; in pxamci_set_ios()
476 clk_disable_unprepare(host->clk); in pxamci_set_ios()
480 if (host->power_mode != ios->power_mode) { in pxamci_set_ios()
483 host->power_mode = ios->power_mode; in pxamci_set_ios()
485 ret = pxamci_set_power(host, ios->power_mode, ios->vdd); in pxamci_set_ios()
498 host->cmdat |= CMDAT_INIT; in pxamci_set_ios()
502 host->cmdat |= CMDAT_SD_4DAT; in pxamci_set_ios()
504 host->cmdat &= ~CMDAT_SD_4DAT; in pxamci_set_ios()
507 host->clkrt, host->cmdat); in pxamci_set_ios()
510 static void pxamci_enable_sdio_irq(struct mmc_host *host, int enable) in pxamci_enable_sdio_irq() argument
512 struct pxamci_host *pxa_host = mmc_priv(host); in pxamci_enable_sdio_irq()
530 struct pxamci_host *host = param; in pxamci_dma_irq() local
536 spin_lock_irqsave(&host->lock, flags); in pxamci_dma_irq()
538 if (!host->data) in pxamci_dma_irq()
541 if (host->data->flags & MMC_DATA_READ) in pxamci_dma_irq()
542 chan = host->dma_chan_rx; in pxamci_dma_irq()
544 chan = host->dma_chan_tx; in pxamci_dma_irq()
546 status = dmaengine_tx_status(chan, host->dma_cookie, &state); in pxamci_dma_irq()
549 writel(BUF_PART_FULL, host->base + MMC_PRTBUF); in pxamci_dma_irq()
551 pr_err("%s: DMA error on %s channel\n", mmc_hostname(host->mmc), in pxamci_dma_irq()
552 host->data->flags & MMC_DATA_READ ? "rx" : "tx"); in pxamci_dma_irq()
553 host->data->error = -EIO; in pxamci_dma_irq()
554 pxamci_data_done(host, 0); in pxamci_dma_irq()
558 spin_unlock_irqrestore(&host->lock, flags); in pxamci_dma_irq()
563 struct pxamci_host *host = mmc_priv(devid); in pxamci_detect_irq() local
565 mmc_detect_change(devid, msecs_to_jiffies(host->detect_delay_ms)); in pxamci_detect_irq()
581 struct pxamci_host *host = mmc_priv(mmc); in pxamci_of_init() local
590 host->detect_delay_ms = tmp; in pxamci_of_init()
609 struct pxamci_host *host = NULL; in pxamci_probe() local
651 host = mmc_priv(mmc); in pxamci_probe()
652 host->mmc = mmc; in pxamci_probe()
653 host->pdata = pdev->dev.platform_data; in pxamci_probe()
654 host->clkrt = CLKRT_OFF; in pxamci_probe()
656 host->clk = devm_clk_get(dev, NULL); in pxamci_probe()
657 if (IS_ERR(host->clk)) { in pxamci_probe()
658 ret = PTR_ERR(host->clk); in pxamci_probe()
659 host->clk = NULL; in pxamci_probe()
663 host->clkrate = clk_get_rate(host->clk); in pxamci_probe()
668 mmc->f_min = (host->clkrate + 63) / 64; in pxamci_probe()
669 mmc->f_max = (mmc_has_26MHz()) ? 26000000 : host->clkrate; in pxamci_probe()
671 ret = pxamci_init_ocr(host); in pxamci_probe()
676 host->cmdat = 0; in pxamci_probe()
679 host->cmdat |= CMDAT_SDIO_INT_EN; in pxamci_probe()
685 spin_lock_init(&host->lock); in pxamci_probe()
686 host->imask = MMC_I_MASK_ALL; in pxamci_probe()
688 host->base = devm_platform_get_and_ioremap_resource(pdev, 0, &r); in pxamci_probe()
689 if (IS_ERR(host->base)) { in pxamci_probe()
690 ret = PTR_ERR(host->base); in pxamci_probe()
693 host->res = r; in pxamci_probe()
696 * Ensure that the host controller is shut down, and setup in pxamci_probe()
699 pxamci_stop_clock(host); in pxamci_probe()
700 writel(0, host->base + MMC_SPI); in pxamci_probe()
701 writel(64, host->base + MMC_RESTO); in pxamci_probe()
702 writel(host->imask, host->base + MMC_I_MASK); in pxamci_probe()
705 DRIVER_NAME, host); in pxamci_probe()
711 host->dma_chan_rx = dma_request_chan(dev, "rx"); in pxamci_probe()
712 if (IS_ERR(host->dma_chan_rx)) { in pxamci_probe()
714 ret = PTR_ERR(host->dma_chan_rx); in pxamci_probe()
715 host->dma_chan_rx = NULL; in pxamci_probe()
719 host->dma_chan_tx = dma_request_chan(dev, "tx"); in pxamci_probe()
720 if (IS_ERR(host->dma_chan_tx)) { in pxamci_probe()
722 ret = PTR_ERR(host->dma_chan_tx); in pxamci_probe()
723 host->dma_chan_tx = NULL; in pxamci_probe()
727 if (host->pdata) { in pxamci_probe()
728 host->detect_delay_ms = host->pdata->detect_delay_ms; in pxamci_probe()
730 host->power = devm_gpiod_get_optional(dev, "power", GPIOD_OUT_LOW); in pxamci_probe()
731 if (IS_ERR(host->power)) { in pxamci_probe()
732 ret = PTR_ERR(host->power); in pxamci_probe()
744 if (!host->pdata->gpio_card_ro_invert) in pxamci_probe()
753 host->use_ro_gpio = true; in pxamci_probe()
755 if (host->pdata->init) in pxamci_probe()
756 host->pdata->init(dev, pxamci_detect_irq, mmc); in pxamci_probe()
758 if (host->power && host->pdata->setpower) in pxamci_probe()
760 if (host->use_ro_gpio && host->pdata->get_ro) in pxamci_probe()
766 if (host->pdata && host->pdata->exit) in pxamci_probe()
767 host->pdata->exit(dev, mmc); in pxamci_probe()
774 if (host) { in pxamci_probe()
775 if (host->dma_chan_rx) in pxamci_probe()
776 dma_release_channel(host->dma_chan_rx); in pxamci_probe()
777 if (host->dma_chan_tx) in pxamci_probe()
778 dma_release_channel(host->dma_chan_tx); in pxamci_probe()
790 struct pxamci_host *host = mmc_priv(mmc); in pxamci_remove() local
794 if (host->pdata && host->pdata->exit) in pxamci_remove()
795 host->pdata->exit(&pdev->dev, mmc); in pxamci_remove()
797 pxamci_stop_clock(host); in pxamci_remove()
800 host->base + MMC_I_MASK); in pxamci_remove()
802 dmaengine_terminate_all(host->dma_chan_rx); in pxamci_remove()
803 dmaengine_terminate_all(host->dma_chan_tx); in pxamci_remove()
804 dma_release_channel(host->dma_chan_rx); in pxamci_remove()
805 dma_release_channel(host->dma_chan_tx); in pxamci_remove()