[ARM] 5578/1: ep93xx: add ep93xx-keypad clock
authorHartley Sweeten <hartleys@visionengravers.com>
Tue, 30 Jun 2009 22:06:43 +0000 (23:06 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Thu, 9 Jul 2009 15:10:51 +0000 (16:10 +0100)
Add clkdev support for the ep93xx_keypad driver.

A matrix keypad driver for the ep93xx just got merged via the
input subsystem group.  For this driver to work the keypad clock
needs to be added to the ep93xx clkdev support.  In order to
accomplish this the following changes are implemented:

  1) Move the EP93XX_EXT_*_RATE defines to mach/include/hardware.h.
  2) Add EP93XX_KEYTCHCLK_DIV{4/16} for the keypad driver.
  3) Add support for programmable clocks (set_rate() callback).
  4) Add clk_keypad for the keypad driver.
  5) tab indent the clk_lookup table for easier reading.
  6) Add the set_rate() callback to program the keypad clock.
     This callback is generalized since the ADC clock (touchscreen)
     can use the same callback.
  7) Use the ep93xx_syscon_swlocked_write() core function for updating
     the software locked register.

Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com>
Acked-by: Ryan Mallon <ryan@bluewatersys.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
arch/arm/mach-ep93xx/clock.c
arch/arm/mach-ep93xx/include/mach/hardware.h

index c7642acfd0224e9882f548358f712f2efb520f89..207e27699410eb61f1b50d393f4dcb919c163c76 100644 (file)
 #include <mach/hardware.h>
 
 
