iop3xx-adma.h

来自「linux 内核源代码」· C头文件 代码 · 共 893 行 · 第 1/2 页

H
893
字号
}static inline u32iop3xx_desc_init_xor(struct iop3xx_desc_aau *hw_desc, int src_cnt, int int_en){	int i, shift;	u32 edcr;	union {		u32 value;		struct iop3xx_aau_desc_ctrl field;	} u_desc_ctrl;	u_desc_ctrl.value = 0;	switch (src_cnt) {	case 25 ... 32:		u_desc_ctrl.field.blk_ctrl = 0x3; /* use EDCR[2:0] */		edcr = 0;		shift = 1;		for (i = 24; i < src_cnt; i++) {			edcr |= (1 << shift);			shift += 3;		}		hw_desc->src_edc[AAU_EDCR2_IDX].e_desc_ctrl = edcr;		src_cnt = 24;		/* fall through */	case 17 ... 24:		if (!u_desc_ctrl.field.blk_ctrl) {			hw_desc->src_edc[AAU_EDCR2_IDX].e_desc_ctrl = 0;			u_desc_ctrl.field.blk_ctrl = 0x3; /* use EDCR[2:0] */		}		edcr = 0;		shift = 1;		for (i = 16; i < src_cnt; i++) {			edcr |= (1 << shift);			shift += 3;		}		hw_desc->src_edc[AAU_EDCR1_IDX].e_desc_ctrl = edcr;		src_cnt = 16;		/* fall through */	case 9 ... 16:		if (!u_desc_ctrl.field.blk_ctrl)			u_desc_ctrl.field.blk_ctrl = 0x2; /* use EDCR0 */		edcr = 0;		shift = 1;		for (i = 8; i < src_cnt; i++) {			edcr |= (1 << shift);			shift += 3;		}		hw_desc->src_edc[AAU_EDCR0_IDX].e_desc_ctrl = edcr;		src_cnt = 8;		/* fall through */	case 2 ... 8:		shift = 1;		for (i = 0; i < src_cnt; i++) {			u_desc_ctrl.value |= (1 << shift);			shift += 3;		}		if (!u_desc_ctrl.field.blk_ctrl && src_cnt > 4)			u_desc_ctrl.field.blk_ctrl = 0x1; /* use mini-desc */	}	u_desc_ctrl.field.dest_write_en = 1;	u_desc_ctrl.field.blk1_cmd_ctrl = 0x7; /* direct fill */	u_desc_ctrl.field.int_en = int_en;	hw_desc->desc_ctrl = u_desc_ctrl.value;	return u_desc_ctrl.value;}static inline voidiop_desc_init_xor(struct iop_adma_desc_slot *desc, int src_cnt, int int_en){	iop3xx_desc_init_xor(desc->hw_desc, src_cnt, int_en);}/* return the number of operations */static inline intiop_desc_init_zero_sum(struct iop_adma_desc_slot *desc, int src_cnt, int int_en){	int slot_cnt = desc->slot_cnt, slots_per_op = desc->slots_per_op;	struct iop3xx_desc_aau *hw_desc, *prev_hw_desc, *iter;	union {		u32 value;		struct iop3xx_aau_desc_ctrl field;	} u_desc_ctrl;	int i, j;	hw_desc = desc->hw_desc;	for (i = 0, j = 0; (slot_cnt -= slots_per_op) >= 0;		i += slots_per_op, j++) {		iter = iop_hw_desc_slot_idx(hw_desc, i);		u_desc_ctrl.value = iop3xx_desc_init_xor(iter, src_cnt, int_en);		u_desc_ctrl.field.dest_write_en = 0;		u_desc_ctrl.field.zero_result_en = 1;		u_desc_ctrl.field.int_en = int_en;		iter->desc_ctrl = u_desc_ctrl.value;		/* for the subsequent descriptors preserve the store queue		 * and chain them together		 */		if (i) {			prev_hw_desc =				iop_hw_desc_slot_idx(hw_desc, i - slots_per_op);			prev_hw_desc->next_desc =				(u32) (desc->async_tx.phys + (i << 5));		}	}	return j;}static inline voidiop_desc_init_null_xor(struct iop_adma_desc_slot *desc, int src_cnt, int int_en){	struct iop3xx_desc_aau *hw_desc = desc->hw_desc;	union {		u32 value;		struct iop3xx_aau_desc_ctrl field;	} u_desc_ctrl;	u_desc_ctrl.value = 0;	switch (src_cnt) {	case 25 ... 32:		u_desc_ctrl.field.blk_ctrl = 0x3; /* use EDCR[2:0] */		hw_desc->src_edc[AAU_EDCR2_IDX].e_desc_ctrl = 0;		/* fall through */	case 17 ... 24:		if (!u_desc_ctrl.field.blk_ctrl) {			hw_desc->src_edc[AAU_EDCR2_IDX].e_desc_ctrl = 0;			u_desc_ctrl.field.blk_ctrl = 0x3; /* use EDCR[2:0] */		}		hw_desc->src_edc[AAU_EDCR1_IDX].e_desc_ctrl = 0;		/* fall through */	case 9 ... 16:		if (!u_desc_ctrl.field.blk_ctrl)			u_desc_ctrl.field.blk_ctrl = 0x2; /* use EDCR0 */		hw_desc->src_edc[AAU_EDCR0_IDX].e_desc_ctrl = 0;		/* fall through */	case 1 ... 8:		if (!u_desc_ctrl.field.blk_ctrl && src_cnt > 4)			u_desc_ctrl.field.blk_ctrl = 0x1; /* use mini-desc */	}	u_desc_ctrl.field.dest_write_en = 0;	u_desc_ctrl.field.int_en = int_en;	hw_desc->desc_ctrl = u_desc_ctrl.value;}static inline void iop_desc_set_byte_count(struct iop_adma_desc_slot *desc,					struct iop_adma_chan *chan,					u32 byte_count){	union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };	switch (chan->device->id) {	case DMA0_ID:	case DMA1_ID:		hw_desc.dma->byte_count = byte_count;		break;	case AAU_ID:		hw_desc.aau->byte_count = byte_count;		break;	default:		BUG();	}}static inline voidiop_desc_init_interrupt(struct iop_adma_desc_slot *desc,			struct iop_adma_chan *chan){	union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };	switch (chan->device->id) {	case DMA0_ID:	case DMA1_ID:		iop_desc_init_memcpy(desc, 1);		hw_desc.dma->byte_count = 0;		hw_desc.dma->dest_addr = 0;		hw_desc.dma->src_addr = 0;		break;	case AAU_ID:		iop_desc_init_null_xor(desc, 2, 1);		hw_desc.aau->byte_count = 0;		hw_desc.aau->dest_addr = 0;		hw_desc.aau->src[0] = 0;		hw_desc.aau->src[1] = 0;		break;	default:		BUG();	}}static inline voidiop_desc_set_zero_sum_byte_count(struct iop_adma_desc_slot *desc, u32 len){	int slots_per_op = desc->slots_per_op;	struct iop3xx_desc_aau *hw_desc = desc->hw_desc, *iter;	int i = 0;	if (len <= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT) {		hw_desc->byte_count = len;	} else {		do {			iter = iop_hw_desc_slot_idx(hw_desc, i);			iter->byte_count = IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;			len -= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;			i += slots_per_op;		} while (len > IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT);		if (len) {			iter = iop_hw_desc_slot_idx(hw_desc, i);			iter->byte_count = len;		}	}}static inline void iop_desc_set_dest_addr(struct iop_adma_desc_slot *desc,					struct iop_adma_chan *chan,					dma_addr_t addr){	union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };	switch (chan->device->id) {	case DMA0_ID:	case DMA1_ID:		hw_desc.dma->dest_addr = addr;		break;	case AAU_ID:		hw_desc.aau->dest_addr = addr;		break;	default:		BUG();	}}static inline void iop_desc_set_memcpy_src_addr(struct iop_adma_desc_slot *desc,					dma_addr_t addr){	struct iop3xx_desc_dma *hw_desc = desc->hw_desc;	hw_desc->src_addr = addr;}static inline voidiop_desc_set_zero_sum_src_addr(struct iop_adma_desc_slot *desc, int src_idx,				dma_addr_t addr){	struct iop3xx_desc_aau *hw_desc = desc->hw_desc, *iter;	int slot_cnt = desc->slot_cnt, slots_per_op = desc->slots_per_op;	int i;	for (i = 0; (slot_cnt -= slots_per_op) >= 0;		i += slots_per_op, addr += IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT) {		iter = iop_hw_desc_slot_idx(hw_desc, i);		iop3xx_aau_desc_set_src_addr(iter, src_idx, addr);	}}static inline void iop_desc_set_xor_src_addr(struct iop_adma_desc_slot *desc,					int src_idx, dma_addr_t addr){	struct iop3xx_desc_aau *hw_desc = desc->hw_desc, *iter;	int slot_cnt = desc->slot_cnt, slots_per_op = desc->slots_per_op;	int i;	for (i = 0; (slot_cnt -= slots_per_op) >= 0;		i += slots_per_op, addr += IOP_ADMA_XOR_MAX_BYTE_COUNT) {		iter = iop_hw_desc_slot_idx(hw_desc, i);		iop3xx_aau_desc_set_src_addr(iter, src_idx, addr);	}}static inline void iop_desc_set_next_desc(struct iop_adma_desc_slot *desc,					u32 next_desc_addr){	/* hw_desc->next_desc is the same location for all channels */	union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };	BUG_ON(hw_desc.dma->next_desc);	hw_desc.dma->next_desc = next_desc_addr;}static inline u32 iop_desc_get_next_desc(struct iop_adma_desc_slot *desc){	/* hw_desc->next_desc is the same location for all channels */	union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };	return hw_desc.dma->next_desc;}static inline void iop_desc_clear_next_desc(struct iop_adma_desc_slot *desc){	/* hw_desc->next_desc is the same location for all channels */	union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };	hw_desc.dma->next_desc = 0;}static inline void iop_desc_set_block_fill_val(struct iop_adma_desc_slot *desc,						u32 val){	struct iop3xx_desc_aau *hw_desc = desc->hw_desc;	hw_desc->src[0] = val;}static inline int iop_desc_get_zero_result(struct iop_adma_desc_slot *desc){	struct iop3xx_desc_aau *hw_desc = desc->hw_desc;	struct iop3xx_aau_desc_ctrl desc_ctrl = hw_desc->desc_ctrl_field;	BUG_ON(!(desc_ctrl.tx_complete && desc_ctrl.zero_result_en));	return desc_ctrl.zero_result_err;}static inline void iop_chan_append(struct iop_adma_chan *chan){	u32 dma_chan_ctrl;	/* workaround dropped interrupts on 3xx */	mod_timer(&chan->cleanup_watchdog, jiffies + msecs_to_jiffies(3));	dma_chan_ctrl = __raw_readl(DMA_CCR(chan));	dma_chan_ctrl |= 0x2;	__raw_writel(dma_chan_ctrl, DMA_CCR(chan));}static inline void iop_chan_idle(int busy, struct iop_adma_chan *chan){	if (!busy)		del_timer(&chan->cleanup_watchdog);}static inline u32 iop_chan_get_status(struct iop_adma_chan *chan){	return __raw_readl(DMA_CSR(chan));}static inline void iop_chan_disable(struct iop_adma_chan *chan){	u32 dma_chan_ctrl = __raw_readl(DMA_CCR(chan));	dma_chan_ctrl &= ~1;	__raw_writel(dma_chan_ctrl, DMA_CCR(chan));}static inline void iop_chan_enable(struct iop_adma_chan *chan){	u32 dma_chan_ctrl = __raw_readl(DMA_CCR(chan));	dma_chan_ctrl |= 1;	__raw_writel(dma_chan_ctrl, DMA_CCR(chan));}static inline void iop_adma_device_clear_eot_status(struct iop_adma_chan *chan){	u32 status = __raw_readl(DMA_CSR(chan));	status &= (1 << 9);	__raw_writel(status, DMA_CSR(chan));}static inline void iop_adma_device_clear_eoc_status(struct iop_adma_chan *chan){	u32 status = __raw_readl(DMA_CSR(chan));	status &= (1 << 8);	__raw_writel(status, DMA_CSR(chan));}static inline void iop_adma_device_clear_err_status(struct iop_adma_chan *chan){	u32 status = __raw_readl(DMA_CSR(chan));	switch (chan->device->id) {	case DMA0_ID:	case DMA1_ID:		status &= (1 << 5) | (1 << 3) | (1 << 2) | (1 << 1);		break;	case AAU_ID:		status &= (1 << 5);		break;	default:		BUG();	}	__raw_writel(status, DMA_CSR(chan));}static inline intiop_is_err_int_parity(unsigned long status, struct iop_adma_chan *chan){	return 0;}static inline intiop_is_err_mcu_abort(unsigned long status, struct iop_adma_chan *chan){	return 0;}static inline intiop_is_err_int_tabort(unsigned long status, struct iop_adma_chan *chan){	return 0;}static inline intiop_is_err_int_mabort(unsigned long status, struct iop_adma_chan *chan){	return test_bit(5, &status);}static inline intiop_is_err_pci_tabort(unsigned long status, struct iop_adma_chan *chan){	switch (chan->device->id) {	case DMA0_ID:	case DMA1_ID:		return test_bit(2, &status);	default:		return 0;	}}static inline intiop_is_err_pci_mabort(unsigned long status, struct iop_adma_chan *chan){	switch (chan->device->id) {	case DMA0_ID:	case DMA1_ID:		return test_bit(3, &status);	default:		return 0;	}}static inline intiop_is_err_split_tx(unsigned long status, struct iop_adma_chan *chan){	switch (chan->device->id) {	case DMA0_ID:	case DMA1_ID:		return test_bit(1, &status);	default:		return 0;	}}#endif /* _ADMA_H */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?