From nobody Fri Sep 25 03:16:17 2026 Received: from pdx-out-002.esa.us-west-2.outbound.mail-perimeter.amazon.com (pdx-out-002.esa.us-west-2.outbound.mail-perimeter.amazon.com [44.246.1.125]) (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 85697379C26; Sat, 19 Sep 2026 17:12:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=44.246.1.125 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789837932; cv=none; b=BoC2WmqD16Conf2l4p3ukEDKkI1NwcKQzmSvaUwsi2Q5m6j7FwqbfGaCX04lelwd28/H7mYPPNoZsi4oBusE51b5w3p4ergnlyC/B43DWJEbTeaFj2n34wkKW0U4GvwK5Re6w9IePAJWLTp815oMNTJovZQOFuI3NaH4Ax6tE/g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789837932; c=relaxed/simple; bh=3gMhXjYjJ18ytp21x/302M108LwhKkA9men9GIEkGQU=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=PDX9LxFoND3mabl188UwDMwnIC2h8uqd8liiUpG2t88dJhtxVkGuaqZQY9WKm4sI+089XidzOO8oDzVv13Hurtgc2deG+c2cxt6wZE5qplRu3ipo/5PKZICS0pdS2aUoKS4ipnsr8WSWolr6KlJ1cEqmLgNX1a+HfrrF2aSjjIs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amazon.com; spf=pass smtp.mailfrom=amazon.com; dkim=pass (2048-bit key) header.d=amazon.com header.i=@amazon.com header.b=VOP1wPoh; arc=none smtp.client-ip=44.246.1.125 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amazon.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=amazon.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=amazon.com header.i=@amazon.com header.b="VOP1wPoh" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.com; i=@amazon.com; q=dns/txt; s=amazoncorp2; t=1789837930; x=1821373930; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=T3ndLXuPaRWRNNorRS1lXsRqCoiSkUTLuVESHyvcFuY=; b=VOP1wPohoWwv7CNOSr4klLsKjPmuT82Hji1dESduXHJaVfiYYZjaBiMq yMNHNIjg29XOqe8RI6t/AXj45fE5fy2BLILSE+IzUgWi1RUEmHn+URFmG 4pdURzRbaC6FOSFmBKBMvPc7qUPoTxQLbV4hrGpD6p7lVz/wO51IY8hwb BU2k7YZtJfQgxDbBAno4RHY08Wq3CI9fQCToPXpOu1fK5fe3SZODAaX+L N6bohgJkPlQCShWQGscwwp6a0IDBjOAdxNq6yx80ZOpInJjb2cwzYCBS7 0pJNcNEGM+KQD5FhJhU41duasl0s4FabKASVim2ApE8KsiB309ufAEkJs A==; X-CSE-ConnectionGUID: fuBJYiU4QT209lvc5CCeUQ== X-CSE-MsgGUID: jS0nVMj7RsuXGAoJw4VP1w== X-IronPort-AV: E=Sophos;i="6.27,111,1787011200"; d="scan'208";a="29116693" Received: from ip-10-5-12-219.us-west-2.compute.internal (HELO smtpout.naws.us-west-2.prod.farcaster.email.amazon.dev) ([10.5.12.219]) by internal-pdx-out-002.esa.us-west-2.outbound.mail-perimeter.amazon.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Sep 2026 17:12:08 +0000 Received: from EX19MTAUWA001.ant.amazon.com [205.251.233.182:26008] by smtpin.naws.us-west-2.prod.farcaster.email.amazon.dev [10.0.49.70:2525] with esmtp (Farcaster) id 26b3a8a7-7408-41ac-95eb-1bb124c263e4; Sat, 19 Sep 2026 17:12:08 +0000 (UTC) X-Farcaster-Flow-ID: 26b3a8a7-7408-41ac-95eb-1bb124c263e4 Received: from EX19D001UWA001.ant.amazon.com (10.13.138.214) by EX19MTAUWA001.ant.amazon.com (10.250.64.217) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) id 15.2.2562.46; Sat, 19 Sep 2026 17:12:07 +0000 Received: from dev-dsk-farbere-1a-46ecabed.eu-west-1.amazon.com (172.19.116.181) by EX19D001UWA001.ant.amazon.com (10.13.138.214) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) id 15.2.2562.49; Sat, 19 Sep 2026 17:12:05 +0000 From: Eliav Farber To: Rodolfo Giometti , Rob Herring , Krzysztof Kozlowski , Conor Dooley CC: Linus Walleij , Bartosz Golaszewski , Fabio Estevam , Andrew Morton , Takashi Sakamoto , Eliav Farber , , , , "Bartosz Golaszewski" Subject: [PATCH v4 1/3] pps: clients: gpio: propagate probe error codes Date: Sat, 19 Sep 2026 17:11:55 +0000 Message-ID: <20260919171157.5502-2-farbere@amazon.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260917075611.47881-1-farbere@amazon.com> References: <20260917075611.47881-1-farbere@amazon.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-ClientProxiedBy: EX19D035UWA002.ant.amazon.com (10.13.139.60) To EX19D001UWA001.ant.amazon.com (10.13.138.214) Content-Type: text/plain; charset="utf-8" On the two probe error paths that map and request the interrupt, probe overwrote the error from gpiod_to_irq() and request_threaded_irq() with a hardcoded -EINVAL, hiding meaningful codes such as -EBUSY, -ENOMEM or -EPROBE_DEFER from the caller. The request_threaded_irq() failure message also logged the IRQ number but not the errno. Return the actual error code from both paths, and add the errno to the request_threaded_irq() failure message. Fixes: 161520451dfa ("pps: new client driver using GPIO") Signed-off-by: Eliav Farber Reviewed-by: Bartosz Golaszewski --- Changes in v4: - Add Fixes: 161520451dfa ("pps: new client driver using GPIO") and Bartosz Golaszewski's Reviewed-by. The hardcoded -EINVAL on both error paths predates 4461d65176b4 (which only switched gpio_to_irq() to gpiod_to_irq() and left those returns as context), so the tag points at the original driver rather than the descriptor conversion Changes in v3: - New patch, split out of the pinctrl change: while converting the probe error paths to a goto, Takashi Sakamoto noted that the hardcoded -EINVAL discards the real gpiod_to_irq()/request_threaded_irq() error, so fix that separately first drivers/pps/clients/pps-gpio.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/pps/clients/pps-gpio.c b/drivers/pps/clients/pps-gpio.c index 73ec2c7335e5..038c55c5f7d4 100644 --- a/drivers/pps/clients/pps-gpio.c +++ b/drivers/pps/clients/pps-gpio.c @@ -165,7 +165,7 @@ static int pps_gpio_probe(struct platform_device *pdev) ret =3D gpiod_to_irq(data->gpio_pin); if (ret < 0) { dev_err(dev, "failed to map GPIO to IRQ: %d\n", ret); - return -EINVAL; + return ret; } data->irq =3D ret; =20 @@ -197,8 +197,8 @@ static int pps_gpio_probe(struct platform_device *pdev) data->info.name, data); if (ret) { pps_unregister_source(data->pps); - dev_err(dev, "failed to acquire IRQ %d\n", data->irq); - return -EINVAL; + dev_err(dev, "failed to acquire IRQ %d: %d\n", data->irq, ret); + return ret; } =20 dev_dbg(&data->pps->dev, "Registered IRQ %d as PPS source\n", --=20 2.47.3 From nobody Fri Sep 25 03:16:17 2026 Received: from pdx-out-014.esa.us-west-2.outbound.mail-perimeter.amazon.com (pdx-out-014.esa.us-west-2.outbound.mail-perimeter.amazon.com [35.83.148.184]) (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 7404C3D9524; Thu, 17 Sep 2026 07:56:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=35.83.148.184 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789631791; cv=none; b=pb+FQPpR2CBhFtNEAHw4uhmbofe4/SHFmrlCXRdqaRMc2p4RMJ+lmIrf4X9H+PqLneM0bBr/LzX3+R+pHt5rr+5D2OVFkCk5N5gexnKFeKShML9D6XCRzlGouI1ulwGs71oUpmz3PhXpbH1KgC2NJodesZJ18t2xAF/4jyH0E0g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789631791; c=relaxed/simple; bh=WZ/Bea7rwxOqc5xuRmAqZ9zK/KsMvwZC82BbYSthMfQ=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=kYT/8a9e4fjfVe8Yh0B99wI48Vx8ycugP/OfeFyyS8uNWMMeyOYPJEuFmsu4c9JZN2Qbu7BOfoCS6haYP3VcGt4rUhgE6zDoS01pzaZuI5InbCnan7yxocri5hGV4qAIGw2qjKEWMjBqG7nYE1cN3Sa57o9yVi4827dFSN1pv9E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amazon.com; spf=pass smtp.mailfrom=amazon.com; dkim=pass (2048-bit key) header.d=amazon.com header.i=@amazon.com header.b=mcFPhC/r; arc=none smtp.client-ip=35.83.148.184 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amazon.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=amazon.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=amazon.com header.i=@amazon.com header.b="mcFPhC/r" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.com; i=@amazon.com; q=dns/txt; s=amazoncorp2; t=1789631789; x=1821167789; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=xuUW1wDEOR1JTwRDOLRr2wDuGAZXd2rLzI0jO308ljo=; b=mcFPhC/rBtrzZKNEtq6n93ksfbQ0mNaI/iSK9btqW1ktnakkt6gvQA2R Q1u9UDzs7/iANA9ppHtFniDMFnpwHRPJuyj644t2HExiPqNpoZc583TP5 ZNqFi191c+0CnGiDUVvXOGDYxgK8NZxhzP/4EAMZCqEiCF8stllduDNIq Cdaq0Cm/jn8jf95705jJHtXsEtvq0RPpf3ApALRpSi2Z/DhjFj2hrcl9a mt6ux4TOHa543Zjmstjo6GXLJk4Aee8y+UozKXjB2fIhYB4E99iqQdX+v dilESKle0qMNqyRT00YBNe59ZajIILFU+Ww+GsDVocUmu3G8NG/z0YO0j A==; X-CSE-ConnectionGUID: cF6XnPu5QNS/g2lzk33Wxw== X-CSE-MsgGUID: JId47upJT7+bFz+ElLF1Bw== X-IronPort-AV: E=Sophos;i="6.27,103,1787011200"; d="scan'208";a="28697243" Received: from ip-10-5-9-48.us-west-2.compute.internal (HELO smtpout.naws.us-west-2.prod.farcaster.email.amazon.dev) ([10.5.9.48]) by internal-pdx-out-014.esa.us-west-2.outbound.mail-perimeter.amazon.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Sep 2026 07:56:24 +0000 Received: from EX19MTAUWC002.ant.amazon.com [205.251.233.51:24358] by smtpin.naws.us-west-2.prod.farcaster.email.amazon.dev [10.0.16.195:2525] with esmtp (Farcaster) id b4cb260b-eb9e-4c95-8112-b1f3dc184fde; Thu, 17 Sep 2026 07:56:24 +0000 (UTC) X-Farcaster-Flow-ID: b4cb260b-eb9e-4c95-8112-b1f3dc184fde Received: from EX19D001UWA001.ant.amazon.com (10.13.138.214) by EX19MTAUWC002.ant.amazon.com (10.250.64.143) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) id 15.2.2562.46; Thu, 17 Sep 2026 07:56:24 +0000 Received: from dev-dsk-farbere-1a-46ecabed.eu-west-1.amazon.com (172.19.116.181) by EX19D001UWA001.ant.amazon.com (10.13.138.214) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) id 15.2.2562.46; Thu, 17 Sep 2026 07:56:22 +0000 From: Eliav Farber To: Rodolfo Giometti , Rob Herring , Krzysztof Kozlowski , Conor Dooley CC: Linus Walleij , Bartosz Golaszewski , Fabio Estevam , Andrew Morton , Takashi Sakamoto , Eliav Farber , , , Subject: [PATCH v3 1/3] pps: clients: gpio: propagate probe error codes Date: Thu, 17 Sep 2026 07:56:09 +0000 Message-ID: <20260917075611.47881-2-farbere@amazon.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260917075611.47881-1-farbere@amazon.com> References: <20260916182641.9768-1-farbere@amazon.com> <20260917075611.47881-1-farbere@amazon.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-ClientProxiedBy: EX19D036UWB001.ant.amazon.com (10.13.139.133) To EX19D001UWA001.ant.amazon.com (10.13.138.214) Content-Type: text/plain; charset="utf-8" On the two probe error paths that map and request the interrupt, probe overwrote the error from gpiod_to_irq() and request_threaded_irq() with a hardcoded -EINVAL, hiding meaningful codes such as -EBUSY, -ENOMEM or -EPROBE_DEFER from the caller. The request_threaded_irq() failure message also logged the IRQ number but not the errno. Return the actual error code from both paths, and add the errno to the request_threaded_irq() failure message. Signed-off-by: Eliav Farber Reviewed-by: Bartosz Golaszewski --- Changes in v3: - New patch, split out of the pinctrl change: while converting the probe error paths to a goto, Takashi Sakamoto noted that the hardcoded -EINVAL discards the real gpiod_to_irq()/request_threaded_irq() error, so fix that separately first drivers/pps/clients/pps-gpio.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/pps/clients/pps-gpio.c b/drivers/pps/clients/pps-gpio.c index 73ec2c7335e5..038c55c5f7d4 100644 --- a/drivers/pps/clients/pps-gpio.c +++ b/drivers/pps/clients/pps-gpio.c @@ -165,7 +165,7 @@ static int pps_gpio_probe(struct platform_device *pdev) ret =3D gpiod_to_irq(data->gpio_pin); if (ret < 0) { dev_err(dev, "failed to map GPIO to IRQ: %d\n", ret); - return -EINVAL; + return ret; } data->irq =3D ret; =20 @@ -197,8 +197,8 @@ static int pps_gpio_probe(struct platform_device *pdev) data->info.name, data); if (ret) { pps_unregister_source(data->pps); - dev_err(dev, "failed to acquire IRQ %d\n", data->irq); - return -EINVAL; + dev_err(dev, "failed to acquire IRQ %d: %d\n", data->irq, ret); + return ret; } =20 dev_dbg(&data->pps->dev, "Registered IRQ %d as PPS source\n", --=20 2.47.3 From nobody Fri Sep 25 03:16:17 2026 Received: from pdx-out-015.esa.us-west-2.outbound.mail-perimeter.amazon.com (pdx-out-015.esa.us-west-2.outbound.mail-perimeter.amazon.com [50.112.246.219]) (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 0FCAA37E5E9; Sat, 19 Sep 2026 17:12:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=50.112.246.219 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789837934; cv=none; b=bSdPiqMnNzVOJXvnROl5x4VAxqFp7ySXv8XhOf9G5MJXvDdfXqPt/M8C/spbkgVA5vv+ZDpq8Yk2KR1wIJ7OBLAlF5WsGkWYpU5UJ4JmCiNUfaUTHRAMhh659rJg3WxOrQmZkbX6euc9h4wTSHlRy7fydBFx+hs6JXHrgNulekk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789837934; c=relaxed/simple; bh=pmcieg6oScmEYU6/MyQ9Mj7cF07ICbZ9Av6qPsPrE1E=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=MJzzMtRplrIIWzZYvhOCh6ntWsqMxMFJHPU4+4b/nkIV9wjXsKwf+TAgITE60+EZUvDM9CXUmkb4OAQLUxkjeAkYEo1Rz/M6wStJ8uDUA2ErH1SXwCowGWj9la9pQsGFvAV5/hfQGjlxQ0k5OBy4szUXCie+Sq7hBc6o/ppjPq4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amazon.com; spf=pass smtp.mailfrom=amazon.com; dkim=pass (2048-bit key) header.d=amazon.com header.i=@amazon.com header.b=sRQyWpus; arc=none smtp.client-ip=50.112.246.219 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amazon.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=amazon.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=amazon.com header.i=@amazon.com header.b="sRQyWpus" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.com; i=@amazon.com; q=dns/txt; s=amazoncorp2; t=1789837933; x=1821373933; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=eohaOZGCuEICBV1DzPfZR6vfi8a+kP71azJvuPSBEO0=; b=sRQyWpusofX5zvzqlCivVa2wdqdAaPjWFoy961ya5RPmKhN7z2jTLhYM uPclA1XJfH5hTBRPlfq5yNXOxEj8oyV9WjLYWCeBai5w/lDc4x0xnqZe/ 0FvopRjlv3M2qkWcsvDRkXhwpBgtyBNzDMDZLNWsAfjvU4V4fw6ouiAbf abfp58euxohTBMqtq2Z1NBK9QWrcw3FaGyyZh2tuS0fEkoIqx5AhLSLdf moa8wz8zpKHut/URLqDCpswOs9qim669rkJloukJ4QYkyEJd1/3G+6TxV mO6R+2WQSQ70cFjJuS+1JtEpauxM8u7hMEDS4GxUAY0FoSiPtDzvoCvwe g==; X-CSE-ConnectionGUID: 1fId1l+JRE2Agv4Ad+Q73w== X-CSE-MsgGUID: t5o0DuLGTGWrgpGe4XraEw== X-IronPort-AV: E=Sophos;i="6.27,111,1787011200"; d="scan'208";a="28893888" Received: from ip-10-5-6-203.us-west-2.compute.internal (HELO smtpout.naws.us-west-2.prod.farcaster.email.amazon.dev) ([10.5.6.203]) by internal-pdx-out-015.esa.us-west-2.outbound.mail-perimeter.amazon.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Sep 2026 17:12:10 +0000 Received: from EX19MTAUWC001.ant.amazon.com [205.251.233.53:18300] by smtpin.naws.us-west-2.prod.farcaster.email.amazon.dev [10.0.1.232:2525] with esmtp (Farcaster) id 817fbdde-ebe3-49f4-98f9-7c018f8aa1a5; Sat, 19 Sep 2026 17:12:10 +0000 (UTC) X-Farcaster-Flow-ID: 817fbdde-ebe3-49f4-98f9-7c018f8aa1a5 Received: from EX19D001UWA001.ant.amazon.com (10.13.138.214) by EX19MTAUWC001.ant.amazon.com (10.250.64.174) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) id 15.2.2562.46; Sat, 19 Sep 2026 17:12:09 +0000 Received: from dev-dsk-farbere-1a-46ecabed.eu-west-1.amazon.com (172.19.116.181) by EX19D001UWA001.ant.amazon.com (10.13.138.214) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) id 15.2.2562.49; Sat, 19 Sep 2026 17:12:07 +0000 From: Eliav Farber To: Rodolfo Giometti , Rob Herring , Krzysztof Kozlowski , Conor Dooley CC: Linus Walleij , Bartosz Golaszewski , Fabio Estevam , Andrew Morton , Takashi Sakamoto , Eliav Farber , , , Subject: [PATCH v4 2/3] dt-bindings: pps: pps-gpio: document optional pinctrl states Date: Sat, 19 Sep 2026 17:11:56 +0000 Message-ID: <20260919171157.5502-3-farbere@amazon.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260917075611.47881-1-farbere@amazon.com> References: <20260917075611.47881-1-farbere@amazon.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-ClientProxiedBy: EX19D035UWA002.ant.amazon.com (10.13.139.60) To EX19D001UWA001.ant.amazon.com (10.13.138.214) Content-Type: text/plain; charset="utf-8" When the PPS input GPIO is routed through a pin controller, a board may need to mux those pins to a different function while pps-gpio is not driving PPS (for example after the driver is unbound or across a kexec). Document the optional "default" and "inactive" pinctrl-names and show both in the example. The "default" state selects the PPS/GPIO function and is applied by the driver core before probe; the optional "inactive" state, when present, describes the mux to restore when the driver is unbound or the system is shut down. "default" is pinctrl-0, matching the implicit ordering the pinctrl core already assigns it, and "inactive" is pinctrl-1; the driver looks each state up by name. Signed-off-by: Eliav Farber --- Changes in v4: - Rework per Rob Herring: do not express the ordering in prose; use an ordered "items" list ("default" then "inactive") with minItems: 1, since pinctrl-0 is already implicitly "default" and its position is fixed. This also fixes the "['default', 'inactive'] is too long" dt_binding_check error seen on v3. Reword the commit message accordingly Changes in v3: - Do not constrain pinctrl-names to a fixed ["default", "inactive"] tuple. The driver looks the states up by name, so "inactive" may appear in any position and other states may coexist; only require (via "contains") that a "default" state exists, and reword the description accordingly Changes in v2: - Rename the released state from "idle" to "inactive" .../devicetree/bindings/pps/pps-gpio.yaml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/pps/pps-gpio.yaml b/Document= ation/devicetree/bindings/pps/pps-gpio.yaml index 383a838744eb..61b5de6724ea 100644 --- a/Documentation/devicetree/bindings/pps/pps-gpio.yaml +++ b/Documentation/devicetree/bindings/pps/pps-gpio.yaml @@ -28,6 +28,17 @@ properties: description: Indicates a falling edge assert, when present. Rising edg= e if absent. type: boolean =20 + pinctrl-names: + description: + The "default" state selects the PPS/GPIO function and is applied by = the + driver core before probe. The optional "inactive" state, when presen= t, + is selected when the driver is unbound or the system is shut down, + handing the pins back to their alternate function. + minItems: 1 + items: + - const: default + - const: inactive + required: - compatible - gpios @@ -40,8 +51,9 @@ examples: =20 pps { compatible =3D "pps-gpio"; - pinctrl-names =3D "default"; + pinctrl-names =3D "default", "inactive"; pinctrl-0 =3D <&pinctrl_pps>; + pinctrl-1 =3D <&pinctrl_pps_inactive>; gpios =3D <&gpio1 26 GPIO_ACTIVE_HIGH>; assert-falling-edge; echo-gpios =3D <&gpio1 27 GPIO_ACTIVE_HIGH>; --=20 2.47.3 From nobody Fri Sep 25 03:16:17 2026 Received: from pdx-out-004.esa.us-west-2.outbound.mail-perimeter.amazon.com (pdx-out-004.esa.us-west-2.outbound.mail-perimeter.amazon.com [44.246.77.92]) (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 19D14393DEB; Thu, 17 Sep 2026 07:56:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=44.246.77.92 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789631791; cv=none; b=kZ0DlLJnt29a7RQzRVvFbnGWljxJuwqpdQpE//HNlw+B6/Qa2jLRJN+myUoua0W7RaYly5o5ERGVr9YMuhC7EpL1nHQkEjg8TmsBJwTC6gtUMaAusSOca6HZI41aGfUd7ZgCpPZtsjB/xG1gESgMYQWXLBQapnQUbsOoKJsjObs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789631791; c=relaxed/simple; bh=iD2HBRQ5r3nw3b/1wVWMJvemxibCM5gCh/wT+mRK2kE=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=XasV7BUVbF+GC+4d64e3wkIsDOwrUM2rWKkMSvhlo15986DtZ/A5KeMMte4Rf/6qnKW6OMpfAhAgPYDf65MxRFT0PMbxFVHd+EFwKJnrrAUjb+t3dpgidsbtnLkGQ31boTkwyr8yDZCCHBr/JpO5xtQS0m6oACB216mk14x3yy4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amazon.com; spf=pass smtp.mailfrom=amazon.com; dkim=pass (2048-bit key) header.d=amazon.com header.i=@amazon.com header.b=c8fUss1m; arc=none smtp.client-ip=44.246.77.92 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amazon.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=amazon.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=amazon.com header.i=@amazon.com header.b="c8fUss1m" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.com; i=@amazon.com; q=dns/txt; s=amazoncorp2; t=1789631790; x=1821167790; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=AiXMnY0Rb7NMl/cA11mu1ttg59pAvJjYYaMy9DrlCfE=; b=c8fUss1mO+mpG26/16WIujLIOzXqAvCYnB9cg3yfdm4n4o6wTrxsVA3c dZBsGfeAYHx43gSw1fjWhieRS419l1+mVdIwBG/dSBO0xWNC7usAYx3qX YxZ7Htqx6dv88mvEAnhVZES+UYexiVM3lhHx1yhCJbQTU9bfdvnDad1cB o+udzUqUpvyVStBa9xWFu0V1Vf3tYZSo2JnGJcw4HSGPlkTAcu/gr+j1B HuCAF/LrXMlMVTYqxA/C5o7sDoCvzScSQY+YaNaf4eOwRSdWVP0yA4o8e /QcMfxfSf6KL1do+EytCa71EVbEAMWu87tdZip5yI+vt5K+22oY64L4D/ Q==; X-CSE-ConnectionGUID: DWWoWfMyTTuvEFsjOTBJSw== X-CSE-MsgGUID: aoO1aD/ZRSCpDKN4gFdyxQ== X-IronPort-AV: E=Sophos;i="6.27,103,1787011200"; d="scan'208";a="28900764" Received: from ip-10-5-6-203.us-west-2.compute.internal (HELO smtpout.naws.us-west-2.prod.farcaster.email.amazon.dev) ([10.5.6.203]) by internal-pdx-out-004.esa.us-west-2.outbound.mail-perimeter.amazon.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Sep 2026 07:56:27 +0000 Received: from EX19MTAUWA001.ant.amazon.com [205.251.233.182:25397] by smtpin.naws.us-west-2.prod.farcaster.email.amazon.dev [10.0.16.195:2525] with esmtp (Farcaster) id 84a1b1b3-96e7-4f6f-8425-9790c103fd27; Thu, 17 Sep 2026 07:56:26 +0000 (UTC) X-Farcaster-Flow-ID: 84a1b1b3-96e7-4f6f-8425-9790c103fd27 Received: from EX19D001UWA001.ant.amazon.com (10.13.138.214) by EX19MTAUWA001.ant.amazon.com (10.250.64.217) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) id 15.2.2562.46; Thu, 17 Sep 2026 07:56:26 +0000 Received: from dev-dsk-farbere-1a-46ecabed.eu-west-1.amazon.com (172.19.116.181) by EX19D001UWA001.ant.amazon.com (10.13.138.214) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) id 15.2.2562.46; Thu, 17 Sep 2026 07:56:24 +0000 From: Eliav Farber To: Rodolfo Giometti , Rob Herring , Krzysztof Kozlowski , Conor Dooley CC: Linus Walleij , Bartosz Golaszewski , Fabio Estevam , Andrew Morton , Takashi Sakamoto , Eliav Farber , , , Subject: [PATCH v3 2/3] dt-bindings: pps: pps-gpio: document optional pinctrl states Date: Thu, 17 Sep 2026 07:56:10 +0000 Message-ID: <20260917075611.47881-3-farbere@amazon.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260917075611.47881-1-farbere@amazon.com> References: <20260916182641.9768-1-farbere@amazon.com> <20260917075611.47881-1-farbere@amazon.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-ClientProxiedBy: EX19D036UWB001.ant.amazon.com (10.13.139.133) To EX19D001UWA001.ant.amazon.com (10.13.138.214) Content-Type: text/plain; charset="utf-8" When the PPS input GPIO is routed through a pin controller, a board may need to mux those pins to a different function while pps-gpio is not driving PPS (for example after the driver is unbound or across a kexec). Document the optional "default" and "inactive" pinctrl-names and show both in the example. The "default" state selects the PPS/GPIO function and is applied by the driver core before probe; the optional "inactive" state, when present, describes the mux to restore when the driver is unbound or the system is shut down. The driver looks the states up by name, so "inactive" may appear in any position; it only requires that a "default" state also exists. Signed-off-by: Eliav Farber --- Changes in v3: - Do not constrain pinctrl-names to a fixed ["default", "inactive"] tuple. The driver looks the states up by name, so "inactive" may appear in any position and other states may coexist; only require (via "contains") that a "default" state exists, and reword the description accordingly Changes in v2: - Rename the released state from "idle" to "inactive" .../devicetree/bindings/pps/pps-gpio.yaml | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/pps/pps-gpio.yaml b/Document= ation/devicetree/bindings/pps/pps-gpio.yaml index 383a838744eb..db6ecb17cb54 100644 --- a/Documentation/devicetree/bindings/pps/pps-gpio.yaml +++ b/Documentation/devicetree/bindings/pps/pps-gpio.yaml @@ -28,6 +28,19 @@ properties: description: Indicates a falling edge assert, when present. Rising edg= e if absent. type: boolean =20 + pinctrl-names: + description: + When the PPS input is muxed through a pin controller, the standard + "default" state selects the PPS/GPIO function and is applied by the + driver core before probe. If a state named "inactive" is also presen= t, + it is selected when the driver is unbound or the system is shut down, + handing the pins back to their alternate function. The "inactive" + state, if used, requires a "default" state; its position among the + names does not matter. + minItems: 1 + contains: + const: default + required: - compatible - gpios @@ -40,8 +53,9 @@ examples: =20 pps { compatible =3D "pps-gpio"; - pinctrl-names =3D "default"; + pinctrl-names =3D "default", "inactive"; pinctrl-0 =3D <&pinctrl_pps>; + pinctrl-1 =3D <&pinctrl_pps_inactive>; gpios =3D <&gpio1 26 GPIO_ACTIVE_HIGH>; assert-falling-edge; echo-gpios =3D <&gpio1 27 GPIO_ACTIVE_HIGH>; --=20 2.47.3 From nobody Fri Sep 25 03:16:17 2026 Received: from pdx-out-015.esa.us-west-2.outbound.mail-perimeter.amazon.com (pdx-out-015.esa.us-west-2.outbound.mail-perimeter.amazon.com [50.112.246.219]) (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 D81BC38422D; Sat, 19 Sep 2026 17:12:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=50.112.246.219 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789837937; cv=none; b=Xf97Jzc1RiI37blaK6rLRebz5/aS43F6+4HczHJxkJLJj/c8781unyquGuqOc1OD75vJvuH3pr2oYdfXOxzN2yKJugWbmwFcuBBVMvAYu2bTogLEOT1Pr+1+kYZlMJkPZsbmHvSy2faq0qnLmA/sEREd0bmqbHsNQN7ShDw+89U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789837937; c=relaxed/simple; bh=ElZm/+cPs6llZQZgkiq4P+Itb+vrYf+i+K1xOm7pdK4=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=ADwQEvRIoecPJTfG9sCQolZAsLFf6T+B4uSoRT6Vd2FFN2pPevRzs3+6bWLi65I64hHSYCwMHHtXhmkGS5IBgOn2czC9PRdIJXyL8GzUGV92YbI2/EWVXWUkApHfRjdELy3zMo6JpOQudGqMHwt3DSqUZvYiz8FQE2cvcYxZqQw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amazon.com; spf=pass smtp.mailfrom=amazon.com; dkim=pass (2048-bit key) header.d=amazon.com header.i=@amazon.com header.b=EmO4KorS; arc=none smtp.client-ip=50.112.246.219 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amazon.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=amazon.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=amazon.com header.i=@amazon.com header.b="EmO4KorS" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.com; i=@amazon.com; q=dns/txt; s=amazoncorp2; t=1789837934; x=1821373934; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Xk3Cf5sxeVxRgOYE+M2NuTsaVOgz6g9f+X0fkr1UOlk=; b=EmO4KorSbzFg6+k5UF7+DjHfpU1T16vmcuxsbSa/TJcqyAh6zV8WrbkV 9R1z+sv4RoZdUOFsXhChOYfqlQl7mr5G2BrqDDI+geIc5J8nHoxJm4tQt ovDm7BCfvWipNxeipPLo4HRPKmJkvC85HA5M1cgXPSE2awEGJcVu8dSWC pBagzS6ZGAfnLB1fRRCYGSLCjoGiiHSMhJnE6Sx9K77/wHl1GrBuLocR7 q0tlVUE2T/jy6ASvMyAKQcW5YLJ51BL4iNpQJqHfcDWhPsijVRPwh55an 0JFHRKHgMPrhUzZ45W9evj1Yk+RazUqR23HIb5UcckX2T1DlFw5KDYDU2 A==; X-CSE-ConnectionGUID: BpDGjYurTJGhkDm0o94R3A== X-CSE-MsgGUID: 6WOIRLGDQ064akDxxyX6vw== X-IronPort-AV: E=Sophos;i="6.27,111,1787011200"; d="scan'208";a="28893891" Received: from ip-10-5-6-203.us-west-2.compute.internal (HELO smtpout.naws.us-west-2.prod.farcaster.email.amazon.dev) ([10.5.6.203]) by internal-pdx-out-015.esa.us-west-2.outbound.mail-perimeter.amazon.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Sep 2026 17:12:12 +0000 Received: from EX19MTAUWB002.ant.amazon.com [205.251.233.48:21429] by smtpin.naws.us-west-2.prod.farcaster.email.amazon.dev [10.0.49.70:2525] with esmtp (Farcaster) id 516d28cf-35ed-4d12-a153-00440b5ff091; Sat, 19 Sep 2026 17:12:12 +0000 (UTC) X-Farcaster-Flow-ID: 516d28cf-35ed-4d12-a153-00440b5ff091 Received: from EX19D001UWA001.ant.amazon.com (10.13.138.214) by EX19MTAUWB002.ant.amazon.com (10.250.64.231) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) id 15.2.2562.46; Sat, 19 Sep 2026 17:12:12 +0000 Received: from dev-dsk-farbere-1a-46ecabed.eu-west-1.amazon.com (172.19.116.181) by EX19D001UWA001.ant.amazon.com (10.13.138.214) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) id 15.2.2562.49; Sat, 19 Sep 2026 17:12:09 +0000 From: Eliav Farber To: Rodolfo Giometti , Rob Herring , Krzysztof Kozlowski , Conor Dooley CC: Linus Walleij , Bartosz Golaszewski , Fabio Estevam , Andrew Morton , Takashi Sakamoto , Eliav Farber , , , Subject: [PATCH v4 3/3] pps: clients: gpio: release pins to an inactive state on remove and shutdown Date: Sat, 19 Sep 2026 17:11:57 +0000 Message-ID: <20260919171157.5502-4-farbere@amazon.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260917075611.47881-1-farbere@amazon.com> References: <20260917075611.47881-1-farbere@amazon.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-ClientProxiedBy: EX19D035UWA002.ant.amazon.com (10.13.139.60) To EX19D001UWA001.ant.amazon.com (10.13.138.214) Content-Type: text/plain; charset="utf-8" Some boards route the PPS input GPIO through a pin controller and need to mux it to another function when pps-gpio is not driving PPS. The driver core applies the "default" pinctrl state before probe, so the pins are muxed for GPIO/PPS use while the driver is bound. Nothing, however, hands the pins back when the driver is unbound or the system is shut down, so they stay stuck in the GPIO function for whatever runs next, kexec included. Look up an optional "inactive" pinctrl state in probe via devm_pinctrl_get() and pinctrl_lookup_state(), and select it with pinctrl_select_state() in remove() and shutdown(). The state is looked up and selected by the driver itself rather than reusing the runtime-PM "idle"/"sleep" states, so its meaning is unambiguous and it does not depend on CONFIG_PM. Boards that do not describe an "inactive" state are unaffected. Since "inactive" is only meaningful as the mux to restore after the core-applied "default" state, reject an "inactive" state that is not paired with a "default" one rather than releasing pins that were never put into a defined PPS state. The mux must not change while something can still drive the pins. On shutdown() the requested IRQ and the echo timer would otherwise outlive the mux change -- device_shutdown() is not the end of the road, the kernel keeps running to load and start the kexec image -- so a timer callback or the PPS handler could poke a line that by then belongs to another function. Tear down in the same order as remove(): free_irq() and timer_delete_sync() first, and the mux change last. shutdown() does not unregister the PPS source, which is a remove-time concern. Signed-off-by: Eliav Farber --- Changes in v4: - No functional change. Raising an open question on the probe-failure path for maintainer guidance rather than changing it (Sashiko [Medium] on v3 3/3): a probe that fails before pps_gpio_get_pins() has run (devm_kzalloc() or pps_gpio_setup()) returns without going through err_release_pins, so the pins are left in the core-applied "default" state rather than "inactive". Note the pins are physically muxed to "default" by the driver core before probe(), and devres release on a failed probe frees the pinctrl handle without selecting a prior state, so the "default" mux persists. Options: A. Move pps_gpio_get_pins() to the top of probe and route the pps_gpio_setup() failure through err_release_pins too, so every path the driver can act on restores "inactive". The devm_kzalloc() failure is inherently before the driver holds any pinctrl handle, so no option can cover it in the driver. B. Keep as-is: treat "inactive" as a successful-ownership concern. A probe that never looked up the state never took the pins, so leaving the long-standing core-applied "default" is acceptable. C. As A, but keep the release helper's NULL guard so it is robust regardless of ordering. I lean towards B; happy to implement A/C if uniform failure paths are preferred. Changes in v3: - Treat -ENODEV from devm_pinctrl_get() (a DT device without a "pinctrl-0" property) as "no pinctrl", not a probe failure; keep propagating everything else, e.g. -EPROBE_DEFER - Restore the "inactive" mux on probe failure too: route the error paths after pps_gpio_get_pins() through a new err_release_pins label so a failed probe does not leave the pins stuck in the "default" state - Warn if pinctrl_select_state() fails to apply the "inactive" state rather than silently ignoring the error (pps_gpio_release_pins() now takes the struct device to log against) - Trim and de-duplicate the added comments Changes in v2: - Rename the released state from "idle" to "inactive" - Look the state up in the driver with devm_pinctrl_get() + pinctrl_lookup_state() + pinctrl_select_state() instead of pinctrl_pm_select_idle_state(), removing the CONFIG_PM dependency - Fix shutdown() to free_irq() and timer_delete_sync() before the mux change, matching remove(), so no IRQ or timer callback can drive a pin after it has been handed back - Require a "default" state whenever "inactive" is present and reject the mismatch drivers/pps/clients/pps-gpio.c | 100 ++++++++++++++++++++++++++++++++- 1 file changed, 97 insertions(+), 3 deletions(-) diff --git a/drivers/pps/clients/pps-gpio.c b/drivers/pps/clients/pps-gpio.c index 038c55c5f7d4..2ee8fba8520c 100644 --- a/drivers/pps/clients/pps-gpio.c +++ b/drivers/pps/clients/pps-gpio.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -30,6 +31,8 @@ struct pps_gpio_device_data { struct gpio_desc *gpio_pin; /* GPIO port descriptors */ struct gpio_desc *echo_pin; struct timer_list echo_timer; /* timer to reset echo active state */ + struct pinctrl *pinctrl; /* pin control handle */ + struct pinctrl_state *pins_inactive; /* pins released when unbound */ bool assert_falling_edge; unsigned int echo_active_ms; /* PPS echo active duration */ unsigned long echo_timeout; /* timer timeout value in jiffies */ @@ -96,6 +99,66 @@ static void pps_gpio_echo_timer_callback(struct timer_li= st *t) gpiod_set_value(info->echo_pin, 0); } =20 +/* + * Look up the optional "inactive" pinctrl state. It requires a "default" + * state (applied by the driver core before probe) and is rejected without + * one. Absent pinctrl, or an absent "inactive" state, is not an error. + */ +static int pps_gpio_get_pins(struct device *dev) +{ + struct pps_gpio_device_data *data =3D dev_get_drvdata(dev); + struct pinctrl_state *pins_default; + + data->pinctrl =3D devm_pinctrl_get(dev); + if (IS_ERR(data->pinctrl)) { + /* + * A DT device without "pinctrl-0" yields -ENODEV, which + * is not an error here; propagate anything else. + */ + if (PTR_ERR(data->pinctrl) =3D=3D -ENODEV) { + data->pinctrl =3D NULL; + return 0; + } + return dev_err_probe(dev, PTR_ERR(data->pinctrl), + "failed to get pinctrl\n"); + } + + /* The "inactive" state is optional. */ + data->pins_inactive =3D pinctrl_lookup_state(data->pinctrl, "inactive"); + if (IS_ERR(data->pins_inactive)) { + data->pins_inactive =3D NULL; + return 0; + } + + /* "inactive" requires a "default" state to return from. */ + pins_default =3D pinctrl_lookup_state(data->pinctrl, "default"); + if (IS_ERR(pins_default)) + return dev_err_probe(dev, PTR_ERR(pins_default), + "\"inactive\" pinctrl state requires a \"default\" state\n"); + + return 0; +} + +/* + * Restore the "inactive" pinctrl state, handing the pins back to whatever + * function uses them while pps-gpio is not driving PPS. This undoes the + * "default" state the driver core applied before probe. A no-op for boards + * that describe no "inactive" state. + */ +static void pps_gpio_release_pins(struct device *dev) +{ + struct pps_gpio_device_data *data =3D dev_get_drvdata(dev); + int ret; + + if (!data->pins_inactive) + return; + + ret =3D pinctrl_select_state(data->pinctrl, data->pins_inactive); + if (ret) + dev_warn(dev, "failed to select inactive pinctrl state: %d\n", + ret); +} + static int pps_gpio_setup(struct device *dev) { struct pps_gpio_device_data *data =3D dev_get_drvdata(dev); @@ -161,11 +224,16 @@ static int pps_gpio_probe(struct platform_device *pde= v) if (ret) return ret; =20 + /* pinctrl setup (optional states) */ + ret =3D pps_gpio_get_pins(dev); + if (ret) + return ret; + /* IRQ setup */ ret =3D gpiod_to_irq(data->gpio_pin); if (ret < 0) { dev_err(dev, "failed to map GPIO to IRQ: %d\n", ret); - return ret; + goto err_release_pins; } data->irq =3D ret; =20 @@ -187,7 +255,8 @@ static int pps_gpio_probe(struct platform_device *pdev) if (IS_ERR(data->pps)) { dev_err(dev, "failed to register IRQ %d as PPS source\n", data->irq); - return PTR_ERR(data->pps); + ret =3D PTR_ERR(data->pps); + goto err_release_pins; } =20 /* register IRQ interrupt handler */ @@ -198,13 +267,18 @@ static int pps_gpio_probe(struct platform_device *pde= v) if (ret) { pps_unregister_source(data->pps); dev_err(dev, "failed to acquire IRQ %d: %d\n", data->irq, ret); - return ret; + goto err_release_pins; } =20 dev_dbg(&data->pps->dev, "Registered IRQ %d as PPS source\n", data->irq); =20 return 0; + +err_release_pins: + /* Restore the inactive mux on probe failure; safe to do last here. */ + pps_gpio_release_pins(dev); + return ret; } =20 static void pps_gpio_remove(struct platform_device *pdev) @@ -216,9 +290,28 @@ static void pps_gpio_remove(struct platform_device *pd= ev) timer_delete_sync(&data->echo_timer); /* reset echo pin in any case */ gpiod_set_value(data->echo_pin, 0); + /* release the pins last, once nothing can drive them */ + pps_gpio_release_pins(&pdev->dev); dev_info(&pdev->dev, "removed IRQ %d as PPS source\n", data->irq); } =20 +static void pps_gpio_shutdown(struct platform_device *pdev) +{ + struct pps_gpio_device_data *data =3D platform_get_drvdata(pdev); + + /* + * The kernel keeps running after device_shutdown() (e.g. to load and + * start a kexec image), so quiesce the hardware before touching the + * mux: free the IRQ and stop the echo timer first, then release the + * pins last, so no callback can drive a pin after it is handed back. + * The PPS source is left registered; that is a remove-time concern. + */ + free_irq(data->irq, data); + timer_delete_sync(&data->echo_timer); + gpiod_set_value(data->echo_pin, 0); + pps_gpio_release_pins(&pdev->dev); +} + static const struct of_device_id pps_gpio_dt_ids[] =3D { { .compatible =3D "pps-gpio", }, { /* sentinel */ } @@ -228,6 +321,7 @@ MODULE_DEVICE_TABLE(of, pps_gpio_dt_ids); static struct platform_driver pps_gpio_driver =3D { .probe =3D pps_gpio_probe, .remove =3D pps_gpio_remove, + .shutdown =3D pps_gpio_shutdown, .driver =3D { .name =3D PPS_GPIO_NAME, .of_match_table =3D pps_gpio_dt_ids, --=20 2.47.3 From nobody Fri Sep 25 03:16:17 2026 Received: from pdx-out-004.esa.us-west-2.outbound.mail-perimeter.amazon.com (pdx-out-004.esa.us-west-2.outbound.mail-perimeter.amazon.com [44.246.77.92]) (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 B88CF3D6CD4; Thu, 17 Sep 2026 07:56:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=44.246.77.92 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789631798; cv=none; b=glcSusXhSXcTFcB7GcbV0pBIcRMu5ncZtEnLThUiDvf/hEIbg/gmCM7+WO9yJpp1u/msj2C1a1Mhco0pzWCy16+5z9WmR/vEa8Z7lkjUB9rR+FO8vcXMJ7+x0x3dzh6uA+Wq9Acgq3hk96Le31MYpKqB0p/I6vSdg3m9Z8OK8sY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789631798; c=relaxed/simple; bh=RR2aHzLqgo4LX0nym8CkvNcAqiJip5DllFnOQJ0cHq0=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=t3GVU2MQz5Owo3mM+MB8UpKVHqM0D2xoSWhUq5N+ND+ONXmqVg+w1RL1wtETQfpAi+odQj5WmAGuiJg/O5V6GxOXmvsiZEAWjPDFxNQ3m7dBeUYncos7eVefc9jjvk2fEww3pu2utgo6Y0OgeFVo4HBAzr5UeOyc7Aqy9hdr74Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amazon.com; spf=pass smtp.mailfrom=amazon.com; dkim=pass (2048-bit key) header.d=amazon.com header.i=@amazon.com header.b=QjTzE/96; arc=none smtp.client-ip=44.246.77.92 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amazon.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=amazon.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=amazon.com header.i=@amazon.com header.b="QjTzE/96" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.com; i=@amazon.com; q=dns/txt; s=amazoncorp2; t=1789631791; x=1821167791; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Fm5FFfmTZuWJ7PoLJRZDVLb+zJTaooCYDjM1eXo4/KM=; b=QjTzE/96z18SJI9VEYtnLcE4ozhQ4mFFF7LU8O0FLyJ9NTWSmPPmrssz 4XJ0SOVmYsdZzq5M8xLEbbLNkIRqAoiqJ2mDxwoWfVy1DBxrMbhTPspou 6GNu6ZGJf29ujfRbpUjs/qFb6TouXp20SWWAHJklT/GEDh6+x4B3J0X0J BXKOVb7lRshqGpnUr+8ICUDdOtB8T7+5InoM4KuWnUz/8kA5jbLbw92/B h9ZqnnbaMMJAuLUwU4ZH5hwoNFbgeJWSEF17tIftPLzqnelUrhrVDcHYu JFBPd1m+UmMgLDghpsv8fzAZQQ/wDoaEc8AVgv4BRVNRCQh7k4ZZ+/+ti g==; X-CSE-ConnectionGUID: fANv7i4TQVaIxJXMkLGArA== X-CSE-MsgGUID: E2AFzm3uSIu/Sm09QyfD3Q== X-IronPort-AV: E=Sophos;i="6.27,103,1787011200"; d="scan'208";a="28900766" Received: from ip-10-5-6-203.us-west-2.compute.internal (HELO smtpout.naws.us-west-2.prod.farcaster.email.amazon.dev) ([10.5.6.203]) by internal-pdx-out-004.esa.us-west-2.outbound.mail-perimeter.amazon.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Sep 2026 07:56:28 +0000 Received: from EX19MTAUWC001.ant.amazon.com [205.251.233.53:11786] by smtpin.naws.us-west-2.prod.farcaster.email.amazon.dev [10.0.35.200:2525] with esmtp (Farcaster) id cd2a0efd-5e7b-441f-a7d7-867217ee62a2; Thu, 17 Sep 2026 07:56:28 +0000 (UTC) X-Farcaster-Flow-ID: cd2a0efd-5e7b-441f-a7d7-867217ee62a2 Received: from EX19D001UWA001.ant.amazon.com (10.13.138.214) by EX19MTAUWC001.ant.amazon.com (10.250.64.174) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) id 15.2.2562.46; Thu, 17 Sep 2026 07:56:28 +0000 Received: from dev-dsk-farbere-1a-46ecabed.eu-west-1.amazon.com (172.19.116.181) by EX19D001UWA001.ant.amazon.com (10.13.138.214) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) id 15.2.2562.46; Thu, 17 Sep 2026 07:56:26 +0000 From: Eliav Farber To: Rodolfo Giometti , Rob Herring , Krzysztof Kozlowski , Conor Dooley CC: Linus Walleij , Bartosz Golaszewski , Fabio Estevam , Andrew Morton , Takashi Sakamoto , Eliav Farber , , , Subject: [PATCH v3 3/3] pps: clients: gpio: release pins to an inactive state on remove and shutdown Date: Thu, 17 Sep 2026 07:56:11 +0000 Message-ID: <20260917075611.47881-4-farbere@amazon.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260917075611.47881-1-farbere@amazon.com> References: <20260916182641.9768-1-farbere@amazon.com> <20260917075611.47881-1-farbere@amazon.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-ClientProxiedBy: EX19D036UWB001.ant.amazon.com (10.13.139.133) To EX19D001UWA001.ant.amazon.com (10.13.138.214) Content-Type: text/plain; charset="utf-8" Some boards route the PPS input GPIO through a pin controller and need to mux it to another function when pps-gpio is not driving PPS. The driver core applies the "default" pinctrl state before probe, so the pins are muxed for GPIO/PPS use while the driver is bound. Nothing, however, hands the pins back when the driver is unbound or the system is shut down, so they stay stuck in the GPIO function for whatever runs next, kexec included. Look up an optional "inactive" pinctrl state in probe via devm_pinctrl_get() and pinctrl_lookup_state(), and select it with pinctrl_select_state() in remove() and shutdown(). The state is looked up and selected by the driver itself rather than reusing the runtime-PM "idle"/"sleep" states, so its meaning is unambiguous and it does not depend on CONFIG_PM. Boards that do not describe an "inactive" state are unaffected. Since "inactive" is only meaningful as the mux to restore after the core-applied "default" state, reject an "inactive" state that is not paired with a "default" one rather than releasing pins that were never put into a defined PPS state. The mux must not change while something can still drive the pins. On shutdown() the requested IRQ and the echo timer would otherwise outlive the mux change -- device_shutdown() is not the end of the road, the kernel keeps running to load and start the kexec image -- so a timer callback or the PPS handler could poke a line that by then belongs to another function. Tear down in the same order as remove(): free_irq() and timer_delete_sync() first, and the mux change last. shutdown() does not unregister the PPS source, which is a remove-time concern. Signed-off-by: Eliav Farber --- Changes in v3: - Treat -ENODEV from devm_pinctrl_get() (a DT device without a "pinctrl-0" property) as "no pinctrl", not a probe failure; keep propagating everything else, e.g. -EPROBE_DEFER - Restore the "inactive" mux on probe failure too: route the error paths after pps_gpio_get_pins() through a new err_release_pins label so a failed probe does not leave the pins stuck in the "default" state - Warn if pinctrl_select_state() fails to apply the "inactive" state rather than silently ignoring the error (pps_gpio_release_pins() now takes the struct device to log against) - Trim and de-duplicate the added comments Changes in v2: - Rename the released state from "idle" to "inactive" - Look the state up in the driver with devm_pinctrl_get() + pinctrl_lookup_state() + pinctrl_select_state() instead of pinctrl_pm_select_idle_state(), removing the CONFIG_PM dependency - Fix shutdown() to free_irq() and timer_delete_sync() before the mux change, matching remove(), so no IRQ or timer callback can drive a pin after it has been handed back - Require a "default" state whenever "inactive" is present and reject the mismatch drivers/pps/clients/pps-gpio.c | 100 ++++++++++++++++++++++++++++++++- 1 file changed, 97 insertions(+), 3 deletions(-) diff --git a/drivers/pps/clients/pps-gpio.c b/drivers/pps/clients/pps-gpio.c index 038c55c5f7d4..2ee8fba8520c 100644 --- a/drivers/pps/clients/pps-gpio.c +++ b/drivers/pps/clients/pps-gpio.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -30,6 +31,8 @@ struct pps_gpio_device_data { struct gpio_desc *gpio_pin; /* GPIO port descriptors */ struct gpio_desc *echo_pin; struct timer_list echo_timer; /* timer to reset echo active state */ + struct pinctrl *pinctrl; /* pin control handle */ + struct pinctrl_state *pins_inactive; /* pins released when unbound */ bool assert_falling_edge; unsigned int echo_active_ms; /* PPS echo active duration */ unsigned long echo_timeout; /* timer timeout value in jiffies */ @@ -96,6 +99,66 @@ static void pps_gpio_echo_timer_callback(struct timer_li= st *t) gpiod_set_value(info->echo_pin, 0); } =20 +/* + * Look up the optional "inactive" pinctrl state. It requires a "default" + * state (applied by the driver core before probe) and is rejected without + * one. Absent pinctrl, or an absent "inactive" state, is not an error. + */ +static int pps_gpio_get_pins(struct device *dev) +{ + struct pps_gpio_device_data *data =3D dev_get_drvdata(dev); + struct pinctrl_state *pins_default; + + data->pinctrl =3D devm_pinctrl_get(dev); + if (IS_ERR(data->pinctrl)) { + /* + * A DT device without "pinctrl-0" yields -ENODEV, which + * is not an error here; propagate anything else. + */ + if (PTR_ERR(data->pinctrl) =3D=3D -ENODEV) { + data->pinctrl =3D NULL; + return 0; + } + return dev_err_probe(dev, PTR_ERR(data->pinctrl), + "failed to get pinctrl\n"); + } + + /* The "inactive" state is optional. */ + data->pins_inactive =3D pinctrl_lookup_state(data->pinctrl, "inactive"); + if (IS_ERR(data->pins_inactive)) { + data->pins_inactive =3D NULL; + return 0; + } + + /* "inactive" requires a "default" state to return from. */ + pins_default =3D pinctrl_lookup_state(data->pinctrl, "default"); + if (IS_ERR(pins_default)) + return dev_err_probe(dev, PTR_ERR(pins_default), + "\"inactive\" pinctrl state requires a \"default\" state\n"); + + return 0; +} + +/* + * Restore the "inactive" pinctrl state, handing the pins back to whatever + * function uses them while pps-gpio is not driving PPS. This undoes the + * "default" state the driver core applied before probe. A no-op for boards + * that describe no "inactive" state. + */ +static void pps_gpio_release_pins(struct device *dev) +{ + struct pps_gpio_device_data *data =3D dev_get_drvdata(dev); + int ret; + + if (!data->pins_inactive) + return; + + ret =3D pinctrl_select_state(data->pinctrl, data->pins_inactive); + if (ret) + dev_warn(dev, "failed to select inactive pinctrl state: %d\n", + ret); +} + static int pps_gpio_setup(struct device *dev) { struct pps_gpio_device_data *data =3D dev_get_drvdata(dev); @@ -161,11 +224,16 @@ static int pps_gpio_probe(struct platform_device *pde= v) if (ret) return ret; =20 + /* pinctrl setup (optional states) */ + ret =3D pps_gpio_get_pins(dev); + if (ret) + return ret; + /* IRQ setup */ ret =3D gpiod_to_irq(data->gpio_pin); if (ret < 0) { dev_err(dev, "failed to map GPIO to IRQ: %d\n", ret); - return ret; + goto err_release_pins; } data->irq =3D ret; =20 @@ -187,7 +255,8 @@ static int pps_gpio_probe(struct platform_device *pdev) if (IS_ERR(data->pps)) { dev_err(dev, "failed to register IRQ %d as PPS source\n", data->irq); - return PTR_ERR(data->pps); + ret =3D PTR_ERR(data->pps); + goto err_release_pins; } =20 /* register IRQ interrupt handler */ @@ -198,13 +267,18 @@ static int pps_gpio_probe(struct platform_device *pde= v) if (ret) { pps_unregister_source(data->pps); dev_err(dev, "failed to acquire IRQ %d: %d\n", data->irq, ret); - return ret; + goto err_release_pins; } =20 dev_dbg(&data->pps->dev, "Registered IRQ %d as PPS source\n", data->irq); =20 return 0; + +err_release_pins: + /* Restore the inactive mux on probe failure; safe to do last here. */ + pps_gpio_release_pins(dev); + return ret; } =20 static void pps_gpio_remove(struct platform_device *pdev) @@ -216,9 +290,28 @@ static void pps_gpio_remove(struct platform_device *pd= ev) timer_delete_sync(&data->echo_timer); /* reset echo pin in any case */ gpiod_set_value(data->echo_pin, 0); + /* release the pins last, once nothing can drive them */ + pps_gpio_release_pins(&pdev->dev); dev_info(&pdev->dev, "removed IRQ %d as PPS source\n", data->irq); } =20 +static void pps_gpio_shutdown(struct platform_device *pdev) +{ + struct pps_gpio_device_data *data =3D platform_get_drvdata(pdev); + + /* + * The kernel keeps running after device_shutdown() (e.g. to load and + * start a kexec image), so quiesce the hardware before touching the + * mux: free the IRQ and stop the echo timer first, then release the + * pins last, so no callback can drive a pin after it is handed back. + * The PPS source is left registered; that is a remove-time concern. + */ + free_irq(data->irq, data); + timer_delete_sync(&data->echo_timer); + gpiod_set_value(data->echo_pin, 0); + pps_gpio_release_pins(&pdev->dev); +} + static const struct of_device_id pps_gpio_dt_ids[] =3D { { .compatible =3D "pps-gpio", }, { /* sentinel */ } @@ -228,6 +321,7 @@ MODULE_DEVICE_TABLE(of, pps_gpio_dt_ids); static struct platform_driver pps_gpio_driver =3D { .probe =3D pps_gpio_probe, .remove =3D pps_gpio_remove, + .shutdown =3D pps_gpio_shutdown, .driver =3D { .name =3D PPS_GPIO_NAME, .of_match_table =3D pps_gpio_dt_ids, --=20 2.47.3