-/*
- * The EP93xx has two external crystal oscillators.  To generate the
- * required high-frequency clocks, the processor uses two phase-locked-
- * loops (PLLs) to multiply the incoming external clock signal to much
- * higher frequencies that are then divided down by programmable dividers
- * to produce the needed clocks.  The PLLs operate independently of one
- * another.
- */
-#define EP93XX_EXT_CLK_RATE    14745600
-#define EP93XX_EXT_RTC_RATE    32768
-
-
 struct clk {
        unsigned long   rate;
        int             users;
@@ -42,11 +30,14 @@ struct clk {
        u32             enable_mask;
 
        unsigned long   (*get_rate)(struct clk *clk);
+       int             (*set_rate)(struct clk *clk, unsigned long rate);
 };
 
 
 static unsigned long get_uart_rate(struct clk *clk);
 
+static int set_keytchclk_rate(struct clk *clk, unsigned long rate);
+
 
 static struct clk clk_uart1 = {
        .sw_locked      = 1,
@@ -75,6 +66,12 @@ static struct clk clk_usb_host = {
        .enable_reg     = EP93XX_SYSCON_PWRCNT,
        .enable_mask    = EP93XX_SYSCON_PWRCNT_USH_EN,
 };
+static struct clk clk_keypad = {
+       .sw_locked      = 1,
+       .enable_reg     = EP93XX_SYSCON_KEYTCHCLKDIV,
+       .enable_mask    = EP93XX_SYSCON_KEYTCHCLKDIV_KEN,
+       .set_rate       = set_keytchclk_rate,
+};
 
 /* DMA Clocks */
 static struct clk clk_m2p0 = {
@@ -130,27 +127,28 @@ static struct clk clk_m2m1 = {
        { .dev_id = dev, .con_id = con, .clk = ck }
 
 static struct clk_lookup clocks[] = {
-       INIT_CK("apb:uart1", NULL, &clk_uart1),
-       INIT_CK("apb:uart2", NULL, &clk_uart2),
-       INIT_CK("apb:uart3", NULL, &clk_uart3),
-       INIT_CK(NULL, "pll1", &clk_pll1),
-       INIT_CK(NULL, "fclk", &clk_f),
-       INIT_CK(NULL, "hclk", &clk_h),
-       INIT_CK(NULL, "pclk", &clk_p),
-       INIT_CK(NULL, "pll2", &clk_pll2),
-       INIT_CK("ep93xx-ohci", NULL, &clk_usb_host),
-       INIT_CK(NULL, "m2p0", &clk_m2p0),
-       INIT_CK(NULL, "m2p1", &clk_m2p1),
-       INIT_CK(NULL, "m2p2", &clk_m2p2),
-       INIT_CK(NULL, "m2p3", &clk_m2p3),
-       INIT_CK(NULL, "m2p4", &clk_m2p4),
-       INIT_CK(NULL, "m2p5", &clk_m2p5),
-       INIT_CK(NULL, "m2p6", &clk_m2p6),
-       INIT_CK(NULL, "m2p7", &clk_m2p7),
-       INIT_CK(NULL, "m2p8", &clk_m2p8),
-       INIT_CK(NULL, "m2p9", &clk_m2p9),
-       INIT_CK(NULL, "m2m0", &clk_m2m0),
-       INIT_CK(NULL, "m2m1", &clk_m2m1),
+       INIT_CK("apb:uart1",            NULL,           &clk_uart1),
+       INIT_CK("apb:uart2",            NULL,           &clk_uart2),
+       INIT_CK("apb:uart3",            NULL,           &clk_uart3),
+       INIT_CK(NULL,                   "pll1",         &clk_pll1),
+       INIT_CK(NULL,                   "fclk",         &clk_f),
+       INIT_CK(NULL,                   "hclk",         &clk_h),
+       INIT_CK(NULL,                   "pclk",         &clk_p),
+       INIT_CK(NULL,                   "pll2",         &clk_pll2),
+       INIT_CK("ep93xx-ohci",          NULL,           &clk_usb_host),
+       INIT_CK("ep93xx-keypad",        NULL,           &clk_keypad),
+       INIT_CK(NULL,                   "m2p0",         &clk_m2p0),
+       INIT_CK(NULL,                   "m2p1",         &clk_m2p1),
+       INIT_CK(NULL,                   "m2p2",         &clk_m2p2),
+       INIT_CK(NULL,                   "m2p3",         &clk_m2p3),
+       INIT_CK(NULL,                   "m2p4",         &clk_m2p4),
+       INIT_CK(NULL,                   "m2p5",         &clk_m2p5),
+       INIT_CK(NULL,                   "m2p6",         &clk_m2p6),
+       INIT_CK(NULL,                   "m2p7",         &clk_m2p7),
+       INIT_CK(NULL,                   "m2p8",         &clk_m2p8),
+       INIT_CK(NULL,                   "m2p9",         &clk_m2p9),
+       INIT_CK(NULL,                   "m2m0",         &clk_m2m0),
+       INIT_CK(NULL,                   "m2m1",         &clk_m2m1),
 };
 
 
@@ -206,6 +204,43 @@ unsigned long clk_get_rate(struct clk *clk)
 }
 EXPORT_SYMBOL(clk_get_rate);
 
+static int set_keytchclk_rate(struct clk *clk, unsigned long rate)
+{
+       u32 val;
+       u32 div_bit;
+
+       val = __raw_readl(clk->enable_reg);
+
+       /*
+        * The Key Matrix and ADC clocks are configured using the same
+        * System Controller register.  The clock used will be either
+        * 1/4 or 1/16 the external clock rate depending on the
+        * EP93XX_SYSCON_KEYTCHCLKDIV_KDIV/EP93XX_SYSCON_KEYTCHCLKDIV_ADIV
+        * bit being set or cleared.
+        */
+       div_bit = clk->enable_mask >> 15;
+
+       if (rate == EP93XX_KEYTCHCLK_DIV4)
+               val |= div_bit;
+       else if (rate == EP93XX_KEYTCHCLK_DIV16)
+               val &= ~div_bit;
+       else
+               return -EINVAL;
+
+       ep93xx_syscon_swlocked_write(val, clk->enable_reg);
+       clk->rate = rate;
+       return 0;
+}
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+       if (clk->set_rate)
+               return clk->set_rate(clk, rate);
+
+       return -EINVAL;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
 
 static char fclk_divisors[] = { 1, 2, 4, 8, 16, 1, 1, 1 };
 static char hclk_divisors[] = { 1, 2, 4, 5, 6, 8, 16, 32 };
index 2866297310b7c9e38f80a7992921481e7140d00b..587c07bdec5b77b252966253ee5f9d876c99c9e3 100644 (file)
 
 #include "ts72xx.h"
 
+/*
+ * The EP93xx has two external crystal oscillators.  To generate the
+ * required high-frequency clocks, the processor uses two phase-locked-
+ * loops (PLLs) to multiply the incoming external clock signal to much
+ * higher frequencies that are then divided down by programmable dividers
+ * to produce the needed clocks.  The PLLs operate independently of one
+ * another.
+ */
+#define EP93XX_EXT_CLK_RATE    14745600
+#define EP93XX_EXT_RTC_RATE    32768
+
+#define EP93XX_KEYTCHCLK_DIV4  (EP93XX_EXT_CLK_RATE / 4)
+#define EP93XX_KEYTCHCLK_DIV16 (EP93XX_EXT_CLK_RATE / 16)
+
 #endif
This page took 0.031377 seconds and 5 git commands to generate.