blob: ff6114775728cfd5f2a066765de73186c27bed0b [file] [log] [blame]
David Brownell7a4f5112009-05-15 23:47:12 +02001/*
2 * Copyright (C) 2004 Texas Instruments.
3 * Copyright (C) 2009 David Brownell
4 *
Wolfgang Denk1a459662013-07-08 09:37:19 +02005 * SPDX-License-Identifier: GPL-2.0+
David Brownell7a4f5112009-05-15 23:47:12 +02006 */
7
8#include <common.h>
Ben Warren84535872009-05-26 00:34:07 -07009#include <netdev.h>
David Brownell7a4f5112009-05-15 23:47:12 +020010#include <asm/arch/hardware.h>
Sekhar Nori91172ba2009-11-12 11:07:22 -050011#include <asm/io.h>
David Brownell7a4f5112009-05-15 23:47:12 +020012
Hadli, Manjunath8f5d4682012-02-06 00:30:44 +000013DECLARE_GLOBAL_DATA_PTR;
14
David Brownell7a4f5112009-05-15 23:47:12 +020015/* 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
Sudhakar Rajashekharab7e68432011-09-03 22:18:04 -040027#define PLLC_PLLDIV7 0x16c
David Brownell7a4f5112009-05-15 23:47:12 +020028#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
Sandeep Paulraj5342a712010-12-29 14:31:26 -050045#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
Sekhar Nori91172ba2009-11-12 11:07:22 -050051#ifdef CONFIG_SOC_DA8XX
Sudhakar Rajashekharab7e68432011-09-03 22:18:04 -040052unsigned int sysdiv[9] = {
53 PLLC_PLLDIV1, PLLC_PLLDIV2, PLLC_PLLDIV3, PLLC_PLLDIV4, PLLC_PLLDIV5,
54 PLLC_PLLDIV6, PLLC_PLLDIV7, PLLC_PLLDIV8, PLLC_PLLDIV9
Sekhar Nori91172ba2009-11-12 11:07:22 -050055};
56
57int clk_get(enum davinci_clk_ids id)
58{
59 int pre_div;
60 int pllm;
61 int post_div;
62 int pll_out;
Sudhakar Rajashekharab7e68432011-09-03 22:18:04 -040063 unsigned int pll_base;
Sekhar Nori91172ba2009-11-12 11:07:22 -050064
65 pll_out = CONFIG_SYS_OSCIN_FREQ;
66
67 if (id == DAVINCI_AUXCLK_CLKID)
68 goto out;
69
Sudhakar Rajashekharab7e68432011-09-03 22:18:04 -040070 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
Sekhar Nori91172ba2009-11-12 11:07:22 -050077 /*
78 * Lets keep this simple. Combining operations can result in
79 * unexpected approximations
80 */
Sudhakar Rajashekharab7e68432011-09-03 22:18:04 -040081 pre_div = (readl(pll_base + PLLC_PREDIV) &
82 DAVINCI_PLLC_DIV_MASK) + 1;
83 pllm = readl(pll_base + PLLC_PLLM) + 1;
Sekhar Nori91172ba2009-11-12 11:07:22 -050084
85 pll_out /= pre_div;
86 pll_out *= pllm;
87
88 if (id == DAVINCI_PLLM_CLKID)
89 goto out;
90
Sudhakar Rajashekharab7e68432011-09-03 22:18:04 -040091 post_div = (readl(pll_base + PLLC_POSTDIV) &
92 DAVINCI_PLLC_DIV_MASK) + 1;
Sekhar Nori91172ba2009-11-12 11:07:22 -050093
94 pll_out /= post_div;
95
96 if (id == DAVINCI_PLLC_CLKID)
97 goto out;
98
Sudhakar Rajashekharab7e68432011-09-03 22:18:04 -040099 pll_out /= (readl(pll_base + sysdiv[id - 1]) &
100 DAVINCI_PLLC_DIV_MASK) + 1;
Sekhar Nori91172ba2009-11-12 11:07:22 -0500101
102out:
103 return pll_out;
104}
Laurence Withersbe7d2572012-07-30 23:30:37 +0000105
106int 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
Heiko Schocher0a0522c2011-09-14 19:59:39 +0000116#else /* CONFIG_SOC_DA8XX */
David Brownell7a4f5112009-05-15 23:47:12 +0200117
David Brownell7a4f5112009-05-15 23:47:12 +0200118static 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
126static 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);
Heiko Schocher29b0bef2011-11-01 20:00:33 +0000134#elif defined(CONFIG_SOC_DM365)
135 return pll_div(pllbase, PLLC_PREDIV);
David Brownell7a4f5112009-05-15 23:47:12 +0200136#endif
137 return 1;
138}
139
140static inline unsigned pll_postdiv(volatile void *pllbase)
141{
Heiko Schocher29b0bef2011-11-01 20:00:33 +0000142#if defined(CONFIG_SOC_DM355) || defined(CONFIG_SOC_DM365)
David Brownell7a4f5112009-05-15 23:47:12 +0200143 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
151static unsigned pll_sysclk_mhz(unsigned pll_addr, unsigned div)
152{
153 volatile void *pllbase = (volatile void *) pll_addr;
Sandeep Paulraj5342a712010-12-29 14:31:26 -0500154#ifdef CONFIG_SOC_DM646X
prabhakar.csengg@gmail.comfda9c202012-02-12 21:38:22 +0000155 unsigned base = CONFIG_REFCLK_FREQ / 1000;
Sandeep Paulraj5342a712010-12-29 14:31:26 -0500156#else
David Brownell7a4f5112009-05-15 23:47:12 +0200157 unsigned base = CONFIG_SYS_HZ_CLOCK / 1000;
Sandeep Paulraj5342a712010-12-29 14:31:26 -0500158#endif
David Brownell7a4f5112009-05-15 23:47:12 +0200159
160 /* the PLL might be bypassed */
Heiko Schocher29b0bef2011-11-01 20:00:33 +0000161 if (readl(pllbase + PLLC_PLLCTL) & BIT(0)) {
David Brownell7a4f5112009-05-15 23:47:12 +0200162 base /= pll_prediv(pllbase);
Heiko Schocher29b0bef2011-11-01 20:00:33 +0000163#if defined(CONFIG_SOC_DM365)
164 base *= 2 * (readl(pllbase + PLLC_PLLM) & 0x0ff);
165#else
David Brownell7a4f5112009-05-15 23:47:12 +0200166 base *= 1 + (REG(pllbase + PLLC_PLLM) & 0x0ff);
Heiko Schocher29b0bef2011-11-01 20:00:33 +0000167#endif
David Brownell7a4f5112009-05-15 23:47:12 +0200168 base /= pll_postdiv(pllbase);
169 }
170 return DIV_ROUND_UP(base, 1000 * pll_div(pllbase, div));
171}
172
Sandeep Paulraj5342a712010-12-29 14:31:26 -0500173#ifdef DAVINCI_DM6467EVM
174unsigned int davinci_arm_clk_get()
175{
176 return pll_sysclk_mhz(DAVINCI_PLL_CNTRL0_BASE, ARM_PLLDIV) * 1000000;
177}
178#endif
Heiko Schocher29b0bef2011-11-01 20:00:33 +0000179
180#if defined(CONFIG_SOC_DM365)
181unsigned int davinci_clk_get(unsigned int div)
182{
183 return pll_sysclk_mhz(DAVINCI_PLL_CNTRL0_BASE, div) * 1000000;
184}
185#endif
David Brownell7a4f5112009-05-15 23:47:12 +0200186
Hadli, Manjunath8f5d4682012-02-06 00:30:44 +0000187int set_cpu_clk_info(void)
188{
Hadli, Manjunath8f5d4682012-02-06 00:30:44 +0000189 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;
Laurence Withersbe7d2572012-07-30 23:30:37 +0000207
Hadli, Manjunath8f5d4682012-02-06 00:30:44 +0000208 return 0;
209}
210
Laurence Withersbe7d2572012-07-30 23:30:37 +0000211#endif /* !CONFIG_SOC_DA8XX */
212
Ben Warren84535872009-05-26 00:34:07 -0700213/*
214 * Initializes on-chip ethernet controllers.
215 * to override, implement board_eth_init()
216 */
217int cpu_eth_init(bd_t *bis)
218{
219#if defined(CONFIG_DRIVER_TI_EMAC)
220 davinci_emac_initialize();
221#endif
222 return 0;
223}