xref: /openbmc/u-boot/arch/arm/mach-davinci/cpu.c (revision ed09a554)
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