162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * 2006-2009 (C) DENX Software Engineering.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Author: Yuri Tikhonov <yur@emcraft.com>
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#ifndef _PPC440SPE_ADMA_H
962306a36Sopenharmony_ci#define _PPC440SPE_ADMA_H
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include <linux/types.h>
1262306a36Sopenharmony_ci#include "dma.h"
1362306a36Sopenharmony_ci#include "xor.h"
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#define to_ppc440spe_adma_chan(chan) \
1662306a36Sopenharmony_ci		container_of(chan, struct ppc440spe_adma_chan, common)
1762306a36Sopenharmony_ci#define to_ppc440spe_adma_device(dev) \
1862306a36Sopenharmony_ci		container_of(dev, struct ppc440spe_adma_device, common)
1962306a36Sopenharmony_ci#define tx_to_ppc440spe_adma_slot(tx) \
2062306a36Sopenharmony_ci		container_of(tx, struct ppc440spe_adma_desc_slot, async_tx)
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci/* Default polynomial (for 440SP is only available) */
2362306a36Sopenharmony_ci#define PPC440SPE_DEFAULT_POLY	0x4d
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci#define PPC440SPE_ADMA_ENGINES_NUM	(XOR_ENGINES_NUM + DMA_ENGINES_NUM)
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci#define PPC440SPE_ADMA_WATCHDOG_MSEC	3
2862306a36Sopenharmony_ci#define PPC440SPE_ADMA_THRESHOLD	1
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci#define PPC440SPE_DMA0_ID	0
3162306a36Sopenharmony_ci#define PPC440SPE_DMA1_ID	1
3262306a36Sopenharmony_ci#define PPC440SPE_XOR_ID	2
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci#define PPC440SPE_ADMA_DMA_MAX_BYTE_COUNT	0xFFFFFFUL
3562306a36Sopenharmony_ci/* this is the XOR_CBBCR width */
3662306a36Sopenharmony_ci#define PPC440SPE_ADMA_XOR_MAX_BYTE_COUNT	(1 << 31)
3762306a36Sopenharmony_ci#define PPC440SPE_ADMA_ZERO_SUM_MAX_BYTE_COUNT PPC440SPE_ADMA_XOR_MAX_BYTE_COUNT
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci#define PPC440SPE_RXOR_RUN	0
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci#define MQ0_CF2H_RXOR_BS_MASK	0x1FF
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci#undef ADMA_LL_DEBUG
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci/**
4662306a36Sopenharmony_ci * struct ppc440spe_adma_device - internal representation of an ADMA device
4762306a36Sopenharmony_ci * @dev: device
4862306a36Sopenharmony_ci * @dma_reg: base for DMAx register access
4962306a36Sopenharmony_ci * @xor_reg: base for XOR register access
5062306a36Sopenharmony_ci * @i2o_reg: base for I2O register access
5162306a36Sopenharmony_ci * @id: HW ADMA Device selector
5262306a36Sopenharmony_ci * @dma_desc_pool_virt: base of DMA descriptor region (CPU address)
5362306a36Sopenharmony_ci * @dma_desc_pool: base of DMA descriptor region (DMA address)
5462306a36Sopenharmony_ci * @pool_size: size of the pool
5562306a36Sopenharmony_ci * @irq: DMAx or XOR irq number
5662306a36Sopenharmony_ci * @err_irq: DMAx error irq number
5762306a36Sopenharmony_ci * @common: embedded struct dma_device
5862306a36Sopenharmony_ci */
5962306a36Sopenharmony_cistruct ppc440spe_adma_device {
6062306a36Sopenharmony_ci	struct device *dev;
6162306a36Sopenharmony_ci	struct dma_regs __iomem *dma_reg;
6262306a36Sopenharmony_ci	struct xor_regs __iomem *xor_reg;
6362306a36Sopenharmony_ci	struct i2o_regs __iomem *i2o_reg;
6462306a36Sopenharmony_ci	int id;
6562306a36Sopenharmony_ci	void *dma_desc_pool_virt;
6662306a36Sopenharmony_ci	dma_addr_t dma_desc_pool;
6762306a36Sopenharmony_ci	size_t pool_size;
6862306a36Sopenharmony_ci	int irq;
6962306a36Sopenharmony_ci	int err_irq;
7062306a36Sopenharmony_ci	struct dma_device common;
7162306a36Sopenharmony_ci};
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci/**
7462306a36Sopenharmony_ci * struct ppc440spe_adma_chan - internal representation of an ADMA channel
7562306a36Sopenharmony_ci * @lock: serializes enqueue/dequeue operations to the slot pool
7662306a36Sopenharmony_ci * @device: parent device
7762306a36Sopenharmony_ci * @chain: device chain view of the descriptors
7862306a36Sopenharmony_ci * @common: common dmaengine channel object members
7962306a36Sopenharmony_ci * @all_slots: complete domain of slots usable by the channel
8062306a36Sopenharmony_ci * @pending: allows batching of hardware operations
8162306a36Sopenharmony_ci * @slots_allocated: records the actual size of the descriptor slot pool
8262306a36Sopenharmony_ci * @hw_chain_inited: h/w descriptor chain initialization flag
8362306a36Sopenharmony_ci * @irq_tasklet: bottom half where ppc440spe_adma_slot_cleanup runs
8462306a36Sopenharmony_ci * @needs_unmap: if buffers should not be unmapped upon final processing
8562306a36Sopenharmony_ci * @pdest_page: P destination page for async validate operation
8662306a36Sopenharmony_ci * @qdest_page: Q destination page for async validate operation
8762306a36Sopenharmony_ci * @pdest: P dma addr for async validate operation
8862306a36Sopenharmony_ci * @qdest: Q dma addr for async validate operation
8962306a36Sopenharmony_ci */
9062306a36Sopenharmony_cistruct ppc440spe_adma_chan {
9162306a36Sopenharmony_ci	spinlock_t lock;
9262306a36Sopenharmony_ci	struct ppc440spe_adma_device *device;
9362306a36Sopenharmony_ci	struct list_head chain;
9462306a36Sopenharmony_ci	struct dma_chan common;
9562306a36Sopenharmony_ci	struct list_head all_slots;
9662306a36Sopenharmony_ci	struct ppc440spe_adma_desc_slot *last_used;
9762306a36Sopenharmony_ci	int pending;
9862306a36Sopenharmony_ci	int slots_allocated;
9962306a36Sopenharmony_ci	int hw_chain_inited;
10062306a36Sopenharmony_ci	struct tasklet_struct irq_tasklet;
10162306a36Sopenharmony_ci	u8 needs_unmap;
10262306a36Sopenharmony_ci	struct page *pdest_page;
10362306a36Sopenharmony_ci	struct page *qdest_page;
10462306a36Sopenharmony_ci	dma_addr_t pdest;
10562306a36Sopenharmony_ci	dma_addr_t qdest;
10662306a36Sopenharmony_ci};
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_cistruct ppc440spe_rxor {
10962306a36Sopenharmony_ci	u32 addrl;
11062306a36Sopenharmony_ci	u32 addrh;
11162306a36Sopenharmony_ci	int len;
11262306a36Sopenharmony_ci	int xor_count;
11362306a36Sopenharmony_ci	int addr_count;
11462306a36Sopenharmony_ci	int desc_count;
11562306a36Sopenharmony_ci	int state;
11662306a36Sopenharmony_ci};
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci/**
11962306a36Sopenharmony_ci * struct ppc440spe_adma_desc_slot - PPC440SPE-ADMA software descriptor
12062306a36Sopenharmony_ci * @phys: hardware address of the hardware descriptor chain
12162306a36Sopenharmony_ci * @group_head: first operation in a transaction
12262306a36Sopenharmony_ci * @hw_next: pointer to the next descriptor in chain
12362306a36Sopenharmony_ci * @async_tx: support for the async_tx api
12462306a36Sopenharmony_ci * @slot_node: node on the iop_adma_chan.all_slots list
12562306a36Sopenharmony_ci * @chain_node: node on the op_adma_chan.chain list
12662306a36Sopenharmony_ci * @group_list: list of slots that make up a multi-descriptor transaction
12762306a36Sopenharmony_ci *              for example transfer lengths larger than the supported hw max
12862306a36Sopenharmony_ci * @unmap_len: transaction bytecount
12962306a36Sopenharmony_ci * @hw_desc: virtual address of the hardware descriptor chain
13062306a36Sopenharmony_ci * @stride: currently chained or not
13162306a36Sopenharmony_ci * @idx: pool index
13262306a36Sopenharmony_ci * @slot_cnt: total slots used in an transaction (group of operations)
13362306a36Sopenharmony_ci * @src_cnt: number of sources set in this descriptor
13462306a36Sopenharmony_ci * @dst_cnt: number of destinations set in the descriptor
13562306a36Sopenharmony_ci * @slots_per_op: number of slots per operation
13662306a36Sopenharmony_ci * @descs_per_op: number of slot per P/Q operation see comment
13762306a36Sopenharmony_ci *                for ppc440spe_prep_dma_pqxor function
13862306a36Sopenharmony_ci * @flags: desc state/type
13962306a36Sopenharmony_ci * @reverse_flags: 1 if a corresponding rxor address uses reversed address order
14062306a36Sopenharmony_ci * @xor_check_result: result of zero sum
14162306a36Sopenharmony_ci * @crc32_result: result crc calculation
14262306a36Sopenharmony_ci */
14362306a36Sopenharmony_cistruct ppc440spe_adma_desc_slot {
14462306a36Sopenharmony_ci	dma_addr_t phys;
14562306a36Sopenharmony_ci	struct ppc440spe_adma_desc_slot *group_head;
14662306a36Sopenharmony_ci	struct ppc440spe_adma_desc_slot *hw_next;
14762306a36Sopenharmony_ci	struct dma_async_tx_descriptor async_tx;
14862306a36Sopenharmony_ci	struct list_head slot_node;
14962306a36Sopenharmony_ci	struct list_head chain_node; /* node in channel ops list */
15062306a36Sopenharmony_ci	struct list_head group_list; /* list */
15162306a36Sopenharmony_ci	unsigned int unmap_len;
15262306a36Sopenharmony_ci	void *hw_desc;
15362306a36Sopenharmony_ci	u16 stride;
15462306a36Sopenharmony_ci	u16 idx;
15562306a36Sopenharmony_ci	u16 slot_cnt;
15662306a36Sopenharmony_ci	u8 src_cnt;
15762306a36Sopenharmony_ci	u8 dst_cnt;
15862306a36Sopenharmony_ci	u8 slots_per_op;
15962306a36Sopenharmony_ci	u8 descs_per_op;
16062306a36Sopenharmony_ci	unsigned long flags;
16162306a36Sopenharmony_ci	unsigned long reverse_flags[8];
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci#define PPC440SPE_DESC_INT	0	/* generate interrupt on complete */
16462306a36Sopenharmony_ci#define PPC440SPE_ZERO_P	1	/* clear P destionaion */
16562306a36Sopenharmony_ci#define PPC440SPE_ZERO_Q	2	/* clear Q destination */
16662306a36Sopenharmony_ci#define PPC440SPE_COHERENT	3	/* src/dst are coherent */
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci#define PPC440SPE_DESC_WXOR	4	/* WXORs are in chain */
16962306a36Sopenharmony_ci#define PPC440SPE_DESC_RXOR	5	/* RXOR is in chain */
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci#define PPC440SPE_DESC_RXOR123	8	/* CDB for RXOR123 operation */
17262306a36Sopenharmony_ci#define PPC440SPE_DESC_RXOR124	9	/* CDB for RXOR124 operation */
17362306a36Sopenharmony_ci#define PPC440SPE_DESC_RXOR125	10	/* CDB for RXOR125 operation */
17462306a36Sopenharmony_ci#define PPC440SPE_DESC_RXOR12	11	/* CDB for RXOR12 operation */
17562306a36Sopenharmony_ci#define PPC440SPE_DESC_RXOR_REV	12	/* CDB has srcs in reversed order */
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci#define PPC440SPE_DESC_PCHECK	13
17862306a36Sopenharmony_ci#define PPC440SPE_DESC_QCHECK	14
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci#define PPC440SPE_DESC_RXOR_MSK	0x3
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci	struct ppc440spe_rxor rxor_cursor;
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci	union {
18562306a36Sopenharmony_ci		u32 *xor_check_result;
18662306a36Sopenharmony_ci		u32 *crc32_result;
18762306a36Sopenharmony_ci	};
18862306a36Sopenharmony_ci};
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci#endif /* _PPC440SPE_ADMA_H */
191