| rjw | 1f88458 | 2022-01-06 17:20:42 +0800 | [diff] [blame] | 1 | /* | 
|  | 2 | * Renesas Clock Pulse Generator / Module Standby and Software Reset | 
|  | 3 | * | 
|  | 4 | * Copyright (C) 2015 Glider bvba | 
|  | 5 | * | 
|  | 6 | * Based on clk-mstp.c, clk-rcar-gen2.c, and clk-rcar-gen3.c | 
|  | 7 | * | 
|  | 8 | * Copyright (C) 2013 Ideas On Board SPRL | 
|  | 9 | * Copyright (C) 2015 Renesas Electronics Corp. | 
|  | 10 | * | 
|  | 11 | * This program is free software; you can redistribute it and/or modify | 
|  | 12 | * it under the terms of the GNU General Public License as published by | 
|  | 13 | * the Free Software Foundation; version 2 of the License. | 
|  | 14 | */ | 
|  | 15 |  | 
|  | 16 | #include <linux/clk.h> | 
|  | 17 | #include <linux/clk-provider.h> | 
|  | 18 | #include <linux/clk/renesas.h> | 
|  | 19 | #include <linux/delay.h> | 
|  | 20 | #include <linux/device.h> | 
|  | 21 | #include <linux/init.h> | 
|  | 22 | #include <linux/mod_devicetable.h> | 
|  | 23 | #include <linux/module.h> | 
|  | 24 | #include <linux/of_address.h> | 
|  | 25 | #include <linux/of_device.h> | 
|  | 26 | #include <linux/platform_device.h> | 
|  | 27 | #include <linux/pm_clock.h> | 
|  | 28 | #include <linux/pm_domain.h> | 
|  | 29 | #include <linux/reset-controller.h> | 
|  | 30 | #include <linux/slab.h> | 
|  | 31 |  | 
|  | 32 | #include <dt-bindings/clock/renesas-cpg-mssr.h> | 
|  | 33 |  | 
|  | 34 | #include "renesas-cpg-mssr.h" | 
|  | 35 | #include "clk-div6.h" | 
|  | 36 |  | 
|  | 37 | #ifdef DEBUG | 
|  | 38 | #define WARN_DEBUG(x)	WARN_ON(x) | 
|  | 39 | #else | 
|  | 40 | #define WARN_DEBUG(x)	do { } while (0) | 
|  | 41 | #endif | 
|  | 42 |  | 
|  | 43 |  | 
|  | 44 | /* | 
|  | 45 | * Module Standby and Software Reset register offets. | 
|  | 46 | * | 
|  | 47 | * If the registers exist, these are valid for SH-Mobile, R-Mobile, | 
|  | 48 | * R-Car Gen2, R-Car Gen3, and RZ/G1. | 
|  | 49 | * These are NOT valid for R-Car Gen1 and RZ/A1! | 
|  | 50 | */ | 
|  | 51 |  | 
|  | 52 | /* | 
|  | 53 | * Module Stop Status Register offsets | 
|  | 54 | */ | 
|  | 55 |  | 
|  | 56 | static const u16 mstpsr[] = { | 
|  | 57 | 0x030, 0x038, 0x040, 0x048, 0x04C, 0x03C, 0x1C0, 0x1C4, | 
|  | 58 | 0x9A0, 0x9A4, 0x9A8, 0x9AC, | 
|  | 59 | }; | 
|  | 60 |  | 
|  | 61 | #define	MSTPSR(i)	mstpsr[i] | 
|  | 62 |  | 
|  | 63 |  | 
|  | 64 | /* | 
|  | 65 | * System Module Stop Control Register offsets | 
|  | 66 | */ | 
|  | 67 |  | 
|  | 68 | static const u16 smstpcr[] = { | 
|  | 69 | 0x130, 0x134, 0x138, 0x13C, 0x140, 0x144, 0x148, 0x14C, | 
|  | 70 | 0x990, 0x994, 0x998, 0x99C, | 
|  | 71 | }; | 
|  | 72 |  | 
|  | 73 | #define	SMSTPCR(i)	smstpcr[i] | 
|  | 74 |  | 
|  | 75 |  | 
|  | 76 | /* | 
|  | 77 | * Software Reset Register offsets | 
|  | 78 | */ | 
|  | 79 |  | 
|  | 80 | static const u16 srcr[] = { | 
|  | 81 | 0x0A0, 0x0A8, 0x0B0, 0x0B8, 0x0BC, 0x0C4, 0x1C8, 0x1CC, | 
|  | 82 | 0x920, 0x924, 0x928, 0x92C, | 
|  | 83 | }; | 
|  | 84 |  | 
|  | 85 | #define	SRCR(i)		srcr[i] | 
|  | 86 |  | 
|  | 87 |  | 
|  | 88 | /* Realtime Module Stop Control Register offsets */ | 
|  | 89 | #define RMSTPCR(i)	(smstpcr[i] - 0x20) | 
|  | 90 |  | 
|  | 91 | /* Modem Module Stop Control Register offsets (r8a73a4) */ | 
|  | 92 | #define MMSTPCR(i)	(smstpcr[i] + 0x20) | 
|  | 93 |  | 
|  | 94 | /* Software Reset Clearing Register offsets */ | 
|  | 95 | #define	SRSTCLR(i)	(0x940 + (i) * 4) | 
|  | 96 |  | 
|  | 97 |  | 
|  | 98 | /** | 
|  | 99 | * Clock Pulse Generator / Module Standby and Software Reset Private Data | 
|  | 100 | * | 
|  | 101 | * @rcdev: Optional reset controller entity | 
|  | 102 | * @dev: CPG/MSSR device | 
|  | 103 | * @base: CPG/MSSR register block base address | 
|  | 104 | * @rmw_lock: protects RMW register accesses | 
|  | 105 | * @clks: Array containing all Core and Module Clocks | 
|  | 106 | * @num_core_clks: Number of Core Clocks in clks[] | 
|  | 107 | * @num_mod_clks: Number of Module Clocks in clks[] | 
|  | 108 | * @last_dt_core_clk: ID of the last Core Clock exported to DT | 
|  | 109 | */ | 
|  | 110 | struct cpg_mssr_priv { | 
|  | 111 | #ifdef CONFIG_RESET_CONTROLLER | 
|  | 112 | struct reset_controller_dev rcdev; | 
|  | 113 | #endif | 
|  | 114 | struct device *dev; | 
|  | 115 | void __iomem *base; | 
|  | 116 | spinlock_t rmw_lock; | 
|  | 117 |  | 
|  | 118 | struct clk **clks; | 
|  | 119 | unsigned int num_core_clks; | 
|  | 120 | unsigned int num_mod_clks; | 
|  | 121 | unsigned int last_dt_core_clk; | 
|  | 122 | }; | 
|  | 123 |  | 
|  | 124 |  | 
|  | 125 | /** | 
|  | 126 | * struct mstp_clock - MSTP gating clock | 
|  | 127 | * @hw: handle between common and hardware-specific interfaces | 
|  | 128 | * @index: MSTP clock number | 
|  | 129 | * @priv: CPG/MSSR private data | 
|  | 130 | */ | 
|  | 131 | struct mstp_clock { | 
|  | 132 | struct clk_hw hw; | 
|  | 133 | u32 index; | 
|  | 134 | struct cpg_mssr_priv *priv; | 
|  | 135 | }; | 
|  | 136 |  | 
|  | 137 | #define to_mstp_clock(_hw) container_of(_hw, struct mstp_clock, hw) | 
|  | 138 |  | 
|  | 139 | static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable) | 
|  | 140 | { | 
|  | 141 | struct mstp_clock *clock = to_mstp_clock(hw); | 
|  | 142 | struct cpg_mssr_priv *priv = clock->priv; | 
|  | 143 | unsigned int reg = clock->index / 32; | 
|  | 144 | unsigned int bit = clock->index % 32; | 
|  | 145 | struct device *dev = priv->dev; | 
|  | 146 | u32 bitmask = BIT(bit); | 
|  | 147 | unsigned long flags; | 
|  | 148 | unsigned int i; | 
|  | 149 | u32 value; | 
|  | 150 |  | 
|  | 151 | dev_dbg(dev, "MSTP %u%02u/%pC %s\n", reg, bit, hw->clk, | 
|  | 152 | enable ? "ON" : "OFF"); | 
|  | 153 | spin_lock_irqsave(&priv->rmw_lock, flags); | 
|  | 154 |  | 
|  | 155 | value = readl(priv->base + SMSTPCR(reg)); | 
|  | 156 | if (enable) | 
|  | 157 | value &= ~bitmask; | 
|  | 158 | else | 
|  | 159 | value |= bitmask; | 
|  | 160 | writel(value, priv->base + SMSTPCR(reg)); | 
|  | 161 |  | 
|  | 162 | spin_unlock_irqrestore(&priv->rmw_lock, flags); | 
|  | 163 |  | 
|  | 164 | if (!enable) | 
|  | 165 | return 0; | 
|  | 166 |  | 
|  | 167 | for (i = 1000; i > 0; --i) { | 
|  | 168 | if (!(readl(priv->base + MSTPSR(reg)) & bitmask)) | 
|  | 169 | break; | 
|  | 170 | cpu_relax(); | 
|  | 171 | } | 
|  | 172 |  | 
|  | 173 | if (!i) { | 
|  | 174 | dev_err(dev, "Failed to enable SMSTP %p[%d]\n", | 
|  | 175 | priv->base + SMSTPCR(reg), bit); | 
|  | 176 | return -ETIMEDOUT; | 
|  | 177 | } | 
|  | 178 |  | 
|  | 179 | return 0; | 
|  | 180 | } | 
|  | 181 |  | 
|  | 182 | static int cpg_mstp_clock_enable(struct clk_hw *hw) | 
|  | 183 | { | 
|  | 184 | return cpg_mstp_clock_endisable(hw, true); | 
|  | 185 | } | 
|  | 186 |  | 
|  | 187 | static void cpg_mstp_clock_disable(struct clk_hw *hw) | 
|  | 188 | { | 
|  | 189 | cpg_mstp_clock_endisable(hw, false); | 
|  | 190 | } | 
|  | 191 |  | 
|  | 192 | static int cpg_mstp_clock_is_enabled(struct clk_hw *hw) | 
|  | 193 | { | 
|  | 194 | struct mstp_clock *clock = to_mstp_clock(hw); | 
|  | 195 | struct cpg_mssr_priv *priv = clock->priv; | 
|  | 196 | u32 value; | 
|  | 197 |  | 
|  | 198 | value = readl(priv->base + MSTPSR(clock->index / 32)); | 
|  | 199 |  | 
|  | 200 | return !(value & BIT(clock->index % 32)); | 
|  | 201 | } | 
|  | 202 |  | 
|  | 203 | static const struct clk_ops cpg_mstp_clock_ops = { | 
|  | 204 | .enable = cpg_mstp_clock_enable, | 
|  | 205 | .disable = cpg_mstp_clock_disable, | 
|  | 206 | .is_enabled = cpg_mstp_clock_is_enabled, | 
|  | 207 | }; | 
|  | 208 |  | 
|  | 209 | static | 
|  | 210 | struct clk *cpg_mssr_clk_src_twocell_get(struct of_phandle_args *clkspec, | 
|  | 211 | void *data) | 
|  | 212 | { | 
|  | 213 | unsigned int clkidx = clkspec->args[1]; | 
|  | 214 | struct cpg_mssr_priv *priv = data; | 
|  | 215 | struct device *dev = priv->dev; | 
|  | 216 | unsigned int idx; | 
|  | 217 | const char *type; | 
|  | 218 | struct clk *clk; | 
|  | 219 |  | 
|  | 220 | switch (clkspec->args[0]) { | 
|  | 221 | case CPG_CORE: | 
|  | 222 | type = "core"; | 
|  | 223 | if (clkidx > priv->last_dt_core_clk) { | 
|  | 224 | dev_err(dev, "Invalid %s clock index %u\n", type, | 
|  | 225 | clkidx); | 
|  | 226 | return ERR_PTR(-EINVAL); | 
|  | 227 | } | 
|  | 228 | clk = priv->clks[clkidx]; | 
|  | 229 | break; | 
|  | 230 |  | 
|  | 231 | case CPG_MOD: | 
|  | 232 | type = "module"; | 
|  | 233 | idx = MOD_CLK_PACK(clkidx); | 
|  | 234 | if (clkidx % 100 > 31 || idx >= priv->num_mod_clks) { | 
|  | 235 | dev_err(dev, "Invalid %s clock index %u\n", type, | 
|  | 236 | clkidx); | 
|  | 237 | return ERR_PTR(-EINVAL); | 
|  | 238 | } | 
|  | 239 | clk = priv->clks[priv->num_core_clks + idx]; | 
|  | 240 | break; | 
|  | 241 |  | 
|  | 242 | default: | 
|  | 243 | dev_err(dev, "Invalid CPG clock type %u\n", clkspec->args[0]); | 
|  | 244 | return ERR_PTR(-EINVAL); | 
|  | 245 | } | 
|  | 246 |  | 
|  | 247 | if (IS_ERR(clk)) | 
|  | 248 | dev_err(dev, "Cannot get %s clock %u: %ld", type, clkidx, | 
|  | 249 | PTR_ERR(clk)); | 
|  | 250 | else | 
|  | 251 | dev_dbg(dev, "clock (%u, %u) is %pC at %lu Hz\n", | 
|  | 252 | clkspec->args[0], clkspec->args[1], clk, | 
|  | 253 | clk_get_rate(clk)); | 
|  | 254 | return clk; | 
|  | 255 | } | 
|  | 256 |  | 
|  | 257 | static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core, | 
|  | 258 | const struct cpg_mssr_info *info, | 
|  | 259 | struct cpg_mssr_priv *priv) | 
|  | 260 | { | 
|  | 261 | struct clk *clk = ERR_PTR(-ENOTSUPP), *parent; | 
|  | 262 | struct device *dev = priv->dev; | 
|  | 263 | unsigned int id = core->id, div = core->div; | 
|  | 264 | const char *parent_name; | 
|  | 265 |  | 
|  | 266 | WARN_DEBUG(id >= priv->num_core_clks); | 
|  | 267 | WARN_DEBUG(PTR_ERR(priv->clks[id]) != -ENOENT); | 
|  | 268 |  | 
|  | 269 | if (!core->name) { | 
|  | 270 | /* Skip NULLified clock */ | 
|  | 271 | return; | 
|  | 272 | } | 
|  | 273 |  | 
|  | 274 | switch (core->type) { | 
|  | 275 | case CLK_TYPE_IN: | 
|  | 276 | clk = of_clk_get_by_name(priv->dev->of_node, core->name); | 
|  | 277 | break; | 
|  | 278 |  | 
|  | 279 | case CLK_TYPE_FF: | 
|  | 280 | case CLK_TYPE_DIV6P1: | 
|  | 281 | case CLK_TYPE_DIV6_RO: | 
|  | 282 | WARN_DEBUG(core->parent >= priv->num_core_clks); | 
|  | 283 | parent = priv->clks[core->parent]; | 
|  | 284 | if (IS_ERR(parent)) { | 
|  | 285 | clk = parent; | 
|  | 286 | goto fail; | 
|  | 287 | } | 
|  | 288 |  | 
|  | 289 | parent_name = __clk_get_name(parent); | 
|  | 290 |  | 
|  | 291 | if (core->type == CLK_TYPE_DIV6_RO) | 
|  | 292 | /* Multiply with the DIV6 register value */ | 
|  | 293 | div *= (readl(priv->base + core->offset) & 0x3f) + 1; | 
|  | 294 |  | 
|  | 295 | if (core->type == CLK_TYPE_DIV6P1) { | 
|  | 296 | clk = cpg_div6_register(core->name, 1, &parent_name, | 
|  | 297 | priv->base + core->offset); | 
|  | 298 | } else { | 
|  | 299 | clk = clk_register_fixed_factor(NULL, core->name, | 
|  | 300 | parent_name, 0, | 
|  | 301 | core->mult, div); | 
|  | 302 | } | 
|  | 303 | break; | 
|  | 304 |  | 
|  | 305 | default: | 
|  | 306 | if (info->cpg_clk_register) | 
|  | 307 | clk = info->cpg_clk_register(dev, core, info, | 
|  | 308 | priv->clks, priv->base); | 
|  | 309 | else | 
|  | 310 | dev_err(dev, "%s has unsupported core clock type %u\n", | 
|  | 311 | core->name, core->type); | 
|  | 312 | break; | 
|  | 313 | } | 
|  | 314 |  | 
|  | 315 | if (IS_ERR_OR_NULL(clk)) | 
|  | 316 | goto fail; | 
|  | 317 |  | 
|  | 318 | dev_dbg(dev, "Core clock %pC at %lu Hz\n", clk, clk_get_rate(clk)); | 
|  | 319 | priv->clks[id] = clk; | 
|  | 320 | return; | 
|  | 321 |  | 
|  | 322 | fail: | 
|  | 323 | dev_err(dev, "Failed to register %s clock %s: %ld\n", "core", | 
|  | 324 | core->name, PTR_ERR(clk)); | 
|  | 325 | } | 
|  | 326 |  | 
|  | 327 | static void __init cpg_mssr_register_mod_clk(const struct mssr_mod_clk *mod, | 
|  | 328 | const struct cpg_mssr_info *info, | 
|  | 329 | struct cpg_mssr_priv *priv) | 
|  | 330 | { | 
|  | 331 | struct mstp_clock *clock = NULL; | 
|  | 332 | struct device *dev = priv->dev; | 
|  | 333 | unsigned int id = mod->id; | 
|  | 334 | struct clk_init_data init; | 
|  | 335 | struct clk *parent, *clk; | 
|  | 336 | const char *parent_name; | 
|  | 337 | unsigned int i; | 
|  | 338 |  | 
|  | 339 | WARN_DEBUG(id < priv->num_core_clks); | 
|  | 340 | WARN_DEBUG(id >= priv->num_core_clks + priv->num_mod_clks); | 
|  | 341 | WARN_DEBUG(mod->parent >= priv->num_core_clks + priv->num_mod_clks); | 
|  | 342 | WARN_DEBUG(PTR_ERR(priv->clks[id]) != -ENOENT); | 
|  | 343 |  | 
|  | 344 | if (!mod->name) { | 
|  | 345 | /* Skip NULLified clock */ | 
|  | 346 | return; | 
|  | 347 | } | 
|  | 348 |  | 
|  | 349 | parent = priv->clks[mod->parent]; | 
|  | 350 | if (IS_ERR(parent)) { | 
|  | 351 | clk = parent; | 
|  | 352 | goto fail; | 
|  | 353 | } | 
|  | 354 |  | 
|  | 355 | clock = kzalloc(sizeof(*clock), GFP_KERNEL); | 
|  | 356 | if (!clock) { | 
|  | 357 | clk = ERR_PTR(-ENOMEM); | 
|  | 358 | goto fail; | 
|  | 359 | } | 
|  | 360 |  | 
|  | 361 | init.name = mod->name; | 
|  | 362 | init.ops = &cpg_mstp_clock_ops; | 
|  | 363 | init.flags = CLK_IS_BASIC | CLK_SET_RATE_PARENT; | 
|  | 364 | for (i = 0; i < info->num_crit_mod_clks; i++) | 
|  | 365 | if (id == info->crit_mod_clks[i]) { | 
|  | 366 | dev_dbg(dev, "MSTP %s setting CLK_IS_CRITICAL\n", | 
|  | 367 | mod->name); | 
|  | 368 | init.flags |= CLK_IS_CRITICAL; | 
|  | 369 | break; | 
|  | 370 | } | 
|  | 371 |  | 
|  | 372 | parent_name = __clk_get_name(parent); | 
|  | 373 | init.parent_names = &parent_name; | 
|  | 374 | init.num_parents = 1; | 
|  | 375 |  | 
|  | 376 | clock->index = id - priv->num_core_clks; | 
|  | 377 | clock->priv = priv; | 
|  | 378 | clock->hw.init = &init; | 
|  | 379 |  | 
|  | 380 | clk = clk_register(NULL, &clock->hw); | 
|  | 381 | if (IS_ERR(clk)) | 
|  | 382 | goto fail; | 
|  | 383 |  | 
|  | 384 | dev_dbg(dev, "Module clock %pC at %lu Hz\n", clk, clk_get_rate(clk)); | 
|  | 385 | priv->clks[id] = clk; | 
|  | 386 | return; | 
|  | 387 |  | 
|  | 388 | fail: | 
|  | 389 | dev_err(dev, "Failed to register %s clock %s: %ld\n", "module", | 
|  | 390 | mod->name, PTR_ERR(clk)); | 
|  | 391 | kfree(clock); | 
|  | 392 | } | 
|  | 393 |  | 
|  | 394 | struct cpg_mssr_clk_domain { | 
|  | 395 | struct generic_pm_domain genpd; | 
|  | 396 | struct device_node *np; | 
|  | 397 | unsigned int num_core_pm_clks; | 
|  | 398 | unsigned int core_pm_clks[0]; | 
|  | 399 | }; | 
|  | 400 |  | 
|  | 401 | static struct cpg_mssr_clk_domain *cpg_mssr_clk_domain; | 
|  | 402 |  | 
|  | 403 | static bool cpg_mssr_is_pm_clk(const struct of_phandle_args *clkspec, | 
|  | 404 | struct cpg_mssr_clk_domain *pd) | 
|  | 405 | { | 
|  | 406 | unsigned int i; | 
|  | 407 |  | 
|  | 408 | if (clkspec->np != pd->np || clkspec->args_count != 2) | 
|  | 409 | return false; | 
|  | 410 |  | 
|  | 411 | switch (clkspec->args[0]) { | 
|  | 412 | case CPG_CORE: | 
|  | 413 | for (i = 0; i < pd->num_core_pm_clks; i++) | 
|  | 414 | if (clkspec->args[1] == pd->core_pm_clks[i]) | 
|  | 415 | return true; | 
|  | 416 | return false; | 
|  | 417 |  | 
|  | 418 | case CPG_MOD: | 
|  | 419 | return true; | 
|  | 420 |  | 
|  | 421 | default: | 
|  | 422 | return false; | 
|  | 423 | } | 
|  | 424 | } | 
|  | 425 |  | 
|  | 426 | int cpg_mssr_attach_dev(struct generic_pm_domain *unused, struct device *dev) | 
|  | 427 | { | 
|  | 428 | struct cpg_mssr_clk_domain *pd = cpg_mssr_clk_domain; | 
|  | 429 | struct device_node *np = dev->of_node; | 
|  | 430 | struct of_phandle_args clkspec; | 
|  | 431 | struct clk *clk; | 
|  | 432 | int i = 0; | 
|  | 433 | int error; | 
|  | 434 |  | 
|  | 435 | if (!pd) { | 
|  | 436 | dev_dbg(dev, "CPG/MSSR clock domain not yet available\n"); | 
|  | 437 | return -EPROBE_DEFER; | 
|  | 438 | } | 
|  | 439 |  | 
|  | 440 | while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", i, | 
|  | 441 | &clkspec)) { | 
|  | 442 | if (cpg_mssr_is_pm_clk(&clkspec, pd)) | 
|  | 443 | goto found; | 
|  | 444 |  | 
|  | 445 | of_node_put(clkspec.np); | 
|  | 446 | i++; | 
|  | 447 | } | 
|  | 448 |  | 
|  | 449 | return 0; | 
|  | 450 |  | 
|  | 451 | found: | 
|  | 452 | clk = of_clk_get_from_provider(&clkspec); | 
|  | 453 | of_node_put(clkspec.np); | 
|  | 454 |  | 
|  | 455 | if (IS_ERR(clk)) | 
|  | 456 | return PTR_ERR(clk); | 
|  | 457 |  | 
|  | 458 | error = pm_clk_create(dev); | 
|  | 459 | if (error) { | 
|  | 460 | dev_err(dev, "pm_clk_create failed %d\n", error); | 
|  | 461 | goto fail_put; | 
|  | 462 | } | 
|  | 463 |  | 
|  | 464 | error = pm_clk_add_clk(dev, clk); | 
|  | 465 | if (error) { | 
|  | 466 | dev_err(dev, "pm_clk_add_clk %pC failed %d\n", clk, error); | 
|  | 467 | goto fail_destroy; | 
|  | 468 | } | 
|  | 469 |  | 
|  | 470 | return 0; | 
|  | 471 |  | 
|  | 472 | fail_destroy: | 
|  | 473 | pm_clk_destroy(dev); | 
|  | 474 | fail_put: | 
|  | 475 | clk_put(clk); | 
|  | 476 | return error; | 
|  | 477 | } | 
|  | 478 |  | 
|  | 479 | void cpg_mssr_detach_dev(struct generic_pm_domain *unused, struct device *dev) | 
|  | 480 | { | 
|  | 481 | if (!pm_clk_no_clocks(dev)) | 
|  | 482 | pm_clk_destroy(dev); | 
|  | 483 | } | 
|  | 484 |  | 
|  | 485 | static int __init cpg_mssr_add_clk_domain(struct device *dev, | 
|  | 486 | const unsigned int *core_pm_clks, | 
|  | 487 | unsigned int num_core_pm_clks) | 
|  | 488 | { | 
|  | 489 | struct device_node *np = dev->of_node; | 
|  | 490 | struct generic_pm_domain *genpd; | 
|  | 491 | struct cpg_mssr_clk_domain *pd; | 
|  | 492 | size_t pm_size = num_core_pm_clks * sizeof(core_pm_clks[0]); | 
|  | 493 |  | 
|  | 494 | pd = devm_kzalloc(dev, sizeof(*pd) + pm_size, GFP_KERNEL); | 
|  | 495 | if (!pd) | 
|  | 496 | return -ENOMEM; | 
|  | 497 |  | 
|  | 498 | pd->np = np; | 
|  | 499 | pd->num_core_pm_clks = num_core_pm_clks; | 
|  | 500 | memcpy(pd->core_pm_clks, core_pm_clks, pm_size); | 
|  | 501 |  | 
|  | 502 | genpd = &pd->genpd; | 
|  | 503 | genpd->name = np->name; | 
|  | 504 | genpd->flags = GENPD_FLAG_PM_CLK; | 
|  | 505 | genpd->attach_dev = cpg_mssr_attach_dev; | 
|  | 506 | genpd->detach_dev = cpg_mssr_detach_dev; | 
|  | 507 | pm_genpd_init(genpd, &pm_domain_always_on_gov, false); | 
|  | 508 | cpg_mssr_clk_domain = pd; | 
|  | 509 |  | 
|  | 510 | of_genpd_add_provider_simple(np, genpd); | 
|  | 511 | return 0; | 
|  | 512 | } | 
|  | 513 |  | 
|  | 514 | #ifdef CONFIG_RESET_CONTROLLER | 
|  | 515 |  | 
|  | 516 | #define rcdev_to_priv(x)	container_of(x, struct cpg_mssr_priv, rcdev) | 
|  | 517 |  | 
|  | 518 | static int cpg_mssr_reset(struct reset_controller_dev *rcdev, | 
|  | 519 | unsigned long id) | 
|  | 520 | { | 
|  | 521 | struct cpg_mssr_priv *priv = rcdev_to_priv(rcdev); | 
|  | 522 | unsigned int reg = id / 32; | 
|  | 523 | unsigned int bit = id % 32; | 
|  | 524 | u32 bitmask = BIT(bit); | 
|  | 525 |  | 
|  | 526 | dev_dbg(priv->dev, "reset %u%02u\n", reg, bit); | 
|  | 527 |  | 
|  | 528 | /* Reset module */ | 
|  | 529 | writel(bitmask, priv->base + SRCR(reg)); | 
|  | 530 |  | 
|  | 531 | /* Wait for at least one cycle of the RCLK clock (@ ca. 32 kHz) */ | 
|  | 532 | udelay(35); | 
|  | 533 |  | 
|  | 534 | /* Release module from reset state */ | 
|  | 535 | writel(bitmask, priv->base + SRSTCLR(reg)); | 
|  | 536 |  | 
|  | 537 | return 0; | 
|  | 538 | } | 
|  | 539 |  | 
|  | 540 | static int cpg_mssr_assert(struct reset_controller_dev *rcdev, unsigned long id) | 
|  | 541 | { | 
|  | 542 | struct cpg_mssr_priv *priv = rcdev_to_priv(rcdev); | 
|  | 543 | unsigned int reg = id / 32; | 
|  | 544 | unsigned int bit = id % 32; | 
|  | 545 | u32 bitmask = BIT(bit); | 
|  | 546 |  | 
|  | 547 | dev_dbg(priv->dev, "assert %u%02u\n", reg, bit); | 
|  | 548 |  | 
|  | 549 | writel(bitmask, priv->base + SRCR(reg)); | 
|  | 550 | return 0; | 
|  | 551 | } | 
|  | 552 |  | 
|  | 553 | static int cpg_mssr_deassert(struct reset_controller_dev *rcdev, | 
|  | 554 | unsigned long id) | 
|  | 555 | { | 
|  | 556 | struct cpg_mssr_priv *priv = rcdev_to_priv(rcdev); | 
|  | 557 | unsigned int reg = id / 32; | 
|  | 558 | unsigned int bit = id % 32; | 
|  | 559 | u32 bitmask = BIT(bit); | 
|  | 560 |  | 
|  | 561 | dev_dbg(priv->dev, "deassert %u%02u\n", reg, bit); | 
|  | 562 |  | 
|  | 563 | writel(bitmask, priv->base + SRSTCLR(reg)); | 
|  | 564 | return 0; | 
|  | 565 | } | 
|  | 566 |  | 
|  | 567 | static int cpg_mssr_status(struct reset_controller_dev *rcdev, | 
|  | 568 | unsigned long id) | 
|  | 569 | { | 
|  | 570 | struct cpg_mssr_priv *priv = rcdev_to_priv(rcdev); | 
|  | 571 | unsigned int reg = id / 32; | 
|  | 572 | unsigned int bit = id % 32; | 
|  | 573 | u32 bitmask = BIT(bit); | 
|  | 574 |  | 
|  | 575 | return !!(readl(priv->base + SRCR(reg)) & bitmask); | 
|  | 576 | } | 
|  | 577 |  | 
|  | 578 | static const struct reset_control_ops cpg_mssr_reset_ops = { | 
|  | 579 | .reset = cpg_mssr_reset, | 
|  | 580 | .assert = cpg_mssr_assert, | 
|  | 581 | .deassert = cpg_mssr_deassert, | 
|  | 582 | .status = cpg_mssr_status, | 
|  | 583 | }; | 
|  | 584 |  | 
|  | 585 | static int cpg_mssr_reset_xlate(struct reset_controller_dev *rcdev, | 
|  | 586 | const struct of_phandle_args *reset_spec) | 
|  | 587 | { | 
|  | 588 | struct cpg_mssr_priv *priv = rcdev_to_priv(rcdev); | 
|  | 589 | unsigned int unpacked = reset_spec->args[0]; | 
|  | 590 | unsigned int idx = MOD_CLK_PACK(unpacked); | 
|  | 591 |  | 
|  | 592 | if (unpacked % 100 > 31 || idx >= rcdev->nr_resets) { | 
|  | 593 | dev_err(priv->dev, "Invalid reset index %u\n", unpacked); | 
|  | 594 | return -EINVAL; | 
|  | 595 | } | 
|  | 596 |  | 
|  | 597 | return idx; | 
|  | 598 | } | 
|  | 599 |  | 
|  | 600 | static int cpg_mssr_reset_controller_register(struct cpg_mssr_priv *priv) | 
|  | 601 | { | 
|  | 602 | priv->rcdev.ops = &cpg_mssr_reset_ops; | 
|  | 603 | priv->rcdev.of_node = priv->dev->of_node; | 
|  | 604 | priv->rcdev.of_reset_n_cells = 1; | 
|  | 605 | priv->rcdev.of_xlate = cpg_mssr_reset_xlate; | 
|  | 606 | priv->rcdev.nr_resets = priv->num_mod_clks; | 
|  | 607 | return devm_reset_controller_register(priv->dev, &priv->rcdev); | 
|  | 608 | } | 
|  | 609 |  | 
|  | 610 | #else /* !CONFIG_RESET_CONTROLLER */ | 
|  | 611 | static inline int cpg_mssr_reset_controller_register(struct cpg_mssr_priv *priv) | 
|  | 612 | { | 
|  | 613 | return 0; | 
|  | 614 | } | 
|  | 615 | #endif /* !CONFIG_RESET_CONTROLLER */ | 
|  | 616 |  | 
|  | 617 |  | 
|  | 618 | static const struct of_device_id cpg_mssr_match[] = { | 
|  | 619 | #ifdef CONFIG_CLK_R8A7743 | 
|  | 620 | { | 
|  | 621 | .compatible = "renesas,r8a7743-cpg-mssr", | 
|  | 622 | .data = &r8a7743_cpg_mssr_info, | 
|  | 623 | }, | 
|  | 624 | #endif | 
|  | 625 | #ifdef CONFIG_CLK_R8A7745 | 
|  | 626 | { | 
|  | 627 | .compatible = "renesas,r8a7745-cpg-mssr", | 
|  | 628 | .data = &r8a7745_cpg_mssr_info, | 
|  | 629 | }, | 
|  | 630 | #endif | 
|  | 631 | #ifdef CONFIG_CLK_R8A7790 | 
|  | 632 | { | 
|  | 633 | .compatible = "renesas,r8a7790-cpg-mssr", | 
|  | 634 | .data = &r8a7790_cpg_mssr_info, | 
|  | 635 | }, | 
|  | 636 | #endif | 
|  | 637 | #ifdef CONFIG_CLK_R8A7791 | 
|  | 638 | { | 
|  | 639 | .compatible = "renesas,r8a7791-cpg-mssr", | 
|  | 640 | .data = &r8a7791_cpg_mssr_info, | 
|  | 641 | }, | 
|  | 642 | /* R-Car M2-N is (almost) identical to R-Car M2-W w.r.t. clocks. */ | 
|  | 643 | { | 
|  | 644 | .compatible = "renesas,r8a7793-cpg-mssr", | 
|  | 645 | .data = &r8a7791_cpg_mssr_info, | 
|  | 646 | }, | 
|  | 647 | #endif | 
|  | 648 | #ifdef CONFIG_CLK_R8A7792 | 
|  | 649 | { | 
|  | 650 | .compatible = "renesas,r8a7792-cpg-mssr", | 
|  | 651 | .data = &r8a7792_cpg_mssr_info, | 
|  | 652 | }, | 
|  | 653 | #endif | 
|  | 654 | #ifdef CONFIG_CLK_R8A7794 | 
|  | 655 | { | 
|  | 656 | .compatible = "renesas,r8a7794-cpg-mssr", | 
|  | 657 | .data = &r8a7794_cpg_mssr_info, | 
|  | 658 | }, | 
|  | 659 | #endif | 
|  | 660 | #ifdef CONFIG_CLK_R8A7795 | 
|  | 661 | { | 
|  | 662 | .compatible = "renesas,r8a7795-cpg-mssr", | 
|  | 663 | .data = &r8a7795_cpg_mssr_info, | 
|  | 664 | }, | 
|  | 665 | #endif | 
|  | 666 | #ifdef CONFIG_CLK_R8A7796 | 
|  | 667 | { | 
|  | 668 | .compatible = "renesas,r8a7796-cpg-mssr", | 
|  | 669 | .data = &r8a7796_cpg_mssr_info, | 
|  | 670 | }, | 
|  | 671 | #endif | 
|  | 672 | #ifdef CONFIG_CLK_R8A77995 | 
|  | 673 | { | 
|  | 674 | .compatible = "renesas,r8a77995-cpg-mssr", | 
|  | 675 | .data = &r8a77995_cpg_mssr_info, | 
|  | 676 | }, | 
|  | 677 | #endif | 
|  | 678 | { /* sentinel */ } | 
|  | 679 | }; | 
|  | 680 |  | 
|  | 681 | static void cpg_mssr_del_clk_provider(void *data) | 
|  | 682 | { | 
|  | 683 | of_clk_del_provider(data); | 
|  | 684 | } | 
|  | 685 |  | 
|  | 686 | static int __init cpg_mssr_probe(struct platform_device *pdev) | 
|  | 687 | { | 
|  | 688 | struct device *dev = &pdev->dev; | 
|  | 689 | struct device_node *np = dev->of_node; | 
|  | 690 | const struct cpg_mssr_info *info; | 
|  | 691 | struct cpg_mssr_priv *priv; | 
|  | 692 | unsigned int nclks, i; | 
|  | 693 | struct resource *res; | 
|  | 694 | struct clk **clks; | 
|  | 695 | int error; | 
|  | 696 |  | 
|  | 697 | info = of_device_get_match_data(dev); | 
|  | 698 | if (info->init) { | 
|  | 699 | error = info->init(dev); | 
|  | 700 | if (error) | 
|  | 701 | return error; | 
|  | 702 | } | 
|  | 703 |  | 
|  | 704 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | 
|  | 705 | if (!priv) | 
|  | 706 | return -ENOMEM; | 
|  | 707 |  | 
|  | 708 | priv->dev = dev; | 
|  | 709 | spin_lock_init(&priv->rmw_lock); | 
|  | 710 |  | 
|  | 711 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 
|  | 712 | priv->base = devm_ioremap_resource(dev, res); | 
|  | 713 | if (IS_ERR(priv->base)) | 
|  | 714 | return PTR_ERR(priv->base); | 
|  | 715 |  | 
|  | 716 | nclks = info->num_total_core_clks + info->num_hw_mod_clks; | 
|  | 717 | clks = devm_kmalloc_array(dev, nclks, sizeof(*clks), GFP_KERNEL); | 
|  | 718 | if (!clks) | 
|  | 719 | return -ENOMEM; | 
|  | 720 |  | 
|  | 721 | priv->clks = clks; | 
|  | 722 | priv->num_core_clks = info->num_total_core_clks; | 
|  | 723 | priv->num_mod_clks = info->num_hw_mod_clks; | 
|  | 724 | priv->last_dt_core_clk = info->last_dt_core_clk; | 
|  | 725 |  | 
|  | 726 | for (i = 0; i < nclks; i++) | 
|  | 727 | clks[i] = ERR_PTR(-ENOENT); | 
|  | 728 |  | 
|  | 729 | for (i = 0; i < info->num_core_clks; i++) | 
|  | 730 | cpg_mssr_register_core_clk(&info->core_clks[i], info, priv); | 
|  | 731 |  | 
|  | 732 | for (i = 0; i < info->num_mod_clks; i++) | 
|  | 733 | cpg_mssr_register_mod_clk(&info->mod_clks[i], info, priv); | 
|  | 734 |  | 
|  | 735 | error = of_clk_add_provider(np, cpg_mssr_clk_src_twocell_get, priv); | 
|  | 736 | if (error) | 
|  | 737 | return error; | 
|  | 738 |  | 
|  | 739 | error = devm_add_action_or_reset(dev, | 
|  | 740 | cpg_mssr_del_clk_provider, | 
|  | 741 | np); | 
|  | 742 | if (error) | 
|  | 743 | return error; | 
|  | 744 |  | 
|  | 745 | error = cpg_mssr_add_clk_domain(dev, info->core_pm_clks, | 
|  | 746 | info->num_core_pm_clks); | 
|  | 747 | if (error) | 
|  | 748 | return error; | 
|  | 749 |  | 
|  | 750 | error = cpg_mssr_reset_controller_register(priv); | 
|  | 751 | if (error) | 
|  | 752 | return error; | 
|  | 753 |  | 
|  | 754 | return 0; | 
|  | 755 | } | 
|  | 756 |  | 
|  | 757 | static struct platform_driver cpg_mssr_driver = { | 
|  | 758 | .driver		= { | 
|  | 759 | .name	= "renesas-cpg-mssr", | 
|  | 760 | .of_match_table = cpg_mssr_match, | 
|  | 761 | }, | 
|  | 762 | }; | 
|  | 763 |  | 
|  | 764 | static int __init cpg_mssr_init(void) | 
|  | 765 | { | 
|  | 766 | return platform_driver_probe(&cpg_mssr_driver, cpg_mssr_probe); | 
|  | 767 | } | 
|  | 768 |  | 
|  | 769 | subsys_initcall(cpg_mssr_init); | 
|  | 770 |  | 
|  | 771 | void __init cpg_core_nullify_range(struct cpg_core_clk *core_clks, | 
|  | 772 | unsigned int num_core_clks, | 
|  | 773 | unsigned int first_clk, | 
|  | 774 | unsigned int last_clk) | 
|  | 775 | { | 
|  | 776 | unsigned int i; | 
|  | 777 |  | 
|  | 778 | for (i = 0; i < num_core_clks; i++) | 
|  | 779 | if (core_clks[i].id >= first_clk && | 
|  | 780 | core_clks[i].id <= last_clk) | 
|  | 781 | core_clks[i].name = NULL; | 
|  | 782 | } | 
|  | 783 |  | 
|  | 784 | void __init mssr_mod_nullify(struct mssr_mod_clk *mod_clks, | 
|  | 785 | unsigned int num_mod_clks, | 
|  | 786 | const unsigned int *clks, unsigned int n) | 
|  | 787 | { | 
|  | 788 | unsigned int i, j; | 
|  | 789 |  | 
|  | 790 | for (i = 0, j = 0; i < num_mod_clks && j < n; i++) | 
|  | 791 | if (mod_clks[i].id == clks[j]) { | 
|  | 792 | mod_clks[i].name = NULL; | 
|  | 793 | j++; | 
|  | 794 | } | 
|  | 795 | } | 
|  | 796 |  | 
|  | 797 | void __init mssr_mod_reparent(struct mssr_mod_clk *mod_clks, | 
|  | 798 | unsigned int num_mod_clks, | 
|  | 799 | const struct mssr_mod_reparent *clks, | 
|  | 800 | unsigned int n) | 
|  | 801 | { | 
|  | 802 | unsigned int i, j; | 
|  | 803 |  | 
|  | 804 | for (i = 0, j = 0; i < num_mod_clks && j < n; i++) | 
|  | 805 | if (mod_clks[i].id == clks[j].clk) { | 
|  | 806 | mod_clks[i].parent = clks[j].parent; | 
|  | 807 | j++; | 
|  | 808 | } | 
|  | 809 | } | 
|  | 810 |  | 
|  | 811 | MODULE_DESCRIPTION("Renesas CPG/MSSR Driver"); | 
|  | 812 | MODULE_LICENSE("GPL v2"); |