From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-106119.protonmail.ch (mail-106119.protonmail.ch [79.135.106.119]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8819830CDB0; Sat, 14 Feb 2026 18:10:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=79.135.106.119 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771092647; cv=none; b=b0qkBP/RPlIfsDssijpiaY1CXnDIOZkGaG0hL0PfjUr9qJV2koYF0dzzuM1JlzviMAwO69EDmuOlPFxhEyxuI6qixRtYY/24pkQlDDs84lWnsLPWg1eKS080HeNx9y0A3wuwSvLdeHewDY3wwFOftHYlZjibapl2wLznP22dyks= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771092647; c=relaxed/simple; bh=dDnUSCEp99oaNFkSEApP6LO+YLiDVKMiK7JlCWM6xYk=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=RrzTBjngMjmEj5dxs5YD/+8jiaJUHeRKd3M6RXJu9eQXVu2HUqVfW1ZVKjIKkJRbdSjYhmUi3XZXhDj2/Wc38QlcIuSoOMRBZrud2bcYPZLtzfm1z/mdzooJZMcwLIPPZR3Y1Hh0+38SrxBVvHR2j4uXkaAbskY7wl/XBDAXyVI= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=protonmail.com; spf=pass smtp.mailfrom=protonmail.com; dkim=pass (2048-bit key) header.d=protonmail.com header.i=@protonmail.com header.b=sFXrVGMS; arc=none smtp.client-ip=79.135.106.119 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=protonmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=protonmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=protonmail.com header.i=@protonmail.com header.b="sFXrVGMS" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=protonmail.com; s=protonmail3; t=1771092631; x=1771351831; bh=pG4KOGJ75N5YkKd/3GD69J7uY+UkiejpCarTJWjDjs8=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID: Message-ID:BIMI-Selector; b=sFXrVGMS6QPQVOJNQimWlLVfz3MXDxgJNMap6EpjuT3RYIrTeXaOr4fhBcogJ+Cd6 ScYURDtx1K0VIvH+yMc4RQd8883yQPcZ0xBq7ZO3Nh0wrEUJnDOONCOI2ZfpC7vHMQ spn8Y+DLjP3+hXDoZzOrvw4yKsQBqwCmTXdyVSfjb6MhZ6ebOtTcc8amn1lU0UCp0L 6DxwFMYnKCxxXSPcZpuNoy3LzMsE8rJhNK7PYbl38dfJpnlz6Xd9TsXVb6S6DRH8k8 g/LfD5D6pjbZDPaLTxBSEKqd7neYRkQ4oYOeEoZMhgVZ9vWOSSH21Nh4KI4J2oAdZF JAStsan9emBMw== Date: Sat, 14 Feb 2026 18:10:25 +0000 To: Michael Turquette , Stephen Boyd , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michal Simek From: Harry Austen Cc: Shubhrajyoti Datta , linux-clk@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Harry Austen Subject: [PATCH v4 2/2] clk: clocking-wizard: add user clock monitor support Message-ID: <20260214180933.42143-3-hpausten@protonmail.com> In-Reply-To: <20260214180933.42143-1-hpausten@protonmail.com> References: <20260214180933.42143-1-hpausten@protonmail.com> Feedback-ID: 53116287:user:proton X-Pm-Message-ID: 2de2d7324fad0080ee117d3c2685689e6a3fc307 Precedence: bulk X-Mailing-List: linux-clk@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Xilinx clocking wizard IP core supports monitoring of up to four optional user clock inputs, with a corresponding interrupt for notification in change of clock state (stop, underrun, overrun or glitch). Give userspace access to this monitor logic through use of the devcoredump framework. Use presence of the user monitor interrupt description in devicetree to indicate whether or not this functionality should be enabled. Also, this functionality is only supported from v6.0 onwards, so add indication of support to the device match data, in order to be tied to the utilised compatible string. All 16 user clock monitor trigger sources are enabled in the IER. When triggered, the values of the first 5 registers are recorded through devcoredump. Signed-off-by: Harry Austen --- v3 -> v4: Rework from auxiliary bus and UIO to devcoredump v2 -> v3: No change v1 -> v2: - Remove direct UIO dependency by utilising auxiliary device - Move some logic from probe into clk_wzrd_setup_monitor for tidiness drivers/clk/xilinx/Kconfig | 1 + drivers/clk/xilinx/clk-xlnx-clock-wizard.c | 69 ++++++++++++++++++++-- 2 files changed, 66 insertions(+), 4 deletions(-) diff --git a/drivers/clk/xilinx/Kconfig b/drivers/clk/xilinx/Kconfig index 051756953558b..37758ac9ab552 100644 --- a/drivers/clk/xilinx/Kconfig +++ b/drivers/clk/xilinx/Kconfig @@ -21,6 +21,7 @@ config COMMON_CLK_XLNX_CLKWZRD =09tristate "Xilinx Clocking Wizard" =09depends on OF =09depends on HAS_IOMEM +=09select WANT_DEV_COREDUMP =09help =09 Support for the Xilinx Clocking Wizard IP core clock generator. =09 Adds support for clocking wizard and compatible. diff --git a/drivers/clk/xilinx/clk-xlnx-clock-wizard.c b/drivers/clk/xilin= x/clk-xlnx-clock-wizard.c index 4a0136349f71a..f14d1ec80a321 100644 --- a/drivers/clk/xilinx/clk-xlnx-clock-wizard.c +++ b/drivers/clk/xilinx/clk-xlnx-clock-wizard.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -19,11 +20,15 @@ #include #include #include +#include #include =20 #define WZRD_NUM_OUTPUTS=097 #define WZRD_ACLK_MAX_FREQ=09250000000UL +#define WZRD_NUM_DUMP_REGS=095 =20 +#define WZRD_INTR_STATUS=090x0C +#define WZRD_INTR_ENABLE=090x10 #define WZRD_CLK_CFG_REG(v, n)=09(0x200 + 0x130 * (v) + 4 * (n)) =20 #define WZRD_CLKOUT0_FRAC_EN=09BIT(18) @@ -124,6 +129,7 @@ enum clk_wzrd_int_clks { /** * struct clk_wzrd - Clock wizard private data structure * + * @pdev:=09=09Platform device * @nb:=09=09=09Notifier block * @base:=09=09Memory base * @clk_in1:=09=09Handle to input clock 'clk_in1' @@ -131,9 +137,11 @@ enum clk_wzrd_int_clks { * @clks_internal:=09Internal clocks * @speed_grade:=09Speed grade of the device * @suspended:=09=09Flag indicating power state of the device + * @work:=09=09Delayed work for devcoredump * @clk_data:=09=09Output clock data */ struct clk_wzrd { +=09struct platform_device *pdev; =09struct notifier_block nb; =09void __iomem *base; =09struct clk *clk_in1; @@ -141,6 +149,7 @@ struct clk_wzrd { =09struct clk_hw *clks_internal[wzrd_clk_int_max]; =09unsigned int speed_grade; =09bool suspended; +=09struct delayed_work work; =09struct clk_hw_onecell_data clk_data; }; =20 @@ -177,8 +186,9 @@ struct clk_wzrd_divider { =09spinlock_t *lock; /* divider lock */ }; =20 -struct versal_clk_data { +struct clk_wzrd_data { =09bool is_versal; +=09bool has_monitor; }; =20 #define to_clk_wzrd(_nb) container_of(_nb, struct clk_wzrd, nb) @@ -984,8 +994,13 @@ static int __maybe_unused clk_wzrd_resume(struct devic= e *dev) static SIMPLE_DEV_PM_OPS(clk_wzrd_dev_pm_ops, clk_wzrd_suspend, =09=09=09 clk_wzrd_resume); =20 -static const struct versal_clk_data versal_data =3D { +static const struct clk_wzrd_data version_6_0_data =3D { +=09.is_versal=09=3D false, +=09.has_monitor=09=3D true, +}; +static const struct clk_wzrd_data versal_data =3D { =09.is_versal=09=3D true, +=09.has_monitor=09=3D true, }; =20 static int clk_wzrd_register_output_clocks(struct device *dev, int nr_outp= uts) @@ -993,7 +1008,7 @@ static int clk_wzrd_register_output_clocks(struct devi= ce *dev, int nr_outputs) =09const char *clkout_name, *clk_name, *clk_mul_name; =09struct clk_wzrd *clk_wzrd =3D dev_get_drvdata(dev); =09u32 regl, regh, edge, regld, reghd, edged, div; -=09const struct versal_clk_data *data; +=09const struct clk_wzrd_data *data; =09unsigned long flags =3D 0; =09bool is_versal =3D false; =09void __iomem *ctrl_reg; @@ -1150,14 +1165,45 @@ static int clk_wzrd_register_output_clocks(struct d= evice *dev, int nr_outputs) =09return 0; } =20 +static irqreturn_t clk_wzrd_user_mon_intr_handler(int irq, void *data) +{ +=09struct clk_wzrd *clk_wzrd =3D platform_get_drvdata(data); + +=09schedule_delayed_work(&clk_wzrd->work, msecs_to_jiffies(10)); +=09return IRQ_HANDLED; +} + +static void clk_wzrd_user_mon_work(struct work_struct *work) +{ +=09struct clk_wzrd *clk_wzrd =3D container_of(work, struct clk_wzrd, work.= work); +=09u32 *dump =3D vmalloc(WZRD_NUM_DUMP_REGS * sizeof(*dump)); + +=09ioread32_rep(clk_wzrd->base, dump, WZRD_NUM_DUMP_REGS); +=09dev_coredumpv(&clk_wzrd->pdev->dev, dump, WZRD_NUM_DUMP_REGS * sizeof(*= dump), GFP_KERNEL); +=09iowrite32(dump[WZRD_INTR_STATUS / sizeof(*dump)], clk_wzrd->base + WZRD= _INTR_STATUS); +} + +static void clk_wzrd_cancel_delayed_work(void *data) +{ +=09struct delayed_work *work =3D data; + +=09cancel_delayed_work_sync(work); +} + static int clk_wzrd_probe(struct platform_device *pdev) { +=09const struct clk_wzrd_data *data =3D device_get_match_data(&pdev->dev); =09struct device_node *np =3D pdev->dev.of_node; =09struct clk_wzrd *clk_wzrd; =09unsigned long rate; =09int nr_outputs; +=09int irq; =09int ret; =20 +=09irq =3D platform_get_irq_optional(pdev, 0); +=09if (irq < 0 && irq !=3D -ENXIO) +=09=09return dev_err_probe(&pdev->dev, irq, "failed to get irq\n"); + =09ret =3D of_property_read_u32(np, "xlnx,nr-outputs", &nr_outputs); =09if (ret || nr_outputs > WZRD_NUM_OUTPUTS) =09=09return -EINVAL; @@ -1226,6 +1272,21 @@ static int clk_wzrd_probe(struct platform_device *pd= ev) =09=09} =09} =20 +=09if (data && data->has_monitor && irq > 0) { +=09=09ret =3D devm_request_irq(&pdev->dev, irq, clk_wzrd_user_mon_intr_han= dler, IRQF_SHARED, +=09=09=09=09 "user_mon", clk_wzrd); +=09=09if (ret) +=09=09=09return dev_err_probe(&pdev->dev, ret, "failed to request irq\n"); + +=09=09INIT_DELAYED_WORK(&clk_wzrd->work, clk_wzrd_user_mon_work); +=09=09ret =3D devm_add_action_or_reset(&pdev->dev, clk_wzrd_cancel_delayed= _work, +=09=09=09=09=09 &clk_wzrd->work); +=09=09if (ret) +=09=09=09return ret; + +=09=09writel(GENMASK(15, 0), clk_wzrd->base + WZRD_INTR_ENABLE); +=09} + =09return 0; } =20 @@ -1233,7 +1294,7 @@ static const struct of_device_id clk_wzrd_ids[] =3D { =09{ .compatible =3D "xlnx,versal-clk-wizard", .data =3D &versal_data }, =09{ .compatible =3D "xlnx,clocking-wizard" }, =09{ .compatible =3D "xlnx,clocking-wizard-v5.2" }, -=09{ .compatible =3D "xlnx,clocking-wizard-v6.0" }, +=09{ .compatible =3D "xlnx,clocking-wizard-v6.0", .data =3D &version_6_0_d= ata }, =09{ }, }; MODULE_DEVICE_TABLE(of, clk_wzrd_ids); --=20 2.53.0