1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Renesas RCar Gen3 CPG MSSR driver 4 * 5 * Copyright (C) 2017 Marek Vasut <marek.vasut@gmail.com> 6 * 7 * Based on the following driver from Linux kernel: 8 * r8a7796 Clock Pulse Generator / Module Standby and Software Reset 9 * 10 * Copyright (C) 2016 Glider bvba 11 */ 12 13 #include <common.h> 14 #include <clk-uclass.h> 15 #include <dm.h> 16 #include <errno.h> 17 #include <wait_bit.h> 18 #include <asm/io.h> 19 20 #include <dt-bindings/clock/renesas-cpg-mssr.h> 21 22 #include "renesas-cpg-mssr.h" 23 #include "rcar-gen3-cpg.h" 24 25 #define CPG_RST_MODEMR 0x0060 26 27 #define CPG_PLL0CR 0x00d8 28 #define CPG_PLL2CR 0x002c 29 #define CPG_PLL4CR 0x01f4 30 31 #define CPG_RPC_PREDIV_MASK 0x3 32 #define CPG_RPC_PREDIV_OFFSET 3 33 #define CPG_RPC_POSTDIV_MASK 0x7 34 #define CPG_RPC_POSTDIV_OFFSET 0 35 36 /* 37 * SDn Clock 38 */ 39 #define CPG_SD_STP_HCK BIT(9) 40 #define CPG_SD_STP_CK BIT(8) 41 42 #define CPG_SD_STP_MASK (CPG_SD_STP_HCK | CPG_SD_STP_CK) 43 #define CPG_SD_FC_MASK (0x7 << 2 | 0x3 << 0) 44 45 #define CPG_SD_DIV_TABLE_DATA(stp_hck, stp_ck, sd_srcfc, sd_fc, sd_div) \ 46 { \ 47 .val = ((stp_hck) ? CPG_SD_STP_HCK : 0) | \ 48 ((stp_ck) ? CPG_SD_STP_CK : 0) | \ 49 ((sd_srcfc) << 2) | \ 50 ((sd_fc) << 0), \ 51 .div = (sd_div), \ 52 } 53 54 struct sd_div_table { 55 u32 val; 56 unsigned int div; 57 }; 58 59 /* SDn divider 60 * sd_srcfc sd_fc div 61 * stp_hck stp_ck (div) (div) = sd_srcfc x sd_fc 62 *------------------------------------------------------------------- 63 * 0 0 0 (1) 1 (4) 4 64 * 0 0 1 (2) 1 (4) 8 65 * 1 0 2 (4) 1 (4) 16 66 * 1 0 3 (8) 1 (4) 32 67 * 1 0 4 (16) 1 (4) 64 68 * 0 0 0 (1) 0 (2) 2 69 * 0 0 1 (2) 0 (2) 4 70 * 1 0 2 (4) 0 (2) 8 71 * 1 0 3 (8) 0 (2) 16 72 * 1 0 4 (16) 0 (2) 32 73 */ 74 static const struct sd_div_table cpg_sd_div_table[] = { 75 /* CPG_SD_DIV_TABLE_DATA(stp_hck, stp_ck, sd_srcfc, sd_fc, sd_div) */ 76 CPG_SD_DIV_TABLE_DATA(0, 0, 0, 1, 4), 77 CPG_SD_DIV_TABLE_DATA(0, 0, 1, 1, 8), 78 CPG_SD_DIV_TABLE_DATA(1, 0, 2, 1, 16), 79 CPG_SD_DIV_TABLE_DATA(1, 0, 3, 1, 32), 80 CPG_SD_DIV_TABLE_DATA(1, 0, 4, 1, 64), 81 CPG_SD_DIV_TABLE_DATA(0, 0, 0, 0, 2), 82 CPG_SD_DIV_TABLE_DATA(0, 0, 1, 0, 4), 83 CPG_SD_DIV_TABLE_DATA(1, 0, 2, 0, 8), 84 CPG_SD_DIV_TABLE_DATA(1, 0, 3, 0, 16), 85 CPG_SD_DIV_TABLE_DATA(1, 0, 4, 0, 32), 86 }; 87 88 static int gen3_clk_get_parent(struct gen3_clk_priv *priv, struct clk *clk, 89 struct cpg_mssr_info *info, struct clk *parent) 90 { 91 const struct cpg_core_clk *core; 92 int ret; 93 94 if (!renesas_clk_is_mod(clk)) { 95 ret = renesas_clk_get_core(clk, info, &core); 96 if (ret) 97 return ret; 98 99 if (core->type == CLK_TYPE_GEN3_PE) { 100 parent->dev = clk->dev; 101 parent->id = core->parent >> (priv->sscg ? 16 : 0); 102 parent->id &= 0xffff; 103 return 0; 104 } 105 } 106 107 return renesas_clk_get_parent(clk, info, parent); 108 } 109 110 static int gen3_clk_setup_sdif_div(struct clk *clk) 111 { 112 struct gen3_clk_priv *priv = dev_get_priv(clk->dev); 113 struct cpg_mssr_info *info = priv->info; 114 const struct cpg_core_clk *core; 115 struct clk parent; 116 int ret; 117 118 ret = gen3_clk_get_parent(priv, clk, info, &parent); 119 if (ret) { 120 printf("%s[%i] parent fail, ret=%i\n", __func__, __LINE__, ret); 121 return ret; 122 } 123 124 if (renesas_clk_is_mod(&parent)) 125 return 0; 126 127 ret = renesas_clk_get_core(&parent, info, &core); 128 if (ret) 129 return ret; 130 131 if (core->type != CLK_TYPE_GEN3_SD) 132 return 0; 133 134 debug("%s[%i] SDIF offset=%x\n", __func__, __LINE__, core->offset); 135 136 writel(1, priv->base + core->offset); 137 138 return 0; 139 } 140 141 static int gen3_clk_enable(struct clk *clk) 142 { 143 struct gen3_clk_priv *priv = dev_get_priv(clk->dev); 144 int ret = gen3_clk_setup_sdif_div(clk); 145 146 if (ret) 147 return ret; 148 149 return renesas_clk_endisable(clk, priv->base, true); 150 } 151 152 static int gen3_clk_disable(struct clk *clk) 153 { 154 struct gen3_clk_priv *priv = dev_get_priv(clk->dev); 155 156 return renesas_clk_endisable(clk, priv->base, false); 157 } 158 159 static u64 gen3_clk_get_rate64(struct clk *clk) 160 { 161 struct gen3_clk_priv *priv = dev_get_priv(clk->dev); 162 struct cpg_mssr_info *info = priv->info; 163 struct clk parent; 164 const struct cpg_core_clk *core; 165 const struct rcar_gen3_cpg_pll_config *pll_config = 166 priv->cpg_pll_config; 167 u32 value, mult, div, prediv, postdiv; 168 u64 rate = 0; 169 int i, ret; 170 171 debug("%s[%i] Clock: id=%lu\n", __func__, __LINE__, clk->id); 172 173 ret = gen3_clk_get_parent(priv, clk, info, &parent); 174 if (ret) { 175 printf("%s[%i] parent fail, ret=%i\n", __func__, __LINE__, ret); 176 return ret; 177 } 178 179 if (renesas_clk_is_mod(clk)) { 180 rate = gen3_clk_get_rate64(&parent); 181 debug("%s[%i] MOD clk: parent=%lu => rate=%llu\n", 182 __func__, __LINE__, parent.id, rate); 183 return rate; 184 } 185 186 ret = renesas_clk_get_core(clk, info, &core); 187 if (ret) 188 return ret; 189 190 switch (core->type) { 191 case CLK_TYPE_IN: 192 if (core->id == info->clk_extal_id) { 193 rate = clk_get_rate(&priv->clk_extal); 194 debug("%s[%i] EXTAL clk: rate=%llu\n", 195 __func__, __LINE__, rate); 196 return rate; 197 } 198 199 if (core->id == info->clk_extalr_id) { 200 rate = clk_get_rate(&priv->clk_extalr); 201 debug("%s[%i] EXTALR clk: rate=%llu\n", 202 __func__, __LINE__, rate); 203 return rate; 204 } 205 206 return -EINVAL; 207 208 case CLK_TYPE_GEN3_MAIN: 209 rate = gen3_clk_get_rate64(&parent) / pll_config->extal_div; 210 debug("%s[%i] MAIN clk: parent=%i extal_div=%i => rate=%llu\n", 211 __func__, __LINE__, 212 core->parent, pll_config->extal_div, rate); 213 return rate; 214 215 case CLK_TYPE_GEN3_PLL0: 216 value = readl(priv->base + CPG_PLL0CR); 217 mult = (((value >> 24) & 0x7f) + 1) * 2; 218 rate = gen3_clk_get_rate64(&parent) * mult; 219 debug("%s[%i] PLL0 clk: parent=%i mult=%u => rate=%llu\n", 220 __func__, __LINE__, core->parent, mult, rate); 221 return rate; 222 223 case CLK_TYPE_GEN3_PLL1: 224 rate = gen3_clk_get_rate64(&parent) * pll_config->pll1_mult; 225 rate /= pll_config->pll1_div; 226 debug("%s[%i] PLL1 clk: parent=%i mul=%i div=%i => rate=%llu\n", 227 __func__, __LINE__, 228 core->parent, pll_config->pll1_mult, 229 pll_config->pll1_div, rate); 230 return rate; 231 232 case CLK_TYPE_GEN3_PLL2: 233 value = readl(priv->base + CPG_PLL2CR); 234 mult = (((value >> 24) & 0x7f) + 1) * 2; 235 rate = gen3_clk_get_rate64(&parent) * mult; 236 debug("%s[%i] PLL2 clk: parent=%i mult=%u => rate=%llu\n", 237 __func__, __LINE__, core->parent, mult, rate); 238 return rate; 239 240 case CLK_TYPE_GEN3_PLL3: 241 rate = gen3_clk_get_rate64(&parent) * pll_config->pll3_mult; 242 rate /= pll_config->pll3_div; 243 debug("%s[%i] PLL3 clk: parent=%i mul=%i div=%i => rate=%llu\n", 244 __func__, __LINE__, 245 core->parent, pll_config->pll3_mult, 246 pll_config->pll3_div, rate); 247 return rate; 248 249 case CLK_TYPE_GEN3_PLL4: 250 value = readl(priv->base + CPG_PLL4CR); 251 mult = (((value >> 24) & 0x7f) + 1) * 2; 252 rate = gen3_clk_get_rate64(&parent) * mult; 253 debug("%s[%i] PLL4 clk: parent=%i mult=%u => rate=%llu\n", 254 __func__, __LINE__, core->parent, mult, rate); 255 return rate; 256 257 case CLK_TYPE_FF: 258 rate = (gen3_clk_get_rate64(&parent) * core->mult) / core->div; 259 debug("%s[%i] FIXED clk: parent=%i mul=%i div=%i => rate=%llu\n", 260 __func__, __LINE__, 261 core->parent, core->mult, core->div, rate); 262 return rate; 263 264 case CLK_TYPE_GEN3_PE: 265 div = (core->div >> (priv->sscg ? 16 : 0)) & 0xffff; 266 rate = gen3_clk_get_rate64(&parent) / div; 267 debug("%s[%i] PE clk: parent=%i div=%u => rate=%llu\n", 268 __func__, __LINE__, 269 (core->parent >> (priv->sscg ? 16 : 0)) & 0xffff, 270 div, rate); 271 return rate; 272 273 case CLK_TYPE_GEN3_SD: /* FIXME */ 274 value = readl(priv->base + core->offset); 275 value &= CPG_SD_STP_MASK | CPG_SD_FC_MASK; 276 277 for (i = 0; i < ARRAY_SIZE(cpg_sd_div_table); i++) { 278 if (cpg_sd_div_table[i].val != value) 279 continue; 280 281 rate = gen3_clk_get_rate64(&parent) / 282 cpg_sd_div_table[i].div; 283 debug("%s[%i] SD clk: parent=%i div=%i => rate=%llu\n", 284 __func__, __LINE__, 285 core->parent, cpg_sd_div_table[i].div, rate); 286 287 return rate; 288 } 289 290 return -EINVAL; 291 292 case CLK_TYPE_GEN3_RPC: 293 rate = gen3_clk_get_rate64(&parent); 294 295 value = readl(priv->base + core->offset); 296 297 prediv = (value >> CPG_RPC_PREDIV_OFFSET) & 298 CPG_RPC_PREDIV_MASK; 299 if (prediv == 2) 300 rate /= 5; 301 else if (prediv == 3) 302 rate /= 6; 303 else 304 return -EINVAL; 305 306 postdiv = (value >> CPG_RPC_POSTDIV_OFFSET) & 307 CPG_RPC_POSTDIV_MASK; 308 rate /= postdiv + 1; 309 310 debug("%s[%i] RPC clk: parent=%i prediv=%i postdiv=%i => rate=%llu\n", 311 __func__, __LINE__, 312 core->parent, prediv, postdiv, rate); 313 314 return -EINVAL; 315 316 } 317 318 printf("%s[%i] unknown fail\n", __func__, __LINE__); 319 320 return -ENOENT; 321 } 322 323 static ulong gen3_clk_get_rate(struct clk *clk) 324 { 325 return gen3_clk_get_rate64(clk); 326 } 327 328 static ulong gen3_clk_set_rate(struct clk *clk, ulong rate) 329 { 330 /* Force correct SD-IF divider configuration if applicable */ 331 gen3_clk_setup_sdif_div(clk); 332 return gen3_clk_get_rate64(clk); 333 } 334 335 static int gen3_clk_of_xlate(struct clk *clk, struct ofnode_phandle_args *args) 336 { 337 if (args->args_count != 2) { 338 debug("Invaild args_count: %d\n", args->args_count); 339 return -EINVAL; 340 } 341 342 clk->id = (args->args[0] << 16) | args->args[1]; 343 344 return 0; 345 } 346 347 const struct clk_ops gen3_clk_ops = { 348 .enable = gen3_clk_enable, 349 .disable = gen3_clk_disable, 350 .get_rate = gen3_clk_get_rate, 351 .set_rate = gen3_clk_set_rate, 352 .of_xlate = gen3_clk_of_xlate, 353 }; 354 355 int gen3_clk_probe(struct udevice *dev) 356 { 357 struct gen3_clk_priv *priv = dev_get_priv(dev); 358 struct cpg_mssr_info *info = 359 (struct cpg_mssr_info *)dev_get_driver_data(dev); 360 fdt_addr_t rst_base; 361 u32 cpg_mode; 362 int ret; 363 364 priv->base = (struct gen3_base *)devfdt_get_addr(dev); 365 if (!priv->base) 366 return -EINVAL; 367 368 priv->info = info; 369 ret = fdt_node_offset_by_compatible(gd->fdt_blob, -1, info->reset_node); 370 if (ret < 0) 371 return ret; 372 373 rst_base = fdtdec_get_addr(gd->fdt_blob, ret, "reg"); 374 if (rst_base == FDT_ADDR_T_NONE) 375 return -EINVAL; 376 377 cpg_mode = readl(rst_base + CPG_RST_MODEMR); 378 379 priv->cpg_pll_config = 380 (struct rcar_gen3_cpg_pll_config *)info->get_pll_config(cpg_mode); 381 if (!priv->cpg_pll_config->extal_div) 382 return -EINVAL; 383 384 priv->sscg = !(cpg_mode & BIT(12)); 385 386 ret = clk_get_by_name(dev, "extal", &priv->clk_extal); 387 if (ret < 0) 388 return ret; 389 390 if (info->extalr_node) { 391 ret = clk_get_by_name(dev, info->extalr_node, &priv->clk_extalr); 392 if (ret < 0) 393 return ret; 394 } 395 396 return 0; 397 } 398 399 int gen3_clk_remove(struct udevice *dev) 400 { 401 struct gen3_clk_priv *priv = dev_get_priv(dev); 402 403 return renesas_clk_remove(priv->base, priv->info); 404 } 405