aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host/wbsd.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-06-05 19:11:43 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-06-05 19:11:43 -0400
commitf60342fac9fae20ada2cd5faadbc2a1337cae03f (patch)
treefe64b1cb3ea699d819e5e808264903aee2d8dc9a /drivers/mmc/host/wbsd.c
parent5231804cf9e584f3e7e763a0d6d2fffe011c1bce (diff)
parentef5332c10d4f332a2ac79e9ad5452f4e89d1815a (diff)
Merge tag 'mmc-v4.18' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc
Pull MMC updates from Ulf Hansson: "MMC core: - Decrease polling rate for erase/trim/discard - Allow non-sleeping GPIOs for card detect - Improve mmc block removal path - Enable support for mmc_sw_reset() for SDIO cards - Add mmc_sw_reset() to allow users to do a soft reset of the card - Allow power delay to be tunable via DT - Allow card detect debounce delay to be tunable via DT - Enable new quirk to limit clock rate for Marvell 8887 chip - Don't show eMMC RPMB and BOOT areas in /proc/partitions - Add capability to avoid 3.3V signaling for fragile HWs MMC host: - Improve/fixup support for handle highmem pages - Remove depends on HAS_DMA in case of platform dependency - mvsdio: Enable support for erase/trim/discard - rtsx_usb: Enable support for erase/trim/discard - renesas_sdhi: Fix WP logic regressions - renesas_sdhi: Add r8a77965 support - renesas_sdhi: Add R8A77980 to whitelist - meson: Add optional support for device reset - meson: Add support for the Meson-AXG platform - dw_mmc: Add new driver for BlueField DW variant - mediatek: Add support for 64G DRAM DMA - sunxi: Deploy runtime PM support - jz4740: Add support for JZ4780 - jz4740: Enable support for DT based platforms - sdhci: Various improvement to timeout handling - sdhci: Disable support for HS200/HS400/UHS when no 1.8V support - sdhci-omap: Add support for controller in k2g SoC - sdhci-omap: Add workarounds for a couple of Erratas - sdhci-omap: Enable support for generic sdhci DT properties - sdhci-cadence: Re-send tune request to deal with errata - sdhci-pci: Fix 3.3V voltage switch for some BYT-based Intel controllers - sdhci-pci: Avoid 3.3V signaling on some NI 904x - sdhci-esdhc-imx: Use watermark levels for PIO access - sdhci-msm: Improve card detection handling - sdhci-msm: Add support voltage pad switching" * tag 'mmc-v4.18' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc: (104 commits) mmc: renesas_sdhi: really fix WP logic regressions mmc: mvsdio: Enable MMC_CAP_ERASE mmc: mvsdio: Respect card busy time out from mmc core mmc: sdhci-msm: Remove NO_CARD_NO_RESET quirk mmc: sunxi: Use ifdef rather than __maybe_unused mmc: mxmmc: Use ifdef rather than __maybe_unused mmc: mxmmc: include linux/highmem.h mmc: sunxi: mark PM functions as __maybe_unused mmc: Throttle calls to MMC_SEND_STATUS during mmc_do_erase() mmc: au1xmmc: handle highmem pages mmc: Allow non-sleeping GPIO cd mmc: sdhci-*: Don't emit error msg if sdhci_add_host() fails mmc: sd: Define name for default speed dtr mmc: core: Move calls to ->prepare_hs400_tuning() closer to mmc code mmc: sdhci-xenon: use match_string() helper mmc: wbsd: handle highmem pages mmc: ushc: handle highmem pages mmc: mxcmmc: handle highmem pages mmc: atmel-mci: use sg_copy_{from,to}_buffer mmc: android-goldfish: use sg_copy_{from,to}_buffer ...
Diffstat (limited to 'drivers/mmc/host/wbsd.c')
-rw-r--r--drivers/mmc/host/wbsd.c68
1 files changed, 30 insertions, 38 deletions
diff --git a/drivers/mmc/host/wbsd.c b/drivers/mmc/host/wbsd.c
index f4233576153b..1e54bbf13d75 100644
--- a/drivers/mmc/host/wbsd.c
+++ b/drivers/mmc/host/wbsd.c
@@ -268,43 +268,29 @@ static inline int wbsd_next_sg(struct wbsd_host *host)
268 return host->num_sg; 268 return host->num_sg;
269} 269}
270 270
271static inline char *wbsd_sg_to_buffer(struct wbsd_host *host) 271static inline char *wbsd_map_sg(struct wbsd_host *host)
272{ 272{
273 return sg_virt(host->cur_sg); 273 return kmap_atomic(sg_page(host->cur_sg)) + host->cur_sg->offset;
274} 274}
275 275
276static inline void wbsd_sg_to_dma(struct wbsd_host *host, struct mmc_data *data) 276static inline void wbsd_sg_to_dma(struct wbsd_host *host, struct mmc_data *data)
277{ 277{
278 unsigned int len, i; 278 size_t len = 0;
279 struct scatterlist *sg; 279 int i;
280 char *dmabuf = host->dma_buffer; 280
281 char *sgbuf; 281 for (i = 0; i < data->sg_len; i++)
282 282 len += data->sg[i].length;
283 sg = data->sg; 283 sg_copy_to_buffer(data->sg, data->sg_len, host->dma_buffer, len);
284 len = data->sg_len;
285
286 for (i = 0; i < len; i++) {
287 sgbuf = sg_virt(&sg[i]);
288 memcpy(dmabuf, sgbuf, sg[i].length);
289 dmabuf += sg[i].length;
290 }
291} 284}
292 285
293static inline void wbsd_dma_to_sg(struct wbsd_host *host, struct mmc_data *data) 286static inline void wbsd_dma_to_sg(struct wbsd_host *host, struct mmc_data *data)
294{ 287{
295 unsigned int len, i; 288 size_t len = 0;
296 struct scatterlist *sg; 289 int i;
297 char *dmabuf = host->dma_buffer; 290
298 char *sgbuf; 291 for (i = 0; i < data->sg_len; i++)
299 292 len += data->sg[i].length;
300 sg = data->sg; 293 sg_copy_from_buffer(data->sg, data->sg_len, host->dma_buffer, len);
301 len = data->sg_len;
302
303 for (i = 0; i < len; i++) {
304 sgbuf = sg_virt(&sg[i]);
305 memcpy(sgbuf, dmabuf, sg[i].length);
306 dmabuf += sg[i].length;
307 }
308} 294}
309 295
310/* 296/*
@@ -418,7 +404,7 @@ static void wbsd_empty_fifo(struct wbsd_host *host)
418{ 404{
419 struct mmc_data *data = host->mrq->cmd->data; 405 struct mmc_data *data = host->mrq->cmd->data;
420 char *buffer; 406 char *buffer;
421 int i, fsr, fifo; 407 int i, idx, fsr, fifo;
422 408
423 /* 409 /*
424 * Handle excessive data. 410 * Handle excessive data.
@@ -426,7 +412,8 @@ static void wbsd_empty_fifo(struct wbsd_host *host)
426 if (host->num_sg == 0) 412 if (host->num_sg == 0)
427 return; 413 return;
428 414
429 buffer = wbsd_sg_to_buffer(host) + host->offset; 415 buffer = wbsd_map_sg(host) + host->offset;
416 idx = 0;
430 417
431 /* 418 /*
432 * Drain the fifo. This has a tendency to loop longer 419 * Drain the fifo. This has a tendency to loop longer
@@ -445,8 +432,7 @@ static void wbsd_empty_fifo(struct wbsd_host *host)
445 fifo = 1; 432 fifo = 1;
446 433
447 for (i = 0; i < fifo; i++) { 434 for (i = 0; i < fifo; i++) {
448 *buffer = inb(host->base + WBSD_DFR); 435 buffer[idx++] = inb(host->base + WBSD_DFR);
449 buffer++;
450 host->offset++; 436 host->offset++;
451 host->remain--; 437 host->remain--;
452 438
@@ -456,16 +442,19 @@ static void wbsd_empty_fifo(struct wbsd_host *host)
456 * End of scatter list entry? 442 * End of scatter list entry?
457 */ 443 */
458 if (host->remain == 0) { 444 if (host->remain == 0) {
445 kunmap_atomic(buffer);
459 /* 446 /*
460 * Get next entry. Check if last. 447 * Get next entry. Check if last.
461 */ 448 */
462 if (!wbsd_next_sg(host)) 449 if (!wbsd_next_sg(host))
463 return; 450 return;
464 451
465 buffer = wbsd_sg_to_buffer(host); 452 buffer = wbsd_map_sg(host);
453 idx = 0;
466 } 454 }
467 } 455 }
468 } 456 }
457 kunmap_atomic(buffer);
469 458
470 /* 459 /*
471 * This is a very dirty hack to solve a 460 * This is a very dirty hack to solve a
@@ -480,7 +469,7 @@ static void wbsd_fill_fifo(struct wbsd_host *host)
480{ 469{
481 struct mmc_data *data = host->mrq->cmd->data; 470 struct mmc_data *data = host->mrq->cmd->data;
482 char *buffer; 471 char *buffer;
483 int i, fsr, fifo; 472 int i, idx, fsr, fifo;
484 473
485 /* 474 /*
486 * Check that we aren't being called after the 475 * Check that we aren't being called after the
@@ -489,7 +478,8 @@ static void wbsd_fill_fifo(struct wbsd_host *host)
489 if (host->num_sg == 0) 478 if (host->num_sg == 0)
490 return; 479 return;
491 480
492 buffer = wbsd_sg_to_buffer(host) + host->offset; 481 buffer = wbsd_map_sg(host) + host->offset;
482 idx = 0;
493 483
494 /* 484 /*
495 * Fill the fifo. This has a tendency to loop longer 485 * Fill the fifo. This has a tendency to loop longer
@@ -508,8 +498,7 @@ static void wbsd_fill_fifo(struct wbsd_host *host)
508 fifo = 15; 498 fifo = 15;
509 499
510 for (i = 16; i > fifo; i--) { 500 for (i = 16; i > fifo; i--) {
511 outb(*buffer, host->base + WBSD_DFR); 501 outb(buffer[idx], host->base + WBSD_DFR);
512 buffer++;
513 host->offset++; 502 host->offset++;
514 host->remain--; 503 host->remain--;
515 504
@@ -519,16 +508,19 @@ static void wbsd_fill_fifo(struct wbsd_host *host)
519 * End of scatter list entry? 508 * End of scatter list entry?
520 */ 509 */
521 if (host->remain == 0) { 510 if (host->remain == 0) {
511 kunmap_atomic(buffer);
522 /* 512 /*
523 * Get next entry. Check if last. 513 * Get next entry. Check if last.
524 */ 514 */
525 if (!wbsd_next_sg(host)) 515 if (!wbsd_next_sg(host))
526 return; 516 return;
527 517
528 buffer = wbsd_sg_to_buffer(host); 518 buffer = wbsd_map_sg(host);
519 idx = 0;
529 } 520 }
530 } 521 }
531 } 522 }
523 kunmap_atomic(buffer);
532 524
533 /* 525 /*
534 * The controller stops sending interrupts for 526 * The controller stops sending interrupts for