From nobody Sat Sep 26 22:56:28 2026 Received: from mta-64-228.siemens.flowmailer.net (mta-64-228.siemens.flowmailer.net [185.136.64.228]) (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 613A8226D18 for ; Fri, 28 Aug 2026 16:44:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.136.64.228 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787935497; cv=none; b=XGxSHlipqDIo75w9kS1pVguKFYlkF3s0c/ddxdhDjouNnijscxW9ps//BtDD+3pODfP/kQ2gGTwa5ESyiNzif/J7c1kssZBU6F0TTv83Qyx0ohNH7X+7CTfWG2yiI3f1oXkKidkq7ueQyq99AZFb7SIep9f48DJCTMphS6y10Ds= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787935497; c=relaxed/simple; bh=a2Z5JjwNxud3x1Fk4ilxgstYmDcVs6aSO2HZ5JIEbIE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=a823tF6GKNBKwpGdBIBSlaEplmxRBZbcuRJjCWwoK9CiDMzX2wPUzLktJ2g9JvIruDQzWhxU1jI6J/BVZYYxqo7F85BwOi6dIpHqIbWcpf7xgvibNgya2SweLq8iDSk6FDLik1IjmMdbl12TaDKXiYc/KYIYFM+eLKPTOqA3LdY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=siemens.com; spf=pass smtp.mailfrom=rts-flowmailer.siemens.com; dkim=pass (2048-bit key) header.d=siemens.com header.i=alexander.sverdlin@siemens.com header.b=der95ZNv; arc=none smtp.client-ip=185.136.64.228 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=siemens.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=rts-flowmailer.siemens.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=siemens.com header.i=alexander.sverdlin@siemens.com header.b="der95ZNv" Received: by mta-64-228.siemens.flowmailer.net with ESMTPSA id 202608281644486d78cd0076000207a0 for ; Fri, 28 Aug 2026 18:44:48 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm2; d=siemens.com; i=alexander.sverdlin@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc:References:In-Reply-To; bh=BZcCro/FSTR14TT7n6Isl1Irs+JM+nnMtBgNPo3XYiE=; b=der95ZNvtlPWTgIUUun2SOCyEiPO5yNDYTRXwyqOLuVuWHiVOi8WBskQmUkzDCONGlmGIv 6afTbDlxsYq12OM9x5LPPUqJWTVhCCKhQHJlh5K3E8jAOUPBmrwv3NBEsLGkc66cx+y9Jwof kz4hI1I1QIGMtdWf9/YPfjWSLUDq4aQ3z6I4cHgOmsqXC37VWgL60V37oD2yxx+P2Vuw6Ugj fa1sBg6QYKtUxpPEtSVSfY+1queMwSUdO3anWmWVSPvaPAE3CDF5nib/pjHRhzmqXN1TvZtm OAn/oyAdZkFkDuLdG9zwrQBgmKD7a7ZB6jq7UzWdu31i3/0gXrxC+yzQ==; From: "A. Sverdlin" To: linux-rtc@vger.kernel.org Cc: Alexander Sverdlin , Alexandre Belloni , linux-kernel@vger.kernel.org Subject: [PATCH v3 1/4] rtc: pcf85063: use devm_of_clk_add_hw_provider() for clkout Date: Fri, 28 Aug 2026 18:44:39 +0200 Message-ID: <20260828164445.3907839-2-alexander.sverdlin@siemens.com> In-Reply-To: <20260828164445.3907839-1-alexander.sverdlin@siemens.com> References: <20260828164445.3907839-1-alexander.sverdlin@siemens.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-456497:519-21489:flowmailer Content-Type: text/plain; charset="utf-8" From: Alexander Sverdlin pcf85063_clkout_register_clk() registered the OF clock provider with the deprecated of_clk_add_provider() and never removed it, so the provider kept pointing at freed data after unbind, leading to a use-after-free the next time the device-tree clock was resolved. Switch to devm_clk_hw_register() and devm_of_clk_add_hw_provider(): both the clock and its OF provider are managed resources now, and the provider is torn down before the clock on unbind. Register the clock on the parent i2c device instead of the rtc device. devm_of_clk_add_hw_provider() must use the parent, which owns the of_node, and the clkout_hw it points at lives in the driver data allocated on the parent. Tying both to the parent releases them together on unbind, before the driver data is freed, and keeps their teardown ordering guaranteed by a single devres list. Registering the clock on the rtc device instead could defer its unregistration past unbind (e.g. while a /dev/rtcN fd is open), after clkout_hw has already been freed. Signed-off-by: Alexander Sverdlin --- Changelog: v3: - new patch (pre-exising issue found by Sashiko) drivers/rtc/rtc-pcf85063.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c index 8cb9ffc73f6d9..ac9ab1c376c0b 100644 --- a/drivers/rtc/rtc-pcf85063.c +++ b/drivers/rtc/rtc-pcf85063.c @@ -495,12 +495,13 @@ static const struct clk_ops pcf85063_clkout_ops =3D { .set_rate =3D pcf85063_clkout_set_rate, }; =20 -static struct clk *pcf85063_clkout_register_clk(struct pcf85063 *pcf85063) +static int pcf85063_clkout_register_clk(struct pcf85063 *pcf85063) { - struct clk *clk; + struct device *dev =3D pcf85063->rtc->dev.parent; struct clk_init_data init =3D {}; - struct device_node *node =3D pcf85063->rtc->dev.parent->of_node; + struct device_node *node =3D dev->of_node; struct device_node *fixed_clock; + int ret; =20 fixed_clock =3D of_get_child_by_name(node, "clock"); if (fixed_clock) { @@ -510,7 +511,7 @@ static struct clk *pcf85063_clkout_register_clk(struct = pcf85063 *pcf85063) * registered automatically when being referenced. */ of_node_put(fixed_clock); - return NULL; + return 0; } =20 init.name =3D "pcf85063-clkout"; @@ -524,12 +525,12 @@ static struct clk *pcf85063_clkout_register_clk(struc= t pcf85063 *pcf85063) of_property_read_string(node, "clock-output-names", &init.name); =20 /* register the clock */ - clk =3D devm_clk_register(&pcf85063->rtc->dev, &pcf85063->clkout_hw); - - if (!IS_ERR(clk)) - of_clk_add_provider(node, of_clk_src_simple_get, clk); + ret =3D devm_clk_hw_register(dev, &pcf85063->clkout_hw); + if (ret) + return ret; =20 - return clk; + return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, + &pcf85063->clkout_hw); } #endif =20 --=20 2.55.0 From nobody Sat Sep 26 22:56:28 2026 Received: from mta-65-226.siemens.flowmailer.net (mta-65-226.siemens.flowmailer.net [185.136.65.226]) (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 45A9A38D006 for ; Fri, 28 Aug 2026 16:44:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.136.65.226 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787935500; cv=none; b=bKKT/cAmei+BL5unfCMH7u0pCaNrVHee97ceUDT/DD7N/WuZI1fFZSoYwwGV7LOKMBWPmVD1kClQkrf75G9jgWMmGaxnIXnv+opFXD5v7G3F70xWJnbb+8wRdLgSiL402fp2678IbrDYvRnuiimh6fWofy2XuDfXdgUv3wtJWY0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787935500; c=relaxed/simple; bh=llONX/NdZoKFEqhCFOoppH176y3je0zUEANfqWHZ5Vk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=p1VjJ4pa3rOruouyBz3i647WzT0KzwtuzKLlEgLlVYcKkkTm1qRsqyQHBvTR8l+d50zsEiK6dz+fteydDNDwQ00qVyyI2LOOO3+y+cDSzqOSTPwBq8jU9vuya5SFsQ5FE2ipYoSO5Q+Q8crd7LzV9odW0tsrO4QtfxO7wfhs67I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=siemens.com; spf=pass smtp.mailfrom=rts-flowmailer.siemens.com; dkim=pass (2048-bit key) header.d=siemens.com header.i=alexander.sverdlin@siemens.com header.b=RBV2WJoc; arc=none smtp.client-ip=185.136.65.226 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=siemens.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=rts-flowmailer.siemens.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=siemens.com header.i=alexander.sverdlin@siemens.com header.b="RBV2WJoc" Received: by mta-65-226.siemens.flowmailer.net with ESMTPSA id 2026082816444832e6769e2e000207d7 for ; Fri, 28 Aug 2026 18:44:48 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm2; d=siemens.com; i=alexander.sverdlin@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc:References:In-Reply-To; bh=yngTCFB+bOnL2vvp7Vkgzb4fmNnuoa1MBLNdfXgLr/8=; b=RBV2WJoc6tcR3CKUocL7lnNNfcHdzYLpbIvYgYM+psRUpwJ68qc0jDoclZqgeSa/fF0DTE KMFAhyBVBzZ/OjpTBqL/irnafhQZSVCeMrrlv2bIQJcCJZLZbxcIjzOBLxaTr+qAIurruVQw H0HwMV0pkJOMTS41A131DUAnh1hb22I0V8uAfZsu1jmmw+eKVDUxWFm9cll2Kz/eXKyG+0/o Mo4QhWMrHcKcOWRJY5f4FgB9Xc0jrruhxkC8Fw30QdGGMPzAWN+P50gCrMKE2yFQx8YuqLvL 8xnpWMghV3pQiZfSfOL5FIknwemIPcjj7SL1OiTMefOdYP7TeBWbphpQ==; From: "A. Sverdlin" To: linux-rtc@vger.kernel.org Cc: Alexander Sverdlin , Alexandre Belloni , linux-kernel@vger.kernel.org Subject: [PATCH v3 2/4] rtc: pcf85063: do not clear AIE in the interrupt handler Date: Fri, 28 Aug 2026 18:44:40 +0200 Message-ID: <20260828164445.3907839-3-alexander.sverdlin@siemens.com> In-Reply-To: <20260828164445.3907839-1-alexander.sverdlin@siemens.com> References: <20260828164445.3907839-1-alexander.sverdlin@siemens.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-456497:519-21489:flowmailer Content-Type: text/plain; charset="utf-8" From: Alexander Sverdlin The interrupt handler cleared the alarm interrupt enable (AIE) bit while acknowledging the alarm flag (AF). This races with process-context updates of AIE in pcf85063_rtc_alarm_irq_enable() and pcf85063_rtc_set_alarm(): a handler running concurrently can clobber an AIE change. The RTC core already disables the alarm interrupt after a one-shot alarm via the .alarm_irq_enable callback, so the handler does not need to touch AIE at all. Acknowledge AF only and leave AIE management to the core. Signed-off-by: Alexander Sverdlin --- Changelog: v3: - new patch (pre-existing issue found by Sashiko) drivers/rtc/rtc-pcf85063.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c index ac9ab1c376c0b..af900fe8ae15e 100644 --- a/drivers/rtc/rtc-pcf85063.c +++ b/drivers/rtc/rtc-pcf85063.c @@ -238,8 +238,7 @@ static irqreturn_t pcf85063_rtc_handle_irq(int irq, voi= d *dev_id) if (val & PCF85063_CTRL2_AF) { rtc_update_irq(pcf85063->rtc, 1, RTC_IRQF | RTC_AF); regmap_update_bits(pcf85063->regmap, PCF85063_REG_CTRL2, - PCF85063_CTRL2_AIE | PCF85063_CTRL2_AF, - 0); + PCF85063_CTRL2_AF, 0); return IRQ_HANDLED; } =20 --=20 2.55.0 From nobody Sat Sep 26 22:56:28 2026 Received: from mta-64-228.siemens.flowmailer.net (mta-64-228.siemens.flowmailer.net [185.136.64.228]) (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 E83A537E5F7 for ; Fri, 28 Aug 2026 16:44:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.136.64.228 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787935496; cv=none; b=WNh9dRQJsBdQ5M976wsiE7HZRshia2KDe9vBwU2PR8T2+S+WCNnqfkgVUHZZDMEn1c3tAARArcuJlwoMQG1o21kpDNn+ObTcrFJt3rb8GRKboEDS8k+wq7RC1vuRlhdQbtjNV9gFXXAGG6lCE0V7h3ExojynjmCXxLfPZjyRz7k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787935496; c=relaxed/simple; bh=457CAtUxAcs/Gwar0TINkysy9s5JEuWwKe+C6AqVrq4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=mG06XDlkEKcvyVn4R1mxVaDXP6s4ajESBp3VwxL1BexxO7gM76uUt6pBmA7feYAdHXzM53TEGVCb75Xe0uCKrJQXafp1fcXgXEaszQ81JGfteG1YOboy9WnuSRsJeHQq8X6EjyYNclkSlj3cjk+5zm++t739LHoazn9L5ns/9xc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=siemens.com; spf=pass smtp.mailfrom=rts-flowmailer.siemens.com; dkim=pass (2048-bit key) header.d=siemens.com header.i=alexander.sverdlin@siemens.com header.b=T9+BO9MN; arc=none smtp.client-ip=185.136.64.228 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=siemens.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=rts-flowmailer.siemens.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=siemens.com header.i=alexander.sverdlin@siemens.com header.b="T9+BO9MN" Received: by mta-64-228.siemens.flowmailer.net with ESMTPSA id 2026082816444836d382e3bf00020765 for ; Fri, 28 Aug 2026 18:44:49 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm2; d=siemens.com; i=alexander.sverdlin@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc:References:In-Reply-To; bh=F0SPxnW9ihACmhsmRod40BgEcDghFlQJr7zg3/N/fbQ=; b=T9+BO9MNZRcou0Lo4vVVYvmasYLAZyVJWpdfWcr9108LBjzv6lQjuV5XFt/76FgQ3FkFiU TaW/cIt6FZz0AA2xGNeAeqpcwFJ3pywRkF2t8UP/EOjYy0OZslipCBe2fkV1c182OLVEqVbB bHjJn5m9viQOarOgdiJ1mOXV3zh4jHj49oxM2BizjSwxy7DWOvY/3dZHOj2zec2qk4GLx4j/ 531dNt3/05/0GhGtfxJOOkgkdQVxJly6hMlNp44dwIuVslQKKlwGnHJOEIkJy4VbA3RwDVyZ tjOqRzmutklRltZM2jhf7xLYDF5Ye32aCXTHaMY9gwGuxZkrwcQhbWZQ==; From: "A. Sverdlin" To: linux-rtc@vger.kernel.org Cc: Alexander Sverdlin , Alexandre Belloni , linux-kernel@vger.kernel.org Subject: [PATCH v3 3/4] rtc: pcf85063: preserve the alarm flag in clkout register updates Date: Fri, 28 Aug 2026 18:44:41 +0200 Message-ID: <20260828164445.3907839-4-alexander.sverdlin@siemens.com> In-Reply-To: <20260828164445.3907839-1-alexander.sverdlin@siemens.com> References: <20260828164445.3907839-1-alexander.sverdlin@siemens.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-456497:519-21489:flowmailer Content-Type: text/plain; charset="utf-8" From: Alexander Sverdlin The clkout rate and enable/disable helpers update CTRL2 with regmap_update_bits() but leave the alarm flag (AF) out of the mask. AF is write-0-to-clear, so an AF that gets asserted between the read and the write of the read-modify-write is written back as 0 and the pending alarm interrupt is lost. Add AF to the mask and write it back as 1 (write-1-to-preserve) so a concurrently asserted alarm flag survives a clkout reconfiguration. Signed-off-by: Alexander Sverdlin --- Changelog: v3: - new patch drivers/rtc/rtc-pcf85063.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c index af900fe8ae15e..a3af86456ccfc 100644 --- a/drivers/rtc/rtc-pcf85063.c +++ b/drivers/rtc/rtc-pcf85063.c @@ -431,7 +431,8 @@ static int pcf85063_clkout_set_rate(struct clk_hw *hw, = unsigned long rate, if (clkout_rates[i] =3D=3D rate) return regmap_update_bits(pcf85063->regmap, PCF85063_REG_CTRL2, - PCF85063_REG_CLKO_F_MASK, i); + PCF85063_REG_CLKO_F_MASK | PCF85063_CTRL2_AF, + i | PCF85063_CTRL2_AF); =20 return -EINVAL; } @@ -460,7 +461,8 @@ static int pcf85063_clkout_control(struct clk_hw *hw, b= ool enable) } =20 return regmap_update_bits(pcf85063->regmap, PCF85063_REG_CTRL2, - PCF85063_REG_CLKO_F_MASK, buf); + PCF85063_REG_CLKO_F_MASK | PCF85063_CTRL2_AF, + buf | PCF85063_CTRL2_AF); } =20 static int pcf85063_clkout_prepare(struct clk_hw *hw) --=20 2.55.0 From nobody Sat Sep 26 22:56:28 2026 Received: from mta-64-226.siemens.flowmailer.net (mta-64-226.siemens.flowmailer.net [185.136.64.226]) (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 A01D838B124 for ; Fri, 28 Aug 2026 16:44:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.136.64.226 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787935501; cv=none; b=GytaDPe77FuNTVgOXZiHr+bjAJu3lNSE9S8x7wr6RQ2YTH+rno0f2cfFIRgsJxfHH4Ww6fZEBXiwYPCkAr4AQ8CNBttUv0TnzefBXh9Hj/BgeX+UPsnMAQW4ZGQDPmIXs8/yUBGit0Osn4nWnBFA+RKsQR4X1xadrcoOf+uQIkY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787935501; c=relaxed/simple; bh=u6cJ7MqHLoBC0SNILU3oVgTt8kyg2HB9w5otXpHsJaY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=U6laz5umMC9bcdUwS1RiEEPiikhJNVjbnbTLChSjvBc4SGcgOGQNklLcrwK+teN9Gekn8RWyN5CMq4LEvvXalgDh2r6xRO9qujerBcS1iKFrrHbMksWpACrWcIWyIUAo901mzSGqKLurNuYulFkDJPFrPEOmZnyNux7bupBhgy8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=siemens.com; spf=pass smtp.mailfrom=rts-flowmailer.siemens.com; dkim=pass (2048-bit key) header.d=siemens.com header.i=alexander.sverdlin@siemens.com header.b=WsFgI7zp; arc=none smtp.client-ip=185.136.64.226 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=siemens.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=rts-flowmailer.siemens.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=siemens.com header.i=alexander.sverdlin@siemens.com header.b="WsFgI7zp" Received: by mta-64-226.siemens.flowmailer.net with ESMTPSA id 202608281644499141f039890002076f for ; Fri, 28 Aug 2026 18:44:49 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm2; d=siemens.com; i=alexander.sverdlin@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc:References:In-Reply-To; bh=dvxXBp5fhAtU91nrjYLGWWLKhFtygUw1X+1C/cjNPxw=; b=WsFgI7zpQSOzTdQhd/2GUadY9mOd7PXfSbW0JGD54u1e8OMSkVPFIchO2EompoM5rCC6pp Dtgedu3UkmP3AHbNcrN0wp25vezUtdT3147KobTHoAtMqYBTa1IGXDuqbybCc7ksCL94jtv8 aiNEsdre+o54xUuNrh6CAog+zxATAeABZogBVyerkL+CRLBV+OfNp1yvw+NgSHFr4XxhSB4n BRne4v57ydN32qD4vYxlaxsWVS4RWcwxm5hudGjpTOPt2ozt1rxN/GluTxyrZcOW/vhxnLGH d6gaBI669537SXDxDTE7UhJpL2O576Tjz1KBU2MVbgqFVOpXKzBrsS0w==; From: "A. Sverdlin" To: linux-rtc@vger.kernel.org Cc: Alexander Sverdlin , Alexandre Belloni , linux-kernel@vger.kernel.org, Adrian Freihofer Subject: [PATCH v3 4/4] rtc: pcf85063: add 1 Hz update interrupt (UIE) support Date: Fri, 28 Aug 2026 18:44:42 +0200 Message-ID: <20260828164445.3907839-5-alexander.sverdlin@siemens.com> In-Reply-To: <20260828164445.3907839-1-alexander.sverdlin@siemens.com> References: <20260828164445.3907839-1-alexander.sverdlin@siemens.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-456497:519-21489:flowmailer Content-Type: text/plain; charset="utf-8" From: Alexander Sverdlin The PCF85063A/RV8263 have no dedicated 1 Hz update interrupt, but their countdown timer can be sourced from a 1 Hz clock (TCF =3D 1 Hz, T =3D 1) to generate a periodic interrupt on the INT pin. Use it to offload UIE to the hardware, following the pattern of other RTC drivers: the timer is enabled from set_alarm()/alarm_irq_enable() whenever uie_rtctimer is active, and the IRQ handler reports RTC_UF when the timer flag (TF) is set. RTC_FEATURE_UPDATE_INTERRUPT is now only cleared when no usable interrupt is wired, preserving the polling emulation for those configurations. Co-developed-by: Adrian Freihofer Signed-off-by: Adrian Freihofer Signed-off-by: Alexander Sverdlin --- Changelog: v3: - replaced racy regmap_write() with regmap_update_bits() in IRQ handler - the timer flag (TF) is write-0-to-clear, so every read-modify-write of CTRL2 preserves it by writing it back as 1 v2: - preserve AF bit in pcf85063_set_timer_1hz() - faster and less racy (regarding AF flag) pcf85063_rtc_handle_irq() - https://lore.kernel.org/all/20260820112437.3715237-1-alexander.sverdlin@s= iemens.com/ drivers/rtc/rtc-pcf85063.c | 121 +++++++++++++++++++++++++++++++++---- 1 file changed, 108 insertions(+), 13 deletions(-) diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c index a3af86456ccfc..32952e73f2f1c 100644 --- a/drivers/rtc/rtc-pcf85063.c +++ b/drivers/rtc/rtc-pcf85063.c @@ -44,6 +44,7 @@ #define PCF85063_REG_CTRL2 0x01 #define PCF85063_CTRL2_AF BIT(6) #define PCF85063_CTRL2_AIE BIT(7) +#define PCF85063_CTRL2_TF BIT(3) =20 #define PCF85063_REG_OFFSET 0x02 #define PCF85063_OFFSET_SIGN_BIT 6 /* 2's complement sign bit */ @@ -63,6 +64,14 @@ #define PCF85063_REG_ALM_S 0x0b #define PCF85063_AEN BIT(7) =20 +#define PCF85063_REG_TIMER_VALUE 0x10 +#define PCF85063_REG_TIMER_MODE 0x11 +#define PCF85063_TIMER_MODE_TI_TP BIT(0) +#define PCF85063_TIMER_MODE_TIE BIT(1) +#define PCF85063_TIMER_MODE_TE BIT(2) +#define PCF85063_TIMER_MODE_TCF_MASK GENMASK(4, 3) +#define PCF85063_TIMER_MODE_TCF_1HZ (2 << 3) + struct pcf85063_config { struct regmap_config regmap; unsigned has_alarms:1; @@ -188,20 +197,75 @@ static int pcf85063_rtc_read_alarm(struct device *dev= , struct rtc_wkalrm *alrm) return 0; } =20 +/* + * The chip has no dedicated 1 Hz update interrupt. Drive the countdown ti= mer + * at 1 Hz to emulate it, so the RTC core can offload UIE to the hardware + * instead of polling. A free-running timer is left untouched to preserve = its + * phase across the per-second re-arming done by the core. + */ +static int pcf85063_set_timer_1hz(struct pcf85063 *pcf85063, bool enable) +{ + unsigned int mask =3D PCF85063_TIMER_MODE_TCF_MASK | + PCF85063_TIMER_MODE_TIE | + PCF85063_TIMER_MODE_TI_TP | + PCF85063_TIMER_MODE_TE; + unsigned int mode =3D 0; + unsigned int cur; + int ret; + + if (enable) + mode =3D PCF85063_TIMER_MODE_TCF_1HZ | PCF85063_TIMER_MODE_TIE | + PCF85063_TIMER_MODE_TI_TP | PCF85063_TIMER_MODE_TE; + + ret =3D regmap_read(pcf85063->regmap, PCF85063_REG_TIMER_MODE, &cur); + if (ret) + return ret; + + if ((cur & mask) =3D=3D mode) + return 0; + + /* Stop the counter before changing its reload value. */ + ret =3D regmap_update_bits(pcf85063->regmap, PCF85063_REG_TIMER_MODE, + PCF85063_TIMER_MODE_TE, 0); + if (ret) + return ret; + + if (enable) { + ret =3D regmap_write(pcf85063->regmap, PCF85063_REG_TIMER_VALUE, 1); + if (ret) + return ret; + + /* Clear TF but preserve AF */ + ret =3D regmap_update_bits(pcf85063->regmap, PCF85063_REG_CTRL2, + PCF85063_CTRL2_TF | PCF85063_CTRL2_AF, PCF85063_CTRL2_AF); + if (ret) + return ret; + } + + return regmap_update_bits(pcf85063->regmap, PCF85063_REG_TIMER_MODE, + mask, mode); +} + static int pcf85063_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *a= lrm) { struct pcf85063 *pcf85063 =3D dev_get_drvdata(dev); u8 buf[5]; int ret; =20 + ret =3D pcf85063_set_timer_1hz(pcf85063, pcf85063->rtc->uie_rtctimer.enab= led); + if (ret) + return ret; + buf[0] =3D bin2bcd(alrm->time.tm_sec); buf[1] =3D bin2bcd(alrm->time.tm_min); buf[2] =3D bin2bcd(alrm->time.tm_hour); buf[3] =3D bin2bcd(alrm->time.tm_mday); buf[4] =3D PCF85063_AEN; /* Do not match on week day */ =20 + /* Preserve TF */ ret =3D regmap_update_bits(pcf85063->regmap, PCF85063_REG_CTRL2, - PCF85063_CTRL2_AIE | PCF85063_CTRL2_AF, 0); + PCF85063_CTRL2_AIE | PCF85063_CTRL2_AF | PCF85063_CTRL2_TF, + PCF85063_CTRL2_TF); if (ret) return ret; =20 @@ -211,23 +275,33 @@ static int pcf85063_rtc_set_alarm(struct device *dev,= struct rtc_wkalrm *alrm) return ret; =20 return regmap_update_bits(pcf85063->regmap, PCF85063_REG_CTRL2, - PCF85063_CTRL2_AIE | PCF85063_CTRL2_AF, - alrm->enabled ? PCF85063_CTRL2_AIE | PCF85063_CTRL2_AF : PCF85063_CT= RL2_AF); + PCF85063_CTRL2_AIE | PCF85063_CTRL2_AF | PCF85063_CTRL2_TF, + pcf85063->rtc->aie_timer.enabled ? + PCF85063_CTRL2_AIE | PCF85063_CTRL2_AF | PCF85063_CTRL2_TF : + PCF85063_CTRL2_AF | PCF85063_CTRL2_TF); } =20 static int pcf85063_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) { struct pcf85063 *pcf85063 =3D dev_get_drvdata(dev); + int ret; + + ret =3D pcf85063_set_timer_1hz(pcf85063, pcf85063->rtc->uie_rtctimer.enab= led); + if (ret) + return ret; =20 return regmap_update_bits(pcf85063->regmap, PCF85063_REG_CTRL2, - PCF85063_CTRL2_AIE, - enabled ? PCF85063_CTRL2_AIE : 0); + PCF85063_CTRL2_AIE | PCF85063_CTRL2_TF, + pcf85063->rtc->aie_timer.enabled ? + PCF85063_CTRL2_AIE | PCF85063_CTRL2_TF : PCF85063_CTRL2_TF); } =20 static irqreturn_t pcf85063_rtc_handle_irq(int irq, void *dev_id) { struct pcf85063 *pcf85063 =3D dev_id; + unsigned long events =3D RTC_IRQF; + irqreturn_t ret =3D IRQ_NONE; unsigned int val; int err; =20 @@ -236,13 +310,33 @@ static irqreturn_t pcf85063_rtc_handle_irq(int irq, v= oid *dev_id) return IRQ_NONE; =20 if (val & PCF85063_CTRL2_AF) { - rtc_update_irq(pcf85063->rtc, 1, RTC_IRQF | RTC_AF); + events |=3D RTC_AF; + val &=3D ~PCF85063_CTRL2_AF; + ret =3D IRQ_HANDLED; + } else { + /* Preserve AF if it comes after the above regmap_read() */ + val |=3D PCF85063_CTRL2_AF; + } + + if (val & PCF85063_CTRL2_TF) { + events |=3D RTC_UF; + val &=3D ~PCF85063_CTRL2_TF; + ret =3D IRQ_HANDLED; + } else { + /* + * While not documented, TF demonstrates the same + * write-1-to-preserve semantics as AF in real HW + */ + val |=3D PCF85063_CTRL2_TF; + } + + if (ret =3D=3D IRQ_HANDLED) { regmap_update_bits(pcf85063->regmap, PCF85063_REG_CTRL2, - PCF85063_CTRL2_AF, 0); - return IRQ_HANDLED; + PCF85063_CTRL2_AF | PCF85063_CTRL2_TF, val); + rtc_update_irq(pcf85063->rtc, 1, events); } =20 - return IRQ_NONE; + return ret; } =20 static int pcf85063_read_offset(struct device *dev, long *offset) @@ -431,8 +525,8 @@ static int pcf85063_clkout_set_rate(struct clk_hw *hw, = unsigned long rate, if (clkout_rates[i] =3D=3D rate) return regmap_update_bits(pcf85063->regmap, PCF85063_REG_CTRL2, - PCF85063_REG_CLKO_F_MASK | PCF85063_CTRL2_AF, - i | PCF85063_CTRL2_AF); + PCF85063_REG_CLKO_F_MASK | PCF85063_CTRL2_AF | PCF85063_CTRL2_TF, + i | PCF85063_CTRL2_AF | PCF85063_CTRL2_TF); =20 return -EINVAL; } @@ -461,8 +555,8 @@ static int pcf85063_clkout_control(struct clk_hw *hw, b= ool enable) } =20 return regmap_update_bits(pcf85063->regmap, PCF85063_REG_CTRL2, - PCF85063_REG_CLKO_F_MASK | PCF85063_CTRL2_AF, - buf | PCF85063_CTRL2_AF); + PCF85063_REG_CLKO_F_MASK | PCF85063_CTRL2_AF | PCF85063_CTRL2_TF, + buf | PCF85063_CTRL2_AF | PCF85063_CTRL2_TF); } =20 static int pcf85063_clkout_prepare(struct clk_hw *hw) @@ -609,6 +703,7 @@ static int pcf85063_probe(struct device *dev, struct re= gmap *regmap, int irq, dev_warn(&pcf85063->rtc->dev, "unable to request IRQ, alarms disabled\n"); } else { + set_bit(RTC_FEATURE_UPDATE_INTERRUPT, pcf85063->rtc->features); set_bit(RTC_FEATURE_ALARM, pcf85063->rtc->features); device_init_wakeup(dev, true); err =3D dev_pm_set_wake_irq(dev, irq); --=20 2.55.0