-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[ARM] S3C24XX: Split DCLK/CLKOUT definitions out of clock.c
Only certain boards need these clocks, and they are not available on some CPUs (such as the S3C24A0) so remove them from arch/arm/plat-s3c24xx/clock.c and into their own file with appropriate Kconfig entries. Signed-off-by: Ben Dooks <ben-linux@fluff.org>
- Loading branch information
Ben Dooks
committed
Dec 15, 2008
1 parent
74b265d
commit 93bc6b6
Showing
6 changed files
with
204 additions
and
171 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,194 @@ | ||
/* linux/arch/arm/plat-s3c24xx/clock-dclk.c | ||
* | ||
* Copyright (c) 2004,2008 Simtec Electronics | ||
* Ben Dooks <ben@simtec.co.uk> | ||
* http://armlinux.simtec.co.uk/ | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License version 2 as | ||
* published by the Free Software Foundation. | ||
* | ||
* S3C24XX - definitions for DCLK and CLKOUT registers | ||
*/ | ||
|
||
#include <linux/kernel.h> | ||
#include <linux/errno.h> | ||
#include <linux/clk.h> | ||
#include <linux/io.h> | ||
|
||
#include <mach/regs-clock.h> | ||
#include <mach/regs-gpio.h> | ||
|
||
#include <plat/clock.h> | ||
#include <plat/cpu.h> | ||
|
||
/* clocks that could be registered by external code */ | ||
|
||
static int s3c24xx_dclk_enable(struct clk *clk, int enable) | ||
{ | ||
unsigned long dclkcon = __raw_readl(S3C24XX_DCLKCON); | ||
|
||
if (enable) | ||
dclkcon |= clk->ctrlbit; | ||
else | ||
dclkcon &= ~clk->ctrlbit; | ||
|
||
__raw_writel(dclkcon, S3C24XX_DCLKCON); | ||
|
||
return 0; | ||
} | ||
|
||
static int s3c24xx_dclk_setparent(struct clk *clk, struct clk *parent) | ||
{ | ||
unsigned long dclkcon; | ||
unsigned int uclk; | ||
|
||
if (parent == &clk_upll) | ||
uclk = 1; | ||
else if (parent == &clk_p) | ||
uclk = 0; | ||
else | ||
return -EINVAL; | ||
|
||
clk->parent = parent; | ||
|
||
dclkcon = __raw_readl(S3C24XX_DCLKCON); | ||
|
||
if (clk->ctrlbit == S3C2410_DCLKCON_DCLK0EN) { | ||
if (uclk) | ||
dclkcon |= S3C2410_DCLKCON_DCLK0_UCLK; | ||
else | ||
dclkcon &= ~S3C2410_DCLKCON_DCLK0_UCLK; | ||
} else { | ||
if (uclk) | ||
dclkcon |= S3C2410_DCLKCON_DCLK1_UCLK; | ||
else | ||
dclkcon &= ~S3C2410_DCLKCON_DCLK1_UCLK; | ||
} | ||
|
||
__raw_writel(dclkcon, S3C24XX_DCLKCON); | ||
|
||
return 0; | ||
} | ||
static unsigned long s3c24xx_calc_div(struct clk *clk, unsigned long rate) | ||
{ | ||
unsigned long div; | ||
|
||
if ((rate == 0) || !clk->parent) | ||
return 0; | ||
|
||
div = clk_get_rate(clk->parent) / rate; | ||
if (div < 2) | ||
div = 2; | ||
else if (div > 16) | ||
div = 16; | ||
|
||
return div; | ||
} | ||
|
||
static unsigned long s3c24xx_round_dclk_rate(struct clk *clk, | ||
unsigned long rate) | ||
{ | ||
unsigned long div = s3c24xx_calc_div(clk, rate); | ||
|
||
if (div == 0) | ||
return 0; | ||
|
||
return clk_get_rate(clk->parent) / div; | ||
} | ||
|
||
static int s3c24xx_set_dclk_rate(struct clk *clk, unsigned long rate) | ||
{ | ||
unsigned long mask, data, div = s3c24xx_calc_div(clk, rate); | ||
|
||
if (div == 0) | ||
return -EINVAL; | ||
|
||
if (clk == &s3c24xx_dclk0) { | ||
mask = S3C2410_DCLKCON_DCLK0_DIV_MASK | | ||
S3C2410_DCLKCON_DCLK0_CMP_MASK; | ||
data = S3C2410_DCLKCON_DCLK0_DIV(div) | | ||
S3C2410_DCLKCON_DCLK0_CMP((div + 1) / 2); | ||
} else if (clk == &s3c24xx_dclk1) { | ||
mask = S3C2410_DCLKCON_DCLK1_DIV_MASK | | ||
S3C2410_DCLKCON_DCLK1_CMP_MASK; | ||
data = S3C2410_DCLKCON_DCLK1_DIV(div) | | ||
S3C2410_DCLKCON_DCLK1_CMP((div + 1) / 2); | ||
} else | ||
return -EINVAL; | ||
|
||
clk->rate = clk_get_rate(clk->parent) / div; | ||
__raw_writel(((__raw_readl(S3C24XX_DCLKCON) & ~mask) | data), | ||
S3C24XX_DCLKCON); | ||
return clk->rate; | ||
} | ||
static int s3c24xx_clkout_setparent(struct clk *clk, struct clk *parent) | ||
{ | ||
unsigned long mask; | ||
unsigned long source; | ||
|
||
/* calculate the MISCCR setting for the clock */ | ||
|
||
if (parent == &clk_xtal) | ||
source = S3C2410_MISCCR_CLK0_MPLL; | ||
else if (parent == &clk_upll) | ||
source = S3C2410_MISCCR_CLK0_UPLL; | ||
else if (parent == &clk_f) | ||
source = S3C2410_MISCCR_CLK0_FCLK; | ||
else if (parent == &clk_h) | ||
source = S3C2410_MISCCR_CLK0_HCLK; | ||
else if (parent == &clk_p) | ||
source = S3C2410_MISCCR_CLK0_PCLK; | ||
else if (clk == &s3c24xx_clkout0 && parent == &s3c24xx_dclk0) | ||
source = S3C2410_MISCCR_CLK0_DCLK0; | ||
else if (clk == &s3c24xx_clkout1 && parent == &s3c24xx_dclk1) | ||
source = S3C2410_MISCCR_CLK0_DCLK0; | ||
else | ||
return -EINVAL; | ||
|
||
clk->parent = parent; | ||
|
||
if (clk == &s3c24xx_clkout0) | ||
mask = S3C2410_MISCCR_CLK0_MASK; | ||
else { | ||
source <<= 4; | ||
mask = S3C2410_MISCCR_CLK1_MASK; | ||
} | ||
|
||
s3c2410_modify_misccr(mask, source); | ||
return 0; | ||
} | ||
|
||
/* external clock definitions */ | ||
|
||
struct clk s3c24xx_dclk0 = { | ||
.name = "dclk0", | ||
.id = -1, | ||
.ctrlbit = S3C2410_DCLKCON_DCLK0EN, | ||
.enable = s3c24xx_dclk_enable, | ||
.set_parent = s3c24xx_dclk_setparent, | ||
.set_rate = s3c24xx_set_dclk_rate, | ||
.round_rate = s3c24xx_round_dclk_rate, | ||
}; | ||
|
||
struct clk s3c24xx_dclk1 = { | ||
.name = "dclk1", | ||
.id = -1, | ||
.ctrlbit = S3C2410_DCLKCON_DCLK1EN, | ||
.enable = s3c24xx_dclk_enable, | ||
.set_parent = s3c24xx_dclk_setparent, | ||
.set_rate = s3c24xx_set_dclk_rate, | ||
.round_rate = s3c24xx_round_dclk_rate, | ||
}; | ||
|
||
struct clk s3c24xx_clkout0 = { | ||
.name = "clkout0", | ||
.id = -1, | ||
.set_parent = s3c24xx_clkout_setparent, | ||
}; | ||
|
||
struct clk s3c24xx_clkout1 = { | ||
.name = "clkout1", | ||
.id = -1, | ||
.set_parent = s3c24xx_clkout_setparent, | ||
}; |
Oops, something went wrong.