.. | .. |
---|
| 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); |
---|