memcpy_mpc5200.c 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  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. * This is a workaround for issues on the MPC5200, where unaligned
  9. * 32-bit-accesses to the local bus will deliver corrupted data. This
  10. * happens for example when trying to use memcpy() from an odd NOR
  11. * flash address; the behaviour can be also seen when using "md" on an
  12. * odd NOR flash address (but there it is not a bug in U-Boot, which
  13. * only shows the behaviour of this processor).
  14. *
  15. * For memcpy(), we test if either the source or the target address
  16. * are not 32 bit aligned, and - if so - if the source address is in
  17. * NOR flash: in this case we perform a byte-wise (slow) then; for
  18. * aligned operations of non-flash areas we use the optimized (fast)
  19. * real __memcpy(). This way we minimize the performance impact of
  20. * this workaround.
  21. *
  22. */
  23. #include <common.h>
  24. #include <flash.h>
  25. #include <linux/types.h>
  26. void *memcpy(void *trg, const void *src, size_t len)
  27. {
  28. extern void* __memcpy(void *, const void *, size_t);
  29. char *s = (char *)src;
  30. char *t = (char *)trg;
  31. void *dest = (void *)src;
  32. /*
  33. * Check is source address is in flash:
  34. * If not, we use the fast assembler code
  35. */
  36. if (((((unsigned long)s & 3) == 0) /* source aligned */
  37. && /* AND */
  38. (((unsigned long)t & 3) == 0)) /* target aligned, */
  39. || /* or */
  40. (addr2info((ulong)s) == NULL)) { /* source not in flash */
  41. return __memcpy(trg, src, len);
  42. }
  43. /*
  44. * Copying from flash, perform byte by byte copy.
  45. */
  46. while (len-- > 0)
  47. *t++ = *s++;
  48. return dest;
  49. }