]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - arch/arm/mach-mx5/clock-mx51-mx53.c
Merge branch 'devel-stable' into devel
[karo-tx-linux.git] / arch / arm / mach-mx5 / clock-mx51-mx53.c
similarity index 79%
rename from arch/arm/mach-mx5/clock-mx51.c
rename to arch/arm/mach-mx5/clock-mx51-mx53.c
index 5975edb47de82ad76e9518bb77a15410faf1fd89..785e1a33618355098e9b9202b4dfe78deb3afcff 100644 (file)
@@ -33,11 +33,15 @@ static struct clk pll1_main_clk;
 static struct clk pll1_sw_clk;
 static struct clk pll2_sw_clk;
 static struct clk pll3_sw_clk;
+static struct clk mx53_pll4_sw_clk;
 static struct clk lp_apm_clk;
 static struct clk periph_apm_clk;
 static struct clk ahb_clk;
 static struct clk ipg_clk;
 static struct clk usboh3_clk;
+static struct clk emi_fast_clk;
+static struct clk ipu_clk;
+static struct clk mipi_hsc1_clk;
 
 #define MAX_DPLL_WAIT_TRIES    1000 /* 1000 * udelay(1) = 1ms */
 
@@ -123,7 +127,7 @@ static inline u32 _get_mux(struct clk *parent, struct clk *m0,
        return -EINVAL;
 }
 
-static inline void __iomem *_get_pll_base(struct clk *pll)
+static inline void __iomem *_mx51_get_pll_base(struct clk *pll)
 {
        if (pll == &pll1_main_clk)
                return MX51_DPLL1_BASE;
@@ -137,6 +141,30 @@ static inline void __iomem *_get_pll_base(struct clk *pll)
        return NULL;
 }
 
+static inline void __iomem *_mx53_get_pll_base(struct clk *pll)
+{
+       if (pll == &pll1_main_clk)
+               return MX53_DPLL1_BASE;
+       else if (pll == &pll2_sw_clk)
+               return MX53_DPLL2_BASE;
+       else if (pll == &pll3_sw_clk)
+               return MX53_DPLL3_BASE;
+       else if (pll == &mx53_pll4_sw_clk)
+               return MX53_DPLL4_BASE;
+       else
+               BUG();
+
+       return NULL;
+}
+
+static inline void __iomem *_get_pll_base(struct clk *pll)
+{
+       if (cpu_is_mx51())
+               return _mx51_get_pll_base(pll);
+       else
+               return _mx53_get_pll_base(pll);
+}
+
 static unsigned long clk_pll_get_rate(struct clk *clk)
 {
        long mfi, mfn, mfd, pdf, ref_clk, mfn_abs;
@@ -514,7 +542,10 @@ static int _clk_max_enable(struct clk *clk)
 
        /* Handshake with MAX when LPM is entered. */
        reg = __raw_readl(MXC_CCM_CLPCR);
-       reg &= ~MXC_CCM_CLPCR_BYPASS_MAX_LPM_HS;
+       if (cpu_is_mx51())
+               reg &= ~MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS;
+       else if (cpu_is_mx53())
+               reg &= ~MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS;
        __raw_writel(reg, MXC_CCM_CLPCR);
 
        return 0;
@@ -528,7 +559,10 @@ static void _clk_max_disable(struct clk *clk)
 
        /* No Handshake with MAX when LPM is entered as its disabled. */
        reg = __raw_readl(MXC_CCM_CLPCR);
-       reg |= MXC_CCM_CLPCR_BYPASS_MAX_LPM_HS;
+       if (cpu_is_mx51())
+               reg |= MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS;
+       else if (cpu_is_mx53())
+               reg &= ~MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS;
        __raw_writel(reg, MXC_CCM_CLPCR);
 }
 
@@ -679,6 +713,19 @@ static unsigned long clk_emi_slow_get_rate(struct clk *clk)
        return clk_get_rate(clk->parent) / div;
 }
 
