Skip to content

Commit

Permalink
[ARM] S3C24XX: Split DCLK/CLKOUT definitions out of clock.c
Browse files Browse the repository at this point in the history
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
Show file tree
Hide file tree
Showing 6 changed files with 204 additions and 171 deletions.
2 changes: 2 additions & 0 deletions arch/arm/mach-s3c2410/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ config ARCH_BAST
select PM_SIMTEC if PM
select SIMTEC_NOR
select MACH_BAST_IDE
select S3C24XX_DCLK
select ISA
help
Say Y here if you are using the Simtec Electronics EB2410ITX
Expand Down Expand Up @@ -117,6 +118,7 @@ config MACH_TCT_HAMMER
config MACH_VR1000
bool "Thorcom VR1000"
select PM_SIMTEC if PM
select S3C24XX_DCLK
select SIMTEC_NOR
select MACH_BAST_IDE
select CPU_S3C2410
Expand Down
2 changes: 2 additions & 0 deletions arch/arm/mach-s3c2440/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ menu "S3C2440 Machines"
config MACH_ANUBIS
bool "Simtec Electronics ANUBIS"
select CPU_S3C2440
select S3C24XX_DCLK
select PM_SIMTEC if PM
select HAVE_PATA_PLATFORM
help
Expand All @@ -38,6 +39,7 @@ config MACH_ANUBIS
config MACH_OSIRIS
bool "Simtec IM2440D20 (OSIRIS) module"
select CPU_S3C2440
select S3C24XX_DCLK
select PM_SIMTEC if PM
help
Say Y here if you are using the Simtec IM2440D20 module, also
Expand Down
5 changes: 5 additions & 0 deletions arch/arm/plat-s3c24xx/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ config S3C2410_CLOCK
Clock code for the S3C2410, and similar processors which
is currently includes the S3C2410, S3C2440, S3C2442.

config S3C24XX_DCLK
bool
help
Clock code for supporting DCLK/CLKOUT on S3C24XX architectures

config CPU_S3C244X
bool
depends on ARCH_S3C2410 && (CPU_S3C2440 || CPU_S3C2442)
Expand Down
1 change: 1 addition & 0 deletions arch/arm/plat-s3c24xx/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ obj-y += gpiolib.o
obj-y += time.o
obj-y += clock.o
obj-y += pwm-clock.o
obj-$(CONFIG_S3C24XX_DCLK) += clock-dclk.o

# Architecture dependant builds

Expand Down
194 changes: 194 additions & 0 deletions arch/arm/plat-s3c24xx/clock-dclk.c
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,
};
Loading

0 comments on commit 93bc6b6

Please sign in to comment.