2 * TNETV107X: Clock management APIs
4 * See file CREDITS for list of people who contributed to this
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include <asm-generic/errno.h>
25 #include <asm/processor.h>
26 #include <asm/arch/clock.h>
28 #define CLOCK_BASE TNETV107X_CLOCK_CONTROL_BASE
29 #define PSC_BASE TNETV107X_PSC_BASE
31 #define BIT(x) (1 << (x))
36 #define MAX_DIV (MAX_PREDIV * MAX_POSTDIV)
39 #define PSC_PTCMD 0x120
40 #define PSC_PTSTAT 0x128
41 #define PSC_MDSTAT(n) (0x800 + (n) * 4)
42 #define PSC_MDCTL(n) (0xA00 + (n) * 4)
44 #define PSC_MDCTL_LRSTZ BIT(8)
46 #define psc_reg_read(reg) __raw_readl((u32 *)(PSC_BASE + (reg)))
47 #define psc_reg_write(reg, val) __raw_writel(val, (u32 *)(PSC_BASE + (reg)))
62 /* SSPLL base addresses */
63 static struct sspll_regs
*sspll_regs
[] = {
64 (struct sspll_regs
*)(CLOCK_BASE
+ 0x040),
65 (struct sspll_regs
*)(CLOCK_BASE
+ 0x080),
66 (struct sspll_regs
*)(CLOCK_BASE
+ 0x0c0),
69 #define sspll_reg(pll, reg) (&(sspll_regs[pll]->reg))
70 #define sspll_reg_read(pll, reg) __raw_readl(sspll_reg(pll, reg))
71 #define sspll_reg_write(pll, reg, val) __raw_writel(val, sspll_reg(pll, reg))
74 /* PLL Control Registers */
110 static struct pllctl_regs
*pllctl_regs
[] = {
111 (struct pllctl_regs
*)(CLOCK_BASE
+ 0x700),
112 (struct pllctl_regs
*)(CLOCK_BASE
+ 0x300),
113 (struct pllctl_regs
*)(CLOCK_BASE
+ 0x500),
116 #define pllctl_reg(pll, reg) (&(pllctl_regs[pll]->reg))
117 #define pllctl_reg_read(pll, reg) __raw_readl(pllctl_reg(pll, reg))
118 #define pllctl_reg_write(pll, reg, val) __raw_writel(val, pllctl_reg(pll, reg))
120 #define pllctl_reg_rmw(pll, reg, mask, val) \
121 pllctl_reg_write(pll, reg, \
122 (pllctl_reg_read(pll, reg) & ~(mask)) | val)
124 #define pllctl_reg_setbits(pll, reg, mask) \
125 pllctl_reg_rmw(pll, reg, 0, mask)
127 #define pllctl_reg_clrbits(pll, reg, mask) \
128 pllctl_reg_rmw(pll, reg, mask, 0)
131 #define PLLCTL_CLKMODE BIT(8)
132 #define PLLCTL_PLLSELB BIT(7)
133 #define PLLCTL_PLLENSRC BIT(5)
134 #define PLLCTL_PLLDIS BIT(4)
135 #define PLLCTL_PLLRST BIT(3)
136 #define PLLCTL_PLLPWRDN BIT(1)
137 #define PLLCTL_PLLEN BIT(0)
139 #define PLLDIV_ENABLE BIT(15)
141 static int pll_div_offset
[] = {
142 #define div_offset(reg) offsetof(struct pllctl_regs, reg)
143 div_offset(div1
), div_offset(div2
), div_offset(div3
),
144 div_offset(div4
), div_offset(div5
), div_offset(div6
),
145 div_offset(div7
), div_offset(div8
),
148 static unsigned long pll_bypass_mask
[] = { 1, 4, 2 };
149 static unsigned long pll_div_mask
[] = { 0x01ff, 0x00ff, 0x00ff };
151 /* Mappings from PLL+DIV to subsystem clocks */
152 #define sys_arm1176_clk {SYS_PLL, 0}
153 #define sys_dsp_clk {SYS_PLL, 1}
154 #define sys_ddr_clk {SYS_PLL, 2}
155 #define sys_full_clk {SYS_PLL, 3}
156 #define sys_lcd_clk {SYS_PLL, 4}
157 #define sys_vlynq_ref_clk {SYS_PLL, 5}
158 #define sys_tsc_clk {SYS_PLL, 6}
159 #define sys_half_clk {SYS_PLL, 7}
161 #define eth_clk_5 {ETH_PLL, 0}
162 #define eth_clk_50 {ETH_PLL, 1}
163 #define eth_clk_125 {ETH_PLL, 2}
164 #define eth_clk_250 {ETH_PLL, 3}
165 #define eth_clk_25 {ETH_PLL, 4}
167 #define tdm_clk {TDM_PLL, 0}
168 #define tdm_extra_clk {TDM_PLL, 1}
169 #define tdm1_clk {TDM_PLL, 2}
171 static const struct lpsc_map lpsc_clk_map
[] = {
172 [TNETV107X_LPSC_ARM
] = sys_arm1176_clk
,
173 [TNETV107X_LPSC_GEM
] = sys_dsp_clk
,
174 [TNETV107X_LPSC_DDR2_PHY
] = sys_ddr_clk
,
175 [TNETV107X_LPSC_TPCC
] = sys_full_clk
,
176 [TNETV107X_LPSC_TPTC0
] = sys_full_clk
,
177 [TNETV107X_LPSC_TPTC1
] = sys_full_clk
,
178 [TNETV107X_LPSC_RAM
] = sys_full_clk
,
179 [TNETV107X_LPSC_MBX_LITE
] = sys_arm1176_clk
,
180 [TNETV107X_LPSC_LCD
] = sys_lcd_clk
,
181 [TNETV107X_LPSC_ETHSS
] = eth_clk_125
,
182 [TNETV107X_LPSC_AEMIF
] = sys_full_clk
,
183 [TNETV107X_LPSC_CHIP_CFG
] = sys_half_clk
,
184 [TNETV107X_LPSC_TSC
] = sys_tsc_clk
,
185 [TNETV107X_LPSC_ROM
] = sys_half_clk
,
186 [TNETV107X_LPSC_UART2
] = sys_half_clk
,
187 [TNETV107X_LPSC_PKTSEC
] = sys_half_clk
,
188 [TNETV107X_LPSC_SECCTL
] = sys_half_clk
,
189 [TNETV107X_LPSC_KEYMGR
] = sys_half_clk
,
190 [TNETV107X_LPSC_KEYPAD
] = sys_half_clk
,
191 [TNETV107X_LPSC_GPIO
] = sys_half_clk
,
192 [TNETV107X_LPSC_MDIO
] = sys_half_clk
,
193 [TNETV107X_LPSC_SDIO0
] = sys_half_clk
,
194 [TNETV107X_LPSC_UART0
] = sys_half_clk
,
195 [TNETV107X_LPSC_UART1
] = sys_half_clk
,
196 [TNETV107X_LPSC_TIMER0
] = sys_half_clk
,
197 [TNETV107X_LPSC_TIMER1
] = sys_half_clk
,
198 [TNETV107X_LPSC_WDT_ARM
] = sys_half_clk
,
199 [TNETV107X_LPSC_WDT_DSP
] = sys_half_clk
,
200 [TNETV107X_LPSC_SSP
] = sys_half_clk
,
201 [TNETV107X_LPSC_TDM0
] = tdm_clk
,
202 [TNETV107X_LPSC_VLYNQ
] = sys_vlynq_ref_clk
,
203 [TNETV107X_LPSC_MCDMA
] = sys_half_clk
,
204 [TNETV107X_LPSC_USB0
] = sys_half_clk
,
205 [TNETV107X_LPSC_TDM1
] = tdm1_clk
,
206 [TNETV107X_LPSC_DEBUGSS
] = sys_half_clk
,
207 [TNETV107X_LPSC_ETHSS_RGMII
] = eth_clk_250
,
208 [TNETV107X_LPSC_SYSTEM
] = sys_half_clk
,
209 [TNETV107X_LPSC_IMCOP
] = sys_dsp_clk
,
210 [TNETV107X_LPSC_SPARE
] = sys_half_clk
,
211 [TNETV107X_LPSC_SDIO1
] = sys_half_clk
,
212 [TNETV107X_LPSC_USB1
] = sys_half_clk
,
213 [TNETV107X_LPSC_USBSS
] = sys_half_clk
,
214 [TNETV107X_LPSC_DDR2_EMIF1_VRST
] = sys_ddr_clk
,
215 [TNETV107X_LPSC_DDR2_EMIF2_VCTL_RST
] = sys_ddr_clk
,
218 static const unsigned long pll_ext_freq
[] = {
219 [SYS_PLL
] = CONFIG_PLL_SYS_EXT_FREQ
,
220 [ETH_PLL
] = CONFIG_PLL_ETH_EXT_FREQ
,
221 [TDM_PLL
] = CONFIG_PLL_TDM_EXT_FREQ
,
224 static unsigned long pll_freq_get(int pll
)
226 unsigned long mult
= 1, prediv
= 1, postdiv
= 1;
227 unsigned long ref
= CONFIG_SYS_INT_OSC_FREQ
;
231 bypass
= __raw_readl((u32
*)(CLOCK_BASE
));
232 if (!(bypass
& pll_bypass_mask
[pll
])) {
233 mult
= sspll_reg_read(pll
, mult_factor
);
234 prediv
= sspll_reg_read(pll
, prediv
) + 1;
235 postdiv
= sspll_reg_read(pll
, postdiv
) + 1;
238 if (pllctl_reg_read(pll
, ctl
) & PLLCTL_CLKMODE
)
239 ref
= pll_ext_freq
[pll
];
241 if (!(pllctl_reg_read(pll
, ctl
) & PLLCTL_PLLEN
))
244 ret
= (unsigned long)(ref
+ ((unsigned long long)ref
* mult
) / 256);
245 ret
/= (prediv
* postdiv
);
250 static unsigned long __pll_div_freq_get(int pll
, unsigned int fpll
,
254 unsigned long divreg
;
256 divreg
= __raw_readl((void *)pllctl_regs
[pll
] + pll_div_offset
[div
]);
258 if (divreg
& PLLDIV_ENABLE
)
259 divider
= (divreg
& pll_div_mask
[pll
]) + 1;
261 return fpll
/ divider
;
264 static unsigned long pll_div_freq_get(int pll
, int div
)
266 unsigned int fpll
= pll_freq_get(pll
);
268 return __pll_div_freq_get(pll
, fpll
, div
);
271 static void __pll_div_freq_set(int pll
, unsigned int fpll
, int div
,
274 int divider
= (fpll
/ hz
- 1);
276 divider
&= pll_div_mask
[pll
];
277 divider
|= PLLDIV_ENABLE
;
279 __raw_writel(divider
, (void *)pllctl_regs
[pll
] + pll_div_offset
[div
]);
280 pllctl_reg_setbits(pll
, alnctl
, (1 << div
));
281 pllctl_reg_setbits(pll
, dchange
, (1 << div
));
284 static unsigned long pll_div_freq_set(int pll
, int div
, unsigned long hz
)
286 unsigned int fpll
= pll_freq_get(pll
);
288 __pll_div_freq_set(pll
, fpll
, div
, hz
);
290 pllctl_reg_write(pll
, cmd
, 1);
292 /* Wait until new divider takes effect */
293 while (pllctl_reg_read(pll
, stat
) & 0x01);
295 return __pll_div_freq_get(pll
, fpll
, div
);
298 unsigned long clk_get_rate(unsigned int clk
)
300 return pll_div_freq_get(lpsc_clk_map
[clk
].pll
, lpsc_clk_map
[clk
].div
);
303 unsigned long clk_round_rate(unsigned int clk
, unsigned long hz
)
305 unsigned long fpll
, divider
, pll
;
307 pll
= lpsc_clk_map
[clk
].pll
;
308 fpll
= pll_freq_get(pll
);
309 divider
= (fpll
/ hz
- 1);
310 divider
&= pll_div_mask
[pll
];
312 return fpll
/ (divider
+ 1);
315 int clk_set_rate(unsigned int clk
, unsigned long _hz
)
319 hz
= clk_round_rate(clk
, _hz
);
321 return -EINVAL
; /* Cannot set to target freq */
323 pll_div_freq_set(lpsc_clk_map
[clk
].pll
, lpsc_clk_map
[clk
].div
, hz
);
327 void lpsc_control(int mod
, unsigned long state
, int lrstz
)
331 mdctl
= psc_reg_read(PSC_MDCTL(mod
));
336 mdctl
&= ~PSC_MDCTL_LRSTZ
;
338 mdctl
|= PSC_MDCTL_LRSTZ
;
340 psc_reg_write(PSC_MDCTL(mod
), mdctl
);
342 psc_reg_write(PSC_PTCMD
, 1);
344 /* wait for power domain transition to end */
345 while (psc_reg_read(PSC_PTSTAT
) & 1);
347 /* Wait for module state change */
348 while ((psc_reg_read(PSC_MDSTAT(mod
)) & 0x1f) != state
);
351 int lpsc_status(unsigned int id
)
353 return psc_reg_read(PSC_MDSTAT(id
)) & 0x1f;
356 static void init_pll(const struct pll_init_data
*data
)
359 unsigned long best_pre
= 0, best_post
= 0, best_mult
= 0;
360 unsigned long div
, prediv
, postdiv
, mult
;
361 unsigned long delta
, actual
;
362 long best_delta
= -1;
366 if (data
->pll
== SYS_PLL
)
367 return; /* cannot reconfigure system pll on the fly */
369 tmp
= pllctl_reg_read(data
->pll
, ctl
);
370 if (data
->internal_osc
) {
371 tmp
&= ~PLLCTL_CLKMODE
;
372 fpll
= CONFIG_SYS_INT_OSC_FREQ
;
374 tmp
|= PLLCTL_CLKMODE
;
375 fpll
= pll_ext_freq
[data
->pll
];
377 pllctl_reg_write(data
->pll
, ctl
, tmp
);
379 mult
= data
->pll_freq
/ fpll
;
380 for (mult
= MAX(mult
, 1); mult
<= MAX_MULT
; mult
++) {
381 div
= (fpll
* mult
) / data
->pll_freq
;
382 if (div
< 1 || div
> MAX_DIV
)
385 for (postdiv
= 1; postdiv
<= min(div
, MAX_POSTDIV
); postdiv
++) {
386 prediv
= div
/ postdiv
;
387 if (prediv
< 1 || prediv
> MAX_PREDIV
)
390 actual
= (fpll
/ prediv
) * (mult
/ postdiv
);
391 delta
= (actual
- data
->pll_freq
);
394 if ((delta
< best_delta
) || (best_delta
== -1)) {
406 if (best_delta
== -1) {
407 printf("pll cannot derive %lu from %lu\n",
408 data
->pll_freq
, fpll
);
412 fpll
= fpll
* best_mult
;
413 fpll
/= best_pre
* best_post
;
415 pllctl_reg_clrbits(data
->pll
, ctl
, PLLCTL_PLLENSRC
);
416 pllctl_reg_clrbits(data
->pll
, ctl
, PLLCTL_PLLEN
);
418 pllctl_reg_setbits(data
->pll
, ctl
, PLLCTL_PLLRST
);
420 pllctl_reg_clrbits(data
->pll
, ctl
, PLLCTL_PLLPWRDN
);
421 pllctl_reg_clrbits(data
->pll
, ctl
, PLLCTL_PLLDIS
);
423 sspll_reg_write(data
->pll
, mult_factor
, (best_mult
- 1) << 8);
424 sspll_reg_write(data
->pll
, prediv
, best_pre
- 1);
425 sspll_reg_write(data
->pll
, postdiv
, best_post
- 1);
427 for (i
= 0; i
< 10; i
++)
428 if (data
->div_freq
[i
])
429 __pll_div_freq_set(data
->pll
, fpll
, i
,
432 pllctl_reg_write(data
->pll
, cmd
, 1);
434 /* Wait until pll "go" operation completes */
435 while (pllctl_reg_read(data
->pll
, stat
) & 0x01);
437 pllctl_reg_clrbits(data
->pll
, ctl
, PLLCTL_PLLRST
);
438 pllctl_reg_setbits(data
->pll
, ctl
, PLLCTL_PLLEN
);
441 void init_plls(int num_pll
, struct pll_init_data
*config
)
445 for (i
= 0; i
< num_pll
; i
++)
446 init_pll(&config
[i
]);