blob: 64514b16341088a93b6d71f636b55d96ec7d4ffc [file] [log] [blame]
Jason Liudec11122011-11-25 00:18:02 +00001/*
2 * Copyright (C) 2010-2011 Freescale Semiconductor, Inc.
3 *
Wolfgang Denkd79de1d2013-07-08 09:37:19 +02004 * SPDX-License-Identifier: GPL-2.0+
Jason Liudec11122011-11-25 00:18:02 +00005 */
6
7#include <common.h>
Christian Gmeinere5848142014-01-08 08:24:25 +01008#include <div64.h>
Jason Liudec11122011-11-25 00:18:02 +00009#include <asm/io.h>
10#include <asm/errno.h>
11#include <asm/arch/imx-regs.h>
Fabio Estevam6479f512012-04-29 08:11:13 +000012#include <asm/arch/crm_regs.h>
Jason Liudec11122011-11-25 00:18:02 +000013#include <asm/arch/clock.h>
Fabio Estevam6479f512012-04-29 08:11:13 +000014#include <asm/arch/sys_proto.h>
Jason Liudec11122011-11-25 00:18:02 +000015
16enum pll_clocks {
17 PLL_SYS, /* System PLL */
18 PLL_BUS, /* System Bus PLL*/
19 PLL_USBOTG, /* OTG USB PLL */
20 PLL_ENET, /* ENET PLL */
21};
22
Fabio Estevam6479f512012-04-29 08:11:13 +000023struct mxc_ccm_reg *imx_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
Jason Liudec11122011-11-25 00:18:02 +000024
Benoît Thébaudeau20db6312013-04-23 10:17:44 +000025#ifdef CONFIG_MXC_OCOTP
26void enable_ocotp_clk(unsigned char enable)
27{
28 u32 reg;
29
30 reg = __raw_readl(&imx_ccm->CCGR2);
31 if (enable)
32 reg |= MXC_CCM_CCGR2_OCOTP_CTRL_MASK;
33 else
34 reg &= ~MXC_CCM_CCGR2_OCOTP_CTRL_MASK;
35 __raw_writel(reg, &imx_ccm->CCGR2);
36}
37#endif
38
Nikita Kiryanov98b76b42014-08-20 15:08:49 +030039#ifdef CONFIG_NAND_MXS
40void setup_gpmi_io_clk(u32 cfg)
41{
42 /* Disable clocks per ERR007177 from MX6 errata */
43 clrbits_le32(&imx_ccm->CCGR4,
44 MXC_CCM_CCGR4_RAWNAND_U_BCH_INPUT_APB_MASK |
45 MXC_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_BCH_MASK |
46 MXC_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_MASK |
47 MXC_CCM_CCGR4_RAWNAND_U_GPMI_INPUT_APB_MASK |
48 MXC_CCM_CCGR4_PL301_MX6QPER1_BCH_MASK);
49
Ye.Li1475bff2015-01-12 16:46:17 +080050#if defined(CONFIG_MX6SX)
51 clrbits_le32(&imx_ccm->CCGR4, MXC_CCM_CCGR4_QSPI2_ENFC_MASK);
52
53 clrsetbits_le32(&imx_ccm->cs2cdr,
54 MXC_CCM_CS2CDR_QSPI2_CLK_PODF_MASK |
55 MXC_CCM_CS2CDR_QSPI2_CLK_PRED_MASK |
56 MXC_CCM_CS2CDR_QSPI2_CLK_SEL_MASK,
57 cfg);
58
59 setbits_le32(&imx_ccm->CCGR4, MXC_CCM_CCGR4_QSPI2_ENFC_MASK);
60#else
Nikita Kiryanov98b76b42014-08-20 15:08:49 +030061 clrbits_le32(&imx_ccm->CCGR2, MXC_CCM_CCGR2_IOMUX_IPT_CLK_IO_MASK);
62
63 clrsetbits_le32(&imx_ccm->cs2cdr,
64 MXC_CCM_CS2CDR_ENFC_CLK_PODF_MASK |
65 MXC_CCM_CS2CDR_ENFC_CLK_PRED_MASK |
66 MXC_CCM_CS2CDR_ENFC_CLK_SEL_MASK,
67 cfg);
68
69 setbits_le32(&imx_ccm->CCGR2, MXC_CCM_CCGR2_IOMUX_IPT_CLK_IO_MASK);
Ye.Li1475bff2015-01-12 16:46:17 +080070#endif
Nikita Kiryanov98b76b42014-08-20 15:08:49 +030071 setbits_le32(&imx_ccm->CCGR4,
72 MXC_CCM_CCGR4_RAWNAND_U_BCH_INPUT_APB_MASK |
73 MXC_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_BCH_MASK |
74 MXC_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_MASK |
75 MXC_CCM_CCGR4_RAWNAND_U_GPMI_INPUT_APB_MASK |
76 MXC_CCM_CCGR4_PL301_MX6QPER1_BCH_MASK);
77}
78#endif
79
Wolfgang Grandegger1859b702012-02-08 22:33:25 +000080void enable_usboh3_clk(unsigned char enable)
81{
82 u32 reg;
83
84 reg = __raw_readl(&imx_ccm->CCGR6);
85 if (enable)
Eric Nelsone4279542012-09-21 07:33:51 +000086 reg |= MXC_CCM_CCGR6_USBOH3_MASK;
Wolfgang Grandegger1859b702012-02-08 22:33:25 +000087 else
Eric Nelsone4279542012-09-21 07:33:51 +000088 reg &= ~(MXC_CCM_CCGR6_USBOH3_MASK);
Wolfgang Grandegger1859b702012-02-08 22:33:25 +000089 __raw_writel(reg, &imx_ccm->CCGR6);
90
Nikita Kiryanov98b76b42014-08-20 15:08:49 +030091}
92
Stefano Babic198249b2014-09-10 13:02:40 +020093#if defined(CONFIG_FEC_MXC) && !defined(CONFIG_MX6SX)
Nikita Kiryanov98b76b42014-08-20 15:08:49 +030094void enable_enet_clk(unsigned char enable)
95{
Peng Fan40a6ed12015-07-20 19:28:27 +080096 u32 mask, *addr;
97
98 if (is_cpu_type(MXC_CPU_MX6UL)) {
99 mask = MXC_CCM_CCGR3_ENET_MASK;
100 addr = &imx_ccm->CCGR3;
101 } else {
102 mask = MXC_CCM_CCGR1_ENET_MASK;
103 addr = &imx_ccm->CCGR1;
104 }
Nikita Kiryanov98b76b42014-08-20 15:08:49 +0300105
106 if (enable)
Peng Fan40a6ed12015-07-20 19:28:27 +0800107 setbits_le32(addr, mask);
Nikita Kiryanov98b76b42014-08-20 15:08:49 +0300108 else
Peng Fan40a6ed12015-07-20 19:28:27 +0800109 clrbits_le32(addr, mask);
Nikita Kiryanov98b76b42014-08-20 15:08:49 +0300110}
111#endif
112
113#ifdef CONFIG_MXC_UART
114void enable_uart_clk(unsigned char enable)
115{
Peng Fan40a6ed12015-07-20 19:28:27 +0800116 u32 mask;
117
118 if (is_cpu_type(MXC_CPU_MX6UL))
119 mask = MXC_CCM_CCGR5_UART_MASK;
120 else
121 mask = MXC_CCM_CCGR5_UART_MASK | MXC_CCM_CCGR5_UART_SERIAL_MASK;
Nikita Kiryanov98b76b42014-08-20 15:08:49 +0300122
123 if (enable)
124 setbits_le32(&imx_ccm->CCGR5, mask);
125 else
126 clrbits_le32(&imx_ccm->CCGR5, mask);
127}
128#endif
129
Nikita Kiryanov98b76b42014-08-20 15:08:49 +0300130#ifdef CONFIG_MMC
131int enable_usdhc_clk(unsigned char enable, unsigned bus_num)
132{
133 u32 mask;
134
135 if (bus_num > 3)
136 return -EINVAL;
137
138 mask = MXC_CCM_CCGR_CG_MASK << (bus_num * 2 + 2);
139 if (enable)
140 setbits_le32(&imx_ccm->CCGR6, mask);
141 else
142 clrbits_le32(&imx_ccm->CCGR6, mask);
143
144 return 0;
Wolfgang Grandegger1859b702012-02-08 22:33:25 +0000145}
Nikita Kiryanov98b76b42014-08-20 15:08:49 +0300146#endif
Wolfgang Grandegger1859b702012-02-08 22:33:25 +0000147
trema49f40a2013-09-21 18:13:35 +0200148#ifdef CONFIG_SYS_I2C_MXC
Heiko Schocher5c4b1e92015-05-18 10:56:24 +0200149/* i2c_num can be from 0 - 3 */
Troy Kiskyd4fdc992012-07-19 08:18:25 +0000150int enable_i2c_clk(unsigned char enable, unsigned i2c_num)
151{
152 u32 reg;
153 u32 mask;
Peng Fand847db72015-07-01 17:01:50 +0800154 u32 *addr;
Troy Kiskyd4fdc992012-07-19 08:18:25 +0000155
Heiko Schocher5c4b1e92015-05-18 10:56:24 +0200156 if (i2c_num > 3)
Troy Kiskyd4fdc992012-07-19 08:18:25 +0000157 return -EINVAL;
Heiko Schocher5c4b1e92015-05-18 10:56:24 +0200158 if (i2c_num < 3) {
159 mask = MXC_CCM_CCGR_CG_MASK
160 << (MXC_CCM_CCGR2_I2C1_SERIAL_OFFSET
161 + (i2c_num << 1));
162 reg = __raw_readl(&imx_ccm->CCGR2);
163 if (enable)
164 reg |= mask;
165 else
166 reg &= ~mask;
167 __raw_writel(reg, &imx_ccm->CCGR2);
168 } else {
Peng Fan40a6ed12015-07-20 19:28:27 +0800169 if (is_cpu_type(MXC_CPU_MX6SX) || is_cpu_type(MXC_CPU_MX6UL)) {
Peng Fand847db72015-07-01 17:01:50 +0800170 mask = MXC_CCM_CCGR6_I2C4_MASK;
171 addr = &imx_ccm->CCGR6;
172 } else {
173 mask = MXC_CCM_CCGR1_I2C4_SERIAL_MASK;
174 addr = &imx_ccm->CCGR1;
175 }
176 reg = __raw_readl(addr);
Heiko Schocher5c4b1e92015-05-18 10:56:24 +0200177 if (enable)
178 reg |= mask;
179 else
180 reg &= ~mask;
Peng Fand847db72015-07-01 17:01:50 +0800181 __raw_writel(reg, addr);
Heiko Schocher5c4b1e92015-05-18 10:56:24 +0200182 }
Troy Kiskyd4fdc992012-07-19 08:18:25 +0000183 return 0;
184}
185#endif
186
Heiko Schocher472a68f2014-07-18 06:07:20 +0200187/* spi_num can be from 0 - SPI_MAX_NUM */
188int enable_spi_clk(unsigned char enable, unsigned spi_num)
189{
190 u32 reg;
191 u32 mask;
192
193 if (spi_num > SPI_MAX_NUM)
194 return -EINVAL;
195
196 mask = MXC_CCM_CCGR_CG_MASK << (spi_num << 1);
197 reg = __raw_readl(&imx_ccm->CCGR1);
198 if (enable)
199 reg |= mask;
200 else
201 reg &= ~mask;
202 __raw_writel(reg, &imx_ccm->CCGR1);
203 return 0;
204}
Jason Liudec11122011-11-25 00:18:02 +0000205static u32 decode_pll(enum pll_clocks pll, u32 infreq)
206{
207 u32 div;
208
209 switch (pll) {
210 case PLL_SYS:
211 div = __raw_readl(&imx_ccm->analog_pll_sys);
212 div &= BM_ANADIG_PLL_SYS_DIV_SELECT;
213
Andre Renaudb0be82e2014-06-10 08:47:13 +1200214 return (infreq * div) >> 1;
Jason Liudec11122011-11-25 00:18:02 +0000215 case PLL_BUS:
216 div = __raw_readl(&imx_ccm->analog_pll_528);
217 div &= BM_ANADIG_PLL_528_DIV_SELECT;
218
219 return infreq * (20 + (div << 1));
220 case PLL_USBOTG:
221 div = __raw_readl(&imx_ccm->analog_usb1_pll_480_ctrl);
222 div &= BM_ANADIG_USB1_PLL_480_CTRL_DIV_SELECT;
223
224 return infreq * (20 + (div << 1));
225 case PLL_ENET:
226 div = __raw_readl(&imx_ccm->analog_pll_enet);
227 div &= BM_ANADIG_PLL_ENET_DIV_SELECT;
228
Fabio Estevam93bc8ea2013-12-03 18:26:13 -0200229 return 25000000 * (div + (div >> 1) + 1);
Jason Liudec11122011-11-25 00:18:02 +0000230 default:
231 return 0;
232 }
233 /* NOTREACHED */
234}
Pierre Auberte8e62a72013-09-19 17:48:59 +0200235static u32 mxc_get_pll_pfd(enum pll_clocks pll, int pfd_num)
236{
237 u32 div;
238 u64 freq;
239
240 switch (pll) {
241 case PLL_BUS:
Peng Fan40a6ed12015-07-20 19:28:27 +0800242 if (!is_cpu_type(MXC_CPU_MX6UL)) {
243 if (pfd_num == 3) {
244 /* No PFD3 on PPL2 */
245 return 0;
246 }
Pierre Auberte8e62a72013-09-19 17:48:59 +0200247 }
248 div = __raw_readl(&imx_ccm->analog_pfd_528);
249 freq = (u64)decode_pll(PLL_BUS, MXC_HCLK);
250 break;
251 case PLL_USBOTG:
252 div = __raw_readl(&imx_ccm->analog_pfd_480);
253 freq = (u64)decode_pll(PLL_USBOTG, MXC_HCLK);
254 break;
255 default:
256 /* No PFD on other PLL */
257 return 0;
258 }
259
Christian Gmeinere5848142014-01-08 08:24:25 +0100260 return lldiv(freq * 18, (div & ANATOP_PFD_FRAC_MASK(pfd_num)) >>
Pierre Auberte8e62a72013-09-19 17:48:59 +0200261 ANATOP_PFD_FRAC_SHIFT(pfd_num));
262}
Jason Liudec11122011-11-25 00:18:02 +0000263
264static u32 get_mcu_main_clk(void)
265{
266 u32 reg, freq;
267
268 reg = __raw_readl(&imx_ccm->cacrr);
269 reg &= MXC_CCM_CACRR_ARM_PODF_MASK;
270 reg >>= MXC_CCM_CACRR_ARM_PODF_OFFSET;
Benoît Thébaudeauafac1652012-09-27 10:19:58 +0000271 freq = decode_pll(PLL_SYS, MXC_HCLK);
Jason Liudec11122011-11-25 00:18:02 +0000272
273 return freq / (reg + 1);
274}
275
Fabio Estevam6479f512012-04-29 08:11:13 +0000276u32 get_periph_clk(void)
Jason Liudec11122011-11-25 00:18:02 +0000277{
Peng Fan40a6ed12015-07-20 19:28:27 +0800278 u32 reg, div = 0, freq = 0;
Jason Liudec11122011-11-25 00:18:02 +0000279
280 reg = __raw_readl(&imx_ccm->cbcdr);
281 if (reg & MXC_CCM_CBCDR_PERIPH_CLK_SEL) {
Peng Fan40a6ed12015-07-20 19:28:27 +0800282 div = (reg & MXC_CCM_CBCDR_PERIPH_CLK2_PODF_MASK) >>
283 MXC_CCM_CBCDR_PERIPH_CLK2_PODF_OFFSET;
Jason Liudec11122011-11-25 00:18:02 +0000284 reg = __raw_readl(&imx_ccm->cbcmr);
285 reg &= MXC_CCM_CBCMR_PERIPH_CLK2_SEL_MASK;
286 reg >>= MXC_CCM_CBCMR_PERIPH_CLK2_SEL_OFFSET;
287
288 switch (reg) {
289 case 0:
Benoît Thébaudeauafac1652012-09-27 10:19:58 +0000290 freq = decode_pll(PLL_USBOTG, MXC_HCLK);
Jason Liudec11122011-11-25 00:18:02 +0000291 break;
292 case 1:
293 case 2:
Benoît Thébaudeauafac1652012-09-27 10:19:58 +0000294 freq = MXC_HCLK;
Jason Liudec11122011-11-25 00:18:02 +0000295 break;
296 default:
297 break;
298 }
299 } else {
300 reg = __raw_readl(&imx_ccm->cbcmr);
301 reg &= MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK;
302 reg >>= MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_OFFSET;
303
304 switch (reg) {
305 case 0:
Benoît Thébaudeauafac1652012-09-27 10:19:58 +0000306 freq = decode_pll(PLL_BUS, MXC_HCLK);
Jason Liudec11122011-11-25 00:18:02 +0000307 break;
308 case 1:
Pierre Auberte8e62a72013-09-19 17:48:59 +0200309 freq = mxc_get_pll_pfd(PLL_BUS, 2);
Jason Liudec11122011-11-25 00:18:02 +0000310 break;
311 case 2:
Pierre Auberte8e62a72013-09-19 17:48:59 +0200312 freq = mxc_get_pll_pfd(PLL_BUS, 0);
Jason Liudec11122011-11-25 00:18:02 +0000313 break;
314 case 3:
Pierre Auberte8e62a72013-09-19 17:48:59 +0200315 /* static / 2 divider */
316 freq = mxc_get_pll_pfd(PLL_BUS, 2) / 2;
Jason Liudec11122011-11-25 00:18:02 +0000317 break;
318 default:
319 break;
320 }
321 }
322
Peng Fan40a6ed12015-07-20 19:28:27 +0800323 return freq / (div + 1);
Jason Liudec11122011-11-25 00:18:02 +0000324}
325
Jason Liudec11122011-11-25 00:18:02 +0000326static u32 get_ipg_clk(void)
327{
328 u32 reg, ipg_podf;
329
330 reg = __raw_readl(&imx_ccm->cbcdr);
331 reg &= MXC_CCM_CBCDR_IPG_PODF_MASK;
332 ipg_podf = reg >> MXC_CCM_CBCDR_IPG_PODF_OFFSET;
333
334 return get_ahb_clk() / (ipg_podf + 1);
335}
336
337static u32 get_ipg_per_clk(void)
338{
339 u32 reg, perclk_podf;
340
341 reg = __raw_readl(&imx_ccm->cscmr1);
Peng Fan53f3c9e2015-07-11 11:38:43 +0800342 if (is_cpu_type(MXC_CPU_MX6SL) || is_cpu_type(MXC_CPU_MX6SX) ||
Peng Fan40a6ed12015-07-20 19:28:27 +0800343 is_mx6dqp() || is_cpu_type(MXC_CPU_MX6UL)) {
Peng Fan53f3c9e2015-07-11 11:38:43 +0800344 if (reg & MXC_CCM_CSCMR1_PER_CLK_SEL_MASK)
345 return MXC_HCLK; /* OSC 24Mhz */
346 }
347
Jason Liudec11122011-11-25 00:18:02 +0000348 perclk_podf = reg & MXC_CCM_CSCMR1_PERCLK_PODF_MASK;
349
350 return get_ipg_clk() / (perclk_podf + 1);
351}
352
353static u32 get_uart_clk(void)
354{
355 u32 reg, uart_podf;
Pierre Auberte8e62a72013-09-19 17:48:59 +0200356 u32 freq = decode_pll(PLL_USBOTG, MXC_HCLK) / 6; /* static divider */
Jason Liudec11122011-11-25 00:18:02 +0000357 reg = __raw_readl(&imx_ccm->cscdr1);
Peng Fan53f3c9e2015-07-11 11:38:43 +0800358
359 if (is_cpu_type(MXC_CPU_MX6SL) || is_cpu_type(MXC_CPU_MX6SX) ||
Peng Fan40a6ed12015-07-20 19:28:27 +0800360 is_mx6dqp() || is_cpu_type(MXC_CPU_MX6UL)) {
Peng Fan53f3c9e2015-07-11 11:38:43 +0800361 if (reg & MXC_CCM_CSCDR1_UART_CLK_SEL)
362 freq = MXC_HCLK;
363 }
364
Jason Liudec11122011-11-25 00:18:02 +0000365 reg &= MXC_CCM_CSCDR1_UART_CLK_PODF_MASK;
366 uart_podf = reg >> MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET;
367
Fabio Estevamf7b9ac22013-04-10 09:32:57 +0000368 return freq / (uart_podf + 1);
Jason Liudec11122011-11-25 00:18:02 +0000369}
370
371static u32 get_cspi_clk(void)
372{
373 u32 reg, cspi_podf;
374
375 reg = __raw_readl(&imx_ccm->cscdr2);
Peng Fan53f3c9e2015-07-11 11:38:43 +0800376 cspi_podf = (reg & MXC_CCM_CSCDR2_ECSPI_CLK_PODF_MASK) >>
377 MXC_CCM_CSCDR2_ECSPI_CLK_PODF_OFFSET;
378
Peng Fan40a6ed12015-07-20 19:28:27 +0800379 if (is_mx6dqp() || is_cpu_type(MXC_CPU_MX6SL) ||
380 is_cpu_type(MXC_CPU_MX6SX) || is_cpu_type(MXC_CPU_MX6UL)) {
Peng Fan53f3c9e2015-07-11 11:38:43 +0800381 if (reg & MXC_CCM_CSCDR2_ECSPI_CLK_SEL_MASK)
382 return MXC_HCLK / (cspi_podf + 1);
383 }
Jason Liudec11122011-11-25 00:18:02 +0000384
Pierre Auberte8e62a72013-09-19 17:48:59 +0200385 return decode_pll(PLL_USBOTG, MXC_HCLK) / (8 * (cspi_podf + 1));
Jason Liudec11122011-11-25 00:18:02 +0000386}
387
388static u32 get_axi_clk(void)
389{
390 u32 root_freq, axi_podf;
391 u32 cbcdr = __raw_readl(&imx_ccm->cbcdr);
392
393 axi_podf = cbcdr & MXC_CCM_CBCDR_AXI_PODF_MASK;
394 axi_podf >>= MXC_CCM_CBCDR_AXI_PODF_OFFSET;
395
396 if (cbcdr & MXC_CCM_CBCDR_AXI_SEL) {
397 if (cbcdr & MXC_CCM_CBCDR_AXI_ALT_SEL)
Pierre Auberte8e62a72013-09-19 17:48:59 +0200398 root_freq = mxc_get_pll_pfd(PLL_BUS, 2);
Jason Liudec11122011-11-25 00:18:02 +0000399 else
Pierre Auberte8e62a72013-09-19 17:48:59 +0200400 root_freq = mxc_get_pll_pfd(PLL_USBOTG, 1);
Jason Liudec11122011-11-25 00:18:02 +0000401 } else
402 root_freq = get_periph_clk();
403
404 return root_freq / (axi_podf + 1);
405}
406
407static u32 get_emi_slow_clk(void)
408{
Andrew Gabbasov4740e242013-07-04 06:27:32 -0500409 u32 emi_clk_sel, emi_slow_podf, cscmr1, root_freq = 0;
Jason Liudec11122011-11-25 00:18:02 +0000410
411 cscmr1 = __raw_readl(&imx_ccm->cscmr1);
412 emi_clk_sel = cscmr1 & MXC_CCM_CSCMR1_ACLK_EMI_SLOW_MASK;
413 emi_clk_sel >>= MXC_CCM_CSCMR1_ACLK_EMI_SLOW_OFFSET;
Andrew Gabbasov4740e242013-07-04 06:27:32 -0500414 emi_slow_podf = cscmr1 & MXC_CCM_CSCMR1_ACLK_EMI_SLOW_PODF_MASK;
415 emi_slow_podf >>= MXC_CCM_CSCMR1_ACLK_EMI_SLOW_PODF_OFFSET;
Jason Liudec11122011-11-25 00:18:02 +0000416
417 switch (emi_clk_sel) {
418 case 0:
419 root_freq = get_axi_clk();
420 break;
421 case 1:
Benoît Thébaudeauafac1652012-09-27 10:19:58 +0000422 root_freq = decode_pll(PLL_USBOTG, MXC_HCLK);
Jason Liudec11122011-11-25 00:18:02 +0000423 break;
424 case 2:
Pierre Auberte8e62a72013-09-19 17:48:59 +0200425 root_freq = mxc_get_pll_pfd(PLL_BUS, 2);
Jason Liudec11122011-11-25 00:18:02 +0000426 break;
427 case 3:
Pierre Auberte8e62a72013-09-19 17:48:59 +0200428 root_freq = mxc_get_pll_pfd(PLL_BUS, 0);
Jason Liudec11122011-11-25 00:18:02 +0000429 break;
430 }
431
Andrew Gabbasov4740e242013-07-04 06:27:32 -0500432 return root_freq / (emi_slow_podf + 1);
Jason Liudec11122011-11-25 00:18:02 +0000433}
434
Fabio Estevamf7b9ac22013-04-10 09:32:57 +0000435static u32 get_mmdc_ch0_clk(void)
436{
437 u32 cbcmr = __raw_readl(&imx_ccm->cbcmr);
438 u32 cbcdr = __raw_readl(&imx_ccm->cbcdr);
Fabio Estevamf7b9ac22013-04-10 09:32:57 +0000439
Peng Fan40a6ed12015-07-20 19:28:27 +0800440 u32 freq, podf, per2_clk2_podf;
Fabio Estevamf7b9ac22013-04-10 09:32:57 +0000441
Peng Fan40a6ed12015-07-20 19:28:27 +0800442 if (is_cpu_type(MXC_CPU_MX6SX) || is_cpu_type(MXC_CPU_MX6UL) ||
443 is_cpu_type(MXC_CPU_MX6SL)) {
444 podf = (cbcdr & MXC_CCM_CBCDR_MMDC_CH1_PODF_MASK) >>
445 MXC_CCM_CBCDR_MMDC_CH1_PODF_OFFSET;
446 if (cbcdr & MXC_CCM_CBCDR_PERIPH2_CLK_SEL) {
447 per2_clk2_podf = (cbcdr & MXC_CCM_CBCDR_PERIPH2_CLK2_PODF_MASK) >>
448 MXC_CCM_CBCDR_PERIPH2_CLK2_PODF_OFFSET;
449 if (is_cpu_type(MXC_CPU_MX6SL)) {
450 if (cbcmr & MXC_CCM_CBCMR_PERIPH2_CLK2_SEL)
451 freq = MXC_HCLK;
452 else
453 freq = decode_pll(PLL_USBOTG, MXC_HCLK);
454 } else {
455 if (cbcmr & MXC_CCM_CBCMR_PERIPH2_CLK2_SEL)
456 freq = decode_pll(PLL_BUS, MXC_HCLK);
457 else
458 freq = decode_pll(PLL_USBOTG, MXC_HCLK);
459 }
460 } else {
461 per2_clk2_podf = 0;
462 switch ((cbcmr &
463 MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_MASK) >>
464 MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_OFFSET) {
465 case 0:
466 freq = decode_pll(PLL_BUS, MXC_HCLK);
467 break;
468 case 1:
469 freq = mxc_get_pll_pfd(PLL_BUS, 2);
470 break;
471 case 2:
472 freq = mxc_get_pll_pfd(PLL_BUS, 0);
473 break;
474 case 3:
475 /* static / 2 divider */
476 freq = mxc_get_pll_pfd(PLL_BUS, 2) / 2;
477 break;
478 }
479 }
480 return freq / (podf + 1) / (per2_clk2_podf + 1);
481 } else {
482 podf = (cbcdr & MXC_CCM_CBCDR_MMDC_CH0_PODF_MASK) >>
483 MXC_CCM_CBCDR_MMDC_CH0_PODF_OFFSET;
484 return get_periph_clk() / (podf + 1);
Fabio Estevamf7b9ac22013-04-10 09:32:57 +0000485 }
Otavio Salvadordc074432013-12-16 20:44:05 -0200486}
Otavio Salvadordc074432013-12-16 20:44:05 -0200487
Peng Fan53ebda82015-10-29 15:54:47 +0800488#if defined(CONFIG_VIDEO_MXS)
489static int enable_pll_video(u32 pll_div, u32 pll_num, u32 pll_denom,
490 u32 post_div)
491{
492 u32 reg = 0;
493 ulong start;
494
495 debug("pll5 div = %d, num = %d, denom = %d\n",
496 pll_div, pll_num, pll_denom);
497
498 /* Power up PLL5 video */
499 writel(BM_ANADIG_PLL_VIDEO_POWERDOWN |
500 BM_ANADIG_PLL_VIDEO_BYPASS |
501 BM_ANADIG_PLL_VIDEO_DIV_SELECT |
502 BM_ANADIG_PLL_VIDEO_POST_DIV_SELECT,
503 &imx_ccm->analog_pll_video_clr);
504
505 /* Set div, num and denom */
506 switch (post_div) {
507 case 1:
508 writel(BF_ANADIG_PLL_VIDEO_DIV_SELECT(pll_div) |
509 BF_ANADIG_PLL_VIDEO_POST_DIV_SELECT(0x2),
510 &imx_ccm->analog_pll_video_set);
511 break;
512 case 2:
513 writel(BF_ANADIG_PLL_VIDEO_DIV_SELECT(pll_div) |
514 BF_ANADIG_PLL_VIDEO_POST_DIV_SELECT(0x1),
515 &imx_ccm->analog_pll_video_set);
516 break;
517 case 4:
518 writel(BF_ANADIG_PLL_VIDEO_DIV_SELECT(pll_div) |
519 BF_ANADIG_PLL_VIDEO_POST_DIV_SELECT(0x0),
520 &imx_ccm->analog_pll_video_set);
521 break;
522 default:
523 puts("Wrong test_div!\n");
524 return -EINVAL;
525 }
526
527 writel(BF_ANADIG_PLL_VIDEO_NUM_A(pll_num),
528 &imx_ccm->analog_pll_video_num);
529 writel(BF_ANADIG_PLL_VIDEO_DENOM_B(pll_denom),
530 &imx_ccm->analog_pll_video_denom);
531
532 /* Wait PLL5 lock */
533 start = get_timer(0); /* Get current timestamp */
534
535 do {
536 reg = readl(&imx_ccm->analog_pll_video);
537 if (reg & BM_ANADIG_PLL_VIDEO_LOCK) {
538 /* Enable PLL out */
539 writel(BM_ANADIG_PLL_VIDEO_ENABLE,
540 &imx_ccm->analog_pll_video_set);
541 return 0;
542 }
543 } while (get_timer(0) < (start + 10)); /* Wait 10ms */
544
545 puts("Lock PLL5 timeout\n");
546
547 return -ETIME;
548}
549
550/*
551 * 24M--> PLL_VIDEO -> LCDIFx_PRED -> LCDIFx_PODF -> LCD
552 *
553 * 'freq' using KHz as unit, see driver/video/mxsfb.c.
554 */
555void mxs_set_lcdclk(u32 base_addr, u32 freq)
556{
557 u32 reg = 0;
558 u32 hck = MXC_HCLK / 1000;
559 /* DIV_SELECT ranges from 27 to 54 */
560 u32 min = hck * 27;
561 u32 max = hck * 54;
562 u32 temp, best = 0;
563 u32 i, j, max_pred = 8, max_postd = 8, pred = 1, postd = 1;
564 u32 pll_div, pll_num, pll_denom, post_div = 1;
565
566 debug("mxs_set_lcdclk, freq = %dKHz\n", freq);
567
568 if ((!is_cpu_type(MXC_CPU_MX6SX)) && !is_cpu_type(MXC_CPU_MX6UL)) {
569 debug("This chip not support lcd!\n");
570 return;
571 }
572
573 if (base_addr == LCDIF1_BASE_ADDR) {
574 reg = readl(&imx_ccm->cscdr2);
575 /* Can't change clocks when clock not from pre-mux */
576 if ((reg & MXC_CCM_CSCDR2_LCDIF1_CLK_SEL_MASK) != 0)
577 return;
578 }
579
580 if (is_cpu_type(MXC_CPU_MX6SX)) {
581 reg = readl(&imx_ccm->cscdr2);
582 /* Can't change clocks when clock not from pre-mux */
583 if ((reg & MXC_CCM_CSCDR2_LCDIF2_CLK_SEL_MASK) != 0)
584 return;
585 }
586
587 temp = freq * max_pred * max_postd;
588 if (temp > max) {
589 puts("Please decrease freq, too large!\n");
590 return;
591 }
592 if (temp < min) {
593 /*
594 * Register: PLL_VIDEO
595 * Bit Field: POST_DIV_SELECT
596 * 00 — Divide by 4.
597 * 01 — Divide by 2.
598 * 10 — Divide by 1.
599 * 11 — Reserved
600 * No need to check post_div(1)
601 */
602 for (post_div = 2; post_div <= 4; post_div <<= 1) {
603 if ((temp * post_div) > min) {
604 freq *= post_div;
605 break;
606 }
607 }
608
609 if (post_div > 4) {
610 printf("Fail to set rate to %dkhz", freq);
611 return;
612 }
613 }
614
615 /* Choose the best pred and postd to match freq for lcd */
616 for (i = 1; i <= max_pred; i++) {
617 for (j = 1; j <= max_postd; j++) {
618 temp = freq * i * j;
619 if (temp > max || temp < min)
620 continue;
621 if (best == 0 || temp < best) {
622 best = temp;
623 pred = i;
624 postd = j;
625 }
626 }
627 }
628
629 if (best == 0) {
630 printf("Fail to set rate to %dKHz", freq);
631 return;
632 }
633
634 debug("best %d, pred = %d, postd = %d\n", best, pred, postd);
635
636 pll_div = best / hck;
637 pll_denom = 1000000;
638 pll_num = (best - hck * pll_div) * pll_denom / hck;
639
640 /*
641 * pll_num
642 * (24MHz * (pll_div + --------- ))
643 * pll_denom
644 *freq KHz = --------------------------------
645 * post_div * pred * postd * 1000
646 */
647
648 if (base_addr == LCDIF1_BASE_ADDR) {
649 if (enable_pll_video(pll_div, pll_num, pll_denom, post_div))
650 return;
651
652 /* Select pre-lcd clock to PLL5 and set pre divider */
653 clrsetbits_le32(&imx_ccm->cscdr2,
654 MXC_CCM_CSCDR2_LCDIF1_PRED_SEL_MASK |
655 MXC_CCM_CSCDR2_LCDIF1_PRE_DIV_MASK,
656 (0x2 << MXC_CCM_CSCDR2_LCDIF1_PRED_SEL_OFFSET) |
657 ((pred - 1) <<
658 MXC_CCM_CSCDR2_LCDIF1_PRE_DIV_OFFSET));
659
660 /* Set the post divider */
661 clrsetbits_le32(&imx_ccm->cbcmr,
662 MXC_CCM_CBCMR_LCDIF1_PODF_MASK,
663 ((postd - 1) <<
664 MXC_CCM_CBCMR_LCDIF1_PODF_OFFSET));
665 } else if (is_cpu_type(MXC_CPU_MX6SX)) {
666 /* Setting LCDIF2 for i.MX6SX */
667 if (enable_pll_video(pll_div, pll_num, pll_denom, post_div))
668 return;
669
670 /* Select pre-lcd clock to PLL5 and set pre divider */
671 clrsetbits_le32(&imx_ccm->cscdr2,
672 MXC_CCM_CSCDR2_LCDIF2_PRED_SEL_MASK |
673 MXC_CCM_CSCDR2_LCDIF2_PRE_DIV_MASK,
674 (0x2 << MXC_CCM_CSCDR2_LCDIF2_PRED_SEL_OFFSET) |
675 ((pred - 1) <<
676 MXC_CCM_CSCDR2_LCDIF2_PRE_DIV_OFFSET));
677
678 /* Set the post divider */
679 clrsetbits_le32(&imx_ccm->cscmr1,
680 MXC_CCM_CSCMR1_LCDIF2_PODF_MASK,
681 ((postd - 1) <<
682 MXC_CCM_CSCMR1_LCDIF2_PODF_OFFSET));
683 }
684}
685
686int enable_lcdif_clock(u32 base_addr)
687{
688 u32 reg = 0;
689 u32 lcdif_clk_sel_mask, lcdif_ccgr3_mask;
690
691 if (is_cpu_type(MXC_CPU_MX6SX)) {
692 if ((base_addr == LCDIF1_BASE_ADDR) ||
693 (base_addr == LCDIF2_BASE_ADDR)) {
694 puts("Wrong LCD interface!\n");
695 return -EINVAL;
696 }
697 /* Set to pre-mux clock at default */
698 lcdif_clk_sel_mask = (base_addr == LCDIF2_BASE_ADDR) ?
699 MXC_CCM_CSCDR2_LCDIF2_CLK_SEL_MASK :
700 MXC_CCM_CSCDR2_LCDIF1_CLK_SEL_MASK;
701 lcdif_ccgr3_mask = (base_addr == LCDIF2_BASE_ADDR) ?
702 (MXC_CCM_CCGR3_LCDIF2_PIX_MASK |
703 MXC_CCM_CCGR3_DISP_AXI_MASK) :
704 (MXC_CCM_CCGR3_LCDIF1_PIX_MASK |
705 MXC_CCM_CCGR3_DISP_AXI_MASK);
706 } else if (is_cpu_type(MXC_CPU_MX6UL)) {
707 if (base_addr != LCDIF1_BASE_ADDR) {
708 puts("Wrong LCD interface!\n");
709 return -EINVAL;
710 }
711 /* Set to pre-mux clock at default */
712 lcdif_clk_sel_mask = MXC_CCM_CSCDR2_LCDIF1_CLK_SEL_MASK;
713 lcdif_ccgr3_mask = MXC_CCM_CCGR3_LCDIF1_PIX_MASK;
714 } else {
715 return 0;
716 }
717
718 reg = readl(&imx_ccm->cscdr2);
719 reg &= ~lcdif_clk_sel_mask;
720 writel(reg, &imx_ccm->cscdr2);
721
722 /* Enable the LCDIF pix clock */
723 reg = readl(&imx_ccm->CCGR3);
724 reg |= lcdif_ccgr3_mask;
725 writel(reg, &imx_ccm->CCGR3);
726
727 reg = readl(&imx_ccm->CCGR2);
728 reg |= MXC_CCM_CCGR2_LCD_MASK;
729 writel(reg, &imx_ccm->CCGR2);
Jeroen Hofsteeb1a4ac62015-11-29 18:30:34 +0100730
731 return 0;
Peng Fan53ebda82015-10-29 15:54:47 +0800732}
733#endif
734
Peng Fan40a6ed12015-07-20 19:28:27 +0800735#ifdef CONFIG_FSL_QSPI
Peng Fan828e4682014-12-31 11:01:38 +0800736/* qspi_num can be from 0 - 1 */
737void enable_qspi_clk(int qspi_num)
738{
739 u32 reg = 0;
740 /* Enable QuadSPI clock */
741 switch (qspi_num) {
742 case 0:
743 /* disable the clock gate */
744 clrbits_le32(&imx_ccm->CCGR3, MXC_CCM_CCGR3_QSPI1_MASK);
745
746 /* set 50M : (50 = 396 / 2 / 4) */
747 reg = readl(&imx_ccm->cscmr1);
748 reg &= ~(MXC_CCM_CSCMR1_QSPI1_PODF_MASK |
749 MXC_CCM_CSCMR1_QSPI1_CLK_SEL_MASK);
750 reg |= ((1 << MXC_CCM_CSCMR1_QSPI1_PODF_OFFSET) |
751 (2 << MXC_CCM_CSCMR1_QSPI1_CLK_SEL_OFFSET));
752 writel(reg, &imx_ccm->cscmr1);
753
754 /* enable the clock gate */
755 setbits_le32(&imx_ccm->CCGR3, MXC_CCM_CCGR3_QSPI1_MASK);
756 break;
757 case 1:
758 /*
759 * disable the clock gate
760 * QSPI2 and GPMI_BCH_INPUT_GPMI_IO share the same clock gate,
761 * disable both of them.
762 */
763 clrbits_le32(&imx_ccm->CCGR4, MXC_CCM_CCGR4_QSPI2_ENFC_MASK |
764 MXC_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_MASK);
765
766 /* set 50M : (50 = 396 / 2 / 4) */
767 reg = readl(&imx_ccm->cs2cdr);
768 reg &= ~(MXC_CCM_CS2CDR_QSPI2_CLK_PODF_MASK |
769 MXC_CCM_CS2CDR_QSPI2_CLK_PRED_MASK |
770 MXC_CCM_CS2CDR_QSPI2_CLK_SEL_MASK);
771 reg |= (MXC_CCM_CS2CDR_QSPI2_CLK_PRED(0x1) |
772 MXC_CCM_CS2CDR_QSPI2_CLK_SEL(0x3));
773 writel(reg, &imx_ccm->cs2cdr);
774
775 /*enable the clock gate*/
776 setbits_le32(&imx_ccm->CCGR4, MXC_CCM_CCGR4_QSPI2_ENFC_MASK |
777 MXC_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_MASK);
778 break;
779 default:
780 break;
781 }
782}
783#endif
784
Otavio Salvadordc074432013-12-16 20:44:05 -0200785#ifdef CONFIG_FEC_MXC
Peng Fan967a83b2015-08-12 17:46:50 +0800786int enable_fec_anatop_clock(int fec_id, enum enet_freq freq)
Fabio Estevam67b8b9d2013-09-13 00:36:28 -0300787{
788 u32 reg = 0;
789 s32 timeout = 100000;
790
791 struct anatop_regs __iomem *anatop =
792 (struct anatop_regs __iomem *)ANATOP_BASE_ADDR;
793
Stefan Roesed7e07312014-11-27 13:46:43 +0100794 if (freq < ENET_25MHZ || freq > ENET_125MHZ)
Fabio Estevamb2903ae2014-01-03 15:55:57 -0200795 return -EINVAL;
796
Peng Fanf868f9f2015-09-06 17:15:47 +0800797 reg = readl(&anatop->pll_enet);
798
Peng Fan967a83b2015-08-12 17:46:50 +0800799 if (fec_id == 0) {
800 reg &= ~BM_ANADIG_PLL_ENET_DIV_SELECT;
801 reg |= BF_ANADIG_PLL_ENET_DIV_SELECT(freq);
802 } else if (fec_id == 1) {
803 /* Only i.MX6SX/UL support ENET2 */
804 if (!(is_cpu_type(MXC_CPU_MX6SX) ||
805 is_cpu_type(MXC_CPU_MX6UL)))
806 return -EINVAL;
807 reg &= ~BM_ANADIG_PLL_ENET2_DIV_SELECT;
808 reg |= BF_ANADIG_PLL_ENET2_DIV_SELECT(freq);
809 } else {
810 return -EINVAL;
811 }
Fabio Estevamb2903ae2014-01-03 15:55:57 -0200812
Fabio Estevam67b8b9d2013-09-13 00:36:28 -0300813 if ((reg & BM_ANADIG_PLL_ENET_POWERDOWN) ||
814 (!(reg & BM_ANADIG_PLL_ENET_LOCK))) {
815 reg &= ~BM_ANADIG_PLL_ENET_POWERDOWN;
816 writel(reg, &anatop->pll_enet);
817 while (timeout--) {
818 if (readl(&anatop->pll_enet) & BM_ANADIG_PLL_ENET_LOCK)
819 break;
820 }
821 if (timeout < 0)
822 return -ETIMEDOUT;
823 }
824
825 /* Enable FEC clock */
Peng Fan967a83b2015-08-12 17:46:50 +0800826 if (fec_id == 0)
827 reg |= BM_ANADIG_PLL_ENET_ENABLE;
828 else
829 reg |= BM_ANADIG_PLL_ENET2_ENABLE;
Fabio Estevam67b8b9d2013-09-13 00:36:28 -0300830 reg &= ~BM_ANADIG_PLL_ENET_BYPASS;
831 writel(reg, &anatop->pll_enet);
832
Fabio Estevamd4d60382014-08-15 00:24:30 -0300833#ifdef CONFIG_MX6SX
834 /*
835 * Set enet ahb clock to 200MHz
836 * pll2_pfd2_396m-> ENET_PODF-> ENET_AHB
837 */
838 reg = readl(&imx_ccm->chsccdr);
839 reg &= ~(MXC_CCM_CHSCCDR_ENET_PRE_CLK_SEL_MASK
840 | MXC_CCM_CHSCCDR_ENET_PODF_MASK
841 | MXC_CCM_CHSCCDR_ENET_CLK_SEL_MASK);
842 /* PLL2 PFD2 */
843 reg |= (4 << MXC_CCM_CHSCCDR_ENET_PRE_CLK_SEL_OFFSET);
844 /* Div = 2*/
845 reg |= (1 << MXC_CCM_CHSCCDR_ENET_PODF_OFFSET);
846 reg |= (0 << MXC_CCM_CHSCCDR_ENET_CLK_SEL_OFFSET);
847 writel(reg, &imx_ccm->chsccdr);
848
849 /* Enable enet system clock */
850 reg = readl(&imx_ccm->CCGR3);
851 reg |= MXC_CCM_CCGR3_ENET_MASK;
852 writel(reg, &imx_ccm->CCGR3);
853#endif
Fabio Estevam67b8b9d2013-09-13 00:36:28 -0300854 return 0;
855}
Fabio Estevamf7b9ac22013-04-10 09:32:57 +0000856#endif
Jason Liudec11122011-11-25 00:18:02 +0000857
858static u32 get_usdhc_clk(u32 port)
859{
860 u32 root_freq = 0, usdhc_podf = 0, clk_sel = 0;
861 u32 cscmr1 = __raw_readl(&imx_ccm->cscmr1);
862 u32 cscdr1 = __raw_readl(&imx_ccm->cscdr1);
863
864 switch (port) {
865 case 0:
866 usdhc_podf = (cscdr1 & MXC_CCM_CSCDR1_USDHC1_PODF_MASK) >>
867 MXC_CCM_CSCDR1_USDHC1_PODF_OFFSET;
868 clk_sel = cscmr1 & MXC_CCM_CSCMR1_USDHC1_CLK_SEL;
869
870 break;
871 case 1:
872 usdhc_podf = (cscdr1 & MXC_CCM_CSCDR1_USDHC2_PODF_MASK) >>
873 MXC_CCM_CSCDR1_USDHC2_PODF_OFFSET;
874 clk_sel = cscmr1 & MXC_CCM_CSCMR1_USDHC2_CLK_SEL;
875
876 break;
877 case 2:
878 usdhc_podf = (cscdr1 & MXC_CCM_CSCDR1_USDHC3_PODF_MASK) >>
879 MXC_CCM_CSCDR1_USDHC3_PODF_OFFSET;
880 clk_sel = cscmr1 & MXC_CCM_CSCMR1_USDHC3_CLK_SEL;
881
882 break;
883 case 3:
884 usdhc_podf = (cscdr1 & MXC_CCM_CSCDR1_USDHC4_PODF_MASK) >>
885 MXC_CCM_CSCDR1_USDHC4_PODF_OFFSET;
886 clk_sel = cscmr1 & MXC_CCM_CSCMR1_USDHC4_CLK_SEL;
887
888 break;
889 default:
890 break;
891 }
892
893 if (clk_sel)
Pierre Auberte8e62a72013-09-19 17:48:59 +0200894 root_freq = mxc_get_pll_pfd(PLL_BUS, 0);
Jason Liudec11122011-11-25 00:18:02 +0000895 else
Pierre Auberte8e62a72013-09-19 17:48:59 +0200896 root_freq = mxc_get_pll_pfd(PLL_BUS, 2);
Jason Liudec11122011-11-25 00:18:02 +0000897
898 return root_freq / (usdhc_podf + 1);
899}
900
901u32 imx_get_uartclk(void)
902{
903 return get_uart_clk();
904}
905
Jason Liu92aa90b2011-12-16 05:17:06 +0000906u32 imx_get_fecclk(void)
907{
Markus Niebel6c109b82014-02-05 10:51:25 +0100908 return mxc_get_clock(MXC_IPG_CLK);
Jason Liu92aa90b2011-12-16 05:17:06 +0000909}
910
Peng Fan40a6ed12015-07-20 19:28:27 +0800911#if defined(CONFIG_CMD_SATA) || defined(CONFIG_PCIE_IMX)
Marek Vasut563dfb22013-12-14 06:27:26 +0100912static int enable_enet_pll(uint32_t en)
Eric Nelsonfdba0762012-03-27 09:52:21 +0000913{
Eric Nelsonfdba0762012-03-27 09:52:21 +0000914 struct mxc_ccm_reg *const imx_ccm
915 = (struct mxc_ccm_reg *) CCM_BASE_ADDR;
Marek Vasut563dfb22013-12-14 06:27:26 +0100916 s32 timeout = 100000;
917 u32 reg = 0;
Eric Nelsonfdba0762012-03-27 09:52:21 +0000918
919 /* Enable PLLs */
920 reg = readl(&imx_ccm->analog_pll_enet);
921 reg &= ~BM_ANADIG_PLL_SYS_POWERDOWN;
922 writel(reg, &imx_ccm->analog_pll_enet);
923 reg |= BM_ANADIG_PLL_SYS_ENABLE;
924 while (timeout--) {
925 if (readl(&imx_ccm->analog_pll_enet) & BM_ANADIG_PLL_SYS_LOCK)
926 break;
927 }
928 if (timeout <= 0)
929 return -EIO;
930 reg &= ~BM_ANADIG_PLL_SYS_BYPASS;
931 writel(reg, &imx_ccm->analog_pll_enet);
Marek Vasut563dfb22013-12-14 06:27:26 +0100932 reg |= en;
Eric Nelsonfdba0762012-03-27 09:52:21 +0000933 writel(reg, &imx_ccm->analog_pll_enet);
Marek Vasut563dfb22013-12-14 06:27:26 +0100934 return 0;
935}
Peng Fan40a6ed12015-07-20 19:28:27 +0800936#endif
Marek Vasut563dfb22013-12-14 06:27:26 +0100937
Peng Fan40a6ed12015-07-20 19:28:27 +0800938#ifdef CONFIG_CMD_SATA
Marek Vasut563dfb22013-12-14 06:27:26 +0100939static void ungate_sata_clock(void)
940{
941 struct mxc_ccm_reg *const imx_ccm =
942 (struct mxc_ccm_reg *)CCM_BASE_ADDR;
943
944 /* Enable SATA clock. */
945 setbits_le32(&imx_ccm->CCGR5, MXC_CCM_CCGR5_SATA_MASK);
946}
947
Marek Vasut563dfb22013-12-14 06:27:26 +0100948int enable_sata_clock(void)
949{
950 ungate_sata_clock();
951 return enable_enet_pll(BM_ANADIG_PLL_ENET_ENABLE_SATA);
952}
Nikita Kiryanov63659b72014-11-21 12:47:22 +0200953
954void disable_sata_clock(void)
955{
956 struct mxc_ccm_reg *const imx_ccm =
957 (struct mxc_ccm_reg *)CCM_BASE_ADDR;
958
959 clrbits_le32(&imx_ccm->CCGR5, MXC_CCM_CCGR5_SATA_MASK);
960}
Fabio Estevam15af7332014-06-24 17:41:00 -0300961#endif
Marek Vasut563dfb22013-12-14 06:27:26 +0100962
Peng Fan40a6ed12015-07-20 19:28:27 +0800963#ifdef CONFIG_PCIE_IMX
964static void ungate_pcie_clock(void)
965{
966 struct mxc_ccm_reg *const imx_ccm =
967 (struct mxc_ccm_reg *)CCM_BASE_ADDR;
968
969 /* Enable PCIe clock. */
970 setbits_le32(&imx_ccm->CCGR4, MXC_CCM_CCGR4_PCIE_MASK);
971}
972
Marek Vasut563dfb22013-12-14 06:27:26 +0100973int enable_pcie_clock(void)
974{
975 struct anatop_regs *anatop_regs =
976 (struct anatop_regs *)ANATOP_BASE_ADDR;
977 struct mxc_ccm_reg *ccm_regs = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
Fabio Estevam211a4902014-08-25 14:26:45 -0300978 u32 lvds1_clk_sel;
Marek Vasut563dfb22013-12-14 06:27:26 +0100979
980 /*
981 * Here be dragons!
982 *
983 * The register ANATOP_MISC1 is not documented in the Freescale
984 * MX6RM. The register that is mapped in the ANATOP space and
985 * marked as ANATOP_MISC1 is actually documented in the PMU section
986 * of the datasheet as PMU_MISC1.
987 *
Fabio Estevam211a4902014-08-25 14:26:45 -0300988 * Switch LVDS clock source to SATA (0xb) on mx6q/dl or PCI (0xa) on
989 * mx6sx, disable clock INPUT and enable clock OUTPUT. This is important
990 * for PCI express link that is clocked from the i.MX6.
Marek Vasut563dfb22013-12-14 06:27:26 +0100991 */
992#define ANADIG_ANA_MISC1_LVDSCLK1_IBEN (1 << 12)
993#define ANADIG_ANA_MISC1_LVDSCLK1_OBEN (1 << 10)
994#define ANADIG_ANA_MISC1_LVDS1_CLK_SEL_MASK 0x0000001F
Fabio Estevam211a4902014-08-25 14:26:45 -0300995#define ANADIG_ANA_MISC1_LVDS1_CLK_SEL_PCIE_REF 0xa
996#define ANADIG_ANA_MISC1_LVDS1_CLK_SEL_SATA_REF 0xb
997
998 if (is_cpu_type(MXC_CPU_MX6SX))
999 lvds1_clk_sel = ANADIG_ANA_MISC1_LVDS1_CLK_SEL_PCIE_REF;
1000 else
1001 lvds1_clk_sel = ANADIG_ANA_MISC1_LVDS1_CLK_SEL_SATA_REF;
1002
Marek Vasut563dfb22013-12-14 06:27:26 +01001003 clrsetbits_le32(&anatop_regs->ana_misc1,
1004 ANADIG_ANA_MISC1_LVDSCLK1_IBEN |
1005 ANADIG_ANA_MISC1_LVDS1_CLK_SEL_MASK,
Fabio Estevam211a4902014-08-25 14:26:45 -03001006 ANADIG_ANA_MISC1_LVDSCLK1_OBEN | lvds1_clk_sel);
Marek Vasut563dfb22013-12-14 06:27:26 +01001007
1008 /* PCIe reference clock sourced from AXI. */
1009 clrbits_le32(&ccm_regs->cbcmr, MXC_CCM_CBCMR_PCIE_AXI_CLK_SEL);
1010
1011 /* Party time! Ungate the clock to the PCIe. */
Peng Fan40a6ed12015-07-20 19:28:27 +08001012#ifdef CONFIG_CMD_SATA
Marek Vasut563dfb22013-12-14 06:27:26 +01001013 ungate_sata_clock();
Fabio Estevam15af7332014-06-24 17:41:00 -03001014#endif
Marek Vasut563dfb22013-12-14 06:27:26 +01001015 ungate_pcie_clock();
Eric Nelsonfdba0762012-03-27 09:52:21 +00001016
Marek Vasut563dfb22013-12-14 06:27:26 +01001017 return enable_enet_pll(BM_ANADIG_PLL_ENET_ENABLE_SATA |
1018 BM_ANADIG_PLL_ENET_ENABLE_PCIE);
Eric Nelsonfdba0762012-03-27 09:52:21 +00001019}
Peng Fan40a6ed12015-07-20 19:28:27 +08001020#endif
Eric Nelsonfdba0762012-03-27 09:52:21 +00001021
Nitin Gargb1ce7012014-09-16 13:33:25 -05001022#ifdef CONFIG_SECURE_BOOT
1023void hab_caam_clock_enable(unsigned char enable)
1024{
1025 u32 reg;
1026
1027 /* CG4 ~ CG6, CAAM clocks */
1028 reg = __raw_readl(&imx_ccm->CCGR0);
1029 if (enable)
1030 reg |= (MXC_CCM_CCGR0_CAAM_WRAPPER_IPG_MASK |
1031 MXC_CCM_CCGR0_CAAM_WRAPPER_ACLK_MASK |
1032 MXC_CCM_CCGR0_CAAM_SECURE_MEM_MASK);
1033 else
1034 reg &= ~(MXC_CCM_CCGR0_CAAM_WRAPPER_IPG_MASK |
1035 MXC_CCM_CCGR0_CAAM_WRAPPER_ACLK_MASK |
1036 MXC_CCM_CCGR0_CAAM_SECURE_MEM_MASK);
1037 __raw_writel(reg, &imx_ccm->CCGR0);
1038
1039 /* EMI slow clk */
1040 reg = __raw_readl(&imx_ccm->CCGR6);
1041 if (enable)
1042 reg |= MXC_CCM_CCGR6_EMI_SLOW_MASK;
1043 else
1044 reg &= ~MXC_CCM_CCGR6_EMI_SLOW_MASK;
1045 __raw_writel(reg, &imx_ccm->CCGR6);
1046}
1047#endif
1048
Nitin Garg59f3be32014-11-20 21:14:12 +08001049static void enable_pll3(void)
1050{
1051 struct anatop_regs __iomem *anatop =
1052 (struct anatop_regs __iomem *)ANATOP_BASE_ADDR;
1053
1054 /* make sure pll3 is enabled */
1055 if ((readl(&anatop->usb1_pll_480_ctrl) &
1056 BM_ANADIG_USB1_PLL_480_CTRL_LOCK) == 0) {
1057 /* enable pll's power */
1058 writel(BM_ANADIG_USB1_PLL_480_CTRL_POWER,
1059 &anatop->usb1_pll_480_ctrl_set);
1060 writel(0x80, &anatop->ana_misc2_clr);
1061 /* wait for pll lock */
1062 while ((readl(&anatop->usb1_pll_480_ctrl) &
1063 BM_ANADIG_USB1_PLL_480_CTRL_LOCK) == 0)
1064 ;
1065 /* disable bypass */
1066 writel(BM_ANADIG_USB1_PLL_480_CTRL_BYPASS,
1067 &anatop->usb1_pll_480_ctrl_clr);
1068 /* enable pll output */
1069 writel(BM_ANADIG_USB1_PLL_480_CTRL_ENABLE,
1070 &anatop->usb1_pll_480_ctrl_set);
1071 }
1072}
1073
1074void enable_thermal_clk(void)
1075{
1076 enable_pll3();
1077}
1078
Jason Liudec11122011-11-25 00:18:02 +00001079unsigned int mxc_get_clock(enum mxc_clock clk)
1080{
1081 switch (clk) {
1082 case MXC_ARM_CLK:
1083 return get_mcu_main_clk();
1084 case MXC_PER_CLK:
1085 return get_periph_clk();
1086 case MXC_AHB_CLK:
1087 return get_ahb_clk();
1088 case MXC_IPG_CLK:
1089 return get_ipg_clk();
1090 case MXC_IPG_PERCLK:
Matthias Weisser99ba3422012-09-24 02:46:53 +00001091 case MXC_I2C_CLK:
Jason Liudec11122011-11-25 00:18:02 +00001092 return get_ipg_per_clk();
1093 case MXC_UART_CLK:
1094 return get_uart_clk();
1095 case MXC_CSPI_CLK:
1096 return get_cspi_clk();
1097 case MXC_AXI_CLK:
1098 return get_axi_clk();
1099 case MXC_EMI_SLOW_CLK:
1100 return get_emi_slow_clk();
1101 case MXC_DDR_CLK:
1102 return get_mmdc_ch0_clk();
1103 case MXC_ESDHC_CLK:
1104 return get_usdhc_clk(0);
1105 case MXC_ESDHC2_CLK:
1106 return get_usdhc_clk(1);
1107 case MXC_ESDHC3_CLK:
1108 return get_usdhc_clk(2);
1109 case MXC_ESDHC4_CLK:
1110 return get_usdhc_clk(3);
1111 case MXC_SATA_CLK:
1112 return get_ahb_clk();
1113 default:
Peng Fan3c7cb492014-11-23 11:52:20 +08001114 printf("Unsupported MXC CLK: %d\n", clk);
Jason Liudec11122011-11-25 00:18:02 +00001115 break;
1116 }
1117
Peng Fan3c7cb492014-11-23 11:52:20 +08001118 return 0;
Jason Liudec11122011-11-25 00:18:02 +00001119}
1120
1121/*
1122 * Dump some core clockes.
1123 */
1124int do_mx6_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1125{
1126 u32 freq;
Benoît Thébaudeauafac1652012-09-27 10:19:58 +00001127 freq = decode_pll(PLL_SYS, MXC_HCLK);
Jason Liudec11122011-11-25 00:18:02 +00001128 printf("PLL_SYS %8d MHz\n", freq / 1000000);
Benoît Thébaudeauafac1652012-09-27 10:19:58 +00001129 freq = decode_pll(PLL_BUS, MXC_HCLK);
Jason Liudec11122011-11-25 00:18:02 +00001130 printf("PLL_BUS %8d MHz\n", freq / 1000000);
Benoît Thébaudeauafac1652012-09-27 10:19:58 +00001131 freq = decode_pll(PLL_USBOTG, MXC_HCLK);
Jason Liudec11122011-11-25 00:18:02 +00001132 printf("PLL_OTG %8d MHz\n", freq / 1000000);
Benoît Thébaudeauafac1652012-09-27 10:19:58 +00001133 freq = decode_pll(PLL_ENET, MXC_HCLK);
Jason Liudec11122011-11-25 00:18:02 +00001134 printf("PLL_NET %8d MHz\n", freq / 1000000);
1135
1136 printf("\n");
1137 printf("IPG %8d kHz\n", mxc_get_clock(MXC_IPG_CLK) / 1000);
1138 printf("UART %8d kHz\n", mxc_get_clock(MXC_UART_CLK) / 1000);
Fabio Estevamf6fde412012-11-16 01:30:10 +00001139#ifdef CONFIG_MXC_SPI
Jason Liudec11122011-11-25 00:18:02 +00001140 printf("CSPI %8d kHz\n", mxc_get_clock(MXC_CSPI_CLK) / 1000);
Fabio Estevamf6fde412012-11-16 01:30:10 +00001141#endif
Jason Liudec11122011-11-25 00:18:02 +00001142 printf("AHB %8d kHz\n", mxc_get_clock(MXC_AHB_CLK) / 1000);
1143 printf("AXI %8d kHz\n", mxc_get_clock(MXC_AXI_CLK) / 1000);
1144 printf("DDR %8d kHz\n", mxc_get_clock(MXC_DDR_CLK) / 1000);
1145 printf("USDHC1 %8d kHz\n", mxc_get_clock(MXC_ESDHC_CLK) / 1000);
1146 printf("USDHC2 %8d kHz\n", mxc_get_clock(MXC_ESDHC2_CLK) / 1000);
1147 printf("USDHC3 %8d kHz\n", mxc_get_clock(MXC_ESDHC3_CLK) / 1000);
1148 printf("USDHC4 %8d kHz\n", mxc_get_clock(MXC_ESDHC4_CLK) / 1000);
1149 printf("EMI SLOW %8d kHz\n", mxc_get_clock(MXC_EMI_SLOW_CLK) / 1000);
1150 printf("IPG PERCLK %8d kHz\n", mxc_get_clock(MXC_IPG_PERCLK) / 1000);
1151
1152 return 0;
1153}
1154
Fabio Estevam15af7332014-06-24 17:41:00 -03001155#ifndef CONFIG_MX6SX
Pardeep Kumar Singlac1fa1302013-07-25 12:12:13 -05001156void enable_ipu_clock(void)
1157{
1158 struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
1159 int reg;
1160 reg = readl(&mxc_ccm->CCGR3);
Pierre Aubert2cb5c382013-09-23 13:37:20 +02001161 reg |= MXC_CCM_CCGR3_IPU1_IPU_MASK;
Pardeep Kumar Singlac1fa1302013-07-25 12:12:13 -05001162 writel(reg, &mxc_ccm->CCGR3);
Peng Fan5a62fcc2015-07-11 11:38:45 +08001163
1164 if (is_mx6dqp()) {
1165 setbits_le32(&mxc_ccm->CCGR6, MXC_CCM_CCGR6_PRG_CLK0_MASK);
1166 setbits_le32(&mxc_ccm->CCGR3, MXC_CCM_CCGR3_IPU2_IPU_MASK);
1167 }
Pardeep Kumar Singlac1fa1302013-07-25 12:12:13 -05001168}
Fabio Estevam15af7332014-06-24 17:41:00 -03001169#endif
Jason Liudec11122011-11-25 00:18:02 +00001170/***************************************************/
1171
1172U_BOOT_CMD(
1173 clocks, CONFIG_SYS_MAXARGS, 1, do_mx6_showclocks,
1174 "display clocks",
1175 ""
1176);