sci-clk.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589
  1. /*
  2. * SCI Clock driver for keystone based devices
  3. *
  4. * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/
  5. * Tero Kristo <t-kristo@ti.com>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License version 2 as
  9. * published by the Free Software Foundation.
  10. *
  11. * This program is distributed "as is" WITHOUT ANY WARRANTY of any
  12. * kind, whether express or implied; without even the implied warranty
  13. * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. */
  16. #include <linux/clk-provider.h>
  17. #include <linux/err.h>
  18. #include <linux/io.h>
  19. #include <linux/module.h>
  20. #include <linux/of_address.h>
  21. #include <linux/of.h>
  22. #include <linux/platform_device.h>
  23. #include <linux/slab.h>
  24. #include <linux/soc/ti/ti_sci_protocol.h>
  25. #include <dt-bindings/clock/k2g.h>
  26. #include <dt-bindings/genpd/k2g.h>
  27. #define SCI_CLK_SSC_ENABLE BIT(0)
  28. #define SCI_CLK_ALLOW_FREQ_CHANGE BIT(1)
  29. #define SCI_CLK_INPUT_TERMINATION BIT(2)
  30. /**
  31. * struct sci_clk_data - TI SCI clock data
  32. * @dev: device index
  33. * @num_clks: number of clocks for this device
  34. * @clocks: clocks array for this device
  35. */
  36. struct sci_clk_data {
  37. u16 dev;
  38. u16 num_clks;
  39. struct clk_hw **clocks;
  40. };
  41. /**
  42. * struct sci_clk_provider - TI SCI clock provider representation
  43. * @sci: Handle to the System Control Interface protocol handler
  44. * @ops: Pointer to the SCI ops to be used by the clocks
  45. * @dev: Device pointer for the clock provider
  46. * @clocks: Clock data
  47. */
  48. struct sci_clk_provider {
  49. const struct ti_sci_handle *sci;
  50. const struct ti_sci_clk_ops *ops;
  51. struct device *dev;
  52. struct sci_clk_data *clocks;
  53. };
  54. /**
  55. * struct sci_clk - TI SCI clock representation
  56. * @hw: Hardware clock cookie for common clock framework
  57. * @dev_id: Device index
  58. * @clk_id: Clock index
  59. * @node: Clocks list link
  60. * @provider: Master clock provider
  61. * @flags: Flags for the clock
  62. */
  63. struct sci_clk {
  64. struct clk_hw hw;
  65. u16 dev_id;
  66. u8 clk_id;
  67. struct list_head node;
  68. struct sci_clk_provider *provider;
  69. u8 flags;
  70. };
  71. #define to_sci_clk(_hw) container_of(_hw, struct sci_clk, hw)
  72. /**
  73. * sci_clk_prepare - Prepare (enable) a TI SCI clock
  74. * @hw: clock to prepare
  75. *
  76. * Prepares a clock to be actively used. Returns the SCI protocol status.
  77. */
  78. static int sci_clk_prepare(struct clk_hw *hw)
  79. {
  80. struct sci_clk *clk = to_sci_clk(hw);
  81. bool enable_ssc = clk->flags & SCI_CLK_SSC_ENABLE;
  82. bool allow_freq_change = clk->flags & SCI_CLK_ALLOW_FREQ_CHANGE;
  83. bool input_termination = clk->flags & SCI_CLK_INPUT_TERMINATION;
  84. return clk->provider->ops->get_clock(clk->provider->sci, clk->dev_id,
  85. clk->clk_id, enable_ssc,
  86. allow_freq_change,
  87. input_termination);
  88. }
  89. /**
  90. * sci_clk_unprepare - Un-prepares (disables) a TI SCI clock
  91. * @hw: clock to unprepare
  92. *
  93. * Un-prepares a clock from active state.
  94. */
  95. static void sci_clk_unprepare(struct clk_hw *hw)
  96. {
  97. struct sci_clk *clk = to_sci_clk(hw);
  98. int ret;
  99. ret = clk->provider->ops->put_clock(clk->provider->sci, clk->dev_id,
  100. clk->clk_id);
  101. if (ret)
  102. dev_err(clk->provider->dev,
  103. "unprepare failed for dev=%d, clk=%d, ret=%d\n",
  104. clk->dev_id, clk->clk_id, ret);
  105. }
  106. /**
  107. * sci_clk_is_prepared - Check if a TI SCI clock is prepared or not
  108. * @hw: clock to check status for
  109. *
  110. * Checks if a clock is prepared (enabled) in hardware. Returns non-zero
  111. * value if clock is enabled, zero otherwise.
  112. */
  113. static int sci_clk_is_prepared(struct clk_hw *hw)
  114. {
  115. struct sci_clk *clk = to_sci_clk(hw);
  116. bool req_state, current_state;
  117. int ret;
  118. ret = clk->provider->ops->is_on(clk->provider->sci, clk->dev_id,
  119. clk->clk_id, &req_state,
  120. &current_state);
  121. if (ret) {
  122. dev_err(clk->provider->dev,
  123. "is_prepared failed for dev=%d, clk=%d, ret=%d\n",
  124. clk->dev_id, clk->clk_id, ret);
  125. return 0;
  126. }
  127. return req_state;
  128. }
  129. /**
  130. * sci_clk_recalc_rate - Get clock rate for a TI SCI clock
  131. * @hw: clock to get rate for
  132. * @parent_rate: parent rate provided by common clock framework, not used
  133. *
  134. * Gets the current clock rate of a TI SCI clock. Returns the current
  135. * clock rate, or zero in failure.
  136. */
  137. static unsigned long sci_clk_recalc_rate(struct clk_hw *hw,
  138. unsigned long parent_rate)
  139. {
  140. struct sci_clk *clk = to_sci_clk(hw);
  141. u64 freq;
  142. int ret;
  143. ret = clk->provider->ops->get_freq(clk->provider->sci, clk->dev_id,
  144. clk->clk_id, &freq);
  145. if (ret) {
  146. dev_err(clk->provider->dev,
  147. "recalc-rate failed for dev=%d, clk=%d, ret=%d\n",
  148. clk->dev_id, clk->clk_id, ret);
  149. return 0;
  150. }
  151. return (u32)freq;
  152. }
  153. /**
  154. * sci_clk_determine_rate - Determines a clock rate a clock can be set to
  155. * @hw: clock to change rate for
  156. * @req: requested rate configuration for the clock
  157. *
  158. * Determines a suitable clock rate and parent for a TI SCI clock.
  159. * The parent handling is un-used, as generally the parent clock rates
  160. * are not known by the kernel; instead these are internally handled
  161. * by the firmware. Returns 0 on success, negative error value on failure.
  162. */
  163. static int sci_clk_determine_rate(struct clk_hw *hw,
  164. struct clk_rate_request *req)
  165. {
  166. struct sci_clk *clk = to_sci_clk(hw);
  167. int ret;
  168. u64 new_rate;
  169. ret = clk->provider->ops->get_best_match_freq(clk->provider->sci,
  170. clk->dev_id,
  171. clk->clk_id,
  172. req->min_rate,
  173. req->rate,
  174. req->max_rate,
  175. &new_rate);
  176. if (ret) {
  177. dev_err(clk->provider->dev,
  178. "determine-rate failed for dev=%d, clk=%d, ret=%d\n",
  179. clk->dev_id, clk->clk_id, ret);
  180. return ret;
  181. }
  182. req->rate = new_rate;
  183. return 0;
  184. }
  185. /**
  186. * sci_clk_set_rate - Set rate for a TI SCI clock
  187. * @hw: clock to change rate for
  188. * @rate: target rate for the clock
  189. * @parent_rate: rate of the clock parent, not used for TI SCI clocks
  190. *
  191. * Sets a clock frequency for a TI SCI clock. Returns the TI SCI
  192. * protocol status.
  193. */
  194. static int sci_clk_set_rate(struct clk_hw *hw, unsigned long rate,
  195. unsigned long parent_rate)
  196. {
  197. struct sci_clk *clk = to_sci_clk(hw);
  198. return clk->provider->ops->set_freq(clk->provider->sci, clk->dev_id,
  199. clk->clk_id, rate, rate, rate);
  200. }
  201. /**
  202. * sci_clk_get_parent - Get the current parent of a TI SCI clock
  203. * @hw: clock to get parent for
  204. *
  205. * Returns the index of the currently selected parent for a TI SCI clock.
  206. */
  207. static u8 sci_clk_get_parent(struct clk_hw *hw)
  208. {
  209. struct sci_clk *clk = to_sci_clk(hw);
  210. u8 parent_id;
  211. int ret;
  212. ret = clk->provider->ops->get_parent(clk->provider->sci, clk->dev_id,
  213. clk->clk_id, &parent_id);
  214. if (ret) {
  215. dev_err(clk->provider->dev,
  216. "get-parent failed for dev=%d, clk=%d, ret=%d\n",
  217. clk->dev_id, clk->clk_id, ret);
  218. return 0;
  219. }
  220. return parent_id - clk->clk_id - 1;
  221. }
  222. /**
  223. * sci_clk_set_parent - Set the parent of a TI SCI clock
  224. * @hw: clock to set parent for
  225. * @index: new parent index for the clock
  226. *
  227. * Sets the parent of a TI SCI clock. Return TI SCI protocol status.
  228. */
  229. static int sci_clk_set_parent(struct clk_hw *hw, u8 index)
  230. {
  231. struct sci_clk *clk = to_sci_clk(hw);
  232. return clk->provider->ops->set_parent(clk->provider->sci, clk->dev_id,
  233. clk->clk_id,
  234. index + 1 + clk->clk_id);
  235. }
  236. static const struct clk_ops sci_clk_ops = {
  237. .prepare = sci_clk_prepare,
  238. .unprepare = sci_clk_unprepare,
  239. .is_prepared = sci_clk_is_prepared,
  240. .recalc_rate = sci_clk_recalc_rate,
  241. .determine_rate = sci_clk_determine_rate,
  242. .set_rate = sci_clk_set_rate,
  243. .get_parent = sci_clk_get_parent,
  244. .set_parent = sci_clk_set_parent,
  245. };
  246. /**
  247. * _sci_clk_get - Gets a handle for an SCI clock
  248. * @provider: Handle to SCI clock provider
  249. * @dev_id: device ID for the clock to register
  250. * @clk_id: clock ID for the clock to register
  251. *
  252. * Gets a handle to an existing TI SCI hw clock, or builds a new clock
  253. * entry and registers it with the common clock framework. Called from
  254. * the common clock framework, when a corresponding of_clk_get call is
  255. * executed, or recursively from itself when parsing parent clocks.
  256. * Returns a pointer to the hw clock struct, or ERR_PTR value in failure.
  257. */
  258. static struct clk_hw *_sci_clk_build(struct sci_clk_provider *provider,
  259. u16 dev_id, u8 clk_id)
  260. {
  261. struct clk_init_data init = { NULL };
  262. struct sci_clk *sci_clk = NULL;
  263. char *name = NULL;
  264. char **parent_names = NULL;
  265. int i;
  266. int ret;
  267. sci_clk = devm_kzalloc(provider->dev, sizeof(*sci_clk), GFP_KERNEL);
  268. if (!sci_clk)
  269. return ERR_PTR(-ENOMEM);
  270. sci_clk->dev_id = dev_id;
  271. sci_clk->clk_id = clk_id;
  272. sci_clk->provider = provider;
  273. ret = provider->ops->get_num_parents(provider->sci, dev_id,
  274. clk_id,
  275. &init.num_parents);
  276. if (ret)
  277. goto err;
  278. name = kasprintf(GFP_KERNEL, "%s:%d:%d", dev_name(provider->dev),
  279. sci_clk->dev_id, sci_clk->clk_id);
  280. init.name = name;
  281. if (init.num_parents < 2)
  282. init.num_parents = 0;
  283. if (init.num_parents) {
  284. parent_names = devm_kcalloc(provider->dev, init.num_parents,
  285. sizeof(char *), GFP_KERNEL);
  286. if (!parent_names) {
  287. ret = -ENOMEM;
  288. goto err;
  289. }
  290. for (i = 0; i < init.num_parents; i++) {
  291. char *parent_name;
  292. parent_name = kasprintf(GFP_KERNEL, "%s:%d:%d",
  293. dev_name(provider->dev),
  294. sci_clk->dev_id,
  295. sci_clk->clk_id + 1 + i);
  296. if (!parent_name) {
  297. ret = -ENOMEM;
  298. goto err;
  299. }
  300. parent_names[i] = parent_name;
  301. }
  302. init.parent_names = (const char * const *)parent_names;
  303. }
  304. init.ops = &sci_clk_ops;
  305. sci_clk->hw.init = &init;
  306. ret = devm_clk_hw_register(provider->dev, &sci_clk->hw);
  307. if (ret) {
  308. dev_err(provider->dev, "failed clk register with %d\n", ret);
  309. goto err;
  310. }
  311. kfree(name);
  312. return &sci_clk->hw;
  313. err:
  314. if (parent_names) {
  315. for (i = 0; i < init.num_parents; i++)
  316. devm_kfree(provider->dev, parent_names[i]);
  317. devm_kfree(provider->dev, parent_names);
  318. }
  319. devm_kfree(provider->dev, sci_clk);
  320. kfree(name);
  321. return ERR_PTR(ret);
  322. }
  323. /**
  324. * sci_clk_get - Xlate function for getting clock handles
  325. * @clkspec: device tree clock specifier
  326. * @data: pointer to the clock provider
  327. *
  328. * Xlate function for retrieving clock TI SCI hw clock handles based on
  329. * device tree clock specifier. Called from the common clock framework,
  330. * when a corresponding of_clk_get call is executed. Returns a pointer
  331. * to the TI SCI hw clock struct, or ERR_PTR value in failure.
  332. */
  333. static struct clk_hw *sci_clk_get(struct of_phandle_args *clkspec, void *data)
  334. {
  335. struct sci_clk_provider *provider = data;
  336. u16 dev_id;
  337. u8 clk_id;
  338. struct sci_clk_data *clks = provider->clocks;
  339. if (clkspec->args_count != 2)
  340. return ERR_PTR(-EINVAL);
  341. dev_id = clkspec->args[0];
  342. clk_id = clkspec->args[1];
  343. while (clks->num_clks) {
  344. if (clks->dev == dev_id) {
  345. if (clk_id >= clks->num_clks)
  346. return ERR_PTR(-EINVAL);
  347. return clks->clocks[clk_id];
  348. }
  349. clks++;
  350. }
  351. return ERR_PTR(-ENODEV);
  352. }
  353. int ti_sci_init_clocks(struct sci_clk_provider *p)
  354. {
  355. struct sci_clk_data *data = p->clocks;
  356. struct clk_hw *hw;
  357. int i;
  358. while (data->num_clks) {
  359. data->clocks = devm_kcalloc(p->dev, data->num_clks,
  360. sizeof(struct sci_clk),
  361. GFP_KERNEL);
  362. if (!data->clocks)
  363. return -ENOMEM;
  364. for (i = 0; i < data->num_clks; i++) {
  365. hw = _sci_clk_build(p, data->dev, i);
  366. if (!IS_ERR(hw)) {
  367. data->clocks[i] = hw;
  368. continue;
  369. }
  370. /* Skip any holes in the clock lists */
  371. if (PTR_ERR(hw) == -ENODEV)
  372. continue;
  373. return PTR_ERR(hw);
  374. }
  375. data++;
  376. }
  377. return 0;
  378. }
  379. static const struct sci_clk_data k2g_clk_data[] = {
  380. { .dev = K2G_DEV_PMMC0, .num_clks = K2G_DEV_PMMC_MPM_DAP_CLK + 1 },
  381. { .dev = K2G_DEV_MLB0, .num_clks = K2G_DEV_MLB_MLBP_IO_CLK + 1 },
  382. { .dev = K2G_DEV_DSS0, .num_clks = K2G_DEV_DSS_PI_DSS_VP_CLK + 1 },
  383. { .dev = K2G_DEV_MCBSP0, .num_clks = K2G_DEV_MCBSP_CLKS_PARENT_UART_PLL + 1 },
  384. { .dev = K2G_DEV_MCASP0, .num_clks = K2G_DEV_MCASP_AUX_CLK_PARENT_UART_PLL + 1 },
  385. { .dev = K2G_DEV_MCASP1, .num_clks = K2G_DEV_MCASP_AUX_CLK_PARENT_UART_PLL + 1 },
  386. { .dev = K2G_DEV_MCASP2, .num_clks = K2G_DEV_MCASP_AUX_CLK_PARENT_UART_PLL + 1 },
  387. { .dev = K2G_DEV_DCAN0, .num_clks = K2G_DEV_DCAN_CAN_CLK + 1 },
  388. { .dev = K2G_DEV_DCAN1, .num_clks = K2G_DEV_DCAN_CAN_CLK + 1 },
  389. { .dev = K2G_DEV_EMIF0, .num_clks = K2G_DEV_EMIF_VBUSP_CLK + 1 },
  390. { .dev = K2G_DEV_MMCHS0, .num_clks = K2G_DEV_MMCHS_CLK32K + 1 },
  391. { .dev = K2G_DEV_MMCHS1, .num_clks = K2G_DEV_MMCHS_CLK32K + 1 },
  392. { .dev = K2G_DEV_GPMC0, .num_clks = K2G_DEV_GPMC_GPMC_FCLK + 1 },
  393. { .dev = K2G_DEV_ELM0, .num_clks = K2G_DEV_ELM_CLK + 1 },
  394. { .dev = K2G_DEV_SPI0, .num_clks = K2G_DEV_SPI_VBUSP_CLK + 1 },
  395. { .dev = K2G_DEV_SPI1, .num_clks = K2G_DEV_SPI_VBUSP_CLK + 1 },
  396. { .dev = K2G_DEV_SPI2, .num_clks = K2G_DEV_SPI_VBUSP_CLK + 1 },
  397. { .dev = K2G_DEV_SPI3, .num_clks = K2G_DEV_SPI_VBUSP_CLK + 1 },
  398. { .dev = K2G_DEV_ICSS0, .num_clks = K2G_DEV_ICSS_IEPCLK_CLK + 1 },
  399. { .dev = K2G_DEV_ICSS1, .num_clks = K2G_DEV_ICSS_IEPCLK_CLK + 1 },
  400. { .dev = K2G_DEV_USB0, .num_clks = K2G_DEV_USB_CLKCORE + 1 },
  401. { .dev = K2G_DEV_USB1, .num_clks = K2G_DEV_USB_CLKCORE + 1 },
  402. { .dev = K2G_DEV_NSS0, .num_clks = K2G_DEV_NSS_RMII_MHZ_50_CLK + 1 },
  403. { .dev = K2G_DEV_PCIE0, .num_clks = K2G_DEV_PCIE_VBUS_CLK + 1 },
  404. { .dev = K2G_DEV_GPIO0, .num_clks = K2G_DEV_GPIO_VBUS_CLK + 1 },
  405. { .dev = K2G_DEV_GPIO1, .num_clks = K2G_DEV_GPIO_VBUS_CLK + 1 },
  406. { .dev = K2G_DEV_TIMER64_0, .num_clks = K2G_DEV_TIMER64_TOUTH + 1 },
  407. { .dev = K2G_DEV_TIMER64_1, .num_clks = K2G_DEV_TIMER64_TOUTH + 1 },
  408. { .dev = K2G_DEV_TIMER64_2, .num_clks = K2G_DEV_TIMER64_TOUTH + 1 },
  409. { .dev = K2G_DEV_TIMER64_3, .num_clks = K2G_DEV_TIMER64_TOUTH + 1 },
  410. { .dev = K2G_DEV_TIMER64_4, .num_clks = K2G_DEV_TIMER64_TOUTH + 1 },
  411. { .dev = K2G_DEV_TIMER64_5, .num_clks = K2G_DEV_TIMER64_TOUTH + 1 },
  412. { .dev = K2G_DEV_TIMER64_6, .num_clks = K2G_DEV_TIMER64_TOUTH + 1 },
  413. { .dev = K2G_DEV_MSGMGR0, .num_clks = K2G_DEV_MSGMGR_VBUS_CLK + 1 },
  414. { .dev = K2G_DEV_BOOTCFG0, .num_clks = K2G_DEV_BOOTCFG_VBUS_CLK + 1 },
  415. { .dev = K2G_DEV_ARM_BOOTROM0, .num_clks = K2G_DEV_ARM_BOOTROM_VBUS_CLK + 1 },
  416. { .dev = K2G_DEV_DSP_BOOTROM0, .num_clks = K2G_DEV_DSP_BOOTROM_VBUS_CLK + 1 },
  417. { .dev = K2G_DEV_DEBUGSS0, .num_clks = K2G_DEV_DEBUGSS_STMXPT_CLK + 1 },
  418. { .dev = K2G_DEV_UART0, .num_clks = K2G_DEV_UART_CBA_CLK_PI + 1 },
  419. { .dev = K2G_DEV_UART1, .num_clks = K2G_DEV_UART_CBA_CLK_PI + 1 },
  420. { .dev = K2G_DEV_UART2, .num_clks = K2G_DEV_UART_CBA_CLK_PI + 1 },
  421. { .dev = K2G_DEV_EHRPWM0, .num_clks = K2G_DEV_EHRPWM_VBUS_CLK + 1 },
  422. { .dev = K2G_DEV_EHRPWM1, .num_clks = K2G_DEV_EHRPWM_VBUS_CLK + 1 },
  423. { .dev = K2G_DEV_EHRPWM2, .num_clks = K2G_DEV_EHRPWM_VBUS_CLK + 1 },
  424. { .dev = K2G_DEV_EHRPWM3, .num_clks = K2G_DEV_EHRPWM_VBUS_CLK + 1 },
  425. { .dev = K2G_DEV_EHRPWM4, .num_clks = K2G_DEV_EHRPWM_VBUS_CLK + 1 },
  426. { .dev = K2G_DEV_EHRPWM5, .num_clks = K2G_DEV_EHRPWM_VBUS_CLK + 1 },
  427. { .dev = K2G_DEV_EQEP0, .num_clks = K2G_DEV_EQEP_VBUS_CLK + 1 },
  428. { .dev = K2G_DEV_EQEP1, .num_clks = K2G_DEV_EQEP_VBUS_CLK + 1 },
  429. { .dev = K2G_DEV_EQEP2, .num_clks = K2G_DEV_EQEP_VBUS_CLK + 1 },
  430. { .dev = K2G_DEV_ECAP0, .num_clks = K2G_DEV_ECAP_VBUS_CLK + 1 },
  431. { .dev = K2G_DEV_ECAP1, .num_clks = K2G_DEV_ECAP_VBUS_CLK + 1 },
  432. { .dev = K2G_DEV_I2C0, .num_clks = K2G_DEV_I2C_VBUS_CLK + 1 },
  433. { .dev = K2G_DEV_I2C1, .num_clks = K2G_DEV_I2C_VBUS_CLK + 1 },
  434. { .dev = K2G_DEV_I2C2, .num_clks = K2G_DEV_I2C_VBUS_CLK + 1 },
  435. { .dev = K2G_DEV_EDMA0, .num_clks = K2G_DEV_EDMA_TPCC_CLK + 1 },
  436. { .dev = K2G_DEV_SEMAPHORE0, .num_clks = K2G_DEV_SEMAPHORE_VBUS_CLK + 1 },
  437. { .dev = K2G_DEV_INTC0, .num_clks = K2G_DEV_INTC_VBUS_CLK + 1 },
  438. { .dev = K2G_DEV_GIC0, .num_clks = K2G_DEV_GIC_VBUS_CLK + 1 },
  439. { .dev = K2G_DEV_QSPI0, .num_clks = K2G_DEV_QSPI_QSPI_CLK_I + 1 },
  440. { .dev = K2G_DEV_ARM_64B_COUNTER0, .num_clks = K2G_DEV_ARM_64B_COUNTER_VBUSP_CLK + 1 },
  441. { .dev = K2G_DEV_TETRIS0, .num_clks = K2G_DEV_TETRIS_SUBSYS_CLK + 1 },
  442. { .dev = K2G_DEV_CGEM0, .num_clks = K2G_DEV_CGEM_TRACE_CLK + 1 },
  443. { .dev = K2G_DEV_MSMC0, .num_clks = K2G_DEV_MSMC_VBUS_CLK + 1 },
  444. { .dev = K2G_DEV_CBASS0, .num_clks = K2G_DEV_CBASS_VBUS_CLK + 1 },
  445. { .dev = K2G_DEV_BOARD0, .num_clks = K2G_DEV_BOARD_TIMO_PARENT_TIMER64_5H + 1 },
  446. { .dev = K2G_DEV_EDMA1, .num_clks = K2G_DEV_EDMA_TPCC_CLK + 1 },
  447. { .num_clks = 0 },
  448. };
  449. static const struct of_device_id ti_sci_clk_of_match[] = {
  450. { .compatible = "ti,k2g-sci-clk", .data = &k2g_clk_data },
  451. { /* Sentinel */ },
  452. };
  453. MODULE_DEVICE_TABLE(of, ti_sci_clk_of_match);
  454. /**
  455. * ti_sci_clk_probe - Probe function for the TI SCI clock driver
  456. * @pdev: platform device pointer to be probed
  457. *
  458. * Probes the TI SCI clock device. Allocates a new clock provider
  459. * and registers this to the common clock framework. Also applies
  460. * any required flags to the identified clocks via clock lists
  461. * supplied from DT. Returns 0 for success, negative error value
  462. * for failure.
  463. */
  464. static int ti_sci_clk_probe(struct platform_device *pdev)
  465. {
  466. struct device *dev = &pdev->dev;
  467. struct device_node *np = dev->of_node;
  468. struct sci_clk_provider *provider;
  469. const struct ti_sci_handle *handle;
  470. struct sci_clk_data *data;
  471. int ret;
  472. data = (struct sci_clk_data *)
  473. of_match_node(ti_sci_clk_of_match, np)->data;
  474. handle = devm_ti_sci_get_handle(dev);
  475. if (IS_ERR(handle))
  476. return PTR_ERR(handle);
  477. provider = devm_kzalloc(dev, sizeof(*provider), GFP_KERNEL);
  478. if (!provider)
  479. return -ENOMEM;
  480. provider->clocks = data;
  481. provider->sci = handle;
  482. provider->ops = &handle->ops.clk_ops;
  483. provider->dev = dev;
  484. ti_sci_init_clocks(provider);
  485. ret = of_clk_add_hw_provider(np, sci_clk_get, provider);
  486. if (ret)
  487. return ret;
  488. return 0;
  489. }
  490. /**
  491. * ti_sci_clk_remove - Remove TI SCI clock device
  492. * @pdev: platform device pointer for the device to be removed
  493. *
  494. * Removes the TI SCI device. Unregisters the clock provider registered
  495. * via common clock framework. Any memory allocated for the device will
  496. * be free'd silently via the devm framework. Returns 0 always.
  497. */
  498. static int ti_sci_clk_remove(struct platform_device *pdev)
  499. {
  500. of_clk_del_provider(pdev->dev.of_node);
  501. return 0;
  502. }
  503. static struct platform_driver ti_sci_clk_driver = {
  504. .probe = ti_sci_clk_probe,
  505. .remove = ti_sci_clk_remove,
  506. .driver = {
  507. .name = "ti-sci-clk",
  508. .of_match_table = of_match_ptr(ti_sci_clk_of_match),
  509. },
  510. };
  511. module_platform_driver(ti_sci_clk_driver);
  512. MODULE_LICENSE("GPL v2");
  513. MODULE_DESCRIPTION("TI System Control Interface(SCI) Clock driver");
  514. MODULE_AUTHOR("Tero Kristo");
  515. MODULE_ALIAS("platform:ti-sci-clk");