clk-sam9x60-pll.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * SAM9X60's PLL clock support.
  4. *
  5. * Copyright (C) 2020 Microchip Technology Inc. and its subsidiaries
  6. *
  7. * Author: Claudiu Beznea <claudiu.beznea@microchip.com>
  8. *
  9. * Based on drivers/clk/at91/clk-sam9x60-pll.c from Linux.
  10. *
  11. */
  12. #include <asm/processor.h>
  13. #include <common.h>
  14. #include <clk-uclass.h>
  15. #include <div64.h>
  16. #include <dm.h>
  17. #include <linux/clk-provider.h>
  18. #include <linux/clk/at91_pmc.h>
  19. #include <linux/delay.h>
  20. #include "pmc.h"
  21. #define UBOOT_DM_CLK_AT91_SAM9X60_DIV_PLL "at91-sam9x60-div-pll-clk"
  22. #define UBOOT_DM_CLK_AT91_SAM9X60_FRAC_PLL "at91-sam9x60-frac-pll-clk"
  23. #define PMC_PLL_CTRL0_DIV_MSK GENMASK(7, 0)
  24. #define PMC_PLL_CTRL1_MUL_MSK GENMASK(31, 24)
  25. #define PMC_PLL_CTRL1_FRACR_MSK GENMASK(21, 0)
  26. #define PLL_DIV_MAX (FIELD_GET(PMC_PLL_CTRL0_DIV_MSK, UINT_MAX) + 1)
  27. #define UPLL_DIV 2
  28. #define PLL_MUL_MAX (FIELD_GET(PMC_PLL_CTRL1_MUL_MSK, UINT_MAX) + 1)
  29. #define FCORE_MIN (600000000)
  30. #define FCORE_MAX (1200000000)
  31. #define PLL_MAX_ID 7
  32. struct sam9x60_pll {
  33. void __iomem *base;
  34. const struct clk_pll_characteristics *characteristics;
  35. const struct clk_pll_layout *layout;
  36. struct clk clk;
  37. u8 id;
  38. };
  39. #define to_sam9x60_pll(_clk) container_of(_clk, struct sam9x60_pll, clk)
  40. static inline bool sam9x60_pll_ready(void __iomem *base, int id)
  41. {
  42. unsigned int status;
  43. pmc_read(base, AT91_PMC_PLL_ISR0, &status);
  44. return !!(status & BIT(id));
  45. }
  46. static long sam9x60_frac_pll_compute_mul_frac(u32 *mul, u32 *frac, ulong rate,
  47. ulong parent_rate)
  48. {
  49. unsigned long tmprate, remainder;
  50. unsigned long nmul = 0;
  51. unsigned long nfrac = 0;
  52. if (rate < FCORE_MIN || rate > FCORE_MAX)
  53. return -ERANGE;
  54. /*
  55. * Calculate the multiplier associated with the current
  56. * divider that provide the closest rate to the requested one.
  57. */
  58. nmul = mult_frac(rate, 1, parent_rate);
  59. tmprate = mult_frac(parent_rate, nmul, 1);
  60. remainder = rate - tmprate;
  61. if (remainder) {
  62. nfrac = DIV_ROUND_CLOSEST_ULL((u64)remainder * (1 << 22),
  63. parent_rate);
  64. tmprate += DIV_ROUND_CLOSEST_ULL((u64)nfrac * parent_rate,
  65. (1 << 22));
  66. }
  67. /* Check if resulted rate is valid. */
  68. if (tmprate < FCORE_MIN || tmprate > FCORE_MAX)
  69. return -ERANGE;
  70. *mul = nmul - 1;
  71. *frac = nfrac;
  72. return tmprate;
  73. }
  74. static ulong sam9x60_frac_pll_set_rate(struct clk *clk, ulong rate)
  75. {
  76. struct sam9x60_pll *pll = to_sam9x60_pll(clk);
  77. void __iomem *base = pll->base;
  78. ulong parent_rate = clk_get_parent_rate(clk);
  79. u32 nmul, cmul, nfrac, cfrac, val;
  80. bool ready = sam9x60_pll_ready(base, pll->id);
  81. long ret;
  82. if (!parent_rate)
  83. return 0;
  84. ret = sam9x60_frac_pll_compute_mul_frac(&nmul, &nfrac, rate,
  85. parent_rate);
  86. if (ret < 0)
  87. return 0;
  88. pmc_update_bits(base, AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MSK,
  89. pll->id);
  90. pmc_read(base, AT91_PMC_PLL_CTRL1, &val);
  91. cmul = (val & pll->layout->mul_mask) >> pll->layout->mul_shift;
  92. cfrac = (val & pll->layout->frac_mask) >> pll->layout->frac_shift;
  93. /* Check against current values. */
  94. if (sam9x60_pll_ready(base, pll->id) &&
  95. nmul == cmul && nfrac == cfrac)
  96. return 0;
  97. /* Update it to hardware. */
  98. pmc_write(base, AT91_PMC_PLL_CTRL1,
  99. (nmul << pll->layout->mul_shift) |
  100. (nfrac << pll->layout->frac_shift));
  101. pmc_update_bits(base, AT91_PMC_PLL_UPDT,
  102. AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
  103. AT91_PMC_PLL_UPDT_UPDATE | pll->id);
  104. while (ready && !sam9x60_pll_ready(base, pll->id)) {
  105. debug("waiting for pll %u...\n", pll->id);
  106. cpu_relax();
  107. }
  108. return parent_rate * (nmul + 1) + ((u64)parent_rate * nfrac >> 22);
  109. }
  110. static ulong sam9x60_frac_pll_get_rate(struct clk *clk)
  111. {
  112. struct sam9x60_pll *pll = to_sam9x60_pll(clk);
  113. void __iomem *base = pll->base;
  114. ulong parent_rate = clk_get_parent_rate(clk);
  115. u32 mul, frac, val;
  116. if (!parent_rate)
  117. return 0;
  118. pmc_update_bits(base, AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MSK,
  119. pll->id);
  120. pmc_read(base, AT91_PMC_PLL_CTRL1, &val);
  121. mul = (val & pll->layout->mul_mask) >> pll->layout->mul_shift;
  122. frac = (val & pll->layout->frac_mask) >> pll->layout->frac_shift;
  123. return (parent_rate * (mul + 1) + ((u64)parent_rate * frac >> 22));
  124. }
  125. static int sam9x60_frac_pll_enable(struct clk *clk)
  126. {
  127. struct sam9x60_pll *pll = to_sam9x60_pll(clk);
  128. void __iomem *base = pll->base;
  129. unsigned int val;
  130. ulong crate;
  131. crate = sam9x60_frac_pll_get_rate(clk);
  132. if (crate < FCORE_MIN || crate > FCORE_MAX)
  133. return -ERANGE;
  134. pmc_update_bits(base, AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MSK,
  135. pll->id);
  136. pmc_read(base, AT91_PMC_PLL_CTRL1, &val);
  137. if (sam9x60_pll_ready(base, pll->id))
  138. return 0;
  139. pmc_update_bits(base, AT91_PMC_PLL_UPDT,
  140. AT91_PMC_PMM_UPDT_STUPTIM_MSK |
  141. AT91_PMC_PLL_UPDT_ID_MSK,
  142. AT91_PMC_PLL_UPDT_STUPTIM(0x3f) | pll->id);
  143. /* Recommended value for AT91_PMC_PLL_ACR */
  144. if (pll->characteristics->upll)
  145. val = AT91_PMC_PLL_ACR_DEFAULT_UPLL;
  146. else
  147. val = AT91_PMC_PLL_ACR_DEFAULT_PLLA;
  148. pmc_write(base, AT91_PMC_PLL_ACR, val);
  149. if (pll->characteristics->upll) {
  150. /* Enable the UTMI internal bandgap */
  151. val |= AT91_PMC_PLL_ACR_UTMIBG;
  152. pmc_write(base, AT91_PMC_PLL_ACR, val);
  153. udelay(10);
  154. /* Enable the UTMI internal regulator */
  155. val |= AT91_PMC_PLL_ACR_UTMIVR;
  156. pmc_write(base, AT91_PMC_PLL_ACR, val);
  157. udelay(10);
  158. pmc_update_bits(base, AT91_PMC_PLL_UPDT,
  159. AT91_PMC_PLL_UPDT_UPDATE |
  160. AT91_PMC_PLL_UPDT_ID_MSK,
  161. AT91_PMC_PLL_UPDT_UPDATE | pll->id);
  162. }
  163. pmc_update_bits(base, AT91_PMC_PLL_CTRL0,
  164. AT91_PMC_PLL_CTRL0_ENLOCK | AT91_PMC_PLL_CTRL0_ENPLL,
  165. AT91_PMC_PLL_CTRL0_ENLOCK | AT91_PMC_PLL_CTRL0_ENPLL);
  166. pmc_update_bits(base, AT91_PMC_PLL_UPDT,
  167. AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
  168. AT91_PMC_PLL_UPDT_UPDATE | pll->id);
  169. while (!sam9x60_pll_ready(base, pll->id)) {
  170. debug("waiting for pll %u...\n", pll->id);
  171. cpu_relax();
  172. }
  173. return 0;
  174. }
  175. static int sam9x60_frac_pll_disable(struct clk *clk)
  176. {
  177. struct sam9x60_pll *pll = to_sam9x60_pll(clk);
  178. void __iomem *base = pll->base;
  179. pmc_update_bits(base, AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MSK,
  180. pll->id);
  181. pmc_update_bits(base, AT91_PMC_PLL_CTRL0,
  182. AT91_PMC_PLL_CTRL0_ENPLL, 0);
  183. if (pll->characteristics->upll)
  184. pmc_update_bits(base, AT91_PMC_PLL_ACR,
  185. AT91_PMC_PLL_ACR_UTMIBG |
  186. AT91_PMC_PLL_ACR_UTMIVR, 0);
  187. pmc_update_bits(base, AT91_PMC_PLL_UPDT,
  188. AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
  189. AT91_PMC_PLL_UPDT_UPDATE | pll->id);
  190. return 0;
  191. }
  192. static const struct clk_ops sam9x60_frac_pll_ops = {
  193. .enable = sam9x60_frac_pll_enable,
  194. .disable = sam9x60_frac_pll_disable,
  195. .set_rate = sam9x60_frac_pll_set_rate,
  196. .get_rate = sam9x60_frac_pll_get_rate,
  197. };
  198. static int sam9x60_div_pll_enable(struct clk *clk)
  199. {
  200. struct sam9x60_pll *pll = to_sam9x60_pll(clk);
  201. void __iomem *base = pll->base;
  202. unsigned int val;
  203. pmc_update_bits(base, AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MSK,
  204. pll->id);
  205. pmc_read(base, AT91_PMC_PLL_CTRL0, &val);
  206. /* Stop if enabled. */
  207. if (val & pll->layout->endiv_mask)
  208. return 0;
  209. pmc_update_bits(base, AT91_PMC_PLL_CTRL0,
  210. pll->layout->endiv_mask,
  211. (1 << pll->layout->endiv_shift));
  212. pmc_update_bits(base, AT91_PMC_PLL_UPDT,
  213. AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
  214. AT91_PMC_PLL_UPDT_UPDATE | pll->id);
  215. while (!sam9x60_pll_ready(base, pll->id)) {
  216. debug("waiting for pll %u...\n", pll->id);
  217. cpu_relax();
  218. }
  219. return 0;
  220. }
  221. static int sam9x60_div_pll_disable(struct clk *clk)
  222. {
  223. struct sam9x60_pll *pll = to_sam9x60_pll(clk);
  224. void __iomem *base = pll->base;
  225. pmc_update_bits(base, AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MSK,
  226. pll->id);
  227. pmc_update_bits(base, AT91_PMC_PLL_CTRL0,
  228. pll->layout->endiv_mask, 0);
  229. pmc_update_bits(base, AT91_PMC_PLL_UPDT,
  230. AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
  231. AT91_PMC_PLL_UPDT_UPDATE | pll->id);
  232. return 0;
  233. }
  234. static ulong sam9x60_div_pll_set_rate(struct clk *clk, ulong rate)
  235. {
  236. struct sam9x60_pll *pll = to_sam9x60_pll(clk);
  237. void __iomem *base = pll->base;
  238. const struct clk_pll_characteristics *characteristics =
  239. pll->characteristics;
  240. ulong parent_rate = clk_get_parent_rate(clk);
  241. u8 div = DIV_ROUND_CLOSEST_ULL(parent_rate, rate) - 1;
  242. ulong req_rate = parent_rate / (div + 1);
  243. bool ready = sam9x60_pll_ready(base, pll->id);
  244. u32 val;
  245. if (!parent_rate || div > pll->layout->div_mask ||
  246. req_rate < characteristics->output[0].min ||
  247. req_rate > characteristics->output[0].max)
  248. return 0;
  249. pmc_update_bits(base, AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MSK,
  250. pll->id);
  251. pmc_read(base, AT91_PMC_PLL_CTRL0, &val);
  252. /* Compare against current value. */
  253. if (div == ((val & pll->layout->div_mask) >> pll->layout->div_shift))
  254. return 0;
  255. /* Update it to hardware. */
  256. pmc_update_bits(base, AT91_PMC_PLL_CTRL0,
  257. pll->layout->div_mask,
  258. div << pll->layout->div_shift);
  259. pmc_update_bits(base, AT91_PMC_PLL_UPDT,
  260. AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
  261. AT91_PMC_PLL_UPDT_UPDATE | pll->id);
  262. while (ready && !sam9x60_pll_ready(base, pll->id)) {
  263. debug("waiting for pll %u...\n", pll->id);
  264. cpu_relax();
  265. }
  266. return req_rate;
  267. }
  268. static ulong sam9x60_div_pll_get_rate(struct clk *clk)
  269. {
  270. struct sam9x60_pll *pll = to_sam9x60_pll(clk);
  271. void __iomem *base = pll->base;
  272. ulong parent_rate = clk_get_parent_rate(clk);
  273. u32 val;
  274. u8 div;
  275. if (!parent_rate)
  276. return 0;
  277. pmc_update_bits(base, AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MSK,
  278. pll->id);
  279. pmc_read(base, AT91_PMC_PLL_CTRL0, &val);
  280. div = (val & pll->layout->div_mask) >> pll->layout->div_shift;
  281. return parent_rate / (div + 1);
  282. }
  283. static const struct clk_ops sam9x60_div_pll_ops = {
  284. .enable = sam9x60_div_pll_enable,
  285. .disable = sam9x60_div_pll_disable,
  286. .set_rate = sam9x60_div_pll_set_rate,
  287. .get_rate = sam9x60_div_pll_get_rate,
  288. };
  289. static struct clk *
  290. sam9x60_clk_register_pll(void __iomem *base, const char *type,
  291. const char *name, const char *parent_name, u8 id,
  292. const struct clk_pll_characteristics *characteristics,
  293. const struct clk_pll_layout *layout, u32 flags)
  294. {
  295. struct sam9x60_pll *pll;
  296. struct clk *clk;
  297. int ret;
  298. if (!base || !type || !name || !parent_name || !characteristics ||
  299. !layout || id > PLL_MAX_ID)
  300. return ERR_PTR(-EINVAL);
  301. pll = kzalloc(sizeof(*pll), GFP_KERNEL);
  302. if (!pll)
  303. return ERR_PTR(-ENOMEM);
  304. pll->id = id;
  305. pll->characteristics = characteristics;
  306. pll->layout = layout;
  307. pll->base = base;
  308. clk = &pll->clk;
  309. clk->flags = flags;
  310. ret = clk_register(clk, type, name, parent_name);
  311. if (ret) {
  312. kfree(pll);
  313. clk = ERR_PTR(ret);
  314. }
  315. return clk;
  316. }
  317. struct clk *
  318. sam9x60_clk_register_div_pll(void __iomem *base, const char *name,
  319. const char *parent_name, u8 id,
  320. const struct clk_pll_characteristics *characteristics,
  321. const struct clk_pll_layout *layout, bool critical)
  322. {
  323. return sam9x60_clk_register_pll(base,
  324. UBOOT_DM_CLK_AT91_SAM9X60_DIV_PLL, name, parent_name, id,
  325. characteristics, layout,
  326. CLK_GET_RATE_NOCACHE | (critical ? CLK_IS_CRITICAL : 0));
  327. }
  328. struct clk *
  329. sam9x60_clk_register_frac_pll(void __iomem *base, const char *name,
  330. const char *parent_name, u8 id,
  331. const struct clk_pll_characteristics *characteristics,
  332. const struct clk_pll_layout *layout, bool critical)
  333. {
  334. return sam9x60_clk_register_pll(base,
  335. UBOOT_DM_CLK_AT91_SAM9X60_FRAC_PLL, name, parent_name, id,
  336. characteristics, layout,
  337. CLK_GET_RATE_NOCACHE | (critical ? CLK_IS_CRITICAL : 0));
  338. }
  339. U_BOOT_DRIVER(at91_sam9x60_div_pll_clk) = {
  340. .name = UBOOT_DM_CLK_AT91_SAM9X60_DIV_PLL,
  341. .id = UCLASS_CLK,
  342. .ops = &sam9x60_div_pll_ops,
  343. .flags = DM_FLAG_PRE_RELOC,
  344. };
  345. U_BOOT_DRIVER(at91_sam9x60_frac_pll_clk) = {
  346. .name = UBOOT_DM_CLK_AT91_SAM9X60_FRAC_PLL,
  347. .id = UCLASS_CLK,
  348. .ops = &sam9x60_frac_pll_ops,
  349. .flags = DM_FLAG_PRE_RELOC,
  350. };