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