Message ID | 20250115113556.2832282-3-mubin.sayyed@amd.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Add initial support for TTC PWM driver | expand |
On Wed, Jan 15, 2025 at 05:05:55PM +0530, Mubin Sayyed wrote: > TTC device can act either as clocksource/clockevent or PWM generator, > it would be decided by pwm-cells property. If pwm-cells property is > present in TTC node, it would be treated as PWM device, and clocksource > driver just calls probe function for PWM functionality, so that TTC > device would be registered with PWM framework. > > Signed-off-by: Mubin Sayyed <mubin.sayyed@amd.com> > --- > Changes for v4: > - In case of pwm-cells property call probe function for PWM > feature instead of returning error. > Changes for v3: > - None > Changes for v2: > - Added comment regarding pwm-cells property > --- > drivers/clocksource/timer-cadence-ttc.c | 34 +++++++++++++++++++++++++ > 1 file changed, 34 insertions(+) > > diff --git a/drivers/clocksource/timer-cadence-ttc.c b/drivers/clocksource/timer-cadence-ttc.c > index 2f33d4c40153..c5ecad9332c9 100644 > --- a/drivers/clocksource/timer-cadence-ttc.c > +++ b/drivers/clocksource/timer-cadence-ttc.c > @@ -35,6 +35,10 @@ > * obtained from device tree. The pre-scaler of 32 is used. > */ > > +struct ttc_timer_config { > + bool is_pwm_mode; > +}; > + > /** > * struct ttc_timer - This definition defines local timer structure > * > @@ -453,6 +457,7 @@ static int __init ttc_setup_clockevent(struct clk *clk, > > static int __init ttc_timer_probe(struct platform_device *pdev) > { > + struct ttc_timer_config *ttc_config; > unsigned int irq; > void __iomem *timer_baseaddr; > struct clk *clk_cs, *clk_ce; > @@ -461,6 +466,24 @@ static int __init ttc_timer_probe(struct platform_device *pdev) > u32 timer_width = 16; > struct device_node *timer = pdev->dev.of_node; > > + ttc_config = devm_kzalloc(&pdev->dev, sizeof(*ttc_config), GFP_KERNEL); > + if (!ttc_config) > + return -ENOMEM; > + > + /* > + * If pwm-cells property is present in TTC node, > + * it would be treated as PWM device. > + */ > + if (of_property_read_bool(timer, "#pwm-cells")) { > + #if defined(CONFIG_PWM_CADENCE) > + ttc_config->is_pwm_mode = true; > + return ttc_pwm_probe(pdev); strange indention. Maybe use if (IS_REACHABLE(CONFIG_PWM_CADENCE)) This is an unusal way to bind the PWM driver. I'd prefer creation of separate device in the PWM case. I wonder if it can happen that ttc_pwm_probe() is called during boot before pwm_init() completed. Or use an auxbus device to distinguish between timer and pwm? > + #else > + return -ENODEV; > + #endif > + } > + dev_set_drvdata(&pdev->dev, ttc_config); > + > if (initialized) > return 0; > Best regards Uwe
diff --git a/drivers/clocksource/timer-cadence-ttc.c b/drivers/clocksource/timer-cadence-ttc.c index 2f33d4c40153..c5ecad9332c9 100644 --- a/drivers/clocksource/timer-cadence-ttc.c +++ b/drivers/clocksource/timer-cadence-ttc.c @@ -35,6 +35,10 @@ * obtained from device tree. The pre-scaler of 32 is used. */ +struct ttc_timer_config { + bool is_pwm_mode; +}; + /** * struct ttc_timer - This definition defines local timer structure * @@ -453,6 +457,7 @@ static int __init ttc_setup_clockevent(struct clk *clk, static int __init ttc_timer_probe(struct platform_device *pdev) { + struct ttc_timer_config *ttc_config; unsigned int irq; void __iomem *timer_baseaddr; struct clk *clk_cs, *clk_ce; @@ -461,6 +466,24 @@ static int __init ttc_timer_probe(struct platform_device *pdev) u32 timer_width = 16; struct device_node *timer = pdev->dev.of_node; + ttc_config = devm_kzalloc(&pdev->dev, sizeof(*ttc_config), GFP_KERNEL); + if (!ttc_config) + return -ENOMEM; + + /* + * If pwm-cells property is present in TTC node, + * it would be treated as PWM device. + */ + if (of_property_read_bool(timer, "#pwm-cells")) { + #if defined(CONFIG_PWM_CADENCE) + ttc_config->is_pwm_mode = true; + return ttc_pwm_probe(pdev); + #else + return -ENODEV; + #endif + } + dev_set_drvdata(&pdev->dev, ttc_config); + if (initialized) return 0; @@ -521,6 +544,16 @@ static int __init ttc_timer_probe(struct platform_device *pdev) return ret; } +static void ttc_timer_remove(struct platform_device *pdev) +{ + #if defined(CONFIG_PWM_CADENCE) + struct ttc_timer_config *ttc_config = dev_get_drvdata(&pdev->dev); + + if (ttc_config->is_pwm_mode) + ttc_pwm_remove(pdev); + #endif +} + static const struct of_device_id ttc_timer_of_match[] = { {.compatible = "cdns,ttc"}, {}, @@ -529,6 +562,7 @@ static const struct of_device_id ttc_timer_of_match[] = { MODULE_DEVICE_TABLE(of, ttc_timer_of_match); static struct platform_driver ttc_timer_driver = { + .remove = ttc_timer_remove, .driver = { .name = "cdns_ttc_timer", .of_match_table = ttc_timer_of_match,
TTC device can act either as clocksource/clockevent or PWM generator, it would be decided by pwm-cells property. If pwm-cells property is present in TTC node, it would be treated as PWM device, and clocksource driver just calls probe function for PWM functionality, so that TTC device would be registered with PWM framework. Signed-off-by: Mubin Sayyed <mubin.sayyed@amd.com> --- Changes for v4: - In case of pwm-cells property call probe function for PWM feature instead of returning error. Changes for v3: - None Changes for v2: - Added comment regarding pwm-cells property --- drivers/clocksource/timer-cadence-ttc.c | 34 +++++++++++++++++++++++++ 1 file changed, 34 insertions(+)