clk-master.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (C) 2013 Boris BREZILLON <[email protected]>
  4. */
  5. #include <linux/clk-provider.h>
  6. #include <linux/clkdev.h>
  7. #include <linux/clk.h>
  8. #include <linux/clk/at91_pmc.h>
  9. #include <linux/of.h>
  10. #include <linux/mfd/syscon.h>
  11. #include <linux/regmap.h>
  12. #include "pmc.h"
  13. #define MASTER_PRES_MASK 0x7
  14. #define MASTER_PRES_MAX MASTER_PRES_MASK
  15. #define MASTER_DIV_SHIFT 8
  16. #define MASTER_DIV_MASK 0x7
  17. #define PMC_MCR_CSS_SHIFT (16)
  18. #define MASTER_MAX_ID 4
  19. #define to_clk_master(hw) container_of(hw, struct clk_master, hw)
  20. struct clk_master {
  21. struct clk_hw hw;
  22. struct regmap *regmap;
  23. spinlock_t *lock;
  24. const struct clk_master_layout *layout;
  25. const struct clk_master_characteristics *characteristics;
  26. struct at91_clk_pms pms;
  27. u32 *mux_table;
  28. u32 mckr;
  29. int chg_pid;
  30. u8 id;
  31. u8 parent;
  32. u8 div;
  33. u32 safe_div;
  34. };
  35. /* MCK div reference to be used by notifier. */
  36. static struct clk_master *master_div;
  37. static inline bool clk_master_ready(struct clk_master *master)
  38. {
  39. unsigned int bit = master->id ? AT91_PMC_MCKXRDY : AT91_PMC_MCKRDY;
  40. unsigned int status;
  41. regmap_read(master->regmap, AT91_PMC_SR, &status);
  42. return !!(status & bit);
  43. }
  44. static int clk_master_prepare(struct clk_hw *hw)
  45. {
  46. struct clk_master *master = to_clk_master(hw);
  47. unsigned long flags;
  48. spin_lock_irqsave(master->lock, flags);
  49. while (!clk_master_ready(master))
  50. cpu_relax();
  51. spin_unlock_irqrestore(master->lock, flags);
  52. return 0;
  53. }
  54. static int clk_master_is_prepared(struct clk_hw *hw)
  55. {
  56. struct clk_master *master = to_clk_master(hw);
  57. unsigned long flags;
  58. bool status;
  59. spin_lock_irqsave(master->lock, flags);
  60. status = clk_master_ready(master);
  61. spin_unlock_irqrestore(master->lock, flags);
  62. return status;
  63. }
  64. static unsigned long clk_master_div_recalc_rate(struct clk_hw *hw,
  65. unsigned long parent_rate)
  66. {
  67. u8 div;
  68. unsigned long flags, rate = parent_rate;
  69. struct clk_master *master = to_clk_master(hw);
  70. const struct clk_master_layout *layout = master->layout;
  71. const struct clk_master_characteristics *characteristics =
  72. master->characteristics;
  73. unsigned int mckr;
  74. spin_lock_irqsave(master->lock, flags);
  75. regmap_read(master->regmap, master->layout->offset, &mckr);
  76. spin_unlock_irqrestore(master->lock, flags);
  77. mckr &= layout->mask;
  78. div = (mckr >> MASTER_DIV_SHIFT) & MASTER_DIV_MASK;
  79. rate /= characteristics->divisors[div];
  80. if (rate < characteristics->output.min)
  81. pr_warn("master clk div is underclocked");
  82. else if (rate > characteristics->output.max)
  83. pr_warn("master clk div is overclocked");
  84. return rate;
  85. }
  86. static int clk_master_div_save_context(struct clk_hw *hw)
  87. {
  88. struct clk_master *master = to_clk_master(hw);
  89. struct clk_hw *parent_hw = clk_hw_get_parent(hw);
  90. unsigned long flags;
  91. unsigned int mckr, div;
  92. spin_lock_irqsave(master->lock, flags);
  93. regmap_read(master->regmap, master->layout->offset, &mckr);
  94. spin_unlock_irqrestore(master->lock, flags);
  95. mckr &= master->layout->mask;
  96. div = (mckr >> MASTER_DIV_SHIFT) & MASTER_DIV_MASK;
  97. div = master->characteristics->divisors[div];
  98. master->pms.parent_rate = clk_hw_get_rate(parent_hw);
  99. master->pms.rate = DIV_ROUND_CLOSEST(master->pms.parent_rate, div);
  100. return 0;
  101. }
  102. static void clk_master_div_restore_context(struct clk_hw *hw)
  103. {
  104. struct clk_master *master = to_clk_master(hw);
  105. unsigned long flags;
  106. unsigned int mckr;
  107. u8 div;
  108. spin_lock_irqsave(master->lock, flags);
  109. regmap_read(master->regmap, master->layout->offset, &mckr);
  110. spin_unlock_irqrestore(master->lock, flags);
  111. mckr &= master->layout->mask;
  112. div = (mckr >> MASTER_DIV_SHIFT) & MASTER_DIV_MASK;
  113. div = master->characteristics->divisors[div];
  114. if (div != DIV_ROUND_CLOSEST(master->pms.parent_rate, master->pms.rate))
  115. pr_warn("MCKR DIV not configured properly by firmware!\n");
  116. }
  117. static const struct clk_ops master_div_ops = {
  118. .prepare = clk_master_prepare,
  119. .is_prepared = clk_master_is_prepared,
  120. .recalc_rate = clk_master_div_recalc_rate,
  121. .save_context = clk_master_div_save_context,
  122. .restore_context = clk_master_div_restore_context,
  123. };
  124. /* This function must be called with lock acquired. */
  125. static int clk_master_div_set(struct clk_master *master,
  126. unsigned long parent_rate, int div)
  127. {
  128. const struct clk_master_characteristics *characteristics =
  129. master->characteristics;
  130. unsigned long rate = parent_rate;
  131. unsigned int max_div = 0, div_index = 0, max_div_index = 0;
  132. unsigned int i, mckr, tmp;
  133. int ret;
  134. for (i = 0; i < ARRAY_SIZE(characteristics->divisors); i++) {
  135. if (!characteristics->divisors[i])
  136. break;
  137. if (div == characteristics->divisors[i])
  138. div_index = i;
  139. if (max_div < characteristics->divisors[i]) {
  140. max_div = characteristics->divisors[i];
  141. max_div_index = i;
  142. }
  143. }
  144. if (div > max_div)
  145. div_index = max_div_index;
  146. ret = regmap_read(master->regmap, master->layout->offset, &mckr);
  147. if (ret)
  148. return ret;
  149. mckr &= master->layout->mask;
  150. tmp = (mckr >> MASTER_DIV_SHIFT) & MASTER_DIV_MASK;
  151. if (tmp == div_index)
  152. return 0;
  153. rate /= characteristics->divisors[div_index];
  154. if (rate < characteristics->output.min)
  155. pr_warn("master clk div is underclocked");
  156. else if (rate > characteristics->output.max)
  157. pr_warn("master clk div is overclocked");
  158. mckr &= ~(MASTER_DIV_MASK << MASTER_DIV_SHIFT);
  159. mckr |= (div_index << MASTER_DIV_SHIFT);
  160. ret = regmap_write(master->regmap, master->layout->offset, mckr);
  161. if (ret)
  162. return ret;
  163. while (!clk_master_ready(master))
  164. cpu_relax();
  165. master->div = characteristics->divisors[div_index];
  166. return 0;
  167. }
  168. static unsigned long clk_master_div_recalc_rate_chg(struct clk_hw *hw,
  169. unsigned long parent_rate)
  170. {
  171. struct clk_master *master = to_clk_master(hw);
  172. return DIV_ROUND_CLOSEST_ULL(parent_rate, master->div);
  173. }
  174. static void clk_master_div_restore_context_chg(struct clk_hw *hw)
  175. {
  176. struct clk_master *master = to_clk_master(hw);
  177. unsigned long flags;
  178. int ret;
  179. spin_lock_irqsave(master->lock, flags);
  180. ret = clk_master_div_set(master, master->pms.parent_rate,
  181. DIV_ROUND_CLOSEST(master->pms.parent_rate,
  182. master->pms.rate));
  183. spin_unlock_irqrestore(master->lock, flags);
  184. if (ret)
  185. pr_warn("Failed to restore MCK DIV clock\n");
  186. }
  187. static const struct clk_ops master_div_ops_chg = {
  188. .prepare = clk_master_prepare,
  189. .is_prepared = clk_master_is_prepared,
  190. .recalc_rate = clk_master_div_recalc_rate_chg,
  191. .save_context = clk_master_div_save_context,
  192. .restore_context = clk_master_div_restore_context_chg,
  193. };
  194. static int clk_master_div_notifier_fn(struct notifier_block *notifier,
  195. unsigned long code, void *data)
  196. {
  197. const struct clk_master_characteristics *characteristics =
  198. master_div->characteristics;
  199. struct clk_notifier_data *cnd = data;
  200. unsigned long flags, new_parent_rate, new_rate;
  201. unsigned int mckr, div, new_div = 0;
  202. int ret, i;
  203. long tmp_diff;
  204. long best_diff = -1;
  205. spin_lock_irqsave(master_div->lock, flags);
  206. switch (code) {
  207. case PRE_RATE_CHANGE:
  208. /*
  209. * We want to avoid any overclocking of MCK DIV domain. To do
  210. * this we set a safe divider (the underclocking is not of
  211. * interest as we can go as low as 32KHz). The relation
  212. * b/w this clock and its parents are as follows:
  213. *
  214. * FRAC PLL -> DIV PLL -> MCK DIV
  215. *
  216. * With the proper safe divider we should be good even with FRAC
  217. * PLL at its maximum value.
  218. */
  219. ret = regmap_read(master_div->regmap, master_div->layout->offset,
  220. &mckr);
  221. if (ret) {
  222. ret = NOTIFY_STOP_MASK;
  223. goto unlock;
  224. }
  225. mckr &= master_div->layout->mask;
  226. div = (mckr >> MASTER_DIV_SHIFT) & MASTER_DIV_MASK;
  227. /* Switch to safe divider. */
  228. clk_master_div_set(master_div,
  229. cnd->old_rate * characteristics->divisors[div],
  230. master_div->safe_div);
  231. break;
  232. case POST_RATE_CHANGE:
  233. /*
  234. * At this point we want to restore MCK DIV domain to its maximum
  235. * allowed rate.
  236. */
  237. ret = regmap_read(master_div->regmap, master_div->layout->offset,
  238. &mckr);
  239. if (ret) {
  240. ret = NOTIFY_STOP_MASK;
  241. goto unlock;
  242. }
  243. mckr &= master_div->layout->mask;
  244. div = (mckr >> MASTER_DIV_SHIFT) & MASTER_DIV_MASK;
  245. new_parent_rate = cnd->new_rate * characteristics->divisors[div];
  246. for (i = 0; i < ARRAY_SIZE(characteristics->divisors); i++) {
  247. if (!characteristics->divisors[i])
  248. break;
  249. new_rate = DIV_ROUND_CLOSEST_ULL(new_parent_rate,
  250. characteristics->divisors[i]);
  251. tmp_diff = characteristics->output.max - new_rate;
  252. if (tmp_diff < 0)
  253. continue;
  254. if (best_diff < 0 || best_diff > tmp_diff) {
  255. new_div = characteristics->divisors[i];
  256. best_diff = tmp_diff;
  257. }
  258. if (!tmp_diff)
  259. break;
  260. }
  261. if (!new_div) {
  262. ret = NOTIFY_STOP_MASK;
  263. goto unlock;
  264. }
  265. /* Update the div to preserve MCK DIV clock rate. */
  266. clk_master_div_set(master_div, new_parent_rate,
  267. new_div);
  268. ret = NOTIFY_OK;
  269. break;
  270. default:
  271. ret = NOTIFY_DONE;
  272. break;
  273. }
  274. unlock:
  275. spin_unlock_irqrestore(master_div->lock, flags);
  276. return ret;
  277. }
  278. static struct notifier_block clk_master_div_notifier = {
  279. .notifier_call = clk_master_div_notifier_fn,
  280. };
  281. static void clk_sama7g5_master_best_diff(struct clk_rate_request *req,
  282. struct clk_hw *parent,
  283. unsigned long parent_rate,
  284. long *best_rate,
  285. long *best_diff,
  286. u32 div)
  287. {
  288. unsigned long tmp_rate, tmp_diff;
  289. if (div == MASTER_PRES_MAX)
  290. tmp_rate = parent_rate / 3;
  291. else
  292. tmp_rate = parent_rate >> div;
  293. tmp_diff = abs(req->rate - tmp_rate);
  294. if (*best_diff < 0 || *best_diff >= tmp_diff) {
  295. *best_rate = tmp_rate;
  296. *best_diff = tmp_diff;
  297. req->best_parent_rate = parent_rate;
  298. req->best_parent_hw = parent;
  299. }
  300. }
  301. static unsigned long clk_master_pres_recalc_rate(struct clk_hw *hw,
  302. unsigned long parent_rate)
  303. {
  304. struct clk_master *master = to_clk_master(hw);
  305. const struct clk_master_characteristics *characteristics =
  306. master->characteristics;
  307. unsigned long flags;
  308. unsigned int val, pres;
  309. spin_lock_irqsave(master->lock, flags);
  310. regmap_read(master->regmap, master->layout->offset, &val);
  311. spin_unlock_irqrestore(master->lock, flags);
  312. val &= master->layout->mask;
  313. pres = (val >> master->layout->pres_shift) & MASTER_PRES_MASK;
  314. if (pres == MASTER_PRES_MAX && characteristics->have_div3_pres)
  315. pres = 3;
  316. else
  317. pres = (1 << pres);
  318. return DIV_ROUND_CLOSEST_ULL(parent_rate, pres);
  319. }
  320. static u8 clk_master_pres_get_parent(struct clk_hw *hw)
  321. {
  322. struct clk_master *master = to_clk_master(hw);
  323. unsigned long flags;
  324. unsigned int mckr;
  325. spin_lock_irqsave(master->lock, flags);
  326. regmap_read(master->regmap, master->layout->offset, &mckr);
  327. spin_unlock_irqrestore(master->lock, flags);
  328. mckr &= master->layout->mask;
  329. return mckr & AT91_PMC_CSS;
  330. }
  331. static int clk_master_pres_save_context(struct clk_hw *hw)
  332. {
  333. struct clk_master *master = to_clk_master(hw);
  334. struct clk_hw *parent_hw = clk_hw_get_parent(hw);
  335. unsigned long flags;
  336. unsigned int val, pres;
  337. spin_lock_irqsave(master->lock, flags);
  338. regmap_read(master->regmap, master->layout->offset, &val);
  339. spin_unlock_irqrestore(master->lock, flags);
  340. val &= master->layout->mask;
  341. pres = (val >> master->layout->pres_shift) & MASTER_PRES_MASK;
  342. if (pres == MASTER_PRES_MAX && master->characteristics->have_div3_pres)
  343. pres = 3;
  344. else
  345. pres = (1 << pres);
  346. master->pms.parent = val & AT91_PMC_CSS;
  347. master->pms.parent_rate = clk_hw_get_rate(parent_hw);
  348. master->pms.rate = DIV_ROUND_CLOSEST_ULL(master->pms.parent_rate, pres);
  349. return 0;
  350. }
  351. static void clk_master_pres_restore_context(struct clk_hw *hw)
  352. {
  353. struct clk_master *master = to_clk_master(hw);
  354. unsigned long flags;
  355. unsigned int val, pres;
  356. spin_lock_irqsave(master->lock, flags);
  357. regmap_read(master->regmap, master->layout->offset, &val);
  358. spin_unlock_irqrestore(master->lock, flags);
  359. val &= master->layout->mask;
  360. pres = (val >> master->layout->pres_shift) & MASTER_PRES_MASK;
  361. if (pres == MASTER_PRES_MAX && master->characteristics->have_div3_pres)
  362. pres = 3;
  363. else
  364. pres = (1 << pres);
  365. if (master->pms.rate !=
  366. DIV_ROUND_CLOSEST_ULL(master->pms.parent_rate, pres) ||
  367. (master->pms.parent != (val & AT91_PMC_CSS)))
  368. pr_warn("MCKR PRES was not configured properly by firmware!\n");
  369. }
  370. static const struct clk_ops master_pres_ops = {
  371. .prepare = clk_master_prepare,
  372. .is_prepared = clk_master_is_prepared,
  373. .recalc_rate = clk_master_pres_recalc_rate,
  374. .get_parent = clk_master_pres_get_parent,
  375. .save_context = clk_master_pres_save_context,
  376. .restore_context = clk_master_pres_restore_context,
  377. };
  378. static struct clk_hw * __init
  379. at91_clk_register_master_internal(struct regmap *regmap,
  380. const char *name, int num_parents,
  381. const char **parent_names,
  382. const struct clk_master_layout *layout,
  383. const struct clk_master_characteristics *characteristics,
  384. const struct clk_ops *ops, spinlock_t *lock, u32 flags)
  385. {
  386. struct clk_master *master;
  387. struct clk_init_data init;
  388. struct clk_hw *hw;
  389. unsigned int mckr;
  390. unsigned long irqflags;
  391. int ret;
  392. if (!name || !num_parents || !parent_names || !lock)
  393. return ERR_PTR(-EINVAL);
  394. master = kzalloc(sizeof(*master), GFP_KERNEL);
  395. if (!master)
  396. return ERR_PTR(-ENOMEM);
  397. init.name = name;
  398. init.ops = ops;
  399. init.parent_names = parent_names;
  400. init.num_parents = num_parents;
  401. init.flags = flags;
  402. master->hw.init = &init;
  403. master->layout = layout;
  404. master->characteristics = characteristics;
  405. master->regmap = regmap;
  406. master->lock = lock;
  407. if (ops == &master_div_ops_chg) {
  408. spin_lock_irqsave(master->lock, irqflags);
  409. regmap_read(master->regmap, master->layout->offset, &mckr);
  410. spin_unlock_irqrestore(master->lock, irqflags);
  411. mckr &= layout->mask;
  412. mckr = (mckr >> MASTER_DIV_SHIFT) & MASTER_DIV_MASK;
  413. master->div = characteristics->divisors[mckr];
  414. }
  415. hw = &master->hw;
  416. ret = clk_hw_register(NULL, &master->hw);
  417. if (ret) {
  418. kfree(master);
  419. hw = ERR_PTR(ret);
  420. }
  421. return hw;
  422. }
  423. struct clk_hw * __init
  424. at91_clk_register_master_pres(struct regmap *regmap,
  425. const char *name, int num_parents,
  426. const char **parent_names,
  427. const struct clk_master_layout *layout,
  428. const struct clk_master_characteristics *characteristics,
  429. spinlock_t *lock)
  430. {
  431. return at91_clk_register_master_internal(regmap, name, num_parents,
  432. parent_names, layout,
  433. characteristics,
  434. &master_pres_ops,
  435. lock, CLK_SET_RATE_GATE);
  436. }
  437. struct clk_hw * __init
  438. at91_clk_register_master_div(struct regmap *regmap,
  439. const char *name, const char *parent_name,
  440. const struct clk_master_layout *layout,
  441. const struct clk_master_characteristics *characteristics,
  442. spinlock_t *lock, u32 flags, u32 safe_div)
  443. {
  444. const struct clk_ops *ops;
  445. struct clk_hw *hw;
  446. if (flags & CLK_SET_RATE_GATE)
  447. ops = &master_div_ops;
  448. else
  449. ops = &master_div_ops_chg;
  450. hw = at91_clk_register_master_internal(regmap, name, 1,
  451. &parent_name, layout,
  452. characteristics, ops,
  453. lock, flags);
  454. if (!IS_ERR(hw) && safe_div) {
  455. master_div = to_clk_master(hw);
  456. master_div->safe_div = safe_div;
  457. clk_notifier_register(hw->clk,
  458. &clk_master_div_notifier);
  459. }
  460. return hw;
  461. }
  462. static unsigned long
  463. clk_sama7g5_master_recalc_rate(struct clk_hw *hw,
  464. unsigned long parent_rate)
  465. {
  466. struct clk_master *master = to_clk_master(hw);
  467. return DIV_ROUND_CLOSEST_ULL(parent_rate, (1 << master->div));
  468. }
  469. static int clk_sama7g5_master_determine_rate(struct clk_hw *hw,
  470. struct clk_rate_request *req)
  471. {
  472. struct clk_master *master = to_clk_master(hw);
  473. struct clk_hw *parent;
  474. long best_rate = LONG_MIN, best_diff = LONG_MIN;
  475. unsigned long parent_rate;
  476. unsigned int div, i;
  477. /* First: check the dividers of MCR. */
  478. for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
  479. parent = clk_hw_get_parent_by_index(hw, i);
  480. if (!parent)
  481. continue;
  482. parent_rate = clk_hw_get_rate(parent);
  483. if (!parent_rate)
  484. continue;
  485. for (div = 0; div < MASTER_PRES_MAX + 1; div++) {
  486. clk_sama7g5_master_best_diff(req, parent, parent_rate,
  487. &best_rate, &best_diff,
  488. div);
  489. if (!best_diff)
  490. break;
  491. }
  492. if (!best_diff)
  493. break;
  494. }
  495. /* Second: try to request rate form changeable parent. */
  496. if (master->chg_pid < 0)
  497. goto end;
  498. parent = clk_hw_get_parent_by_index(hw, master->chg_pid);
  499. if (!parent)
  500. goto end;
  501. for (div = 0; div < MASTER_PRES_MAX + 1; div++) {
  502. struct clk_rate_request req_parent;
  503. unsigned long req_rate;
  504. if (div == MASTER_PRES_MAX)
  505. req_rate = req->rate * 3;
  506. else
  507. req_rate = req->rate << div;
  508. clk_hw_forward_rate_request(hw, req, parent, &req_parent, req_rate);
  509. if (__clk_determine_rate(parent, &req_parent))
  510. continue;
  511. clk_sama7g5_master_best_diff(req, parent, req_parent.rate,
  512. &best_rate, &best_diff, div);
  513. if (!best_diff)
  514. break;
  515. }
  516. end:
  517. pr_debug("MCK: %s, best_rate = %ld, parent clk: %s @ %ld\n",
  518. __func__, best_rate,
  519. __clk_get_name((req->best_parent_hw)->clk),
  520. req->best_parent_rate);
  521. if (best_rate < 0)
  522. return -EINVAL;
  523. req->rate = best_rate;
  524. return 0;
  525. }
  526. static u8 clk_sama7g5_master_get_parent(struct clk_hw *hw)
  527. {
  528. struct clk_master *master = to_clk_master(hw);
  529. unsigned long flags;
  530. u8 index;
  531. spin_lock_irqsave(master->lock, flags);
  532. index = clk_mux_val_to_index(&master->hw, master->mux_table, 0,
  533. master->parent);
  534. spin_unlock_irqrestore(master->lock, flags);
  535. return index;
  536. }
  537. static int clk_sama7g5_master_set_parent(struct clk_hw *hw, u8 index)
  538. {
  539. struct clk_master *master = to_clk_master(hw);
  540. unsigned long flags;
  541. if (index >= clk_hw_get_num_parents(hw))
  542. return -EINVAL;
  543. spin_lock_irqsave(master->lock, flags);
  544. master->parent = clk_mux_index_to_val(master->mux_table, 0, index);
  545. spin_unlock_irqrestore(master->lock, flags);
  546. return 0;
  547. }
  548. static void clk_sama7g5_master_set(struct clk_master *master,
  549. unsigned int status)
  550. {
  551. unsigned long flags;
  552. unsigned int val, cparent;
  553. unsigned int enable = status ? AT91_PMC_MCR_V2_EN : 0;
  554. unsigned int parent = master->parent << PMC_MCR_CSS_SHIFT;
  555. unsigned int div = master->div << MASTER_DIV_SHIFT;
  556. spin_lock_irqsave(master->lock, flags);
  557. regmap_write(master->regmap, AT91_PMC_MCR_V2,
  558. AT91_PMC_MCR_V2_ID(master->id));
  559. regmap_read(master->regmap, AT91_PMC_MCR_V2, &val);
  560. regmap_update_bits(master->regmap, AT91_PMC_MCR_V2,
  561. enable | AT91_PMC_MCR_V2_CSS | AT91_PMC_MCR_V2_DIV |
  562. AT91_PMC_MCR_V2_CMD | AT91_PMC_MCR_V2_ID_MSK,
  563. enable | parent | div | AT91_PMC_MCR_V2_CMD |
  564. AT91_PMC_MCR_V2_ID(master->id));
  565. cparent = (val & AT91_PMC_MCR_V2_CSS) >> PMC_MCR_CSS_SHIFT;
  566. /* Wait here only if parent is being changed. */
  567. while ((cparent != master->parent) && !clk_master_ready(master))
  568. cpu_relax();
  569. spin_unlock_irqrestore(master->lock, flags);
  570. }
  571. static int clk_sama7g5_master_enable(struct clk_hw *hw)
  572. {
  573. struct clk_master *master = to_clk_master(hw);
  574. clk_sama7g5_master_set(master, 1);
  575. return 0;
  576. }
  577. static void clk_sama7g5_master_disable(struct clk_hw *hw)
  578. {
  579. struct clk_master *master = to_clk_master(hw);
  580. unsigned long flags;
  581. spin_lock_irqsave(master->lock, flags);
  582. regmap_write(master->regmap, AT91_PMC_MCR_V2, master->id);
  583. regmap_update_bits(master->regmap, AT91_PMC_MCR_V2,
  584. AT91_PMC_MCR_V2_EN | AT91_PMC_MCR_V2_CMD |
  585. AT91_PMC_MCR_V2_ID_MSK,
  586. AT91_PMC_MCR_V2_CMD |
  587. AT91_PMC_MCR_V2_ID(master->id));
  588. spin_unlock_irqrestore(master->lock, flags);
  589. }
  590. static int clk_sama7g5_master_is_enabled(struct clk_hw *hw)
  591. {
  592. struct clk_master *master = to_clk_master(hw);
  593. unsigned long flags;
  594. unsigned int val;
  595. spin_lock_irqsave(master->lock, flags);
  596. regmap_write(master->regmap, AT91_PMC_MCR_V2, master->id);
  597. regmap_read(master->regmap, AT91_PMC_MCR_V2, &val);
  598. spin_unlock_irqrestore(master->lock, flags);
  599. return !!(val & AT91_PMC_MCR_V2_EN);
  600. }
  601. static int clk_sama7g5_master_set_rate(struct clk_hw *hw, unsigned long rate,
  602. unsigned long parent_rate)
  603. {
  604. struct clk_master *master = to_clk_master(hw);
  605. unsigned long div, flags;
  606. div = DIV_ROUND_CLOSEST(parent_rate, rate);
  607. if ((div > (1 << (MASTER_PRES_MAX - 1))) || (div & (div - 1)))
  608. return -EINVAL;
  609. if (div == 3)
  610. div = MASTER_PRES_MAX;
  611. else if (div)
  612. div = ffs(div) - 1;
  613. spin_lock_irqsave(master->lock, flags);
  614. master->div = div;
  615. spin_unlock_irqrestore(master->lock, flags);
  616. return 0;
  617. }
  618. static int clk_sama7g5_master_save_context(struct clk_hw *hw)
  619. {
  620. struct clk_master *master = to_clk_master(hw);
  621. master->pms.status = clk_sama7g5_master_is_enabled(hw);
  622. return 0;
  623. }
  624. static void clk_sama7g5_master_restore_context(struct clk_hw *hw)
  625. {
  626. struct clk_master *master = to_clk_master(hw);
  627. if (master->pms.status)
  628. clk_sama7g5_master_set(master, master->pms.status);
  629. }
  630. static const struct clk_ops sama7g5_master_ops = {
  631. .enable = clk_sama7g5_master_enable,
  632. .disable = clk_sama7g5_master_disable,
  633. .is_enabled = clk_sama7g5_master_is_enabled,
  634. .recalc_rate = clk_sama7g5_master_recalc_rate,
  635. .determine_rate = clk_sama7g5_master_determine_rate,
  636. .set_rate = clk_sama7g5_master_set_rate,
  637. .get_parent = clk_sama7g5_master_get_parent,
  638. .set_parent = clk_sama7g5_master_set_parent,
  639. .save_context = clk_sama7g5_master_save_context,
  640. .restore_context = clk_sama7g5_master_restore_context,
  641. };
  642. struct clk_hw * __init
  643. at91_clk_sama7g5_register_master(struct regmap *regmap,
  644. const char *name, int num_parents,
  645. const char **parent_names,
  646. u32 *mux_table,
  647. spinlock_t *lock, u8 id,
  648. bool critical, int chg_pid)
  649. {
  650. struct clk_master *master;
  651. struct clk_hw *hw;
  652. struct clk_init_data init;
  653. unsigned long flags;
  654. unsigned int val;
  655. int ret;
  656. if (!name || !num_parents || !parent_names || !mux_table ||
  657. !lock || id > MASTER_MAX_ID)
  658. return ERR_PTR(-EINVAL);
  659. master = kzalloc(sizeof(*master), GFP_KERNEL);
  660. if (!master)
  661. return ERR_PTR(-ENOMEM);
  662. init.name = name;
  663. init.ops = &sama7g5_master_ops;
  664. init.parent_names = parent_names;
  665. init.num_parents = num_parents;
  666. init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE;
  667. if (chg_pid >= 0)
  668. init.flags |= CLK_SET_RATE_PARENT;
  669. if (critical)
  670. init.flags |= CLK_IS_CRITICAL;
  671. master->hw.init = &init;
  672. master->regmap = regmap;
  673. master->id = id;
  674. master->chg_pid = chg_pid;
  675. master->lock = lock;
  676. master->mux_table = mux_table;
  677. spin_lock_irqsave(master->lock, flags);
  678. regmap_write(master->regmap, AT91_PMC_MCR_V2, master->id);
  679. regmap_read(master->regmap, AT91_PMC_MCR_V2, &val);
  680. master->parent = (val & AT91_PMC_MCR_V2_CSS) >> PMC_MCR_CSS_SHIFT;
  681. master->div = (val & AT91_PMC_MCR_V2_DIV) >> MASTER_DIV_SHIFT;
  682. spin_unlock_irqrestore(master->lock, flags);
  683. hw = &master->hw;
  684. ret = clk_hw_register(NULL, &master->hw);
  685. if (ret) {
  686. kfree(master);
  687. hw = ERR_PTR(ret);
  688. }
  689. return hw;
  690. }
  691. const struct clk_master_layout at91rm9200_master_layout = {
  692. .mask = 0x31F,
  693. .pres_shift = 2,
  694. .offset = AT91_PMC_MCKR,
  695. };
  696. const struct clk_master_layout at91sam9x5_master_layout = {
  697. .mask = 0x373,
  698. .pres_shift = 4,
  699. .offset = AT91_PMC_MCKR,
  700. };