Lines Matching refs:host
205 static void usdhi6_write(struct usdhi6_host *host, u32 reg, u32 data) in usdhi6_write() argument
207 iowrite32(data, host->base + reg); in usdhi6_write()
208 dev_vdbg(mmc_dev(host->mmc), "%s(0x%p + 0x%x) = 0x%x\n", __func__, in usdhi6_write()
209 host->base, reg, data); in usdhi6_write()
212 static void usdhi6_write16(struct usdhi6_host *host, u32 reg, u16 data) in usdhi6_write16() argument
214 iowrite16(data, host->base + reg); in usdhi6_write16()
215 dev_vdbg(mmc_dev(host->mmc), "%s(0x%p + 0x%x) = 0x%x\n", __func__, in usdhi6_write16()
216 host->base, reg, data); in usdhi6_write16()
219 static u32 usdhi6_read(struct usdhi6_host *host, u32 reg) in usdhi6_read() argument
221 u32 data = ioread32(host->base + reg); in usdhi6_read()
222 dev_vdbg(mmc_dev(host->mmc), "%s(0x%p + 0x%x) = 0x%x\n", __func__, in usdhi6_read()
223 host->base, reg, data); in usdhi6_read()
227 static u16 usdhi6_read16(struct usdhi6_host *host, u32 reg) in usdhi6_read16() argument
229 u16 data = ioread16(host->base + reg); in usdhi6_read16()
230 dev_vdbg(mmc_dev(host->mmc), "%s(0x%p + 0x%x) = 0x%x\n", __func__, in usdhi6_read16()
231 host->base, reg, data); in usdhi6_read16()
235 static void usdhi6_irq_enable(struct usdhi6_host *host, u32 info1, u32 info2) in usdhi6_irq_enable() argument
237 host->status_mask = USDHI6_SD_INFO1_IRQ & ~info1; in usdhi6_irq_enable()
238 host->status2_mask = USDHI6_SD_INFO2_IRQ & ~info2; in usdhi6_irq_enable()
239 usdhi6_write(host, USDHI6_SD_INFO1_MASK, host->status_mask); in usdhi6_irq_enable()
240 usdhi6_write(host, USDHI6_SD_INFO2_MASK, host->status2_mask); in usdhi6_irq_enable()
243 static void usdhi6_wait_for_resp(struct usdhi6_host *host) in usdhi6_wait_for_resp() argument
245 usdhi6_irq_enable(host, USDHI6_SD_INFO1_RSP_END | in usdhi6_wait_for_resp()
250 static void usdhi6_wait_for_brwe(struct usdhi6_host *host, bool read) in usdhi6_wait_for_brwe() argument
252 usdhi6_irq_enable(host, USDHI6_SD_INFO1_ACCESS_END | in usdhi6_wait_for_brwe()
257 static void usdhi6_only_cd(struct usdhi6_host *host) in usdhi6_only_cd() argument
260 usdhi6_irq_enable(host, USDHI6_SD_INFO1_CARD_CD, 0); in usdhi6_only_cd()
263 static void usdhi6_mask_all(struct usdhi6_host *host) in usdhi6_mask_all() argument
265 usdhi6_irq_enable(host, 0, 0); in usdhi6_mask_all()
268 static int usdhi6_error_code(struct usdhi6_host *host) in usdhi6_error_code() argument
272 usdhi6_write(host, USDHI6_SD_STOP, USDHI6_SD_STOP_STP); in usdhi6_error_code()
274 if (host->io_error & in usdhi6_error_code()
276 u32 rsp54 = usdhi6_read(host, USDHI6_SD_RSP54); in usdhi6_error_code()
277 int opc = host->mrq ? host->mrq->cmd->opcode : -1; in usdhi6_error_code()
279 err = usdhi6_read(host, USDHI6_SD_ERR_STS2); in usdhi6_error_code()
281 if (host->wait == USDHI6_WAIT_FOR_CMD) in usdhi6_error_code()
282 dev_dbg(mmc_dev(host->mmc), in usdhi6_error_code()
284 err, rsp54, host->wait, opc); in usdhi6_error_code()
286 dev_warn(mmc_dev(host->mmc), in usdhi6_error_code()
288 err, rsp54, host->wait, opc); in usdhi6_error_code()
292 err = usdhi6_read(host, USDHI6_SD_ERR_STS1); in usdhi6_error_code()
294 dev_warn(mmc_dev(host->mmc), "Err sts 0x%x, state %u, CMD%d\n", in usdhi6_error_code()
295 err, host->wait, host->mrq ? host->mrq->cmd->opcode : -1); in usdhi6_error_code()
296 if (host->io_error & USDHI6_SD_INFO2_ILA) in usdhi6_error_code()
310 static void usdhi6_blk_bounce(struct usdhi6_host *host, in usdhi6_blk_bounce() argument
313 struct mmc_data *data = host->mrq->data; in usdhi6_blk_bounce()
314 size_t blk_head = host->head_len; in usdhi6_blk_bounce()
316 dev_dbg(mmc_dev(host->mmc), "%s(): CMD%u of %u SG: %ux%u @ 0x%x\n", in usdhi6_blk_bounce()
317 __func__, host->mrq->cmd->opcode, data->sg_len, in usdhi6_blk_bounce()
320 host->head_pg.page = host->pg.page; in usdhi6_blk_bounce()
321 host->head_pg.mapped = host->pg.mapped; in usdhi6_blk_bounce()
322 host->pg.page = nth_page(host->pg.page, 1); in usdhi6_blk_bounce()
323 host->pg.mapped = kmap(host->pg.page); in usdhi6_blk_bounce()
325 host->blk_page = host->bounce_buf; in usdhi6_blk_bounce()
326 host->offset = 0; in usdhi6_blk_bounce()
331 memcpy(host->bounce_buf, host->head_pg.mapped + PAGE_SIZE - blk_head, in usdhi6_blk_bounce()
333 memcpy(host->bounce_buf + blk_head, host->pg.mapped, in usdhi6_blk_bounce()
338 static void usdhi6_sg_prep(struct usdhi6_host *host) in usdhi6_sg_prep() argument
340 struct mmc_request *mrq = host->mrq; in usdhi6_sg_prep()
343 usdhi6_write(host, USDHI6_SD_SECCNT, data->blocks); in usdhi6_sg_prep()
345 host->sg = data->sg; in usdhi6_sg_prep()
347 host->offset = host->sg->offset; in usdhi6_sg_prep()
351 static void *usdhi6_sg_map(struct usdhi6_host *host) in usdhi6_sg_map() argument
353 struct mmc_data *data = host->mrq->data; in usdhi6_sg_map()
354 struct scatterlist *sg = data->sg_len > 1 ? host->sg : data->sg; in usdhi6_sg_map()
358 WARN(host->pg.page, "%p not properly unmapped!\n", host->pg.page); in usdhi6_sg_map()
364 host->pg.page = sg_page(sg); in usdhi6_sg_map()
365 host->pg.mapped = kmap(host->pg.page); in usdhi6_sg_map()
366 host->offset = sg->offset; in usdhi6_sg_map()
372 host->head_len = blk_head; in usdhi6_sg_map()
379 usdhi6_blk_bounce(host, sg); in usdhi6_sg_map()
381 host->blk_page = host->pg.mapped; in usdhi6_sg_map()
383 dev_dbg(mmc_dev(host->mmc), "Mapped %p (%lx) at %p + %u for CMD%u @ 0x%p\n", in usdhi6_sg_map()
384 host->pg.page, page_to_pfn(host->pg.page), host->pg.mapped, in usdhi6_sg_map()
385 sg->offset, host->mrq->cmd->opcode, host->mrq); in usdhi6_sg_map()
387 return host->blk_page + host->offset; in usdhi6_sg_map()
391 static void usdhi6_sg_unmap(struct usdhi6_host *host, bool force) in usdhi6_sg_unmap() argument
393 struct mmc_data *data = host->mrq->data; in usdhi6_sg_unmap()
394 struct page *page = host->head_pg.page; in usdhi6_sg_unmap()
399 host->sg : data->sg; in usdhi6_sg_unmap()
400 size_t blk_head = host->head_len; in usdhi6_sg_unmap()
403 memcpy(host->head_pg.mapped + PAGE_SIZE - blk_head, in usdhi6_sg_unmap()
404 host->bounce_buf, blk_head); in usdhi6_sg_unmap()
405 memcpy(host->pg.mapped, host->bounce_buf + blk_head, in usdhi6_sg_unmap()
412 host->head_pg.page = NULL; in usdhi6_sg_unmap()
415 (host->page_idx << PAGE_SHIFT) + data->blksz - blk_head) in usdhi6_sg_unmap()
420 page = host->pg.page; in usdhi6_sg_unmap()
427 host->pg.page = NULL; in usdhi6_sg_unmap()
431 static void usdhi6_sg_advance(struct usdhi6_host *host) in usdhi6_sg_advance() argument
433 struct mmc_data *data = host->mrq->data; in usdhi6_sg_advance()
437 if (host->head_pg.page) { in usdhi6_sg_advance()
439 host->page_idx++; in usdhi6_sg_advance()
440 host->offset = data->blksz - host->head_len; in usdhi6_sg_advance()
441 host->blk_page = host->pg.mapped; in usdhi6_sg_advance()
442 usdhi6_sg_unmap(host, false); in usdhi6_sg_advance()
444 host->offset += data->blksz; in usdhi6_sg_advance()
446 if (host->offset == PAGE_SIZE) { in usdhi6_sg_advance()
448 host->offset = 0; in usdhi6_sg_advance()
449 host->page_idx++; in usdhi6_sg_advance()
459 done = (host->page_idx << PAGE_SHIFT) + host->offset; in usdhi6_sg_advance()
460 total = host->sg->offset + sg_dma_len(host->sg); in usdhi6_sg_advance()
462 dev_dbg(mmc_dev(host->mmc), "%s(): %zu of %zu @ %zu\n", __func__, in usdhi6_sg_advance()
463 done, total, host->offset); in usdhi6_sg_advance()
465 if (done < total && host->offset) { in usdhi6_sg_advance()
467 if (host->offset + data->blksz > PAGE_SIZE) in usdhi6_sg_advance()
469 usdhi6_blk_bounce(host, host->sg); in usdhi6_sg_advance()
475 usdhi6_sg_unmap(host, false); in usdhi6_sg_advance()
483 struct scatterlist *next = sg_next(host->sg); in usdhi6_sg_advance()
485 host->page_idx = 0; in usdhi6_sg_advance()
488 host->wait = USDHI6_WAIT_FOR_DATA_END; in usdhi6_sg_advance()
489 host->sg = next; in usdhi6_sg_advance()
502 host->pg.page = nth_page(sg_page(host->sg), host->page_idx); in usdhi6_sg_advance()
503 host->pg.mapped = kmap(host->pg.page); in usdhi6_sg_advance()
504 host->blk_page = host->pg.mapped; in usdhi6_sg_advance()
506 dev_dbg(mmc_dev(host->mmc), "Mapped %p (%lx) at %p for CMD%u @ 0x%p\n", in usdhi6_sg_advance()
507 host->pg.page, page_to_pfn(host->pg.page), host->pg.mapped, in usdhi6_sg_advance()
508 host->mrq->cmd->opcode, host->mrq); in usdhi6_sg_advance()
513 static void usdhi6_dma_release(struct usdhi6_host *host) in usdhi6_dma_release() argument
515 host->dma_active = false; in usdhi6_dma_release()
516 if (host->chan_tx) { in usdhi6_dma_release()
517 struct dma_chan *chan = host->chan_tx; in usdhi6_dma_release()
518 host->chan_tx = NULL; in usdhi6_dma_release()
521 if (host->chan_rx) { in usdhi6_dma_release()
522 struct dma_chan *chan = host->chan_rx; in usdhi6_dma_release()
523 host->chan_rx = NULL; in usdhi6_dma_release()
528 static void usdhi6_dma_stop_unmap(struct usdhi6_host *host) in usdhi6_dma_stop_unmap() argument
530 struct mmc_data *data = host->mrq->data; in usdhi6_dma_stop_unmap()
532 if (!host->dma_active) in usdhi6_dma_stop_unmap()
535 usdhi6_write(host, USDHI6_CC_EXT_MODE, 0); in usdhi6_dma_stop_unmap()
536 host->dma_active = false; in usdhi6_dma_stop_unmap()
539 dma_unmap_sg(host->chan_rx->device->dev, data->sg, in usdhi6_dma_stop_unmap()
542 dma_unmap_sg(host->chan_tx->device->dev, data->sg, in usdhi6_dma_stop_unmap()
548 struct usdhi6_host *host = arg; in usdhi6_dma_complete() local
549 struct mmc_request *mrq = host->mrq; in usdhi6_dma_complete()
552 dev_name(mmc_dev(host->mmc)), mrq)) in usdhi6_dma_complete()
555 dev_dbg(mmc_dev(host->mmc), "%s(): CMD%u DMA completed\n", __func__, in usdhi6_dma_complete()
558 usdhi6_dma_stop_unmap(host); in usdhi6_dma_complete()
559 usdhi6_wait_for_brwe(host, mrq->data->flags & MMC_DATA_READ); in usdhi6_dma_complete()
562 static int usdhi6_dma_setup(struct usdhi6_host *host, struct dma_chan *chan, in usdhi6_dma_setup() argument
565 struct mmc_data *data = host->mrq->data; in usdhi6_dma_setup()
585 host->dma_active = true; in usdhi6_dma_setup()
592 desc->callback_param = host; in usdhi6_dma_setup()
596 dev_dbg(mmc_dev(host->mmc), "%s(): mapped %d -> %d, cookie %d @ %p\n", in usdhi6_dma_setup()
603 usdhi6_dma_release(host); in usdhi6_dma_setup()
604 dev_warn(mmc_dev(host->mmc), in usdhi6_dma_setup()
611 static int usdhi6_dma_start(struct usdhi6_host *host) in usdhi6_dma_start() argument
613 if (!host->chan_rx || !host->chan_tx) in usdhi6_dma_start()
616 if (host->mrq->data->flags & MMC_DATA_READ) in usdhi6_dma_start()
617 return usdhi6_dma_setup(host, host->chan_rx, DMA_DEV_TO_MEM); in usdhi6_dma_start()
619 return usdhi6_dma_setup(host, host->chan_tx, DMA_MEM_TO_DEV); in usdhi6_dma_start()
622 static void usdhi6_dma_kill(struct usdhi6_host *host) in usdhi6_dma_kill() argument
624 struct mmc_data *data = host->mrq->data; in usdhi6_dma_kill()
626 dev_dbg(mmc_dev(host->mmc), "%s(): SG of %u: %ux%u\n", in usdhi6_dma_kill()
630 dmaengine_terminate_all(host->chan_rx); in usdhi6_dma_kill()
632 dmaengine_terminate_all(host->chan_tx); in usdhi6_dma_kill()
635 static void usdhi6_dma_check_error(struct usdhi6_host *host) in usdhi6_dma_check_error() argument
637 struct mmc_data *data = host->mrq->data; in usdhi6_dma_check_error()
639 dev_dbg(mmc_dev(host->mmc), "%s(): IO error %d, status 0x%x\n", in usdhi6_dma_check_error()
640 __func__, host->io_error, usdhi6_read(host, USDHI6_SD_INFO1)); in usdhi6_dma_check_error()
642 if (host->io_error) { in usdhi6_dma_check_error()
643 data->error = usdhi6_error_code(host); in usdhi6_dma_check_error()
645 usdhi6_dma_kill(host); in usdhi6_dma_check_error()
646 usdhi6_dma_release(host); in usdhi6_dma_check_error()
647 dev_warn(mmc_dev(host->mmc), in usdhi6_dma_check_error()
657 if (host->irq_status & USDHI6_SD_INFO1_RSP_END) in usdhi6_dma_check_error()
658 dev_warn(mmc_dev(host->mmc), "Unexpected response received!\n"); in usdhi6_dma_check_error()
661 static void usdhi6_dma_kick(struct usdhi6_host *host) in usdhi6_dma_kick() argument
663 if (host->mrq->data->flags & MMC_DATA_READ) in usdhi6_dma_kick()
664 dma_async_issue_pending(host->chan_rx); in usdhi6_dma_kick()
666 dma_async_issue_pending(host->chan_tx); in usdhi6_dma_kick()
669 static void usdhi6_dma_request(struct usdhi6_host *host, phys_addr_t start) in usdhi6_dma_request() argument
677 host->chan_tx = dma_request_slave_channel(mmc_dev(host->mmc), "tx"); in usdhi6_dma_request()
678 dev_dbg(mmc_dev(host->mmc), "%s: TX: got channel %p\n", __func__, in usdhi6_dma_request()
679 host->chan_tx); in usdhi6_dma_request()
681 if (!host->chan_tx) in usdhi6_dma_request()
688 ret = dmaengine_slave_config(host->chan_tx, &cfg); in usdhi6_dma_request()
692 host->chan_rx = dma_request_slave_channel(mmc_dev(host->mmc), "rx"); in usdhi6_dma_request()
693 dev_dbg(mmc_dev(host->mmc), "%s: RX: got channel %p\n", __func__, in usdhi6_dma_request()
694 host->chan_rx); in usdhi6_dma_request()
696 if (!host->chan_rx) in usdhi6_dma_request()
703 ret = dmaengine_slave_config(host->chan_rx, &cfg); in usdhi6_dma_request()
710 dma_release_channel(host->chan_rx); in usdhi6_dma_request()
711 host->chan_rx = NULL; in usdhi6_dma_request()
713 dma_release_channel(host->chan_tx); in usdhi6_dma_request()
714 host->chan_tx = NULL; in usdhi6_dma_request()
719 static void usdhi6_clk_set(struct usdhi6_host *host, struct mmc_ios *ios) in usdhi6_clk_set() argument
726 if (usdhi6_read(host, USDHI6_SD_INFO2) & USDHI6_SD_INFO2_SCLKDIVEN) in usdhi6_clk_set()
732 dev_err(mmc_dev(host->mmc), "SD bus busy, clock set aborted\n"); in usdhi6_clk_set()
736 val = usdhi6_read(host, USDHI6_SD_CLK_CTRL) & ~USDHI6_SD_CLK_CTRL_DIV_MASK; in usdhi6_clk_set()
741 if (host->imclk <= rate) { in usdhi6_clk_set()
744 new_rate = host->imclk; in usdhi6_clk_set()
747 new_rate = host->imclk / 2; in usdhi6_clk_set()
751 roundup_pow_of_two(DIV_ROUND_UP(host->imclk, rate)); in usdhi6_clk_set()
753 new_rate = host->imclk / div; in usdhi6_clk_set()
756 if (host->rate == new_rate) in usdhi6_clk_set()
759 host->rate = new_rate; in usdhi6_clk_set()
761 dev_dbg(mmc_dev(host->mmc), "target %lu, div %u, set %lu\n", in usdhi6_clk_set()
769 if (host->imclk == rate || host->imclk == host->rate || !rate) in usdhi6_clk_set()
770 usdhi6_write(host, USDHI6_SD_CLK_CTRL, in usdhi6_clk_set()
774 host->rate = 0; in usdhi6_clk_set()
778 usdhi6_write(host, USDHI6_SD_CLK_CTRL, val); in usdhi6_clk_set()
780 if (host->imclk == rate || host->imclk == host->rate || in usdhi6_clk_set()
782 usdhi6_write(host, USDHI6_SD_CLK_CTRL, in usdhi6_clk_set()
786 static void usdhi6_set_power(struct usdhi6_host *host, struct mmc_ios *ios) in usdhi6_set_power() argument
788 struct mmc_host *mmc = host->mmc; in usdhi6_set_power()
796 static int usdhi6_reset(struct usdhi6_host *host) in usdhi6_reset() argument
800 usdhi6_write(host, USDHI6_SOFT_RST, USDHI6_SOFT_RST_RESERVED); in usdhi6_reset()
802 usdhi6_write(host, USDHI6_SOFT_RST, USDHI6_SOFT_RST_RESERVED | USDHI6_SOFT_RST_RESET); in usdhi6_reset()
804 if (usdhi6_read(host, USDHI6_SOFT_RST) & USDHI6_SOFT_RST_RESET) in usdhi6_reset()
812 struct usdhi6_host *host = mmc_priv(mmc); in usdhi6_set_ios() local
821 usdhi6_set_power(host, ios); in usdhi6_set_ios()
822 usdhi6_only_cd(host); in usdhi6_set_ios()
829 ret = usdhi6_reset(host); in usdhi6_set_ios()
833 usdhi6_set_power(host, ios); in usdhi6_set_ios()
834 usdhi6_only_cd(host); in usdhi6_set_ios()
838 option = usdhi6_read(host, USDHI6_SD_OPTION); in usdhi6_set_ios()
854 usdhi6_write(host, USDHI6_SD_OPTION, option); in usdhi6_set_ios()
855 usdhi6_write(host, USDHI6_SDIF_MODE, mode); in usdhi6_set_ios()
859 if (host->rate != ios->clock) in usdhi6_set_ios()
860 usdhi6_clk_set(host, ios); in usdhi6_set_ios()
864 static void usdhi6_timeout_set(struct usdhi6_host *host) in usdhi6_timeout_set() argument
866 struct mmc_request *mrq = host->mrq; in usdhi6_timeout_set()
871 ticks = host->rate / 1000 * mrq->cmd->busy_timeout; in usdhi6_timeout_set()
873 ticks = host->rate / 1000000 * (mrq->data->timeout_ns / 1000) + in usdhi6_timeout_set()
885 dev_dbg(mmc_dev(host->mmc), "Set %s timeout %lu ticks @ %lu Hz\n", in usdhi6_timeout_set()
886 mrq->data ? "data" : "cmd", ticks, host->rate); in usdhi6_timeout_set()
889 usdhi6_write(host, USDHI6_SD_OPTION, (val << USDHI6_SD_OPTION_TIMEOUT_SHIFT) | in usdhi6_timeout_set()
890 (usdhi6_read(host, USDHI6_SD_OPTION) & ~USDHI6_SD_OPTION_TIMEOUT_MASK)); in usdhi6_timeout_set()
893 static void usdhi6_request_done(struct usdhi6_host *host) in usdhi6_request_done() argument
895 struct mmc_request *mrq = host->mrq; in usdhi6_request_done()
898 if (WARN(host->pg.page || host->head_pg.page, in usdhi6_request_done()
900 host->pg.page, host->head_pg.page, host->wait, mrq->cmd->opcode, in usdhi6_request_done()
902 data ? host->offset : 0, data ? data->blocks : 0, in usdhi6_request_done()
904 usdhi6_sg_unmap(host, true); in usdhi6_request_done()
909 dev_dbg(mmc_dev(host->mmc), "%s(CMD%d: %ux%u): err %d %d %d\n", in usdhi6_request_done()
917 usdhi6_write(host, USDHI6_CC_EXT_MODE, 0); in usdhi6_request_done()
918 host->wait = USDHI6_WAIT_FOR_REQUEST; in usdhi6_request_done()
919 host->mrq = NULL; in usdhi6_request_done()
921 mmc_request_done(host->mmc, mrq); in usdhi6_request_done()
924 static int usdhi6_cmd_flags(struct usdhi6_host *host) in usdhi6_cmd_flags() argument
926 struct mmc_request *mrq = host->mrq; in usdhi6_cmd_flags()
930 if (host->app_cmd) { in usdhi6_cmd_flags()
931 host->app_cmd = false; in usdhi6_cmd_flags()
967 dev_warn(mmc_dev(host->mmc), in usdhi6_cmd_flags()
977 static int usdhi6_rq_start(struct usdhi6_host *host) in usdhi6_rq_start() argument
979 struct mmc_request *mrq = host->mrq; in usdhi6_rq_start()
982 int opc = usdhi6_cmd_flags(host); in usdhi6_rq_start()
989 if (!(usdhi6_read(host, USDHI6_SD_INFO2) & USDHI6_SD_INFO2_CBSY)) in usdhi6_rq_start()
995 dev_dbg(mmc_dev(host->mmc), "Command active, request aborted\n"); in usdhi6_rq_start()
1003 host->page_idx = 0; in usdhi6_rq_start()
1026 dev_warn(mmc_dev(host->mmc), "%s(): %u blocks of %u bytes\n", in usdhi6_rq_start()
1035 usdhi6_sg_prep(host); in usdhi6_rq_start()
1037 usdhi6_write(host, USDHI6_SD_SIZE, data->blksz); in usdhi6_rq_start()
1043 dev_dbg(mmc_dev(host->mmc), in usdhi6_rq_start()
1050 usdhi6_dma_start(host) >= DMA_MIN_COOKIE; in usdhi6_rq_start()
1053 usdhi6_write(host, USDHI6_CC_EXT_MODE, USDHI6_CC_EXT_MODE_SDRW); in usdhi6_rq_start()
1055 dev_dbg(mmc_dev(host->mmc), in usdhi6_rq_start()
1062 dev_dbg(mmc_dev(host->mmc), "%s(): request opcode %u\n", in usdhi6_rq_start()
1067 usdhi6_wait_for_resp(host); in usdhi6_rq_start()
1069 host->wait = USDHI6_WAIT_FOR_CMD; in usdhi6_rq_start()
1070 schedule_delayed_work(&host->timeout_work, host->timeout); in usdhi6_rq_start()
1073 usdhi6_write(host, USDHI6_SD_STOP, in usdhi6_rq_start()
1075 usdhi6_write(host, USDHI6_SD_ARG, cmd->arg); in usdhi6_rq_start()
1078 usdhi6_write(host, USDHI6_SD_CMD, opc); in usdhi6_rq_start()
1085 struct usdhi6_host *host = mmc_priv(mmc); in usdhi6_request() local
1088 cancel_delayed_work_sync(&host->timeout_work); in usdhi6_request()
1090 host->mrq = mrq; in usdhi6_request()
1091 host->sg = NULL; in usdhi6_request()
1093 usdhi6_timeout_set(host); in usdhi6_request()
1094 ret = usdhi6_rq_start(host); in usdhi6_request()
1097 usdhi6_request_done(host); in usdhi6_request()
1103 struct usdhi6_host *host = mmc_priv(mmc); in usdhi6_get_cd() local
1105 u32 status = usdhi6_read(host, USDHI6_SD_INFO1) & USDHI6_SD_INFO1_CD; in usdhi6_get_cd()
1119 struct usdhi6_host *host = mmc_priv(mmc); in usdhi6_get_ro() local
1121 u32 status = usdhi6_read(host, USDHI6_SD_INFO1) & USDHI6_SD_INFO1_WP; in usdhi6_get_ro()
1135 struct usdhi6_host *host = mmc_priv(mmc); in usdhi6_enable_sdio_irq() local
1140 host->sdio_mask = USDHI6_SDIO_INFO1_IRQ & ~USDHI6_SDIO_INFO1_IOIRQ; in usdhi6_enable_sdio_irq()
1141 usdhi6_write(host, USDHI6_SDIO_INFO1_MASK, host->sdio_mask); in usdhi6_enable_sdio_irq()
1142 usdhi6_write(host, USDHI6_SDIO_MODE, 1); in usdhi6_enable_sdio_irq()
1144 usdhi6_write(host, USDHI6_SDIO_MODE, 0); in usdhi6_enable_sdio_irq()
1145 usdhi6_write(host, USDHI6_SDIO_INFO1_MASK, USDHI6_SDIO_INFO1_IRQ); in usdhi6_enable_sdio_irq()
1146 host->sdio_mask = USDHI6_SDIO_INFO1_IRQ; in usdhi6_enable_sdio_irq()
1160 static void usdhi6_resp_cmd12(struct usdhi6_host *host) in usdhi6_resp_cmd12() argument
1162 struct mmc_command *cmd = host->mrq->stop; in usdhi6_resp_cmd12()
1163 cmd->resp[0] = usdhi6_read(host, USDHI6_SD_RSP10); in usdhi6_resp_cmd12()
1166 static void usdhi6_resp_read(struct usdhi6_host *host) in usdhi6_resp_read() argument
1168 struct mmc_command *cmd = host->mrq->cmd; in usdhi6_resp_read()
1189 if (!(host->irq_status & USDHI6_SD_INFO1_RSP_END)) { in usdhi6_resp_read()
1190 dev_err(mmc_dev(host->mmc), in usdhi6_resp_read()
1199 tmp = usdhi6_read(host, USDHI6_SD_RSP10 + i * 8); in usdhi6_resp_read()
1205 rsp[0] = usdhi6_read(host, USDHI6_SD_RSP54); in usdhi6_resp_read()
1207 rsp[0] = usdhi6_read(host, USDHI6_SD_RSP10); in usdhi6_resp_read()
1209 dev_dbg(mmc_dev(host->mmc), "Response 0x%x\n", rsp[0]); in usdhi6_resp_read()
1212 static int usdhi6_blk_read(struct usdhi6_host *host) in usdhi6_blk_read() argument
1214 struct mmc_data *data = host->mrq->data; in usdhi6_blk_read()
1218 if (host->io_error) { in usdhi6_blk_read()
1219 data->error = usdhi6_error_code(host); in usdhi6_blk_read()
1223 if (host->pg.page) { in usdhi6_blk_read()
1224 p = host->blk_page + host->offset; in usdhi6_blk_read()
1226 p = usdhi6_sg_map(host); in usdhi6_blk_read()
1234 *p = usdhi6_read(host, USDHI6_SD_BUF0); in usdhi6_blk_read()
1238 u16 d = usdhi6_read16(host, USDHI6_SD_BUF0); in usdhi6_blk_read()
1247 dev_dbg(mmc_dev(host->mmc), "%s(): %d\n", __func__, data->error); in usdhi6_blk_read()
1248 host->wait = USDHI6_WAIT_FOR_REQUEST; in usdhi6_blk_read()
1252 static int usdhi6_blk_write(struct usdhi6_host *host) in usdhi6_blk_write() argument
1254 struct mmc_data *data = host->mrq->data; in usdhi6_blk_write()
1258 if (host->io_error) { in usdhi6_blk_write()
1259 data->error = usdhi6_error_code(host); in usdhi6_blk_write()
1263 if (host->pg.page) { in usdhi6_blk_write()
1264 p = host->blk_page + host->offset; in usdhi6_blk_write()
1266 p = usdhi6_sg_map(host); in usdhi6_blk_write()
1274 usdhi6_write(host, USDHI6_SD_BUF0, *p); in usdhi6_blk_write()
1284 usdhi6_write16(host, USDHI6_SD_BUF0, d); in usdhi6_blk_write()
1290 dev_dbg(mmc_dev(host->mmc), "%s(): %d\n", __func__, data->error); in usdhi6_blk_write()
1291 host->wait = USDHI6_WAIT_FOR_REQUEST; in usdhi6_blk_write()
1295 static int usdhi6_stop_cmd(struct usdhi6_host *host) in usdhi6_stop_cmd() argument
1297 struct mmc_request *mrq = host->mrq; in usdhi6_stop_cmd()
1303 host->wait = USDHI6_WAIT_FOR_STOP; in usdhi6_stop_cmd()
1308 dev_err(mmc_dev(host->mmc), in usdhi6_stop_cmd()
1317 static bool usdhi6_end_cmd(struct usdhi6_host *host) in usdhi6_end_cmd() argument
1319 struct mmc_request *mrq = host->mrq; in usdhi6_end_cmd()
1322 if (host->io_error) { in usdhi6_end_cmd()
1323 cmd->error = usdhi6_error_code(host); in usdhi6_end_cmd()
1327 usdhi6_resp_read(host); in usdhi6_end_cmd()
1332 if (host->dma_active) { in usdhi6_end_cmd()
1333 usdhi6_dma_kick(host); in usdhi6_end_cmd()
1335 host->wait = USDHI6_WAIT_FOR_DMA; in usdhi6_end_cmd()
1336 else if (usdhi6_stop_cmd(host) < 0) in usdhi6_end_cmd()
1342 host->wait = USDHI6_WAIT_FOR_MREAD; in usdhi6_end_cmd()
1344 host->wait = USDHI6_WAIT_FOR_READ; in usdhi6_end_cmd()
1349 host->wait = USDHI6_WAIT_FOR_MWRITE; in usdhi6_end_cmd()
1351 host->wait = USDHI6_WAIT_FOR_WRITE; in usdhi6_end_cmd()
1357 static bool usdhi6_read_block(struct usdhi6_host *host) in usdhi6_read_block() argument
1360 int ret = usdhi6_blk_read(host); in usdhi6_read_block()
1367 usdhi6_sg_unmap(host, true); in usdhi6_read_block()
1372 host->wait = USDHI6_WAIT_FOR_DATA_END; in usdhi6_read_block()
1376 static bool usdhi6_mread_block(struct usdhi6_host *host) in usdhi6_mread_block() argument
1378 int ret = usdhi6_blk_read(host); in usdhi6_mread_block()
1383 usdhi6_sg_advance(host); in usdhi6_mread_block()
1385 return !host->mrq->data->error && in usdhi6_mread_block()
1386 (host->wait != USDHI6_WAIT_FOR_DATA_END || !host->mrq->stop); in usdhi6_mread_block()
1389 static bool usdhi6_write_block(struct usdhi6_host *host) in usdhi6_write_block() argument
1391 int ret = usdhi6_blk_write(host); in usdhi6_write_block()
1394 usdhi6_sg_unmap(host, true); in usdhi6_write_block()
1399 host->wait = USDHI6_WAIT_FOR_DATA_END; in usdhi6_write_block()
1403 static bool usdhi6_mwrite_block(struct usdhi6_host *host) in usdhi6_mwrite_block() argument
1405 int ret = usdhi6_blk_write(host); in usdhi6_mwrite_block()
1410 usdhi6_sg_advance(host); in usdhi6_mwrite_block()
1412 return !host->mrq->data->error && in usdhi6_mwrite_block()
1413 (host->wait != USDHI6_WAIT_FOR_DATA_END || !host->mrq->stop); in usdhi6_mwrite_block()
1420 struct usdhi6_host *host = dev_id; in usdhi6_sd_bh() local
1426 cancel_delayed_work_sync(&host->timeout_work); in usdhi6_sd_bh()
1428 mrq = host->mrq; in usdhi6_sd_bh()
1435 switch (host->wait) { in usdhi6_sd_bh()
1441 io_wait = usdhi6_end_cmd(host); in usdhi6_sd_bh()
1445 io_wait = usdhi6_mread_block(host); in usdhi6_sd_bh()
1449 io_wait = usdhi6_read_block(host); in usdhi6_sd_bh()
1453 io_wait = usdhi6_mwrite_block(host); in usdhi6_sd_bh()
1457 io_wait = usdhi6_write_block(host); in usdhi6_sd_bh()
1460 usdhi6_dma_check_error(host); in usdhi6_sd_bh()
1463 usdhi6_write(host, USDHI6_SD_STOP, 0); in usdhi6_sd_bh()
1464 if (host->io_error) { in usdhi6_sd_bh()
1465 int ret = usdhi6_error_code(host); in usdhi6_sd_bh()
1470 dev_warn(mmc_dev(host->mmc), "%s(): %d\n", __func__, ret); in usdhi6_sd_bh()
1473 usdhi6_resp_cmd12(host); in usdhi6_sd_bh()
1477 if (host->io_error) { in usdhi6_sd_bh()
1478 mrq->data->error = usdhi6_error_code(host); in usdhi6_sd_bh()
1479 dev_warn(mmc_dev(host->mmc), "%s(): %d\n", __func__, in usdhi6_sd_bh()
1485 dev_err(mmc_dev(host->mmc), "Invalid state %u\n", host->wait); in usdhi6_sd_bh()
1486 usdhi6_request_done(host); in usdhi6_sd_bh()
1491 schedule_delayed_work(&host->timeout_work, host->timeout); in usdhi6_sd_bh()
1493 if (!host->dma_active) in usdhi6_sd_bh()
1494 usdhi6_wait_for_brwe(host, mrq->data->flags & MMC_DATA_READ); in usdhi6_sd_bh()
1501 if (host->wait != USDHI6_WAIT_FOR_STOP && in usdhi6_sd_bh()
1502 host->mrq->stop && in usdhi6_sd_bh()
1503 !host->mrq->stop->error && in usdhi6_sd_bh()
1504 !usdhi6_stop_cmd(host)) { in usdhi6_sd_bh()
1506 usdhi6_wait_for_resp(host); in usdhi6_sd_bh()
1508 schedule_delayed_work(&host->timeout_work, in usdhi6_sd_bh()
1509 host->timeout); in usdhi6_sd_bh()
1517 dev_warn(mmc_dev(host->mmc), "%s(): data error %d\n", in usdhi6_sd_bh()
1519 usdhi6_sg_unmap(host, true); in usdhi6_sd_bh()
1522 host->app_cmd = true; in usdhi6_sd_bh()
1526 usdhi6_request_done(host); in usdhi6_sd_bh()
1533 struct usdhi6_host *host = dev_id; in usdhi6_sd() local
1536 status = usdhi6_read(host, USDHI6_SD_INFO1) & ~host->status_mask & in usdhi6_sd()
1538 status2 = usdhi6_read(host, USDHI6_SD_INFO2) & ~host->status2_mask; in usdhi6_sd()
1540 usdhi6_only_cd(host); in usdhi6_sd()
1542 dev_dbg(mmc_dev(host->mmc), in usdhi6_sd()
1552 usdhi6_write(host, USDHI6_SD_INFO1, in usdhi6_sd()
1560 usdhi6_write(host, USDHI6_SD_INFO2, in usdhi6_sd()
1564 host->io_error = error; in usdhi6_sd()
1565 host->irq_status = status; in usdhi6_sd()
1569 if (host->wait != USDHI6_WAIT_FOR_CMD || in usdhi6_sd()
1571 dev_warn(mmc_dev(host->mmc), in usdhi6_sd()
1575 dev_dbg(mmc_dev(host->mmc), in usdhi6_sd()
1585 struct usdhi6_host *host = dev_id; in usdhi6_sdio() local
1586 u32 status = usdhi6_read(host, USDHI6_SDIO_INFO1) & ~host->sdio_mask; in usdhi6_sdio()
1588 dev_dbg(mmc_dev(host->mmc), "%s(): status 0x%x\n", __func__, status); in usdhi6_sdio()
1593 usdhi6_write(host, USDHI6_SDIO_INFO1, ~status); in usdhi6_sdio()
1595 mmc_signal_sdio_irq(host->mmc); in usdhi6_sdio()
1602 struct usdhi6_host *host = dev_id; in usdhi6_cd() local
1603 struct mmc_host *mmc = host->mmc; in usdhi6_cd()
1607 status = usdhi6_read(host, USDHI6_SD_INFO1) & ~host->status_mask & in usdhi6_cd()
1614 usdhi6_write(host, USDHI6_SD_INFO1, ~status); in usdhi6_cd()
1634 struct usdhi6_host *host = container_of(d, struct usdhi6_host, timeout_work); in usdhi6_timeout_work() local
1635 struct mmc_request *mrq = host->mrq; in usdhi6_timeout_work()
1639 dev_warn(mmc_dev(host->mmc), in usdhi6_timeout_work()
1641 host->dma_active ? "DMA" : "PIO", in usdhi6_timeout_work()
1642 host->wait, mrq ? mrq->cmd->opcode : -1, in usdhi6_timeout_work()
1643 usdhi6_read(host, USDHI6_SD_INFO1), in usdhi6_timeout_work()
1644 usdhi6_read(host, USDHI6_SD_INFO2), host->irq_status); in usdhi6_timeout_work()
1646 if (host->dma_active) { in usdhi6_timeout_work()
1647 usdhi6_dma_kill(host); in usdhi6_timeout_work()
1648 usdhi6_dma_stop_unmap(host); in usdhi6_timeout_work()
1651 switch (host->wait) { in usdhi6_timeout_work()
1653 dev_err(mmc_dev(host->mmc), "Invalid state %u\n", host->wait); in usdhi6_timeout_work()
1656 usdhi6_error_code(host); in usdhi6_timeout_work()
1661 usdhi6_error_code(host); in usdhi6_timeout_work()
1669 sg = host->sg ?: data->sg; in usdhi6_timeout_work()
1670 dev_dbg(mmc_dev(host->mmc), in usdhi6_timeout_work()
1672 data->flags & MMC_DATA_READ ? 'R' : 'W', host->page_idx, in usdhi6_timeout_work()
1673 host->offset, data->blocks, data->blksz, data->sg_len, in usdhi6_timeout_work()
1675 usdhi6_sg_unmap(host, true); in usdhi6_timeout_work()
1681 usdhi6_error_code(host); in usdhi6_timeout_work()
1686 usdhi6_request_done(host); in usdhi6_timeout_work()
1701 struct usdhi6_host *host; in usdhi6_probe() local
1728 host = mmc_priv(mmc); in usdhi6_probe()
1729 host->mmc = mmc; in usdhi6_probe()
1730 host->wait = USDHI6_WAIT_FOR_REQUEST; in usdhi6_probe()
1731 host->timeout = msecs_to_jiffies(4000); in usdhi6_probe()
1734 host->base = devm_ioremap_resource(dev, res); in usdhi6_probe()
1735 if (IS_ERR(host->base)) { in usdhi6_probe()
1736 ret = PTR_ERR(host->base); in usdhi6_probe()
1740 host->clk = devm_clk_get(dev, NULL); in usdhi6_probe()
1741 if (IS_ERR(host->clk)) { in usdhi6_probe()
1742 ret = PTR_ERR(host->clk); in usdhi6_probe()
1746 host->imclk = clk_get_rate(host->clk); in usdhi6_probe()
1748 ret = clk_prepare_enable(host->clk); in usdhi6_probe()
1752 version = usdhi6_read(host, USDHI6_VERSION); in usdhi6_probe()
1759 usdhi6_read(host, USDHI6_SD_PORT_SEL) >> USDHI6_SD_PORT_SEL_PORTS_SHIFT); in usdhi6_probe()
1761 usdhi6_mask_all(host); in usdhi6_probe()
1765 dev_name(dev), host); in usdhi6_probe()
1773 dev_name(dev), host); in usdhi6_probe()
1778 dev_name(dev), host); in usdhi6_probe()
1782 INIT_DELAYED_WORK(&host->timeout_work, usdhi6_timeout_work); in usdhi6_probe()
1784 usdhi6_dma_request(host, res->start); in usdhi6_probe()
1804 mmc->f_max = host->imclk; in usdhi6_probe()
1805 mmc->f_min = host->imclk / 512; in usdhi6_probe()
1807 platform_set_drvdata(pdev, host); in usdhi6_probe()
1816 clk_disable_unprepare(host->clk); in usdhi6_probe()
1825 struct usdhi6_host *host = platform_get_drvdata(pdev); in usdhi6_remove() local
1827 mmc_remove_host(host->mmc); in usdhi6_remove()
1829 usdhi6_mask_all(host); in usdhi6_remove()
1830 cancel_delayed_work_sync(&host->timeout_work); in usdhi6_remove()
1831 usdhi6_dma_release(host); in usdhi6_remove()
1832 clk_disable_unprepare(host->clk); in usdhi6_remove()
1833 mmc_free_host(host->mmc); in usdhi6_remove()