.. | .. |
---|
| 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 | |
---|
.. | .. |
---|
1085 | 1044 | mmc->f_min = mmc->f_max / 128; |
---|
1086 | 1045 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; |
---|
1087 | 1046 | |
---|
| 1047 | + /* |
---|
| 1048 | + * We use a fixed timeout of 5s, hence inform the core about it. A |
---|
| 1049 | + * future improvement should instead respect the cmd->busy_timeout. |
---|
| 1050 | + */ |
---|
| 1051 | + mmc->max_busy_timeout = JZ_MMC_REQ_TIMEOUT_MS; |
---|
| 1052 | + |
---|
1088 | 1053 | mmc->max_blk_size = (1 << 10) - 1; |
---|
1089 | 1054 | mmc->max_blk_count = (1 << 15) - 1; |
---|
1090 | 1055 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; |
---|
.. | .. |
---|
1103 | 1068 | dev_name(&pdev->dev), host); |
---|
1104 | 1069 | if (ret) { |
---|
1105 | 1070 | dev_err(&pdev->dev, "Failed to request irq: %d\n", ret); |
---|
1106 | | - goto err_free_gpios; |
---|
| 1071 | + goto err_free_host; |
---|
1107 | 1072 | } |
---|
1108 | 1073 | |
---|
1109 | 1074 | jz4740_mmc_clock_disable(host); |
---|
.. | .. |
---|
1121 | 1086 | dev_err(&pdev->dev, "Failed to add mmc host: %d\n", ret); |
---|
1122 | 1087 | goto err_release_dma; |
---|
1123 | 1088 | } |
---|
1124 | | - dev_info(&pdev->dev, "JZ SD/MMC card driver registered\n"); |
---|
| 1089 | + dev_info(&pdev->dev, "Ingenic SD/MMC card driver registered\n"); |
---|
1125 | 1090 | |
---|
1126 | 1091 | dev_info(&pdev->dev, "Using %s, %d-bit mode\n", |
---|
1127 | 1092 | host->use_dma ? "DMA" : "PIO", |
---|
1128 | | - (mmc->caps & MMC_CAP_4_BIT_DATA) ? 4 : 1); |
---|
| 1093 | + (mmc->caps & MMC_CAP_8_BIT_DATA) ? 8 : |
---|
| 1094 | + ((mmc->caps & MMC_CAP_4_BIT_DATA) ? 4 : 1)); |
---|
1129 | 1095 | |
---|
1130 | 1096 | return 0; |
---|
1131 | 1097 | |
---|
.. | .. |
---|
1134 | 1100 | jz4740_mmc_release_dma_channels(host); |
---|
1135 | 1101 | err_free_irq: |
---|
1136 | 1102 | free_irq(host->irq, host); |
---|
1137 | | -err_free_gpios: |
---|
1138 | | - jz4740_mmc_free_gpios(pdev); |
---|
1139 | 1103 | err_free_host: |
---|
1140 | 1104 | mmc_free_host(mmc); |
---|
1141 | 1105 | |
---|
.. | .. |
---|
1154 | 1118 | |
---|
1155 | 1119 | free_irq(host->irq, host); |
---|
1156 | 1120 | |
---|
1157 | | - jz4740_mmc_free_gpios(pdev); |
---|
1158 | | - |
---|
1159 | 1121 | if (host->use_dma) |
---|
1160 | 1122 | jz4740_mmc_release_dma_channels(host); |
---|
1161 | 1123 | |
---|
.. | .. |
---|
1164 | 1126 | return 0; |
---|
1165 | 1127 | } |
---|
1166 | 1128 | |
---|
1167 | | -#ifdef CONFIG_PM_SLEEP |
---|
1168 | | - |
---|
1169 | | -static int jz4740_mmc_suspend(struct device *dev) |
---|
| 1129 | +static int __maybe_unused jz4740_mmc_suspend(struct device *dev) |
---|
1170 | 1130 | { |
---|
1171 | 1131 | return pinctrl_pm_select_sleep_state(dev); |
---|
1172 | 1132 | } |
---|
1173 | 1133 | |
---|
1174 | | -static int jz4740_mmc_resume(struct device *dev) |
---|
| 1134 | +static int __maybe_unused jz4740_mmc_resume(struct device *dev) |
---|
1175 | 1135 | { |
---|
1176 | | - return pinctrl_pm_select_default_state(dev); |
---|
| 1136 | + return pinctrl_select_default_state(dev); |
---|
1177 | 1137 | } |
---|
1178 | 1138 | |
---|
1179 | 1139 | static SIMPLE_DEV_PM_OPS(jz4740_mmc_pm_ops, jz4740_mmc_suspend, |
---|
1180 | 1140 | 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 | 1141 | |
---|
1186 | 1142 | static struct platform_driver jz4740_mmc_driver = { |
---|
1187 | 1143 | .probe = jz4740_mmc_probe, |
---|
.. | .. |
---|
1190 | 1146 | .name = "jz4740-mmc", |
---|
1191 | 1147 | .probe_type = PROBE_PREFER_ASYNCHRONOUS, |
---|
1192 | 1148 | .of_match_table = of_match_ptr(jz4740_mmc_of_match), |
---|
1193 | | - .pm = JZ4740_MMC_PM_OPS, |
---|
| 1149 | + .pm = pm_ptr(&jz4740_mmc_pm_ops), |
---|
1194 | 1150 | }, |
---|
1195 | 1151 | }; |
---|
1196 | 1152 | |
---|