diff options
author | Micky Ching <micky_ching@realsil.com.cn> | 2014-06-06 03:05:44 -0400 |
---|---|---|
committer | Lee Jones <lee.jones@linaro.org> | 2014-07-09 09:14:58 -0400 |
commit | 8cd118308a8649c649533a0133af0ce731d223bb (patch) | |
tree | d133d73fcded3bac7b0b73f63617dc79b4591353 | |
parent | cd3de83f147601356395b57a8673e9c5ff1e59d1 (diff) |
mfd: rtsx: Add dma transfer function
rtsx driver using a single function for transfer data, dma map/unmap are
placed in one fix function. We need map/unmap dma in different place(for
mmc async driver), so add three function for dma map, dma transfer and
dma unmap.
Signed-off-by: Micky Ching <micky_ching@realsil.com.cn>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
-rw-r--r-- | drivers/mfd/rtsx_pcr.c | 76 | ||||
-rw-r--r-- | include/linux/mfd/rtsx_pci.h | 6 |
2 files changed, 54 insertions, 28 deletions
diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c index 1d15735f9ef9..d01b8c249231 100644 --- a/drivers/mfd/rtsx_pcr.c +++ b/drivers/mfd/rtsx_pcr.c | |||
@@ -337,40 +337,64 @@ static void rtsx_pci_add_sg_tbl(struct rtsx_pcr *pcr, | |||
337 | int rtsx_pci_transfer_data(struct rtsx_pcr *pcr, struct scatterlist *sglist, | 337 | int rtsx_pci_transfer_data(struct rtsx_pcr *pcr, struct scatterlist *sglist, |
338 | int num_sg, bool read, int timeout) | 338 | int num_sg, bool read, int timeout) |
339 | { | 339 | { |
340 | struct completion trans_done; | 340 | int err = 0, count; |
341 | u8 dir; | ||
342 | int err = 0, i, count; | ||
343 | long timeleft; | ||
344 | unsigned long flags; | ||
345 | struct scatterlist *sg; | ||
346 | enum dma_data_direction dma_dir; | ||
347 | u32 val; | ||
348 | dma_addr_t addr; | ||
349 | unsigned int len; | ||
350 | 341 | ||
351 | dev_dbg(&(pcr->pci->dev), "--> %s: num_sg = %d\n", __func__, num_sg); | 342 | dev_dbg(&(pcr->pci->dev), "--> %s: num_sg = %d\n", __func__, num_sg); |
343 | count = rtsx_pci_dma_map_sg(pcr, sglist, num_sg, read); | ||
344 | if (count < 1) | ||
345 | return -EINVAL; | ||
346 | dev_dbg(&(pcr->pci->dev), "DMA mapping count: %d\n", count); | ||
347 | |||
348 | err = rtsx_pci_dma_transfer(pcr, sglist, count, read, timeout); | ||
349 | |||
350 | rtsx_pci_dma_unmap_sg(pcr, sglist, num_sg, read); | ||
351 | |||
352 | return err; | ||
353 | } | ||
354 | EXPORT_SYMBOL_GPL(rtsx_pci_transfer_data); | ||
355 | |||
356 | int rtsx_pci_dma_map_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist, | ||
357 | int num_sg, bool read) | ||
358 | { | ||
359 | enum dma_data_direction dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE; | ||
352 | 360 | ||
353 | /* don't transfer data during abort processing */ | ||
354 | if (pcr->remove_pci) | 361 | if (pcr->remove_pci) |
355 | return -EINVAL; | 362 | return -EINVAL; |
356 | 363 | ||
357 | if ((sglist == NULL) || (num_sg <= 0)) | 364 | if ((sglist == NULL) || (num_sg <= 0)) |
358 | return -EINVAL; | 365 | return -EINVAL; |
359 | 366 | ||
360 | if (read) { | 367 | return dma_map_sg(&(pcr->pci->dev), sglist, num_sg, dir); |
361 | dir = DEVICE_TO_HOST; | 368 | } |
362 | dma_dir = DMA_FROM_DEVICE; | 369 | EXPORT_SYMBOL_GPL(rtsx_pci_dma_map_sg); |
363 | } else { | ||
364 | dir = HOST_TO_DEVICE; | ||
365 | dma_dir = DMA_TO_DEVICE; | ||
366 | } | ||
367 | 370 | ||
368 | count = dma_map_sg(&(pcr->pci->dev), sglist, num_sg, dma_dir); | 371 | void rtsx_pci_dma_unmap_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist, |
369 | if (count < 1) { | 372 | int num_sg, bool read) |
370 | dev_err(&(pcr->pci->dev), "scatterlist map failed\n"); | 373 | { |
374 | enum dma_data_direction dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE; | ||
375 | |||
376 | dma_unmap_sg(&(pcr->pci->dev), sglist, num_sg, dir); | ||
377 | } | ||
378 | EXPORT_SYMBOL_GPL(rtsx_pci_dma_unmap_sg); | ||
379 | |||
380 | int rtsx_pci_dma_transfer(struct rtsx_pcr *pcr, struct scatterlist *sglist, | ||
381 | int count, bool read, int timeout) | ||
382 | { | ||
383 | struct completion trans_done; | ||
384 | struct scatterlist *sg; | ||
385 | dma_addr_t addr; | ||
386 | long timeleft; | ||
387 | unsigned long flags; | ||
388 | unsigned int len; | ||
389 | int i, err = 0; | ||
390 | u32 val; | ||
391 | u8 dir = read ? DEVICE_TO_HOST : HOST_TO_DEVICE; | ||
392 | |||
393 | if (pcr->remove_pci) | ||
394 | return -ENODEV; | ||
395 | |||
396 | if ((sglist == NULL) || (count < 1)) | ||
371 | return -EINVAL; | 397 | return -EINVAL; |
372 | } | ||
373 | dev_dbg(&(pcr->pci->dev), "DMA mapping count: %d\n", count); | ||
374 | 398 | ||
375 | val = ((u32)(dir & 0x01) << 29) | TRIG_DMA | ADMA_MODE; | 399 | val = ((u32)(dir & 0x01) << 29) | TRIG_DMA | ADMA_MODE; |
376 | pcr->sgi = 0; | 400 | pcr->sgi = 0; |
@@ -400,12 +424,10 @@ int rtsx_pci_transfer_data(struct rtsx_pcr *pcr, struct scatterlist *sglist, | |||
400 | } | 424 | } |
401 | 425 | ||
402 | spin_lock_irqsave(&pcr->lock, flags); | 426 | spin_lock_irqsave(&pcr->lock, flags); |
403 | |||
404 | if (pcr->trans_result == TRANS_RESULT_FAIL) | 427 | if (pcr->trans_result == TRANS_RESULT_FAIL) |
405 | err = -EINVAL; | 428 | err = -EINVAL; |
406 | else if (pcr->trans_result == TRANS_NO_DEVICE) | 429 | else if (pcr->trans_result == TRANS_NO_DEVICE) |
407 | err = -ENODEV; | 430 | err = -ENODEV; |
408 | |||
409 | spin_unlock_irqrestore(&pcr->lock, flags); | 431 | spin_unlock_irqrestore(&pcr->lock, flags); |
410 | 432 | ||
411 | out: | 433 | out: |
@@ -413,8 +435,6 @@ out: | |||
413 | pcr->done = NULL; | 435 | pcr->done = NULL; |
414 | spin_unlock_irqrestore(&pcr->lock, flags); | 436 | spin_unlock_irqrestore(&pcr->lock, flags); |
415 | 437 | ||
416 | dma_unmap_sg(&(pcr->pci->dev), sglist, num_sg, dma_dir); | ||
417 | |||
418 | if ((err < 0) && (err != -ENODEV)) | 438 | if ((err < 0) && (err != -ENODEV)) |
419 | rtsx_pci_stop_cmd(pcr); | 439 | rtsx_pci_stop_cmd(pcr); |
420 | 440 | ||
@@ -423,7 +443,7 @@ out: | |||
423 | 443 | ||
424 | return err; | 444 | return err; |
425 | } | 445 | } |
426 | EXPORT_SYMBOL_GPL(rtsx_pci_transfer_data); | 446 | EXPORT_SYMBOL_GPL(rtsx_pci_dma_transfer); |
427 | 447 | ||
428 | int rtsx_pci_read_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len) | 448 | int rtsx_pci_read_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len) |
429 | { | 449 | { |
diff --git a/include/linux/mfd/rtsx_pci.h b/include/linux/mfd/rtsx_pci.h index a3835976f7c6..74346d5e7899 100644 --- a/include/linux/mfd/rtsx_pci.h +++ b/include/linux/mfd/rtsx_pci.h | |||
@@ -943,6 +943,12 @@ void rtsx_pci_send_cmd_no_wait(struct rtsx_pcr *pcr); | |||
943 | int rtsx_pci_send_cmd(struct rtsx_pcr *pcr, int timeout); | 943 | int rtsx_pci_send_cmd(struct rtsx_pcr *pcr, int timeout); |
944 | int rtsx_pci_transfer_data(struct rtsx_pcr *pcr, struct scatterlist *sglist, | 944 | int rtsx_pci_transfer_data(struct rtsx_pcr *pcr, struct scatterlist *sglist, |
945 | int num_sg, bool read, int timeout); | 945 | int num_sg, bool read, int timeout); |
946 | int rtsx_pci_dma_map_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist, | ||
947 | int num_sg, bool read); | ||
948 | void rtsx_pci_dma_unmap_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist, | ||
949 | int num_sg, bool read); | ||
950 | int rtsx_pci_dma_transfer(struct rtsx_pcr *pcr, struct scatterlist *sglist, | ||
951 | int count, bool read, int timeout); | ||
946 | int rtsx_pci_read_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len); | 952 | int rtsx_pci_read_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len); |
947 | int rtsx_pci_write_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len); | 953 | int rtsx_pci_write_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len); |
948 | int rtsx_pci_card_pull_ctl_enable(struct rtsx_pcr *pcr, int card); | 954 | int rtsx_pci_card_pull_ctl_enable(struct rtsx_pcr *pcr, int card); |