Skip to content

Commit

Permalink
dmaengine: xilinx: xdma: Add user logic interrupt support
Browse files Browse the repository at this point in the history
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 register/unregister interrupt handler 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>
  • Loading branch information
houlz0507 committed Sep 21, 2022
1 parent 9c3de69 commit 4f24f17
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 0 deletions.
84 changes: 84 additions & 0 deletions drivers/dma/xilinx/xdma.c
Expand Up @@ -742,6 +742,7 @@ static int xdma_set_vector_reg(struct xdma_device *xdev, u32 vec_tbl_start,
static int xdma_irq_init(struct xdma_device *xdev)
{
u32 irq = xdev->irq_start;
u32 user_irq_start;
int i, j, ret;

/* return failure if there are not enough IRQs */
Expand Down Expand Up @@ -795,6 +796,18 @@ static int xdma_irq_init(struct xdma_device *xdev)
goto failed;
}

/* config user IRQ registers if needed */
user_irq_start = xdev->h2c_chan_num + xdev->c2h_chan_num;
if (xdev->irq_num > user_irq_start) {
ret = xdma_set_vector_reg(xdev, XDMA_IRQ_USER_VEC_NUM,
user_irq_start,
xdev->irq_num - user_irq_start);
if (ret) {
xdma_err(xdev, "failed to set user vectors: %d", ret);
goto failed;
}
}

/* enable interrupt */
ret = xdma_enable_intr(xdev);
if (ret) {
Expand Down Expand Up @@ -826,6 +839,77 @@ static bool xdma_filter_fn(struct dma_chan *chan, void *param)
return true;
}

/**
* xdma_free_user_irq - Free user interrupt
* @pdev: Pointer to the platform_device structure
* @user_irq_index: User IRQ index
* @arg: User interrupt cookie
*/
void xdma_free_user_irq(struct platform_device *pdev, u32 user_irq_index,
void *arg)
{
struct xdma_device *xdev = platform_get_drvdata(pdev);
u32 user_irq;
int ret;

user_irq = xdev->h2c_chan_num + xdev->c2h_chan_num + user_irq_index;
if (user_irq >= xdev->irq_num) {
xdma_err(xdev, "invalid user irq index");
return;
}
user_irq += xdev->irq_start;

ret = xdma_write_reg(xdev, XDMA_IRQ_BASE, XDMA_IRQ_USER_INT_EN_W1C,
(1 << user_irq_index));
if (ret) {
xdma_err(xdev, "clear user irq mask failed, %d", ret);
return;
}

free_irq(user_irq, arg);
}
EXPORT_SYMBOL(xdma_free_user_irq);

/**
* xdma_request_user_irq - Register user interrupt
* @pdev: Pointer to the platform_device structure
* @user_irq_index: User IRQ index
* @flags: Handling flags
* @handler: User interrupt handler
* @arg: User interrupt cookie
*/
int xdma_request_user_irq(struct platform_device *pdev, u32 user_irq_index,
irq_handler_t handler, void *arg, ulong flags)
{
struct xdma_device *xdev = platform_get_drvdata(pdev);
u32 user_irq;
int ret;

user_irq = xdev->h2c_chan_num + xdev->c2h_chan_num + user_irq_index;
if (user_irq >= xdev->irq_num) {
xdma_err(xdev, "invalid user irq index");
return -EINVAL;
}
user_irq += xdev->irq_start;

ret = request_irq(user_irq, handler, flags, "xdma-user", arg);
if (ret) {
xdma_err(xdev, "request irq failed, %d", ret);
return ret;
}

ret = xdma_write_reg(xdev, XDMA_IRQ_BASE, XDMA_IRQ_USER_INT_EN_W1S,
(1 << user_irq_index));
if (ret) {
xdma_err(xdev, "set user irq mask failed, %d", ret);
free_irq(user_irq, arg);
return ret;
}

return 0;
}
EXPORT_SYMBOL(xdma_request_user_irq);

/**
* xdma_remove - Driver remove function
* @pdev: Pointer to the platform_device structure
Expand Down
17 changes: 17 additions & 0 deletions include/linux/dma/amd_xdma.h
@@ -0,0 +1,17 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (C) 2022 Advanced Micro Devices, Inc. All rights reserved.
*/

#ifndef _DMAENGINE_AMD_XDMA_H
#define _DMAENGINE_AMD_XDMA_H

#include <linux/interrupt.h>
#include <linux/platform_device.h>

int xdma_request_user_irq(struct platform_device *pdev, u32 user_irq_index,
irq_handler_t handler, void *arg, ulong flags);
void xdma_free_user_irq(struct platform_device *pdev, u32 user_irq_index,
void *arg);

#endif /* _DMAENGINE_AMD_XDMA_H */

0 comments on commit 4f24f17

Please sign in to comment.