13fd784f7SMasahiro Yamada // SPDX-License-Identifier: GPL-2.0 23fd784f7SMasahiro Yamada // 33fd784f7SMasahiro Yamada // Copyright (C) 2017-2018 Socionext Inc. 43fd784f7SMasahiro Yamada // Author: Masahiro Yamada <yamada.masahiro@socionext.com> 53fd784f7SMasahiro Yamada 63fd784f7SMasahiro Yamada #include <linux/bitfield.h> 73fd784f7SMasahiro Yamada #include <linux/bitops.h> 83fd784f7SMasahiro Yamada #include <linux/clk.h> 93fd784f7SMasahiro Yamada #include <linux/delay.h> 103fd784f7SMasahiro Yamada #include <linux/dma-mapping.h> 113fd784f7SMasahiro Yamada #include <linux/mfd/tmio.h> 123fd784f7SMasahiro Yamada #include <linux/mmc/host.h> 133fd784f7SMasahiro Yamada #include <linux/module.h> 143fd784f7SMasahiro Yamada #include <linux/of.h> 153fd784f7SMasahiro Yamada #include <linux/of_device.h> 163fd784f7SMasahiro Yamada #include <linux/pinctrl/consumer.h> 173fd784f7SMasahiro Yamada #include <linux/platform_device.h> 183fd784f7SMasahiro Yamada #include <linux/reset.h> 193fd784f7SMasahiro Yamada 203fd784f7SMasahiro Yamada #include "tmio_mmc.h" 213fd784f7SMasahiro Yamada 223fd784f7SMasahiro Yamada #define UNIPHIER_SD_CLK_CTL_DIV1024 BIT(16) 233fd784f7SMasahiro Yamada #define UNIPHIER_SD_CLK_CTL_DIV1 BIT(10) 243fd784f7SMasahiro Yamada #define UNIPHIER_SD_CLKCTL_OFFEN BIT(9) // auto SDCLK stop 253fd784f7SMasahiro Yamada #define UNIPHIER_SD_CC_EXT_MODE 0x1b0 263fd784f7SMasahiro Yamada #define UNIPHIER_SD_CC_EXT_MODE_DMA BIT(1) 273fd784f7SMasahiro Yamada #define UNIPHIER_SD_HOST_MODE 0x1c8 283fd784f7SMasahiro Yamada #define UNIPHIER_SD_VOLT 0x1e4 293fd784f7SMasahiro Yamada #define UNIPHIER_SD_VOLT_MASK GENMASK(1, 0) 303fd784f7SMasahiro Yamada #define UNIPHIER_SD_VOLT_OFF 0 313fd784f7SMasahiro Yamada #define UNIPHIER_SD_VOLT_330 1 // 3.3V signal 323fd784f7SMasahiro Yamada #define UNIPHIER_SD_VOLT_180 2 // 1.8V signal 333fd784f7SMasahiro Yamada #define UNIPHIER_SD_DMA_MODE 0x410 343fd784f7SMasahiro Yamada #define UNIPHIER_SD_DMA_MODE_DIR_MASK GENMASK(17, 16) 353fd784f7SMasahiro Yamada #define UNIPHIER_SD_DMA_MODE_DIR_TO_DEV 0 363fd784f7SMasahiro Yamada #define UNIPHIER_SD_DMA_MODE_DIR_FROM_DEV 1 373fd784f7SMasahiro Yamada #define UNIPHIER_SD_DMA_MODE_WIDTH_MASK GENMASK(5, 4) 383fd784f7SMasahiro Yamada #define UNIPHIER_SD_DMA_MODE_WIDTH_8 0 393fd784f7SMasahiro Yamada #define UNIPHIER_SD_DMA_MODE_WIDTH_16 1 403fd784f7SMasahiro Yamada #define UNIPHIER_SD_DMA_MODE_WIDTH_32 2 413fd784f7SMasahiro Yamada #define UNIPHIER_SD_DMA_MODE_WIDTH_64 3 423fd784f7SMasahiro Yamada #define UNIPHIER_SD_DMA_MODE_ADDR_INC BIT(0) // 1: inc, 0: fixed 433fd784f7SMasahiro Yamada #define UNIPHIER_SD_DMA_CTL 0x414 443fd784f7SMasahiro Yamada #define UNIPHIER_SD_DMA_CTL_START BIT(0) // start DMA (auto cleared) 453fd784f7SMasahiro Yamada #define UNIPHIER_SD_DMA_RST 0x418 463fd784f7SMasahiro Yamada #define UNIPHIER_SD_DMA_RST_CH1 BIT(9) 473fd784f7SMasahiro Yamada #define UNIPHIER_SD_DMA_RST_CH0 BIT(8) 483fd784f7SMasahiro Yamada #define UNIPHIER_SD_DMA_ADDR_L 0x440 493fd784f7SMasahiro Yamada #define UNIPHIER_SD_DMA_ADDR_H 0x444 503fd784f7SMasahiro Yamada 513fd784f7SMasahiro Yamada /* 523fd784f7SMasahiro Yamada * IP is extended to support various features: built-in DMA engine, 533fd784f7SMasahiro Yamada * 1/1024 divisor, etc. 543fd784f7SMasahiro Yamada */ 553fd784f7SMasahiro Yamada #define UNIPHIER_SD_CAP_EXTENDED_IP BIT(0) 563fd784f7SMasahiro Yamada /* RX channel of the built-in DMA controller is broken (Pro5) */ 573fd784f7SMasahiro Yamada #define UNIPHIER_SD_CAP_BROKEN_DMA_RX BIT(1) 583fd784f7SMasahiro Yamada 593fd784f7SMasahiro Yamada struct uniphier_sd_priv { 603fd784f7SMasahiro Yamada struct tmio_mmc_data tmio_data; 613fd784f7SMasahiro Yamada struct pinctrl *pinctrl; 623fd784f7SMasahiro Yamada struct pinctrl_state *pinstate_uhs; 633fd784f7SMasahiro Yamada struct clk *clk; 643fd784f7SMasahiro Yamada struct reset_control *rst; 653fd784f7SMasahiro Yamada struct reset_control *rst_br; 663fd784f7SMasahiro Yamada struct reset_control *rst_hw; 673fd784f7SMasahiro Yamada struct dma_chan *chan; 683fd784f7SMasahiro Yamada enum dma_data_direction dma_dir; 693fd784f7SMasahiro Yamada unsigned long clk_rate; 703fd784f7SMasahiro Yamada unsigned long caps; 713fd784f7SMasahiro Yamada }; 723fd784f7SMasahiro Yamada 733fd784f7SMasahiro Yamada static void *uniphier_sd_priv(struct tmio_mmc_host *host) 743fd784f7SMasahiro Yamada { 753fd784f7SMasahiro Yamada return container_of(host->pdata, struct uniphier_sd_priv, tmio_data); 763fd784f7SMasahiro Yamada } 773fd784f7SMasahiro Yamada 783fd784f7SMasahiro Yamada static void uniphier_sd_dma_endisable(struct tmio_mmc_host *host, int enable) 793fd784f7SMasahiro Yamada { 80b7ced877SMasahiro Yamada sd_ctrl_write16(host, CTL_DMA_ENABLE, enable ? DMA_ENABLE_DMASDRW : 0); 813fd784f7SMasahiro Yamada } 823fd784f7SMasahiro Yamada 833fd784f7SMasahiro Yamada /* external DMA engine */ 843fd784f7SMasahiro Yamada static void uniphier_sd_external_dma_issue(unsigned long arg) 853fd784f7SMasahiro Yamada { 863fd784f7SMasahiro Yamada struct tmio_mmc_host *host = (void *)arg; 873fd784f7SMasahiro Yamada struct uniphier_sd_priv *priv = uniphier_sd_priv(host); 883fd784f7SMasahiro Yamada 893fd784f7SMasahiro Yamada uniphier_sd_dma_endisable(host, 1); 903fd784f7SMasahiro Yamada dma_async_issue_pending(priv->chan); 913fd784f7SMasahiro Yamada } 923fd784f7SMasahiro Yamada 933fd784f7SMasahiro Yamada static void uniphier_sd_external_dma_callback(void *param, 943fd784f7SMasahiro Yamada const struct dmaengine_result *result) 953fd784f7SMasahiro Yamada { 963fd784f7SMasahiro Yamada struct tmio_mmc_host *host = param; 973fd784f7SMasahiro Yamada struct uniphier_sd_priv *priv = uniphier_sd_priv(host); 983fd784f7SMasahiro Yamada unsigned long flags; 993fd784f7SMasahiro Yamada 1003fd784f7SMasahiro Yamada dma_unmap_sg(mmc_dev(host->mmc), host->sg_ptr, host->sg_len, 1013fd784f7SMasahiro Yamada priv->dma_dir); 1023fd784f7SMasahiro Yamada 1033fd784f7SMasahiro Yamada spin_lock_irqsave(&host->lock, flags); 1043fd784f7SMasahiro Yamada 1053fd784f7SMasahiro Yamada if (result->result == DMA_TRANS_NOERROR) { 1063fd784f7SMasahiro Yamada /* 1073fd784f7SMasahiro Yamada * When the external DMA engine is enabled, strangely enough, 1083fd784f7SMasahiro Yamada * the DATAEND flag can be asserted even if the DMA engine has 1093fd784f7SMasahiro Yamada * not been kicked yet. Enable the TMIO_STAT_DATAEND irq only 1103fd784f7SMasahiro Yamada * after we make sure the DMA engine finishes the transfer, 1113fd784f7SMasahiro Yamada * hence, in this callback. 1123fd784f7SMasahiro Yamada */ 1133fd784f7SMasahiro Yamada tmio_mmc_enable_mmc_irqs(host, TMIO_STAT_DATAEND); 1143fd784f7SMasahiro Yamada } else { 1153fd784f7SMasahiro Yamada host->data->error = -ETIMEDOUT; 1163fd784f7SMasahiro Yamada tmio_mmc_do_data_irq(host); 1173fd784f7SMasahiro Yamada } 1183fd784f7SMasahiro Yamada 1193fd784f7SMasahiro Yamada spin_unlock_irqrestore(&host->lock, flags); 1203fd784f7SMasahiro Yamada } 1213fd784f7SMasahiro Yamada 1223fd784f7SMasahiro Yamada static void uniphier_sd_external_dma_start(struct tmio_mmc_host *host, 1233fd784f7SMasahiro Yamada struct mmc_data *data) 1243fd784f7SMasahiro Yamada { 1253fd784f7SMasahiro Yamada struct uniphier_sd_priv *priv = uniphier_sd_priv(host); 1263fd784f7SMasahiro Yamada enum dma_transfer_direction dma_tx_dir; 1273fd784f7SMasahiro Yamada struct dma_async_tx_descriptor *desc; 1283fd784f7SMasahiro Yamada dma_cookie_t cookie; 1293fd784f7SMasahiro Yamada int sg_len; 1303fd784f7SMasahiro Yamada 1313fd784f7SMasahiro Yamada if (!priv->chan) 1323fd784f7SMasahiro Yamada goto force_pio; 1333fd784f7SMasahiro Yamada 1343fd784f7SMasahiro Yamada if (data->flags & MMC_DATA_READ) { 1353fd784f7SMasahiro Yamada priv->dma_dir = DMA_FROM_DEVICE; 1363fd784f7SMasahiro Yamada dma_tx_dir = DMA_DEV_TO_MEM; 1373fd784f7SMasahiro Yamada } else { 1383fd784f7SMasahiro Yamada priv->dma_dir = DMA_TO_DEVICE; 1393fd784f7SMasahiro Yamada dma_tx_dir = DMA_MEM_TO_DEV; 1403fd784f7SMasahiro Yamada } 1413fd784f7SMasahiro Yamada 1423fd784f7SMasahiro Yamada sg_len = dma_map_sg(mmc_dev(host->mmc), host->sg_ptr, host->sg_len, 1433fd784f7SMasahiro Yamada priv->dma_dir); 1443fd784f7SMasahiro Yamada if (sg_len == 0) 1453fd784f7SMasahiro Yamada goto force_pio; 1463fd784f7SMasahiro Yamada 1473fd784f7SMasahiro Yamada desc = dmaengine_prep_slave_sg(priv->chan, host->sg_ptr, sg_len, 1483fd784f7SMasahiro Yamada dma_tx_dir, DMA_CTRL_ACK); 1493fd784f7SMasahiro Yamada if (!desc) 1503fd784f7SMasahiro Yamada goto unmap_sg; 1513fd784f7SMasahiro Yamada 1523fd784f7SMasahiro Yamada desc->callback_result = uniphier_sd_external_dma_callback; 1533fd784f7SMasahiro Yamada desc->callback_param = host; 1543fd784f7SMasahiro Yamada 1553fd784f7SMasahiro Yamada cookie = dmaengine_submit(desc); 1563fd784f7SMasahiro Yamada if (cookie < 0) 1573fd784f7SMasahiro Yamada goto unmap_sg; 1583fd784f7SMasahiro Yamada 159d3dd5db0SMasahiro Yamada host->dma_on = true; 160d3dd5db0SMasahiro Yamada 1613fd784f7SMasahiro Yamada return; 1623fd784f7SMasahiro Yamada 1633fd784f7SMasahiro Yamada unmap_sg: 1643fd784f7SMasahiro Yamada dma_unmap_sg(mmc_dev(host->mmc), host->sg_ptr, host->sg_len, 1653fd784f7SMasahiro Yamada priv->dma_dir); 1663fd784f7SMasahiro Yamada force_pio: 1673fd784f7SMasahiro Yamada uniphier_sd_dma_endisable(host, 0); 1683fd784f7SMasahiro Yamada } 1693fd784f7SMasahiro Yamada 1703fd784f7SMasahiro Yamada static void uniphier_sd_external_dma_enable(struct tmio_mmc_host *host, 1713fd784f7SMasahiro Yamada bool enable) 1723fd784f7SMasahiro Yamada { 1733fd784f7SMasahiro Yamada } 1743fd784f7SMasahiro Yamada 1753fd784f7SMasahiro Yamada static void uniphier_sd_external_dma_request(struct tmio_mmc_host *host, 1763fd784f7SMasahiro Yamada struct tmio_mmc_data *pdata) 1773fd784f7SMasahiro Yamada { 1783fd784f7SMasahiro Yamada struct uniphier_sd_priv *priv = uniphier_sd_priv(host); 1793fd784f7SMasahiro Yamada struct dma_chan *chan; 1803fd784f7SMasahiro Yamada 1813fd784f7SMasahiro Yamada chan = dma_request_chan(mmc_dev(host->mmc), "rx-tx"); 1823fd784f7SMasahiro Yamada if (IS_ERR(chan)) { 1833fd784f7SMasahiro Yamada dev_warn(mmc_dev(host->mmc), 1843fd784f7SMasahiro Yamada "failed to request DMA channel. falling back to PIO\n"); 1853fd784f7SMasahiro Yamada return; /* just use PIO even for -EPROBE_DEFER */ 1863fd784f7SMasahiro Yamada } 1873fd784f7SMasahiro Yamada 1883fd784f7SMasahiro Yamada /* this driver uses a single channel for both RX an TX */ 1893fd784f7SMasahiro Yamada priv->chan = chan; 1903fd784f7SMasahiro Yamada host->chan_rx = chan; 1913fd784f7SMasahiro Yamada host->chan_tx = chan; 1923fd784f7SMasahiro Yamada 1933fd784f7SMasahiro Yamada tasklet_init(&host->dma_issue, uniphier_sd_external_dma_issue, 1943fd784f7SMasahiro Yamada (unsigned long)host); 1953fd784f7SMasahiro Yamada } 1963fd784f7SMasahiro Yamada 1973fd784f7SMasahiro Yamada static void uniphier_sd_external_dma_release(struct tmio_mmc_host *host) 1983fd784f7SMasahiro Yamada { 1993fd784f7SMasahiro Yamada struct uniphier_sd_priv *priv = uniphier_sd_priv(host); 2003fd784f7SMasahiro Yamada 2013fd784f7SMasahiro Yamada if (priv->chan) 2023fd784f7SMasahiro Yamada dma_release_channel(priv->chan); 2033fd784f7SMasahiro Yamada } 2043fd784f7SMasahiro Yamada 2053fd784f7SMasahiro Yamada static void uniphier_sd_external_dma_abort(struct tmio_mmc_host *host) 2063fd784f7SMasahiro Yamada { 2073fd784f7SMasahiro Yamada struct uniphier_sd_priv *priv = uniphier_sd_priv(host); 2083fd784f7SMasahiro Yamada 2093fd784f7SMasahiro Yamada uniphier_sd_dma_endisable(host, 0); 2103fd784f7SMasahiro Yamada 2113fd784f7SMasahiro Yamada if (priv->chan) 2123fd784f7SMasahiro Yamada dmaengine_terminate_sync(priv->chan); 2133fd784f7SMasahiro Yamada } 2143fd784f7SMasahiro Yamada 2153fd784f7SMasahiro Yamada static void uniphier_sd_external_dma_dataend(struct tmio_mmc_host *host) 2163fd784f7SMasahiro Yamada { 2173fd784f7SMasahiro Yamada uniphier_sd_dma_endisable(host, 0); 2183fd784f7SMasahiro Yamada 2193fd784f7SMasahiro Yamada tmio_mmc_do_data_irq(host); 2203fd784f7SMasahiro Yamada } 2213fd784f7SMasahiro Yamada 2223fd784f7SMasahiro Yamada static const struct tmio_mmc_dma_ops uniphier_sd_external_dma_ops = { 2233fd784f7SMasahiro Yamada .start = uniphier_sd_external_dma_start, 2243fd784f7SMasahiro Yamada .enable = uniphier_sd_external_dma_enable, 2253fd784f7SMasahiro Yamada .request = uniphier_sd_external_dma_request, 2263fd784f7SMasahiro Yamada .release = uniphier_sd_external_dma_release, 2273fd784f7SMasahiro Yamada .abort = uniphier_sd_external_dma_abort, 2283fd784f7SMasahiro Yamada .dataend = uniphier_sd_external_dma_dataend, 2293fd784f7SMasahiro Yamada }; 2303fd784f7SMasahiro Yamada 2313fd784f7SMasahiro Yamada static void uniphier_sd_internal_dma_issue(unsigned long arg) 2323fd784f7SMasahiro Yamada { 2333fd784f7SMasahiro Yamada struct tmio_mmc_host *host = (void *)arg; 2343fd784f7SMasahiro Yamada unsigned long flags; 2353fd784f7SMasahiro Yamada 2363fd784f7SMasahiro Yamada spin_lock_irqsave(&host->lock, flags); 2373fd784f7SMasahiro Yamada tmio_mmc_enable_mmc_irqs(host, TMIO_STAT_DATAEND); 2383fd784f7SMasahiro Yamada spin_unlock_irqrestore(&host->lock, flags); 2393fd784f7SMasahiro Yamada 2403fd784f7SMasahiro Yamada uniphier_sd_dma_endisable(host, 1); 2413fd784f7SMasahiro Yamada writel(UNIPHIER_SD_DMA_CTL_START, host->ctl + UNIPHIER_SD_DMA_CTL); 2423fd784f7SMasahiro Yamada } 2433fd784f7SMasahiro Yamada 2443fd784f7SMasahiro Yamada static void uniphier_sd_internal_dma_start(struct tmio_mmc_host *host, 2453fd784f7SMasahiro Yamada struct mmc_data *data) 2463fd784f7SMasahiro Yamada { 2473fd784f7SMasahiro Yamada struct uniphier_sd_priv *priv = uniphier_sd_priv(host); 2483fd784f7SMasahiro Yamada struct scatterlist *sg = host->sg_ptr; 2493fd784f7SMasahiro Yamada dma_addr_t dma_addr; 2503fd784f7SMasahiro Yamada unsigned int dma_mode_dir; 2513fd784f7SMasahiro Yamada u32 dma_mode; 2523fd784f7SMasahiro Yamada int sg_len; 2533fd784f7SMasahiro Yamada 25490f83541SMasahiro Yamada if ((data->flags & MMC_DATA_READ) && !host->chan_rx) 25590f83541SMasahiro Yamada goto force_pio; 25690f83541SMasahiro Yamada 2573fd784f7SMasahiro Yamada if (WARN_ON(host->sg_len != 1)) 2583fd784f7SMasahiro Yamada goto force_pio; 2593fd784f7SMasahiro Yamada 2603fd784f7SMasahiro Yamada if (!IS_ALIGNED(sg->offset, 8)) 2613fd784f7SMasahiro Yamada goto force_pio; 2623fd784f7SMasahiro Yamada 2633fd784f7SMasahiro Yamada if (data->flags & MMC_DATA_READ) { 2643fd784f7SMasahiro Yamada priv->dma_dir = DMA_FROM_DEVICE; 2653fd784f7SMasahiro Yamada dma_mode_dir = UNIPHIER_SD_DMA_MODE_DIR_FROM_DEV; 2663fd784f7SMasahiro Yamada } else { 2673fd784f7SMasahiro Yamada priv->dma_dir = DMA_TO_DEVICE; 2683fd784f7SMasahiro Yamada dma_mode_dir = UNIPHIER_SD_DMA_MODE_DIR_TO_DEV; 2693fd784f7SMasahiro Yamada } 2703fd784f7SMasahiro Yamada 2713fd784f7SMasahiro Yamada sg_len = dma_map_sg(mmc_dev(host->mmc), sg, 1, priv->dma_dir); 2723fd784f7SMasahiro Yamada if (sg_len == 0) 2733fd784f7SMasahiro Yamada goto force_pio; 2743fd784f7SMasahiro Yamada 2753fd784f7SMasahiro Yamada dma_mode = FIELD_PREP(UNIPHIER_SD_DMA_MODE_DIR_MASK, dma_mode_dir); 2763fd784f7SMasahiro Yamada dma_mode |= FIELD_PREP(UNIPHIER_SD_DMA_MODE_WIDTH_MASK, 2773fd784f7SMasahiro Yamada UNIPHIER_SD_DMA_MODE_WIDTH_64); 2783fd784f7SMasahiro Yamada dma_mode |= UNIPHIER_SD_DMA_MODE_ADDR_INC; 2793fd784f7SMasahiro Yamada 2803fd784f7SMasahiro Yamada writel(dma_mode, host->ctl + UNIPHIER_SD_DMA_MODE); 2813fd784f7SMasahiro Yamada 2823fd784f7SMasahiro Yamada dma_addr = sg_dma_address(data->sg); 2833fd784f7SMasahiro Yamada writel(lower_32_bits(dma_addr), host->ctl + UNIPHIER_SD_DMA_ADDR_L); 2843fd784f7SMasahiro Yamada writel(upper_32_bits(dma_addr), host->ctl + UNIPHIER_SD_DMA_ADDR_H); 2853fd784f7SMasahiro Yamada 286d3dd5db0SMasahiro Yamada host->dma_on = true; 287d3dd5db0SMasahiro Yamada 2883fd784f7SMasahiro Yamada return; 2893fd784f7SMasahiro Yamada force_pio: 2903fd784f7SMasahiro Yamada uniphier_sd_dma_endisable(host, 0); 2913fd784f7SMasahiro Yamada } 2923fd784f7SMasahiro Yamada 2933fd784f7SMasahiro Yamada static void uniphier_sd_internal_dma_enable(struct tmio_mmc_host *host, 2943fd784f7SMasahiro Yamada bool enable) 2953fd784f7SMasahiro Yamada { 2963fd784f7SMasahiro Yamada } 2973fd784f7SMasahiro Yamada 2983fd784f7SMasahiro Yamada static void uniphier_sd_internal_dma_request(struct tmio_mmc_host *host, 2993fd784f7SMasahiro Yamada struct tmio_mmc_data *pdata) 3003fd784f7SMasahiro Yamada { 3013fd784f7SMasahiro Yamada struct uniphier_sd_priv *priv = uniphier_sd_priv(host); 3023fd784f7SMasahiro Yamada 3033fd784f7SMasahiro Yamada /* 3043fd784f7SMasahiro Yamada * Due to a hardware bug, Pro5 cannot use DMA for RX. 3053fd784f7SMasahiro Yamada * We can still use DMA for TX, but PIO for RX. 3063fd784f7SMasahiro Yamada */ 3073fd784f7SMasahiro Yamada if (!(priv->caps & UNIPHIER_SD_CAP_BROKEN_DMA_RX)) 3083fd784f7SMasahiro Yamada host->chan_rx = (void *)0xdeadbeaf; 3093fd784f7SMasahiro Yamada 3103fd784f7SMasahiro Yamada host->chan_tx = (void *)0xdeadbeaf; 3113fd784f7SMasahiro Yamada 3123fd784f7SMasahiro Yamada tasklet_init(&host->dma_issue, uniphier_sd_internal_dma_issue, 3133fd784f7SMasahiro Yamada (unsigned long)host); 3143fd784f7SMasahiro Yamada } 3153fd784f7SMasahiro Yamada 3163fd784f7SMasahiro Yamada static void uniphier_sd_internal_dma_release(struct tmio_mmc_host *host) 3173fd784f7SMasahiro Yamada { 3183fd784f7SMasahiro Yamada /* Each value is set to zero to assume "disabling" each DMA */ 3193fd784f7SMasahiro Yamada host->chan_rx = NULL; 3203fd784f7SMasahiro Yamada host->chan_tx = NULL; 3213fd784f7SMasahiro Yamada } 3223fd784f7SMasahiro Yamada 3233fd784f7SMasahiro Yamada static void uniphier_sd_internal_dma_abort(struct tmio_mmc_host *host) 3243fd784f7SMasahiro Yamada { 3253fd784f7SMasahiro Yamada u32 tmp; 3263fd784f7SMasahiro Yamada 3273fd784f7SMasahiro Yamada uniphier_sd_dma_endisable(host, 0); 3283fd784f7SMasahiro Yamada 3293fd784f7SMasahiro Yamada tmp = readl(host->ctl + UNIPHIER_SD_DMA_RST); 3303fd784f7SMasahiro Yamada tmp &= ~(UNIPHIER_SD_DMA_RST_CH1 | UNIPHIER_SD_DMA_RST_CH0); 3313fd784f7SMasahiro Yamada writel(tmp, host->ctl + UNIPHIER_SD_DMA_RST); 3323fd784f7SMasahiro Yamada 3333fd784f7SMasahiro Yamada tmp |= UNIPHIER_SD_DMA_RST_CH1 | UNIPHIER_SD_DMA_RST_CH0; 3343fd784f7SMasahiro Yamada writel(tmp, host->ctl + UNIPHIER_SD_DMA_RST); 3353fd784f7SMasahiro Yamada } 3363fd784f7SMasahiro Yamada 3373fd784f7SMasahiro Yamada static void uniphier_sd_internal_dma_dataend(struct tmio_mmc_host *host) 3383fd784f7SMasahiro Yamada { 3393fd784f7SMasahiro Yamada struct uniphier_sd_priv *priv = uniphier_sd_priv(host); 3403fd784f7SMasahiro Yamada 3413fd784f7SMasahiro Yamada uniphier_sd_dma_endisable(host, 0); 3423fd784f7SMasahiro Yamada dma_unmap_sg(mmc_dev(host->mmc), host->sg_ptr, 1, priv->dma_dir); 3433fd784f7SMasahiro Yamada 3443fd784f7SMasahiro Yamada tmio_mmc_do_data_irq(host); 3453fd784f7SMasahiro Yamada } 3463fd784f7SMasahiro Yamada 3473fd784f7SMasahiro Yamada static const struct tmio_mmc_dma_ops uniphier_sd_internal_dma_ops = { 3483fd784f7SMasahiro Yamada .start = uniphier_sd_internal_dma_start, 3493fd784f7SMasahiro Yamada .enable = uniphier_sd_internal_dma_enable, 3503fd784f7SMasahiro Yamada .request = uniphier_sd_internal_dma_request, 3513fd784f7SMasahiro Yamada .release = uniphier_sd_internal_dma_release, 3523fd784f7SMasahiro Yamada .abort = uniphier_sd_internal_dma_abort, 3533fd784f7SMasahiro Yamada .dataend = uniphier_sd_internal_dma_dataend, 3543fd784f7SMasahiro Yamada }; 3553fd784f7SMasahiro Yamada 3563fd784f7SMasahiro Yamada static int uniphier_sd_clk_enable(struct tmio_mmc_host *host) 3573fd784f7SMasahiro Yamada { 3583fd784f7SMasahiro Yamada struct uniphier_sd_priv *priv = uniphier_sd_priv(host); 3593fd784f7SMasahiro Yamada struct mmc_host *mmc = host->mmc; 3603fd784f7SMasahiro Yamada int ret; 3613fd784f7SMasahiro Yamada 3623fd784f7SMasahiro Yamada ret = clk_prepare_enable(priv->clk); 3633fd784f7SMasahiro Yamada if (ret) 3643fd784f7SMasahiro Yamada return ret; 3653fd784f7SMasahiro Yamada 3663fd784f7SMasahiro Yamada ret = clk_set_rate(priv->clk, ULONG_MAX); 3673fd784f7SMasahiro Yamada if (ret) 3683fd784f7SMasahiro Yamada goto disable_clk; 3693fd784f7SMasahiro Yamada 3703fd784f7SMasahiro Yamada priv->clk_rate = clk_get_rate(priv->clk); 3713fd784f7SMasahiro Yamada 3723fd784f7SMasahiro Yamada /* If max-frequency property is set, use it. */ 3733fd784f7SMasahiro Yamada if (!mmc->f_max) 3743fd784f7SMasahiro Yamada mmc->f_max = priv->clk_rate; 3753fd784f7SMasahiro Yamada 3763fd784f7SMasahiro Yamada /* 3773fd784f7SMasahiro Yamada * 1/512 is the finest divisor in the original IP. Newer versions 3783fd784f7SMasahiro Yamada * also supports 1/1024 divisor. (UniPhier-specific extension) 3793fd784f7SMasahiro Yamada */ 3803fd784f7SMasahiro Yamada if (priv->caps & UNIPHIER_SD_CAP_EXTENDED_IP) 3813fd784f7SMasahiro Yamada mmc->f_min = priv->clk_rate / 1024; 3823fd784f7SMasahiro Yamada else 3833fd784f7SMasahiro Yamada mmc->f_min = priv->clk_rate / 512; 3843fd784f7SMasahiro Yamada 3853fd784f7SMasahiro Yamada ret = reset_control_deassert(priv->rst); 3863fd784f7SMasahiro Yamada if (ret) 3873fd784f7SMasahiro Yamada goto disable_clk; 3883fd784f7SMasahiro Yamada 3893fd784f7SMasahiro Yamada ret = reset_control_deassert(priv->rst_br); 3903fd784f7SMasahiro Yamada if (ret) 3913fd784f7SMasahiro Yamada goto assert_rst; 3923fd784f7SMasahiro Yamada 3933fd784f7SMasahiro Yamada return 0; 3943fd784f7SMasahiro Yamada 3953fd784f7SMasahiro Yamada assert_rst: 3963fd784f7SMasahiro Yamada reset_control_assert(priv->rst); 3973fd784f7SMasahiro Yamada disable_clk: 3983fd784f7SMasahiro Yamada clk_disable_unprepare(priv->clk); 3993fd784f7SMasahiro Yamada 4003fd784f7SMasahiro Yamada return ret; 4013fd784f7SMasahiro Yamada } 4023fd784f7SMasahiro Yamada 4033fd784f7SMasahiro Yamada static void uniphier_sd_clk_disable(struct tmio_mmc_host *host) 4043fd784f7SMasahiro Yamada { 4053fd784f7SMasahiro Yamada struct uniphier_sd_priv *priv = uniphier_sd_priv(host); 4063fd784f7SMasahiro Yamada 4073fd784f7SMasahiro Yamada reset_control_assert(priv->rst_br); 4083fd784f7SMasahiro Yamada reset_control_assert(priv->rst); 4093fd784f7SMasahiro Yamada clk_disable_unprepare(priv->clk); 4103fd784f7SMasahiro Yamada } 4113fd784f7SMasahiro Yamada 4123fd784f7SMasahiro Yamada static void uniphier_sd_hw_reset(struct tmio_mmc_host *host) 4133fd784f7SMasahiro Yamada { 4143fd784f7SMasahiro Yamada struct uniphier_sd_priv *priv = uniphier_sd_priv(host); 4153fd784f7SMasahiro Yamada 4163fd784f7SMasahiro Yamada reset_control_assert(priv->rst_hw); 4173fd784f7SMasahiro Yamada /* For eMMC, minimum is 1us but give it 9us for good measure */ 4183fd784f7SMasahiro Yamada udelay(9); 4193fd784f7SMasahiro Yamada reset_control_deassert(priv->rst_hw); 4203fd784f7SMasahiro Yamada /* For eMMC, minimum is 200us but give it 300us for good measure */ 4213fd784f7SMasahiro Yamada usleep_range(300, 1000); 4223fd784f7SMasahiro Yamada } 4233fd784f7SMasahiro Yamada 4243fd784f7SMasahiro Yamada static void uniphier_sd_set_clock(struct tmio_mmc_host *host, 4253fd784f7SMasahiro Yamada unsigned int clock) 4263fd784f7SMasahiro Yamada { 4273fd784f7SMasahiro Yamada struct uniphier_sd_priv *priv = uniphier_sd_priv(host); 4283fd784f7SMasahiro Yamada unsigned long divisor; 4293fd784f7SMasahiro Yamada u32 tmp; 4303fd784f7SMasahiro Yamada 4313fd784f7SMasahiro Yamada tmp = readl(host->ctl + (CTL_SD_CARD_CLK_CTL << 1)); 4323fd784f7SMasahiro Yamada 4333fd784f7SMasahiro Yamada /* stop the clock before changing its rate to avoid a glitch signal */ 4343fd784f7SMasahiro Yamada tmp &= ~CLK_CTL_SCLKEN; 4353fd784f7SMasahiro Yamada writel(tmp, host->ctl + (CTL_SD_CARD_CLK_CTL << 1)); 4363fd784f7SMasahiro Yamada 4373fd784f7SMasahiro Yamada if (clock == 0) 4383fd784f7SMasahiro Yamada return; 4393fd784f7SMasahiro Yamada 4403fd784f7SMasahiro Yamada tmp &= ~UNIPHIER_SD_CLK_CTL_DIV1024; 4413fd784f7SMasahiro Yamada tmp &= ~UNIPHIER_SD_CLK_CTL_DIV1; 4423fd784f7SMasahiro Yamada tmp &= ~CLK_CTL_DIV_MASK; 4433fd784f7SMasahiro Yamada 4443fd784f7SMasahiro Yamada divisor = priv->clk_rate / clock; 4453fd784f7SMasahiro Yamada 4463fd784f7SMasahiro Yamada /* 4473fd784f7SMasahiro Yamada * In the original IP, bit[7:0] represents the divisor. 4483fd784f7SMasahiro Yamada * bit7 set: 1/512, ... bit0 set:1/4, all bits clear: 1/2 4493fd784f7SMasahiro Yamada * 4503fd784f7SMasahiro Yamada * The IP does not define a way to achieve 1/1. For UniPhier variants, 4513fd784f7SMasahiro Yamada * bit10 is used for 1/1. Newer versions of UniPhier variants use 4523fd784f7SMasahiro Yamada * bit16 for 1/1024. 4533fd784f7SMasahiro Yamada */ 4543fd784f7SMasahiro Yamada if (divisor <= 1) 4553fd784f7SMasahiro Yamada tmp |= UNIPHIER_SD_CLK_CTL_DIV1; 4563fd784f7SMasahiro Yamada else if (priv->caps & UNIPHIER_SD_CAP_EXTENDED_IP && divisor > 512) 4573fd784f7SMasahiro Yamada tmp |= UNIPHIER_SD_CLK_CTL_DIV1024; 4583fd784f7SMasahiro Yamada else 4593fd784f7SMasahiro Yamada tmp |= roundup_pow_of_two(divisor) >> 2; 4603fd784f7SMasahiro Yamada 4613fd784f7SMasahiro Yamada writel(tmp, host->ctl + (CTL_SD_CARD_CLK_CTL << 1)); 4623fd784f7SMasahiro Yamada 4633fd784f7SMasahiro Yamada tmp |= CLK_CTL_SCLKEN; 4643fd784f7SMasahiro Yamada writel(tmp, host->ctl + (CTL_SD_CARD_CLK_CTL << 1)); 4653fd784f7SMasahiro Yamada } 4663fd784f7SMasahiro Yamada 4673fd784f7SMasahiro Yamada static void uniphier_sd_host_init(struct tmio_mmc_host *host) 4683fd784f7SMasahiro Yamada { 4693fd784f7SMasahiro Yamada struct uniphier_sd_priv *priv = uniphier_sd_priv(host); 4703fd784f7SMasahiro Yamada u32 val; 4713fd784f7SMasahiro Yamada 4723fd784f7SMasahiro Yamada /* 4733fd784f7SMasahiro Yamada * Connected to 32bit AXI. 4743fd784f7SMasahiro Yamada * This register holds settings for SoC-specific internal bus 4753fd784f7SMasahiro Yamada * connection. What is worse, the register spec was changed, 4763fd784f7SMasahiro Yamada * breaking the backward compatibility. Write an appropriate 4773fd784f7SMasahiro Yamada * value depending on a flag associated with a compatible string. 4783fd784f7SMasahiro Yamada */ 4793fd784f7SMasahiro Yamada if (priv->caps & UNIPHIER_SD_CAP_EXTENDED_IP) 4803fd784f7SMasahiro Yamada val = 0x00000101; 4813fd784f7SMasahiro Yamada else 4823fd784f7SMasahiro Yamada val = 0x00000000; 4833fd784f7SMasahiro Yamada 4843fd784f7SMasahiro Yamada writel(val, host->ctl + UNIPHIER_SD_HOST_MODE); 4853fd784f7SMasahiro Yamada 4863fd784f7SMasahiro Yamada val = 0; 4873fd784f7SMasahiro Yamada /* 4883fd784f7SMasahiro Yamada * If supported, the controller can automatically 4893fd784f7SMasahiro Yamada * enable/disable the clock line to the card. 4903fd784f7SMasahiro Yamada */ 4913fd784f7SMasahiro Yamada if (priv->caps & UNIPHIER_SD_CAP_EXTENDED_IP) 4923fd784f7SMasahiro Yamada val |= UNIPHIER_SD_CLKCTL_OFFEN; 4933fd784f7SMasahiro Yamada 4943fd784f7SMasahiro Yamada writel(val, host->ctl + (CTL_SD_CARD_CLK_CTL << 1)); 4953fd784f7SMasahiro Yamada } 4963fd784f7SMasahiro Yamada 4973fd784f7SMasahiro Yamada static int uniphier_sd_start_signal_voltage_switch(struct mmc_host *mmc, 4983fd784f7SMasahiro Yamada struct mmc_ios *ios) 4993fd784f7SMasahiro Yamada { 5003fd784f7SMasahiro Yamada struct tmio_mmc_host *host = mmc_priv(mmc); 5013fd784f7SMasahiro Yamada struct uniphier_sd_priv *priv = uniphier_sd_priv(host); 5028e9a9936SUlf Hansson struct pinctrl_state *pinstate = NULL; 5033fd784f7SMasahiro Yamada u32 val, tmp; 5043fd784f7SMasahiro Yamada 5053fd784f7SMasahiro Yamada switch (ios->signal_voltage) { 5063fd784f7SMasahiro Yamada case MMC_SIGNAL_VOLTAGE_330: 5073fd784f7SMasahiro Yamada val = UNIPHIER_SD_VOLT_330; 5083fd784f7SMasahiro Yamada break; 5093fd784f7SMasahiro Yamada case MMC_SIGNAL_VOLTAGE_180: 5103fd784f7SMasahiro Yamada val = UNIPHIER_SD_VOLT_180; 5113fd784f7SMasahiro Yamada pinstate = priv->pinstate_uhs; 5123fd784f7SMasahiro Yamada break; 5133fd784f7SMasahiro Yamada default: 5143fd784f7SMasahiro Yamada return -ENOTSUPP; 5153fd784f7SMasahiro Yamada } 5163fd784f7SMasahiro Yamada 5173fd784f7SMasahiro Yamada tmp = readl(host->ctl + UNIPHIER_SD_VOLT); 5183fd784f7SMasahiro Yamada tmp &= ~UNIPHIER_SD_VOLT_MASK; 5193fd784f7SMasahiro Yamada tmp |= FIELD_PREP(UNIPHIER_SD_VOLT_MASK, val); 5203fd784f7SMasahiro Yamada writel(tmp, host->ctl + UNIPHIER_SD_VOLT); 5213fd784f7SMasahiro Yamada 5228e9a9936SUlf Hansson if (pinstate) 5233fd784f7SMasahiro Yamada pinctrl_select_state(priv->pinctrl, pinstate); 5248e9a9936SUlf Hansson else 5258e9a9936SUlf Hansson pinctrl_select_default_state(mmc_dev(mmc)); 5263fd784f7SMasahiro Yamada 5273fd784f7SMasahiro Yamada return 0; 5283fd784f7SMasahiro Yamada } 5293fd784f7SMasahiro Yamada 5303fd784f7SMasahiro Yamada static int uniphier_sd_uhs_init(struct tmio_mmc_host *host, 5313fd784f7SMasahiro Yamada struct uniphier_sd_priv *priv) 5323fd784f7SMasahiro Yamada { 5333fd784f7SMasahiro Yamada priv->pinctrl = devm_pinctrl_get(mmc_dev(host->mmc)); 5343fd784f7SMasahiro Yamada if (IS_ERR(priv->pinctrl)) 5353fd784f7SMasahiro Yamada return PTR_ERR(priv->pinctrl); 5363fd784f7SMasahiro Yamada 5373fd784f7SMasahiro Yamada priv->pinstate_uhs = pinctrl_lookup_state(priv->pinctrl, "uhs"); 5383fd784f7SMasahiro Yamada if (IS_ERR(priv->pinstate_uhs)) 5393fd784f7SMasahiro Yamada return PTR_ERR(priv->pinstate_uhs); 5403fd784f7SMasahiro Yamada 5413fd784f7SMasahiro Yamada host->ops.start_signal_voltage_switch = 5423fd784f7SMasahiro Yamada uniphier_sd_start_signal_voltage_switch; 5433fd784f7SMasahiro Yamada 5443fd784f7SMasahiro Yamada return 0; 5453fd784f7SMasahiro Yamada } 5463fd784f7SMasahiro Yamada 5473fd784f7SMasahiro Yamada static int uniphier_sd_probe(struct platform_device *pdev) 5483fd784f7SMasahiro Yamada { 5493fd784f7SMasahiro Yamada struct device *dev = &pdev->dev; 5503fd784f7SMasahiro Yamada struct uniphier_sd_priv *priv; 5513fd784f7SMasahiro Yamada struct tmio_mmc_data *tmio_data; 5523fd784f7SMasahiro Yamada struct tmio_mmc_host *host; 5533fd784f7SMasahiro Yamada int irq, ret; 5543fd784f7SMasahiro Yamada 5553fd784f7SMasahiro Yamada irq = platform_get_irq(pdev, 0); 5569a7957d0SStephen Boyd if (irq < 0) 5573fd784f7SMasahiro Yamada return irq; 5583fd784f7SMasahiro Yamada 5593fd784f7SMasahiro Yamada priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 5603fd784f7SMasahiro Yamada if (!priv) 5613fd784f7SMasahiro Yamada return -ENOMEM; 5623fd784f7SMasahiro Yamada 5633fd784f7SMasahiro Yamada priv->caps = (unsigned long)of_device_get_match_data(dev); 5643fd784f7SMasahiro Yamada 5653fd784f7SMasahiro Yamada priv->clk = devm_clk_get(dev, NULL); 5663fd784f7SMasahiro Yamada if (IS_ERR(priv->clk)) { 5673fd784f7SMasahiro Yamada dev_err(dev, "failed to get clock\n"); 5683fd784f7SMasahiro Yamada return PTR_ERR(priv->clk); 5693fd784f7SMasahiro Yamada } 5703fd784f7SMasahiro Yamada 5713fd784f7SMasahiro Yamada priv->rst = devm_reset_control_get_shared(dev, "host"); 5723fd784f7SMasahiro Yamada if (IS_ERR(priv->rst)) { 5733fd784f7SMasahiro Yamada dev_err(dev, "failed to get host reset\n"); 5743fd784f7SMasahiro Yamada return PTR_ERR(priv->rst); 5753fd784f7SMasahiro Yamada } 5763fd784f7SMasahiro Yamada 5773fd784f7SMasahiro Yamada /* old version has one more reset */ 5783fd784f7SMasahiro Yamada if (!(priv->caps & UNIPHIER_SD_CAP_EXTENDED_IP)) { 5793fd784f7SMasahiro Yamada priv->rst_br = devm_reset_control_get_shared(dev, "bridge"); 5803fd784f7SMasahiro Yamada if (IS_ERR(priv->rst_br)) { 5813fd784f7SMasahiro Yamada dev_err(dev, "failed to get bridge reset\n"); 5823fd784f7SMasahiro Yamada return PTR_ERR(priv->rst_br); 5833fd784f7SMasahiro Yamada } 5843fd784f7SMasahiro Yamada } 5853fd784f7SMasahiro Yamada 5863fd784f7SMasahiro Yamada tmio_data = &priv->tmio_data; 5873fd784f7SMasahiro Yamada tmio_data->flags |= TMIO_MMC_32BIT_DATA_PORT; 5883fd784f7SMasahiro Yamada 5893fd784f7SMasahiro Yamada host = tmio_mmc_host_alloc(pdev, tmio_data); 5903fd784f7SMasahiro Yamada if (IS_ERR(host)) 5913fd784f7SMasahiro Yamada return PTR_ERR(host); 5923fd784f7SMasahiro Yamada 5933fd784f7SMasahiro Yamada if (host->mmc->caps & MMC_CAP_HW_RESET) { 5943fd784f7SMasahiro Yamada priv->rst_hw = devm_reset_control_get_exclusive(dev, "hw"); 5953fd784f7SMasahiro Yamada if (IS_ERR(priv->rst_hw)) { 5963fd784f7SMasahiro Yamada dev_err(dev, "failed to get hw reset\n"); 5973fd784f7SMasahiro Yamada ret = PTR_ERR(priv->rst_hw); 5983fd784f7SMasahiro Yamada goto free_host; 5993fd784f7SMasahiro Yamada } 6003fd784f7SMasahiro Yamada host->hw_reset = uniphier_sd_hw_reset; 6013fd784f7SMasahiro Yamada } 6023fd784f7SMasahiro Yamada 6033fd784f7SMasahiro Yamada if (host->mmc->caps & MMC_CAP_UHS) { 6043fd784f7SMasahiro Yamada ret = uniphier_sd_uhs_init(host, priv); 6053fd784f7SMasahiro Yamada if (ret) { 6063fd784f7SMasahiro Yamada dev_warn(dev, 6073fd784f7SMasahiro Yamada "failed to setup UHS (error %d). Disabling UHS.", 6083fd784f7SMasahiro Yamada ret); 6093fd784f7SMasahiro Yamada host->mmc->caps &= ~MMC_CAP_UHS; 6103fd784f7SMasahiro Yamada } 6113fd784f7SMasahiro Yamada } 6123fd784f7SMasahiro Yamada 6133fd784f7SMasahiro Yamada ret = devm_request_irq(dev, irq, tmio_mmc_irq, IRQF_SHARED, 6143fd784f7SMasahiro Yamada dev_name(dev), host); 6153fd784f7SMasahiro Yamada if (ret) 6163fd784f7SMasahiro Yamada goto free_host; 6173fd784f7SMasahiro Yamada 6183fd784f7SMasahiro Yamada if (priv->caps & UNIPHIER_SD_CAP_EXTENDED_IP) 6193fd784f7SMasahiro Yamada host->dma_ops = &uniphier_sd_internal_dma_ops; 6203fd784f7SMasahiro Yamada else 6213fd784f7SMasahiro Yamada host->dma_ops = &uniphier_sd_external_dma_ops; 6223fd784f7SMasahiro Yamada 6233fd784f7SMasahiro Yamada host->bus_shift = 1; 6243fd784f7SMasahiro Yamada host->clk_enable = uniphier_sd_clk_enable; 6253fd784f7SMasahiro Yamada host->clk_disable = uniphier_sd_clk_disable; 6263fd784f7SMasahiro Yamada host->set_clock = uniphier_sd_set_clock; 6273fd784f7SMasahiro Yamada 6283fd784f7SMasahiro Yamada ret = uniphier_sd_clk_enable(host); 6293fd784f7SMasahiro Yamada if (ret) 6303fd784f7SMasahiro Yamada goto free_host; 6313fd784f7SMasahiro Yamada 6323fd784f7SMasahiro Yamada uniphier_sd_host_init(host); 6333fd784f7SMasahiro Yamada 6343fd784f7SMasahiro Yamada tmio_data->ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34; 6353fd784f7SMasahiro Yamada if (host->mmc->caps & MMC_CAP_UHS) 6363fd784f7SMasahiro Yamada tmio_data->ocr_mask |= MMC_VDD_165_195; 6373fd784f7SMasahiro Yamada 6383fd784f7SMasahiro Yamada tmio_data->max_segs = 1; 6393fd784f7SMasahiro Yamada tmio_data->max_blk_count = U16_MAX; 6403fd784f7SMasahiro Yamada 6413fd784f7SMasahiro Yamada ret = tmio_mmc_host_probe(host); 6423fd784f7SMasahiro Yamada if (ret) 6433fd784f7SMasahiro Yamada goto free_host; 6443fd784f7SMasahiro Yamada 6453fd784f7SMasahiro Yamada return 0; 6463fd784f7SMasahiro Yamada 6473fd784f7SMasahiro Yamada free_host: 6483fd784f7SMasahiro Yamada tmio_mmc_host_free(host); 6493fd784f7SMasahiro Yamada 6503fd784f7SMasahiro Yamada return ret; 6513fd784f7SMasahiro Yamada } 6523fd784f7SMasahiro Yamada 6533fd784f7SMasahiro Yamada static int uniphier_sd_remove(struct platform_device *pdev) 6543fd784f7SMasahiro Yamada { 6553fd784f7SMasahiro Yamada struct tmio_mmc_host *host = platform_get_drvdata(pdev); 6563fd784f7SMasahiro Yamada 6573fd784f7SMasahiro Yamada tmio_mmc_host_remove(host); 6583fd784f7SMasahiro Yamada uniphier_sd_clk_disable(host); 6593fd784f7SMasahiro Yamada 6603fd784f7SMasahiro Yamada return 0; 6613fd784f7SMasahiro Yamada } 6623fd784f7SMasahiro Yamada 6633fd784f7SMasahiro Yamada static const struct of_device_id uniphier_sd_match[] = { 6643fd784f7SMasahiro Yamada { 6653fd784f7SMasahiro Yamada .compatible = "socionext,uniphier-sd-v2.91", 6663fd784f7SMasahiro Yamada }, 6673fd784f7SMasahiro Yamada { 6683fd784f7SMasahiro Yamada .compatible = "socionext,uniphier-sd-v3.1", 6693fd784f7SMasahiro Yamada .data = (void *)(UNIPHIER_SD_CAP_EXTENDED_IP | 6703fd784f7SMasahiro Yamada UNIPHIER_SD_CAP_BROKEN_DMA_RX), 6713fd784f7SMasahiro Yamada }, 6723fd784f7SMasahiro Yamada { 6733fd784f7SMasahiro Yamada .compatible = "socionext,uniphier-sd-v3.1.1", 6743fd784f7SMasahiro Yamada .data = (void *)UNIPHIER_SD_CAP_EXTENDED_IP, 6753fd784f7SMasahiro Yamada }, 6763fd784f7SMasahiro Yamada { /* sentinel */ } 6773fd784f7SMasahiro Yamada }; 6783fd784f7SMasahiro Yamada MODULE_DEVICE_TABLE(of, uniphier_sd_match); 6793fd784f7SMasahiro Yamada 6803fd784f7SMasahiro Yamada static struct platform_driver uniphier_sd_driver = { 6813fd784f7SMasahiro Yamada .probe = uniphier_sd_probe, 6823fd784f7SMasahiro Yamada .remove = uniphier_sd_remove, 6833fd784f7SMasahiro Yamada .driver = { 6843fd784f7SMasahiro Yamada .name = "uniphier-sd", 6853fd784f7SMasahiro Yamada .of_match_table = uniphier_sd_match, 6863fd784f7SMasahiro Yamada }, 6873fd784f7SMasahiro Yamada }; 6883fd784f7SMasahiro Yamada module_platform_driver(uniphier_sd_driver); 6893fd784f7SMasahiro Yamada 6903fd784f7SMasahiro Yamada MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro@socionext.com>"); 6913fd784f7SMasahiro Yamada MODULE_DESCRIPTION("UniPhier SD/eMMC host controller driver"); 6923fd784f7SMasahiro Yamada MODULE_LICENSE("GPL v2"); 693