From nobody Mon Jun 15 13:39:43 2026 Received: from mail-wm1-f47.google.com (mail-wm1-f47.google.com [209.85.128.47]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 233DB3CC9F6 for ; Fri, 10 Apr 2026 14:07:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775830026; cv=none; b=lyLMEFirm8cj0Xp2A48xYBZ0zr//hANo/tCcM9wl59/Xv8LOpOUqUJsN/tKYD437rX9EW/Y2pFX3r0UPtJKrj37+3HWTOTx6DkMMjpHMFmXogZGIUFGcBXRBukziqk+10xeWxuYNgyXPK6VF71II5x9Nd5JYWnYtj4r+yVxuwHo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775830026; c=relaxed/simple; bh=s8hb9g9paEXCL92IjeHXdzwCUqKzbSkiTf1BUkd/xRM=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=tBrYPwzr1ae852rUQ6JudtpvNlYqVB40gbu8H6AOf9ubuUVVZwEghZsc34IlQwlfC1b/rmMRiO4CuCpN4Rl7gouz5LnXudo+u23wA2NcoeGX6LJmZVzXFLLOirR4OoIalRObA92E5THIvhQNjgcZRvxcsOtQnLkhosoq0yboGNE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=suse.com; spf=pass smtp.mailfrom=suse.com; dkim=pass (2048-bit key) header.d=suse.com header.i=@suse.com header.b=b3wQiR2K; arc=none smtp.client-ip=209.85.128.47 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=suse.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=suse.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=suse.com header.i=@suse.com header.b="b3wQiR2K" Received: by mail-wm1-f47.google.com with SMTP id 5b1f17b1804b1-488ba6366a7so25727265e9.0 for ; Fri, 10 Apr 2026 07:07:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=google; t=1775830023; x=1776434823; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=b4GNYk08qocSjMmlFQv9r58JfdZ961NOnAm9HRPCHcY=; b=b3wQiR2KcNM3YgYKGgNs39nI/DXdq5JQKehikBrE6OsKsryBv/H0JJtSfkfTqRdYhv +vj3EOGx0wtZEYkQGzQRnwuCIoWqEb8X6HZ+A0XIDoyaMn9C9hGIBhtEGOu160a5ASFP Dynex2IjxTxdJ7BSVPb7EHqb663WXwRY8TSu2oM5J+QMSavRV3MZFzv6cd857fwbk4e3 IIMKotzFN/aXVpFu6ijMVJmbltUCxS6T8aV8Z9pZftLqbJi1gTIdowfC13k0HYt7J6Jl IUCoOEwUv5qNC8pm95z9H9C5yQHlRonlMPBRNYHxL1X7cXYQJVyTGyr3yyAKLsl3sub0 s3Qw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775830023; x=1776434823; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=b4GNYk08qocSjMmlFQv9r58JfdZ961NOnAm9HRPCHcY=; b=aE1DSQfHBpWqdxi64viXS1cpl1V7CAIz7TcBr8imvJhs9KS6K8ALBJaXXPvB1X6SnT wVJzbYVpmH+Hi+UoXs4t7KI9ZlbJxGf/tqAWPakuLyWE/M0OiWIk+Atpa3paEtOH6B9M XxoM1nJhklAZQ6Q85LuLBGbZnP3QGallgFPm2f3EwPCHbs7AKpRHW+RKmOA9jWr4yodS 8lnkZxS+2Olsj8GvPdhnrv/qDv4j+U959m6hIOLF/1D1RxYpaY1NiTmjHFclhxMkeeXd oury+fnPUO9LTsZHTlUss3jJDQwcu6r3ByxAXXCSIAvjnQNwcHtfk/QcsAFWdUmu1xx+ cbhA== X-Forwarded-Encrypted: i=1; AJvYcCXX3VSZeOjLjLJ6+5nZew3YqC+iVHNqnny/XxF8eO2b2yG9fvRThvsgxTVxePiCA3MnaQh98rYRmgFcNsk=@vger.kernel.org X-Gm-Message-State: AOJu0Ywb5x9GZpy2s/fJYohpxuIz60VC3BFMVQk4NSRooRObMZMd4x3T /4I6A0zMfSO2HEV1WNi1uH2aY+i86cd9u5XGSdH2P0Q1HZk6xjL8klIizpMW1yXIaxQ= X-Gm-Gg: AeBDiev5wAmvYkFUgF6tiziUhz2/lz8tV0swrtSX2It8tiWpwlFQ/jTU6uQ+EHN4DTO Aw8W8OtNmBfqVd7NSUtXHl9MFzMqsV/oOFTZJIDZp1HCDd3hvqLK4WtvHY8DV11q6eK75u2/fdh KoATi0lQoAaa0SWzxO4vnr5cvnCFNYOh65F4oOdPG9h+DhE8cmJHjIjUvcvMFYfP/dtFq/EaGSy iuaSNNV6DrUQXr/xXRtXwnEBe0miN+7XXDetXwwHGvCl0x8sw3krRfVlVKMlRqe0tS4WWlYtl/F 4beisXUYEGYkJ+b3BD7NV7twV2mTwYAo05C2PkauypeYj8ZI7DsZNI4/frhBIEfpvvFe1zcA85c FbScyUxp1411rzQXQ6qVRCqfhd0JivXI6yHOWi3AthliEqPgnSTko7XFmVwWV/8c3ojW3eRW2R8 P+VlIH1sPIymG5njYjfjHgos17pmefWqsO8K5fvmxayC+gzOglpA== X-Received: by 2002:a05:600c:1391:b0:487:5c0:671f with SMTP id 5b1f17b1804b1-488d67e6a48mr46582625e9.9.1775830023400; Fri, 10 Apr 2026 07:07:03 -0700 (PDT) Received: from localhost (93-41-3-120.ip79.fastwebnet.it. [93.41.3.120]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-488d67b46ffsm27847985e9.6.2026.04.10.07.07.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Apr 2026 07:07:01 -0700 (PDT) From: Andrea della Porta To: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= , linux-pwm@vger.kernel.org, Rob Herring , Krzysztof Kozlowski , Conor Dooley , Florian Fainelli , Broadcom internal kernel review list , Andrea della Porta , devicetree@vger.kernel.org, linux-rpi-kernel@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Naushir Patuck , Stanimir Varbanov , mbrugger@suse.com Subject: [PATCH v2 1/3] dt-bindings: pwm: Add Raspberry Pi RP1 PWM controller Date: Fri, 10 Apr 2026 16:09:57 +0200 Message-ID: <6f0fa1a817b5af5040b652320daa7268297932a9.1775829499.git.andrea.porta@suse.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: References: 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 Content-Type: text/plain; charset="utf-8" From: Naushir Patuck Add the devicetree binding documentation for the PWM controller found in the Raspberry Pi RP1 chipset. Signed-off-by: Naushir Patuck Co-developed-by: Stanimir Varbanov Signed-off-by: Stanimir Varbanov Signed-off-by: Andrea della Porta Reviewed-by: Krzysztof Kozlowski --- .../bindings/pwm/raspberrypi,rp1-pwm.yaml | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 Documentation/devicetree/bindings/pwm/raspberrypi,rp1-p= wm.yaml diff --git a/Documentation/devicetree/bindings/pwm/raspberrypi,rp1-pwm.yaml= b/Documentation/devicetree/bindings/pwm/raspberrypi,rp1-pwm.yaml new file mode 100644 index 0000000000000..6f8461d0454f7 --- /dev/null +++ b/Documentation/devicetree/bindings/pwm/raspberrypi,rp1-pwm.yaml @@ -0,0 +1,54 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pwm/raspberrypi,rp1-pwm.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Raspberry Pi RP1 PWM controller + +maintainers: + - Naushir Patuck + +allOf: + - $ref: pwm.yaml# + +description: | + The PWM peripheral is a flexible waveform generator with a + variety of operational modes. It has the following features: + - four independent output channels + - 32-bit counter widths + - Seven output generation modes + - Optional per-channel output inversion + - Optional duty-cycle data FIFO with DMA support + - Optional sigma-delta noise shaping engine + Serves as a fan speed provider to other nodes for a PWM-connected + fan using shared registers (syscon). + +properties: + compatible: + const: raspberrypi,rp1-pwm + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + "#pwm-cells": + const: 3 + +required: + - compatible + - reg + - clocks + +unevaluatedProperties: false + +examples: + - | + pwm@98000 { + compatible =3D "raspberrypi,rp1-pwm"; + reg =3D <0x98000 0x100>; + clocks =3D <&rp1_clocks 17>; + #pwm-cells =3D <3>; + }; --=20 2.35.3 From nobody Mon Jun 15 13:39:43 2026 Received: from mail-wm1-f52.google.com (mail-wm1-f52.google.com [209.85.128.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0DC743CD8B6 for ; Fri, 10 Apr 2026 14:07:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775830028; cv=none; b=bbCrbxQsc2eLqbuUd/6LVP6IPm1gXMJSfWyHM8OtuG0mPBqBmWE+oVw39R7qDCDx6O7yiLBdu5xNWBXem2BYr/3uDYJhuPFoAP8GOuxBcl+RIwPj5dRwkJlayS1d6Yk4qC1XL0QNze3QPSWzEFpPWqd6y9qhDLQBt1mm7gcLZRY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775830028; c=relaxed/simple; bh=jfTieWK0v3wB1u8q3YW98anrGlNYzfKbPTAkMW7RJG4=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=FdgQuYbRS7QOM0QnSUY0R0DkWYkjLUOEJYw+nRljMBXhaJZ3qrajoQDX6GlUgeJx/nqTMqZ4nhHthGkqmbTL+pIdebfJaqmpfS9K9SZf9AG6FLSz6CCN2LfDVZy108vEzETViHuiRNKVdzhOsdyqKN93psN5yZ7LRipC0xzfQcQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=suse.com; spf=pass smtp.mailfrom=suse.com; dkim=pass (2048-bit key) header.d=suse.com header.i=@suse.com header.b=C0pZfns8; arc=none smtp.client-ip=209.85.128.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=suse.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=suse.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=suse.com header.i=@suse.com header.b="C0pZfns8" Received: by mail-wm1-f52.google.com with SMTP id 5b1f17b1804b1-488aa77a06eso32947095e9.0 for ; Fri, 10 Apr 2026 07:07:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=google; t=1775830025; x=1776434825; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=SFH9HkuqRORBaQ1DhfyanXw+/L8CLUaspI4xBL/ZFQc=; b=C0pZfns8WsfgNKKUXXTsZSgKv8aDFe1jkJ+twDWMFl3Ay5flYiFltdDT+Ki42J6ee0 osj8G15CMpB8vQlUFcaDTCQmG2VdfXZ6JNAupsQe1lD+QhVprYAyKbI5EHEI+jzqGaaU TCe6Y01q4/MNKkyDk1xsMUv2q65SlV8/axzeyOVTVti1lJL///gYMJDygn0otMjOWyDN +juAL295lBFoFGJ6xGnwfIidvau3lCEztWoK/GdVs3kcW/0myN7d+Bl2nFCW7AeKAIpO huax9GNnTDmOQMDdL4tNDR5KMDamwyByhp2cIPHIAqw5hllfZBuxUZH2h+OkJcz3/kNF DQOw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775830025; x=1776434825; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=SFH9HkuqRORBaQ1DhfyanXw+/L8CLUaspI4xBL/ZFQc=; b=Pv0m7phzUiYHFki1qejaSjw6ah3ghUsD4GGEfMXfeluzUXRdV3bRg9+E753kG9aye1 IsssDvxHoCP+1xPIgxZv1cvm/uJlWwE22KoTjqJg+Xn2rPAIolOEPo7f3WylYVfPStvC W+rTYSkIdRCMj+BbLMkV3D26xXjoXskm1LwN6t1K4S4Yngwko3X4Vfok7PCJijjxqibj lMKysguatpai+yU7wRY+oo5SLvgrJT2TdnIMhNKyaOvnAscvM6pMfwrTU7eyJUsA5hCF Jr0tqQvlgC2goxRmvMnUt4w2XoCPmEEm7EPVQp2LwgGaAnHT420YXzvzkoBvb9IVQl7w w7Mg== X-Forwarded-Encrypted: i=1; AJvYcCWAfpiB70QKnq/cOX3CJDCw0+jz4tzPvKOsoPdU8KfhFiVBcI+VoaowZ9Wo+di4lqr0UJtyhOOTS402zwY=@vger.kernel.org X-Gm-Message-State: AOJu0YzazD6BG1IORHelPa+j3Pw1RzD9lYkWNS/okETZue1GRldxQOUP SCgx8mUUdtJQTAbxWXacD4sI3IJKMynRhw5IcBej1mC7vZ+lygqDGs0YJXhiaMdCFHw= X-Gm-Gg: AeBDietSoEg5UV8G+CC/nZXsbb1xVpQFe1/0iS8I0RcEnHUDldTkK9nVmvwuUudr/Nq ZhW1oK4E2VG8PHnIiuIFNGaQPaaqV7ejyLoGfPR7hKpV+DzM5PoVLXM4m3UVTHS5c+g8yOKBiBy ihyWTjKl6zkVsWChZJMHlII07vM97t9aMBjWYodLCPSnpTGTNbe8l0WKbAowP3U52lp6lJBYOE6 0KESwbBMXGcj0VFp1RP48d0cKIrxpqYW7bt8QrmNARZXbAyO3SDlR2iZTR9eoehtzNs/ii5oM70 3p/2mdUOnET2q3Kyx1niQIlUaeV9nDktIuGvywW6OdYpiFnJGF8tMZY7TgTcrHAxLJetjMji8Hw c3TFFxsJmW9Z3FZ4jq5Z04EBOoPl++Cn5wWMgnJcfj5nvjTX5K2iUd28bKF4VU5iOtAK93yGMsL rBz57gYwIvQT7fcS5aLLf0eqGjrg57R1qr+odalcgBnGhqQG4kwA== X-Received: by 2002:a05:600c:5298:b0:485:3ee1:eba5 with SMTP id 5b1f17b1804b1-488d68820abmr45138605e9.27.1775830025295; Fri, 10 Apr 2026 07:07:05 -0700 (PDT) Received: from localhost (93-41-3-120.ip79.fastwebnet.it. [93.41.3.120]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-488d5344e28sm81284895e9.7.2026.04.10.07.07.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Apr 2026 07:07:04 -0700 (PDT) From: Andrea della Porta To: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= , linux-pwm@vger.kernel.org, Rob Herring , Krzysztof Kozlowski , Conor Dooley , Florian Fainelli , Broadcom internal kernel review list , Andrea della Porta , devicetree@vger.kernel.org, linux-rpi-kernel@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Naushir Patuck , Stanimir Varbanov , mbrugger@suse.com Subject: [PATCH v2 2/3] pwm: rp1: Add RP1 PWM controller driver Date: Fri, 10 Apr 2026 16:09:58 +0200 Message-ID: <0d99317b9150310dfbd98de1cb2a890f0bffe7cd.1775829499.git.andrea.porta@suse.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Naushir Patuck The Raspberry Pi RP1 southbridge features an embedded PWM controller with 4 output channels, alongside an RPM interface to read the fan speed on the Raspberry Pi 5. Add the supporting driver. Signed-off-by: Naushir Patuck Co-developed-by: Stanimir Varbanov Signed-off-by: Stanimir Varbanov Signed-off-by: Andrea della Porta --- drivers/pwm/Kconfig | 9 ++ drivers/pwm/Makefile | 1 + drivers/pwm/pwm-rp1.c | 344 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 354 insertions(+) create mode 100644 drivers/pwm/pwm-rp1.c diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index 6f3147518376a..32031f2af75af 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -625,6 +625,15 @@ config PWM_ROCKCHIP Generic PWM framework driver for the PWM controller found on Rockchip SoCs. =20 +config PWM_RASPBERRYPI_RP1 + bool "RP1 PWM support" + depends on MISC_RP1 || COMPILE_TEST + depends on HAS_IOMEM + select REGMAP_MMIO + select MFD_SYSCON + help + PWM framework driver for Raspberry Pi RP1 controller. + config PWM_SAMSUNG tristate "Samsung PWM support" depends on PLAT_SAMSUNG || ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile index 0dc0d2b69025d..59f29f60f9123 100644 --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile @@ -56,6 +56,7 @@ obj-$(CONFIG_PWM_RENESAS_RZG2L_GPT) +=3D pwm-rzg2l-gpt.o obj-$(CONFIG_PWM_RENESAS_RZ_MTU3) +=3D pwm-rz-mtu3.o obj-$(CONFIG_PWM_RENESAS_TPU) +=3D pwm-renesas-tpu.o obj-$(CONFIG_PWM_ROCKCHIP) +=3D pwm-rockchip.o +obj-$(CONFIG_PWM_RASPBERRYPI_RP1) +=3D pwm-rp1.o obj-$(CONFIG_PWM_SAMSUNG) +=3D pwm-samsung.o obj-$(CONFIG_PWM_SIFIVE) +=3D pwm-sifive.o obj-$(CONFIG_PWM_SL28CPLD) +=3D pwm-sl28cpld.o diff --git a/drivers/pwm/pwm-rp1.c b/drivers/pwm/pwm-rp1.c new file mode 100644 index 0000000000000..b88c697d9567e --- /dev/null +++ b/drivers/pwm/pwm-rp1.c @@ -0,0 +1,344 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * pwm-rp1.c + * + * Raspberry Pi RP1 PWM. + * + * Copyright =C2=A9 2026 Raspberry Pi Ltd. + * + * Author: Naushir Patuck (naush@raspberrypi.com) + * + * Based on the pwm-bcm2835 driver by: + * Bart Tanghe + * + * Datasheet: https://pip-assets.raspberrypi.com/categories/892-raspberry-= pi-5/documents/RP-008370-DS-1-rp1-peripherals.pdf?disposition=3Dinline + * + * Limitations: + * - Channels can be enabled/disabled and their duty cycle and period can + * be updated glitchlessly. Update are synchronized with the next strobe + * at the end of the current period of the respective channel, once the + * update bit is set. The update flag is global, not per-channel. + * - Channels are phase-capable, but on RPi5, the firmware can use a chann= el + * phase register to report the RPM of the fan connected to that PWM + * channel. As a result, phase control will be ignored for now. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define RP1_PWM_GLOBAL_CTRL 0x000 +#define RP1_PWM_CHANNEL_CTRL(x) (0x014 + ((x) * 0x10)) +#define RP1_PWM_RANGE(x) (0x018 + ((x) * 0x10)) +#define RP1_PWM_PHASE(x) (0x01C + ((x) * 0x10)) +#define RP1_PWM_DUTY(x) (0x020 + ((x) * 0x10)) + +/* 8:FIFO_POP_MASK + 0:Trailing edge M/S modulation */ +#define RP1_PWM_CHANNEL_DEFAULT (BIT(8) + BIT(0)) +#define RP1_PWM_CHANNEL_ENABLE(x) BIT(x) +#define RP1_PWM_POLARITY BIT(3) +#define RP1_PWM_SET_UPDATE BIT(31) +#define RP1_PWM_MODE_MASK GENMASK(1, 0) + +#define RP1_PWM_NUM_PWMS 4 + +struct rp1_pwm { + struct regmap *regmap; + struct clk *clk; + unsigned long clk_rate; + bool clk_enabled; +}; + +struct rp1_pwm_waveform { + u32 period_ticks; + u32 duty_ticks; + bool enabled; + bool inverted_polarity; +}; + +static const struct regmap_config rp1_pwm_regmap_config =3D { + .reg_bits =3D 32, + .val_bits =3D 32, + .reg_stride =3D 4, + .max_register =3D 0x60, +}; + +static void rp1_pwm_apply_config(struct pwm_chip *chip, struct pwm_device = *pwm) +{ + struct rp1_pwm *rp1 =3D pwmchip_get_drvdata(chip); + u32 value; + + /* update the changed registers on the next strobe to avoid glitches */ + regmap_read(rp1->regmap, RP1_PWM_GLOBAL_CTRL, &value); + value |=3D RP1_PWM_SET_UPDATE; + regmap_write(rp1->regmap, RP1_PWM_GLOBAL_CTRL, value); +} + +static int rp1_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct rp1_pwm *rp1 =3D pwmchip_get_drvdata(chip); + + /* init channel to reset defaults */ + regmap_write(rp1->regmap, RP1_PWM_CHANNEL_CTRL(pwm->hwpwm), RP1_PWM_CHANN= EL_DEFAULT); + return 0; +} + +static int rp1_pwm_round_waveform_tohw(struct pwm_chip *chip, + struct pwm_device *pwm, + const struct pwm_waveform *wf, + void *_wfhw) +{ + struct rp1_pwm *rp1 =3D pwmchip_get_drvdata(chip); + struct rp1_pwm_waveform *wfhw =3D _wfhw; + u64 clk_rate =3D rp1->clk_rate; + u64 ticks; + + ticks =3D mul_u64_u64_div_u64(wf->period_length_ns, clk_rate, NSEC_PER_SE= C); + + if (ticks > U32_MAX) + ticks =3D U32_MAX; + wfhw->period_ticks =3D ticks; + + if (wf->duty_offset_ns + wf->duty_length_ns >=3D wf->period_length_ns) { + ticks =3D mul_u64_u64_div_u64(wf->period_length_ns - wf->duty_length_ns, + clk_rate, NSEC_PER_SEC); + wfhw->inverted_polarity =3D true; + } else { + ticks =3D mul_u64_u64_div_u64(wf->duty_length_ns, clk_rate, NSEC_PER_SEC= ); + wfhw->inverted_polarity =3D false; + } + + if (ticks > wfhw->period_ticks) + ticks =3D wfhw->period_ticks; + wfhw->duty_ticks =3D ticks; + + wfhw->enabled =3D !!wfhw->duty_ticks; + + return 0; +} + +static int rp1_pwm_round_waveform_fromhw(struct pwm_chip *chip, + struct pwm_device *pwm, + const void *_wfhw, + struct pwm_waveform *wf) +{ + struct rp1_pwm *rp1 =3D pwmchip_get_drvdata(chip); + const struct rp1_pwm_waveform *wfhw =3D _wfhw; + u64 clk_rate =3D rp1->clk_rate; + u32 ticks; + + memset(wf, 0, sizeof(*wf)); + + if (!wfhw->enabled) + return 0; + + wf->period_length_ns =3D DIV_ROUND_UP_ULL((u64)wfhw->period_ticks * NSEC_= PER_SEC, clk_rate); + + if (wfhw->inverted_polarity) { + wf->duty_length_ns =3D DIV_ROUND_UP_ULL((u64)wfhw->duty_ticks * NSEC_PER= _SEC, + clk_rate); + } else { + wf->duty_offset_ns =3D DIV_ROUND_UP_ULL((u64)wfhw->duty_ticks * NSEC_PER= _SEC, + clk_rate); + ticks =3D wfhw->period_ticks - wfhw->duty_ticks; + wf->duty_length_ns =3D DIV_ROUND_UP_ULL((u64)ticks * NSEC_PER_SEC, clk_r= ate); + } + + return 0; +} + +static int rp1_pwm_write_waveform(struct pwm_chip *chip, + struct pwm_device *pwm, + const void *_wfhw) +{ + struct rp1_pwm *rp1 =3D pwmchip_get_drvdata(chip); + const struct rp1_pwm_waveform *wfhw =3D _wfhw; + u32 value; + + /* set period and duty cycle */ + regmap_write(rp1->regmap, + RP1_PWM_RANGE(pwm->hwpwm), wfhw->period_ticks); + regmap_write(rp1->regmap, + RP1_PWM_DUTY(pwm->hwpwm), wfhw->duty_ticks); + + /* set polarity */ + regmap_read(rp1->regmap, RP1_PWM_CHANNEL_CTRL(pwm->hwpwm), &value); + if (!wfhw->inverted_polarity) + value &=3D ~RP1_PWM_POLARITY; + else + value |=3D RP1_PWM_POLARITY; + regmap_write(rp1->regmap, RP1_PWM_CHANNEL_CTRL(pwm->hwpwm), value); + + /* enable/disable */ + regmap_read(rp1->regmap, RP1_PWM_GLOBAL_CTRL, &value); + if (wfhw->enabled) + value |=3D RP1_PWM_CHANNEL_ENABLE(pwm->hwpwm); + else + value &=3D ~RP1_PWM_CHANNEL_ENABLE(pwm->hwpwm); + regmap_write(rp1->regmap, RP1_PWM_GLOBAL_CTRL, value); + + rp1_pwm_apply_config(chip, pwm); + + return 0; +} + +static int rp1_pwm_read_waveform(struct pwm_chip *chip, + struct pwm_device *pwm, + void *_wfhw) +{ + struct rp1_pwm *rp1 =3D pwmchip_get_drvdata(chip); + struct rp1_pwm_waveform *wfhw =3D _wfhw; + u32 value; + + regmap_read(rp1->regmap, RP1_PWM_GLOBAL_CTRL, &value); + wfhw->enabled =3D !!(value & RP1_PWM_CHANNEL_ENABLE(pwm->hwpwm)); + + regmap_read(rp1->regmap, RP1_PWM_CHANNEL_CTRL(pwm->hwpwm), &value); + wfhw->inverted_polarity =3D !!(value & RP1_PWM_POLARITY); + + if (wfhw->enabled) { + regmap_read(rp1->regmap, RP1_PWM_RANGE(pwm->hwpwm), &wfhw->period_ticks); + regmap_read(rp1->regmap, RP1_PWM_DUTY(pwm->hwpwm), &wfhw->duty_ticks); + } else { + wfhw->period_ticks =3D 0; + wfhw->duty_ticks =3D 0; + } + + return 0; +} + +static const struct pwm_ops rp1_pwm_ops =3D { + .sizeof_wfhw =3D sizeof(struct rp1_pwm_waveform), + .request =3D rp1_pwm_request, + .round_waveform_tohw =3D rp1_pwm_round_waveform_tohw, + .round_waveform_fromhw =3D rp1_pwm_round_waveform_fromhw, + .read_waveform =3D rp1_pwm_read_waveform, + .write_waveform =3D rp1_pwm_write_waveform, +}; + +static int rp1_pwm_probe(struct platform_device *pdev) +{ + struct device *dev =3D &pdev->dev; + struct device_node *np =3D dev->of_node; + unsigned long clk_rate; + struct pwm_chip *chip; + void __iomem *base; + struct rp1_pwm *rp1; + int ret; + + chip =3D devm_pwmchip_alloc(dev, RP1_PWM_NUM_PWMS, sizeof(*rp1)); + if (IS_ERR(chip)) + return PTR_ERR(chip); + + rp1 =3D pwmchip_get_drvdata(chip); + + base =3D devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + rp1->regmap =3D devm_regmap_init_mmio(dev, base, &rp1_pwm_regmap_config); + if (IS_ERR(rp1->regmap)) + return dev_err_probe(dev, PTR_ERR(rp1->regmap), "Cannot initialize regma= p\n"); + + ret =3D of_syscon_register_regmap(np, rp1->regmap); + if (ret) + return dev_err_probe(dev, ret, "Failed to register syscon\n"); + + rp1->clk =3D devm_clk_get(dev, NULL); + if (IS_ERR(rp1->clk)) + return dev_err_probe(dev, PTR_ERR(rp1->clk), "Clock not found\n"); + + ret =3D clk_prepare_enable(rp1->clk); + if (ret) + return dev_err_probe(dev, ret, "Failed to enable clock\n"); + rp1->clk_enabled =3D true; + + ret =3D devm_clk_rate_exclusive_get(dev, rp1->clk); + if (ret) { + dev_err_probe(dev, ret, "Fail to get exclusive rate\n"); + goto err_disable_clk; + } + + clk_rate =3D clk_get_rate(rp1->clk); + if (!clk_rate) { + ret =3D dev_err_probe(dev, -EINVAL, "Failed to get clock rate\n"); + goto err_disable_clk; + } + rp1->clk_rate =3D clk_rate; + + chip->ops =3D &rp1_pwm_ops; + + platform_set_drvdata(pdev, chip); + + ret =3D devm_pwmchip_add(dev, chip); + if (ret) { + dev_err_probe(dev, ret, "Failed to register PWM chip\n"); + goto err_disable_clk; + } + + return 0; + +err_disable_clk: + clk_disable_unprepare(rp1->clk); + + return ret; +} + +static int rp1_pwm_suspend(struct device *dev) +{ + struct rp1_pwm *rp1 =3D dev_get_drvdata(dev); + + if (rp1->clk_enabled) { + clk_disable_unprepare(rp1->clk); + rp1->clk_enabled =3D false; + } + + return 0; +} + +static int rp1_pwm_resume(struct device *dev) +{ + struct rp1_pwm *rp1 =3D dev_get_drvdata(dev); + int ret; + + ret =3D clk_prepare_enable(rp1->clk); + if (ret) { + dev_err(dev, "Failed to enable clock on resume: %d\n", ret); + return ret; + } + + rp1->clk_enabled =3D true; + + return 0; +} + +static DEFINE_SIMPLE_DEV_PM_OPS(rp1_pwm_pm_ops, rp1_pwm_suspend, rp1_pwm_r= esume); + +static const struct of_device_id rp1_pwm_of_match[] =3D { + { .compatible =3D "raspberrypi,rp1-pwm" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, rp1_pwm_of_match); + +static struct platform_driver rp1_pwm_driver =3D { + .probe =3D rp1_pwm_probe, + .driver =3D { + .name =3D "rp1-pwm", + .of_match_table =3D rp1_pwm_of_match, + .pm =3D pm_ptr(&rp1_pwm_pm_ops), + .suppress_bind_attrs =3D true, + }, +}; +module_platform_driver(rp1_pwm_driver); + +MODULE_DESCRIPTION("RP1 PWM driver"); +MODULE_AUTHOR("Naushir Patuck "); +MODULE_AUTHOR("Andrea della Porta "); +MODULE_LICENSE("GPL"); --=20 2.35.3 From nobody Mon Jun 15 13:39:43 2026 Received: from mail-wm1-f47.google.com (mail-wm1-f47.google.com [209.85.128.47]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A3C683CD8D1 for ; Fri, 10 Apr 2026 14:07:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775830030; cv=none; b=cN+QwrT+80CB0k+FMY5ULDtE2tjDwHbXWvh+evPUjn1yrlJ6nSEq529Z+zD9TYYHOG7tN01GMpQgy+n1m758z/5NuiP3D5LDoIyFJWZh01j3fy/0FB8srmHlOUjyliLXaPyfgjGjszJCXpkLZFLvhcLqbhrnEfTOFPv8foU2LJ8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775830030; c=relaxed/simple; bh=fLM8M+exZKgQsFh5tdcGS1DmZreTyFRyr9bIXtCcplM=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=iuSgIIS1tfvFc5TO8PnA4LG5k0G8oxiXD9zphZzumqawvU5oH+webKylTQFS7AoL+tVl5DmE9/qrTsQQ3RwHgjBbWj35M8FtnE+mcOe5z8oZjtwtZP36YmEFhW/jhqsTTezvbN+Z82qLwtsU0fFFi/QIYFdmk3OcefHW1ccGgQI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=suse.com; spf=pass smtp.mailfrom=suse.com; dkim=pass (2048-bit key) header.d=suse.com header.i=@suse.com header.b=guIaUm/I; arc=none smtp.client-ip=209.85.128.47 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=suse.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=suse.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=suse.com header.i=@suse.com header.b="guIaUm/I" Received: by mail-wm1-f47.google.com with SMTP id 5b1f17b1804b1-488afb0427eso26724525e9.1 for ; Fri, 10 Apr 2026 07:07:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=google; t=1775830027; x=1776434827; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=aUTaySjIgh6lfu9rWtVOEFr4avLmeO2LROURou8Y2uw=; b=guIaUm/Ig4S1Znyrp4UMP1qm/cqwoz4yl+Cs6Cf4bz/F4dQw2j88pEL219KHWtyKQc 2dp9fSPasQGM4zSKpeLlj4j0UqfyztGDVBhsYhh6rooIK7u2g5uDrN+Wpyr+/7FiHnHU AVthi2J7QEarl+YEyLmZzMXuM4OIh0B1giq9k6oRt/jN3ejDPcK84B1bAjuVABaAcnGj gEUo1SUnwBDSCaBLy3MqEekG/jrPQ+fWt9cZyBuy8nt/bqiNYSmdgcRQWBc6rGP9IrdF Dx+SB7Co7JsSB8+TsdXtO37P0NFv9diJbQQ0kzGpWLDMnY0XOLYUVMh6jlURGFK7K1Zf 3xAQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775830027; x=1776434827; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=aUTaySjIgh6lfu9rWtVOEFr4avLmeO2LROURou8Y2uw=; b=BeYxDGULGxQqhwMy+11PNmkPi/iV308GMSEWG6AwZp2jtnB5RJ8rBqEpJ5i2TzO8P7 b5cWYn3dp8He7nJ9qeo6m1PFSGro/D1sFfg9Ja7c1GMazt2YVlhogeWqvOScZjDf1q2L 1RVLAi2IZm9x64bX2C5Xhz7iAtKa11nHBnfCtdqLdpQb4elYshRXAfPGy/LNLNPQtw/S n//cjVHd2byQTj+24ix5UNiXYj4wxSIyhATknQmq102OWm5qInnxn18zk/1ROKal6io+ 7EZ6PpXFZR7mTntpPVfijWL0nEto+ec8szyVCHPmLdgRvLPZmAFgUEsJWu/RSpgIxjAs UVsw== X-Forwarded-Encrypted: i=1; AJvYcCWmBbu791qXxLz55SvAVUNDdvvwKiqjd4L/W+N/LTs3StXEWyT0EYGu01ADTIWrvy1ILZ9qvXNZE6gor5E=@vger.kernel.org X-Gm-Message-State: AOJu0Yx1tFOnCIMwZgvIJaBnVSO7K2gqyqe6Thr9q7oQT+MVPVg4d5Hj gBgfCwxXV59n3gW8F7w+lDl857DIxxQeWJREB2UASZIK11mJnwhi6//qnZtmQN5yTIg= X-Gm-Gg: AeBDiet8QZg8tMNSKQxWNnwknX6YCmb/U0pcDsk76DaXay0XwmQErIv7wS7yLv2T32t KZ29Xt40pM4SfLAda3mDu1+FhgsOcrJscwIj/FJNRdEyvCLon4l7tw7NysY/rGZiq2IWeCOr3Fy 2pxCf4Kht+HIkuueixGyWDUuy+0rVM1dLFoYhpCnpizlnnEmYNzkz77gOP0UgHnETnuJPkP6cLA WCrPDArBx5aqLULfBgjLQkjycc3djc9+IiOJdVtTBdRNTK4341K08Wdvwv6kW6QcVmP+67OAsNe VC7x+5m2y8yanhse8Cj9XepVtRl8zkb2PysjKXvvSmHEDiJPaUR04ngclSt4ZlHZWRWlHb7zb32 UGrHO1bT0uf0UPZzPcKzQbFHYt2jQhF5UX3IsvXWPNpQfV7TwGOdjDPa0s39p2cn/E/MpCMc0T6 8l/dpOWLFzAPj6O2NrwyDB6uburEVQ/w9hbrSc5Qnprj/IqNyf8qFPQrSMJbiK X-Received: by 2002:a05:600c:608e:b0:488:8185:e672 with SMTP id 5b1f17b1804b1-488d688d2fbmr43720335e9.30.1775830026934; Fri, 10 Apr 2026 07:07:06 -0700 (PDT) Received: from localhost (93-41-3-120.ip79.fastwebnet.it. [93.41.3.120]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-43d63deb904sm8504646f8f.9.2026.04.10.07.07.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Apr 2026 07:07:06 -0700 (PDT) From: Andrea della Porta To: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= , linux-pwm@vger.kernel.org, Rob Herring , Krzysztof Kozlowski , Conor Dooley , Florian Fainelli , Broadcom internal kernel review list , Andrea della Porta , devicetree@vger.kernel.org, linux-rpi-kernel@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Naushir Patuck , Stanimir Varbanov , mbrugger@suse.com Subject: [PATCH v2 3/3] arm64: dts: broadcom: rpi-5: Add RP1 PWM node Date: Fri, 10 Apr 2026 16:09:59 +0200 Message-ID: X-Mailer: git-send-email 2.51.0 In-Reply-To: References: 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 Content-Type: text/plain; charset="utf-8" From: Stanimir Varbanov The RP1 chipset used on the Raspberry Pi 5 features an integrated PWM controller to drive the cooling fan. Add the corresponding DT node for this PWM controller. Signed-off-by: Stanimir Varbanov Co-developed-by: Andrea della Porta Signed-off-by: Andrea della Porta --- arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts | 12 ++++++++++++ arch/arm64/boot/dts/broadcom/rp1-common.dtsi | 10 ++++++++++ 2 files changed, 22 insertions(+) diff --git a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts b/arch/arm64/= boot/dts/broadcom/bcm2712-rpi-5-b.dts index 2856082814462..a4e5ba23bf536 100644 --- a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts +++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts @@ -64,12 +64,24 @@ phy1: ethernet-phy@1 { }; =20 &rp1_gpio { + fan_pwm_default_state: fan-pwm-default-state { + function =3D "pwm1"; + pins =3D "gpio45"; + bias-pull-down; + }; + usb_vbus_default_state: usb-vbus-default-state { function =3D "vbus1"; groups =3D "vbus1"; }; }; =20 +&rp1_pwm { + pinctrl-0 =3D <&fan_pwm_default_state>; + pinctrl-names =3D "default"; + status =3D "okay"; +}; + &rp1_usb0 { pinctrl-0 =3D <&usb_vbus_default_state>; pinctrl-names =3D "default"; diff --git a/arch/arm64/boot/dts/broadcom/rp1-common.dtsi b/arch/arm64/boot= /dts/broadcom/rp1-common.dtsi index 5a815c3797945..d0f4d6be75500 100644 --- a/arch/arm64/boot/dts/broadcom/rp1-common.dtsi +++ b/arch/arm64/boot/dts/broadcom/rp1-common.dtsi @@ -26,6 +26,16 @@ rp1_clocks: clocks@40018000 { <200000000>; // RP1_CLK_SYS }; =20 + rp1_pwm: pwm@4009c000 { + compatible =3D "raspberrypi,rp1-pwm"; + reg =3D <0x00 0x4009c000 0x0 0x100>; + clocks =3D <&rp1_clocks RP1_CLK_PWM1>; + assigned-clocks =3D <&rp1_clocks RP1_CLK_PWM1>; + assigned-clock-rates =3D <50000000>; + #pwm-cells =3D <3>; + status =3D "disabled"; + }; + rp1_gpio: pinctrl@400d0000 { compatible =3D "raspberrypi,rp1-gpio"; reg =3D <0x00 0x400d0000 0x0 0xc000>, --=20 2.35.3