mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 0/5] Add PWM support for Cadence TTC
@ 2026-10-07  9:06 Meher Thanmaiee
  2026-10-07  9:06 ` [PATCH 1/5] clocksource: timer-cadence-ttc: Move register definitions to shared header Meher Thanmaiee
                   ` (4 more replies)
  0 siblings, 5 replies; 7+ messages in thread
From: Meher Thanmaiee @ 2026-10-07  9:06 UTC (permalink / raw)
  To: michal.simek, tglx, ukleinek, daniel.lezcano
  Cc: linux-arm-kernel, linux-kernel, git, meherthanmaiee.vanukuri, linux-pwm

The Cadence Triple Timer Counter (TTC) IP found on Xilinx Zynq,
ZynqMP, and Versal SoCs provides three timer channels per instance.
The existing TTC driver supports clocksource and clockevent use.
This series adds support for using a TTC instance as a three-channel
PWM controller, with the interval counter defining the period and
the match counter defining the duty cycle.

For TTC nodes containing #pwm-cells, the timer driver creates an
auxiliary-bus child device instead of registering the instance as a
clocksource/clockevent device. A separate PWM driver binds to the
child and exposes the three channels through the PWM framework.
This reuses the existing "cdns,ttc" compatible and #pwm-cells
binding. Nodes without #pwm-cells continue to use the timer path.

This reworks the earlier TTC PWM series by Mubin Sayyed [1] and
is submitted as a new series because the driver integration has
been redesigned. The earlier series called PWM probe code directly
from the timer driver under a CONFIG_PWM_CADENCE guard, coupling
the timer and PWM paths inside a single probe flow instead of
using separate device binding. During review of that series, an
auxiliary-bus device was suggested to separate the timer and PWM
drivers. This series implements that approach.

The first three patches prepare the TTC timer driver by moving shared
register definitions into a common header, allowing deferred probing,
and factoring out MMIO mapping and timer-width parsing. The remaining
patches add the PWM driver and timer-side auxiliary-device support.

PWM support is limited to TTC instances whose channels use the
shared internal/reference clock. Instances configured to use an
external channel clock are rejected at probe time.

[1] https://lore.kernel.org/all/20250115113556.2832282-1-mubin.sayyed@amd.com/

Signed-off-by: Meher Thanmaiee <meherthanmaiee.vanukuri@amd.com>
---
Meher Thanmaiee (5):
      clocksource: timer-cadence-ttc: Move register definitions to shared header
      clocksource: timer-cadence-ttc: Allow deferred probing
      clocksource: timer-cadence-ttc: Refactor common TTC resource setup
      pwm: cadence: Add TTC PWM driver
      clocksource: timer-cadence-ttc: Add PWM auxiliary-device support

 MAINTAINERS                             |   2 +
 drivers/clocksource/Kconfig             |   5 +
 drivers/clocksource/timer-cadence-ttc.c | 208 +++++++++++++++++++++-------
 drivers/pwm/Kconfig                     |  13 ++
 drivers/pwm/Makefile                    |   1 +
 drivers/pwm/pwm-cadence.c               | 231 ++++++++++++++++++++++++++++++++
 include/linux/timer-cadence-ttc.h       |  74 ++++++++++
 7 files changed, 487 insertions(+), 47 deletions(-)
---
base-commit: a90ee4305c4a5df72c11b31dacfdc76e00fcf78a
change-id: 20261005-cadence-ttc-pwm-2cf98b4c696b

Best regards,
--  
Meher Thanmaiee <meherthanmaiee.vanukuri@amd.com>


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/5] clocksource: timer-cadence-ttc: Move register definitions to shared header
  2026-10-07  9:06 [PATCH 0/5] Add PWM support for Cadence TTC Meher Thanmaiee
@ 2026-10-07  9:06 ` Meher Thanmaiee
  2026-10-07  9:07 ` [PATCH 2/5] clocksource: timer-cadence-ttc: Allow deferred probing Meher Thanmaiee
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Meher Thanmaiee @ 2026-10-07  9:06 UTC (permalink / raw)
  To: michal.simek, tglx, ukleinek, daniel.lezcano
  Cc: linux-arm-kernel, linux-kernel, git, meherthanmaiee.vanukuri, linux-pwm

Move the Cadence TTC register offsets and existing bit-field definitions
from timer-cadence-ttc.c into a new include/linux/timer-cadence-ttc.h
header. While moving them, convert bit-mask definitions to use BIT()
and GENMASK() macros.

The shared header will be reused by subsequent patches adding PWM
support for Cadence TTC.

Signed-off-by: Meher Thanmaiee <meherthanmaiee.vanukuri@amd.com>
---
 MAINTAINERS                             |  1 +
 drivers/clocksource/timer-cadence-ttc.c | 18 +-----------------
 include/linux/timer-cadence-ttc.h       | 28 ++++++++++++++++++++++++++++
 3 files changed, 30 insertions(+), 17 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 65e8a4b5c90b..b25ad0c18ffd 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3922,6 +3922,7 @@ F:	drivers/edac/synopsys_edac.c
 F:	drivers/i2c/busses/i2c-cadence.c
 F:	drivers/i2c/busses/i2c-xiic.c
 F:	drivers/mmc/host/sdhci-of-arasan.c
+F:	include/linux/timer-cadence-ttc.h
 N:	zynq
 N:	xilinx
 
diff --git a/drivers/clocksource/timer-cadence-ttc.c b/drivers/clocksource/timer-cadence-ttc.c
index 3c50d6892849..8be13d344007 100644
--- a/drivers/clocksource/timer-cadence-ttc.c
+++ b/drivers/clocksource/timer-cadence-ttc.c
@@ -18,6 +18,7 @@
 #include <linux/sched_clock.h>
 #include <linux/module.h>
 #include <linux/of_platform.h>
+#include <linux/timer-cadence-ttc.h>
 
 /*
  * This driver configures the 2 16/32-bit count-up timers as follows:
@@ -34,23 +35,6 @@
  * obtained from device tree. The pre-scaler of 32 is used.
  */
 
