clk-cv18xx-pll.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2023 Inochi Amaoto <inochiama@outlook.com>
  4. */
  5. #include <linux/clk-provider.h>
  6. #include <linux/io.h>
  7. #include <linux/limits.h>
  8. #include <linux/spinlock.h>
  9. #include "clk-cv18xx-pll.h"
  10. static inline struct cv1800_clk_pll *hw_to_cv1800_clk_pll(struct clk_hw *hw)
  11. {
  12. struct cv1800_clk_common *common = hw_to_cv1800_clk_common(hw);
  13. return container_of(common, struct cv1800_clk_pll, common);
  14. }
  15. static unsigned long ipll_calc_rate(unsigned long parent_rate,
  16. unsigned long pre_div_sel,
  17. unsigned long div_sel,
  18. unsigned long post_div_sel)
  19. {
  20. uint64_t rate = parent_rate;
  21. rate *= div_sel;
  22. do_div(rate, pre_div_sel * post_div_sel);
  23. return rate;
  24. }
  25. static unsigned long ipll_recalc_rate(struct clk_hw *hw,
  26. unsigned long parent_rate)
  27. {
  28. struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw);
  29. u32 value;
  30. value = readl(pll->common.base + pll->pll_reg);
  31. return ipll_calc_rate(parent_rate,
  32. PLL_GET_PRE_DIV_SEL(value),
  33. PLL_GET_DIV_SEL(value),
  34. PLL_GET_POST_DIV_SEL(value));
  35. }
  36. static int ipll_find_rate(const struct cv1800_clk_pll_limit *limit,
  37. unsigned long prate, unsigned long *rate,
  38. u32 *value)
  39. {
  40. unsigned long best_rate = 0;
  41. unsigned long trate = *rate;
  42. unsigned long pre_div_sel = 0, div_sel = 0, post_div_sel = 0;
  43. unsigned long pre, div, post;
  44. u32 detected = *value;
  45. unsigned long tmp;
  46. for_each_pll_limit_range(pre, &limit->pre_div) {
  47. for_each_pll_limit_range(div, &limit->div) {
  48. for_each_pll_limit_range(post, &limit->post_div) {
  49. tmp = ipll_calc_rate(prate, pre, div, post);
  50. if (tmp > trate)
  51. continue;
  52. if ((trate - tmp) < (trate - best_rate)) {
  53. best_rate = tmp;
  54. pre_div_sel = pre;
  55. div_sel = div;
  56. post_div_sel = post;
  57. }
  58. }
  59. }
  60. }
  61. if (best_rate) {
  62. detected = PLL_SET_PRE_DIV_SEL(detected, pre_div_sel);
  63. detected = PLL_SET_POST_DIV_SEL(detected, post_div_sel);
  64. detected = PLL_SET_DIV_SEL(detected, div_sel);
  65. *value = detected;
  66. *rate = best_rate;
  67. return 0;
  68. }
  69. return -EINVAL;
  70. }
  71. static int ipll_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
  72. {
  73. u32 val;
  74. struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw);
  75. return ipll_find_rate(pll->pll_limit, req->best_parent_rate,
  76. &req->rate, &val);
  77. }
  78. static void pll_get_mode_ctrl(unsigned long div_sel,
  79. bool (*mode_ctrl_check)(unsigned long,
  80. unsigned long,
  81. unsigned long),
  82. const struct cv1800_clk_pll_limit *limit,
  83. u32 *value)
  84. {
  85. unsigned long ictrl = 0, mode = 0;
  86. u32 detected = *value;
  87. for_each_pll_limit_range(mode, &limit->mode) {
  88. for_each_pll_limit_range(ictrl, &limit->ictrl) {
  89. if (mode_ctrl_check(div_sel, ictrl, mode)) {
  90. detected = PLL_SET_SEL_MODE(detected, mode);
  91. detected = PLL_SET_ICTRL(detected, ictrl);
  92. *value = detected;
  93. return;
  94. }
  95. }
  96. }
  97. }
  98. static bool ipll_check_mode_ctrl_restrict(unsigned long div_sel,
  99. unsigned long ictrl,
  100. unsigned long mode)
  101. {
  102. unsigned long left_rest = 20 * div_sel;
  103. unsigned long right_rest = 35 * div_sel;
  104. unsigned long test = 184 * (1 + mode) * (1 + ictrl) / 2;
  105. return test > left_rest && test <= right_rest;
  106. }
  107. static int ipll_set_rate(struct clk_hw *hw, unsigned long rate,
  108. unsigned long parent_rate)
  109. {
  110. u32 regval, detected = 0;
  111. unsigned long flags;
  112. struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw);
  113. ipll_find_rate(pll->pll_limit, parent_rate, &rate, &detected);
  114. pll_get_mode_ctrl(PLL_GET_DIV_SEL(detected),
  115. ipll_check_mode_ctrl_restrict,
  116. pll->pll_limit, &detected);
  117. spin_lock_irqsave(pll->common.lock, flags);
  118. regval = readl(pll->common.base + pll->pll_reg);
  119. regval = PLL_COPY_REG(regval, detected);
  120. writel(regval, pll->common.base + pll->pll_reg);
  121. spin_unlock_irqrestore(pll->common.lock, flags);
  122. cv1800_clk_wait_for_lock(&pll->common, pll->pll_status.reg,
  123. BIT(pll->pll_status.shift));
  124. return 0;
  125. }
  126. static int pll_enable(struct clk_hw *hw)
  127. {
  128. struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw);
  129. return cv1800_clk_clearbit(&pll->common, &pll->pll_pwd);
  130. }
  131. static void pll_disable(struct clk_hw *hw)
  132. {
  133. struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw);
  134. cv1800_clk_setbit(&pll->common, &pll->pll_pwd);
  135. }
  136. static int pll_is_enable(struct clk_hw *hw)
  137. {
  138. struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw);
  139. return cv1800_clk_checkbit(&pll->common, &pll->pll_pwd) == 0;
  140. }
  141. const struct clk_ops cv1800_clk_ipll_ops = {
  142. .disable = pll_disable,
  143. .enable = pll_enable,
  144. .is_enabled = pll_is_enable,
  145. .recalc_rate = ipll_recalc_rate,
  146. .determine_rate = ipll_determine_rate,
  147. .set_rate = ipll_set_rate,
  148. };
  149. #define PLL_SYN_FACTOR_DOT_POS 26
  150. #define PLL_SYN_FACTOR_MINIMUM ((4 << PLL_SYN_FACTOR_DOT_POS) + 1)
  151. static bool fpll_is_factional_mode(struct cv1800_clk_pll *pll)
  152. {
  153. return cv1800_clk_checkbit(&pll->common, &pll->pll_syn->en);
  154. }
  155. static unsigned long fpll_calc_rate(unsigned long parent_rate,
  156. unsigned long pre_div_sel,
  157. unsigned long div_sel,
  158. unsigned long post_div_sel,
  159. unsigned long ssc_syn_set,
  160. bool is_full_parent)
  161. {
  162. u64 dividend = parent_rate * div_sel;
  163. u64 factor = ssc_syn_set * pre_div_sel * post_div_sel;
  164. unsigned long rate;
  165. dividend <<= PLL_SYN_FACTOR_DOT_POS - 1;
  166. rate = div64_u64_rem(dividend, factor, &dividend);
  167. if (is_full_parent) {
  168. dividend <<= 1;
  169. rate <<= 1;
  170. }
  171. rate += DIV64_U64_ROUND_CLOSEST(dividend, factor);
  172. return rate;
  173. }
  174. static unsigned long fpll_recalc_rate(struct clk_hw *hw,
  175. unsigned long parent_rate)
  176. {
  177. struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw);
  178. u32 value;
  179. bool clk_full;
  180. u32 syn_set;
  181. if (!fpll_is_factional_mode(pll))
  182. return ipll_recalc_rate(hw, parent_rate);
  183. syn_set = readl(pll->common.base + pll->pll_syn->set);
  184. if (syn_set == 0)
  185. return 0;
  186. clk_full = cv1800_clk_checkbit(&pll->common,
  187. &pll->pll_syn->clk_half);
  188. value = readl(pll->common.base + pll->pll_reg);
  189. return fpll_calc_rate(parent_rate,
  190. PLL_GET_PRE_DIV_SEL(value),
  191. PLL_GET_DIV_SEL(value),
  192. PLL_GET_POST_DIV_SEL(value),
  193. syn_set, clk_full);
  194. }
  195. static unsigned long fpll_find_synthesizer(unsigned long parent,
  196. unsigned long rate,
  197. unsigned long pre_div,
  198. unsigned long div,
  199. unsigned long post_div,
  200. bool is_full_parent,
  201. u32 *ssc_syn_set)
  202. {
  203. u32 test_max = U32_MAX, test_min = PLL_SYN_FACTOR_MINIMUM;
  204. unsigned long trate;
  205. while (test_min < test_max) {
  206. u32 tssc = (test_max + test_min) / 2;
  207. trate = fpll_calc_rate(parent, pre_div, div, post_div,
  208. tssc, is_full_parent);
  209. if (trate == rate) {
  210. test_min = tssc;
  211. break;
  212. }
  213. if (trate > rate)
  214. test_min = tssc + 1;
  215. else
  216. test_max = tssc - 1;
  217. }
  218. if (trate != 0)
  219. *ssc_syn_set = test_min;
  220. return trate;
  221. }
  222. static int fpll_find_rate(struct cv1800_clk_pll *pll,
  223. const struct cv1800_clk_pll_limit *limit,
  224. unsigned long prate,
  225. unsigned long *rate,
  226. u32 *value, u32 *ssc_syn_set)
  227. {
  228. unsigned long best_rate = 0;
  229. unsigned long pre_div_sel = 0, div_sel = 0, post_div_sel = 0;
  230. unsigned long pre, div, post;
  231. unsigned long trate = *rate;
  232. u32 detected = *value;
  233. unsigned long tmp;
  234. bool clk_full = cv1800_clk_checkbit(&pll->common,
  235. &pll->pll_syn->clk_half);
  236. for_each_pll_limit_range(pre, &limit->pre_div) {
  237. for_each_pll_limit_range(post, &limit->post_div) {
  238. for_each_pll_limit_range(div, &limit->div) {
  239. tmp = fpll_find_synthesizer(prate, trate,
  240. pre, div, post,
  241. clk_full,
  242. ssc_syn_set);
  243. if ((trate - tmp) < (trate - best_rate)) {
  244. best_rate = tmp;
  245. pre_div_sel = pre;
  246. div_sel = div;
  247. post_div_sel = post;
  248. }
  249. }
  250. }
  251. }
  252. if (best_rate) {
  253. detected = PLL_SET_PRE_DIV_SEL(detected, pre_div_sel);
  254. detected = PLL_SET_POST_DIV_SEL(detected, post_div_sel);
  255. detected = PLL_SET_DIV_SEL(detected, div_sel);
  256. *value = detected;
  257. *rate = best_rate;
  258. return 0;
  259. }
  260. return -EINVAL;
  261. }
  262. static int fpll_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
  263. {
  264. struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw);
  265. u32 val, ssc_syn_set;
  266. if (!fpll_is_factional_mode(pll))
  267. return ipll_determine_rate(hw, req);
  268. fpll_find_rate(pll, &pll->pll_limit[2], req->best_parent_rate,
  269. &req->rate, &val, &ssc_syn_set);
  270. return 0;
  271. }
  272. static bool fpll_check_mode_ctrl_restrict(unsigned long div_sel,
  273. unsigned long ictrl,
  274. unsigned long mode)
  275. {
  276. unsigned long left_rest = 10 * div_sel;
  277. unsigned long right_rest = 24 * div_sel;
  278. unsigned long test = 184 * (1 + mode) * (1 + ictrl) / 2;
  279. return test > left_rest && test <= right_rest;
  280. }
  281. static int fpll_set_rate(struct clk_hw *hw, unsigned long rate,
  282. unsigned long parent_rate)
  283. {
  284. u32 regval;
  285. u32 detected = 0, detected_ssc = 0;
  286. unsigned long flags;
  287. struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw);
  288. if (!fpll_is_factional_mode(pll))
  289. return ipll_set_rate(hw, rate, parent_rate);
  290. fpll_find_rate(pll, &pll->pll_limit[2], parent_rate,
  291. &rate, &detected, &detected_ssc);
  292. pll_get_mode_ctrl(PLL_GET_DIV_SEL(detected),
  293. fpll_check_mode_ctrl_restrict,
  294. pll->pll_limit, &detected);
  295. spin_lock_irqsave(pll->common.lock, flags);
  296. writel(detected_ssc, pll->common.base + pll->pll_syn->set);
  297. regval = readl(pll->common.base + pll->pll_reg);
  298. regval = PLL_COPY_REG(regval, detected);
  299. writel(regval, pll->common.base + pll->pll_reg);
  300. spin_unlock_irqrestore(pll->common.lock, flags);
  301. cv1800_clk_wait_for_lock(&pll->common, pll->pll_status.reg,
  302. BIT(pll->pll_status.shift));
  303. return 0;
  304. }
  305. static u8 fpll_get_parent(struct clk_hw *hw)
  306. {
  307. struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw);
  308. if (fpll_is_factional_mode(pll))
  309. return 1;
  310. return 0;
  311. }
  312. static int fpll_set_parent(struct clk_hw *hw, u8 index)
  313. {
  314. struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw);
  315. if (index)
  316. cv1800_clk_setbit(&pll->common, &pll->pll_syn->en);
  317. else
  318. cv1800_clk_clearbit(&pll->common, &pll->pll_syn->en);
  319. return 0;
  320. }
  321. const struct clk_ops cv1800_clk_fpll_ops = {
  322. .disable = pll_disable,
  323. .enable = pll_enable,
  324. .is_enabled = pll_is_enable,
  325. .recalc_rate = fpll_recalc_rate,
  326. .determine_rate = fpll_determine_rate,
  327. .set_rate = fpll_set_rate,
  328. .set_parent = fpll_set_parent,
  329. .get_parent = fpll_get_parent,
  330. };