This patch adds clock support for the following AM35xx modules
        - Ethernet MAC
        - CAN Controller (HECC)
        - New MUSB OTG Controller with integrated Phy
        - Video Processing Front End (VPFE)
        - Additional UART (UART4)

Signed-off-by: Ranjith Lohithakshan <[email protected]>
---
 arch/arm/mach-omap2/clock34xx.c       |   93 ++++++++++++++++++++++++++
 arch/arm/mach-omap2/clock34xx.h       |    4 +
 arch/arm/mach-omap2/clock34xx_data.c  |  117 +++++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/cm-regbits-34xx.h |   10 +++
 4 files changed, 224 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c
index 97752e4..9da21b7 100644
--- a/arch/arm/mach-omap2/clock34xx.c
+++ b/arch/arm/mach-omap2/clock34xx.c
@@ -51,6 +51,16 @@
  */
 #define DPLL5_FREQ_FOR_USBHOST         120000000
 
+/*
+ * In AM35xx IPSS, the {ICK,FCK} enable bits for modules are exported
+ * in the same register at a bit offset of 0x8. The EN_ACK for ICK is 
+ * at an offset of 4 from ICK enable bit.
+ */
+#define AM35XX_IPSS_ICK_MASK                   0xF
+#define AM35XX_IPSS_ICK_EN_ACK_OFFSET  0x4
+#define AM35XX_IPSS_ICK_FCK_OFFSET             0x8
+#define AM35XX_IPSS_CLK_IDLEST_VAL             0
+
 /* needed by omap3_core_dpll_m2_set_rate() */
 struct clk *sdrc_ick_p, *arm_fck_p;
 
@@ -156,6 +166,89 @@ const struct clkops clkops_noncore_dpll_ops = {
        .disable        = omap3_noncore_dpll_disable,
 };
 
