root/include/linux/dma/edma.h
/* 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_plat_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
 * @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
 * @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 */