Lines Matching +full:mmc +full:- +full:host
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
6 * JZ4740 SD/MMC controller driver
13 #include <linux/dma-mapping.h>
18 #include <linux/mmc/host.h>
19 #include <linux/mmc/slot-gpio.h>
130 * The MMC core allows to prepare a mmc_request while another mmc_request
131 * is in-flight. This is used via the pre_req/post_req hooks.
149 struct mmc_host *mmc; member
188 static void jz4740_mmc_write_irq_mask(struct jz4740_mmc_host *host, in jz4740_mmc_write_irq_mask() argument
191 if (host->version >= JZ_MMC_JZ4725B) in jz4740_mmc_write_irq_mask()
192 return writel(val, host->base + JZ_REG_MMC_IMASK); in jz4740_mmc_write_irq_mask()
194 return writew(val, host->base + JZ_REG_MMC_IMASK); in jz4740_mmc_write_irq_mask()
197 static void jz4740_mmc_write_irq_reg(struct jz4740_mmc_host *host, in jz4740_mmc_write_irq_reg() argument
200 if (host->version >= JZ_MMC_JZ4780) in jz4740_mmc_write_irq_reg()
201 writel(val, host->base + JZ_REG_MMC_IREG); in jz4740_mmc_write_irq_reg()
203 writew(val, host->base + JZ_REG_MMC_IREG); in jz4740_mmc_write_irq_reg()
206 static uint32_t jz4740_mmc_read_irq_reg(struct jz4740_mmc_host *host) in jz4740_mmc_read_irq_reg() argument
208 if (host->version >= JZ_MMC_JZ4780) in jz4740_mmc_read_irq_reg()
209 return readl(host->base + JZ_REG_MMC_IREG); in jz4740_mmc_read_irq_reg()
211 return readw(host->base + JZ_REG_MMC_IREG); in jz4740_mmc_read_irq_reg()
214 /*----------------------------------------------------------------------------*/
217 static void jz4740_mmc_release_dma_channels(struct jz4740_mmc_host *host) in jz4740_mmc_release_dma_channels() argument
219 if (!host->use_dma) in jz4740_mmc_release_dma_channels()
222 dma_release_channel(host->dma_tx); in jz4740_mmc_release_dma_channels()
223 if (host->dma_rx) in jz4740_mmc_release_dma_channels()
224 dma_release_channel(host->dma_rx); in jz4740_mmc_release_dma_channels()
227 static int jz4740_mmc_acquire_dma_channels(struct jz4740_mmc_host *host) in jz4740_mmc_acquire_dma_channels() argument
229 struct device *dev = mmc_dev(host->mmc); in jz4740_mmc_acquire_dma_channels()
231 host->dma_tx = dma_request_chan(dev, "tx-rx"); in jz4740_mmc_acquire_dma_channels()
232 if (!IS_ERR(host->dma_tx)) in jz4740_mmc_acquire_dma_channels()
235 if (PTR_ERR(host->dma_tx) != -ENODEV) { in jz4740_mmc_acquire_dma_channels()
236 dev_err(dev, "Failed to get dma tx-rx channel\n"); in jz4740_mmc_acquire_dma_channels()
237 return PTR_ERR(host->dma_tx); in jz4740_mmc_acquire_dma_channels()
240 host->dma_tx = dma_request_chan(mmc_dev(host->mmc), "tx"); in jz4740_mmc_acquire_dma_channels()
241 if (IS_ERR(host->dma_tx)) { in jz4740_mmc_acquire_dma_channels()
242 dev_err(mmc_dev(host->mmc), "Failed to get dma_tx channel\n"); in jz4740_mmc_acquire_dma_channels()
243 return PTR_ERR(host->dma_tx); in jz4740_mmc_acquire_dma_channels()
246 host->dma_rx = dma_request_chan(mmc_dev(host->mmc), "rx"); in jz4740_mmc_acquire_dma_channels()
247 if (IS_ERR(host->dma_rx)) { in jz4740_mmc_acquire_dma_channels()
248 dev_err(mmc_dev(host->mmc), "Failed to get dma_rx channel\n"); in jz4740_mmc_acquire_dma_channels()
249 dma_release_channel(host->dma_tx); in jz4740_mmc_acquire_dma_channels()
250 return PTR_ERR(host->dma_rx); in jz4740_mmc_acquire_dma_channels()
257 if (host->dma_tx) { in jz4740_mmc_acquire_dma_channels()
258 struct device *dev = host->dma_tx->device->dev; in jz4740_mmc_acquire_dma_channels()
261 if (max_seg_size < host->mmc->max_seg_size) in jz4740_mmc_acquire_dma_channels()
262 host->mmc->max_seg_size = max_seg_size; in jz4740_mmc_acquire_dma_channels()
265 if (host->dma_rx) { in jz4740_mmc_acquire_dma_channels()
266 struct device *dev = host->dma_rx->device->dev; in jz4740_mmc_acquire_dma_channels()
269 if (max_seg_size < host->mmc->max_seg_size) in jz4740_mmc_acquire_dma_channels()
270 host->mmc->max_seg_size = max_seg_size; in jz4740_mmc_acquire_dma_channels()
276 static inline struct dma_chan *jz4740_mmc_get_dma_chan(struct jz4740_mmc_host *host, in jz4740_mmc_get_dma_chan() argument
279 if ((data->flags & MMC_DATA_READ) && host->dma_rx) in jz4740_mmc_get_dma_chan()
280 return host->dma_rx; in jz4740_mmc_get_dma_chan()
282 return host->dma_tx; in jz4740_mmc_get_dma_chan()
285 static void jz4740_mmc_dma_unmap(struct jz4740_mmc_host *host, in jz4740_mmc_dma_unmap() argument
288 struct dma_chan *chan = jz4740_mmc_get_dma_chan(host, data); in jz4740_mmc_dma_unmap()
291 dma_unmap_sg(chan->device->dev, data->sg, data->sg_len, dir); in jz4740_mmc_dma_unmap()
292 data->host_cookie = COOKIE_UNMAPPED; in jz4740_mmc_dma_unmap()
296 * A request can be in-flight when this is called.
298 static int jz4740_mmc_prepare_dma_data(struct jz4740_mmc_host *host, in jz4740_mmc_prepare_dma_data() argument
302 struct dma_chan *chan = jz4740_mmc_get_dma_chan(host, data); in jz4740_mmc_prepare_dma_data()
306 if (data->host_cookie == COOKIE_PREMAPPED) in jz4740_mmc_prepare_dma_data()
307 return data->sg_count; in jz4740_mmc_prepare_dma_data()
309 sg_count = dma_map_sg(chan->device->dev, in jz4740_mmc_prepare_dma_data()
310 data->sg, in jz4740_mmc_prepare_dma_data()
311 data->sg_len, in jz4740_mmc_prepare_dma_data()
315 dev_err(mmc_dev(host->mmc), in jz4740_mmc_prepare_dma_data()
317 return -EINVAL; in jz4740_mmc_prepare_dma_data()
320 data->sg_count = sg_count; in jz4740_mmc_prepare_dma_data()
321 data->host_cookie = cookie; in jz4740_mmc_prepare_dma_data()
323 return data->sg_count; in jz4740_mmc_prepare_dma_data()
326 static int jz4740_mmc_start_dma_transfer(struct jz4740_mmc_host *host, in jz4740_mmc_start_dma_transfer() argument
329 struct dma_chan *chan = jz4740_mmc_get_dma_chan(host, data); in jz4740_mmc_start_dma_transfer()
339 if (data->flags & MMC_DATA_WRITE) { in jz4740_mmc_start_dma_transfer()
341 conf.dst_addr = host->mem_res->start + JZ_REG_MMC_TXFIFO; in jz4740_mmc_start_dma_transfer()
344 conf.src_addr = host->mem_res->start + JZ_REG_MMC_RXFIFO; in jz4740_mmc_start_dma_transfer()
347 sg_count = jz4740_mmc_prepare_dma_data(host, data, COOKIE_MAPPED); in jz4740_mmc_start_dma_transfer()
352 desc = dmaengine_prep_slave_sg(chan, data->sg, sg_count, in jz4740_mmc_start_dma_transfer()
356 dev_err(mmc_dev(host->mmc), in jz4740_mmc_start_dma_transfer()
368 if (data->host_cookie == COOKIE_MAPPED) in jz4740_mmc_start_dma_transfer()
369 jz4740_mmc_dma_unmap(host, data); in jz4740_mmc_start_dma_transfer()
370 return -ENOMEM; in jz4740_mmc_start_dma_transfer()
373 static void jz4740_mmc_pre_request(struct mmc_host *mmc, in jz4740_mmc_pre_request() argument
376 struct jz4740_mmc_host *host = mmc_priv(mmc); in jz4740_mmc_pre_request() local
377 struct mmc_data *data = mrq->data; in jz4740_mmc_pre_request()
379 if (!host->use_dma) in jz4740_mmc_pre_request()
382 data->host_cookie = COOKIE_UNMAPPED; in jz4740_mmc_pre_request()
383 if (jz4740_mmc_prepare_dma_data(host, data, COOKIE_PREMAPPED) < 0) in jz4740_mmc_pre_request()
384 data->host_cookie = COOKIE_UNMAPPED; in jz4740_mmc_pre_request()
387 static void jz4740_mmc_post_request(struct mmc_host *mmc, in jz4740_mmc_post_request() argument
391 struct jz4740_mmc_host *host = mmc_priv(mmc); in jz4740_mmc_post_request() local
392 struct mmc_data *data = mrq->data; in jz4740_mmc_post_request()
394 if (data && data->host_cookie != COOKIE_UNMAPPED) in jz4740_mmc_post_request()
395 jz4740_mmc_dma_unmap(host, data); in jz4740_mmc_post_request()
398 struct dma_chan *chan = jz4740_mmc_get_dma_chan(host, data); in jz4740_mmc_post_request()
404 /*----------------------------------------------------------------------------*/
406 static void jz4740_mmc_set_irq_enabled(struct jz4740_mmc_host *host, in jz4740_mmc_set_irq_enabled() argument
411 spin_lock_irqsave(&host->lock, flags); in jz4740_mmc_set_irq_enabled()
413 host->irq_mask &= ~irq; in jz4740_mmc_set_irq_enabled()
415 host->irq_mask |= irq; in jz4740_mmc_set_irq_enabled()
417 jz4740_mmc_write_irq_mask(host, host->irq_mask); in jz4740_mmc_set_irq_enabled()
418 spin_unlock_irqrestore(&host->lock, flags); in jz4740_mmc_set_irq_enabled()
421 static void jz4740_mmc_clock_enable(struct jz4740_mmc_host *host, in jz4740_mmc_clock_enable() argument
429 writew(val, host->base + JZ_REG_MMC_STRPCL); in jz4740_mmc_clock_enable()
432 static void jz4740_mmc_clock_disable(struct jz4740_mmc_host *host) in jz4740_mmc_clock_disable() argument
437 writew(JZ_MMC_STRPCL_CLOCK_STOP, host->base + JZ_REG_MMC_STRPCL); in jz4740_mmc_clock_disable()
439 status = readl(host->base + JZ_REG_MMC_STATUS); in jz4740_mmc_clock_disable()
440 } while (status & JZ_MMC_STATUS_CLK_EN && --timeout); in jz4740_mmc_clock_disable()
443 static void jz4740_mmc_reset(struct jz4740_mmc_host *host) in jz4740_mmc_reset() argument
448 writew(JZ_MMC_STRPCL_RESET, host->base + JZ_REG_MMC_STRPCL); in jz4740_mmc_reset()
451 status = readl(host->base + JZ_REG_MMC_STATUS); in jz4740_mmc_reset()
452 } while (status & JZ_MMC_STATUS_IS_RESETTING && --timeout); in jz4740_mmc_reset()
455 static void jz4740_mmc_request_done(struct jz4740_mmc_host *host) in jz4740_mmc_request_done() argument
460 req = host->req; in jz4740_mmc_request_done()
461 data = req->data; in jz4740_mmc_request_done()
462 host->req = NULL; in jz4740_mmc_request_done()
464 if (data && data->host_cookie == COOKIE_MAPPED) in jz4740_mmc_request_done()
465 jz4740_mmc_dma_unmap(host, data); in jz4740_mmc_request_done()
466 mmc_request_done(host->mmc, req); in jz4740_mmc_request_done()
469 static unsigned int jz4740_mmc_poll_irq(struct jz4740_mmc_host *host, in jz4740_mmc_poll_irq() argument
476 status = jz4740_mmc_read_irq_reg(host); in jz4740_mmc_poll_irq()
477 } while (!(status & irq) && --timeout); in jz4740_mmc_poll_irq()
480 set_bit(0, &host->waiting); in jz4740_mmc_poll_irq()
481 mod_timer(&host->timeout_timer, in jz4740_mmc_poll_irq()
483 jz4740_mmc_set_irq_enabled(host, irq, true); in jz4740_mmc_poll_irq()
490 static void jz4740_mmc_transfer_check_state(struct jz4740_mmc_host *host, in jz4740_mmc_transfer_check_state() argument
495 status = readl(host->base + JZ_REG_MMC_STATUS); in jz4740_mmc_transfer_check_state()
498 host->req->cmd->error = -ETIMEDOUT; in jz4740_mmc_transfer_check_state()
499 data->error = -ETIMEDOUT; in jz4740_mmc_transfer_check_state()
501 host->req->cmd->error = -EIO; in jz4740_mmc_transfer_check_state()
502 data->error = -EIO; in jz4740_mmc_transfer_check_state()
506 host->req->cmd->error = -ETIMEDOUT; in jz4740_mmc_transfer_check_state()
507 data->error = -ETIMEDOUT; in jz4740_mmc_transfer_check_state()
509 host->req->cmd->error = -EIO; in jz4740_mmc_transfer_check_state()
510 data->error = -EIO; in jz4740_mmc_transfer_check_state()
515 static bool jz4740_mmc_write_data(struct jz4740_mmc_host *host, in jz4740_mmc_write_data() argument
518 struct sg_mapping_iter *miter = &host->miter; in jz4740_mmc_write_data()
519 void __iomem *fifo_addr = host->base + JZ_REG_MMC_TXFIFO; in jz4740_mmc_write_data()
525 buf = miter->addr; in jz4740_mmc_write_data()
526 i = miter->length / 4; in jz4740_mmc_write_data()
530 timeout = jz4740_mmc_poll_irq(host, JZ_MMC_IRQ_TXFIFO_WR_REQ); in jz4740_mmc_write_data()
543 --j; in jz4740_mmc_write_data()
546 timeout = jz4740_mmc_poll_irq(host, JZ_MMC_IRQ_TXFIFO_WR_REQ); in jz4740_mmc_write_data()
553 --i; in jz4740_mmc_write_data()
556 data->bytes_xfered += miter->length; in jz4740_mmc_write_data()
563 miter->consumed = (void *)buf - miter->addr; in jz4740_mmc_write_data()
564 data->bytes_xfered += miter->consumed; in jz4740_mmc_write_data()
570 static bool jz4740_mmc_read_data(struct jz4740_mmc_host *host, in jz4740_mmc_read_data() argument
573 struct sg_mapping_iter *miter = &host->miter; in jz4740_mmc_read_data()
574 void __iomem *fifo_addr = host->base + JZ_REG_MMC_RXFIFO; in jz4740_mmc_read_data()
582 buf = miter->addr; in jz4740_mmc_read_data()
583 i = miter->length; in jz4740_mmc_read_data()
587 timeout = jz4740_mmc_poll_irq(host, JZ_MMC_IRQ_RXFIFO_RD_REQ); in jz4740_mmc_read_data()
601 --j; in jz4740_mmc_read_data()
605 timeout = jz4740_mmc_poll_irq(host, JZ_MMC_IRQ_RXFIFO_RD_REQ); in jz4740_mmc_read_data()
611 i -= 4; in jz4740_mmc_read_data()
618 data->bytes_xfered += miter->length; in jz4740_mmc_read_data()
625 status = readl(host->base + JZ_REG_MMC_STATUS); in jz4740_mmc_read_data()
626 while (!(status & JZ_MMC_STATUS_DATA_FIFO_EMPTY) && --timeout) { in jz4740_mmc_read_data()
628 status = readl(host->base + JZ_REG_MMC_STATUS); in jz4740_mmc_read_data()
634 miter->consumed = (void *)buf - miter->addr; in jz4740_mmc_read_data()
635 data->bytes_xfered += miter->consumed; in jz4740_mmc_read_data()
643 struct jz4740_mmc_host *host = from_timer(host, t, timeout_timer); in jz4740_mmc_timeout() local
645 if (!test_and_clear_bit(0, &host->waiting)) in jz4740_mmc_timeout()
648 jz4740_mmc_set_irq_enabled(host, JZ_MMC_IRQ_END_CMD_RES, false); in jz4740_mmc_timeout()
650 host->req->cmd->error = -ETIMEDOUT; in jz4740_mmc_timeout()
651 jz4740_mmc_request_done(host); in jz4740_mmc_timeout()
654 static void jz4740_mmc_read_response(struct jz4740_mmc_host *host, in jz4740_mmc_read_response() argument
659 void __iomem *fifo_addr = host->base + JZ_REG_MMC_RESP_FIFO; in jz4740_mmc_read_response()
661 if (cmd->flags & MMC_RSP_136) { in jz4740_mmc_read_response()
664 cmd->resp[i] = tmp << 24; in jz4740_mmc_read_response()
666 cmd->resp[i] |= tmp << 8; in jz4740_mmc_read_response()
668 cmd->resp[i] |= tmp >> 8; in jz4740_mmc_read_response()
671 cmd->resp[0] = readw(fifo_addr) << 24; in jz4740_mmc_read_response()
672 cmd->resp[0] |= readw(fifo_addr) << 8; in jz4740_mmc_read_response()
673 cmd->resp[0] |= readw(fifo_addr) & 0xff; in jz4740_mmc_read_response()
677 static void jz4740_mmc_send_command(struct jz4740_mmc_host *host, in jz4740_mmc_send_command() argument
680 uint32_t cmdat = host->cmdat; in jz4740_mmc_send_command()
682 host->cmdat &= ~JZ_MMC_CMDAT_INIT; in jz4740_mmc_send_command()
683 jz4740_mmc_clock_disable(host); in jz4740_mmc_send_command()
685 host->cmd = cmd; in jz4740_mmc_send_command()
687 if (cmd->flags & MMC_RSP_BUSY) in jz4740_mmc_send_command()
705 if (cmd->data) { in jz4740_mmc_send_command()
707 if (cmd->data->flags & MMC_DATA_WRITE) in jz4740_mmc_send_command()
709 if (host->use_dma) { in jz4740_mmc_send_command()
711 * The JZ4780's MMC controller has integrated DMA ability in jz4740_mmc_send_command()
719 if (host->version >= JZ_MMC_JZ4780) { in jz4740_mmc_send_command()
721 host->base + JZ_REG_MMC_DMAC); in jz4740_mmc_send_command()
725 } else if (host->version >= JZ_MMC_JZ4780) { in jz4740_mmc_send_command()
726 writel(0, host->base + JZ_REG_MMC_DMAC); in jz4740_mmc_send_command()
729 writew(cmd->data->blksz, host->base + JZ_REG_MMC_BLKLEN); in jz4740_mmc_send_command()
730 writew(cmd->data->blocks, host->base + JZ_REG_MMC_NOB); in jz4740_mmc_send_command()
733 writeb(cmd->opcode, host->base + JZ_REG_MMC_CMD); in jz4740_mmc_send_command()
734 writel(cmd->arg, host->base + JZ_REG_MMC_ARG); in jz4740_mmc_send_command()
735 writel(cmdat, host->base + JZ_REG_MMC_CMDAT); in jz4740_mmc_send_command()
737 jz4740_mmc_clock_enable(host, 1); in jz4740_mmc_send_command()
740 static void jz_mmc_prepare_data_transfer(struct jz4740_mmc_host *host) in jz_mmc_prepare_data_transfer() argument
742 struct mmc_command *cmd = host->req->cmd; in jz_mmc_prepare_data_transfer()
743 struct mmc_data *data = cmd->data; in jz_mmc_prepare_data_transfer()
746 if (data->flags & MMC_DATA_READ) in jz_mmc_prepare_data_transfer()
751 sg_miter_start(&host->miter, data->sg, data->sg_len, direction); in jz_mmc_prepare_data_transfer()
757 struct jz4740_mmc_host *host = (struct jz4740_mmc_host *)devid; in jz_mmc_irq_worker() local
758 struct mmc_command *cmd = host->req->cmd; in jz_mmc_irq_worker()
759 struct mmc_request *req = host->req; in jz_mmc_irq_worker()
760 struct mmc_data *data = cmd->data; in jz_mmc_irq_worker()
763 if (cmd->error) in jz_mmc_irq_worker()
764 host->state = JZ4740_MMC_STATE_DONE; in jz_mmc_irq_worker()
766 switch (host->state) { in jz_mmc_irq_worker()
768 if (cmd->flags & MMC_RSP_PRESENT) in jz_mmc_irq_worker()
769 jz4740_mmc_read_response(host, cmd); in jz_mmc_irq_worker()
774 jz_mmc_prepare_data_transfer(host); in jz_mmc_irq_worker()
778 if (host->use_dma) { in jz_mmc_irq_worker()
785 timeout = jz4740_mmc_start_dma_transfer(host, data); in jz_mmc_irq_worker()
786 data->bytes_xfered = data->blocks * data->blksz; in jz_mmc_irq_worker()
787 } else if (data->flags & MMC_DATA_READ) in jz_mmc_irq_worker()
793 timeout = jz4740_mmc_read_data(host, data); in jz_mmc_irq_worker()
795 timeout = jz4740_mmc_write_data(host, data); in jz_mmc_irq_worker()
798 host->state = JZ4740_MMC_STATE_TRANSFER_DATA; in jz_mmc_irq_worker()
802 jz4740_mmc_transfer_check_state(host, data); in jz_mmc_irq_worker()
804 timeout = jz4740_mmc_poll_irq(host, JZ_MMC_IRQ_DATA_TRAN_DONE); in jz_mmc_irq_worker()
806 host->state = JZ4740_MMC_STATE_SEND_STOP; in jz_mmc_irq_worker()
809 jz4740_mmc_write_irq_reg(host, JZ_MMC_IRQ_DATA_TRAN_DONE); in jz_mmc_irq_worker()
813 if (!req->stop) in jz_mmc_irq_worker()
816 jz4740_mmc_send_command(host, req->stop); in jz_mmc_irq_worker()
818 if (mmc_resp_type(req->stop) & MMC_RSP_BUSY) { in jz_mmc_irq_worker()
819 timeout = jz4740_mmc_poll_irq(host, in jz_mmc_irq_worker()
822 host->state = JZ4740_MMC_STATE_DONE; in jz_mmc_irq_worker()
833 jz4740_mmc_request_done(host); in jz_mmc_irq_worker()
840 struct jz4740_mmc_host *host = devid; in jz_mmc_irq() local
841 struct mmc_command *cmd = host->cmd; in jz_mmc_irq()
844 status = readl(host->base + JZ_REG_MMC_STATUS); in jz_mmc_irq()
845 irq_reg = jz4740_mmc_read_irq_reg(host); in jz_mmc_irq()
848 irq_reg &= ~host->irq_mask; in jz_mmc_irq()
854 jz4740_mmc_write_irq_reg(host, tmp & ~irq_reg); in jz_mmc_irq()
857 jz4740_mmc_write_irq_reg(host, JZ_MMC_IRQ_SDIO); in jz_mmc_irq()
858 mmc_signal_sdio_irq(host->mmc); in jz_mmc_irq()
862 if (host->req && cmd && irq_reg) { in jz_mmc_irq()
863 if (test_and_clear_bit(0, &host->waiting)) { in jz_mmc_irq()
864 del_timer(&host->timeout_timer); in jz_mmc_irq()
867 cmd->error = -ETIMEDOUT; in jz_mmc_irq()
869 cmd->error = -EIO; in jz_mmc_irq()
872 if (cmd->data) in jz_mmc_irq()
873 cmd->data->error = -EIO; in jz_mmc_irq()
874 cmd->error = -EIO; in jz_mmc_irq()
877 jz4740_mmc_set_irq_enabled(host, irq_reg, false); in jz_mmc_irq()
878 jz4740_mmc_write_irq_reg(host, irq_reg); in jz_mmc_irq()
887 static int jz4740_mmc_set_clock_rate(struct jz4740_mmc_host *host, int rate) in jz4740_mmc_set_clock_rate() argument
892 jz4740_mmc_clock_disable(host); in jz4740_mmc_set_clock_rate()
893 clk_set_rate(host->clk, host->mmc->f_max); in jz4740_mmc_set_clock_rate()
895 real_rate = clk_get_rate(host->clk); in jz4740_mmc_set_clock_rate()
902 writew(div, host->base + JZ_REG_MMC_CLKRT); in jz4740_mmc_set_clock_rate()
905 if (host->version >= JZ_MMC_JZ4780) { in jz4740_mmc_set_clock_rate()
909 host->base + JZ_REG_MMC_LPM); in jz4740_mmc_set_clock_rate()
910 } else if (host->version >= JZ_MMC_JZ4760) { in jz4740_mmc_set_clock_rate()
913 host->base + JZ_REG_MMC_LPM); in jz4740_mmc_set_clock_rate()
914 } else if (host->version >= JZ_MMC_JZ4725B) in jz4740_mmc_set_clock_rate()
916 host->base + JZ_REG_MMC_LPM); in jz4740_mmc_set_clock_rate()
922 static void jz4740_mmc_request(struct mmc_host *mmc, struct mmc_request *req) in jz4740_mmc_request() argument
924 struct jz4740_mmc_host *host = mmc_priv(mmc); in jz4740_mmc_request() local
926 host->req = req; in jz4740_mmc_request()
928 jz4740_mmc_write_irq_reg(host, ~0); in jz4740_mmc_request()
929 jz4740_mmc_set_irq_enabled(host, JZ_MMC_IRQ_END_CMD_RES, true); in jz4740_mmc_request()
931 host->state = JZ4740_MMC_STATE_READ_RESPONSE; in jz4740_mmc_request()
932 set_bit(0, &host->waiting); in jz4740_mmc_request()
933 mod_timer(&host->timeout_timer, in jz4740_mmc_request()
935 jz4740_mmc_send_command(host, req->cmd); in jz4740_mmc_request()
938 static void jz4740_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) in jz4740_mmc_set_ios() argument
940 struct jz4740_mmc_host *host = mmc_priv(mmc); in jz4740_mmc_set_ios() local
943 if (ios->clock) in jz4740_mmc_set_ios()
944 jz4740_mmc_set_clock_rate(host, ios->clock); in jz4740_mmc_set_ios()
946 switch (ios->power_mode) { in jz4740_mmc_set_ios()
948 jz4740_mmc_reset(host); in jz4740_mmc_set_ios()
949 if (!IS_ERR(mmc->supply.vmmc)) in jz4740_mmc_set_ios()
950 mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd); in jz4740_mmc_set_ios()
951 host->cmdat |= JZ_MMC_CMDAT_INIT; in jz4740_mmc_set_ios()
952 clk_prepare_enable(host->clk); in jz4740_mmc_set_ios()
955 if (!IS_ERR(mmc->supply.vqmmc) && !host->vqmmc_enabled) { in jz4740_mmc_set_ios()
956 ret = regulator_enable(mmc->supply.vqmmc); in jz4740_mmc_set_ios()
958 dev_err(&host->pdev->dev, "Failed to set vqmmc power!\n"); in jz4740_mmc_set_ios()
960 host->vqmmc_enabled = true; in jz4740_mmc_set_ios()
964 if (!IS_ERR(mmc->supply.vmmc)) in jz4740_mmc_set_ios()
965 mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); in jz4740_mmc_set_ios()
966 if (!IS_ERR(mmc->supply.vqmmc) && host->vqmmc_enabled) { in jz4740_mmc_set_ios()
967 regulator_disable(mmc->supply.vqmmc); in jz4740_mmc_set_ios()
968 host->vqmmc_enabled = false; in jz4740_mmc_set_ios()
970 clk_disable_unprepare(host->clk); in jz4740_mmc_set_ios()
976 switch (ios->bus_width) { in jz4740_mmc_set_ios()
978 host->cmdat &= ~JZ_MMC_CMDAT_BUS_WIDTH_MASK; in jz4740_mmc_set_ios()
981 host->cmdat &= ~JZ_MMC_CMDAT_BUS_WIDTH_MASK; in jz4740_mmc_set_ios()
982 host->cmdat |= JZ_MMC_CMDAT_BUS_WIDTH_4BIT; in jz4740_mmc_set_ios()
985 host->cmdat &= ~JZ_MMC_CMDAT_BUS_WIDTH_MASK; in jz4740_mmc_set_ios()
986 host->cmdat |= JZ_MMC_CMDAT_BUS_WIDTH_8BIT; in jz4740_mmc_set_ios()
993 static void jz4740_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) in jz4740_mmc_enable_sdio_irq() argument
995 struct jz4740_mmc_host *host = mmc_priv(mmc); in jz4740_mmc_enable_sdio_irq() local
996 jz4740_mmc_set_irq_enabled(host, JZ_MMC_IRQ_SDIO, enable); in jz4740_mmc_enable_sdio_irq()
999 static int jz4740_voltage_switch(struct mmc_host *mmc, struct mmc_ios *ios) in jz4740_voltage_switch() argument
1004 if (!IS_ERR(mmc->supply.vqmmc)) { in jz4740_voltage_switch()
1005 ret = mmc_regulator_set_vqmmc(mmc, ios); in jz4740_voltage_switch()
1010 if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) in jz4740_voltage_switch()
1013 return -EINVAL; in jz4740_voltage_switch()
1028 { .compatible = "ingenic,jz4740-mmc", .data = (void *) JZ_MMC_JZ4740 },
1029 { .compatible = "ingenic,jz4725b-mmc", .data = (void *)JZ_MMC_JZ4725B },
1030 { .compatible = "ingenic,jz4760-mmc", .data = (void *) JZ_MMC_JZ4760 },
1031 { .compatible = "ingenic,jz4775-mmc", .data = (void *) JZ_MMC_JZ4780 },
1032 { .compatible = "ingenic,jz4780-mmc", .data = (void *) JZ_MMC_JZ4780 },
1033 { .compatible = "ingenic,x1000-mmc", .data = (void *) JZ_MMC_X1000 },
1041 struct mmc_host *mmc; in jz4740_mmc_probe() local
1042 struct jz4740_mmc_host *host; in jz4740_mmc_probe() local
1045 mmc = mmc_alloc_host(sizeof(struct jz4740_mmc_host), &pdev->dev); in jz4740_mmc_probe()
1046 if (!mmc) { in jz4740_mmc_probe()
1047 dev_err(&pdev->dev, "Failed to alloc mmc host structure\n"); in jz4740_mmc_probe()
1048 return -ENOMEM; in jz4740_mmc_probe()
1051 host = mmc_priv(mmc); in jz4740_mmc_probe()
1053 match = of_match_device(jz4740_mmc_of_match, &pdev->dev); in jz4740_mmc_probe()
1055 host->version = (enum jz4740_mmc_version)match->data; in jz4740_mmc_probe()
1058 host->version = JZ_MMC_JZ4740; in jz4740_mmc_probe()
1061 ret = mmc_of_parse(mmc); in jz4740_mmc_probe()
1063 dev_err_probe(&pdev->dev, ret, "could not parse device properties\n"); in jz4740_mmc_probe()
1067 mmc_regulator_get_supply(mmc); in jz4740_mmc_probe()
1069 host->irq = platform_get_irq(pdev, 0); in jz4740_mmc_probe()
1070 if (host->irq < 0) { in jz4740_mmc_probe()
1071 ret = host->irq; in jz4740_mmc_probe()
1075 host->clk = devm_clk_get(&pdev->dev, "mmc"); in jz4740_mmc_probe()
1076 if (IS_ERR(host->clk)) { in jz4740_mmc_probe()
1077 ret = PTR_ERR(host->clk); in jz4740_mmc_probe()
1078 dev_err(&pdev->dev, "Failed to get mmc clock\n"); in jz4740_mmc_probe()
1082 host->base = devm_platform_get_and_ioremap_resource(pdev, 0, &host->mem_res); in jz4740_mmc_probe()
1083 if (IS_ERR(host->base)) { in jz4740_mmc_probe()
1084 ret = PTR_ERR(host->base); in jz4740_mmc_probe()
1088 mmc->ops = &jz4740_mmc_ops; in jz4740_mmc_probe()
1089 if (!mmc->f_max) in jz4740_mmc_probe()
1090 mmc->f_max = JZ_MMC_CLK_RATE; in jz4740_mmc_probe()
1098 if (host->version == JZ_MMC_JZ4760 && mmc->f_max > JZ_MMC_CLK_RATE) in jz4740_mmc_probe()
1099 mmc->f_max = JZ_MMC_CLK_RATE; in jz4740_mmc_probe()
1101 mmc->f_min = mmc->f_max / 128; in jz4740_mmc_probe()
1102 mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; in jz4740_mmc_probe()
1106 * future improvement should instead respect the cmd->busy_timeout. in jz4740_mmc_probe()
1108 mmc->max_busy_timeout = JZ_MMC_REQ_TIMEOUT_MS; in jz4740_mmc_probe()
1110 mmc->max_blk_size = (1 << 10) - 1; in jz4740_mmc_probe()
1111 mmc->max_blk_count = (1 << 15) - 1; in jz4740_mmc_probe()
1112 mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; in jz4740_mmc_probe()
1114 mmc->max_segs = 128; in jz4740_mmc_probe()
1115 mmc->max_seg_size = mmc->max_req_size; in jz4740_mmc_probe()
1117 host->mmc = mmc; in jz4740_mmc_probe()
1118 host->pdev = pdev; in jz4740_mmc_probe()
1119 spin_lock_init(&host->lock); in jz4740_mmc_probe()
1120 host->irq_mask = ~0; in jz4740_mmc_probe()
1122 jz4740_mmc_reset(host); in jz4740_mmc_probe()
1124 ret = request_threaded_irq(host->irq, jz_mmc_irq, jz_mmc_irq_worker, 0, in jz4740_mmc_probe()
1125 dev_name(&pdev->dev), host); in jz4740_mmc_probe()
1127 dev_err(&pdev->dev, "Failed to request irq: %d\n", ret); in jz4740_mmc_probe()
1131 jz4740_mmc_clock_disable(host); in jz4740_mmc_probe()
1132 timer_setup(&host->timeout_timer, jz4740_mmc_timeout, 0); in jz4740_mmc_probe()
1134 ret = jz4740_mmc_acquire_dma_channels(host); in jz4740_mmc_probe()
1135 if (ret == -EPROBE_DEFER) in jz4740_mmc_probe()
1137 host->use_dma = !ret; in jz4740_mmc_probe()
1139 platform_set_drvdata(pdev, host); in jz4740_mmc_probe()
1140 ret = mmc_add_host(mmc); in jz4740_mmc_probe()
1143 dev_err(&pdev->dev, "Failed to add mmc host: %d\n", ret); in jz4740_mmc_probe()
1146 dev_info(&pdev->dev, "Ingenic SD/MMC card driver registered\n"); in jz4740_mmc_probe()
1148 dev_info(&pdev->dev, "Using %s, %d-bit mode\n", in jz4740_mmc_probe()
1149 host->use_dma ? "DMA" : "PIO", in jz4740_mmc_probe()
1150 (mmc->caps & MMC_CAP_8_BIT_DATA) ? 8 : in jz4740_mmc_probe()
1151 ((mmc->caps & MMC_CAP_4_BIT_DATA) ? 4 : 1)); in jz4740_mmc_probe()
1156 if (host->use_dma) in jz4740_mmc_probe()
1157 jz4740_mmc_release_dma_channels(host); in jz4740_mmc_probe()
1159 free_irq(host->irq, host); in jz4740_mmc_probe()
1161 mmc_free_host(mmc); in jz4740_mmc_probe()
1168 struct jz4740_mmc_host *host = platform_get_drvdata(pdev); in jz4740_mmc_remove() local
1170 del_timer_sync(&host->timeout_timer); in jz4740_mmc_remove()
1171 jz4740_mmc_set_irq_enabled(host, 0xff, false); in jz4740_mmc_remove()
1172 jz4740_mmc_reset(host); in jz4740_mmc_remove()
1174 mmc_remove_host(host->mmc); in jz4740_mmc_remove()
1176 free_irq(host->irq, host); in jz4740_mmc_remove()
1178 if (host->use_dma) in jz4740_mmc_remove()
1179 jz4740_mmc_release_dma_channels(host); in jz4740_mmc_remove()
1181 mmc_free_host(host->mmc); in jz4740_mmc_remove()
1201 .name = "jz4740-mmc",
1210 MODULE_DESCRIPTION("JZ4740 SD/MMC controller driver");
1212 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");