clk-eth.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright 2014 Broadcom Corporation.
  4. */
  5. #include <common.h>
  6. #include <asm/io.h>
  7. #include <linux/delay.h>
  8. #include <linux/errno.h>
  9. #include <asm/arch/sysmap.h>
  10. #include <asm/kona-common/clk.h>
  11. #include "clk-core.h"
  12. #define WR_ACCESS_ADDR ESUB_CLK_BASE_ADDR
  13. #define WR_ACCESS_PASSWORD 0xA5A500
  14. #define PLLE_POST_RESETB_ADDR (ESUB_CLK_BASE_ADDR + 0x00000C00)
  15. #define PLLE_RESETB_ADDR (ESUB_CLK_BASE_ADDR + 0x00000C58)
  16. #define PLLE_RESETB_I_PLL_RESETB_PLLE_MASK 0x00010000
  17. #define PLLE_POST_RESETB_I_POST_RESETB_PLLE_MASK 0x00000001
  18. #define PLL_LOCK_ADDR (ESUB_CLK_BASE_ADDR + 0x00000C38)
  19. #define PLL_LOCK_PLL_LOCK_PLLE_MASK 0x00000001
  20. #define ESW_SYS_DIV_ADDR (ESUB_CLK_BASE_ADDR + 0x00000A04)
  21. #define ESW_SYS_DIV_PLL_SELECT_MASK 0x00000300
  22. #define ESW_SYS_DIV_DIV_MASK 0x0000001C
  23. #define ESW_SYS_DIV_PLL_VAR_208M_CLK_SELECT 0x00000100
  24. #define ESW_SYS_DIV_DIV_SELECT 0x4
  25. #define ESW_SYS_DIV_TRIGGER_MASK 0x00000001
  26. #define ESUB_AXI_DIV_DEBUG_ADDR (ESUB_CLK_BASE_ADDR + 0x00000E04)
  27. #define ESUB_AXI_DIV_DEBUG_PLL_SELECT_MASK 0x0000001C
  28. #define ESUB_AXI_DIV_DEBUG_PLL_SELECT_OVERRIDE_MASK 0x00000040
  29. #define ESUB_AXI_DIV_DEBUG_PLL_VAR_208M_CLK_SELECT 0x0
  30. #define ESUB_AXI_DIV_DEBUG_TRIGGER_MASK 0x00000001
  31. #define PLL_MAX_RETRY 100
  32. /* Enable appropriate clocks for Ethernet */
  33. int clk_eth_enable(void)
  34. {
  35. int rc = -1;
  36. int retry_count = 0;
  37. rc = clk_get_and_enable("esub_ccu_clk");
  38. /* Enable Access to CCU registers */
  39. writel((1 | WR_ACCESS_PASSWORD), WR_ACCESS_ADDR);
  40. writel(readl(PLLE_POST_RESETB_ADDR) &
  41. ~PLLE_POST_RESETB_I_POST_RESETB_PLLE_MASK,
  42. PLLE_POST_RESETB_ADDR);
  43. /* Take PLL out of reset and put into normal mode */
  44. writel(readl(PLLE_RESETB_ADDR) | PLLE_RESETB_I_PLL_RESETB_PLLE_MASK,
  45. PLLE_RESETB_ADDR);
  46. /* Wait for PLL lock */
  47. rc = -1;
  48. while (retry_count < PLL_MAX_RETRY) {
  49. udelay(100);
  50. if (readl(PLL_LOCK_ADDR) & PLL_LOCK_PLL_LOCK_PLLE_MASK) {
  51. rc = 0;
  52. break;
  53. }
  54. retry_count++;
  55. }
  56. if (rc == -1) {
  57. printf("%s: ETH-PLL lock timeout, Ethernet is not enabled!\n",
  58. __func__);
  59. return -1;
  60. }
  61. writel(readl(PLLE_POST_RESETB_ADDR) |
  62. PLLE_POST_RESETB_I_POST_RESETB_PLLE_MASK,
  63. PLLE_POST_RESETB_ADDR);
  64. /* Switch esw_sys_clk to use 104MHz(208MHz/2) clock */
  65. writel((readl(ESW_SYS_DIV_ADDR) &
  66. ~(ESW_SYS_DIV_PLL_SELECT_MASK | ESW_SYS_DIV_DIV_MASK)) |
  67. ESW_SYS_DIV_PLL_VAR_208M_CLK_SELECT | ESW_SYS_DIV_DIV_SELECT,
  68. ESW_SYS_DIV_ADDR);
  69. writel(readl(ESW_SYS_DIV_ADDR) | ESW_SYS_DIV_TRIGGER_MASK,
  70. ESW_SYS_DIV_ADDR);
  71. /* Wait for trigger complete */
  72. rc = -1;
  73. retry_count = 0;
  74. while (retry_count < PLL_MAX_RETRY) {
  75. udelay(100);
  76. if (!(readl(ESW_SYS_DIV_ADDR) & ESW_SYS_DIV_TRIGGER_MASK)) {
  77. rc = 0;
  78. break;
  79. }
  80. retry_count++;
  81. }
  82. if (rc == -1) {
  83. printf("%s: SYS CLK Trigger timeout, Ethernet is not enabled!\n",
  84. __func__);
  85. return -1;
  86. }
  87. /* switch Esub AXI clock to 208MHz */
  88. writel((readl(ESUB_AXI_DIV_DEBUG_ADDR) &
  89. ~(ESUB_AXI_DIV_DEBUG_PLL_SELECT_MASK |
  90. ESUB_AXI_DIV_DEBUG_PLL_SELECT_OVERRIDE_MASK |
  91. ESUB_AXI_DIV_DEBUG_TRIGGER_MASK)) |
  92. ESUB_AXI_DIV_DEBUG_PLL_VAR_208M_CLK_SELECT |
  93. ESUB_AXI_DIV_DEBUG_PLL_SELECT_OVERRIDE_MASK,
  94. ESUB_AXI_DIV_DEBUG_ADDR);
  95. writel(readl(ESUB_AXI_DIV_DEBUG_ADDR) |
  96. ESUB_AXI_DIV_DEBUG_TRIGGER_MASK,
  97. ESUB_AXI_DIV_DEBUG_ADDR);
  98. /* Wait for trigger complete */
  99. rc = -1;
  100. retry_count = 0;
  101. while (retry_count < PLL_MAX_RETRY) {
  102. udelay(100);
  103. if (!(readl(ESUB_AXI_DIV_DEBUG_ADDR) &
  104. ESUB_AXI_DIV_DEBUG_TRIGGER_MASK)) {
  105. rc = 0;
  106. break;
  107. }
  108. retry_count++;
  109. }
  110. if (rc == -1) {
  111. printf("%s: AXI CLK Trigger timeout, Ethernet is not enabled!\n",
  112. __func__);
  113. return -1;
  114. }
  115. /* Disable Access to CCU registers */
  116. writel(WR_ACCESS_PASSWORD, WR_ACCESS_ADDR);
  117. return rc;
  118. }