From nobody Fri Oct 23 22:16:11 2026 Received: from mail.cjdns.fr (mail.cjdns.fr [5.135.140.105]) (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 7F8FE53C3AB; Thu, 15 Oct 2026 16:54:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=5.135.140.105 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792083276; cv=none; b=YEPL41Qv6RBk5cVI/x/rL3hNCsRQ6cl1/RwVWvm086voJ59P9TX/T9AF+gIwM6J9kiGJEWUsKXkCoLPFPjj5z9Th4LAZEGfSCx68txqrtrjwH2jJz0330bVEFOdI6OPoYtHLO0I1Rxz2IgUo/fHotg2quq82lG8eIJj909mFHy8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792083276; c=relaxed/simple; bh=Ze4Nv8y680E6FSf/un9hYJUthpJ2COzdxd+LB34Yb2I=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=HLqzJUVwSTLvIKWJl8F34L/AraySL470+n+3e4EsJwthdvC4jag/nR58jEJLYrTLllp07wmT5m+/NgYi+I6VRwVCELvaQ5hj+Z34snkl19GogzNdu55bqaT8iXzUctWPKwLyouFv1fZ1BYx3l3K3W1PQWiEqrCqc2l4fpY9dqB4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=cjdns.fr; spf=none smtp.mailfrom=cjdns.fr; dkim=pass (2048-bit key) header.d=cjdns.fr header.i=@cjdns.fr header.b=UvPSnBYP; arc=none smtp.client-ip=5.135.140.105 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=cjdns.fr Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=cjdns.fr Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=cjdns.fr header.i=@cjdns.fr header.b="UvPSnBYP" Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id F22F15B4015; Thu, 15 Oct 2026 18:54:10 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cjdns.fr; s=dkim; t=1792083252; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=X5WYmjC+W1XLRGqsI2xwQZ9HsjRo/iUHSgzYnXKRgcw=; b=UvPSnBYPS3fe5I2KHCP7uE9h/FXHgcjq4H0kOInhncfwTsWTo5xh+ZddNCgr6xmApSxL6p Dwa1GqRhoqnLg2Dh/0ILVB38XEbrKJFpBvlbccTn6jtvQ4+JbLHTPFMVtfvl7HVjNuF6A2 gRu8N43s7Bzi/miKwAOC6eGDbPPsMd8Pm6pHii3GjeAEuiE7P92wZ28LHlpeZLEcaizuDF dczm44B1ZI+Q0qCFeRB9CycEObVkF3+w1noaL5lpn3igZKS/jrfpiA7r+bpp7ihzXQMyJE CSGuyxtFbNKs58yybhpRS7zNp0WjYRaLaALb8nfpRWs7ZWeZJ2rW5sshpMclKg== From: Caleb James DeLisle To: linux-mips@vger.kernel.org Cc: conor+dt@kernel.org, daniel.lezcano@kernel.org, devicetree@vger.kernel.org, krzk+dt@kernel.org, linux-kernel@vger.kernel.org, naseefkm@gmail.com, robh@kernel.org, tglx@kernel.org, grandmaster@al2klimov.de, Caleb James DeLisle , Conor Dooley Subject: [PATCH v11 1/5] dt-bindings: timer: econet: Update EN751627 for multi-IRQ Date: Thu, 15 Oct 2026 16:54:00 +0000 Message-Id: <20261015165404.519741-2-cjd@cjdns.fr> In-Reply-To: <20261015165404.519741-1-cjd@cjdns.fr> References: <20261015165404.519741-1-cjd@cjdns.fr> 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-Last-TLS-Session-Version: TLSv1.3 Content-Type: text/plain; charset="utf-8" This hardware is found in the EN751221 SoC family as well as the EN751627. The former uses a percpu IRQ for all timers while the latter uses an individual IRQ number per timer. Signed-off-by: Caleb James DeLisle Acked-by: Conor Dooley --- .../bindings/timer/econet,en751221-timer.yaml | 31 ++++++++++++------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/Documentation/devicetree/bindings/timer/econet,en751221-timer.= yaml b/Documentation/devicetree/bindings/timer/econet,en751221-timer.yaml index c1e7c2b6afde..ac25785ecfdf 100644 --- a/Documentation/devicetree/bindings/timer/econet,en751221-timer.yaml +++ b/Documentation/devicetree/bindings/timer/econet,en751221-timer.yaml @@ -12,24 +12,23 @@ maintainers: description: The EcoNet High Precision Timer (HPT) is a timer peripheral found in var= ious EcoNet SoCs, including the EN751221 and EN751627 families. It provides p= er-VPE - count/compare registers and a per-CPU control register, with a single in= terrupt - line using a percpu-devid interrupt mechanism. + count/compare registers and a per-CPU control register. On EN751221 it u= ses a + single interrupt line using a percpu-devid interrupt mechanism, and on + EN751627 it uses an interrupt per VPE. =20 properties: compatible: - oneOf: - - const: econet,en751221-timer - - items: - - const: econet,en751627-timer - - const: econet,en751221-timer + enum: + - econet,en751221-timer + - econet,en751627-timer =20 reg: minItems: 1 maxItems: 2 =20 interrupts: - maxItems: 1 - description: A percpu-devid timer interrupt shared across CPUs. + minItems: 1 + maxItems: 4 =20 clocks: maxItems: 1 @@ -52,21 +51,31 @@ allOf: items: - description: VPE timers 0 and 1 - description: VPE timers 2 and 3 + interrupts: + description: An interrupt for each timer (one per VPE) + minItems: 4 else: properties: reg: items: - description: VPE timers 0 and 1 + interrupts: + description: A percpu-devid timer interrupt shared across timers + maxItems: 1 =20 additionalProperties: false =20 examples: - | + #include timer@1fbf0400 { - compatible =3D "econet,en751627-timer", "econet,en751221-timer"; + compatible =3D "econet,en751627-timer"; reg =3D <0x1fbf0400 0x100>, <0x1fbe0000 0x100>; interrupt-parent =3D <&intc>; - interrupts =3D <30>; + interrupts =3D , + , + , + ; clocks =3D <&hpt_clock>; }; - | --=20 2.39.5 From nobody Fri Oct 23 22:16:11 2026 Received: from mail.cjdns.fr (mail.cjdns.fr [5.135.140.105]) (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 3071137F72F; Thu, 15 Oct 2026 16:54:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=5.135.140.105 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792083269; cv=none; b=Wy7hcrUyQZsPeH62oNcanWHXKUXI+astkmVBJPHoMfU+HoryV49O3zdgUJXMpVD+lf8p6IuKqVQUUOOf5HqTeQWyDorBInv/2O9r2SVjaokvW0r0pHtGJ+UMh46FQgPJTvL2uOzWq49sE3pLRWJJNItwItd1FsvoBsiKAtae2pI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792083269; c=relaxed/simple; bh=xkU7FTh2Qx1l444kXVxCZ72X6BDvMmnbijkDMtD0tYY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=bBBRm4gCkAvy7CaIR5TNtH/WqMz+prZZmZ0nl+IOsV++Wn6sp+mRRi7STeqJH/gG9Uek0JmkbBrGLPQmma034WGNfysmlR0NC8VKXmYftSFwntDQMA7fEdcldOVs5Wv3qHk2xkAtfz3fdf9m/loSY376+/yTTale+SCx/YhyXbE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=cjdns.fr; spf=none smtp.mailfrom=cjdns.fr; dkim=pass (2048-bit key) header.d=cjdns.fr header.i=@cjdns.fr header.b=o2/bqiwY; arc=none smtp.client-ip=5.135.140.105 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=cjdns.fr Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=cjdns.fr Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=cjdns.fr header.i=@cjdns.fr header.b="o2/bqiwY" Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 201985B2177; Thu, 15 Oct 2026 18:54:13 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cjdns.fr; s=dkim; t=1792083254; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=B1OV7lBJrmDaac8ePy8dHk2DEYoP6HJXQm0PFK+z8S0=; b=o2/bqiwYFoQukh7daTnuMvtpICDH7iJx6/jBpaH5AWDeomi1y/qqQkbEDL9iYONx6xlVMx CwkXC6cpG//dZ+NKRgnmyrwkKyrYmeuRGrYTxZxVNt2b+Q9qvxDgU+Bdlo9mTehjDkO7dn 4dMRHJ64D469r+RkLibhRicJI7DRKhoYdUoJxwgzdPTU1ZxQv3YDAMEUzzKooes4Ef06Xd yJBu+PWDxrpd7YqZk3ArUD6KAx9hMez3osMLpCsGwlIV2xzIXpOP4zytByvfEu+s2gSjUu qQiP+jZhPWyLmUB59WeusFYpmWuwNAs+tClU6HiwPPsPcSpSSh2VkLarWrBrPA== From: Caleb James DeLisle To: linux-mips@vger.kernel.org Cc: conor+dt@kernel.org, daniel.lezcano@kernel.org, devicetree@vger.kernel.org, krzk+dt@kernel.org, linux-kernel@vger.kernel.org, naseefkm@gmail.com, robh@kernel.org, tglx@kernel.org, grandmaster@al2klimov.de, Caleb James DeLisle Subject: [PATCH v11 2/5] clocksource/timer-econet-en751221: Init teardown on error if possible Date: Thu, 15 Oct 2026 16:54:01 +0000 Message-Id: <20261015165404.519741-3-cjd@cjdns.fr> In-Reply-To: <20261015165404.519741-1-cjd@cjdns.fr> References: <20261015165404.519741-1-cjd@cjdns.fr> 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-Last-TLS-Session-Version: TLSv1.3 Content-Type: text/plain; charset="utf-8" As a clocksource, much of the initialization process is irreversible and the impact of a failure to initialize is a failure to boot. That said, good practice is to attempt a clean exit if probing fails, and supporting this pattern will reduce the likelihood that future contributions introduce a bug by trying to teardown after it is no longer possible to do so. Convert the init process into two clearly delineated phases, one which is reverted in case of error, and the other which can't be. Move all IRQ and address resource mapping before that point, and add teardown logic in case of error before the point of no return. Signed-off-by: Caleb James DeLisle --- drivers/clocksource/timer-econet-en751221.c | 84 ++++++++++++--------- 1 file changed, 50 insertions(+), 34 deletions(-) diff --git a/drivers/clocksource/timer-econet-en751221.c b/drivers/clocksou= rce/timer-econet-en751221.c index 1859335345b5..714702b9ef12 100644 --- a/drivers/clocksource/timer-econet-en751221.c +++ b/drivers/clocksource/timer-econet-en751221.c @@ -24,6 +24,7 @@ =20 static struct { void __iomem *membase[ECONET_NUM_BLOCKS]; + int irq; u32 freq_hz; } econet_timer __ro_after_init; =20 @@ -126,22 +127,9 @@ static void __init cevt_dev_init(uint cpu) iowrite32(U32_MAX, reg_compare(cpu)); } =20 -static int __init cevt_init(struct device_node *np) +static void __init cevt_init(struct device_node *np) { - int i, irq, ret; - - irq =3D irq_of_parse_and_map(np, 0); - if (irq <=3D 0) { - pr_err("%pOFn: irq_of_parse_and_map failed", np); - return -EINVAL; - } - - ret =3D request_percpu_irq(irq, cevt_interrupt, np->name, &econet_timer_p= cpu); - - if (ret < 0) { - pr_err("%pOFn: IRQ %d setup failed (%d)\n", np, irq, ret); - goto err_unmap_irq; - } + int i; =20 for_each_possible_cpu(i) { struct clock_event_device *cd =3D &per_cpu(econet_timer_pcpu, i); @@ -151,21 +139,12 @@ static int __init cevt_init(struct device_node *np) CLOCK_EVT_FEAT_C3STOP | CLOCK_EVT_FEAT_PERCPU; cd->set_next_event =3D cevt_set_next_event; - cd->irq =3D irq; + cd->irq =3D econet_timer.irq; cd->cpumask =3D cpumask_of(i); cd->name =3D np->name; =20 cevt_dev_init(i); } - - cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, - "clockevents/econet/timer:starting", - cevt_init_cpu, NULL); - return 0; - -err_unmap_irq: - irq_dispose_mapping(irq); - return ret; } =20 static int __init timer_init(struct device_node *np) @@ -187,22 +166,45 @@ static int __init timer_init(struct device_node *np) econet_timer.membase[i] =3D of_iomap(np, i); if (!econet_timer.membase[i]) { pr_err("%pOFn: failed to map register [%d]\n", np, i); - return -ENXIO; + ret =3D -ENXIO; + goto out_membase; } } =20 + econet_timer.irq =3D irq_of_parse_and_map(np, 0); + if (econet_timer.irq <=3D 0) { + pr_err("%pOFn: irq_of_parse_and_map failed\n", np); + ret =3D -EINVAL; + goto out_membase; + } + + ret =3D request_percpu_irq(econet_timer.irq, cevt_interrupt, np->name, + &econet_timer_pcpu); + + if (ret < 0) { + pr_err("%pOFn: IRQ %d setup failed (%d)\n", np, + econet_timer.irq, ret); + goto out_irq_mapping; + } + + cevt_init(np); + + ret =3D cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, + "clockevents/econet/timer:starting", + cevt_init_cpu, NULL); + if (ret < 0) { + pr_err("%pOFn: cpuhp setup failed (%d)\n", np, ret); + goto out_irq_free; + } + + /* Point of no return, do not attempt to tear down after this. */ + /* For clocksource purposes always read clock zero, whatever the CPU */ ret =3D clocksource_mmio_init(reg_count(0), np->name, econet_timer.freq_hz, 301, ECONET_BITS, clocksource_mmio_readl_up); - if (ret) { - pr_err("%pOFn: clocksource_mmio_init failed: %d", np, ret); - return ret; - } - - ret =3D cevt_init(np); - if (ret < 0) - return ret; + if (ret) + pr_err("%pOFn: clocksource_mmio_init failed: %d\n", np, ret); =20 sched_clock_register(sched_clock_read, ECONET_BITS, econet_timer.freq_hz); @@ -212,6 +214,20 @@ static int __init timer_init(struct device_node *np) (econet_timer.freq_hz / 1000) % 1000); =20 return 0; + +out_irq_free: + free_percpu_irq(econet_timer.irq, &econet_timer_pcpu); +out_irq_mapping: + irq_dispose_mapping(econet_timer.irq); +out_membase: + for (int i =3D 0; i < ARRAY_SIZE(econet_timer.membase); i++) { + if (econet_timer.membase[i]) { + iounmap(econet_timer.membase[i]); + econet_timer.membase[i] =3D NULL; + } + } + + return ret; } =20 TIMER_OF_DECLARE(econet_timer_hpt, "econet,en751221-timer", timer_init); --=20 2.39.5 From nobody Fri Oct 23 22:16:11 2026 Received: from mail.cjdns.fr (mail.cjdns.fr [5.135.140.105]) (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 A6EA038399D; Thu, 15 Oct 2026 16:54:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=5.135.140.105 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792083272; cv=none; b=Mpm7W9IPPOeSyrTQE5IDfrbDlSqk6sOthZgTPvrUcK42x9LXLyXruTxVjbHYXA5KEz/bFmEN3hDRRddvrieiY4W6d+YTrdYjTgvRUMArHY03zupXoyN5UrOs3olERao39aleR0llOy0Q/Jb+VMYdv1dySI+OWa+WUMNXeqoubOw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792083272; c=relaxed/simple; bh=x0XMny1qGGl4AJoowktjLCWIaQ/7L5RzSu5rS1V5VRE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=nvysLiueQ24DJBq5JejwNsG/ezoEzX//enou5jFOXGbp+dAsECtvJO+72Kp+BRZTrlLXjYIPNuTRhThKGYPPylWelTjsVoXekKc19Gzgy4POuMCFETNHNn0WM8er1IK1OOTtewL5kbOdCKaXwSa13hoa0b0B0RNjK2/PKHl6qnE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=cjdns.fr; spf=none smtp.mailfrom=cjdns.fr; dkim=pass (2048-bit key) header.d=cjdns.fr header.i=@cjdns.fr header.b=sBzXEYDP; arc=none smtp.client-ip=5.135.140.105 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=cjdns.fr Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=cjdns.fr Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=cjdns.fr header.i=@cjdns.fr header.b="sBzXEYDP" Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 1BFBD5B37D1; Thu, 15 Oct 2026 18:54:15 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cjdns.fr; s=dkim; t=1792083256; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=lRhqM7LAgl/X+6g5+JRRCWTiassQyFmX1v5QtTJrszQ=; b=sBzXEYDPI2L+k0X/53X/CWJ+6LxVMiNcTpp9835drzxi4RUwuW88aeS5/PafrHpdLon5U0 bLZaiR9e1vZK4u7664vv//Hi+zMKwoCZyStglXDxlKAOE+I+NT9AhZYf/smZo1DyK16MBG QPHhNeFK4yNHdL3tEU3eTmlPBT6oKHEwlTxUVIN50wb6RisL9GeOFfs/SNwUPESWMBKs3S gl/KxnUy39KtEmfOi7nre0h7L8WYv6nN3cVkNbIpcUTyy0o2asGirnUx/gdouSb7pUJ0SB pw31pW/Y4t8UPpHRDHk8ZRTBPiaYXdT+BbxkxSzFxYB4IrOEYXLhBGcEdUfKlA== From: Caleb James DeLisle To: linux-mips@vger.kernel.org Cc: conor+dt@kernel.org, daniel.lezcano@kernel.org, devicetree@vger.kernel.org, krzk+dt@kernel.org, linux-kernel@vger.kernel.org, naseefkm@gmail.com, robh@kernel.org, tglx@kernel.org, grandmaster@al2klimov.de, Caleb James DeLisle Subject: [PATCH v11 3/5] clocksource/timer-econet-en751221: Disable IRQ until cevt registered Date: Thu, 15 Oct 2026 16:54:02 +0000 Message-Id: <20261015165404.519741-4-cjd@cjdns.fr> In-Reply-To: <20261015165404.519741-1-cjd@cjdns.fr> References: <20261015165404.519741-1-cjd@cjdns.fr> 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-Last-TLS-Session-Version: TLSv1.3 Content-Type: text/plain; charset="utf-8" Eliminate a race condition where cevt_interrupt may trigger before clockevents_config_and_register has been called, and dev->event_handler is at that point NULL. Additionally, NULL check dev->event_handler in interrupt callback just in case clockevents_config_and_register failed. Signed-off-by: Caleb James DeLisle --- drivers/clocksource/timer-econet-en751221.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/clocksource/timer-econet-en751221.c b/drivers/clocksou= rce/timer-econet-en751221.c index 714702b9ef12..f2c4c1ee0a56 100644 --- a/drivers/clocksource/timer-econet-en751221.c +++ b/drivers/clocksource/timer-econet-en751221.c @@ -75,7 +75,10 @@ static irqreturn_t cevt_interrupt(int irq, void *dev_id) return IRQ_NONE; =20 iowrite32(ioread32(reg_count(cpu)), reg_compare(cpu)); - dev->event_handler(dev); + + if (dev->event_handler) + dev->event_handler(dev); + return IRQ_HANDLED; } =20 @@ -104,12 +107,11 @@ static int cevt_init_cpu(uint cpu) reg =3D ioread32(reg_ctl(cpu)) | ctl_bit_enabled(cpu); iowrite32(reg, reg_ctl(cpu)); =20 - enable_percpu_irq(cd->irq, IRQ_TYPE_NONE); - - /* Do this last because it synchronously configures the timer */ clockevents_config_and_register(cd, econet_timer.freq_hz, ECONET_MIN_DELTA, ECONET_MAX_DELTA); =20 + enable_percpu_irq(cd->irq, IRQ_TYPE_NONE); + return 0; } =20 @@ -178,6 +180,8 @@ static int __init timer_init(struct device_node *np) goto out_membase; } =20 + irq_set_status_flags(econet_timer.irq, IRQ_NOAUTOEN); + ret =3D request_percpu_irq(econet_timer.irq, cevt_interrupt, np->name, &econet_timer_pcpu); =20 --=20 2.39.5 From nobody Fri Oct 23 22:16:11 2026 Received: from mail.cjdns.fr (mail.cjdns.fr [5.135.140.105]) (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 9026F466B58; Thu, 15 Oct 2026 16:54:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=5.135.140.105 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792083272; cv=none; b=NxLVDty/pDvY2CWv/V3irShdTQwGNTWdd2ZEn8ptsOYHizPGU2axo86cN8IuOEwC07OxLBUZei4V7Q7hk5nMVyKKqP4CIPVFK+oblmKtDbJKQbNoOiNWjEqbay+q+PJKlF9QzmoYJPrhdtYDfhQvM/YmYB3Nvu2M9cRMKCGMrVs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792083272; c=relaxed/simple; bh=vJ7yaF/s1PN/Y+AKFOHB8iQZrg/BOIou3eSrh43ytaU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=IIri2nbZ+ws1bk6x4cNl8kChauTsUbVPUTAhVzLL/D9VFQBuFxvqWemuFoMDSVQ7bYl2+dPiPma9Q8RDpq/NN+vWPJ/cWKI1mUZtGc5rTmn6cALOq/j5oRprcwllvTLkevnR3psJSgIW+1HySHydxGDk61moKoZn4b+eqCNGPzw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=cjdns.fr; spf=none smtp.mailfrom=cjdns.fr; dkim=pass (2048-bit key) header.d=cjdns.fr header.i=@cjdns.fr header.b=uUhrrdPI; arc=none smtp.client-ip=5.135.140.105 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=cjdns.fr Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=cjdns.fr Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=cjdns.fr header.i=@cjdns.fr header.b="uUhrrdPI" Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id CE4B45B37FB; Thu, 15 Oct 2026 18:54:16 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cjdns.fr; s=dkim; t=1792083258; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=5S49agrrdRdFjaIYgnVtJdcSozvn6OBmzUxnGJiDdhs=; b=uUhrrdPI45Q9RWApF9KNFBOa+tvFdczyukWZBU6lNZruGA3JvL7qT+H5cShOIB/iBxClJj W8qv9ZDnYLohoR0rvIrJURs/lYbPsqQqv6hi82vLuqZ9bxNbmf291WtTv6FU7A5ySkirGO qd/EazHd0wPJRgC/ALurukic3QN/FX8OqzG2zEvdLI5PiiC2ors652XPgi+XZ+if+laOe5 Z7doRTcXiVCXiJdUPsqbhTejtHzDopaDOPRP2J/SWsWncicSpU83lAUXuHM/H9ivZ3XZjy dJr6CIZq3R+ibYlu+Uc2DpTpKFWYGcpssjIFGRBShEw3rtOBCJ+xqFbl9TObJg== From: Caleb James DeLisle To: linux-mips@vger.kernel.org Cc: conor+dt@kernel.org, daniel.lezcano@kernel.org, devicetree@vger.kernel.org, krzk+dt@kernel.org, linux-kernel@vger.kernel.org, naseefkm@gmail.com, robh@kernel.org, tglx@kernel.org, grandmaster@al2klimov.de, Caleb James DeLisle Subject: [PATCH v11 4/5] clocksource/timer-econet-en751221: Support EN751627 without percpu IRQ Date: Thu, 15 Oct 2026 16:54:03 +0000 Message-Id: <20261015165404.519741-5-cjd@cjdns.fr> In-Reply-To: <20261015165404.519741-1-cjd@cjdns.fr> References: <20261015165404.519741-1-cjd@cjdns.fr> 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-Last-TLS-Session-Version: TLSv1.3 Content-Type: text/plain; charset="utf-8" EN751627 is based on the 1004Kc which uses a different interrupt number for each CPU timer. Support both this and the EN751221 which uses a single percpu interrupt. CPU hotplug path is intentionally unsupported because this CPU timer is part of a legacy MIPS CPU which never had support for it. Signed-off-by: Caleb James DeLisle --- drivers/clocksource/timer-econet-en751221.c | 131 ++++++++++++++++---- 1 file changed, 108 insertions(+), 23 deletions(-) diff --git a/drivers/clocksource/timer-econet-en751221.c b/drivers/clocksou= rce/timer-econet-en751221.c index f2c4c1ee0a56..edb3db3125ce 100644 --- a/drivers/clocksource/timer-econet-en751221.c +++ b/drivers/clocksource/timer-econet-en751221.c @@ -24,7 +24,9 @@ =20 static struct { void __iomem *membase[ECONET_NUM_BLOCKS]; - int irq; + int *irqs; + int num_irqs; + bool is_percpu; u32 freq_hz; } econet_timer __ro_after_init; =20 @@ -102,6 +104,25 @@ static int cevt_init_cpu(uint cpu) struct clock_event_device *cd =3D &per_cpu(econet_timer_pcpu, cpu); u32 reg; =20 + if (!reg_ctl(cpu)) { + pr_err("%s: missing address resource for CPU %d\n", cd->name, + cpu); + return -EINVAL; + } + if (cd->irq <=3D 0) { + pr_err("%s: missing IRQ for CPU %d\n", cd->name, cpu); + return -EINVAL; + } + if (!econet_timer.is_percpu) { + int ret =3D irq_force_affinity(cd->irq, cpumask_of(cpu)); + + if (ret) { + pr_err("%s: failed to set IRQ affinity to CPU %d: %pe\n", + cd->name, cpu, ERR_PTR(ret)); + return ret; + } + } + pr_debug("%s: Setting up clockevent for CPU %d\n", cd->name, cpu); =20 reg =3D ioread32(reg_ctl(cpu)) | ctl_bit_enabled(cpu); @@ -110,7 +131,10 @@ static int cevt_init_cpu(uint cpu) clockevents_config_and_register(cd, econet_timer.freq_hz, ECONET_MIN_DELTA, ECONET_MAX_DELTA); =20 - enable_percpu_irq(cd->irq, IRQ_TYPE_NONE); + if (econet_timer.is_percpu) + enable_percpu_irq(cd->irq, IRQ_TYPE_NONE); + else + enable_irq(cd->irq); =20 return 0; } @@ -141,19 +165,52 @@ static void __init cevt_init(struct device_node *np) CLOCK_EVT_FEAT_C3STOP | CLOCK_EVT_FEAT_PERCPU; cd->set_next_event =3D cevt_set_next_event; - cd->irq =3D econet_timer.irq; cd->cpumask =3D cpumask_of(i); cd->name =3D np->name; =20 - cevt_dev_init(i); + /* + * If not enough IRQs were specified for the CPUs, leave IRQ -1 + * and error in cevt_init_cpu + */ + if (econet_timer.is_percpu) + cd->irq =3D econet_timer.irqs[0]; + else if (i < econet_timer.num_irqs) + cd->irq =3D econet_timer.irqs[i]; + else + cd->irq =3D -1; + + /* + * Tolerate CPUs that could exist but don't. + * Fail in cevt_init_cpu when they try to start. + */ + if (reg_ctl(i) && cd->irq > -1) + cevt_dev_init(i); } } =20 static int __init timer_init(struct device_node *np) { - int num_blocks =3D DIV_ROUND_UP(num_possible_cpus(), 2); + int num_blocks =3D of_address_count(np); + int num_irqs =3D of_irq_count(np); struct clk *clk; - int ret; + int ret, i; + + econet_timer.is_percpu =3D of_device_is_compatible(np, "econet,en751221-t= imer"); + + if (econet_timer.is_percpu && num_irqs !=3D 1) { + pr_err("%pOFn: EN751221 clock must have 1 IRQ not %d\n", np, + num_irqs); + return -EINVAL; + } + if (num_blocks > ARRAY_SIZE(econet_timer.membase)) { + pr_err("%pOFn: Too many regs: max %zd got %d\n", np, + ARRAY_SIZE(econet_timer.membase), num_blocks); + return -EINVAL; + } + if (num_blocks =3D=3D 0) { + pr_err("%pOFn: At least one reg block must be provided\n", np); + return -EINVAL; + } =20 clk =3D of_clk_get(np, 0); if (IS_ERR(clk)) { @@ -164,7 +221,13 @@ static int __init timer_init(struct device_node *np) econet_timer.freq_hz =3D clk_get_rate(clk); clk_put(clk); =20 - for (int i =3D 0; i < num_blocks; i++) { + econet_timer.num_irqs =3D num_irqs; + econet_timer.irqs =3D kcalloc(num_irqs, sizeof(*econet_timer.irqs), + GFP_KERNEL); + if (!econet_timer.irqs) + return -ENOMEM; + + for (i =3D 0; i < num_blocks; i++) { econet_timer.membase[i] =3D of_iomap(np, i); if (!econet_timer.membase[i]) { pr_err("%pOFn: failed to map register [%d]\n", np, i); @@ -173,22 +236,32 @@ static int __init timer_init(struct device_node *np) } } =20 - econet_timer.irq =3D irq_of_parse_and_map(np, 0); - if (econet_timer.irq <=3D 0) { - pr_err("%pOFn: irq_of_parse_and_map failed\n", np); - ret =3D -EINVAL; - goto out_membase; + for (i =3D 0; i < num_irqs; i++) { + econet_timer.irqs[i] =3D irq_of_parse_and_map(np, i); + if (econet_timer.irqs[i] <=3D 0) { + pr_err("%pOFn: failed mapping irq %d\n", np, i); + ret =3D -EINVAL; + goto out_irq_mapping; + } } =20 - irq_set_status_flags(econet_timer.irq, IRQ_NOAUTOEN); - - ret =3D request_percpu_irq(econet_timer.irq, cevt_interrupt, np->name, - &econet_timer_pcpu); - - if (ret < 0) { - pr_err("%pOFn: IRQ %d setup failed (%d)\n", np, - econet_timer.irq, ret); - goto out_irq_mapping; + for (i =3D 0; i < num_irqs; i++) { + irq_set_status_flags(econet_timer.irqs[i], IRQ_NOAUTOEN); + + if (econet_timer.is_percpu) + ret =3D request_percpu_irq(econet_timer.irqs[i], + cevt_interrupt, np->name, + &econet_timer_pcpu); + else + ret =3D request_irq(econet_timer.irqs[i], cevt_interrupt, + IRQF_TIMER | IRQF_NOBALANCING, + np->name, NULL); + + if (ret < 0) { + pr_err("%pOFn: IRQ %d setup failed: %pe\n", np, + i, ERR_PTR(ret)); + goto out_irq_free; + } } =20 cevt_init(np); @@ -220,9 +293,17 @@ static int __init timer_init(struct device_node *np) return 0; =20 out_irq_free: - free_percpu_irq(econet_timer.irq, &econet_timer_pcpu); + while (--i >=3D 0) { + if (econet_timer.is_percpu) + free_percpu_irq(econet_timer.irqs[i], &econet_timer_pcpu); + else + free_irq(econet_timer.irqs[i], NULL); + } out_irq_mapping: - irq_dispose_mapping(econet_timer.irq); + for (i =3D 0; i < num_irqs; i++) { + if (econet_timer.irqs[i] > 0) + irq_dispose_mapping(econet_timer.irqs[i]); + } out_membase: for (int i =3D 0; i < ARRAY_SIZE(econet_timer.membase); i++) { if (econet_timer.membase[i]) { @@ -231,7 +312,11 @@ static int __init timer_init(struct device_node *np) } } =20 + kfree(econet_timer.irqs); + econet_timer.irqs =3D NULL; + return ret; } =20 TIMER_OF_DECLARE(econet_timer_hpt, "econet,en751221-timer", timer_init); +TIMER_OF_DECLARE(econet_timer_en751627, "econet,en751627-timer", timer_ini= t); --=20 2.39.5 From nobody Fri Oct 23 22:16:11 2026 Received: from mail.cjdns.fr (mail.cjdns.fr [5.135.140.105]) (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 50ED95476EA; Thu, 15 Oct 2026 16:54:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=5.135.140.105 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792083280; cv=none; b=msAVURWg1XAIOa4BQg6sUAjFn0sBMiSayWoMBfu+ey+cnCOhU0amp0b9NAgdnrU+MkgjsheZYAfZ/C4KTWghKwbsCfmO9P92jGo94d6qRK5F9hYUkCSEZMNbwh2yx5+U93uSYUwGGHSsdaEePooMJWDbpQDcGFEH+Vf4uQomB28= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792083280; c=relaxed/simple; bh=8B/xTP972nIvHtcMSPD8tKL/H9idus5A5CGIIMszGO4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=cQoXyI0IbhJVVRkyzsMDIJTpfrHg8+oZakuxWMJASd4xKAqN27wd+gtZMyVm58mxFsgPMLsxlZJ/c3rMFXRsX6buHBrjT7i08ARqkHNvtI3lC7/9yFDsIuIVmhZi2+ReCtJ7lLrUi+FxVg11YxUUMindIAeGSTDaBKd/PuMsLmQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=cjdns.fr; spf=none smtp.mailfrom=cjdns.fr; dkim=pass (2048-bit key) header.d=cjdns.fr header.i=@cjdns.fr header.b=fVpB/Lsz; arc=none smtp.client-ip=5.135.140.105 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=cjdns.fr Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=cjdns.fr Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=cjdns.fr header.i=@cjdns.fr header.b="fVpB/Lsz" Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 7BD2C5B2CF1; Thu, 15 Oct 2026 18:54:18 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cjdns.fr; s=dkim; t=1792083259; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=Bo4Pkqkj8MYnxBK3j+0sK35BN5q+7GSDcZpoAAftl5U=; b=fVpB/LszLupa0Oa0/xT5FAbaNNLAJji3h7oL3PBfRdyF5rUtZPDtlAxzKbDLPJdfe9VfVY HFmN1brZkpDE2VijaH9QIy4dFGCH3BRCvx8LjAc2vCMq2oYZPYfLyQbX9o+q+R+PoMtOZc VbiIcj6QXpEzSBiBMbgulnGpxefEGl99LHd6FmO8/KiVmNjPDYkuSEhoWj0oiMG4lHuvJP 8vmqWtg7n7nnB9p26gHpkHhSkBTyhcvkXun01eTlGqI745YL6k4WVWQTadfHR3NdvZng5j YmELPV5+rh3UEN3jLjDzgxKU0+ehNrm9dXC+bhVKLjfgzCtNI+AGFtb0pY+SlQ== From: Caleb James DeLisle To: linux-mips@vger.kernel.org Cc: conor+dt@kernel.org, daniel.lezcano@kernel.org, devicetree@vger.kernel.org, krzk+dt@kernel.org, linux-kernel@vger.kernel.org, naseefkm@gmail.com, robh@kernel.org, tglx@kernel.org, grandmaster@al2klimov.de, Caleb James DeLisle Subject: [PATCH v11 5/5] clocksource/timer-econet-en751221: Do not use NR_CPUS for resource array size Date: Thu, 15 Oct 2026 16:54:04 +0000 Message-Id: <20261015165404.519741-6-cjd@cjdns.fr> In-Reply-To: <20261015165404.519741-1-cjd@cjdns.fr> References: <20261015165404.519741-1-cjd@cjdns.fr> 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-Last-TLS-Session-Version: TLSv1.3 Content-Type: text/plain; charset="utf-8" Each pair of VPEs has one timer block, so the number of blocks is half the number of CPUs on the hardware. However, since NR_CPUS is a configuration, it is possible that it will be less than the number of actual CPUs on the hardware which will cause the array to be too small for the specified DT. Switch to an allocated buffer for storing the iomem resources, as is done for the IRQs. Signed-off-by: Caleb James DeLisle --- drivers/clocksource/timer-econet-en751221.c | 29 ++++++++++++++------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/drivers/clocksource/timer-econet-en751221.c b/drivers/clocksou= rce/timer-econet-en751221.c index edb3db3125ce..9f28cc238372 100644 --- a/drivers/clocksource/timer-econet-en751221.c +++ b/drivers/clocksource/timer-econet-en751221.c @@ -19,11 +19,10 @@ #define ECONET_BITS 32 #define ECONET_MIN_DELTA 0x00001000 #define ECONET_MAX_DELTA GENMASK(ECONET_BITS - 2, 0) -/* 34Kc hardware has 1 block and 1004Kc has 2. */ -#define ECONET_NUM_BLOCKS DIV_ROUND_UP(NR_CPUS, 2) =20 static struct { - void __iomem *membase[ECONET_NUM_BLOCKS]; + void __iomem **membase; + int num_membase; int *irqs; int num_irqs; bool is_percpu; @@ -37,6 +36,10 @@ static DEFINE_PER_CPU(struct clock_event_device, econet_= timer_pcpu); */ static inline void __iomem *reg_ctl(u32 timer_n) { + /* reg_ctl() is used to check if a clock exists */ + if (timer_n >> 1 >=3D econet_timer.num_membase) + return NULL; + return econet_timer.membase[timer_n >> 1]; } =20 @@ -202,11 +205,6 @@ static int __init timer_init(struct device_node *np) num_irqs); return -EINVAL; } - if (num_blocks > ARRAY_SIZE(econet_timer.membase)) { - pr_err("%pOFn: Too many regs: max %zd got %d\n", np, - ARRAY_SIZE(econet_timer.membase), num_blocks); - return -EINVAL; - } if (num_blocks =3D=3D 0) { pr_err("%pOFn: At least one reg block must be provided\n", np); return -EINVAL; @@ -227,6 +225,15 @@ static int __init timer_init(struct device_node *np) if (!econet_timer.irqs) return -ENOMEM; =20 + econet_timer.num_membase =3D num_blocks; + econet_timer.membase =3D kcalloc(num_blocks, + sizeof(*econet_timer.membase), + GFP_KERNEL); + if (!econet_timer.membase) { + ret =3D -ENOMEM; + goto out_kfree_irqs; + } + for (i =3D 0; i < num_blocks; i++) { econet_timer.membase[i] =3D of_iomap(np, i); if (!econet_timer.membase[i]) { @@ -305,13 +312,17 @@ static int __init timer_init(struct device_node *np) irq_dispose_mapping(econet_timer.irqs[i]); } out_membase: - for (int i =3D 0; i < ARRAY_SIZE(econet_timer.membase); i++) { + for (int i =3D 0; i < num_blocks; i++) { if (econet_timer.membase[i]) { iounmap(econet_timer.membase[i]); econet_timer.membase[i] =3D NULL; } } =20 + kfree(econet_timer.membase); + econet_timer.membase =3D NULL; + +out_kfree_irqs: kfree(econet_timer.irqs); econet_timer.irqs =3D NULL; =20 --=20 2.39.5