ARM: mx6: Add PCI express clock configuration
authorMarek Vasut <marex@denx.de>
Sat, 14 Dec 2013 05:27:26 +0000 (06:27 +0100)
committerStefano Babic <sbabic@denx.de>
Sun, 26 Jan 2014 11:41:20 +0000 (12:41 +0100)
Split the SATA clock enabling function and add PCI express clock
enabling function. The SATA clock enabling function starts up the
100MHz SATA reference PLL in ENET_PLL register, but the code can
be re-used to enable the 125MHz PCIe reference in ENET_PLL, so pull
this code into separate function. Moreover, add the PCIe clock
enabling code.

Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Albert Aribaud <albert.u.boot@aribaud.net>
Cc: Eric Nelson <eric.nelson@boundarydevices.com>
Cc: Fabio Estevam <fabio.estevam@freescale.com>
Cc: Stefano Babic <sbabic@denx.de>
Acked-by: Jagannadha Sutradharudu Teki <jagannadh.teki@gmail.com>
arch/arm/cpu/armv7/mx6/clock.c
arch/arm/include/asm/arch-mx6/clock.h

index 5617a410da9f5c67f17cad0e4709904f86e75fcc..61f71cfa85e280c6a3f013939aa33daab790ae40 100644 (file)
@@ -412,17 +412,12 @@ u32 imx_get_fecclk(void)
        return decode_pll(PLL_ENET, MXC_HCLK);
 }
 
-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);
@@ -437,10 +432,70 @@ 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;
+}
 
-       return 0 ;
+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);
+}
+
+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);
+}
+
+int enable_sata_clock(void)
+{
+       ungate_sata_clock();
+       return enable_enet_pll(BM_ANADIG_PLL_ENET_ENABLE_SATA);
+}
+
+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. */
+       ungate_sata_clock();
+       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)
index e31ba0a955efa519067b408927438dcbc3d79aac..1b4ded7feba50e54f1cf6001955958d4fe777f07 100644 (file)
@@ -55,6 +55,7 @@ unsigned int mxc_get_clock(enum mxc_clock clk);
 void enable_ocotp_clk(unsigned char enable);
 void enable_usboh3_clk(unsigned char enable);
 int enable_sata_clock(void);
+int enable_pcie_clock(void);
 int enable_i2c_clk(unsigned char enable, unsigned i2c_num);
 void enable_ipu_clock(void);
 int enable_fec_anatop_clock(enum enet_freq freq);