clk-rpmi.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * RISC-V MPXY Based Clock Driver
  4. *
  5. * Copyright (C) 2025 Ventana Micro Systems Ltd.
  6. */
  7. #include <linux/clk-provider.h>
  8. #include <linux/err.h>
  9. #include <linux/mailbox_client.h>
  10. #include <linux/mailbox/riscv-rpmi-message.h>
  11. #include <linux/module.h>
  12. #include <linux/platform_device.h>
  13. #include <linux/types.h>
  14. #include <linux/slab.h>
  15. #include <linux/wordpart.h>
  16. #define RPMI_CLK_DISCRETE_MAX_NUM_RATES 16
  17. #define RPMI_CLK_NAME_LEN 16
  18. #define to_rpmi_clk(clk) container_of(clk, struct rpmi_clk, hw)
  19. enum rpmi_clk_config {
  20. RPMI_CLK_DISABLE = 0,
  21. RPMI_CLK_ENABLE = 1,
  22. RPMI_CLK_CONFIG_MAX_IDX
  23. };
  24. #define RPMI_CLK_TYPE_MASK GENMASK(1, 0)
  25. enum rpmi_clk_type {
  26. RPMI_CLK_DISCRETE = 0,
  27. RPMI_CLK_LINEAR = 1,
  28. RPMI_CLK_TYPE_MAX_IDX
  29. };
  30. struct rpmi_clk_context {
  31. struct device *dev;
  32. struct mbox_chan *chan;
  33. struct mbox_client client;
  34. u32 max_msg_data_size;
  35. };
  36. /*
  37. * rpmi_clk_rates represents the rates format
  38. * as specified by the RPMI specification.
  39. * No other data format (e.g., struct linear_range)
  40. * is required to avoid to and from conversion.
  41. */
  42. union rpmi_clk_rates {
  43. u64 discrete[RPMI_CLK_DISCRETE_MAX_NUM_RATES];
  44. struct {
  45. u64 min;
  46. u64 max;
  47. u64 step;
  48. } linear;
  49. };
  50. struct rpmi_clk {
  51. struct rpmi_clk_context *context;
  52. u32 id;
  53. u32 num_rates;
  54. u32 transition_latency;
  55. enum rpmi_clk_type type;
  56. union rpmi_clk_rates *rates;
  57. char name[RPMI_CLK_NAME_LEN];
  58. struct clk_hw hw;
  59. };
  60. struct rpmi_clk_rate_discrete {
  61. __le32 lo;
  62. __le32 hi;
  63. };
  64. struct rpmi_clk_rate_linear {
  65. __le32 min_lo;
  66. __le32 min_hi;
  67. __le32 max_lo;
  68. __le32 max_hi;
  69. __le32 step_lo;
  70. __le32 step_hi;
  71. };
  72. struct rpmi_get_num_clocks_rx {
  73. __le32 status;
  74. __le32 num_clocks;
  75. };
  76. struct rpmi_get_attrs_tx {
  77. __le32 clkid;
  78. };
  79. struct rpmi_get_attrs_rx {
  80. __le32 status;
  81. __le32 flags;
  82. __le32 num_rates;
  83. __le32 transition_latency;
  84. char name[RPMI_CLK_NAME_LEN];
  85. };
  86. struct rpmi_get_supp_rates_tx {
  87. __le32 clkid;
  88. __le32 clk_rate_idx;
  89. };
  90. struct rpmi_get_supp_rates_rx {
  91. __le32 status;
  92. __le32 flags;
  93. __le32 remaining;
  94. __le32 returned;
  95. __le32 rates[];
  96. };
  97. struct rpmi_get_rate_tx {
  98. __le32 clkid;
  99. };
  100. struct rpmi_get_rate_rx {
  101. __le32 status;
  102. __le32 lo;
  103. __le32 hi;
  104. };
  105. struct rpmi_set_rate_tx {
  106. __le32 clkid;
  107. __le32 flags;
  108. __le32 lo;
  109. __le32 hi;
  110. };
  111. struct rpmi_set_rate_rx {
  112. __le32 status;
  113. };
  114. struct rpmi_set_config_tx {
  115. __le32 clkid;
  116. __le32 config;
  117. };
  118. struct rpmi_set_config_rx {
  119. __le32 status;
  120. };
  121. static inline u64 rpmi_clkrate_u64(u32 __hi, u32 __lo)
  122. {
  123. return (((u64)(__hi) << 32) | (u32)(__lo));
  124. }
  125. static u32 rpmi_clk_get_num_clocks(struct rpmi_clk_context *context)
  126. {
  127. struct rpmi_get_num_clocks_rx rx, *resp;
  128. struct rpmi_mbox_message msg;
  129. int ret;
  130. rpmi_mbox_init_send_with_response(&msg, RPMI_CLK_SRV_GET_NUM_CLOCKS,
  131. NULL, 0, &rx, sizeof(rx));
  132. ret = rpmi_mbox_send_message(context->chan, &msg);
  133. if (ret)
  134. return 0;
  135. resp = rpmi_mbox_get_msg_response(&msg);
  136. if (!resp || resp->status)
  137. return 0;
  138. return le32_to_cpu(resp->num_clocks);
  139. }
  140. static int rpmi_clk_get_attrs(u32 clkid, struct rpmi_clk *rpmi_clk)
  141. {
  142. struct rpmi_clk_context *context = rpmi_clk->context;
  143. struct rpmi_mbox_message msg;
  144. struct rpmi_get_attrs_tx tx;
  145. struct rpmi_get_attrs_rx rx, *resp;
  146. u8 format;
  147. int ret;
  148. tx.clkid = cpu_to_le32(clkid);
  149. rpmi_mbox_init_send_with_response(&msg, RPMI_CLK_SRV_GET_ATTRIBUTES,
  150. &tx, sizeof(tx), &rx, sizeof(rx));
  151. ret = rpmi_mbox_send_message(context->chan, &msg);
  152. if (ret)
  153. return ret;
  154. resp = rpmi_mbox_get_msg_response(&msg);
  155. if (!resp)
  156. return -EINVAL;
  157. if (resp->status)
  158. return rpmi_to_linux_error(le32_to_cpu(resp->status));
  159. rpmi_clk->id = clkid;
  160. rpmi_clk->num_rates = le32_to_cpu(resp->num_rates);
  161. rpmi_clk->transition_latency = le32_to_cpu(resp->transition_latency);
  162. strscpy(rpmi_clk->name, resp->name, RPMI_CLK_NAME_LEN);
  163. format = le32_to_cpu(resp->flags) & RPMI_CLK_TYPE_MASK;
  164. if (format >= RPMI_CLK_TYPE_MAX_IDX)
  165. return -EINVAL;
  166. rpmi_clk->type = format;
  167. return 0;
  168. }
  169. static int rpmi_clk_get_supported_rates(u32 clkid, struct rpmi_clk *rpmi_clk)
  170. {
  171. struct rpmi_clk_context *context = rpmi_clk->context;
  172. struct rpmi_clk_rate_discrete *rate_discrete;
  173. struct rpmi_clk_rate_linear *rate_linear;
  174. struct rpmi_get_supp_rates_tx tx;
  175. struct rpmi_get_supp_rates_rx *resp;
  176. struct rpmi_mbox_message msg;
  177. size_t clk_rate_idx;
  178. int ret, rateidx, j;
  179. tx.clkid = cpu_to_le32(clkid);
  180. tx.clk_rate_idx = 0;
  181. /*
  182. * Make sure we allocate rx buffer sufficient to be accommodate all
  183. * the rates sent in one RPMI message.
  184. */
  185. struct rpmi_get_supp_rates_rx *rx __free(kfree) =
  186. kzalloc(context->max_msg_data_size, GFP_KERNEL);
  187. if (!rx)
  188. return -ENOMEM;
  189. rpmi_mbox_init_send_with_response(&msg, RPMI_CLK_SRV_GET_SUPPORTED_RATES,
  190. &tx, sizeof(tx), rx, context->max_msg_data_size);
  191. ret = rpmi_mbox_send_message(context->chan, &msg);
  192. if (ret)
  193. return ret;
  194. resp = rpmi_mbox_get_msg_response(&msg);
  195. if (!resp)
  196. return -EINVAL;
  197. if (resp->status)
  198. return rpmi_to_linux_error(le32_to_cpu(resp->status));
  199. if (!le32_to_cpu(resp->returned))
  200. return -EINVAL;
  201. if (rpmi_clk->type == RPMI_CLK_DISCRETE) {
  202. rate_discrete = (struct rpmi_clk_rate_discrete *)resp->rates;
  203. for (rateidx = 0; rateidx < le32_to_cpu(resp->returned); rateidx++) {
  204. rpmi_clk->rates->discrete[rateidx] =
  205. rpmi_clkrate_u64(le32_to_cpu(rate_discrete[rateidx].hi),
  206. le32_to_cpu(rate_discrete[rateidx].lo));
  207. }
  208. /*
  209. * Keep sending the request message until all
  210. * the rates are received.
  211. */
  212. clk_rate_idx = 0;
  213. while (le32_to_cpu(resp->remaining)) {
  214. clk_rate_idx += le32_to_cpu(resp->returned);
  215. tx.clk_rate_idx = cpu_to_le32(clk_rate_idx);
  216. rpmi_mbox_init_send_with_response(&msg,
  217. RPMI_CLK_SRV_GET_SUPPORTED_RATES,
  218. &tx, sizeof(tx),
  219. rx, context->max_msg_data_size);
  220. ret = rpmi_mbox_send_message(context->chan, &msg);
  221. if (ret)
  222. return ret;
  223. resp = rpmi_mbox_get_msg_response(&msg);
  224. if (!resp)
  225. return -EINVAL;
  226. if (resp->status)
  227. return rpmi_to_linux_error(le32_to_cpu(resp->status));
  228. if (!le32_to_cpu(resp->returned))
  229. return -EINVAL;
  230. for (j = 0; j < le32_to_cpu(resp->returned); j++) {
  231. if (rateidx >= clk_rate_idx + le32_to_cpu(resp->returned))
  232. break;
  233. rpmi_clk->rates->discrete[rateidx++] =
  234. rpmi_clkrate_u64(le32_to_cpu(rate_discrete[j].hi),
  235. le32_to_cpu(rate_discrete[j].lo));
  236. }
  237. }
  238. } else if (rpmi_clk->type == RPMI_CLK_LINEAR) {
  239. rate_linear = (struct rpmi_clk_rate_linear *)resp->rates;
  240. rpmi_clk->rates->linear.min = rpmi_clkrate_u64(le32_to_cpu(rate_linear->min_hi),
  241. le32_to_cpu(rate_linear->min_lo));
  242. rpmi_clk->rates->linear.max = rpmi_clkrate_u64(le32_to_cpu(rate_linear->max_hi),
  243. le32_to_cpu(rate_linear->max_lo));
  244. rpmi_clk->rates->linear.step = rpmi_clkrate_u64(le32_to_cpu(rate_linear->step_hi),
  245. le32_to_cpu(rate_linear->step_lo));
  246. }
  247. return 0;
  248. }
  249. static unsigned long rpmi_clk_recalc_rate(struct clk_hw *hw,
  250. unsigned long parent_rate)
  251. {
  252. struct rpmi_clk *rpmi_clk = to_rpmi_clk(hw);
  253. struct rpmi_clk_context *context = rpmi_clk->context;
  254. struct rpmi_mbox_message msg;
  255. struct rpmi_get_rate_tx tx;
  256. struct rpmi_get_rate_rx rx, *resp;
  257. int ret;
  258. tx.clkid = cpu_to_le32(rpmi_clk->id);
  259. rpmi_mbox_init_send_with_response(&msg, RPMI_CLK_SRV_GET_RATE,
  260. &tx, sizeof(tx), &rx, sizeof(rx));
  261. ret = rpmi_mbox_send_message(context->chan, &msg);
  262. if (ret)
  263. return ret;
  264. resp = rpmi_mbox_get_msg_response(&msg);
  265. if (!resp)
  266. return -EINVAL;
  267. if (resp->status)
  268. return rpmi_to_linux_error(le32_to_cpu(resp->status));
  269. return rpmi_clkrate_u64(le32_to_cpu(resp->hi), le32_to_cpu(resp->lo));
  270. }
  271. static int rpmi_clk_determine_rate(struct clk_hw *hw,
  272. struct clk_rate_request *req)
  273. {
  274. struct rpmi_clk *rpmi_clk = to_rpmi_clk(hw);
  275. u64 fmin, fmax, ftmp;
  276. /*
  277. * Keep the requested rate if the clock format
  278. * is of discrete type. Let the platform which
  279. * is actually controlling the clock handle that.
  280. */
  281. if (rpmi_clk->type == RPMI_CLK_DISCRETE)
  282. return 0;
  283. fmin = rpmi_clk->rates->linear.min;
  284. fmax = rpmi_clk->rates->linear.max;
  285. if (req->rate <= fmin) {
  286. req->rate = fmin;
  287. return 0;
  288. } else if (req->rate >= fmax) {
  289. req->rate = fmax;
  290. return 0;
  291. }
  292. ftmp = req->rate - fmin;
  293. ftmp += rpmi_clk->rates->linear.step - 1;
  294. do_div(ftmp, rpmi_clk->rates->linear.step);
  295. req->rate = ftmp * rpmi_clk->rates->linear.step + fmin;
  296. return 0;
  297. }
  298. static int rpmi_clk_set_rate(struct clk_hw *hw, unsigned long rate,
  299. unsigned long parent_rate)
  300. {
  301. struct rpmi_clk *rpmi_clk = to_rpmi_clk(hw);
  302. struct rpmi_clk_context *context = rpmi_clk->context;
  303. struct rpmi_mbox_message msg;
  304. struct rpmi_set_rate_tx tx;
  305. struct rpmi_set_rate_rx rx, *resp;
  306. int ret;
  307. tx.clkid = cpu_to_le32(rpmi_clk->id);
  308. tx.lo = cpu_to_le32(lower_32_bits(rate));
  309. tx.hi = cpu_to_le32(upper_32_bits(rate));
  310. rpmi_mbox_init_send_with_response(&msg, RPMI_CLK_SRV_SET_RATE,
  311. &tx, sizeof(tx), &rx, sizeof(rx));
  312. ret = rpmi_mbox_send_message(context->chan, &msg);
  313. if (ret)
  314. return ret;
  315. resp = rpmi_mbox_get_msg_response(&msg);
  316. if (!resp)
  317. return -EINVAL;
  318. if (resp->status)
  319. return rpmi_to_linux_error(le32_to_cpu(resp->status));
  320. return 0;
  321. }
  322. static int rpmi_clk_enable(struct clk_hw *hw)
  323. {
  324. struct rpmi_clk *rpmi_clk = to_rpmi_clk(hw);
  325. struct rpmi_clk_context *context = rpmi_clk->context;
  326. struct rpmi_mbox_message msg;
  327. struct rpmi_set_config_tx tx;
  328. struct rpmi_set_config_rx rx, *resp;
  329. int ret;
  330. tx.config = cpu_to_le32(RPMI_CLK_ENABLE);
  331. tx.clkid = cpu_to_le32(rpmi_clk->id);
  332. rpmi_mbox_init_send_with_response(&msg, RPMI_CLK_SRV_SET_CONFIG,
  333. &tx, sizeof(tx), &rx, sizeof(rx));
  334. ret = rpmi_mbox_send_message(context->chan, &msg);
  335. if (ret)
  336. return ret;
  337. resp = rpmi_mbox_get_msg_response(&msg);
  338. if (!resp)
  339. return -EINVAL;
  340. if (resp->status)
  341. return rpmi_to_linux_error(le32_to_cpu(resp->status));
  342. return 0;
  343. }
  344. static void rpmi_clk_disable(struct clk_hw *hw)
  345. {
  346. struct rpmi_clk *rpmi_clk = to_rpmi_clk(hw);
  347. struct rpmi_clk_context *context = rpmi_clk->context;
  348. struct rpmi_mbox_message msg;
  349. struct rpmi_set_config_tx tx;
  350. struct rpmi_set_config_rx rx;
  351. tx.config = cpu_to_le32(RPMI_CLK_DISABLE);
  352. tx.clkid = cpu_to_le32(rpmi_clk->id);
  353. rpmi_mbox_init_send_with_response(&msg, RPMI_CLK_SRV_SET_CONFIG,
  354. &tx, sizeof(tx), &rx, sizeof(rx));
  355. rpmi_mbox_send_message(context->chan, &msg);
  356. }
  357. static const struct clk_ops rpmi_clk_ops = {
  358. .recalc_rate = rpmi_clk_recalc_rate,
  359. .determine_rate = rpmi_clk_determine_rate,
  360. .set_rate = rpmi_clk_set_rate,
  361. .prepare = rpmi_clk_enable,
  362. .unprepare = rpmi_clk_disable,
  363. };
  364. static struct clk_hw *rpmi_clk_enumerate(struct rpmi_clk_context *context, u32 clkid)
  365. {
  366. struct device *dev = context->dev;
  367. unsigned long min_rate, max_rate;
  368. union rpmi_clk_rates *rates;
  369. struct rpmi_clk *rpmi_clk;
  370. struct clk_init_data init = {};
  371. struct clk_hw *clk_hw;
  372. int ret;
  373. rates = devm_kzalloc(dev, sizeof(*rates), GFP_KERNEL);
  374. if (!rates)
  375. return ERR_PTR(-ENOMEM);
  376. rpmi_clk = devm_kzalloc(dev, sizeof(*rpmi_clk), GFP_KERNEL);
  377. if (!rpmi_clk)
  378. return ERR_PTR(-ENOMEM);
  379. rpmi_clk->context = context;
  380. rpmi_clk->rates = rates;
  381. ret = rpmi_clk_get_attrs(clkid, rpmi_clk);
  382. if (ret)
  383. return dev_err_ptr_probe(dev, ret,
  384. "Failed to get clk-%u attributes\n",
  385. clkid);
  386. ret = rpmi_clk_get_supported_rates(clkid, rpmi_clk);
  387. if (ret)
  388. return dev_err_ptr_probe(dev, ret,
  389. "Get supported rates failed for clk-%u\n",
  390. clkid);
  391. init.flags = CLK_GET_RATE_NOCACHE;
  392. init.num_parents = 0;
  393. init.ops = &rpmi_clk_ops;
  394. init.name = rpmi_clk->name;
  395. clk_hw = &rpmi_clk->hw;
  396. clk_hw->init = &init;
  397. ret = devm_clk_hw_register(dev, clk_hw);
  398. if (ret)
  399. return dev_err_ptr_probe(dev, ret,
  400. "Unable to register clk-%u\n",
  401. clkid);
  402. if (rpmi_clk->type == RPMI_CLK_DISCRETE) {
  403. min_rate = rpmi_clk->rates->discrete[0];
  404. max_rate = rpmi_clk->rates->discrete[rpmi_clk->num_rates - 1];
  405. } else {
  406. min_rate = rpmi_clk->rates->linear.min;
  407. max_rate = rpmi_clk->rates->linear.max;
  408. }
  409. clk_hw_set_rate_range(clk_hw, min_rate, max_rate);
  410. return clk_hw;
  411. }
  412. static void rpmi_clk_mbox_chan_release(void *data)
  413. {
  414. struct mbox_chan *chan = data;
  415. mbox_free_channel(chan);
  416. }
  417. static int rpmi_clk_probe(struct platform_device *pdev)
  418. {
  419. int ret;
  420. unsigned int num_clocks, i;
  421. struct clk_hw_onecell_data *clk_data;
  422. struct rpmi_clk_context *context;
  423. struct rpmi_mbox_message msg;
  424. struct clk_hw *hw_ptr;
  425. struct device *dev = &pdev->dev;
  426. context = devm_kzalloc(dev, sizeof(*context), GFP_KERNEL);
  427. if (!context)
  428. return -ENOMEM;
  429. context->dev = dev;
  430. platform_set_drvdata(pdev, context);
  431. context->client.dev = context->dev;
  432. context->client.rx_callback = NULL;
  433. context->client.tx_block = false;
  434. context->client.knows_txdone = true;
  435. context->client.tx_tout = 0;
  436. context->chan = mbox_request_channel(&context->client, 0);
  437. if (IS_ERR(context->chan))
  438. return PTR_ERR(context->chan);
  439. ret = devm_add_action_or_reset(dev, rpmi_clk_mbox_chan_release, context->chan);
  440. if (ret)
  441. return dev_err_probe(dev, ret, "Failed to add rpmi mbox channel cleanup\n");
  442. rpmi_mbox_init_get_attribute(&msg, RPMI_MBOX_ATTR_SPEC_VERSION);
  443. ret = rpmi_mbox_send_message(context->chan, &msg);
  444. if (ret)
  445. return dev_err_probe(dev, ret, "Failed to get spec version\n");
  446. if (msg.attr.value < RPMI_MKVER(1, 0)) {
  447. return dev_err_probe(dev, -EINVAL,
  448. "msg protocol version mismatch, expected 0x%x, found 0x%x\n",
  449. RPMI_MKVER(1, 0), msg.attr.value);
  450. }
  451. rpmi_mbox_init_get_attribute(&msg, RPMI_MBOX_ATTR_SERVICEGROUP_ID);
  452. ret = rpmi_mbox_send_message(context->chan, &msg);
  453. if (ret)
  454. return dev_err_probe(dev, ret, "Failed to get service group ID\n");
  455. if (msg.attr.value != RPMI_SRVGRP_CLOCK) {
  456. return dev_err_probe(dev, -EINVAL,
  457. "service group match failed, expected 0x%x, found 0x%x\n",
  458. RPMI_SRVGRP_CLOCK, msg.attr.value);
  459. }
  460. rpmi_mbox_init_get_attribute(&msg, RPMI_MBOX_ATTR_SERVICEGROUP_VERSION);
  461. ret = rpmi_mbox_send_message(context->chan, &msg);
  462. if (ret)
  463. return dev_err_probe(dev, ret, "Failed to get service group version\n");
  464. if (msg.attr.value < RPMI_MKVER(1, 0)) {
  465. return dev_err_probe(dev, -EINVAL,
  466. "service group version failed, expected 0x%x, found 0x%x\n",
  467. RPMI_MKVER(1, 0), msg.attr.value);
  468. }
  469. rpmi_mbox_init_get_attribute(&msg, RPMI_MBOX_ATTR_MAX_MSG_DATA_SIZE);
  470. ret = rpmi_mbox_send_message(context->chan, &msg);
  471. if (ret)
  472. return dev_err_probe(dev, ret, "Failed to get max message data size\n");
  473. context->max_msg_data_size = msg.attr.value;
  474. num_clocks = rpmi_clk_get_num_clocks(context);
  475. if (!num_clocks)
  476. return dev_err_probe(dev, -ENODEV, "No clocks found\n");
  477. clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, num_clocks),
  478. GFP_KERNEL);
  479. if (!clk_data)
  480. return dev_err_probe(dev, -ENOMEM, "No memory for clock data\n");
  481. clk_data->num = num_clocks;
  482. for (i = 0; i < clk_data->num; i++) {
  483. hw_ptr = rpmi_clk_enumerate(context, i);
  484. if (IS_ERR(hw_ptr)) {
  485. return dev_err_probe(dev, PTR_ERR(hw_ptr),
  486. "Failed to register clk-%d\n", i);
  487. }
  488. clk_data->hws[i] = hw_ptr;
  489. }
  490. ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clk_data);
  491. if (ret)
  492. return dev_err_probe(dev, ret, "Failed to register clock HW provider\n");
  493. return 0;
  494. }
  495. static const struct of_device_id rpmi_clk_of_match[] = {
  496. { .compatible = "riscv,rpmi-clock" },
  497. { }
  498. };
  499. MODULE_DEVICE_TABLE(of, rpmi_clk_of_match);
  500. static struct platform_driver rpmi_clk_driver = {
  501. .driver = {
  502. .name = "riscv-rpmi-clock",
  503. .of_match_table = rpmi_clk_of_match,
  504. },
  505. .probe = rpmi_clk_probe,
  506. };
  507. module_platform_driver(rpmi_clk_driver);
  508. MODULE_AUTHOR("Rahul Pathak <rpathak@ventanamicro.com>");
  509. MODULE_DESCRIPTION("Clock Driver based on RPMI message protocol");
  510. MODULE_LICENSE("GPL");