-/*
- * Timer Register Offset Definitions of Timer 1, Increment base address by 4
- * and use same offsets for Timer 2
- */
-#define TTC_CLK_CNTRL_OFFSET		0x00 /* Clock Control Reg, RW */
-#define TTC_CNT_CNTRL_OFFSET		0x0C /* Counter Control Reg, RW */
-#define TTC_COUNT_VAL_OFFSET		0x18 /* Counter Value Reg, RO */
-#define TTC_INTR_VAL_OFFSET		0x24 /* Interval Count Reg, RW */
-#define TTC_ISR_OFFSET		0x54 /* Interrupt Status Reg, RO */
-#define TTC_IER_OFFSET		0x60 /* Interrupt Enable Reg, RW */
-
-#define TTC_CNT_CNTRL_DISABLE_MASK	0x1
-
-#define TTC_CLK_CNTRL_CSRC_MASK		(1 << 5)	/* clock source */
-#define TTC_CLK_CNTRL_PSV_MASK		0x1e
-#define TTC_CLK_CNTRL_PSV_SHIFT		1
-
 /*
  * Setup the timers to use pre-scaling, using a fixed value for now that will
  * work across most input frequency, but it may need to be more dynamic
diff --git a/include/linux/timer-cadence-ttc.h b/include/linux/timer-cadence-ttc.h
new file mode 100644
index 000000000000..4f2b85e0ff78
--- /dev/null
+++ b/include/linux/timer-cadence-ttc.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Shared definitions for the Cadence Triple Timer Counter (TTC).
+ *
+ * Copyright (C) 2011 - 2013, Xilinx, Inc.
+ * Copyright (C) 2026, Advanced Micro Devices, Inc.
+ */
+
+#ifndef _LINUX_TIMER_CADENCE_TTC_H
+#define _LINUX_TIMER_CADENCE_TTC_H
+
+#include <linux/bits.h>
+
+/* Timer Register Offset Definitions of Timer 1 */
+#define TTC_CLK_CNTRL_OFFSET		0x00 /* Clock Control Reg, RW */
+#define TTC_CNT_CNTRL_OFFSET		0x0C /* Counter Control Reg, RW */
+#define TTC_COUNT_VAL_OFFSET		0x18 /* Counter Value Reg, RO */
+#define TTC_INTR_VAL_OFFSET		0x24 /* Interval Count Reg, RW */
+#define TTC_ISR_OFFSET			0x54 /* Interrupt Status Reg, RO */
+#define TTC_IER_OFFSET			0x60 /* Interrupt Enable Reg, RW */
+
+#define TTC_CNT_CNTRL_DISABLE_MASK	BIT(0)
+
+#define TTC_CLK_CNTRL_CSRC_MASK		BIT(5) /* clock source */
+#define TTC_CLK_CNTRL_PSV_MASK		GENMASK(4, 1)
+#define TTC_CLK_CNTRL_PSV_SHIFT		1
+
+#endif /* _LINUX_TIMER_CADENCE_TTC_H */

-- 
2.34.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 2/5] clocksource: timer-cadence-ttc: Allow deferred probing
  2026-10-07  9:06 [PATCH 0/5] Add PWM support for Cadence TTC Meher Thanmaiee
  2026-10-07  9:06 ` [PATCH 1/5] clocksource: timer-cadence-ttc: Move register definitions to shared header Meher Thanmaiee
@ 2026-10-07  9:07 ` Meher Thanmaiee
  2026-10-07  9:07 ` [PATCH 3/5] clocksource: timer-cadence-ttc: Refactor common TTC resource setup Meher Thanmaiee
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Meher Thanmaiee @ 2026-10-07  9:07 UTC (permalink / raw)
  To: michal.simek, tglx, ukleinek, daniel.lezcano
  Cc: linux-arm-kernel, linux-kernel, git, meherthanmaiee.vanukuri, linux-pwm

Switch from builtin_platform_driver_probe() to builtin_platform_driver()
to support deferred probing. The existing timer probe path calls
of_clk_get(), which can return -EPROBE_DEFER when the clock provider is
not yet available. builtin_platform_driver_probe() discards the probe
callback after init and cannot retry probing, so switch to
builtin_platform_driver(), which keeps it available. This requires
removing the __init annotations from ttc_timer_probe(),
ttc_setup_clocksource(), and ttc_setup_clockevent().

Move the initialized flag assignment to after clocksource and
clockevent registration succeeds so that a retried probe does not see
initialized = true and return early before the timer is configured.

Signed-off-by: Meher Thanmaiee <meherthanmaiee.vanukuri@amd.com>
---
 drivers/clocksource/timer-cadence-ttc.c | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/drivers/clocksource/timer-cadence-ttc.c b/drivers/clocksource/timer-cadence-ttc.c
index 8be13d344007..75bc0af1fa9e 100644
--- a/drivers/clocksource/timer-cadence-ttc.c
+++ b/drivers/clocksource/timer-cadence-ttc.c
@@ -312,8 +312,8 @@ static int ttc_rate_change_clocksource_cb(struct notifier_block *nb,
 	return NOTIFY_DONE;
 }
 
-static int __init ttc_setup_clocksource(struct clk *clk, void __iomem *base,
-					 u32 timer_width)
+static int ttc_setup_clocksource(struct clk *clk, void __iomem *base,
+				 u32 timer_width)
 {
 	struct ttc_timer_clocksource *ttccs;
 	int err;
@@ -395,8 +395,8 @@ static int ttc_rate_change_clockevent_cb(struct notifier_block *nb,
 	}
 }
 
-static int __init ttc_setup_clockevent(struct clk *clk,
-				       void __iomem *base, u32 irq)
+static int ttc_setup_clockevent(struct clk *clk,
+				void __iomem *base, u32 irq)
 {
 	struct ttc_timer_clockevent *ttcce;
 	int err;
@@ -463,7 +463,7 @@ static int __init ttc_setup_clockevent(struct clk *clk,
 	return err;
 }
 
-static int __init ttc_timer_probe(struct platform_device *pdev)
+static int ttc_timer_probe(struct platform_device *pdev)
 {
 	unsigned int irq;
 	void __iomem *timer_baseaddr;
@@ -476,8 +476,6 @@ static int __init ttc_timer_probe(struct platform_device *pdev)
 	if (initialized)
 		return 0;
 
-	initialized = 1;
-
 	/*
 	 * Get the 1st Triple Timer Counter (TTC) block from the device tree
 	 * and use it. Note that the event timer uses the interrupt and it's the
@@ -522,6 +520,8 @@ static int __init ttc_timer_probe(struct platform_device *pdev)
 	if (ret)
 		goto put_clk_ce;
 
+	initialized = 1;
+
 	pr_info("%pOFn #0 at %p, irq=%d\n", timer, timer_baseaddr, irq);
 
 	return 0;
@@ -541,9 +541,10 @@ 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 = {
+	.probe = ttc_timer_probe,
 	.driver = {
 		.name	= "cdns_ttc_timer",
 		.of_match_table = ttc_timer_of_match,
 	},
 };
-builtin_platform_driver_probe(ttc_timer_driver, ttc_timer_probe);
+builtin_platform_driver(ttc_timer_driver);

-- 
2.34.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 3/5] clocksource: timer-cadence-ttc: Refactor common TTC resource setup
  2026-10-07  9:06 [PATCH 0/5] Add PWM support for Cadence TTC Meher Thanmaiee
  2026-10-07  9:06 ` [PATCH 1/5] clocksource: timer-cadence-ttc: Move register definitions to shared header Meher Thanmaiee
  2026-10-07  9:07 ` [PATCH 2/5] clocksource: timer-cadence-ttc: Allow deferred probing Meher Thanmaiee
@ 2026-10-07  9:07 ` Meher Thanmaiee
  2026-10-07  9:07 ` [PATCH 4/5] pwm: cadence: Add TTC PWM driver Meher Thanmaiee
  2026-10-07  9:07 ` [PATCH 5/5] clocksource: timer-cadence-ttc: Add PWM auxiliary-device support Meher Thanmaiee
  4 siblings, 0 replies; 7+ messages in thread
