Lines Matching +full:jz4770 +full:- +full:pwm
1 // SPDX-License-Identifier: GPL-2.0
14 #include <linux/mfd/ingenic-tcu.h>
23 #include <dt-bindings/clock/ingenic,tcu.h>
56 regmap_read(tcu->map, TCU_REG_TCNTc(tcu->cs_channel), &count); in ingenic_tcu_timer_read()
69 return container_of(timer, struct ingenic_tcu, timers[timer->cpu]); in to_ingenic_tcu()
83 regmap_write(tcu->map, TCU_REG_TECR, BIT(timer->channel)); in ingenic_tcu_cevt_set_state_shutdown()
95 return -EINVAL; in ingenic_tcu_cevt_set_next()
97 regmap_write(tcu->map, TCU_REG_TDFRc(timer->channel), next); in ingenic_tcu_cevt_set_next()
98 regmap_write(tcu->map, TCU_REG_TCNTc(timer->channel), 0); in ingenic_tcu_cevt_set_next()
99 regmap_write(tcu->map, TCU_REG_TESR, BIT(timer->channel)); in ingenic_tcu_cevt_set_next()
108 cevt->event_handler(cevt); in ingenic_per_cpu_event_handler()
117 regmap_write(tcu->map, TCU_REG_TECR, BIT(timer->channel)); in ingenic_tcu_cevt_cb()
119 if (timer->cevt.event_handler) { in ingenic_tcu_cevt_cb()
120 csd = &per_cpu(ingenic_cevt_csd, timer->cpu); in ingenic_tcu_cevt_cb()
121 csd->info = (void *) &timer->cevt; in ingenic_tcu_cevt_cb()
122 csd->func = ingenic_per_cpu_event_handler; in ingenic_tcu_cevt_cb()
123 smp_call_function_single_async(timer->cpu, csd); in ingenic_tcu_cevt_cb()
143 struct ingenic_tcu_timer *timer = &tcu->timers[cpu]; in ingenic_tcu_setup_cevt()
149 timer->clk = ingenic_tcu_get_clock(tcu->np, timer->channel); in ingenic_tcu_setup_cevt()
150 if (IS_ERR(timer->clk)) in ingenic_tcu_setup_cevt()
151 return PTR_ERR(timer->clk); in ingenic_tcu_setup_cevt()
153 err = clk_prepare_enable(timer->clk); in ingenic_tcu_setup_cevt()
157 rate = clk_get_rate(timer->clk); in ingenic_tcu_setup_cevt()
159 err = -EINVAL; in ingenic_tcu_setup_cevt()
163 domain = irq_find_host(tcu->np); in ingenic_tcu_setup_cevt()
165 err = -ENODEV; in ingenic_tcu_setup_cevt()
169 timer_virq = irq_create_mapping(domain, timer->channel); in ingenic_tcu_setup_cevt()
171 err = -EINVAL; in ingenic_tcu_setup_cevt()
175 snprintf(timer->name, sizeof(timer->name), "TCU%u", timer->channel); in ingenic_tcu_setup_cevt()
178 timer->name, timer); in ingenic_tcu_setup_cevt()
182 timer->cpu = smp_processor_id(); in ingenic_tcu_setup_cevt()
183 timer->cevt.cpumask = cpumask_of(smp_processor_id()); in ingenic_tcu_setup_cevt()
184 timer->cevt.features = CLOCK_EVT_FEAT_ONESHOT; in ingenic_tcu_setup_cevt()
185 timer->cevt.name = timer->name; in ingenic_tcu_setup_cevt()
186 timer->cevt.rating = 200; in ingenic_tcu_setup_cevt()
187 timer->cevt.set_state_shutdown = ingenic_tcu_cevt_set_state_shutdown; in ingenic_tcu_setup_cevt()
188 timer->cevt.set_next_event = ingenic_tcu_cevt_set_next; in ingenic_tcu_setup_cevt()
190 clockevents_config_and_register(&timer->cevt, rate, 10, 0xffff); in ingenic_tcu_setup_cevt()
197 clk_disable_unprepare(timer->clk); in ingenic_tcu_setup_cevt()
199 clk_put(timer->clk); in ingenic_tcu_setup_cevt()
206 unsigned int channel = tcu->cs_channel; in ingenic_tcu_clocksource_init()
207 struct clocksource *cs = &tcu->cs; in ingenic_tcu_clocksource_init()
211 tcu->cs_clk = ingenic_tcu_get_clock(np, channel); in ingenic_tcu_clocksource_init()
212 if (IS_ERR(tcu->cs_clk)) in ingenic_tcu_clocksource_init()
213 return PTR_ERR(tcu->cs_clk); in ingenic_tcu_clocksource_init()
215 err = clk_prepare_enable(tcu->cs_clk); in ingenic_tcu_clocksource_init()
219 rate = clk_get_rate(tcu->cs_clk); in ingenic_tcu_clocksource_init()
221 err = -EINVAL; in ingenic_tcu_clocksource_init()
226 regmap_update_bits(tcu->map, TCU_REG_TCSRc(channel), in ingenic_tcu_clocksource_init()
230 regmap_write(tcu->map, TCU_REG_TDFRc(channel), 0xffff); in ingenic_tcu_clocksource_init()
231 regmap_write(tcu->map, TCU_REG_TCNTc(channel), 0); in ingenic_tcu_clocksource_init()
234 regmap_write(tcu->map, TCU_REG_TESR, BIT(channel)); in ingenic_tcu_clocksource_init()
236 cs->name = "ingenic-timer"; in ingenic_tcu_clocksource_init()
237 cs->rating = 200; in ingenic_tcu_clocksource_init()
238 cs->flags = CLOCK_SOURCE_IS_CONTINUOUS; in ingenic_tcu_clocksource_init()
239 cs->mask = CLOCKSOURCE_MASK(16); in ingenic_tcu_clocksource_init()
240 cs->read = ingenic_tcu_timer_cs_read; in ingenic_tcu_clocksource_init()
249 clk_disable_unprepare(tcu->cs_clk); in ingenic_tcu_clocksource_init()
251 clk_put(tcu->cs_clk); in ingenic_tcu_clocksource_init()
264 { .compatible = "ingenic,jz4740-tcu", .data = &jz4740_soc_info, },
265 { .compatible = "ingenic,jz4725b-tcu", .data = &jz4725b_soc_info, },
266 { .compatible = "ingenic,jz4760-tcu", .data = &jz4740_soc_info, },
267 { .compatible = "ingenic,jz4770-tcu", .data = &jz4740_soc_info, },
268 { .compatible = "ingenic,x1000-tcu", .data = &jz4740_soc_info, },
275 const struct ingenic_soc_info *soc_info = id->data; in ingenic_tcu_init()
280 int ret, last_bit = -1; in ingenic_tcu_init()
292 return -ENOMEM; in ingenic_tcu_init()
295 * Enable all TCU channels for PWM use by default except channels 0/1, in ingenic_tcu_init()
298 tcu->pwm_channels_mask = GENMASK(soc_info->num_channels - 1, in ingenic_tcu_init()
300 of_property_read_u32(np, "ingenic,pwm-channels-mask", in ingenic_tcu_init()
301 (u32 *)&tcu->pwm_channels_mask); in ingenic_tcu_init()
304 if (hweight8(tcu->pwm_channels_mask) > in ingenic_tcu_init()
305 soc_info->num_channels - num_possible_cpus() + 1) { in ingenic_tcu_init()
306 pr_crit("%s: Invalid PWM channel mask: 0x%02lx\n", __func__, in ingenic_tcu_init()
307 tcu->pwm_channels_mask); in ingenic_tcu_init()
308 ret = -EINVAL; in ingenic_tcu_init()
312 tcu->map = map; in ingenic_tcu_init()
313 tcu->np = np; in ingenic_tcu_init()
317 timer = &tcu->timers[cpu]; in ingenic_tcu_init()
319 timer->cpu = cpu; in ingenic_tcu_init()
320 timer->channel = find_next_zero_bit(&tcu->pwm_channels_mask, in ingenic_tcu_init()
321 soc_info->num_channels, in ingenic_tcu_init()
323 last_bit = timer->channel; in ingenic_tcu_init()
326 tcu->cs_channel = find_next_zero_bit(&tcu->pwm_channels_mask, in ingenic_tcu_init()
327 soc_info->num_channels, in ingenic_tcu_init()
345 rate = clk_get_rate(tcu->cs_clk); in ingenic_tcu_init()
351 clocksource_unregister(&tcu->cs); in ingenic_tcu_init()
352 clk_disable_unprepare(tcu->cs_clk); in ingenic_tcu_init()
353 clk_put(tcu->cs_clk); in ingenic_tcu_init()
359 TIMER_OF_DECLARE(jz4740_tcu_intc, "ingenic,jz4740-tcu", ingenic_tcu_init);
360 TIMER_OF_DECLARE(jz4725b_tcu_intc, "ingenic,jz4725b-tcu", ingenic_tcu_init);
361 TIMER_OF_DECLARE(jz4760_tcu_intc, "ingenic,jz4760-tcu", ingenic_tcu_init);
362 TIMER_OF_DECLARE(jz4770_tcu_intc, "ingenic,jz4770-tcu", ingenic_tcu_init);
363 TIMER_OF_DECLARE(x1000_tcu_intc, "ingenic,x1000-tcu", ingenic_tcu_init);
377 clk_disable(tcu->cs_clk); in ingenic_tcu_suspend()
380 clk_disable(tcu->timers[cpu].clk); in ingenic_tcu_suspend()
392 ret = clk_enable(tcu->timers[cpu].clk); in ingenic_tcu_resume()
397 ret = clk_enable(tcu->cs_clk); in ingenic_tcu_resume()
404 for (; cpu > 0; cpu--) in ingenic_tcu_resume()
405 clk_disable(tcu->timers[cpu - 1].clk); in ingenic_tcu_resume()
417 .name = "ingenic-tcu-timer",