linux/drivers/clk/renesas/r8a779a0-cpg-mssr.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * r8a779a0 Clock Pulse Generator / Module Standby and Software Reset
   4 *
   5 * Copyright (C) 2020 Renesas Electronics Corp.
   6 *
   7 * Based on r8a7795-cpg-mssr.c
   8 *
   9 * Copyright (C) 2015 Glider bvba
  10 * Copyright (C) 2015 Renesas Electronics Corp.
  11 */
  12
  13#include <linux/bug.h>
  14#include <linux/bitfield.h>
  15#include <linux/clk.h>
  16#include <linux/clk-provider.h>
  17#include <linux/device.h>
  18#include <linux/err.h>
  19#include <linux/init.h>
  20#include <linux/io.h>
  21#include <linux/kernel.h>
  22#include <linux/pm.h>
  23#include <linux/slab.h>
  24#include <linux/soc/renesas/rcar-rst.h>
  25
  26#include <dt-bindings/clock/r8a779a0-cpg-mssr.h>
  27
  28#include "rcar-cpg-lib.h"
  29#include "renesas-cpg-mssr.h"
  30
  31enum rcar_r8a779a0_clk_types {
  32        CLK_TYPE_R8A779A0_MAIN = CLK_TYPE_CUSTOM,
  33        CLK_TYPE_R8A779A0_PLL1,
  34        CLK_TYPE_R8A779A0_PLL2X_3X,     /* PLL[23][01] */
  35        CLK_TYPE_R8A779A0_PLL5,
  36        CLK_TYPE_R8A779A0_SD,
  37        CLK_TYPE_R8A779A0_MDSEL,        /* Select parent/divider using mode pin */
  38        CLK_TYPE_R8A779A0_OSC,  /* OSC EXTAL predivider and fixed divider */
  39};
  40
  41struct rcar_r8a779a0_cpg_pll_config {
  42        u8 extal_div;
  43        u8 pll1_mult;
  44        u8 pll1_div;
  45        u8 pll5_mult;
  46        u8 pll5_div;
  47        u8 osc_prediv;
  48};
  49
  50enum clk_ids {
  51        /* Core Clock Outputs exported to DT */
  52        LAST_DT_CORE_CLK = R8A779A0_CLK_OSC,
  53
  54        /* External Input Clocks */
  55        CLK_EXTAL,
  56        CLK_EXTALR,
  57
  58        /* Internal Core Clocks */
  59        CLK_MAIN,
  60        CLK_PLL1,
  61        CLK_PLL20,
  62        CLK_PLL21,
  63        CLK_PLL30,
  64        CLK_PLL31,
  65        CLK_PLL5,
  66        CLK_PLL1_DIV2,
  67        CLK_PLL20_DIV2,
  68        CLK_PLL21_DIV2,
  69        CLK_PLL30_DIV2,
  70        CLK_PLL31_DIV2,
  71        CLK_PLL5_DIV2,
  72        CLK_PLL5_DIV4,
  73        CLK_S1,
  74        CLK_S3,
  75        CLK_SDSRC,
  76        CLK_RPCSRC,
  77        CLK_OCO,
  78
  79        /* Module Clocks */
  80        MOD_CLK_BASE
  81};
  82
  83#define DEF_PLL(_name, _id, _offset)    \
  84        DEF_BASE(_name, _id, CLK_TYPE_R8A779A0_PLL2X_3X, CLK_MAIN, \
  85                 .offset = _offset)
  86
  87#define DEF_SD(_name, _id, _parent, _offset)   \
  88        DEF_BASE(_name, _id, CLK_TYPE_R8A779A0_SD, _parent, .offset = _offset)
  89
  90#define DEF_MDSEL(_name, _id, _md, _parent0, _div0, _parent1, _div1) \
  91        DEF_BASE(_name, _id, CLK_TYPE_R8A779A0_MDSEL,   \
  92                 (_parent0) << 16 | (_parent1),         \
  93                 .div = (_div0) << 16 | (_div1), .offset = _md)
  94
  95#define DEF_OSC(_name, _id, _parent, _div)              \
  96        DEF_BASE(_name, _id, CLK_TYPE_R8A779A0_OSC, _parent, .div = _div)
  97
  98static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = {
  99        /* External Clock Inputs */
 100        DEF_INPUT("extal",  CLK_EXTAL),
 101        DEF_INPUT("extalr", CLK_EXTALR),
 102
 103        /* Internal Core Clocks */
 104        DEF_BASE(".main", CLK_MAIN,     CLK_TYPE_R8A779A0_MAIN, CLK_EXTAL),
 105        DEF_BASE(".pll1", CLK_PLL1,     CLK_TYPE_R8A779A0_PLL1, CLK_MAIN),
 106        DEF_BASE(".pll5", CLK_PLL5,     CLK_TYPE_R8A779A0_PLL5, CLK_MAIN),
 107        DEF_PLL(".pll20", CLK_PLL20,    0x0834),
 108        DEF_PLL(".pll21", CLK_PLL21,    0x0838),
 109        DEF_PLL(".pll30", CLK_PLL30,    0x083c),
 110        DEF_PLL(".pll31", CLK_PLL31,    0x0840),
 111
 112        DEF_FIXED(".pll1_div2",         CLK_PLL1_DIV2,  CLK_PLL1,       2, 1),
 113        DEF_FIXED(".pll20_div2",        CLK_PLL20_DIV2, CLK_PLL20,      2, 1),
 114        DEF_FIXED(".pll21_div2",        CLK_PLL21_DIV2, CLK_PLL21,      2, 1),
 115        DEF_FIXED(".pll30_div2",        CLK_PLL30_DIV2, CLK_PLL30,      2, 1),
 116        DEF_FIXED(".pll31_div2",        CLK_PLL31_DIV2, CLK_PLL31,      2, 1),
 117        DEF_FIXED(".pll5_div2",         CLK_PLL5_DIV2,  CLK_PLL5,       2, 1),
 118        DEF_FIXED(".pll5_div4",         CLK_PLL5_DIV4,  CLK_PLL5_DIV2,  2, 1),
 119        DEF_FIXED(".s1",                CLK_S1,         CLK_PLL1_DIV2,  2, 1),
 120        DEF_FIXED(".s3",                CLK_S3,         CLK_PLL1_DIV2,  4, 1),
 121        DEF_FIXED(".sdsrc",             CLK_SDSRC,      CLK_PLL5_DIV4,  1, 1),
 122        DEF_RATE(".oco",                CLK_OCO,        32768),
 123
 124        /* Core Clock Outputs */
 125        DEF_FIXED("zx",         R8A779A0_CLK_ZX,        CLK_PLL20_DIV2, 2, 1),
 126        DEF_FIXED("s1d1",       R8A779A0_CLK_S1D1,      CLK_S1,         1, 1),
 127        DEF_FIXED("s1d2",       R8A779A0_CLK_S1D2,      CLK_S1,         2, 1),
 128        DEF_FIXED("s1d4",       R8A779A0_CLK_S1D4,      CLK_S1,         4, 1),
 129        DEF_FIXED("s1d8",       R8A779A0_CLK_S1D8,      CLK_S1,         8, 1),
 130        DEF_FIXED("s1d12",      R8A779A0_CLK_S1D12,     CLK_S1,         12, 1),
 131        DEF_FIXED("s3d1",       R8A779A0_CLK_S3D1,      CLK_S3,         1, 1),
 132        DEF_FIXED("s3d2",       R8A779A0_CLK_S3D2,      CLK_S3,         2, 1),
 133        DEF_FIXED("s3d4",       R8A779A0_CLK_S3D4,      CLK_S3,         4, 1),
 134        DEF_FIXED("zs",         R8A779A0_CLK_ZS,        CLK_PLL1_DIV2,  4, 1),
 135        DEF_FIXED("zt",         R8A779A0_CLK_ZT,        CLK_PLL1_DIV2,  2, 1),
 136        DEF_FIXED("ztr",        R8A779A0_CLK_ZTR,       CLK_PLL1_DIV2,  2, 1),
 137        DEF_FIXED("zr",         R8A779A0_CLK_ZR,        CLK_PLL1_DIV2,  1, 1),
 138        DEF_FIXED("dsi",        R8A779A0_CLK_DSI,       CLK_PLL5_DIV4,  1, 1),
 139        DEF_FIXED("cnndsp",     R8A779A0_CLK_CNNDSP,    CLK_PLL5_DIV4,  1, 1),
 140        DEF_FIXED("vip",        R8A779A0_CLK_VIP,       CLK_PLL5,       5, 1),
 141        DEF_FIXED("adgh",       R8A779A0_CLK_ADGH,      CLK_PLL5_DIV4,  1, 1),
 142        DEF_FIXED("icu",        R8A779A0_CLK_ICU,       CLK_PLL5_DIV4,  2, 1),
 143        DEF_FIXED("icud2",      R8A779A0_CLK_ICUD2,     CLK_PLL5_DIV4,  4, 1),
 144        DEF_FIXED("vcbus",      R8A779A0_CLK_VCBUS,     CLK_PLL5_DIV4,  1, 1),
 145        DEF_FIXED("cbfusa",     R8A779A0_CLK_CBFUSA,    CLK_EXTAL,      2, 1),
 146        DEF_FIXED("cp",         R8A779A0_CLK_CP,        CLK_EXTAL,      2, 1),
 147        DEF_FIXED("cl16mck",    R8A779A0_CLK_CL16MCK,   CLK_PLL1_DIV2,  64, 1),
 148
 149        DEF_SD("sd0",           R8A779A0_CLK_SD0,       CLK_SDSRC,      0x870),
 150
 151        DEF_DIV6P1("mso",       R8A779A0_CLK_MSO,       CLK_PLL5_DIV4,  0x87c),
 152        DEF_DIV6P1("canfd",     R8A779A0_CLK_CANFD,     CLK_PLL5_DIV4,  0x878),
 153        DEF_DIV6P1("csi0",      R8A779A0_CLK_CSI0,      CLK_PLL5_DIV4,  0x880),
 154
 155        DEF_OSC("osc",          R8A779A0_CLK_OSC,       CLK_EXTAL,      8),
 156        DEF_MDSEL("r",          R8A779A0_CLK_R, 29, CLK_EXTALR, 1, CLK_OCO, 1),
 157};
 158
 159static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = {
 160        DEF_MOD("avb0",         211,    R8A779A0_CLK_S3D2),
 161        DEF_MOD("avb1",         212,    R8A779A0_CLK_S3D2),
 162        DEF_MOD("avb2",         213,    R8A779A0_CLK_S3D2),
 163        DEF_MOD("avb3",         214,    R8A779A0_CLK_S3D2),
 164        DEF_MOD("avb4",         215,    R8A779A0_CLK_S3D2),
 165        DEF_MOD("avb5",         216,    R8A779A0_CLK_S3D2),
 166        DEF_MOD("csi40",        331,    R8A779A0_CLK_CSI0),
 167        DEF_MOD("csi41",        400,    R8A779A0_CLK_CSI0),
 168        DEF_MOD("csi42",        401,    R8A779A0_CLK_CSI0),
 169        DEF_MOD("csi43",        402,    R8A779A0_CLK_CSI0),
 170        DEF_MOD("fcpvd0",       508,    R8A779A0_CLK_S3D1),
 171        DEF_MOD("fcpvd1",       509,    R8A779A0_CLK_S3D1),
 172        DEF_MOD("hscif0",       514,    R8A779A0_CLK_S1D2),
 173        DEF_MOD("hscif1",       515,    R8A779A0_CLK_S1D2),
 174        DEF_MOD("hscif2",       516,    R8A779A0_CLK_S1D2),
 175        DEF_MOD("hscif3",       517,    R8A779A0_CLK_S1D2),
 176        DEF_MOD("i2c0",         518,    R8A779A0_CLK_S1D4),
 177        DEF_MOD("i2c1",         519,    R8A779A0_CLK_S1D4),
 178        DEF_MOD("i2c2",         520,    R8A779A0_CLK_S1D4),
 179        DEF_MOD("i2c3",         521,    R8A779A0_CLK_S1D4),
 180        DEF_MOD("i2c4",         522,    R8A779A0_CLK_S1D4),
 181        DEF_MOD("i2c5",         523,    R8A779A0_CLK_S1D4),
 182        DEF_MOD("i2c6",         524,    R8A779A0_CLK_S1D4),
 183        DEF_MOD("ispcs0",       612,    R8A779A0_CLK_S1D1),
 184        DEF_MOD("ispcs1",       613,    R8A779A0_CLK_S1D1),
 185        DEF_MOD("ispcs2",       614,    R8A779A0_CLK_S1D1),
 186        DEF_MOD("ispcs3",       615,    R8A779A0_CLK_S1D1),
 187        DEF_MOD("msi0",         618,    R8A779A0_CLK_MSO),
 188        DEF_MOD("msi1",         619,    R8A779A0_CLK_MSO),
 189        DEF_MOD("msi2",         620,    R8A779A0_CLK_MSO),
 190        DEF_MOD("msi3",         621,    R8A779A0_CLK_MSO),
 191        DEF_MOD("msi4",         622,    R8A779A0_CLK_MSO),
 192        DEF_MOD("msi5",         623,    R8A779A0_CLK_MSO),
 193        DEF_MOD("scif0",        702,    R8A779A0_CLK_S1D8),
 194        DEF_MOD("scif1",        703,    R8A779A0_CLK_S1D8),
 195        DEF_MOD("scif3",        704,    R8A779A0_CLK_S1D8),
 196        DEF_MOD("scif4",        705,    R8A779A0_CLK_S1D8),
 197        DEF_MOD("sdhi0",        706,    R8A779A0_CLK_SD0),
 198        DEF_MOD("sydm1",        709,    R8A779A0_CLK_S1D2),
 199        DEF_MOD("sydm2",        710,    R8A779A0_CLK_S1D2),
 200        DEF_MOD("tmu0",         713,    R8A779A0_CLK_CL16MCK),
 201        DEF_MOD("tmu1",         714,    R8A779A0_CLK_S1D4),
 202        DEF_MOD("tmu2",         715,    R8A779A0_CLK_S1D4),
 203        DEF_MOD("tmu3",         716,    R8A779A0_CLK_S1D4),
 204        DEF_MOD("tmu4",         717,    R8A779A0_CLK_S1D4),
 205        DEF_MOD("vin00",        730,    R8A779A0_CLK_S1D1),
 206        DEF_MOD("vin01",        731,    R8A779A0_CLK_S1D1),
 207        DEF_MOD("vin02",        800,    R8A779A0_CLK_S1D1),
 208        DEF_MOD("vin03",        801,    R8A779A0_CLK_S1D1),
 209        DEF_MOD("vin04",        802,    R8A779A0_CLK_S1D1),
 210        DEF_MOD("vin05",        803,    R8A779A0_CLK_S1D1),
 211        DEF_MOD("vin06",        804,    R8A779A0_CLK_S1D1),
 212        DEF_MOD("vin07",        805,    R8A779A0_CLK_S1D1),
 213        DEF_MOD("vin10",        806,    R8A779A0_CLK_S1D1),
 214        DEF_MOD("vin11",        807,    R8A779A0_CLK_S1D1),
 215        DEF_MOD("vin12",        808,    R8A779A0_CLK_S1D1),
 216        DEF_MOD("vin13",        809,    R8A779A0_CLK_S1D1),
 217        DEF_MOD("vin14",        810,    R8A779A0_CLK_S1D1),
 218        DEF_MOD("vin15",        811,    R8A779A0_CLK_S1D1),
 219        DEF_MOD("vin16",        812,    R8A779A0_CLK_S1D1),
 220        DEF_MOD("vin17",        813,    R8A779A0_CLK_S1D1),
 221        DEF_MOD("vin20",        814,    R8A779A0_CLK_S1D1),
 222        DEF_MOD("vin21",        815,    R8A779A0_CLK_S1D1),
 223        DEF_MOD("vin22",        816,    R8A779A0_CLK_S1D1),
 224        DEF_MOD("vin23",        817,    R8A779A0_CLK_S1D1),
 225        DEF_MOD("vin24",        818,    R8A779A0_CLK_S1D1),
 226        DEF_MOD("vin25",        819,    R8A779A0_CLK_S1D1),
 227        DEF_MOD("vin26",        820,    R8A779A0_CLK_S1D1),
 228        DEF_MOD("vin27",        821,    R8A779A0_CLK_S1D1),
 229        DEF_MOD("vin30",        822,    R8A779A0_CLK_S1D1),
 230        DEF_MOD("vin31",        823,    R8A779A0_CLK_S1D1),
 231        DEF_MOD("vin32",        824,    R8A779A0_CLK_S1D1),
 232        DEF_MOD("vin33",        825,    R8A779A0_CLK_S1D1),
 233        DEF_MOD("vin34",        826,    R8A779A0_CLK_S1D1),
 234        DEF_MOD("vin35",        827,    R8A779A0_CLK_S1D1),
 235        DEF_MOD("vin36",        828,    R8A779A0_CLK_S1D1),
 236        DEF_MOD("vin37",        829,    R8A779A0_CLK_S1D1),
 237        DEF_MOD("vspd0",        830,    R8A779A0_CLK_S3D1),
 238        DEF_MOD("vspd1",        831,    R8A779A0_CLK_S3D1),
 239        DEF_MOD("rwdt",         907,    R8A779A0_CLK_R),
 240        DEF_MOD("cmt0",         910,    R8A779A0_CLK_R),
 241        DEF_MOD("cmt1",         911,    R8A779A0_CLK_R),
 242        DEF_MOD("cmt2",         912,    R8A779A0_CLK_R),
 243        DEF_MOD("cmt3",         913,    R8A779A0_CLK_R),
 244        DEF_MOD("pfc0",         915,    R8A779A0_CLK_CP),
 245        DEF_MOD("pfc1",         916,    R8A779A0_CLK_CP),
 246        DEF_MOD("pfc2",         917,    R8A779A0_CLK_CP),
 247        DEF_MOD("pfc3",         918,    R8A779A0_CLK_CP),
 248        DEF_MOD("tsc",          919,    R8A779A0_CLK_CL16MCK),
 249        DEF_MOD("vspx0",        1028,   R8A779A0_CLK_S1D1),
 250        DEF_MOD("vspx1",        1029,   R8A779A0_CLK_S1D1),
 251        DEF_MOD("vspx2",        1030,   R8A779A0_CLK_S1D1),
 252        DEF_MOD("vspx3",        1031,   R8A779A0_CLK_S1D1),
 253};
 254
 255static const struct rcar_r8a779a0_cpg_pll_config *cpg_pll_config __initdata;
 256static unsigned int cpg_clk_extalr __initdata;
 257static u32 cpg_mode __initdata;
 258
 259static struct clk * __init rcar_r8a779a0_cpg_clk_register(struct device *dev,
 260        const struct cpg_core_clk *core, const struct cpg_mssr_info *info,
 261        struct clk **clks, void __iomem *base,
 262        struct raw_notifier_head *notifiers)
 263{
 264        const struct clk *parent;
 265        unsigned int mult = 1;
 266        unsigned int div = 1;
 267        u32 value;
 268
 269        parent = clks[core->parent & 0xffff];   /* some types use high bits */
 270        if (IS_ERR(parent))
 271                return ERR_CAST(parent);
 272
 273        switch (core->type) {
 274        case CLK_TYPE_R8A779A0_MAIN:
 275                div = cpg_pll_config->extal_div;
 276                break;
 277
 278        case CLK_TYPE_R8A779A0_PLL1:
 279                mult = cpg_pll_config->pll1_mult;
 280                div = cpg_pll_config->pll1_div;
 281                break;
 282
 283        case CLK_TYPE_R8A779A0_PLL2X_3X:
 284                value = readl(base + core->offset);
 285                mult = (((value >> 24) & 0x7f) + 1) * 2;
 286                break;
 287
 288        case CLK_TYPE_R8A779A0_PLL5:
 289                mult = cpg_pll_config->pll5_mult;
 290                div = cpg_pll_config->pll5_div;
 291                break;
 292
 293        case CLK_TYPE_R8A779A0_SD:
 294                return cpg_sd_clk_register(core->name, base, core->offset,
 295                                           __clk_get_name(parent), notifiers,
 296                                           false);
 297                break;
 298
 299        case CLK_TYPE_R8A779A0_MDSEL:
 300                /*
 301                 * Clock selectable between two parents and two fixed dividers
 302                 * using a mode pin
 303                 */
 304                if (cpg_mode & BIT(core->offset)) {
 305                        div = core->div & 0xffff;
 306                } else {
 307                        parent = clks[core->parent >> 16];
 308                        if (IS_ERR(parent))
 309                                return ERR_CAST(parent);
 310                        div = core->div >> 16;
 311                }
 312                mult = 1;
 313                break;
 314
 315        case CLK_TYPE_R8A779A0_OSC:
 316                /*
 317                 * Clock combining OSC EXTAL predivider and a fixed divider
 318                 */
 319                div = cpg_pll_config->osc_prediv * core->div;
 320                break;
 321
 322        default:
 323                return ERR_PTR(-EINVAL);
 324        }
 325
 326        return clk_register_fixed_factor(NULL, core->name,
 327                                         __clk_get_name(parent), 0, mult, div);
 328}
 329
 330static const unsigned int r8a779a0_crit_mod_clks[] __initconst = {
 331        MOD_CLK_ID(907),        /* RWDT */
 332};
 333
 334/*
 335 * CPG Clock Data
 336 */
 337/*
 338 *   MD  EXTAL          PLL1    PLL20   PLL30   PLL4    PLL5    OSC
 339 * 14 13 (MHz)                     21      31
 340 * --------------------------------------------------------
 341 * 0  0  16.66 x 1      x128    x216    x128    x144    x192    /16
 342 * 0  1  20    x 1      x106    x180    x106    x120    x160    /19
 343 * 1  0  Prohibited setting
 344 * 1  1  33.33 / 2      x128    x216    x128    x144    x192    /32
 345 */
 346#define CPG_PLL_CONFIG_INDEX(md)        ((((md) & BIT(14)) >> 13) | \
 347                                         (((md) & BIT(13)) >> 13))
 348
 349static const struct rcar_r8a779a0_cpg_pll_config cpg_pll_configs[4] = {
 350        /* EXTAL div    PLL1 mult/div   PLL5 mult/div   OSC prediv */
 351        { 1,            128,    1,      192,    1,      16,     },
 352        { 1,            106,    1,      160,    1,      19,     },
 353        { 0,            0,      0,      0,      0,      0,      },
 354        { 2,            128,    1,      192,    1,      32,     },
 355};
 356
 357static int __init r8a779a0_cpg_mssr_init(struct device *dev)
 358{
 359        int error;
 360
 361        error = rcar_rst_read_mode_pins(&cpg_mode);
 362        if (error)
 363                return error;
 364
 365        cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
 366        cpg_clk_extalr = CLK_EXTALR;
 367        spin_lock_init(&cpg_lock);
 368
 369        return 0;
 370}
 371
 372const struct cpg_mssr_info r8a779a0_cpg_mssr_info __initconst = {
 373        /* Core Clocks */
 374        .core_clks = r8a779a0_core_clks,
 375        .num_core_clks = ARRAY_SIZE(r8a779a0_core_clks),
 376        .last_dt_core_clk = LAST_DT_CORE_CLK,
 377        .num_total_core_clks = MOD_CLK_BASE,
 378
 379        /* Module Clocks */
 380        .mod_clks = r8a779a0_mod_clks,
 381        .num_mod_clks = ARRAY_SIZE(r8a779a0_mod_clks),
 382        .num_hw_mod_clks = 15 * 32,
 383
 384        /* Critical Module Clocks */
 385        .crit_mod_clks          = r8a779a0_crit_mod_clks,
 386        .num_crit_mod_clks      = ARRAY_SIZE(r8a779a0_crit_mod_clks),
 387
 388        /* Callbacks */
 389        .init = r8a779a0_cpg_mssr_init,
 390        .cpg_clk_register = rcar_r8a779a0_cpg_clk_register,
 391
 392        .reg_layout = CLK_REG_LAYOUT_RCAR_V3U,
 393};
 394
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.