From: Meher Thanmaiee @ 2026-10-07  9:07 UTC (permalink / raw)
  To: michal.simek, tglx, ukleinek, daniel.lezcano
  Cc: linux-arm-kernel, linux-kernel, git, meherthanmaiee.vanukuri, linux-pwm

Factor the TTC MMIO mapping and timer-width parsing in the timer probe
path into a helper.

As part of the refactor, switch the timer probe path from
devm_of_iomap() to devm_platform_ioremap_resource(). This is safe
because each Cadence TTC device tree node has a dedicated,
non-overlapping MMIO resource.

Also replace the hardcoded default timer width and channel stride with
TTC_DEFAULT_TIMER_WIDTH and TTC_CH_OFFSET, and switch to
device_property_read_u32() when reading timer-width.

This prepares the timer driver for later reuse of the common resource
setup by the PWM auxiliary-device path.

Signed-off-by: Meher Thanmaiee <meherthanmaiee.vanukuri@amd.com>
---
 drivers/clocksource/timer-cadence-ttc.c | 49 ++++++++++++++++++---------------
 include/linux/timer-cadence-ttc.h       |  5 ++++
 2 files changed, 32 insertions(+), 22 deletions(-)

diff --git a/drivers/clocksource/timer-cadence-ttc.c b/drivers/clocksource/timer-cadence-ttc.c
index 75bc0af1fa9e..954a9b85a958 100644
--- a/drivers/clocksource/timer-cadence-ttc.c
+++ b/drivers/clocksource/timer-cadence-ttc.c
@@ -8,16 +8,16 @@
  */
 
 #include <linux/clk.h>
-#include <linux/interrupt.h>
 #include <linux/clockchips.h>
 #include <linux/clocksource.h>
-#include <linux/of_address.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
 #include <linux/of_irq.h>
+#include <linux/of_platform.h>
 #include <linux/platform_device.h>
-#include <linux/slab.h>
+#include <linux/property.h>
 #include <linux/sched_clock.h>
-#include <linux/module.h>
-#include <linux/of_platform.h>
+#include <linux/slab.h>
 #include <linux/timer-cadence-ttc.h>
 
 /*
@@ -463,29 +463,36 @@ static int ttc_setup_clockevent(struct clk *clk,
 	return err;
 }
 
+static int ttc_init_common(struct platform_device *pdev,
+			   void __iomem **base, u32 *timer_width)
+{
+	*base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(*base))
+		return PTR_ERR(*base);
+
+	*timer_width = TTC_DEFAULT_TIMER_WIDTH;
+	device_property_read_u32(&pdev->dev, "timer-width", timer_width);
+
+	return 0;
+}
+
 static int ttc_timer_probe(struct platform_device *pdev)
 {
-	unsigned int irq;
+	struct device_node *timer = pdev->dev.of_node;
 	void __iomem *timer_baseaddr;
 	struct clk *clk_cs, *clk_ce;
 	static int initialized;
+	unsigned int irq;
+	u32 timer_width;
 	int clksel, ret;
-	u32 timer_width = 16;
-	struct device_node *timer = pdev->dev.of_node;
 
 	if (initialized)
 		return 0;
 
-	/*
-	 * Get the 1st Triple Timer Counter (TTC) block from the device tree
-	 * and use it. Note that the event timer uses the interrupt and it's the
-	 * 2nd TTC hence the irq_of_parse_and_map(,1)
-	 */
-	timer_baseaddr = devm_of_iomap(&pdev->dev, timer, 0, NULL);
-	if (IS_ERR(timer_baseaddr)) {
-		pr_err("ERROR: invalid timer base address\n");
-		return PTR_ERR(timer_baseaddr);
-	}
+	ret = ttc_init_common(pdev, &timer_baseaddr, &timer_width);
+	if (ret)
+		return dev_err_probe(&pdev->dev, ret,
+				     "failed to map timer registers\n");
 
 	irq = irq_of_parse_and_map(timer, 1);
 	if (irq <= 0) {
@@ -493,8 +500,6 @@ static int ttc_timer_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
-	of_property_read_u32(timer, "timer-width", &timer_width);
-
 	clksel = readl_relaxed(timer_baseaddr + TTC_CLK_CNTRL_OFFSET);
 	clksel = !!(clksel & TTC_CLK_CNTRL_CSRC_MASK);
 	clk_cs = of_clk_get(timer, clksel);
@@ -503,7 +508,7 @@ static int ttc_timer_probe(struct platform_device *pdev)
 		return PTR_ERR(clk_cs);
 	}
 
