clk_ast2500.c 14 KB

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