Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 145173
b: refs/heads/master
c: ff05c03
h: refs/heads/master
i:
  145171: 50426a8
v: v3
  • Loading branch information
Hartley Sweeten authored and Russell King committed May 16, 2009
1 parent a20b235 commit 0abe807
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 10 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: cddb783552f51b5e39fc2db3a34d150d753758e4
refs/heads/master: ff05c0330b9880f9ccbb7fa40f2ed3b5842f5693
69 changes: 61 additions & 8 deletions trunk/arch/arm/mach-ep93xx/clock.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,50 @@
#include <asm/div64.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 {
unsigned long rate;
int users;
int sw_locked;
u32 enable_reg;
u32 enable_mask;

unsigned long (*get_rate)(struct clk *clk);
};

static struct clk clk_uart = {
.rate = 14745600,

static unsigned long get_uart_rate(struct clk *clk);


static struct clk clk_uart1 = {
.sw_locked = 1,
.enable_reg = EP93XX_SYSCON_DEVICE_CONFIG,
.enable_mask = EP93XX_SYSCON_DEVICE_CONFIG_U1EN,
.get_rate = get_uart_rate,
};
static struct clk clk_uart2 = {
.sw_locked = 1,
.enable_reg = EP93XX_SYSCON_DEVICE_CONFIG,
.enable_mask = EP93XX_SYSCON_DEVICE_CONFIG_U2EN,
.get_rate = get_uart_rate,
};
static struct clk clk_uart3 = {
.sw_locked = 1,
.enable_reg = EP93XX_SYSCON_DEVICE_CONFIG,
.enable_mask = EP93XX_SYSCON_DEVICE_CONFIG_U3EN,
.get_rate = get_uart_rate,
};
static struct clk clk_pll1;
static struct clk clk_f;
Expand Down Expand Up @@ -95,9 +130,9 @@ static struct clk clk_m2m1 = {
{ .dev_id = dev, .con_id = con, .clk = ck }

static struct clk_lookup clocks[] = {
INIT_CK("apb:uart1", NULL, &clk_uart),
INIT_CK("apb:uart2", NULL, &clk_uart),
INIT_CK("apb:uart3", NULL, &clk_uart),
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),
Expand Down Expand Up @@ -125,6 +160,8 @@ int clk_enable(struct clk *clk)
u32 value;

value = __raw_readl(clk->enable_reg);
if (clk->sw_locked)
__raw_writel(0xaa, EP93XX_SYSCON_SWLOCK);
__raw_writel(value | clk->enable_mask, clk->enable_reg);
}

Expand All @@ -138,13 +175,29 @@ void clk_disable(struct clk *clk)
u32 value;

value = __raw_readl(clk->enable_reg);
if (clk->sw_locked)
__raw_writel(0xaa, EP93XX_SYSCON_SWLOCK);
__raw_writel(value & ~clk->enable_mask, clk->enable_reg);
}
}
EXPORT_SYMBOL(clk_disable);

static unsigned long get_uart_rate(struct clk *clk)
{
u32 value;

value = __raw_readl(EP93XX_SYSCON_CLOCK_CONTROL);
if (value & EP93XX_SYSCON_CLOCK_UARTBAUD)
return EP93XX_EXT_CLK_RATE;
else
return EP93XX_EXT_CLK_RATE / 2;
}

unsigned long clk_get_rate(struct clk *clk)
{
if (clk->get_rate)
return clk->get_rate(clk);

return clk->rate;
}
EXPORT_SYMBOL(clk_get_rate);
Expand All @@ -162,7 +215,7 @@ static unsigned long calc_pll_rate(u32 config_word)
unsigned long long rate;
int i;

rate = 14745600;
rate = EP93XX_EXT_CLK_RATE;
rate *= ((config_word >> 11) & 0x1f) + 1; /* X1FBD */
rate *= ((config_word >> 5) & 0x3f) + 1; /* X2FBD */
do_div(rate, (config_word & 0x1f) + 1); /* X2IPD */
Expand Down Expand Up @@ -195,7 +248,7 @@ static int __init ep93xx_clock_init(void)

value = __raw_readl(EP93XX_SYSCON_CLOCK_SET1);
if (!(value & 0x00800000)) { /* PLL1 bypassed? */
clk_pll1.rate = 14745600;
clk_pll1.rate = EP93XX_EXT_CLK_RATE;
} else {
clk_pll1.rate = calc_pll_rate(value);
}
Expand All @@ -206,7 +259,7 @@ static int __init ep93xx_clock_init(void)

value = __raw_readl(EP93XX_SYSCON_CLOCK_SET2);
if (!(value & 0x00080000)) { /* PLL2 bypassed? */
clk_pll2.rate = 14745600;
clk_pll2.rate = EP93XX_EXT_CLK_RATE;
} else if (value & 0x00040000) { /* PLL2 enabled? */
clk_pll2.rate = calc_pll_rate(value);
} else {
Expand Down
5 changes: 4 additions & 1 deletion trunk/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,10 @@
#define EP93XX_SYSCON_CLOCK_SET1 EP93XX_SYSCON_REG(0x20)
#define EP93XX_SYSCON_CLOCK_SET2 EP93XX_SYSCON_REG(0x24)
#define EP93XX_SYSCON_DEVICE_CONFIG EP93XX_SYSCON_REG(0x80)
#define EP93XX_SYSCON_DEVICE_CONFIG_CRUNCH_ENABLE 0x00800000
#define EP93XX_SYSCON_DEVICE_CONFIG_U3EN (1<<24)
#define EP93XX_SYSCON_DEVICE_CONFIG_CRUNCH_ENABLE (1<<23)
#define EP93XX_SYSCON_DEVICE_CONFIG_U2EN (1<<20)
#define EP93XX_SYSCON_DEVICE_CONFIG_U1EN (1<<18)
#define EP93XX_SYSCON_SWLOCK EP93XX_SYSCON_REG(0xc0)

#define EP93XX_WATCHDOG_BASE (EP93XX_APB_VIRT_BASE + 0x00140000)
Expand Down

0 comments on commit 0abe807

Please sign in to comment.