1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * JZ47xx SoCs TCU clocks driver 4 * Copyright (C) 2019 Paul Cercueil <paul@crapouillou.net> 5 */ 6 7 #include <linux/clk.h> 8 #include <linux/clk-provider.h> 9 #include <linux/clockchips.h> 10 #include <linux/mfd/ingenic-tcu.h> 11 #include <linux/mfd/syscon.h> 12 #include <linux/regmap.h> 13 #include <linux/slab.h> 14 #include <linux/syscore_ops.h> 15 16 #include <dt-bindings/clock/ingenic,tcu.h> 17 18 /* 8 channels max + watchdog + OST */ 19 #define TCU_CLK_COUNT 10 20 21 #undef pr_fmt 22 #define pr_fmt(fmt) "ingenic-tcu-clk: " fmt 23 24 enum tcu_clk_parent { 25 TCU_PARENT_PCLK, 26 TCU_PARENT_RTC, 27 TCU_PARENT_EXT, 28 }; 29 30 struct ingenic_soc_info { 31 unsigned int num_channels; 32 bool has_ost; 33 bool has_tcu_clk; 34 }; 35 36 struct ingenic_tcu_clk_info { 37 struct clk_init_data init_data; 38 u8 gate_bit; 39 u8 tcsr_reg; 40 }; 41 42 struct ingenic_tcu_clk { 43 struct clk_hw hw; 44 unsigned int idx; 45 struct ingenic_tcu *tcu; 46 const struct ingenic_tcu_clk_info *info; 47 }; 48 49 struct ingenic_tcu { 50 const struct ingenic_soc_info *soc_info; 51 struct regmap *map; 52 struct clk *clk; 53 54 struct clk_hw_onecell_data *clocks; 55 }; 56 57 static struct ingenic_tcu *ingenic_tcu; 58 59 static inline struct ingenic_tcu_clk *to_tcu_clk(struct clk_hw *hw) 60 { 61 return container_of(hw, struct ingenic_tcu_clk, hw); 62 } 63 64 static int ingenic_tcu_enable(struct clk_hw *hw) 65 { 66 struct ingenic_tcu_clk *tcu_clk = to_tcu_clk(hw); 67 const struct ingenic_tcu_clk_info *info = tcu_clk->info; 68 struct ingenic_tcu *tcu = tcu_clk->tcu; 69 70 regmap_write(tcu->map, TCU_REG_TSCR, BIT(info->gate_bit)); 71 72 return 0; 73 } 74 75 static void ingenic_tcu_disable(struct clk_hw *hw) 76 { 77 struct ingenic_tcu_clk *tcu_clk = to_tcu_clk(hw); 78 const struct ingenic_tcu_clk_info *info = tcu_clk->info; 79 struct ingenic_tcu *tcu = tcu_clk->tcu; 80 81 regmap_write(tcu->map, TCU_REG_TSSR, BIT(info->gate_bit)); 82 } 83 84 static int ingenic_tcu_is_enabled(struct clk_hw *hw) 85 { 86 struct ingenic_tcu_clk *tcu_clk = to_tcu_clk(hw); 87 const struct ingenic_tcu_clk_info *info = tcu_clk->info; 88 unsigned int value; 89 90 regmap_read(tcu_clk->tcu->map, TCU_REG_TSR, &value); 91 92 return !(value & BIT(info->gate_bit)); 93 } 94 95 static bool ingenic_tcu_enable_regs(struct clk_hw *hw) 96 { 97 struct ingenic_tcu_clk *tcu_clk = to_tcu_clk(hw); 98 const struct ingenic_tcu_clk_info *info = tcu_clk->info; 99 struct ingenic_tcu *tcu = tcu_clk->tcu; 100 bool enabled = false; 101 102 /* 103 * If the SoC has no global TCU clock, we must ungate the channel's 104 * clock to be able to access its registers. 105 * If we have a TCU clock, it will be enabled automatically as it has 106 * been attached to the regmap. 107 */ 108 if (!tcu->clk) { 109 enabled = !!ingenic_tcu_is_enabled(hw); 110 regmap_write(tcu->map, TCU_REG_TSCR, BIT(info->gate_bit)); 111 } 112 113 return enabled; 114 } 115 116 static void ingenic_tcu_disable_regs(struct clk_hw *hw) 117 { 118 struct ingenic_tcu_clk *tcu_clk = to_tcu_clk(hw); 119 const struct ingenic_tcu_clk_info *info = tcu_clk->info; 120 struct ingenic_tcu *tcu = tcu_clk->tcu; 121 122 if (!tcu->clk) 123 regmap_write(tcu->map, TCU_REG_TSSR, BIT(info->gate_bit)); 124 } 125 126 static u8 ingenic_tcu_get_parent(struct clk_hw *hw) 127 { 128 struct ingenic_tcu_clk *tcu_clk = to_tcu_clk(hw); 129 const struct ingenic_tcu_clk_info *info = tcu_clk->info; 130 unsigned int val = 0; 131 int ret; 132 133 ret = regmap_read(tcu_clk->tcu->map, info->tcsr_reg, &val); 134 WARN_ONCE(ret < 0, "Unable to read TCSR %d", tcu_clk->idx); 135 136 return ffs(val & TCU_TCSR_PARENT_CLOCK_MASK) - 1; 137 } 138 139 static int ingenic_tcu_set_parent(struct clk_hw *hw, u8 idx) 140 { 141 struct ingenic_tcu_clk *tcu_clk = to_tcu_clk(hw); 142 const struct ingenic_tcu_clk_info *info = tcu_clk->info; 143 bool was_enabled; 144 int ret; 145 146 was_enabled = ingenic_tcu_enable_regs(hw); 147 148 ret = regmap_update_bits(tcu_clk->tcu->map, info->tcsr_reg, 149 TCU_TCSR_PARENT_CLOCK_MASK, BIT(idx)); 150 WARN_ONCE(ret < 0, "Unable to update TCSR %d", tcu_clk->idx); 151 152 if (!was_enabled) 153 ingenic_tcu_disable_regs(hw); 154 155 return 0; 156 } 157 158 static unsigned long ingenic_tcu_recalc_rate(struct clk_hw *hw, 159 unsigned long parent_rate) 160 { 161 struct ingenic_tcu_clk *tcu_clk = to_tcu_clk(hw); 162 const struct ingenic_tcu_clk_info *info = tcu_clk->info; 163 unsigned int prescale; 164 int ret; 165 166 ret = regmap_read(tcu_clk->tcu->map, info->tcsr_reg, &prescale); 167 WARN_ONCE(ret < 0, "Unable to read TCSR %d", tcu_clk->idx); 168 169 prescale = (prescale & TCU_TCSR_PRESCALE_MASK) >> TCU_TCSR_PRESCALE_LSB; 170 171 return parent_rate >> (prescale * 2); 172 } 173 174 static u8 ingenic_tcu_get_prescale(unsigned long rate, unsigned long req_rate) 175 { 176 u8 prescale; 177 178 for (prescale = 0; prescale < 5; prescale++) 179 if ((rate >> (prescale * 2)) <= req_rate) 180 return prescale; 181 182 return 5; /* /1024 divider */ 183 } 184 185 static long ingenic_tcu_round_rate(struct clk_hw *hw, unsigned long req_rate, 186 unsigned long *parent_rate) 187 { 188 unsigned long rate = *parent_rate; 189 u8 prescale; 190 191 if (req_rate > rate) 192 return -EINVAL; 193 194 prescale = ingenic_tcu_get_prescale(rate, req_rate); 195 196 return rate >> (prescale * 2); 197 } 198 199 static int ingenic_tcu_set_rate(struct clk_hw *hw, unsigned long req_rate, 200 unsigned long parent_rate) 201 { 202 struct ingenic_tcu_clk *tcu_clk = to_tcu_clk(hw); 203 const struct ingenic_tcu_clk_info *info = tcu_clk->info; 204 u8 prescale = ingenic_tcu_get_prescale(parent_rate, req_rate); 205 bool was_enabled; 206 int ret; 207 208 was_enabled = ingenic_tcu_enable_regs(hw); 209 210 ret = regmap_update_bits(tcu_clk->tcu->map, info->tcsr_reg, 211 TCU_TCSR_PRESCALE_MASK, 212 prescale << TCU_TCSR_PRESCALE_LSB); 213 WARN_ONCE(ret < 0, "Unable to update TCSR %d", tcu_clk->idx); 214 215 if (!was_enabled) 216 ingenic_tcu_disable_regs(hw); 217 218 return 0; 219 } 220 221 static const struct clk_ops ingenic_tcu_clk_ops = { 222 .get_parent = ingenic_tcu_get_parent, 223 .set_parent = ingenic_tcu_set_parent, 224 225 .recalc_rate = ingenic_tcu_recalc_rate, 226 .round_rate = ingenic_tcu_round_rate, 227 .set_rate = ingenic_tcu_set_rate, 228 229 .enable = ingenic_tcu_enable, 230 .disable = ingenic_tcu_disable, 231 .is_enabled = ingenic_tcu_is_enabled, 232 }; 233 234 static const char * const ingenic_tcu_timer_parents[] = { 235 [TCU_PARENT_PCLK] = "pclk", 236 [TCU_PARENT_RTC] = "rtc", 237 [TCU_PARENT_EXT] = "ext", 238 }; 239 240 #define DEF_TIMER(_name, _gate_bit, _tcsr) \ 241 { \ 242 .init_data = { \ 243 .name = _name, \ 244 .parent_names = ingenic_tcu_timer_parents, \ 245 .num_parents = ARRAY_SIZE(ingenic_tcu_timer_parents),\ 246 .ops = &ingenic_tcu_clk_ops, \ 247 .flags = CLK_SET_RATE_UNGATE, \ 248 }, \ 249 .gate_bit = _gate_bit, \ 250 .tcsr_reg = _tcsr, \ 251 } 252 static const struct ingenic_tcu_clk_info ingenic_tcu_clk_info[] = { 253 [TCU_CLK_TIMER0] = DEF_TIMER("timer0", 0, TCU_REG_TCSRc(0)), 254 [TCU_CLK_TIMER1] = DEF_TIMER("timer1", 1, TCU_REG_TCSRc(1)), 255 [TCU_CLK_TIMER2] = DEF_TIMER("timer2", 2, TCU_REG_TCSRc(2)), 256 [TCU_CLK_TIMER3] = DEF_TIMER("timer3", 3, TCU_REG_TCSRc(3)), 257 [TCU_CLK_TIMER4] = DEF_TIMER("timer4", 4, TCU_REG_TCSRc(4)), 258 [TCU_CLK_TIMER5] = DEF_TIMER("timer5", 5, TCU_REG_TCSRc(5)), 259 [TCU_CLK_TIMER6] = DEF_TIMER("timer6", 6, TCU_REG_TCSRc(6)), 260 [TCU_CLK_TIMER7] = DEF_TIMER("timer7", 7, TCU_REG_TCSRc(7)), 261 }; 262 263 static const struct ingenic_tcu_clk_info ingenic_tcu_watchdog_clk_info = 264 DEF_TIMER("wdt", 16, TCU_REG_WDT_TCSR); 265 static const struct ingenic_tcu_clk_info ingenic_tcu_ost_clk_info = 266 DEF_TIMER("ost", 15, TCU_REG_OST_TCSR); 267 #undef DEF_TIMER 268 269 static int __init ingenic_tcu_register_clock(struct ingenic_tcu *tcu, 270 unsigned int idx, enum tcu_clk_parent parent, 271 const struct ingenic_tcu_clk_info *info, 272 struct clk_hw_onecell_data *clocks) 273 { 274 struct ingenic_tcu_clk *tcu_clk; 275 int err; 276 277 tcu_clk = kzalloc(sizeof(*tcu_clk), GFP_KERNEL); 278 if (!tcu_clk) 279 return -ENOMEM; 280 281 tcu_clk->hw.init = &info->init_data; 282 tcu_clk->idx = idx; 283 tcu_clk->info = info; 284 tcu_clk->tcu = tcu; 285 286 /* Reset channel and clock divider, set default parent */ 287 ingenic_tcu_enable_regs(&tcu_clk->hw); 288 regmap_update_bits(tcu->map, info->tcsr_reg, 0xffff, BIT(parent)); 289 ingenic_tcu_disable_regs(&tcu_clk->hw); 290 291 err = clk_hw_register(NULL, &tcu_clk->hw); 292 if (err) { 293 kfree(tcu_clk); 294 return err; 295 } 296 297 clocks->hws[idx] = &tcu_clk->hw; 298 299 return 0; 300 } 301 302 static const struct ingenic_soc_info jz4740_soc_info = { 303 .num_channels = 8, 304 .has_ost = false, 305 .has_tcu_clk = true, 306 }; 307 308 static const struct ingenic_soc_info jz4725b_soc_info = { 309 .num_channels = 6, 310 .has_ost = true, 311 .has_tcu_clk = true, 312 }; 313 314 static const struct ingenic_soc_info jz4770_soc_info = { 315 .num_channels = 8, 316 .has_ost = true, 317 .has_tcu_clk = false, 318 }; 319 320 static const struct of_device_id ingenic_tcu_of_match[] __initconst = { 321 { .compatible = "ingenic,jz4740-tcu", .data = &jz4740_soc_info, }, 322 { .compatible = "ingenic,jz4725b-tcu", .data = &jz4725b_soc_info, }, 323 { .compatible = "ingenic,jz4770-tcu", .data = &jz4770_soc_info, }, 324 { /* sentinel */ } 325 }; 326 327 static int __init ingenic_tcu_probe(struct device_node *np) 328 { 329 const struct of_device_id *id = of_match_node(ingenic_tcu_of_match, np); 330 struct ingenic_tcu *tcu; 331 struct regmap *map; 332 unsigned int i; 333 int ret; 334 335 map = device_node_to_regmap(np); 336 if (IS_ERR(map)) 337 return PTR_ERR(map); 338 339 tcu = kzalloc(sizeof(*tcu), GFP_KERNEL); 340 if (!tcu) 341 return -ENOMEM; 342 343 tcu->map = map; 344 tcu->soc_info = id->data; 345 346 if (tcu->soc_info->has_tcu_clk) { 347 tcu->clk = of_clk_get_by_name(np, "tcu"); 348 if (IS_ERR(tcu->clk)) { 349 ret = PTR_ERR(tcu->clk); 350 pr_crit("Cannot get TCU clock\n"); 351 goto err_free_tcu; 352 } 353 354 ret = clk_prepare_enable(tcu->clk); 355 if (ret) { 356 pr_crit("Unable to enable TCU clock\n"); 357 goto err_put_clk; 358 } 359 } 360 361 tcu->clocks = kzalloc(sizeof(*tcu->clocks) + 362 sizeof(*tcu->clocks->hws) * TCU_CLK_COUNT, 363 GFP_KERNEL); 364 if (!tcu->clocks) { 365 ret = -ENOMEM; 366 goto err_clk_disable; 367 } 368 369 tcu->clocks->num = TCU_CLK_COUNT; 370 371 for (i = 0; i < tcu->soc_info->num_channels; i++) { 372 ret = ingenic_tcu_register_clock(tcu, i, TCU_PARENT_EXT, 373 &ingenic_tcu_clk_info[i], 374 tcu->clocks); 375 if (ret) { 376 pr_crit("cannot register clock %d\n", i); 377 goto err_unregister_timer_clocks; 378 } 379 } 380 381 /* 382 * We set EXT as the default parent clock for all the TCU clocks 383 * except for the watchdog one, where we set the RTC clock as the 384 * parent. Since the EXT and PCLK are much faster than the RTC clock, 385 * the watchdog would kick after a maximum time of 5s, and we might 386 * want a slower kicking time. 387 */ 388 ret = ingenic_tcu_register_clock(tcu, TCU_CLK_WDT, TCU_PARENT_RTC, 389 &ingenic_tcu_watchdog_clk_info, 390 tcu->clocks); 391 if (ret) { 392 pr_crit("cannot register watchdog clock\n"); 393 goto err_unregister_timer_clocks; 394 } 395 396 if (tcu->soc_info->has_ost) { 397 ret = ingenic_tcu_register_clock(tcu, TCU_CLK_OST, 398 TCU_PARENT_EXT, 399 &ingenic_tcu_ost_clk_info, 400 tcu->clocks); 401 if (ret) { 402 pr_crit("cannot register ost clock\n"); 403 goto err_unregister_watchdog_clock; 404 } 405 } 406 407 ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, tcu->clocks); 408 if (ret) { 409 pr_crit("cannot add OF clock provider\n"); 410 goto err_unregister_ost_clock; 411 } 412 413 ingenic_tcu = tcu; 414 415 return 0; 416 417 err_unregister_ost_clock: 418 if (tcu->soc_info->has_ost) 419 clk_hw_unregister(tcu->clocks->hws[i + 1]); 420 err_unregister_watchdog_clock: 421 clk_hw_unregister(tcu->clocks->hws[i]); 422 err_unregister_timer_clocks: 423 for (i = 0; i < tcu->clocks->num; i++) 424 if (tcu->clocks->hws[i]) 425 clk_hw_unregister(tcu->clocks->hws[i]); 426 kfree(tcu->clocks); 427 err_clk_disable: 428 if (tcu->soc_info->has_tcu_clk) 429 clk_disable_unprepare(tcu->clk); 430 err_put_clk: 431 if (tcu->soc_info->has_tcu_clk) 432 clk_put(tcu->clk); 433 err_free_tcu: 434 kfree(tcu); 435 return ret; 436 } 437 438 static int __maybe_unused tcu_pm_suspend(void) 439 { 440 struct ingenic_tcu *tcu = ingenic_tcu; 441 442 if (tcu->clk) 443 clk_disable(tcu->clk); 444 445 return 0; 446 } 447 448 static void __maybe_unused tcu_pm_resume(void) 449 { 450 struct ingenic_tcu *tcu = ingenic_tcu; 451 452 if (tcu->clk) 453 clk_enable(tcu->clk); 454 } 455 456 static struct syscore_ops __maybe_unused tcu_pm_ops = { 457 .suspend = tcu_pm_suspend, 458 .resume = tcu_pm_resume, 459 }; 460 461 static void __init ingenic_tcu_init(struct device_node *np) 462 { 463 int ret = ingenic_tcu_probe(np); 464 465 if (ret) 466 pr_crit("Failed to initialize TCU clocks: %d\n", ret); 467 468 if (IS_ENABLED(CONFIG_PM_SLEEP)) 469 register_syscore_ops(&tcu_pm_ops); 470 } 471 472 CLK_OF_DECLARE_DRIVER(jz4740_cgu, "ingenic,jz4740-tcu", ingenic_tcu_init); 473 CLK_OF_DECLARE_DRIVER(jz4725b_cgu, "ingenic,jz4725b-tcu", ingenic_tcu_init); 474 CLK_OF_DECLARE_DRIVER(jz4770_cgu, "ingenic,jz4770-tcu", ingenic_tcu_init); 475