305 lines · c
1/* SPDX-License-Identifier: GPL-2.0-only */2/*3 * Driver for the TXx9 SoC DMA Controller4 *5 * Copyright (C) 2009 Atsushi Nemoto6 */7#ifndef TXX9DMAC_H8#define TXX9DMAC_H9 10#include <linux/dmaengine.h>11#include <asm/txx9/dmac.h>12 13/*14 * Design Notes:15 *16 * This DMAC have four channels and one FIFO buffer. Each channel can17 * be configured for memory-memory or device-memory transfer, but only18 * one channel can do alignment-free memory-memory transfer at a time19 * while the channel should occupy the FIFO buffer for effective20 * transfers.21 *22 * Instead of dynamically assign the FIFO buffer to channels, I chose23 * make one dedicated channel for memory-memory transfer. The24 * dedicated channel is public. Other channels are private and used25 * for slave transfer. Some devices in the SoC are wired to certain26 * DMA channel.27 */28 29#ifdef CONFIG_MACH_TX49XX30static inline bool txx9_dma_have_SMPCHN(void)31{32 return true;33}34#define TXX9_DMA_USE_SIMPLE_CHAIN35#else36static inline bool txx9_dma_have_SMPCHN(void)37{38 return false;39}40#endif41 42#ifdef __LITTLE_ENDIAN43#ifdef CONFIG_MACH_TX49XX44#define CCR_LE TXX9_DMA_CCR_LE45#define MCR_LE 046#else47#define CCR_LE 048#define MCR_LE TXX9_DMA_MCR_LE49#endif50#else51#define CCR_LE 052#define MCR_LE 053#endif54 55/*56 * Redefine this macro to handle differences between 32- and 64-bit57 * addressing, big vs. little endian, etc.58 */59#ifdef __BIG_ENDIAN60#define TXX9_DMA_REG32(name) u32 __pad_##name; u32 name61#else62#define TXX9_DMA_REG32(name) u32 name; u32 __pad_##name63#endif64 65/* Hardware register definitions. */66struct txx9dmac_cregs {67#if defined(CONFIG_32BIT) && !defined(CONFIG_PHYS_ADDR_T_64BIT)68 TXX9_DMA_REG32(CHAR); /* Chain Address Register */69#else70 u64 CHAR; /* Chain Address Register */71#endif72 u64 SAR; /* Source Address Register */73 u64 DAR; /* Destination Address Register */74 TXX9_DMA_REG32(CNTR); /* Count Register */75 TXX9_DMA_REG32(SAIR); /* Source Address Increment Register */76 TXX9_DMA_REG32(DAIR); /* Destination Address Increment Register */77 TXX9_DMA_REG32(CCR); /* Channel Control Register */78 TXX9_DMA_REG32(CSR); /* Channel Status Register */79};80struct txx9dmac_cregs32 {81 u32 CHAR;82 u32 SAR;83 u32 DAR;84 u32 CNTR;85 u32 SAIR;86 u32 DAIR;87 u32 CCR;88 u32 CSR;89};90 91struct txx9dmac_regs {92 /* per-channel registers */93 struct txx9dmac_cregs CHAN[TXX9_DMA_MAX_NR_CHANNELS];94 u64 __pad[9];95 u64 MFDR; /* Memory Fill Data Register */96 TXX9_DMA_REG32(MCR); /* Master Control Register */97};98struct txx9dmac_regs32 {99 struct txx9dmac_cregs32 CHAN[TXX9_DMA_MAX_NR_CHANNELS];100 u32 __pad[9];101 u32 MFDR;102 u32 MCR;103};104 105/* bits for MCR */106#define TXX9_DMA_MCR_EIS(ch) (0x10000000<<(ch))107#define TXX9_DMA_MCR_DIS(ch) (0x01000000<<(ch))108#define TXX9_DMA_MCR_RSFIF 0x00000080109#define TXX9_DMA_MCR_FIFUM(ch) (0x00000008<<(ch))110#define TXX9_DMA_MCR_LE 0x00000004111#define TXX9_DMA_MCR_RPRT 0x00000002112#define TXX9_DMA_MCR_MSTEN 0x00000001113 114/* bits for CCRn */115#define TXX9_DMA_CCR_IMMCHN 0x20000000116#define TXX9_DMA_CCR_USEXFSZ 0x10000000117#define TXX9_DMA_CCR_LE 0x08000000118#define TXX9_DMA_CCR_DBINH 0x04000000119#define TXX9_DMA_CCR_SBINH 0x02000000120#define TXX9_DMA_CCR_CHRST 0x01000000121#define TXX9_DMA_CCR_RVBYTE 0x00800000122#define TXX9_DMA_CCR_ACKPOL 0x00400000123#define TXX9_DMA_CCR_REQPL 0x00200000124#define TXX9_DMA_CCR_EGREQ 0x00100000125#define TXX9_DMA_CCR_CHDN 0x00080000126#define TXX9_DMA_CCR_DNCTL 0x00060000127#define TXX9_DMA_CCR_EXTRQ 0x00010000128#define TXX9_DMA_CCR_INTRQD 0x0000e000129#define TXX9_DMA_CCR_INTENE 0x00001000130#define TXX9_DMA_CCR_INTENC 0x00000800131#define TXX9_DMA_CCR_INTENT 0x00000400132#define TXX9_DMA_CCR_CHNEN 0x00000200133#define TXX9_DMA_CCR_XFACT 0x00000100134#define TXX9_DMA_CCR_SMPCHN 0x00000020135#define TXX9_DMA_CCR_XFSZ(order) (((order) << 2) & 0x0000001c)136#define TXX9_DMA_CCR_XFSZ_1 TXX9_DMA_CCR_XFSZ(0)137#define TXX9_DMA_CCR_XFSZ_2 TXX9_DMA_CCR_XFSZ(1)138#define TXX9_DMA_CCR_XFSZ_4 TXX9_DMA_CCR_XFSZ(2)139#define TXX9_DMA_CCR_XFSZ_8 TXX9_DMA_CCR_XFSZ(3)140#define TXX9_DMA_CCR_XFSZ_X4 TXX9_DMA_CCR_XFSZ(4)141#define TXX9_DMA_CCR_XFSZ_X8 TXX9_DMA_CCR_XFSZ(5)142#define TXX9_DMA_CCR_XFSZ_X16 TXX9_DMA_CCR_XFSZ(6)143#define TXX9_DMA_CCR_XFSZ_X32 TXX9_DMA_CCR_XFSZ(7)144#define TXX9_DMA_CCR_MEMIO 0x00000002145#define TXX9_DMA_CCR_SNGAD 0x00000001146 147/* bits for CSRn */148#define TXX9_DMA_CSR_CHNEN 0x00000400149#define TXX9_DMA_CSR_STLXFER 0x00000200150#define TXX9_DMA_CSR_XFACT 0x00000100151#define TXX9_DMA_CSR_ABCHC 0x00000080152#define TXX9_DMA_CSR_NCHNC 0x00000040153#define TXX9_DMA_CSR_NTRNFC 0x00000020154#define TXX9_DMA_CSR_EXTDN 0x00000010155#define TXX9_DMA_CSR_CFERR 0x00000008156#define TXX9_DMA_CSR_CHERR 0x00000004157#define TXX9_DMA_CSR_DESERR 0x00000002158#define TXX9_DMA_CSR_SORERR 0x00000001159 160struct txx9dmac_chan {161 struct dma_chan chan;162 struct dma_device dma;163 struct txx9dmac_dev *ddev;164 void __iomem *ch_regs;165 struct tasklet_struct tasklet;166 int irq;167 u32 ccr;168 169 spinlock_t lock;170 171 /* these other elements are all protected by lock */172 struct list_head active_list;173 struct list_head queue;174 struct list_head free_list;175 176 unsigned int descs_allocated;177};178 179struct txx9dmac_dev {180 void __iomem *regs;181 struct tasklet_struct tasklet;182 int irq;183 struct txx9dmac_chan *chan[TXX9_DMA_MAX_NR_CHANNELS];184 bool have_64bit_regs;185 unsigned int descsize;186};187 188static inline bool __is_dmac64(const struct txx9dmac_dev *ddev)189{190 return ddev->have_64bit_regs;191}192 193static inline bool is_dmac64(const struct txx9dmac_chan *dc)194{195 return __is_dmac64(dc->ddev);196}197 198#ifdef TXX9_DMA_USE_SIMPLE_CHAIN199/* Hardware descriptor definition. (for simple-chain) */200struct txx9dmac_hwdesc {201#if defined(CONFIG_32BIT) && !defined(CONFIG_PHYS_ADDR_T_64BIT)202 TXX9_DMA_REG32(CHAR);203#else204 u64 CHAR;205#endif206 u64 SAR;207 u64 DAR;208 TXX9_DMA_REG32(CNTR);209};210struct txx9dmac_hwdesc32 {211 u32 CHAR;212 u32 SAR;213 u32 DAR;214 u32 CNTR;215};216#else217#define txx9dmac_hwdesc txx9dmac_cregs218#define txx9dmac_hwdesc32 txx9dmac_cregs32219#endif220 221struct txx9dmac_desc {222 /* FIRST values the hardware uses */223 union {224 struct txx9dmac_hwdesc hwdesc;225 struct txx9dmac_hwdesc32 hwdesc32;226 };227 228 /* THEN values for driver housekeeping */229 struct list_head desc_node ____cacheline_aligned;230 struct list_head tx_list;231 struct dma_async_tx_descriptor txd;232 size_t len;233};234 235#ifdef TXX9_DMA_USE_SIMPLE_CHAIN236 237static inline bool txx9dmac_chan_INTENT(struct txx9dmac_chan *dc)238{239 return (dc->ccr & TXX9_DMA_CCR_INTENT) != 0;240}241 242static inline void txx9dmac_chan_set_INTENT(struct txx9dmac_chan *dc)243{244 dc->ccr |= TXX9_DMA_CCR_INTENT;245}246 247static inline void txx9dmac_desc_set_INTENT(struct txx9dmac_dev *ddev,248 struct txx9dmac_desc *desc)249{250}251 252static inline void txx9dmac_chan_set_SMPCHN(struct txx9dmac_chan *dc)253{254 dc->ccr |= TXX9_DMA_CCR_SMPCHN;255}256 257static inline void txx9dmac_desc_set_nosimple(struct txx9dmac_dev *ddev,258 struct txx9dmac_desc *desc,259 u32 sair, u32 dair, u32 ccr)260{261}262 263#else /* TXX9_DMA_USE_SIMPLE_CHAIN */264 265static inline bool txx9dmac_chan_INTENT(struct txx9dmac_chan *dc)266{267 return true;268}269 270static void txx9dmac_chan_set_INTENT(struct txx9dmac_chan *dc)271{272}273 274static inline void txx9dmac_desc_set_INTENT(struct txx9dmac_dev *ddev,275 struct txx9dmac_desc *desc)276{277 if (__is_dmac64(ddev))278 desc->hwdesc.CCR |= TXX9_DMA_CCR_INTENT;279 else280 desc->hwdesc32.CCR |= TXX9_DMA_CCR_INTENT;281}282 283static inline void txx9dmac_chan_set_SMPCHN(struct txx9dmac_chan *dc)284{285}286 287static inline void txx9dmac_desc_set_nosimple(struct txx9dmac_dev *ddev,288 struct txx9dmac_desc *desc,289 u32 sai, u32 dai, u32 ccr)290{291 if (__is_dmac64(ddev)) {292 desc->hwdesc.SAIR = sai;293 desc->hwdesc.DAIR = dai;294 desc->hwdesc.CCR = ccr;295 } else {296 desc->hwdesc32.SAIR = sai;297 desc->hwdesc32.DAIR = dai;298 desc->hwdesc32.CCR = ccr;299 }300}301 302#endif /* TXX9_DMA_USE_SIMPLE_CHAIN */303 304#endif /* TXX9DMAC_H */305