* [PATCH v6 0/7] Add STM32MP25 LPTIM support: MFD, PWM, IIO, counter, clocksource
@ 2025-04-29 12:51 Fabrice Gasnier
2025-04-29 12:51 ` [PATCH v6 1/7] dt-bindings: mfd: stm32-lptimer: add support for stm32mp25 Fabrice Gasnier
` (10 more replies)
0 siblings, 11 replies; 14+ messages in thread
From: Fabrice Gasnier @ 2025-04-29 12:51 UTC (permalink / raw)
To: daniel.lezcano, lee, alexandre.torgue, tglx
Cc: ukleinek, krzk+dt, conor+dt, jic23, robh, catalin.marinas, will,
devicetree, wbg, linux-stm32, linux-arm-kernel, linux-kernel,
linux-iio, linux-pwm, olivier.moysan, fabrice.gasnier
This series adds support for STM32MP25 to MFD PWM, IIO, counter and
clocksource low-power timer (LPTIM) drivers.
This new variant is managed by using a new DT compatible string, hardware
configuration and version registers.
It comes with a slightly updated register set, some new features and new
interconnect signals inside the SoC.
Same feature list as on STM32MP1x is supported currently.
The device tree files add all instances in stm32mp251 dtsi file.
Changes in V6
---
- Fixed kernel test robot warning
https://lore.kernel.org/oe-kbuild-all/202504261456.aCATBoYN-lkp@intel.com/
Changes in V5
---
- Add a necessary delay in clocksource driver, when enabling the timer.
- Add collected Acks
- Dropped IIO trigger patch as applied by Jonathan [1] (no dependency)
[1] https://lore.kernel.org/all/20250331110435.26157ebe@jic23-huawei/
Changes in V4
---
- Simplify IIO trigger driver as per Jonathan's comments.
- Rework clocksource driver: encapsulate mp25 changes in separate function
after Daniel's suggestion.
- Add some definitions to MFD header.
Changes in V3
---
- Yaml indentation issue fixed, reported by Rob's bot
Changes in V2
---
- Review comments from Krzysztof
- Adopt compatible fallback in dt-bindings and driver
- drivers: drop "st,stm32mp25-..." compatibles when unused (e.g. no .data)
- counter driver: no update (patch dropped)
- defconfig: only enable the necessary config for upstream board
- add lptimer DT node in stm32mp257f-ev1 board
- Add missing management of IER access for stm32mp25
Fabrice Gasnier (7):
dt-bindings: mfd: stm32-lptimer: add support for stm32mp25
mfd: stm32-lptimer: add support for stm32mp25
clocksource: stm32-lptimer: add support for stm32mp25
pwm: stm32-lp: add support for stm32mp25
arm64: defconfig: enable STM32 LP timer clockevent driver
arm64: dts: st: add low-power timer nodes on stm32mp251
arm64: dts: st: use lptimer3 as tick broadcast source on
stm32mp257f-ev1
.../bindings/mfd/st,stm32-lptimer.yaml | 40 +++-
arch/arm64/boot/dts/st/stm32mp251.dtsi | 177 ++++++++++++++
arch/arm64/boot/dts/st/stm32mp257f-ev1.dts | 8 +
arch/arm64/configs/defconfig | 2 +
drivers/clocksource/timer-stm32-lp.c | 61 ++++-
drivers/mfd/stm32-lptimer.c | 33 ++-
drivers/pwm/pwm-stm32-lp.c | 219 +++++++++++++++---
include/linux/mfd/stm32-lptimer.h | 37 ++-
8 files changed, 537 insertions(+), 40 deletions(-)
--
2.25.1
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v6 1/7] dt-bindings: mfd: stm32-lptimer: add support for stm32mp25
2025-04-29 12:51 [PATCH v6 0/7] Add STM32MP25 LPTIM support: MFD, PWM, IIO, counter, clocksource Fabrice Gasnier
@ 2025-04-29 12:51 ` Fabrice Gasnier
2025-04-29 12:51 ` [PATCH v6 2/7] " Fabrice Gasnier
` (9 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Fabrice Gasnier @ 2025-04-29 12:51 UTC (permalink / raw)
To: daniel.lezcano, lee, alexandre.torgue, tglx
Cc: ukleinek, krzk+dt, conor+dt, jic23, robh, catalin.marinas, will,
devicetree, wbg, linux-stm32, linux-arm-kernel, linux-kernel,
linux-iio, linux-pwm, olivier.moysan, fabrice.gasnier
Add a new stm32mp25 compatible to stm32-lptimer dt-bindings, to support
STM32MP25 SoC. Some features has been updated or added to the low-power
timer:
- new capture compare channels
- up to two PWM channels
- PWM input capture
- peripheral interconnect in stm32mp25 has been updated (new triggers).
- registers/bits has been added or revisited (IER access).
So introduce a new compatible to handle this diversity.
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
Signed-off-by: Fabrice Gasnier <fabrice.gasnier@foss.st.com>
---
Changes in V4:
- Add Rob's Reviewed-by tag
Changes in V3:
- Fix yaml indentation issue found by Rob's bot
Changes in V2:
- Use fallback compatibles, along with stm32mp25 specific compatible
- trigger identifier can be up to 4 (e.g. from LPTIM1..5)
---
.../bindings/mfd/st,stm32-lptimer.yaml | 40 ++++++++++++++++---
1 file changed, 34 insertions(+), 6 deletions(-)
diff --git a/Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml b/Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml
index d41308856408..4eabafb8079d 100644
--- a/Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml
+++ b/Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml
@@ -21,7 +21,12 @@ maintainers:
properties:
compatible:
- const: st,stm32-lptimer
+ oneOf:
+ - items:
+ - const: st,stm32mp25-lptimer
+ - const: st,stm32-lptimer
+ - items:
+ - const: st,stm32-lptimer
reg:
maxItems: 1
@@ -48,13 +53,21 @@ properties:
minItems: 1
maxItems: 2
+ power-domains:
+ maxItems: 1
+
pwm:
type: object
additionalProperties: false
properties:
compatible:
- const: st,stm32-pwm-lp
+ oneOf:
+ - items:
+ - const: st,stm32mp25-pwm-lp
+ - const: st,stm32-pwm-lp
+ - items:
+ - const: st,stm32-pwm-lp
"#pwm-cells":
const: 3
@@ -69,7 +82,12 @@ properties:
properties:
compatible:
- const: st,stm32-lptimer-counter
+ oneOf:
+ - items:
+ - const: st,stm32mp25-lptimer-counter
+ - const: st,stm32-lptimer-counter
+ - items:
+ - const: st,stm32-lptimer-counter
required:
- compatible
@@ -80,7 +98,12 @@ properties:
properties:
compatible:
- const: st,stm32-lptimer-timer
+ oneOf:
+ - items:
+ - const: st,stm32mp25-lptimer-timer
+ - const: st,stm32-lptimer-timer
+ - items:
+ - const: st,stm32-lptimer-timer
required:
- compatible
@@ -92,13 +115,18 @@ patternProperties:
properties:
compatible:
- const: st,stm32-lptimer-trigger
+ oneOf:
+ - items:
+ - const: st,stm32mp25-lptimer-trigger
+ - const: st,stm32-lptimer-trigger
+ - items:
+ - const: st,stm32-lptimer-trigger
reg:
description: Identify trigger hardware block.
items:
minimum: 0
- maximum: 2
+ maximum: 4
required:
- compatible
--
2.25.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v6 2/7] mfd: stm32-lptimer: add support for stm32mp25
2025-04-29 12:51 [PATCH v6 0/7] Add STM32MP25 LPTIM support: MFD, PWM, IIO, counter, clocksource Fabrice Gasnier
2025-04-29 12:51 ` [PATCH v6 1/7] dt-bindings: mfd: stm32-lptimer: add support for stm32mp25 Fabrice Gasnier
@ 2025-04-29 12:51 ` Fabrice Gasnier
2025-04-29 12:51 ` [PATCH v6 3/7] clocksource: " Fabrice Gasnier
` (8 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Fabrice Gasnier @ 2025-04-29 12:51 UTC (permalink / raw)
To: daniel.lezcano, lee, alexandre.torgue, tglx
Cc: ukleinek, krzk+dt, conor+dt, jic23, robh, catalin.marinas, will,
devicetree, wbg, linux-stm32, linux-arm-kernel, linux-kernel,
linux-iio, linux-pwm, olivier.moysan, fabrice.gasnier
Add support for STM32MP25 SoC.
A new hardware configuration register (HWCFGR2) has been added, to gather
number of capture/compare channels, autonomous mode and input capture
capability. The full feature set is implemented in LPTIM1/2/3/4. LPTIM5
supports a smaller set of features. This can now be read from HWCFGR
registers.
Add new registers to the stm32-lptimer.h: CCMR1, CCR2, HWCFGR1/2 and VERR.
Update the stm32_lptimer data struct so signal the number of
capture/compare channels to the child devices.
Also Remove some unused bit masks (CMPOK_ARROK / CMPOKCF_ARROKCF).
Signed-off-by: Fabrice Gasnier <fabrice.gasnier@foss.st.com>
---
Changes in V4:
- Add DIEROK, ARROK status flags, and their clear flags.
Changes in V2:
- rely on fallback compatible as no specific .data is associated to the
driver. Compatibility is added by reading hardware configuration
registers.
- read version register, to be used by clockevent child driver
- rename register/bits definitions
---
drivers/mfd/stm32-lptimer.c | 33 ++++++++++++++++++++++++++-
include/linux/mfd/stm32-lptimer.h | 37 ++++++++++++++++++++++++++++---
2 files changed, 66 insertions(+), 4 deletions(-)
diff --git a/drivers/mfd/stm32-lptimer.c b/drivers/mfd/stm32-lptimer.c
index b2704a9809c7..09073dbc9c80 100644
--- a/drivers/mfd/stm32-lptimer.c
+++ b/drivers/mfd/stm32-lptimer.c
@@ -6,6 +6,7 @@
* Inspired by Benjamin Gaignard's stm32-timers driver
*/
+#include <linux/bitfield.h>
#include <linux/mfd/stm32-lptimer.h>
#include <linux/module.h>
#include <linux/of_platform.h>
@@ -49,6 +50,36 @@ static int stm32_lptimer_detect_encoder(struct stm32_lptimer *ddata)
return 0;
}
+static int stm32_lptimer_detect_hwcfgr(struct stm32_lptimer *ddata)
+{
+ u32 val;
+ int ret;
+
+ ret = regmap_read(ddata->regmap, STM32_LPTIM_VERR, &ddata->version);
+ if (ret)
+ return ret;
+
+ /* Try to guess parameters from HWCFGR: e.g. encoder mode (STM32MP15) */
+ ret = regmap_read(ddata->regmap, STM32_LPTIM_HWCFGR1, &val);
+ if (ret)
+ return ret;
+
+ /* Fallback to legacy init if HWCFGR isn't present */
+ if (!val)
+ return stm32_lptimer_detect_encoder(ddata);
+
+ ddata->has_encoder = FIELD_GET(STM32_LPTIM_HWCFGR1_ENCODER, val);
+
+ ret = regmap_read(ddata->regmap, STM32_LPTIM_HWCFGR2, &val);
+ if (ret)
+ return ret;
+
+ /* Number of capture/compare channels */
+ ddata->num_cc_chans = FIELD_GET(STM32_LPTIM_HWCFGR2_CHAN_NUM, val);
+
+ return 0;
+}
+
static int stm32_lptimer_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -73,7 +104,7 @@ static int stm32_lptimer_probe(struct platform_device *pdev)
if (IS_ERR(ddata->clk))
return PTR_ERR(ddata->clk);
- ret = stm32_lptimer_detect_encoder(ddata);
+ ret = stm32_lptimer_detect_hwcfgr(ddata);
if (ret)
return ret;
diff --git a/include/linux/mfd/stm32-lptimer.h b/include/linux/mfd/stm32-lptimer.h
index 06d3f11dc3c9..a592c8dc716d 100644
--- a/include/linux/mfd/stm32-lptimer.h
+++ b/include/linux/mfd/stm32-lptimer.h
@@ -17,20 +17,30 @@
#define STM32_LPTIM_IER 0x08 /* Interrupt Enable Reg */
#define STM32_LPTIM_CFGR 0x0C /* Configuration Reg */
#define STM32_LPTIM_CR 0x10 /* Control Reg */
-#define STM32_LPTIM_CMP 0x14 /* Compare Reg */
+#define STM32_LPTIM_CMP 0x14 /* Compare Reg (MP25 CCR1) */
#define STM32_LPTIM_ARR 0x18 /* Autoreload Reg */
#define STM32_LPTIM_CNT 0x1C /* Counter Reg */
+#define STM32_LPTIM_CCMR1 0x2C /* Capture/Compare Mode MP25 */
+#define STM32_LPTIM_CCR2 0x34 /* Compare Reg2 MP25 */
+
+#define STM32_LPTIM_HWCFGR2 0x3EC /* Hardware configuration register 2 - MP25 */
+#define STM32_LPTIM_HWCFGR1 0x3F0 /* Hardware configuration register 1 - MP15 */
+#define STM32_LPTIM_VERR 0x3F4 /* Version identification register - MP15 */
/* STM32_LPTIM_ISR - bit fields */
+#define STM32_LPTIM_DIEROK_ARROK (BIT(24) | BIT(4)) /* MP25 */
+#define STM32_LPTIM_CMP2_ARROK (BIT(19) | BIT(4))
#define STM32_LPTIM_CMPOK_ARROK GENMASK(4, 3)
#define STM32_LPTIM_ARROK BIT(4)
#define STM32_LPTIM_CMPOK BIT(3)
/* STM32_LPTIM_ICR - bit fields */
-#define STM32_LPTIM_ARRMCF BIT(1)
+#define STM32_LPTIM_DIEROKCF_ARROKCF (BIT(24) | BIT(4)) /* MP25 */
+#define STM32_LPTIM_CMP2OKCF_ARROKCF (BIT(19) | BIT(4))
#define STM32_LPTIM_CMPOKCF_ARROKCF GENMASK(4, 3)
+#define STM32_LPTIM_ARRMCF BIT(1)
-/* STM32_LPTIM_IER - bit flieds */
+/* STM32_LPTIM_IER - bit fields */
#define STM32_LPTIM_ARRMIE BIT(1)
/* STM32_LPTIM_CR - bit fields */
@@ -53,16 +63,37 @@
/* STM32_LPTIM_ARR */
#define STM32_LPTIM_MAX_ARR 0xFFFF
+/* STM32_LPTIM_CCMR1 */
+#define STM32_LPTIM_CC2P GENMASK(19, 18)
+#define STM32_LPTIM_CC2E BIT(17)
+#define STM32_LPTIM_CC2SEL BIT(16)
+#define STM32_LPTIM_CC1P GENMASK(3, 2)
+#define STM32_LPTIM_CC1E BIT(1)
+#define STM32_LPTIM_CC1SEL BIT(0)
+
+/* STM32_LPTIM_HWCFGR1 */
+#define STM32_LPTIM_HWCFGR1_ENCODER BIT(16)
+
+/* STM32_LPTIM_HWCFGR2 */
+#define STM32_LPTIM_HWCFGR2_CHAN_NUM GENMASK(3, 0)
+
+/* STM32_LPTIM_VERR */
+#define STM32_LPTIM_VERR_23 0x23 /* STM32MP25 */
+
/**
* struct stm32_lptimer - STM32 Low-Power Timer data assigned by parent device
* @clk: clock reference for this instance
* @regmap: register map reference for this instance
* @has_encoder: indicates this Low-Power Timer supports encoder mode
+ * @num_cc_chans: indicates the number of capture/compare channels
+ * @version: indicates the major and minor revision of the controller
*/
struct stm32_lptimer {
struct clk *clk;
struct regmap *regmap;
bool has_encoder;
+ unsigned int num_cc_chans;
+ u32 version;
};
#endif
--
2.25.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v6 3/7] clocksource: stm32-lptimer: add support for stm32mp25
2025-04-29 12:51 [PATCH v6 0/7] Add STM32MP25 LPTIM support: MFD, PWM, IIO, counter, clocksource Fabrice Gasnier
2025-04-29 12:51 ` [PATCH v6 1/7] dt-bindings: mfd: stm32-lptimer: add support for stm32mp25 Fabrice Gasnier
2025-04-29 12:51 ` [PATCH v6 2/7] " Fabrice Gasnier
@ 2025-04-29 12:51 ` Fabrice Gasnier
2025-05-07 7:55 ` Daniel Lezcano
2025-04-29 12:51 ` [PATCH v6 4/7] pwm: stm32-lp: " Fabrice Gasnier
` (7 subsequent siblings)
10 siblings, 1 reply; 14+ messages in thread
From: Fabrice Gasnier @ 2025-04-29 12:51 UTC (permalink / raw)
To: daniel.lezcano, lee, alexandre.torgue, tglx
Cc: ukleinek, krzk+dt, conor+dt, jic23, robh, catalin.marinas, will,
devicetree, wbg, linux-stm32, linux-arm-kernel, linux-kernel,
linux-iio, linux-pwm, olivier.moysan, fabrice.gasnier
On stm32mp25, DIER (former IER) must only be modified when the lptimer
is enabled. On earlier SoCs, it must be only be modified when it is
disabled. There's also a new DIEROK flag, to ensure register access
has completed.
Add a new "set_evt" routine to be used on stm32mp25, called depending
on the version register, read by the MFD core (LPTIM_VERR).
Signed-off-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
Signed-off-by: Fabrice Gasnier <fabrice.gasnier@foss.st.com>
---
Changes in V6:
- Fixed warning reported by kernel test robot in
https://lore.kernel.org/oe-kbuild-all/202504261456.aCATBoYN-lkp@intel.com/
use FIELD_GET() macro
Changes in V5:
- Added a delay after timer enable, it needs two clock cycles.
Changes in V4:
- Daniel suggests to encapsulate IER write into a separate function
that manages the enabling/disabling of the LP timer. In addition,
DIEROK and ARROK flags checks have been added. So adopt a new routine
to set the event into ARR register and enable the interrupt.
Changes in V2:
- rely on fallback compatible as no specific .data is associated to the
driver. Use version data from MFD core.
- Added interrupt enable register access update in (missed in V1)
---
drivers/clocksource/timer-stm32-lp.c | 61 ++++++++++++++++++++++++++--
1 file changed, 57 insertions(+), 4 deletions(-)
diff --git a/drivers/clocksource/timer-stm32-lp.c b/drivers/clocksource/timer-stm32-lp.c
index 928da2f6de69..6e7944ffd7c0 100644
--- a/drivers/clocksource/timer-stm32-lp.c
+++ b/drivers/clocksource/timer-stm32-lp.c
@@ -5,6 +5,7 @@
* Pascal Paillet <p.paillet@st.com> for STMicroelectronics.
*/
+#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/clockchips.h>
#include <linux/interrupt.h>
@@ -27,6 +28,7 @@ struct stm32_lp_private {
u32 psc;
struct device *dev;
struct clk *clk;
+ u32 version;
};
static struct stm32_lp_private*
@@ -47,12 +49,46 @@ static int stm32_clkevent_lp_shutdown(struct clock_event_device *clkevt)
return 0;
}
-static int stm32_clkevent_lp_set_timer(unsigned long evt,
- struct clock_event_device *clkevt,
- int is_periodic)
+static int stm32mp25_clkevent_lp_set_evt(struct stm32_lp_private *priv, unsigned long evt)
{
- struct stm32_lp_private *priv = to_priv(clkevt);
+ int ret;
+ u32 val;
+
+ regmap_read(priv->reg, STM32_LPTIM_CR, &val);
+ if (!FIELD_GET(STM32_LPTIM_ENABLE, val)) {
+ /* Enable LPTIMER to be able to write into IER and ARR registers */
+ regmap_write(priv->reg, STM32_LPTIM_CR, STM32_LPTIM_ENABLE);
+ /*
+ * After setting the ENABLE bit, a delay of two counter clock cycles is needed
+ * before the LPTIM is actually enabled. For 32KHz rate, this makes approximately
+ * 62.5 micro-seconds, round it up.
+ */
+ udelay(63);
+ }
+ /* set next event counter */
+ regmap_write(priv->reg, STM32_LPTIM_ARR, evt);
+ /* enable ARR interrupt */
+ regmap_write(priv->reg, STM32_LPTIM_IER, STM32_LPTIM_ARRMIE);
+
+ /* Poll DIEROK and ARROK to ensure register access has completed */
+ ret = regmap_read_poll_timeout_atomic(priv->reg, STM32_LPTIM_ISR, val,
+ (val & STM32_LPTIM_DIEROK_ARROK) ==
+ STM32_LPTIM_DIEROK_ARROK,
+ 10, 500);
+ if (ret) {
+ dev_err(priv->dev, "access to LPTIM timed out\n");
+ /* Disable LPTIMER */
+ regmap_write(priv->reg, STM32_LPTIM_CR, 0);
+ return ret;
+ }
+ /* Clear DIEROK and ARROK flags */
+ regmap_write(priv->reg, STM32_LPTIM_ICR, STM32_LPTIM_DIEROKCF_ARROKCF);
+ return 0;
+}
+
+static void stm32_clkevent_lp_set_evt(struct stm32_lp_private *priv, unsigned long evt)
+{
/* disable LPTIMER to be able to write into IER register*/
regmap_write(priv->reg, STM32_LPTIM_CR, 0);
/* enable ARR interrupt */
@@ -61,6 +97,22 @@ static int stm32_clkevent_lp_set_timer(unsigned long evt,
regmap_write(priv->reg, STM32_LPTIM_CR, STM32_LPTIM_ENABLE);
/* set next event counter */
regmap_write(priv->reg, STM32_LPTIM_ARR, evt);
+}
+
+static int stm32_clkevent_lp_set_timer(unsigned long evt,
+ struct clock_event_device *clkevt,
+ int is_periodic)
+{
+ struct stm32_lp_private *priv = to_priv(clkevt);
+ int ret;
+
+ if (priv->version == STM32_LPTIM_VERR_23) {
+ ret = stm32mp25_clkevent_lp_set_evt(priv, evt);
+ if (ret)
+ return ret;
+ } else {
+ stm32_clkevent_lp_set_evt(priv, evt);
+ }
/* start counter */
if (is_periodic)
@@ -176,6 +228,7 @@ static int stm32_clkevent_lp_probe(struct platform_device *pdev)
return -ENOMEM;
priv->reg = ddata->regmap;
+ priv->version = ddata->version;
priv->clk = ddata->clk;
ret = clk_prepare_enable(priv->clk);
if (ret)
--
2.25.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v6 4/7] pwm: stm32-lp: add support for stm32mp25
2025-04-29 12:51 [PATCH v6 0/7] Add STM32MP25 LPTIM support: MFD, PWM, IIO, counter, clocksource Fabrice Gasnier
` (2 preceding siblings ...)
2025-04-29 12:51 ` [PATCH v6 3/7] clocksource: " Fabrice Gasnier
@ 2025-04-29 12:51 ` Fabrice Gasnier
2025-04-29 12:51 ` [PATCH v6 5/7] arm64: defconfig: enable STM32 LP timer clockevent driver Fabrice Gasnier
` (6 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Fabrice Gasnier @ 2025-04-29 12:51 UTC (permalink / raw)
To: daniel.lezcano, lee, alexandre.torgue, tglx
Cc: ukleinek, krzk+dt, conor+dt, jic23, robh, catalin.marinas, will,
devicetree, wbg, linux-stm32, linux-arm-kernel, linux-kernel,
linux-iio, linux-pwm, olivier.moysan, fabrice.gasnier
Add support for STM32MP25 SoC. A new compatible has been added to the
dt-bindings. It represents handle new features, registers and bits
diversity.
It isn't used currently in the driver, as matching is done by retrieving
MFD parent data.
New dedicated capture/compare channels has been added: e.g. a new compare
register for channel 2. Some controls (polarity / cc channel enable) are
handled in CCMR register on this new variant (instead of wavepol bit).
So, Low-power timer can now have up to two PWM outputs. Use device data
from the MFD parent to configure the number of PWM channels e.g. 'npwm'.
Update current get_state() and apply() ops to support either:
- one PWM channel (as on older revision, or LPTIM5 on STM32MP25)
- two PWM channels (e.g. LPTIM1/2/3/4 on STM32MP25 that has the full
feature set)
Introduce new routines to manage common prescaler, reload register and
global enable bit.
Acked-by: Uwe Kleine-König <ukleinek@kernel.org>
Signed-off-by: Fabrice Gasnier <fabrice.gasnier@foss.st.com>
---
Changes in V5:
- Add Uwe's Acked-by
Changes in V2:
- rely on fallback compatible as no specific .data is associated to the
driver. Matching is achieved by using MFD parent data.
- renamed registers/bits defintions
---
drivers/pwm/pwm-stm32-lp.c | 219 ++++++++++++++++++++++++++++++++-----
1 file changed, 193 insertions(+), 26 deletions(-)
diff --git a/drivers/pwm/pwm-stm32-lp.c b/drivers/pwm/pwm-stm32-lp.c
index 5832dce8ed9d..4789eafb8bac 100644
--- a/drivers/pwm/pwm-stm32-lp.c
+++ b/drivers/pwm/pwm-stm32-lp.c
@@ -20,6 +20,7 @@
struct stm32_pwm_lp {
struct clk *clk;
struct regmap *regmap;
+ unsigned int num_cc_chans;
};
static inline struct stm32_pwm_lp *to_stm32_pwm_lp(struct pwm_chip *chip)
@@ -30,13 +31,101 @@ static inline struct stm32_pwm_lp *to_stm32_pwm_lp(struct pwm_chip *chip)
/* STM32 Low-Power Timer is preceded by a configurable power-of-2 prescaler */
#define STM32_LPTIM_MAX_PRESCALER 128
+static int stm32_pwm_lp_update_allowed(struct stm32_pwm_lp *priv, int channel)
+{
+ int ret;
+ u32 ccmr1;
+ unsigned long ccmr;
+
+ /* Only one PWM on this LPTIMER: enable, prescaler and reload value can be changed */
+ if (!priv->num_cc_chans)
+ return true;
+
+ ret = regmap_read(priv->regmap, STM32_LPTIM_CCMR1, &ccmr1);
+ if (ret)
+ return ret;
+ ccmr = ccmr1 & (STM32_LPTIM_CC1E | STM32_LPTIM_CC2E);
+
+ /* More than one channel enabled: enable, prescaler or ARR value can't be changed */
+ if (bitmap_weight(&ccmr, sizeof(u32) * BITS_PER_BYTE) > 1)
+ return false;
+
+ /*
+ * Only one channel is enabled (or none): check status on the other channel, to
+ * report if enable, prescaler or ARR value can be changed.
+ */
+ if (channel)
+ return !(ccmr1 & STM32_LPTIM_CC1E);
+ else
+ return !(ccmr1 & STM32_LPTIM_CC2E);
+}
+
+static int stm32_pwm_lp_compare_channel_apply(struct stm32_pwm_lp *priv, int channel,
+ bool enable, enum pwm_polarity polarity)
+{
+ u32 ccmr1, val, mask;
+ bool reenable;
+ int ret;
+
+ /* No dedicated CC channel: nothing to do */
+ if (!priv->num_cc_chans)
+ return 0;
+
+ ret = regmap_read(priv->regmap, STM32_LPTIM_CCMR1, &ccmr1);
+ if (ret)
+ return ret;
+
+ if (channel) {
+ /* Must disable CC channel (CCxE) to modify polarity (CCxP), then re-enable */
+ reenable = (enable && FIELD_GET(STM32_LPTIM_CC2E, ccmr1)) &&
+ (polarity != FIELD_GET(STM32_LPTIM_CC2P, ccmr1));
+
+ mask = STM32_LPTIM_CC2SEL | STM32_LPTIM_CC2E | STM32_LPTIM_CC2P;
+ val = FIELD_PREP(STM32_LPTIM_CC2P, polarity);
+ val |= FIELD_PREP(STM32_LPTIM_CC2E, enable);
+ } else {
+ reenable = (enable && FIELD_GET(STM32_LPTIM_CC1E, ccmr1)) &&
+ (polarity != FIELD_GET(STM32_LPTIM_CC1P, ccmr1));
+
+ mask = STM32_LPTIM_CC1SEL | STM32_LPTIM_CC1E | STM32_LPTIM_CC1P;
+ val = FIELD_PREP(STM32_LPTIM_CC1P, polarity);
+ val |= FIELD_PREP(STM32_LPTIM_CC1E, enable);
+ }
+
+ if (reenable) {
+ u32 cfgr, presc;
+ unsigned long rate;
+ unsigned int delay_us;
+
+ ret = regmap_update_bits(priv->regmap, STM32_LPTIM_CCMR1,
+ channel ? STM32_LPTIM_CC2E : STM32_LPTIM_CC1E, 0);
+ if (ret)
+ return ret;
+ /*
+ * After a write to the LPTIM_CCMRx register, a new write operation can only be
+ * performed after a delay of at least (PRESC × 3) clock cycles
+ */
+ ret = regmap_read(priv->regmap, STM32_LPTIM_CFGR, &cfgr);
+ if (ret)
+ return ret;
+ presc = FIELD_GET(STM32_LPTIM_PRESC, cfgr);
+ rate = clk_get_rate(priv->clk) >> presc;
+ if (!rate)
+ return -EINVAL;
+ delay_us = 3 * DIV_ROUND_UP(USEC_PER_SEC, rate);
+ usleep_range(delay_us, delay_us * 2);
+ }
+
+ return regmap_update_bits(priv->regmap, STM32_LPTIM_CCMR1, mask, val);
+}
+
static int stm32_pwm_lp_apply(struct pwm_chip *chip, struct pwm_device *pwm,
const struct pwm_state *state)
{
struct stm32_pwm_lp *priv = to_stm32_pwm_lp(chip);
unsigned long long prd, div, dty;
struct pwm_state cstate;
- u32 val, mask, cfgr, presc = 0;
+ u32 arr, val, mask, cfgr, presc = 0;
bool reenable;
int ret;
@@ -45,10 +134,28 @@ static int stm32_pwm_lp_apply(struct pwm_chip *chip, struct pwm_device *pwm,
if (!state->enabled) {
if (cstate.enabled) {
- /* Disable LP timer */
- ret = regmap_write(priv->regmap, STM32_LPTIM_CR, 0);
+ /* Disable CC channel if any */
+ ret = stm32_pwm_lp_compare_channel_apply(priv, pwm->hwpwm, false,
+ state->polarity);
if (ret)
return ret;
+ ret = regmap_write(priv->regmap, pwm->hwpwm ?
+ STM32_LPTIM_CCR2 : STM32_LPTIM_CMP, 0);
+ if (ret)
+ return ret;
+
+ /* Check if the timer can be disabled */
+ ret = stm32_pwm_lp_update_allowed(priv, pwm->hwpwm);
+ if (ret < 0)
+ return ret;
+
+ if (ret) {
+ /* Disable LP timer */
+ ret = regmap_write(priv->regmap, STM32_LPTIM_CR, 0);
+ if (ret)
+ return ret;
+ }
+
/* disable clock to PWM counter */
clk_disable(priv->clk);
}
@@ -79,6 +186,23 @@ static int stm32_pwm_lp_apply(struct pwm_chip *chip, struct pwm_device *pwm,
dty = prd * state->duty_cycle;
do_div(dty, state->period);
+ ret = regmap_read(priv->regmap, STM32_LPTIM_CFGR, &cfgr);
+ if (ret)
+ return ret;
+
+ /*
+ * When there are several channels, they share the same prescaler and reload value.
+ * Check if this can be changed, or the values are the same for all channels.
+ */
+ if (!stm32_pwm_lp_update_allowed(priv, pwm->hwpwm)) {
+ ret = regmap_read(priv->regmap, STM32_LPTIM_ARR, &arr);
+ if (ret)
+ return ret;
+
+ if ((FIELD_GET(STM32_LPTIM_PRESC, cfgr) != presc) || (arr != prd - 1))
+ return -EBUSY;
+ }
+
if (!cstate.enabled) {
/* enable clock to drive PWM counter */
ret = clk_enable(priv->clk);
@@ -86,15 +210,20 @@ static int stm32_pwm_lp_apply(struct pwm_chip *chip, struct pwm_device *pwm,
return ret;
}
- ret = regmap_read(priv->regmap, STM32_LPTIM_CFGR, &cfgr);
- if (ret)
- goto err;
-
if ((FIELD_GET(STM32_LPTIM_PRESC, cfgr) != presc) ||
- (FIELD_GET(STM32_LPTIM_WAVPOL, cfgr) != state->polarity)) {
+ ((FIELD_GET(STM32_LPTIM_WAVPOL, cfgr) != state->polarity) && !priv->num_cc_chans)) {
val = FIELD_PREP(STM32_LPTIM_PRESC, presc);
- val |= FIELD_PREP(STM32_LPTIM_WAVPOL, state->polarity);
- mask = STM32_LPTIM_PRESC | STM32_LPTIM_WAVPOL;
+ mask = STM32_LPTIM_PRESC;
+
+ if (!priv->num_cc_chans) {
+ /*
+ * WAVPOL bit is only available when no capature compare channel is used,
+ * e.g. on LPTIMER instances that have only one output channel. CCMR1 is
+ * used otherwise.
+ */
+ val |= FIELD_PREP(STM32_LPTIM_WAVPOL, state->polarity);
+ mask |= STM32_LPTIM_WAVPOL;
+ }
/* Must disable LP timer to modify CFGR */
reenable = true;
@@ -120,20 +249,27 @@ static int stm32_pwm_lp_apply(struct pwm_chip *chip, struct pwm_device *pwm,
if (ret)
goto err;
- ret = regmap_write(priv->regmap, STM32_LPTIM_CMP, prd - (1 + dty));
+ /* Write CMP/CCRx register and ensure it's been properly written */
+ ret = regmap_write(priv->regmap, pwm->hwpwm ? STM32_LPTIM_CCR2 : STM32_LPTIM_CMP,
+ prd - (1 + dty));
if (ret)
goto err;
- /* ensure CMP & ARR registers are properly written */
- ret = regmap_read_poll_timeout(priv->regmap, STM32_LPTIM_ISR, val,
+ /* ensure ARR and CMP/CCRx registers are properly written */
+ ret = regmap_read_poll_timeout(priv->regmap, STM32_LPTIM_ISR, val, pwm->hwpwm ?
+ (val & STM32_LPTIM_CMP2_ARROK) == STM32_LPTIM_CMP2_ARROK :
(val & STM32_LPTIM_CMPOK_ARROK) == STM32_LPTIM_CMPOK_ARROK,
100, 1000);
if (ret) {
dev_err(pwmchip_parent(chip), "ARR/CMP registers write issue\n");
goto err;
}
- ret = regmap_write(priv->regmap, STM32_LPTIM_ICR,
- STM32_LPTIM_CMPOKCF_ARROKCF);
+ ret = regmap_write(priv->regmap, STM32_LPTIM_ICR, pwm->hwpwm ?
+ STM32_LPTIM_CMP2OKCF_ARROKCF : STM32_LPTIM_CMPOKCF_ARROKCF);
+ if (ret)
+ goto err;
+
+ ret = stm32_pwm_lp_compare_channel_apply(priv, pwm->hwpwm, true, state->polarity);
if (ret)
goto err;
@@ -161,11 +297,22 @@ static int stm32_pwm_lp_get_state(struct pwm_chip *chip,
{
struct stm32_pwm_lp *priv = to_stm32_pwm_lp(chip);
unsigned long rate = clk_get_rate(priv->clk);
- u32 val, presc, prd;
+ u32 val, presc, prd, ccmr1;
+ bool enabled;
u64 tmp;
regmap_read(priv->regmap, STM32_LPTIM_CR, &val);
- state->enabled = !!FIELD_GET(STM32_LPTIM_ENABLE, val);
+ enabled = !!FIELD_GET(STM32_LPTIM_ENABLE, val);
+ if (priv->num_cc_chans) {
+ /* There's a CC chan, need to also check if it's enabled */
+ regmap_read(priv->regmap, STM32_LPTIM_CCMR1, &ccmr1);
+ if (pwm->hwpwm)
+ enabled &= !!FIELD_GET(STM32_LPTIM_CC2E, ccmr1);
+ else
+ enabled &= !!FIELD_GET(STM32_LPTIM_CC1E, ccmr1);
+ }
+ state->enabled = enabled;
+
/* Keep PWM counter clock refcount in sync with PWM initial state */
if (state->enabled) {
int ret = clk_enable(priv->clk);
@@ -176,14 +323,21 @@ static int stm32_pwm_lp_get_state(struct pwm_chip *chip,
regmap_read(priv->regmap, STM32_LPTIM_CFGR, &val);
presc = FIELD_GET(STM32_LPTIM_PRESC, val);
- state->polarity = FIELD_GET(STM32_LPTIM_WAVPOL, val);
+ if (priv->num_cc_chans) {
+ if (pwm->hwpwm)
+ state->polarity = FIELD_GET(STM32_LPTIM_CC2P, ccmr1);
+ else
+ state->polarity = FIELD_GET(STM32_LPTIM_CC1P, ccmr1);
+ } else {
+ state->polarity = FIELD_GET(STM32_LPTIM_WAVPOL, val);
+ }
regmap_read(priv->regmap, STM32_LPTIM_ARR, &prd);
tmp = prd + 1;
tmp = (tmp << presc) * NSEC_PER_SEC;
state->period = DIV_ROUND_CLOSEST_ULL(tmp, rate);
- regmap_read(priv->regmap, STM32_LPTIM_CMP, &val);
+ regmap_read(priv->regmap, pwm->hwpwm ? STM32_LPTIM_CCR2 : STM32_LPTIM_CMP, &val);
tmp = prd - val;
tmp = (tmp << presc) * NSEC_PER_SEC;
state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, rate);
@@ -201,15 +355,25 @@ static int stm32_pwm_lp_probe(struct platform_device *pdev)
struct stm32_lptimer *ddata = dev_get_drvdata(pdev->dev.parent);
struct stm32_pwm_lp *priv;
struct pwm_chip *chip;
+ unsigned int npwm;
int ret;
- chip = devm_pwmchip_alloc(&pdev->dev, 1, sizeof(*priv));
+ if (!ddata->num_cc_chans) {
+ /* No dedicated CC channel, so there's only one PWM channel */
+ npwm = 1;
+ } else {
+ /* There are dedicated CC channels, each with one PWM output */
+ npwm = ddata->num_cc_chans;
+ }
+
+ chip = devm_pwmchip_alloc(&pdev->dev, npwm, sizeof(*priv));
if (IS_ERR(chip))
return PTR_ERR(chip);
priv = to_stm32_pwm_lp(chip);
priv->regmap = ddata->regmap;
priv->clk = ddata->clk;
+ priv->num_cc_chans = ddata->num_cc_chans;
chip->ops = &stm32_pwm_lp_ops;
ret = devm_pwmchip_add(&pdev->dev, chip);
@@ -225,12 +389,15 @@ static int stm32_pwm_lp_suspend(struct device *dev)
{
struct pwm_chip *chip = dev_get_drvdata(dev);
struct pwm_state state;
-
- pwm_get_state(&chip->pwms[0], &state);
- if (state.enabled) {
- dev_err(dev, "The consumer didn't stop us (%s)\n",
- chip->pwms[0].label);
- return -EBUSY;
+ unsigned int i;
+
+ for (i = 0; i < chip->npwm; i++) {
+ pwm_get_state(&chip->pwms[i], &state);
+ if (state.enabled) {
+ dev_err(dev, "The consumer didn't stop us (%s)\n",
+ chip->pwms[i].label);
+ return -EBUSY;
+ }
}
return pinctrl_pm_select_sleep_state(dev);
--
2.25.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v6 5/7] arm64: defconfig: enable STM32 LP timer clockevent driver
2025-04-29 12:51 [PATCH v6 0/7] Add STM32MP25 LPTIM support: MFD, PWM, IIO, counter, clocksource Fabrice Gasnier
` (3 preceding siblings ...)
2025-04-29 12:51 ` [PATCH v6 4/7] pwm: stm32-lp: " Fabrice Gasnier
@ 2025-04-29 12:51 ` Fabrice Gasnier
2025-04-29 12:51 ` [PATCH v6 6/7] arm64: dts: st: add low-power timer nodes on stm32mp251 Fabrice Gasnier
` (5 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Fabrice Gasnier @ 2025-04-29 12:51 UTC (permalink / raw)
To: daniel.lezcano, lee, alexandre.torgue, tglx
Cc: ukleinek, krzk+dt, conor+dt, jic23, robh, catalin.marinas, will,
devicetree, wbg, linux-stm32, linux-arm-kernel, linux-kernel,
linux-iio, linux-pwm, olivier.moysan, fabrice.gasnier
Enable the STM32 LP timer MFD core and clockevent drivers used on
STM32MP257F-EV1 board, for PSCI OSI.
Signed-off-by: Fabrice Gasnier <fabrice.gasnier@foss.st.com>
---
Changes in v2:
- dropped unused IIO trigger, PWM and counter driver unused on upstream
board currently, as advised by Krzysztof
---
arch/arm64/configs/defconfig | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 5bb8f09422a2..d106cdac05fa 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -777,6 +777,7 @@ CONFIG_MFD_TI_LP873X=m
CONFIG_MFD_TPS65219=y
CONFIG_MFD_TPS6594_I2C=m
CONFIG_MFD_ROHM_BD718XX=y
+CONFIG_MFD_STM32_LPTIMER=m
CONFIG_MFD_WCD934X=m
CONFIG_MFD_KHADAS_MCU=m
CONFIG_REGULATOR_FIXED_VOLTAGE=y
@@ -1414,6 +1415,7 @@ CONFIG_CLK_RENESAS_VBATTB=m
CONFIG_HWSPINLOCK=y
CONFIG_HWSPINLOCK_QCOM=y
CONFIG_TEGRA186_TIMER=y
+CONFIG_CLKSRC_STM32_LP=y
CONFIG_RENESAS_OSTM=y
CONFIG_ARM_MHU=y
CONFIG_IMX_MBOX=y
--
2.25.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v6 6/7] arm64: dts: st: add low-power timer nodes on stm32mp251
2025-04-29 12:51 [PATCH v6 0/7] Add STM32MP25 LPTIM support: MFD, PWM, IIO, counter, clocksource Fabrice Gasnier
` (4 preceding siblings ...)
2025-04-29 12:51 ` [PATCH v6 5/7] arm64: defconfig: enable STM32 LP timer clockevent driver Fabrice Gasnier
@ 2025-04-29 12:51 ` Fabrice Gasnier
2025-04-29 12:51 ` [PATCH v6 7/7] arm64: dts: st: use lptimer3 as tick broadcast source on stm32mp257f-ev1 Fabrice Gasnier
` (4 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Fabrice Gasnier @ 2025-04-29 12:51 UTC (permalink / raw)
To: daniel.lezcano, lee, alexandre.torgue, tglx
Cc: ukleinek, krzk+dt, conor+dt, jic23, robh, catalin.marinas, will,
devicetree, wbg, linux-stm32, linux-arm-kernel, linux-kernel,
linux-iio, linux-pwm, olivier.moysan, fabrice.gasnier
Add low-power timer (LPTimer) support on STM32MP25 SoC.
The full feature set is implemented in LPTIM1/2/3/4. LPTIM5 supports a
smaller set of features (no capture/compare) channel. Still, LPTIM5 can
be used as single PWM, counter, trigger or timer.
Signed-off-by: Fabrice Gasnier <fabrice.gasnier@foss.st.com>
---
Changes in V2:
- Adopt two compatibles: newly introduced "st,stm32mp25-..." compatible,
and fallback "st,stm32-...".
---
arch/arm64/boot/dts/st/stm32mp251.dtsi | 177 +++++++++++++++++++++++++
1 file changed, 177 insertions(+)
diff --git a/arch/arm64/boot/dts/st/stm32mp251.dtsi b/arch/arm64/boot/dts/st/stm32mp251.dtsi
index f3c6cdfd7008..505176276e72 100644
--- a/arch/arm64/boot/dts/st/stm32mp251.dtsi
+++ b/arch/arm64/boot/dts/st/stm32mp251.dtsi
@@ -238,6 +238,78 @@ rifsc: bus@42080000 {
#access-controller-cells = <1>;
ranges;
+ lptimer1: timer@40090000 {
+ compatible = "st,stm32mp25-lptimer", "st,stm32-lptimer";
+ reg = <0x40090000 0x400>;
+ interrupts-extended = <&exti1 47 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rcc CK_KER_LPTIM1>;
+ clock-names = "mux";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ access-controllers = <&rifsc 17>;
+ power-domains = <&RET_PD>;
+ wakeup-source;
+ status = "disabled";
+
+ counter {
+ compatible = "st,stm32mp25-lptimer-counter", "st,stm32-lptimer-counter";
+ status = "disabled";
+ };
+
+ pwm {
+ compatible = "st,stm32mp25-pwm-lp", "st,stm32-pwm-lp";
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ timer {
+ compatible = "st,stm32mp25-lptimer-timer", "st,stm32-lptimer-timer";
+ status = "disabled";
+ };
+
+ trigger@0 {
+ compatible = "st,stm32mp25-lptimer-trigger", "st,stm32-lptimer-trigger";
+ reg = <0>;
+ status = "disabled";
+ };
+ };
+
+ lptimer2: timer@400a0000 {
+ compatible = "st,stm32mp25-lptimer", "st,stm32-lptimer";
+ reg = <0x400a0000 0x400>;
+ interrupts-extended = <&exti1 48 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rcc CK_KER_LPTIM2>;
+ clock-names = "mux";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ access-controllers = <&rifsc 18>;
+ power-domains = <&RET_PD>;
+ wakeup-source;
+ status = "disabled";
+
+ counter {
+ compatible = "st,stm32mp25-lptimer-counter", "st,stm32-lptimer-counter";
+ status = "disabled";
+ };
+
+ pwm {
+ compatible = "st,stm32mp25-pwm-lp", "st,stm32-pwm-lp";
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ timer {
+ compatible = "st,stm32mp25-lptimer-timer", "st,stm32-lptimer-timer";
+ status = "disabled";
+ };
+
+ trigger@1 {
+ compatible = "st,stm32mp25-lptimer-trigger", "st,stm32-lptimer-trigger";
+ reg = <1>;
+ status = "disabled";
+ };
+ };
+
i2s2: audio-controller@400b0000 {
compatible = "st,stm32mp25-i2s";
reg = <0x400b0000 0x400>;
@@ -799,6 +871,111 @@ i2c8: i2c@46040000 {
status = "disabled";
};
+ lptimer3: timer@46050000 {
+ compatible = "st,stm32mp25-lptimer", "st,stm32-lptimer";
+ reg = <0x46050000 0x400>;
+ interrupts-extended = <&exti2 29 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rcc CK_KER_LPTIM3>;
+ clock-names = "mux";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ access-controllers = <&rifsc 19>;
+ wakeup-source;
+ status = "disabled";
+
+ counter {
+ compatible = "st,stm32mp25-lptimer-counter", "st,stm32-lptimer-counter";
+ status = "disabled";
+ };
+
+ pwm {
+ compatible = "st,stm32mp25-pwm-lp", "st,stm32-pwm-lp";
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ timer {
+ compatible = "st,stm32mp25-lptimer-timer", "st,stm32-lptimer-timer";
+ status = "disabled";
+ };
+
+ trigger@2 {
+ compatible = "st,stm32mp25-lptimer-trigger", "st,stm32-lptimer-trigger";
+ reg = <2>;
+ status = "disabled";
+ };
+ };
+
+ lptimer4: timer@46060000 {
+ compatible = "st,stm32mp25-lptimer", "st,stm32-lptimer";
+ reg = <0x46060000 0x400>;
+ interrupts-extended = <&exti2 30 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rcc CK_KER_LPTIM4>;
+ clock-names = "mux";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ access-controllers = <&rifsc 20>;
+ wakeup-source;
+ status = "disabled";
+
+ counter {
+ compatible = "st,stm32mp25-lptimer-counter", "st,stm32-lptimer-counter";
+ status = "disabled";
+ };
+
+ pwm {
+ compatible = "st,stm32mp25-pwm-lp", "st,stm32-pwm-lp";
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ timer {
+ compatible = "st,stm32mp25-lptimer-timer", "st,stm32-lptimer-timer";
+ status = "disabled";
+ };
+
+ trigger@3 {
+ compatible = "st,stm32mp25-lptimer-trigger", "st,stm32-lptimer-trigger";
+ reg = <3>;
+ status = "disabled";
+ };
+ };
+
+ lptimer5: timer@46070000 {
+ compatible = "st,stm32mp25-lptimer", "st,stm32-lptimer";
+ reg = <0x46070000 0x400>;
+ interrupts-extended = <&exti2 31 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rcc CK_KER_LPTIM5>;
+ clock-names = "mux";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ access-controllers = <&rifsc 21>;
+ wakeup-source;
+ status = "disabled";
+
+ counter {
+ compatible = "st,stm32mp25-lptimer-counter", "st,stm32-lptimer-counter";
+ status = "disabled";
+ };
+
+ pwm {
+ compatible = "st,stm32mp25-pwm-lp", "st,stm32-pwm-lp";
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ timer {
+ compatible = "st,stm32mp25-lptimer-timer", "st,stm32-lptimer-timer";
+ status = "disabled";
+ };
+
+ trigger@4 {
+ compatible = "st,stm32mp25-lptimer-trigger", "st,stm32-lptimer-trigger";
+ reg = <4>;
+ status = "disabled";
+ };
+ };
+
csi: csi@48020000 {
compatible = "st,stm32mp25-csi";
reg = <0x48020000 0x2000>;
--
2.25.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v6 7/7] arm64: dts: st: use lptimer3 as tick broadcast source on stm32mp257f-ev1
2025-04-29 12:51 [PATCH v6 0/7] Add STM32MP25 LPTIM support: MFD, PWM, IIO, counter, clocksource Fabrice Gasnier
` (5 preceding siblings ...)
2025-04-29 12:51 ` [PATCH v6 6/7] arm64: dts: st: add low-power timer nodes on stm32mp251 Fabrice Gasnier
@ 2025-04-29 12:51 ` Fabrice Gasnier
2025-05-01 13:14 ` [PATCH v6 0/7] Add STM32MP25 LPTIM support: MFD, PWM, IIO, counter, clocksource Lee Jones
` (3 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Fabrice Gasnier @ 2025-04-29 12:51 UTC (permalink / raw)
To: daniel.lezcano, lee, alexandre.torgue, tglx
Cc: ukleinek, krzk+dt, conor+dt, jic23, robh, catalin.marinas, will,
devicetree, wbg, linux-stm32, linux-arm-kernel, linux-kernel,
linux-iio, linux-pwm, olivier.moysan, fabrice.gasnier
During the low power modes the generic ARM timer is deactivated, so the
the tick broadcast is used, based on LPTIMER3 which is clocked by LSE on
STMicroelectronics boards.
Signed-off-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
Signed-off-by: Fabrice Gasnier <fabrice.gasnier@foss.st.com>
---
arch/arm64/boot/dts/st/stm32mp257f-ev1.dts | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts b/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
index 1b88485a62a1..242115863ab4 100644
--- a/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
+++ b/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
@@ -190,6 +190,14 @@ &i2c8 {
status = "disabled";
};
+/* use LPTIMER with tick broadcast for suspend mode */
+&lptimer3 {
+ status = "okay";
+ timer {
+ status = "okay";
+ };
+};
+
&rtc {
status = "okay";
};
--
2.25.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v6 0/7] Add STM32MP25 LPTIM support: MFD, PWM, IIO, counter, clocksource
2025-04-29 12:51 [PATCH v6 0/7] Add STM32MP25 LPTIM support: MFD, PWM, IIO, counter, clocksource Fabrice Gasnier
` (6 preceding siblings ...)
2025-04-29 12:51 ` [PATCH v6 7/7] arm64: dts: st: use lptimer3 as tick broadcast source on stm32mp257f-ev1 Fabrice Gasnier
@ 2025-05-01 13:14 ` Lee Jones
2025-05-05 12:17 ` Fabrice Gasnier
[not found] ` <174713127684.4157861.15977616973399970511.b4-ty@kernel.org>
` (2 subsequent siblings)
10 siblings, 1 reply; 14+ messages in thread
From: Lee Jones @ 2025-05-01 13:14 UTC (permalink / raw)
To: Fabrice Gasnier
Cc: daniel.lezcano, alexandre.torgue, tglx, ukleinek, krzk+dt,
conor+dt, jic23, robh, catalin.marinas, will, devicetree, wbg,
linux-stm32, linux-arm-kernel, linux-kernel, linux-iio, linux-pwm,
olivier.moysan
On Tue, 29 Apr 2025, Fabrice Gasnier wrote:
> This series adds support for STM32MP25 to MFD PWM, IIO, counter and
> clocksource low-power timer (LPTIM) drivers.
> This new variant is managed by using a new DT compatible string, hardware
> configuration and version registers.
> It comes with a slightly updated register set, some new features and new
> interconnect signals inside the SoC.
> Same feature list as on STM32MP1x is supported currently.
> The device tree files add all instances in stm32mp251 dtsi file.
>
> Changes in V6
> ---
> - Fixed kernel test robot warning
> https://lore.kernel.org/oe-kbuild-all/202504261456.aCATBoYN-lkp@intel.com/
>
> Changes in V5
> ---
> - Add a necessary delay in clocksource driver, when enabling the timer.
> - Add collected Acks
> - Dropped IIO trigger patch as applied by Jonathan [1] (no dependency)
> [1] https://lore.kernel.org/all/20250331110435.26157ebe@jic23-huawei/
>
> Changes in V4
> ---
> - Simplify IIO trigger driver as per Jonathan's comments.
> - Rework clocksource driver: encapsulate mp25 changes in separate function
> after Daniel's suggestion.
> - Add some definitions to MFD header.
>
> Changes in V3
> ---
> - Yaml indentation issue fixed, reported by Rob's bot
>
> Changes in V2
> ---
> - Review comments from Krzysztof
> - Adopt compatible fallback in dt-bindings and driver
> - drivers: drop "st,stm32mp25-..." compatibles when unused (e.g. no .data)
> - counter driver: no update (patch dropped)
> - defconfig: only enable the necessary config for upstream board
> - add lptimer DT node in stm32mp257f-ev1 board
> - Add missing management of IER access for stm32mp25
>
> Fabrice Gasnier (7):
> dt-bindings: mfd: stm32-lptimer: add support for stm32mp25
> mfd: stm32-lptimer: add support for stm32mp25
> clocksource: stm32-lptimer: add support for stm32mp25
> pwm: stm32-lp: add support for stm32mp25
> arm64: defconfig: enable STM32 LP timer clockevent driver
> arm64: dts: st: add low-power timer nodes on stm32mp251
> arm64: dts: st: use lptimer3 as tick broadcast source on
> stm32mp257f-ev1
>
> .../bindings/mfd/st,stm32-lptimer.yaml | 40 +++-
> arch/arm64/boot/dts/st/stm32mp251.dtsi | 177 ++++++++++++++
> arch/arm64/boot/dts/st/stm32mp257f-ev1.dts | 8 +
> arch/arm64/configs/defconfig | 2 +
> drivers/clocksource/timer-stm32-lp.c | 61 ++++-
> drivers/mfd/stm32-lptimer.c | 33 ++-
> drivers/pwm/pwm-stm32-lp.c | 219 +++++++++++++++---
> include/linux/mfd/stm32-lptimer.h | 37 ++-
> 8 files changed, 537 insertions(+), 40 deletions(-)
Is it just the Clocksource Ack that we're waiting on now?
--
Lee Jones [李琼斯]
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v6 0/7] Add STM32MP25 LPTIM support: MFD, PWM, IIO, counter, clocksource
2025-05-01 13:14 ` [PATCH v6 0/7] Add STM32MP25 LPTIM support: MFD, PWM, IIO, counter, clocksource Lee Jones
@ 2025-05-05 12:17 ` Fabrice Gasnier
0 siblings, 0 replies; 14+ messages in thread
From: Fabrice Gasnier @ 2025-05-05 12:17 UTC (permalink / raw)
To: Lee Jones
Cc: daniel.lezcano, alexandre.torgue, tglx, ukleinek, krzk+dt,
conor+dt, jic23, robh, catalin.marinas, will, devicetree, wbg,
linux-stm32, linux-arm-kernel, linux-kernel, linux-iio, linux-pwm,
olivier.moysan
On 5/1/25 15:14, Lee Jones wrote:
> On Tue, 29 Apr 2025, Fabrice Gasnier wrote:
>
>> This series adds support for STM32MP25 to MFD PWM, IIO, counter and
>> clocksource low-power timer (LPTIM) drivers.
>> This new variant is managed by using a new DT compatible string, hardware
>> configuration and version registers.
>> It comes with a slightly updated register set, some new features and new
>> interconnect signals inside the SoC.
>> Same feature list as on STM32MP1x is supported currently.
>> The device tree files add all instances in stm32mp251 dtsi file.
>>
>> Changes in V6
>> ---
>> - Fixed kernel test robot warning
>> https://lore.kernel.org/oe-kbuild-all/202504261456.aCATBoYN-lkp@intel.com/
>>
>> Changes in V5
>> ---
>> - Add a necessary delay in clocksource driver, when enabling the timer.
>> - Add collected Acks
>> - Dropped IIO trigger patch as applied by Jonathan [1] (no dependency)
>> [1] https://lore.kernel.org/all/20250331110435.26157ebe@jic23-huawei/
>>
>> Changes in V4
>> ---
>> - Simplify IIO trigger driver as per Jonathan's comments.
>> - Rework clocksource driver: encapsulate mp25 changes in separate function
>> after Daniel's suggestion.
>> - Add some definitions to MFD header.
>>
>> Changes in V3
>> ---
>> - Yaml indentation issue fixed, reported by Rob's bot
>>
>> Changes in V2
>> ---
>> - Review comments from Krzysztof
>> - Adopt compatible fallback in dt-bindings and driver
>> - drivers: drop "st,stm32mp25-..." compatibles when unused (e.g. no .data)
>> - counter driver: no update (patch dropped)
>> - defconfig: only enable the necessary config for upstream board
>> - add lptimer DT node in stm32mp257f-ev1 board
>> - Add missing management of IER access for stm32mp25
>>
>> Fabrice Gasnier (7):
>> dt-bindings: mfd: stm32-lptimer: add support for stm32mp25
>> mfd: stm32-lptimer: add support for stm32mp25
>> clocksource: stm32-lptimer: add support for stm32mp25
>> pwm: stm32-lp: add support for stm32mp25
>> arm64: defconfig: enable STM32 LP timer clockevent driver
>> arm64: dts: st: add low-power timer nodes on stm32mp251
>> arm64: dts: st: use lptimer3 as tick broadcast source on
>> stm32mp257f-ev1
>>
>> .../bindings/mfd/st,stm32-lptimer.yaml | 40 +++-
>> arch/arm64/boot/dts/st/stm32mp251.dtsi | 177 ++++++++++++++
>> arch/arm64/boot/dts/st/stm32mp257f-ev1.dts | 8 +
>> arch/arm64/configs/defconfig | 2 +
>> drivers/clocksource/timer-stm32-lp.c | 61 ++++-
>> drivers/mfd/stm32-lptimer.c | 33 ++-
>> drivers/pwm/pwm-stm32-lp.c | 219 +++++++++++++++---
>> include/linux/mfd/stm32-lptimer.h | 37 ++-
>> 8 files changed, 537 insertions(+), 40 deletions(-)
>
> Is it just the Clocksource Ack that we're waiting on now?
>
Hi Lee,
Yes,
Best Regards,
Fabrice
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v6 3/7] clocksource: stm32-lptimer: add support for stm32mp25
2025-04-29 12:51 ` [PATCH v6 3/7] clocksource: " Fabrice Gasnier
@ 2025-05-07 7:55 ` Daniel Lezcano
0 siblings, 0 replies; 14+ messages in thread
From: Daniel Lezcano @ 2025-05-07 7:55 UTC (permalink / raw)
To: Fabrice Gasnier
Cc: lee, alexandre.torgue, tglx, ukleinek, krzk+dt, conor+dt, jic23,
robh, catalin.marinas, will, devicetree, wbg, linux-stm32,
linux-arm-kernel, linux-kernel, linux-iio, linux-pwm,
olivier.moysan
On Tue, Apr 29, 2025 at 02:51:29PM +0200, Fabrice Gasnier wrote:
> On stm32mp25, DIER (former IER) must only be modified when the lptimer
> is enabled. On earlier SoCs, it must be only be modified when it is
> disabled. There's also a new DIEROK flag, to ensure register access
> has completed.
> Add a new "set_evt" routine to be used on stm32mp25, called depending
> on the version register, read by the MFD core (LPTIM_VERR).
>
> Signed-off-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
> Signed-off-by: Fabrice Gasnier <fabrice.gasnier@foss.st.com>
> ---
> Changes in V6:
> - Fixed warning reported by kernel test robot in
> https://lore.kernel.org/oe-kbuild-all/202504261456.aCATBoYN-lkp@intel.com/
> use FIELD_GET() macro
> Changes in V5:
> - Added a delay after timer enable, it needs two clock cycles.
> Changes in V4:
> - Daniel suggests to encapsulate IER write into a separate function
> that manages the enabling/disabling of the LP timer. In addition,
> DIEROK and ARROK flags checks have been added. So adopt a new routine
> to set the event into ARR register and enable the interrupt.
> Changes in V2:
> - rely on fallback compatible as no specific .data is associated to the
> driver. Use version data from MFD core.
> - Added interrupt enable register access update in (missed in V1)
> ---
Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org>
--
<http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs
Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: (subset) [PATCH v6 0/7] Add STM32MP25 LPTIM support: MFD, PWM, IIO, counter, clocksource
[not found] ` <174713127684.4157861.15977616973399970511.b4-ty@kernel.org>
@ 2025-05-13 10:17 ` Lee Jones
0 siblings, 0 replies; 14+ messages in thread
From: Lee Jones @ 2025-05-13 10:17 UTC (permalink / raw)
To: daniel.lezcano, alexandre.torgue, tglx, Fabrice Gasnier
Cc: ukleinek, krzk+dt, conor+dt, jic23, robh, catalin.marinas, will,
devicetree, wbg, linux-stm32, linux-arm-kernel, linux-kernel,
linux-iio, linux-pwm, olivier.moysan
On Tue, 13 May 2025, Lee Jones wrote:
> On Tue, 29 Apr 2025 14:51:26 +0200, Fabrice Gasnier wrote:
> > This series adds support for STM32MP25 to MFD PWM, IIO, counter and
> > clocksource low-power timer (LPTIM) drivers.
> > This new variant is managed by using a new DT compatible string, hardware
> > configuration and version registers.
> > It comes with a slightly updated register set, some new features and new
> > interconnect signals inside the SoC.
> > Same feature list as on STM32MP1x is supported currently.
> > The device tree files add all instances in stm32mp251 dtsi file.
> >
> > [...]
>
> Applied, thanks!
>
> [1/7] dt-bindings: mfd: stm32-lptimer: add support for stm32mp25
> commit: 3f9ce9d0760ad68a9c20167664d026d91da66879
> [2/7] mfd: stm32-lptimer: add support for stm32mp25
> commit: 4f8ceb0302b36c5f78bcc8d0e7cfa2372fba134c
> [3/7] clocksource: stm32-lptimer: add support for stm32mp25
> commit: 5414bc8c57c41038b1994cd21a2cc0b8415c1544
> [4/7] pwm: stm32-lp: add support for stm32mp25
> commit: 3f51b232c1da8e59eb562f1d81533334827a4799
In future, please match the subject format with that expected by the
subsystem. For this, `git log --oneline -- <subsystem>` is your friend.
I changed them all for you this time.
The above patches have been applied and submitted for build testing.
Once complete, I'll follow-up with an PR for the other maintainers to
pull from.
Note to self: ib-mfd-clocksource-pwm-6.16
--
Lee Jones [李琼斯]
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: (subset)[PATCH v6 0/7] Add STM32MP25 LPTIM support: MFD, PWM, IIO, counter, clocksource
2025-04-29 12:51 [PATCH v6 0/7] Add STM32MP25 LPTIM support: MFD, PWM, IIO, counter, clocksource Fabrice Gasnier
` (8 preceding siblings ...)
[not found] ` <174713127684.4157861.15977616973399970511.b4-ty@kernel.org>
@ 2025-05-14 8:24 ` Alexandre TORGUE
2025-05-19 7:35 ` [GIT PULL] Immutable branch between MFD, Clocksource and PWM due for the v6.16 merge window Lee Jones
10 siblings, 0 replies; 14+ messages in thread
From: Alexandre TORGUE @ 2025-05-14 8:24 UTC (permalink / raw)
To: Fabrice Gasnier, daniel.lezcano, lee, tglx
Cc: ukleinek, krzk+dt, conor+dt, jic23, robh, catalin.marinas, will,
devicetree, wbg, linux-stm32, linux-arm-kernel, linux-kernel,
linux-iio, linux-pwm, olivier.moysan
Hi Fabrice
On 4/29/25 14:51, Fabrice Gasnier wrote:
> This series adds support for STM32MP25 to MFD PWM, IIO, counter and
> clocksource low-power timer (LPTIM) drivers.
> This new variant is managed by using a new DT compatible string, hardware
> configuration and version registers.
> It comes with a slightly updated register set, some new features and new
> interconnect signals inside the SoC.
> Same feature list as on STM32MP1x is supported currently.
> The device tree files add all instances in stm32mp251 dtsi file.
>
Following patches are applied on stm32-next:
[PATCH v6 5/7] arm64: defconfig: enable STM32 LP timer clockevent driver
[PATCH v6 6/7] arm64: dts: st: add low-power timer nodes on stm32mp251
[PATCH v6 7/7] arm64: dts: st: use lptimer3 as tick broadcast source on
stm32mp257f-ev1
Thanks
Alex
^ permalink raw reply [flat|nested] 14+ messages in thread
* [GIT PULL] Immutable branch between MFD, Clocksource and PWM due for the v6.16 merge window
2025-04-29 12:51 [PATCH v6 0/7] Add STM32MP25 LPTIM support: MFD, PWM, IIO, counter, clocksource Fabrice Gasnier
` (9 preceding siblings ...)
2025-05-14 8:24 ` (subset)[PATCH " Alexandre TORGUE
@ 2025-05-19 7:35 ` Lee Jones
10 siblings, 0 replies; 14+ messages in thread
From: Lee Jones @ 2025-05-19 7:35 UTC (permalink / raw)
To: Fabrice Gasnier
Cc: daniel.lezcano, alexandre.torgue, tglx, ukleinek, krzk+dt,
conor+dt, jic23, robh, catalin.marinas, will, devicetree, wbg,
linux-stm32, linux-arm-kernel, linux-kernel, linux-iio, linux-pwm,
olivier.moysan
Enjoy!
The following changes since commit 0af2f6be1b4281385b618cb86ad946eded089ac8:
Linux 6.15-rc1 (2025-04-06 13:11:33 -0700)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git ib-mfd-clocksource-pwm-v6.16
for you to fetch changes up to 3f51b232c1da8e59eb562f1d81533334827a4799:
pwm: stm32-lp: Add support for stm32mp25 (2025-05-13 11:13:56 +0100)
----------------------------------------------------------------
Immutable branch between MFD, Clocksource and PWM due for the v6.16 merge window
----------------------------------------------------------------
Fabrice Gasnier (4):
dt-bindings: mfd: stm32-lptimer: Add support for stm32mp25
mfd: stm32-lptimer: Add support for stm32mp25
clocksource/drivers/stm32-lptimer: Add support for stm32mp25
pwm: stm32-lp: Add support for stm32mp25
.../devicetree/bindings/mfd/st,stm32-lptimer.yaml | 40 +++-
drivers/clocksource/timer-stm32-lp.c | 61 +++++-
drivers/mfd/stm32-lptimer.c | 33 +++-
drivers/pwm/pwm-stm32-lp.c | 219 ++++++++++++++++++---
include/linux/mfd/stm32-lptimer.h | 37 +++-
5 files changed, 350 insertions(+), 40 deletions(-)
--
Lee Jones [李琼斯]
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2025-05-19 7:38 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-04-29 12:51 [PATCH v6 0/7] Add STM32MP25 LPTIM support: MFD, PWM, IIO, counter, clocksource Fabrice Gasnier
2025-04-29 12:51 ` [PATCH v6 1/7] dt-bindings: mfd: stm32-lptimer: add support for stm32mp25 Fabrice Gasnier
2025-04-29 12:51 ` [PATCH v6 2/7] " Fabrice Gasnier
2025-04-29 12:51 ` [PATCH v6 3/7] clocksource: " Fabrice Gasnier
2025-05-07 7:55 ` Daniel Lezcano
2025-04-29 12:51 ` [PATCH v6 4/7] pwm: stm32-lp: " Fabrice Gasnier
2025-04-29 12:51 ` [PATCH v6 5/7] arm64: defconfig: enable STM32 LP timer clockevent driver Fabrice Gasnier
2025-04-29 12:51 ` [PATCH v6 6/7] arm64: dts: st: add low-power timer nodes on stm32mp251 Fabrice Gasnier
2025-04-29 12:51 ` [PATCH v6 7/7] arm64: dts: st: use lptimer3 as tick broadcast source on stm32mp257f-ev1 Fabrice Gasnier
2025-05-01 13:14 ` [PATCH v6 0/7] Add STM32MP25 LPTIM support: MFD, PWM, IIO, counter, clocksource Lee Jones
2025-05-05 12:17 ` Fabrice Gasnier
[not found] ` <174713127684.4157861.15977616973399970511.b4-ty@kernel.org>
2025-05-13 10:17 ` (subset) " Lee Jones
2025-05-14 8:24 ` (subset)[PATCH " Alexandre TORGUE
2025-05-19 7:35 ` [GIT PULL] Immutable branch between MFD, Clocksource and PWM due for the v6.16 merge window Lee Jones
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).