+static unsigned long _clk_ddr_hf_get_rate(struct clk *clk)
+{
+       unsigned long rate;
+       u32 reg, div;
+
+       reg = __raw_readl(MXC_CCM_CBCDR);
+       div = ((reg & MXC_CCM_CBCDR_DDR_PODF_MASK) >>
+               MXC_CCM_CBCDR_DDR_PODF_OFFSET) + 1;
+       rate = clk_get_rate(clk->parent) / div;
+
+       return rate;
+}
+
 /* External high frequency clock */
 static struct clk ckih_clk = {
        .get_rate = get_high_reference_clock_rate,
@@ -739,6 +786,14 @@ static struct clk pll3_sw_clk = {
        .disable = _clk_pll_disable,
 };
 
+/* PLL4 SW supplies to LVDS Display Bridge(LDB) */
+static struct clk mx53_pll4_sw_clk = {
+       .parent = &osc_clk,
+       .set_rate = _clk_pll_set_rate,
+       .enable = _clk_pll_enable,
+       .disable = _clk_pll_disable,
+};
+
 /* Low-power Audio Playback Mode clock */
 static struct clk lp_apm_clk = {
        .parent = &osc_clk,
@@ -763,6 +818,12 @@ static struct clk ahb_clk = {
        .round_rate = _clk_ahb_round_rate,
 };
 
+static struct clk iim_clk = {
+       .parent = &ipg_clk,
+       .enable_reg = MXC_CCM_CCGR0,
+       .enable_shift = MXC_CCM_CCGRx_CG15_OFFSET,
+};
+
 /* Main IP interface clock for access to registers */
 static struct clk ipg_clk = {
        .parent = &ahb_clk,
@@ -810,6 +871,10 @@ static struct clk kpp_clk = {
        .id = 0,
 };
 
+static struct clk dummy_clk = {
+       .id = 0,
+};
+
 static struct clk emi_slow_clk = {
        .parent = &pll2_sw_clk,
        .enable_reg = MXC_CCM_CCGR5,
@@ -819,6 +884,109 @@ static struct clk emi_slow_clk = {
        .get_rate = clk_emi_slow_get_rate,
 };
 
+static int clk_ipu_enable(struct clk *clk)
+{
+       u32 reg;
+
+       _clk_ccgr_enable(clk);
+
+       /* Enable handshake with IPU when certain clock rates are changed */
+       reg = __raw_readl(MXC_CCM_CCDR);
+       reg &= ~MXC_CCM_CCDR_IPU_HS_MASK;
+       __raw_writel(reg, MXC_CCM_CCDR);
+
+       /* Enable handshake with IPU when LPM is entered */
+       reg = __raw_readl(MXC_CCM_CLPCR);
+       reg &= ~MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS;
+       __raw_writel(reg, MXC_CCM_CLPCR);
+
+       return 0;
+}
+
+static void clk_ipu_disable(struct clk *clk)
+{
+       u32 reg;
+
+       _clk_ccgr_disable(clk);
+
+       /* Disable handshake with IPU whe dividers are changed */
+       reg = __raw_readl(MXC_CCM_CCDR);
+       reg |= MXC_CCM_CCDR_IPU_HS_MASK;
+       __raw_writel(reg, MXC_CCM_CCDR);
+
+       /* Disable handshake with IPU when LPM is entered */
+       reg = __raw_readl(MXC_CCM_CLPCR);
+       reg |= MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS;
+       __raw_writel(reg, MXC_CCM_CLPCR);
+}
+
+static struct clk ahbmux1_clk = {
+       .parent = &ahb_clk,
+       .secondary = &ahb_max_clk,
+       .enable_reg = MXC_CCM_CCGR0,
+       .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
+       .enable = _clk_ccgr_enable,
+       .disable = _clk_ccgr_disable_inwait,
+};
+
+static struct clk ipu_sec_clk = {
+       .parent = &emi_fast_clk,
+       .secondary = &ahbmux1_clk,
+};
+
+static struct clk ddr_hf_clk = {
+       .parent = &pll1_sw_clk,
+       .get_rate = _clk_ddr_hf_get_rate,
+};
+
+static struct clk ddr_clk = {
+       .parent = &ddr_hf_clk,
+};
+
+/* clock definitions for MIPI HSC unit which has been removed
+ * from documentation, but not from hardware
+ */
+static int _clk_hsc_enable(struct clk *clk)
+{
+       u32 reg;
+
+       _clk_ccgr_enable(clk);
+       /* Handshake with IPU when certain clock rates are changed. */
+       reg = __raw_readl(MXC_CCM_CCDR);
+       reg &= ~MXC_CCM_CCDR_HSC_HS_MASK;
+       __raw_writel(reg, MXC_CCM_CCDR);
+
+       reg = __raw_readl(MXC_CCM_CLPCR);
+       reg &= ~MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS;
+       __raw_writel(reg, MXC_CCM_CLPCR);
+
+       return 0;
+}
+
+static void _clk_hsc_disable(struct clk *clk)
+{
+       u32 reg;
+
+       _clk_ccgr_disable(clk);
+       /* No handshake with HSC as its not enabled. */
+       reg = __raw_readl(MXC_CCM_CCDR);
+       reg |= MXC_CCM_CCDR_HSC_HS_MASK;
+       __raw_writel(reg, MXC_CCM_CCDR);
+
+       reg = __raw_readl(MXC_CCM_CLPCR);
+       reg |= MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS;
+       __raw_writel(reg, MXC_CCM_CLPCR);
+}
+
+static struct clk mipi_hsp_clk = {
+       .parent = &ipu_clk,
+       .enable_reg = MXC_CCM_CCGR4,
+       .enable_shift = MXC_CCM_CCGRx_CG6_OFFSET,
+       .enable = _clk_hsc_enable,
+       .disable = _clk_hsc_disable,
+       .secondary = &mipi_hsc1_clk,
+};
+
 #define DEFINE_CLOCK_CCGR(name, i, er, es, pfx, p, s)  \
        static struct clk name = {                      \
                .id             = i,                    \
@@ -927,6 +1095,41 @@ static struct clk usboh3_clk = {
        .parent = &pll2_sw_clk,
        .get_rate = clk_usboh3_get_rate,
        .set_parent = clk_usboh3_set_parent,
+       .enable = _clk_ccgr_enable,
+       .disable = _clk_ccgr_disable,
+       .enable_reg = MXC_CCM_CCGR2,
+       .enable_shift = MXC_CCM_CCGRx_CG14_OFFSET,
+};
+
+static struct clk usb_ahb_clk = {
+       .parent = &ipg_clk,
+       .enable = _clk_ccgr_enable,
+       .disable = _clk_ccgr_disable,
+       .enable_reg = MXC_CCM_CCGR2,
+       .enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
+};
+
+static int clk_usb_phy1_set_parent(struct clk *clk, struct clk *parent)
+{
+       u32 reg;
+
+       reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USB_PHY_CLK_SEL;
+
+       if (parent == &pll3_sw_clk)
+               reg |= 1 << MXC_CCM_CSCMR1_USB_PHY_CLK_SEL_OFFSET;
+
+       __raw_writel(reg, MXC_CCM_CSCMR1);
+
+       return 0;
+}
+
+static struct clk usb_phy1_clk = {
+       .parent = &pll3_sw_clk,
+       .set_parent = clk_usb_phy1_set_parent,
+       .enable = _clk_ccgr_enable,
+       .enable_reg = MXC_CCM_CCGR2,
+       .enable_shift = MXC_CCM_CCGRx_CG0_OFFSET,
+       .disable = _clk_ccgr_disable,
 };
 
 /* eCSPI */
@@ -1013,6 +1216,10 @@ DEFINE_CLOCK(ssi2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG10_OFFSET,
        NULL, NULL, &ipg_clk, NULL);
 DEFINE_CLOCK(ssi2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG11_OFFSET,
        NULL, NULL, &pll3_sw_clk, &ssi2_ipg_clk);
+DEFINE_CLOCK(ssi3_ipg_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG12_OFFSET,
+       NULL, NULL, &ipg_clk, NULL);
+DEFINE_CLOCK(ssi3_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG13_OFFSET,
+       NULL, NULL, &pll3_sw_clk, &ssi3_ipg_clk);
 
 /* eCSPI */
 DEFINE_CLOCK_FULL(ecspi1_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG9_OFFSET,
@@ -1046,6 +1253,23 @@ DEFINE_CLOCK_FULL(esdhc2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG2_OFFSET,
 DEFINE_CLOCK_MAX(esdhc2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG3_OFFSET,
        clk_esdhc2, &pll2_sw_clk, &esdhc2_ipg_clk);
 
+DEFINE_CLOCK(mipi_esc_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG5_OFFSET, NULL, NULL, NULL, &pll2_sw_clk);
+DEFINE_CLOCK(mipi_hsc2_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG4_OFFSET, NULL, NULL, &mipi_esc_clk, &pll2_sw_clk);
+DEFINE_CLOCK(mipi_hsc1_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG3_OFFSET, NULL, NULL, &mipi_hsc2_clk, &pll2_sw_clk);
+
+/* IPU */
+DEFINE_CLOCK_FULL(ipu_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG5_OFFSET,
+       NULL,  NULL, clk_ipu_enable, clk_ipu_disable, &ahb_clk, &ipu_sec_clk);
+
+DEFINE_CLOCK_FULL(emi_fast_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG7_OFFSET,
+               NULL, NULL, _clk_ccgr_enable, _clk_ccgr_disable_inwait,
+               &ddr_clk, NULL);
+
+DEFINE_CLOCK(ipu_di0_clk, 0, MXC_CCM_CCGR6, MXC_CCM_CCGRx_CG5_OFFSET,
+               NULL, NULL, &pll3_sw_clk, NULL);
+DEFINE_CLOCK(ipu_di1_clk, 0, MXC_CCM_CCGR6, MXC_CCM_CCGRx_CG6_OFFSET,
+               NULL, NULL, &pll3_sw_clk, NULL);
+
 #define _REGISTER_CLOCK(d, n, c) \
        { \
                .dev_id = d, \
@@ -1053,7 +1277,7 @@ DEFINE_CLOCK_MAX(esdhc2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG3_OFFSET,
                .clk = &c,   \
        },
 
-static struct clk_lookup lookups[] = {
+static struct clk_lookup mx51_lookups[] = {
        _REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
        _REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
        _REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
@@ -1063,15 +1287,19 @@ static struct clk_lookup lookups[] = {
        _REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
        _REGISTER_CLOCK("imx-i2c.2", NULL, hsi2c_clk)
        _REGISTER_CLOCK("mxc-ehci.0", "usb", usboh3_clk)
-       _REGISTER_CLOCK("mxc-ehci.0", "usb_ahb", ahb_clk)
+       _REGISTER_CLOCK("mxc-ehci.0", "usb_ahb", usb_ahb_clk)
+       _REGISTER_CLOCK("mxc-ehci.0", "usb_phy1", usb_phy1_clk)
        _REGISTER_CLOCK("mxc-ehci.1", "usb", usboh3_clk)
-       _REGISTER_CLOCK("mxc-ehci.1", "usb_ahb", ahb_clk)
+       _REGISTER_CLOCK("mxc-ehci.1", "usb_ahb", usb_ahb_clk)
+       _REGISTER_CLOCK("mxc-ehci.2", "usb", usboh3_clk)
+       _REGISTER_CLOCK("mxc-ehci.2", "usb_ahb", usb_ahb_clk)
        _REGISTER_CLOCK("fsl-usb2-udc", "usb", usboh3_clk)
        _REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", ahb_clk)
        _REGISTER_CLOCK("imx-keypad.0", NULL, kpp_clk)
        _REGISTER_CLOCK("mxc_nand", NULL, nfc_clk)
        _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
        _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
+       _REGISTER_CLOCK("imx-ssi.2", NULL, ssi3_clk)
        _REGISTER_CLOCK("imx-sdma", NULL, sdma_clk)
        _REGISTER_CLOCK(NULL, "ckih", ckih_clk)
        _REGISTER_CLOCK(NULL, "ckih2", ckih2_clk)
@@ -1082,6 +1310,22 @@ static struct clk_lookup lookups[] = {
        _REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
        _REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk)
        _REGISTER_CLOCK(NULL, "cpu_clk", cpu_clk)
+       _REGISTER_CLOCK(NULL, "iim_clk", iim_clk)
+       _REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk)
+       _REGISTER_CLOCK("imx2-wdt.1", NULL, dummy_clk)
+       _REGISTER_CLOCK(NULL, "mipi_hsp", mipi_hsp_clk)
+       _REGISTER_CLOCK("imx-ipuv3", NULL, ipu_clk)
+       _REGISTER_CLOCK("imx-ipuv3", "di0", ipu_di0_clk)
+       _REGISTER_CLOCK("imx-ipuv3", "di1", ipu_di1_clk)
+};
+
+static struct clk_lookup mx53_lookups[] = {
+       _REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
+       _REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
+       _REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
+       _REGISTER_CLOCK(NULL, "gpt", gpt_clk)
+       _REGISTER_CLOCK("fec.0", NULL, fec_clk)
+       _REGISTER_CLOCK(NULL, "iim_clk", iim_clk)
 };
 
 static void clk_tree_init(void)
@@ -1114,14 +1358,22 @@ int __init mx51_clocks_init(unsigned long ckil, unsigned long osc,
        ckih2_reference = ckih2;
        oscillator_reference = osc;
 
-       for (i = 0; i < ARRAY_SIZE(lookups); i++)
-               clkdev_add(&lookups[i]);
+       for (i = 0; i < ARRAY_SIZE(mx51_lookups); i++)
+               clkdev_add(&mx51_lookups[i]);
 
        clk_tree_init();
 
+       clk_set_parent(&uart_root_clk, &pll3_sw_clk);
        clk_enable(&cpu_clk);
        clk_enable(&main_bus_clk);
 
+       clk_enable(&iim_clk);
+       mx51_revision();
+       clk_disable(&iim_clk);
+
+       /* move usb_phy_clk to 24MHz */
+       clk_set_parent(&usb_phy1_clk, &osc_clk);
+
        /* set the usboh3_clk parent to pll2_sw_clk */
        clk_set_parent(&usboh3_clk, &pll2_sw_clk);
 
@@ -1138,3 +1390,31 @@ int __init mx51_clocks_init(unsigned long ckil, unsigned long osc,
                MX51_MXC_INT_GPT);
        return 0;
 }
+
+int __init mx53_clocks_init(unsigned long ckil, unsigned long osc,
+                       unsigned long ckih1, unsigned long ckih2)
+{
+       int i;
+
+       external_low_reference = ckil;
+       external_high_reference = ckih1;
+       ckih2_reference = ckih2;
+       oscillator_reference = osc;
+
+       for (i = 0; i < ARRAY_SIZE(mx53_lookups); i++)
+               clkdev_add(&mx53_lookups[i]);
+
+       clk_tree_init();
+
+       clk_enable(&cpu_clk);
+       clk_enable(&main_bus_clk);
+
+       clk_enable(&iim_clk);
+       mx53_revision();
+       clk_disable(&iim_clk);
+
+       /* System timer */
+       mxc_timer_init(&gpt_clk, MX53_IO_ADDRESS(MX53_GPT1_BASE_ADDR),
+               MX53_INT_GPT);
+       return 0;
+}