mpc83xx_clk.c 9.5 KB

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