.. | .. |
---|
| 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 | } |
---|
.. | .. |
---|
3584 | 3598 | spin_lock_init(&base->lcla_pool.lock); |
---|
3585 | 3599 | |
---|
3586 | 3600 | base->irq = platform_get_irq(pdev, 0); |
---|
| 3601 | + if (base->irq < 0) { |
---|
| 3602 | + ret = base->irq; |
---|
| 3603 | + goto destroy_cache; |
---|
| 3604 | + } |
---|
3587 | 3605 | |
---|
3588 | 3606 | ret = request_irq(base->irq, d40_handle_interrupt, 0, D40_NAME, base); |
---|
3589 | 3607 | if (ret) { |
---|
.. | .. |
---|
3624 | 3642 | if (ret) |
---|
3625 | 3643 | goto destroy_cache; |
---|
3626 | 3644 | |
---|
3627 | | - base->dev->dma_parms = &base->dma_parms; |
---|
3628 | 3645 | ret = dma_set_max_seg_size(base->dev, STEDMA40_MAX_SEG_SIZE); |
---|
3629 | 3646 | if (ret) { |
---|
3630 | 3647 | d40_err(&pdev->dev, "Failed to set dma max seg size\n"); |
---|