+/**
+ * am35xx_clk_find_idlest - return clock ACK info for AM35XX IPSS
+ * @clk: struct clk * being enabled
+ * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
+ * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
+ * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
+ *
+ * The interface clocks on AM35xx IPSS reflects the clock idle status
+ * in the enable register itsel at a bit offset of 4 from the enable
+ * bit. A value of 1 indicates that clock is enabled.
+ */
+static void am35xx_clk_find_idlest(struct clk *clk,
+                                           void __iomem **idlest_reg,
+                                           u8 *idlest_bit,
+                                           u8 *idlest_val)
+{
+       *idlest_reg = (__force void __iomem *)(clk->enable_reg);
+       *idlest_bit = clk->enable_bit + AM35XX_IPSS_ICK_EN_ACK_OFFSET;
+       *idlest_val = AM35XX_IPSS_CLK_IDLEST_VAL;
+}
+
+/**
+ * am35xx_clk_find_companion - find companion clock to @clk
+ * @clk: struct clk * to find the companion clock of
+ * @other_reg: void __iomem ** to return the companion clock CM_*CLKEN va in
+ * @other_bit: u8 ** to return the companion clock bit shift in
+ *
+ * Some clocks don't have companion clocks.  For example, modules with
+ * only an interface clock (such as HECC) don't have a companion
+ * clock.  Right now, this code relies on the hardware exporting a bit
+ * in the correct companion register that indicates that the
+ * nonexistent 'companion clock' is active.  Future patches will
+ * associate this type of code with per-module data structures to
+ * avoid this issue, and remove the casts.  No return value.
+ */
+void am35xx_clk_find_companion(struct clk *clk, void __iomem **other_reg,
+                                          u8 *other_bit)
+{
+       *other_reg = (__force void __iomem *)(clk->enable_reg);
+       if (clk->enable_bit & AM35XX_IPSS_ICK_MASK)
+               *other_bit = clk->enable_bit + AM35XX_IPSS_ICK_FCK_OFFSET;
+       else
+               *other_bit = clk->enable_bit - AM35XX_IPSS_ICK_FCK_OFFSET;
+}
+
+const struct clkops clkops_am35xx_ipss_module_wait = {
+       .enable         = omap2_dflt_clk_enable,
+       .disable        = omap2_dflt_clk_disable,
+       .find_idlest    = am35xx_clk_find_idlest,
+       .find_companion = am35xx_clk_find_companion,
+};
+
+/**
+ * am35xx_clk_ipss_find_idlest - return CM_IDLEST info for IPSS
+ * @clk: struct clk * being enabled
+ * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
+ * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
+ * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
+ *
+ * The IPSS target CM_IDLEST bit is at a different shift from the
+ * CM_{I,F}CLKEN bit.  Pass back the correct info via @idlest_reg
+ * and @idlest_bit.  No return value.
+ */
+static void am35xx_clk_ipss_find_idlest(struct clk *clk,
+                                               void __iomem **idlest_reg,
+                                               u8 *idlest_bit,
+                                               u8 *idlest_val)
+{
+       u32 r;
+
+       r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
+       *idlest_reg = (__force void __iomem *)r;
+       *idlest_bit = AM35XX_ST_IPSS_SHIFT;
+       *idlest_val = OMAP34XX_CM_IDLEST_VAL;
+}
+
+const struct clkops clkops_am35xx_ipss_wait = {
+       .enable     = omap2_dflt_clk_enable,
+       .disable    = omap2_dflt_clk_disable,
+       .find_idlest    = am35xx_clk_ipss_find_idlest,
+       .find_companion = omap2_clk_dflt_find_companion,
+};
+
 int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate)
 {
        /*
diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h
index 9a2c07e..00d06e9 100644
--- a/arch/arm/mach-omap2/clock34xx.h
+++ b/arch/arm/mach-omap2/clock34xx.h
@@ -21,4 +21,8 @@ extern const struct clkops clkops_omap3430es2_hsotgusb_wait;
 extern const struct clkops clkops_omap3430es2_dss_usbhost_wait;
 extern const struct clkops clkops_noncore_dpll_ops;
 
+/* AM35xx-specific clkops */
+extern const struct clkops clkops_am35xx_ipss_module_wait;
+extern const struct clkops clkops_am35xx_ipss_wait;
+
 #endif
diff --git a/arch/arm/mach-omap2/clock34xx_data.c 
b/arch/arm/mach-omap2/clock34xx_data.c
index f5ef08d..2ac1721 100644
--- a/arch/arm/mach-omap2/clock34xx_data.c
+++ b/arch/arm/mach-omap2/clock34xx_data.c
@@ -2987,6 +2987,112 @@ static struct clk wdt1_fck = {
        .recalc         = &followparent_recalc,
 };
 
+/* Clocks for AM35XX */
+static struct clk ipss_ick = {
+       .name       = "ipss_ick",
+       .ops        = &clkops_am35xx_ipss_wait,
+       .parent     = &core_l3_ick,
+       .clkdm_name = "core_l3_clkdm",
+       .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+       .enable_bit = AM35XX_EN_IPSS_SHIFT,
+       .recalc     = &followparent_recalc,
+};
+
+static struct clk emac_ick = {
+       .name       = "emac_ick",
+       .ops        = &clkops_am35xx_ipss_module_wait,
+       .parent     = &ipss_ick,
+       .clkdm_name = "core_l3_clkdm",
+       .enable_reg = OMAP343X_CTRL_REGADDR(AM35XX_CONTROL_IPSS_CLK_CTRL),
+       .enable_bit = AM35XX_CPGMAC_VBUSP_CLK_SHIFT,
+       .recalc     = &followparent_recalc,
+};
+
+static struct clk rmii_ck = {
+       .name       = "rmii_ck",
+       .ops        = &clkops_null,
+       .flags      = RATE_FIXED,
+       .rate       = 50000000,
+};
+
+static struct clk emac_fck = {
+       .name       = "emac_fck",
+       .ops        = &clkops_omap2_dflt,
+       .parent     = &rmii_ck,
+       .enable_reg = OMAP343X_CTRL_REGADDR(AM35XX_CONTROL_IPSS_CLK_CTRL),
+       .enable_bit = AM35XX_CPGMAC_FCLK_SHIFT,
+       .recalc     = &followparent_recalc,
+};
+
+static struct clk hsotgusb_ick_am35xx = {
+       .name       = "hsotgusb_ick",
+       .ops        = &clkops_am35xx_ipss_module_wait,
+       .parent     = &ipss_ick,
+       .clkdm_name = "core_l3_clkdm",
+       .enable_reg = OMAP343X_CTRL_REGADDR(AM35XX_CONTROL_IPSS_CLK_CTRL),
+       .enable_bit = AM35XX_USBOTG_VBUSP_CLK_SHIFT,
+       .recalc     = &followparent_recalc,
+};
+
+static struct clk hsotgusb_fck_am35xx = {
+       .name       = "hsotgusb_fck",
+       .ops        = &clkops_omap2_dflt,
+       .parent     = &sys_ck,
+       .clkdm_name = "core_l3_clkdm",
+       .enable_reg = OMAP343X_CTRL_REGADDR(AM35XX_CONTROL_IPSS_CLK_CTRL),
+       .enable_bit = AM35XX_USBOTG_FCLK_SHIFT,
+       .recalc     = &followparent_recalc,
+};
+
+static struct clk hecc_ck = {
+       .name       = "hecc_ck",
+       .ops        = &clkops_am35xx_ipss_module_wait,
+       .parent     = &sys_ck,
+       .clkdm_name = "core_l3_clkdm",
+       .enable_reg = OMAP343X_CTRL_REGADDR(AM35XX_CONTROL_IPSS_CLK_CTRL),
+       .enable_bit = AM35XX_HECC_VBUSP_CLK_SHIFT,
+       .recalc     = &followparent_recalc,
+};
+
+static struct clk vpfe_ick = {
+       .name       = "vpfe_ick",
+       .ops        = &clkops_am35xx_ipss_module_wait,
+       .parent     = &ipss_ick,
+       .clkdm_name = "core_l3_clkdm",
+       .enable_reg = OMAP343X_CTRL_REGADDR(AM35XX_CONTROL_IPSS_CLK_CTRL),
+       .enable_bit = AM35XX_VPFE_VBUSP_CLK_SHIFT,
+       .recalc     = &followparent_recalc,
+};
+
+static struct clk pclk_ck = {
+       .name       = "pclk_ck",
+       .ops        = &clkops_null,
+       .flags      = RATE_FIXED,
+       .rate       = 27000000,
+};
+static struct clk vpfe_fck = {
+       .name       = "vpfe_fck",
+       .ops        = &clkops_omap2_dflt,
+       .parent     = &pclk_ck,
+       .enable_reg = OMAP343X_CTRL_REGADDR(AM35XX_CONTROL_IPSS_CLK_CTRL),
+       .enable_bit = AM35XX_VPFE_FCLK_SHIFT,
+       .recalc     = &followparent_recalc,
+};
+
+/*
+ * The UART1/2 functional clock acts as the functional
+ * clock for UART4. No separate fclk control available.
+ */
+static struct clk uart4_ick_am35xx = {
+       .name       = "uart4_ick",
+       .ops        = &clkops_omap2_dflt_wait,
+       .parent     = &core_l4_ick,
+       .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+       .enable_bit = AM35XX_EN_UART4_SHIFT,
+       .clkdm_name = "core_l4_clkdm",
+       .recalc     = &followparent_recalc,
+};
+
 
 /*
  * clkdev
@@ -3213,6 +3319,17 @@ static struct omap_clk omap3xxx_clks[] = {
        CLK(NULL,       "secure_32k_fck", &secure_32k_fck, CK_3XXX),
        CLK(NULL,       "gpt12_fck",    &gpt12_fck,     CK_3XXX),
        CLK(NULL,       "wdt1_fck",     &wdt1_fck,      CK_3XXX),
+       CLK(NULL,       "ipss_ick",     &ipss_ick,      CK_AM35XX),
+       CLK(NULL,       "rmii_ck",      &rmii_ck,       CK_AM35XX),
+       CLK(NULL,       "pclk_ck",      &pclk_ck,       CK_AM35XX),
+       CLK("davinci_emac",     "ick",          &emac_ick,      CK_AM35XX),
+       CLK("davinci_emac",     "fck",          &emac_fck,      CK_AM35XX),
+       CLK("vpfe-capture",     "master",       &vpfe_ick,      CK_AM35XX),
+       CLK("vpfe-capture",     "slave",        &vpfe_fck,      CK_AM35XX),
+       CLK("musb_hdrc",        "ick",          &hsotgusb_ick_am35xx,   
CK_AM35XX),
+       CLK("musb_hdrc",        "fck",          &hsotgusb_fck_am35xx,   
CK_AM35XX),
+       CLK(NULL,       "hecc_ck",      &hecc_ck,       CK_AM35XX),
+       CLK(NULL,       "uart4_ick",    &uart4_ick_am35xx,      CK_AM35XX),
 };
 
 
diff --git a/arch/arm/mach-omap2/cm-regbits-34xx.h 
b/arch/arm/mach-omap2/cm-regbits-34xx.h
index 6923deb..4ff0e24 100644
--- a/arch/arm/mach-omap2/cm-regbits-34xx.h
+++ b/arch/arm/mach-omap2/cm-regbits-34xx.h
@@ -168,6 +168,12 @@
 #define OMAP3430_EN_SDRC                               (1 << 1)
 #define OMAP3430_EN_SDRC_SHIFT                         1
 
+/* AM35XX specific CM_ICLKEN1_CORE bits */
+#define AM35XX_EN_IPSS                                 (1 << 4)
+#define AM35XX_EN_IPSS_SHIFT                           4
+#define AM35XX_EN_UART4                                (1 << 23)
+#define AM35XX_EN_UART4_SHIFT                          23
+
 /* CM_ICLKEN2_CORE */
 #define OMAP3430_EN_PKA                                        (1 << 4)
 #define OMAP3430_EN_PKA_SHIFT                          4
@@ -220,6 +226,10 @@
 #define OMAP3430_ST_SSI_STDBY_SHIFT                    0
 #define OMAP3430_ST_SSI_STDBY_MASK                     (1 << 0)
 
+/* AM35xx specific CM_IDLEST1_CORE bits */
+#define AM35XX_ST_IPSS_SHIFT                           5
+#define AM35XX_ST_IPSS_MASK                            (1 << 5)
+
 /* CM_IDLEST2_CORE */
 #define OMAP3430_ST_PKA_SHIFT                          4
 #define OMAP3430_ST_PKA_MASK                           (1 << 4)
-- 
1.6.2.4

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to