dmaengine: dw: fix byte order of hw descriptor fields

If the DMA controller uses a different byte order than the host CPU,
the hardware linked list descriptor fields need to be byte-swapped.

This patch makes the driver write these fields using the same byte
order it uses for mmio accesses to the DMA engine. I do not know
if this is guaranteed to always be correct.

Signed-off-by: Mans Rullgard <mans@mansr.com>
Acked-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
这个提交包含在:
Mans Rullgard
2016-03-18 16:24:43 +02:00
提交者 Vinod Koul
父节点 bb3450ad0e
当前提交 df1f3a2305
修改 2 个文件,包含 85 行新增66 行删除

查看文件

@@ -308,26 +308,44 @@ static inline struct dw_dma *to_dw_dma(struct dma_device *ddev)
return container_of(ddev, struct dw_dma, dma);
}
#ifdef CONFIG_DW_DMAC_BIG_ENDIAN_IO
typedef __be32 __dw32;
#else
typedef __le32 __dw32;
#endif
/* LLI == Linked List Item; a.k.a. DMA block descriptor */
struct dw_lli {
/* values that are not changed by hardware */
u32 sar;
u32 dar;
u32 llp; /* chain to next lli */
u32 ctllo;
__dw32 sar;
__dw32 dar;
__dw32 llp; /* chain to next lli */
__dw32 ctllo;
/* values that may get written back: */
u32 ctlhi;
__dw32 ctlhi;
/* sstat and dstat can snapshot peripheral register state.
* silicon config may discard either or both...
*/
u32 sstat;
u32 dstat;
__dw32 sstat;
__dw32 dstat;
};
struct dw_desc {
/* FIRST values the hardware uses */
struct dw_lli lli;
#ifdef CONFIG_DW_DMAC_BIG_ENDIAN_IO
#define lli_set(d, reg, v) ((d)->lli.reg |= cpu_to_be32(v))
#define lli_clear(d, reg, v) ((d)->lli.reg &= ~cpu_to_be32(v))
#define lli_read(d, reg) be32_to_cpu((d)->lli.reg)
#define lli_write(d, reg, v) ((d)->lli.reg = cpu_to_be32(v))
#else
#define lli_set(d, reg, v) ((d)->lli.reg |= cpu_to_le32(v))
#define lli_clear(d, reg, v) ((d)->lli.reg &= ~cpu_to_le32(v))
#define lli_read(d, reg) le32_to_cpu((d)->lli.reg)
#define lli_write(d, reg, v) ((d)->lli.reg = cpu_to_le32(v))
#endif
/* THEN values for driver housekeeping */
struct list_head desc_node;
struct list_head tx_list;