// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) 2021 Sean Anderson <[email protected]> * * Limitations: * - When changing both duty cycle and period, we may end up with one cycle * with the old duty cycle and the new period. This is because the counters * may only be reloaded by first stopping them, or by letting them be * automatically reloaded at the end of a cycle. If this automatic reload * happens after we set TLR0 but before we set TLR1 then we will have a * bad cycle. This could probably be fixed by reading TCR0 just before * reprogramming, but I think it would add complexity for little gain. * - Cannot produce 100% duty cycle by configuring the TLRs. This might be * possible by stopping the counters at an appropriate point in the cycle, * but this is not (yet) implemented. * - Only produces "normal" output. * - Always produces low output if disabled. */ #include <clocksource/timer-xilinx.h> #include <linux/clk.h> #include <linux/clk-provider.h> #include <linux/device.h> #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> #include <linux/pwm.h> #include <linux/regmap.h> /* * The following functions are "common" to drivers for this device, and may be * exported at a future date. */ u32 xilinx_timer_tlr_cycles(struct xilinx_timer_priv *priv, u32 tcsr, u64 cycles) { … } unsigned int xilinx_timer_get_period(struct xilinx_timer_priv *priv, u32 tlr, u32 tcsr) { … } /* * The idea here is to capture whether the PWM is actually running (e.g. * because we or the bootloader set it up) and we need to be careful to ensure * we don't cause a glitch. According to the data sheet, to enable the PWM we * need to * * - Set both timers to generate mode (MDT=1) * - Set both timers to PWM mode (PWMA=1) * - Enable the generate out signals (GENT=1) * * In addition, * * - The timer must be running (ENT=1) * - The timer must auto-reload TLR into TCR (ARHT=1) * - We must not be in the process of loading TLR into TCR (LOAD=0) * - Cascade mode must be disabled (CASC=0) * * If any of these differ from usual, then the PWM is either disabled, or is * running in a mode that this driver does not support. */ #define TCSR_PWM_SET … #define TCSR_PWM_CLEAR … #define TCSR_PWM_MASK … static inline struct xilinx_timer_priv *xilinx_pwm_chip_to_priv(struct pwm_chip *chip) { … } static bool xilinx_timer_pwm_enabled(u32 tcsr0, u32 tcsr1) { … } static int xilinx_pwm_apply(struct pwm_chip *chip, struct pwm_device *unused, const struct pwm_state *state) { … } static int xilinx_pwm_get_state(struct pwm_chip *chip, struct pwm_device *unused, struct pwm_state *state) { … } static const struct pwm_ops xilinx_pwm_ops = …; static const struct regmap_config xilinx_pwm_regmap_config = …; static int xilinx_pwm_probe(struct platform_device *pdev) { … } static const struct of_device_id xilinx_pwm_of_match[] = …; MODULE_DEVICE_TABLE(of, xilinx_pwm_of_match); static struct platform_driver xilinx_pwm_driver = …; module_platform_driver(…) …; MODULE_ALIAS(…) …; MODULE_DESCRIPTION(…) …; MODULE_LICENSE(…) …;