mpc83xx_clk.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * (C) Copyright 2017
  4. * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
  5. */
  6. #include <common.h>
  7. #include <clk-uclass.h>
  8. #include <clock_legacy.h>
  9. #include <command.h>
  10. #include <dm.h>
  11. #include <log.h>
  12. #include <vsprintf.h>
  13. #include <dm/lists.h>
  14. #include <dt-bindings/clk/mpc83xx-clk.h>
  15. #include <asm/arch/soc.h>
  16. #include <linux/bitops.h>
  17. #include "mpc83xx_clk.h"
  18. DECLARE_GLOBAL_DATA_PTR;
  19. /**
  20. * struct mpc83xx_clk_priv - Private data structure for the MPC83xx clock
  21. * driver
  22. * @speed: Array containing the speed values of all system clocks (initialized
  23. * once, then only read back)
  24. */
  25. struct mpc83xx_clk_priv {
  26. u32 speed[MPC83XX_CLK_COUNT];
  27. };
  28. /**
  29. * is_clk_valid() - Check if clock ID is valid for given clock device
  30. * @clk: The clock device for which to check a clock ID
  31. * @id: The clock ID to check
  32. *
  33. * Return: true if clock ID is valid for clock device, false if not
  34. */
  35. static inline bool is_clk_valid(struct udevice *clk, int id)
  36. {
  37. ulong type = dev_get_driver_data(clk);
  38. switch (id) {
  39. case MPC83XX_CLK_MEM:
  40. return true;
  41. case MPC83XX_CLK_MEM_SEC:
  42. return type == SOC_MPC8360;
  43. case MPC83XX_CLK_ENC:
  44. return (type == SOC_MPC8308) || (type == SOC_MPC8309);
  45. case MPC83XX_CLK_I2C1:
  46. return true;
  47. case MPC83XX_CLK_TDM:
  48. return type == SOC_MPC8315;
  49. case MPC83XX_CLK_SDHC:
  50. return mpc83xx_has_sdhc(type);
  51. case MPC83XX_CLK_TSEC1:
  52. case MPC83XX_CLK_TSEC2:
  53. return mpc83xx_has_tsec(type);
  54. case MPC83XX_CLK_USBDR:
  55. return type == SOC_MPC8360;
  56. case MPC83XX_CLK_USBMPH:
  57. return type == SOC_MPC8349;
  58. case MPC83XX_CLK_PCIEXP1:
  59. return mpc83xx_has_pcie1(type);
  60. case MPC83XX_CLK_PCIEXP2:
  61. return mpc83xx_has_pcie2(type);
  62. case MPC83XX_CLK_SATA:
  63. return mpc83xx_has_sata(type);
  64. case MPC83XX_CLK_DMAC:
  65. return (type == SOC_MPC8308) || (type == SOC_MPC8309);
  66. case MPC83XX_CLK_PCI:
  67. /*
  68. * FIXME: implement proper support for this.
  69. */
  70. return 0 && mpc83xx_has_pci(type);
  71. case MPC83XX_CLK_CSB:
  72. return true;
  73. case MPC83XX_CLK_I2C2:
  74. return mpc83xx_has_second_i2c(type);
  75. case MPC83XX_CLK_QE:
  76. case MPC83XX_CLK_BRG:
  77. return mpc83xx_has_quicc_engine(type) && (type != SOC_MPC8309);
  78. case MPC83XX_CLK_LCLK:
  79. case MPC83XX_CLK_LBIU:
  80. case MPC83XX_CLK_CORE:
  81. return true;
  82. }
  83. return false;
  84. }
  85. /**
  86. * init_single_clk() - Initialize a clock with a given ID
  87. * @dev: The clock device for which to initialize the clock
  88. * @clk: The clock ID
  89. *
  90. * The clock speed is read from the hardware's registers, and stored in the
  91. * private data structure of the driver. From there it is only retrieved, and
  92. * not set.
  93. *
  94. * Return: 0 if OK, -ve on error
  95. */
  96. static int init_single_clk(struct udevice *dev, int clk)
  97. {
  98. struct mpc83xx_clk_priv *priv = dev_get_priv(dev);
  99. immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
  100. ulong type = dev_get_driver_data(dev);
  101. struct clk_mode mode;
  102. ulong mask;
  103. u32 csb_clk = get_csb_clk(im);
  104. int ret;
  105. ret = retrieve_mode(clk, type, &mode);
  106. if (ret) {
  107. debug("%s: Could not retrieve mode for clk %d (ret = %d)\n",
  108. dev->name, clk, ret);
  109. return ret;
  110. }
  111. if (mode.type == TYPE_INVALID) {
  112. debug("%s: clock %d invalid\n", dev->name, clk);
  113. return -EINVAL;
  114. }
  115. if (mode.type == TYPE_SCCR_STANDARD) {
  116. mask = GENMASK(31 - mode.low, 31 - mode.high);
  117. switch (sccr_field(im, mask)) {
  118. case 0:
  119. priv->speed[clk] = 0;
  120. break;
  121. case 1:
  122. priv->speed[clk] = csb_clk;
  123. break;
  124. case 2:
  125. priv->speed[clk] = csb_clk / 2;
  126. break;
  127. case 3:
  128. priv->speed[clk] = csb_clk / 3;
  129. break;
  130. default:
  131. priv->speed[clk] = 0;
  132. }
  133. return 0;
  134. }
  135. if (mode.type == TYPE_SPMR_DIRECT_MULTIPLY) {
  136. mask = GENMASK(31 - mode.low, 31 - mode.high);
  137. priv->speed[clk] = csb_clk * (1 + sccr_field(im, mask));
  138. return 0;
  139. }
  140. if (clk == MPC83XX_CLK_CSB || clk == MPC83XX_CLK_I2C2) {
  141. priv->speed[clk] = csb_clk; /* i2c-2 clk is equal to csb clk */
  142. return 0;
  143. }
  144. if (clk == MPC83XX_CLK_QE || clk == MPC83XX_CLK_BRG) {
  145. u32 pci_sync_in = get_pci_sync_in(im);
  146. u32 qepmf = spmr_field(im, SPMR_CEPMF);
  147. u32 qepdf = spmr_field(im, SPMR_CEPDF);
  148. u32 qe_clk = (pci_sync_in * qepmf) / (1 + qepdf);
  149. if (clk == MPC83XX_CLK_QE)
  150. priv->speed[clk] = qe_clk;
  151. else
  152. priv->speed[clk] = qe_clk / 2;
  153. return 0;
  154. }
  155. if (clk == MPC83XX_CLK_LCLK || clk == MPC83XX_CLK_LBIU) {
  156. u32 lbiu_clk = csb_clk *
  157. (1 + spmr_field(im, SPMR_LBIUCM));
  158. u32 clkdiv = lcrr_field(im, LCRR_CLKDIV);
  159. if (clk == MPC83XX_CLK_LBIU)
  160. priv->speed[clk] = lbiu_clk;
  161. switch (clkdiv) {
  162. case 2:
  163. case 4:
  164. case 8:
  165. priv->speed[clk] = lbiu_clk / clkdiv;
  166. break;
  167. default:
  168. /* unknown lcrr */
  169. priv->speed[clk] = 0;
  170. }
  171. return 0;
  172. }
  173. if (clk == MPC83XX_CLK_CORE) {
  174. u8 corepll = spmr_field(im, SPMR_COREPLL);
  175. u32 corecnf_tab_index = ((corepll & 0x1F) << 2) |
  176. ((corepll & 0x60) >> 5);
  177. if (corecnf_tab_index > (ARRAY_SIZE(corecnf_tab))) {
  178. debug("%s: Core configuration index %02x too high; possible wrong value",
  179. dev->name, corecnf_tab_index);
  180. return -EINVAL;
  181. }
  182. switch (corecnf_tab[corecnf_tab_index].core_csb_ratio) {
  183. case RAT_BYP:
  184. case RAT_1_TO_1:
  185. priv->speed[clk] = csb_clk;
  186. break;
  187. case RAT_1_5_TO_1:
  188. priv->speed[clk] = (3 * csb_clk) / 2;
  189. break;
  190. case RAT_2_TO_1:
  191. priv->speed[clk] = 2 * csb_clk;
  192. break;
  193. case RAT_2_5_TO_1:
  194. priv->speed[clk] = (5 * csb_clk) / 2;
  195. break;
  196. case RAT_3_TO_1:
  197. priv->speed[clk] = 3 * csb_clk;
  198. break;
  199. default:
  200. /* unknown core to csb ratio */
  201. priv->speed[clk] = 0;
  202. }
  203. return 0;
  204. }
  205. /* Unknown clk value -> error */
  206. debug("%s: clock %d invalid\n", dev->name, clk);
  207. return -EINVAL;
  208. }
  209. /**
  210. * init_all_clks() - Initialize all clocks of a clock device
  211. * @dev: The clock device whose clocks should be initialized
  212. *
  213. * Return: 0 if OK, -ve on error
  214. */
  215. static inline int init_all_clks(struct udevice *dev)
  216. {
  217. int i;
  218. for (i = 0; i < MPC83XX_CLK_COUNT; i++) {
  219. int ret;
  220. if (!is_clk_valid(dev, i))
  221. continue;
  222. ret = init_single_clk(dev, i);
  223. if (ret) {
  224. debug("%s: Failed to initialize %s clock\n",
  225. dev->name, names[i]);
  226. return ret;
  227. }
  228. }
  229. return 0;
  230. }
  231. static int mpc83xx_clk_request(struct clk *clock)
  232. {
  233. /* Reject requests of clocks that are not available */
  234. if (is_clk_valid(clock->dev, clock->id))
  235. return 0;
  236. else
  237. return -ENODEV;
  238. }
  239. static ulong mpc83xx_clk_get_rate(struct clk *clk)
  240. {
  241. struct mpc83xx_clk_priv *priv = dev_get_priv(clk->dev);
  242. if (clk->id >= MPC83XX_CLK_COUNT) {
  243. debug("%s: clock index %lu invalid\n", __func__, clk->id);
  244. return 0;
  245. }
  246. return priv->speed[clk->id];
  247. }
  248. static int mpc83xx_clk_enable(struct clk *clk)
  249. {
  250. /* MPC83xx clocks are always enabled */
  251. return 0;
  252. }
  253. int get_clocks(void)
  254. {
  255. /* Empty implementation to keep the prototype in common.h happy */
  256. return 0;
  257. }
  258. int get_serial_clock(void)
  259. {
  260. struct mpc83xx_clk_priv *priv;
  261. struct udevice *clk;
  262. int ret;
  263. ret = uclass_first_device_err(UCLASS_CLK, &clk);
  264. if (ret) {
  265. debug("%s: Could not get clock device\n", __func__);
  266. return ret;
  267. }
  268. priv = dev_get_priv(clk);
  269. return priv->speed[MPC83XX_CLK_CSB];
  270. }
  271. const struct clk_ops mpc83xx_clk_ops = {
  272. .request = mpc83xx_clk_request,
  273. .get_rate = mpc83xx_clk_get_rate,
  274. .enable = mpc83xx_clk_enable,
  275. };
  276. static const struct udevice_id mpc83xx_clk_match[] = {
  277. { .compatible = "fsl,mpc8308-clk", .data = SOC_MPC8308 },
  278. { .compatible = "fsl,mpc8309-clk", .data = SOC_MPC8309 },
  279. { .compatible = "fsl,mpc8313-clk", .data = SOC_MPC8313 },
  280. { .compatible = "fsl,mpc8315-clk", .data = SOC_MPC8315 },
  281. { .compatible = "fsl,mpc832x-clk", .data = SOC_MPC832X },
  282. { .compatible = "fsl,mpc8349-clk", .data = SOC_MPC8349 },
  283. { .compatible = "fsl,mpc8360-clk", .data = SOC_MPC8360 },
  284. { .compatible = "fsl,mpc8379-clk", .data = SOC_MPC8379 },
  285. { /* sentinel */ }
  286. };
  287. static int mpc83xx_clk_probe(struct udevice *dev)
  288. {
  289. struct mpc83xx_clk_priv *priv = dev_get_priv(dev);
  290. ulong type;
  291. int ret;
  292. ret = init_all_clks(dev);
  293. if (ret) {
  294. debug("%s: Could not initialize all clocks (ret = %d)\n",
  295. dev->name, ret);
  296. return ret;
  297. }
  298. type = dev_get_driver_data(dev);
  299. if (mpc83xx_has_sdhc(type))
  300. gd->arch.sdhc_clk = priv->speed[MPC83XX_CLK_SDHC];
  301. gd->arch.core_clk = priv->speed[MPC83XX_CLK_CORE];
  302. gd->arch.i2c1_clk = priv->speed[MPC83XX_CLK_I2C1];
  303. if (mpc83xx_has_second_i2c(type))
  304. gd->arch.i2c2_clk = priv->speed[MPC83XX_CLK_I2C2];
  305. gd->mem_clk = priv->speed[MPC83XX_CLK_MEM];
  306. if (mpc83xx_has_pci(type))
  307. gd->pci_clk = priv->speed[MPC83XX_CLK_PCI];
  308. gd->cpu_clk = priv->speed[MPC83XX_CLK_CORE];
  309. gd->bus_clk = priv->speed[MPC83XX_CLK_CSB];
  310. return 0;
  311. }
  312. static int mpc83xx_clk_bind(struct udevice *dev)
  313. {
  314. int ret;
  315. struct udevice *sys_child;
  316. /*
  317. * Since there is no corresponding device tree entry, and since the
  318. * clock driver has to be present in either case, bind the sysreset
  319. * driver here.
  320. */
  321. ret = device_bind_driver(dev, "mpc83xx_sysreset", "sysreset",
  322. &sys_child);
  323. if (ret)
  324. debug("%s: No sysreset driver: ret=%d\n",
  325. dev->name, ret);
  326. return 0;
  327. }
  328. U_BOOT_DRIVER(mpc83xx_clk) = {
  329. .name = "mpc83xx_clk",
  330. .id = UCLASS_CLK,
  331. .of_match = mpc83xx_clk_match,
  332. .ops = &mpc83xx_clk_ops,
  333. .probe = mpc83xx_clk_probe,
  334. .priv_auto_alloc_size = sizeof(struct mpc83xx_clk_priv),
  335. .bind = mpc83xx_clk_bind,
  336. };
  337. static int do_clocks(struct cmd_tbl *cmdtp, int flag, int argc,
  338. char *const argv[])
  339. {
  340. int i;
  341. char buf[32];
  342. struct udevice *clk;
  343. int ret;
  344. struct mpc83xx_clk_priv *priv;
  345. ret = uclass_first_device_err(UCLASS_CLK, &clk);
  346. if (ret) {
  347. debug("%s: Could not get clock device\n", __func__);
  348. return ret;
  349. }
  350. for (i = 0; i < MPC83XX_CLK_COUNT; i++) {
  351. if (!is_clk_valid(clk, i))
  352. continue;
  353. priv = dev_get_priv(clk);
  354. printf("%s = %s MHz\n", names[i], strmhz(buf, priv->speed[i]));
  355. }
  356. return 0;
  357. }
  358. U_BOOT_CMD(clocks, 1, 1, do_clocks,
  359. "display values of SoC's clocks",
  360. ""
  361. );