1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2013 Samsung Electronics Co., Ltd. 4 * Copyright (c) 2013 Linaro Ltd. 5 * Author: Thomas Abraham <thomas.ab@samsung.com> 6 * 7 * This file includes utility functions to register clocks to common 8 * clock framework for Samsung platforms. 9 */ 10 11 #include <linux/slab.h> 12 #include <linux/clkdev.h> 13 #include <linux/clk-provider.h> 14 #include <linux/io.h> 15 #include <linux/mfd/syscon.h> 16 #include <linux/of_address.h> 17 #include <linux/regmap.h> 18 #include <linux/syscore_ops.h> 19 20 #include "clk.h" 21 22 static LIST_HEAD(clock_reg_cache_list); 23 24 void samsung_clk_save(void __iomem *base, 25 struct regmap *regmap, 26 struct samsung_clk_reg_dump *rd, 27 unsigned int num_regs) 28 { 29 for (; num_regs > 0; --num_regs, ++rd) { 30 if (base) 31 rd->value = readl(base + rd->offset); 32 else if (regmap) 33 regmap_read(regmap, rd->offset, &rd->value); 34 } 35 } 36 37 void samsung_clk_restore(void __iomem *base, 38 struct regmap *regmap, 39 const struct samsung_clk_reg_dump *rd, 40 unsigned int num_regs) 41 { 42 for (; num_regs > 0; --num_regs, ++rd) { 43 if (base) 44 writel(rd->value, base + rd->offset); 45 else if (regmap) 46 regmap_write(regmap, rd->offset, rd->value); 47 } 48 } 49 50 struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump( 51 const unsigned long *rdump, 52 unsigned long nr_rdump) 53 { 54 struct samsung_clk_reg_dump *rd; 55 unsigned int i; 56 57 rd = kzalloc_objs(*rd, nr_rdump); 58 if (!rd) 59 return NULL; 60 61 for (i = 0; i < nr_rdump; ++i) 62 rd[i].offset = rdump[i]; 63 64 return rd; 65 } 66 67 /** 68 * samsung_clk_init() - Create and initialize a clock provider object 69 * @dev: CMU device to enable runtime PM, or NULL if RPM is not needed 70 * @base: Start address (mapped) of CMU registers 71 * @nr_clks: Total clock count to allocate in clock provider object 72 * 73 * Setup the essentials required to support clock lookup using Common Clock 74 * Framework. 75 * 76 * Return: Allocated and initialized clock provider object. 77 */ 78 struct samsung_clk_provider * __init samsung_clk_init(struct device *dev, 79 void __iomem *base, unsigned long nr_clks) 80 { 81 struct samsung_clk_provider *ctx; 82 int i; 83 84 ctx = kzalloc_flex(*ctx, clk_data.hws, nr_clks); 85 if (!ctx) 86 panic("could not allocate clock provider context.\n"); 87 88 ctx->clk_data.num = nr_clks; 89 for (i = 0; i < nr_clks; ++i) 90 ctx->clk_data.hws[i] = ERR_PTR(-ENOENT); 91 92 ctx->dev = dev; 93 ctx->reg_base = base; 94 spin_lock_init(&ctx->lock); 95 96 return ctx; 97 } 98 99 void __init samsung_clk_of_add_provider(struct device_node *np, 100 struct samsung_clk_provider *ctx) 101 { 102 if (np) { 103 if (of_clk_add_hw_provider(np, of_clk_hw_onecell_get, 104 &ctx->clk_data)) 105 panic("could not register clk provider\n"); 106 } 107 } 108 109 /* add a clock instance to the clock lookup table used for dt based lookup */ 110 void samsung_clk_add_lookup(struct samsung_clk_provider *ctx, 111 struct clk_hw *clk_hw, unsigned int id) 112 { 113 if (id) 114 ctx->clk_data.hws[id] = clk_hw; 115 } 116 117 /* register a list of aliases */ 118 void __init samsung_clk_register_alias(struct samsung_clk_provider *ctx, 119 const struct samsung_clock_alias *list, 120 unsigned int nr_clk) 121 { 122 struct clk_hw *clk_hw; 123 unsigned int idx, ret; 124 125 for (idx = 0; idx < nr_clk; idx++, list++) { 126 if (!list->id) { 127 pr_err("%s: clock id missing for index %d\n", __func__, 128 idx); 129 continue; 130 } 131 132 clk_hw = ctx->clk_data.hws[list->id]; 133 if (!clk_hw) { 134 pr_err("%s: failed to find clock %d\n", __func__, 135 list->id); 136 continue; 137 } 138 139 ret = clk_hw_register_clkdev(clk_hw, list->alias, 140 list->dev_name); 141 if (ret) 142 pr_err("%s: failed to register lookup %s\n", 143 __func__, list->alias); 144 } 145 } 146 147 /* register a list of fixed clocks */ 148 void __init samsung_clk_register_fixed_rate(struct samsung_clk_provider *ctx, 149 const struct samsung_fixed_rate_clock *list, 150 unsigned int nr_clk) 151 { 152 struct clk_hw *clk_hw; 153 unsigned int idx; 154 155 for (idx = 0; idx < nr_clk; idx++, list++) { 156 clk_hw = clk_hw_register_fixed_rate(ctx->dev, list->name, 157 list->parent_name, list->flags, list->fixed_rate); 158 if (IS_ERR(clk_hw)) { 159 pr_err("%s: failed to register clock %s\n", __func__, 160 list->name); 161 continue; 162 } 163 164 samsung_clk_add_lookup(ctx, clk_hw, list->id); 165 } 166 } 167 168 /* register a list of fixed factor clocks */ 169 void __init samsung_clk_register_fixed_factor(struct samsung_clk_provider *ctx, 170 const struct samsung_fixed_factor_clock *list, unsigned int nr_clk) 171 { 172 struct clk_hw *clk_hw; 173 unsigned int idx; 174 175 for (idx = 0; idx < nr_clk; idx++, list++) { 176 clk_hw = clk_hw_register_fixed_factor(ctx->dev, list->name, 177 list->parent_name, list->flags, list->mult, list->div); 178 if (IS_ERR(clk_hw)) { 179 pr_err("%s: failed to register clock %s\n", __func__, 180 list->name); 181 continue; 182 } 183 184 samsung_clk_add_lookup(ctx, clk_hw, list->id); 185 } 186 } 187 188 /* register a list of mux clocks */ 189 void __init samsung_clk_register_mux(struct samsung_clk_provider *ctx, 190 const struct samsung_mux_clock *list, 191 unsigned int nr_clk) 192 { 193 struct clk_hw *clk_hw; 194 unsigned int idx; 195 196 for (idx = 0; idx < nr_clk; idx++, list++) { 197 clk_hw = clk_hw_register_mux(ctx->dev, list->name, 198 list->parent_names, list->num_parents, list->flags, 199 ctx->reg_base + list->offset, 200 list->shift, list->width, list->mux_flags, &ctx->lock); 201 if (IS_ERR(clk_hw)) { 202 pr_err("%s: failed to register clock %s\n", __func__, 203 list->name); 204 continue; 205 } 206 207 samsung_clk_add_lookup(ctx, clk_hw, list->id); 208 } 209 } 210 211 /* register a list of div clocks */ 212 void __init samsung_clk_register_div(struct samsung_clk_provider *ctx, 213 const struct samsung_div_clock *list, 214 unsigned int nr_clk) 215 { 216 struct clk_hw *clk_hw; 217 unsigned int idx; 218 219 for (idx = 0; idx < nr_clk; idx++, list++) { 220 if (list->table) 221 clk_hw = clk_hw_register_divider_table(ctx->dev, 222 list->name, list->parent_name, list->flags, 223 ctx->reg_base + list->offset, 224 list->shift, list->width, list->div_flags, 225 list->table, &ctx->lock); 226 else 227 clk_hw = clk_hw_register_divider(ctx->dev, list->name, 228 list->parent_name, list->flags, 229 ctx->reg_base + list->offset, list->shift, 230 list->width, list->div_flags, &ctx->lock); 231 if (IS_ERR(clk_hw)) { 232 pr_err("%s: failed to register clock %s\n", __func__, 233 list->name); 234 continue; 235 } 236 237 samsung_clk_add_lookup(ctx, clk_hw, list->id); 238 } 239 } 240 241 /* 242 * Some older DT's have an incorrect CMU resource size which is incompatible 243 * with the auto clock mode feature. In such cases we switch back to manual 244 * clock gating mode. 245 */ 246 bool samsung_is_auto_capable(struct device_node *np) 247 { 248 struct resource res; 249 resource_size_t size; 250 251 if (of_address_to_resource(np, 0, &res)) 252 return false; 253 254 size = resource_size(&res); 255 if (size != 0x10000) { 256 pr_warn("%pOF: incorrect res size for automatic clocks\n", np); 257 return false; 258 } 259 return true; 260 } 261 262 #define ACG_MSK GENMASK(6, 4) 263 #define CLK_IDLE GENMASK(5, 4) 264 static int samsung_auto_clk_gate_is_en(struct clk_hw *hw) 265 { 266 u32 reg; 267 struct clk_gate *gate = to_clk_gate(hw); 268 269 reg = readl(gate->reg); 270 return ((reg & ACG_MSK) == CLK_IDLE) ? 0 : 1; 271 } 272 273 /* enable and disable are nops in automatic clock mode */ 274 static int samsung_auto_clk_gate_en(struct clk_hw *hw) 275 { 276 return 0; 277 } 278 279 static void samsung_auto_clk_gate_dis(struct clk_hw *hw) 280 { 281 } 282 283 static const struct clk_ops samsung_auto_clk_gate_ops = { 284 .enable = samsung_auto_clk_gate_en, 285 .disable = samsung_auto_clk_gate_dis, 286 .is_enabled = samsung_auto_clk_gate_is_en, 287 }; 288 289 struct clk_hw *samsung_register_auto_gate(struct device *dev, 290 struct device_node *np, const char *name, 291 const char *parent_name, const struct clk_hw *parent_hw, 292 const struct clk_parent_data *parent_data, 293 unsigned long flags, 294 void __iomem *reg, u8 bit_idx, 295 u8 clk_gate_flags, spinlock_t *lock) 296 { 297 struct clk_gate *gate; 298 struct clk_hw *hw; 299 struct clk_init_data init = {}; 300 int ret = -EINVAL; 301 302 /* allocate the gate */ 303 gate = kzalloc_obj(*gate); 304 if (!gate) 305 return ERR_PTR(-ENOMEM); 306 307 init.name = name; 308 init.ops = &samsung_auto_clk_gate_ops; 309 init.flags = flags; 310 init.parent_names = parent_name ? &parent_name : NULL; 311 init.parent_hws = parent_hw ? &parent_hw : NULL; 312 init.parent_data = parent_data; 313 if (parent_name || parent_hw || parent_data) 314 init.num_parents = 1; 315 else 316 init.num_parents = 0; 317 318 /* struct clk_gate assignments */ 319 gate->reg = reg; 320 gate->bit_idx = bit_idx; 321 gate->flags = clk_gate_flags; 322 gate->lock = lock; 323 gate->hw.init = &init; 324 325 hw = &gate->hw; 326 if (dev || !np) 327 ret = clk_hw_register(dev, hw); 328 else if (np) 329 ret = of_clk_hw_register(np, hw); 330 if (ret) { 331 kfree(gate); 332 hw = ERR_PTR(ret); 333 } 334 335 return hw; 336 } 337 338 /* register a list of gate clocks */ 339 void __init samsung_clk_register_gate(struct samsung_clk_provider *ctx, 340 const struct samsung_gate_clock *list, 341 unsigned int nr_clk) 342 { 343 struct clk_hw *clk_hw; 344 unsigned int idx; 345 void __iomem *reg_offs; 346 347 for (idx = 0; idx < nr_clk; idx++, list++) { 348 reg_offs = ctx->reg_base + list->offset; 349 350 if (ctx->auto_clock_gate && ctx->gate_dbg_offset) 351 clk_hw = samsung_register_auto_gate(ctx->dev, NULL, 352 list->name, list->parent_name, NULL, NULL, 353 list->flags, reg_offs + ctx->gate_dbg_offset, 354 list->bit_idx, list->gate_flags, &ctx->lock); 355 else 356 clk_hw = clk_hw_register_gate(ctx->dev, list->name, 357 list->parent_name, list->flags, 358 ctx->reg_base + list->offset, list->bit_idx, 359 list->gate_flags, &ctx->lock); 360 if (IS_ERR(clk_hw)) { 361 pr_err("%s: failed to register clock %s: %pe\n", __func__, 362 list->name, clk_hw); 363 continue; 364 } 365 366 samsung_clk_add_lookup(ctx, clk_hw, list->id); 367 } 368 } 369 370 /* 371 * obtain the clock speed of all external fixed clock sources from device 372 * tree and register it 373 */ 374 void __init samsung_clk_of_register_fixed_ext(struct samsung_clk_provider *ctx, 375 struct samsung_fixed_rate_clock *fixed_rate_clk, 376 unsigned int nr_fixed_rate_clk, 377 const struct of_device_id *clk_matches) 378 { 379 const struct of_device_id *match; 380 struct device_node *clk_np; 381 u32 freq; 382 383 for_each_matching_node_and_match(clk_np, clk_matches, &match) { 384 if (of_property_read_u32(clk_np, "clock-frequency", &freq)) 385 continue; 386 fixed_rate_clk[(unsigned long)match->data].fixed_rate = freq; 387 } 388 samsung_clk_register_fixed_rate(ctx, fixed_rate_clk, nr_fixed_rate_clk); 389 } 390 391 #ifdef CONFIG_PM_SLEEP 392 static int samsung_clk_suspend(void *data) 393 { 394 struct samsung_clock_reg_cache *reg_cache; 395 396 list_for_each_entry(reg_cache, &clock_reg_cache_list, node) { 397 samsung_clk_save(reg_cache->reg_base, reg_cache->sysreg, 398 reg_cache->rdump, reg_cache->rd_num); 399 samsung_clk_restore(reg_cache->reg_base, reg_cache->sysreg, 400 reg_cache->rsuspend, 401 reg_cache->rsuspend_num); 402 } 403 return 0; 404 } 405 406 static void samsung_clk_resume(void *data) 407 { 408 struct samsung_clock_reg_cache *reg_cache; 409 410 list_for_each_entry(reg_cache, &clock_reg_cache_list, node) 411 samsung_clk_restore(reg_cache->reg_base, reg_cache->sysreg, 412 reg_cache->rdump, reg_cache->rd_num); 413 } 414 415 static const struct syscore_ops samsung_clk_syscore_ops = { 416 .suspend = samsung_clk_suspend, 417 .resume = samsung_clk_resume, 418 }; 419 420 static struct syscore samsung_clk_syscore = { 421 .ops = &samsung_clk_syscore_ops, 422 }; 423 424 void samsung_clk_extended_sleep_init(void __iomem *reg_base, 425 struct regmap *sysreg, 426 const unsigned long *rdump, 427 unsigned long nr_rdump, 428 const struct samsung_clk_reg_dump *rsuspend, 429 unsigned long nr_rsuspend) 430 { 431 struct samsung_clock_reg_cache *reg_cache; 432 int i; 433 434 reg_cache = kzalloc_flex(*reg_cache, rdump, nr_rdump); 435 if (!reg_cache) 436 panic("could not allocate register reg_cache.\n"); 437 438 reg_cache->rd_num = nr_rdump; 439 440 for (i = 0; i < nr_rdump; ++i) 441 reg_cache->rdump[i].offset = rdump[i]; 442 443 if (list_empty(&clock_reg_cache_list)) 444 register_syscore(&samsung_clk_syscore); 445 446 reg_cache->reg_base = reg_base; 447 reg_cache->sysreg = sysreg; 448 reg_cache->rsuspend = rsuspend; 449 reg_cache->rsuspend_num = nr_rsuspend; 450 list_add_tail(®_cache->node, &clock_reg_cache_list); 451 } 452 #endif 453 454 /** 455 * samsung_cmu_register_clocks() - Register all clocks provided in CMU object 456 * @ctx: Clock provider object 457 * @cmu: CMU object with clocks to register 458 * @np: CMU device tree node 459 */ 460 void __init samsung_cmu_register_clocks(struct samsung_clk_provider *ctx, 461 const struct samsung_cmu_info *cmu, 462 struct device_node *np) 463 { 464 if (cmu->auto_clock_gate && samsung_is_auto_capable(np)) 465 ctx->auto_clock_gate = cmu->auto_clock_gate; 466 467 ctx->gate_dbg_offset = cmu->gate_dbg_offset; 468 ctx->option_offset = cmu->option_offset; 469 ctx->drcg_offset = cmu->drcg_offset; 470 ctx->memclk_offset = cmu->memclk_offset; 471 472 if (cmu->pll_clks) 473 samsung_clk_register_pll(ctx, cmu->pll_clks, cmu->nr_pll_clks); 474 if (cmu->mux_clks) 475 samsung_clk_register_mux(ctx, cmu->mux_clks, cmu->nr_mux_clks); 476 if (cmu->div_clks) 477 samsung_clk_register_div(ctx, cmu->div_clks, cmu->nr_div_clks); 478 if (cmu->gate_clks) 479 samsung_clk_register_gate(ctx, cmu->gate_clks, 480 cmu->nr_gate_clks); 481 if (cmu->fixed_clks) 482 samsung_clk_register_fixed_rate(ctx, cmu->fixed_clks, 483 cmu->nr_fixed_clks); 484 if (cmu->fixed_factor_clks) 485 samsung_clk_register_fixed_factor(ctx, cmu->fixed_factor_clks, 486 cmu->nr_fixed_factor_clks); 487 if (cmu->cpu_clks) 488 samsung_clk_register_cpu(ctx, cmu->cpu_clks, cmu->nr_cpu_clks); 489 } 490 491 /* Each bit enable/disables DRCG of a bus component */ 492 #define DRCG_EN_MSK GENMASK(31, 0) 493 #define MEMCLK_EN BIT(0) 494 495 /* Enable Dynamic Root Clock Gating (DRCG) of bus components */ 496 void samsung_en_dyn_root_clk_gating(struct device_node *np, 497 struct samsung_clk_provider *ctx, 498 const struct samsung_cmu_info *cmu, 499 bool cmu_has_pm) 500 { 501 if (!ctx->auto_clock_gate) 502 return; 503 504 ctx->sysreg = syscon_regmap_lookup_by_phandle(np, "samsung,sysreg"); 505 if (IS_ERR(ctx->sysreg)) { 506 pr_warn("%pOF: Unable to get CMU sysreg\n", np); 507 ctx->sysreg = NULL; 508 } else { 509 /* Enable DRCG for all bus components */ 510 regmap_write(ctx->sysreg, ctx->drcg_offset, DRCG_EN_MSK); 511 /* Enable memclk gate (not present on all sysreg) */ 512 if (ctx->memclk_offset) 513 regmap_write_bits(ctx->sysreg, ctx->memclk_offset, 514 MEMCLK_EN, 0x0); 515 516 if (!cmu_has_pm) 517 /* 518 * When a CMU has PM support, clocks are saved/restored 519 * via its PM handlers, so only register them with the 520 * syscore suspend / resume paths if PM is not in use. 521 */ 522 samsung_clk_extended_sleep_init(NULL, ctx->sysreg, 523 cmu->sysreg_clk_regs, 524 cmu->nr_sysreg_clk_regs, 525 NULL, 0); 526 } 527 } 528 529 /* 530 * Common function which registers plls, muxes, dividers and gates 531 * for each CMU. It also add CMU register list to register cache. 532 */ 533 struct samsung_clk_provider * __init samsung_cmu_register_one( 534 struct device_node *np, 535 const struct samsung_cmu_info *cmu) 536 { 537 void __iomem *reg_base; 538 struct samsung_clk_provider *ctx; 539 540 reg_base = of_iomap(np, 0); 541 if (!reg_base) { 542 panic("%s: failed to map registers\n", __func__); 543 return NULL; 544 } 545 546 ctx = samsung_clk_init(NULL, reg_base, cmu->nr_clk_ids); 547 samsung_cmu_register_clocks(ctx, cmu, np); 548 549 if (cmu->clk_regs) 550 samsung_clk_extended_sleep_init(reg_base, NULL, 551 cmu->clk_regs, cmu->nr_clk_regs, 552 cmu->suspend_regs, cmu->nr_suspend_regs); 553 554 samsung_clk_of_add_provider(np, ctx); 555 556 /* sysreg DT nodes reference a clock in this CMU */ 557 samsung_en_dyn_root_clk_gating(np, ctx, cmu, false); 558 559 return ctx; 560 } 561