Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

dmaengine: xilinx: xdma: Add user logic interrupt support

The Xilinx DMA/Bridge Subsystem for PCIe (XDMA) provides up to 16 user
interrupt wires to user logic that generate interrupts to the host.
This patch adds APIs to enable/disable user logic interrupt for a given
interrupt wire index.

Signed-off-by: Lizhi Hou <lizhi.hou@amd.com>
Signed-off-by: Sonal Santan <sonal.santan@amd.com>
Signed-off-by: Max Zhen <max.zhen@amd.com>
Signed-off-by: Brian Xu <brian.xu@amd.com>
Tested-by: Martin Tuma <tumic@gpxsee.org>
Link: https://lore.kernel.org/r/1674145926-29449-3-git-send-email-lizhi.hou@amd.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>

authored by

Lizhi Hou and committed by
Vinod Koul
ecf294a6 17ce2522

+98
+1
MAINTAINERS
··· 22897 22897 S: Supported 22898 22898 F: drivers/dma/xilinx/xdma-regs.h 22899 22899 F: drivers/dma/xilinx/xdma.c 22900 + F: include/linux/dma/amd_xdma.h 22900 22901 F: include/linux/platform_data/amd_xdma.h 22901 22902 22902 22903 XILINX ZYNQMP DPDMA DRIVER
+81
drivers/dma/xilinx/xdma.c
··· 25 25 #include <linux/dmapool.h> 26 26 #include <linux/regmap.h> 27 27 #include <linux/dmaengine.h> 28 + #include <linux/dma/amd_xdma.h> 28 29 #include <linux/platform_device.h> 29 30 #include <linux/platform_data/amd_xdma.h> 30 31 #include <linux/dma-mapping.h> ··· 688 687 static int xdma_irq_init(struct xdma_device *xdev) 689 688 { 690 689 u32 irq = xdev->irq_start; 690 + u32 user_irq_start; 691 691 int i, j, ret; 692 692 693 693 /* return failure if there are not enough IRQs */ ··· 731 729 goto failed_init_c2h; 732 730 } 733 731 732 + /* config user IRQ registers if needed */ 733 + user_irq_start = XDMA_CHAN_NUM(xdev); 734 + if (xdev->irq_num > user_irq_start) { 735 + ret = xdma_set_vector_reg(xdev, XDMA_IRQ_USER_VEC_NUM, 736 + user_irq_start, 737 + xdev->irq_num - user_irq_start); 738 + if (ret) { 739 + xdma_err(xdev, "failed to set user vectors: %d", ret); 740 + goto failed_init_c2h; 741 + } 742 + } 743 + 734 744 /* enable interrupt */ 735 745 ret = regmap_write(xdev->rmap, XDMA_IRQ_CHAN_INT_EN_W1S, ~0); 736 746 if (ret) ··· 767 753 768 754 return chan_info->dir == xdma_chan->dir; 769 755 } 756 + 757 + /** 758 + * xdma_disable_user_irq - Disable user interrupt 759 + * @pdev: Pointer to the platform_device structure 760 + * @irq_num: System IRQ number 761 + */ 762 + void xdma_disable_user_irq(struct platform_device *pdev, u32 irq_num) 763 + { 764 + struct xdma_device *xdev = platform_get_drvdata(pdev); 765 + u32 index; 766 + 767 + index = irq_num - xdev->irq_start; 768 + if (index < XDMA_CHAN_NUM(xdev) || index >= xdev->irq_num) { 769 + xdma_err(xdev, "invalid user irq number"); 770 + return; 771 + } 772 + index -= XDMA_CHAN_NUM(xdev); 773 + 774 + regmap_write(xdev->rmap, XDMA_IRQ_USER_INT_EN_W1C, 1 << index); 775 + } 776 + EXPORT_SYMBOL(xdma_disable_user_irq); 777 + 778 + /** 779 + * xdma_enable_user_irq - Enable user logic interrupt 780 + * @pdev: Pointer to the platform_device structure 781 + * @irq_num: System IRQ number 782 + */ 783 + int xdma_enable_user_irq(struct platform_device *pdev, u32 irq_num) 784 + { 785 + struct xdma_device *xdev = platform_get_drvdata(pdev); 786 + u32 index; 787 + int ret; 788 + 789 + index = irq_num - xdev->irq_start; 790 + if (index < XDMA_CHAN_NUM(xdev) || index >= xdev->irq_num) { 791 + xdma_err(xdev, "invalid user irq number"); 792 + return -EINVAL; 793 + } 794 + index -= XDMA_CHAN_NUM(xdev); 795 + 796 + ret = regmap_write(xdev->rmap, XDMA_IRQ_USER_INT_EN_W1S, 1 << index); 797 + if (ret) 798 + return ret; 799 + 800 + return 0; 801 + } 802 + EXPORT_SYMBOL(xdma_enable_user_irq); 803 + 804 + /** 805 + * xdma_get_user_irq - Get system IRQ number 806 + * @pdev: Pointer to the platform_device structure 807 + * @user_irq_index: User logic IRQ wire index 808 + * 809 + * Return: The system IRQ number allocated for the given wire index. 810 + */ 811 + int xdma_get_user_irq(struct platform_device *pdev, u32 user_irq_index) 812 + { 813 + struct xdma_device *xdev = platform_get_drvdata(pdev); 814 + 815 + if (XDMA_CHAN_NUM(xdev) + user_irq_index >= xdev->irq_num) { 816 + xdma_err(xdev, "invalid user irq index"); 817 + return -EINVAL; 818 + } 819 + 820 + return xdev->irq_start + XDMA_CHAN_NUM(xdev) + user_irq_index; 821 + } 822 + EXPORT_SYMBOL(xdma_get_user_irq); 770 823 771 824 /** 772 825 * xdma_remove - Driver remove function
+16
include/linux/dma/amd_xdma.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 + /* 3 + * Copyright (C) 2022, Advanced Micro Devices, Inc. 4 + */ 5 + 6 + #ifndef _DMAENGINE_AMD_XDMA_H 7 + #define _DMAENGINE_AMD_XDMA_H 8 + 9 + #include <linux/interrupt.h> 10 + #include <linux/platform_device.h> 11 + 12 + int xdma_enable_user_irq(struct platform_device *pdev, u32 irq_num); 13 + void xdma_disable_user_irq(struct platform_device *pdev, u32 irq_num); 14 + int xdma_get_user_irq(struct platform_device *pdev, u32 user_irq_index); 15 + 16 + #endif /* _DMAENGINE_AMD_XDMA_H */