clk_ast2500.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. /*
  2. * (C) Copyright 2016 Google, Inc
  3. *
  4. * SPDX-License-Identifier: GPL-2.0
  5. */
  6. #include <common.h>
  7. #include <clk-uclass.h>
  8. #include <dm.h>
  9. #include <asm/io.h>
  10. #include <asm/arch/scu_ast2500.h>
  11. #include <dm/lists.h>
  12. #include <dt-bindings/clock/ast2500-scu.h>
  13. /*
  14. * MAC Clock Delay settings, taken from Aspeed SDK
  15. */
  16. #define RGMII_TXCLK_ODLY 8
  17. #define RMII_RXCLK_IDLY 2
  18. /*
  19. * TGMII Clock Duty constants, taken from Aspeed SDK
  20. */
  21. #define RGMII2_TXCK_DUTY 0x66
  22. #define RGMII1_TXCK_DUTY 0x64
  23. #define D2PLL_DEFAULT_RATE (250 * 1000 * 1000)
  24. DECLARE_GLOBAL_DATA_PTR;
  25. /*
  26. * Clock divider/multiplier configuration struct.
  27. * For H-PLL and M-PLL the formula is
  28. * (Output Frequency) = CLKIN * ((M + 1) / (N + 1)) / (P + 1)
  29. * M - Numerator
  30. * N - Denumerator
  31. * P - Post Divider
  32. * They have the same layout in their control register.
  33. *
  34. * D-PLL and D2-PLL have extra divider (OD + 1), which is not
  35. * yet needed and ignored by clock configurations.
  36. */
  37. struct ast2500_div_config {
  38. unsigned int num;
  39. unsigned int denum;
  40. unsigned int post_div;
  41. };
  42. /*
  43. * Get the rate of the M-PLL clock from input clock frequency and
  44. * the value of the M-PLL Parameter Register.
  45. */
  46. static ulong ast2500_get_mpll_rate(ulong clkin, u32 mpll_reg)
  47. {
  48. const ulong num = (mpll_reg & SCU_MPLL_NUM_MASK) >> SCU_MPLL_NUM_SHIFT;
  49. const ulong denum = (mpll_reg & SCU_MPLL_DENUM_MASK)
  50. >> SCU_MPLL_DENUM_SHIFT;
  51. const ulong post_div = (mpll_reg & SCU_MPLL_POST_MASK)
  52. >> SCU_MPLL_POST_SHIFT;
  53. return (clkin * ((num + 1) / (denum + 1))) / (post_div + 1);
  54. }
  55. /*
  56. * Get the rate of the H-PLL clock from input clock frequency and
  57. * the value of the H-PLL Parameter Register.
  58. */
  59. static ulong ast2500_get_hpll_rate(ulong clkin, u32 hpll_reg)
  60. {
  61. const ulong num = (hpll_reg & SCU_HPLL_NUM_MASK) >> SCU_HPLL_NUM_SHIFT;
  62. const ulong denum = (hpll_reg & SCU_HPLL_DENUM_MASK)
  63. >> SCU_HPLL_DENUM_SHIFT;
  64. const ulong post_div = (hpll_reg & SCU_HPLL_POST_MASK)
  65. >> SCU_HPLL_POST_SHIFT;
  66. return (clkin * ((num + 1) / (denum + 1))) / (post_div + 1);
  67. }
  68. static ulong ast2500_get_clkin(struct ast2500_scu *scu)
  69. {
  70. return readl(&scu->hwstrap) & SCU_HWSTRAP_CLKIN_25MHZ
  71. ? 25 * 1000 * 1000 : 24 * 1000 * 1000;
  72. }
  73. /**
  74. * Get current rate or uart clock
  75. *
  76. * @scu SCU registers
  77. * @uart_index UART index, 1-5
  78. *
  79. * @return current setting for uart clock rate
  80. */
  81. static ulong ast2500_get_uart_clk_rate(struct ast2500_scu *scu, int uart_index)
  82. {
  83. /*
  84. * ast2500 datasheet is very confusing when it comes to UART clocks,
  85. * especially when CLKIN = 25 MHz. The settings are in
  86. * different registers and it is unclear how they interact.
  87. *
  88. * This has only been tested with default settings and CLKIN = 24 MHz.
  89. */
  90. ulong uart_clkin;
  91. if (readl(&scu->misc_ctrl2) &
  92. (1 << (uart_index - 1 + SCU_MISC2_UARTCLK_SHIFT)))
  93. uart_clkin = 192 * 1000 * 1000;
  94. else
  95. uart_clkin = 24 * 1000 * 1000;
  96. if (readl(&scu->misc_ctrl1) & SCU_MISC_UARTCLK_DIV13)
  97. uart_clkin /= 13;
  98. return uart_clkin;
  99. }
  100. static ulong ast2500_clk_get_rate(struct clk *clk)
  101. {
  102. struct ast2500_clk_priv *priv = dev_get_priv(clk->dev);
  103. ulong clkin = ast2500_get_clkin(priv->scu);
  104. ulong rate;
  105. switch (clk->id) {
  106. case PLL_HPLL:
  107. case ARMCLK:
  108. /*
  109. * This ignores dynamic/static slowdown of ARMCLK and may
  110. * be inaccurate.
  111. */
  112. rate = ast2500_get_hpll_rate(clkin,
  113. readl(&priv->scu->h_pll_param));
  114. break;
  115. case MCLK_DDR:
  116. rate = ast2500_get_mpll_rate(clkin,
  117. readl(&priv->scu->m_pll_param));
  118. break;
  119. case BCLK_PCLK:
  120. {
  121. ulong apb_div = 4 + 4 * ((readl(&priv->scu->clk_sel1)
  122. & SCU_PCLK_DIV_MASK)
  123. >> SCU_PCLK_DIV_SHIFT);
  124. rate = ast2500_get_hpll_rate(clkin,
  125. readl(&priv->
  126. scu->h_pll_param));
  127. rate = rate / apb_div;
  128. }
  129. break;
  130. case PCLK_UART1:
  131. rate = ast2500_get_uart_clk_rate(priv->scu, 1);
  132. break;
  133. case PCLK_UART2:
  134. rate = ast2500_get_uart_clk_rate(priv->scu, 2);
  135. break;
  136. case PCLK_UART3:
  137. rate = ast2500_get_uart_clk_rate(priv->scu, 3);
  138. break;
  139. case PCLK_UART4:
  140. rate = ast2500_get_uart_clk_rate(priv->scu, 4);
  141. break;
  142. case PCLK_UART5:
  143. rate = ast2500_get_uart_clk_rate(priv->scu, 5);
  144. break;
  145. default:
  146. return -ENOENT;
  147. }
  148. return rate;
  149. }
  150. /*
  151. * @input_rate - the rate of input clock in Hz
  152. * @requested_rate - desired output rate in Hz
  153. * @div - this is an IN/OUT parameter, at input all fields of the config
  154. * need to be set to their maximum allowed values.
  155. * The result (the best config we could find), would also be returned
  156. * in this structure.
  157. *
  158. * @return The clock rate, when the resulting div_config is used.
  159. */
  160. static ulong ast2500_calc_clock_config(ulong input_rate, ulong requested_rate,
  161. struct ast2500_div_config *cfg)
  162. {
  163. /*
  164. * The assumption is that kHz precision is good enough and
  165. * also enough to avoid overflow when multiplying.
  166. */
  167. const ulong input_rate_khz = input_rate / 1000;
  168. const ulong rate_khz = requested_rate / 1000;
  169. const struct ast2500_div_config max_vals = *cfg;
  170. struct ast2500_div_config it = { 0, 0, 0 };
  171. ulong delta = rate_khz;
  172. ulong new_rate_khz = 0;
  173. for (; it.denum <= max_vals.denum; ++it.denum) {
  174. for (it.post_div = 0; it.post_div <= max_vals.post_div;
  175. ++it.post_div) {
  176. it.num = (rate_khz * (it.post_div + 1) / input_rate_khz)
  177. * (it.denum + 1);
  178. if (it.num > max_vals.num)
  179. continue;
  180. new_rate_khz = (input_rate_khz
  181. * ((it.num + 1) / (it.denum + 1)))
  182. / (it.post_div + 1);
  183. /* Keep the rate below requested one. */
  184. if (new_rate_khz > rate_khz)
  185. continue;
  186. if (new_rate_khz - rate_khz < delta) {
  187. delta = new_rate_khz - rate_khz;
  188. *cfg = it;
  189. if (delta == 0)
  190. return new_rate_khz * 1000;
  191. }
  192. }
  193. }
  194. return new_rate_khz * 1000;
  195. }
  196. static ulong ast2500_configure_ddr(struct ast2500_scu *scu, ulong rate)
  197. {
  198. ulong clkin = ast2500_get_clkin(scu);
  199. u32 mpll_reg;
  200. struct ast2500_div_config div_cfg = {
  201. .num = (SCU_MPLL_NUM_MASK >> SCU_MPLL_NUM_SHIFT),
  202. .denum = (SCU_MPLL_DENUM_MASK >> SCU_MPLL_DENUM_SHIFT),
  203. .post_div = (SCU_MPLL_POST_MASK >> SCU_MPLL_POST_SHIFT),
  204. };
  205. ast2500_calc_clock_config(clkin, rate, &div_cfg);
  206. mpll_reg = readl(&scu->m_pll_param);
  207. mpll_reg &= ~(SCU_MPLL_POST_MASK | SCU_MPLL_NUM_MASK
  208. | SCU_MPLL_DENUM_MASK);
  209. mpll_reg |= (div_cfg.post_div << SCU_MPLL_POST_SHIFT)
  210. | (div_cfg.num << SCU_MPLL_NUM_SHIFT)
  211. | (div_cfg.denum << SCU_MPLL_DENUM_SHIFT);
  212. ast_scu_unlock(scu);
  213. writel(mpll_reg, &scu->m_pll_param);
  214. ast_scu_lock(scu);
  215. return ast2500_get_mpll_rate(clkin, mpll_reg);
  216. }
  217. static ulong ast2500_configure_mac(struct ast2500_scu *scu, int index)
  218. {
  219. ulong clkin = ast2500_get_clkin(scu);
  220. ulong hpll_rate = ast2500_get_hpll_rate(clkin,
  221. readl(&scu->h_pll_param));
  222. ulong required_rate;
  223. u32 hwstrap;
  224. u32 divisor;
  225. u32 reset_bit;
  226. u32 clkstop_bit;
  227. /*
  228. * According to data sheet, for 10/100 mode the MAC clock frequency
  229. * should be at least 25MHz and for 1000 mode at least 100MHz
  230. */
  231. hwstrap = readl(&scu->hwstrap);
  232. if (hwstrap & (SCU_HWSTRAP_MAC1_RGMII | SCU_HWSTRAP_MAC2_RGMII))
  233. required_rate = 100 * 1000 * 1000;
  234. else
  235. required_rate = 25 * 1000 * 1000;
  236. divisor = hpll_rate / required_rate;
  237. if (divisor < 4) {
  238. /* Clock can't run fast enough, but let's try anyway */
  239. debug("MAC clock too slow\n");
  240. divisor = 4;
  241. } else if (divisor > 16) {
  242. /* Can't slow down the clock enough, but let's try anyway */
  243. debug("MAC clock too fast\n");
  244. divisor = 16;
  245. }
  246. switch (index) {
  247. case 1:
  248. reset_bit = SCU_SYSRESET_MAC1;
  249. clkstop_bit = SCU_CLKSTOP_MAC1;
  250. break;
  251. case 2:
  252. reset_bit = SCU_SYSRESET_MAC2;
  253. clkstop_bit = SCU_CLKSTOP_MAC2;
  254. break;
  255. default:
  256. return -EINVAL;
  257. }
  258. ast_scu_unlock(scu);
  259. clrsetbits_le32(&scu->clk_sel1, SCU_MACCLK_MASK,
  260. ((divisor - 2) / 2) << SCU_MACCLK_SHIFT);
  261. /*
  262. * Disable MAC, start its clock and re-enable it.
  263. * The procedure and the delays (100us & 10ms) are
  264. * specified in the datasheet.
  265. */
  266. setbits_le32(&scu->sysreset_ctrl1, reset_bit);
  267. udelay(100);
  268. clrbits_le32(&scu->clk_stop_ctrl1, clkstop_bit);
  269. mdelay(10);
  270. clrbits_le32(&scu->sysreset_ctrl1, reset_bit);
  271. writel((RGMII2_TXCK_DUTY << SCU_CLKDUTY_RGMII2TXCK_SHIFT)
  272. | (RGMII1_TXCK_DUTY << SCU_CLKDUTY_RGMII1TXCK_SHIFT),
  273. &scu->clk_duty_sel);
  274. ast_scu_lock(scu);
  275. return required_rate;
  276. }
  277. static ulong ast2500_configure_d2pll(struct ast2500_scu *scu, ulong rate)
  278. {
  279. /*
  280. * The values and the meaning of the next three
  281. * parameters are undocumented. Taken from Aspeed SDK.
  282. */
  283. const u32 d2_pll_ext_param = 0x2c;
  284. const u32 d2_pll_sip = 0x11;
  285. const u32 d2_pll_sic = 0x18;
  286. u32 clk_delay_settings =
  287. (RMII_RXCLK_IDLY << SCU_MICDS_MAC1RMII_RDLY_SHIFT)
  288. | (RMII_RXCLK_IDLY << SCU_MICDS_MAC2RMII_RDLY_SHIFT)
  289. | (RGMII_TXCLK_ODLY << SCU_MICDS_MAC1RGMII_TXDLY_SHIFT)
  290. | (RGMII_TXCLK_ODLY << SCU_MICDS_MAC2RGMII_TXDLY_SHIFT);
  291. struct ast2500_div_config div_cfg = {
  292. .num = SCU_D2PLL_NUM_MASK >> SCU_D2PLL_NUM_SHIFT,
  293. .denum = SCU_D2PLL_DENUM_MASK >> SCU_D2PLL_DENUM_SHIFT,
  294. .post_div = SCU_D2PLL_POST_MASK >> SCU_D2PLL_POST_SHIFT,
  295. };
  296. ulong clkin = ast2500_get_clkin(scu);
  297. ulong new_rate;
  298. ast_scu_unlock(scu);
  299. writel((d2_pll_ext_param << SCU_D2PLL_EXT1_PARAM_SHIFT)
  300. | SCU_D2PLL_EXT1_OFF
  301. | SCU_D2PLL_EXT1_RESET, &scu->d2_pll_ext_param[0]);
  302. /*
  303. * Select USB2.0 port1 PHY clock as a clock source for GCRT.
  304. * This would disconnect it from D2-PLL.
  305. */
  306. clrsetbits_le32(&scu->misc_ctrl1, SCU_MISC_D2PLL_OFF,
  307. SCU_MISC_GCRT_USB20CLK);
  308. new_rate = ast2500_calc_clock_config(clkin, rate, &div_cfg);
  309. writel((d2_pll_sip << SCU_D2PLL_SIP_SHIFT)
  310. | (d2_pll_sic << SCU_D2PLL_SIC_SHIFT)
  311. | (div_cfg.num << SCU_D2PLL_NUM_SHIFT)
  312. | (div_cfg.denum << SCU_D2PLL_DENUM_SHIFT)
  313. | (div_cfg.post_div << SCU_D2PLL_POST_SHIFT),
  314. &scu->d2_pll_param);
  315. clrbits_le32(&scu->d2_pll_ext_param[0],
  316. SCU_D2PLL_EXT1_OFF | SCU_D2PLL_EXT1_RESET);
  317. clrsetbits_le32(&scu->misc_ctrl2,
  318. SCU_MISC2_RGMII_HPLL | SCU_MISC2_RMII_MPLL
  319. | SCU_MISC2_RGMII_CLKDIV_MASK |
  320. SCU_MISC2_RMII_CLKDIV_MASK,
  321. (4 << SCU_MISC2_RMII_CLKDIV_SHIFT));
  322. writel(clk_delay_settings | SCU_MICDS_RGMIIPLL, &scu->mac_clk_delay);
  323. writel(clk_delay_settings, &scu->mac_clk_delay_100M);
  324. writel(clk_delay_settings, &scu->mac_clk_delay_10M);
  325. ast_scu_lock(scu);
  326. return new_rate;
  327. }
  328. static ulong ast2500_clk_set_rate(struct clk *clk, ulong rate)
  329. {
  330. struct ast2500_clk_priv *priv = dev_get_priv(clk->dev);
  331. ulong new_rate;
  332. switch (clk->id) {
  333. case PLL_MPLL:
  334. case MCLK_DDR:
  335. new_rate = ast2500_configure_ddr(priv->scu, rate);
  336. break;
  337. case PLL_D2PLL:
  338. new_rate = ast2500_configure_d2pll(priv->scu, rate);
  339. break;
  340. default:
  341. return -ENOENT;
  342. }
  343. return new_rate;
  344. }
  345. static int ast2500_clk_enable(struct clk *clk)
  346. {
  347. struct ast2500_clk_priv *priv = dev_get_priv(clk->dev);
  348. switch (clk->id) {
  349. /*
  350. * For MAC clocks the clock rate is
  351. * configured based on whether RGMII or RMII mode has been selected
  352. * through hardware strapping.
  353. */
  354. case PCLK_MAC1:
  355. ast2500_configure_mac(priv->scu, 1);
  356. break;
  357. case PCLK_MAC2:
  358. ast2500_configure_mac(priv->scu, 2);
  359. break;
  360. case PLL_D2PLL:
  361. ast2500_configure_d2pll(priv->scu, D2PLL_DEFAULT_RATE);
  362. default:
  363. return -ENOENT;
  364. }
  365. return 0;
  366. }
  367. struct clk_ops ast2500_clk_ops = {
  368. .get_rate = ast2500_clk_get_rate,
  369. .set_rate = ast2500_clk_set_rate,
  370. .enable = ast2500_clk_enable,
  371. };
  372. static int ast2500_clk_probe(struct udevice *dev)
  373. {
  374. struct ast2500_clk_priv *priv = dev_get_priv(dev);
  375. priv->scu = devfdt_get_addr_ptr(dev);
  376. if (IS_ERR(priv->scu))
  377. return PTR_ERR(priv->scu);
  378. return 0;
  379. }
  380. static int ast2500_clk_bind(struct udevice *dev)
  381. {
  382. int ret;
  383. /* The reset driver does not have a device node, so bind it here */
  384. ret = device_bind_driver(gd->dm_root, "ast_sysreset", "reset", &dev);
  385. if (ret)
  386. debug("Warning: No reset driver: ret=%d\n", ret);
  387. return 0;
  388. }
  389. static const struct udevice_id ast2500_clk_ids[] = {
  390. { .compatible = "aspeed,ast2500-scu" },
  391. { }
  392. };
  393. U_BOOT_DRIVER(aspeed_ast2500_scu) = {
  394. .name = "aspeed_ast2500_scu",
  395. .id = UCLASS_CLK,
  396. .of_match = ast2500_clk_ids,
  397. .priv_auto_alloc_size = sizeof(struct ast2500_clk_priv),
  398. .ops = &ast2500_clk_ops,
  399. .bind = ast2500_clk_bind,
  400. .probe = ast2500_clk_probe,
  401. };