]> git.sur5r.net Git - u-boot/blob - drivers/ddr/marvell/a38x/xor.c
Merge tag 'xilinx-for-v2018.03' of git://git.denx.de/u-boot-microblaze
[u-boot] / drivers / ddr / marvell / a38x / xor.c
1 /*
2  * Copyright (C) Marvell International Ltd. and its affiliates
3  *
4  * SPDX-License-Identifier:     GPL-2.0
5  */
6
7 #include <common.h>
8 #include <i2c.h>
9 #include <spl.h>
10 #include <asm/io.h>
11 #include <asm/arch/cpu.h>
12 #include <asm/arch/soc.h>
13
14 #include "ddr3_init.h"
15 #include "xor_regs.h"
16
17 /* defines  */
18 #ifdef MV_DEBUG
19 #define DB(x)   x
20 #else
21 #define DB(x)
22 #endif
23
24 static u32 ui_xor_regs_ctrl_backup;
25 static u32 ui_xor_regs_base_backup[MAX_CS];
26 static u32 ui_xor_regs_mask_backup[MAX_CS];
27
28 void mv_sys_xor_init(u32 num_of_cs, u32 cs_ena, u32 cs_size, u32 base_delta)
29 {
30         u32 reg, ui, base, cs_count;
31
32         ui_xor_regs_ctrl_backup = reg_read(XOR_WINDOW_CTRL_REG(0, 0));
33         for (ui = 0; ui < MAX_CS; ui++)
34                 ui_xor_regs_base_backup[ui] =
35                         reg_read(XOR_BASE_ADDR_REG(0, ui));
36         for (ui = 0; ui < MAX_CS; ui++)
37                 ui_xor_regs_mask_backup[ui] =
38                         reg_read(XOR_SIZE_MASK_REG(0, ui));
39
40         reg = 0;
41         for (ui = 0; ui < (num_of_cs); ui++) {
42                 /* Enable Window x for each CS */
43                 reg |= (0x1 << (ui));
44                 /* Enable Window x for each CS */
45                 reg |= (0x3 << ((ui * 2) + 16));
46         }
47
48         reg_write(XOR_WINDOW_CTRL_REG(0, 0), reg);
49
50         cs_count = 0;
51         for (ui = 0; ui < num_of_cs; ui++) {
52                 if (cs_ena & (1 << ui)) {
53                         /*
54                          * window x - Base - 0x00000000,
55                          * Attribute 0x0e - DRAM
56                          */
57                         base = cs_size * ui + base_delta;
58                         switch (ui) {
59                         case 0:
60                                 base |= 0xe00;
61                                 break;
62                         case 1:
63                                 base |= 0xd00;
64                                 break;
65                         case 2:
66                                 base |= 0xb00;
67                                 break;
68                         case 3:
69                                 base |= 0x700;
70                                 break;
71                         }
72
73                         reg_write(XOR_BASE_ADDR_REG(0, cs_count), base);
74
75                         /* window x - Size */
76                         reg_write(XOR_SIZE_MASK_REG(0, cs_count), 0x7fff0000);
77                         cs_count++;
78                 }
79         }
80
81         mv_xor_hal_init(1);
82
83         return;
84 }
85
86 void mv_sys_xor_finish(void)
87 {
88         u32 ui;
89
90         reg_write(XOR_WINDOW_CTRL_REG(0, 0), ui_xor_regs_ctrl_backup);
91         for (ui = 0; ui < MAX_CS; ui++)
92                 reg_write(XOR_BASE_ADDR_REG(0, ui),
93                           ui_xor_regs_base_backup[ui]);
94         for (ui = 0; ui < MAX_CS; ui++)
95                 reg_write(XOR_SIZE_MASK_REG(0, ui),
96                           ui_xor_regs_mask_backup[ui]);
97
98         reg_write(XOR_ADDR_OVRD_REG(0, 0), 0);
99 }
100
101 /*
102  * mv_xor_hal_init - Initialize XOR engine
103  *
104  * DESCRIPTION:
105  *               This function initialize XOR unit.
106  * INPUT:
107  *       None.
108  *
109  * OUTPUT:
110  *       None.
111  *
112  * RETURN:
113  *       MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise.
114  */
115 void mv_xor_hal_init(u32 xor_chan_num)
116 {
117         u32 i;
118
119         /* Abort any XOR activity & set default configuration */
120         for (i = 0; i < xor_chan_num; i++) {
121                 mv_xor_command_set(i, MV_STOP);
122                 mv_xor_ctrl_set(i, (1 << XEXCR_REG_ACC_PROTECT_OFFS) |
123                                 (4 << XEXCR_DST_BURST_LIMIT_OFFS) |
124                                 (4 << XEXCR_SRC_BURST_LIMIT_OFFS));
125         }
126 }
127
128 /*
129  * mv_xor_ctrl_set - Set XOR channel control registers
130  *
131  * DESCRIPTION:
132  *
133  * INPUT:
134  *
135  * OUTPUT:
136  *       None.
137  *
138  * RETURN:
139  *       MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise.
140  * NOTE:
141  *  This function does not modify the Operation_mode field of control register.
142  */
143 int mv_xor_ctrl_set(u32 chan, u32 xor_ctrl)
144 {
145         u32 old_value;
146
147         /* update the XOR Engine [0..1] Configuration Registers (XEx_c_r) */
148         old_value = reg_read(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan))) &
149                 XEXCR_OPERATION_MODE_MASK;
150         xor_ctrl &= ~XEXCR_OPERATION_MODE_MASK;
151         xor_ctrl |= old_value;
152         reg_write(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)), xor_ctrl);
153
154         return MV_OK;
155 }
156
157 int mv_xor_mem_init(u32 chan, u32 start_ptr, u32 block_size,
158                     u32 init_val_high, u32 init_val_low)
159 {
160         u32 temp;
161
162         /* Parameter checking */
163         if (chan >= MV_XOR_MAX_CHAN)
164                 return MV_BAD_PARAM;
165
166         if (MV_ACTIVE == mv_xor_state_get(chan))
167                 return MV_BUSY;
168
169         if ((block_size < XEXBSR_BLOCK_SIZE_MIN_VALUE) ||
170             (block_size > XEXBSR_BLOCK_SIZE_MAX_VALUE))
171                 return MV_BAD_PARAM;
172
173         /* set the operation mode to Memory Init */
174         temp = reg_read(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)));
175         temp &= ~XEXCR_OPERATION_MODE_MASK;
176         temp |= XEXCR_OPERATION_MODE_MEM_INIT;
177         reg_write(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)), temp);
178
179         /*
180          * update the start_ptr field in XOR Engine [0..1] Destination Pointer
181          * Register
182          */
183         reg_write(XOR_DST_PTR_REG(XOR_UNIT(chan), XOR_CHAN(chan)), start_ptr);
184
185         /*
186          * update the Block_size field in the XOR Engine[0..1] Block Size
187          * Registers
188          */
189         reg_write(XOR_BLOCK_SIZE_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
190                   block_size);
191
192         /*
193          * update the field Init_val_l in the XOR Engine Initial Value Register
194          * Low (XEIVRL)
195          */
196         reg_write(XOR_INIT_VAL_LOW_REG(XOR_UNIT(chan)), init_val_low);
197
198         /*
199          * update the field Init_val_h in the XOR Engine Initial Value Register
200          * High (XEIVRH)
201          */
202         reg_write(XOR_INIT_VAL_HIGH_REG(XOR_UNIT(chan)), init_val_high);
203
204         /* start transfer */
205         reg_bit_set(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
206                     XEXACTR_XESTART_MASK);
207
208         return MV_OK;
209 }
210
211 /*
212  * mv_xor_state_get - Get XOR channel state.
213  *
214  * DESCRIPTION:
215  *       XOR channel activity state can be active, idle, paused.
216  *       This function retrunes the channel activity state.
217  *
218  * INPUT:
219  *       chan     - the channel number
220  *
221  * OUTPUT:
222  *       None.
223  *
224  * RETURN:
225  *       XOR_CHANNEL_IDLE    - If the engine is idle.
226  *       XOR_CHANNEL_ACTIVE  - If the engine is busy.
227  *       XOR_CHANNEL_PAUSED  - If the engine is paused.
228  *       MV_UNDEFINED_STATE  - If the engine state is undefind or there is no
229  *                             such engine
230  */
231 enum mv_state mv_xor_state_get(u32 chan)
232 {
233         u32 state;
234
235         /* Parameter checking   */
236         if (chan >= MV_XOR_MAX_CHAN) {
237                 DB(printf("%s: ERR. Invalid chan num %d\n", __func__, chan));
238                 return MV_UNDEFINED_STATE;
239         }
240
241         /* read the current state */
242         state = reg_read(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)));
243         state &= XEXACTR_XESTATUS_MASK;
244
245         /* return the state */
246         switch (state) {
247         case XEXACTR_XESTATUS_IDLE:
248                 return MV_IDLE;
249         case XEXACTR_XESTATUS_ACTIVE:
250                 return MV_ACTIVE;
251         case XEXACTR_XESTATUS_PAUSED:
252                 return MV_PAUSED;
253         }
254
255         return MV_UNDEFINED_STATE;
256 }
257
258 /*
259  * mv_xor_command_set - Set command of XOR channel
260  *
261  * DESCRIPTION:
262  *       XOR channel can be started, idle, paused and restarted.
263  *       Paused can be set only if channel is active.
264  *       Start can be set only if channel is idle or paused.
265  *       Restart can be set only if channel is paused.
266  *       Stop can be set only if channel is active.
267  *
268  * INPUT:
269  *       chan     - The channel number
270  *       command  - The command type (start, stop, restart, pause)
271  *
272  * OUTPUT:
273  *       None.
274  *
275  * RETURN:
276  *       MV_OK on success , MV_BAD_PARAM on erroneous parameter, MV_ERROR on
277  *       undefind XOR engine mode
278  */
279 int mv_xor_command_set(u32 chan, enum mv_command command)
280 {
281         enum mv_state state;
282
283         /* Parameter checking */
284         if (chan >= MV_XOR_MAX_CHAN) {
285                 DB(printf("%s: ERR. Invalid chan num %d\n", __func__, chan));
286                 return MV_BAD_PARAM;
287         }
288
289         /* get the current state */
290         state = mv_xor_state_get(chan);
291
292         if ((command == MV_START) && (state == MV_IDLE)) {
293                 /* command is start and current state is idle */
294                 reg_bit_set(XOR_ACTIVATION_REG
295                             (XOR_UNIT(chan), XOR_CHAN(chan)),
296                             XEXACTR_XESTART_MASK);
297                 return MV_OK;
298         } else if ((command == MV_STOP) && (state == MV_ACTIVE)) {
299                 /* command is stop and current state is active */
300                 reg_bit_set(XOR_ACTIVATION_REG
301                             (XOR_UNIT(chan), XOR_CHAN(chan)),
302                             XEXACTR_XESTOP_MASK);
303                 return MV_OK;
304         } else if (((enum mv_state)command == MV_PAUSED) &&
305                    (state == MV_ACTIVE)) {
306                 /* command is paused and current state is active */
307                 reg_bit_set(XOR_ACTIVATION_REG
308                             (XOR_UNIT(chan), XOR_CHAN(chan)),
309                             XEXACTR_XEPAUSE_MASK);
310                 return MV_OK;
311         } else if ((command == MV_RESTART) && (state == MV_PAUSED)) {
312                 /* command is restart and current state is paused */
313                 reg_bit_set(XOR_ACTIVATION_REG
314                             (XOR_UNIT(chan), XOR_CHAN(chan)),
315                             XEXACTR_XERESTART_MASK);
316                 return MV_OK;
317         } else if ((command == MV_STOP) && (state == MV_IDLE)) {
318                 /* command is stop and current state is active */
319                 return MV_OK;
320         }
321
322         /* illegal command */
323         DB(printf("%s: ERR. Illegal command\n", __func__));
324
325         return MV_BAD_PARAM;
326 }
327
328 void ddr3_new_tip_ecc_scrub(void)
329 {
330         u32 cs_c, max_cs;
331         u32 cs_ena = 0;
332
333         printf("DDR3 Training Sequence - Start scrubbing\n");
334
335         max_cs = hws_ddr3_tip_max_cs_get();
336         for (cs_c = 0; cs_c < max_cs; cs_c++)
337                 cs_ena |= 1 << cs_c;
338
339         mv_sys_xor_init(max_cs, cs_ena, 0x80000000, 0);
340
341         mv_xor_mem_init(0, 0x00000000, 0x80000000, 0xdeadbeef, 0xdeadbeef);
342         /* wait for previous transfer completion */
343         while (mv_xor_state_get(0) != MV_IDLE)
344                 ;
345
346         mv_xor_mem_init(0, 0x80000000, 0x40000000, 0xdeadbeef, 0xdeadbeef);
347
348         /* wait for previous transfer completion */
349         while (mv_xor_state_get(0) != MV_IDLE)
350                 ;
351
352         /* Return XOR State */
353         mv_sys_xor_finish();
354
355         printf("DDR3 Training Sequence - End scrubbing\n");
356 }