summaryrefslogtreecommitdiff
path: root/drivers/dma/fsl-edma-common.h
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2024-03-15 22:25:13 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2024-03-15 22:25:13 +0300
commit2b3a4192dd01154bbb9f7c887c4b0fe35c9dc712 (patch)
tree1d207bf593c5c2112dd20b6345a0eadd43e23c7d /drivers/dma/fsl-edma-common.h
parentb898db92f10724420cb823c989adb1737fc046bb (diff)
parent716141d366f45d62ffe4dd53a045867b26e29d19 (diff)
downloadlinux-2b3a4192dd01154bbb9f7c887c4b0fe35c9dc712.tar.xz
Merge tag 'dmaengine-6.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine
Pull dmaengine updates from Vinod Koul: "New hardware support: - Allwinner H616 dma support - Renesas r8a779h0 dma controller support - TI CSI2RX dma support Updates: - Freescale edma driver updates for TCD64csupport for i.MX95 - constify of pointers and args - Yaml conversion for MediaTek High-Speed controller binding - TI k3 udma support for TX/RX DMA channels for thread IDs: * tag 'dmaengine-6.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine: (25 commits) dmaengine: of: constify of_phandle_args in of_dma_find_controller() dmaengine: pl08x: constify pointer to char in filter function MAINTAINERS: change in AMD ptdma maintainer MAINTAINERS: adjust file entry in MEDIATEK DMA DRIVER dmaengine: idxd: constify the struct device_type usage dt-bindings: renesas,rcar-dmac: Add r8a779h0 support dt-bindings: dma: convert MediaTek High-Speed controller to the json-schema dmaengine: idxd: make dsa_bus_type const dmaengine: fsl-edma: integrate TCD64 support for i.MX95 dt-bindings: fsl-dma: fsl-edma: add fsl,imx95-edma5 compatible string dmaengine: mcf-edma: utilize edma_write_tcdreg() macro for TCD Access dmaengine: fsl-edma: add address for channel mux register in fsl_edma_chan dmaengine: fsl-edma: fix spare build warning dmaengine: fsl-edma: involve help macro fsl_edma_set(get)_tcd() dt-bindings: mmp-dma: convert to YAML dmaengine: ti: k3-psil-j721s2: Add entry for CSI2RX dmaengine: ti: k3-udma-glue: Add function to request RX chan for thread ID dmaengine: ti: k3-udma-glue: Add function to request TX chan for thread ID dmaengine: ti: k3-udma-glue: Update name for remote RX channel device dmaengine: ti: k3-udma-glue: Add function to parse channel by ID ...
Diffstat (limited to 'drivers/dma/fsl-edma-common.h')
-rw-r--r--drivers/dma/fsl-edma-common.h161
1 files changed, 147 insertions, 14 deletions
diff --git a/drivers/dma/fsl-edma-common.h b/drivers/dma/fsl-edma-common.h
index f5e216b157c7..7bf0aba471a8 100644
--- a/drivers/dma/fsl-edma-common.h
+++ b/drivers/dma/fsl-edma-common.h
@@ -88,6 +88,20 @@ struct fsl_edma_hw_tcd {
__le16 biter;
};
+struct fsl_edma_hw_tcd64 {
+ __le64 saddr;
+ __le16 soff;
+ __le16 attr;
+ __le32 nbytes;
+ __le64 slast;
+ __le64 daddr;
+ __le64 dlast_sga;
+ __le16 doff;
+ __le16 citer;
+ __le16 csr;
+ __le16 biter;
+} __packed;
+
struct fsl_edma3_ch_reg {
__le32 ch_csr;
__le32 ch_es;
@@ -97,7 +111,10 @@ struct fsl_edma3_ch_reg {
__le32 ch_mux;
__le32 ch_mattr; /* edma4, reserved for edma3 */
__le32 ch_reserved;
- struct fsl_edma_hw_tcd tcd;
+ union {
+ struct fsl_edma_hw_tcd tcd;
+ struct fsl_edma_hw_tcd64 tcd64;
+ };
} __packed;
/*
@@ -126,7 +143,7 @@ struct edma_regs {
struct fsl_edma_sw_tcd {
dma_addr_t ptcd;
- struct fsl_edma_hw_tcd *vtcd;
+ void *vtcd;
};
struct fsl_edma_chan {
@@ -145,7 +162,8 @@ struct fsl_edma_chan {
u32 dma_dev_size;
enum dma_data_direction dma_dir;
char chan_name[32];
- struct fsl_edma_hw_tcd __iomem *tcd;
+ void __iomem *tcd;
+ void __iomem *mux_addr;
u32 real_count;
struct work_struct issue_worker;
struct platform_device *pdev;
@@ -188,6 +206,7 @@ struct fsl_edma_desc {
#define FSL_EDMA_DRV_CLEAR_DONE_E_SG BIT(13)
/* Need clean CHn_CSR DONE before enable TCD's MAJORELINK */
#define FSL_EDMA_DRV_CLEAR_DONE_E_LINK BIT(14)
+#define FSL_EDMA_DRV_TCD64 BIT(15)
#define FSL_EDMA_DRV_EDMA3 (FSL_EDMA_DRV_SPLIT_REG | \
FSL_EDMA_DRV_BUS_8BYTE | \
@@ -207,6 +226,8 @@ struct fsl_edma_drvdata {
u32 chreg_off;
u32 chreg_space_sz;
u32 flags;
+ u32 mux_off; /* channel mux register offset */
+ u32 mux_skip; /* how much skip for each channel */
int (*setup_irq)(struct platform_device *pdev,
struct fsl_edma_engine *fsl_edma);
};
@@ -229,23 +250,108 @@ struct fsl_edma_engine {
struct fsl_edma_chan chans[] __counted_by(n_chans);
};
-#define edma_read_tcdreg(chan, __name) \
-(sizeof(chan->tcd->__name) == sizeof(u32) ? \
- edma_readl(chan->edma, &chan->tcd->__name) : \
- edma_readw(chan->edma, &chan->tcd->__name))
-
-#define edma_write_tcdreg(chan, val, __name) \
-(sizeof(chan->tcd->__name) == sizeof(u32) ? \
- edma_writel(chan->edma, (u32 __force)val, &chan->tcd->__name) : \
- edma_writew(chan->edma, (u16 __force)val, &chan->tcd->__name))
+#define edma_read_tcdreg_c(chan, _tcd, __name) \
+(sizeof((_tcd)->__name) == sizeof(u64) ? \
+ edma_readq(chan->edma, &(_tcd)->__name) : \
+ ((sizeof((_tcd)->__name) == sizeof(u32)) ? \
+ edma_readl(chan->edma, &(_tcd)->__name) : \
+ edma_readw(chan->edma, &(_tcd)->__name) \
+ ))
+
+#define edma_read_tcdreg(chan, __name) \
+((fsl_edma_drvflags(chan) & FSL_EDMA_DRV_TCD64) ? \
+ edma_read_tcdreg_c(chan, ((struct fsl_edma_hw_tcd64 __iomem *)chan->tcd), __name) : \
+ edma_read_tcdreg_c(chan, ((struct fsl_edma_hw_tcd __iomem *)chan->tcd), __name) \
+)
+
+#define edma_write_tcdreg_c(chan, _tcd, _val, __name) \
+do { \
+ switch (sizeof(_tcd->__name)) { \
+ case sizeof(u64): \
+ edma_writeq(chan->edma, (u64 __force)_val, &_tcd->__name); \
+ break; \
+ case sizeof(u32): \
+ edma_writel(chan->edma, (u32 __force)_val, &_tcd->__name); \
+ break; \
+ case sizeof(u16): \
+ edma_writew(chan->edma, (u16 __force)_val, &_tcd->__name); \
+ break; \
+ case sizeof(u8): \
+ edma_writeb(chan->edma, (u8 __force)_val, &_tcd->__name); \
+ break; \
+ } \
+} while (0)
+
+#define edma_write_tcdreg(chan, val, __name) \
+do { \
+ struct fsl_edma_hw_tcd64 __iomem *tcd64_r = (struct fsl_edma_hw_tcd64 __iomem *)chan->tcd; \
+ struct fsl_edma_hw_tcd __iomem *tcd_r = (struct fsl_edma_hw_tcd __iomem *)chan->tcd; \
+ \
+ if (fsl_edma_drvflags(chan) & FSL_EDMA_DRV_TCD64) \
+ edma_write_tcdreg_c(chan, tcd64_r, val, __name); \
+ else \
+ edma_write_tcdreg_c(chan, tcd_r, val, __name); \
+} while (0)
+
+#define edma_cp_tcd_to_reg(chan, __tcd, __name) \
+do { \
+ struct fsl_edma_hw_tcd64 __iomem *tcd64_r = (struct fsl_edma_hw_tcd64 __iomem *)chan->tcd; \
+ struct fsl_edma_hw_tcd __iomem *tcd_r = (struct fsl_edma_hw_tcd __iomem *)chan->tcd; \
+ struct fsl_edma_hw_tcd64 *tcd64_m = (struct fsl_edma_hw_tcd64 *)__tcd; \
+ struct fsl_edma_hw_tcd *tcd_m = (struct fsl_edma_hw_tcd *)__tcd; \
+ \
+ if (fsl_edma_drvflags(chan) & FSL_EDMA_DRV_TCD64) \
+ edma_write_tcdreg_c(chan, tcd64_r, tcd64_m->__name, __name); \
+ else \
+ edma_write_tcdreg_c(chan, tcd_r, tcd_m->__name, __name); \
+} while (0)
#define edma_readl_chreg(chan, __name) \
edma_readl(chan->edma, \
- (void __iomem *)&(container_of(chan->tcd, struct fsl_edma3_ch_reg, tcd)->__name))
+ (void __iomem *)&(container_of(((__force void *)chan->tcd),\
+ struct fsl_edma3_ch_reg, tcd)->__name))
#define edma_writel_chreg(chan, val, __name) \
edma_writel(chan->edma, val, \
- (void __iomem *)&(container_of(chan->tcd, struct fsl_edma3_ch_reg, tcd)->__name))
+ (void __iomem *)&(container_of(((__force void *)chan->tcd),\
+ struct fsl_edma3_ch_reg, tcd)->__name))
+
+#define fsl_edma_get_tcd(_chan, _tcd, _field) \
+(fsl_edma_drvflags(_chan) & FSL_EDMA_DRV_TCD64 ? (((struct fsl_edma_hw_tcd64 *)_tcd)->_field) : \
+ (((struct fsl_edma_hw_tcd *)_tcd)->_field))
+
+#define fsl_edma_le_to_cpu(x) \
+(sizeof(x) == sizeof(u64) ? le64_to_cpu((__force __le64)(x)) : \
+ (sizeof(x) == sizeof(u32) ? le32_to_cpu((__force __le32)(x)) : \
+ le16_to_cpu((__force __le16)(x))))
+
+#define fsl_edma_get_tcd_to_cpu(_chan, _tcd, _field) \
+(fsl_edma_drvflags(_chan) & FSL_EDMA_DRV_TCD64 ? \
+ fsl_edma_le_to_cpu(((struct fsl_edma_hw_tcd64 *)_tcd)->_field) : \
+ fsl_edma_le_to_cpu(((struct fsl_edma_hw_tcd *)_tcd)->_field))
+
+#define fsl_edma_set_tcd_to_le_c(_tcd, _val, _field) \
+do { \
+ switch (sizeof((_tcd)->_field)) { \
+ case sizeof(u64): \
+ *(__force __le64 *)(&((_tcd)->_field)) = cpu_to_le64(_val); \
+ break; \
+ case sizeof(u32): \
+ *(__force __le32 *)(&((_tcd)->_field)) = cpu_to_le32(_val); \
+ break; \
+ case sizeof(u16): \
+ *(__force __le16 *)(&((_tcd)->_field)) = cpu_to_le16(_val); \
+ break; \
+ } \
+} while (0)
+
+#define fsl_edma_set_tcd_to_le(_chan, _tcd, _val, _field) \
+do { \
+ if (fsl_edma_drvflags(_chan) & FSL_EDMA_DRV_TCD64) \
+ fsl_edma_set_tcd_to_le_c((struct fsl_edma_hw_tcd64 *)_tcd, _val, _field); \
+ else \
+ fsl_edma_set_tcd_to_le_c((struct fsl_edma_hw_tcd *)_tcd, _val, _field); \
+} while (0)
/*
* R/W functions for big- or little-endian registers:
@@ -253,6 +359,21 @@ struct fsl_edma_engine {
* For the big-endian IP module, the offset for 8-bit or 16-bit registers
* should also be swapped opposite to that in little-endian IP.
*/
+static inline u64 edma_readq(struct fsl_edma_engine *edma, void __iomem *addr)
+{
+ u64 l, h;
+
+ if (edma->big_endian) {
+ l = ioread32be(addr);
+ h = ioread32be(addr + 4);
+ } else {
+ l = ioread32(addr);
+ h = ioread32(addr + 4);
+ }
+
+ return (h << 32) | l;
+}
+
static inline u32 edma_readl(struct fsl_edma_engine *edma, void __iomem *addr)
{
if (edma->big_endian)
@@ -298,6 +419,18 @@ static inline void edma_writel(struct fsl_edma_engine *edma,
iowrite32(val, addr);
}
+static inline void edma_writeq(struct fsl_edma_engine *edma,
+ u64 val, void __iomem *addr)
+{
+ if (edma->big_endian) {
+ iowrite32be(val & 0xFFFFFFFF, addr);
+ iowrite32be(val >> 32, addr + 4);
+ } else {
+ iowrite32(val & 0xFFFFFFFF, addr);
+ iowrite32(val >> 32, addr + 4);
+ }
+}
+
static inline struct fsl_edma_chan *to_fsl_edma_chan(struct dma_chan *chan)
{
return container_of(chan, struct fsl_edma_chan, vchan.chan);