| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (C) 2013-2014 Renesas Electronics Europe Ltd. |
|---|
| 3 | 4 | * Author: Guennadi Liakhovetski <g.liakhovetski@gmx.de> |
|---|
| 4 | | - * |
|---|
| 5 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 6 | | - * it under the terms of version 2 of the GNU General Public License as |
|---|
| 7 | | - * published by the Free Software Foundation. |
|---|
| 8 | 5 | */ |
|---|
| 9 | 6 | |
|---|
| 10 | 7 | #include <linux/clk.h> |
|---|
| .. | .. |
|---|
| 139 | 136 | |
|---|
| 140 | 137 | #define USDHI6_MIN_DMA 64 |
|---|
| 141 | 138 | |
|---|
| 139 | +#define USDHI6_REQ_TIMEOUT_MS 4000 |
|---|
| 140 | + |
|---|
| 142 | 141 | enum usdhi6_wait_for { |
|---|
| 143 | 142 | USDHI6_WAIT_FOR_REQUEST, |
|---|
| 144 | 143 | USDHI6_WAIT_FOR_CMD, |
|---|
| .. | .. |
|---|
| 202 | 201 | |
|---|
| 203 | 202 | /* Pin control */ |
|---|
| 204 | 203 | struct pinctrl *pinctrl; |
|---|
| 205 | | - struct pinctrl_state *pins_default; |
|---|
| 206 | 204 | struct pinctrl_state *pins_uhs; |
|---|
| 207 | 205 | }; |
|---|
| 208 | 206 | |
|---|
| .. | .. |
|---|
| 680 | 678 | }; |
|---|
| 681 | 679 | int ret; |
|---|
| 682 | 680 | |
|---|
| 683 | | - host->chan_tx = dma_request_slave_channel(mmc_dev(host->mmc), "tx"); |
|---|
| 681 | + host->chan_tx = dma_request_chan(mmc_dev(host->mmc), "tx"); |
|---|
| 684 | 682 | dev_dbg(mmc_dev(host->mmc), "%s: TX: got channel %p\n", __func__, |
|---|
| 685 | 683 | host->chan_tx); |
|---|
| 686 | 684 | |
|---|
| 687 | | - if (!host->chan_tx) |
|---|
| 685 | + if (IS_ERR(host->chan_tx)) { |
|---|
| 686 | + host->chan_tx = NULL; |
|---|
| 688 | 687 | return; |
|---|
| 688 | + } |
|---|
| 689 | 689 | |
|---|
| 690 | 690 | cfg.direction = DMA_MEM_TO_DEV; |
|---|
| 691 | 691 | cfg.dst_addr = start + USDHI6_SD_BUF0; |
|---|
| .. | .. |
|---|
| 695 | 695 | if (ret < 0) |
|---|
| 696 | 696 | goto e_release_tx; |
|---|
| 697 | 697 | |
|---|
| 698 | | - host->chan_rx = dma_request_slave_channel(mmc_dev(host->mmc), "rx"); |
|---|
| 698 | + host->chan_rx = dma_request_chan(mmc_dev(host->mmc), "rx"); |
|---|
| 699 | 699 | dev_dbg(mmc_dev(host->mmc), "%s: RX: got channel %p\n", __func__, |
|---|
| 700 | 700 | host->chan_rx); |
|---|
| 701 | 701 | |
|---|
| 702 | | - if (!host->chan_rx) |
|---|
| 702 | + if (IS_ERR(host->chan_rx)) { |
|---|
| 703 | + host->chan_rx = NULL; |
|---|
| 703 | 704 | goto e_release_tx; |
|---|
| 705 | + } |
|---|
| 704 | 706 | |
|---|
| 705 | 707 | cfg.direction = DMA_DEV_TO_MEM; |
|---|
| 706 | 708 | cfg.src_addr = cfg.dst_addr; |
|---|
| .. | .. |
|---|
| 1165 | 1167 | host->pins_uhs); |
|---|
| 1166 | 1168 | |
|---|
| 1167 | 1169 | default: |
|---|
| 1168 | | - return pinctrl_select_state(host->pinctrl, |
|---|
| 1169 | | - host->pins_default); |
|---|
| 1170 | + return pinctrl_select_default_state(mmc_dev(host->mmc)); |
|---|
| 1170 | 1171 | } |
|---|
| 1171 | 1172 | } |
|---|
| 1172 | 1173 | |
|---|
| .. | .. |
|---|
| 1342 | 1343 | host->wait = USDHI6_WAIT_FOR_STOP; |
|---|
| 1343 | 1344 | return 0; |
|---|
| 1344 | 1345 | } |
|---|
| 1345 | | - /* Unsupported STOP command */ |
|---|
| 1346 | + fallthrough; /* Unsupported STOP command */ |
|---|
| 1346 | 1347 | default: |
|---|
| 1347 | 1348 | dev_err(mmc_dev(host->mmc), |
|---|
| 1348 | 1349 | "unsupported stop CMD%d for CMD%d\n", |
|---|
| .. | .. |
|---|
| 1690 | 1691 | switch (host->wait) { |
|---|
| 1691 | 1692 | default: |
|---|
| 1692 | 1693 | dev_err(mmc_dev(host->mmc), "Invalid state %u\n", host->wait); |
|---|
| 1693 | | - /* mrq can be NULL in this actually impossible case */ |
|---|
| 1694 | + fallthrough; /* mrq can be NULL, but is impossible */ |
|---|
| 1694 | 1695 | case USDHI6_WAIT_FOR_CMD: |
|---|
| 1695 | 1696 | usdhi6_error_code(host); |
|---|
| 1696 | 1697 | if (mrq) |
|---|
| .. | .. |
|---|
| 1712 | 1713 | host->offset, data->blocks, data->blksz, data->sg_len, |
|---|
| 1713 | 1714 | sg_dma_len(sg), sg->offset); |
|---|
| 1714 | 1715 | usdhi6_sg_unmap(host, true); |
|---|
| 1715 | | - /* |
|---|
| 1716 | | - * If USDHI6_WAIT_FOR_DATA_END times out, we have already unmapped |
|---|
| 1717 | | - * the page |
|---|
| 1718 | | - */ |
|---|
| 1716 | + fallthrough; /* page unmapped in USDHI6_WAIT_FOR_DATA_END */ |
|---|
| 1719 | 1717 | case USDHI6_WAIT_FOR_DATA_END: |
|---|
| 1720 | 1718 | usdhi6_error_code(host); |
|---|
| 1721 | 1719 | data->error = -ETIMEDOUT; |
|---|
| .. | .. |
|---|
| 1767 | 1765 | host = mmc_priv(mmc); |
|---|
| 1768 | 1766 | host->mmc = mmc; |
|---|
| 1769 | 1767 | host->wait = USDHI6_WAIT_FOR_REQUEST; |
|---|
| 1770 | | - host->timeout = msecs_to_jiffies(4000); |
|---|
| 1768 | + host->timeout = msecs_to_jiffies(USDHI6_REQ_TIMEOUT_MS); |
|---|
| 1769 | + /* |
|---|
| 1770 | + * We use a fixed timeout of 4s, hence inform the core about it. A |
|---|
| 1771 | + * future improvement should instead respect the cmd->busy_timeout. |
|---|
| 1772 | + */ |
|---|
| 1773 | + mmc->max_busy_timeout = USDHI6_REQ_TIMEOUT_MS; |
|---|
| 1771 | 1774 | |
|---|
| 1772 | 1775 | host->pinctrl = devm_pinctrl_get(&pdev->dev); |
|---|
| 1773 | 1776 | if (IS_ERR(host->pinctrl)) { |
|---|
| .. | .. |
|---|
| 1776 | 1779 | } |
|---|
| 1777 | 1780 | |
|---|
| 1778 | 1781 | host->pins_uhs = pinctrl_lookup_state(host->pinctrl, "state_uhs"); |
|---|
| 1779 | | - if (!IS_ERR(host->pins_uhs)) { |
|---|
| 1780 | | - host->pins_default = pinctrl_lookup_state(host->pinctrl, |
|---|
| 1781 | | - PINCTRL_STATE_DEFAULT); |
|---|
| 1782 | | - |
|---|
| 1783 | | - if (IS_ERR(host->pins_default)) { |
|---|
| 1784 | | - dev_err(dev, |
|---|
| 1785 | | - "UHS pinctrl requires a default pin state.\n"); |
|---|
| 1786 | | - ret = PTR_ERR(host->pins_default); |
|---|
| 1787 | | - goto e_free_mmc; |
|---|
| 1788 | | - } |
|---|
| 1789 | | - } |
|---|
| 1790 | 1782 | |
|---|
| 1791 | 1783 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
|---|
| 1792 | 1784 | host->base = devm_ioremap_resource(dev, res); |
|---|
| .. | .. |
|---|
| 1901 | 1893 | .remove = usdhi6_remove, |
|---|
| 1902 | 1894 | .driver = { |
|---|
| 1903 | 1895 | .name = "usdhi6rol0", |
|---|
| 1896 | + .probe_type = PROBE_PREFER_ASYNCHRONOUS, |
|---|
| 1904 | 1897 | .of_match_table = usdhi6_of_match, |
|---|
| 1905 | 1898 | }, |
|---|
| 1906 | 1899 | }; |
|---|