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