Lines Matching +full:jz4770 +full:- +full:watchdog
1 // SPDX-License-Identifier: GPL-2.0
8 #include <linux/clk-provider.h>
10 #include <linux/mfd/ingenic-tcu.h>
16 #include <dt-bindings/clock/ingenic,tcu.h>
18 /* 8 channels max + watchdog + OST */
22 #define pr_fmt(fmt) "ingenic-tcu-clk: " fmt
67 const struct ingenic_tcu_clk_info *info = tcu_clk->info; in ingenic_tcu_enable()
68 struct ingenic_tcu *tcu = tcu_clk->tcu; in ingenic_tcu_enable()
70 regmap_write(tcu->map, TCU_REG_TSCR, BIT(info->gate_bit)); in ingenic_tcu_enable()
78 const struct ingenic_tcu_clk_info *info = tcu_clk->info; in ingenic_tcu_disable()
79 struct ingenic_tcu *tcu = tcu_clk->tcu; in ingenic_tcu_disable()
81 regmap_write(tcu->map, TCU_REG_TSSR, BIT(info->gate_bit)); in ingenic_tcu_disable()
87 const struct ingenic_tcu_clk_info *info = tcu_clk->info; in ingenic_tcu_is_enabled()
90 regmap_read(tcu_clk->tcu->map, TCU_REG_TSR, &value); in ingenic_tcu_is_enabled()
92 return !(value & BIT(info->gate_bit)); in ingenic_tcu_is_enabled()
98 const struct ingenic_tcu_clk_info *info = tcu_clk->info; in ingenic_tcu_enable_regs()
99 struct ingenic_tcu *tcu = tcu_clk->tcu; in ingenic_tcu_enable_regs()
108 if (!tcu->clk) { in ingenic_tcu_enable_regs()
110 regmap_write(tcu->map, TCU_REG_TSCR, BIT(info->gate_bit)); in ingenic_tcu_enable_regs()
119 const struct ingenic_tcu_clk_info *info = tcu_clk->info; in ingenic_tcu_disable_regs()
120 struct ingenic_tcu *tcu = tcu_clk->tcu; in ingenic_tcu_disable_regs()
122 if (!tcu->clk) in ingenic_tcu_disable_regs()
123 regmap_write(tcu->map, TCU_REG_TSSR, BIT(info->gate_bit)); in ingenic_tcu_disable_regs()
129 const struct ingenic_tcu_clk_info *info = tcu_clk->info; in ingenic_tcu_get_parent()
133 ret = regmap_read(tcu_clk->tcu->map, info->tcsr_reg, &val); in ingenic_tcu_get_parent()
134 WARN_ONCE(ret < 0, "Unable to read TCSR %d", tcu_clk->idx); in ingenic_tcu_get_parent()
136 return ffs(val & TCU_TCSR_PARENT_CLOCK_MASK) - 1; in ingenic_tcu_get_parent()
142 const struct ingenic_tcu_clk_info *info = tcu_clk->info; in ingenic_tcu_set_parent()
148 ret = regmap_update_bits(tcu_clk->tcu->map, info->tcsr_reg, in ingenic_tcu_set_parent()
150 WARN_ONCE(ret < 0, "Unable to update TCSR %d", tcu_clk->idx); in ingenic_tcu_set_parent()
162 const struct ingenic_tcu_clk_info *info = tcu_clk->info; in ingenic_tcu_recalc_rate()
166 ret = regmap_read(tcu_clk->tcu->map, info->tcsr_reg, &prescale); in ingenic_tcu_recalc_rate()
167 WARN_ONCE(ret < 0, "Unable to read TCSR %d", tcu_clk->idx); in ingenic_tcu_recalc_rate()
203 const struct ingenic_tcu_clk_info *info = tcu_clk->info; in ingenic_tcu_set_rate()
210 ret = regmap_update_bits(tcu_clk->tcu->map, info->tcsr_reg, in ingenic_tcu_set_rate()
213 WARN_ONCE(ret < 0, "Unable to update TCSR %d", tcu_clk->idx); in ingenic_tcu_set_rate()
279 return -ENOMEM; in ingenic_tcu_register_clock()
281 tcu_clk->hw.init = &info->init_data; in ingenic_tcu_register_clock()
282 tcu_clk->idx = idx; in ingenic_tcu_register_clock()
283 tcu_clk->info = info; in ingenic_tcu_register_clock()
284 tcu_clk->tcu = tcu; in ingenic_tcu_register_clock()
287 ingenic_tcu_enable_regs(&tcu_clk->hw); in ingenic_tcu_register_clock()
288 regmap_update_bits(tcu->map, info->tcsr_reg, 0xffff, BIT(parent)); in ingenic_tcu_register_clock()
289 ingenic_tcu_disable_regs(&tcu_clk->hw); in ingenic_tcu_register_clock()
291 err = clk_hw_register(NULL, &tcu_clk->hw); in ingenic_tcu_register_clock()
297 clocks->hws[idx] = &tcu_clk->hw; in ingenic_tcu_register_clock()
327 { .compatible = "ingenic,jz4740-tcu", .data = &jz4740_soc_info, },
328 { .compatible = "ingenic,jz4725b-tcu", .data = &jz4725b_soc_info, },
329 { .compatible = "ingenic,jz4770-tcu", .data = &jz4770_soc_info, },
330 { .compatible = "ingenic,x1000-tcu", .data = &x1000_soc_info, },
348 return -ENOMEM; in ingenic_tcu_probe()
350 tcu->map = map; in ingenic_tcu_probe()
351 tcu->soc_info = id->data; in ingenic_tcu_probe()
353 if (tcu->soc_info->has_tcu_clk) { in ingenic_tcu_probe()
354 tcu->clk = of_clk_get_by_name(np, "tcu"); in ingenic_tcu_probe()
355 if (IS_ERR(tcu->clk)) { in ingenic_tcu_probe()
356 ret = PTR_ERR(tcu->clk); in ingenic_tcu_probe()
361 ret = clk_prepare_enable(tcu->clk); in ingenic_tcu_probe()
368 tcu->clocks = kzalloc(struct_size(tcu->clocks, hws, TCU_CLK_COUNT), in ingenic_tcu_probe()
370 if (!tcu->clocks) { in ingenic_tcu_probe()
371 ret = -ENOMEM; in ingenic_tcu_probe()
375 tcu->clocks->num = TCU_CLK_COUNT; in ingenic_tcu_probe()
377 for (i = 0; i < tcu->soc_info->num_channels; i++) { in ingenic_tcu_probe()
380 tcu->clocks); in ingenic_tcu_probe()
389 * except for the watchdog one, where we set the RTC clock as the in ingenic_tcu_probe()
391 * the watchdog would kick after a maximum time of 5s, and we might in ingenic_tcu_probe()
396 tcu->clocks); in ingenic_tcu_probe()
398 pr_crit("cannot register watchdog clock\n"); in ingenic_tcu_probe()
402 if (tcu->soc_info->has_ost) { in ingenic_tcu_probe()
406 tcu->clocks); in ingenic_tcu_probe()
413 ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, tcu->clocks); in ingenic_tcu_probe()
424 if (tcu->soc_info->has_ost) in ingenic_tcu_probe()
425 clk_hw_unregister(tcu->clocks->hws[i + 1]); in ingenic_tcu_probe()
427 clk_hw_unregister(tcu->clocks->hws[i]); in ingenic_tcu_probe()
429 for (i = 0; i < tcu->clocks->num; i++) in ingenic_tcu_probe()
430 if (tcu->clocks->hws[i]) in ingenic_tcu_probe()
431 clk_hw_unregister(tcu->clocks->hws[i]); in ingenic_tcu_probe()
432 kfree(tcu->clocks); in ingenic_tcu_probe()
434 if (tcu->soc_info->has_tcu_clk) in ingenic_tcu_probe()
435 clk_disable_unprepare(tcu->clk); in ingenic_tcu_probe()
437 if (tcu->soc_info->has_tcu_clk) in ingenic_tcu_probe()
438 clk_put(tcu->clk); in ingenic_tcu_probe()
448 if (tcu->clk) in tcu_pm_suspend()
449 clk_disable(tcu->clk); in tcu_pm_suspend()
458 if (tcu->clk) in tcu_pm_resume()
459 clk_enable(tcu->clk); in tcu_pm_resume()
478 CLK_OF_DECLARE_DRIVER(jz4740_cgu, "ingenic,jz4740-tcu", ingenic_tcu_init);
479 CLK_OF_DECLARE_DRIVER(jz4725b_cgu, "ingenic,jz4725b-tcu", ingenic_tcu_init);
480 CLK_OF_DECLARE_DRIVER(jz4770_cgu, "ingenic,jz4770-tcu", ingenic_tcu_init);
481 CLK_OF_DECLARE_DRIVER(x1000_cgu, "ingenic,x1000-tcu", ingenic_tcu_init);