PageRenderTime 60ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 1ms

/drivers/clk/tegra/clk-bpmp.c

https://github.com/gby/linux
C | 620 lines | 473 code | 129 blank | 18 comment | 51 complexity | 512e1d26695ad06c8079d5458d324167 MD5 | raw file
  1. /*
  2. * Copyright (C) 2016 NVIDIA Corporation
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License version 2 as
  6. * published by the Free Software Foundation.
  7. */
  8. #include <linux/clk-provider.h>
  9. #include <linux/device.h>
  10. #include <linux/seq_buf.h>
  11. #include <linux/slab.h>
  12. #include <soc/tegra/bpmp.h>
  13. #include <soc/tegra/bpmp-abi.h>
  14. #define TEGRA_BPMP_DUMP_CLOCK_INFO 0
  15. #define TEGRA_BPMP_CLK_HAS_MUX BIT(0)
  16. #define TEGRA_BPMP_CLK_HAS_SET_RATE BIT(1)
  17. #define TEGRA_BPMP_CLK_IS_ROOT BIT(2)
  18. struct tegra_bpmp_clk_info {
  19. unsigned int id;
  20. char name[MRQ_CLK_NAME_MAXLEN];
  21. unsigned int parents[MRQ_CLK_MAX_PARENTS];
  22. unsigned int num_parents;
  23. unsigned long flags;
  24. };
  25. struct tegra_bpmp_clk {
  26. struct clk_hw hw;
  27. struct tegra_bpmp *bpmp;
  28. unsigned int id;
  29. unsigned int num_parents;
  30. unsigned int *parents;
  31. };
  32. static inline struct tegra_bpmp_clk *to_tegra_bpmp_clk(struct clk_hw *hw)
  33. {
  34. return container_of(hw, struct tegra_bpmp_clk, hw);
  35. }
  36. struct tegra_bpmp_clk_message {
  37. unsigned int cmd;
  38. unsigned int id;
  39. struct {
  40. const void *data;
  41. size_t size;
  42. } tx;
  43. struct {
  44. void *data;
  45. size_t size;
  46. } rx;
  47. };
  48. static int tegra_bpmp_clk_transfer(struct tegra_bpmp *bpmp,
  49. const struct tegra_bpmp_clk_message *clk)
  50. {
  51. struct mrq_clk_request request;
  52. struct tegra_bpmp_message msg;
  53. void *req = &request;
  54. memset(&request, 0, sizeof(request));
  55. request.cmd_and_id = (clk->cmd << 24) | clk->id;
  56. /*
  57. * The mrq_clk_request structure has an anonymous union at offset 4
  58. * that contains all possible sub-command structures. Copy the data
  59. * to that union. Ideally we'd be able to refer to it by name, but
  60. * doing so would require changing the ABI header and increase the
  61. * maintenance burden.
  62. */
  63. memcpy(req + 4, clk->tx.data, clk->tx.size);
  64. memset(&msg, 0, sizeof(msg));
  65. msg.mrq = MRQ_CLK;
  66. msg.tx.data = &request;
  67. msg.tx.size = sizeof(request);
  68. msg.rx.data = clk->rx.data;
  69. msg.rx.size = clk->rx.size;
  70. return tegra_bpmp_transfer(bpmp, &msg);
  71. }
  72. static int tegra_bpmp_clk_prepare(struct clk_hw *hw)
  73. {
  74. struct tegra_bpmp_clk *clk = to_tegra_bpmp_clk(hw);
  75. struct tegra_bpmp_clk_message msg;
  76. memset(&msg, 0, sizeof(msg));
  77. msg.cmd = CMD_CLK_ENABLE;
  78. msg.id = clk->id;
  79. return tegra_bpmp_clk_transfer(clk->bpmp, &msg);
  80. }
  81. static void tegra_bpmp_clk_unprepare(struct clk_hw *hw)
  82. {
  83. struct tegra_bpmp_clk *clk = to_tegra_bpmp_clk(hw);
  84. struct tegra_bpmp_clk_message msg;
  85. int err;
  86. memset(&msg, 0, sizeof(msg));
  87. msg.cmd = CMD_CLK_DISABLE;
  88. msg.id = clk->id;
  89. err = tegra_bpmp_clk_transfer(clk->bpmp, &msg);
  90. if (err < 0)
  91. dev_err(clk->bpmp->dev, "failed to disable clock %s: %d\n",
  92. clk_hw_get_name(hw), err);
  93. }
  94. static int tegra_bpmp_clk_is_prepared(struct clk_hw *hw)
  95. {
  96. struct tegra_bpmp_clk *clk = to_tegra_bpmp_clk(hw);
  97. struct cmd_clk_is_enabled_response response;
  98. struct tegra_bpmp_clk_message msg;
  99. int err;
  100. memset(&msg, 0, sizeof(msg));
  101. msg.cmd = CMD_CLK_IS_ENABLED;
  102. msg.id = clk->id;
  103. msg.rx.data = &response;
  104. msg.rx.size = sizeof(response);
  105. err = tegra_bpmp_clk_transfer(clk->bpmp, &msg);
  106. if (err < 0)
  107. return err;
  108. return response.state;
  109. }
  110. static unsigned long tegra_bpmp_clk_recalc_rate(struct clk_hw *hw,
  111. unsigned long parent_rate)
  112. {
  113. struct tegra_bpmp_clk *clk = to_tegra_bpmp_clk(hw);
  114. struct cmd_clk_get_rate_response response;
  115. struct cmd_clk_get_rate_request request;
  116. struct tegra_bpmp_clk_message msg;
  117. int err;
  118. memset(&msg, 0, sizeof(msg));
  119. msg.cmd = CMD_CLK_GET_RATE;
  120. msg.id = clk->id;
  121. msg.tx.data = &request;
  122. msg.tx.size = sizeof(request);
  123. msg.rx.data = &response;
  124. msg.rx.size = sizeof(response);
  125. err = tegra_bpmp_clk_transfer(clk->bpmp, &msg);
  126. if (err < 0)
  127. return err;
  128. return response.rate;
  129. }
  130. static long tegra_bpmp_clk_round_rate(struct clk_hw *hw, unsigned long rate,
  131. unsigned long *parent_rate)
  132. {
  133. struct tegra_bpmp_clk *clk = to_tegra_bpmp_clk(hw);
  134. struct cmd_clk_round_rate_response response;
  135. struct cmd_clk_round_rate_request request;
  136. struct tegra_bpmp_clk_message msg;
  137. int err;
  138. memset(&request, 0, sizeof(request));
  139. request.rate = rate;
  140. memset(&msg, 0, sizeof(msg));
  141. msg.cmd = CMD_CLK_ROUND_RATE;
  142. msg.id = clk->id;
  143. msg.tx.data = &request;
  144. msg.tx.size = sizeof(request);
  145. msg.rx.data = &response;
  146. msg.rx.size = sizeof(response);
  147. err = tegra_bpmp_clk_transfer(clk->bpmp, &msg);
  148. if (err < 0)
  149. return err;
  150. return response.rate;
  151. }
  152. static int tegra_bpmp_clk_set_parent(struct clk_hw *hw, u8 index)
  153. {
  154. struct tegra_bpmp_clk *clk = to_tegra_bpmp_clk(hw);
  155. struct cmd_clk_set_parent_response response;
  156. struct cmd_clk_set_parent_request request;
  157. struct tegra_bpmp_clk_message msg;
  158. int err;
  159. memset(&request, 0, sizeof(request));
  160. request.parent_id = clk->parents[index];
  161. memset(&msg, 0, sizeof(msg));
  162. msg.cmd = CMD_CLK_SET_PARENT;
  163. msg.id = clk->id;
  164. msg.tx.data = &request;
  165. msg.tx.size = sizeof(request);
  166. msg.rx.data = &response;
  167. msg.rx.size = sizeof(response);
  168. err = tegra_bpmp_clk_transfer(clk->bpmp, &msg);
  169. if (err < 0)
  170. return err;
  171. /* XXX check parent ID in response */
  172. return 0;
  173. }
  174. static u8 tegra_bpmp_clk_get_parent(struct clk_hw *hw)
  175. {
  176. struct tegra_bpmp_clk *clk = to_tegra_bpmp_clk(hw);
  177. struct cmd_clk_get_parent_response response;
  178. struct tegra_bpmp_clk_message msg;
  179. unsigned int i;
  180. int err;
  181. memset(&msg, 0, sizeof(msg));
  182. msg.cmd = CMD_CLK_GET_PARENT;
  183. msg.id = clk->id;
  184. msg.rx.data = &response;
  185. msg.rx.size = sizeof(response);
  186. err = tegra_bpmp_clk_transfer(clk->bpmp, &msg);
  187. if (err < 0) {
  188. dev_err(clk->bpmp->dev, "failed to get parent for %s: %d\n",
  189. clk_hw_get_name(hw), err);
  190. return U8_MAX;
  191. }
  192. for (i = 0; i < clk->num_parents; i++)
  193. if (clk->parents[i] == response.parent_id)
  194. return i;
  195. return U8_MAX;
  196. }
  197. static int tegra_bpmp_clk_set_rate(struct clk_hw *hw, unsigned long rate,
  198. unsigned long parent_rate)
  199. {
  200. struct tegra_bpmp_clk *clk = to_tegra_bpmp_clk(hw);
  201. struct cmd_clk_set_rate_response response;
  202. struct cmd_clk_set_rate_request request;
  203. struct tegra_bpmp_clk_message msg;
  204. memset(&request, 0, sizeof(request));
  205. request.rate = rate;
  206. memset(&msg, 0, sizeof(msg));
  207. msg.cmd = CMD_CLK_SET_RATE;
  208. msg.id = clk->id;
  209. msg.tx.data = &request;
  210. msg.tx.size = sizeof(request);
  211. msg.rx.data = &response;
  212. msg.rx.size = sizeof(response);
  213. return tegra_bpmp_clk_transfer(clk->bpmp, &msg);
  214. }
  215. static const struct clk_ops tegra_bpmp_clk_gate_ops = {
  216. .prepare = tegra_bpmp_clk_prepare,
  217. .unprepare = tegra_bpmp_clk_unprepare,
  218. .is_prepared = tegra_bpmp_clk_is_prepared,
  219. .recalc_rate = tegra_bpmp_clk_recalc_rate,
  220. };
  221. static const struct clk_ops tegra_bpmp_clk_mux_ops = {
  222. .prepare = tegra_bpmp_clk_prepare,
  223. .unprepare = tegra_bpmp_clk_unprepare,
  224. .is_prepared = tegra_bpmp_clk_is_prepared,
  225. .recalc_rate = tegra_bpmp_clk_recalc_rate,
  226. .set_parent = tegra_bpmp_clk_set_parent,
  227. .get_parent = tegra_bpmp_clk_get_parent,
  228. };
  229. static const struct clk_ops tegra_bpmp_clk_rate_ops = {
  230. .prepare = tegra_bpmp_clk_prepare,
  231. .unprepare = tegra_bpmp_clk_unprepare,
  232. .is_prepared = tegra_bpmp_clk_is_prepared,
  233. .recalc_rate = tegra_bpmp_clk_recalc_rate,
  234. .round_rate = tegra_bpmp_clk_round_rate,
  235. .set_rate = tegra_bpmp_clk_set_rate,
  236. };
  237. static const struct clk_ops tegra_bpmp_clk_mux_rate_ops = {
  238. .prepare = tegra_bpmp_clk_prepare,
  239. .unprepare = tegra_bpmp_clk_unprepare,
  240. .is_prepared = tegra_bpmp_clk_is_prepared,
  241. .recalc_rate = tegra_bpmp_clk_recalc_rate,
  242. .round_rate = tegra_bpmp_clk_round_rate,
  243. .set_parent = tegra_bpmp_clk_set_parent,
  244. .get_parent = tegra_bpmp_clk_get_parent,
  245. .set_rate = tegra_bpmp_clk_set_rate,
  246. };
  247. static int tegra_bpmp_clk_get_max_id(struct tegra_bpmp *bpmp)
  248. {
  249. struct cmd_clk_get_max_clk_id_response response;
  250. struct tegra_bpmp_clk_message msg;
  251. int err;
  252. memset(&msg, 0, sizeof(msg));
  253. msg.cmd = CMD_CLK_GET_MAX_CLK_ID;
  254. msg.rx.data = &response;
  255. msg.rx.size = sizeof(response);
  256. err = tegra_bpmp_clk_transfer(bpmp, &msg);
  257. if (err < 0)
  258. return err;
  259. if (response.max_id > INT_MAX)
  260. return -E2BIG;
  261. return response.max_id;
  262. }
  263. static int tegra_bpmp_clk_get_info(struct tegra_bpmp *bpmp, unsigned int id,
  264. struct tegra_bpmp_clk_info *info)
  265. {
  266. struct cmd_clk_get_all_info_response response;
  267. struct tegra_bpmp_clk_message msg;
  268. unsigned int i;
  269. int err;
  270. memset(&msg, 0, sizeof(msg));
  271. msg.cmd = CMD_CLK_GET_ALL_INFO;
  272. msg.id = id;
  273. msg.rx.data = &response;
  274. msg.rx.size = sizeof(response);
  275. err = tegra_bpmp_clk_transfer(bpmp, &msg);
  276. if (err < 0)
  277. return err;
  278. strlcpy(info->name, response.name, MRQ_CLK_NAME_MAXLEN);
  279. info->num_parents = response.num_parents;
  280. for (i = 0; i < info->num_parents; i++)
  281. info->parents[i] = response.parents[i];
  282. info->flags = response.flags;
  283. return 0;
  284. }
  285. static void tegra_bpmp_clk_info_dump(struct tegra_bpmp *bpmp,
  286. const char *level,
  287. const struct tegra_bpmp_clk_info *info)
  288. {
  289. const char *prefix = "";
  290. struct seq_buf buf;
  291. unsigned int i;
  292. char flags[64];
  293. seq_buf_init(&buf, flags, sizeof(flags));
  294. if (info->flags)
  295. seq_buf_printf(&buf, "(");
  296. if (info->flags & TEGRA_BPMP_CLK_HAS_MUX) {
  297. seq_buf_printf(&buf, "%smux", prefix);
  298. prefix = ", ";
  299. }
  300. if ((info->flags & TEGRA_BPMP_CLK_HAS_SET_RATE) == 0) {
  301. seq_buf_printf(&buf, "%sfixed", prefix);
  302. prefix = ", ";
  303. }
  304. if (info->flags & TEGRA_BPMP_CLK_IS_ROOT) {
  305. seq_buf_printf(&buf, "%sroot", prefix);
  306. prefix = ", ";
  307. }
  308. if (info->flags)
  309. seq_buf_printf(&buf, ")");
  310. dev_printk(level, bpmp->dev, "%03u: %s\n", info->id, info->name);
  311. dev_printk(level, bpmp->dev, " flags: %lx %s\n", info->flags, flags);
  312. dev_printk(level, bpmp->dev, " parents: %u\n", info->num_parents);
  313. for (i = 0; i < info->num_parents; i++)
  314. dev_printk(level, bpmp->dev, " %03u\n", info->parents[i]);
  315. }
  316. static int tegra_bpmp_probe_clocks(struct tegra_bpmp *bpmp,
  317. struct tegra_bpmp_clk_info **clocksp)
  318. {
  319. struct tegra_bpmp_clk_info *clocks;
  320. unsigned int max_id, id, count = 0;
  321. unsigned int holes = 0;
  322. int err;
  323. err = tegra_bpmp_clk_get_max_id(bpmp);
  324. if (err < 0)
  325. return err;
  326. max_id = err;
  327. dev_dbg(bpmp->dev, "maximum clock ID: %u\n", max_id);
  328. clocks = kcalloc(max_id + 1, sizeof(*clocks), GFP_KERNEL);
  329. if (!clocks)
  330. return -ENOMEM;
  331. for (id = 0; id <= max_id; id++) {
  332. struct tegra_bpmp_clk_info *info = &clocks[count];
  333. err = tegra_bpmp_clk_get_info(bpmp, id, info);
  334. if (err < 0) {
  335. dev_err(bpmp->dev, "failed to query clock %u: %d\n",
  336. id, err);
  337. continue;
  338. }
  339. if (info->num_parents >= U8_MAX) {
  340. dev_err(bpmp->dev,
  341. "clock %u has too many parents (%u, max: %u)\n",
  342. id, info->num_parents, U8_MAX);
  343. continue;
  344. }
  345. /* clock not exposed by BPMP */
  346. if (info->name[0] == '\0') {
  347. holes++;
  348. continue;
  349. }
  350. info->id = id;
  351. count++;
  352. if (TEGRA_BPMP_DUMP_CLOCK_INFO)
  353. tegra_bpmp_clk_info_dump(bpmp, KERN_DEBUG, info);
  354. }
  355. dev_dbg(bpmp->dev, "holes: %u\n", holes);
  356. *clocksp = clocks;
  357. return count;
  358. }
  359. static const struct tegra_bpmp_clk_info *
  360. tegra_bpmp_clk_find(const struct tegra_bpmp_clk_info *clocks,
  361. unsigned int num_clocks, unsigned int id)
  362. {
  363. unsigned int i;
  364. for (i = 0; i < num_clocks; i++)
  365. if (clocks[i].id == id)
  366. return &clocks[i];
  367. return NULL;
  368. }
  369. static struct tegra_bpmp_clk *
  370. tegra_bpmp_clk_register(struct tegra_bpmp *bpmp,
  371. const struct tegra_bpmp_clk_info *info,
  372. const struct tegra_bpmp_clk_info *clocks,
  373. unsigned int num_clocks)
  374. {
  375. struct tegra_bpmp_clk *clk;
  376. struct clk_init_data init;
  377. const char **parents;
  378. unsigned int i;
  379. int err;
  380. clk = devm_kzalloc(bpmp->dev, sizeof(*clk), GFP_KERNEL);
  381. if (!clk)
  382. return ERR_PTR(-ENOMEM);
  383. clk->id = info->id;
  384. clk->bpmp = bpmp;
  385. clk->parents = devm_kcalloc(bpmp->dev, info->num_parents,
  386. sizeof(*clk->parents), GFP_KERNEL);
  387. if (!clk->parents)
  388. return ERR_PTR(-ENOMEM);
  389. clk->num_parents = info->num_parents;
  390. /* hardware clock initialization */
  391. memset(&init, 0, sizeof(init));
  392. init.name = info->name;
  393. clk->hw.init = &init;
  394. if (info->flags & TEGRA_BPMP_CLK_HAS_MUX) {
  395. if (info->flags & TEGRA_BPMP_CLK_HAS_SET_RATE)
  396. init.ops = &tegra_bpmp_clk_mux_rate_ops;
  397. else
  398. init.ops = &tegra_bpmp_clk_mux_ops;
  399. } else {
  400. if (info->flags & TEGRA_BPMP_CLK_HAS_SET_RATE)
  401. init.ops = &tegra_bpmp_clk_rate_ops;
  402. else
  403. init.ops = &tegra_bpmp_clk_gate_ops;
  404. }
  405. init.num_parents = info->num_parents;
  406. parents = kcalloc(info->num_parents, sizeof(*parents), GFP_KERNEL);
  407. if (!parents)
  408. return ERR_PTR(-ENOMEM);
  409. for (i = 0; i < info->num_parents; i++) {
  410. const struct tegra_bpmp_clk_info *parent;
  411. /* keep a private copy of the ID to parent index map */
  412. clk->parents[i] = info->parents[i];
  413. parent = tegra_bpmp_clk_find(clocks, num_clocks,
  414. info->parents[i]);
  415. if (!parent) {
  416. dev_err(bpmp->dev, "no parent %u found for %u\n",
  417. info->parents[i], info->id);
  418. continue;
  419. }
  420. parents[i] = parent->name;
  421. }
  422. init.parent_names = parents;
  423. err = devm_clk_hw_register(bpmp->dev, &clk->hw);
  424. kfree(parents);
  425. if (err < 0)
  426. return ERR_PTR(err);
  427. return clk;
  428. }
  429. static int tegra_bpmp_register_clocks(struct tegra_bpmp *bpmp,
  430. struct tegra_bpmp_clk_info *infos,
  431. unsigned int count)
  432. {
  433. struct tegra_bpmp_clk *clk;
  434. unsigned int i;
  435. bpmp->num_clocks = count;
  436. bpmp->clocks = devm_kcalloc(bpmp->dev, count, sizeof(clk), GFP_KERNEL);
  437. if (!bpmp->clocks)
  438. return -ENOMEM;
  439. for (i = 0; i < count; i++) {
  440. struct tegra_bpmp_clk_info *info = &infos[i];
  441. clk = tegra_bpmp_clk_register(bpmp, info, infos, count);
  442. if (IS_ERR(clk)) {
  443. dev_err(bpmp->dev,
  444. "failed to register clock %u (%s): %ld\n",
  445. info->id, info->name, PTR_ERR(clk));
  446. continue;
  447. }
  448. bpmp->clocks[i] = clk;
  449. }
  450. return 0;
  451. }
  452. static void tegra_bpmp_unregister_clocks(struct tegra_bpmp *bpmp)
  453. {
  454. unsigned int i;
  455. for (i = 0; i < bpmp->num_clocks; i++)
  456. clk_hw_unregister(&bpmp->clocks[i]->hw);
  457. }
  458. static struct clk_hw *tegra_bpmp_clk_of_xlate(struct of_phandle_args *clkspec,
  459. void *data)
  460. {
  461. unsigned int id = clkspec->args[0], i;
  462. struct tegra_bpmp *bpmp = data;
  463. for (i = 0; i < bpmp->num_clocks; i++)
  464. if (bpmp->clocks[i]->id == id)
  465. return &bpmp->clocks[i]->hw;
  466. return NULL;
  467. }
  468. int tegra_bpmp_init_clocks(struct tegra_bpmp *bpmp)
  469. {
  470. struct tegra_bpmp_clk_info *clocks;
  471. unsigned int count;
  472. int err;
  473. err = tegra_bpmp_probe_clocks(bpmp, &clocks);
  474. if (err < 0)
  475. return err;
  476. count = err;
  477. dev_dbg(bpmp->dev, "%u clocks probed\n", count);
  478. err = tegra_bpmp_register_clocks(bpmp, clocks, count);
  479. if (err < 0)
  480. goto free;
  481. err = of_clk_add_hw_provider(bpmp->dev->of_node,
  482. tegra_bpmp_clk_of_xlate,
  483. bpmp);
  484. if (err < 0) {
  485. tegra_bpmp_unregister_clocks(bpmp);
  486. goto free;
  487. }
  488. free:
  489. kfree(clocks);
  490. return err;
  491. }