Skip to content

Commit

Permalink
ARM: integrator: convert to common clock
Browse files Browse the repository at this point in the history
This converts the Integrator platform to use common clock
and the ICST driver. Since from this point not all ARM
reference platforms use the clock, we define
CONFIG_PLAT_VERSATILE_CLOCK and select it for all platforms
except the Integrator.

Open issue: I could not use the .init_early() field of the
machine descriptor to initialize the clocks, but had to
move them to .init_irq(), so presumably .init_early() is
so early that common clock is not up, and .init_machine()
is too late since it's needed for the clockevent/clocksource
initialization. Any suggestions on how to solve this is
very welcome.

Cc: Russell King <linux@arm.linux.org.uk>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
[mturquette@linaro.org: use 'select' instead of versatile Kconfig]
Signed-off-by: Mike Turquette <mturquette@linaro.org>
  • Loading branch information
Linus Walleij authored and Mike Turquette committed Jul 12, 2012
1 parent 91b87a4 commit a613163
Show file tree
Hide file tree
Showing 10 changed files with 131 additions and 136 deletions.
7 changes: 5 additions & 2 deletions arch/arm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -254,8 +254,8 @@ config ARCH_INTEGRATOR
bool "ARM Ltd. Integrator family"
select ARM_AMBA
select ARCH_HAS_CPUFREQ
select CLKDEV_LOOKUP
select HAVE_MACH_CLKDEV
select COMMON_CLK
select CLK_VERSATILE
select HAVE_TCM
select ICST
select GENERIC_CLOCKEVENTS
Expand All @@ -277,6 +277,7 @@ config ARCH_REALVIEW
select GENERIC_CLOCKEVENTS
select ARCH_WANT_OPTIONAL_GPIOLIB
select PLAT_VERSATILE
select PLAT_VERSATILE_CLOCK
select PLAT_VERSATILE_CLCD
select ARM_TIMER_SP804
select GPIO_PL061 if GPIOLIB
Expand All @@ -295,6 +296,7 @@ config ARCH_VERSATILE
select ARCH_WANT_OPTIONAL_GPIOLIB
select NEED_MACH_IO_H if PCI
select PLAT_VERSATILE
select PLAT_VERSATILE_CLOCK
select PLAT_VERSATILE_CLCD
select PLAT_VERSATILE_FPGA_IRQ
select ARM_TIMER_SP804
Expand All @@ -314,6 +316,7 @@ config ARCH_VEXPRESS
select ICST
select NO_IOPORT
select PLAT_VERSATILE
select PLAT_VERSATILE_CLOCK
select PLAT_VERSATILE_CLCD
help
This enables support for the ARM Ltd Versatile Express boards.
Expand Down
45 changes: 0 additions & 45 deletions arch/arm/mach-integrator/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
#include <linux/amba/bus.h>
#include <linux/amba/serial.h>
#include <linux/io.h>
#include <linux/clkdev.h>

#include <mach/hardware.h>
#include <mach/platform.h>
Expand Down Expand Up @@ -61,50 +60,6 @@ static struct amba_device *amba_devs[] __initdata = {
&kmi1_device,
};

/*
* These are fixed clocks.
*/
static struct clk clk24mhz = {
.rate = 24000000,
};

static struct clk uartclk = {
.rate = 14745600,
};

static struct clk dummy_apb_pclk;

static struct clk_lookup lookups[] = {
{ /* Bus clock */
.con_id = "apb_pclk",
.clk = &dummy_apb_pclk,
}, {
/* Integrator/AP timer frequency */
.dev_id = "ap_timer",
.clk = &clk24mhz,
}, { /* UART0 */
.dev_id = "uart0",
.clk = &uartclk,
}, { /* UART1 */
.dev_id = "uart1",
.clk = &uartclk,
}, { /* KMI0 */
.dev_id = "kmi0",
.clk = &clk24mhz,
}, { /* KMI1 */
.dev_id = "kmi1",
.clk = &clk24mhz,
}, { /* MMCI - IntegratorCP */
.dev_id = "mmci",
.clk = &uartclk,
}
};

void __init integrator_init_early(void)
{
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
}

