X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=arch%2Farm%2Fcpu%2Farmv7%2Fmx6%2Fclock.c;h=abd9d619dc92a3d10de0a9432372c73ff08cb364;hb=a0ae0091d783b1140f8d321d8c6d221aeb0d39d0;hp=fcc4f352c3676c40577ddbe32deb7d468bd01866;hpb=7f673c99c2d8d1aa21996c5b914f06d784b080ca;p=oweals%2Fu-boot.git diff --git a/arch/arm/cpu/armv7/mx6/clock.c b/arch/arm/cpu/armv7/mx6/clock.c index fcc4f352c3..abd9d619dc 100644 --- a/arch/arm/cpu/armv7/mx6/clock.c +++ b/arch/arm/cpu/armv7/mx6/clock.c @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -70,6 +71,24 @@ int enable_i2c_clk(unsigned char enable, unsigned i2c_num) } #endif +/* spi_num can be from 0 - SPI_MAX_NUM */ +int enable_spi_clk(unsigned char enable, unsigned spi_num) +{ + u32 reg; + u32 mask; + + if (spi_num > SPI_MAX_NUM) + return -EINVAL; + + mask = MXC_CCM_CCGR_CG_MASK << (spi_num << 1); + reg = __raw_readl(&imx_ccm->CCGR1); + if (enable) + reg |= mask; + else + reg &= ~mask; + __raw_writel(reg, &imx_ccm->CCGR1); + return 0; +} static u32 decode_pll(enum pll_clocks pll, u32 infreq) { u32 div; @@ -79,7 +98,7 @@ static u32 decode_pll(enum pll_clocks pll, u32 infreq) div = __raw_readl(&imx_ccm->analog_pll_sys); div &= BM_ANADIG_PLL_SYS_DIV_SELECT; - return infreq * (div >> 1); + return (infreq * div) >> 1; case PLL_BUS: div = __raw_readl(&imx_ccm->analog_pll_528); div &= BM_ANADIG_PLL_528_DIV_SELECT; @@ -123,7 +142,7 @@ static u32 mxc_get_pll_pfd(enum pll_clocks pll, int pfd_num) return 0; } - return (freq * 18) / ((div & ANATOP_PFD_FRAC_MASK(pfd_num)) >> + return lldiv(freq * 18, (div & ANATOP_PFD_FRAC_MASK(pfd_num)) >> ANATOP_PFD_FRAC_SHIFT(pfd_num)); } @@ -213,7 +232,7 @@ static u32 get_uart_clk(void) u32 reg, uart_podf; u32 freq = decode_pll(PLL_USBOTG, MXC_HCLK) / 6; /* static divider */ reg = __raw_readl(&imx_ccm->cscdr1); -#ifdef CONFIG_MX6SL +#if (defined(CONFIG_MX6SL) || defined(CONFIG_MX6SX)) if (reg & MXC_CCM_CSCDR1_UART_CLK_SEL) freq = MXC_HCLK; #endif @@ -281,7 +300,7 @@ static u32 get_emi_slow_clk(void) return root_freq / (emi_slow_podf + 1); } -#ifdef CONFIG_MX6SL +#if (defined(CONFIG_MX6SL) || defined(CONFIG_MX6SX)) static u32 get_mmdc_ch0_clk(void) { u32 cbcmr = __raw_readl(&imx_ccm->cbcmr); @@ -322,7 +341,7 @@ static u32 get_mmdc_ch0_clk(void) #endif #ifdef CONFIG_FEC_MXC -int enable_fec_anatop_clock(void) +int enable_fec_anatop_clock(enum enet_freq freq) { u32 reg = 0; s32 timeout = 100000; @@ -330,7 +349,13 @@ int enable_fec_anatop_clock(void) struct anatop_regs __iomem *anatop = (struct anatop_regs __iomem *)ANATOP_BASE_ADDR; + if (freq < ENET_25MHz || freq > ENET_125MHz) + return -EINVAL; + reg = readl(&anatop->pll_enet); + reg &= ~BM_ANADIG_PLL_ENET_DIV_SELECT; + reg |= freq; + if ((reg & BM_ANADIG_PLL_ENET_POWERDOWN) || (!(reg & BM_ANADIG_PLL_ENET_LOCK))) { reg &= ~BM_ANADIG_PLL_ENET_POWERDOWN; @@ -402,20 +427,15 @@ u32 imx_get_uartclk(void) u32 imx_get_fecclk(void) { - return decode_pll(PLL_ENET, MXC_HCLK); + return mxc_get_clock(MXC_IPG_CLK); } -int enable_sata_clock(void) +static int enable_enet_pll(uint32_t en) { - u32 reg = 0; - s32 timeout = 100000; struct mxc_ccm_reg *const imx_ccm = (struct mxc_ccm_reg *) CCM_BASE_ADDR; - - /* Enable sata clock */ - reg = readl(&imx_ccm->CCGR5); /* CCGR5 */ - reg |= MXC_CCM_CCGR5_SATA_MASK; - writel(reg, &imx_ccm->CCGR5); + s32 timeout = 100000; + u32 reg = 0; /* Enable PLLs */ reg = readl(&imx_ccm->analog_pll_enet); @@ -430,10 +450,76 @@ int enable_sata_clock(void) return -EIO; reg &= ~BM_ANADIG_PLL_SYS_BYPASS; writel(reg, &imx_ccm->analog_pll_enet); - reg |= BM_ANADIG_PLL_ENET_ENABLE_SATA; + reg |= en; writel(reg, &imx_ccm->analog_pll_enet); + return 0; +} + +#ifndef CONFIG_MX6SX +static void ungate_sata_clock(void) +{ + struct mxc_ccm_reg *const imx_ccm = + (struct mxc_ccm_reg *)CCM_BASE_ADDR; + + /* Enable SATA clock. */ + setbits_le32(&imx_ccm->CCGR5, MXC_CCM_CCGR5_SATA_MASK); +} +#endif + +static void ungate_pcie_clock(void) +{ + struct mxc_ccm_reg *const imx_ccm = + (struct mxc_ccm_reg *)CCM_BASE_ADDR; + + /* Enable PCIe clock. */ + setbits_le32(&imx_ccm->CCGR4, MXC_CCM_CCGR4_PCIE_MASK); +} + +#ifndef CONFIG_MX6SX +int enable_sata_clock(void) +{ + ungate_sata_clock(); + return enable_enet_pll(BM_ANADIG_PLL_ENET_ENABLE_SATA); +} +#endif - return 0 ; +int enable_pcie_clock(void) +{ + struct anatop_regs *anatop_regs = + (struct anatop_regs *)ANATOP_BASE_ADDR; + struct mxc_ccm_reg *ccm_regs = (struct mxc_ccm_reg *)CCM_BASE_ADDR; + + /* + * Here be dragons! + * + * The register ANATOP_MISC1 is not documented in the Freescale + * MX6RM. The register that is mapped in the ANATOP space and + * marked as ANATOP_MISC1 is actually documented in the PMU section + * of the datasheet as PMU_MISC1. + * + * Switch LVDS clock source to SATA (0xb), disable clock INPUT and + * enable clock OUTPUT. This is important for PCI express link that + * is clocked from the i.MX6. + */ +#define ANADIG_ANA_MISC1_LVDSCLK1_IBEN (1 << 12) +#define ANADIG_ANA_MISC1_LVDSCLK1_OBEN (1 << 10) +#define ANADIG_ANA_MISC1_LVDS1_CLK_SEL_MASK 0x0000001F + clrsetbits_le32(&anatop_regs->ana_misc1, + ANADIG_ANA_MISC1_LVDSCLK1_IBEN | + ANADIG_ANA_MISC1_LVDS1_CLK_SEL_MASK, + ANADIG_ANA_MISC1_LVDSCLK1_OBEN | 0xb); + + /* PCIe reference clock sourced from AXI. */ + clrbits_le32(&ccm_regs->cbcmr, MXC_CCM_CBCMR_PCIE_AXI_CLK_SEL); + + /* Party time! Ungate the clock to the PCIe. */ +#ifndef CONFIG_MX6SX + ungate_sata_clock(); +#endif + ungate_pcie_clock(); + + return enable_enet_pll(BM_ANADIG_PLL_ENET_ENABLE_SATA | + BM_ANADIG_PLL_ENET_ENABLE_PCIE); } unsigned int mxc_get_clock(enum mxc_clock clk) @@ -511,6 +597,7 @@ int do_mx6_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return 0; } +#ifndef CONFIG_MX6SX void enable_ipu_clock(void) { struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; @@ -519,6 +606,7 @@ void enable_ipu_clock(void) reg |= MXC_CCM_CCGR3_IPU1_IPU_MASK; writel(reg, &mxc_ccm->CCGR3); } +#endif /***************************************************/ U_BOOT_CMD(