mpc8xx.c 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. /*
  2. * MPC8xx support functions
  3. *
  4. * Author: Scott Wood <scottwood@freescale.com>
  5. *
  6. * Copyright (c) 2007 Freescale Semiconductor, Inc.
  7. *
  8. * This program is free software; you can redistribute it and/or modify it
  9. * under the terms of the GNU General Public License version 2 as published
  10. * by the Free Software Foundation.
  11. */
  12. #include "ops.h"
  13. #include "types.h"
  14. #include "fsl-soc.h"
  15. #include "mpc8xx.h"
  16. #include "stdio.h"
  17. #include "io.h"
  18. #define MPC8XX_PLPRCR (0x284/4) /* PLL and Reset Control Register */
  19. /* Return system clock from crystal frequency */
  20. u32 mpc885_get_clock(u32 crystal)
  21. {
  22. u32 *immr;
  23. u32 plprcr;
  24. int mfi, mfn, mfd, pdf, div;
  25. u32 ret;
  26. immr = fsl_get_immr();
  27. if (!immr) {
  28. printf("mpc885_get_clock: Couldn't get IMMR base.\r\n");
  29. return 0;
  30. }
  31. plprcr = in_be32(&immr[MPC8XX_PLPRCR]);
  32. mfi = (plprcr >> 16) & 15;
  33. if (mfi < 5) {
  34. printf("Warning: PLPRCR[MFI] value of %d out-of-bounds\r\n",
  35. mfi);
  36. mfi = 5;
  37. }
  38. pdf = (plprcr >> 1) & 0xf;
  39. div = (plprcr >> 20) & 3;
  40. mfd = (plprcr >> 22) & 0x1f;
  41. mfn = (plprcr >> 27) & 0x1f;
  42. ret = crystal * mfi;
  43. if (mfn != 0)
  44. ret += crystal * mfn / (mfd + 1);
  45. return ret / (pdf + 1);
  46. }
  47. /* Set common device tree fields based on the given clock frequencies. */
  48. void mpc8xx_set_clocks(u32 sysclk)
  49. {
  50. void *node;
  51. dt_fixup_cpu_clocks(sysclk, sysclk / 16, sysclk);
  52. node = finddevice("/soc/cpm");
  53. if (node)
  54. setprop(node, "clock-frequency", &sysclk, 4);
  55. node = finddevice("/soc/cpm/brg");
  56. if (node)
  57. setprop(node, "clock-frequency", &sysclk, 4);
  58. }
  59. int mpc885_fixup_clocks(u32 crystal)
  60. {
  61. u32 sysclk = mpc885_get_clock(crystal);
  62. if (!sysclk)
  63. return 0;
  64. mpc8xx_set_clocks(sysclk);
  65. return 1;
  66. }