root/arch/sh/kernel/cpu/sh4a/clock-sh7366.c

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

DEFINITIONS

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

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * arch/sh/kernel/cpu/sh4a/clock-sh7366.c
   4  *
   5  * SH7366 clock framework support
   6  *
   7  * Copyright (C) 2009 Magnus Damm
   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 /* SH7366 registers */
  16 #define FRQCR           0xa4150000
  17 #define VCLKCR          0xa4150004
  18 #define SCLKACR         0xa4150008
  19 #define SCLKBCR         0xa415000c
  20 #define PLLCR           0xa4150024
  21 #define MSTPCR0         0xa4150030
  22 #define MSTPCR1         0xa4150034
  23 #define MSTPCR2         0xa4150038
  24 #define DLLFRQ          0xa4150050
  25 
  26 /* Fixed 32 KHz root clock for RTC and Power Management purposes */
  27 static struct clk r_clk = {
  28         .rate           = 32768,
  29 };
  30 
  31 /*
  32  * Default rate for the root input clock, reset this with clk_set_rate()
  33  * from the platform code.
  34  */
  35 struct clk extal_clk = {
  36         .rate           = 33333333,
  37 };
  38 
  39 /* The dll block multiplies the 32khz r_clk, may be used instead of extal */
  40 static unsigned long dll_recalc(struct clk *clk)
  41 {
  42         unsigned long mult;
  43 
  44         if (__raw_readl(PLLCR) & 0x1000)
  45                 mult = __raw_readl(DLLFRQ);
  46         else
  47                 mult = 0;
  48 
  49         return clk->parent->rate * mult;
  50 }
  51 
  52 static struct sh_clk_ops dll_clk_ops = {
  53         .recalc         = dll_recalc,
  54 };
  55 
  56 static struct clk dll_clk = {
  57         .ops            = &dll_clk_ops,
  58         .parent         = &r_clk,
  59         .flags          = CLK_ENABLE_ON_INIT,
  60 };
  61 
  62 static unsigned long pll_recalc(struct clk *clk)
  63 {
  64         unsigned long mult = 1;
  65         unsigned long div = 1;
  66 
  67         if (__raw_readl(PLLCR) & 0x4000)
  68                 mult = (((__raw_readl(FRQCR) >> 24) & 0x1f) + 1);
  69         else
  70                 div = 2;
  71 
  72         return (clk->parent->rate * mult) / div;
  73 }
  74 
  75 static struct sh_clk_ops pll_clk_ops = {
  76         .recalc         = pll_recalc,
  77 };
  78 
  79 static struct clk pll_clk = {
  80         .ops            = &pll_clk_ops,
  81         .flags          = CLK_ENABLE_ON_INIT,
  82 };
  83 
  84 struct clk *main_clks[] = {
  85         &r_clk,
  86         &extal_clk,
  87         &dll_clk,
  88         &pll_clk,
  89 };
  90 
  91 static int multipliers[] = { 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
  92 static int divisors[] = { 1, 3, 2, 5, 3, 4, 5, 6, 8, 10, 12, 16, 20 };
  93 
  94 static struct clk_div_mult_table div4_div_mult_table = {
  95         .divisors = divisors,
  96         .nr_divisors = ARRAY_SIZE(divisors),
  97         .multipliers = multipliers,
  98         .nr_multipliers = ARRAY_SIZE(multipliers),
  99 };
 100 
 101 static struct clk_div4_table div4_table = {
 102         .div_mult_table = &div4_div_mult_table,
 103 };
 104 
 105 enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_B3, DIV4_P,
 106        DIV4_SIUA, DIV4_SIUB, DIV4_NR };
 107 
 108 #define DIV4(_reg, _bit, _mask, _flags) \
 109   SH_CLK_DIV4(&pll_clk, _reg, _bit, _mask, _flags)
 110 
 111 struct clk div4_clks[DIV4_NR] = {
 112         [DIV4_I] = DIV4(FRQCR, 20, 0x1fef, CLK_ENABLE_ON_INIT),
 113         [DIV4_U] = DIV4(FRQCR, 16, 0x1fff, CLK_ENABLE_ON_INIT),
 114         [DIV4_SH] = DIV4(FRQCR, 12, 0x1fff, CLK_ENABLE_ON_INIT),
 115         [DIV4_B] = DIV4(FRQCR, 8, 0x1fff, CLK_ENABLE_ON_INIT),
 116         [DIV4_B3] = DIV4(FRQCR, 4, 0x1fff, CLK_ENABLE_ON_INIT),
 117         [DIV4_P] = DIV4(FRQCR, 0, 0x1fff, 0),
 118         [DIV4_SIUA] = DIV4(SCLKACR, 0, 0x1fff, 0),
 119         [DIV4_SIUB] = DIV4(SCLKBCR, 0, 0x1fff, 0),
 120 };
 121 
 122 enum { DIV6_V, DIV6_NR };
 123 
 124 struct clk div6_clks[DIV6_NR] = {
 125         [DIV6_V] = SH_CLK_DIV6(&pll_clk, VCLKCR, 0),
 126 };
 127 
 128 #define MSTP(_parent, _reg, _bit, _flags) \
 129   SH_CLK_MSTP32(_parent, _reg, _bit, _flags)
 130 
 131 enum { MSTP031, MSTP030, MSTP029, MSTP028, MSTP026,
 132        MSTP023, MSTP022, MSTP021, MSTP020, MSTP019, MSTP018, MSTP017, MSTP016,
 133        MSTP015, MSTP014, MSTP013, MSTP012, MSTP011, MSTP010,
 134        MSTP007, MSTP006, MSTP005, MSTP002, MSTP001,
 135        MSTP109, MSTP100,
 136        MSTP227, MSTP226, MSTP224, MSTP223, MSTP222, MSTP218, MSTP217,
 137        MSTP211, MSTP207, MSTP205, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
 138        MSTP_NR };
 139 
 140 static struct clk mstp_clks[MSTP_NR] = {
 141         /* See page 52 of Datasheet V0.40: Overview -> Block Diagram */
 142         [MSTP031] = MSTP(&div4_clks[DIV4_I], MSTPCR0, 31, CLK_ENABLE_ON_INIT),
 143         [MSTP030] = MSTP(&div4_clks[DIV4_I], MSTPCR0, 30, CLK_ENABLE_ON_INIT),
 144         [MSTP029] = MSTP(&div4_clks[DIV4_I], MSTPCR0, 29, CLK_ENABLE_ON_INIT),
 145         [MSTP028] = MSTP(&div4_clks[DIV4_SH], MSTPCR0, 28, CLK_ENABLE_ON_INIT),
 146         [MSTP026] = MSTP(&div4_clks[DIV4_B], MSTPCR0, 26, CLK_ENABLE_ON_INIT),
 147         [MSTP023] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 23, 0),
 148         [MSTP022] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 22, 0),
 149         [MSTP021] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 21, 0),
 150         [MSTP020] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 20, 0),
 151         [MSTP019] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 19, 0),
 152         [MSTP017] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 17, 0),
 153         [MSTP015] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 15, 0),
 154         [MSTP014] = MSTP(&r_clk, MSTPCR0, 14, 0),
 155         [MSTP013] = MSTP(&r_clk, MSTPCR0, 13, 0),
 156         [MSTP011] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 11, 0),
 157         [MSTP010] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 10, 0),
 158         [MSTP007] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 7, 0),
 159         [MSTP006] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 6, 0),
 160         [MSTP005] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 5, 0),
 161         [MSTP002] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 2, 0),
 162         [MSTP001] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 1, 0),
 163 
 164         [MSTP109] = MSTP(&div4_clks[DIV4_P], MSTPCR1, 9, 0),
 165 
 166         [MSTP227] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 27, 0),
 167         [MSTP226] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 26, 0),
 168         [MSTP224] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 24, 0),
 169         [MSTP223] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 23, 0),
 170         [MSTP222] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 22, 0),
 171         [MSTP218] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 18, 0),
 172         [MSTP217] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 17, 0),
 173         [MSTP211] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 11, 0),
 174         [MSTP207] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 7, CLK_ENABLE_ON_INIT),
 175         [MSTP205] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 5, 0),
 176         [MSTP204] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 4, 0),
 177         [MSTP203] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 3, 0),
 178         [MSTP202] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 2, CLK_ENABLE_ON_INIT),
 179         [MSTP201] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 1, CLK_ENABLE_ON_INIT),
 180         [MSTP200] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 0, 0),
 181 };
 182 
 183 static struct clk_lookup lookups[] = {
 184         /* main clocks */
 185         CLKDEV_CON_ID("rclk", &r_clk),
 186         CLKDEV_CON_ID("extal", &extal_clk),
 187         CLKDEV_CON_ID("dll_clk", &dll_clk),
 188         CLKDEV_CON_ID("pll_clk", &pll_clk),
 189 
 190         /* DIV4 clocks */
 191         CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
 192         CLKDEV_CON_ID("umem_clk", &div4_clks[DIV4_U]),
 193         CLKDEV_CON_ID("shyway_clk", &div4_clks[DIV4_SH]),
 194         CLKDEV_CON_ID("bus_clk", &div4_clks[DIV4_B]),
 195         CLKDEV_CON_ID("b3_clk", &div4_clks[DIV4_B3]),
 196         CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]),
 197         CLKDEV_CON_ID("siua_clk", &div4_clks[DIV4_SIUA]),
 198         CLKDEV_CON_ID("siub_clk", &div4_clks[DIV4_SIUB]),
 199 
 200         /* DIV6 clocks */
 201         CLKDEV_CON_ID("video_clk", &div6_clks[DIV6_V]),
 202 
 203         /* MSTP32 clocks */
 204         CLKDEV_CON_ID("tlb0", &mstp_clks[MSTP031]),
 205         CLKDEV_CON_ID("ic0", &mstp_clks[MSTP030]),
 206         CLKDEV_CON_ID("oc0", &mstp_clks[MSTP029]),
 207         CLKDEV_CON_ID("rsmem0", &mstp_clks[MSTP028]),
 208         CLKDEV_CON_ID("xymem0", &mstp_clks[MSTP026]),
 209         CLKDEV_CON_ID("intc3", &mstp_clks[MSTP023]),
 210         CLKDEV_CON_ID("intc0", &mstp_clks[MSTP022]),
 211         CLKDEV_CON_ID("dmac0", &mstp_clks[MSTP021]),
 212         CLKDEV_CON_ID("sh0", &mstp_clks[MSTP020]),
 213         CLKDEV_CON_ID("hudi0", &mstp_clks[MSTP019]),
 214         CLKDEV_CON_ID("ubc0", &mstp_clks[MSTP017]),
 215         CLKDEV_CON_ID("tmu_fck", &mstp_clks[MSTP015]),
 216         CLKDEV_ICK_ID("fck", "sh-cmt-32.0", &mstp_clks[MSTP014]),
 217         CLKDEV_CON_ID("rwdt0", &mstp_clks[MSTP013]),
 218         CLKDEV_CON_ID("mfi0", &mstp_clks[MSTP011]),
 219         CLKDEV_CON_ID("flctl0", &mstp_clks[MSTP010]),
 220 
 221         CLKDEV_ICK_ID("fck", "sh-sci.0", &mstp_clks[MSTP007]),
 222         CLKDEV_ICK_ID("fck", "sh-sci.1", &mstp_clks[MSTP006]),
 223         CLKDEV_ICK_ID("fck", "sh-sci.2", &mstp_clks[MSTP005]),
 224 
 225         CLKDEV_CON_ID("msiof0", &mstp_clks[MSTP002]),
 226         CLKDEV_CON_ID("sbr0", &mstp_clks[MSTP001]),
 227         CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP109]),
 228         CLKDEV_CON_ID("icb0", &mstp_clks[MSTP227]),
 229         CLKDEV_CON_ID("meram0", &mstp_clks[MSTP226]),
 230         CLKDEV_CON_ID("dacy1", &mstp_clks[MSTP224]),
 231         CLKDEV_CON_ID("dacy0", &mstp_clks[MSTP223]),
 232         CLKDEV_CON_ID("tsif0", &mstp_clks[MSTP222]),
 233         CLKDEV_CON_ID("sdhi0", &mstp_clks[MSTP218]),
 234         CLKDEV_CON_ID("mmcif0", &mstp_clks[MSTP217]),
 235         CLKDEV_CON_ID("usbf0", &mstp_clks[MSTP211]),
 236         CLKDEV_CON_ID("veu1", &mstp_clks[MSTP207]),
 237         CLKDEV_CON_ID("vou0", &mstp_clks[MSTP205]),
 238         CLKDEV_CON_ID("beu0", &mstp_clks[MSTP204]),
 239         CLKDEV_CON_ID("ceu0", &mstp_clks[MSTP203]),
 240         CLKDEV_CON_ID("veu0", &mstp_clks[MSTP202]),
 241         CLKDEV_CON_ID("vpu0", &mstp_clks[MSTP201]),
 242         CLKDEV_CON_ID("lcdc0", &mstp_clks[MSTP200]),
 243 };
 244 
 245 int __init arch_clk_init(void)
 246 {
 247         int k, ret = 0;
 248 
 249         /* autodetect extal or dll configuration */
 250         if (__raw_readl(PLLCR) & 0x1000)
 251                 pll_clk.parent = &dll_clk;
 252         else
 253                 pll_clk.parent = &extal_clk;
 254 
 255         for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
 256                 ret = clk_register(main_clks[k]);
 257 
 258         clkdev_add_table(lookups, ARRAY_SIZE(lookups));
 259 
 260         if (!ret)
 261                 ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
 262 
 263         if (!ret)
 264                 ret = sh_clk_div6_register(div6_clks, DIV6_NR);
 265 
 266         if (!ret)
 267                 ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
 268 
 269         return ret;
 270 }

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