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