-	clksel = readl_relaxed(timer_baseaddr + 4 + TTC_CLK_CNTRL_OFFSET);
+	clksel = readl_relaxed(timer_baseaddr + TTC_CH_OFFSET + TTC_CLK_CNTRL_OFFSET);
 	clksel = !!(clksel & TTC_CLK_CNTRL_CSRC_MASK);
 	clk_ce = of_clk_get(timer, clksel);
 	if (IS_ERR(clk_ce)) {
@@ -516,7 +521,7 @@ static int ttc_timer_probe(struct platform_device *pdev)
 	if (ret)
 		goto put_clk_ce;
 
-	ret = ttc_setup_clockevent(clk_ce, timer_baseaddr + 4, irq);
+	ret = ttc_setup_clockevent(clk_ce, timer_baseaddr + TTC_CH_OFFSET, irq);
 	if (ret)
 		goto put_clk_ce;
 
diff --git a/include/linux/timer-cadence-ttc.h b/include/linux/timer-cadence-ttc.h
index 4f2b85e0ff78..37ac775d6d50 100644
--- a/include/linux/timer-cadence-ttc.h
+++ b/include/linux/timer-cadence-ttc.h
@@ -11,6 +11,11 @@
 
 #include <linux/bits.h>
 
+#define TTC_DEFAULT_TIMER_WIDTH		16
+
+/* Per-channel register offset stride */
+#define TTC_CH_OFFSET			0x04
+
 /* Timer Register Offset Definitions of Timer 1 */
 #define TTC_CLK_CNTRL_OFFSET		0x00 /* Clock Control Reg, RW */
 #define TTC_CNT_CNTRL_OFFSET		0x0C /* Counter Control Reg, RW */

-- 
2.34.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 4/5] pwm: cadence: Add TTC PWM driver
  2026-10-07  9:06 [PATCH 0/5] Add PWM support for Cadence TTC Meher Thanmaiee
                   ` (2 preceding siblings ...)
  2026-10-07  9:07 ` [PATCH 3/5] clocksource: timer-cadence-ttc: Refactor common TTC resource setup Meher Thanmaiee
