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