alistair23-linux/arch/metag/kernel/clock.c
James Hogan cf07053214 metag: log core and timer frequencies from arch code
Log core clock and Meta timer frequencies during init in architecture
generic code, removing the need for equivalent log messages in SoC
specific code.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: John Stultz <john.stultz@linaro.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
2013-06-13 12:55:27 +01:00

111 lines
2.6 KiB
C

/*
* arch/metag/kernel/clock.c
*
* Copyright (C) 2012 Imagination Technologies Ltd.
*
* 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.
*/
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/of.h>
#include <asm/param.h>
#include <asm/clock.h>
struct meta_clock_desc _meta_clock;
/* Default machine get_core_freq callback. */
static unsigned long get_core_freq_default(void)
{
#ifdef CONFIG_METAG_META21
/*
* Meta 2 cores divide down the core clock for the Meta timers, so we
* can estimate the core clock from the divider.
*/
return (metag_in32(EXPAND_TIMER_DIV) + 1) * 1000000;
#else
/*
* On Meta 1 we don't know the core clock, but assuming the Meta timer
* is correct it can be estimated based on loops_per_jiffy.
*/
return (loops_per_jiffy * HZ * 5) >> 1;
#endif
}
static struct clk *clk_core;
/* Clk based get_core_freq callback. */
static unsigned long get_core_freq_clk(void)
{
return clk_get_rate(clk_core);
}
/**
* init_metag_core_clock() - Set up core clock from devicetree.
*
* Checks to see if a "core" clock is provided in the device tree, and overrides
* the get_core_freq callback to use it.
*/
static void __init init_metag_core_clock(void)
{
/*
* See if a core clock is provided by the devicetree (and
* registered by the init callback above).
*/
struct device_node *node;
node = of_find_compatible_node(NULL, NULL, "img,meta");
if (!node) {
pr_warn("%s: no compatible img,meta DT node found\n",
__func__);
return;
}
clk_core = of_clk_get_by_name(node, "core");
if (IS_ERR(clk_core)) {
pr_warn("%s: no core clock found in DT\n",
__func__);
return;
}
/*
* Override the core frequency callback to use
* this clk.
*/
_meta_clock.get_core_freq = get_core_freq_clk;
}
/**
* init_metag_clocks() - Set up clocks from devicetree.
*
* Set up important clocks from device tree. In particular any needed for clock
* sources.
*/
void __init init_metag_clocks(void)
{
init_metag_core_clock();
pr_info("Core clock frequency: %lu Hz\n", get_coreclock());
}
/**
* setup_meta_clocks() - Early set up of the Meta clock.
* @desc: Clock descriptor usually provided by machine description
*
* Ensures all callbacks are valid.
*/
void __init setup_meta_clocks(struct meta_clock_desc *desc)
{
/* copy callbacks */
if (desc)
_meta_clock = *desc;
/* set fallback functions */
if (!_meta_clock.get_core_freq)
_meta_clock.get_core_freq = get_core_freq_default;
}