linux/arch/sh/kernel/cpu/sh4a/clock-sh7763.c
<<
>>
Prefs
   1/*
   2 * arch/sh/kernel/cpu/sh4a/clock-sh7763.c
   3 *
   4 * SH7763 support for the clock framework
   5 *
   6 *  Copyright (C) 2005  Paul Mundt
   7 *  Copyright (C) 2007  Yoshihiro Shimoda
   8 *
   9 * This file is subject to the terms and conditions of the GNU General Public
  10 * License.  See the file "COPYING" in the main directory of this archive
  11 * for more details.
  12 */
  13#include <linux/init.h>
  14#include <linux/kernel.h>
  15#include <linux/io.h>
  16#include <linux/clkdev.h>
  17#include <asm/clock.h>
  18#include <asm/freq.h>
  19#include <asm/io.h>
  20
  21static int bfc_divisors[] = { 1, 1, 1, 8, 1, 1, 1, 1 };
  22static int p0fc_divisors[] = { 1, 1, 1, 8, 1, 1, 1, 1 };
  23static int cfc_divisors[] = { 1, 1, 4, 1, 1, 1, 1, 1 };
  24
  25static void master_clk_init(struct clk *clk)
  26{
  27        clk->rate *= p0fc_divisors[(__raw_readl(FRQCR) >> 4) & 0x07];
  28}
  29
  30static struct sh_clk_ops sh7763_master_clk_ops = {
  31        .init           = master_clk_init,
  32};
  33
  34static unsigned long module_clk_recalc(struct clk *clk)
  35{
  36        int idx = ((__raw_readl(FRQCR) >> 4) & 0x07);
  37        return clk->parent->rate / p0fc_divisors[idx];
  38}
  39
  40static struct sh_clk_ops sh7763_module_clk_ops = {
  41        .recalc         = module_clk_recalc,
  42};
  43
  44static unsigned long bus_clk_recalc(struct clk *clk)
  45{
  46        int idx = ((__raw_readl(FRQCR) >> 16) & 0x07);
  47        return clk->parent->rate / bfc_divisors[idx];
  48}
  49
  50static struct sh_clk_ops sh7763_bus_clk_ops = {
  51        .recalc         = bus_clk_recalc,
  52};
  53
  54static struct sh_clk_ops sh7763_cpu_clk_ops = {
  55        .recalc         = followparent_recalc,
  56};
  57
  58static struct sh_clk_ops *sh7763_clk_ops[] = {
  59        &sh7763_master_clk_ops,
  60        &sh7763_module_clk_ops,
  61        &sh7763_bus_clk_ops,
  62        &sh7763_cpu_clk_ops,
  63};
  64
  65void __init arch_init_clk_ops(struct sh_clk_ops **ops, int idx)
  66{
  67        if (idx < ARRAY_SIZE(sh7763_clk_ops))
  68                *ops = sh7763_clk_ops[idx];
  69}
  70
  71static unsigned long shyway_clk_recalc(struct clk *clk)
  72{
  73        int idx = ((__raw_readl(FRQCR) >> 20) & 0x07);
  74        return clk->parent->rate / cfc_divisors[idx];
  75}
  76
  77static struct sh_clk_ops sh7763_shyway_clk_ops = {
  78        .recalc         = shyway_clk_recalc,
  79};
  80
  81static struct clk sh7763_shyway_clk = {
  82        .flags          = CLK_ENABLE_ON_INIT,
  83        .ops            = &sh7763_shyway_clk_ops,
  84};
  85
  86/*
  87 * Additional SH7763-specific on-chip clocks that aren't already part of the
  88 * clock framework
  89 */
  90static struct clk *sh7763_onchip_clocks[] = {
  91        &sh7763_shyway_clk,
  92};
  93
  94static struct clk_lookup lookups[] = {
  95        /* main clocks */
  96        CLKDEV_CON_ID("shyway_clk", &sh7763_shyway_clk),
  97};
  98
  99int __init arch_clk_init(void)
 100{
 101        struct clk *clk;
 102        int i, ret = 0;
 103
 104        cpg_clk_init();
 105
 106        clk = clk_get(NULL, "master_clk");
 107        for (i = 0; i < ARRAY_SIZE(sh7763_onchip_clocks); i++) {
 108                struct clk *clkp = sh7763_onchip_clocks[i];
 109
 110                clkp->parent = clk;
 111                ret |= clk_register(clkp);
 112        }
 113
 114        clk_put(clk);
 115
 116        clkdev_add_table(lookups, ARRAY_SIZE(lookups));
 117
 118        return ret;
 119}
 120