xref: /openbmc/u-boot/drivers/ddr/marvell/a38x/xor.c (revision d94604d5)
183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0
2f1df9364SStefan Roese /*
3f1df9364SStefan Roese  * Copyright (C) Marvell International Ltd. and its affiliates
4f1df9364SStefan Roese  */
5f1df9364SStefan Roese 
6f1df9364SStefan Roese #include "ddr3_init.h"
7*ebb1a593SChris Packham #include "mv_ddr_common.h"
8f1df9364SStefan Roese #include "xor_regs.h"
9f1df9364SStefan Roese 
10f1df9364SStefan Roese /* defines  */
11f1df9364SStefan Roese #ifdef MV_DEBUG
12f1df9364SStefan Roese #define DB(x)	x
13f1df9364SStefan Roese #else
14f1df9364SStefan Roese #define DB(x)
15f1df9364SStefan Roese #endif
16f1df9364SStefan Roese 
17f1df9364SStefan Roese static u32 ui_xor_regs_ctrl_backup;
182b4ffbf6SChris Packham static u32 ui_xor_regs_base_backup[MAX_CS_NUM + 1];
192b4ffbf6SChris Packham static u32 ui_xor_regs_mask_backup[MAX_CS_NUM + 1];
20f1df9364SStefan Roese 
mv_sys_xor_init(u32 num_of_cs,u32 cs_ena,uint64_t cs_size,u32 base_delta)212b4ffbf6SChris Packham void mv_sys_xor_init(u32 num_of_cs, u32 cs_ena, uint64_t cs_size, u32 base_delta)
22f1df9364SStefan Roese {
232b4ffbf6SChris Packham 	u32 reg, ui, cs_count;
242b4ffbf6SChris Packham 	uint64_t base, size_mask;
25f1df9364SStefan Roese 
26f1df9364SStefan Roese 	ui_xor_regs_ctrl_backup = reg_read(XOR_WINDOW_CTRL_REG(0, 0));
272b4ffbf6SChris Packham 	for (ui = 0; ui < MAX_CS_NUM + 1; ui++)
28f1df9364SStefan Roese 		ui_xor_regs_base_backup[ui] =
29f1df9364SStefan Roese 			reg_read(XOR_BASE_ADDR_REG(0, ui));
302b4ffbf6SChris Packham 	for (ui = 0; ui < MAX_CS_NUM + 1; ui++)
31f1df9364SStefan Roese 		ui_xor_regs_mask_backup[ui] =
32f1df9364SStefan Roese 			reg_read(XOR_SIZE_MASK_REG(0, ui));
33f1df9364SStefan Roese 
34f1df9364SStefan Roese 	reg = 0;
352b4ffbf6SChris Packham 	for (ui = 0, cs_count = 0;
362b4ffbf6SChris Packham 	     (cs_count < num_of_cs) && (ui < 8);
372b4ffbf6SChris Packham 	     ui++, cs_count++) {
382b4ffbf6SChris Packham 		if (cs_ena & (1 << ui)) {
39f1df9364SStefan Roese 			/* Enable Window x for each CS */
40f1df9364SStefan Roese 			reg |= (0x1 << (ui));
41f1df9364SStefan Roese 			/* Enable Window x for each CS */
42f1df9364SStefan Roese 			reg |= (0x3 << ((ui * 2) + 16));
43f1df9364SStefan Roese 		}
442b4ffbf6SChris Packham 	}
45f1df9364SStefan Roese 
46f1df9364SStefan Roese 	reg_write(XOR_WINDOW_CTRL_REG(0, 0), reg);
47f1df9364SStefan Roese 
48f1df9364SStefan Roese 	cs_count = 0;
492b4ffbf6SChris Packham 	for (ui = 0, cs_count = 0;
502b4ffbf6SChris Packham 	     (cs_count < num_of_cs) && (ui < 8);
512b4ffbf6SChris Packham 	     ui++, cs_count++) {
52f1df9364SStefan Roese 		if (cs_ena & (1 << ui)) {
53f1df9364SStefan Roese 			/*
54f1df9364SStefan Roese 			 * window x - Base - 0x00000000,
55f1df9364SStefan Roese 			 * Attribute 0x0e - DRAM
56f1df9364SStefan Roese 			 */
57f1df9364SStefan Roese 			base = cs_size * ui + base_delta;
582b4ffbf6SChris Packham 			/* fixed size 2GB for each CS */
592b4ffbf6SChris Packham 			size_mask = 0x7FFF0000;
60f1df9364SStefan Roese 			switch (ui) {
61f1df9364SStefan Roese 			case 0:
62f1df9364SStefan Roese 				base |= 0xe00;
63f1df9364SStefan Roese 				break;
64f1df9364SStefan Roese 			case 1:
65f1df9364SStefan Roese 				base |= 0xd00;
66f1df9364SStefan Roese 				break;
67f1df9364SStefan Roese 			case 2:
68f1df9364SStefan Roese 				base |= 0xb00;
69f1df9364SStefan Roese 				break;
70f1df9364SStefan Roese 			case 3:
71f1df9364SStefan Roese 				base |= 0x700;
72f1df9364SStefan Roese 				break;
732b4ffbf6SChris Packham 			case 4: /* SRAM */
742b4ffbf6SChris Packham 				base = 0x40000000;
752b4ffbf6SChris Packham 				/* configure as shared transaction */
762b4ffbf6SChris Packham 				base |= 0x1F00;
772b4ffbf6SChris Packham 				size_mask = 0xF0000;
782b4ffbf6SChris Packham 				break;
79f1df9364SStefan Roese 			}
80f1df9364SStefan Roese 
812b4ffbf6SChris Packham 			reg_write(XOR_BASE_ADDR_REG(0, ui), (u32)base);
822b4ffbf6SChris Packham 			size_mask = (cs_size / _64K) - 1;
832b4ffbf6SChris Packham 			size_mask = (size_mask << XESMRX_SIZE_MASK_OFFS) & XESMRX_SIZE_MASK_MASK;
84f1df9364SStefan Roese 			/* window x - Size */
852b4ffbf6SChris Packham 			reg_write(XOR_SIZE_MASK_REG(0, ui), (u32)size_mask);
86f1df9364SStefan Roese 		}
87f1df9364SStefan Roese 	}
88f1df9364SStefan Roese 
89f1df9364SStefan Roese 	mv_xor_hal_init(1);
90f1df9364SStefan Roese 
91f1df9364SStefan Roese 	return;
92f1df9364SStefan Roese }
93f1df9364SStefan Roese 
mv_sys_xor_finish(void)94f1df9364SStefan Roese void mv_sys_xor_finish(void)
95f1df9364SStefan Roese {
96f1df9364SStefan Roese 	u32 ui;
97f1df9364SStefan Roese 
98f1df9364SStefan Roese 	reg_write(XOR_WINDOW_CTRL_REG(0, 0), ui_xor_regs_ctrl_backup);
992b4ffbf6SChris Packham 	for (ui = 0; ui < MAX_CS_NUM + 1; ui++)
100f1df9364SStefan Roese 		reg_write(XOR_BASE_ADDR_REG(0, ui),
101f1df9364SStefan Roese 			  ui_xor_regs_base_backup[ui]);
1022b4ffbf6SChris Packham 	for (ui = 0; ui < MAX_CS_NUM + 1; ui++)
103f1df9364SStefan Roese 		reg_write(XOR_SIZE_MASK_REG(0, ui),
104f1df9364SStefan Roese 			  ui_xor_regs_mask_backup[ui]);
105f1df9364SStefan Roese 
106f1df9364SStefan Roese 	reg_write(XOR_ADDR_OVRD_REG(0, 0), 0);
107f1df9364SStefan Roese }
108f1df9364SStefan Roese 
109f1df9364SStefan Roese /*
110f1df9364SStefan Roese  * mv_xor_hal_init - Initialize XOR engine
111f1df9364SStefan Roese  *
112f1df9364SStefan Roese  * DESCRIPTION:
113f1df9364SStefan Roese  *               This function initialize XOR unit.
114f1df9364SStefan Roese  * INPUT:
115f1df9364SStefan Roese  *       None.
116f1df9364SStefan Roese  *
117f1df9364SStefan Roese  * OUTPUT:
118f1df9364SStefan Roese  *       None.
119f1df9364SStefan Roese  *
120f1df9364SStefan Roese  * RETURN:
121f1df9364SStefan Roese  *       MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise.
122f1df9364SStefan Roese  */
mv_xor_hal_init(u32 xor_chan_num)123f1df9364SStefan Roese void mv_xor_hal_init(u32 xor_chan_num)
124f1df9364SStefan Roese {
125f1df9364SStefan Roese 	u32 i;
126f1df9364SStefan Roese 
127f1df9364SStefan Roese 	/* Abort any XOR activity & set default configuration */
128f1df9364SStefan Roese 	for (i = 0; i < xor_chan_num; i++) {
129f1df9364SStefan Roese 		mv_xor_command_set(i, MV_STOP);
130f1df9364SStefan Roese 		mv_xor_ctrl_set(i, (1 << XEXCR_REG_ACC_PROTECT_OFFS) |
131f1df9364SStefan Roese 				(4 << XEXCR_DST_BURST_LIMIT_OFFS) |
132f1df9364SStefan Roese 				(4 << XEXCR_SRC_BURST_LIMIT_OFFS));
133f1df9364SStefan Roese 	}
134f1df9364SStefan Roese }
135f1df9364SStefan Roese 
136f1df9364SStefan Roese /*
137f1df9364SStefan Roese  * mv_xor_ctrl_set - Set XOR channel control registers
138f1df9364SStefan Roese  *
139f1df9364SStefan Roese  * DESCRIPTION:
140f1df9364SStefan Roese  *
141f1df9364SStefan Roese  * INPUT:
142f1df9364SStefan Roese  *
143f1df9364SStefan Roese  * OUTPUT:
144f1df9364SStefan Roese  *       None.
145f1df9364SStefan Roese  *
146f1df9364SStefan Roese  * RETURN:
147f1df9364SStefan Roese  *       MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise.
148f1df9364SStefan Roese  * NOTE:
149f1df9364SStefan Roese  *  This function does not modify the Operation_mode field of control register.
150f1df9364SStefan Roese  */
mv_xor_ctrl_set(u32 chan,u32 xor_ctrl)151f1df9364SStefan Roese int mv_xor_ctrl_set(u32 chan, u32 xor_ctrl)
152f1df9364SStefan Roese {
153f1df9364SStefan Roese 	u32 old_value;
154f1df9364SStefan Roese 
155f1df9364SStefan Roese 	/* update the XOR Engine [0..1] Configuration Registers (XEx_c_r) */
156f1df9364SStefan Roese 	old_value = reg_read(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan))) &
157f1df9364SStefan Roese 		XEXCR_OPERATION_MODE_MASK;
158f1df9364SStefan Roese 	xor_ctrl &= ~XEXCR_OPERATION_MODE_MASK;
159f1df9364SStefan Roese 	xor_ctrl |= old_value;
160f1df9364SStefan Roese 	reg_write(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)), xor_ctrl);
161f1df9364SStefan Roese 
162f1df9364SStefan Roese 	return MV_OK;
163f1df9364SStefan Roese }
164f1df9364SStefan Roese 
mv_xor_mem_init(u32 chan,u32 start_ptr,unsigned long long block_size,u32 init_val_high,u32 init_val_low)1652b4ffbf6SChris Packham int mv_xor_mem_init(u32 chan, u32 start_ptr, unsigned long long block_size,
166f1df9364SStefan Roese 		    u32 init_val_high, u32 init_val_low)
167f1df9364SStefan Roese {
168f1df9364SStefan Roese 	u32 temp;
169f1df9364SStefan Roese 
1702b4ffbf6SChris Packham 	if (block_size == _4G)
1712b4ffbf6SChris Packham 		block_size -= 1;
1722b4ffbf6SChris Packham 
173f1df9364SStefan Roese 	/* Parameter checking */
174f1df9364SStefan Roese 	if (chan >= MV_XOR_MAX_CHAN)
175f1df9364SStefan Roese 		return MV_BAD_PARAM;
176f1df9364SStefan Roese 
177f1df9364SStefan Roese 	if (MV_ACTIVE == mv_xor_state_get(chan))
178f1df9364SStefan Roese 		return MV_BUSY;
179f1df9364SStefan Roese 
180f1df9364SStefan Roese 	if ((block_size < XEXBSR_BLOCK_SIZE_MIN_VALUE) ||
181f1df9364SStefan Roese 	    (block_size > XEXBSR_BLOCK_SIZE_MAX_VALUE))
182f1df9364SStefan Roese 		return MV_BAD_PARAM;
183f1df9364SStefan Roese 
184f1df9364SStefan Roese 	/* set the operation mode to Memory Init */
185f1df9364SStefan Roese 	temp = reg_read(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)));
186f1df9364SStefan Roese 	temp &= ~XEXCR_OPERATION_MODE_MASK;
187f1df9364SStefan Roese 	temp |= XEXCR_OPERATION_MODE_MEM_INIT;
188f1df9364SStefan Roese 	reg_write(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)), temp);
189f1df9364SStefan Roese 
190f1df9364SStefan Roese 	/*
191f1df9364SStefan Roese 	 * update the start_ptr field in XOR Engine [0..1] Destination Pointer
192f1df9364SStefan Roese 	 * Register
193f1df9364SStefan Roese 	 */
194f1df9364SStefan Roese 	reg_write(XOR_DST_PTR_REG(XOR_UNIT(chan), XOR_CHAN(chan)), start_ptr);
195f1df9364SStefan Roese 
196f1df9364SStefan Roese 	/*
197f1df9364SStefan Roese 	 * update the Block_size field in the XOR Engine[0..1] Block Size
198f1df9364SStefan Roese 	 * Registers
199f1df9364SStefan Roese 	 */
200f1df9364SStefan Roese 	reg_write(XOR_BLOCK_SIZE_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
201f1df9364SStefan Roese 		  block_size);
202f1df9364SStefan Roese 
203f1df9364SStefan Roese 	/*
204f1df9364SStefan Roese 	 * update the field Init_val_l in the XOR Engine Initial Value Register
205f1df9364SStefan Roese 	 * Low (XEIVRL)
206f1df9364SStefan Roese 	 */
207f1df9364SStefan Roese 	reg_write(XOR_INIT_VAL_LOW_REG(XOR_UNIT(chan)), init_val_low);
208f1df9364SStefan Roese 
209f1df9364SStefan Roese 	/*
210f1df9364SStefan Roese 	 * update the field Init_val_h in the XOR Engine Initial Value Register
211f1df9364SStefan Roese 	 * High (XEIVRH)
212f1df9364SStefan Roese 	 */
213f1df9364SStefan Roese 	reg_write(XOR_INIT_VAL_HIGH_REG(XOR_UNIT(chan)), init_val_high);
214f1df9364SStefan Roese 
215f1df9364SStefan Roese 	/* start transfer */
216f1df9364SStefan Roese 	reg_bit_set(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
217f1df9364SStefan Roese 		    XEXACTR_XESTART_MASK);
218f1df9364SStefan Roese 
219f1df9364SStefan Roese 	return MV_OK;
220f1df9364SStefan Roese }
221f1df9364SStefan Roese 
222f1df9364SStefan Roese /*
223f1df9364SStefan Roese  * mv_xor_state_get - Get XOR channel state.
224f1df9364SStefan Roese  *
225f1df9364SStefan Roese  * DESCRIPTION:
226f1df9364SStefan Roese  *       XOR channel activity state can be active, idle, paused.
227f1df9364SStefan Roese  *       This function retrunes the channel activity state.
228f1df9364SStefan Roese  *
229f1df9364SStefan Roese  * INPUT:
230f1df9364SStefan Roese  *       chan     - the channel number
231f1df9364SStefan Roese  *
232f1df9364SStefan Roese  * OUTPUT:
233f1df9364SStefan Roese  *       None.
234f1df9364SStefan Roese  *
235f1df9364SStefan Roese  * RETURN:
236f1df9364SStefan Roese  *       XOR_CHANNEL_IDLE    - If the engine is idle.
237f1df9364SStefan Roese  *       XOR_CHANNEL_ACTIVE  - If the engine is busy.
238f1df9364SStefan Roese  *       XOR_CHANNEL_PAUSED  - If the engine is paused.
239f1df9364SStefan Roese  *       MV_UNDEFINED_STATE  - If the engine state is undefind or there is no
240f1df9364SStefan Roese  *                             such engine
241f1df9364SStefan Roese  */
mv_xor_state_get(u32 chan)242f1df9364SStefan Roese enum mv_state mv_xor_state_get(u32 chan)
243f1df9364SStefan Roese {
244f1df9364SStefan Roese 	u32 state;
245f1df9364SStefan Roese 
246f1df9364SStefan Roese 	/* Parameter checking   */
247f1df9364SStefan Roese 	if (chan >= MV_XOR_MAX_CHAN) {
248f1df9364SStefan Roese 		DB(printf("%s: ERR. Invalid chan num %d\n", __func__, chan));
249f1df9364SStefan Roese 		return MV_UNDEFINED_STATE;
250f1df9364SStefan Roese 	}
251f1df9364SStefan Roese 
252f1df9364SStefan Roese 	/* read the current state */
253f1df9364SStefan Roese 	state = reg_read(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)));
254f1df9364SStefan Roese 	state &= XEXACTR_XESTATUS_MASK;
255f1df9364SStefan Roese 
256f1df9364SStefan Roese 	/* return the state */
257f1df9364SStefan Roese 	switch (state) {
258f1df9364SStefan Roese 	case XEXACTR_XESTATUS_IDLE:
259f1df9364SStefan Roese 		return MV_IDLE;
260f1df9364SStefan Roese 	case XEXACTR_XESTATUS_ACTIVE:
261f1df9364SStefan Roese 		return MV_ACTIVE;
262f1df9364SStefan Roese 	case XEXACTR_XESTATUS_PAUSED:
263f1df9364SStefan Roese 		return MV_PAUSED;
264f1df9364SStefan Roese 	}
265f1df9364SStefan Roese 
266f1df9364SStefan Roese 	return MV_UNDEFINED_STATE;
267f1df9364SStefan Roese }
268f1df9364SStefan Roese 
269f1df9364SStefan Roese /*
270f1df9364SStefan Roese  * mv_xor_command_set - Set command of XOR channel
271f1df9364SStefan Roese  *
272f1df9364SStefan Roese  * DESCRIPTION:
273f1df9364SStefan Roese  *       XOR channel can be started, idle, paused and restarted.
274f1df9364SStefan Roese  *       Paused can be set only if channel is active.
275f1df9364SStefan Roese  *       Start can be set only if channel is idle or paused.
276f1df9364SStefan Roese  *       Restart can be set only if channel is paused.
277f1df9364SStefan Roese  *       Stop can be set only if channel is active.
278f1df9364SStefan Roese  *
279f1df9364SStefan Roese  * INPUT:
280f1df9364SStefan Roese  *       chan     - The channel number
281f1df9364SStefan Roese  *       command  - The command type (start, stop, restart, pause)
282f1df9364SStefan Roese  *
283f1df9364SStefan Roese  * OUTPUT:
284f1df9364SStefan Roese  *       None.
285f1df9364SStefan Roese  *
286f1df9364SStefan Roese  * RETURN:
287f1df9364SStefan Roese  *       MV_OK on success , MV_BAD_PARAM on erroneous parameter, MV_ERROR on
288f1df9364SStefan Roese  *       undefind XOR engine mode
289f1df9364SStefan Roese  */
mv_xor_command_set(u32 chan,enum mv_command command)290f1df9364SStefan Roese int mv_xor_command_set(u32 chan, enum mv_command command)
291f1df9364SStefan Roese {
292f1df9364SStefan Roese 	enum mv_state state;
293f1df9364SStefan Roese 
294f1df9364SStefan Roese 	/* Parameter checking */
295f1df9364SStefan Roese 	if (chan >= MV_XOR_MAX_CHAN) {
296f1df9364SStefan Roese 		DB(printf("%s: ERR. Invalid chan num %d\n", __func__, chan));
297f1df9364SStefan Roese 		return MV_BAD_PARAM;
298f1df9364SStefan Roese 	}
299f1df9364SStefan Roese 
300f1df9364SStefan Roese 	/* get the current state */
301f1df9364SStefan Roese 	state = mv_xor_state_get(chan);
302f1df9364SStefan Roese 
303f1df9364SStefan Roese 	if ((command == MV_START) && (state == MV_IDLE)) {
304f1df9364SStefan Roese 		/* command is start and current state is idle */
305f1df9364SStefan Roese 		reg_bit_set(XOR_ACTIVATION_REG
306f1df9364SStefan Roese 			    (XOR_UNIT(chan), XOR_CHAN(chan)),
307f1df9364SStefan Roese 			    XEXACTR_XESTART_MASK);
308f1df9364SStefan Roese 		return MV_OK;
309f1df9364SStefan Roese 	} else if ((command == MV_STOP) && (state == MV_ACTIVE)) {
310f1df9364SStefan Roese 		/* command is stop and current state is active */
311f1df9364SStefan Roese 		reg_bit_set(XOR_ACTIVATION_REG
312f1df9364SStefan Roese 			    (XOR_UNIT(chan), XOR_CHAN(chan)),
313f1df9364SStefan Roese 			    XEXACTR_XESTOP_MASK);
314f1df9364SStefan Roese 		return MV_OK;
315f1df9364SStefan Roese 	} else if (((enum mv_state)command == MV_PAUSED) &&
316f1df9364SStefan Roese 		   (state == MV_ACTIVE)) {
317f1df9364SStefan Roese 		/* command is paused and current state is active */
318f1df9364SStefan Roese 		reg_bit_set(XOR_ACTIVATION_REG
319f1df9364SStefan Roese 			    (XOR_UNIT(chan), XOR_CHAN(chan)),
320f1df9364SStefan Roese 			    XEXACTR_XEPAUSE_MASK);
321f1df9364SStefan Roese 		return MV_OK;
322f1df9364SStefan Roese 	} else if ((command == MV_RESTART) && (state == MV_PAUSED)) {
323f1df9364SStefan Roese 		/* command is restart and current state is paused */
324f1df9364SStefan Roese 		reg_bit_set(XOR_ACTIVATION_REG
325f1df9364SStefan Roese 			    (XOR_UNIT(chan), XOR_CHAN(chan)),
326f1df9364SStefan Roese 			    XEXACTR_XERESTART_MASK);
327f1df9364SStefan Roese 		return MV_OK;
328f1df9364SStefan Roese 	} else if ((command == MV_STOP) && (state == MV_IDLE)) {
329f1df9364SStefan Roese 		/* command is stop and current state is active */
330f1df9364SStefan Roese 		return MV_OK;
331f1df9364SStefan Roese 	}
332f1df9364SStefan Roese 
333f1df9364SStefan Roese 	/* illegal command */
334f1df9364SStefan Roese 	DB(printf("%s: ERR. Illegal command\n", __func__));
335f1df9364SStefan Roese 
336f1df9364SStefan Roese 	return MV_BAD_PARAM;
337f1df9364SStefan Roese }
338f1df9364SStefan Roese 
ddr3_new_tip_ecc_scrub(void)339f1df9364SStefan Roese void ddr3_new_tip_ecc_scrub(void)
340f1df9364SStefan Roese {
341f1df9364SStefan Roese 	u32 cs_c, max_cs;
342f1df9364SStefan Roese 	u32 cs_ena = 0;
3432b4ffbf6SChris Packham 	uint64_t total_mem_size, cs_mem_size = 0;
344f1df9364SStefan Roese 
3452b4ffbf6SChris Packham 	printf("DDR Training Sequence - Start scrubbing\n");
346*ebb1a593SChris Packham 	max_cs = mv_ddr_cs_num_get();
347f1df9364SStefan Roese 	for (cs_c = 0; cs_c < max_cs; cs_c++)
348f1df9364SStefan Roese 		cs_ena |= 1 << cs_c;
349f1df9364SStefan Roese 
350*ebb1a593SChris Packham #if defined(CONFIG_ARMADA_38X) || defined(CONFIG_ARMADA_39X)
351*ebb1a593SChris Packham 	/* all chip-selects are of same size */
352db363dbcSChris Packham 	ddr3_calc_mem_cs_size(0, &cs_mem_size);
353*ebb1a593SChris Packham #endif
354db363dbcSChris Packham 
3552b4ffbf6SChris Packham 	mv_sys_xor_init(max_cs, cs_ena, cs_mem_size, 0);
3562b4ffbf6SChris Packham 	total_mem_size = max_cs * cs_mem_size;
3572b4ffbf6SChris Packham 	mv_xor_mem_init(0, 0, total_mem_size, 0xdeadbeef, 0xdeadbeef);
358f1df9364SStefan Roese 	/* wait for previous transfer completion */
359f1df9364SStefan Roese 	while (mv_xor_state_get(0) != MV_IDLE)
360f1df9364SStefan Roese 		;
361f1df9364SStefan Roese 	/* Return XOR State */
362f1df9364SStefan Roese 	mv_sys_xor_finish();
363f1df9364SStefan Roese 
364f1df9364SStefan Roese 	printf("DDR3 Training Sequence - End scrubbing\n");
365f1df9364SStefan Roese }
3662b4ffbf6SChris Packham 
3672b4ffbf6SChris Packham /*
3682b4ffbf6SChris Packham * mv_xor_transfer - Transfer data from source to destination in one of
3692b4ffbf6SChris Packham *		    three modes: XOR, CRC32 or DMA
3702b4ffbf6SChris Packham *
3712b4ffbf6SChris Packham * DESCRIPTION:
3722b4ffbf6SChris Packham *	This function initiates XOR channel, according to function parameters,
3732b4ffbf6SChris Packham *	in order to perform XOR, CRC32 or DMA transaction.
3742b4ffbf6SChris Packham *	To gain maximum performance the user is asked to keep the following
3752b4ffbf6SChris Packham *	restrictions:
3762b4ffbf6SChris Packham *	1) Selected engine is available (not busy).
3772b4ffbf6SChris Packham *	2) This module does not take into consideration CPU MMU issues.
3782b4ffbf6SChris Packham *	   In order for the XOR engine to access the appropriate source
3792b4ffbf6SChris Packham *	   and destination, address parameters must be given in system
3802b4ffbf6SChris Packham *	   physical mode.
3812b4ffbf6SChris Packham *	3) This API does not take care of cache coherency issues. The source,
3822b4ffbf6SChris Packham *	   destination and, in case of chain, the descriptor list are assumed
3832b4ffbf6SChris Packham *	   to be cache coherent.
3842b4ffbf6SChris Packham *	4) Parameters validity.
3852b4ffbf6SChris Packham *
3862b4ffbf6SChris Packham * INPUT:
3872b4ffbf6SChris Packham *	chan		- XOR channel number.
3882b4ffbf6SChris Packham *	type	- One of three: XOR, CRC32 and DMA operations.
3892b4ffbf6SChris Packham *	xor_chain_ptr	- address of chain pointer
3902b4ffbf6SChris Packham *
3912b4ffbf6SChris Packham * OUTPUT:
3922b4ffbf6SChris Packham *	None.
3932b4ffbf6SChris Packham *
3942b4ffbf6SChris Packham * RETURN:
3952b4ffbf6SChris Packham *       MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise.
3962b4ffbf6SChris Packham *
3972b4ffbf6SChris Packham *******************************************************************************/
mv_xor_transfer(u32 chan,enum xor_type type,u32 xor_chain_ptr)3982b4ffbf6SChris Packham int mv_xor_transfer(u32 chan, enum xor_type type, u32 xor_chain_ptr)
3992b4ffbf6SChris Packham {
4002b4ffbf6SChris Packham 	u32 temp;
4012b4ffbf6SChris Packham 
4022b4ffbf6SChris Packham 	/* Parameter checking */
4032b4ffbf6SChris Packham 	if (chan >= MV_XOR_MAX_CHAN) {
4042b4ffbf6SChris Packham 		DB(printf("%s: ERR. Invalid chan num %d\n", __func__, chan));
4052b4ffbf6SChris Packham 		return MV_BAD_PARAM;
4062b4ffbf6SChris Packham 	}
4072b4ffbf6SChris Packham 	if (mv_xor_state_get(chan) == MV_ACTIVE) {
4082b4ffbf6SChris Packham 		DB(printf("%s: ERR. Channel is already active\n", __func__));
4092b4ffbf6SChris Packham 		return MV_BUSY;
4102b4ffbf6SChris Packham 	}
4112b4ffbf6SChris Packham 	if (xor_chain_ptr == 0x0) {
4122b4ffbf6SChris Packham 		DB(printf("%s: ERR. xor_chain_ptr is NULL pointer\n", __func__));
4132b4ffbf6SChris Packham 		return MV_BAD_PARAM;
4142b4ffbf6SChris Packham 	}
4152b4ffbf6SChris Packham 
4162b4ffbf6SChris Packham 	/* read configuration register and mask the operation mode field */
4172b4ffbf6SChris Packham 	temp = reg_read(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)));
4182b4ffbf6SChris Packham 	temp &= ~XEXCR_OPERATION_MODE_MASK;
4192b4ffbf6SChris Packham 
4202b4ffbf6SChris Packham 	switch (type) {
4212b4ffbf6SChris Packham 	case MV_XOR:
4222b4ffbf6SChris Packham 		if ((xor_chain_ptr & XEXDPR_DST_PTR_XOR_MASK) != 0) {
4232b4ffbf6SChris Packham 			DB(printf("%s: ERR. Invalid chain pointer (bits [5:0] must be cleared)\n",
4242b4ffbf6SChris Packham 				  __func__));
4252b4ffbf6SChris Packham 			return MV_BAD_PARAM;
4262b4ffbf6SChris Packham 		}
4272b4ffbf6SChris Packham 		/* set the operation mode to XOR */
4282b4ffbf6SChris Packham 		temp |= XEXCR_OPERATION_MODE_XOR;
4292b4ffbf6SChris Packham 		break;
4302b4ffbf6SChris Packham 	case MV_DMA:
4312b4ffbf6SChris Packham 		if ((xor_chain_ptr & XEXDPR_DST_PTR_DMA_MASK) != 0) {
4322b4ffbf6SChris Packham 			DB(printf("%s: ERR. Invalid chain pointer (bits [4:0] must be cleared)\n",
4332b4ffbf6SChris Packham 				  __func__));
4342b4ffbf6SChris Packham 			return MV_BAD_PARAM;
4352b4ffbf6SChris Packham 		}
4362b4ffbf6SChris Packham 		/* set the operation mode to DMA */
4372b4ffbf6SChris Packham 		temp |= XEXCR_OPERATION_MODE_DMA;
4382b4ffbf6SChris Packham 		break;
4392b4ffbf6SChris Packham 	case MV_CRC32:
4402b4ffbf6SChris Packham 		if ((xor_chain_ptr & XEXDPR_DST_PTR_CRC_MASK) != 0) {
4412b4ffbf6SChris Packham 			DB(printf("%s: ERR. Invalid chain pointer (bits [4:0] must be cleared)\n",
4422b4ffbf6SChris Packham 				  __func__));
4432b4ffbf6SChris Packham 			return MV_BAD_PARAM;
4442b4ffbf6SChris Packham 		}
4452b4ffbf6SChris Packham 		/* set the operation mode to CRC32 */
4462b4ffbf6SChris Packham 		temp |= XEXCR_OPERATION_MODE_CRC;
4472b4ffbf6SChris Packham 		break;
4482b4ffbf6SChris Packham 	default:
4492b4ffbf6SChris Packham 		return MV_BAD_PARAM;
4502b4ffbf6SChris Packham 	}
4512b4ffbf6SChris Packham 
4522b4ffbf6SChris Packham 	/* write the operation mode to the register */
4532b4ffbf6SChris Packham 	reg_write(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)), temp);
4542b4ffbf6SChris Packham 	/*
4552b4ffbf6SChris Packham 	 * update the NextDescPtr field in the XOR Engine [0..1] Next Descriptor
4562b4ffbf6SChris Packham 	 * Pointer Register (XExNDPR)
4572b4ffbf6SChris Packham 	 */
4582b4ffbf6SChris Packham 	reg_write(XOR_NEXT_DESC_PTR_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
4592b4ffbf6SChris Packham 		  xor_chain_ptr);
4602b4ffbf6SChris Packham 
4612b4ffbf6SChris Packham 	/* start transfer */
4622b4ffbf6SChris Packham 	reg_bit_set(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
4632b4ffbf6SChris Packham 		    XEXACTR_XESTART_MASK);
4642b4ffbf6SChris Packham 
4652b4ffbf6SChris Packham 	return MV_OK;
4662b4ffbf6SChris Packham }
467