1 /* 2 * Copyright (C) 2004 Texas Instruments. 3 * Copyright (C) 2009 David Brownell 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #include <common.h> 9 #include <netdev.h> 10 #include <asm/arch/hardware.h> 11 #include <asm/io.h> 12 13 DECLARE_GLOBAL_DATA_PTR; 14 15 /* offsets from PLL controller base */ 16 #define PLLC_PLLCTL 0x100 17 #define PLLC_PLLM 0x110 18 #define PLLC_PREDIV 0x114 19 #define PLLC_PLLDIV1 0x118 20 #define PLLC_PLLDIV2 0x11c 21 #define PLLC_PLLDIV3 0x120 22 #define PLLC_POSTDIV 0x128 23 #define PLLC_BPDIV 0x12c 24 #define PLLC_PLLDIV4 0x160 25 #define PLLC_PLLDIV5 0x164 26 #define PLLC_PLLDIV6 0x168 27 #define PLLC_PLLDIV7 0x16c 28 #define PLLC_PLLDIV8 0x170 29 #define PLLC_PLLDIV9 0x174 30 31 /* SOC-specific pll info */ 32 #ifdef CONFIG_SOC_DM355 33 #define ARM_PLLDIV PLLC_PLLDIV1 34 #define DDR_PLLDIV PLLC_PLLDIV1 35 #endif 36 37 #ifdef CONFIG_SOC_DM644X 38 #define ARM_PLLDIV PLLC_PLLDIV2 39 #define DSP_PLLDIV PLLC_PLLDIV1 40 #define DDR_PLLDIV PLLC_PLLDIV2 41 #endif 42 43 #ifdef CONFIG_SOC_DM646X 44 #define DSP_PLLDIV PLLC_PLLDIV1 45 #define ARM_PLLDIV PLLC_PLLDIV2 46 #define DDR_PLLDIV PLLC_PLLDIV1 47 #endif 48 49 #ifdef CONFIG_SOC_DA8XX 50 unsigned int sysdiv[9] = { 51 PLLC_PLLDIV1, PLLC_PLLDIV2, PLLC_PLLDIV3, PLLC_PLLDIV4, PLLC_PLLDIV5, 52 PLLC_PLLDIV6, PLLC_PLLDIV7, PLLC_PLLDIV8, PLLC_PLLDIV9 53 }; 54 55 int clk_get(enum davinci_clk_ids id) 56 { 57 int pre_div; 58 int pllm; 59 int post_div; 60 int pll_out; 61 unsigned int pll_base; 62 63 pll_out = CONFIG_SYS_OSCIN_FREQ; 64 65 if (id == DAVINCI_AUXCLK_CLKID) 66 goto out; 67 68 if ((id >> 16) == 1) 69 pll_base = (unsigned int)davinci_pllc1_regs; 70 else 71 pll_base = (unsigned int)davinci_pllc0_regs; 72 73 id &= 0xFFFF; 74 75 /* 76 * Lets keep this simple. Combining operations can result in 77 * unexpected approximations 78 */ 79 pre_div = (readl(pll_base + PLLC_PREDIV) & 80 DAVINCI_PLLC_DIV_MASK) + 1; 81 pllm = readl(pll_base + PLLC_PLLM) + 1; 82 83 pll_out /= pre_div; 84 pll_out *= pllm; 85 86 if (id == DAVINCI_PLLM_CLKID) 87 goto out; 88 89 post_div = (readl(pll_base + PLLC_POSTDIV) & 90 DAVINCI_PLLC_DIV_MASK) + 1; 91 92 pll_out /= post_div; 93 94 if (id == DAVINCI_PLLC_CLKID) 95 goto out; 96 97 pll_out /= (readl(pll_base + sysdiv[id - 1]) & 98 DAVINCI_PLLC_DIV_MASK) + 1; 99 100 out: 101 return pll_out; 102 } 103 104 int set_cpu_clk_info(void) 105 { 106 gd->bd->bi_arm_freq = clk_get(DAVINCI_ARM_CLKID) / 1000000; 107 /* DDR PHY uses an x2 input clock */ 108 gd->bd->bi_ddr_freq = cpu_is_da830() ? 0 : 109 (clk_get(DAVINCI_DDR_CLKID) / 1000000); 110 gd->bd->bi_dsp_freq = 0; 111 return 0; 112 } 113 114 #else /* CONFIG_SOC_DA8XX */ 115 116 static unsigned pll_div(volatile void *pllbase, unsigned offset) 117 { 118 u32 div; 119 120 div = REG(pllbase + offset); 121 return (div & BIT(15)) ? (1 + (div & 0x1f)) : 1; 122 } 123 124 static inline unsigned pll_prediv(volatile void *pllbase) 125 { 126 #ifdef CONFIG_SOC_DM355 127 /* this register read seems to fail on pll0 */ 128 if (pllbase == (volatile void *)DAVINCI_PLL_CNTRL0_BASE) 129 return 8; 130 else 131 return pll_div(pllbase, PLLC_PREDIV); 132 #elif defined(CONFIG_SOC_DM365) 133 return pll_div(pllbase, PLLC_PREDIV); 134 #endif 135 return 1; 136 } 137 138 static inline unsigned pll_postdiv(volatile void *pllbase) 139 { 140 #if defined(CONFIG_SOC_DM355) || defined(CONFIG_SOC_DM365) 141 return pll_div(pllbase, PLLC_POSTDIV); 142 #elif defined(CONFIG_SOC_DM6446) 143 if (pllbase == (volatile void *)DAVINCI_PLL_CNTRL0_BASE) 144 return pll_div(pllbase, PLLC_POSTDIV); 145 #endif 146 return 1; 147 } 148 149 static unsigned pll_sysclk_mhz(unsigned pll_addr, unsigned div) 150 { 151 volatile void *pllbase = (volatile void *) pll_addr; 152 #ifdef CONFIG_SOC_DM646X 153 unsigned base = CONFIG_REFCLK_FREQ / 1000; 154 #else 155 unsigned base = CONFIG_SYS_HZ_CLOCK / 1000; 156 #endif 157 158 /* the PLL might be bypassed */ 159 if (readl(pllbase + PLLC_PLLCTL) & BIT(0)) { 160 base /= pll_prediv(pllbase); 161 #if defined(CONFIG_SOC_DM365) 162 base *= 2 * (readl(pllbase + PLLC_PLLM) & 0x0ff); 163 #else 164 base *= 1 + (REG(pllbase + PLLC_PLLM) & 0x0ff); 165 #endif 166 base /= pll_postdiv(pllbase); 167 } 168 return DIV_ROUND_UP(base, 1000 * pll_div(pllbase, div)); 169 } 170 171 #ifdef DAVINCI_DM6467EVM 172 unsigned int davinci_arm_clk_get() 173 { 174 return pll_sysclk_mhz(DAVINCI_PLL_CNTRL0_BASE, ARM_PLLDIV) * 1000000; 175 } 176 #endif 177 178 #if defined(CONFIG_SOC_DM365) 179 unsigned int davinci_clk_get(unsigned int div) 180 { 181 return pll_sysclk_mhz(DAVINCI_PLL_CNTRL0_BASE, div) * 1000000; 182 } 183 #endif 184 185 int set_cpu_clk_info(void) 186 { 187 unsigned int pllbase = DAVINCI_PLL_CNTRL0_BASE; 188 #if defined(CONFIG_SOC_DM365) 189 pllbase = DAVINCI_PLL_CNTRL1_BASE; 190 #endif 191 gd->bd->bi_arm_freq = pll_sysclk_mhz(pllbase, ARM_PLLDIV); 192 193 #ifdef DSP_PLLDIV 194 gd->bd->bi_dsp_freq = 195 pll_sysclk_mhz(DAVINCI_PLL_CNTRL0_BASE, DSP_PLLDIV); 196 #else 197 gd->bd->bi_dsp_freq = 0; 198 #endif 199 200 pllbase = DAVINCI_PLL_CNTRL1_BASE; 201 #if defined(CONFIG_SOC_DM365) 202 pllbase = DAVINCI_PLL_CNTRL0_BASE; 203 #endif 204 gd->bd->bi_ddr_freq = pll_sysclk_mhz(pllbase, DDR_PLLDIV) / 2; 205 206 return 0; 207 } 208 209 #endif /* !CONFIG_SOC_DA8XX */ 210 211 /* 212 * Initializes on-chip ethernet controllers. 213 * to override, implement board_eth_init() 214 */ 215 int cpu_eth_init(bd_t *bis) 216 { 217 #if defined(CONFIG_DRIVER_TI_EMAC) 218 davinci_emac_initialize(); 219 #endif 220 return 0; 221 } 222