pll.h 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. /* arch/arm/plat-s5p/include/plat/pll.h
  2. *
  3. * Copyright (c) 2009 Samsung Electronics Co., Ltd.
  4. * http://www.samsung.com/
  5. *
  6. * S5P PLL code
  7. *
  8. * Based on arch/arm/plat-s3c64xx/include/plat/pll.h
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License version 2 as
  12. * published by the Free Software Foundation.
  13. */
  14. #include <asm/div64.h>
  15. #define PLL35XX_MDIV_MASK (0x3FF)
  16. #define PLL35XX_PDIV_MASK (0x3F)
  17. #define PLL35XX_SDIV_MASK (0x7)
  18. #define PLL35XX_MDIV_SHIFT (16)
  19. #define PLL35XX_PDIV_SHIFT (8)
  20. #define PLL35XX_SDIV_SHIFT (0)
  21. static inline unsigned long s5p_get_pll35xx(unsigned long baseclk, u32 pll_con)
  22. {
  23. u32 mdiv, pdiv, sdiv;
  24. u64 fvco = baseclk;
  25. mdiv = (pll_con >> PLL35XX_MDIV_SHIFT) & PLL35XX_MDIV_MASK;
  26. pdiv = (pll_con >> PLL35XX_PDIV_SHIFT) & PLL35XX_PDIV_MASK;
  27. sdiv = (pll_con >> PLL35XX_SDIV_SHIFT) & PLL35XX_SDIV_MASK;
  28. fvco *= mdiv;
  29. do_div(fvco, (pdiv << sdiv));
  30. return (unsigned long)fvco;
  31. }
  32. #define PLL36XX_KDIV_MASK (0xFFFF)
  33. #define PLL36XX_MDIV_MASK (0x1FF)
  34. #define PLL36XX_PDIV_MASK (0x3F)
  35. #define PLL36XX_SDIV_MASK (0x7)
  36. #define PLL36XX_MDIV_SHIFT (16)
  37. #define PLL36XX_PDIV_SHIFT (8)
  38. #define PLL36XX_SDIV_SHIFT (0)
  39. static inline unsigned long s5p_get_pll36xx(unsigned long baseclk,
  40. u32 pll_con0, u32 pll_con1)
  41. {
  42. unsigned long result;
  43. u32 mdiv, pdiv, sdiv, kdiv;
  44. u64 tmp;
  45. mdiv = (pll_con0 >> PLL36XX_MDIV_SHIFT) & PLL36XX_MDIV_MASK;
  46. pdiv = (pll_con0 >> PLL36XX_PDIV_SHIFT) & PLL36XX_PDIV_MASK;
  47. sdiv = (pll_con0 >> PLL36XX_SDIV_SHIFT) & PLL36XX_SDIV_MASK;
  48. kdiv = pll_con1 & PLL36XX_KDIV_MASK;
  49. tmp = baseclk;
  50. tmp *= (mdiv << 16) + kdiv;
  51. do_div(tmp, (pdiv << sdiv));
  52. result = tmp >> 16;
  53. return result;
  54. }
  55. #define PLL45XX_MDIV_MASK (0x3FF)
  56. #define PLL45XX_PDIV_MASK (0x3F)
  57. #define PLL45XX_SDIV_MASK (0x7)
  58. #define PLL45XX_MDIV_SHIFT (16)
  59. #define PLL45XX_PDIV_SHIFT (8)
  60. #define PLL45XX_SDIV_SHIFT (0)
  61. enum pll45xx_type_t {
  62. pll_4500,
  63. pll_4502,
  64. pll_4508
  65. };
  66. static inline unsigned long s5p_get_pll45xx(unsigned long baseclk, u32 pll_con,
  67. enum pll45xx_type_t pll_type)
  68. {
  69. u32 mdiv, pdiv, sdiv;
  70. u64 fvco = baseclk;
  71. mdiv = (pll_con >> PLL45XX_MDIV_SHIFT) & PLL45XX_MDIV_MASK;
  72. pdiv = (pll_con >> PLL45XX_PDIV_SHIFT) & PLL45XX_PDIV_MASK;
  73. sdiv = (pll_con >> PLL45XX_SDIV_SHIFT) & PLL45XX_SDIV_MASK;
  74. if (pll_type == pll_4508)
  75. sdiv = sdiv - 1;
  76. fvco *= mdiv;
  77. do_div(fvco, (pdiv << sdiv));
  78. return (unsigned long)fvco;
  79. }
  80. /* CON0 bit-fields */
  81. #define PLL46XX_MDIV_MASK (0x1FF)
  82. #define PLL46XX_PDIV_MASK (0x3F)
  83. #define PLL46XX_SDIV_MASK (0x7)
  84. #define PLL46XX_LOCKED_SHIFT (29)
  85. #define PLL46XX_MDIV_SHIFT (16)
  86. #define PLL46XX_PDIV_SHIFT (8)
  87. #define PLL46XX_SDIV_SHIFT (0)
  88. /* CON1 bit-fields */
  89. #define PLL46XX_MRR_MASK (0x1F)
  90. #define PLL46XX_MFR_MASK (0x3F)
  91. #define PLL46XX_KDIV_MASK (0xFFFF)
  92. #define PLL4650C_KDIV_MASK (0xFFF)
  93. #define PLL46XX_MRR_SHIFT (24)
  94. #define PLL46XX_MFR_SHIFT (16)
  95. #define PLL46XX_KDIV_SHIFT (0)
  96. enum pll46xx_type_t {
  97. pll_4600,
  98. pll_4650,
  99. pll_4650c,
  100. };
  101. static inline unsigned long s5p_get_pll46xx(unsigned long baseclk,
  102. u32 pll_con0, u32 pll_con1,
  103. enum pll46xx_type_t pll_type)
  104. {
  105. unsigned long result;
  106. u32 mdiv, pdiv, sdiv, kdiv;
  107. u64 tmp;
  108. mdiv = (pll_con0 >> PLL46XX_MDIV_SHIFT) & PLL46XX_MDIV_MASK;
  109. pdiv = (pll_con0 >> PLL46XX_PDIV_SHIFT) & PLL46XX_PDIV_MASK;
  110. sdiv = (pll_con0 >> PLL46XX_SDIV_SHIFT) & PLL46XX_SDIV_MASK;
  111. if (pll_type == pll_4650c)
  112. kdiv = pll_con1 & PLL4650C_KDIV_MASK;
  113. else
  114. kdiv = pll_con1 & PLL46XX_KDIV_MASK;
  115. tmp = baseclk;
  116. if (pll_type == pll_4600) {
  117. tmp *= (mdiv << 16) + kdiv;
  118. do_div(tmp, (pdiv << sdiv));
  119. result = tmp >> 16;
  120. } else {
  121. tmp *= (mdiv << 10) + kdiv;
  122. do_div(tmp, (pdiv << sdiv));
  123. result = tmp >> 10;
  124. }
  125. return result;
  126. }
  127. #define PLL90XX_MDIV_MASK (0xFF)
  128. #define PLL90XX_PDIV_MASK (0x3F)
  129. #define PLL90XX_SDIV_MASK (0x7)
  130. #define PLL90XX_KDIV_MASK (0xffff)
  131. #define PLL90XX_LOCKED_SHIFT (29)
  132. #define PLL90XX_MDIV_SHIFT (16)
  133. #define PLL90XX_PDIV_SHIFT (8)
  134. #define PLL90XX_SDIV_SHIFT (0)
  135. #define PLL90XX_KDIV_SHIFT (0)
  136. static inline unsigned long s5p_get_pll90xx(unsigned long baseclk,
  137. u32 pll_con, u32 pll_conk)
  138. {
  139. unsigned long result;
  140. u32 mdiv, pdiv, sdiv, kdiv;
  141. u64 tmp;
  142. mdiv = (pll_con >> PLL90XX_MDIV_SHIFT) & PLL90XX_MDIV_MASK;
  143. pdiv = (pll_con >> PLL90XX_PDIV_SHIFT) & PLL90XX_PDIV_MASK;
  144. sdiv = (pll_con >> PLL90XX_SDIV_SHIFT) & PLL90XX_SDIV_MASK;
  145. kdiv = pll_conk & PLL90XX_KDIV_MASK;
  146. /* We need to multiple baseclk by mdiv (the integer part) and kdiv
  147. * which is in 2^16ths, so shift mdiv up (does not overflow) and
  148. * add kdiv before multiplying. The use of tmp is to avoid any
  149. * overflows before shifting bac down into result when multipling
  150. * by the mdiv and kdiv pair.
  151. */
  152. tmp = baseclk;
  153. tmp *= (mdiv << 16) + kdiv;
  154. do_div(tmp, (pdiv << sdiv));
  155. result = tmp >> 16;
  156. return result;
  157. }
  158. #define PLL65XX_MDIV_MASK (0x3FF)
  159. #define PLL65XX_PDIV_MASK (0x3F)
  160. #define PLL65XX_SDIV_MASK (0x7)
  161. #define PLL65XX_MDIV_SHIFT (16)
  162. #define PLL65XX_PDIV_SHIFT (8)
  163. #define PLL65XX_SDIV_SHIFT (0)
  164. static inline unsigned long s5p_get_pll65xx(unsigned long baseclk, u32 pll_con)
  165. {
  166. u32 mdiv, pdiv, sdiv;
  167. u64 fvco = baseclk;
  168. mdiv = (pll_con >> PLL65XX_MDIV_SHIFT) & PLL65XX_MDIV_MASK;
  169. pdiv = (pll_con >> PLL65XX_PDIV_SHIFT) & PLL65XX_PDIV_MASK;
  170. sdiv = (pll_con >> PLL65XX_SDIV_SHIFT) & PLL65XX_SDIV_MASK;
  171. fvco *= mdiv;
  172. do_div(fvco, (pdiv << sdiv));
  173. return (unsigned long)fvco;
  174. }