@ 2026-10-07  9:07 ` Meher Thanmaiee
  2026-10-07 11:41   ` Uwe Kleine-König
  2026-10-07  9:07 ` [PATCH 5/5] clocksource: timer-cadence-ttc: Add PWM auxiliary-device support Meher Thanmaiee
  4 siblings, 1 reply; 7+ messages in thread
From: Meher Thanmaiee @ 2026-10-07  9:07 UTC (permalink / raw)
  To: michal.simek, tglx, ukleinek, daniel.lezcano
  Cc: linux-arm-kernel, linux-kernel, git, meherthanmaiee.vanukuri, linux-pwm

Add a PWM driver for the Cadence Triple Timer Counter (TTC) IP found
on Xilinx Zynq, ZynqMP, and Versal SoCs.

The driver binds to auxiliary-bus devices created by the TTC timer
driver when #pwm-cells is present in the device tree, and exposes the
three TTC channels as PWM outputs. The PWM period is programmed
through the interval counter and the duty cycle through the match
counter.

Add the PWM-specific TTC register definitions, shared data structure,
and per-channel access helpers to the shared TTC header so the driver
can access the parent-provided MMIO base, clock, rate, and timer width.

Co-developed-by: Mubin Sayyed <mubin.sayyed@amd.com>
Signed-off-by: Mubin Sayyed <mubin.sayyed@amd.com>
Signed-off-by: Meher Thanmaiee <meherthanmaiee.vanukuri@amd.com>
---
 MAINTAINERS                       |   1 +
 drivers/pwm/Kconfig               |  13 +++
 drivers/pwm/Makefile              |   1 +
 drivers/pwm/pwm-cadence.c         | 231 ++++++++++++++++++++++++++++++++++++++
 include/linux/timer-cadence-ttc.h |  40 +++++++
 5 files changed, 286 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index b25ad0c18ffd..071290662523 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3922,6 +3922,7 @@ F:	drivers/edac/synopsys_edac.c
 F:	drivers/i2c/busses/i2c-cadence.c
 F:	drivers/i2c/busses/i2c-xiic.c
 F:	drivers/mmc/host/sdhci-of-arasan.c
+F:	drivers/pwm/pwm-cadence.c
 F:	include/linux/timer-cadence-ttc.h
 N:	zynq
 N:	xilinx
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index 729776086879..a267a15a9685 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -196,6 +196,19 @@ config PWM_BRCMSTB
 	  To compile this driver as a module, choose M Here: the module
 	  will be called pwm-brcmstb.c.
 
+config PWM_CADENCE
+	tristate "Cadence TTC PWM support"
+	depends on CADENCE_TTC_TIMER
+	help
+	  PWM framework driver for the Cadence TTC IP found on Xilinx
+	  Zynq/ZynqMP/Versal SoCs. Binds to auxiliary-bus devices
+	  created by the TTC clocksource driver when a TTC node
+	  contains the #pwm-cells property. Each TTC provides up to
+	  3 PWM channels.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called pwm-cadence.
+
 config PWM_CLK
 	tristate "Clock based PWM support"
 	depends on HAVE_CLK || COMPILE_TEST
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index 5630a521a7cf..f116b9629eee 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_PWM_BCM_IPROC)	+= pwm-bcm-iproc.o
 obj-$(CONFIG_PWM_BCM_KONA)	+= pwm-bcm-kona.o
 obj-$(CONFIG_PWM_BERLIN)	+= pwm-berlin.o
 obj-$(CONFIG_PWM_BRCMSTB)	+= pwm-brcmstb.o
+obj-$(CONFIG_PWM_CADENCE)	+= pwm-cadence.o
 obj-$(CONFIG_PWM_CLK)		+= pwm-clk.o
 obj-$(CONFIG_PWM_CLPS711X)	+= pwm-clps711x.o
 obj-$(CONFIG_PWM_CRC)		+= pwm-crc.o
diff --git a/drivers/pwm/pwm-cadence.c b/drivers/pwm/pwm-cadence.c
new file mode 100644
index 000000000000..f02f37ccb741
--- /dev/null
+++ b/drivers/pwm/pwm-cadence.c
@@ -0,0 +1,231 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Cadence TTC PWM driver
+ *
+ * Configures Cadence Triple Timer Counter channels as PWM outputs.
+ * Binds to auxiliary-bus devices created by the TTC clocksource driver.
+ *
+ * Limitations:
+ * - When PWM is stopped, timer counter gets stopped immediately. This
+ *   doesn't allow the current PWM period to complete and stops abruptly.
+ * - Disabled PWM emits inactive level.
+ * - When user requests a change in any parameter of PWM (period/duty cycle/polarity)
+ *   while PWM is in enabled state:
+ *	- PWM is stopped abruptly.
+ *	- Requested parameter is changed.
+ *	- Fresh PWM cycle is started.
+ *
+ * Copyright (C) 2026, Advanced Micro Devices, Inc.
+ */
+
+#include <linux/auxiliary_bus.h>
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/log2.h>
+#include <linux/math64.h>
+#include <linux/module.h>
+#include <linux/pwm.h>
+#include <linux/timer-cadence-ttc.h>
+
+struct cdns_ttc_pwm {
+	const struct ttc_shared_data	*sd;
+	u32				max_count;
+};
+
+static inline struct cdns_ttc_pwm *to_cdns_ttc_pwm(struct pwm_chip *chip)
+{
+	return pwmchip_get_drvdata(chip);
+}
+
+static void cdns_ttc_pwm_enable(struct cdns_ttc_pwm *priv, unsigned int hwpwm)
+{
+	u32 ctrl;
+
+	ctrl = ttc_ch_readl(priv->sd, hwpwm, TTC_CNT_CNTRL_OFFSET);
+	ctrl |= TTC_CNT_CNTRL_INT | TTC_CNT_CNTRL_MATCH | TTC_CNT_CNTRL_RST;
+	ctrl &= ~(TTC_CNT_CNTRL_DISABLE_MASK | TTC_CNT_CNTRL_WAVE_EN);
+	ttc_ch_writel(priv->sd, hwpwm, TTC_CNT_CNTRL_OFFSET, ctrl);
+}
+
+static void cdns_ttc_pwm_disable(struct cdns_ttc_pwm *priv, unsigned int hwpwm)
+{
+	u32 ctrl;
+
+	ctrl = ttc_ch_readl(priv->sd, hwpwm, TTC_CNT_CNTRL_OFFSET);
+	ctrl |= TTC_CNT_CNTRL_DISABLE_MASK;
+	ttc_ch_writel(priv->sd, hwpwm, TTC_CNT_CNTRL_OFFSET, ctrl);
+}
+
+static int cdns_ttc_pwm_apply(struct pwm_chip *chip,
+			      struct pwm_device *pwm,
+			      const struct pwm_state *state)
+{
+	struct cdns_ttc_pwm *priv = to_cdns_ttc_pwm(chip);
+	unsigned long rate = priv->sd->rate;
+	unsigned int hwpwm = pwm->hwpwm;
+	u64 period_cycles, duty_cycles;
+	bool use_prescaler = false;
+	u32 ctrl, psv;
+
+	if (!state->enabled) {
+		cdns_ttc_pwm_disable(priv, hwpwm);
+		return 0;
+	}
+
+	period_cycles = mul_u64_u64_div_u64(state->period, rate, NSEC_PER_SEC);
+
+	if (period_cycles > priv->max_count) {
+		unsigned int shift;
+
+		/*
+		 * Prescaler divides input clock by 2^(psv+1).
+		 * Calculate required shift and derive PSV register value.
+		 */
+		shift = order_base_2(DIV_ROUND_UP_ULL(period_cycles,
+						      priv->max_count));
+		if (shift > TTC_CLK_CNTRL_PSV_MAX + 1)
+			return -ERANGE;
+
+		use_prescaler = true;
+		psv = shift - 1;
+
+		period_cycles = mul_u64_u64_div_u64(state->period, rate,
+						    (u64)NSEC_PER_SEC << shift);
+	}
+
+	if (!period_cycles)
+		return -EINVAL;
+
+	cdns_ttc_pwm_disable(priv, hwpwm);
+
+	ctrl = ttc_ch_readl(priv->sd, hwpwm, TTC_CNT_CNTRL_OFFSET);
+	if (state->polarity == PWM_POLARITY_NORMAL)
+		ctrl |= TTC_CNT_CNTRL_WAVE_POL;
+	else
+		ctrl &= ~TTC_CNT_CNTRL_WAVE_POL;
+	ttc_ch_writel(priv->sd, hwpwm, TTC_CNT_CNTRL_OFFSET, ctrl);
+
+	if (use_prescaler) {
+		duty_cycles = mul_u64_u64_div_u64(state->duty_cycle, rate,
+						  (u64)NSEC_PER_SEC << (psv + 1));
+	} else {
+		duty_cycles = mul_u64_u64_div_u64(state->duty_cycle, rate,
+						  NSEC_PER_SEC);
+	}
+
+	ttc_ch_writel(priv->sd, hwpwm, TTC_INTR_VAL_OFFSET, (u32)period_cycles);
+	ttc_ch_writel(priv->sd, hwpwm, TTC_MATCH_CNT_VAL_OFFSET, (u32)duty_cycles);
+
+	ctrl = ttc_ch_readl(priv->sd, hwpwm, TTC_CLK_CNTRL_OFFSET);
+	if (use_prescaler) {
+		ctrl &= ~TTC_CLK_CNTRL_PSV_MASK;
+		ctrl |= FIELD_PREP(TTC_CLK_CNTRL_PSV_MASK, psv);
+		ctrl |= TTC_CLK_CNTRL_PS_EN;
+	} else {
+		ctrl &= ~TTC_CLK_CNTRL_PS_EN;
+	}
+	ttc_ch_writel(priv->sd, hwpwm, TTC_CLK_CNTRL_OFFSET, ctrl);
+
+	cdns_ttc_pwm_enable(priv, hwpwm);
+
+	return 0;
+}
+
+static int cdns_ttc_pwm_get_state(struct pwm_chip *chip,
+				  struct pwm_device *pwm,
+				  struct pwm_state *state)
+{
+	struct cdns_ttc_pwm *priv = to_cdns_ttc_pwm(chip);
+	unsigned long rate = priv->sd->rate;
+	unsigned int hwpwm = pwm->hwpwm;
+	u32 ctrl, clk_ctrl, pres;
+	u64 tmp;
+
+	ctrl = ttc_ch_readl(priv->sd, hwpwm, TTC_CNT_CNTRL_OFFSET);
+
+	state->polarity = (ctrl & TTC_CNT_CNTRL_WAVE_POL) ?
+			  PWM_POLARITY_NORMAL : PWM_POLARITY_INVERSED;
+
+	if (ctrl & TTC_CNT_CNTRL_DISABLE_MASK) {
+		state->enabled = false;
+		state->period = 0;
+		state->duty_cycle = 0;
+		return 0;
+	}
+
+	state->enabled = true;
+
+	clk_ctrl = ttc_ch_readl(priv->sd, hwpwm, TTC_CLK_CNTRL_OFFSET);
+	pres = 0;
+	if (clk_ctrl & TTC_CLK_CNTRL_PS_EN)
+		pres = FIELD_GET(TTC_CLK_CNTRL_PSV_MASK, clk_ctrl) + 1;
+
+	tmp = (u64)ttc_ch_readl(priv->sd, hwpwm, TTC_INTR_VAL_OFFSET) << pres;
+	state->period = mul_u64_u64_div_u64(tmp, NSEC_PER_SEC, rate);
+	if (mul_u64_u64_div_u64(state->period, rate, NSEC_PER_SEC) < tmp)
+		state->period++;
+
+	tmp = (u64)ttc_ch_readl(priv->sd, hwpwm, TTC_MATCH_CNT_VAL_OFFSET) << pres;
+	state->duty_cycle = mul_u64_u64_div_u64(tmp, NSEC_PER_SEC, rate);
+	if (mul_u64_u64_div_u64(state->duty_cycle, rate, NSEC_PER_SEC) < tmp)
+		state->duty_cycle++;
+
+	return 0;
+}
+
+static const struct pwm_ops cdns_ttc_pwm_ops = {
+	.apply = cdns_ttc_pwm_apply,
+	.get_state = cdns_ttc_pwm_get_state,
+};
+
+static int cdns_ttc_pwm_probe(struct auxiliary_device *auxdev,
+			      const struct auxiliary_device_id *id)
+{
+	const struct ttc_shared_data *sd = dev_get_platdata(&auxdev->dev);
+	struct device *dev = &auxdev->dev;
+	struct cdns_ttc_pwm *priv;
+	struct pwm_chip *chip;
+	int ret;
+
+	if (!sd)
+		return -EINVAL;
+
+	chip = devm_pwmchip_alloc(dev, TTC_NUM_CHANNELS, sizeof(*priv));
+	if (IS_ERR(chip))
+		return PTR_ERR(chip);
+
+	priv = to_cdns_ttc_pwm(chip);
+	priv->sd = sd;
+	priv->max_count = BIT_ULL(sd->timer_width) - 1;
+
+	ret = devm_clk_rate_exclusive_get(dev, sd->clk);
+	if (ret)
+		return dev_err_probe(dev, ret,
+				     "failed to lock clock rate\n");
+
+	chip->ops = &cdns_ttc_pwm_ops;
+
+	ret = devm_pwmchip_add(dev, chip);
+	if (ret)
+		return dev_err_probe(dev, ret, "could not register PWM chip\n");
+
+	return 0;
+}
+
+static const struct auxiliary_device_id cdns_ttc_pwm_id_table[] = {
+	{ .name = "timer_cadence_ttc.pwm" },
+	{},
+};
+MODULE_DEVICE_TABLE(auxiliary, cdns_ttc_pwm_id_table);
+
+static struct auxiliary_driver cdns_ttc_pwm_driver = {
+	.name     = "cdns_ttc_pwm",
+	.probe    = cdns_ttc_pwm_probe,
+	.id_table = cdns_ttc_pwm_id_table,
+};
+module_auxiliary_driver(cdns_ttc_pwm_driver);
+
+MODULE_AUTHOR("Mubin Sayyed <mubin.sayyed@amd.com>");
+MODULE_AUTHOR("Meher Thanmaiee <meherthanmaiee.vanukuri@amd.com>");
+MODULE_DESCRIPTION("Cadence TTC PWM driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/timer-cadence-ttc.h b/include/linux/timer-cadence-ttc.h
index 37ac775d6d50..05b7edd88626 100644
--- a/include/linux/timer-cadence-ttc.h
+++ b/include/linux/timer-cadence-ttc.h
@@ -10,24 +10,64 @@
 #define _LINUX_TIMER_CADENCE_TTC_H
 
 #include <linux/bits.h>
+#include <linux/io.h>
+#include <linux/types.h>
+
+struct clk;
 
 #define TTC_DEFAULT_TIMER_WIDTH		16
 
 /* Per-channel register offset stride */
 #define TTC_CH_OFFSET			0x04
 
+#define TTC_NUM_CHANNELS		3
+
 /* Timer Register Offset Definitions of Timer 1 */
 #define TTC_CLK_CNTRL_OFFSET		0x00 /* Clock Control Reg, RW */
 #define TTC_CNT_CNTRL_OFFSET		0x0C /* Counter Control Reg, RW */
 #define TTC_COUNT_VAL_OFFSET		0x18 /* Counter Value Reg, RO */
 #define TTC_INTR_VAL_OFFSET		0x24 /* Interval Count Reg, RW */
+#define TTC_MATCH_CNT_VAL_OFFSET	0x30 /* Match 1 Count Reg, RW */
 #define TTC_ISR_OFFSET			0x54 /* Interrupt Status Reg, RO */
 #define TTC_IER_OFFSET			0x60 /* Interrupt Enable Reg, RW */
 
 #define TTC_CNT_CNTRL_DISABLE_MASK	BIT(0)
+#define TTC_CNT_CNTRL_INT		BIT(1)
+#define TTC_CNT_CNTRL_MATCH		BIT(3)
+#define TTC_CNT_CNTRL_RST		BIT(4)
+#define TTC_CNT_CNTRL_WAVE_EN		BIT(5)
+#define TTC_CNT_CNTRL_WAVE_POL		BIT(6)
 
+#define TTC_CLK_CNTRL_PS_EN		BIT(0)
 #define TTC_CLK_CNTRL_CSRC_MASK		BIT(5) /* clock source */
 #define TTC_CLK_CNTRL_PSV_MASK		GENMASK(4, 1)
 #define TTC_CLK_CNTRL_PSV_SHIFT		1
+#define TTC_CLK_CNTRL_PSV_MAX		15 /* 4-bit prescaler field */
+
+/**
+ * struct ttc_shared_data - Data passed from parent to auxiliary device
+ * @base:		MMIO base address
+ * @clk:		Input clock
+ * @rate:		Input clock rate in Hz
+ * @timer_width:	Counter width in bits (16 or 32)
+ */
+struct ttc_shared_data {
+	void __iomem		*base;
+	struct clk		*clk;
+	unsigned long		rate;
+	u32			timer_width;
+};
+
+static inline u32 ttc_ch_readl(const struct ttc_shared_data *sd,
+			       unsigned int ch, u32 reg)
+{
+	return readl_relaxed(sd->base + reg + TTC_CH_OFFSET * ch);
+}
+
+static inline void ttc_ch_writel(const struct ttc_shared_data *sd,
+				 unsigned int ch, u32 reg, u32 val)
+{
+	writel_relaxed(val, sd->base + reg + TTC_CH_OFFSET * ch);
+}
 
 #endif /* _LINUX_TIMER_CADENCE_TTC_H */

-- 
2.34.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 5/5] clocksource: timer-cadence-ttc: Add PWM auxiliary-device support
  2026-10-07  9:06 [PATCH 0/5] Add PWM support for Cadence TTC Meher Thanmaiee
                   ` (3 preceding siblings ...)
  2026-10-07  9:07 ` [PATCH 4/5] pwm: cadence: Add TTC PWM driver Meher Thanmaiee
@ 2026-10-07  9:07 ` Meher Thanmaiee
  4 siblings, 0 replies; 7+ messages in thread
