2 * Copyright (C) 2010-2011 Freescale Semiconductor, Inc.
4 * SPDX-License-Identifier: GPL-2.0+
10 #include <asm/arch/imx-regs.h>
11 #include <asm/arch/crm_regs.h>
12 #include <asm/arch/clock.h>
13 #include <asm/arch/sys_proto.h>
16 PLL_ARM, /* PLL1: ARM PLL */
17 PLL_BUS, /* PLL2: System Bus PLL*/
18 PLL_USBOTG, /* PLL3: OTG USB PLL */
19 PLL_AUDIO, /* PLL4: Audio PLL */
20 PLL_VIDEO, /* PLL5: Video PLL */
21 PLL_ENET, /* PLL6: ENET PLL */
22 PLL_USB2, /* PLL7: USB2 PLL */
23 PLL_MLB, /* PLL8: MLB PLL */
26 struct mxc_ccm_reg *const imx_ccm = (void *)CCM_BASE_ADDR;
27 struct anatop_regs *const anatop = (void *)ANATOP_BASE_ADDR;
29 int clk_enable(struct clk *clk)
35 if (clk->usecount == 0) {
36 debug("%s: Enabling %s clock\n", __func__, clk->name);
37 ret = clk->enable(clk);
42 assert(clk->usecount > 0);
46 void clk_disable(struct clk *clk)
51 assert(clk->usecount > 0);
52 if (!(--clk->usecount)) {
54 debug("%s: Disabling %s clock\n", __func__, clk->name);
60 int clk_get_usecount(struct clk *clk)
68 u32 clk_get_rate(struct clk *clk)
76 struct clk *clk_get_parent(struct clk *clk)
84 int clk_set_rate(struct clk *clk, unsigned long rate)
86 if (clk && clk->set_rate)
87 clk->set_rate(clk, rate);
91 long clk_round_rate(struct clk *clk, unsigned long rate)
93 if (clk == NULL || !clk->round_rate)
96 return clk->round_rate(clk, rate);
99 int clk_set_parent(struct clk *clk, struct clk *parent)
101 debug("Setting parent of clk %p to %p (%p)\n", clk, parent,
102 clk ? clk->parent : NULL);
104 if (!clk || clk == parent)
107 if (clk->set_parent) {
110 ret = clk->set_parent(clk, parent);
114 clk->parent = parent;
118 #ifdef CONFIG_MXC_OCOTP
119 void enable_ocotp_clk(unsigned char enable)
123 reg = __raw_readl(&imx_ccm->CCGR2);
125 reg |= MXC_CCM_CCGR2_OCOTP_CTRL_MASK;
127 reg &= ~MXC_CCM_CCGR2_OCOTP_CTRL_MASK;
128 __raw_writel(reg, &imx_ccm->CCGR2);
132 void enable_usboh3_clk(unsigned char enable)
136 reg = __raw_readl(&imx_ccm->CCGR6);
138 reg |= MXC_CCM_CCGR6_USBOH3_MASK;
140 reg &= ~(MXC_CCM_CCGR6_USBOH3_MASK);
141 __raw_writel(reg, &imx_ccm->CCGR6);
145 #ifdef CONFIG_I2C_MXC
146 /* i2c_num can be from 0 - 2 */
147 int enable_i2c_clk(unsigned char enable, unsigned i2c_num)
155 mask = MXC_CCM_CCGR_CG_MASK
156 << (MXC_CCM_CCGR2_I2C1_SERIAL_OFFSET + (i2c_num << 1));
157 reg = __raw_readl(&imx_ccm->CCGR2);
162 __raw_writel(reg, &imx_ccm->CCGR2);
167 static u32 decode_pll(enum pll_clocks pll, u32 infreq)
173 div = __raw_readl(&anatop->pll_arm);
174 if (div & BM_ANADIG_PLL_ARM_BYPASS)
175 /* Assume the bypass clock is always derived from OSC */
177 div &= BM_ANADIG_PLL_ARM_DIV_SELECT;
179 return infreq * div / 2;
181 div = __raw_readl(&anatop->pll_528);
182 if (div & BM_ANADIG_PLL_SYS_BYPASS)
184 div &= BM_ANADIG_PLL_SYS_DIV_SELECT;
186 return infreq * (20 + div * 2);
188 div = __raw_readl(&anatop->usb1_pll_480_ctrl);
189 if (div & BM_ANADIG_USB1_PLL_480_CTRL_BYPASS)
191 div &= BM_ANADIG_USB1_PLL_480_CTRL_DIV_SELECT;
193 return infreq * (20 + div * 2);
195 div = __raw_readl(&anatop->pll_audio);
196 if (div & BM_ANADIG_PLL_AUDIO_BYPASS)
198 div &= BM_ANADIG_PLL_AUDIO_DIV_SELECT;
202 div = __raw_readl(&anatop->pll_video);
203 if (div & BM_ANADIG_PLL_VIDEO_BYPASS)
205 div &= BM_ANADIG_PLL_VIDEO_DIV_SELECT;
209 div = __raw_readl(&anatop->pll_enet);
210 if (div & BM_ANADIG_PLL_ENET_BYPASS)
212 div &= BM_ANADIG_PLL_ENET_DIV_SELECT;
214 return (div == 3 ? 125000000 : 25000000 * div * 2);
216 div = __raw_readl(&anatop->usb2_pll_480_ctrl);
217 if (div & BM_ANADIG_USB2_PLL_480_CTRL_BYPASS)
219 div &= BM_ANADIG_USB2_PLL_480_CTRL_DIV_SELECT;
221 return infreq * (20 + div * 2);
223 div = __raw_readl(&anatop->pll_mlb);
224 if (div & BM_ANADIG_PLL_MLB_BYPASS)
226 /* unknown external clock provided on MLB_CLK pin */
232 static u32 get_mcu_main_clk(void)
236 reg = __raw_readl(&imx_ccm->cacrr);
237 reg &= MXC_CCM_CACRR_ARM_PODF_MASK;
238 reg >>= MXC_CCM_CACRR_ARM_PODF_OFFSET;
239 freq = decode_pll(PLL_ARM, MXC_HCLK);
241 return freq / (reg + 1);
244 u32 get_periph_clk(void)
248 reg = __raw_readl(&imx_ccm->cbcdr);
249 if (reg & MXC_CCM_CBCDR_PERIPH_CLK_SEL) {
250 reg = __raw_readl(&imx_ccm->cbcmr);
251 reg &= MXC_CCM_CBCMR_PERIPH_CLK2_SEL_MASK;
252 reg >>= MXC_CCM_CBCMR_PERIPH_CLK2_SEL_OFFSET;
256 freq = decode_pll(PLL_USBOTG, MXC_HCLK);
264 reg = __raw_readl(&imx_ccm->cbcmr);
265 reg &= MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK;
266 reg >>= MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_OFFSET;
270 freq = decode_pll(PLL_BUS, MXC_HCLK);
273 freq = PLL2_PFD2_FREQ;
276 freq = PLL2_PFD0_FREQ;
279 freq = PLL2_PFD2_DIV_FREQ;
287 static u32 get_ipg_clk(void)
291 reg = __raw_readl(&imx_ccm->cbcdr);
292 reg &= MXC_CCM_CBCDR_IPG_PODF_MASK;
293 ipg_podf = reg >> MXC_CCM_CBCDR_IPG_PODF_OFFSET;
295 return get_ahb_clk() / (ipg_podf + 1);
298 static u32 get_ipg_per_clk(void)
300 u32 reg, perclk_podf;
302 reg = __raw_readl(&imx_ccm->cscmr1);
303 perclk_podf = reg & MXC_CCM_CSCMR1_PERCLK_PODF_MASK;
305 return get_ipg_clk() / (perclk_podf + 1);
308 static u32 get_uart_clk(void)
312 reg = __raw_readl(&imx_ccm->cscdr1);
314 if (reg & MXC_CCM_CSCDR1_UART_CLK_SEL)
317 reg &= MXC_CCM_CSCDR1_UART_CLK_PODF_MASK;
318 uart_podf = reg >> MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET;
320 return freq / (uart_podf + 1);
323 static u32 get_cspi_clk(void)
327 reg = __raw_readl(&imx_ccm->cscdr2);
328 reg &= MXC_CCM_CSCDR2_ECSPI_CLK_PODF_MASK;
329 cspi_podf = reg >> MXC_CCM_CSCDR2_ECSPI_CLK_PODF_OFFSET;
331 return PLL3_60M / (cspi_podf + 1);
334 static u32 get_axi_clk(void)
336 u32 root_freq, axi_podf;
337 u32 cbcdr = __raw_readl(&imx_ccm->cbcdr);
339 axi_podf = cbcdr & MXC_CCM_CBCDR_AXI_PODF_MASK;
340 axi_podf >>= MXC_CCM_CBCDR_AXI_PODF_OFFSET;
342 if (cbcdr & MXC_CCM_CBCDR_AXI_SEL) {
343 if (cbcdr & MXC_CCM_CBCDR_AXI_ALT_SEL)
344 root_freq = PLL2_PFD2_FREQ;
346 root_freq = PLL3_PFD1_FREQ;
348 root_freq = get_periph_clk();
350 return root_freq / (axi_podf + 1);
353 static u32 get_emi_slow_clk(void)
355 u32 emi_clk_sel, emi_slow_pof, cscmr1, root_freq = 0;
357 cscmr1 = __raw_readl(&imx_ccm->cscmr1);
358 emi_clk_sel = cscmr1 & MXC_CCM_CSCMR1_ACLK_EMI_SLOW_MASK;
359 emi_clk_sel >>= MXC_CCM_CSCMR1_ACLK_EMI_SLOW_OFFSET;
360 emi_slow_pof = cscmr1 & MXC_CCM_CSCMR1_ACLK_EMI_SLOW_PODF_MASK;
361 emi_slow_pof >>= MXC_CCM_CSCMR1_ACLK_EMI_PODF_OFFSET;
363 switch (emi_clk_sel) {
365 root_freq = get_axi_clk();
368 root_freq = decode_pll(PLL_USBOTG, MXC_HCLK);
371 root_freq = PLL2_PFD2_FREQ;
374 root_freq = PLL2_PFD0_FREQ;
378 return root_freq / (emi_slow_pof + 1);
381 static u32 get_nfc_clk(void)
383 u32 cs2cdr = __raw_readl(&imx_ccm->cs2cdr);
384 u32 podf = (cs2cdr & MXC_CCM_CS2CDR_ENFC_CLK_PODF_MASK) >> MXC_CCM_CS2CDR_ENFC_CLK_PODF_OFFSET;
385 u32 pred = (cs2cdr & MXC_CCM_CS2CDR_ENFC_CLK_PRED_MASK) >> MXC_CCM_CS2CDR_ENFC_CLK_PRED_OFFSET;
386 int nfc_clk_sel = (cs2cdr & MXC_CCM_CS2CDR_ENFC_CLK_SEL_MASK) >>
387 MXC_CCM_CS2CDR_ENFC_CLK_SEL_OFFSET;
390 switch (nfc_clk_sel) {
392 root_freq = PLL2_PFD0_FREQ;
395 root_freq = decode_pll(PLL_BUS, MXC_HCLK);
398 root_freq = decode_pll(PLL_USBOTG, MXC_HCLK);
401 root_freq = PLL2_PFD2_FREQ;
405 return root_freq / (pred + 1) / (podf + 1);
408 #define CS2CDR_ENFC_MASK (MXC_CCM_CS2CDR_ENFC_CLK_PODF_MASK | \
409 MXC_CCM_CS2CDR_ENFC_CLK_PRED_MASK | \
410 MXC_CCM_CS2CDR_ENFC_CLK_SEL_MASK)
412 static int set_nfc_clk(u32 ref, u32 freq_khz)
414 u32 cs2cdr = __raw_readl(&imx_ccm->cs2cdr);
421 u32 freq = freq_khz * 1000;
423 for (nfc_clk_sel = 0; nfc_clk_sel < 4; nfc_clk_sel++) {
427 if (ref < 4 && ref != nfc_clk_sel)
430 switch (nfc_clk_sel) {
432 root_freq = PLL2_PFD0_FREQ;
435 root_freq = decode_pll(PLL_BUS, MXC_HCLK);
438 root_freq = decode_pll(PLL_USBOTG, MXC_HCLK);
441 root_freq = PLL2_PFD2_FREQ;
444 if (root_freq < freq)
447 podf = min(DIV_ROUND_UP(root_freq, freq), 1 << 6);
448 pred = min(DIV_ROUND_UP(root_freq / podf, freq), 8);
449 act_freq = root_freq / pred / podf;
450 err = (freq - act_freq) * 100 / freq;
451 debug("root=%d[%u] freq=%u pred=%u podf=%u act=%u err=%d\n",
452 nfc_clk_sel, root_freq, freq, pred, podf, act_freq, err);
456 nfc_val = (podf - 1) << MXC_CCM_CS2CDR_ENFC_CLK_PODF_OFFSET;
457 nfc_val |= (pred - 1) << MXC_CCM_CS2CDR_ENFC_CLK_PRED_OFFSET;
458 nfc_val |= nfc_clk_sel << MXC_CCM_CS2CDR_ENFC_CLK_SEL_OFFSET;
465 if (nfc_val == ~0 || min_err > 10)
468 if ((cs2cdr & CS2CDR_ENFC_MASK) != nfc_val) {
469 debug("changing cs2cdr from %08x to %08x\n", cs2cdr,
470 (cs2cdr & ~CS2CDR_ENFC_MASK) | nfc_val);
471 __raw_writel((cs2cdr & ~CS2CDR_ENFC_MASK) | nfc_val,
474 debug("Leaving cs2cdr unchanged [%08x]\n", cs2cdr);
480 static u32 get_mmdc_ch0_clk(void)
482 u32 cbcmr = __raw_readl(&imx_ccm->cbcmr);
483 u32 cbcdr = __raw_readl(&imx_ccm->cbcdr);
486 podf = (cbcdr & MXC_CCM_CBCDR_MMDC_CH1_PODF_MASK) \
487 >> MXC_CCM_CBCDR_MMDC_CH1_PODF_OFFSET;
489 switch ((cbcmr & MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_MASK) >>
490 MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_OFFSET) {
492 freq = decode_pll(PLL_BUS, MXC_HCLK);
495 freq = PLL2_PFD2_FREQ;
498 freq = PLL2_PFD0_FREQ;
501 freq = PLL2_PFD2_DIV_FREQ;
504 return freq / (podf + 1);
508 static u32 get_mmdc_ch0_clk(void)
510 u32 cbcdr = __raw_readl(&imx_ccm->cbcdr);
511 u32 mmdc_ch0_podf = (cbcdr & MXC_CCM_CBCDR_MMDC_CH0_PODF_MASK) >>
512 MXC_CCM_CBCDR_MMDC_CH0_PODF_OFFSET;
514 return get_periph_clk() / (mmdc_ch0_podf + 1);
518 static u32 get_usdhc_clk(u32 port)
520 u32 root_freq = 0, usdhc_podf = 0, clk_sel = 0;
521 u32 cscmr1 = __raw_readl(&imx_ccm->cscmr1);
522 u32 cscdr1 = __raw_readl(&imx_ccm->cscdr1);
526 usdhc_podf = (cscdr1 & MXC_CCM_CSCDR1_USDHC1_PODF_MASK) >>
527 MXC_CCM_CSCDR1_USDHC1_PODF_OFFSET;
528 clk_sel = cscmr1 & MXC_CCM_CSCMR1_USDHC1_CLK_SEL;
532 usdhc_podf = (cscdr1 & MXC_CCM_CSCDR1_USDHC2_PODF_MASK) >>
533 MXC_CCM_CSCDR1_USDHC2_PODF_OFFSET;
534 clk_sel = cscmr1 & MXC_CCM_CSCMR1_USDHC2_CLK_SEL;
538 usdhc_podf = (cscdr1 & MXC_CCM_CSCDR1_USDHC3_PODF_MASK) >>
539 MXC_CCM_CSCDR1_USDHC3_PODF_OFFSET;
540 clk_sel = cscmr1 & MXC_CCM_CSCMR1_USDHC3_CLK_SEL;
544 usdhc_podf = (cscdr1 & MXC_CCM_CSCDR1_USDHC4_PODF_MASK) >>
545 MXC_CCM_CSCDR1_USDHC4_PODF_OFFSET;
546 clk_sel = cscmr1 & MXC_CCM_CSCMR1_USDHC4_CLK_SEL;
554 root_freq = PLL2_PFD0_FREQ;
556 root_freq = PLL2_PFD2_FREQ;
558 return root_freq / (usdhc_podf + 1);
561 u32 imx_get_uartclk(void)
563 return get_uart_clk();
566 u32 imx_get_fecclk(void)
568 return decode_pll(PLL_ENET, MXC_HCLK);
571 int enable_sata_clock(void)
574 s32 timeout = 100000;
576 /* Enable sata clock */
577 reg = readl(&imx_ccm->CCGR5); /* CCGR5 */
578 reg |= MXC_CCM_CCGR5_SATA_MASK;
579 writel(reg, &imx_ccm->CCGR5);
582 reg = readl(&anatop->pll_enet);
583 reg &= ~BM_ANADIG_PLL_ENET_POWERDOWN;
584 writel(reg, &anatop->pll_enet);
585 reg |= BM_ANADIG_PLL_ENET_ENABLE;
587 if (readl(&anatop->pll_enet) & BM_ANADIG_PLL_ENET_LOCK)
592 reg &= ~BM_ANADIG_PLL_ENET_BYPASS;
593 writel(reg, &anatop->pll_enet);
594 reg |= BM_ANADIG_PLL_ENET_ENABLE_SATA;
595 writel(reg, &anatop->pll_enet);
600 void ipu_clk_enable(void)
602 u32 reg = readl(&imx_ccm->CCGR3);
603 reg |= MXC_CCM_CCGR3_IPU1_IPU_MASK;
604 writel(reg, &imx_ccm->CCGR3);
607 void ipu_clk_disable(void)
609 u32 reg = readl(&imx_ccm->CCGR3);
610 reg &= ~MXC_CCM_CCGR3_IPU1_IPU_MASK;
611 writel(reg, &imx_ccm->CCGR3);
614 void ocotp_clk_enable(void)
616 u32 reg = readl(&imx_ccm->CCGR2);
617 reg |= MXC_CCM_CCGR2_OCOTP_CTRL_MASK;
618 writel(reg, &imx_ccm->CCGR2);
621 void ocotp_clk_disable(void)
623 u32 reg = readl(&imx_ccm->CCGR2);
624 reg &= ~MXC_CCM_CCGR2_OCOTP_CTRL_MASK;
625 writel(reg, &imx_ccm->CCGR2);
628 unsigned int mxc_get_clock(enum mxc_clock clk)
632 return get_mcu_main_clk();
634 return get_periph_clk();
636 return get_ahb_clk();
638 return get_ipg_clk();
641 return get_ipg_per_clk();
643 return get_uart_clk();
645 return get_cspi_clk();
647 return get_axi_clk();
648 case MXC_EMI_SLOW_CLK:
649 return get_emi_slow_clk();
651 return get_mmdc_ch0_clk();
653 return get_usdhc_clk(0);
655 return get_usdhc_clk(1);
657 return get_usdhc_clk(2);
659 return get_usdhc_clk(3);
661 return get_ahb_clk();
663 return get_nfc_clk();
669 static inline int gcd(int m, int n)
683 /* Config CPU clock */
684 static int set_arm_clk(u32 ref, u32 freq_khz)
692 if (freq_khz > ref / 1000 * 108 / 2 || freq_khz < ref / 1000 * 54 / 8 / 2) {
693 printf("Frequency %u.%03uMHz is out of range: %u.%03u..%u.%03u\n",
694 freq_khz / 1000, freq_khz % 1000,
695 54 * ref / 1000000 / 8 / 2, 54 * ref / 1000 / 8 / 2 % 1000,
696 108 * ref / 1000000 / 2, 108 * ref / 1000 / 2 % 1000);
700 for (d = DIV_ROUND_UP(648000, freq_khz); d <= 8; d++) {
701 int m = freq_khz * 2 * d / (ref / 1000);
706 debug("%s@%d: d=%d m=%d\n", __func__, __LINE__,
712 if (f > freq_khz * 1000) {
713 debug("%s@%d: d=%d m=%d f=%u freq=%u\n", __func__, __LINE__,
719 err = freq_khz * 1000 - f;
720 debug("%s@%d: d=%d m=%d f=%u freq=%u err=%d\n", __func__, __LINE__,
721 d, m, f, freq_khz, err);
732 debug("Setting M=%3u D=%2u for %u.%03uMHz (actual: %u.%03uMHz)\n",
733 mul, div, freq_khz / 1000, freq_khz % 1000,
734 ref * mul / 2 / div / 1000000, ref * mul / 2 / div / 1000 % 1000);
736 reg = readl(&anatop->pll_arm);
737 debug("anadig_pll_arm=%08x -> %08x\n",
738 reg, (reg & ~0x7f) | mul);
741 writel(reg, &anatop->pll_arm); /* bypass PLL */
743 reg = (reg & ~0x7f) | mul;
744 writel(reg, &anatop->pll_arm);
746 writel(div - 1, &imx_ccm->cacrr);
749 writel(reg, &anatop->pll_arm); /* disable PLL bypass */
755 * This function assumes the expected core clock has to be changed by
756 * modifying the PLL. This is NOT true always but for most of the times,
757 * it is. So it assumes the PLL output freq is the same as the expected
758 * core clock (presc=1) unless the core clock is less than PLL_FREQ_MIN.
759 * In the latter case, it will try to increase the presc value until
760 * (presc*core_clk) is greater than PLL_FREQ_MIN. It then makes call to
761 * calc_pll_params() and obtains the values of PD, MFI,MFN, MFD based
762 * on the targeted PLL and reference input clock to the PLL. Lastly,
763 * it sets the register based on these values along with the dividers.
764 * Note 1) There is no value checking for the passed-in divider values
765 * so the caller has to make sure those values are sensible.
766 * 2) Also adjust the NFC divider such that the NFC clock doesn't
767 * exceed NFC_CLK_MAX.
768 * 3) IPU HSP clock is independent of AHB clock. Even it can go up to
769 * 177MHz for higher voltage, this function fixes the max to 133MHz.
770 * 4) This function should not have allowed diag_printf() calls since
771 * the serial driver has been stoped. But leave then here to allow
772 * easy debugging by NOT calling the cyg_hal_plf_serial_stop().
774 int mxc_set_clock(u32 ref, u32 freq, enum mxc_clock clk)
782 ret = set_arm_clk(ref, freq);
786 ret = set_nfc_clk(ref, freq);
790 printf("Warning: Unsupported or invalid clock type: %d\n",
799 * Dump some core clocks.
801 #define print_pll(pll) { \
802 u32 __pll = decode_pll(pll, MXC_HCLK); \
803 printf("%-12s %4d.%03d MHz\n", #pll, \
804 __pll / 1000000, __pll / 1000 % 1000); \
807 #define MXC_IPG_PER_CLK MXC_IPG_PERCLK
809 #define print_clk(clk) { \
810 u32 __clk = mxc_get_clock(MXC_##clk##_CLK); \
811 printf("%-12s %4d.%03d MHz\n", #clk, \
812 __clk / 1000000, __clk / 1000 % 1000); \
815 #define print_pfd(pll, pfd) { \
816 u32 __pfd = readl(&anatop->pfd_##pll); \
817 if (__pfd & (0x80 << 8 * pfd)) { \
818 printf("PFD_%s[%d] OFF\n", #pll, pfd); \
820 __pfd = (__pfd >> 8 * pfd) & 0x3f; \
821 printf("PFD_%s[%d] %4d.%03d MHz\n", #pll, pfd, \
823 pll * 18 * 1000 / __pfd % 1000); \
827 static void do_mx6_showclocks(void)
831 print_pll(PLL_USBOTG);
832 print_pll(PLL_AUDIO);
833 print_pll(PLL_VIDEO);
864 static struct clk_lookup {
867 } mx6_clk_lookup[] = {
868 { "arm", MXC_ARM_CLK, },
869 { "nfc", MXC_NFC_CLK, },
872 int do_clocks(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
876 unsigned long ref = ~0UL;
880 return CMD_RET_SUCCESS;
881 } else if (argc == 2 || argc > 4) {
882 return CMD_RET_USAGE;
885 freq = simple_strtoul(argv[2], NULL, 0);
887 printf("Invalid clock frequency %lu\n", freq);
888 return CMD_RET_FAILURE;
891 ref = simple_strtoul(argv[3], NULL, 0);
893 for (i = 0; i < ARRAY_SIZE(mx6_clk_lookup); i++) {
894 if (strcasecmp(argv[1], mx6_clk_lookup[i].name) == 0) {
895 switch (mx6_clk_lookup[i].index) {
898 return CMD_RET_USAGE;
899 ref = CONFIG_SYS_MX6_HCLK;
903 if (argc > 3 && ref > 3) {
904 printf("Invalid clock selector value: %lu\n", ref);
905 return CMD_RET_FAILURE;
909 printf("Setting %s clock to %lu MHz\n",
910 mx6_clk_lookup[i].name, freq);
911 if (mxc_set_clock(ref, freq, mx6_clk_lookup[i].index))
913 freq = mxc_get_clock(mx6_clk_lookup[i].index);
914 printf("%s clock set to %lu.%03lu MHz\n",
915 mx6_clk_lookup[i].name,
916 freq / 1000000, freq / 1000 % 1000);
917 return CMD_RET_SUCCESS;
920 if (i == ARRAY_SIZE(mx6_clk_lookup)) {
921 printf("clock %s not found; supported clocks are:\n", argv[1]);
922 for (i = 0; i < ARRAY_SIZE(mx6_clk_lookup); i++) {
923 printf("\t%s\n", mx6_clk_lookup[i].name);
926 printf("Failed to set clock %s to %s MHz\n",
929 return CMD_RET_FAILURE;
932 /***************************************************/
935 clocks, 4, 0, do_clocks,
936 "display/set clocks",
937 " - display clock settings\n"
938 "clocks <clkname> <freq> - set clock <clkname> to <freq> MHz"