mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-30 08:02:30 +00:00
e74c39573d
Add support for HDMA NATIVE, as long the IP design has set the compatible register map parameter-HDMA_NATIVE, which allows compatibility for native HDMA register configuration. The HDMA Hyper-DMA IP is an enhancement of the eDMA embedded-DMA IP. And the native HDMA registers are different from eDMA, so this patch add support for HDMA NATIVE mode. HDMA write and read channels operate independently to maximize the performance of the HDMA read and write data transfer over the link When you configure the HDMA with multiple read channels, then it uses a round robin (RR) arbitration scheme to select the next read channel to be serviced.The same applies when you have multiple write channels. The native HDMA driver also supports a maximum of 16 independent channels (8 write + 8 read), which can run simultaneously. Both SAR (Source Address Register) and DAR (Destination Address Register) are aligned to byte. Signed-off-by: Cai Huoqing <cai.huoqing@linux.dev> Reviewed-by: Serge Semin <fancer.lancer@gmail.com> Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> Tested-by: Serge Semin <fancer.lancer@gmail.com> Link: https://lore.kernel.org/r/20230520050854.73160-4-cai.huoqing@linux.dev Signed-off-by: Vinod Koul <vkoul@kernel.org>
120 lines
3.2 KiB
C
120 lines
3.2 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/*
|
|
* Copyright (c) 2018-2019 Synopsys, Inc. and/or its affiliates.
|
|
* Synopsys DesignWare eDMA core driver
|
|
*
|
|
* Author: Gustavo Pimentel <gustavo.pimentel@synopsys.com>
|
|
*/
|
|
|
|
#ifndef _DW_EDMA_H
|
|
#define _DW_EDMA_H
|
|
|
|
#include <linux/device.h>
|
|
#include <linux/dmaengine.h>
|
|
|
|
#define EDMA_MAX_WR_CH 8
|
|
#define EDMA_MAX_RD_CH 8
|
|
|
|
struct dw_edma;
|
|
|
|
struct dw_edma_region {
|
|
u64 paddr;
|
|
union {
|
|
void *mem;
|
|
void __iomem *io;
|
|
} vaddr;
|
|
size_t sz;
|
|
};
|
|
|
|
/**
|
|
* struct dw_edma_core_ops - platform-specific eDMA methods
|
|
* @irq_vector: Get IRQ number of the passed eDMA channel. Note the
|
|
* method accepts the channel id in the end-to-end
|
|
* numbering with the eDMA write channels being placed
|
|
* first in the row.
|
|
* @pci_address: Get PCIe bus address corresponding to the passed CPU
|
|
* address. Note there is no need in specifying this
|
|
* function if the address translation is performed by
|
|
* the DW PCIe RP/EP controller with the DW eDMA device in
|
|
* subject and DMA_BYPASS isn't set for all the outbound
|
|
* iATU windows. That will be done by the controller
|
|
* automatically.
|
|
*/
|
|
struct dw_edma_plat_ops {
|
|
int (*irq_vector)(struct device *dev, unsigned int nr);
|
|
u64 (*pci_address)(struct device *dev, phys_addr_t cpu_addr);
|
|
};
|
|
|
|
enum dw_edma_map_format {
|
|
EDMA_MF_EDMA_LEGACY = 0x0,
|
|
EDMA_MF_EDMA_UNROLL = 0x1,
|
|
EDMA_MF_HDMA_COMPAT = 0x5,
|
|
EDMA_MF_HDMA_NATIVE = 0x7,
|
|
};
|
|
|
|
/**
|
|
* enum dw_edma_chip_flags - Flags specific to an eDMA chip
|
|
* @DW_EDMA_CHIP_LOCAL: eDMA is used locally by an endpoint
|
|
*/
|
|
enum dw_edma_chip_flags {
|
|
DW_EDMA_CHIP_LOCAL = BIT(0),
|
|
};
|
|
|
|
/**
|
|
* struct dw_edma_chip - representation of DesignWare eDMA controller hardware
|
|
* @dev: struct device of the eDMA controller
|
|
* @id: instance ID
|
|
* @nr_irqs: total number of DMA IRQs
|
|
* @ops DMA channel to IRQ number mapping
|
|
* @flags dw_edma_chip_flags
|
|
* @reg_base DMA register base address
|
|
* @ll_wr_cnt DMA write link list count
|
|
* @ll_rd_cnt DMA read link list count
|
|
* @rg_region DMA register region
|
|
* @ll_region_wr DMA descriptor link list memory for write channel
|
|
* @ll_region_rd DMA descriptor link list memory for read channel
|
|
* @dt_region_wr DMA data memory for write channel
|
|
* @dt_region_rd DMA data memory for read channel
|
|
* @mf DMA register map format
|
|
* @dw: struct dw_edma that is filled by dw_edma_probe()
|
|
*/
|
|
struct dw_edma_chip {
|
|
struct device *dev;
|
|
int nr_irqs;
|
|
const struct dw_edma_plat_ops *ops;
|
|
u32 flags;
|
|
|
|
void __iomem *reg_base;
|
|
|
|
u16 ll_wr_cnt;
|
|
u16 ll_rd_cnt;
|
|
/* link list address */
|
|
struct dw_edma_region ll_region_wr[EDMA_MAX_WR_CH];
|
|
struct dw_edma_region ll_region_rd[EDMA_MAX_RD_CH];
|
|
|
|
/* data region */
|
|
struct dw_edma_region dt_region_wr[EDMA_MAX_WR_CH];
|
|
struct dw_edma_region dt_region_rd[EDMA_MAX_RD_CH];
|
|
|
|
enum dw_edma_map_format mf;
|
|
|
|
struct dw_edma *dw;
|
|
};
|
|
|
|
/* Export to the platform drivers */
|
|
#if IS_REACHABLE(CONFIG_DW_EDMA)
|
|
int dw_edma_probe(struct dw_edma_chip *chip);
|
|
int dw_edma_remove(struct dw_edma_chip *chip);
|
|
#else
|
|
static inline int dw_edma_probe(struct dw_edma_chip *chip)
|
|
{
|
|
return -ENODEV;
|
|
}
|
|
|
|
static inline int dw_edma_remove(struct dw_edma_chip *chip)
|
|
{
|
|
return 0;
|
|
}
|
|
#endif /* CONFIG_DW_EDMA */
|
|
|
|
#endif /* _DW_EDMA_H */
|