From patchwork Mon Jul 12 22:04:34 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Iwona Winiarska X-Patchwork-Id: 473196 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3B1FDC11F66 for ; Mon, 12 Jul 2021 22:07:34 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 285F561242 for ; Mon, 12 Jul 2021 22:07:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230030AbhGLWKW (ORCPT ); Mon, 12 Jul 2021 18:10:22 -0400 Received: from mga11.intel.com ([192.55.52.93]:15028 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229503AbhGLWKW (ORCPT ); Mon, 12 Jul 2021 18:10:22 -0400 X-IronPort-AV: E=McAfee;i="6200,9189,10043"; a="207045610" X-IronPort-AV: E=Sophos;i="5.84,235,1620716400"; d="scan'208";a="207045610" Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Jul 2021 15:07:32 -0700 X-IronPort-AV: E=Sophos;i="5.84,235,1620716400"; d="scan'208";a="464367464" Received: from jzloch-mobl1.ger.corp.intel.com (HELO localhost) ([10.249.136.11]) by fmsmga008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Jul 2021 15:07:27 -0700 From: Iwona Winiarska To: linux-kernel@vger.kernel.org, openbmc@lists.ozlabs.org Cc: x86@kernel.org, devicetree@vger.kernel.org, linux-aspeed@lists.ozlabs.org, linux-arm-kernel@lists.infradead.org, linux-hwmon@vger.kernel.org, linux-doc@vger.kernel.org, Greg Kroah-Hartman , Rob Herring , Joel Stanley , Andrew Jeffery , Jean Delvare , Guenter Roeck , Jonathan Corbet , Thomas Gleixner , Andy Lutomirski , Ingo Molnar , Borislav Petkov , Yazen Ghannam , Mauro Carvalho Chehab , Pierre-Louis Bossart , Tony Luck , Andy Shevchenko , Jae Hyun Yoo , Iwona Winiarska Subject: [PATCH 01/14] x86/cpu: Move intel-family to arch-independent headers Date: Tue, 13 Jul 2021 00:04:34 +0200 Message-Id: <20210712220447.957418-2-iwona.winiarska@intel.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210712220447.957418-1-iwona.winiarska@intel.com> References: <20210712220447.957418-1-iwona.winiarska@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Baseboard management controllers (BMC) often run Linux but are usually implemented with non-X86 processors. They can use PECI to access package config space (PCS) registers on the host CPU and since some information, e.g. figuring out the core count, can be obtained using different registers on different CPU generations, they need to decode the family and model. Move the data from arch/x86/include/asm/intel-family.h into a new file include/linux/x86/intel-family.h so that it can be used by other architectures. Signed-off-by: Iwona Winiarska Reviewed-by: Tony Luck Reviewed-by: Dan Williams --- To limit tree-wide changes and help people that were expecting intel-family defines in arch/x86 to find it more easily without going through git history, we're not removing the original header completely, we're keeping it as a "stub" that includes the new one. If there is a consensus that the tree-wide option is better, we can choose this approach. MAINTAINERS | 1 + arch/x86/include/asm/intel-family.h | 141 +-------------------------- include/linux/x86/intel-family.h | 146 ++++++++++++++++++++++++++++ 3 files changed, 148 insertions(+), 140 deletions(-) create mode 100644 include/linux/x86/intel-family.h diff --git a/MAINTAINERS b/MAINTAINERS index a61f4f3b78a9..ec5987a00800 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9240,6 +9240,7 @@ M: x86@kernel.org L: linux-kernel@vger.kernel.org S: Supported F: arch/x86/include/asm/intel-family.h +F: include/linux/x86/intel-family.h INTEL DRM DRIVERS (excluding Poulsbo, Moorestown and derivative chipsets) M: Jani Nikula diff --git a/arch/x86/include/asm/intel-family.h b/arch/x86/include/asm/intel-family.h index 27158436f322..0d4fe1b4e1f6 100644 --- a/arch/x86/include/asm/intel-family.h +++ b/arch/x86/include/asm/intel-family.h @@ -2,145 +2,6 @@ #ifndef _ASM_X86_INTEL_FAMILY_H #define _ASM_X86_INTEL_FAMILY_H -/* - * "Big Core" Processors (Branded as Core, Xeon, etc...) - * - * While adding a new CPUID for a new microarchitecture, add a new - * group to keep logically sorted out in chronological order. Within - * that group keep the CPUID for the variants sorted by model number. - * - * The defined symbol names have the following form: - * INTEL_FAM6{OPTFAMILY}_{MICROARCH}{OPTDIFF} - * where: - * OPTFAMILY Describes the family of CPUs that this belongs to. Default - * is assumed to be "_CORE" (and should be omitted). Other values - * currently in use are _ATOM and _XEON_PHI - * MICROARCH Is the code name for the micro-architecture for this core. - * N.B. Not the platform name. - * OPTDIFF If needed, a short string to differentiate by market segment. - * - * Common OPTDIFFs: - * - * - regular client parts - * _L - regular mobile parts - * _G - parts with extra graphics on - * _X - regular server parts - * _D - micro server parts - * - * Historical OPTDIFFs: - * - * _EP - 2 socket server parts - * _EX - 4+ socket server parts - * - * The #define line may optionally include a comment including platform or core - * names. An exception is made for skylake/kabylake where steppings seem to have gotten - * their own names :-( - */ - -/* Wildcard match for FAM6 so X86_MATCH_INTEL_FAM6_MODEL(ANY) works */ -#define INTEL_FAM6_ANY X86_MODEL_ANY - -#define INTEL_FAM6_CORE_YONAH 0x0E - -#define INTEL_FAM6_CORE2_MEROM 0x0F -#define INTEL_FAM6_CORE2_MEROM_L 0x16 -#define INTEL_FAM6_CORE2_PENRYN 0x17 -#define INTEL_FAM6_CORE2_DUNNINGTON 0x1D - -#define INTEL_FAM6_NEHALEM 0x1E -#define INTEL_FAM6_NEHALEM_G 0x1F /* Auburndale / Havendale */ -#define INTEL_FAM6_NEHALEM_EP 0x1A -#define INTEL_FAM6_NEHALEM_EX 0x2E - -#define INTEL_FAM6_WESTMERE 0x25 -#define INTEL_FAM6_WESTMERE_EP 0x2C -#define INTEL_FAM6_WESTMERE_EX 0x2F - -#define INTEL_FAM6_SANDYBRIDGE 0x2A -#define INTEL_FAM6_SANDYBRIDGE_X 0x2D -#define INTEL_FAM6_IVYBRIDGE 0x3A -#define INTEL_FAM6_IVYBRIDGE_X 0x3E - -#define INTEL_FAM6_HASWELL 0x3C -#define INTEL_FAM6_HASWELL_X 0x3F -#define INTEL_FAM6_HASWELL_L 0x45 -#define INTEL_FAM6_HASWELL_G 0x46 - -#define INTEL_FAM6_BROADWELL 0x3D -#define INTEL_FAM6_BROADWELL_G 0x47 -#define INTEL_FAM6_BROADWELL_X 0x4F -#define INTEL_FAM6_BROADWELL_D 0x56 - -#define INTEL_FAM6_SKYLAKE_L 0x4E /* Sky Lake */ -#define INTEL_FAM6_SKYLAKE 0x5E /* Sky Lake */ -#define INTEL_FAM6_SKYLAKE_X 0x55 /* Sky Lake */ -/* CASCADELAKE_X 0x55 Sky Lake -- s: 7 */ -/* COOPERLAKE_X 0x55 Sky Lake -- s: 11 */ - -#define INTEL_FAM6_KABYLAKE_L 0x8E /* Sky Lake */ -/* AMBERLAKE_L 0x8E Sky Lake -- s: 9 */ -/* COFFEELAKE_L 0x8E Sky Lake -- s: 10 */ -/* WHISKEYLAKE_L 0x8E Sky Lake -- s: 11,12 */ - -#define INTEL_FAM6_KABYLAKE 0x9E /* Sky Lake */ -/* COFFEELAKE 0x9E Sky Lake -- s: 10-13 */ - -#define INTEL_FAM6_COMETLAKE 0xA5 /* Sky Lake */ -#define INTEL_FAM6_COMETLAKE_L 0xA6 /* Sky Lake */ - -#define INTEL_FAM6_CANNONLAKE_L 0x66 /* Palm Cove */ - -#define INTEL_FAM6_ICELAKE_X 0x6A /* Sunny Cove */ -#define INTEL_FAM6_ICELAKE_D 0x6C /* Sunny Cove */ -#define INTEL_FAM6_ICELAKE 0x7D /* Sunny Cove */ -#define INTEL_FAM6_ICELAKE_L 0x7E /* Sunny Cove */ -#define INTEL_FAM6_ICELAKE_NNPI 0x9D /* Sunny Cove */ - -#define INTEL_FAM6_LAKEFIELD 0x8A /* Sunny Cove / Tremont */ - -#define INTEL_FAM6_ROCKETLAKE 0xA7 /* Cypress Cove */ - -#define INTEL_FAM6_TIGERLAKE_L 0x8C /* Willow Cove */ -#define INTEL_FAM6_TIGERLAKE 0x8D /* Willow Cove */ - -#define INTEL_FAM6_SAPPHIRERAPIDS_X 0x8F /* Golden Cove */ - -#define INTEL_FAM6_ALDERLAKE 0x97 /* Golden Cove / Gracemont */ -#define INTEL_FAM6_ALDERLAKE_L 0x9A /* Golden Cove / Gracemont */ - -/* "Small Core" Processors (Atom) */ - -#define INTEL_FAM6_ATOM_BONNELL 0x1C /* Diamondville, Pineview */ -#define INTEL_FAM6_ATOM_BONNELL_MID 0x26 /* Silverthorne, Lincroft */ - -#define INTEL_FAM6_ATOM_SALTWELL 0x36 /* Cedarview */ -#define INTEL_FAM6_ATOM_SALTWELL_MID 0x27 /* Penwell */ -#define INTEL_FAM6_ATOM_SALTWELL_TABLET 0x35 /* Cloverview */ - -#define INTEL_FAM6_ATOM_SILVERMONT 0x37 /* Bay Trail, Valleyview */ -#define INTEL_FAM6_ATOM_SILVERMONT_D 0x4D /* Avaton, Rangely */ -#define INTEL_FAM6_ATOM_SILVERMONT_MID 0x4A /* Merriefield */ - -#define INTEL_FAM6_ATOM_AIRMONT 0x4C /* Cherry Trail, Braswell */ -#define INTEL_FAM6_ATOM_AIRMONT_MID 0x5A /* Moorefield */ -#define INTEL_FAM6_ATOM_AIRMONT_NP 0x75 /* Lightning Mountain */ - -#define INTEL_FAM6_ATOM_GOLDMONT 0x5C /* Apollo Lake */ -#define INTEL_FAM6_ATOM_GOLDMONT_D 0x5F /* Denverton */ - -/* Note: the micro-architecture is "Goldmont Plus" */ -#define INTEL_FAM6_ATOM_GOLDMONT_PLUS 0x7A /* Gemini Lake */ - -#define INTEL_FAM6_ATOM_TREMONT_D 0x86 /* Jacobsville */ -#define INTEL_FAM6_ATOM_TREMONT 0x96 /* Elkhart Lake */ -#define INTEL_FAM6_ATOM_TREMONT_L 0x9C /* Jasper Lake */ - -/* Xeon Phi */ - -#define INTEL_FAM6_XEON_PHI_KNL 0x57 /* Knights Landing */ -#define INTEL_FAM6_XEON_PHI_KNM 0x85 /* Knights Mill */ - -/* Family 5 */ -#define INTEL_FAM5_QUARK_X1000 0x09 /* Quark X1000 SoC */ +#include #endif /* _ASM_X86_INTEL_FAMILY_H */ diff --git a/include/linux/x86/intel-family.h b/include/linux/x86/intel-family.h new file mode 100644 index 000000000000..ae4b075c1ab9 --- /dev/null +++ b/include/linux/x86/intel-family.h @@ -0,0 +1,146 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_X86_INTEL_FAMILY_H +#define _LINUX_X86_INTEL_FAMILY_H + +/* + * "Big Core" Processors (Branded as Core, Xeon, etc...) + * + * While adding a new CPUID for a new microarchitecture, add a new + * group to keep logically sorted out in chronological order. Within + * that group keep the CPUID for the variants sorted by model number. + * + * The defined symbol names have the following form: + * INTEL_FAM6{OPTFAMILY}_{MICROARCH}{OPTDIFF} + * where: + * OPTFAMILY Describes the family of CPUs that this belongs to. Default + * is assumed to be "_CORE" (and should be omitted). Other values + * currently in use are _ATOM and _XEON_PHI + * MICROARCH Is the code name for the micro-architecture for this core. + * N.B. Not the platform name. + * OPTDIFF If needed, a short string to differentiate by market segment. + * + * Common OPTDIFFs: + * + * - regular client parts + * _L - regular mobile parts + * _G - parts with extra graphics on + * _X - regular server parts + * _D - micro server parts + * + * Historical OPTDIFFs: + * + * _EP - 2 socket server parts + * _EX - 4+ socket server parts + * + * The #define line may optionally include a comment including platform or core + * names. An exception is made for skylake/kabylake where steppings seem to have gotten + * their own names :-( + */ + +/* Wildcard match for FAM6 so X86_MATCH_INTEL_FAM6_MODEL(ANY) works */ +#define INTEL_FAM6_ANY X86_MODEL_ANY + +#define INTEL_FAM6_CORE_YONAH 0x0E + +#define INTEL_FAM6_CORE2_MEROM 0x0F +#define INTEL_FAM6_CORE2_MEROM_L 0x16 +#define INTEL_FAM6_CORE2_PENRYN 0x17 +#define INTEL_FAM6_CORE2_DUNNINGTON 0x1D + +#define INTEL_FAM6_NEHALEM 0x1E +#define INTEL_FAM6_NEHALEM_G 0x1F /* Auburndale / Havendale */ +#define INTEL_FAM6_NEHALEM_EP 0x1A +#define INTEL_FAM6_NEHALEM_EX 0x2E + +#define INTEL_FAM6_WESTMERE 0x25 +#define INTEL_FAM6_WESTMERE_EP 0x2C +#define INTEL_FAM6_WESTMERE_EX 0x2F + +#define INTEL_FAM6_SANDYBRIDGE 0x2A +#define INTEL_FAM6_SANDYBRIDGE_X 0x2D +#define INTEL_FAM6_IVYBRIDGE 0x3A +#define INTEL_FAM6_IVYBRIDGE_X 0x3E + +#define INTEL_FAM6_HASWELL 0x3C +#define INTEL_FAM6_HASWELL_X 0x3F +#define INTEL_FAM6_HASWELL_L 0x45 +#define INTEL_FAM6_HASWELL_G 0x46 + +#define INTEL_FAM6_BROADWELL 0x3D +#define INTEL_FAM6_BROADWELL_G 0x47 +#define INTEL_FAM6_BROADWELL_X 0x4F +#define INTEL_FAM6_BROADWELL_D 0x56 + +#define INTEL_FAM6_SKYLAKE_L 0x4E /* Sky Lake */ +#define INTEL_FAM6_SKYLAKE 0x5E /* Sky Lake */ +#define INTEL_FAM6_SKYLAKE_X 0x55 /* Sky Lake */ +/* CASCADELAKE_X 0x55 Sky Lake -- s: 7 */ +/* COOPERLAKE_X 0x55 Sky Lake -- s: 11 */ + +#define INTEL_FAM6_KABYLAKE_L 0x8E /* Sky Lake */ +/* AMBERLAKE_L 0x8E Sky Lake -- s: 9 */ +/* COFFEELAKE_L 0x8E Sky Lake -- s: 10 */ +/* WHISKEYLAKE_L 0x8E Sky Lake -- s: 11,12 */ + +#define INTEL_FAM6_KABYLAKE 0x9E /* Sky Lake */ +/* COFFEELAKE 0x9E Sky Lake -- s: 10-13 */ + +#define INTEL_FAM6_COMETLAKE 0xA5 /* Sky Lake */ +#define INTEL_FAM6_COMETLAKE_L 0xA6 /* Sky Lake */ + +#define INTEL_FAM6_CANNONLAKE_L 0x66 /* Palm Cove */ + +#define INTEL_FAM6_ICELAKE_X 0x6A /* Sunny Cove */ +#define INTEL_FAM6_ICELAKE_D 0x6C /* Sunny Cove */ +#define INTEL_FAM6_ICELAKE 0x7D /* Sunny Cove */ +#define INTEL_FAM6_ICELAKE_L 0x7E /* Sunny Cove */ +#define INTEL_FAM6_ICELAKE_NNPI 0x9D /* Sunny Cove */ + +#define INTEL_FAM6_LAKEFIELD 0x8A /* Sunny Cove / Tremont */ + +#define INTEL_FAM6_ROCKETLAKE 0xA7 /* Cypress Cove */ + +#define INTEL_FAM6_TIGERLAKE_L 0x8C /* Willow Cove */ +#define INTEL_FAM6_TIGERLAKE 0x8D /* Willow Cove */ + +#define INTEL_FAM6_SAPPHIRERAPIDS_X 0x8F /* Golden Cove */ + +#define INTEL_FAM6_ALDERLAKE 0x97 /* Golden Cove / Gracemont */ +#define INTEL_FAM6_ALDERLAKE_L 0x9A /* Golden Cove / Gracemont */ + +/* "Small Core" Processors (Atom) */ + +#define INTEL_FAM6_ATOM_BONNELL 0x1C /* Diamondville, Pineview */ +#define INTEL_FAM6_ATOM_BONNELL_MID 0x26 /* Silverthorne, Lincroft */ + +#define INTEL_FAM6_ATOM_SALTWELL 0x36 /* Cedarview */ +#define INTEL_FAM6_ATOM_SALTWELL_MID 0x27 /* Penwell */ +#define INTEL_FAM6_ATOM_SALTWELL_TABLET 0x35 /* Cloverview */ + +#define INTEL_FAM6_ATOM_SILVERMONT 0x37 /* Bay Trail, Valleyview */ +#define INTEL_FAM6_ATOM_SILVERMONT_D 0x4D /* Avaton, Rangely */ +#define INTEL_FAM6_ATOM_SILVERMONT_MID 0x4A /* Merriefield */ + +#define INTEL_FAM6_ATOM_AIRMONT 0x4C /* Cherry Trail, Braswell */ +#define INTEL_FAM6_ATOM_AIRMONT_MID 0x5A /* Moorefield */ +#define INTEL_FAM6_ATOM_AIRMONT_NP 0x75 /* Lightning Mountain */ + +#define INTEL_FAM6_ATOM_GOLDMONT 0x5C /* Apollo Lake */ +#define INTEL_FAM6_ATOM_GOLDMONT_D 0x5F /* Denverton */ + +/* Note: the micro-architecture is "Goldmont Plus" */ +#define INTEL_FAM6_ATOM_GOLDMONT_PLUS 0x7A /* Gemini Lake */ + +#define INTEL_FAM6_ATOM_TREMONT_D 0x86 /* Jacobsville */ +#define INTEL_FAM6_ATOM_TREMONT 0x96 /* Elkhart Lake */ +#define INTEL_FAM6_ATOM_TREMONT_L 0x9C /* Jasper Lake */ + +/* Xeon Phi */ + +#define INTEL_FAM6_XEON_PHI_KNL 0x57 /* Knights Landing */ +#define INTEL_FAM6_XEON_PHI_KNM 0x85 /* Knights Mill */ + +/* Family 5 */ +#define INTEL_FAM5_QUARK_X1000 0x09 /* Quark X1000 SoC */ + +#endif /* _LINUX_X86_INTEL_FAMILY_H */ From patchwork Mon Jul 12 22:04:36 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Iwona Winiarska X-Patchwork-Id: 473195 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1D7C2C07E9A for ; Mon, 12 Jul 2021 22:08:01 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 07FF261248 for ; Mon, 12 Jul 2021 22:08:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231835AbhGLWKs (ORCPT ); Mon, 12 Jul 2021 18:10:48 -0400 Received: from mga03.intel.com ([134.134.136.65]:22376 "EHLO mga03.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231252AbhGLWKs (ORCPT ); Mon, 12 Jul 2021 18:10:48 -0400 X-IronPort-AV: E=McAfee;i="6200,9189,10043"; a="210105057" X-IronPort-AV: E=Sophos;i="5.84,235,1620716400"; d="scan'208";a="210105057" Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by orsmga103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Jul 2021 15:07:58 -0700 X-IronPort-AV: E=Sophos;i="5.84,235,1620716400"; d="scan'208";a="464371996" Received: from jzloch-mobl1.ger.corp.intel.com (HELO localhost) ([10.249.136.11]) by fmsmga008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Jul 2021 15:07:53 -0700 From: Iwona Winiarska To: linux-kernel@vger.kernel.org, openbmc@lists.ozlabs.org Cc: x86@kernel.org, devicetree@vger.kernel.org, linux-aspeed@lists.ozlabs.org, linux-arm-kernel@lists.infradead.org, linux-hwmon@vger.kernel.org, linux-doc@vger.kernel.org, Greg Kroah-Hartman , Rob Herring , Joel Stanley , Andrew Jeffery , Jean Delvare , Guenter Roeck , Jonathan Corbet , Thomas Gleixner , Andy Lutomirski , Ingo Molnar , Borislav Petkov , Yazen Ghannam , Mauro Carvalho Chehab , Pierre-Louis Bossart , Tony Luck , Andy Shevchenko , Jae Hyun Yoo , Iwona Winiarska Subject: [PATCH 03/14] dt-bindings: Add generic bindings for PECI Date: Tue, 13 Jul 2021 00:04:36 +0200 Message-Id: <20210712220447.957418-4-iwona.winiarska@intel.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210712220447.957418-1-iwona.winiarska@intel.com> References: <20210712220447.957418-1-iwona.winiarska@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Add device tree bindings for the PECI controller. Signed-off-by: Iwona Winiarska --- .../bindings/peci/peci-controller.yaml | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 Documentation/devicetree/bindings/peci/peci-controller.yaml diff --git a/Documentation/devicetree/bindings/peci/peci-controller.yaml b/Documentation/devicetree/bindings/peci/peci-controller.yaml new file mode 100644 index 000000000000..54ae8fc333d3 --- /dev/null +++ b/Documentation/devicetree/bindings/peci/peci-controller.yaml @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/peci/peci-controller.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Generic Device Tree Bindings for PECI + +maintainers: + - Iwona Winiarska + +description: | + PECI (Platform Environment Control Interface) is an interface that provides a + communication channel from Intel processors and chipset components to external + monitoring or control devices. + +properties: + $nodename: + pattern: "^peci-controller(@.*)?$" + +additionalProperties: true + +examples: + - | + peci-controller@1e78b000 { + reg = <0x1e78b000 0x100>; + }; +... From patchwork Mon Jul 12 22:04:38 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Iwona Winiarska X-Patchwork-Id: 473194 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C7EE8C11F67 for ; Mon, 12 Jul 2021 22:09:26 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id AE3F661178 for ; Mon, 12 Jul 2021 22:09:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230456AbhGLWMO (ORCPT ); Mon, 12 Jul 2021 18:12:14 -0400 Received: from mga17.intel.com ([192.55.52.151]:34283 "EHLO mga17.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230098AbhGLWMO (ORCPT ); Mon, 12 Jul 2021 18:12:14 -0400 X-IronPort-AV: E=McAfee;i="6200,9189,10043"; a="190442554" X-IronPort-AV: E=Sophos;i="5.84,235,1620716400"; d="scan'208";a="190442554" Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Jul 2021 15:09:25 -0700 X-IronPort-AV: E=Sophos;i="5.84,235,1620716400"; d="scan'208";a="464386166" Received: from jzloch-mobl1.ger.corp.intel.com (HELO localhost) ([10.249.136.11]) by fmsmga008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Jul 2021 15:09:19 -0700 From: Iwona Winiarska To: linux-kernel@vger.kernel.org, openbmc@lists.ozlabs.org Cc: x86@kernel.org, devicetree@vger.kernel.org, linux-aspeed@lists.ozlabs.org, linux-arm-kernel@lists.infradead.org, linux-hwmon@vger.kernel.org, linux-doc@vger.kernel.org, Greg Kroah-Hartman , Rob Herring , Joel Stanley , Andrew Jeffery , Jean Delvare , Guenter Roeck , Jonathan Corbet , Thomas Gleixner , Andy Lutomirski , Ingo Molnar , Borislav Petkov , Yazen Ghannam , Mauro Carvalho Chehab , Pierre-Louis Bossart , Tony Luck , Andy Shevchenko , Jae Hyun Yoo , Iwona Winiarska Subject: [PATCH 05/14] ARM: dts: aspeed: Add PECI controller nodes Date: Tue, 13 Jul 2021 00:04:38 +0200 Message-Id: <20210712220447.957418-6-iwona.winiarska@intel.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210712220447.957418-1-iwona.winiarska@intel.com> References: <20210712220447.957418-1-iwona.winiarska@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Add PECI controller nodes with all required information. Co-developed-by: Jae Hyun Yoo Signed-off-by: Jae Hyun Yoo Signed-off-by: Iwona Winiarska --- arch/arm/boot/dts/aspeed-g4.dtsi | 14 ++++++++++++++ arch/arm/boot/dts/aspeed-g5.dtsi | 14 ++++++++++++++ arch/arm/boot/dts/aspeed-g6.dtsi | 14 ++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/arch/arm/boot/dts/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed-g4.dtsi index c5aeb3cf3a09..de733c03ec18 100644 --- a/arch/arm/boot/dts/aspeed-g4.dtsi +++ b/arch/arm/boot/dts/aspeed-g4.dtsi @@ -385,6 +385,20 @@ ibt: ibt@140 { }; }; + peci0: peci-controller@1e78b000 { + compatible = "aspeed,ast2400-peci"; + reg = <0x1e78b000 0x60>; + interrupts = <15>; + clocks = <&syscon ASPEED_CLK_GATE_REFCLK>; + resets = <&syscon ASPEED_RESET_PECI>; + clock-divider = <0>; + msg-timing = <1>; + addr-timing = <1>; + rd-sampling-point = <8>; + cmd-timeout-ms = <1000>; + status = "disabled"; + }; + uart2: serial@1e78d000 { compatible = "ns16550a"; reg = <0x1e78d000 0x20>; diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi index 329eaeef66fb..e7db9cf56114 100644 --- a/arch/arm/boot/dts/aspeed-g5.dtsi +++ b/arch/arm/boot/dts/aspeed-g5.dtsi @@ -506,6 +506,20 @@ ibt: ibt@140 { }; }; + peci0: peci-controller@1e78b000 { + compatible = "aspeed,ast2500-peci"; + reg = <0x1e78b000 0x60>; + interrupts = <15>; + clocks = <&syscon ASPEED_CLK_GATE_REFCLK>; + resets = <&syscon ASPEED_RESET_PECI>; + clock-divider = <0>; + msg-timing = <1>; + addr-timing = <1>; + rd-sampling-point = <8>; + cmd-timeout-ms = <1000>; + status = "disabled"; + }; + uart2: serial@1e78d000 { compatible = "ns16550a"; reg = <0x1e78d000 0x20>; diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi index f96607b7b4e2..1e951bb7ff65 100644 --- a/arch/arm/boot/dts/aspeed-g6.dtsi +++ b/arch/arm/boot/dts/aspeed-g6.dtsi @@ -459,6 +459,20 @@ wdt4: watchdog@1e7850c0 { status = "disabled"; }; + peci0: peci-controller@1e78b000 { + compatible = "aspeed,ast2600-peci"; + reg = <0x1e78b000 0x100>; + interrupts = ; + clocks = <&syscon ASPEED_CLK_GATE_REF0CLK>; + resets = <&syscon ASPEED_RESET_PECI>; + clock-divider = <0>; + msg-timing = <1>; + addr-timing = <1>; + rd-sampling-point = <8>; + cmd-timeout-ms = <1000>; + status = "disabled"; + }; + lpc: lpc@1e789000 { compatible = "aspeed,ast2600-lpc-v2", "simple-mfd", "syscon"; reg = <0x1e789000 0x1000>; From patchwork Mon Jul 12 22:04:40 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Iwona Winiarska X-Patchwork-Id: 473193 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9F8E5C07E9A for ; Mon, 12 Jul 2021 22:09:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8C79661248 for ; Mon, 12 Jul 2021 22:09:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231836AbhGLWMk (ORCPT ); Mon, 12 Jul 2021 18:12:40 -0400 Received: from mga02.intel.com ([134.134.136.20]:6647 "EHLO mga02.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229910AbhGLWMj (ORCPT ); Mon, 12 Jul 2021 18:12:39 -0400 X-IronPort-AV: E=McAfee;i="6200,9189,10043"; a="197246318" X-IronPort-AV: E=Sophos;i="5.84,235,1620716400"; d="scan'208";a="197246318" Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Jul 2021 15:09:50 -0700 X-IronPort-AV: E=Sophos;i="5.84,235,1620716400"; d="scan'208";a="464390274" Received: from jzloch-mobl1.ger.corp.intel.com (HELO localhost) ([10.249.136.11]) by fmsmga008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Jul 2021 15:09:44 -0700 From: Iwona Winiarska To: linux-kernel@vger.kernel.org, openbmc@lists.ozlabs.org Cc: x86@kernel.org, devicetree@vger.kernel.org, linux-aspeed@lists.ozlabs.org, linux-arm-kernel@lists.infradead.org, linux-hwmon@vger.kernel.org, linux-doc@vger.kernel.org, Greg Kroah-Hartman , Rob Herring , Joel Stanley , Andrew Jeffery , Jean Delvare , Guenter Roeck , Jonathan Corbet , Thomas Gleixner , Andy Lutomirski , Ingo Molnar , Borislav Petkov , Yazen Ghannam , Mauro Carvalho Chehab , Pierre-Louis Bossart , Tony Luck , Andy Shevchenko , Jae Hyun Yoo , Iwona Winiarska Subject: [PATCH 07/14] peci: Add peci-aspeed controller driver Date: Tue, 13 Jul 2021 00:04:40 +0200 Message-Id: <20210712220447.957418-8-iwona.winiarska@intel.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210712220447.957418-1-iwona.winiarska@intel.com> References: <20210712220447.957418-1-iwona.winiarska@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org From: Jae Hyun Yoo ASPEED AST24xx/AST25xx/AST26xx SoCs supports the PECI electrical interface (a.k.a PECI wire). Signed-off-by: Jae Hyun Yoo Co-developed-by: Iwona Winiarska Signed-off-by: Iwona Winiarska Reviewed-by: Pierre-Louis Bossart --- MAINTAINERS | 9 + drivers/peci/Kconfig | 6 + drivers/peci/Makefile | 3 + drivers/peci/controller/Kconfig | 12 + drivers/peci/controller/Makefile | 3 + drivers/peci/controller/peci-aspeed.c | 501 ++++++++++++++++++++++++++ 6 files changed, 534 insertions(+) create mode 100644 drivers/peci/controller/Kconfig create mode 100644 drivers/peci/controller/Makefile create mode 100644 drivers/peci/controller/peci-aspeed.c diff --git a/MAINTAINERS b/MAINTAINERS index 47411e2b6336..4ba874afa2fa 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2865,6 +2865,15 @@ S: Maintained F: Documentation/hwmon/asc7621.rst F: drivers/hwmon/asc7621.c +ASPEED PECI CONTROLLER +M: Iwona Winiarska +M: Jae Hyun Yoo +L: linux-aspeed@lists.ozlabs.org (moderated for non-subscribers) +L: openbmc@lists.ozlabs.org (moderated for non-subscribers) +S: Supported +F: Documentation/devicetree/bindings/peci/peci-aspeed.yaml +F: drivers/peci/controller/peci-aspeed.c + ASPEED PINCTRL DRIVERS M: Andrew Jeffery L: linux-aspeed@lists.ozlabs.org (moderated for non-subscribers) diff --git a/drivers/peci/Kconfig b/drivers/peci/Kconfig index 601cc3c3c852..0d0ee8009713 100644 --- a/drivers/peci/Kconfig +++ b/drivers/peci/Kconfig @@ -12,3 +12,9 @@ menuconfig PECI This support is also available as a module. If so, the module will be called peci. + +if PECI + +source "drivers/peci/controller/Kconfig" + +endif # PECI diff --git a/drivers/peci/Makefile b/drivers/peci/Makefile index 2bb2f51bcda7..621a993e306a 100644 --- a/drivers/peci/Makefile +++ b/drivers/peci/Makefile @@ -3,3 +3,6 @@ # Core functionality peci-y := core.o sysfs.o obj-$(CONFIG_PECI) += peci.o + +# Hardware specific bus drivers +obj-y += controller/ diff --git a/drivers/peci/controller/Kconfig b/drivers/peci/controller/Kconfig new file mode 100644 index 000000000000..8ddbe494677f --- /dev/null +++ b/drivers/peci/controller/Kconfig @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-only + +config PECI_ASPEED + tristate "ASPEED PECI support" + depends on ARCH_ASPEED || COMPILE_TEST + depends on OF + depends on HAS_IOMEM + help + Enable this driver if you want to support ASPEED PECI controller. + + This driver can be also build as a module. If so, the module + will be called peci-aspeed. diff --git a/drivers/peci/controller/Makefile b/drivers/peci/controller/Makefile new file mode 100644 index 000000000000..022c28ef1bf0 --- /dev/null +++ b/drivers/peci/controller/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0-only + +obj-$(CONFIG_PECI_ASPEED) += peci-aspeed.o diff --git a/drivers/peci/controller/peci-aspeed.c b/drivers/peci/controller/peci-aspeed.c new file mode 100644 index 000000000000..888b46383ea4 --- /dev/null +++ b/drivers/peci/controller/peci-aspeed.c @@ -0,0 +1,501 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (C) 2012-2017 ASPEED Technology Inc. +// Copyright (c) 2018-2021 Intel Corporation + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* ASPEED PECI Registers */ +/* Control Register */ +#define ASPEED_PECI_CTRL 0x00 +#define ASPEED_PECI_CTRL_SAMPLING_MASK GENMASK(19, 16) +#define ASPEED_PECI_CTRL_READ_MODE_MASK GENMASK(13, 12) +#define ASPEED_PECI_CTRL_READ_MODE_COUNT BIT(12) +#define ASPEED_PECI_CTRL_READ_MODE_DBG BIT(13) +#define ASPEED_PECI_CTRL_CLK_SOURCE_MASK BIT(11) +#define ASPEED_PECI_CTRL_CLK_DIV_MASK GENMASK(10, 8) +#define ASPEED_PECI_CTRL_INVERT_OUT BIT(7) +#define ASPEED_PECI_CTRL_INVERT_IN BIT(6) +#define ASPEED_PECI_CTRL_BUS_CONTENT_EN BIT(5) +#define ASPEED_PECI_CTRL_PECI_EN BIT(4) +#define ASPEED_PECI_CTRL_PECI_CLK_EN BIT(0) + +/* Timing Negotiation Register */ +#define ASPEED_PECI_TIMING_NEGOTIATION 0x04 +#define ASPEED_PECI_TIMING_MESSAGE_MASK GENMASK(15, 8) +#define ASPEED_PECI_TIMING_ADDRESS_MASK GENMASK(7, 0) + +/* Command Register */ +#define ASPEED_PECI_CMD 0x08 +#define ASPEED_PECI_CMD_PIN_MON BIT(31) +#define ASPEED_PECI_CMD_STS_MASK GENMASK(27, 24) +#define ASPEED_PECI_CMD_STS_ADDR_T_NEGO 0x3 +#define ASPEED_PECI_CMD_IDLE_MASK \ + (ASPEED_PECI_CMD_STS_MASK | ASPEED_PECI_CMD_PIN_MON) +#define ASPEED_PECI_CMD_FIRE BIT(0) + +/* Read/Write Length Register */ +#define ASPEED_PECI_RW_LENGTH 0x0c +#define ASPEED_PECI_AW_FCS_EN BIT(31) +#define ASPEED_PECI_READ_LEN_MASK GENMASK(23, 16) +#define ASPEED_PECI_WRITE_LEN_MASK GENMASK(15, 8) +#define ASPEED_PECI_TAGET_ADDR_MASK GENMASK(7, 0) + +/* Expected FCS Data Register */ +#define ASPEED_PECI_EXP_FCS 0x10 +#define ASPEED_PECI_EXP_READ_FCS_MASK GENMASK(23, 16) +#define ASPEED_PECI_EXP_AW_FCS_AUTO_MASK GENMASK(15, 8) +#define ASPEED_PECI_EXP_WRITE_FCS_MASK GENMASK(7, 0) + +/* Captured FCS Data Register */ +#define ASPEED_PECI_CAP_FCS 0x14 +#define ASPEED_PECI_CAP_READ_FCS_MASK GENMASK(23, 16) +#define ASPEED_PECI_CAP_WRITE_FCS_MASK GENMASK(7, 0) + +/* Interrupt Register */ +#define ASPEED_PECI_INT_CTRL 0x18 +#define ASPEED_PECI_TIMING_NEGO_SEL_MASK GENMASK(31, 30) +#define ASPEED_PECI_1ST_BIT_OF_ADDR_NEGO 0 +#define ASPEED_PECI_2ND_BIT_OF_ADDR_NEGO 1 +#define ASPEED_PECI_MESSAGE_NEGO 2 +#define ASPEED_PECI_INT_MASK GENMASK(4, 0) +#define ASPEED_PECI_INT_BUS_TIMEOUT BIT(4) +#define ASPEED_PECI_INT_BUS_CONNECT BIT(3) +#define ASPEED_PECI_INT_W_FCS_BAD BIT(2) +#define ASPEED_PECI_INT_W_FCS_ABORT BIT(1) +#define ASPEED_PECI_INT_CMD_DONE BIT(0) + +/* Interrupt Status Register */ +#define ASPEED_PECI_INT_STS 0x1c +#define ASPEED_PECI_INT_TIMING_RESULT_MASK GENMASK(29, 16) + /* bits[4..0]: Same bit fields in the 'Interrupt Register' */ + +/* Rx/Tx Data Buffer Registers */ +#define ASPEED_PECI_W_DATA0 0x20 +#define ASPEED_PECI_W_DATA1 0x24 +#define ASPEED_PECI_W_DATA2 0x28 +#define ASPEED_PECI_W_DATA3 0x2c +#define ASPEED_PECI_R_DATA0 0x30 +#define ASPEED_PECI_R_DATA1 0x34 +#define ASPEED_PECI_R_DATA2 0x38 +#define ASPEED_PECI_R_DATA3 0x3c +#define ASPEED_PECI_W_DATA4 0x40 +#define ASPEED_PECI_W_DATA5 0x44 +#define ASPEED_PECI_W_DATA6 0x48 +#define ASPEED_PECI_W_DATA7 0x4c +#define ASPEED_PECI_R_DATA4 0x50 +#define ASPEED_PECI_R_DATA5 0x54 +#define ASPEED_PECI_R_DATA6 0x58 +#define ASPEED_PECI_R_DATA7 0x5c +#define ASPEED_PECI_DATA_BUF_SIZE_MAX 32 + +/* Timing Negotiation */ +#define ASPEED_PECI_RD_SAMPLING_POINT_DEFAULT 8 +#define ASPEED_PECI_RD_SAMPLING_POINT_MAX (BIT(4) - 1) +#define ASPEED_PECI_CLK_DIV_DEFAULT 0 +#define ASPEED_PECI_CLK_DIV_MAX (BIT(3) - 1) +#define ASPEED_PECI_MSG_TIMING_DEFAULT 1 +#define ASPEED_PECI_MSG_TIMING_MAX (BIT(8) - 1) +#define ASPEED_PECI_ADDR_TIMING_DEFAULT 1 +#define ASPEED_PECI_ADDR_TIMING_MAX (BIT(8) - 1) + +/* Timeout */ +#define ASPEED_PECI_IDLE_CHECK_TIMEOUT_US (50 * USEC_PER_MSEC) +#define ASPEED_PECI_IDLE_CHECK_INTERVAL_US (10 * USEC_PER_MSEC) +#define ASPEED_PECI_CMD_TIMEOUT_MS_DEFAULT (1000) +#define ASPEED_PECI_CMD_TIMEOUT_MS_MAX (1000) + +struct aspeed_peci { + struct peci_controller controller; + struct device *dev; + void __iomem *base; + struct clk *clk; + struct reset_control *rst; + int irq; + spinlock_t lock; /* to sync completion status handling */ + struct completion xfer_complete; + u32 status; + u32 cmd_timeout_ms; + u32 msg_timing; + u32 addr_timing; + u32 rd_sampling_point; + u32 clk_div; +}; + +static inline struct aspeed_peci *to_aspeed_peci(struct peci_controller *a) +{ + return container_of(a, struct aspeed_peci, controller); +} + +static void aspeed_peci_init_regs(struct aspeed_peci *priv) +{ + u32 val; + + val = FIELD_PREP(ASPEED_PECI_CTRL_CLK_DIV_MASK, ASPEED_PECI_CLK_DIV_DEFAULT); + val |= ASPEED_PECI_CTRL_PECI_CLK_EN; + writel(val, priv->base + ASPEED_PECI_CTRL); + /* + * Timing negotiation period setting. + * The unit of the programmed value is 4 times of PECI clock period. + */ + val = FIELD_PREP(ASPEED_PECI_TIMING_MESSAGE_MASK, priv->msg_timing); + val |= FIELD_PREP(ASPEED_PECI_TIMING_ADDRESS_MASK, priv->addr_timing); + writel(val, priv->base + ASPEED_PECI_TIMING_NEGOTIATION); + + /* Clear interrupts */ + val = readl(priv->base + ASPEED_PECI_INT_STS) | ASPEED_PECI_INT_MASK; + writel(val, priv->base + ASPEED_PECI_INT_STS); + + /* Set timing negotiation mode and enable interrupts */ + val = FIELD_PREP(ASPEED_PECI_TIMING_NEGO_SEL_MASK, ASPEED_PECI_1ST_BIT_OF_ADDR_NEGO); + val |= ASPEED_PECI_INT_MASK; + writel(val, priv->base + ASPEED_PECI_INT_CTRL); + + val = FIELD_PREP(ASPEED_PECI_CTRL_SAMPLING_MASK, priv->rd_sampling_point); + val |= FIELD_PREP(ASPEED_PECI_CTRL_CLK_DIV_MASK, priv->clk_div); + val |= ASPEED_PECI_CTRL_PECI_EN; + val |= ASPEED_PECI_CTRL_PECI_CLK_EN; + writel(val, priv->base + ASPEED_PECI_CTRL); +} + +static inline int aspeed_peci_check_idle(struct aspeed_peci *priv) +{ + u32 cmd_sts = readl(priv->base + ASPEED_PECI_CMD); + + if (FIELD_GET(ASPEED_PECI_CMD_STS_MASK, cmd_sts) == ASPEED_PECI_CMD_STS_ADDR_T_NEGO) + aspeed_peci_init_regs(priv); + + return readl_poll_timeout(priv->base + ASPEED_PECI_CMD, + cmd_sts, + !(cmd_sts & ASPEED_PECI_CMD_IDLE_MASK), + ASPEED_PECI_IDLE_CHECK_INTERVAL_US, + ASPEED_PECI_IDLE_CHECK_TIMEOUT_US); +} + +static int aspeed_peci_xfer(struct peci_controller *controller, + u8 addr, struct peci_request *req) +{ + struct aspeed_peci *priv = to_aspeed_peci(controller); + unsigned long flags, timeout = msecs_to_jiffies(priv->cmd_timeout_ms); + u32 peci_head; + int ret; + + if (req->tx.len > ASPEED_PECI_DATA_BUF_SIZE_MAX || + req->rx.len > ASPEED_PECI_DATA_BUF_SIZE_MAX) + return -EINVAL; + + /* Check command sts and bus idle state */ + ret = aspeed_peci_check_idle(priv); + if (ret) + return ret; /* -ETIMEDOUT */ + + spin_lock_irqsave(&priv->lock, flags); + reinit_completion(&priv->xfer_complete); + + peci_head = FIELD_PREP(ASPEED_PECI_TAGET_ADDR_MASK, addr) | + FIELD_PREP(ASPEED_PECI_WRITE_LEN_MASK, req->tx.len) | + FIELD_PREP(ASPEED_PECI_READ_LEN_MASK, req->rx.len); + + writel(peci_head, priv->base + ASPEED_PECI_RW_LENGTH); + + memcpy_toio(priv->base + ASPEED_PECI_W_DATA0, req->tx.buf, + req->tx.len > 16 ? 16 : req->tx.len); + if (req->tx.len > 16) + memcpy_toio(priv->base + ASPEED_PECI_W_DATA4, req->tx.buf + 16, + req->tx.len - 16); + + dev_dbg(priv->dev, "HEAD : 0x%08x\n", peci_head); + print_hex_dump_bytes("TX : ", DUMP_PREFIX_NONE, req->tx.buf, req->tx.len); + + priv->status = 0; + writel(ASPEED_PECI_CMD_FIRE, priv->base + ASPEED_PECI_CMD); + spin_unlock_irqrestore(&priv->lock, flags); + + ret = wait_for_completion_interruptible_timeout(&priv->xfer_complete, timeout); + if (ret < 0) + return ret; + + if (ret == 0) { + dev_dbg(priv->dev, "Timeout waiting for a response!\n"); + return -ETIMEDOUT; + } + + spin_lock_irqsave(&priv->lock, flags); + + writel(0, priv->base + ASPEED_PECI_CMD); + + if (priv->status != ASPEED_PECI_INT_CMD_DONE) { + spin_unlock_irqrestore(&priv->lock, flags); + dev_dbg(priv->dev, "No valid response!\n"); + return -EIO; + } + + spin_unlock_irqrestore(&priv->lock, flags); + + memcpy_fromio(req->rx.buf, priv->base + ASPEED_PECI_R_DATA0, + req->rx.len > 16 ? 16 : req->rx.len); + if (req->rx.len > 16) + memcpy_fromio(req->rx.buf + 16, priv->base + ASPEED_PECI_R_DATA4, + req->rx.len - 16); + + print_hex_dump_bytes("RX : ", DUMP_PREFIX_NONE, req->rx.buf, req->rx.len); + + return 0; +} + +static irqreturn_t aspeed_peci_irq_handler(int irq, void *arg) +{ + struct aspeed_peci *priv = arg; + u32 status; + + spin_lock(&priv->lock); + status = readl(priv->base + ASPEED_PECI_INT_STS); + writel(status, priv->base + ASPEED_PECI_INT_STS); + priv->status |= (status & ASPEED_PECI_INT_MASK); + + /* + * In most cases, interrupt bits will be set one by one but also note + * that multiple interrupt bits could be set at the same time. + */ + if (status & ASPEED_PECI_INT_BUS_TIMEOUT) + dev_dbg_ratelimited(priv->dev, "ASPEED_PECI_INT_BUS_TIMEOUT\n"); + + if (status & ASPEED_PECI_INT_BUS_CONNECT) + dev_dbg_ratelimited(priv->dev, "ASPEED_PECI_INT_BUS_CONNECT\n"); + + if (status & ASPEED_PECI_INT_W_FCS_BAD) + dev_dbg_ratelimited(priv->dev, "ASPEED_PECI_INT_W_FCS_BAD\n"); + + if (status & ASPEED_PECI_INT_W_FCS_ABORT) + dev_dbg_ratelimited(priv->dev, "ASPEED_PECI_INT_W_FCS_ABORT\n"); + + /* + * All commands should be ended up with a ASPEED_PECI_INT_CMD_DONE bit + * set even in an error case. + */ + if (status & ASPEED_PECI_INT_CMD_DONE) + complete(&priv->xfer_complete); + + spin_unlock(&priv->lock); + + return IRQ_HANDLED; +} + +static void __sanitize_clock_divider(struct aspeed_peci *priv) +{ + u32 clk_div; + int ret; + + ret = device_property_read_u32(priv->dev, "clock-divider", &clk_div); + if (ret) { + clk_div = ASPEED_PECI_CLK_DIV_DEFAULT; + } else if (clk_div > ASPEED_PECI_CLK_DIV_MAX) { + dev_warn(priv->dev, "Invalid clock-divider: %u, Using default: %u\n", + clk_div, ASPEED_PECI_CLK_DIV_DEFAULT); + + clk_div = ASPEED_PECI_CLK_DIV_DEFAULT; + } + + priv->clk_div = clk_div; +} + +static void __sanitize_msg_timing(struct aspeed_peci *priv) +{ + u32 msg_timing; + int ret; + + ret = device_property_read_u32(priv->dev, "msg-timing", &msg_timing); + if (ret) { + msg_timing = ASPEED_PECI_MSG_TIMING_DEFAULT; + } else if (msg_timing > ASPEED_PECI_MSG_TIMING_MAX) { + dev_warn(priv->dev, "Invalid msg-timing : %u, Use default : %u\n", + msg_timing, ASPEED_PECI_MSG_TIMING_DEFAULT); + + msg_timing = ASPEED_PECI_MSG_TIMING_DEFAULT; + } + + priv->msg_timing = msg_timing; +} + +static void __sanitize_addr_timing(struct aspeed_peci *priv) +{ + u32 addr_timing; + int ret; + + ret = device_property_read_u32(priv->dev, "addr-timing", &addr_timing); + if (ret) { + addr_timing = ASPEED_PECI_ADDR_TIMING_DEFAULT; + } else if (addr_timing > ASPEED_PECI_ADDR_TIMING_MAX) { + dev_warn(priv->dev, "Invalid addr-timing : %u, Use default : %u\n", + addr_timing, ASPEED_PECI_ADDR_TIMING_DEFAULT); + + addr_timing = ASPEED_PECI_ADDR_TIMING_DEFAULT; + } + + priv->addr_timing = addr_timing; +} + +static void __sanitize_rd_sampling_point(struct aspeed_peci *priv) +{ + u32 rd_sampling_point; + int ret; + + ret = device_property_read_u32(priv->dev, "rd-sampling-point", &rd_sampling_point); + if (ret) { + rd_sampling_point = ASPEED_PECI_RD_SAMPLING_POINT_DEFAULT; + } else if (rd_sampling_point > ASPEED_PECI_RD_SAMPLING_POINT_MAX) { + dev_warn(priv->dev, "Invalid rd-sampling-point: %u, Use default : %u\n", + rd_sampling_point, ASPEED_PECI_RD_SAMPLING_POINT_DEFAULT); + + rd_sampling_point = ASPEED_PECI_RD_SAMPLING_POINT_DEFAULT; + } + + priv->rd_sampling_point = rd_sampling_point; +} + +static void __sanitize_cmd_timeout(struct aspeed_peci *priv) +{ + u32 timeout; + int ret; + + ret = device_property_read_u32(priv->dev, "cmd-timeout-ms", &timeout); + if (ret) { + timeout = ASPEED_PECI_CMD_TIMEOUT_MS_DEFAULT; + } else if (timeout > ASPEED_PECI_CMD_TIMEOUT_MS_MAX || timeout == 0) { + dev_warn(priv->dev, "Invalid cmd-timeout-ms: %u, Use default: %u\n", + timeout, ASPEED_PECI_CMD_TIMEOUT_MS_DEFAULT); + + timeout = ASPEED_PECI_CMD_TIMEOUT_MS_DEFAULT; + } + + priv->cmd_timeout_ms = timeout; +} + +static void aspeed_peci_device_property_sanitize(struct aspeed_peci *priv) +{ + __sanitize_clock_divider(priv); + __sanitize_msg_timing(priv); + __sanitize_addr_timing(priv); + __sanitize_rd_sampling_point(priv); + __sanitize_cmd_timeout(priv); +} + +static void aspeed_peci_disable_clk(void *data) +{ + clk_disable_unprepare(data); +} + +static int aspeed_peci_init_ctrl(struct aspeed_peci *priv) +{ + int ret; + + priv->clk = devm_clk_get(priv->dev, NULL); + if (IS_ERR(priv->clk)) + return dev_err_probe(priv->dev, PTR_ERR(priv->clk), "Failed to get clk source\n"); + + ret = clk_prepare_enable(priv->clk); + if (ret) { + dev_err(priv->dev, "Failed to enable clock\n"); + return ret; + } + + ret = devm_add_action_or_reset(priv->dev, aspeed_peci_disable_clk, priv->clk); + if (ret) + return ret; + + aspeed_peci_device_property_sanitize(priv); + + aspeed_peci_init_regs(priv); + + return 0; +} + +static int aspeed_peci_probe(struct platform_device *pdev) +{ + struct aspeed_peci *priv; + int ret; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->dev = &pdev->dev; + dev_set_drvdata(priv->dev, priv); + + priv->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(priv->base)) + return PTR_ERR(priv->base); + + priv->irq = platform_get_irq(pdev, 0); + if (!priv->irq) + return priv->irq; + + ret = devm_request_irq(&pdev->dev, priv->irq, aspeed_peci_irq_handler, + 0, "peci-aspeed-irq", priv); + if (ret) + return ret; + + init_completion(&priv->xfer_complete); + spin_lock_init(&priv->lock); + + priv->controller.xfer = aspeed_peci_xfer; + + priv->rst = devm_reset_control_get(&pdev->dev, NULL); + if (IS_ERR(priv->rst)) { + dev_err(&pdev->dev, "Missing or invalid reset controller entry\n"); + return PTR_ERR(priv->rst); + } + reset_control_deassert(priv->rst); + + ret = aspeed_peci_init_ctrl(priv); + if (ret) + return ret; + + return peci_controller_add(&priv->controller, priv->dev); +} + +static int aspeed_peci_remove(struct platform_device *pdev) +{ + struct aspeed_peci *priv = dev_get_drvdata(&pdev->dev); + + peci_controller_remove(&priv->controller); + reset_control_assert(priv->rst); + + return 0; +} + +static const struct of_device_id aspeed_peci_of_table[] = { + { .compatible = "aspeed,ast2400-peci", }, + { .compatible = "aspeed,ast2500-peci", }, + { .compatible = "aspeed,ast2600-peci", }, + { } +}; +MODULE_DEVICE_TABLE(of, aspeed_peci_of_table); + +static struct platform_driver aspeed_peci_driver = { + .probe = aspeed_peci_probe, + .remove = aspeed_peci_remove, + .driver = { + .name = "peci-aspeed", + .of_match_table = aspeed_peci_of_table, + }, +}; +module_platform_driver(aspeed_peci_driver); + +MODULE_AUTHOR("Ryan Chen "); +MODULE_AUTHOR("Jae Hyun Yoo "); +MODULE_DESCRIPTION("ASPEED PECI driver"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(PECI); From patchwork Mon Jul 12 22:04:42 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Iwona Winiarska X-Patchwork-Id: 473192 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4A06AC07E99 for ; Mon, 12 Jul 2021 22:10:12 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 34808611C0 for ; Mon, 12 Jul 2021 22:10:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231744AbhGLWM7 (ORCPT ); Mon, 12 Jul 2021 18:12:59 -0400 Received: from mga02.intel.com ([134.134.136.20]:6673 "EHLO mga02.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229910AbhGLWM7 (ORCPT ); Mon, 12 Jul 2021 18:12:59 -0400 X-IronPort-AV: E=McAfee;i="6200,9189,10043"; a="197246350" X-IronPort-AV: E=Sophos;i="5.84,235,1620716400"; d="scan'208";a="197246350" Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Jul 2021 15:10:10 -0700 X-IronPort-AV: E=Sophos;i="5.84,235,1620716400"; d="scan'208";a="464394240" Received: from jzloch-mobl1.ger.corp.intel.com (HELO localhost) ([10.249.136.11]) by fmsmga008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Jul 2021 15:10:04 -0700 From: Iwona Winiarska To: linux-kernel@vger.kernel.org, openbmc@lists.ozlabs.org Cc: x86@kernel.org, devicetree@vger.kernel.org, linux-aspeed@lists.ozlabs.org, linux-arm-kernel@lists.infradead.org, linux-hwmon@vger.kernel.org, linux-doc@vger.kernel.org, Greg Kroah-Hartman , Rob Herring , Joel Stanley , Andrew Jeffery , Jean Delvare , Guenter Roeck , Jonathan Corbet , Thomas Gleixner , Andy Lutomirski , Ingo Molnar , Borislav Petkov , Yazen Ghannam , Mauro Carvalho Chehab , Pierre-Louis Bossart , Tony Luck , Andy Shevchenko , Jae Hyun Yoo , Iwona Winiarska Subject: [PATCH 09/14] peci: Add support for PECI device drivers Date: Tue, 13 Jul 2021 00:04:42 +0200 Message-Id: <20210712220447.957418-10-iwona.winiarska@intel.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210712220447.957418-1-iwona.winiarska@intel.com> References: <20210712220447.957418-1-iwona.winiarska@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Here we're adding support for PECI device drivers, which unlike PECI controller drivers are actually able to provide functionalities to userspace. We're also extending peci_request API to allow querying more details about PECI device (e.g. model/family), that's going to be used to find a compatible peci_driver. Signed-off-by: Iwona Winiarska Reviewed-by: Pierre-Louis Bossart --- drivers/peci/Kconfig | 1 + drivers/peci/core.c | 49 +++++++++ drivers/peci/device.c | 99 ++++++++++++++++++ drivers/peci/internal.h | 75 ++++++++++++++ drivers/peci/request.c | 217 ++++++++++++++++++++++++++++++++++++++++ include/linux/peci.h | 19 ++++ lib/Kconfig | 2 +- 7 files changed, 461 insertions(+), 1 deletion(-) diff --git a/drivers/peci/Kconfig b/drivers/peci/Kconfig index 0d0ee8009713..27c31535843c 100644 --- a/drivers/peci/Kconfig +++ b/drivers/peci/Kconfig @@ -2,6 +2,7 @@ menuconfig PECI tristate "PECI support" + select GENERIC_LIB_X86 help The Platform Environment Control Interface (PECI) is an interface that provides a communication channel to Intel processors and diff --git a/drivers/peci/core.c b/drivers/peci/core.c index ae7a9572cdf3..94426b7f2618 100644 --- a/drivers/peci/core.c +++ b/drivers/peci/core.c @@ -143,8 +143,57 @@ void peci_controller_remove(struct peci_controller *controller) } EXPORT_SYMBOL_NS_GPL(peci_controller_remove, PECI); +static const struct peci_device_id * +peci_bus_match_device_id(const struct peci_device_id *id, struct peci_device *device) +{ + while (id->family != 0) { + if (id->family == device->info.family && + id->model == device->info.model) + return id; + id++; + } + + return NULL; +} + +static int peci_bus_device_match(struct device *dev, struct device_driver *drv) +{ + struct peci_device *device = to_peci_device(dev); + struct peci_driver *peci_drv = to_peci_driver(drv); + + if (dev->type != &peci_device_type) + return 0; + + if (peci_bus_match_device_id(peci_drv->id_table, device)) + return 1; + + return 0; +} + +static int peci_bus_device_probe(struct device *dev) +{ + struct peci_device *device = to_peci_device(dev); + struct peci_driver *driver = to_peci_driver(dev->driver); + + return driver->probe(device, peci_bus_match_device_id(driver->id_table, device)); +} + +static int peci_bus_device_remove(struct device *dev) +{ + struct peci_device *device = to_peci_device(dev); + struct peci_driver *driver = to_peci_driver(dev->driver); + + if (driver->remove) + driver->remove(device); + + return 0; +} + struct bus_type peci_bus_type = { .name = "peci", + .match = peci_bus_device_match, + .probe = peci_bus_device_probe, + .remove = peci_bus_device_remove, .bus_groups = peci_bus_groups, }; diff --git a/drivers/peci/device.c b/drivers/peci/device.c index 1124862211e2..8c4bd1ebbc29 100644 --- a/drivers/peci/device.c +++ b/drivers/peci/device.c @@ -1,11 +1,79 @@ // SPDX-License-Identifier: GPL-2.0-only // Copyright (c) 2018-2021 Intel Corporation +#include #include #include +#include #include "internal.h" +#define REVISION_NUM_MASK GENMASK(15, 8) +static int peci_get_revision(struct peci_device *device, u8 *revision) +{ + struct peci_request *req; + u64 dib; + + req = peci_get_dib(device); + if (IS_ERR(req)) + return PTR_ERR(req); + + dib = peci_request_data_dib(req); + if (dib == 0) { + peci_request_free(req); + return -EIO; + } + + *revision = FIELD_GET(REVISION_NUM_MASK, dib); + + peci_request_free(req); + + return 0; +} + +static int peci_get_cpu_id(struct peci_device *device, u32 *cpu_id) +{ + struct peci_request *req; + int ret; + + req = peci_pkg_cfg_readl(device, PECI_PCS_PKG_ID, PECI_PKG_ID_CPU_ID); + if (IS_ERR(req)) + return PTR_ERR(req); + + ret = peci_request_status(req); + if (ret) + goto out_req_free; + + *cpu_id = peci_request_data_readl(req); +out_req_free: + peci_request_free(req); + + return ret; +} + +static int peci_device_info_init(struct peci_device *device) +{ + u8 revision; + u32 cpu_id; + int ret; + + ret = peci_get_cpu_id(device, &cpu_id); + if (ret) + return ret; + + device->info.family = x86_family(cpu_id); + device->info.model = x86_model(cpu_id); + + ret = peci_get_revision(device, &revision); + if (ret) + return ret; + device->info.peci_revision = revision; + + device->info.socket_id = device->addr - PECI_BASE_ADDR; + + return 0; +} + static int peci_detect(struct peci_controller *controller, u8 addr) { struct peci_request *req; @@ -75,6 +143,10 @@ int peci_device_create(struct peci_controller *controller, u8 addr) device->dev.bus = &peci_bus_type; device->dev.type = &peci_device_type; + ret = peci_device_info_init(device); + if (ret) + goto err_free; + ret = dev_set_name(&device->dev, "%d-%02x", controller->id, device->addr); if (ret) goto err_free; @@ -98,6 +170,33 @@ void peci_device_destroy(struct peci_device *device) device_unregister(&device->dev); } +int __peci_driver_register(struct peci_driver *driver, struct module *owner, + const char *mod_name) +{ + driver->driver.bus = &peci_bus_type; + driver->driver.owner = owner; + driver->driver.mod_name = mod_name; + + if (!driver->probe) { + pr_err("peci: trying to register driver without probe callback\n"); + return -EINVAL; + } + + if (!driver->id_table) { + pr_err("peci: trying to register driver without device id table\n"); + return -EINVAL; + } + + return driver_register(&driver->driver); +} +EXPORT_SYMBOL_NS_GPL(__peci_driver_register, PECI); + +void peci_driver_unregister(struct peci_driver *driver) +{ + driver_unregister(&driver->driver); +} +EXPORT_SYMBOL_NS_GPL(peci_driver_unregister, PECI); + static void peci_device_release(struct device *dev) { struct peci_device *device = to_peci_device(dev); diff --git a/drivers/peci/internal.h b/drivers/peci/internal.h index 6b139adaf6b8..c891c93e077a 100644 --- a/drivers/peci/internal.h +++ b/drivers/peci/internal.h @@ -19,6 +19,34 @@ struct peci_request; struct peci_request *peci_request_alloc(struct peci_device *device, u8 tx_len, u8 rx_len); void peci_request_free(struct peci_request *req); +int peci_request_status(struct peci_request *req); +u64 peci_request_data_dib(struct peci_request *req); + +u8 peci_request_data_readb(struct peci_request *req); +u16 peci_request_data_readw(struct peci_request *req); +u32 peci_request_data_readl(struct peci_request *req); +u64 peci_request_data_readq(struct peci_request *req); + +struct peci_request *peci_get_dib(struct peci_device *device); +struct peci_request *peci_get_temp(struct peci_device *device); + +struct peci_request *peci_pkg_cfg_readb(struct peci_device *device, u8 index, u16 param); +struct peci_request *peci_pkg_cfg_readw(struct peci_device *device, u8 index, u16 param); +struct peci_request *peci_pkg_cfg_readl(struct peci_device *device, u8 index, u16 param); +struct peci_request *peci_pkg_cfg_readq(struct peci_device *device, u8 index, u16 param); + +/** + * struct peci_device_id - PECI device data to match + * @data: pointer to driver private data specific to device + * @family: device family + * @model: device model + */ +struct peci_device_id { + const void *data; + u16 family; + u8 model; +}; + extern struct device_type peci_device_type; extern const struct attribute_group *peci_device_groups[]; @@ -28,6 +56,53 @@ void peci_device_destroy(struct peci_device *device); extern struct bus_type peci_bus_type; extern const struct attribute_group *peci_bus_groups[]; +/** + * struct peci_driver - PECI driver + * @driver: inherit device driver + * @probe: probe callback + * @remove: remove callback + * @id_table: PECI device match table to decide which device to bind + */ +struct peci_driver { + struct device_driver driver; + int (*probe)(struct peci_device *device, const struct peci_device_id *id); + void (*remove)(struct peci_device *device); + const struct peci_device_id *id_table; +}; + +static inline struct peci_driver *to_peci_driver(struct device_driver *d) +{ + return container_of(d, struct peci_driver, driver); +} + +int __peci_driver_register(struct peci_driver *driver, struct module *owner, + const char *mod_name); +/** + * peci_driver_register() - register PECI driver + * @driver: the driver to be registered + * @owner: owner module of the driver being registered + * @mod_name: module name string + * + * PECI drivers that don't need to do anything special in module init should + * use the convenience "module_peci_driver" macro instead + * + * Return: zero on success, else a negative error code. + */ +#define peci_driver_register(driver) \ + __peci_driver_register(driver, THIS_MODULE, KBUILD_MODNAME) +void peci_driver_unregister(struct peci_driver *driver); + +/** + * module_peci_driver() - Helper macro for registering a modular PECI driver + * @__peci_driver: peci_driver struct + * + * Helper macro for PECI drivers which do not do anything special in module + * init/exit. This eliminates a lot of boilerplate. Each module may only + * use this macro once, and calling it replaces module_init() and module_exit() + */ +#define module_peci_driver(__peci_driver) \ + module_driver(__peci_driver, peci_driver_register, peci_driver_unregister) + extern struct device_type peci_controller_type; int peci_controller_scan_devices(struct peci_controller *controller); diff --git a/drivers/peci/request.c b/drivers/peci/request.c index 78cee51dfae1..48354455b554 100644 --- a/drivers/peci/request.c +++ b/drivers/peci/request.c @@ -1,13 +1,142 @@ // SPDX-License-Identifier: GPL-2.0-only // Copyright (c) 2021 Intel Corporation +#include #include #include #include #include +#include + #include "internal.h" +#define PECI_GET_DIB_CMD 0xf7 +#define PECI_GET_DIB_WR_LEN 1 +#define PECI_GET_DIB_RD_LEN 8 + +#define PECI_RDPKGCFG_CMD 0xa1 +#define PECI_RDPKGCFG_WRITE_LEN 5 +#define PECI_RDPKGCFG_READ_LEN_BASE 1 +#define PECI_WRPKGCFG_CMD 0xa5 +#define PECI_WRPKGCFG_WRITE_LEN_BASE 6 +#define PECI_WRPKGCFG_READ_LEN 1 + +/* Device Specific Completion Code (CC) Definition */ +#define PECI_CC_SUCCESS 0x40 +#define PECI_CC_NEED_RETRY 0x80 +#define PECI_CC_OUT_OF_RESOURCE 0x81 +#define PECI_CC_UNAVAIL_RESOURCE 0x82 +#define PECI_CC_INVALID_REQ 0x90 +#define PECI_CC_MCA_ERROR 0x91 +#define PECI_CC_CATASTROPHIC_MCA_ERROR 0x93 +#define PECI_CC_FATAL_MCA_ERROR 0x94 +#define PECI_CC_PARITY_ERR_GPSB_OR_PMSB 0x98 +#define PECI_CC_PARITY_ERR_GPSB_OR_PMSB_IERR 0x9B +#define PECI_CC_PARITY_ERR_GPSB_OR_PMSB_MCA 0x9C + +#define PECI_RETRY_BIT BIT(0) + +#define PECI_RETRY_TIMEOUT msecs_to_jiffies(700) +#define PECI_RETRY_INTERVAL_MIN msecs_to_jiffies(1) +#define PECI_RETRY_INTERVAL_MAX msecs_to_jiffies(128) + +static u8 peci_request_data_cc(struct peci_request *req) +{ + return req->rx.buf[0]; +} + +/** + * peci_request_status() - return -errno based on PECI completion code + * @req: the PECI request that contains response data with completion code + * + * It can't be used for Ping(), GetDIB() and GetTemp() - for those commands we + * don't expect completion code in the response. + * + * Return: -errno + */ +int peci_request_status(struct peci_request *req) +{ + u8 cc = peci_request_data_cc(req); + + if (cc != PECI_CC_SUCCESS) + dev_dbg(&req->device->dev, "ret: %#02x\n", cc); + + switch (cc) { + case PECI_CC_SUCCESS: + return 0; + case PECI_CC_NEED_RETRY: + case PECI_CC_OUT_OF_RESOURCE: + case PECI_CC_UNAVAIL_RESOURCE: + return -EAGAIN; + case PECI_CC_INVALID_REQ: + return -EINVAL; + case PECI_CC_MCA_ERROR: + case PECI_CC_CATASTROPHIC_MCA_ERROR: + case PECI_CC_FATAL_MCA_ERROR: + case PECI_CC_PARITY_ERR_GPSB_OR_PMSB: + case PECI_CC_PARITY_ERR_GPSB_OR_PMSB_IERR: + case PECI_CC_PARITY_ERR_GPSB_OR_PMSB_MCA: + return -EIO; + } + + WARN_ONCE(1, "Unknown PECI completion code: %#02x\n", cc); + + return -EIO; +} +EXPORT_SYMBOL_NS_GPL(peci_request_status, PECI); + +static int peci_request_xfer(struct peci_request *req) +{ + struct peci_device *device = req->device; + struct peci_controller *controller = device->controller; + int ret; + + mutex_lock(&controller->bus_lock); + ret = controller->xfer(controller, device->addr, req); + mutex_unlock(&controller->bus_lock); + + return ret; +} + +static int peci_request_xfer_retry(struct peci_request *req) +{ + long wait_interval = PECI_RETRY_INTERVAL_MIN; + struct peci_device *device = req->device; + struct peci_controller *controller = device->controller; + unsigned long start = jiffies; + int ret; + + /* Don't try to use it for ping */ + if (WARN_ON(!req->rx.buf)) + return 0; + + do { + ret = peci_request_xfer(req); + if (ret) { + dev_dbg(&controller->dev, "xfer error: %d\n", ret); + return ret; + } + + if (peci_request_status(req) != -EAGAIN) + return 0; + + /* Set the retry bit to indicate a retry attempt */ + req->tx.buf[1] |= PECI_RETRY_BIT; + + if (schedule_timeout_interruptible(wait_interval)) + return -ERESTARTSYS; + + wait_interval *= 2; + if (wait_interval > PECI_RETRY_INTERVAL_MAX) + wait_interval = PECI_RETRY_INTERVAL_MAX; + } while (time_before(jiffies, start + PECI_RETRY_TIMEOUT)); + + dev_dbg(&controller->dev, "request timed out\n"); + + return -ETIMEDOUT; +} + /** * peci_request_alloc() - allocate &struct peci_request with buffers with given lengths * @device: PECI device to which request is going to be sent @@ -72,3 +201,91 @@ void peci_request_free(struct peci_request *req) kfree(req); } EXPORT_SYMBOL_NS_GPL(peci_request_free, PECI); + +struct peci_request *peci_get_dib(struct peci_device *device) +{ + struct peci_request *req; + int ret; + + req = peci_request_alloc(device, PECI_GET_DIB_WR_LEN, PECI_GET_DIB_RD_LEN); + if (!req) + return ERR_PTR(-ENOMEM); + + req->tx.buf[0] = PECI_GET_DIB_CMD; + + ret = peci_request_xfer(req); + if (ret) { + peci_request_free(req); + return ERR_PTR(ret); + } + + return req; +} +EXPORT_SYMBOL_NS_GPL(peci_get_dib, PECI); + +static struct peci_request * +__pkg_cfg_read(struct peci_device *device, u8 index, u16 param, u8 len) +{ + struct peci_request *req; + int ret; + + req = peci_request_alloc(device, PECI_RDPKGCFG_WRITE_LEN, + PECI_RDPKGCFG_READ_LEN_BASE + len); + if (!req) + return ERR_PTR(-ENOMEM); + + req->tx.buf[0] = PECI_RDPKGCFG_CMD; + req->tx.buf[1] = 0; + req->tx.buf[2] = index; + put_unaligned_le16(param, &req->tx.buf[3]); + + ret = peci_request_xfer_retry(req); + if (ret) { + peci_request_free(req); + return ERR_PTR(ret); + } + + return req; +} + +u8 peci_request_data_readb(struct peci_request *req) +{ + return req->rx.buf[1]; +} +EXPORT_SYMBOL_NS_GPL(peci_request_data_readb, PECI); + +u16 peci_request_data_readw(struct peci_request *req) +{ + return get_unaligned_le16(&req->rx.buf[1]); +} +EXPORT_SYMBOL_NS_GPL(peci_request_data_readw, PECI); + +u32 peci_request_data_readl(struct peci_request *req) +{ + return get_unaligned_le32(&req->rx.buf[1]); +} +EXPORT_SYMBOL_NS_GPL(peci_request_data_readl, PECI); + +u64 peci_request_data_readq(struct peci_request *req) +{ + return get_unaligned_le64(&req->rx.buf[1]); +} +EXPORT_SYMBOL_NS_GPL(peci_request_data_readq, PECI); + +u64 peci_request_data_dib(struct peci_request *req) +{ + return get_unaligned_le64(&req->rx.buf[0]); +} +EXPORT_SYMBOL_NS_GPL(peci_request_data_dib, PECI); + +#define __read_pkg_config(x, type) \ +struct peci_request *peci_pkg_cfg_##x(struct peci_device *device, u8 index, u16 param) \ +{ \ + return __pkg_cfg_read(device, index, param, sizeof(type)); \ +} \ +EXPORT_SYMBOL_NS_GPL(peci_pkg_cfg_##x, PECI) + +__read_pkg_config(readb, u8); +__read_pkg_config(readw, u16); +__read_pkg_config(readl, u32); +__read_pkg_config(readq, u64); diff --git a/include/linux/peci.h b/include/linux/peci.h index cdf3008321fd..f9f37b874011 100644 --- a/include/linux/peci.h +++ b/include/linux/peci.h @@ -9,6 +9,14 @@ #include #include +#define PECI_PCS_PKG_ID 0 /* Package Identifier Read */ +#define PECI_PKG_ID_CPU_ID 0x0000 /* CPUID Info */ +#define PECI_PKG_ID_PLATFORM_ID 0x0001 /* Platform ID */ +#define PECI_PKG_ID_DEVICE_ID 0x0002 /* Uncore Device ID */ +#define PECI_PKG_ID_MAX_THREAD_ID 0x0003 /* Max Thread ID */ +#define PECI_PKG_ID_MICROCODE_REV 0x0004 /* CPU Microcode Update Revision */ +#define PECI_PKG_ID_MCA_ERROR_LOG 0x0005 /* Machine Check Status */ + struct peci_request; /** @@ -41,6 +49,11 @@ static inline struct peci_controller *to_peci_controller(void *d) * struct peci_device - PECI device * @dev: device object to register PECI device to the device model * @controller: manages the bus segment hosting this PECI device + * @info: PECI device characteristics + * @info.family: device family + * @info.model: device model + * @info.peci_revision: PECI revision supported by the PECI device + * @info.socket_id: the socket ID represented by the PECI device * @addr: address used on the PECI bus connected to the parent controller * * A peci_device identifies a single device (i.e. CPU) connected to a PECI bus. @@ -50,6 +63,12 @@ static inline struct peci_controller *to_peci_controller(void *d) struct peci_device { struct device dev; struct peci_controller *controller; + struct { + u16 family; + u8 model; + u8 peci_revision; + u8 socket_id; + } info; u8 addr; }; diff --git a/lib/Kconfig b/lib/Kconfig index cc28bc1f2d84..a74e6c0fa75c 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -721,5 +721,5 @@ config ASN1_ENCODER config GENERIC_LIB_X86 bool - depends on X86 + depends on X86 || PECI default n From patchwork Mon Jul 12 22:04:44 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Iwona Winiarska X-Patchwork-Id: 473191 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 09BADC11F67 for ; Mon, 12 Jul 2021 22:11:32 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E060461206 for ; Mon, 12 Jul 2021 22:11:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232131AbhGLWOT (ORCPT ); Mon, 12 Jul 2021 18:14:19 -0400 Received: from mga12.intel.com ([192.55.52.136]:20662 "EHLO mga12.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229910AbhGLWOT (ORCPT ); Mon, 12 Jul 2021 18:14:19 -0400 X-IronPort-AV: E=McAfee;i="6200,9189,10043"; a="189746331" X-IronPort-AV: E=Sophos;i="5.84,235,1620716400"; d="scan'208";a="189746331" Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Jul 2021 15:11:30 -0700 X-IronPort-AV: E=Sophos;i="5.84,235,1620716400"; d="scan'208";a="464410024" Received: from jzloch-mobl1.ger.corp.intel.com (HELO localhost) ([10.249.136.11]) by fmsmga008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Jul 2021 15:11:24 -0700 From: Iwona Winiarska To: linux-kernel@vger.kernel.org, openbmc@lists.ozlabs.org Cc: x86@kernel.org, devicetree@vger.kernel.org, linux-aspeed@lists.ozlabs.org, linux-arm-kernel@lists.infradead.org, linux-hwmon@vger.kernel.org, linux-doc@vger.kernel.org, Greg Kroah-Hartman , Rob Herring , Joel Stanley , Andrew Jeffery , Jean Delvare , Guenter Roeck , Jonathan Corbet , Thomas Gleixner , Andy Lutomirski , Ingo Molnar , Borislav Petkov , Yazen Ghannam , Mauro Carvalho Chehab , Pierre-Louis Bossart , Tony Luck , Andy Shevchenko , Jae Hyun Yoo , Iwona Winiarska Subject: [PATCH 11/14] hwmon: peci: Add cputemp driver Date: Tue, 13 Jul 2021 00:04:44 +0200 Message-Id: <20210712220447.957418-12-iwona.winiarska@intel.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210712220447.957418-1-iwona.winiarska@intel.com> References: <20210712220447.957418-1-iwona.winiarska@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Add peci-cputemp driver for Digital Thermal Sensor (DTS) thermal readings of the processor package and processor cores that are accessible via the PECI interface. The main use case for the driver (and PECI interface) is out-of-band management, where we're able to obtain the DTS readings from an external entity connected with PECI, e.g. BMC on server platforms. Co-developed-by: Jae Hyun Yoo Signed-off-by: Jae Hyun Yoo Signed-off-by: Iwona Winiarska Reviewed-by: Pierre-Louis Bossart --- MAINTAINERS | 7 + drivers/hwmon/Kconfig | 2 + drivers/hwmon/Makefile | 1 + drivers/hwmon/peci/Kconfig | 18 ++ drivers/hwmon/peci/Makefile | 5 + drivers/hwmon/peci/common.h | 46 ++++ drivers/hwmon/peci/cputemp.c | 503 +++++++++++++++++++++++++++++++++++ 7 files changed, 582 insertions(+) create mode 100644 drivers/hwmon/peci/Kconfig create mode 100644 drivers/hwmon/peci/Makefile create mode 100644 drivers/hwmon/peci/common.h create mode 100644 drivers/hwmon/peci/cputemp.c diff --git a/MAINTAINERS b/MAINTAINERS index f47b5f634293..35ba9e3646bd 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14504,6 +14504,13 @@ L: platform-driver-x86@vger.kernel.org S: Maintained F: drivers/platform/x86/peaq-wmi.c +PECI HARDWARE MONITORING DRIVERS +M: Iwona Winiarska +R: Jae Hyun Yoo +L: linux-hwmon@vger.kernel.org +S: Supported +F: drivers/hwmon/peci/ + PECI SUBSYSTEM M: Iwona Winiarska R: Jae Hyun Yoo diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index e3675377bc5d..61c0e3404415 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -1507,6 +1507,8 @@ config SENSORS_PCF8591 These devices are hard to detect and rarely found on mainstream hardware. If unsure, say N. +source "drivers/hwmon/peci/Kconfig" + source "drivers/hwmon/pmbus/Kconfig" config SENSORS_PWM_FAN diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index d712c61c1f5e..f52331f212ed 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -202,6 +202,7 @@ obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o obj-$(CONFIG_SENSORS_XGENE) += xgene-hwmon.o obj-$(CONFIG_SENSORS_OCC) += occ/ +obj-$(CONFIG_SENSORS_PECI) += peci/ obj-$(CONFIG_PMBUS) += pmbus/ ccflags-$(CONFIG_HWMON_DEBUG_CHIP) := -DDEBUG diff --git a/drivers/hwmon/peci/Kconfig b/drivers/hwmon/peci/Kconfig new file mode 100644 index 000000000000..e10eed68d70a --- /dev/null +++ b/drivers/hwmon/peci/Kconfig @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0-only + +config SENSORS_PECI_CPUTEMP + tristate "PECI CPU temperature monitoring client" + depends on PECI + select SENSORS_PECI + select PECI_CPU + help + If you say yes here you get support for the generic Intel PECI + cputemp driver which provides Digital Thermal Sensor (DTS) thermal + readings of the CPU package and CPU cores that are accessible via + the processor PECI interface. + + This driver can also be built as a module. If so, the module + will be called peci-cputemp. + +config SENSORS_PECI + tristate diff --git a/drivers/hwmon/peci/Makefile b/drivers/hwmon/peci/Makefile new file mode 100644 index 000000000000..e8a0ada5ab1f --- /dev/null +++ b/drivers/hwmon/peci/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0-only + +peci-cputemp-y := cputemp.o + +obj-$(CONFIG_SENSORS_PECI_CPUTEMP) += peci-cputemp.o diff --git a/drivers/hwmon/peci/common.h b/drivers/hwmon/peci/common.h new file mode 100644 index 000000000000..54580c100d06 --- /dev/null +++ b/drivers/hwmon/peci/common.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright (c) 2021 Intel Corporation */ + +#include + +#ifndef __PECI_HWMON_COMMON_H +#define __PECI_HWMON_COMMON_H + +#define UPDATE_INTERVAL_DEFAULT HZ + +/** + * struct peci_sensor_data - PECI sensor information + * @valid: flag to indicate the sensor value is valid + * @value: sensor value in milli units + * @last_updated: time of the last update in jiffies + */ +struct peci_sensor_data { + unsigned int valid; + s32 value; + unsigned long last_updated; +}; + +/** + * peci_sensor_need_update() - check whether sensor update is needed or not + * @sensor: pointer to sensor data struct + * + * Return: true if update is needed, false if not. + */ + +static inline bool peci_sensor_need_update(struct peci_sensor_data *sensor) +{ + return !sensor->valid || + time_after(jiffies, sensor->last_updated + UPDATE_INTERVAL_DEFAULT); +} + +/** + * peci_sensor_mark_updated() - mark the sensor is updated + * @sensor: pointer to sensor data struct + */ +static inline void peci_sensor_mark_updated(struct peci_sensor_data *sensor) +{ + sensor->valid = 1; + sensor->last_updated = jiffies; +} + +#endif /* __PECI_HWMON_COMMON_H */ diff --git a/drivers/hwmon/peci/cputemp.c b/drivers/hwmon/peci/cputemp.c new file mode 100644 index 000000000000..56a526471687 --- /dev/null +++ b/drivers/hwmon/peci/cputemp.c @@ -0,0 +1,503 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2018-2021 Intel Corporation + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" + +#define CORE_NUMS_MAX 64 + +#define DEFAULT_CHANNEL_NUMS 5 +#define CORETEMP_CHANNEL_NUMS CORE_NUMS_MAX +#define CPUTEMP_CHANNEL_NUMS (DEFAULT_CHANNEL_NUMS + CORETEMP_CHANNEL_NUMS) + +#define TEMP_TARGET_FAN_TEMP_MASK GENMASK(15, 8) +#define TEMP_TARGET_REF_TEMP_MASK GENMASK(23, 16) +#define TEMP_TARGET_TJ_OFFSET_MASK GENMASK(29, 24) + +#define DTS_MARGIN_MASK GENMASK(15, 0) +#define PCS_MODULE_TEMP_MASK GENMASK(15, 0) + +#define DTS_FIXED_POINT_FRACTION 64 + +struct resolved_cores_reg { + u8 bus; + u8 dev; + u8 func; + u8 offset; +}; + +struct cpu_info { + struct resolved_cores_reg *reg; + u8 min_peci_revision; +}; + +struct peci_cputemp { + struct peci_device *peci_dev; + struct device *dev; + const char *name; + const struct cpu_info *gen_info; + struct { + struct peci_sensor_data die; + struct peci_sensor_data dts; + struct peci_sensor_data tcontrol; + struct peci_sensor_data tthrottle; + struct peci_sensor_data tjmax; + struct peci_sensor_data core[CORETEMP_CHANNEL_NUMS]; + } temp; + const char **coretemp_label; + DECLARE_BITMAP(core_mask, CORE_NUMS_MAX); +}; + +enum cputemp_channels { + channel_die, + channel_dts, + channel_tcontrol, + channel_tthrottle, + channel_tjmax, + channel_core, +}; + +static const char *cputemp_label[DEFAULT_CHANNEL_NUMS] = { + "Die", + "DTS", + "Tcontrol", + "Tthrottle", + "Tjmax", +}; + +static int get_temp_targets(struct peci_cputemp *priv) +{ + s32 tthrottle_offset, tcontrol_margin; + u32 pcs; + int ret; + + /* + * Just use only the tcontrol marker to determine if target values need + * update. + */ + if (!peci_sensor_need_update(&priv->temp.tcontrol)) + return 0; + + ret = peci_pcs_read(priv->peci_dev, PECI_PCS_TEMP_TARGET, 0, &pcs); + if (ret) + return ret; + + priv->temp.tjmax.value = FIELD_GET(TEMP_TARGET_REF_TEMP_MASK, pcs) * MILLIDEGREE_PER_DEGREE; + + tcontrol_margin = FIELD_GET(TEMP_TARGET_FAN_TEMP_MASK, pcs); + tcontrol_margin = sign_extend32(tcontrol_margin, 7) * MILLIDEGREE_PER_DEGREE; + priv->temp.tcontrol.value = priv->temp.tjmax.value - tcontrol_margin; + + tthrottle_offset = FIELD_GET(TEMP_TARGET_TJ_OFFSET_MASK, pcs) * MILLIDEGREE_PER_DEGREE; + priv->temp.tthrottle.value = priv->temp.tjmax.value - tthrottle_offset; + + peci_sensor_mark_updated(&priv->temp.tcontrol); + + return 0; +} + +/* + * Processors return a value of DTS reading in S10.6 fixed point format + * (sign, 10 bits signed integer value, 6 bits fractional). + * Error codes: + * 0x8000: General sensor error + * 0x8001: Reserved + * 0x8002: Underflow on reading value + * 0x8003-0x81ff: Reserved + */ +static bool dts_valid(s32 val) +{ + return val < 0x8000 || val > 0x81ff; +} + +static s32 dts_to_millidegree(s32 val) +{ + return sign_extend32(val, 15) * MILLIDEGREE_PER_DEGREE / DTS_FIXED_POINT_FRACTION; +} + +static int get_die_temp(struct peci_cputemp *priv) +{ + s16 temp; + int ret; + + if (!peci_sensor_need_update(&priv->temp.die)) + return 0; + + ret = peci_temp_read(priv->peci_dev, &temp); + if (ret) + return ret; + + if (!dts_valid(temp)) + return -EIO; + + /* Note that the tjmax should be available before calling it */ + priv->temp.die.value = priv->temp.tjmax.value + dts_to_millidegree(temp); + + peci_sensor_mark_updated(&priv->temp.die); + + return 0; +} + +static int get_dts(struct peci_cputemp *priv) +{ + s32 dts_margin; + u32 pcs; + int ret; + + if (!peci_sensor_need_update(&priv->temp.dts)) + return 0; + + ret = peci_pcs_read(priv->peci_dev, PECI_PCS_THERMAL_MARGIN, 0, &pcs); + if (ret) + return ret; + + dts_margin = FIELD_GET(DTS_MARGIN_MASK, pcs); + if (!dts_valid(dts_margin)) + return -EIO; + + /* Note that the tcontrol should be available before calling it */ + priv->temp.dts.value = priv->temp.tcontrol.value - dts_to_millidegree(dts_margin); + + peci_sensor_mark_updated(&priv->temp.dts); + + return 0; +} + +static int get_core_temp(struct peci_cputemp *priv, int core_index) +{ + s32 core_dts_margin; + u32 pcs; + int ret; + + if (!peci_sensor_need_update(&priv->temp.core[core_index])) + return 0; + + ret = peci_pcs_read(priv->peci_dev, PECI_PCS_MODULE_TEMP, core_index, &pcs); + if (ret) + return ret; + + core_dts_margin = FIELD_GET(PCS_MODULE_TEMP_MASK, pcs); + if (!dts_valid(core_dts_margin)) + return -EIO; + + /* Note that the tjmax should be available before calling it */ + priv->temp.core[core_index].value = + priv->temp.tjmax.value + dts_to_millidegree(core_dts_margin); + + peci_sensor_mark_updated(&priv->temp.core[core_index]); + + return 0; +} + +static int cputemp_read_string(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, const char **str) +{ + struct peci_cputemp *priv = dev_get_drvdata(dev); + + if (attr != hwmon_temp_label) + return -EOPNOTSUPP; + + *str = channel < channel_core ? + cputemp_label[channel] : priv->coretemp_label[channel - channel_core]; + + return 0; +} + +static int cputemp_read(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long *val) +{ + struct peci_cputemp *priv = dev_get_drvdata(dev); + int ret, core_index; + + ret = get_temp_targets(priv); + if (ret) + return ret; + + switch (attr) { + case hwmon_temp_input: + switch (channel) { + case channel_die: + ret = get_die_temp(priv); + if (ret) + return ret; + + *val = priv->temp.die.value; + break; + case channel_dts: + ret = get_dts(priv); + if (ret) + return ret; + + *val = priv->temp.dts.value; + break; + case channel_tcontrol: + *val = priv->temp.tcontrol.value; + break; + case channel_tthrottle: + *val = priv->temp.tthrottle.value; + break; + case channel_tjmax: + *val = priv->temp.tjmax.value; + break; + default: + core_index = channel - channel_core; + ret = get_core_temp(priv, core_index); + if (ret) + return ret; + + *val = priv->temp.core[core_index].value; + break; + } + break; + case hwmon_temp_max: + *val = priv->temp.tcontrol.value; + break; + case hwmon_temp_crit: + *val = priv->temp.tjmax.value; + break; + case hwmon_temp_crit_hyst: + *val = priv->temp.tjmax.value - priv->temp.tcontrol.value; + break; + default: + return -EOPNOTSUPP; + } + + return 0; +} + +static umode_t cputemp_is_visible(const void *data, enum hwmon_sensor_types type, + u32 attr, int channel) +{ + const struct peci_cputemp *priv = data; + + if (channel > CPUTEMP_CHANNEL_NUMS) + return 0; + + if (channel < channel_core) + return 0444; + + if (test_bit(channel - channel_core, priv->core_mask)) + return 0444; + + return 0; +} + +static int init_core_mask(struct peci_cputemp *priv) +{ + struct peci_device *peci_dev = priv->peci_dev; + struct resolved_cores_reg *reg = priv->gen_info->reg; + u64 core_mask; + u32 data; + int ret; + + /* Get the RESOLVED_CORES register value */ + switch (peci_dev->info.model) { + case INTEL_FAM6_ICELAKE_X: + case INTEL_FAM6_ICELAKE_D: + ret = peci_ep_pci_local_read(peci_dev, 0, reg->bus, reg->dev, + reg->func, reg->offset + 4, &data); + if (ret) + return ret; + + core_mask = (u64)data << 32; + + ret = peci_ep_pci_local_read(peci_dev, 0, reg->bus, reg->dev, + reg->func, reg->offset, &data); + if (ret) + return ret; + + core_mask |= data; + + break; + default: + ret = peci_pci_local_read(peci_dev, reg->bus, reg->dev, + reg->func, reg->offset, &data); + if (ret) + return ret; + + core_mask = data; + + break; + } + + if (!core_mask) + return -EIO; + + bitmap_from_u64(priv->core_mask, core_mask); + + return 0; +} + +static int create_temp_label(struct peci_cputemp *priv) +{ + unsigned long core_max = find_last_bit(priv->core_mask, CORE_NUMS_MAX); + int i; + + priv->coretemp_label = devm_kzalloc(priv->dev, core_max * sizeof(char *), GFP_KERNEL); + if (!priv->coretemp_label) + return -ENOMEM; + + for_each_set_bit(i, priv->core_mask, CORE_NUMS_MAX) { + priv->coretemp_label[i] = devm_kasprintf(priv->dev, GFP_KERNEL, "Core %d", i); + if (!priv->coretemp_label[i]) + return -ENOMEM; + } + + return 0; +} + +static void check_resolved_cores(struct peci_cputemp *priv) +{ + int ret; + + ret = init_core_mask(priv); + if (ret) + return; + + ret = create_temp_label(priv); + if (ret) + bitmap_zero(priv->core_mask, CORE_NUMS_MAX); +} + +static const struct hwmon_ops peci_cputemp_ops = { + .is_visible = cputemp_is_visible, + .read_string = cputemp_read_string, + .read = cputemp_read, +}; + +static const u32 peci_cputemp_temp_channel_config[] = { + /* Die temperature */ + HWMON_T_LABEL | HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT | HWMON_T_CRIT_HYST, + /* DTS margin */ + HWMON_T_LABEL | HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT | HWMON_T_CRIT_HYST, + /* Tcontrol temperature */ + HWMON_T_LABEL | HWMON_T_INPUT | HWMON_T_CRIT, + /* Tthrottle temperature */ + HWMON_T_LABEL | HWMON_T_INPUT, + /* Tjmax temperature */ + HWMON_T_LABEL | HWMON_T_INPUT, + /* Core temperature - for all core channels */ + [channel_core ... CPUTEMP_CHANNEL_NUMS - 1] = HWMON_T_LABEL | HWMON_T_INPUT, + 0 +}; + +static const struct hwmon_channel_info peci_cputemp_temp_channel = { + .type = hwmon_temp, + .config = peci_cputemp_temp_channel_config, +}; + +static const struct hwmon_channel_info *peci_cputemp_info[] = { + &peci_cputemp_temp_channel, + NULL +}; + +static const struct hwmon_chip_info peci_cputemp_chip_info = { + .ops = &peci_cputemp_ops, + .info = peci_cputemp_info, +}; + +static int peci_cputemp_probe(struct auxiliary_device *adev, + const struct auxiliary_device_id *id) +{ + struct device *dev = &adev->dev; + struct peci_device *peci_dev = to_peci_device(dev->parent); + struct peci_cputemp *priv; + struct device *hwmon_dev; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->name = devm_kasprintf(dev, GFP_KERNEL, "peci_cputemp.cpu%d", + peci_dev->info.socket_id); + if (!priv->name) + return -ENOMEM; + + dev_set_drvdata(dev, priv); + priv->dev = dev; + priv->peci_dev = peci_dev; + priv->gen_info = (const struct cpu_info *)id->driver_data; + + check_resolved_cores(priv); + + hwmon_dev = devm_hwmon_device_register_with_info(priv->dev, priv->name, + priv, &peci_cputemp_chip_info, NULL); + + return PTR_ERR_OR_ZERO(hwmon_dev); +} + +static struct resolved_cores_reg resolved_cores_reg_hsx = { + .bus = 1, + .dev = 30, + .func = 3, + .offset = 0xb4, +}; + +static struct resolved_cores_reg resolved_cores_reg_icx = { + .bus = 14, + .dev = 30, + .func = 3, + .offset = 0xd0, +}; + +static const struct cpu_info cpu_hsx = { + .reg = &resolved_cores_reg_hsx, + .min_peci_revision = 0x30, +}; + +static const struct cpu_info cpu_icx = { + .reg = &resolved_cores_reg_icx, + .min_peci_revision = 0x40, +}; + +static const struct auxiliary_device_id peci_cputemp_ids[] = { + { + .name = "peci_cpu.cputemp.hsx", + .driver_data = (kernel_ulong_t)&cpu_hsx, + }, + { + .name = "peci_cpu.cputemp.bdx", + .driver_data = (kernel_ulong_t)&cpu_hsx, + }, + { + .name = "peci_cpu.cputemp.bdxd", + .driver_data = (kernel_ulong_t)&cpu_hsx, + }, + { + .name = "peci_cpu.cputemp.skx", + .driver_data = (kernel_ulong_t)&cpu_hsx, + }, + { + .name = "peci_cpu.cputemp.icx", + .driver_data = (kernel_ulong_t)&cpu_icx, + }, + { + .name = "peci_cpu.cputemp.icxd", + .driver_data = (kernel_ulong_t)&cpu_icx, + }, + { } +}; +MODULE_DEVICE_TABLE(auxiliary, peci_cputemp_ids); + +static struct auxiliary_driver peci_cputemp_driver = { + .probe = peci_cputemp_probe, + .id_table = peci_cputemp_ids, +}; + +module_auxiliary_driver(peci_cputemp_driver); + +MODULE_AUTHOR("Jae Hyun Yoo "); +MODULE_AUTHOR("Iwona Winiarska "); +MODULE_DESCRIPTION("PECI cputemp driver"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(PECI_CPU); From patchwork Mon Jul 12 22:04:46 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Iwona Winiarska X-Patchwork-Id: 473190 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2E3C0C07E9A for ; Mon, 12 Jul 2021 22:11:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1776F61289 for ; Mon, 12 Jul 2021 22:11:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231423AbhGLWOk (ORCPT ); Mon, 12 Jul 2021 18:14:40 -0400 Received: from mga18.intel.com ([134.134.136.126]:10147 "EHLO mga18.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230518AbhGLWOk (ORCPT ); Mon, 12 Jul 2021 18:14:40 -0400 X-IronPort-AV: E=McAfee;i="6200,9189,10043"; a="197335227" X-IronPort-AV: E=Sophos;i="5.84,235,1620716400"; d="scan'208";a="197335227" Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Jul 2021 15:11:51 -0700 X-IronPort-AV: E=Sophos;i="5.84,235,1620716400"; d="scan'208";a="464413638" Received: from jzloch-mobl1.ger.corp.intel.com (HELO localhost) ([10.249.136.11]) by fmsmga008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Jul 2021 15:11:45 -0700 From: Iwona Winiarska To: linux-kernel@vger.kernel.org, openbmc@lists.ozlabs.org Cc: x86@kernel.org, devicetree@vger.kernel.org, linux-aspeed@lists.ozlabs.org, linux-arm-kernel@lists.infradead.org, linux-hwmon@vger.kernel.org, linux-doc@vger.kernel.org, Greg Kroah-Hartman , Rob Herring , Joel Stanley , Andrew Jeffery , Jean Delvare , Guenter Roeck , Jonathan Corbet , Thomas Gleixner , Andy Lutomirski , Ingo Molnar , Borislav Petkov , Yazen Ghannam , Mauro Carvalho Chehab , Pierre-Louis Bossart , Tony Luck , Andy Shevchenko , Jae Hyun Yoo , Iwona Winiarska Subject: [PATCH 13/14] docs: hwmon: Document PECI drivers Date: Tue, 13 Jul 2021 00:04:46 +0200 Message-Id: <20210712220447.957418-14-iwona.winiarska@intel.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210712220447.957418-1-iwona.winiarska@intel.com> References: <20210712220447.957418-1-iwona.winiarska@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org From: Jae Hyun Yoo Add documentation for peci-cputemp driver that provides DTS thermal readings for CPU packages and CPU cores and peci-dimmtemp driver that provides DTS thermal readings for DIMMs. Signed-off-by: Jae Hyun Yoo Co-developed-by: Iwona Winiarska Signed-off-by: Iwona Winiarska Reviewed-by: Pierre-Louis Bossart --- Documentation/hwmon/index.rst | 2 + Documentation/hwmon/peci-cputemp.rst | 93 +++++++++++++++++++++++++++ Documentation/hwmon/peci-dimmtemp.rst | 58 +++++++++++++++++ MAINTAINERS | 2 + 4 files changed, 155 insertions(+) create mode 100644 Documentation/hwmon/peci-cputemp.rst create mode 100644 Documentation/hwmon/peci-dimmtemp.rst diff --git a/Documentation/hwmon/index.rst b/Documentation/hwmon/index.rst index bc01601ea81a..cc76b5b3f791 100644 --- a/Documentation/hwmon/index.rst +++ b/Documentation/hwmon/index.rst @@ -154,6 +154,8 @@ Hardware Monitoring Kernel Drivers pcf8591 pim4328 pm6764tr + peci-cputemp + peci-dimmtemp pmbus powr1220 pxe1610 diff --git a/Documentation/hwmon/peci-cputemp.rst b/Documentation/hwmon/peci-cputemp.rst new file mode 100644 index 000000000000..d3a218ba810a --- /dev/null +++ b/Documentation/hwmon/peci-cputemp.rst @@ -0,0 +1,93 @@ +.. SPDX-License-Identifier: GPL-2.0-only + +Kernel driver peci-cputemp +========================== + +Supported chips: + One of Intel server CPUs listed below which is connected to a PECI bus. + * Intel Xeon E5/E7 v3 server processors + Intel Xeon E5-14xx v3 family + Intel Xeon E5-24xx v3 family + Intel Xeon E5-16xx v3 family + Intel Xeon E5-26xx v3 family + Intel Xeon E5-46xx v3 family + Intel Xeon E7-48xx v3 family + Intel Xeon E7-88xx v3 family + * Intel Xeon E5/E7 v4 server processors + Intel Xeon E5-16xx v4 family + Intel Xeon E5-26xx v4 family + Intel Xeon E5-46xx v4 family + Intel Xeon E7-48xx v4 family + Intel Xeon E7-88xx v4 family + * Intel Xeon Scalable server processors + Intel Xeon D family + Intel Xeon Bronze family + Intel Xeon Silver family + Intel Xeon Gold family + Intel Xeon Platinum family + + Datasheet: Available from http://www.intel.com/design/literature.htm + +Author: Jae Hyun Yoo + +Description +----------- + +This driver implements a generic PECI hwmon feature which provides Digital +Thermal Sensor (DTS) thermal readings of the CPU package and CPU cores that are +accessible via the processor PECI interface. + +All temperature values are given in millidegree Celsius and will be measurable +only when the target CPU is powered on. + +Sysfs interface +------------------- + +======================= ======================================================= +temp1_label "Die" +temp1_input Provides current die temperature of the CPU package. +temp1_max Provides thermal control temperature of the CPU package + which is also known as Tcontrol. +temp1_crit Provides shutdown temperature of the CPU package which + is also known as the maximum processor junction + temperature, Tjmax or Tprochot. +temp1_crit_hyst Provides the hysteresis value from Tcontrol to Tjmax of + the CPU package. + +temp2_label "DTS" +temp2_input Provides current DTS temperature of the CPU package. +temp2_max Provides thermal control temperature of the CPU package + which is also known as Tcontrol. +temp2_crit Provides shutdown temperature of the CPU package which + is also known as the maximum processor junction + temperature, Tjmax or Tprochot. +temp2_crit_hyst Provides the hysteresis value from Tcontrol to Tjmax of + the CPU package. + +temp3_label "Tcontrol" +temp3_input Provides current Tcontrol temperature of the CPU + package which is also known as Fan Temperature target. + Indicates the relative value from thermal monitor trip + temperature at which fans should be engaged. +temp3_crit Provides Tcontrol critical value of the CPU package + which is same to Tjmax. + +temp4_label "Tthrottle" +temp4_input Provides current Tthrottle temperature of the CPU + package. Used for throttling temperature. If this value + is allowed and lower than Tjmax - the throttle will + occur and reported at lower than Tjmax. + +temp5_label "Tjmax" +temp5_input Provides the maximum junction temperature, Tjmax of the + CPU package. + +temp[6-N]_label Provides string "Core X", where X is resolved core + number. +temp[6-N]_input Provides current temperature of each core. +temp[6-N]_max Provides thermal control temperature of the core. +temp[6-N]_crit Provides shutdown temperature of the core. +temp[6-N]_crit_hyst Provides the hysteresis value from Tcontrol to Tjmax of + the core. + +======================= ======================================================= diff --git a/Documentation/hwmon/peci-dimmtemp.rst b/Documentation/hwmon/peci-dimmtemp.rst new file mode 100644 index 000000000000..1778d9317e43 --- /dev/null +++ b/Documentation/hwmon/peci-dimmtemp.rst @@ -0,0 +1,58 @@ +.. SPDX-License-Identifier: GPL-2.0 + +Kernel driver peci-dimmtemp +=========================== + +Supported chips: + One of Intel server CPUs listed below which is connected to a PECI bus. + * Intel Xeon E5/E7 v3 server processors + Intel Xeon E5-14xx v3 family + Intel Xeon E5-24xx v3 family + Intel Xeon E5-16xx v3 family + Intel Xeon E5-26xx v3 family + Intel Xeon E5-46xx v3 family + Intel Xeon E7-48xx v3 family + Intel Xeon E7-88xx v3 family + * Intel Xeon E5/E7 v4 server processors + Intel Xeon E5-16xx v4 family + Intel Xeon E5-26xx v4 family + Intel Xeon E5-46xx v4 family + Intel Xeon E7-48xx v4 family + Intel Xeon E7-88xx v4 family + * Intel Xeon Scalable server processors + Intel Xeon D family + Intel Xeon Bronze family + Intel Xeon Silver family + Intel Xeon Gold family + Intel Xeon Platinum family + + Datasheet: Available from http://www.intel.com/design/literature.htm + +Author: Jae Hyun Yoo + +Description +----------- + +This driver implements a generic PECI hwmon feature which provides Digital +Thermal Sensor (DTS) thermal readings of DIMM components that are accessible +via the processor PECI interface. + +All temperature values are given in millidegree Celsius and will be measurable +only when the target CPU is powered on. + +Sysfs interface +------------------- + +======================= ======================================================= + +temp[N]_label Provides string "DIMM CI", where C is DIMM channel and + I is DIMM index of the populated DIMM. +temp[N]_input Provides current temperature of the populated DIMM. +temp[N]_max Provides thermal control temperature of the DIMM. +temp[N]_crit Provides shutdown temperature of the DIMM. + +======================= ======================================================= + +Note: + DIMM temperature attributes will appear when the client CPU's BIOS + completes memory training and testing. diff --git a/MAINTAINERS b/MAINTAINERS index 35ba9e3646bd..d16da127bbdc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14509,6 +14509,8 @@ M: Iwona Winiarska R: Jae Hyun Yoo L: linux-hwmon@vger.kernel.org S: Supported +F: Documentation/hwmon/peci-cputemp.rst +F: Documentation/hwmon/peci-dimmtemp.rst F: drivers/hwmon/peci/ PECI SUBSYSTEM