Merge branch 'master' of git://git.denx.de/u-boot-dm
[platform/kernel/u-boot.git] / arch / powerpc / lib / memcpy_mpc5200.c
1 /*
2  * (C) Copyright 2010
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  */
7
8 /*
9  * This is a workaround for issues on the MPC5200, where unaligned
10  * 32-bit-accesses to the local bus will deliver corrupted data. This
11  * happens for example when trying to use memcpy() from an odd NOR
12  * flash address; the behaviour can be also seen when using "md" on an
13  * odd NOR flash address (but there it is not a bug in U-Boot, which
14  * only shows the behaviour of this processor).
15  *
16  * For memcpy(), we test if either the source or the target address
17  * are not 32 bit aligned, and - if so - if the source address is in
18  * NOR flash: in this case we perform a byte-wise (slow) then; for
19  * aligned operations of non-flash areas we use the optimized (fast)
20  * real __memcpy().  This way we minimize the performance impact of
21  * this workaround.
22  *
23  */
24
25 #include <common.h>
26 #include <flash.h>
27 #include <linux/types.h>
28
29 void *memcpy(void *trg, const void *src, size_t len)
30 {
31         extern void* __memcpy(void *, const void *, size_t);
32         char *s = (char *)src;
33         char *t = (char *)trg;
34         void *dest = (void *)src;
35
36         /*
37          * Check is source address is in flash:
38          * If not, we use the fast assembler code
39          */
40         if (((((unsigned long)s & 3) == 0)      /* source aligned  */
41                 &&                              /*      AND        */
42              (((unsigned long)t & 3) == 0))     /* target aligned, */
43                 ||                              /*      or         */
44             (addr2info((ulong)s) == NULL)) {    /* source not in flash */
45                 return __memcpy(trg, src, len);
46         }
47
48         /*
49          * Copying from flash, perform byte by byte copy.
50          */
51         while (len-- > 0)
52                 *t++ = *s++;
53
54         return dest;
55 }