diff options
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/card/Kconfig | 10 | ||||
-rw-r--r-- | drivers/mmc/card/block.c | 3 | ||||
-rw-r--r-- | drivers/mmc/card/mmc_test.c | 2 | ||||
-rw-r--r-- | drivers/mmc/core/core.c | 107 | ||||
-rw-r--r-- | drivers/mmc/core/mmc.c | 19 | ||||
-rw-r--r-- | drivers/mmc/core/mmc_ops.c | 65 | ||||
-rw-r--r-- | drivers/mmc/core/mmc_ops.h | 1 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-tegra.c | 68 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci.c | 20 | ||||
-rw-r--r-- | drivers/mmc/host/sh_mmcif.c | 5 | ||||
-rw-r--r-- | drivers/mmc/host/tmio_mmc_dma.c | 5 |
11 files changed, 266 insertions, 39 deletions
diff --git a/drivers/mmc/card/Kconfig b/drivers/mmc/card/Kconfig index ebb4afe6c702..3875c21e04fa 100644 --- a/drivers/mmc/card/Kconfig +++ b/drivers/mmc/card/Kconfig @@ -76,3 +76,13 @@ config MMC_TEST This driver is only of interest to those developing or testing a host driver. Most people should say N here. + +config MMC_BKOPS + bool "Enable background ops" + default n + help + Say Y here to enable background ops in driver. This will result + in issuing of MMC_SWITCH command to write byte 164 of EXT_CSD, + in order to trigger background ops in the MMC device's + firmware, whenever URGENT_BKOPS flag is found to be set in a + read/write command's response. diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 2bd93d7a5170..bd5427d1f9e3 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -59,8 +59,6 @@ MODULE_ALIAS("mmc:block"); #define INAND_CMD38_ARG_SECTRIM1 0x81 #define INAND_CMD38_ARG_SECTRIM2 0x88 -#define MMC_CMD_RETRIES 10 - static DEFINE_MUTEX(block_mutex); /* @@ -945,7 +943,6 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, if (!mmc_card_blockaddr(card)) brq->cmd.arg <<= 9; brq->cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; - brq->cmd.retries = MMC_CMD_RETRIES; brq->data.blksz = 512; brq->stop.opcode = MMC_STOP_TRANSMISSION; brq->stop.arg = 0; diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c index 440b97d9e44b..86817085aec7 100644 --- a/drivers/mmc/card/mmc_test.c +++ b/drivers/mmc/card/mmc_test.c @@ -211,7 +211,7 @@ static struct mmc_test_parameter mmc_test_parameter[] = { static long mmc_test_set_testcase(struct mmc_test_card *test) { - return 0; + return mmc_test_parameter[0].value; } static long mmc_test_set_clock(struct mmc_test_card *test) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 2a288e936a84..35f3df8810e0 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -109,11 +109,6 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq) cmd->retries--; cmd->error = 0; - if (mrq->data) { - mrq->data->error = 0; - if (mrq->stop) - mrq->stop->error = 0; - } host->ops->request(host, mrq); } else { led_trigger_event(host->led, LED_OFF); @@ -277,13 +272,44 @@ struct mmc_async_req *mmc_start_req(struct mmc_host *host, { int err = 0; struct mmc_async_req *data = host->areq; + struct mmc_card *card = host->card; + struct timeval before_time, after_time; /* Prepare a new request */ if (areq) mmc_pre_req(host, areq->mrq, !host->areq); if (host->areq) { + if (card->ext_csd.refresh && + (host->areq->mrq->data->flags & MMC_DATA_WRITE)) + do_gettimeofday(&before_time); mmc_wait_for_req_done(host, host->areq->mrq); + if (card->ext_csd.refresh && + (host->areq->mrq->data->flags & MMC_DATA_WRITE)) { + do_gettimeofday(&after_time); + switch (after_time.tv_sec - before_time.tv_sec) { + case 0: + if (after_time.tv_usec - + before_time.tv_usec >= + MMC_SLOW_WRITE_TIME) { + card->ext_csd.last_tv_sec = + after_time.tv_sec; + card->ext_csd.last_bkops_tv_sec = + after_time.tv_sec; + } + break; + case 1: + if (after_time.tv_usec - + before_time.tv_usec < + MMC_SLOW_WRITE_TIME - 1000000) + break; + default: + card->ext_csd.last_tv_sec = + after_time.tv_sec; + card->ext_csd.last_bkops_tv_sec = + after_time.tv_sec; + } + } err = host->areq->err_check(host->card, host->areq); if (err) { mmc_post_req(host, host->areq->mrq, 0); @@ -336,6 +362,7 @@ int mmc_bkops_start(struct mmc_card *card, bool is_synchronous) { int err; unsigned long flags; + struct timeval before_time, after_time; BUG_ON(!card); @@ -343,10 +370,29 @@ int mmc_bkops_start(struct mmc_card *card, bool is_synchronous) return 1; mmc_claim_host(card->host); + if (card->ext_csd.refresh) + do_gettimeofday(&before_time); err = mmc_send_bk_ops_cmd(card, is_synchronous); if (err) pr_err("%s: abort bk ops (%d error)\n", mmc_hostname(card->host), err); + if (card->ext_csd.refresh) { + do_gettimeofday(&after_time); + switch (after_time.tv_sec - before_time.tv_sec) { + case 0: + if (after_time.tv_usec - before_time.tv_usec >= + MMC_SLOW_WRITE_TIME) + card->ext_csd.last_tv_sec = after_time.tv_sec; + break; + case 1: + if (after_time.tv_usec - before_time.tv_usec < + MMC_SLOW_WRITE_TIME - 1000000) + break; + default: + card->ext_csd.last_tv_sec = after_time.tv_sec; + } + card->ext_csd.last_bkops_tv_sec = after_time.tv_sec; + } /* * Incase of asynchronous backops, set card state @@ -365,6 +411,57 @@ int mmc_bkops_start(struct mmc_card *card, bool is_synchronous) } EXPORT_SYMBOL(mmc_bkops_start); +static void mmc_bkops_work(struct work_struct *work) +{ + struct mmc_card *card = container_of(work, struct mmc_card, bkops); + mmc_bkops_start(card, true); +} + +static void mmc_refresh_work(struct work_struct *work) +{ + struct mmc_card *card = container_of(work, struct mmc_card, refresh); + char buf[512]; + mmc_gen_cmd(card, buf, 0x44, 0x1, 0x0, 0x1); +} + +void mmc_refresh(unsigned long data) +{ + struct mmc_card *card = (struct mmc_card *) data; + struct timeval cur_time; + __kernel_time_t timeout, timeout1, timeout2; + + if ((!card) || (!card->ext_csd.refresh)) + return; + + INIT_WORK(&card->bkops, (work_func_t) mmc_bkops_work); + INIT_WORK(&card->refresh, (work_func_t) mmc_refresh_work); + + do_gettimeofday(&cur_time); + timeout1 = MMC_REFRESH_INTERVAL - (cur_time.tv_sec - + card->ext_csd.last_tv_sec); + if ((cur_time.tv_sec < card->ext_csd.last_tv_sec) || + (timeout1 <= 0)) { + queue_work(workqueue, &card->refresh); + card->ext_csd.last_tv_sec = cur_time.tv_sec; + card->ext_csd.last_bkops_tv_sec = cur_time.tv_sec; + timeout1 = MMC_REFRESH_INTERVAL; + } + + timeout2 = MMC_BKOPS_INTERVAL - (cur_time.tv_sec - + card->ext_csd.last_bkops_tv_sec); + if ((cur_time.tv_sec < card->ext_csd.last_bkops_tv_sec) || + (timeout2 <= 0)) { + mmc_card_set_need_bkops(card); + queue_work(workqueue, &card->bkops); + timeout2 = MMC_BKOPS_INTERVAL; + } + + timeout = timeout1 < timeout2 ? timeout1 : timeout2; + card->timer.expires = jiffies + timeout*HZ; + add_timer(&card->timer); +} +EXPORT_SYMBOL(mmc_refresh); + /** * mmc_interrupt_hpi - Issue for High priority Interrupt * @card: the MMC card associated with the HPI transfer diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 69fb2275845c..40c93b3dccd7 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -96,6 +96,7 @@ static int mmc_decode_cid(struct mmc_card *card) card->cid.prod_name[3] = UNSTUFF_BITS(resp, 72, 8); card->cid.prod_name[4] = UNSTUFF_BITS(resp, 64, 8); card->cid.prod_name[5] = UNSTUFF_BITS(resp, 56, 8); + card->cid.prod_rev = UNSTUFF_BITS(resp, 48, 8); card->cid.serial = UNSTUFF_BITS(resp, 16, 32); card->cid.month = UNSTUFF_BITS(resp, 12, 4); card->cid.year = UNSTUFF_BITS(resp, 8, 4) + 1997; @@ -425,6 +426,11 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) /* Check whether the eMMC card supports background ops */ if (ext_csd[EXT_CSD_BKOPS_SUPPORT] & 0x1) card->ext_csd.bk_ops = 1; + + /* Check whether the eMMC card needs proactive refresh */ + if ((card->cid.manfid == 0x90) && ((card->cid.prod_rev == 0x73) + || (card->cid.prod_rev == 0x7b))) + card->ext_csd.refresh = 1; } if (ext_csd[EXT_CSD_ERASED_MEM_CONT]) @@ -516,6 +522,7 @@ MMC_DEV_ATTR(hwrev, "0x%x\n", card->cid.hwrev); MMC_DEV_ATTR(manfid, "0x%06x\n", card->cid.manfid); MMC_DEV_ATTR(name, "%s\n", card->cid.prod_name); MMC_DEV_ATTR(oemid, "0x%04x\n", card->cid.oemid); +MMC_DEV_ATTR(prv, "0x%x\n", card->cid.prod_rev); MMC_DEV_ATTR(serial, "0x%08x\n", card->cid.serial); MMC_DEV_ATTR(enhanced_area_offset, "%llu\n", card->ext_csd.enhanced_area_offset); @@ -532,6 +539,7 @@ static struct attribute *mmc_std_attrs[] = { &dev_attr_manfid.attr, &dev_attr_name.attr, &dev_attr_oemid.attr, + &dev_attr_prv.attr, &dev_attr_serial.attr, &dev_attr_enhanced_area_offset.attr, &dev_attr_enhanced_area_size.attr, @@ -672,6 +680,17 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, if (err) goto free_card; + if (card->ext_csd.refresh) { + init_timer(&card->timer); + card->timer.data = (unsigned long) card; + card->timer.function = mmc_refresh; + card->timer.expires = MMC_BKOPS_INTERVAL < + MMC_REFRESH_INTERVAL ? MMC_BKOPS_INTERVAL : + MMC_REFRESH_INTERVAL; + card->timer.expires *= HZ; + card->timer.expires += jiffies; + add_timer(&card->timer); + } /* If doing byte addressing, check if required to do sector * addressing. Handle the case of <2GB cards needing sector * addressing. See section 8.1 JEDEC Standard JED84-A441; diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 330b968393d6..c85c58aca3e2 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -588,7 +588,7 @@ int mmc_send_bk_ops_cmd(struct mmc_card *card, bool is_synchronous) cmd.opcode = MMC_SWITCH; cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | - (EXT_CSD_BKOPS_EN << 16) | + (EXT_CSD_BKOPS_START << 16) | (1 << 8) | EXT_CSD_CMD_SET_NORMAL; if (is_synchronous) @@ -617,3 +617,66 @@ int mmc_send_bk_ops_cmd(struct mmc_card *card, bool is_synchronous) return 0; } + +int mmc_gen_cmd(struct mmc_card *card, void *buf, u8 index, u8 arg1, u8 arg2, u8 mode) +{ + struct mmc_request mrq; + struct mmc_command cmd; + struct mmc_data data; + struct mmc_command stop; + struct scatterlist sg; + void *data_buf; + + mmc_set_blocklen(card, 512); + + data_buf = kmalloc(512, GFP_KERNEL); + if (data_buf == NULL) + return -ENOMEM; + + memset(&mrq, 0, sizeof(struct mmc_request)); + memset(&cmd, 0, sizeof(struct mmc_command)); + memset(&data, 0, sizeof(struct mmc_data)); + memset(&stop, 0, sizeof(struct mmc_command)); + + mrq.cmd = &cmd; + mrq.data = &data; + mrq.stop = &stop; + + cmd.opcode = MMC_GEN_CMD; + cmd.arg = (arg2 << 16) | + (arg1 << 8) | + (index << 1) | + mode; + + cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; + + data.blksz = 512; + data.blocks = 1; + data.flags = MMC_DATA_READ; + data.sg = &sg; + data.sg_len = 1; + + stop.opcode = MMC_STOP_TRANSMISSION; + stop.arg = 0; + stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; + + sg_init_one(&sg, data_buf, 512); + + mmc_set_data_timeout(&data, card); + + mmc_claim_host(card->host); + mmc_wait_for_req(card->host, &mrq); + mmc_release_host(card->host); + + memcpy(buf, data_buf, 512); + kfree(data_buf); + + if (cmd.error) + return cmd.error; + if (data.error) + return data.error; + if (stop.error) + return stop.error; + + return 0; +} diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h index d8f157dee147..a453531b46b6 100644 --- a/drivers/mmc/core/mmc_ops.h +++ b/drivers/mmc/core/mmc_ops.h @@ -29,6 +29,7 @@ int mmc_card_sleepawake(struct mmc_host *host, int sleep); int mmc_bus_test(struct mmc_card *card, u8 bus_width); int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status); int mmc_send_bk_ops_cmd(struct mmc_card *card, bool is_synchronous); +int mmc_gen_cmd(struct mmc_card *card, void *buf, u8 index, u8 arg1, u8 arg2, u8 mode); #endif diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index d6ed03d4f22a..609fd6391d1f 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c @@ -112,9 +112,13 @@ struct tegra_sdhci_host { unsigned int vddio_max_uv; /* max clk supported by the platform */ unsigned int max_clk_limit; + /* max ddr clk supported by the platform */ + unsigned int ddr_clk_limit; struct tegra_io_dpd *dpd; bool card_present; bool is_rail_enabled; + struct clk *emc_clk; + unsigned int emc_max_clk; }; static u32 tegra_sdhci_readl(struct sdhci_host *host, int reg) @@ -366,14 +370,30 @@ static void tegra_sdhci_set_clk_rate(struct sdhci_host *sdhci, struct sdhci_pltfm_host *pltfm_host = sdhci_priv(sdhci); struct tegra_sdhci_host *tegra_host = pltfm_host->priv; unsigned int clk_rate; + unsigned int emc_clk; + /* + * In SDR50 mode, run the sdmmc controller at freq greater than + * 104MHz to ensure the core voltage is at 1.2V. If the core voltage + * is below 1.2V, CRC errors would occur during data transfers. + */ if (sdhci->mmc->card && - mmc_card_ddr_mode(sdhci->mmc->card)) { + (mmc_card_ddr_mode(sdhci->mmc->card) || + (sdhci->mmc->ios.timing == MMC_TIMING_UHS_SDR50))) { /* * In ddr mode, tegra sdmmc controller clock frequency * should be double the card clock frequency. */ - clk_rate = clock * 2; + if (tegra_host->ddr_clk_limit) { + clk_rate = tegra_host->ddr_clk_limit * 2; + if (tegra_host->emc_clk) { + emc_clk = clk_get_rate(tegra_host->emc_clk); + if (emc_clk == tegra_host->emc_max_clk) + clk_rate = clock * 2; + } + } else { + clk_rate = clock * 2; + } } else { if (clock <= tegra_sdhost_min_freq) clk_rate = tegra_sdhost_min_freq; @@ -381,15 +401,6 @@ static void tegra_sdhci_set_clk_rate(struct sdhci_host *sdhci, clk_rate = tegra_sdhost_std_freq; else clk_rate = clock; - - /* - * In SDR50 mode, run the sdmmc controller at 208MHz to ensure - * the core voltage is at 1.2V. If the core voltage is below 1.2V, CRC - * errors would occur during data transfers. - */ - if ((sdhci->mmc->ios.timing == MMC_TIMING_UHS_SDR50) && - (clk_rate == tegra_sdhost_std_freq)) - clk_rate <<= 1; } if (tegra_host->max_clk_limit && @@ -534,11 +545,6 @@ static int tegra_sdhci_signal_voltage_switch(struct sdhci_host *sdhci, u16 clk, ctrl; unsigned int val; - /* Switch OFF the card clock to prevent glitches on the clock line */ - clk = sdhci_readw(sdhci, SDHCI_CLOCK_CONTROL); - clk &= ~SDHCI_CLOCK_CARD_EN; - sdhci_writew(sdhci, clk, SDHCI_CLOCK_CONTROL); - ctrl = sdhci_readw(sdhci, SDHCI_HOST_CONTROL2); if (signal_voltage == MMC_SIGNAL_VOLTAGE_180) { ctrl |= SDHCI_CTRL_VDD_180; @@ -548,6 +554,17 @@ static int tegra_sdhci_signal_voltage_switch(struct sdhci_host *sdhci, if (ctrl & SDHCI_CTRL_VDD_180) ctrl &= ~SDHCI_CTRL_VDD_180; } + + /* Check if the slot can support the required voltage */ + if (min_uV > tegra_host->vddio_max_uv) + return 0; + + /* Switch OFF the card clock to prevent glitches on the clock line */ + clk = sdhci_readw(sdhci, SDHCI_CLOCK_CONTROL); + clk &= ~SDHCI_CLOCK_CARD_EN; + sdhci_writew(sdhci, clk, SDHCI_CLOCK_CONTROL); + + /* Set/clear the 1.8V signalling */ sdhci_writew(sdhci, ctrl, SDHCI_HOST_CONTROL2); /* Switch the I/O rail voltage */ @@ -1075,10 +1092,23 @@ static int __devinit sdhci_tegra_probe(struct platform_device *pdev) rc = clk_enable(clk); if (rc != 0) goto err_clk_put; + + if (!strcmp(dev_name(mmc_dev(host->mmc)), "sdhci-tegra.3")) { + tegra_host->emc_clk = clk_get(mmc_dev(host->mmc), "emc"); + if (IS_ERR(tegra_host->emc_clk)) { + dev_err(mmc_dev(host->mmc), "clk err\n"); + rc = PTR_ERR(tegra_host->emc_clk); + goto err_clk_put; + } + tegra_host->emc_max_clk = + clk_round_rate(tegra_host->emc_clk, ULONG_MAX); + } + pltfm_host->clk = clk; pltfm_host->priv = tegra_host; tegra_host->clk_enabled = true; tegra_host->max_clk_limit = plat->max_clk_limit; + tegra_host->ddr_clk_limit = plat->ddr_clk_limit; tegra_host->instance = pdev->id; tegra_host->dpd = tegra_io_dpd_get(mmc_dev(host->mmc)); @@ -1098,6 +1128,11 @@ static int __devinit sdhci_tegra_probe(struct platform_device *pdev) host->mmc->caps |= MMC_CAP_NONREMOVABLE; } host->mmc->pm_flags |= MMC_PM_IGNORE_PM_NOTIFY; + +#ifdef CONFIG_MMC_BKOPS + host->mmc->caps |= MMC_CAP_BKOPS; +#endif + #ifdef CONFIG_MMC_EMBEDDED_SDIO /* Do not turn OFF embedded sdio cards as it support Wake on Wireless */ if (plat->mmc_data.embedded_sdio) @@ -1120,6 +1155,7 @@ static int __devinit sdhci_tegra_probe(struct platform_device *pdev) return 0; err_add_host: + clk_put(tegra_host->emc_clk); clk_disable(pltfm_host->clk); err_clk_put: clk_put(pltfm_host->clk); diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 495586924d60..22814660bc34 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -2330,20 +2330,34 @@ out: int sdhci_suspend_host(struct sdhci_host *host, pm_message_t state) { int ret = 0; + bool has_tuning_timer; struct mmc_host *mmc = host->mmc; sdhci_disable_card_detection(host); /* Disable tuning since we are suspending */ - if (host->version >= SDHCI_SPEC_300 && host->tuning_count && - host->tuning_mode == SDHCI_TUNING_MODE_1) { + has_tuning_timer = host->version >= SDHCI_SPEC_300 && + host->tuning_count && host->tuning_mode == SDHCI_TUNING_MODE_1; + if (has_tuning_timer) { host->flags &= ~SDHCI_NEEDS_RETUNING; mod_timer(&host->tuning_timer, jiffies + host->tuning_count * HZ); } - if (mmc->card) + if (mmc->card) { ret = mmc_suspend_host(host->mmc); + if (ret) { + if (has_tuning_timer) { + host->flags |= SDHCI_NEEDS_RETUNING; + mod_timer(&host->tuning_timer, jiffies + + host->tuning_count * HZ); + } + + sdhci_enable_card_detection(host); + + return ret; + } + } if (mmc->pm_flags & MMC_PM_KEEP_POWER) host->card_int_set = sdhci_readl(host, SDHCI_INT_ENABLE) & diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 34f83a4c9561..dc44c5c33e01 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -277,13 +277,8 @@ static void sh_mmcif_start_dma_tx(struct sh_mmcif_host *host) DMA_TO_DEVICE); if (ret > 0) { host->dma_active = true; -<<<<<<< HEAD - desc = chan->device->device_prep_slave_sg(chan, sg, ret, - DMA_TO_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); -======= desc = dmaengine_prep_slave_sg(chan, sg, ret, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); ->>>>>>> 1605282... dmaengine/dma_slave: introduce inline wrappers } if (desc) { diff --git a/drivers/mmc/host/tmio_mmc_dma.c b/drivers/mmc/host/tmio_mmc_dma.c index d298e7bd26d2..def9c54f73f5 100644 --- a/drivers/mmc/host/tmio_mmc_dma.c +++ b/drivers/mmc/host/tmio_mmc_dma.c @@ -157,13 +157,8 @@ static void tmio_mmc_start_dma_tx(struct tmio_mmc_host *host) ret = dma_map_sg(chan->device->dev, sg, host->sg_len, DMA_TO_DEVICE); if (ret > 0) -<<<<<<< HEAD - desc = chan->device->device_prep_slave_sg(chan, sg, ret, - DMA_TO_DEVICE, DMA_CTRL_ACK); -======= desc = dmaengine_prep_slave_sg(chan, sg, ret, DMA_MEM_TO_DEV, DMA_CTRL_ACK); ->>>>>>> 1605282... dmaengine/dma_slave: introduce inline wrappers if (desc) { cookie = dmaengine_submit(desc); |