static int __init integrator_init(void)
{
int i;
Expand Down
26 changes: 0 additions & 26 deletions arch/arm/mach-integrator/include/mach/clkdev.h

This file was deleted.

8 changes: 7 additions & 1 deletion arch/arm/mach-integrator/integrator_ap.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include <linux/io.h>
#include <linux/mtd/physmap.h>
#include <linux/clk.h>
#include <linux/platform_data/clk-integrator.h>
#include <video/vga.h>

#include <mach/hardware.h>
Expand Down Expand Up @@ -174,6 +175,7 @@ static void __init ap_init_irq(void)

fpga_irq_init(VA_IC_BASE, "SC", IRQ_PIC_START,
-1, INTEGRATOR_SC_VALID_INT, NULL);
integrator_clk_init(false);
}

#ifdef CONFIG_PM
Expand Down Expand Up @@ -440,6 +442,10 @@ static void integrator_clockevent_init(unsigned long inrate)
0xffffU);
}

void __init ap_init_early(void)
{
}

/*
* Set up timer(s).
*/
Expand Down Expand Up @@ -471,7 +477,7 @@ MACHINE_START(INTEGRATOR, "ARM-Integrator")
.reserve = integrator_reserve,
.map_io = ap_map_io,
.nr_irqs = NR_IRQS_INTEGRATOR_AP,
.init_early = integrator_init_early,
.init_early = ap_init_early,
.init_irq = ap_init_irq,
.handle_irq = fpga_handle_irq,
.timer = &ap_timer,
Expand Down
63 changes: 2 additions & 61 deletions arch/arm/mach-integrator/integrator_cp.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
#include <linux/amba/mmci.h>
#include <linux/io.h>
#include <linux/gfp.h>
#include <linux/clkdev.h>
#include <linux/mtd/physmap.h>
#include <linux/platform_data/clk-integrator.h>

#include <mach/hardware.h>
#include <mach/platform.h>
Expand Down Expand Up @@ -171,64 +171,9 @@ static void __init intcp_init_irq(void)

fpga_irq_init(INTCP_VA_SIC_BASE, "SIC", IRQ_SIC_START,
IRQ_CP_CPPLDINT, sic_mask, NULL);
integrator_clk_init(true);
}

/*
* Clock handling
*/
#define CM_LOCK (__io_address(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_LOCK_OFFSET)
#define CM_AUXOSC (__io_address(INTEGRATOR_HDR_BASE)+0x1c)

static const struct icst_params cp_auxvco_params = {
.ref = 24000000,
.vco_max = ICST525_VCO_MAX_5V,
.vco_min = ICST525_VCO_MIN,
.vd_min = 8,
.vd_max = 263,
.rd_min = 3,
.rd_max = 65,
.s2div = icst525_s2div,
.idx2s = icst525_idx2s,
};

static void cp_auxvco_set(struct clk *clk, struct icst_vco vco)
{
u32 val;

val = readl(clk->vcoreg) & ~0x7ffff;
val |= vco.v | (vco.r << 9) | (vco.s << 16);

writel(0xa05f, CM_LOCK);
writel(val, clk->vcoreg);
writel(0, CM_LOCK);
}

static const struct clk_ops cp_auxclk_ops = {
.round = icst_clk_round,
.set = icst_clk_set,
.setvco = cp_auxvco_set,
};

static struct clk cp_auxclk = {
.ops = &cp_auxclk_ops,
.params = &cp_auxvco_params,
.vcoreg = CM_AUXOSC,
};

static struct clk sp804_clk = {
.rate = 1000000,
};

static struct clk_lookup cp_lookups[] = {
{ /* CLCD */
.dev_id = "clcd",
.clk = &cp_auxclk,
}, { /* SP804 timers */
.dev_id = "sp804",
.clk = &sp804_clk,
},
};

