| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (C) Ericsson AB 2007-2008 |
|---|
| 3 | 4 | * Copyright (C) ST-Ericsson SA 2008-2010 |
|---|
| 4 | 5 | * Author: Per Forlin <per.forlin@stericsson.com> for ST-Ericsson |
|---|
| 5 | 6 | * Author: Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson |
|---|
| 6 | | - * License terms: GNU General Public License (GPL) version 2 |
|---|
| 7 | 7 | */ |
|---|
| 8 | 8 | |
|---|
| 9 | 9 | #include <linux/dma-mapping.h> |
|---|
| .. | .. |
|---|
| 381 | 381 | * struct d40_lcla_pool - LCLA pool settings and data. |
|---|
| 382 | 382 | * |
|---|
| 383 | 383 | * @base: The virtual address of LCLA. 18 bit aligned. |
|---|
| 384 | + * @dma_addr: DMA address, if mapped |
|---|
| 384 | 385 | * @base_unaligned: The orignal kmalloc pointer, if kmalloc is used. |
|---|
| 385 | 386 | * This pointer is only there for clean-up on error. |
|---|
| 386 | 387 | * @pages: The number of pages needed for all physical channels. |
|---|
| .. | .. |
|---|
| 442 | 443 | * @queue: Queued jobs. |
|---|
| 443 | 444 | * @prepare_queue: Prepared jobs. |
|---|
| 444 | 445 | * @dma_cfg: The client configuration of this dma channel. |
|---|
| 446 | + * @slave_config: DMA slave configuration. |
|---|
| 445 | 447 | * @configured: whether the dma_cfg configuration is valid |
|---|
| 446 | 448 | * @base: Pointer to the device instance struct. |
|---|
| 447 | 449 | * @src_def_cfg: Default cfg register setting for src. |
|---|
| .. | .. |
|---|
| 468 | 470 | struct list_head queue; |
|---|
| 469 | 471 | struct list_head prepare_queue; |
|---|
| 470 | 472 | struct stedma40_chan_cfg dma_cfg; |
|---|
| 473 | + struct dma_slave_config slave_config; |
|---|
| 471 | 474 | bool configured; |
|---|
| 472 | 475 | struct d40_base *base; |
|---|
| 473 | 476 | /* Default register configurations */ |
|---|
| .. | .. |
|---|
| 573 | 576 | int num_memcpy_chans; |
|---|
| 574 | 577 | int num_phy_chans; |
|---|
| 575 | 578 | int num_log_chans; |
|---|
| 576 | | - struct device_dma_parameters dma_parms; |
|---|
| 577 | 579 | struct dma_device dma_both; |
|---|
| 578 | 580 | struct dma_device dma_slave; |
|---|
| 579 | 581 | struct dma_device dma_memcpy; |
|---|
| .. | .. |
|---|
| 624 | 626 | |
|---|
| 625 | 627 | #define chan_err(d40c, format, arg...) \ |
|---|
| 626 | 628 | d40_err(chan2dev(d40c), format, ## arg) |
|---|
| 629 | + |
|---|
| 630 | +static int d40_set_runtime_config_write(struct dma_chan *chan, |
|---|
| 631 | + struct dma_slave_config *config, |
|---|
| 632 | + enum dma_transfer_direction direction); |
|---|
| 627 | 633 | |
|---|
| 628 | 634 | static int d40_pool_lli_alloc(struct d40_chan *d40c, struct d40_desc *d40d, |
|---|
| 629 | 635 | int lli_len) |
|---|
| .. | .. |
|---|
| 1565 | 1571 | |
|---|
| 1566 | 1572 | } |
|---|
| 1567 | 1573 | |
|---|
| 1568 | | -static void dma_tasklet(unsigned long data) |
|---|
| 1574 | +static void dma_tasklet(struct tasklet_struct *t) |
|---|
| 1569 | 1575 | { |
|---|
| 1570 | | - struct d40_chan *d40c = (struct d40_chan *) data; |
|---|
| 1576 | + struct d40_chan *d40c = from_tasklet(d40c, t, tasklet); |
|---|
| 1571 | 1577 | struct d40_desc *d40d; |
|---|
| 1572 | 1578 | unsigned long flags; |
|---|
| 1573 | 1579 | bool callback_active; |
|---|
| .. | .. |
|---|
| 2216 | 2222 | return NULL; |
|---|
| 2217 | 2223 | } |
|---|
| 2218 | 2224 | |
|---|
| 2225 | + d40_set_runtime_config_write(dchan, &chan->slave_config, direction); |
|---|
| 2226 | + |
|---|
| 2219 | 2227 | spin_lock_irqsave(&chan->lock, flags); |
|---|
| 2220 | 2228 | |
|---|
| 2221 | 2229 | desc = d40_prep_desc(chan, sg_src, sg_len, dma_flags); |
|---|
| .. | .. |
|---|
| 2634 | 2642 | return 0; |
|---|
| 2635 | 2643 | } |
|---|
| 2636 | 2644 | |
|---|
| 2637 | | -/* Runtime reconfiguration extension */ |
|---|
| 2638 | 2645 | static int d40_set_runtime_config(struct dma_chan *chan, |
|---|
| 2639 | 2646 | struct dma_slave_config *config) |
|---|
| 2647 | +{ |
|---|
| 2648 | + struct d40_chan *d40c = container_of(chan, struct d40_chan, chan); |
|---|
| 2649 | + |
|---|
| 2650 | + memcpy(&d40c->slave_config, config, sizeof(*config)); |
|---|
| 2651 | + |
|---|
| 2652 | + return 0; |
|---|
| 2653 | +} |
|---|
| 2654 | + |
|---|
| 2655 | +/* Runtime reconfiguration extension */ |
|---|
| 2656 | +static int d40_set_runtime_config_write(struct dma_chan *chan, |
|---|
| 2657 | + struct dma_slave_config *config, |
|---|
| 2658 | + enum dma_transfer_direction direction) |
|---|
| 2640 | 2659 | { |
|---|
| 2641 | 2660 | struct d40_chan *d40c = container_of(chan, struct d40_chan, chan); |
|---|
| 2642 | 2661 | struct stedma40_chan_cfg *cfg = &d40c->dma_cfg; |
|---|
| .. | .. |
|---|
| 2655 | 2674 | dst_addr_width = config->dst_addr_width; |
|---|
| 2656 | 2675 | dst_maxburst = config->dst_maxburst; |
|---|
| 2657 | 2676 | |
|---|
| 2658 | | - if (config->direction == DMA_DEV_TO_MEM) { |
|---|
| 2677 | + if (direction == DMA_DEV_TO_MEM) { |
|---|
| 2659 | 2678 | config_addr = config->src_addr; |
|---|
| 2660 | 2679 | |
|---|
| 2661 | 2680 | if (cfg->dir != DMA_DEV_TO_MEM) |
|---|
| .. | .. |
|---|
| 2671 | 2690 | if (dst_maxburst == 0) |
|---|
| 2672 | 2691 | dst_maxburst = src_maxburst; |
|---|
| 2673 | 2692 | |
|---|
| 2674 | | - } else if (config->direction == DMA_MEM_TO_DEV) { |
|---|
| 2693 | + } else if (direction == DMA_MEM_TO_DEV) { |
|---|
| 2675 | 2694 | config_addr = config->dst_addr; |
|---|
| 2676 | 2695 | |
|---|
| 2677 | 2696 | if (cfg->dir != DMA_MEM_TO_DEV) |
|---|
| .. | .. |
|---|
| 2689 | 2708 | } else { |
|---|
| 2690 | 2709 | dev_err(d40c->base->dev, |
|---|
| 2691 | 2710 | "unrecognized channel direction %d\n", |
|---|
| 2692 | | - config->direction); |
|---|
| 2711 | + direction); |
|---|
| 2693 | 2712 | return -EINVAL; |
|---|
| 2694 | 2713 | } |
|---|
| 2695 | 2714 | |
|---|
| .. | .. |
|---|
| 2746 | 2765 | |
|---|
| 2747 | 2766 | /* These settings will take precedence later */ |
|---|
| 2748 | 2767 | d40c->runtime_addr = config_addr; |
|---|
| 2749 | | - d40c->runtime_direction = config->direction; |
|---|
| 2768 | + d40c->runtime_direction = direction; |
|---|
| 2750 | 2769 | dev_dbg(d40c->base->dev, |
|---|
| 2751 | 2770 | "configured channel %s for %s, data width %d/%d, " |
|---|
| 2752 | 2771 | "maxburst %d/%d elements, LE, no flow control\n", |
|---|
| 2753 | 2772 | dma_chan_name(chan), |
|---|
| 2754 | | - (config->direction == DMA_DEV_TO_MEM) ? "RX" : "TX", |
|---|
| 2773 | + (direction == DMA_DEV_TO_MEM) ? "RX" : "TX", |
|---|
| 2755 | 2774 | src_addr_width, dst_addr_width, |
|---|
| 2756 | 2775 | src_maxburst, dst_maxburst); |
|---|
| 2757 | 2776 | |
|---|
| .. | .. |
|---|
| 2785 | 2804 | INIT_LIST_HEAD(&d40c->client); |
|---|
| 2786 | 2805 | INIT_LIST_HEAD(&d40c->prepare_queue); |
|---|
| 2787 | 2806 | |
|---|
| 2788 | | - tasklet_init(&d40c->tasklet, dma_tasklet, |
|---|
| 2789 | | - (unsigned long) d40c); |
|---|
| 2807 | + tasklet_setup(&d40c->tasklet, dma_tasklet); |
|---|
| 2790 | 2808 | |
|---|
| 2791 | 2809 | list_add_tail(&d40c->chan.device_node, |
|---|
| 2792 | 2810 | &dma->channels); |
|---|
| .. | .. |
|---|
| 2839 | 2857 | |
|---|
| 2840 | 2858 | d40_ops_init(base, &base->dma_slave); |
|---|
| 2841 | 2859 | |
|---|
| 2842 | | - err = dma_async_device_register(&base->dma_slave); |
|---|
| 2860 | + err = dmaenginem_async_device_register(&base->dma_slave); |
|---|
| 2843 | 2861 | |
|---|
| 2844 | 2862 | if (err) { |
|---|
| 2845 | 2863 | d40_err(base->dev, "Failed to register slave channels\n"); |
|---|
| .. | .. |
|---|
| 2854 | 2872 | |
|---|
| 2855 | 2873 | d40_ops_init(base, &base->dma_memcpy); |
|---|
| 2856 | 2874 | |
|---|
| 2857 | | - err = dma_async_device_register(&base->dma_memcpy); |
|---|
| 2875 | + err = dmaenginem_async_device_register(&base->dma_memcpy); |
|---|
| 2858 | 2876 | |
|---|
| 2859 | 2877 | if (err) { |
|---|
| 2860 | 2878 | d40_err(base->dev, |
|---|
| 2861 | 2879 | "Failed to register memcpy only channels\n"); |
|---|
| 2862 | | - goto unregister_slave; |
|---|
| 2880 | + goto exit; |
|---|
| 2863 | 2881 | } |
|---|
| 2864 | 2882 | |
|---|
| 2865 | 2883 | d40_chan_init(base, &base->dma_both, base->phy_chans, |
|---|
| .. | .. |
|---|
| 2871 | 2889 | dma_cap_set(DMA_CYCLIC, base->dma_slave.cap_mask); |
|---|
| 2872 | 2890 | |
|---|
| 2873 | 2891 | d40_ops_init(base, &base->dma_both); |
|---|
| 2874 | | - err = dma_async_device_register(&base->dma_both); |
|---|
| 2892 | + err = dmaenginem_async_device_register(&base->dma_both); |
|---|
| 2875 | 2893 | |
|---|
| 2876 | 2894 | if (err) { |
|---|
| 2877 | 2895 | d40_err(base->dev, |
|---|
| 2878 | 2896 | "Failed to register logical and physical capable channels\n"); |
|---|
| 2879 | | - goto unregister_memcpy; |
|---|
| 2897 | + goto exit; |
|---|
| 2880 | 2898 | } |
|---|
| 2881 | 2899 | return 0; |
|---|
| 2882 | | - unregister_memcpy: |
|---|
| 2883 | | - dma_async_device_unregister(&base->dma_memcpy); |
|---|
| 2884 | | - unregister_slave: |
|---|
| 2885 | | - dma_async_device_unregister(&base->dma_slave); |
|---|
| 2886 | 2900 | exit: |
|---|
| 2887 | 2901 | return err; |
|---|
| 2888 | 2902 | } |
|---|
| .. | .. |
|---|
| 3624 | 3638 | if (ret) |
|---|
| 3625 | 3639 | goto destroy_cache; |
|---|
| 3626 | 3640 | |
|---|
| 3627 | | - base->dev->dma_parms = &base->dma_parms; |
|---|
| 3628 | 3641 | ret = dma_set_max_seg_size(base->dev, STEDMA40_MAX_SEG_SIZE); |
|---|
| 3629 | 3642 | if (ret) { |
|---|
| 3630 | 3643 | d40_err(&pdev->dev, "Failed to set dma max seg size\n"); |
|---|