From: Meher Thanmaiee @ 2026-10-07  9:07 UTC (permalink / raw)
  To: michal.simek, tglx, ukleinek, daniel.lezcano
  Cc: linux-arm-kernel, linux-kernel, git, meherthanmaiee.vanukuri, linux-pwm

When a TTC device tree node contains #pwm-cells, create an
auxiliary-bus child device so the Cadence TTC PWM driver can bind to
that instance instead of using it as a clocksource and clockevent
device.

Propagate the parent device tree node to the auxiliary device so PWM
consumers can be matched through the device tree, and pass the mapped
register base, input clock, clock rate, and timer width to the child
driver through shared TTC data.

PWM support is limited to TTC instances whose channels use the shared
internal/reference clock. Reject instances configured to use the
alternate external clock source, which would require per-channel clock
source selection and rate handling.

Select AUXILIARY_BUS in Kconfig for the auxiliary-bus device creation.

Signed-off-by: Meher Thanmaiee <meherthanmaiee.vanukuri@amd.com>
---
 drivers/clocksource/Kconfig             |   5 ++
 drivers/clocksource/timer-cadence-ttc.c | 124 ++++++++++++++++++++++++++++++++
 include/linux/timer-cadence-ttc.h       |   1 +
 3 files changed, 130 insertions(+)

diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index d9c76dd443f8..098cc40f68b0 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -201,9 +201,14 @@ config NPCM7XX_TIMER
 config CADENCE_TTC_TIMER
 	bool "Cadence TTC timer driver" if COMPILE_TEST
 	depends on COMMON_CLK
+	select AUXILIARY_BUS
 	help
 	  Enables support for the Cadence TTC driver.
 
+	  When a TTC device-tree node contains #pwm-cells, this
+	  driver creates an auxiliary-bus device that is bound by
+	  the Cadence TTC PWM driver.
+
 config ASM9260_TIMER
 	bool "ASM9260 timer driver" if COMPILE_TEST
 	select CLKSRC_MMIO
diff --git a/drivers/clocksource/timer-cadence-ttc.c b/drivers/clocksource/timer-cadence-ttc.c
index 954a9b85a958..fded136b448e 100644
--- a/drivers/clocksource/timer-cadence-ttc.c
+++ b/drivers/clocksource/timer-cadence-ttc.c
@@ -7,6 +7,8 @@
  * based on arch/mips/kernel/time.c timer driver
  */
 
+#include <linux/atomic.h>
+#include <linux/auxiliary_bus.h>
 #include <linux/clk.h>
 #include <linux/clockchips.h>
 #include <linux/clocksource.h>
@@ -476,6 +478,121 @@ static int ttc_init_common(struct platform_device *pdev,
 	return 0;
 }
 