/*
* Flash handling.
*/
Expand Down Expand Up @@ -406,10 +351,6 @@ static struct amba_device *amba_devs[] __initdata = {

static void __init intcp_init_early(void)
{
clkdev_add_table(cp_lookups, ARRAY_SIZE(cp_lookups));

integrator_init_early();

#ifdef CONFIG_PLAT_VERSATILE_SCHED_CLOCK
versatile_sched_clock_init(REFCOUNTER, 24000000);
#endif
Expand Down
3 changes: 3 additions & 0 deletions arch/arm/plat-versatile/Kconfig
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
if PLAT_VERSATILE

config PLAT_VERSATILE_CLOCK
bool

config PLAT_VERSATILE_CLCD
bool

Expand Down
2 changes: 1 addition & 1 deletion arch/arm/plat-versatile/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
obj-y := clock.o
obj-$(CONFIG_PLAT_VERSATILE_CLOCK) += clock.o
obj-$(CONFIG_PLAT_VERSATILE_CLCD) += clcd.o
obj-$(CONFIG_PLAT_VERSATILE_FPGA_IRQ) += fpga-irq.o
obj-$(CONFIG_PLAT_VERSATILE_LEDS) += leds.o
Expand Down
1 change: 1 addition & 0 deletions drivers/clk/versatile/Makefile
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
# Makefile for Versatile-specific clocks
obj-$(CONFIG_ICST) += clk-icst.o
obj-$(CONFIG_ARCH_INTEGRATOR) += clk-integrator.o
111 changes: 111 additions & 0 deletions drivers/clk/versatile/clk-integrator.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/clk-provider.h>

#include <mach/hardware.h>
#include <mach/platform.h>

#include "clk-icst.h"

/*
* Implementation of the ARM Integrator/AP and Integrator/CP clock tree.
* Inspired by portions of:
* plat-versatile/clock.c and plat-versatile/include/plat/clock.h
*/
#define CM_LOCK (__io_address(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_LOCK_OFFSET)
#define CM_AUXOSC (__io_address(INTEGRATOR_HDR_BASE)+0x1c)

/**
* cp_auxvco_get() - get ICST VCO settings for the Integrator/CP
* @vco: ICST VCO parameters to update with hardware status
*/
static struct icst_vco cp_auxvco_get(void)
{
u32 val;
struct icst_vco vco;

val = readl(CM_AUXOSC);
vco.v = val & 0x1ff;
vco.r = (val >> 9) & 0x7f;
vco.s = (val >> 16) & 03;
return vco;
}

/**
* cp_auxvco_set() - commit changes to Integrator/CP ICST VCO
* @vco: ICST VCO parameters to commit
*/
static void cp_auxvco_set(struct icst_vco vco)
{
u32 val;

val = readl(CM_AUXOSC) & ~0x7ffff;
val |= vco.v | (vco.r << 9) | (vco.s << 16);

/* This magic unlocks the CM VCO so it can be controlled */
writel(0xa05f, CM_LOCK);
writel(val, CM_AUXOSC);
/* This locks the CM again */
writel(0, CM_LOCK);
}

static const struct icst_params cp_auxvco_params = {
.ref = 24000000,
.vco_max = ICST525_VCO_MAX_5V,
.vco_min = ICST525_VCO_MIN,
.vd_min = 8,
.vd_max = 263,
.rd_min = 3,
.rd_max = 65,
.s2div = icst525_s2div,
.idx2s = icst525_idx2s,
};

static const struct clk_icst_desc __initdata cp_icst_desc = {
.params = &cp_auxvco_params,
.getvco = cp_auxvco_get,
.setvco = cp_auxvco_set,
};

/*
* integrator_clk_init() - set up the integrator clock tree
* @is_cp: pass true if it's the Integrator/CP else AP is assumed
*/
void __init integrator_clk_init(bool is_cp)
{
struct clk *clk;

/* APB clock dummy */
clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT, 0);
clk_register_clkdev(clk, "apb_pclk", NULL);

/* UART reference clock */
clk = clk_register_fixed_rate(NULL, "uartclk", NULL, CLK_IS_ROOT,
14745600);
clk_register_clkdev(clk, NULL, "uart0");
clk_register_clkdev(clk, NULL, "uart1");
if (is_cp)
clk_register_clkdev(clk, NULL, "mmci");

/* 24 MHz clock */
clk = clk_register_fixed_rate(NULL, "clk24mhz", NULL, CLK_IS_ROOT,
24000000);
clk_register_clkdev(clk, NULL, "kmi0");
clk_register_clkdev(clk, NULL, "kmi1");
if (!is_cp)
clk_register_clkdev(clk, NULL, "ap_timer");

if (!is_cp)
return;

/* 1 MHz clock */
clk = clk_register_fixed_rate(NULL, "clk1mhz", NULL, CLK_IS_ROOT,
1000000);
clk_register_clkdev(clk, NULL, "sp804");

/* ICST VCO clock used on the Integrator/CP CLCD */
clk = icst_clk_register(NULL, &cp_icst_desc);
clk_register_clkdev(clk, NULL, "clcd");
}
1 change: 1 addition & 0 deletions include/linux/platform_data/clk-integrator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
void integrator_clk_init(bool is_cp);

0 comments on commit a613163

Please sign in to comment.