linux/arch/sh/kernel/cpu/sh2a/clock-sh7269.c
<<
>>
Prefs
   1/*
   2 * arch/sh/kernel/cpu/sh2a/clock-sh7269.c
   3 *
   4 * SH7269 clock framework support
   5 *
   6 * Copyright (C) 2012  Phil Edworthy
   7 *
   8 * This file is subject to the terms and conditions of the GNU General Public
   9 * License.  See the file "COPYING" in the main directory of this archive
  10 * for more details.
  11 */
  12#include <linux/init.h>
  13#include <linux/kernel.h>
  14#include <linux/io.h>
  15#include <linux/clkdev.h>
  16#include <asm/clock.h>
  17
  18/* SH7269 registers */
  19#define FRQCR           0xfffe0010
  20#define STBCR3          0xfffe0408
  21#define STBCR4          0xfffe040c
  22#define STBCR5          0xfffe0410
  23#define STBCR6          0xfffe0414
  24#define STBCR7          0xfffe0418
  25
  26#define PLL_RATE 20
  27
  28/* Fixed 32 KHz root clock for RTC */
  29static struct clk r_clk = {
  30        .rate           = 32768,
  31};
  32
  33/*
  34 * Default rate for the root input clock, reset this with clk_set_rate()
  35 * from the platform code.
  36 */
  37static struct clk extal_clk = {
  38        .rate           = 13340000,
  39};
  40
  41static unsigned long pll_recalc(struct clk *clk)
  42{
  43        return clk->parent->rate * PLL_RATE;
  44}
  45
  46static struct sh_clk_ops pll_clk_ops = {
  47        .recalc         = pll_recalc,
  48};
  49
  50static struct clk pll_clk = {
  51        .ops            = &pll_clk_ops,
  52        .parent         = &extal_clk,
  53        .flags          = CLK_ENABLE_ON_INIT,
  54};
  55
  56static unsigned long peripheral0_recalc(struct clk *clk)
  57{
  58        return clk->parent->rate / 8;
  59}
  60
  61static struct sh_clk_ops peripheral0_clk_ops = {
  62        .recalc         = peripheral0_recalc,
  63};
  64
  65static struct clk peripheral0_clk = {
  66        .ops            = &peripheral0_clk_ops,
  67        .parent         = &pll_clk,
  68        .flags          = CLK_ENABLE_ON_INIT,
  69};
  70
  71static unsigned long peripheral1_recalc(struct clk *clk)
  72{
  73        return clk->parent->rate / 4;
  74}
  75
  76static struct sh_clk_ops peripheral1_clk_ops = {
  77        .recalc         = peripheral1_recalc,
  78};
  79
  80static struct clk peripheral1_clk = {
  81        .ops            = &peripheral1_clk_ops,
  82        .parent         = &pll_clk,
  83        .flags          = CLK_ENABLE_ON_INIT,
  84};
  85
  86struct clk *main_clks[] = {
  87        &r_clk,
  88        &extal_clk,
  89        &pll_clk,
  90        &peripheral0_clk,
  91        &peripheral1_clk,
  92};
  93
  94static int div2[] = { 1, 2, 0, 4 };
  95
  96static struct clk_div_mult_table div4_div_mult_table = {
  97        .divisors = div2,
  98        .nr_divisors = ARRAY_SIZE(div2),
  99};
 100
 101static struct clk_div4_table div4_table = {
 102        .div_mult_table = &div4_div_mult_table,
 103};
 104
 105enum { DIV4_I, DIV4_B,
 106       DIV4_NR };
 107
 108#define DIV4(_reg, _bit, _mask, _flags) \
 109  SH_CLK_DIV4(&pll_clk, _reg, _bit, _mask, _flags)
 110
 111/* The mask field specifies the div2 entries that are valid */
 112struct clk div4_clks[DIV4_NR] = {
 113        [DIV4_I]  = DIV4(FRQCR, 8, 0xB, CLK_ENABLE_REG_16BIT
 114                                        | CLK_ENABLE_ON_INIT),
 115        [DIV4_B]  = DIV4(FRQCR, 4, 0xA, CLK_ENABLE_REG_16BIT
 116                                        | CLK_ENABLE_ON_INIT),
 117};
 118
 119enum { MSTP72,
 120        MSTP60,
 121        MSTP47, MSTP46, MSTP45, MSTP44, MSTP43, MSTP42, MSTP41, MSTP40,
 122        MSTP35, MSTP32, MSTP30,
 123        MSTP_NR };
 124
 125static struct clk mstp_clks[MSTP_NR] = {
 126        [MSTP72] = SH_CLK_MSTP8(&peripheral0_clk, STBCR7, 2, 0), /* CMT */
 127        [MSTP60] = SH_CLK_MSTP8(&peripheral1_clk, STBCR6, 0, 0), /* USB */
 128        [MSTP47] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 7, 0), /* SCIF0 */
 129        [MSTP46] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 6, 0), /* SCIF1 */
 130        [MSTP45] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 5, 0), /* SCIF2 */
 131        [MSTP44] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 4, 0), /* SCIF3 */
 132        [MSTP43] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 3, 0), /* SCIF4 */
 133        [MSTP42] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 2, 0), /* SCIF5 */
 134        [MSTP41] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 1, 0), /* SCIF6 */
 135        [MSTP40] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 0, 0), /* SCIF7 */
 136        [MSTP35] = SH_CLK_MSTP8(&peripheral0_clk, STBCR3, 5, 0), /* MTU2 */
 137        [MSTP32] = SH_CLK_MSTP8(&peripheral1_clk, STBCR3, 2, 0), /* ADC */
 138        [MSTP30] = SH_CLK_MSTP8(&r_clk, STBCR3, 0, 0), /* RTC */
 139};
 140
 141static struct clk_lookup lookups[] = {
 142        /* main clocks */
 143        CLKDEV_CON_ID("rclk", &r_clk),
 144        CLKDEV_CON_ID("extal", &extal_clk),
 145        CLKDEV_CON_ID("pll_clk", &pll_clk),
 146        CLKDEV_CON_ID("peripheral_clk", &peripheral1_clk),
 147
 148        /* DIV4 clocks */
 149        CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
 150        CLKDEV_CON_ID("bus_clk", &div4_clks[DIV4_B]),
 151
 152        /* MSTP clocks */
 153        CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP47]),
 154        CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP46]),
 155        CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP45]),
 156        CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[MSTP44]),
 157        CLKDEV_ICK_ID("sci_fck", "sh-sci.4", &mstp_clks[MSTP43]),
 158        CLKDEV_ICK_ID("sci_fck", "sh-sci.5", &mstp_clks[MSTP42]),
 159        CLKDEV_ICK_ID("sci_fck", "sh-sci.6", &mstp_clks[MSTP41]),
 160        CLKDEV_ICK_ID("sci_fck", "sh-sci.7", &mstp_clks[MSTP40]),
 161        CLKDEV_ICK_ID("fck", "sh-cmt-16.0", &mstp_clks[MSTP72]),
 162        CLKDEV_CON_ID("usb0", &mstp_clks[MSTP60]),
 163        CLKDEV_ICK_ID("fck", "sh-mtu2", &mstp_clks[MSTP35]),
 164        CLKDEV_CON_ID("adc0", &mstp_clks[MSTP32]),
 165        CLKDEV_CON_ID("rtc0", &mstp_clks[MSTP30]),
 166};
 167
 168int __init arch_clk_init(void)
 169{
 170        int k, ret = 0;
 171
 172        for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
 173                ret = clk_register(main_clks[k]);
 174
 175        clkdev_add_table(lookups, ARRAY_SIZE(lookups));
 176
 177        if (!ret)
 178                ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
 179
 180        if (!ret)
 181                ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
 182
 183        return ret;
 184}
 185