]> git.karo-electronics.de Git - karo-tx-uboot.git/blob - drivers/ddr/mvebu/xor.c
66c96aef4ecb826aca9f0387d75a315f8ec7d6be
[karo-tx-uboot.git] / drivers / ddr / mvebu / 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 "xor.h"
15 #include "xor_regs.h"
16
17 static u32 xor_regs_ctrl_backup;
18 static u32 xor_regs_base_backup[MAX_CS];
19 static u32 xor_regs_mask_backup[MAX_CS];
20
21 static void mv_xor_hal_init(u32 chan_num);
22 static int mv_xor_cmd_set(u32 chan, int command);
23 static int mv_xor_ctrl_set(u32 chan, u32 xor_ctrl);
24
25 void mv_sys_xor_init(MV_DRAM_INFO *dram_info)
26 {
27         u32 reg, ui, base, cs_count;
28
29         xor_regs_ctrl_backup = reg_read(XOR_WINDOW_CTRL_REG(0, 0));
30         for (ui = 0; ui < MAX_CS; ui++)
31                 xor_regs_base_backup[ui] = reg_read(XOR_BASE_ADDR_REG(0, ui));
32         for (ui = 0; ui < MAX_CS; ui++)
33                 xor_regs_mask_backup[ui] = reg_read(XOR_SIZE_MASK_REG(0, ui));
34
35         reg = 0;
36         for (ui = 0; ui < (dram_info->num_cs + 1); ui++) {
37                 /* Enable Window x for each CS */
38                 reg |= (0x1 << (ui));
39                 /* Enable Window x for each CS */
40                 reg |= (0x3 << ((ui * 2) + 16));
41         }
42
43         reg_write(XOR_WINDOW_CTRL_REG(0, 0), reg);
44
45         /* Last window - Base - 0x40000000, Attribute 0x1E - SRAM */
46         base = (SRAM_BASE & 0xFFFF0000) | 0x1E00;
47         reg_write(XOR_BASE_ADDR_REG(0, dram_info->num_cs), base);
48         /* Last window - Size - 64 MB */
49         reg_write(XOR_SIZE_MASK_REG(0, dram_info->num_cs), 0x03FF0000);
50
51         cs_count = 0;
52         for (ui = 0; ui < MAX_CS; ui++) {
53                 if (dram_info->cs_ena & (1 << ui)) {
54                         /*
55                          * Window x - Base - 0x00000000, Attribute 0x0E - DRAM
56                          */
57                         base = 0;
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 - 256 MB */
76                         reg_write(XOR_SIZE_MASK_REG(0, cs_count), 0x0FFF0000);
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), xor_regs_ctrl_backup);
91         for (ui = 0; ui < MAX_CS; ui++)
92                 reg_write(XOR_BASE_ADDR_REG(0, ui), xor_regs_base_backup[ui]);
93         for (ui = 0; ui < MAX_CS; ui++)
94                 reg_write(XOR_SIZE_MASK_REG(0, ui), xor_regs_mask_backup[ui]);
95
96         reg_write(XOR_ADDR_OVRD_REG(0, 0), 0);
97 }
98
99 /*
100  * mv_xor_hal_init - Initialize XOR engine
101  *
102  * DESCRIPTION:
103  *               This function initialize XOR unit.
104  * INPUT:
105  *       None.
106  *
107  * OUTPUT:
108  *       None.
109  *
110  * RETURN:
111  *       MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise.
112  */
113 static void mv_xor_hal_init(u32 chan_num)
114 {
115         u32 i;
116
117         /* Abort any XOR activity & set default configuration */
118         for (i = 0; i < chan_num; i++) {
119                 mv_xor_cmd_set(i, MV_STOP);
120                 mv_xor_ctrl_set(i, (1 << XEXCR_REG_ACC_PROTECT_OFFS) |
121                                 (4 << XEXCR_DST_BURST_LIMIT_OFFS) |
122                                 (4 << XEXCR_SRC_BURST_LIMIT_OFFS));
123         }
124 }
125
126 /*
127  * mv_xor_ctrl_set - Set XOR channel control registers
128  *
129  * DESCRIPTION:
130  *
131  * INPUT:
132  *
133  * OUTPUT:
134  *       None.
135  *
136  * RETURN:
137  *       MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise.
138  * NOTE:
139  *    This function does not modify the OperationMode field of control register.
140  *
141  */
142 static int mv_xor_ctrl_set(u32 chan, u32 xor_ctrl)
143 {
144         u32 val;
145
146         /* Update the XOR Engine [0..1] Configuration Registers (XExCR) */
147         val = reg_read(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)))
148             & XEXCR_OPERATION_MODE_MASK;
149         xor_ctrl &= ~XEXCR_OPERATION_MODE_MASK;
150         xor_ctrl |= val;
151         reg_write(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)), xor_ctrl);
152
153         return MV_OK;
154 }
155
156 int mv_xor_mem_init(u32 chan, u32 start_ptr, u32 block_size, u32 init_val_high,
157                     u32 init_val_low)
158 {
159         u32 tmp;
160
161         /* Parameter checking */
162         if (chan >= MV_XOR_MAX_CHAN)
163                 return MV_BAD_PARAM;
164
165         if (MV_ACTIVE == mv_xor_state_get(chan))
166                 return MV_BUSY;
167
168         if ((block_size < XEXBSR_BLOCK_SIZE_MIN_VALUE) ||
169             (block_size > XEXBSR_BLOCK_SIZE_MAX_VALUE))
170                 return MV_BAD_PARAM;
171
172         /* Set the operation mode to Memory Init */
173         tmp = reg_read(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)));
174         tmp &= ~XEXCR_OPERATION_MODE_MASK;
175         tmp |= XEXCR_OPERATION_MODE_MEM_INIT;
176         reg_write(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)), tmp);
177
178         /*
179          * Update the start_ptr field in XOR Engine [0..1] Destination Pointer
180          * Register (XExDPR0)
181          */
182         reg_write(XOR_DST_PTR_REG(XOR_UNIT(chan), XOR_CHAN(chan)), start_ptr);
183
184         /*
185          * Update the BlockSize field in the XOR Engine[0..1] Block Size
186          * Registers (XExBSR)
187          */
188         reg_write(XOR_BLOCK_SIZE_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
189                   block_size);
190
191         /*
192          * Update the field InitValL in the XOR Engine Initial Value Register
193          * Low (XEIVRL)
194          */
195         reg_write(XOR_INIT_VAL_LOW_REG(XOR_UNIT(chan)), init_val_low);
196
197         /*
198          * Update the field InitValH in the XOR Engine Initial Value Register
199          * High (XEIVRH)
200          */
201         reg_write(XOR_INIT_VAL_HIGH_REG(XOR_UNIT(chan)), init_val_high);
202
203         /* Start transfer */
204         reg_bit_set(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
205                     XEXACTR_XESTART_MASK);
206
207         return MV_OK;
208 }
209
210 /*
211  * mv_xor_transfer - Transfer data from source to destination on one of
212  *                 three modes (XOR,CRC32,DMA)
213  *
214  * DESCRIPTION:
215  *       This function initiates XOR channel, according to function parameters,
216  *       in order to perform XOR or CRC32 or DMA transaction.
217  *       To gain maximum performance the user is asked to keep the following
218  *       restrictions:
219  *       1) Selected engine is available (not busy).
220  *       1) This module does not take into consideration CPU MMU issues.
221  *          In order for the XOR engine to access the appropreate source
222  *          and destination, address parameters must be given in system
223  *          physical mode.
224  *       2) This API does not take care of cache coherency issues. The source,
225  *          destination and in case of chain the descriptor list are assumed
226  *          to be cache coherent.
227  *       4) Parameters validity. For example, does size parameter exceeds
228  *          maximum byte count of descriptor mode (16M or 64K).
229  *
230  * INPUT:
231  *       chan          - XOR channel number. See MV_XOR_CHANNEL enumerator.
232  *       xor_type      - One of three: XOR, CRC32 and DMA operations.
233  *       xor_chain_ptr - address of chain pointer
234  *
235  * OUTPUT:
236  *       None.
237  *
238  * RETURS:
239  *       MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise.
240  *
241  */
242 int mv_xor_transfer(u32 chan, int xor_type, u32 xor_chain_ptr)
243 {
244         u32 tmp;
245
246         /* Parameter checking */
247         if (chan >= MV_XOR_MAX_CHAN) {
248                 debug("%s: ERR. Invalid chan num %d\n", __func__, chan);
249                 return MV_BAD_PARAM;
250         }
251
252         if (MV_ACTIVE == mv_xor_state_get(chan)) {
253                 debug("%s: ERR. Channel is already active\n", __func__);
254                 return MV_BUSY;
255         }
256
257         if (0x0 == xor_chain_ptr) {
258                 debug("%s: ERR. xor_chain_ptr is NULL pointer\n", __func__);
259                 return MV_BAD_PARAM;
260         }
261
262         /* Read configuration register and mask the operation mode field */
263         tmp = reg_read(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)));
264         tmp &= ~XEXCR_OPERATION_MODE_MASK;
265
266         switch (xor_type) {
267         case MV_XOR:
268                 if (0 != (xor_chain_ptr & XEXDPR_DST_PTR_XOR_MASK)) {
269                         debug("%s: ERR. Invalid chain pointer (bits [5:0] must be cleared)\n",
270                               __func__);
271                         return MV_BAD_PARAM;
272                 }
273
274                 /* Set the operation mode to XOR */
275                 tmp |= XEXCR_OPERATION_MODE_XOR;
276                 break;
277
278         case MV_DMA:
279                 if (0 != (xor_chain_ptr & XEXDPR_DST_PTR_DMA_MASK)) {
280                         debug("%s: ERR. Invalid chain pointer (bits [4:0] must be cleared)\n",
281                               __func__);
282                         return MV_BAD_PARAM;
283                 }
284
285                 /* Set the operation mode to DMA */
286                 tmp |= XEXCR_OPERATION_MODE_DMA;
287                 break;
288
289         case MV_CRC32:
290                 if (0 != (xor_chain_ptr & XEXDPR_DST_PTR_CRC_MASK)) {
291                         debug("%s: ERR. Invalid chain pointer (bits [4:0] must be cleared)\n",
292                               __func__);
293                         return MV_BAD_PARAM;
294                 }
295
296                 /* Set the operation mode to CRC32 */
297                 tmp |= XEXCR_OPERATION_MODE_CRC;
298                 break;
299
300         default:
301                 return MV_BAD_PARAM;
302         }
303
304         /* Write the operation mode to the register */
305         reg_write(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)), tmp);
306
307         /*
308          * Update the NextDescPtr field in the XOR Engine [0..1] Next Descriptor
309          * Pointer Register (XExNDPR)
310          */
311         reg_write(XOR_NEXT_DESC_PTR_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
312                   xor_chain_ptr);
313
314         /* Start transfer */
315         reg_bit_set(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
316                     XEXACTR_XESTART_MASK);
317
318         return MV_OK;
319 }
320
321 /*
322  * mv_xor_state_get - Get XOR channel state.
323  *
324  * DESCRIPTION:
325  *       XOR channel activity state can be active, idle, paused.
326  *       This function retrunes the channel activity state.
327  *
328  * INPUT:
329  *       chan     - the channel number
330  *
331  * OUTPUT:
332  *       None.
333  *
334  * RETURN:
335  *       XOR_CHANNEL_IDLE    - If the engine is idle.
336  *       XOR_CHANNEL_ACTIVE  - If the engine is busy.
337  *       XOR_CHANNEL_PAUSED  - If the engine is paused.
338  *       MV_UNDEFINED_STATE  - If the engine state is undefind or there is no
339  *                             such engine
340  *
341  */
342 int mv_xor_state_get(u32 chan)
343 {
344         u32 state;
345
346         /* Parameter checking */
347         if (chan >= MV_XOR_MAX_CHAN) {
348                 debug("%s: ERR. Invalid chan num %d\n", __func__, chan);
349                 return MV_UNDEFINED_STATE;
350         }
351
352         /* Read the current state */
353         state = reg_read(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)));
354         state &= XEXACTR_XESTATUS_MASK;
355
356         /* Return the state */
357         switch (state) {
358         case XEXACTR_XESTATUS_IDLE:
359                 return MV_IDLE;
360         case XEXACTR_XESTATUS_ACTIVE:
361                 return MV_ACTIVE;
362         case XEXACTR_XESTATUS_PAUSED:
363                 return MV_PAUSED;
364         }
365
366         return MV_UNDEFINED_STATE;
367 }
368
369 /*
370  * mv_xor_cmd_set - Set command of XOR channel
371  *
372  * DESCRIPTION:
373  *       XOR channel can be started, idle, paused and restarted.
374  *       Paused can be set only if channel is active.
375  *       Start can be set only if channel is idle or paused.
376  *       Restart can be set only if channel is paused.
377  *       Stop can be set only if channel is active.
378  *
379  * INPUT:
380  *       chan     - The channel number
381  *       command  - The command type (start, stop, restart, pause)
382  *
383  * OUTPUT:
384  *       None.
385  *
386  * RETURN:
387  *       MV_OK on success , MV_BAD_PARAM on erroneous parameter, MV_ERROR on
388  *       undefind XOR engine mode
389  *
390  */
391 static int mv_xor_cmd_set(u32 chan, int command)
392 {
393         int state;
394
395         /* Parameter checking */
396         if (chan >= MV_XOR_MAX_CHAN) {
397                 debug("%s: ERR. Invalid chan num %d\n", __func__, chan);
398                 return MV_BAD_PARAM;
399         }
400
401         /* Get the current state */
402         state = mv_xor_state_get(chan);
403
404         /* Command is start and current state is idle */
405         if ((command == MV_START) && (state == MV_IDLE)) {
406                 reg_bit_set(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
407                             XEXACTR_XESTART_MASK);
408                 return MV_OK;
409         }
410         /* Command is stop and current state is active */
411         else if ((command == MV_STOP) && (state == MV_ACTIVE)) {
412                 reg_bit_set(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
413                             XEXACTR_XESTOP_MASK);
414                 return MV_OK;
415         }
416         /* Command is paused and current state is active */
417         else if ((command == MV_PAUSED) && (state == MV_ACTIVE)) {
418                 reg_bit_set(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
419                             XEXACTR_XEPAUSE_MASK);
420                 return MV_OK;
421         }
422         /* Command is restart and current state is paused */
423         else if ((command == MV_RESTART) && (state == MV_PAUSED)) {
424                 reg_bit_set(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
425                             XEXACTR_XERESTART_MASK);
426                 return MV_OK;
427         }
428         /* Command is stop and current state is active */
429         else if ((command == MV_STOP) && (state == MV_IDLE))
430                 return MV_OK;
431
432         /* Illegal command */
433         debug("%s: ERR. Illegal command\n", __func__);
434
435         return MV_BAD_PARAM;
436 }