linux/arch/arm/mach-shmobile/clock-r8a7790.c
<<
>>
Prefs
   1/*
   2 * r8a7790 clock framework support
   3 *
   4 * Copyright (C) 2013  Renesas Solutions Corp.
   5 * Copyright (C) 2013  Magnus Damm
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License as published by
   9 * the Free Software Foundation; version 2 of the License.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * along with this program; if not, write to the Free Software
  18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  19 */
  20#include <linux/init.h>
  21#include <linux/io.h>
  22#include <linux/kernel.h>
  23#include <linux/sh_clk.h>
  24#include <linux/clkdev.h>
  25#include <mach/clock.h>
  26#include <mach/common.h>
  27
  28/*
  29 *   MD         EXTAL           PLL0    PLL1    PLL3
  30 * 14 13 19     (MHz)           *1      *1
  31 *---------------------------------------------------
  32 * 0  0  0      15 x 1          x172/2  x208/2  x106
  33 * 0  0  1      15 x 1          x172/2  x208/2  x88
  34 * 0  1  0      20 x 1          x130/2  x156/2  x80
  35 * 0  1  1      20 x 1          x130/2  x156/2  x66
  36 * 1  0  0      26 / 2          x200/2  x240/2  x122
  37 * 1  0  1      26 / 2          x200/2  x240/2  x102
  38 * 1  1  0      30 / 2          x172/2  x208/2  x106
  39 * 1  1  1      30 / 2          x172/2  x208/2  x88
  40 *
  41 * *1 : Table 7.6 indicates VCO ouput (PLLx = VCO/2)
  42 *      see "p1 / 2" on R8A7790_CLOCK_ROOT() below
  43 */
  44
  45#define MD(nr)  (1 << nr)
  46
  47#define CPG_BASE 0xe6150000
  48#define CPG_LEN 0x1000
  49
  50#define SMSTPCR2 0xe6150138
  51#define SMSTPCR3 0xe615013c
  52#define SMSTPCR7 0xe615014c
  53
  54#define MODEMR          0xE6160060
  55#define SDCKCR          0xE6150074
  56#define SD2CKCR         0xE6150078
  57#define SD3CKCR         0xE615007C
  58#define MMC0CKCR        0xE6150240
  59#define MMC1CKCR        0xE6150244
  60#define SSPCKCR         0xE6150248
  61#define SSPRSCKCR       0xE615024C
  62
  63static struct clk_mapping cpg_mapping = {
  64        .phys   = CPG_BASE,
  65        .len    = CPG_LEN,
  66};
  67
  68static struct clk extal_clk = {
  69        /* .rate will be updated on r8a7790_clock_init() */
  70        .mapping        = &cpg_mapping,
  71};
  72
  73static struct sh_clk_ops followparent_clk_ops = {
  74        .recalc = followparent_recalc,
  75};
  76
  77static struct clk main_clk = {
  78        /* .parent will be set r8a73a4_clock_init */
  79        .ops    = &followparent_clk_ops,
  80};
  81
  82/*
  83 * clock ratio of these clock will be updated
  84 * on r8a7790_clock_init()
  85 */
  86SH_FIXED_RATIO_CLK_SET(pll1_clk,                main_clk,       1, 1);
  87SH_FIXED_RATIO_CLK_SET(pll3_clk,                main_clk,       1, 1);
  88SH_FIXED_RATIO_CLK_SET(lb_clk,                  pll1_clk,       1, 1);
  89SH_FIXED_RATIO_CLK_SET(qspi_clk,                pll1_clk,       1, 1);
  90
  91/* fixed ratio clock */
  92SH_FIXED_RATIO_CLK_SET(extal_div2_clk,          extal_clk,      1, 2);
  93SH_FIXED_RATIO_CLK_SET(cp_clk,                  extal_clk,      1, 2);
  94
  95SH_FIXED_RATIO_CLK_SET(pll1_div2_clk,           pll1_clk,       1, 2);
  96SH_FIXED_RATIO_CLK_SET(zg_clk,                  pll1_clk,       1, 3);
  97SH_FIXED_RATIO_CLK_SET(zx_clk,                  pll1_clk,       1, 3);
  98SH_FIXED_RATIO_CLK_SET(zs_clk,                  pll1_clk,       1, 6);
  99SH_FIXED_RATIO_CLK_SET(hp_clk,                  pll1_clk,       1, 12);
 100SH_FIXED_RATIO_CLK_SET(i_clk,                   pll1_clk,       1, 2);
 101SH_FIXED_RATIO_CLK_SET(b_clk,                   pll1_clk,       1, 12);
 102SH_FIXED_RATIO_CLK_SET(p_clk,                   pll1_clk,       1, 24);
 103SH_FIXED_RATIO_CLK_SET(cl_clk,                  pll1_clk,       1, 48);
 104SH_FIXED_RATIO_CLK_SET(m2_clk,                  pll1_clk,       1, 8);
 105SH_FIXED_RATIO_CLK_SET(imp_clk,                 pll1_clk,       1, 4);
 106SH_FIXED_RATIO_CLK_SET(rclk_clk,                pll1_clk,       1, (48 * 1024));
 107SH_FIXED_RATIO_CLK_SET(oscclk_clk,              pll1_clk,       1, (12 * 1024));
 108
 109SH_FIXED_RATIO_CLK_SET(zb3_clk,                 pll3_clk,       1, 4);
 110SH_FIXED_RATIO_CLK_SET(zb3d2_clk,               pll3_clk,       1, 8);
 111SH_FIXED_RATIO_CLK_SET(ddr_clk,                 pll3_clk,       1, 8);
 112SH_FIXED_RATIO_CLK_SET(mp_clk,                  pll1_div2_clk,  1, 15);
 113
 114static struct clk *main_clks[] = {
 115        &extal_clk,
 116        &extal_div2_clk,
 117        &main_clk,
 118        &pll1_clk,
 119        &pll1_div2_clk,
 120        &pll3_clk,
 121        &lb_clk,
 122        &qspi_clk,
 123        &zg_clk,
 124        &zx_clk,
 125        &zs_clk,
 126        &hp_clk,
 127        &i_clk,
 128        &b_clk,
 129        &p_clk,
 130        &cl_clk,
 131        &m2_clk,
 132        &imp_clk,
 133        &rclk_clk,
 134        &oscclk_clk,
 135        &zb3_clk,
 136        &zb3d2_clk,
 137        &ddr_clk,
 138        &mp_clk,
 139        &cp_clk,
 140};
 141
 142/* SDHI (DIV4) clock */
 143static int divisors[] = { 2, 3, 4, 6, 8, 12, 16, 18, 24, 0, 36, 48, 10 };
 144
 145static struct clk_div_mult_table div4_div_mult_table = {
 146        .divisors = divisors,
 147        .nr_divisors = ARRAY_SIZE(divisors),
 148};
 149
 150static struct clk_div4_table div4_table = {
 151        .div_mult_table = &div4_div_mult_table,
 152};
 153
 154enum {
 155        DIV4_SDH, DIV4_SD0, DIV4_SD1, DIV4_NR
 156};
 157
 158static struct clk div4_clks[DIV4_NR] = {
 159        [DIV4_SDH] = SH_CLK_DIV4(&pll1_clk, SDCKCR, 8, 0x0dff, CLK_ENABLE_ON_INIT),
 160        [DIV4_SD0] = SH_CLK_DIV4(&pll1_clk, SDCKCR, 4, 0x1de0, CLK_ENABLE_ON_INIT),
 161        [DIV4_SD1] = SH_CLK_DIV4(&pll1_clk, SDCKCR, 0, 0x1de0, CLK_ENABLE_ON_INIT),
 162};
 163
 164/* DIV6 clocks */
 165enum {
 166        DIV6_SD2, DIV6_SD3,
 167        DIV6_MMC0, DIV6_MMC1,
 168        DIV6_SSP, DIV6_SSPRS,
 169        DIV6_NR
 170};
 171
 172static struct clk div6_clks[DIV6_NR] = {
 173        [DIV6_SD2]      = SH_CLK_DIV6(&pll1_div2_clk, SD2CKCR, 0),
 174        [DIV6_SD3]      = SH_CLK_DIV6(&pll1_div2_clk, SD3CKCR, 0),
 175        [DIV6_MMC0]     = SH_CLK_DIV6(&pll1_div2_clk, MMC0CKCR, 0),
 176        [DIV6_MMC1]     = SH_CLK_DIV6(&pll1_div2_clk, MMC1CKCR, 0),
 177        [DIV6_SSP]      = SH_CLK_DIV6(&pll1_div2_clk, SSPCKCR, 0),
 178        [DIV6_SSPRS]    = SH_CLK_DIV6(&pll1_div2_clk, SSPRSCKCR, 0),
 179};
 180
 181/* MSTP */
 182enum {
 183        MSTP721, MSTP720,
 184        MSTP717, MSTP716,
 185        MSTP315, MSTP314, MSTP313, MSTP312, MSTP311, MSTP305, MSTP304,
 186        MSTP216, MSTP207, MSTP206, MSTP204, MSTP203, MSTP202,
 187        MSTP_NR
 188};
 189
 190static struct clk mstp_clks[MSTP_NR] = {
 191        [MSTP721] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 21, 0), /* SCIF0 */
 192        [MSTP720] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 20, 0), /* SCIF1 */
 193        [MSTP315] = SH_CLK_MSTP32(&div6_clks[DIV6_MMC0], SMSTPCR3, 15, 0), /* MMC0 */
 194        [MSTP314] = SH_CLK_MSTP32(&div4_clks[DIV4_SD0], SMSTPCR3, 14, 0), /* SDHI0 */
 195        [MSTP313] = SH_CLK_MSTP32(&div4_clks[DIV4_SD1], SMSTPCR3, 13, 0), /* SDHI1 */
 196        [MSTP312] = SH_CLK_MSTP32(&div6_clks[DIV6_SD2], SMSTPCR3, 12, 0), /* SDHI2 */
 197        [MSTP311] = SH_CLK_MSTP32(&div6_clks[DIV6_SD3], SMSTPCR3, 11, 0), /* SDHI3 */
 198        [MSTP305] = SH_CLK_MSTP32(&div6_clks[DIV6_MMC1], SMSTPCR3, 5, 0), /* MMC1 */
 199        [MSTP304] = SH_CLK_MSTP32(&cp_clk, SMSTPCR3, 4, 0), /* TPU0 */
 200        [MSTP216] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 16, 0), /* SCIFB2 */
 201        [MSTP207] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 7, 0), /* SCIFB1 */
 202        [MSTP206] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 6, 0), /* SCIFB0 */
 203        [MSTP204] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 4, 0), /* SCIFA0 */
 204        [MSTP203] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 3, 0), /* SCIFA1 */
 205        [MSTP202] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 2, 0), /* SCIFA2 */
 206        [MSTP717] = SH_CLK_MSTP32(&zs_clk, SMSTPCR7, 17, 0), /* HSCIF0 */
 207        [MSTP716] = SH_CLK_MSTP32(&zs_clk, SMSTPCR7, 16, 0), /* HSCIF1 */
 208};
 209
 210static struct clk_lookup lookups[] = {
 211
 212        /* main clocks */
 213        CLKDEV_CON_ID("extal",          &extal_clk),
 214        CLKDEV_CON_ID("extal_div2",     &extal_div2_clk),
 215        CLKDEV_CON_ID("main",           &main_clk),
 216        CLKDEV_CON_ID("pll1",           &pll1_clk),
 217        CLKDEV_CON_ID("pll1_div2",      &pll1_div2_clk),
 218        CLKDEV_CON_ID("pll3",           &pll3_clk),
 219        CLKDEV_CON_ID("zg",             &zg_clk),
 220        CLKDEV_CON_ID("zx",             &zx_clk),
 221        CLKDEV_CON_ID("zs",             &zs_clk),
 222        CLKDEV_CON_ID("hp",             &hp_clk),
 223        CLKDEV_CON_ID("i",              &i_clk),
 224        CLKDEV_CON_ID("b",              &b_clk),
 225        CLKDEV_CON_ID("lb",             &lb_clk),
 226        CLKDEV_CON_ID("p",              &p_clk),
 227        CLKDEV_CON_ID("cl",             &cl_clk),
 228        CLKDEV_CON_ID("m2",             &m2_clk),
 229        CLKDEV_CON_ID("imp",            &imp_clk),
 230        CLKDEV_CON_ID("rclk",           &rclk_clk),
 231        CLKDEV_CON_ID("oscclk",         &oscclk_clk),
 232        CLKDEV_CON_ID("zb3",            &zb3_clk),
 233        CLKDEV_CON_ID("zb3d2",          &zb3d2_clk),
 234        CLKDEV_CON_ID("ddr",            &ddr_clk),
 235        CLKDEV_CON_ID("mp",             &mp_clk),
 236        CLKDEV_CON_ID("qspi",           &qspi_clk),
 237        CLKDEV_CON_ID("cp",             &cp_clk),
 238
 239        /* DIV4 */
 240        CLKDEV_CON_ID("sdh",            &div4_clks[DIV4_SDH]),
 241
 242        /* DIV6 */
 243        CLKDEV_CON_ID("ssp",            &div6_clks[DIV6_SSP]),
 244        CLKDEV_CON_ID("ssprs",          &div6_clks[DIV6_SSPRS]),
 245
 246        /* MSTP */
 247        CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]),
 248        CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP203]),
 249        CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP206]),
 250        CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP207]),
 251        CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP216]),
 252        CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP202]),
 253        CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP721]),
 254        CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP720]),
 255        CLKDEV_DEV_ID("sh-sci.8", &mstp_clks[MSTP717]),
 256        CLKDEV_DEV_ID("sh-sci.9", &mstp_clks[MSTP716]),
 257        CLKDEV_DEV_ID("ee200000.mmcif", &mstp_clks[MSTP315]),
 258        CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP315]),
 259        CLKDEV_DEV_ID("ee100000.sdhi", &mstp_clks[MSTP314]),
 260        CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]),
 261        CLKDEV_DEV_ID("ee120000.sdhi", &mstp_clks[MSTP313]),
 262        CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]),
 263        CLKDEV_DEV_ID("ee140000.sdhi", &mstp_clks[MSTP312]),
 264        CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP312]),
 265        CLKDEV_DEV_ID("ee160000.sdhi", &mstp_clks[MSTP311]),
 266        CLKDEV_DEV_ID("sh_mobile_sdhi.3", &mstp_clks[MSTP311]),
 267        CLKDEV_DEV_ID("ee220000.mmcif", &mstp_clks[MSTP305]),
 268        CLKDEV_DEV_ID("sh_mmcif.1", &mstp_clks[MSTP305]),
 269};
 270
 271#define R8A7790_CLOCK_ROOT(e, m, p0, p1, p30, p31)              \
 272        extal_clk.rate  = e * 1000 * 1000;                      \
 273        main_clk.parent = m;                                    \
 274        SH_CLK_SET_RATIO(&pll1_clk_ratio, p1 / 2, 1);           \
 275        if (mode & MD(19))                                      \
 276                SH_CLK_SET_RATIO(&pll3_clk_ratio, p31, 1);      \
 277        else                                                    \
 278                SH_CLK_SET_RATIO(&pll3_clk_ratio, p30, 1)
 279
 280
 281void __init r8a7790_clock_init(void)
 282{
 283        void __iomem *modemr = ioremap_nocache(MODEMR, PAGE_SIZE);
 284        u32 mode;
 285        int k, ret = 0;
 286
 287        BUG_ON(!modemr);
 288        mode = ioread32(modemr);
 289        iounmap(modemr);
 290
 291        switch (mode & (MD(14) | MD(13))) {
 292        case 0:
 293                R8A7790_CLOCK_ROOT(15, &extal_clk, 172, 208, 106, 88);
 294                break;
 295        case MD(13):
 296                R8A7790_CLOCK_ROOT(20, &extal_clk, 130, 156, 80, 66);
 297                break;
 298        case MD(14):
 299                R8A7790_CLOCK_ROOT(26, &extal_div2_clk, 200, 240, 122, 102);
 300                break;
 301        case MD(13) | MD(14):
 302                R8A7790_CLOCK_ROOT(30, &extal_div2_clk, 172, 208, 106, 88);
 303                break;
 304        }
 305
 306        if (mode & (MD(18)))
 307                SH_CLK_SET_RATIO(&lb_clk_ratio, 1, 36);
 308        else
 309                SH_CLK_SET_RATIO(&lb_clk_ratio, 1, 24);
 310
 311        if ((mode & (MD(3) | MD(2) | MD(1))) == MD(2))
 312                SH_CLK_SET_RATIO(&qspi_clk_ratio, 1, 16);
 313        else
 314                SH_CLK_SET_RATIO(&qspi_clk_ratio, 1, 20);
 315
 316        for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
 317                ret = clk_register(main_clks[k]);
 318
 319        if (!ret)
 320                ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
 321
 322        if (!ret)
 323                ret = sh_clk_div6_register(div6_clks, DIV6_NR);
 324
 325        if (!ret)
 326                ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
 327
 328        clkdev_add_table(lookups, ARRAY_SIZE(lookups));
 329
 330        if (!ret)
 331                shmobile_clk_init();
 332        else
 333                panic("failed to setup r8a7790 clocks\n");
 334}
 335