X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=arch%2Farm%2Fcpu%2Farmv7%2Fmx5%2Fclock.c;h=bf52f0d19e546e0b98b2717b25618c4c6711e92b;hb=ae27120c31d58b8bb694d9155bcffdcfae8552a6;hp=fe0c0d3cb7d6c1287528f6db4365bd30c96bc639;hpb=649dc8abd9be85f6de441c3d4d2b7e0588156a38;p=oweals%2Fu-boot.git diff --git a/arch/arm/cpu/armv7/mx5/clock.c b/arch/arm/cpu/armv7/mx5/clock.c index fe0c0d3cb7..bf52f0d19e 100644 --- a/arch/arm/cpu/armv7/mx5/clock.c +++ b/arch/arm/cpu/armv7/mx5/clock.c @@ -4,23 +4,7 @@ * * (C) Copyright 2009 Freescale Semiconductor, Inc. * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA + * SPDX-License-Identifier: GPL-2.0+ */ #include @@ -101,7 +85,7 @@ void set_usboh3_clk(void) MXC_CCM_CSCDR1_USBOH3_CLK_PODF(1)); } -void enable_usboh3_clk(unsigned char enable) +void enable_usboh3_clk(bool enable) { unsigned int cg = enable ? MXC_CCM_CCGR_CG_ON : MXC_CCM_CCGR_CG_OFF; @@ -110,13 +94,17 @@ void enable_usboh3_clk(unsigned char enable) MXC_CCM_CCGR2_USBOH3_60M(cg)); } -#ifdef CONFIG_I2C_MXC -/* i2c_num can be from 0 - 2 */ +#ifdef CONFIG_SYS_I2C_MXC +/* i2c_num can be from 0, to 1 for i.MX51 and 2 for i.MX53 */ int enable_i2c_clk(unsigned char enable, unsigned i2c_num) { u32 mask; +#if defined(CONFIG_MX51) + if (i2c_num > 1) +#elif defined(CONFIG_MX53) if (i2c_num > 2) +#endif return -EINVAL; mask = MXC_CCM_CCGR_CG_MASK << (MXC_CCM_CCGR1_I2C1_OFFSET + (i2c_num << 1)); @@ -134,7 +122,7 @@ void set_usb_phy_clk(void) } #if defined(CONFIG_MX51) -void enable_usb_phy1_clk(unsigned char enable) +void enable_usb_phy1_clk(bool enable) { unsigned int cg = enable ? MXC_CCM_CCGR_CG_ON : MXC_CCM_CCGR_CG_OFF; @@ -143,12 +131,12 @@ void enable_usb_phy1_clk(unsigned char enable) MXC_CCM_CCGR2_USB_PHY(cg)); } -void enable_usb_phy2_clk(unsigned char enable) +void enable_usb_phy2_clk(bool enable) { /* i.MX51 has a single USB PHY clock, so do nothing here. */ } #elif defined(CONFIG_MX53) -void enable_usb_phy1_clk(unsigned char enable) +void enable_usb_phy1_clk(bool enable) { unsigned int cg = enable ? MXC_CCM_CCGR_CG_ON : MXC_CCM_CCGR_CG_OFF; @@ -157,7 +145,7 @@ void enable_usb_phy1_clk(unsigned char enable) MXC_CCM_CCGR4_USB_PHY1(cg)); } -void enable_usb_phy2_clk(unsigned char enable) +void enable_usb_phy2_clk(bool enable) { unsigned int cg = enable ? MXC_CCM_CCGR_CG_ON : MXC_CCM_CCGR_CG_OFF; @@ -221,6 +209,44 @@ static uint32_t decode_pll(struct mxc_pll_reg *pll, uint32_t infreq) return ret; } +#ifdef CONFIG_MX51 +/* + * This function returns the Frequency Pre-Multiplier clock. + */ +static u32 get_fpm(void) +{ + u32 mult; + u32 ccr = readl(&mxc_ccm->ccr); + + if (ccr & MXC_CCM_CCR_FPM_MULT) + mult = 1024; + else + mult = 512; + + return MXC_CLK32 * mult; +} +#endif + +/* + * This function returns the low power audio clock. + */ +static u32 get_lp_apm(void) +{ + u32 ret_val = 0; + u32 ccsr = readl(&mxc_ccm->ccsr); + + if (ccsr & MXC_CCM_CCSR_LP_APM) +#if defined(CONFIG_MX51) + ret_val = get_fpm(); +#elif defined(CONFIG_MX53) + ret_val = decode_pll(mxc_plls[PLL4_CLOCK], MXC_HCLK); +#endif + else + ret_val = MXC_HCLK; + + return ret_val; +} + /* * Get mcu main rate */ @@ -249,6 +275,8 @@ u32 get_periph_clk(void) return decode_pll(mxc_plls[PLL1_CLOCK], MXC_HCLK); case 1: return decode_pll(mxc_plls[PLL3_CLOCK], MXC_HCLK); + case 2: + return get_lp_apm(); default: return 0; } @@ -275,62 +303,62 @@ static u32 get_ipg_clk(void) */ static u32 get_ipg_per_clk(void) { - u32 pred1, pred2, podf; + u32 freq, pred1, pred2, podf; if (readl(&mxc_ccm->cbcmr) & MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL) return get_ipg_clk(); - /* Fixme: not handle what about lpm*/ + + if (readl(&mxc_ccm->cbcmr) & MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL) + freq = get_lp_apm(); + else + freq = get_periph_clk(); podf = readl(&mxc_ccm->cbcdr); pred1 = MXC_CCM_CBCDR_PERCLK_PRED1_RD(podf); pred2 = MXC_CCM_CBCDR_PERCLK_PRED2_RD(podf); podf = MXC_CCM_CBCDR_PERCLK_PODF_RD(podf); - return get_periph_clk() / ((pred1 + 1) * (pred2 + 1) * (podf + 1)); + return freq / ((pred1 + 1) * (pred2 + 1) * (podf + 1)); } -/* - * Get the rate of uart clk. - */ -static u32 get_uart_clk(void) +/* Get the output clock rate of a standard PLL MUX for peripherals. */ +static u32 get_standard_pll_sel_clk(u32 clk_sel) { - unsigned int freq, reg, pred, podf; + u32 freq = 0; - reg = readl(&mxc_ccm->cscmr1); - switch (MXC_CCM_CSCMR1_UART_CLK_SEL_RD(reg)) { - case 0x0: + switch (clk_sel & 0x3) { + case 0: freq = decode_pll(mxc_plls[PLL1_CLOCK], MXC_HCLK); break; - case 0x1: + case 1: freq = decode_pll(mxc_plls[PLL2_CLOCK], MXC_HCLK); break; - case 0x2: + case 2: freq = decode_pll(mxc_plls[PLL3_CLOCK], MXC_HCLK); break; - default: - return 66500000; + case 3: + freq = get_lp_apm(); + break; } - reg = readl(&mxc_ccm->cscdr1); - pred = MXC_CCM_CSCDR1_UART_CLK_PRED_RD(reg); - podf = MXC_CCM_CSCDR1_UART_CLK_PODF_RD(reg); - freq /= (pred + 1) * (podf + 1); - return freq; } /* - * This function returns the low power audio clock. + * Get the rate of uart clk. */ -static u32 get_lp_apm(void) +static u32 get_uart_clk(void) { - u32 ret_val = 0; - u32 ccsr = readl(&mxc_ccm->ccsr); + unsigned int clk_sel, freq, reg, pred, podf; - if (ccsr & MXC_CCM_CCSR_LP_APM) - ret_val = MXC_CLK32 * 1024; - else - ret_val = MXC_HCLK; + reg = readl(&mxc_ccm->cscmr1); + clk_sel = MXC_CCM_CSCMR1_UART_CLK_SEL_RD(reg); + freq = get_standard_pll_sel_clk(clk_sel); - return ret_val; + reg = readl(&mxc_ccm->cscdr1); + pred = MXC_CCM_CSCDR1_UART_CLK_PRED_RD(reg); + podf = MXC_CCM_CSCDR1_UART_CLK_PODF_RD(reg); + freq /= (pred + 1) * (podf + 1); + + return freq; } /* @@ -338,33 +366,54 @@ static u32 get_lp_apm(void) */ static u32 imx_get_cspiclk(void) { - u32 ret_val = 0, pdf, pre_pdf, clk_sel; + u32 ret_val = 0, pdf, pre_pdf, clk_sel, freq; u32 cscmr1 = readl(&mxc_ccm->cscmr1); u32 cscdr2 = readl(&mxc_ccm->cscdr2); pre_pdf = MXC_CCM_CSCDR2_CSPI_CLK_PRED_RD(cscdr2); pdf = MXC_CCM_CSCDR2_CSPI_CLK_PODF_RD(cscdr2); clk_sel = MXC_CCM_CSCMR1_CSPI_CLK_SEL_RD(cscmr1); + freq = get_standard_pll_sel_clk(clk_sel); + ret_val = freq / ((pre_pdf + 1) * (pdf + 1)); + return ret_val; +} - switch (clk_sel) { +/* + * get esdhc clock rate. + */ +static u32 get_esdhc_clk(u32 port) +{ + u32 clk_sel = 0, pred = 0, podf = 0, freq = 0; + u32 cscmr1 = readl(&mxc_ccm->cscmr1); + u32 cscdr1 = readl(&mxc_ccm->cscdr1); + + switch (port) { case 0: - ret_val = decode_pll(mxc_plls[PLL1_CLOCK], MXC_HCLK) / - ((pre_pdf + 1) * (pdf + 1)); + clk_sel = MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_RD(cscmr1); + pred = MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_RD(cscdr1); + podf = MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_RD(cscdr1); break; case 1: - ret_val = decode_pll(mxc_plls[PLL2_CLOCK], MXC_HCLK) / - ((pre_pdf + 1) * (pdf + 1)); + clk_sel = MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_RD(cscmr1); + pred = MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_RD(cscdr1); + podf = MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_RD(cscdr1); break; case 2: - ret_val = decode_pll(mxc_plls[PLL3_CLOCK], MXC_HCLK) / - ((pre_pdf + 1) * (pdf + 1)); - break; + if (cscmr1 & MXC_CCM_CSCMR1_ESDHC3_CLK_SEL) + return get_esdhc_clk(1); + else + return get_esdhc_clk(0); + case 3: + if (cscmr1 & MXC_CCM_CSCMR1_ESDHC4_CLK_SEL) + return get_esdhc_clk(1); + else + return get_esdhc_clk(0); default: - ret_val = get_lp_apm() / ((pre_pdf + 1) * (pdf + 1)); break; } - return ret_val; + freq = get_standard_pll_sel_clk(clk_sel) / ((pred + 1) * (podf + 1)); + return freq; } static u32 get_axi_a_clk(void) @@ -450,8 +499,16 @@ unsigned int mxc_get_clock(enum mxc_clock clk) return get_uart_clk(); case MXC_CSPI_CLK: return imx_get_cspiclk(); + case MXC_ESDHC_CLK: + return get_esdhc_clk(0); + case MXC_ESDHC2_CLK: + return get_esdhc_clk(1); + case MXC_ESDHC3_CLK: + return get_esdhc_clk(2); + case MXC_ESDHC4_CLK: + return get_esdhc_clk(3); case MXC_FEC_CLK: - return decode_pll(mxc_plls[PLL1_CLOCK], MXC_HCLK); + return get_ipg_clk(); case MXC_SATA_CLK: return get_ahb_clk(); case MXC_DDR_CLK: @@ -467,10 +524,9 @@ u32 imx_get_uartclk(void) return get_uart_clk(); } - u32 imx_get_fecclk(void) { - return mxc_get_clock(MXC_IPG_CLK); + return get_ipg_clk(); } static int gcd(int m, int n) @@ -667,10 +723,11 @@ static int config_core_clk(u32 ref, u32 freq) static int config_nfc_clk(u32 nfc_clk) { u32 parent_rate = get_emi_slow_clk(); - u32 div = parent_rate / nfc_clk; + u32 div; - if (nfc_clk <= 0) + if (nfc_clk == 0) return -EINVAL; + div = parent_rate / nfc_clk; if (div == 0) div++; if (parent_rate / div > NFC_CLK_MAX) @@ -683,6 +740,27 @@ static int config_nfc_clk(u32 nfc_clk) return 0; } +void enable_nfc_clk(unsigned char enable) +{ + unsigned int cg = enable ? MXC_CCM_CCGR_CG_ON : MXC_CCM_CCGR_CG_OFF; + + clrsetbits_le32(&mxc_ccm->CCGR5, + MXC_CCM_CCGR5_EMI_ENFC(MXC_CCM_CCGR_CG_MASK), + MXC_CCM_CCGR5_EMI_ENFC(cg)); +} + +#ifdef CONFIG_FSL_IIM +void enable_efuse_prog_supply(bool enable) +{ + if (enable) + setbits_le32(&mxc_ccm->cgpr, + MXC_CCM_CGPR_EFUSE_PROG_SUPPLY_GATE); + else + clrbits_le32(&mxc_ccm->cgpr, + MXC_CCM_CGPR_EFUSE_PROG_SUPPLY_GATE); +} +#endif + /* Config main_bus_clock for periphs */ static int config_periph_clk(u32 ref, u32 freq) { @@ -856,7 +934,9 @@ int do_mx5_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) printf("IPG %8d kHz\n", mxc_get_clock(MXC_IPG_CLK) / 1000); printf("IPG PERCLK %8d kHz\n", mxc_get_clock(MXC_IPG_PERCLK) / 1000); printf("DDR %8d kHz\n", mxc_get_clock(MXC_DDR_CLK) / 1000); - +#ifdef CONFIG_MXC_SPI + printf("CSPI %8d kHz\n", mxc_get_clock(MXC_CSPI_CLK) / 1000); +#endif return 0; }