linux/arch/metag/kernel/clock.c
<<
>>
Prefs
   1/*
   2 * arch/metag/kernel/clock.c
   3 *
   4 * Copyright (C) 2012 Imagination Technologies Ltd.
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 as
   8 * published by the Free Software Foundation.
   9 */
  10
  11#include <linux/clk.h>
  12#include <linux/delay.h>
  13#include <linux/io.h>
  14#include <linux/of.h>
  15
  16#include <asm/param.h>
  17#include <asm/clock.h>
  18
  19struct meta_clock_desc _meta_clock;
  20
  21/* Default machine get_core_freq callback. */
  22static unsigned long get_core_freq_default(void)
  23{
  24#ifdef CONFIG_METAG_META21
  25        /*
  26         * Meta 2 cores divide down the core clock for the Meta timers, so we
  27         * can estimate the core clock from the divider.
  28         */
  29        return (metag_in32(EXPAND_TIMER_DIV) + 1) * 1000000;
  30#else
  31        /*
  32         * On Meta 1 we don't know the core clock, but assuming the Meta timer
  33         * is correct it can be estimated based on loops_per_jiffy.
  34         */
  35        return (loops_per_jiffy * HZ * 5) >> 1;
  36#endif
  37}
  38
  39static struct clk *clk_core;
  40
  41/* Clk based get_core_freq callback. */
  42static unsigned long get_core_freq_clk(void)
  43{
  44        return clk_get_rate(clk_core);
  45}
  46
  47/**
  48 * init_metag_core_clock() - Set up core clock from devicetree.
  49 *
  50 * Checks to see if a "core" clock is provided in the device tree, and overrides
  51 * the get_core_freq callback to use it.
  52 */
  53static void __init init_metag_core_clock(void)
  54{
  55        /*
  56         * See if a core clock is provided by the devicetree (and
  57         * registered by the init callback above).
  58         */
  59        struct device_node *node;
  60        node = of_find_compatible_node(NULL, NULL, "img,meta");
  61        if (!node) {
  62                pr_warn("%s: no compatible img,meta DT node found\n",
  63                        __func__);
  64                return;
  65        }
  66
  67        clk_core = of_clk_get_by_name(node, "core");
  68        if (IS_ERR(clk_core)) {
  69                pr_warn("%s: no core clock found in DT\n",
  70                        __func__);
  71                return;
  72        }
  73
  74        /*
  75         * Override the core frequency callback to use
  76         * this clk.
  77         */
  78        _meta_clock.get_core_freq = get_core_freq_clk;
  79}
  80
  81/**
  82 * init_metag_clocks() - Set up clocks from devicetree.
  83 *
  84 * Set up important clocks from device tree. In particular any needed for clock
  85 * sources.
  86 */
  87void __init init_metag_clocks(void)
  88{
  89        init_metag_core_clock();
  90
  91        pr_info("Core clock frequency: %lu Hz\n", get_coreclock());
  92}
  93
  94/**
  95 * setup_meta_clocks() - Early set up of the Meta clock.
  96 * @desc:       Clock descriptor usually provided by machine description
  97 *
  98 * Ensures all callbacks are valid.
  99 */
 100void __init setup_meta_clocks(struct meta_clock_desc *desc)
 101{
 102        /* copy callbacks */
 103        if (desc)
 104                _meta_clock = *desc;
 105
 106        /* set fallback functions */
 107        if (!_meta_clock.get_core_freq)
 108                _meta_clock.get_core_freq = get_core_freq_default;
 109}
 110
 111