mirror of
https://github.com/torvalds/linux.git
synced 2024-10-31 09:11:49 +00:00
[ARM] 5578/1: ep93xx: add ep93xx-keypad clock
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>
This commit is contained in:
parent
02239f0a42
commit
701fac823e
@ -22,18 +22,6 @@
|
|||||||
#include <mach/hardware.h>
|
#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 {
|
struct clk {
|
||||||
unsigned long rate;
|
unsigned long rate;
|
||||||
int users;
|
int users;
|
||||||
@ -42,11 +30,14 @@ struct clk {
|
|||||||
u32 enable_mask;
|
u32 enable_mask;
|
||||||
|
|
||||||
unsigned long (*get_rate)(struct clk *clk);
|
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 unsigned long get_uart_rate(struct clk *clk);
|
||||||
|
|
||||||
|
static int set_keytchclk_rate(struct clk *clk, unsigned long rate);
|
||||||
|
|
||||||
|
|
||||||
static struct clk clk_uart1 = {
|
static struct clk clk_uart1 = {
|
||||||
.sw_locked = 1,
|
.sw_locked = 1,
|
||||||
@ -75,6 +66,12 @@ static struct clk clk_usb_host = {
|
|||||||
.enable_reg = EP93XX_SYSCON_PWRCNT,
|
.enable_reg = EP93XX_SYSCON_PWRCNT,
|
||||||
.enable_mask = EP93XX_SYSCON_PWRCNT_USH_EN,
|
.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 */
|
/* DMA Clocks */
|
||||||
static struct clk clk_m2p0 = {
|
static struct clk clk_m2p0 = {
|
||||||
@ -130,27 +127,28 @@ static struct clk clk_m2m1 = {
|
|||||||
{ .dev_id = dev, .con_id = con, .clk = ck }
|
{ .dev_id = dev, .con_id = con, .clk = ck }
|
||||||
|
|
||||||
static struct clk_lookup clocks[] = {
|
static struct clk_lookup clocks[] = {
|
||||||
INIT_CK("apb:uart1", NULL, &clk_uart1),
|
INIT_CK("apb:uart1", NULL, &clk_uart1),
|
||||||
INIT_CK("apb:uart2", NULL, &clk_uart2),
|
INIT_CK("apb:uart2", NULL, &clk_uart2),
|
||||||
INIT_CK("apb:uart3", NULL, &clk_uart3),
|
INIT_CK("apb:uart3", NULL, &clk_uart3),
|
||||||
INIT_CK(NULL, "pll1", &clk_pll1),
|
INIT_CK(NULL, "pll1", &clk_pll1),
|
||||||
INIT_CK(NULL, "fclk", &clk_f),
|
INIT_CK(NULL, "fclk", &clk_f),
|
||||||
INIT_CK(NULL, "hclk", &clk_h),
|
INIT_CK(NULL, "hclk", &clk_h),
|
||||||
INIT_CK(NULL, "pclk", &clk_p),
|
INIT_CK(NULL, "pclk", &clk_p),
|
||||||
INIT_CK(NULL, "pll2", &clk_pll2),
|
INIT_CK(NULL, "pll2", &clk_pll2),
|
||||||
INIT_CK("ep93xx-ohci", NULL, &clk_usb_host),
|
INIT_CK("ep93xx-ohci", NULL, &clk_usb_host),
|
||||||
INIT_CK(NULL, "m2p0", &clk_m2p0),
|
INIT_CK("ep93xx-keypad", NULL, &clk_keypad),
|
||||||
INIT_CK(NULL, "m2p1", &clk_m2p1),
|
INIT_CK(NULL, "m2p0", &clk_m2p0),
|
||||||
INIT_CK(NULL, "m2p2", &clk_m2p2),
|
INIT_CK(NULL, "m2p1", &clk_m2p1),
|
||||||
INIT_CK(NULL, "m2p3", &clk_m2p3),
|
INIT_CK(NULL, "m2p2", &clk_m2p2),
|
||||||
INIT_CK(NULL, "m2p4", &clk_m2p4),
|
INIT_CK(NULL, "m2p3", &clk_m2p3),
|
||||||
INIT_CK(NULL, "m2p5", &clk_m2p5),
|
INIT_CK(NULL, "m2p4", &clk_m2p4),
|
||||||
INIT_CK(NULL, "m2p6", &clk_m2p6),
|
INIT_CK(NULL, "m2p5", &clk_m2p5),
|
||||||
INIT_CK(NULL, "m2p7", &clk_m2p7),
|
INIT_CK(NULL, "m2p6", &clk_m2p6),
|
||||||
INIT_CK(NULL, "m2p8", &clk_m2p8),
|
INIT_CK(NULL, "m2p7", &clk_m2p7),
|
||||||
INIT_CK(NULL, "m2p9", &clk_m2p9),
|
INIT_CK(NULL, "m2p8", &clk_m2p8),
|
||||||
INIT_CK(NULL, "m2m0", &clk_m2m0),
|
INIT_CK(NULL, "m2p9", &clk_m2p9),
|
||||||
INIT_CK(NULL, "m2m1", &clk_m2m1),
|
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);
|
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 fclk_divisors[] = { 1, 2, 4, 8, 16, 1, 1, 1 };
|
||||||
static char hclk_divisors[] = { 1, 2, 4, 5, 6, 8, 16, 32 };
|
static char hclk_divisors[] = { 1, 2, 4, 5, 6, 8, 16, 32 };
|
||||||
|
@ -12,4 +12,18 @@
|
|||||||
|
|
||||||
#include "ts72xx.h"
|
#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
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user