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