| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de> |
|---|
| 3 | 4 | * Copyright (C) 2013, Imagination Technologies |
|---|
| 4 | 5 | * |
|---|
| 5 | 6 | * JZ4740 SD/MMC controller driver |
|---|
| 6 | | - * |
|---|
| 7 | | - * This program is free software; you can redistribute it and/or modify it |
|---|
| 8 | | - * under the terms of the GNU General Public License as published by the |
|---|
| 9 | | - * Free Software Foundation; either version 2 of the License, or (at your |
|---|
| 10 | | - * option) any later version. |
|---|
| 11 | | - * |
|---|
| 12 | | - * You should have received a copy of the GNU General Public License along |
|---|
| 13 | | - * with this program; if not, write to the Free Software Foundation, Inc., |
|---|
| 14 | | - * 675 Mass Ave, Cambridge, MA 02139, USA. |
|---|
| 15 | | - * |
|---|
| 16 | 7 | */ |
|---|
| 17 | 8 | |
|---|
| 18 | 9 | #include <linux/bitops.h> |
|---|
| .. | .. |
|---|
| 21 | 12 | #include <linux/dmaengine.h> |
|---|
| 22 | 13 | #include <linux/dma-mapping.h> |
|---|
| 23 | 14 | #include <linux/err.h> |
|---|
| 24 | | -#include <linux/gpio.h> |
|---|
| 25 | 15 | #include <linux/interrupt.h> |
|---|
| 26 | 16 | #include <linux/io.h> |
|---|
| 27 | 17 | #include <linux/irq.h> |
|---|
| .. | .. |
|---|
| 34 | 24 | #include <linux/scatterlist.h> |
|---|
| 35 | 25 | |
|---|
| 36 | 26 | #include <asm/cacheflush.h> |
|---|
| 37 | | - |
|---|
| 38 | | -#include <asm/mach-jz4740/dma.h> |
|---|
| 39 | | -#include <asm/mach-jz4740/jz4740_mmc.h> |
|---|
| 40 | 27 | |
|---|
| 41 | 28 | #define JZ_REG_MMC_STRPCL 0x00 |
|---|
| 42 | 29 | #define JZ_REG_MMC_STATUS 0x04 |
|---|
| .. | .. |
|---|
| 54 | 41 | #define JZ_REG_MMC_RESP_FIFO 0x34 |
|---|
| 55 | 42 | #define JZ_REG_MMC_RXFIFO 0x38 |
|---|
| 56 | 43 | #define JZ_REG_MMC_TXFIFO 0x3C |
|---|
| 44 | +#define JZ_REG_MMC_LPM 0x40 |
|---|
| 57 | 45 | #define JZ_REG_MMC_DMAC 0x44 |
|---|
| 58 | 46 | |
|---|
| 59 | 47 | #define JZ_MMC_STRPCL_EXIT_MULTIPLE BIT(7) |
|---|
| .. | .. |
|---|
| 90 | 78 | |
|---|
| 91 | 79 | #define JZ_MMC_CMDAT_IO_ABORT BIT(11) |
|---|
| 92 | 80 | #define JZ_MMC_CMDAT_BUS_WIDTH_4BIT BIT(10) |
|---|
| 81 | +#define JZ_MMC_CMDAT_BUS_WIDTH_8BIT (BIT(10) | BIT(9)) |
|---|
| 82 | +#define JZ_MMC_CMDAT_BUS_WIDTH_MASK (BIT(10) | BIT(9)) |
|---|
| 93 | 83 | #define JZ_MMC_CMDAT_DMA_EN BIT(8) |
|---|
| 94 | 84 | #define JZ_MMC_CMDAT_INIT BIT(7) |
|---|
| 95 | 85 | #define JZ_MMC_CMDAT_BUSY BIT(6) |
|---|
| .. | .. |
|---|
| 111 | 101 | #define JZ_MMC_DMAC_DMA_SEL BIT(1) |
|---|
| 112 | 102 | #define JZ_MMC_DMAC_DMA_EN BIT(0) |
|---|
| 113 | 103 | |
|---|
| 104 | +#define JZ_MMC_LPM_DRV_RISING BIT(31) |
|---|
| 105 | +#define JZ_MMC_LPM_DRV_RISING_QTR_PHASE_DLY BIT(31) |
|---|
| 106 | +#define JZ_MMC_LPM_DRV_RISING_1NS_DLY BIT(30) |
|---|
| 107 | +#define JZ_MMC_LPM_SMP_RISING_QTR_OR_HALF_PHASE_DLY BIT(29) |
|---|
| 108 | +#define JZ_MMC_LPM_LOW_POWER_MODE_EN BIT(0) |
|---|
| 109 | + |
|---|
| 114 | 110 | #define JZ_MMC_CLK_RATE 24000000 |
|---|
| 111 | +#define JZ_MMC_REQ_TIMEOUT_MS 5000 |
|---|
| 115 | 112 | |
|---|
| 116 | 113 | enum jz4740_mmc_version { |
|---|
| 117 | 114 | JZ_MMC_JZ4740, |
|---|
| 118 | | - JZ_MMC_JZ4750, |
|---|
| 115 | + JZ_MMC_JZ4725B, |
|---|
| 116 | + JZ_MMC_JZ4760, |
|---|
| 119 | 117 | JZ_MMC_JZ4780, |
|---|
| 118 | + JZ_MMC_X1000, |
|---|
| 120 | 119 | }; |
|---|
| 121 | 120 | |
|---|
| 122 | 121 | enum jz4740_mmc_state { |
|---|
| .. | .. |
|---|
| 126 | 125 | JZ4740_MMC_STATE_DONE, |
|---|
| 127 | 126 | }; |
|---|
| 128 | 127 | |
|---|
| 129 | | -struct jz4740_mmc_host_next { |
|---|
| 130 | | - int sg_len; |
|---|
| 131 | | - s32 cookie; |
|---|
| 128 | +/* |
|---|
| 129 | + * The MMC core allows to prepare a mmc_request while another mmc_request |
|---|
| 130 | + * is in-flight. This is used via the pre_req/post_req hooks. |
|---|
| 131 | + * This driver uses the pre_req/post_req hooks to map/unmap the mmc_request. |
|---|
| 132 | + * Following what other drivers do (sdhci, dw_mmc) we use the following cookie |
|---|
| 133 | + * flags to keep track of the mmc_request mapping state. |
|---|
| 134 | + * |
|---|
| 135 | + * COOKIE_UNMAPPED: the request is not mapped. |
|---|
| 136 | + * COOKIE_PREMAPPED: the request was mapped in pre_req, |
|---|
| 137 | + * and should be unmapped in post_req. |
|---|
| 138 | + * COOKIE_MAPPED: the request was mapped in the irq handler, |
|---|
| 139 | + * and should be unmapped before mmc_request_done is called.. |
|---|
| 140 | + */ |
|---|
| 141 | +enum jz4780_cookie { |
|---|
| 142 | + COOKIE_UNMAPPED = 0, |
|---|
| 143 | + COOKIE_PREMAPPED, |
|---|
| 144 | + COOKIE_MAPPED, |
|---|
| 132 | 145 | }; |
|---|
| 133 | 146 | |
|---|
| 134 | 147 | struct jz4740_mmc_host { |
|---|
| 135 | 148 | struct mmc_host *mmc; |
|---|
| 136 | 149 | struct platform_device *pdev; |
|---|
| 137 | | - struct jz4740_mmc_platform_data *pdata; |
|---|
| 138 | 150 | struct clk *clk; |
|---|
| 139 | 151 | |
|---|
| 140 | 152 | enum jz4740_mmc_version version; |
|---|
| .. | .. |
|---|
| 162 | 174 | /* DMA support */ |
|---|
| 163 | 175 | struct dma_chan *dma_rx; |
|---|
| 164 | 176 | struct dma_chan *dma_tx; |
|---|
| 165 | | - struct jz4740_mmc_host_next next_data; |
|---|
| 166 | 177 | bool use_dma; |
|---|
| 167 | | - int sg_len; |
|---|
| 168 | 178 | |
|---|
| 169 | 179 | /* The DMA trigger level is 8 words, that is to say, the DMA read |
|---|
| 170 | 180 | * trigger is when data words in MSC_RXFIFO is >= 8 and the DMA write |
|---|
| .. | .. |
|---|
| 176 | 186 | static void jz4740_mmc_write_irq_mask(struct jz4740_mmc_host *host, |
|---|
| 177 | 187 | uint32_t val) |
|---|
| 178 | 188 | { |
|---|
| 179 | | - if (host->version >= JZ_MMC_JZ4750) |
|---|
| 189 | + if (host->version >= JZ_MMC_JZ4725B) |
|---|
| 180 | 190 | return writel(val, host->base + JZ_REG_MMC_IMASK); |
|---|
| 181 | 191 | else |
|---|
| 182 | 192 | return writew(val, host->base + JZ_REG_MMC_IMASK); |
|---|
| .. | .. |
|---|
| 186 | 196 | uint32_t val) |
|---|
| 187 | 197 | { |
|---|
| 188 | 198 | if (host->version >= JZ_MMC_JZ4780) |
|---|
| 189 | | - return writel(val, host->base + JZ_REG_MMC_IREG); |
|---|
| 199 | + writel(val, host->base + JZ_REG_MMC_IREG); |
|---|
| 190 | 200 | else |
|---|
| 191 | | - return writew(val, host->base + JZ_REG_MMC_IREG); |
|---|
| 201 | + writew(val, host->base + JZ_REG_MMC_IREG); |
|---|
| 192 | 202 | } |
|---|
| 193 | 203 | |
|---|
| 194 | 204 | static uint32_t jz4740_mmc_read_irq_reg(struct jz4740_mmc_host *host) |
|---|
| .. | .. |
|---|
| 226 | 236 | return PTR_ERR(host->dma_rx); |
|---|
| 227 | 237 | } |
|---|
| 228 | 238 | |
|---|
| 229 | | - /* Initialize DMA pre request cookie */ |
|---|
| 230 | | - host->next_data.cookie = 1; |
|---|
| 239 | + /* |
|---|
| 240 | + * Limit the maximum segment size in any SG entry according to |
|---|
| 241 | + * the parameters of the DMA engine device. |
|---|
| 242 | + */ |
|---|
| 243 | + if (host->dma_tx) { |
|---|
| 244 | + struct device *dev = host->dma_tx->device->dev; |
|---|
| 245 | + unsigned int max_seg_size = dma_get_max_seg_size(dev); |
|---|
| 246 | + |
|---|
| 247 | + if (max_seg_size < host->mmc->max_seg_size) |
|---|
| 248 | + host->mmc->max_seg_size = max_seg_size; |
|---|
| 249 | + } |
|---|
| 250 | + |
|---|
| 251 | + if (host->dma_rx) { |
|---|
| 252 | + struct device *dev = host->dma_rx->device->dev; |
|---|
| 253 | + unsigned int max_seg_size = dma_get_max_seg_size(dev); |
|---|
| 254 | + |
|---|
| 255 | + if (max_seg_size < host->mmc->max_seg_size) |
|---|
| 256 | + host->mmc->max_seg_size = max_seg_size; |
|---|
| 257 | + } |
|---|
| 231 | 258 | |
|---|
| 232 | 259 | return 0; |
|---|
| 233 | 260 | } |
|---|
| .. | .. |
|---|
| 245 | 272 | enum dma_data_direction dir = mmc_get_dma_dir(data); |
|---|
| 246 | 273 | |
|---|
| 247 | 274 | dma_unmap_sg(chan->device->dev, data->sg, data->sg_len, dir); |
|---|
| 275 | + data->host_cookie = COOKIE_UNMAPPED; |
|---|
| 248 | 276 | } |
|---|
| 249 | 277 | |
|---|
| 250 | | -/* Prepares DMA data for current/next transfer, returns non-zero on failure */ |
|---|
| 278 | +/* Prepares DMA data for current or next transfer. |
|---|
| 279 | + * A request can be in-flight when this is called. |
|---|
| 280 | + */ |
|---|
| 251 | 281 | static int jz4740_mmc_prepare_dma_data(struct jz4740_mmc_host *host, |
|---|
| 252 | 282 | struct mmc_data *data, |
|---|
| 253 | | - struct jz4740_mmc_host_next *next, |
|---|
| 254 | | - struct dma_chan *chan) |
|---|
| 283 | + int cookie) |
|---|
| 255 | 284 | { |
|---|
| 256 | | - struct jz4740_mmc_host_next *next_data = &host->next_data; |
|---|
| 285 | + struct dma_chan *chan = jz4740_mmc_get_dma_chan(host, data); |
|---|
| 257 | 286 | enum dma_data_direction dir = mmc_get_dma_dir(data); |
|---|
| 258 | | - int sg_len; |
|---|
| 287 | + int sg_count; |
|---|
| 259 | 288 | |
|---|
| 260 | | - if (!next && data->host_cookie && |
|---|
| 261 | | - data->host_cookie != host->next_data.cookie) { |
|---|
| 262 | | - dev_warn(mmc_dev(host->mmc), |
|---|
| 263 | | - "[%s] invalid cookie: data->host_cookie %d host->next_data.cookie %d\n", |
|---|
| 264 | | - __func__, |
|---|
| 265 | | - data->host_cookie, |
|---|
| 266 | | - host->next_data.cookie); |
|---|
| 267 | | - data->host_cookie = 0; |
|---|
| 268 | | - } |
|---|
| 289 | + if (data->host_cookie == COOKIE_PREMAPPED) |
|---|
| 290 | + return data->sg_count; |
|---|
| 269 | 291 | |
|---|
| 270 | | - /* Check if next job is already prepared */ |
|---|
| 271 | | - if (next || data->host_cookie != host->next_data.cookie) { |
|---|
| 272 | | - sg_len = dma_map_sg(chan->device->dev, |
|---|
| 273 | | - data->sg, |
|---|
| 274 | | - data->sg_len, |
|---|
| 275 | | - dir); |
|---|
| 292 | + sg_count = dma_map_sg(chan->device->dev, |
|---|
| 293 | + data->sg, |
|---|
| 294 | + data->sg_len, |
|---|
| 295 | + dir); |
|---|
| 276 | 296 | |
|---|
| 277 | | - } else { |
|---|
| 278 | | - sg_len = next_data->sg_len; |
|---|
| 279 | | - next_data->sg_len = 0; |
|---|
| 280 | | - } |
|---|
| 281 | | - |
|---|
| 282 | | - if (sg_len <= 0) { |
|---|
| 297 | + if (sg_count <= 0) { |
|---|
| 283 | 298 | dev_err(mmc_dev(host->mmc), |
|---|
| 284 | 299 | "Failed to map scatterlist for DMA operation\n"); |
|---|
| 285 | 300 | return -EINVAL; |
|---|
| 286 | 301 | } |
|---|
| 287 | 302 | |
|---|
| 288 | | - if (next) { |
|---|
| 289 | | - next->sg_len = sg_len; |
|---|
| 290 | | - data->host_cookie = ++next->cookie < 0 ? 1 : next->cookie; |
|---|
| 291 | | - } else |
|---|
| 292 | | - host->sg_len = sg_len; |
|---|
| 303 | + data->sg_count = sg_count; |
|---|
| 304 | + data->host_cookie = cookie; |
|---|
| 293 | 305 | |
|---|
| 294 | | - return 0; |
|---|
| 306 | + return data->sg_count; |
|---|
| 295 | 307 | } |
|---|
| 296 | 308 | |
|---|
| 297 | 309 | static int jz4740_mmc_start_dma_transfer(struct jz4740_mmc_host *host, |
|---|
| 298 | 310 | struct mmc_data *data) |
|---|
| 299 | 311 | { |
|---|
| 300 | | - int ret; |
|---|
| 301 | | - struct dma_chan *chan; |
|---|
| 312 | + struct dma_chan *chan = jz4740_mmc_get_dma_chan(host, data); |
|---|
| 302 | 313 | struct dma_async_tx_descriptor *desc; |
|---|
| 303 | 314 | struct dma_slave_config conf = { |
|---|
| 304 | 315 | .src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, |
|---|
| .. | .. |
|---|
| 306 | 317 | .src_maxburst = JZ4740_MMC_FIFO_HALF_SIZE, |
|---|
| 307 | 318 | .dst_maxburst = JZ4740_MMC_FIFO_HALF_SIZE, |
|---|
| 308 | 319 | }; |
|---|
| 320 | + int sg_count; |
|---|
| 309 | 321 | |
|---|
| 310 | 322 | if (data->flags & MMC_DATA_WRITE) { |
|---|
| 311 | 323 | conf.direction = DMA_MEM_TO_DEV; |
|---|
| 312 | 324 | conf.dst_addr = host->mem_res->start + JZ_REG_MMC_TXFIFO; |
|---|
| 313 | | - conf.slave_id = JZ4740_DMA_TYPE_MMC_TRANSMIT; |
|---|
| 314 | | - chan = host->dma_tx; |
|---|
| 315 | 325 | } else { |
|---|
| 316 | 326 | conf.direction = DMA_DEV_TO_MEM; |
|---|
| 317 | 327 | conf.src_addr = host->mem_res->start + JZ_REG_MMC_RXFIFO; |
|---|
| 318 | | - conf.slave_id = JZ4740_DMA_TYPE_MMC_RECEIVE; |
|---|
| 319 | | - chan = host->dma_rx; |
|---|
| 320 | 328 | } |
|---|
| 321 | 329 | |
|---|
| 322 | | - ret = jz4740_mmc_prepare_dma_data(host, data, NULL, chan); |
|---|
| 323 | | - if (ret) |
|---|
| 324 | | - return ret; |
|---|
| 330 | + sg_count = jz4740_mmc_prepare_dma_data(host, data, COOKIE_MAPPED); |
|---|
| 331 | + if (sg_count < 0) |
|---|
| 332 | + return sg_count; |
|---|
| 325 | 333 | |
|---|
| 326 | 334 | dmaengine_slave_config(chan, &conf); |
|---|
| 327 | | - desc = dmaengine_prep_slave_sg(chan, |
|---|
| 328 | | - data->sg, |
|---|
| 329 | | - host->sg_len, |
|---|
| 330 | | - conf.direction, |
|---|
| 331 | | - DMA_PREP_INTERRUPT | DMA_CTRL_ACK); |
|---|
| 335 | + desc = dmaengine_prep_slave_sg(chan, data->sg, sg_count, |
|---|
| 336 | + conf.direction, |
|---|
| 337 | + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); |
|---|
| 332 | 338 | if (!desc) { |
|---|
| 333 | 339 | dev_err(mmc_dev(host->mmc), |
|---|
| 334 | 340 | "Failed to allocate DMA %s descriptor", |
|---|
| .. | .. |
|---|
| 342 | 348 | return 0; |
|---|
| 343 | 349 | |
|---|
| 344 | 350 | dma_unmap: |
|---|
| 345 | | - jz4740_mmc_dma_unmap(host, data); |
|---|
| 351 | + if (data->host_cookie == COOKIE_MAPPED) |
|---|
| 352 | + jz4740_mmc_dma_unmap(host, data); |
|---|
| 346 | 353 | return -ENOMEM; |
|---|
| 347 | 354 | } |
|---|
| 348 | 355 | |
|---|
| .. | .. |
|---|
| 351 | 358 | { |
|---|
| 352 | 359 | struct jz4740_mmc_host *host = mmc_priv(mmc); |
|---|
| 353 | 360 | struct mmc_data *data = mrq->data; |
|---|
| 354 | | - struct jz4740_mmc_host_next *next_data = &host->next_data; |
|---|
| 355 | 361 | |
|---|
| 356 | | - BUG_ON(data->host_cookie); |
|---|
| 362 | + if (!host->use_dma) |
|---|
| 363 | + return; |
|---|
| 357 | 364 | |
|---|
| 358 | | - if (host->use_dma) { |
|---|
| 359 | | - struct dma_chan *chan = jz4740_mmc_get_dma_chan(host, data); |
|---|
| 360 | | - |
|---|
| 361 | | - if (jz4740_mmc_prepare_dma_data(host, data, next_data, chan)) |
|---|
| 362 | | - data->host_cookie = 0; |
|---|
| 363 | | - } |
|---|
| 365 | + data->host_cookie = COOKIE_UNMAPPED; |
|---|
| 366 | + if (jz4740_mmc_prepare_dma_data(host, data, COOKIE_PREMAPPED) < 0) |
|---|
| 367 | + data->host_cookie = COOKIE_UNMAPPED; |
|---|
| 364 | 368 | } |
|---|
| 365 | 369 | |
|---|
| 366 | 370 | static void jz4740_mmc_post_request(struct mmc_host *mmc, |
|---|
| .. | .. |
|---|
| 370 | 374 | struct jz4740_mmc_host *host = mmc_priv(mmc); |
|---|
| 371 | 375 | struct mmc_data *data = mrq->data; |
|---|
| 372 | 376 | |
|---|
| 373 | | - if (host->use_dma && data->host_cookie) { |
|---|
| 377 | + if (data && data->host_cookie != COOKIE_UNMAPPED) |
|---|
| 374 | 378 | jz4740_mmc_dma_unmap(host, data); |
|---|
| 375 | | - data->host_cookie = 0; |
|---|
| 376 | | - } |
|---|
| 377 | 379 | |
|---|
| 378 | 380 | if (err) { |
|---|
| 379 | 381 | struct dma_chan *chan = jz4740_mmc_get_dma_chan(host, data); |
|---|
| .. | .. |
|---|
| 436 | 438 | static void jz4740_mmc_request_done(struct jz4740_mmc_host *host) |
|---|
| 437 | 439 | { |
|---|
| 438 | 440 | struct mmc_request *req; |
|---|
| 441 | + struct mmc_data *data; |
|---|
| 439 | 442 | |
|---|
| 440 | 443 | req = host->req; |
|---|
| 444 | + data = req->data; |
|---|
| 441 | 445 | host->req = NULL; |
|---|
| 442 | 446 | |
|---|
| 447 | + if (data && data->host_cookie == COOKIE_MAPPED) |
|---|
| 448 | + jz4740_mmc_dma_unmap(host, data); |
|---|
| 443 | 449 | mmc_request_done(host->mmc, req); |
|---|
| 444 | 450 | } |
|---|
| 445 | 451 | |
|---|
| .. | .. |
|---|
| 455 | 461 | |
|---|
| 456 | 462 | if (timeout == 0) { |
|---|
| 457 | 463 | set_bit(0, &host->waiting); |
|---|
| 458 | | - mod_timer(&host->timeout_timer, jiffies + 5*HZ); |
|---|
| 464 | + mod_timer(&host->timeout_timer, |
|---|
| 465 | + jiffies + msecs_to_jiffies(JZ_MMC_REQ_TIMEOUT_MS)); |
|---|
| 459 | 466 | jz4740_mmc_set_irq_enabled(host, irq, true); |
|---|
| 460 | 467 | return true; |
|---|
| 461 | 468 | } |
|---|
| .. | .. |
|---|
| 752 | 759 | break; |
|---|
| 753 | 760 | |
|---|
| 754 | 761 | jz_mmc_prepare_data_transfer(host); |
|---|
| 762 | + fallthrough; |
|---|
| 755 | 763 | |
|---|
| 756 | 764 | case JZ4740_MMC_STATE_TRANSFER_DATA: |
|---|
| 757 | 765 | if (host->use_dma) { |
|---|
| .. | .. |
|---|
| 786 | 794 | break; |
|---|
| 787 | 795 | } |
|---|
| 788 | 796 | jz4740_mmc_write_irq_reg(host, JZ_MMC_IRQ_DATA_TRAN_DONE); |
|---|
| 797 | + fallthrough; |
|---|
| 789 | 798 | |
|---|
| 790 | 799 | case JZ4740_MMC_STATE_SEND_STOP: |
|---|
| 791 | 800 | if (!req->stop) |
|---|
| .. | .. |
|---|
| 840 | 849 | del_timer(&host->timeout_timer); |
|---|
| 841 | 850 | |
|---|
| 842 | 851 | if (status & JZ_MMC_STATUS_TIMEOUT_RES) { |
|---|
| 843 | | - cmd->error = -ETIMEDOUT; |
|---|
| 852 | + cmd->error = -ETIMEDOUT; |
|---|
| 844 | 853 | } else if (status & JZ_MMC_STATUS_CRC_RES_ERR) { |
|---|
| 845 | | - cmd->error = -EIO; |
|---|
| 854 | + cmd->error = -EIO; |
|---|
| 846 | 855 | } else if (status & (JZ_MMC_STATUS_CRC_READ_ERROR | |
|---|
| 847 | 856 | JZ_MMC_STATUS_CRC_WRITE_ERROR)) { |
|---|
| 848 | | - if (cmd->data) |
|---|
| 849 | | - cmd->data->error = -EIO; |
|---|
| 850 | | - cmd->error = -EIO; |
|---|
| 857 | + if (cmd->data) |
|---|
| 858 | + cmd->data->error = -EIO; |
|---|
| 859 | + cmd->error = -EIO; |
|---|
| 851 | 860 | } |
|---|
| 852 | 861 | |
|---|
| 853 | 862 | jz4740_mmc_set_irq_enabled(host, irq_reg, false); |
|---|
| .. | .. |
|---|
| 876 | 885 | } |
|---|
| 877 | 886 | |
|---|
| 878 | 887 | writew(div, host->base + JZ_REG_MMC_CLKRT); |
|---|
| 888 | + |
|---|
| 889 | + if (real_rate > 25000000) { |
|---|
| 890 | + if (host->version >= JZ_MMC_X1000) { |
|---|
| 891 | + writel(JZ_MMC_LPM_DRV_RISING_QTR_PHASE_DLY | |
|---|
| 892 | + JZ_MMC_LPM_SMP_RISING_QTR_OR_HALF_PHASE_DLY | |
|---|
| 893 | + JZ_MMC_LPM_LOW_POWER_MODE_EN, |
|---|
| 894 | + host->base + JZ_REG_MMC_LPM); |
|---|
| 895 | + } else if (host->version >= JZ_MMC_JZ4760) { |
|---|
| 896 | + writel(JZ_MMC_LPM_DRV_RISING | |
|---|
| 897 | + JZ_MMC_LPM_LOW_POWER_MODE_EN, |
|---|
| 898 | + host->base + JZ_REG_MMC_LPM); |
|---|
| 899 | + } else if (host->version >= JZ_MMC_JZ4725B) |
|---|
| 900 | + writel(JZ_MMC_LPM_LOW_POWER_MODE_EN, |
|---|
| 901 | + host->base + JZ_REG_MMC_LPM); |
|---|
| 902 | + } |
|---|
| 903 | + |
|---|
| 879 | 904 | return real_rate; |
|---|
| 880 | 905 | } |
|---|
| 881 | 906 | |
|---|
| .. | .. |
|---|
| 890 | 915 | |
|---|
| 891 | 916 | host->state = JZ4740_MMC_STATE_READ_RESPONSE; |
|---|
| 892 | 917 | set_bit(0, &host->waiting); |
|---|
| 893 | | - mod_timer(&host->timeout_timer, jiffies + 5*HZ); |
|---|
| 918 | + mod_timer(&host->timeout_timer, |
|---|
| 919 | + jiffies + msecs_to_jiffies(JZ_MMC_REQ_TIMEOUT_MS)); |
|---|
| 894 | 920 | jz4740_mmc_send_command(host, req->cmd); |
|---|
| 895 | 921 | } |
|---|
| 896 | 922 | |
|---|
| .. | .. |
|---|
| 903 | 929 | switch (ios->power_mode) { |
|---|
| 904 | 930 | case MMC_POWER_UP: |
|---|
| 905 | 931 | jz4740_mmc_reset(host); |
|---|
| 906 | | - if (host->pdata && gpio_is_valid(host->pdata->gpio_power)) |
|---|
| 907 | | - gpio_set_value(host->pdata->gpio_power, |
|---|
| 908 | | - !host->pdata->power_active_low); |
|---|
| 932 | + if (!IS_ERR(mmc->supply.vmmc)) |
|---|
| 933 | + mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd); |
|---|
| 909 | 934 | host->cmdat |= JZ_MMC_CMDAT_INIT; |
|---|
| 910 | 935 | clk_prepare_enable(host->clk); |
|---|
| 911 | 936 | break; |
|---|
| 912 | 937 | case MMC_POWER_ON: |
|---|
| 913 | 938 | break; |
|---|
| 914 | 939 | default: |
|---|
| 915 | | - if (host->pdata && gpio_is_valid(host->pdata->gpio_power)) |
|---|
| 916 | | - gpio_set_value(host->pdata->gpio_power, |
|---|
| 917 | | - host->pdata->power_active_low); |
|---|
| 940 | + if (!IS_ERR(mmc->supply.vmmc)) |
|---|
| 941 | + mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); |
|---|
| 918 | 942 | clk_disable_unprepare(host->clk); |
|---|
| 919 | 943 | break; |
|---|
| 920 | 944 | } |
|---|
| 921 | 945 | |
|---|
| 922 | 946 | switch (ios->bus_width) { |
|---|
| 923 | 947 | case MMC_BUS_WIDTH_1: |
|---|
| 924 | | - host->cmdat &= ~JZ_MMC_CMDAT_BUS_WIDTH_4BIT; |
|---|
| 948 | + host->cmdat &= ~JZ_MMC_CMDAT_BUS_WIDTH_MASK; |
|---|
| 925 | 949 | break; |
|---|
| 926 | 950 | case MMC_BUS_WIDTH_4: |
|---|
| 951 | + host->cmdat &= ~JZ_MMC_CMDAT_BUS_WIDTH_MASK; |
|---|
| 927 | 952 | host->cmdat |= JZ_MMC_CMDAT_BUS_WIDTH_4BIT; |
|---|
| 953 | + break; |
|---|
| 954 | + case MMC_BUS_WIDTH_8: |
|---|
| 955 | + host->cmdat &= ~JZ_MMC_CMDAT_BUS_WIDTH_MASK; |
|---|
| 956 | + host->cmdat |= JZ_MMC_CMDAT_BUS_WIDTH_8BIT; |
|---|
| 928 | 957 | break; |
|---|
| 929 | 958 | default: |
|---|
| 930 | 959 | break; |
|---|
| .. | .. |
|---|
| 947 | 976 | .enable_sdio_irq = jz4740_mmc_enable_sdio_irq, |
|---|
| 948 | 977 | }; |
|---|
| 949 | 978 | |
|---|
| 950 | | -static int jz4740_mmc_request_gpio(struct device *dev, int gpio, |
|---|
| 951 | | - const char *name, bool output, int value) |
|---|
| 952 | | -{ |
|---|
| 953 | | - int ret; |
|---|
| 954 | | - |
|---|
| 955 | | - if (!gpio_is_valid(gpio)) |
|---|
| 956 | | - return 0; |
|---|
| 957 | | - |
|---|
| 958 | | - ret = gpio_request(gpio, name); |
|---|
| 959 | | - if (ret) { |
|---|
| 960 | | - dev_err(dev, "Failed to request %s gpio: %d\n", name, ret); |
|---|
| 961 | | - return ret; |
|---|
| 962 | | - } |
|---|
| 963 | | - |
|---|
| 964 | | - if (output) |
|---|
| 965 | | - gpio_direction_output(gpio, value); |
|---|
| 966 | | - else |
|---|
| 967 | | - gpio_direction_input(gpio); |
|---|
| 968 | | - |
|---|
| 969 | | - return 0; |
|---|
| 970 | | -} |
|---|
| 971 | | - |
|---|
| 972 | | -static int jz4740_mmc_request_gpios(struct mmc_host *mmc, |
|---|
| 973 | | - struct platform_device *pdev) |
|---|
| 974 | | -{ |
|---|
| 975 | | - struct jz4740_mmc_platform_data *pdata = dev_get_platdata(&pdev->dev); |
|---|
| 976 | | - int ret = 0; |
|---|
| 977 | | - |
|---|
| 978 | | - if (!pdata) |
|---|
| 979 | | - return 0; |
|---|
| 980 | | - |
|---|
| 981 | | - if (!pdata->card_detect_active_low) |
|---|
| 982 | | - mmc->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH; |
|---|
| 983 | | - if (!pdata->read_only_active_low) |
|---|
| 984 | | - mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; |
|---|
| 985 | | - |
|---|
| 986 | | - /* |
|---|
| 987 | | - * Get optional card detect and write protect GPIOs, |
|---|
| 988 | | - * only back out on probe deferral. |
|---|
| 989 | | - */ |
|---|
| 990 | | - ret = mmc_gpiod_request_cd(mmc, "cd", 0, false, 0, NULL); |
|---|
| 991 | | - if (ret == -EPROBE_DEFER) |
|---|
| 992 | | - return ret; |
|---|
| 993 | | - |
|---|
| 994 | | - ret = mmc_gpiod_request_ro(mmc, "wp", 0, false, 0, NULL); |
|---|
| 995 | | - if (ret == -EPROBE_DEFER) |
|---|
| 996 | | - return ret; |
|---|
| 997 | | - |
|---|
| 998 | | - return jz4740_mmc_request_gpio(&pdev->dev, pdata->gpio_power, |
|---|
| 999 | | - "MMC read only", true, pdata->power_active_low); |
|---|
| 1000 | | -} |
|---|
| 1001 | | - |
|---|
| 1002 | | -static void jz4740_mmc_free_gpios(struct platform_device *pdev) |
|---|
| 1003 | | -{ |
|---|
| 1004 | | - struct jz4740_mmc_platform_data *pdata = dev_get_platdata(&pdev->dev); |
|---|
| 1005 | | - |
|---|
| 1006 | | - if (!pdata) |
|---|
| 1007 | | - return; |
|---|
| 1008 | | - |
|---|
| 1009 | | - if (gpio_is_valid(pdata->gpio_power)) |
|---|
| 1010 | | - gpio_free(pdata->gpio_power); |
|---|
| 1011 | | -} |
|---|
| 1012 | | - |
|---|
| 1013 | 979 | static const struct of_device_id jz4740_mmc_of_match[] = { |
|---|
| 1014 | 980 | { .compatible = "ingenic,jz4740-mmc", .data = (void *) JZ_MMC_JZ4740 }, |
|---|
| 981 | + { .compatible = "ingenic,jz4725b-mmc", .data = (void *)JZ_MMC_JZ4725B }, |
|---|
| 982 | + { .compatible = "ingenic,jz4760-mmc", .data = (void *) JZ_MMC_JZ4760 }, |
|---|
| 1015 | 983 | { .compatible = "ingenic,jz4780-mmc", .data = (void *) JZ_MMC_JZ4780 }, |
|---|
| 984 | + { .compatible = "ingenic,x1000-mmc", .data = (void *) JZ_MMC_X1000 }, |
|---|
| 1016 | 985 | {}, |
|---|
| 1017 | 986 | }; |
|---|
| 1018 | 987 | MODULE_DEVICE_TABLE(of, jz4740_mmc_of_match); |
|---|
| .. | .. |
|---|
| 1023 | 992 | struct mmc_host *mmc; |
|---|
| 1024 | 993 | struct jz4740_mmc_host *host; |
|---|
| 1025 | 994 | const struct of_device_id *match; |
|---|
| 1026 | | - struct jz4740_mmc_platform_data *pdata; |
|---|
| 1027 | | - |
|---|
| 1028 | | - pdata = dev_get_platdata(&pdev->dev); |
|---|
| 1029 | 995 | |
|---|
| 1030 | 996 | mmc = mmc_alloc_host(sizeof(struct jz4740_mmc_host), &pdev->dev); |
|---|
| 1031 | 997 | if (!mmc) { |
|---|
| .. | .. |
|---|
| 1034 | 1000 | } |
|---|
| 1035 | 1001 | |
|---|
| 1036 | 1002 | host = mmc_priv(mmc); |
|---|
| 1037 | | - host->pdata = pdata; |
|---|
| 1038 | 1003 | |
|---|
| 1039 | 1004 | match = of_match_device(jz4740_mmc_of_match, &pdev->dev); |
|---|
| 1040 | 1005 | if (match) { |
|---|
| 1041 | 1006 | host->version = (enum jz4740_mmc_version)match->data; |
|---|
| 1042 | | - ret = mmc_of_parse(mmc); |
|---|
| 1043 | | - if (ret) { |
|---|
| 1044 | | - if (ret != -EPROBE_DEFER) |
|---|
| 1045 | | - dev_err(&pdev->dev, |
|---|
| 1046 | | - "could not parse of data: %d\n", ret); |
|---|
| 1047 | | - goto err_free_host; |
|---|
| 1048 | | - } |
|---|
| 1049 | 1007 | } else { |
|---|
| 1050 | 1008 | /* JZ4740 should be the only one using legacy probe */ |
|---|
| 1051 | 1009 | host->version = JZ_MMC_JZ4740; |
|---|
| 1052 | | - mmc->caps |= MMC_CAP_SDIO_IRQ; |
|---|
| 1053 | | - if (!(pdata && pdata->data_1bit)) |
|---|
| 1054 | | - mmc->caps |= MMC_CAP_4_BIT_DATA; |
|---|
| 1055 | | - ret = jz4740_mmc_request_gpios(mmc, pdev); |
|---|
| 1056 | | - if (ret) |
|---|
| 1057 | | - goto err_free_host; |
|---|
| 1058 | 1010 | } |
|---|
| 1011 | + |
|---|
| 1012 | + ret = mmc_of_parse(mmc); |
|---|
| 1013 | + if (ret) { |
|---|
| 1014 | + dev_err_probe(&pdev->dev, ret, "could not parse device properties\n"); |
|---|
| 1015 | + goto err_free_host; |
|---|
| 1016 | + } |
|---|
| 1017 | + |
|---|
| 1018 | + mmc_regulator_get_supply(mmc); |
|---|
| 1059 | 1019 | |
|---|
| 1060 | 1020 | host->irq = platform_get_irq(pdev, 0); |
|---|
| 1061 | 1021 | if (host->irq < 0) { |
|---|
| 1062 | 1022 | ret = host->irq; |
|---|
| 1063 | | - dev_err(&pdev->dev, "Failed to get platform irq: %d\n", ret); |
|---|
| 1064 | 1023 | goto err_free_host; |
|---|
| 1065 | 1024 | } |
|---|
| 1066 | 1025 | |
|---|
| .. | .. |
|---|
| 1082 | 1041 | mmc->ops = &jz4740_mmc_ops; |
|---|
| 1083 | 1042 | if (!mmc->f_max) |
|---|
| 1084 | 1043 | mmc->f_max = JZ_MMC_CLK_RATE; |
|---|
| 1044 | + |
|---|
| 1045 | + /* |
|---|
| 1046 | + * There seems to be a problem with this driver on the JZ4760 and |
|---|
| 1047 | + * JZ4760B SoCs. There, when using the maximum rate supported (50 MHz), |
|---|
| 1048 | + * the communication fails with many SD cards. |
|---|
| 1049 | + * Until this bug is sorted out, limit the maximum rate to 24 MHz. |
|---|
| 1050 | + */ |
|---|
| 1051 | + if (host->version == JZ_MMC_JZ4760 && mmc->f_max > JZ_MMC_CLK_RATE) |
|---|
| 1052 | + mmc->f_max = JZ_MMC_CLK_RATE; |
|---|
| 1053 | + |
|---|
| 1085 | 1054 | mmc->f_min = mmc->f_max / 128; |
|---|
| 1086 | 1055 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; |
|---|
| 1056 | + |
|---|
| 1057 | + /* |
|---|
| 1058 | + * We use a fixed timeout of 5s, hence inform the core about it. A |
|---|
| 1059 | + * future improvement should instead respect the cmd->busy_timeout. |
|---|
| 1060 | + */ |
|---|
| 1061 | + mmc->max_busy_timeout = JZ_MMC_REQ_TIMEOUT_MS; |
|---|
| 1087 | 1062 | |
|---|
| 1088 | 1063 | mmc->max_blk_size = (1 << 10) - 1; |
|---|
| 1089 | 1064 | mmc->max_blk_count = (1 << 15) - 1; |
|---|
| .. | .. |
|---|
| 1103 | 1078 | dev_name(&pdev->dev), host); |
|---|
| 1104 | 1079 | if (ret) { |
|---|
| 1105 | 1080 | dev_err(&pdev->dev, "Failed to request irq: %d\n", ret); |
|---|
| 1106 | | - goto err_free_gpios; |
|---|
| 1081 | + goto err_free_host; |
|---|
| 1107 | 1082 | } |
|---|
| 1108 | 1083 | |
|---|
| 1109 | 1084 | jz4740_mmc_clock_disable(host); |
|---|
| .. | .. |
|---|
| 1121 | 1096 | dev_err(&pdev->dev, "Failed to add mmc host: %d\n", ret); |
|---|
| 1122 | 1097 | goto err_release_dma; |
|---|
| 1123 | 1098 | } |
|---|
| 1124 | | - dev_info(&pdev->dev, "JZ SD/MMC card driver registered\n"); |
|---|
| 1099 | + dev_info(&pdev->dev, "Ingenic SD/MMC card driver registered\n"); |
|---|
| 1125 | 1100 | |
|---|
| 1126 | 1101 | dev_info(&pdev->dev, "Using %s, %d-bit mode\n", |
|---|
| 1127 | 1102 | host->use_dma ? "DMA" : "PIO", |
|---|
| 1128 | | - (mmc->caps & MMC_CAP_4_BIT_DATA) ? 4 : 1); |
|---|
| 1103 | + (mmc->caps & MMC_CAP_8_BIT_DATA) ? 8 : |
|---|
| 1104 | + ((mmc->caps & MMC_CAP_4_BIT_DATA) ? 4 : 1)); |
|---|
| 1129 | 1105 | |
|---|
| 1130 | 1106 | return 0; |
|---|
| 1131 | 1107 | |
|---|
| .. | .. |
|---|
| 1134 | 1110 | jz4740_mmc_release_dma_channels(host); |
|---|
| 1135 | 1111 | err_free_irq: |
|---|
| 1136 | 1112 | free_irq(host->irq, host); |
|---|
| 1137 | | -err_free_gpios: |
|---|
| 1138 | | - jz4740_mmc_free_gpios(pdev); |
|---|
| 1139 | 1113 | err_free_host: |
|---|
| 1140 | 1114 | mmc_free_host(mmc); |
|---|
| 1141 | 1115 | |
|---|
| .. | .. |
|---|
| 1154 | 1128 | |
|---|
| 1155 | 1129 | free_irq(host->irq, host); |
|---|
| 1156 | 1130 | |
|---|
| 1157 | | - jz4740_mmc_free_gpios(pdev); |
|---|
| 1158 | | - |
|---|
| 1159 | 1131 | if (host->use_dma) |
|---|
| 1160 | 1132 | jz4740_mmc_release_dma_channels(host); |
|---|
| 1161 | 1133 | |
|---|
| .. | .. |
|---|
| 1164 | 1136 | return 0; |
|---|
| 1165 | 1137 | } |
|---|
| 1166 | 1138 | |
|---|
| 1167 | | -#ifdef CONFIG_PM_SLEEP |
|---|
| 1168 | | - |
|---|
| 1169 | | -static int jz4740_mmc_suspend(struct device *dev) |
|---|
| 1139 | +static int __maybe_unused jz4740_mmc_suspend(struct device *dev) |
|---|
| 1170 | 1140 | { |
|---|
| 1171 | 1141 | return pinctrl_pm_select_sleep_state(dev); |
|---|
| 1172 | 1142 | } |
|---|
| 1173 | 1143 | |
|---|
| 1174 | | -static int jz4740_mmc_resume(struct device *dev) |
|---|
| 1144 | +static int __maybe_unused jz4740_mmc_resume(struct device *dev) |
|---|
| 1175 | 1145 | { |
|---|
| 1176 | | - return pinctrl_pm_select_default_state(dev); |
|---|
| 1146 | + return pinctrl_select_default_state(dev); |
|---|
| 1177 | 1147 | } |
|---|
| 1178 | 1148 | |
|---|
| 1179 | 1149 | static SIMPLE_DEV_PM_OPS(jz4740_mmc_pm_ops, jz4740_mmc_suspend, |
|---|
| 1180 | 1150 | jz4740_mmc_resume); |
|---|
| 1181 | | -#define JZ4740_MMC_PM_OPS (&jz4740_mmc_pm_ops) |
|---|
| 1182 | | -#else |
|---|
| 1183 | | -#define JZ4740_MMC_PM_OPS NULL |
|---|
| 1184 | | -#endif |
|---|
| 1185 | 1151 | |
|---|
| 1186 | 1152 | static struct platform_driver jz4740_mmc_driver = { |
|---|
| 1187 | 1153 | .probe = jz4740_mmc_probe, |
|---|
| .. | .. |
|---|
| 1190 | 1156 | .name = "jz4740-mmc", |
|---|
| 1191 | 1157 | .probe_type = PROBE_PREFER_ASYNCHRONOUS, |
|---|
| 1192 | 1158 | .of_match_table = of_match_ptr(jz4740_mmc_of_match), |
|---|
| 1193 | | - .pm = JZ4740_MMC_PM_OPS, |
|---|
| 1159 | + .pm = pm_ptr(&jz4740_mmc_pm_ops), |
|---|
| 1194 | 1160 | }, |
|---|
| 1195 | 1161 | }; |
|---|
| 1196 | 1162 | |
|---|