From nobody Mon Feb 9 17:07:26 2026 Received: from mail-yw1-f177.google.com (mail-yw1-f177.google.com [209.85.128.177]) (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 6E6753D669E for ; Thu, 22 Jan 2026 22:37:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.177 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769121444; cv=none; b=mElcT9Lpizc6MaqTTCVkJN06XreojFX/mbwcbJuKeQo6CuDzd1sB73xPO4WlDzuLvfLQd5YM3aGoQwEr/cgfSYfFnopd5U9K0q+OqiR5Hw6/oZGPyzrrzV+mfyYygZDAgttjxlA3NsP1YjnXbp2YGTFkr8SQuX8Tr9+g3fL1TX8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769121444; c=relaxed/simple; bh=nuJdKHGCTV0D09Z7qyDqhwfvfBu5By5qCwePaRgr+WM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Q4UBtzTq8IaP/fLT/ZXWjbNs0xjh3AlwDn4Ac/TScLze42GKiyjiEvfcgj7h+1aOis9tbVE7LxZrhRgxWbSyunQ7L7H4xnIFDcpMKMIazmmcGa+1Lxcr5ZvpYYaxqX0/tIukZnM7Mh9/NwkcGnsMh4qy8DILa7gBySRPvPg3y34= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=oss.tenstorrent.com; spf=pass smtp.mailfrom=tenstorrent.com; dkim=pass (2048-bit key) header.d=tenstorrent.com header.i=@tenstorrent.com header.b=dsC+Ock5; arc=none smtp.client-ip=209.85.128.177 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=oss.tenstorrent.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=tenstorrent.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=tenstorrent.com header.i=@tenstorrent.com header.b="dsC+Ock5" Received: by mail-yw1-f177.google.com with SMTP id 00721157ae682-7942fca0da6so8588317b3.3 for ; Thu, 22 Jan 2026 14:37:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tenstorrent.com; s=google; t=1769121428; x=1769726228; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=Jy1u4d8feAZPBgF+/xH/YbvlGqaa/pPappPh2V1R7Jg=; b=dsC+Ock5bi5/CkuEg4RiqlIMQpa8KsOe1MgQpLC3V5E5bpqRpEdu3XDfBWDQNFOEB/ bI+2UgLhwXPlZ5sBHH1WzlEMVQgovXzZKiz3a5wP6sdVTkUlkf7FQKkUY/sifXxDW38y +TkQbtxrr3BackU8icSYS0J0zGfun6Ei2VvbvVOpdJhK82FpL74/s1M+vYs7ee1j0ATW BZR/p0oSfi+M27XB8ozfVlrijQT6sB/8DoPhmA4vLaKJxMRQyGNFeZ/jcXhne8vxCHnF QO8qnK5BUVW+70OW2mmtOMVDOxpSfS2PlapPonuDoy70l9IeDs6bljfGMfA42jVx0tWI TVpw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1769121428; x=1769726228; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=Jy1u4d8feAZPBgF+/xH/YbvlGqaa/pPappPh2V1R7Jg=; b=PXue84+nd4OcZXXWaPcsaN5Kf4VAD16f0tlzxxGbhUQjHKyORYtZOUnzhFAmeEH7k3 Izt4j5XFtDtFA3PYHUv0lPkNM2qqdo1k4SwmYZNRpyGBxxCiGPaGrY66+3NknVfm9WUZ 1656E6e1j3hcgOsFngV+P/nBNuPAA0B7Y1trD8L9+QS6GKkY0cT+ImhMO23DrVXbpJs7 kHz6e/96efPsq4e3md2raAtDXSK5ZoHlekVdNVD/yRWa/+xx1a8IOcAOn+xcjB7v005b 3hRrTommQKQrtbG/0LO5F425hTT7of4GGhAtFkbFl6FwIsamYSlD9gJtQMBIrZM8vyva trOQ== X-Forwarded-Encrypted: i=1; AJvYcCU+1N5C3XdkwLDLkliq5SmVGW/Zm07FRRh+R9M6bTB0PwbmX5dSWLRpb6MuMNF6ml74Y0YlkCSgBkammXI=@vger.kernel.org X-Gm-Message-State: AOJu0YwG9p3t5CMWQNq7ouw2KkUaJtiwgOuRs6AdVnY7R6YFhWdlBYEW R7zkydSJ11OgP+iNSY0/soT1x2nLXHIR0ngLq1cASKGJwNwvxxqxiwVq5T0famNWqW0= X-Gm-Gg: AZuq6aJJDaZ+2g6c2sEyySrnT3Egejr9Z7UCEG2ftJE6gy31j4PiNPPp+EmIw7QsC6m g7MTdSdgtSaG6J+o7IKI+C50tpiq+yDxqFTKJnWeY9OxZhWREWJDy6YFQGpIHqYdbZHH/tJJc2o 0EM06RfB1Mij6R5zzH5KQgChnOHCT612Sbnv+MHa+NLTwd3bw989No/a0bvp2tJ4pfaMXkU3eRC hM2oWGHRIZhIMQj6ZiQu6+tumsPjz0k/jSGfUM+z4gjreCgBFVkvj2XXncoDtnSAg8oBtuY5kDc fby6qrwjNovPQyy5X2xIjSPel//bg04Oo/RLhEEPIGGltSfSZSIUS0Mb9/HyIlPfBdU+V2fHS7x 6XuOEpFeJn3+l1chxjQAjfaCtW/esbvSfLXdjVMezrpC0rKOYDbXkAFezmihWelUpzni0+Fgdf5 pFbBug2IefaGCfPcAIOXXYUGuTZcYuxp8WJD50OsmPrgcE6F0jKW55aGxThvN33AWhotC8tg3sJ tNAn/ARLw== X-Received: by 2002:a05:690c:c50c:b0:794:3cb7:80fe with SMTP id 00721157ae682-7943cb78460mr470627b3.20.1769121428408; Thu, 22 Jan 2026 14:37:08 -0800 (PST) Received: from [192.168.5.15] ([68.95.197.245]) by smtp.gmail.com with ESMTPSA id 00721157ae682-7943b01b09csm2766167b3.15.2026.01.22.14.37.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 22 Jan 2026 14:37:08 -0800 (PST) From: Anirudh Srinivasan Date: Thu, 22 Jan 2026 16:36:37 -0600 Subject: [PATCH v2 1/3] dt-bindings: soc: tenstorrent: Add tenstorrent,atlantis-syscon 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 Message-Id: <20260122-atlantis-clocks-v2-1-c66371639e66@oss.tenstorrent.com> References: <20260122-atlantis-clocks-v2-0-c66371639e66@oss.tenstorrent.com> In-Reply-To: <20260122-atlantis-clocks-v2-0-c66371639e66@oss.tenstorrent.com> To: Drew Fustini , Joel Stanley , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd , Anirudh Srinivasan , Philipp Zabel Cc: linux-riscv@lists.infradead.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, joel@jms.id.au, fustini@kernel.org, mpe@kernel.org, mpe@oss.tenstorrent.com, npiggin@oss.tenstorrent.com, agross@kernel.org, agross@oss.tenstorrent.com, bmasney@redhat.com X-Mailer: b4 0.14.3 Document bindings for Tenstorrent Atlantis syscon that manages clocks and resets. This syscon block is instantiated 4 times in the SoC. This commit documents the clocks from the RCPU syscon block. Signed-off-by: Anirudh Srinivasan --- .../tenstorrent/tenstorrent,atlantis-syscon.yaml | 90 ++++++++++++++++++ MAINTAINERS | 2 + .../clock/tenstorrent,atlantis-syscon.h | 101 +++++++++++++++++= ++++ 3 files changed, 193 insertions(+) diff --git a/Documentation/devicetree/bindings/soc/tenstorrent/tenstorrent,= atlantis-syscon.yaml b/Documentation/devicetree/bindings/soc/tenstorrent/te= nstorrent,atlantis-syscon.yaml new file mode 100644 index 000000000000..49fbe2423be0 --- /dev/null +++ b/Documentation/devicetree/bindings/soc/tenstorrent/tenstorrent,atlanti= s-syscon.yaml @@ -0,0 +1,90 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/soc/tenstorrent/tenstorrent,atlantis-sy= scon.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Tenstorrent Atlantis SoC Syscon + +maintainers: + - Anirudh Srinivasan + +description: + Multifunctional register block found in Tenstorrent Atlantis SoC whose m= ain function + is to control clocks and resets. This Block is instantiated multiple tim= es in the SoC, + each block controls clock and resets for a different subsystem. + + RCPU syscon serves low speed IO interfaces on chip + PCIe syscon serves all PCIe related functions + HSIO syscon serves high speed IO interfaces (Ethernet, USB) + MM syscon serves GPU, display and video processing functions + +properties: + compatible: + enum: + - tenstorrent,atlantis-syscon-rcpu + - tenstorrent,atlantis-syscon-pcie + - tenstorrent,atlantis-syscon-mm + - tenstorrent,atlantis-syscon-hsio + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + "#clock-cells": + const: 1 + description: + See for valid indi= ces. + + "#reset-cells": + const: 1 + + tenstorrent,syscon-rcpu: + $ref: /schemas/types.yaml#/definitions/phandle + description: + Phandle reference to RCPU syscon, needed by other 3 syscons (PCIe, M= M, HSIO) + as the control registers for the PLLs that drive these subsystems ar= e in RCPU + syscon's range + +required: + - compatible + - reg + - clocks + - "#clock-cells" + - "#reset-cells" + +allOf: + - if: + properties: + compatible: + contains: + enum: + - tenstorrent,atlantis-syscon-pcie + - tenstorrent,atlantis-syscon-mm + - tenstorrent,atlantis-syscon-hsio + then: + required: + - tenstorrent,syscon-rcpu + +additionalProperties: false + +examples: + - | + syscon_rcpu: system-controller@a8000000 { + compatible =3D "tenstorrent,atlantis-syscon-rcpu"; + reg =3D <0xa8000000 0x10000>; + clocks =3D <&osc_24m>; + #clock-cells =3D <1>; + #reset-cells =3D <1>; + }; + - | + syscon_hsio: system-controller@e00c0000 { + compatible =3D "tenstorrent,atlantis-syscon-hsio"; + reg =3D <0xe00c0000 0x500>; + clocks =3D <&osc_24m>; + #clock-cells =3D <1>; + #reset-cells =3D <1>; + tenstorrent,syscon-rcpu =3D <&syscon_rcpu>; + }; diff --git a/MAINTAINERS b/MAINTAINERS index dc731d37c8fe..19a98b1fa456 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -22535,7 +22535,9 @@ L: linux-riscv@lists.infradead.org S: Maintained T: git https://github.com/tenstorrent/linux.git F: Documentation/devicetree/bindings/riscv/tenstorrent.yaml +F: Documentation/devicetree/bindings/soc/tenstorrent/tenstorrent,atlantis-= syscon.yaml F: arch/riscv/boot/dts/tenstorrent/ +F: include/dt-bindings/clock/tenstorrent,atlantis-syscon.h =20 RISC-V THEAD SoC SUPPORT M: Drew Fustini diff --git a/include/dt-bindings/clock/tenstorrent,atlantis-syscon.h b/incl= ude/dt-bindings/clock/tenstorrent,atlantis-syscon.h new file mode 100644 index 000000000000..053cef2b43c8 --- /dev/null +++ b/include/dt-bindings/clock/tenstorrent,atlantis-syscon.h @@ -0,0 +1,101 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) 2026 Tenstorrent + */ + +#ifndef _DT_BINDINGS_ATLANTIS_SYSCON_H +#define _DT_BINDINGS_ATLANTIS_SYSCON_H + +/* + * RCPU Domain Clock IDs + */ +#define CLK_RCPU_PLL 0 +#define CLK_RCPU_ROOT 1 +#define CLK_RCPU_DIV2 2 +#define CLK_RCPU_DIV4 3 +#define CLK_RCPU_RTC 4 +#define CLK_SMNDMA0_ACLK 5 +#define CLK_SMNDMA1_ACLK 6 +#define CLK_WDT0_PCLK 7 +#define CLK_WDT1_PCLK 8 +#define CLK_TIMER_PCLK 9 +#define CLK_PVTC_PCLK 10 +#define CLK_PMU_PCLK 11 +#define CLK_MAILBOX_HCLK 12 +#define CLK_SEC_SPACC_HCLK 13 +#define CLK_SEC_OTP_HCLK 14 +#define CLK_TRNG_PCLK 15 +#define CLK_SEC_CRC_HCLK 16 +#define CLK_SMN_HCLK 17 +#define CLK_AHB0_HCLK 18 +#define CLK_SMN_PCLK 19 +#define CLK_SMN_CLK 20 +#define CLK_SCRATCHPAD_CLK 21 +#define CLK_RCPU_CORE_CLK 22 +#define CLK_RCPU_ROM_CLK 23 +#define CLK_OTP_LOAD_CLK 24 +#define CLK_NOC_PLL 25 +#define CLK_NOCC_CLK 26 +#define CLK_NOCC_DIV2 27 +#define CLK_NOCC_DIV4 28 +#define CLK_NOCC_RTC 29 +#define CLK_NOCC_CAN 30 +#define CLK_QSPI_SCLK 31 +#define CLK_QSPI_HCLK 32 +#define CLK_I2C0_PCLK 33 +#define CLK_I2C1_PCLK 34 +#define CLK_I2C2_PCLK 35 +#define CLK_I2C3_PCLK 36 +#define CLK_I2C4_PCLK 37 +#define CLK_UART0_PCLK 38 +#define CLK_UART1_PCLK 39 +#define CLK_UART2_PCLK 40 +#define CLK_UART3_PCLK 41 +#define CLK_UART4_PCLK 42 +#define CLK_SPI0_PCLK 43 +#define CLK_SPI1_PCLK 44 +#define CLK_SPI2_PCLK 45 +#define CLK_SPI3_PCLK 46 +#define CLK_GPIO_PCLK 47 +#define CLK_CAN0_HCLK 48 +#define CLK_CAN0_CLK 49 +#define CLK_CAN1_HCLK 50 +#define CLK_CAN1_CLK 51 +#define CLK_CAN0_TIMER_CLK 52 +#define CLK_CAN1_TIMER_CLK 53 + +/* RCPU domain reset */ +#define RST_SMNDMA0 0 +#define RST_SMNDMA1 1 +#define RST_WDT0 2 +#define RST_WDT1 3 +#define RST_TMR 4 +#define RST_PVTC 5 +#define RST_PMU 6 +#define RST_MAILBOX 7 +#define RST_SPACC 8 +#define RST_OTP 9 +#define RST_TRNG 10 +#define RST_CRC 11 +#define RST_QSPI 12 +#define RST_I2C0 13 +#define RST_I2C1 14 +#define RST_I2C2 15 +#define RST_I2C3 16 +#define RST_I2C4 17 +#define RST_UART0 18 +#define RST_UART1 19 +#define RST_UART2 20 +#define RST_UART3 21 +#define RST_UART4 22 +#define RST_SPI0 23 +#define RST_SPI1 24 +#define RST_SPI2 25 +#define RST_SPI3 26 +#define RST_GPIO 27 +#define RST_CAN0 28 +#define RST_CAN1 29 +#define RST_I2S0 30 +#define RST_I2S1 31 + +#endif /* _DT_BINDINGS_ATLANTIS_SYSCON_H */ --=20 2.43.0 From nobody Mon Feb 9 17:07:26 2026 Received: from mail-yw1-f180.google.com (mail-yw1-f180.google.com [209.85.128.180]) (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 6D54D3D5230 for ; Thu, 22 Jan 2026 22:37:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.180 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769121440; cv=none; b=Q7n/r6Y6DLcnYlncKIO4TfJfWJ2qo77glV3S6JPX77Xq46KAsLgneEdVUBZvDxgJQ81L+jZUUhW/W6XHtFghDuQJJ6LyybxN2LNs+vei9PBHIzoCsOr462nCd9lP58NYii1f9LO88f0VAvq1MK5HSeozTx6bz5g8zUvxsQN0ndg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769121440; c=relaxed/simple; bh=8vvsZYpkw2SRSEyDStWOP/8CnG6U/EbywSNgTD4SaQE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=NbiUwyVErh7gz5vm1g4A/LpDDFVIJNpSMSOHPk57J3OfmsOEh84kkSaeCDwMFpJUAzhFmmEvo7NA/pOG2xcj9zZB0A87E3PhhDxvZVesZICUGFH58gGo3k3buT3Fm0qA8aD6gKSP9AE+dNB2iZtPw/pWWjUuyGqWbU1pMIa3RPo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=oss.tenstorrent.com; spf=pass smtp.mailfrom=tenstorrent.com; dkim=pass (2048-bit key) header.d=tenstorrent.com header.i=@tenstorrent.com header.b=a31ZF0sx; arc=none smtp.client-ip=209.85.128.180 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=oss.tenstorrent.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=tenstorrent.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=tenstorrent.com header.i=@tenstorrent.com header.b="a31ZF0sx" Received: by mail-yw1-f180.google.com with SMTP id 00721157ae682-78fb6c7874cso16646207b3.0 for ; Thu, 22 Jan 2026 14:37:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tenstorrent.com; s=google; t=1769121429; x=1769726229; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=nFuE/Ue22jMLFn8jDio4s3sGtCW+4e1hKG320llZvAk=; b=a31ZF0sxqJ8Q6j3U/XHJfZ2p0fuk0CvknqaKDoEr1QXkQMGE/yJ1QMZn4iMMuNgx77 Ru7FIVuYGh2/C/zCs4uXmX78oK4zRto2Fk8cqVyQuT2kXREpnRqxrTemQ4TvmkCUZFXf O9xKF0/CK5Mb7OBHplIve1cNKaY4UKsSBkA2BCtVg94dTGITyDlzQl/fVUVD+c9XAzjQ Ac+SftJAyPKa2CZKvHH2KcJPOgERoMihdggztTizOMaAjoPy0cpuGHG/6mdOJMlHdovJ nk/8vB9cVyPGXaVrd5jj/S0Z1VWeeJzH/enzepgDzd9O7nELFdJWlegHq/MMkXj8JwJd zbxg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1769121429; x=1769726229; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=nFuE/Ue22jMLFn8jDio4s3sGtCW+4e1hKG320llZvAk=; b=oG2oyJk/8tbrR5FZL9aMdIWXxbpRTVipr48WoFfq0uebSd8uGqdUbyAS/0KDEN8CG9 bmqN73AzAFmemj+ItX52L6Nii7cMc2hsTs8TE3kbhig0zAR96+NGShfwWJXE7Uassvxm +Z62/fCmFpyAjC8K18vFynLW7IjvxwDrlUEutbRRN/JNbkqVRl4IKqRdV6WizatxsaJq YbXgYq7GvmCeAof9m1Z3GDOEHkszQo+5LK+HTm4eYelMHEDTmaxc/sG/G7Xu5g+0z40s GgHT3QL2jPWKh83gnvZckAHuU8LL+RkDxeNZfqRmZx2plfcl/6PcMyphlsOUmz2LtYY5 +oIw== X-Forwarded-Encrypted: i=1; AJvYcCVQYHHX2Vvb1X23uhnX+jiTzINNpZ/KLD/UXJCsspcFTmHEcq45WB7fj7pRKkm8/OYA7+gnanYfdo9fTLw=@vger.kernel.org X-Gm-Message-State: AOJu0YxHJMIjj+ndFwl9en1WIcKb9n10BS1jasMSSHwvcZLVJKKk8JDH HeZaJZdB/lZuufCs28+jEQRUwsLwEQ+8/Lyvi8Ey0b4Xj7Z4mw1mSbtLA56YwFyzeqw= X-Gm-Gg: AZuq6aI/a13h58UvhBrFDeUlXAP3SIM4ih2KB1pElhxa/qbkzeR9T7slqgvWGN7BKS4 xW2eHvKWScdVtliaHIWQdrgAP7scsqlH/hg7uJ9Kh2TOEqPKFJMhnvvnpSm5BhiAhzPL05fZCjC VVGJAQujlmRMn2t8IaNaYD4IEn/Yq9G7uv3Ai4KlDf6e0yrhSFITe2F9DqdzoEplNJRtde0FBap r28hXbryz/p54bb3r55TkCaVtvEMqrFfDa4NeR6qZc5QCy15KVb5jFeoFLnRD6p1UX3ovkyEUij QpkjRhyLeTB1vVrc96djImgjNTXOc8GLCyBPpxJOFLEVM9pgJEn5jnOk7taD9CiLL4jiq4ZFq8F RKBCxQb3UF/ArnATtkT1YKMfKfctSoDzQpdhs7+tEJrVWUyuzV3KQyoRu/GsKSJ2OEJLq4O7VmT 5xec1CMhHGhgIYPCZybKwHqu8DY1veTuS5Lq/8Ci8pI0nTrK0V6yabrWSNFbt6fmnhWP/EcUk= X-Received: by 2002:a05:690c:6f0a:b0:794:2169:10e0 with SMTP id 00721157ae682-79439a1a818mr8718407b3.46.1769121429549; Thu, 22 Jan 2026 14:37:09 -0800 (PST) Received: from [192.168.5.15] ([68.95.197.245]) by smtp.gmail.com with ESMTPSA id 00721157ae682-7943b01b09csm2766167b3.15.2026.01.22.14.37.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 22 Jan 2026 14:37:09 -0800 (PST) From: Anirudh Srinivasan Date: Thu, 22 Jan 2026 16:36:38 -0600 Subject: [PATCH v2 2/3] reset: tenstorrent: Add reset controller for Atlantis 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 Message-Id: <20260122-atlantis-clocks-v2-2-c66371639e66@oss.tenstorrent.com> References: <20260122-atlantis-clocks-v2-0-c66371639e66@oss.tenstorrent.com> In-Reply-To: <20260122-atlantis-clocks-v2-0-c66371639e66@oss.tenstorrent.com> To: Drew Fustini , Joel Stanley , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd , Anirudh Srinivasan , Philipp Zabel Cc: linux-riscv@lists.infradead.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, joel@jms.id.au, fustini@kernel.org, mpe@kernel.org, mpe@oss.tenstorrent.com, npiggin@oss.tenstorrent.com, agross@kernel.org, agross@oss.tenstorrent.com, bmasney@redhat.com X-Mailer: b4 0.14.3 Adds Atlantis Reset Controller and auxiliary device definitions for reset to share same regmap interface as clock controller. This version of the reset controller driver covers resets from the RCPU syscon. Signed-off-by: Anirudh Srinivasan --- MAINTAINERS | 2 + drivers/reset/Kconfig | 11 ++ drivers/reset/Makefile | 1 + drivers/reset/reset-tenstorrent-atlantis.c | 158 +++++++++++++++++++++++++= ++++ include/soc/tenstorrent/atlantis-syscon.h | 26 +++++ 5 files changed, 198 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 19a98b1fa456..cf7c8e2153dc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -22537,7 +22537,9 @@ T: git https://github.com/tenstorrent/linux.git F: Documentation/devicetree/bindings/riscv/tenstorrent.yaml F: Documentation/devicetree/bindings/soc/tenstorrent/tenstorrent,atlantis-= syscon.yaml F: arch/riscv/boot/dts/tenstorrent/ +F: drivers/reset/reset-tenstorrent-atlantis.c F: include/dt-bindings/clock/tenstorrent,atlantis-syscon.h +F: include/soc/tenstorrent/ =20 RISC-V THEAD SoC SUPPORT M: Drew Fustini diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index 6e5d6deffa7d..cade77717492 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -324,6 +324,17 @@ config RESET_SUNXI help This enables the reset driver for Allwinner SoCs. =20 +config RESET_TENSTORRENT_ATLANTIS + tristate "Tenstorrent atlantis reset driver" + depends on ARCH_TENSTORRENT || COMPILE_TEST + select AUXILIARY_BUS + default ARCH_TENSTORRENT + help + This enables the driver for the reset controller + present in the Tenstorrent Atlantis SoC. + Enable this option to be able to use hardware + resets on Atalantis based systems. + config RESET_TH1520 tristate "T-HEAD TH1520 reset controller" depends on ARCH_THEAD || COMPILE_TEST diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index 9c3e484dfd81..a31959da0a88 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -41,6 +41,7 @@ obj-$(CONFIG_RESET_SOCFPGA) +=3D reset-socfpga.o obj-$(CONFIG_RESET_SPACEMIT) +=3D reset-spacemit.o obj-$(CONFIG_RESET_SUNPLUS) +=3D reset-sunplus.o obj-$(CONFIG_RESET_SUNXI) +=3D reset-sunxi.o +obj-$(CONFIG_RESET_TENSTORRENT_ATLANTIS) +=3D reset-tenstorrent-atlantis.o obj-$(CONFIG_RESET_TH1520) +=3D reset-th1520.o obj-$(CONFIG_RESET_TI_SCI) +=3D reset-ti-sci.o obj-$(CONFIG_RESET_TI_SYSCON) +=3D reset-ti-syscon.o diff --git a/drivers/reset/reset-tenstorrent-atlantis.c b/drivers/reset/res= et-tenstorrent-atlantis.c new file mode 100644 index 000000000000..2e7f09409f79 --- /dev/null +++ b/drivers/reset/reset-tenstorrent-atlantis.c @@ -0,0 +1,158 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2026 Tenstorrent + */ + +#include +#include +#include +#include +#include + +struct atlantis_reset_data { + u8 bit; + u16 reg; + bool active_low; +}; + +struct atlantis_reset_controller_data { + const struct atlantis_reset_data *reset_data; + size_t count; +}; + +struct atlantis_reset_controller { + struct reset_controller_dev rcdev; + const struct atlantis_reset_controller_data *data; + struct regmap *regmap; +}; + +#define to_atlantis_reset_controller(_rcdev) \ + container_of((_rcdev), struct atlantis_reset_controller, rcdev) + +#define RESET_DATA(_reg, _bit, _active_low) \ + { \ + .bit =3D _bit, .reg =3D _reg, .active_low =3D _active_low, \ + } + +static const struct atlantis_reset_data atlantis_rcpu_resets[] =3D { + [RST_SMNDMA0] =3D RESET_DATA(RCPU_BLK_RST_REG, 0, true), + [RST_SMNDMA1] =3D RESET_DATA(RCPU_BLK_RST_REG, 1, true), + [RST_WDT0] =3D RESET_DATA(RCPU_BLK_RST_REG, 2, true), + [RST_WDT1] =3D RESET_DATA(RCPU_BLK_RST_REG, 3, true), + [RST_TMR] =3D RESET_DATA(RCPU_BLK_RST_REG, 4, true), + [RST_PVTC] =3D RESET_DATA(RCPU_BLK_RST_REG, 12, true), + [RST_PMU] =3D RESET_DATA(RCPU_BLK_RST_REG, 13, true), + [RST_MAILBOX] =3D RESET_DATA(RCPU_BLK_RST_REG, 14, true), + [RST_SPACC] =3D RESET_DATA(RCPU_BLK_RST_REG, 26, true), + [RST_OTP] =3D RESET_DATA(RCPU_BLK_RST_REG, 28, true), + [RST_TRNG] =3D RESET_DATA(RCPU_BLK_RST_REG, 29, true), + [RST_CRC] =3D RESET_DATA(RCPU_BLK_RST_REG, 30, true), + [RST_QSPI] =3D RESET_DATA(LSIO_BLK_RST_REG, 0, true), + [RST_I2C0] =3D RESET_DATA(LSIO_BLK_RST_REG, 1, true), + [RST_I2C1] =3D RESET_DATA(LSIO_BLK_RST_REG, 2, true), + [RST_I2C2] =3D RESET_DATA(LSIO_BLK_RST_REG, 3, true), + [RST_I2C3] =3D RESET_DATA(LSIO_BLK_RST_REG, 4, true), + [RST_I2C4] =3D RESET_DATA(LSIO_BLK_RST_REG, 5, true), + [RST_UART0] =3D RESET_DATA(LSIO_BLK_RST_REG, 6, true), + [RST_UART1] =3D RESET_DATA(LSIO_BLK_RST_REG, 7, true), + [RST_UART2] =3D RESET_DATA(LSIO_BLK_RST_REG, 8, true), + [RST_UART3] =3D RESET_DATA(LSIO_BLK_RST_REG, 9, true), + [RST_UART4] =3D RESET_DATA(LSIO_BLK_RST_REG, 10, true), + [RST_SPI0] =3D RESET_DATA(LSIO_BLK_RST_REG, 11, true), + [RST_SPI1] =3D RESET_DATA(LSIO_BLK_RST_REG, 12, true), + [RST_SPI2] =3D RESET_DATA(LSIO_BLK_RST_REG, 13, true), + [RST_SPI3] =3D RESET_DATA(LSIO_BLK_RST_REG, 14, true), + [RST_GPIO] =3D RESET_DATA(LSIO_BLK_RST_REG, 15, true), + [RST_CAN0] =3D RESET_DATA(LSIO_BLK_RST_REG, 17, true), + [RST_CAN1] =3D RESET_DATA(LSIO_BLK_RST_REG, 18, true), + [RST_I2S0] =3D RESET_DATA(LSIO_BLK_RST_REG, 19, true), + [RST_I2S1] =3D RESET_DATA(LSIO_BLK_RST_REG, 20, true), + +}; + +static const struct atlantis_reset_controller_data atlantis_rcpu_reset_dat= a =3D { + .reset_data =3D atlantis_rcpu_resets, + .count =3D ARRAY_SIZE(atlantis_rcpu_resets), +}; + +static int atlantis_reset_update(struct reset_controller_dev *rcdev, + unsigned long id, bool assert) +{ + unsigned int val; + struct atlantis_reset_controller *rst =3D + to_atlantis_reset_controller(rcdev); + const struct atlantis_reset_data *data =3D &rst->data->reset_data[id]; + unsigned int mask =3D BIT(data->bit); + struct regmap *regmap =3D rst->regmap; + + if (data->active_low ^ assert) + val =3D mask; + else + val =3D ~mask; + + return regmap_update_bits(regmap, data->reg, mask, val); +} + +static int atlantis_reset_assert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + return atlantis_reset_update(rcdev, id, true); +} + +static int atlantis_reset_deassert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + return atlantis_reset_update(rcdev, id, false); +} + +static const struct reset_control_ops atlantis_reset_control_ops =3D { + .assert =3D atlantis_reset_assert, + .deassert =3D atlantis_reset_deassert, +}; + +static int +atlantis_reset_controller_register(struct device *dev, + struct atlantis_reset_controller *controller) +{ + struct reset_controller_dev *rcdev =3D &controller->rcdev; + + rcdev->ops =3D &atlantis_reset_control_ops; + rcdev->owner =3D THIS_MODULE; + rcdev->of_node =3D dev->of_node; + rcdev->nr_resets =3D controller->data->count; + + return devm_reset_controller_register(dev, &controller->rcdev); +} +static int atlantis_reset_probe(struct auxiliary_device *adev, + const struct auxiliary_device_id *id) +{ + struct atlantis_ccu_adev *rdev =3D to_atlantis_ccu_adev(adev); + struct atlantis_reset_controller *controller; + struct device *dev =3D &adev->dev; + + controller =3D devm_kzalloc(dev, sizeof(*controller), GFP_KERNEL); + if (!controller) + return -ENOMEM; + controller->data =3D + (const struct atlantis_reset_controller_data *)id->driver_data; + controller->regmap =3D rdev->regmap; + + return atlantis_reset_controller_register(dev, controller); +} + +static const struct auxiliary_device_id atlantis_reset_ids[] =3D { + { .name =3D "atlantis_ccu.rcpu-reset", + .driver_data =3D (kernel_ulong_t)&atlantis_rcpu_reset_data }, + {}, +}; +MODULE_DEVICE_TABLE(auxiliary, atlantis_reset_ids); + +static struct auxiliary_driver atlantis_reset_driver =3D { + .probe =3D atlantis_reset_probe, + .id_table =3D atlantis_reset_ids, +}; +module_auxiliary_driver(atlantis_reset_driver); + +MODULE_AUTHOR("Anirudh Srinivasan "); +MODULE_DESCRIPTION("Atlantis reset controller driver"); +MODULE_LICENSE("GPL"); diff --git a/include/soc/tenstorrent/atlantis-syscon.h b/include/soc/tensto= rrent/atlantis-syscon.h new file mode 100644 index 000000000000..2c6387e5c21a --- /dev/null +++ b/include/soc/tenstorrent/atlantis-syscon.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) 2026 Tenstorrent + */ +#ifndef __SOC_ATLANTIS_SYSCON_H__ +#define __SOC_ATLANTIS_SYSCON_H__ + +#include +#include + +struct atlantis_ccu_adev { + struct auxiliary_device adev; + struct regmap *regmap; +}; + +#define to_atlantis_ccu_adev(_adev) \ + container_of((_adev), struct atlantis_ccu_adev, adev) + +/* RCPU Reset Register Offsets */ +#define RCPU_BLK_RST_REG 0x001c +#define LSIO_BLK_RST_REG 0x0020 +#define HSIO_BLK_RST_REG 0x000c +#define PCIE_SUBS_RST_REG 0x0000 +#define MM_RSTN_REG 0x0014 + +#endif --=20 2.43.0 From nobody Mon Feb 9 17:07:26 2026 Received: from mail-yx1-f46.google.com (mail-yx1-f46.google.com [74.125.224.46]) (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 56C383D726A for ; Thu, 22 Jan 2026 22:37:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.224.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769121444; cv=none; b=T9j75pgfUNSCbqw1SFuSedafw0yy6noFPy6RdKoPL9+7eTUXJx93rewzac0J/ICCXP566YxwzeFinj+NsF1MhtNANPCs3WlM+JWLx5B8/lBvSJOlwmzp2osfS1WltK0J2+7EQYyTyx2oMieL47uI6aAiWUhjrfZNG6tmtFGQIzc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769121444; c=relaxed/simple; bh=hndFwFg5NVXa7t4DhB7MpnBO3lcv5K5M9TKcimcDU9s=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=lUPW3sokULVaOvpCLHpJ9VSEde4NTDP7quZhRtRzPBpqU8nBgptTpakVOBWQMysCYAKecFm2gvQLbQkyVTwNz9WlNdh1QxiHKRQFRSv3NHS7o0sSrRX2fZn5jfBBnk8qCkzFNDZlrRfeJ7D0lNMdzCrsrKt6Rp5MAZuxBgyYPDk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=oss.tenstorrent.com; spf=pass smtp.mailfrom=tenstorrent.com; dkim=pass (2048-bit key) header.d=tenstorrent.com header.i=@tenstorrent.com header.b=SJAm9bCV; arc=none smtp.client-ip=74.125.224.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=oss.tenstorrent.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=tenstorrent.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=tenstorrent.com header.i=@tenstorrent.com header.b="SJAm9bCV" Received: by mail-yx1-f46.google.com with SMTP id 956f58d0204a3-649295a4a5bso1484179d50.2 for ; Thu, 22 Jan 2026 14:37:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tenstorrent.com; s=google; t=1769121431; x=1769726231; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=Zya4Sm1WmaZbjd0+MYsYrg+GSHCeLVoe02E97sJq4zM=; b=SJAm9bCVkIU7SypJmQ0x6Pics6gYCm4/dznTwDIyQM3ImvIoZm56akpG8oqq73PRwe PUUVcFRDDGqW/i2U8vSwzm6YDiwAI2e09mU9UzwdIPMO5SqAATDhhfkinrtkYqs0ZDkq JJI+NiUtND8wmw0jdzXFrEwGsb9k9V8InMG7rJ1TsjaLTZGU7MNoRmGW9Ie8LI9jPyMN FV8Bs6gC3wkpIrdze8teH/Efzv6RhCtLQH5V+nAM5uw1GUE228V01F6c8wiSWMoHRrKp RFDDUlxAj4Fw6hKVu4NzkftvVFXkA7FOLkwwdsgBduGX2ALcgKN+wdcLLZpqPdOzEMzT Qixw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1769121431; x=1769726231; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=Zya4Sm1WmaZbjd0+MYsYrg+GSHCeLVoe02E97sJq4zM=; b=EFc980Kst+z2ISBbULnXHLBsK0EerPCcAsGbvr4Vims3LIZefKQfnTeNQ2wV2UnK/6 jmn+RyinGnOy6358LHWf/bLGFzPMXQyv+CwUt8Su1879RaJznP4pEhZP4/GcSvjFAhrR ZPDqagy0KkUB59BvOnPB/0nSG924YBz52OLPNjde/LjNjJ12E97gJhhE1RPo3iYxbsLE MJV1B4CHGDISTwR3085MzNIirD+wx45yvSVUnspztPIrPgV4wUx0wUHD00pd6c+CYETx nEJGkaXg2S8Mv+pv7HxHXWNrCxPP3Tv/BGNjPM/VfSalOJ9BwYqV6pv84Talx7bNyrXr rXiQ== X-Forwarded-Encrypted: i=1; AJvYcCVaSnLDr2sQF4rYEyw0JwRTTRrNwtGqMdM9UZxi9PNYnc+TT+dpYxsgTuZfOb21L3Wc94wxrv7lFXwTmJM=@vger.kernel.org X-Gm-Message-State: AOJu0YyjQGume4ge3ISDoS26HIsasUrTlKk12Utq38usBMUPgxLBpQ3W 0Q1aEIOdToRI1q1EpkM/Ra93XPZn0+EsaeexCmE/zch0bzCejAn+ASXYDMykw3yMuUA= X-Gm-Gg: AZuq6aJcnBCBDRzhqek+8uONXAnXtCKyx3RmivPbayjDmAGJuWCaJBmF929yLVZoEhe ZnhtYCfH/uuNuUd2g0OL7tErcBs6+vPyuh7j6Am5h4wWx5hvetKNSytP1oWwuT3mLFbWDnc+r5o S/BoMH9SII8q2SaS26N7p1ALvlnk7Xyo2G4YoexrlqZVxVjOr1cEsPoBwGkSxDUO9LfwBPdMOCD nrzPgAwxTenKiOpVHetB7R+ZLt4KThHmVA3xf5bxRzZYwM7Z+wpGt5t1FWdFioSU1pUE9iZPnKL xgc9C5mYMPpZwJT+FbBQhlzOvVLpm+M7LMLh/8WQrGcSV8spiPviCuYLEgNSbbbmfR1S0sGYDF3 X3rorzIvDYUYwZW1v1m7trY2+j8UWGkff2kBhBwAThwKx9lGXwBfbYjKFcgvZF+CBAyv9JpO4kr sUM9/yjwmoI/fgUxmjL0DGhHA0T/ojaW4DfbtuROXHmH3JKpkYxw4cEnEJRQrAiD6LnKRrpUo= X-Received: by 2002:a05:690c:6310:b0:78f:afbe:3e85 with SMTP id 00721157ae682-794398ceb9cmr22933947b3.24.1769121430720; Thu, 22 Jan 2026 14:37:10 -0800 (PST) Received: from [192.168.5.15] ([68.95.197.245]) by smtp.gmail.com with ESMTPSA id 00721157ae682-7943b01b09csm2766167b3.15.2026.01.22.14.37.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 22 Jan 2026 14:37:10 -0800 (PST) From: Anirudh Srinivasan Date: Thu, 22 Jan 2026 16:36:39 -0600 Subject: [PATCH v2 3/3] clk: tenstorrent: Add Atlantis clock controller driver 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 Message-Id: <20260122-atlantis-clocks-v2-3-c66371639e66@oss.tenstorrent.com> References: <20260122-atlantis-clocks-v2-0-c66371639e66@oss.tenstorrent.com> In-Reply-To: <20260122-atlantis-clocks-v2-0-c66371639e66@oss.tenstorrent.com> To: Drew Fustini , Joel Stanley , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd , Anirudh Srinivasan , Philipp Zabel Cc: linux-riscv@lists.infradead.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, joel@jms.id.au, fustini@kernel.org, mpe@kernel.org, mpe@oss.tenstorrent.com, npiggin@oss.tenstorrent.com, agross@kernel.org, agross@oss.tenstorrent.com, bmasney@redhat.com X-Mailer: b4 0.14.3 Add driver for clock controller in Tenstorrent Atlantis SoC. This version of the driver coves clocks from RCPU syscon. 5 types of clocks generated by this controller: PLLs (PLLs with bypass functionality and an additional Gate clk at output), Shared Gates (Multiple Gate clks that share an enable bit), standard Muxes, Dividers and Gates. All clocks are implemented using custom clk ops and use the regmap interface associated with the syscon. All clocks are derived from a 24 Mhz oscillator. The reset controller is also setup as an auxiliary device of the clock controller. Signed-off-by: Anirudh Srinivasan --- MAINTAINERS | 1 + drivers/clk/Kconfig | 1 + drivers/clk/Makefile | 1 + drivers/clk/tenstorrent/Kconfig | 14 + drivers/clk/tenstorrent/Makefile | 3 + drivers/clk/tenstorrent/atlantis-ccu.c | 939 ++++++++++++++++++++++++++= ++++ include/soc/tenstorrent/atlantis-syscon.h | 27 + 7 files changed, 986 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index cf7c8e2153dc..31c3e5bcb32d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -22537,6 +22537,7 @@ T: git https://github.com/tenstorrent/linux.git F: Documentation/devicetree/bindings/riscv/tenstorrent.yaml F: Documentation/devicetree/bindings/soc/tenstorrent/tenstorrent,atlantis-= syscon.yaml F: arch/riscv/boot/dts/tenstorrent/ +F: drivers/clk/tenstorrent/ F: drivers/reset/reset-tenstorrent-atlantis.c F: include/dt-bindings/clock/tenstorrent,atlantis-syscon.h F: include/soc/tenstorrent/ diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 3a1611008e48..643084887257 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -542,6 +542,7 @@ source "drivers/clk/starfive/Kconfig" source "drivers/clk/sunxi/Kconfig" source "drivers/clk/sunxi-ng/Kconfig" source "drivers/clk/tegra/Kconfig" +source "drivers/clk/tenstorrent/Kconfig" source "drivers/clk/thead/Kconfig" source "drivers/clk/stm32/Kconfig" source "drivers/clk/ti/Kconfig" diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 61ec08404442..f88c116d315f 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -156,6 +156,7 @@ obj-y +=3D starfive/ obj-$(CONFIG_ARCH_SUNXI) +=3D sunxi/ obj-y +=3D sunxi-ng/ obj-$(CONFIG_ARCH_TEGRA) +=3D tegra/ +obj-y +=3D tenstorrent/ obj-$(CONFIG_ARCH_THEAD) +=3D thead/ obj-y +=3D ti/ obj-$(CONFIG_CLK_UNIPHIER) +=3D uniphier/ diff --git a/drivers/clk/tenstorrent/Kconfig b/drivers/clk/tenstorrent/Kcon= fig new file mode 100644 index 000000000000..6bcef9e4feb4 --- /dev/null +++ b/drivers/clk/tenstorrent/Kconfig @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-only + +config TENSTORRENT_ATLANTIS_CCU + tristate "Support for Tenstorrent Atlantis Clock Controllers" + depends on ARCH_TENSTORRENT || COMPILE_TEST + default ARCH_TENSTORRENT + select REGMAP_MMIO + select AUXILIARY_BUS + select MFD_SYSCON + help + Say yes here to support the different clock + controllers found in the Tenstorrent Atlantis SoC. + This includes the clocks from the RCPU, HSIO, MMIO + and PCIE domain. diff --git a/drivers/clk/tenstorrent/Makefile b/drivers/clk/tenstorrent/Mak= efile new file mode 100644 index 000000000000..cc4fc01df75b --- /dev/null +++ b/drivers/clk/tenstorrent/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_TENSTORRENT_ATLANTIS_CCU) +=3D atlantis-ccu.o diff --git a/drivers/clk/tenstorrent/atlantis-ccu.c b/drivers/clk/tenstorre= nt/atlantis-ccu.c new file mode 100644 index 000000000000..a4ad2fc3b621 --- /dev/null +++ b/drivers/clk/tenstorrent/atlantis-ccu.c @@ -0,0 +1,939 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2026 Tenstorrent + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct atlantis_clk_common { + int clkid; + struct regmap *regmap; + struct clk_hw hw; +}; + +#define hw_to_atlantis_clk_common(_hw) \ + container_of((_hw), struct atlantis_clk_common, hw) + +struct atlantis_clk_mux_config { + u8 shift; + u8 width; + u32 reg_offset; +}; + +struct atlantis_clk_mux { + struct atlantis_clk_common common; + struct atlantis_clk_mux_config config; +}; + +struct atlantis_clk_gate_config { + u32 reg_offset; + u32 enable; +}; + +struct atlantis_clk_gate { + struct atlantis_clk_common common; + struct atlantis_clk_gate_config config; +}; + +struct atlantis_clk_divider_config { + u8 shift; + u8 width; + u32 flags; + u32 reg_offset; +}; + +struct atlantis_clk_divider { + struct atlantis_clk_common common; + struct atlantis_clk_divider_config config; +}; + +struct atlantis_clk_pll_config { + u32 tbl_num; + u32 reg_offset; + u32 en_reg_offset; + u32 cg_reg_offset; + u32 cg_reg_enable; +}; + +/* Models a PLL with Bypass Functionality and Enable Bit + a Gate Clock at= it's output */ +struct atlantis_clk_pll { + struct atlantis_clk_common common; + struct atlantis_clk_pll_config config; +}; + +struct atlantis_clk_gate_shared_config { + u32 reg_offset; + u32 enable; + unsigned int *share_count; + spinlock_t *refcount_lock; +}; + +struct atlantis_clk_gate_shared { + struct atlantis_clk_common common; + struct atlantis_clk_gate_shared_config config; +}; + +struct atlantis_clk_fixed_factor_config { + unsigned int mult; + unsigned int div; +}; + +struct atlantis_clk_fixed_factor { + struct atlantis_clk_fixed_factor_config config; + struct atlantis_clk_common common; +}; + +static inline struct atlantis_clk_mux *hw_to_atlantis_clk_mux(struct clk_h= w *hw) +{ + struct atlantis_clk_common *common =3D hw_to_atlantis_clk_common(hw); + + return container_of(common, struct atlantis_clk_mux, common); +} + +static inline struct atlantis_clk_gate * +hw_to_atlantis_clk_gate(struct clk_hw *hw) +{ + struct atlantis_clk_common *common =3D hw_to_atlantis_clk_common(hw); + + return container_of(common, struct atlantis_clk_gate, common); +} + +static inline struct atlantis_clk_divider * +hw_to_atlantis_clk_divider(struct clk_hw *hw) +{ + struct atlantis_clk_common *common =3D hw_to_atlantis_clk_common(hw); + + return container_of(common, struct atlantis_clk_divider, common); +} + +static inline struct atlantis_clk_pll *hw_to_atlantis_pll(struct clk_hw *h= w) +{ + struct atlantis_clk_common *common =3D hw_to_atlantis_clk_common(hw); + + return container_of(common, struct atlantis_clk_pll, common); +} + +static inline struct atlantis_clk_gate_shared * +hw_to_atlantis_clk_gate_shared(struct clk_hw *hw) +{ + struct atlantis_clk_common *common =3D hw_to_atlantis_clk_common(hw); + + return container_of(common, struct atlantis_clk_gate_shared, common); +} + +static inline struct atlantis_clk_fixed_factor * +hw_to_atlantis_clk_fixed_factor(struct clk_hw *hw) +{ + struct atlantis_clk_common *common =3D hw_to_atlantis_clk_common(hw); + + return container_of(common, struct atlantis_clk_fixed_factor, common); +} + +static u8 atlantis_clk_mux_get_parent(struct clk_hw *hw) +{ + struct atlantis_clk_mux *mux =3D hw_to_atlantis_clk_mux(hw); + u32 val; + + regmap_read(mux->common.regmap, mux->config.reg_offset, &val); + val >>=3D mux->config.shift; + val &=3D (BIT(mux->config.width) - 1); + + return val; +} + +static int atlantis_clk_mux_set_parent(struct clk_hw *hw, u8 index) +{ + struct atlantis_clk_mux *mux =3D hw_to_atlantis_clk_mux(hw); + u32 val =3D index; + + return regmap_update_bits(mux->common.regmap, mux->config.reg_offset, + (BIT(mux->config.width) - 1) + << mux->config.shift, + val << mux->config.shift); +} + +static int atlantis_clk_mux_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + return clk_mux_determine_rate_flags(hw, req, hw->init->flags); +} + +const struct clk_ops atlantis_clk_mux_ops =3D { + .get_parent =3D atlantis_clk_mux_get_parent, + .set_parent =3D atlantis_clk_mux_set_parent, + .determine_rate =3D atlantis_clk_mux_determine_rate, +}; + +static void atlantis_clk_gate_endisable(struct clk_hw *hw, int enable) +{ + struct atlantis_clk_gate *gate =3D hw_to_atlantis_clk_gate(hw); + u32 val; + + if (enable) + val =3D gate->config.enable; + else + val =3D ~(gate->config.enable); + + regmap_update_bits(gate->common.regmap, gate->config.reg_offset, + gate->config.enable, val); +} + +static int atlantis_clk_gate_enable(struct clk_hw *hw) +{ + atlantis_clk_gate_endisable(hw, 1); + + return 0; +} + +static void atlantis_clk_gate_disable(struct clk_hw *hw) +{ + atlantis_clk_gate_endisable(hw, 0); +} + +static int atlantis_clk_gate_is_enabled(struct clk_hw *hw) +{ + struct atlantis_clk_gate *gate =3D hw_to_atlantis_clk_gate(hw); + u32 val; + + regmap_read(gate->common.regmap, gate->config.reg_offset, &val); + + val &=3D gate->config.enable; + + return val ? 1 : 0; +} + +const struct clk_ops atlantis_clk_gate_ops =3D { + .enable =3D atlantis_clk_gate_enable, + .disable =3D atlantis_clk_gate_disable, + .is_enabled =3D atlantis_clk_gate_is_enabled, +}; + +static unsigned long atlantis_clk_divider_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct atlantis_clk_divider *divider =3D hw_to_atlantis_clk_divider(hw); + u32 val; + + regmap_read(divider->common.regmap, divider->config.reg_offset, &val); + + val >>=3D divider->config.shift; + val &=3D ((1 << (divider->config.width)) - 1); + + return DIV_ROUND_UP_ULL((u64)parent_rate, val + 1); +} + +const struct clk_ops atlantis_clk_divider_ops =3D { + .recalc_rate =3D atlantis_clk_divider_recalc_rate, +}; + +static unsigned long +atlantis_clk_fixed_factor_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct atlantis_clk_fixed_factor *factor =3D + hw_to_atlantis_clk_fixed_factor(hw); + unsigned long long rate; + + rate =3D (unsigned long long)parent_rate * factor->config.mult; + do_div(rate, factor->config.div); + return (unsigned long)rate; +} + +const struct clk_ops atlantis_clk_fixed_factor_ops =3D { + .recalc_rate =3D atlantis_clk_fixed_factor_recalc_rate, +}; + +static int atlantis_clk_pll_is_enabled(struct clk_hw *hw) +{ + struct atlantis_clk_pll *pll =3D hw_to_atlantis_pll(hw); + u32 val, en_val, cg_val; + + regmap_read(pll->common.regmap, pll->config.reg_offset, &val); + regmap_read(pll->common.regmap, pll->config.en_reg_offset, &en_val); + regmap_read(pll->common.regmap, pll->config.cg_reg_offset, &cg_val); + + /* Check if PLL is powered on, locked and Gate clk is enabled */ + return !!(en_val & PLL_CFG_EN_BIT) && !!(val & PLL_CFG_LOCK_BIT) && + !!(cg_val && pll->config.cg_reg_enable); +} + +static int atlantis_clk_pll_enable(struct clk_hw *hw) +{ + struct atlantis_clk_pll *pll =3D hw_to_atlantis_pll(hw); + u32 val, en_val, cg_val; + int ret; + + regmap_read(pll->common.regmap, pll->config.reg_offset, &val); + regmap_read(pll->common.regmap, pll->config.en_reg_offset, &en_val); + regmap_read(pll->common.regmap, pll->config.cg_reg_offset, &cg_val); + + /* Check if PLL is already enabled, locked and Gate clk is enabled */ + if ((en_val & PLL_CFG_EN_BIT) && (val & PLL_CFG_LOCK_BIT) && + (cg_val && pll->config.cg_reg_enable) && + !(val & PLL_CFG_BYPASS_BIT)) { + return 0; + } + + /* Step 1: Set bypass mode first */ + regmap_update_bits(pll->common.regmap, pll->config.reg_offset, + PLL_CFG_BYPASS_BIT, PLL_CFG_BYPASS_BIT); + + /* Step 2: Enable PLL (clear then set power bit) */ + regmap_update_bits(pll->common.regmap, pll->config.en_reg_offset, + PLL_CFG_EN_BIT, 0); + + regmap_update_bits(pll->common.regmap, pll->config.en_reg_offset, + PLL_CFG_EN_BIT, PLL_CFG_EN_BIT); + + /* Step 3: Wait for PLL lock */ + ret =3D regmap_read_poll_timeout(pll->common.regmap, + pll->config.reg_offset, val, + val & PLL_CFG_LOCK_BIT, 10, + PLL_BYPASS_WAIT_US); + if (ret) { + pr_err("PLL failed to lock within timeout\n"); + return ret; + } + + /* Step 4: Switch from bypass to PLL output */ + regmap_update_bits(pll->common.regmap, pll->config.reg_offset, + PLL_CFG_BYPASS_BIT, 0); + + /* Enable Gate clk at PLL Output */ + return regmap_update_bits(pll->common.regmap, pll->config.cg_reg_offset, + pll->config.cg_reg_enable, + pll->config.cg_reg_enable); +} + +static void atlantis_clk_pll_disable(struct clk_hw *hw) +{ + struct atlantis_clk_pll *pll =3D hw_to_atlantis_pll(hw); + + /* Step 1: Switch to bypass mode before disabling */ + regmap_update_bits(pll->common.regmap, pll->config.reg_offset, + PLL_CFG_BYPASS_BIT, PLL_CFG_BYPASS_BIT); + /* Step 2: Power down PLL */ + regmap_update_bits(pll->common.regmap, pll->config.en_reg_offset, + PLL_CFG_EN_BIT, 0); +} + +static unsigned long atlantis_clk_pll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct atlantis_clk_pll *pll =3D hw_to_atlantis_pll(hw); + + u32 val, refdiv, fbdiv, postdiv1, postdiv2; + u64 fout; + + regmap_read(pll->common.regmap, pll->config.reg_offset, &val); + + if (val & PLL_CFG_BYPASS_BIT) + return parent_rate; + + refdiv =3D FIELD_GET(PLL_CFG_REFDIV_MASK, val); + fbdiv =3D FIELD_GET(PLL_CFG_FBDIV_MASK, val); + postdiv1 =3D FIELD_GET(PLL_CFG_POSTDIV1_MASK, val); + postdiv2 =3D FIELD_GET(PLL_CFG_POSTDIV2_MASK, val); + + if (!refdiv) + refdiv =3D 1; + if (!postdiv1) + postdiv1 =3D 1; + if (!postdiv2) + postdiv2 =3D 1; + if (!fbdiv) + return 0; + + fout =3D div64_u64((u64)parent_rate * fbdiv, + refdiv * postdiv1 * postdiv2); + + return fout; +} + +const struct clk_ops atlantis_clk_pll_ops =3D { + .enable =3D atlantis_clk_pll_enable, + .disable =3D atlantis_clk_pll_disable, + .recalc_rate =3D atlantis_clk_pll_recalc_rate, + .is_enabled =3D atlantis_clk_pll_is_enabled, +}; + +static int atlantis_clk_gate_shared_enable(struct clk_hw *hw) +{ + struct atlantis_clk_gate_shared *gate =3D + hw_to_atlantis_clk_gate_shared(hw); + bool need_enable; + u32 reg; + + scoped_guard(spinlock_irqsave, gate->config.refcount_lock) + { + need_enable =3D (*gate->config.share_count)++ =3D=3D 0; + if (need_enable) { + regmap_read(gate->common.regmap, + gate->config.reg_offset, ®); + reg |=3D gate->config.enable; + regmap_write(gate->common.regmap, + gate->config.reg_offset, reg); + } + } + + if (need_enable) { + regmap_read(gate->common.regmap, gate->config.reg_offset, ®); + + if (!(reg & gate->config.enable)) { + pr_warn("%s: gate enable %d failed to enable\n", + clk_hw_get_name(hw), gate->config.enable); + return -EIO; + } + } + + return 0; +} + +static void atlantis_clk_gate_shared_disable(struct clk_hw *hw) +{ + struct atlantis_clk_gate_shared *gate =3D + hw_to_atlantis_clk_gate_shared(hw); + u32 reg; + + scoped_guard(spinlock_irqsave, gate->config.refcount_lock) + { + if (WARN_ON(*gate->config.share_count =3D=3D 0)) + return; + if (--(*gate->config.share_count) > 0) + return; + + regmap_read(gate->common.regmap, gate->config.reg_offset, ®); + reg &=3D ~gate->config.enable; + regmap_write(gate->common.regmap, gate->config.reg_offset, reg); + } +} + +static int atlantis_clk_gate_shared_is_enabled(struct clk_hw *hw) +{ + struct atlantis_clk_gate_shared *gate =3D + hw_to_atlantis_clk_gate_shared(hw); + u32 reg; + + regmap_read(gate->common.regmap, gate->config.reg_offset, ®); + + return !!(reg & gate->config.enable); +} + +static void atlantis_clk_gate_shared_disable_unused(struct clk_hw *hw) +{ + struct atlantis_clk_gate_shared *gate =3D + hw_to_atlantis_clk_gate_shared(hw); + + u32 reg; + + scoped_guard(spinlock_irqsave, gate->config.refcount_lock) + { + if (*gate->config.share_count =3D=3D 0) { + regmap_read(gate->common.regmap, + gate->config.reg_offset, ®); + reg &=3D ~gate->config.enable; + regmap_write(gate->common.regmap, + gate->config.reg_offset, reg); + } + } +} + +const struct clk_ops atlantis_clk_gate_shared_ops =3D { + .enable =3D atlantis_clk_gate_shared_enable, + .disable =3D atlantis_clk_gate_shared_disable, + .disable_unused =3D atlantis_clk_gate_shared_disable_unused, + .is_enabled =3D atlantis_clk_gate_shared_is_enabled, +}; + +#define ATLANTIS_PLL_CONFIG(_reg_offset, _en_reg_offset, _cg_reg_offset, \ + _cg_reg_enable) \ + { \ + .reg_offset =3D (_reg_offset), \ + .en_reg_offset =3D (_en_reg_offset), \ + .cg_reg_offset =3D (_cg_reg_offset), \ + .cg_reg_enable =3D (_cg_reg_enable), \ + } + +#define ATLANTIS_PLL_DEFINE(_clkid, _name, _parent, _reg_offset, = \ + _en_reg_offset, _cg_reg_offset, _cg_reg_enable, \ + _flags) \ + static struct atlantis_clk_pll _name =3D { \ + .config =3D ATLANTIS_PLL_CONFIG(_reg_offset, _en_reg_offset, \ + _cg_reg_offset, _cg_reg_enable), \ + .common =3D { .clkid =3D _clkid, \ + .hw.init =3D CLK_HW_INIT_PARENTS_DATA( \ + #_name, _parent, &atlantis_clk_pll_ops, \ + _flags) }, \ + } +#define ATLANTIS_MUX_CONFIG(_shift, _width, _reg_offset) = \ + { \ + .shift =3D _shift, .width =3D _width, .reg_offset =3D _reg_offset \ + } + +#define ATLANTIS_MUX_DEFINE(_clkid, _name, _parents, _reg_offset, _shift, = \ + _width, _flags) \ + static struct atlantis_clk_mux _name =3D { \ + .config =3D ATLANTIS_MUX_CONFIG(_shift, _width, _reg_offset), \ + .common =3D { .clkid =3D _clkid, \ + .hw.init =3D CLK_HW_INIT_PARENTS_DATA( \ + #_name, _parents, &atlantis_clk_mux_ops, \ + _flags) } \ + } + +#define ATLANTIS_DIVIDER_CONFIG(_shift, _width, _flags, _reg_offset) \ + { \ + .shift =3D _shift, .width =3D _width, .flags =3D _flags, \ + .reg_offset =3D _reg_offset \ + } + +#define ATLANTIS_DIVIDER_DEFINE(_clkid, _name, _parent, _reg_offset, _shif= t, \ + _width, _divflags, _flags) \ + static struct atlantis_clk_divider _name =3D { \ + .config =3D ATLANTIS_DIVIDER_CONFIG(_shift, _width, _divflags, \ + _reg_offset), \ + .common =3D { .clkid =3D _clkid, \ + .hw.init =3D CLK_HW_INIT_HW( \ + #_name, &_parent.common.hw, \ + &atlantis_clk_divider_ops, _flags) } \ + } +#define ATLANTIS_GATE_CONFIG(_enable, _reg_offset) \ + { \ + .enable =3D _enable, .reg_offset =3D _reg_offset \ + } + +#define ATLANTIS_GATE_DEFINE(_clkid, _name, _parent, _reg_offset, _enable,= \ + _flags) \ + static struct atlantis_clk_gate _name =3D { \ + .config =3D ATLANTIS_GATE_CONFIG(_enable, _reg_offset), \ + .common =3D { .clkid =3D _clkid, \ + .hw.init =3D CLK_HW_INIT_HW( \ + #_name, &_parent.common.hw, \ + &atlantis_clk_gate_ops, _flags) } \ + } +#define ATLANTIS_GATE_SHARED_CONFIG(_reg_offset, _enable, _share_count) = \ + { \ + .reg_offset =3D _reg_offset, .enable =3D _enable, \ + .share_count =3D _share_count, .refcount_lock =3D &refcount_lock \ + } +#define ATLANTIS_GATE_SHARED_DEFINE(_clkid, _name, _parent, _reg_offset, = \ + _enable, _share_count, _flags) \ + static struct atlantis_clk_gate_shared _name =3D { \ + .config =3D ATLANTIS_GATE_SHARED_CONFIG(_reg_offset, _enable, \ + _share_count), \ + .common =3D { .clkid =3D _clkid, \ + .hw.init =3D CLK_HW_INIT_HW( \ + #_name, &_parent.common.hw, \ + &atlantis_clk_gate_shared_ops, _flags) } \ + } +#define ATLANTIS_CLK_FIXED_FACTOR_DEFINE(_clkid, _name, _parent, _mult, _d= iv, \ + _flags) \ + static struct atlantis_clk_fixed_factor _name =3D { \ + .config =3D { .mult =3D _mult, .div =3D _div }, \ + .common =3D { .clkid =3D _clkid, \ + .hw.init =3D CLK_HW_INIT_HW( \ + #_name, &_parent.common.hw, \ + &atlantis_clk_fixed_factor_ops, _flags) } \ + } + +static DEFINE_SPINLOCK(refcount_lock); /* Lock for refcount value accesses= */ + +static const struct regmap_config atlantis_ccu_regmap_config =3D { + .reg_bits =3D 32, + .reg_stride =3D 4, + .val_bits =3D 32, + .max_register =3D 0xFFFC, + .cache_type =3D REGCACHE_NONE, +}; +struct atlantis_ccu { + struct device *dev; + + struct regmap *regmap; + void __iomem *base; + + struct clk_hw_onecell_data *clk_data; +}; + +struct atlantis_ccu_data { + struct clk_hw **hws; + size_t num; + const char *reset_name; +}; + +static const struct clk_parent_data osc_24m_clk[] =3D { + { .index =3D 0 }, +}; + +ATLANTIS_PLL_DEFINE(CLK_RCPU_PLL, rcpu_pll_clk, osc_24m_clk, RCPU_PLL_CFG_= REG, + PLL_RCPU_EN_REG, BUS_CG_REG, BIT(7), + CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_UNGATE | + CLK_IS_CRITICAL); + +static const struct clk_parent_data rcpu_root_parents[] =3D { + { .index =3D 0 }, + { .hw =3D &rcpu_pll_clk.common.hw }, +}; + +ATLANTIS_MUX_DEFINE(CLK_RCPU_ROOT, rcpu_root_mux, rcpu_root_parents, + RCPU_DIV_CFG_REG, 0, 1, CLK_SET_RATE_NO_REPARENT); + +ATLANTIS_DIVIDER_DEFINE(CLK_RCPU_DIV2, rcpu_div2_clk, rcpu_root_mux, + RCPU_DIV_CFG_REG, 2, 4, 0, 0); +ATLANTIS_DIVIDER_DEFINE(CLK_RCPU_DIV4, rcpu_div4_clk, rcpu_root_mux, + RCPU_DIV_CFG_REG, 7, 4, 0, 0); +ATLANTIS_DIVIDER_DEFINE(CLK_RCPU_RTC, rcpu_rtc_clk, rcpu_div4_clk, + RCPU_DIV_CFG_REG, 12, 6, 0, 0); + +ATLANTIS_GATE_DEFINE(CLK_SMNDMA0_ACLK, smndma0_aclk, rcpu_div2_clk, + RCPU_BLK_CG_REG, BIT(0), 0); +ATLANTIS_GATE_DEFINE(CLK_SMNDMA1_ACLK, smndma1_aclk, rcpu_div2_clk, + RCPU_BLK_CG_REG, BIT(1), 0); +ATLANTIS_GATE_DEFINE(CLK_WDT0_PCLK, wdt0_pclk, rcpu_div4_clk, RCPU_BLK_CG_= REG, + BIT(2), 0); +ATLANTIS_GATE_DEFINE(CLK_WDT1_PCLK, wdt1_pclk, rcpu_div4_clk, RCPU_BLK_CG_= REG, + BIT(3), 0); +ATLANTIS_GATE_DEFINE(CLK_TIMER_PCLK, timer_pclk, rcpu_div4_clk, RCPU_BLK_C= G_REG, + BIT(4), 0); +ATLANTIS_GATE_DEFINE(CLK_PVTC_PCLK, pvtc_pclk, rcpu_div4_clk, RCPU_BLK_CG_= REG, + BIT(12), 0); +ATLANTIS_GATE_DEFINE(CLK_PMU_PCLK, pmu_pclk, rcpu_div4_clk, RCPU_BLK_CG_RE= G, + BIT(13), 0); +ATLANTIS_GATE_DEFINE(CLK_MAILBOX_HCLK, mb_hclk, rcpu_div2_clk, RCPU_BLK_CG= _REG, + BIT(14), 0); +ATLANTIS_GATE_DEFINE(CLK_SEC_SPACC_HCLK, sec_spacc_hclk, rcpu_div2_clk, + RCPU_BLK_CG_REG, BIT(26), 0); +ATLANTIS_GATE_DEFINE(CLK_SEC_OTP_HCLK, sec_otp_hclk, rcpu_div2_clk, + RCPU_BLK_CG_REG, BIT(28), 0); +ATLANTIS_GATE_DEFINE(CLK_TRNG_PCLK, trng_pclk, rcpu_div4_clk, RCPU_BLK_CG_= REG, + BIT(29), 0); +ATLANTIS_GATE_DEFINE(CLK_SEC_CRC_HCLK, sec_crc_hclk, rcpu_div2_clk, + RCPU_BLK_CG_REG, BIT(30), 0); + +ATLANTIS_CLK_FIXED_FACTOR_DEFINE(CLK_SMN_HCLK, rcpu_smn_hclk, rcpu_div2_cl= k, 1, + 1, 0); +ATLANTIS_CLK_FIXED_FACTOR_DEFINE(CLK_AHB0_HCLK, rcpu_ahb0_hclk, rcpu_div2_= clk, + 1, 1, 0); + +ATLANTIS_CLK_FIXED_FACTOR_DEFINE(CLK_SMN_PCLK, rcpu_smn_pclk, rcpu_div4_cl= k, 1, + 1, 0); + +ATLANTIS_CLK_FIXED_FACTOR_DEFINE(CLK_SMN_CLK, rcpu_smn_clk, rcpu_root_mux,= 1, 1, + 0); +ATLANTIS_CLK_FIXED_FACTOR_DEFINE(CLK_SCRATCHPAD_CLK, rcpu_scratchpad_aclk, + rcpu_root_mux, 1, 1, 0); +ATLANTIS_CLK_FIXED_FACTOR_DEFINE(CLK_RCPU_CORE_CLK, rcpu_core_clk, + rcpu_root_mux, 1, 1, 0); +ATLANTIS_CLK_FIXED_FACTOR_DEFINE(CLK_RCPU_ROM_CLK, rcpu_rom_aclk, rcpu_roo= t_mux, + 1, 1, 0); + +static struct atlantis_clk_fixed_factor + otp_load_clk =3D { .config =3D { .mult =3D 1, .div =3D 1 }, + .common =3D { + .clkid =3D CLK_OTP_LOAD_CLK, + .hw.init =3D CLK_HW_INIT_PARENTS_DATA( + "otp_load_clk", osc_24m_clk, + &atlantis_clk_fixed_factor_ops, + CLK_SET_RATE_NO_REPARENT), + } }; + +ATLANTIS_PLL_DEFINE(CLK_NOC_PLL, nocc_pll_clk, osc_24m_clk, + RCPU_NOCC_PLL_CFG_REG, PLL_NOCC_EN_REG, BUS_CG_REG, BIT(0), + CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_UNGATE | + CLK_IS_CRITICAL); + +static const struct clk_parent_data nocc_mux_parents[] =3D { + { .index =3D 0 }, + { .hw =3D &nocc_pll_clk.common.hw }, +}; + +ATLANTIS_MUX_DEFINE(CLK_NOCC_CLK, nocc_clk_mux, nocc_mux_parents, + RCPU_NOCC_CLK_CFG_REG, 0, 1, CLK_SET_RATE_NO_REPARENT); + +ATLANTIS_DIVIDER_DEFINE(CLK_NOCC_DIV2, nocc_div2_clk, nocc_clk_mux, + RCPU_NOCC_CLK_CFG_REG, 1, 4, 0, 0); +ATLANTIS_DIVIDER_DEFINE(CLK_NOCC_DIV4, nocc_div4_clk, nocc_clk_mux, + RCPU_NOCC_CLK_CFG_REG, 5, 4, 0, 0); +ATLANTIS_DIVIDER_DEFINE(CLK_NOCC_RTC, nocc_rtc_clk, nocc_div4_clk, + RCPU_NOCC_CLK_CFG_REG, 9, 6, 0, 0); +ATLANTIS_DIVIDER_DEFINE(CLK_NOCC_CAN, nocc_can_div, nocc_clk_mux, + RCPU_NOCC_CLK_CFG_REG, 15, 4, 0, 0); + +static unsigned int refcnt_qspi; +ATLANTIS_GATE_SHARED_DEFINE(CLK_QSPI_SCLK, qspi_sclk, nocc_clk_mux, + LSIO_BLK_CG_REG, BIT(0), &refcnt_qspi, 0); +ATLANTIS_GATE_SHARED_DEFINE(CLK_QSPI_HCLK, qspi_hclk, nocc_div2_clk, + LSIO_BLK_CG_REG, BIT(0), &refcnt_qspi, 0); +ATLANTIS_GATE_DEFINE(CLK_I2C0_PCLK, i2c0_pclk, nocc_div4_clk, LSIO_BLK_CG_= REG, + BIT(1), 0); +ATLANTIS_GATE_DEFINE(CLK_I2C1_PCLK, i2c1_pclk, nocc_div4_clk, LSIO_BLK_CG_= REG, + BIT(2), 0); +ATLANTIS_GATE_DEFINE(CLK_I2C2_PCLK, i2c2_pclk, nocc_div4_clk, LSIO_BLK_CG_= REG, + BIT(3), 0); +ATLANTIS_GATE_DEFINE(CLK_I2C3_PCLK, i2c3_pclk, nocc_div4_clk, LSIO_BLK_CG_= REG, + BIT(4), 0); +ATLANTIS_GATE_DEFINE(CLK_I2C4_PCLK, i2c4_pclk, nocc_div4_clk, LSIO_BLK_CG_= REG, + BIT(5), 0); + +ATLANTIS_GATE_DEFINE(CLK_UART0_PCLK, uart0_pclk, nocc_div4_clk, LSIO_BLK_C= G_REG, + BIT(6), 0); +ATLANTIS_GATE_DEFINE(CLK_UART1_PCLK, uart1_pclk, nocc_div4_clk, LSIO_BLK_C= G_REG, + BIT(7), 0); +ATLANTIS_GATE_DEFINE(CLK_UART2_PCLK, uart2_pclk, nocc_div4_clk, LSIO_BLK_C= G_REG, + BIT(8), 0); +ATLANTIS_GATE_DEFINE(CLK_UART3_PCLK, uart3_pclk, nocc_div4_clk, LSIO_BLK_C= G_REG, + BIT(9), 0); +ATLANTIS_GATE_DEFINE(CLK_UART4_PCLK, uart4_pclk, nocc_div4_clk, LSIO_BLK_C= G_REG, + BIT(10), 0); +ATLANTIS_GATE_DEFINE(CLK_SPI0_PCLK, spi0_pclk, nocc_div4_clk, LSIO_BLK_CG_= REG, + BIT(11), 0); +ATLANTIS_GATE_DEFINE(CLK_SPI1_PCLK, spi1_pclk, nocc_div4_clk, LSIO_BLK_CG_= REG, + BIT(12), 0); +ATLANTIS_GATE_DEFINE(CLK_SPI2_PCLK, spi2_pclk, nocc_div4_clk, LSIO_BLK_CG_= REG, + BIT(13), 0); +ATLANTIS_GATE_DEFINE(CLK_SPI3_PCLK, spi3_pclk, nocc_div4_clk, LSIO_BLK_CG_= REG, + BIT(14), 0); +ATLANTIS_GATE_DEFINE(CLK_GPIO_PCLK, gpio_pclk, nocc_div4_clk, LSIO_BLK_CG_= REG, + BIT(15), 0); + +static unsigned int refcnt_can0; +ATLANTIS_GATE_SHARED_DEFINE(CLK_CAN0_HCLK, can0_hclk, nocc_div2_clk, + LSIO_BLK_CG_REG, BIT(17), &refcnt_can0, 0); +ATLANTIS_GATE_SHARED_DEFINE(CLK_CAN0_CLK, can0_clk, nocc_can_div, + LSIO_BLK_CG_REG, BIT(17), &refcnt_can0, 0); + +static unsigned int refcnt_can1; +ATLANTIS_GATE_SHARED_DEFINE(CLK_CAN1_HCLK, can1_hclk, nocc_div2_clk, + LSIO_BLK_CG_REG, BIT(18), &refcnt_can1, 0); +ATLANTIS_GATE_SHARED_DEFINE(CLK_CAN1_CLK, can1_clk, nocc_can_div, + LSIO_BLK_CG_REG, BIT(18), &refcnt_can1, 0); + +ATLANTIS_CLK_FIXED_FACTOR_DEFINE(CLK_CAN0_TIMER_CLK, can0_timer_clk, + nocc_rtc_clk, 1, 1, 0); +ATLANTIS_CLK_FIXED_FACTOR_DEFINE(CLK_CAN1_TIMER_CLK, can1_timer_clk, + nocc_rtc_clk, 1, 1, 0); + +static struct clk_hw *atlantis_rcpu_clks[] =3D { + [CLK_RCPU_PLL] =3D &rcpu_pll_clk.common.hw, + [CLK_RCPU_ROOT] =3D &rcpu_root_mux.common.hw, + [CLK_RCPU_DIV2] =3D &rcpu_div2_clk.common.hw, + [CLK_RCPU_DIV4] =3D &rcpu_div4_clk.common.hw, + [CLK_RCPU_RTC] =3D &rcpu_rtc_clk.common.hw, + [CLK_SMNDMA0_ACLK] =3D &smndma0_aclk.common.hw, + [CLK_SMNDMA1_ACLK] =3D &smndma1_aclk.common.hw, + [CLK_WDT0_PCLK] =3D &wdt0_pclk.common.hw, + [CLK_WDT1_PCLK] =3D &wdt1_pclk.common.hw, + [CLK_TIMER_PCLK] =3D &timer_pclk.common.hw, + [CLK_PVTC_PCLK] =3D &pvtc_pclk.common.hw, + [CLK_PMU_PCLK] =3D &pmu_pclk.common.hw, + [CLK_MAILBOX_HCLK] =3D &mb_hclk.common.hw, + [CLK_SEC_SPACC_HCLK] =3D &sec_spacc_hclk.common.hw, + [CLK_SEC_OTP_HCLK] =3D &sec_otp_hclk.common.hw, + [CLK_TRNG_PCLK] =3D &trng_pclk.common.hw, + [CLK_SEC_CRC_HCLK] =3D &sec_crc_hclk.common.hw, + [CLK_SMN_HCLK] =3D &rcpu_smn_hclk.common.hw, + [CLK_AHB0_HCLK] =3D &rcpu_ahb0_hclk.common.hw, + [CLK_SMN_PCLK] =3D &rcpu_smn_pclk.common.hw, + [CLK_SMN_CLK] =3D &rcpu_smn_clk.common.hw, + [CLK_SCRATCHPAD_CLK] =3D &rcpu_scratchpad_aclk.common.hw, + [CLK_RCPU_CORE_CLK] =3D &rcpu_core_clk.common.hw, + [CLK_RCPU_ROM_CLK] =3D &rcpu_rom_aclk.common.hw, + [CLK_OTP_LOAD_CLK] =3D &otp_load_clk.common.hw, + [CLK_NOC_PLL] =3D &nocc_pll_clk.common.hw, + [CLK_NOCC_CLK] =3D &nocc_clk_mux.common.hw, + [CLK_NOCC_DIV2] =3D &nocc_div2_clk.common.hw, + [CLK_NOCC_DIV4] =3D &nocc_div4_clk.common.hw, + [CLK_NOCC_RTC] =3D &nocc_rtc_clk.common.hw, + [CLK_NOCC_CAN] =3D &nocc_can_div.common.hw, + [CLK_QSPI_SCLK] =3D &qspi_sclk.common.hw, + [CLK_QSPI_HCLK] =3D &qspi_hclk.common.hw, + [CLK_I2C0_PCLK] =3D &i2c0_pclk.common.hw, + [CLK_I2C1_PCLK] =3D &i2c1_pclk.common.hw, + [CLK_I2C2_PCLK] =3D &i2c2_pclk.common.hw, + [CLK_I2C3_PCLK] =3D &i2c3_pclk.common.hw, + [CLK_I2C4_PCLK] =3D &i2c4_pclk.common.hw, + [CLK_UART0_PCLK] =3D &uart0_pclk.common.hw, + [CLK_UART1_PCLK] =3D &uart1_pclk.common.hw, + [CLK_UART2_PCLK] =3D &uart2_pclk.common.hw, + [CLK_UART3_PCLK] =3D &uart3_pclk.common.hw, + [CLK_UART4_PCLK] =3D &uart4_pclk.common.hw, + [CLK_SPI0_PCLK] =3D &spi0_pclk.common.hw, + [CLK_SPI1_PCLK] =3D &spi1_pclk.common.hw, + [CLK_SPI2_PCLK] =3D &spi2_pclk.common.hw, + [CLK_SPI3_PCLK] =3D &spi3_pclk.common.hw, + [CLK_GPIO_PCLK] =3D &gpio_pclk.common.hw, + [CLK_CAN0_HCLK] =3D &can0_hclk.common.hw, + [CLK_CAN0_CLK] =3D &can0_clk.common.hw, + [CLK_CAN1_HCLK] =3D &can1_hclk.common.hw, + [CLK_CAN1_CLK] =3D &can1_clk.common.hw, + [CLK_CAN0_TIMER_CLK] =3D &can0_timer_clk.common.hw, + [CLK_CAN1_TIMER_CLK] =3D &can1_timer_clk.common.hw, +}; + +static const struct atlantis_ccu_data atlantis_ccu_rcpu_data =3D { + .hws =3D atlantis_rcpu_clks, + .num =3D ARRAY_SIZE(atlantis_rcpu_clks), + .reset_name =3D "rcpu-reset" +}; + +static int atlantis_ccu_clocks_register(struct device *dev, + struct atlantis_ccu *ccu, + const struct atlantis_ccu_data *data) +{ + struct regmap *regmap =3D ccu->regmap; + struct clk_hw_onecell_data *clk_data; + int i, ret; + size_t num_clks =3D data->num; + + clk_data =3D devm_kzalloc(dev, struct_size(clk_data, hws, data->num), + GFP_KERNEL); + if (!clk_data) + return -ENOMEM; + + ccu->clk_data =3D clk_data; + + for (i =3D 0; i < data->num; i++) { + struct clk_hw *hw =3D data->hws[i]; + const char *name =3D hw->init->name; + struct atlantis_clk_common *common =3D + hw_to_atlantis_clk_common(hw); + common->regmap =3D regmap; + + ret =3D devm_clk_hw_register(dev, hw); + + if (ret) { + dev_err(dev, "Cannot register clock %d - %s\n", i, + name); + return ret; + } + + clk_data->hws[common->clkid] =3D hw; + } + + clk_data->num =3D num_clks; + + ret =3D devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clk_data); + if (ret) + dev_err(dev, "failed to add clock hardware provider (%d)\n", + ret); + + return ret; +} + +static void atlantis_cadev_release(struct device *dev) +{ + struct auxiliary_device *adev =3D to_auxiliary_dev(dev); + + kfree(to_atlantis_ccu_adev(adev)); +} + +static void atlantis_adev_unregister(void *data) +{ + struct auxiliary_device *adev =3D data; + + auxiliary_device_delete(adev); + auxiliary_device_uninit(adev); +} + +static int atlantis_ccu_adev_register(struct device *dev, + struct atlantis_ccu *ccu, + const struct atlantis_ccu_data *data, + const char *adev_name) +{ + struct atlantis_ccu_adev *cadev; + struct auxiliary_device *adev; + int ret; + + cadev =3D kzalloc(sizeof(*cadev), GFP_KERNEL); + if (!cadev) + return -ENOMEM; + + cadev->regmap =3D ccu->regmap; + + adev =3D &cadev->adev; + adev->name =3D adev_name; + adev->dev.parent =3D dev; + adev->dev.release =3D atlantis_cadev_release; + adev->dev.of_node =3D dev->of_node; + + ret =3D auxiliary_device_init(adev); + if (ret) + goto err_free_cadev; + + ret =3D auxiliary_device_add(adev); + if (ret) { + auxiliary_device_uninit(adev); + return ret; + } + + return devm_add_action_or_reset(dev, atlantis_adev_unregister, adev); + +err_free_cadev: + kfree(cadev); + + return ret; +} +static int atlantis_ccu_probe(struct platform_device *pdev) +{ + const struct atlantis_ccu_data *data; + struct device *dev =3D &pdev->dev; + int ret; + + struct atlantis_ccu *ccu =3D devm_kzalloc(dev, sizeof(*ccu), GFP_KERNEL); + + if (!ccu) + return -ENOMEM; + + ccu->dev =3D dev; + + ccu->base =3D devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(ccu->base)) + return dev_err_probe(dev, PTR_ERR(ccu->base), + "Failed to map registers\n"); + + ccu->regmap =3D devm_regmap_init_mmio(dev, ccu->base, + &atlantis_ccu_regmap_config); + if (IS_ERR(ccu->regmap)) + return dev_err_probe(dev, PTR_ERR(ccu->regmap), + "Failed to init regmap\n"); + + data =3D of_device_get_match_data(dev); + + ret =3D atlantis_ccu_clocks_register(dev, ccu, data); + if (ret) + return dev_err_probe(dev, ret, "failed to register clocks\n"); + + ret =3D atlantis_ccu_adev_register(dev, ccu, data, data->reset_name); + if (ret) + return dev_err_probe(dev, ret, "failed to register resets\n"); + + return 0; +} + +static const struct of_device_id atlantis_ccu_of_match[] =3D { + { + .compatible =3D "tenstorrent,atlantis-syscon-rcpu", + .data =3D &atlantis_ccu_rcpu_data, + }, + {} + +}; +MODULE_DEVICE_TABLE(of, atlantis_ccu_of_match); + +static struct platform_driver atlantis_ccu_driver =3D { + .probe =3D atlantis_ccu_probe, + .driver =3D { + .name =3D "atlantis-ccu", + .of_match_table =3D atlantis_ccu_of_match, + }, +}; +module_platform_driver(atlantis_ccu_driver); + +MODULE_DESCRIPTION("Tenstorrent Atlantis Clock Controller Driver"); +MODULE_AUTHOR("Anirudh Srinivasan "); +MODULE_LICENSE("GPL"); diff --git a/include/soc/tenstorrent/atlantis-syscon.h b/include/soc/tensto= rrent/atlantis-syscon.h index 2c6387e5c21a..541b8c2f56c1 100644 --- a/include/soc/tenstorrent/atlantis-syscon.h +++ b/include/soc/tenstorrent/atlantis-syscon.h @@ -16,6 +16,17 @@ struct atlantis_ccu_adev { #define to_atlantis_ccu_adev(_adev) \ container_of((_adev), struct atlantis_ccu_adev, adev) =20 +/* RCPU Clock Register Offsets */ +#define RCPU_PLL_CFG_REG 0x0000 +#define RCPU_NOCC_PLL_CFG_REG 0x0004 +#define RCPU_NOCC_CLK_CFG_REG 0x0008 +#define RCPU_DIV_CFG_REG 0x000C +#define RCPU_BLK_CG_REG 0x0014 +#define LSIO_BLK_CG_REG 0x0018 +#define PLL_RCPU_EN_REG 0x011c +#define PLL_NOCC_EN_REG 0x0120 +#define BUS_CG_REG 0x01FC + /* RCPU Reset Register Offsets */ #define RCPU_BLK_RST_REG 0x001c #define LSIO_BLK_RST_REG 0x0020 @@ -23,4 +34,20 @@ struct atlantis_ccu_adev { #define PCIE_SUBS_RST_REG 0x0000 #define MM_RSTN_REG 0x0014 =20 +/* PLL Bit Definitions */ +#define PLL_CFG_EN_BIT BIT(0) +#define PLL_CFG_BYPASS_BIT BIT(1) +#define PLL_CFG_REFDIV_MASK GENMASK(7, 2) +#define PLL_CFG_REFDIV_SHIFT 2 +#define PLL_CFG_POSTDIV1_MASK GENMASK(10, 8) +#define PLL_CFG_POSTDIV1_SHIFT 8 +#define PLL_CFG_POSTDIV2_MASK GENMASK(13, 11) +#define PLL_CFG_POSTDIV2_SHIFT 11 +#define PLL_CFG_FBDIV_MASK GENMASK(25, 14) +#define PLL_CFG_FBDIV_SHIFT 14 +#define PLL_CFG_LKDT_BIT BIT(30) +#define PLL_CFG_LOCK_BIT BIT(31) +#define PLL_LOCK_TIMEOUT_US 1000 +#define PLL_BYPASS_WAIT_US 500 + #endif --=20 2.43.0