root/arch/sh/kernel/cpu/sh2a/clock-sh7264.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pll_recalc
  2. arch_clk_init

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * arch/sh/kernel/cpu/sh2a/clock-sh7264.c
   4  *
   5  * SH7264 clock framework support
   6  *
   7  * Copyright (C) 2012  Phil Edworthy
   8  */
   9 #include <linux/init.h>
  10 #include <linux/kernel.h>
  11 #include <linux/io.h>
  12 #include <linux/clkdev.h>
  13 #include <asm/clock.h>
  14 
  15 /* SH7264 registers */
  16 #define FRQCR           0xfffe0010
  17 #define STBCR3          0xfffe0408
  18 #define STBCR4          0xfffe040c
  19 #define STBCR5          0xfffe0410
  20 #define STBCR6          0xfffe0414
  21 #define STBCR7          0xfffe0418
  22 #define STBCR8          0xfffe041c
  23 
  24 static const unsigned int pll1rate[] = {8, 12};
  25 
  26 static unsigned int pll1_div;
  27 
  28 /* Fixed 32 KHz root clock for RTC */
  29 static 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  */
  37 static struct clk extal_clk = {
  38         .rate           = 18000000,
  39 };
  40 
  41 static unsigned long pll_recalc(struct clk *clk)
  42 {
  43         unsigned long rate = clk->parent->rate / pll1_div;
  44         return rate * pll1rate[(__raw_readw(FRQCR) >> 8) & 1];
  45 }
  46 
  47 static struct sh_clk_ops pll_clk_ops = {
  48         .recalc         = pll_recalc,
  49 };
  50 
  51 static struct clk pll_clk = {
  52         .ops            = &pll_clk_ops,
  53         .parent         = &extal_clk,
  54         .flags          = CLK_ENABLE_ON_INIT,
  55 };
  56 
  57 struct clk *main_clks[] = {
  58         &r_clk,
  59         &extal_clk,
  60         &pll_clk,
  61 };
  62 
  63 static int div2[] = { 1, 2, 3, 4, 6, 8, 12 };
  64 
  65 static struct clk_div_mult_table div4_div_mult_table = {
  66         .divisors = div2,
  67         .nr_divisors = ARRAY_SIZE(div2),
  68 };
  69 
  70 static struct clk_div4_table div4_table = {
  71         .div_mult_table = &div4_div_mult_table,
  72 };
  73 
  74 enum { DIV4_I, DIV4_P,
  75        DIV4_NR };
  76 
  77 #define DIV4(_reg, _bit, _mask, _flags) \
  78   SH_CLK_DIV4(&pll_clk, _reg, _bit, _mask, _flags)
  79 
  80 /* The mask field specifies the div2 entries that are valid */
  81 struct clk div4_clks[DIV4_NR] = {
  82         [DIV4_I] = DIV4(FRQCR, 4, 0x7,  CLK_ENABLE_REG_16BIT
  83                                         | CLK_ENABLE_ON_INIT),
  84         [DIV4_P] = DIV4(FRQCR, 0, 0x78, CLK_ENABLE_REG_16BIT),
  85 };
  86 
  87 enum {  MSTP77, MSTP74, MSTP72,
  88         MSTP60,
  89         MSTP35, MSTP34, MSTP33, MSTP32, MSTP30,
  90         MSTP_NR };
  91 
  92 static struct clk mstp_clks[MSTP_NR] = {
  93         [MSTP77] = SH_CLK_MSTP8(&div4_clks[DIV4_P], STBCR7, 7, 0), /* SCIF */
  94         [MSTP74] = SH_CLK_MSTP8(&div4_clks[DIV4_P], STBCR7, 4, 0), /* VDC */
  95         [MSTP72] = SH_CLK_MSTP8(&div4_clks[DIV4_P], STBCR7, 2, 0), /* CMT */
  96         [MSTP60] = SH_CLK_MSTP8(&div4_clks[DIV4_P], STBCR6, 0, 0), /* USB */
  97         [MSTP35] = SH_CLK_MSTP8(&div4_clks[DIV4_P], STBCR3, 6, 0), /* MTU2 */
  98         [MSTP34] = SH_CLK_MSTP8(&div4_clks[DIV4_P], STBCR3, 4, 0), /* SDHI0 */
  99         [MSTP33] = SH_CLK_MSTP8(&div4_clks[DIV4_P], STBCR3, 3, 0), /* SDHI1 */
 100         [MSTP32] = SH_CLK_MSTP8(&div4_clks[DIV4_P], STBCR3, 2, 0), /* ADC */
 101         [MSTP30] = SH_CLK_MSTP8(&r_clk, STBCR3, 0, 0),  /* RTC */
 102 };
 103 
 104 static struct clk_lookup lookups[] = {
 105         /* main clocks */
 106         CLKDEV_CON_ID("rclk", &r_clk),
 107         CLKDEV_CON_ID("extal", &extal_clk),
 108         CLKDEV_CON_ID("pll_clk", &pll_clk),
 109 
 110         /* DIV4 clocks */
 111         CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
 112         CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]),
 113 
 114         /* MSTP clocks */
 115         CLKDEV_ICK_ID("fck", "sh-sci.0", &mstp_clks[MSTP77]),
 116         CLKDEV_ICK_ID("fck", "sh-sci.1", &mstp_clks[MSTP77]),
 117         CLKDEV_ICK_ID("fck", "sh-sci.2", &mstp_clks[MSTP77]),
 118         CLKDEV_ICK_ID("fck", "sh-sci.3", &mstp_clks[MSTP77]),
 119         CLKDEV_ICK_ID("fck", "sh-sci.4", &mstp_clks[MSTP77]),
 120         CLKDEV_ICK_ID("fck", "sh-sci.5", &mstp_clks[MSTP77]),
 121         CLKDEV_ICK_ID("fck", "sh-sci.6", &mstp_clks[MSTP77]),
 122         CLKDEV_ICK_ID("fck", "sh-sci.7", &mstp_clks[MSTP77]),
 123         CLKDEV_CON_ID("vdc3", &mstp_clks[MSTP74]),
 124         CLKDEV_ICK_ID("fck", "sh-cmt-16.0", &mstp_clks[MSTP72]),
 125         CLKDEV_CON_ID("usb0", &mstp_clks[MSTP60]),
 126         CLKDEV_ICK_ID("fck", "sh-mtu2", &mstp_clks[MSTP35]),
 127         CLKDEV_CON_ID("sdhi0", &mstp_clks[MSTP34]),
 128         CLKDEV_CON_ID("sdhi1", &mstp_clks[MSTP33]),
 129         CLKDEV_CON_ID("adc0", &mstp_clks[MSTP32]),
 130         CLKDEV_CON_ID("rtc0", &mstp_clks[MSTP30]),
 131 };
 132 
 133 int __init arch_clk_init(void)
 134 {
 135         int k, ret = 0;
 136 
 137         if (test_mode_pin(MODE_PIN0)) {
 138                 if (test_mode_pin(MODE_PIN1))
 139                         pll1_div = 3;
 140                 else
 141                         pll1_div = 4;
 142         } else
 143                 pll1_div = 1;
 144 
 145         for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
 146                 ret = clk_register(main_clks[k]);
 147 
 148         clkdev_add_table(lookups, ARRAY_SIZE(lookups));
 149 
 150         if (!ret)
 151                 ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
 152 
 153         if (!ret)
 154                 ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
 155 
 156         return ret;
 157 }

/* [<][>][^][v][top][bottom][index][help] */