+#if IS_ENABLED(CONFIG_PWM_CADENCE)
+
+/* Auxiliary-bus device wrapper */
+struct ttc_auxdev {
+	struct auxiliary_device adev;
+	struct ttc_shared_data sd;
+};
+
+static void ttc_auxdev_release(struct device *dev)
+{
+	struct auxiliary_device *adev = to_auxiliary_dev(dev);
+	struct ttc_auxdev *ta = container_of(adev, struct ttc_auxdev, adev);
+
+	of_node_put(dev->of_node);
+	kfree(ta);
+}
+
+static atomic_t ttc_auxdev_id;
+
+static void ttc_auxdev_teardown(void *data)
+{
+	struct auxiliary_device *adev = data;
+
+	auxiliary_device_delete(adev);
+	auxiliary_device_uninit(adev);
+}
+
+static int ttc_create_aux(struct device *parent, const char *name,
+			  const struct ttc_shared_data *sd)
+{
+	struct ttc_auxdev *ta;
+	int ret;
+
+	ta = kzalloc_obj(*ta);
+	if (!ta)
+		return -ENOMEM;
+
+	ta->sd = *sd;
+	ta->adev.name = name;
+	ta->adev.id = atomic_fetch_inc(&ttc_auxdev_id);
+	ta->adev.dev.parent = parent;
+	ta->adev.dev.release = ttc_auxdev_release;
+	ta->adev.dev.platform_data = &ta->sd;
+	device_set_of_node_from_dev(&ta->adev.dev, parent);
+
+	ret = auxiliary_device_init(&ta->adev);
+	if (ret) {
+		of_node_put(ta->adev.dev.of_node);
+		kfree(ta);
+		return ret;
+	}
+
+	ret = auxiliary_device_add(&ta->adev);
+	if (ret) {
+		auxiliary_device_uninit(&ta->adev);
+		return ret;
+	}
+
+	return devm_add_action_or_reset(parent, ttc_auxdev_teardown,
+					&ta->adev);
+}
+
+static int ttc_probe_auxbus(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct ttc_shared_data sd;
+	struct clk *clk;
+	int i, ret;
+	u32 val;
+
+	ret = ttc_init_common(pdev, &sd.base, &sd.timer_width);
+	if (ret)
+		return ret;
+
+	if (sd.timer_width == 0 || sd.timer_width > TTC_MAX_TIMER_WIDTH)
+		return dev_err_probe(dev, -EINVAL,
+				     "invalid timer-width value\n");
+
+	/*
+	 * PWM support is limited to the shared internal/reference clock on
+	 * all channels. Supporting the alternate external clock source
+	 * would require per-channel clock and rate handling.
+	 */
+	for (i = 0; i < TTC_NUM_CHANNELS; i++) {
+		val = ttc_ch_readl(&sd, i, TTC_CLK_CNTRL_OFFSET);
+		if (val & TTC_CLK_CNTRL_CSRC_MASK)
+			return dev_err_probe(dev, -EINVAL,
+					     "external clock source not supported for PWM\n");
+	}
+
+	clk = devm_clk_get_enabled(dev, NULL);
+	if (IS_ERR(clk))
+		return dev_err_probe(dev, PTR_ERR(clk),
+				     "failed to get timer input clock\n");
+
+	sd.clk = clk;
+	sd.rate = clk_get_rate(clk);
+	if (!sd.rate)
+		return dev_err_probe(dev, -EINVAL,
+				     "failed to get clock rate\n");
+
+	ret = ttc_create_aux(dev, "pwm", &sd);
+	if (ret)
+		return dev_err_probe(dev, ret,
+				     "failed to create PWM aux device\n");
+
+	return 0;
+}
+#else
+static inline int ttc_probe_auxbus(struct platform_device *pdev)
+{
+	return 0;
+}
+#endif
+
 static int ttc_timer_probe(struct platform_device *pdev)
 {
 	struct device_node *timer = pdev->dev.of_node;
@@ -486,6 +603,13 @@ static int ttc_timer_probe(struct platform_device *pdev)
 	u32 timer_width;
 	int clksel, ret;
 
+	/*
+	 * If #pwm-cells is present, this TTC is used for PWM.
+	 * Create an auxiliary-bus child device for the PWM driver.
+	 */
+	if (device_property_present(&pdev->dev, "#pwm-cells"))
+		return ttc_probe_auxbus(pdev);
+
 	if (initialized)
 		return 0;
 
diff --git a/include/linux/timer-cadence-ttc.h b/include/linux/timer-cadence-ttc.h
index 05b7edd88626..58cc7db72693 100644
--- a/include/linux/timer-cadence-ttc.h
+++ b/include/linux/timer-cadence-ttc.h
@@ -16,6 +16,7 @@
 struct clk;
 
 #define TTC_DEFAULT_TIMER_WIDTH		16
+#define TTC_MAX_TIMER_WIDTH		32
 
 /* Per-channel register offset stride */
 #define TTC_CH_OFFSET			0x04

-- 
2.34.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 4/5] pwm: cadence: Add TTC PWM driver
  2026-10-07  9:07 ` [PATCH 4/5] pwm: cadence: Add TTC PWM driver Meher Thanmaiee
@ 2026-10-07 11:41   ` Uwe Kleine-König
  0 siblings, 0 replies; 7+ messages in thread
From: Uwe Kleine-König @ 2026-10-07 11:41 UTC (permalink / raw)
  To: Meher Thanmaiee
  Cc: michal.simek, tglx, daniel.lezcano, linux-arm-kernel,
	linux-kernel, git, linux-pwm, Michal Wilczynski

[-- Attachment #1: Type: text/plain, Size: 477 bytes --]

Hello,

On Wed, Oct 07, 2026 at 02:37:02PM +0530, Meher Thanmaiee wrote:
> +static const struct pwm_ops cdns_ttc_pwm_ops = {
> +	.apply = cdns_ttc_pwm_apply,
> +	.get_state = cdns_ttc_pwm_get_state,
> +};

Just a very quick review: I won't take any new drivers using .apply().
Please use the waveform stuff. And also note that there is Rust support
for PWMs, so if you're adventurous try that. (The reference in that case
would be drivers/pwm/pwm_th1520.rs.)

Best regards
Uwe

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-10-07 11:41 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-07  9:06 [PATCH 0/5] Add PWM support for Cadence TTC Meher Thanmaiee
2026-10-07  9:06 ` [PATCH 1/5] clocksource: timer-cadence-ttc: Move register definitions to shared header Meher Thanmaiee
2026-10-07  9:07 ` [PATCH 2/5] clocksource: timer-cadence-ttc: Allow deferred probing Meher Thanmaiee
2026-10-07  9:07 ` [PATCH 3/5] clocksource: timer-cadence-ttc: Refactor common TTC resource setup Meher Thanmaiee
2026-10-07  9:07 ` [PATCH 4/5] pwm: cadence: Add TTC PWM driver Meher Thanmaiee
2026-10-07 11:41   ` Uwe Kleine-König
2026-10-07  9:07 ` [PATCH 5/5] clocksource: timer-cadence-ttc: Add PWM auxiliary-device support Meher Thanmaiee

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®