linux/arch/arm/mach-shmobile/clock-sh7367.c
<<
>>
Prefs
   1/*
   2 * SH7367 clock framework support
   3 *
   4 * Copyright (C) 2010  Magnus Damm
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License as published by
   8 * the Free Software Foundation; version 2 of the License.
   9 *
  10 * This program is distributed in the hope that it will be useful,
  11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 * GNU General Public License for more details.
  14 *
  15 * You should have received a copy of the GNU General Public License
  16 * along with this program; if not, write to the Free Software
  17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  18 */
  19#include <linux/init.h>
  20#include <linux/kernel.h>
  21#include <linux/io.h>
  22#include <linux/sh_clk.h>
  23#include <linux/clkdev.h>
  24#include <mach/common.h>
  25
  26/* SH7367 registers */
  27#define RTFRQCR    0xe6150000
  28#define SYFRQCR    0xe6150004
  29#define CMFRQCR    0xe61500E0
  30#define VCLKCR1    0xe6150008
  31#define VCLKCR2    0xe615000C
  32#define VCLKCR3    0xe615001C
  33#define SCLKACR    0xe6150010
  34#define SCLKBCR    0xe6150014
  35#define SUBUSBCKCR 0xe6158080
  36#define SPUCKCR    0xe6150084
  37#define MSUCKCR    0xe6150088
  38#define MVI3CKCR   0xe6150090
  39#define VOUCKCR    0xe6150094
  40#define MFCK1CR    0xe6150098
  41#define MFCK2CR    0xe615009C
  42#define PLLC1CR    0xe6150028
  43#define PLLC2CR    0xe615002C
  44#define RTMSTPCR0  0xe6158030
  45#define RTMSTPCR2  0xe6158038
  46#define SYMSTPCR0  0xe6158040
  47#define SYMSTPCR2  0xe6158048
  48#define CMMSTPCR0  0xe615804c
  49
  50/* Fixed 32 KHz root clock from EXTALR pin */
  51static struct clk r_clk = {
  52        .rate           = 32768,
  53};
  54
  55/*
  56 * 26MHz default rate for the EXTALB1 root input clock.
  57 * If needed, reset this with clk_set_rate() from the platform code.
  58 */
  59struct clk sh7367_extalb1_clk = {
  60        .rate           = 26666666,
  61};
  62
  63/*
  64 * 48MHz default rate for the EXTAL2 root input clock.
  65 * If needed, reset this with clk_set_rate() from the platform code.
  66 */
  67struct clk sh7367_extal2_clk = {
  68        .rate           = 48000000,
  69};
  70
  71/* A fixed divide-by-2 block */
  72static unsigned long div2_recalc(struct clk *clk)
  73{
  74        return clk->parent->rate / 2;
  75}
  76
  77static struct clk_ops div2_clk_ops = {
  78        .recalc         = div2_recalc,
  79};
  80
  81/* Divide extalb1 by two */
  82static struct clk extalb1_div2_clk = {
  83        .ops            = &div2_clk_ops,
  84        .parent         = &sh7367_extalb1_clk,
  85};
  86
  87/* Divide extal2 by two */
  88static struct clk extal2_div2_clk = {
  89        .ops            = &div2_clk_ops,
  90        .parent         = &sh7367_extal2_clk,
  91};
  92
  93/* PLLC1 */
  94static unsigned long pllc1_recalc(struct clk *clk)
  95{
  96        unsigned long mult = 1;
  97
  98        if (__raw_readl(PLLC1CR) & (1 << 14))
  99                mult = (((__raw_readl(RTFRQCR) >> 24) & 0x3f) + 1) * 2;
 100
 101        return clk->parent->rate * mult;
 102}
 103
 104static struct clk_ops pllc1_clk_ops = {
 105        .recalc         = pllc1_recalc,
 106};
 107
 108static struct clk pllc1_clk = {
 109        .ops            = &pllc1_clk_ops,
 110        .flags          = CLK_ENABLE_ON_INIT,
 111        .parent         = &extalb1_div2_clk,
 112};
 113
 114/* Divide PLLC1 by two */
 115static struct clk pllc1_div2_clk = {
 116        .ops            = &div2_clk_ops,
 117        .parent         = &pllc1_clk,
 118};
 119
 120/* PLLC2 */
 121static unsigned long pllc2_recalc(struct clk *clk)
 122{
 123        unsigned long mult = 1;
 124
 125        if (__raw_readl(PLLC2CR) & (1 << 31))
 126                mult = (((__raw_readl(PLLC2CR) >> 24) & 0x3f) + 1) * 2;
 127
 128        return clk->parent->rate * mult;
 129}
 130
 131static struct clk_ops pllc2_clk_ops = {
 132        .recalc         = pllc2_recalc,
 133};
 134
 135static struct clk pllc2_clk = {
 136        .ops            = &pllc2_clk_ops,
 137        .flags          = CLK_ENABLE_ON_INIT,
 138        .parent         = &extalb1_div2_clk,
 139};
 140
 141static struct clk *main_clks[] = {
 142        &r_clk,
 143        &sh7367_extalb1_clk,
 144        &sh7367_extal2_clk,
 145        &extalb1_div2_clk,
 146        &extal2_div2_clk,
 147        &pllc1_clk,
 148        &pllc1_div2_clk,
 149        &pllc2_clk,
 150};
 151
 152static void div4_kick(struct clk *clk)
 153{
 154        unsigned long value;
 155
 156        /* set KICK bit in SYFRQCR to update hardware setting */
 157        value = __raw_readl(SYFRQCR);
 158        value |= (1 << 31);
 159        __raw_writel(value, SYFRQCR);
 160}
 161
 162static int divisors[] = { 2, 3, 4, 6, 8, 12, 16, 18,
 163                          24, 32, 36, 48, 0, 72, 0, 0 };
 164
 165static struct clk_div_mult_table div4_div_mult_table = {
 166        .divisors = divisors,
 167        .nr_divisors = ARRAY_SIZE(divisors),
 168};
 169
 170static struct clk_div4_table div4_table = {
 171        .div_mult_table = &div4_div_mult_table,
 172        .kick = div4_kick,
 173};
 174
 175enum { DIV4_I, DIV4_G, DIV4_S, DIV4_B,
 176       DIV4_ZX, DIV4_ZT, DIV4_Z, DIV4_ZD, DIV4_HP,
 177       DIV4_ZS, DIV4_ZB, DIV4_ZB3, DIV4_CP, DIV4_NR };
 178
 179#define DIV4(_reg, _bit, _mask, _flags) \
 180  SH_CLK_DIV4(&pllc1_clk, _reg, _bit, _mask, _flags)
 181
 182static struct clk div4_clks[DIV4_NR] = {
 183        [DIV4_I] = DIV4(RTFRQCR, 20, 0x6fff, CLK_ENABLE_ON_INIT),
 184        [DIV4_G] = DIV4(RTFRQCR, 16, 0x6fff, CLK_ENABLE_ON_INIT),
 185        [DIV4_S] = DIV4(RTFRQCR, 12, 0x6fff, CLK_ENABLE_ON_INIT),
 186        [DIV4_B] = DIV4(RTFRQCR, 8, 0x6fff, CLK_ENABLE_ON_INIT),
 187        [DIV4_ZX] = DIV4(SYFRQCR, 20, 0x6fff, 0),
 188        [DIV4_ZT] = DIV4(SYFRQCR, 16, 0x6fff, 0),
 189        [DIV4_Z] = DIV4(SYFRQCR, 12, 0x6fff, 0),
 190        [DIV4_ZD] = DIV4(SYFRQCR, 8, 0x6fff, 0),
 191        [DIV4_HP] = DIV4(SYFRQCR, 4, 0x6fff, 0),
 192        [DIV4_ZS] = DIV4(CMFRQCR, 12, 0x6fff, 0),
 193        [DIV4_ZB] = DIV4(CMFRQCR, 8, 0x6fff, 0),
 194        [DIV4_ZB3] = DIV4(CMFRQCR, 4, 0x6fff, 0),
 195        [DIV4_CP] = DIV4(CMFRQCR, 0, 0x6fff, 0),
 196};
 197
 198enum { DIV6_SUB, DIV6_SIUA, DIV6_SIUB, DIV6_MSU, DIV6_SPU,
 199       DIV6_MVI3, DIV6_MF1, DIV6_MF2,
 200       DIV6_VCK1, DIV6_VCK2, DIV6_VCK3, DIV6_VOU,
 201       DIV6_NR };
 202
 203static struct clk div6_clks[DIV6_NR] = {
 204        [DIV6_SUB] = SH_CLK_DIV6(&sh7367_extal2_clk, SUBUSBCKCR, 0),
 205        [DIV6_SIUA] = SH_CLK_DIV6(&pllc1_div2_clk, SCLKACR, 0),
 206        [DIV6_SIUB] = SH_CLK_DIV6(&pllc1_div2_clk, SCLKBCR, 0),
 207        [DIV6_MSU] = SH_CLK_DIV6(&pllc1_div2_clk, MSUCKCR, 0),
 208        [DIV6_SPU] = SH_CLK_DIV6(&pllc1_div2_clk, SPUCKCR, 0),
 209        [DIV6_MVI3] = SH_CLK_DIV6(&pllc1_div2_clk, MVI3CKCR, 0),
 210        [DIV6_MF1] = SH_CLK_DIV6(&pllc1_div2_clk, MFCK1CR, 0),
 211        [DIV6_MF2] = SH_CLK_DIV6(&pllc1_div2_clk, MFCK2CR, 0),
 212        [DIV6_VCK1] = SH_CLK_DIV6(&pllc1_div2_clk, VCLKCR1, 0),
 213        [DIV6_VCK2] = SH_CLK_DIV6(&pllc1_div2_clk, VCLKCR2, 0),
 214        [DIV6_VCK3] = SH_CLK_DIV6(&pllc1_div2_clk, VCLKCR3, 0),
 215        [DIV6_VOU] = SH_CLK_DIV6(&pllc1_div2_clk, VOUCKCR, 0),
 216};
 217
 218enum { RTMSTP001,
 219       RTMSTP231, RTMSTP230, RTMSTP229, RTMSTP228, RTMSTP226,
 220       RTMSTP216, RTMSTP206, RTMSTP205, RTMSTP201,
 221       SYMSTP023, SYMSTP007, SYMSTP006, SYMSTP004,
 222       SYMSTP003, SYMSTP002, SYMSTP001, SYMSTP000,
 223       SYMSTP231, SYMSTP229, SYMSTP225, SYMSTP223, SYMSTP222,
 224       SYMSTP215, SYMSTP214, SYMSTP213, SYMSTP211,
 225       CMMSTP003,
 226       MSTP_NR };
 227
 228#define MSTP(_parent, _reg, _bit, _flags) \
 229  SH_CLK_MSTP32(_parent, _reg, _bit, _flags)
 230
 231static struct clk mstp_clks[MSTP_NR] = {
 232        [RTMSTP001] = MSTP(&div6_clks[DIV6_SUB], RTMSTPCR0, 1, 0), /* IIC2 */
 233        [RTMSTP231] = MSTP(&div4_clks[DIV4_B], RTMSTPCR2, 31, 0), /* VEU3 */
 234        [RTMSTP230] = MSTP(&div4_clks[DIV4_B], RTMSTPCR2, 30, 0), /* VEU2 */
 235        [RTMSTP229] = MSTP(&div4_clks[DIV4_B], RTMSTPCR2, 29, 0), /* VEU1 */
 236        [RTMSTP228] = MSTP(&div4_clks[DIV4_B], RTMSTPCR2, 28, 0), /* VEU0 */
 237        [RTMSTP226] = MSTP(&div4_clks[DIV4_B], RTMSTPCR2, 26, 0), /* VEU2H */
 238        [RTMSTP216] = MSTP(&div6_clks[DIV6_SUB], RTMSTPCR2, 16, 0), /* IIC0 */
 239        [RTMSTP206] = MSTP(&div4_clks[DIV4_B], RTMSTPCR2, 6, 0), /* JPU */
 240        [RTMSTP205] = MSTP(&div6_clks[DIV6_VOU], RTMSTPCR2, 5, 0), /* VOU */
 241        [RTMSTP201] = MSTP(&div4_clks[DIV4_B], RTMSTPCR2, 1, 0), /* VPU */
 242        [SYMSTP023] = MSTP(&div6_clks[DIV6_SPU], SYMSTPCR0, 23, 0), /* SPU1 */
 243        [SYMSTP007] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR0, 7, 0), /* SCIFA5 */
 244        [SYMSTP006] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR0, 6, 0), /* SCIFB */
 245        [SYMSTP004] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR0, 4, 0), /* SCIFA0 */
 246        [SYMSTP003] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR0, 3, 0), /* SCIFA1 */
 247        [SYMSTP002] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR0, 2, 0), /* SCIFA2 */
 248        [SYMSTP001] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR0, 1, 0), /* SCIFA3 */
 249        [SYMSTP000] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR0, 0, 0), /* SCIFA4 */
 250        [SYMSTP231] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR2, 31, 0), /* SIU */
 251        [SYMSTP229] = MSTP(&r_clk, SYMSTPCR2, 29, 0), /* CMT10 */
 252        [SYMSTP225] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR2, 25, 0), /* IRDA */
 253        [SYMSTP223] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR2, 23, 0), /* IIC1 */
 254        [SYMSTP222] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR2, 22, 0), /* USBHS */
 255        [SYMSTP215] = MSTP(&div4_clks[DIV4_HP], SYMSTPCR2, 15, 0), /* FLCTL */
 256        [SYMSTP214] = MSTP(&div4_clks[DIV4_HP], SYMSTPCR2, 14, 0), /* SDHI0 */
 257        [SYMSTP213] = MSTP(&div4_clks[DIV4_HP], SYMSTPCR2, 13, 0), /* SDHI1 */
 258        [SYMSTP211] = MSTP(&div4_clks[DIV4_HP], SYMSTPCR2, 11, 0), /* SDHI2 */
 259        [CMMSTP003] = MSTP(&r_clk, CMMSTPCR0, 3, 0), /* KEYSC */
 260};
 261
 262#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
 263#define CLKDEV_DEV_ID(_id, _clk) { .dev_id = _id, .clk = _clk }
 264
 265static struct clk_lookup lookups[] = {
 266        /* main clocks */
 267        CLKDEV_CON_ID("r_clk", &r_clk),
 268        CLKDEV_CON_ID("extalb1", &sh7367_extalb1_clk),
 269        CLKDEV_CON_ID("extal2", &sh7367_extal2_clk),
 270        CLKDEV_CON_ID("extalb1_div2_clk", &extalb1_div2_clk),
 271        CLKDEV_CON_ID("extal2_div2_clk", &extal2_div2_clk),
 272        CLKDEV_CON_ID("pllc1_clk", &pllc1_clk),
 273        CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk),
 274        CLKDEV_CON_ID("pllc2_clk", &pllc2_clk),
 275
 276        /* DIV4 clocks */
 277        CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]),
 278        CLKDEV_CON_ID("g_clk", &div4_clks[DIV4_G]),
 279        CLKDEV_CON_ID("b_clk", &div4_clks[DIV4_B]),
 280        CLKDEV_CON_ID("zx_clk", &div4_clks[DIV4_ZX]),
 281        CLKDEV_CON_ID("zt_clk", &div4_clks[DIV4_ZT]),
 282        CLKDEV_CON_ID("z_clk", &div4_clks[DIV4_Z]),
 283        CLKDEV_CON_ID("zd_clk", &div4_clks[DIV4_ZD]),
 284        CLKDEV_CON_ID("hp_clk", &div4_clks[DIV4_HP]),
 285        CLKDEV_CON_ID("zs_clk", &div4_clks[DIV4_ZS]),
 286        CLKDEV_CON_ID("zb_clk", &div4_clks[DIV4_ZB]),
 287        CLKDEV_CON_ID("zb3_clk", &div4_clks[DIV4_ZB3]),
 288        CLKDEV_CON_ID("cp_clk", &div4_clks[DIV4_CP]),
 289
 290        /* DIV6 clocks */
 291        CLKDEV_CON_ID("sub_clk", &div6_clks[DIV6_SUB]),
 292        CLKDEV_CON_ID("siua_clk", &div6_clks[DIV6_SIUA]),
 293        CLKDEV_CON_ID("siub_clk", &div6_clks[DIV6_SIUB]),
 294        CLKDEV_CON_ID("msu_clk", &div6_clks[DIV6_MSU]),
 295        CLKDEV_CON_ID("spu_clk", &div6_clks[DIV6_SPU]),
 296        CLKDEV_CON_ID("mvi3_clk", &div6_clks[DIV6_MVI3]),
 297        CLKDEV_CON_ID("mf1_clk", &div6_clks[DIV6_MF1]),
 298        CLKDEV_CON_ID("mf2_clk", &div6_clks[DIV6_MF2]),
 299        CLKDEV_CON_ID("vck1_clk", &div6_clks[DIV6_VCK1]),
 300        CLKDEV_CON_ID("vck2_clk", &div6_clks[DIV6_VCK2]),
 301        CLKDEV_CON_ID("vck3_clk", &div6_clks[DIV6_VCK3]),
 302        CLKDEV_CON_ID("vou_clk", &div6_clks[DIV6_VOU]),
 303
 304        /* MSTP32 clocks */
 305        CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[RTMSTP001]), /* IIC2 */
 306        CLKDEV_DEV_ID("uio_pdrv_genirq.4", &mstp_clks[RTMSTP231]), /* VEU3 */
 307        CLKDEV_DEV_ID("uio_pdrv_genirq.3", &mstp_clks[RTMSTP230]), /* VEU2 */
 308        CLKDEV_DEV_ID("uio_pdrv_genirq.2", &mstp_clks[RTMSTP229]), /* VEU1 */
 309        CLKDEV_DEV_ID("uio_pdrv_genirq.1", &mstp_clks[RTMSTP228]), /* VEU0 */
 310        CLKDEV_DEV_ID("uio_pdrv_genirq.5", &mstp_clks[RTMSTP226]), /* VEU2H */
 311        CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[RTMSTP216]), /* IIC0 */
 312        CLKDEV_DEV_ID("uio_pdrv_genirq.6", &mstp_clks[RTMSTP206]), /* JPU */
 313        CLKDEV_DEV_ID("sh-vou", &mstp_clks[RTMSTP205]), /* VOU */
 314        CLKDEV_DEV_ID("uio_pdrv_genirq.0", &mstp_clks[RTMSTP201]), /* VPU */
 315        CLKDEV_DEV_ID("uio_pdrv_genirq.7", &mstp_clks[SYMSTP023]), /* SPU1 */
 316        CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[SYMSTP007]), /* SCIFA5 */
 317        CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[SYMSTP006]), /* SCIFB */
 318        CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[SYMSTP004]), /* SCIFA0 */
 319        CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[SYMSTP003]), /* SCIFA1 */
 320        CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[SYMSTP002]), /* SCIFA2 */
 321        CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[SYMSTP001]), /* SCIFA3 */
 322        CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[SYMSTP000]), /* SCIFA4 */
 323        CLKDEV_DEV_ID("sh_siu", &mstp_clks[SYMSTP231]), /* SIU */
 324        CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[SYMSTP229]), /* CMT10 */
 325        CLKDEV_DEV_ID("sh_irda", &mstp_clks[SYMSTP225]), /* IRDA */
 326        CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[SYMSTP223]), /* IIC1 */
 327        CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[SYMSTP222]), /* USBHS */
 328        CLKDEV_DEV_ID("r8a66597_udc.0", &mstp_clks[SYMSTP222]), /* USBHS */
 329        CLKDEV_DEV_ID("sh_flctl", &mstp_clks[SYMSTP215]), /* FLCTL */
 330        CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[SYMSTP214]), /* SDHI0 */
 331        CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[SYMSTP213]), /* SDHI1 */
 332        CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[SYMSTP211]), /* SDHI2 */
 333        CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[CMMSTP003]), /* KEYSC */
 334};
 335
 336void __init sh7367_clock_init(void)
 337{
 338        int k, ret = 0;
 339
 340        for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
 341                ret = clk_register(main_clks[k]);
 342
 343        if (!ret)
 344                ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
 345
 346        if (!ret)
 347                ret = sh_clk_div6_register(div6_clks, DIV6_NR);
 348
 349        if (!ret)
 350                ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
 351
 352        clkdev_add_table(lookups, ARRAY_SIZE(lookups));
 353
 354        if (!ret)
 355                clk_init();
 356        else
 357                panic("failed to setup sh7367 clocks\n");
 358}
 359