From nobody Fri Dec 19 17:36:46 2025 Received: from esa.microchip.iphmx.com (esa.microchip.iphmx.com [68.232.153.233]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C027D2820B0; Tue, 15 Apr 2025 13:27:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=68.232.153.233 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744723653; cv=none; b=NQbukTZhS7f0sGJZkuHK3EvFQ5+U6Ks78YInOe7Yk/AlUyNBKGACX1KZaRj10emUeglpGpRfgk3bM6oO7C20wTlrBm30+pjGVgvw//NSVUamTM5p1dfuujD3KwiB03WZxJDyC/8FBMlRTJYO0oLEsvgFVraezkeAtiQrsz1RM4Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744723653; c=relaxed/simple; bh=xZRvVk5qzUx/BSBKzSNc1vMSD4GWcEGpcr1tfcGLHmU=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Pg6j0VHqtShUvmiVF5VYUbDX50aaNt5IBdZjeWiEj/VZ6Ds3MwyJman9BF02+aKouCzmP5mt7dGa7nw0e6TudpfXRZBxPg/96NaHCQX73koc0DRgYYYQg36A43dJUXZDWv5mkI6LYg9qpTNe5KEr39AWODwIbEdsAvBwT09U5QI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=microchip.com; spf=pass smtp.mailfrom=microchip.com; dkim=pass (2048-bit key) header.d=microchip.com header.i=@microchip.com header.b=u08LAllH; arc=none smtp.client-ip=68.232.153.233 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=microchip.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=microchip.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=microchip.com header.i=@microchip.com header.b="u08LAllH" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1744723652; x=1776259652; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=xZRvVk5qzUx/BSBKzSNc1vMSD4GWcEGpcr1tfcGLHmU=; b=u08LAllHVXZU5ZadnLBpf981BYcuQDuahIaVssLZ9hMbgXs8Jb8FVoZx OL1fc9vkhRRasYgn7iaS/9AC51MY2T9VjE69dxVjzg0Wp9kzLe9JelZ/s apGbWNcA+dysmjjXQNBCeCJ3klMUSzC1ka+Lcsbw2AWu5mlQDcGEgyR91 q+iQd60RfzxbUt6G3Z/IsLxvyNcEKiTdKb3iVbe4Dh0SloGYihlL9+OZ2 8nxoQMqGihVTIycWCvG3U/WeiVbco+X14TxD31GFaxsKnWfeEIP6yfd/2 2OQaQkfiQ5GfXyo0/2hLb0PumVxL7B142AFh4kFZ5I1Nsaz81C9YmS+TQ w==; X-CSE-ConnectionGUID: FN4IPNwESQaGizKyN6d47Q== X-CSE-MsgGUID: V4DD7CvSTzCKsqBNaCUQUw== X-IronPort-AV: E=Sophos;i="6.15,213,1739862000"; d="scan'208";a="40495080" X-Amp-Result: SKIPPED(no attachment in message) Received: from unknown (HELO email.microchip.com) ([170.129.1.10]) by esa3.microchip.iphmx.com with ESMTP/TLS/ECDHE-RSA-AES128-GCM-SHA256; 15 Apr 2025 06:27:31 -0700 Received: from chn-vm-ex04.mchp-main.com (10.10.85.152) by chn-vm-ex02.mchp-main.com (10.10.85.144) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.44; Tue, 15 Apr 2025 06:27:01 -0700 Received: from vduicu-Virtual-Machine.mshome.net (10.10.85.11) by chn-vm-ex04.mchp-main.com (10.10.85.152) with Microsoft SMTP Server id 15.1.2507.44 via Frontend Transport; Tue, 15 Apr 2025 06:26:59 -0700 From: To: CC: , , , , , , Subject: [PATCH v1 1/2] dt-bindings: iio: temperature: add support for MCP998X Date: Tue, 15 Apr 2025 16:26:22 +0300 Message-ID: <20250415132623.14913-2-victor.duicu@microchip.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20250415132623.14913-1-victor.duicu@microchip.com> References: <20250415132623.14913-1-victor.duicu@microchip.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Victor Duicu This is the devicetree schema for Microchip MCP998X/33 and MCP998XD/33D Multichannel Automotive Temperature Monitor Family. Signed-off-by: Victor Duicu --- .../iio/temperature/microchip,mcp9982.yaml | 182 ++++++++++++++++++ 1 file changed, 182 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/temperature/micro= chip,mcp9982.yaml diff --git a/Documentation/devicetree/bindings/iio/temperature/microchip,mc= p9982.yaml b/Documentation/devicetree/bindings/iio/temperature/microchip,mc= p9982.yaml new file mode 100644 index 000000000000..8cbf897d1278 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/temperature/microchip,mcp9982.y= aml @@ -0,0 +1,182 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/temperature/microchip,mcp9982.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Microchip MCP998X/33 and MCP998XD/33D Multichannel Automotive Tempe= rature Monitor Family + +maintainers: + - Victor Duicu + +description: | + The MCP998X/33 and MCP998XD/33D family is a high-accuracy 2-wire multich= annel + automotive temperature monitor. + The datasheet can be found here: + https://ww1.microchip.com/downloads/aemDocuments/documents/MSLD/Produc= tDocuments/DataSheets/MCP998X-Family-Data-Sheet-DS20006827.pdf + +properties: + compatible: + enum: + - microchip,mcp9933 + - microchip,mcp9933D + - microchip,mcp9982 + - microchip,mcp9982D + - microchip,mcp9983 + - microchip,mcp9983D + - microchip,mcp9984 + - microchip,mcp9984D + - microchip,mcp9985 + - microchip,mcp9985D + + reg: + maxItems: 1 + =20 + interrupts: + maxItems: 2 + =20 + interrupt-names: + description: | + ALERT1 indicates a HIGH or LOW limit was exceeded. + ALERT2 indicates a THERM limit was exceeded. + items: + - const: ALERT1 + - const: ALERT2 + =20 + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + + microchip,temp-hysteresis: + description: | + Value of temperature limit hysteresis. + Omit this tag to set the default value. + $ref: /schemas/types.yaml#/definitions/uint32 + =20 + microchip,extended-temp-range: + description: | + Set the chip to work in the extended temperature range -64 degrees C= to 191.875 degrees C. + Omit this tag to set the default range 0 degrees C to 127.875 degree= s C + type: boolean + =20 + microchip,beta-channel1: + description: | + The beta compensation factor for external channel 1 can be set + by the user, or can be set automatically by the chip. + If one wants to enable beta autodetection, omit this tag. + Please consult the documentation if one wants to set a specific beta. + If anti-parallel diode operation is enabled, the default value is set + and can't be changed. + type: boolean + =20 + microchip,beta-channel2: + description: | + The beta compensation factor for external channel 2 can be set + by the user, or can be set automatically by the chip. + If one wants to enable beta autodetection, omit this tag. + Please consult the documentation if one wants to set a specific beta. + If anti-parallel diode operation is enabled, the default value is set + and can't be changed. + type: boolean + =20 + microchip,apdd-state: + description: | + Enable anti-parallel diode mode operation. + Omit this tag to disable anti-parallel diode mode by default. + type: boolean + =20 + microchip,recd12: + description: | + Enable resistance error correction for external channels 1 and 2. + Not all chips support resistance error correction on external + channels 1 and 2, please consult the documentation. + Omit this tag to disable REC for channels 1 and 2 by default. + type: boolean + =20 + microchip,recd34: + description: | + Enable resistance error correction for external channels 3 and 4. + Not all chips support resistance error correction on external + channels 3 and 4, please consult the documentation. + Omit this tag to disable REC for channels 3 and 4 by default. + type: boolean + =20 + label: + description: Unique name to identify which device this is. + =20 + vdd-supply: true +=20 +patternProperties: + "^channel@[1-4]+$": + description: | + Represents the external temperature channels to which a remote diode= is + connected. + type: object + + properties: + reg: + items: + minimum: 1 + maximum: 4 + =20 + microchip,ideality-factor: + description: | + Each channel has an ideality factor. + Beta compensation and resistance error correction automatically = correct + for most ideality error. So ideality factor does not need to be = adjusted in general. + Omit this tag in order to set the default value. + Please consult the documentation if one wants to set a specific = ideality value. + $ref: /schemas/types.yaml#/definitions/uint32 + =20 + label: + description: Unique name to identify which channel this is. + =20 + required: + - reg + =20 + unevaluatedProperties: false + +required: + - compatible + - reg + - vdd-supply + +additionalProperties: false + +examples: + - | + i2c { + #address-cells =3D <1>; + #size-cells =3D <0>; + =20 + temperature-sensor@4c { + compatible =3D "microchip,mcp9985"; + reg =3D <0x4c>; + =20 + #address-cells =3D <1>; + #size-cells =3D <0>; + + label =3D "temperature-sensor"; + =20 + microchip,temp-hysteresis =3D <10>; + microchip,extended-temp-range; + microchip,apdd-state; + microchip,recd12; + microchip,recd34; + vdd-supply =3D <&vdd>; + =20 + channel@1{ + reg =3D <0x1>; + label =3D "CPU Temperature"; + }; + =20 + channel@2{ + reg =3D <0x2>; + label =3D "GPU Temperature"; + }; + }; + }; + +... --=20 2.45.2 From nobody Fri Dec 19 17:36:46 2025 Received: from esa.microchip.iphmx.com (esa.microchip.iphmx.com [68.232.153.233]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 72F7E297A67; Tue, 15 Apr 2025 13:28:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=68.232.153.233 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744723703; cv=none; b=qBGbYWILpYbFx8KOKE+OqQ0xVmVc2CzIgCGH3VCHFhxQgbl0HyIsz0YrWs0fstrxk/hAiSHBqHfuDVzyf6Ss8K5lAMIfj2apMGusFl7V4FJg0FBMv/GMGFmojEU1CfD4UXw49uVSJM5cLZJGou85SRHSBePcEzwMUpXHleJotDU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744723703; c=relaxed/simple; bh=I5HEUK6GDAgzz1al1NoxKGJFGaTV1dZt33bpL9WlF/M=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=jtmzLPquSW4NB+xG16AlNN94cy309xwHPU2LZxHtCv8E4M8LMsA0iBL/KVpnEw/nCEYvKotQewzHnf26mPBIo/+j+KLYyTCkKXLdW+Hto/hgaiFpHnvniGvmqL3Jc38nPj+9/TtIcUJzDppRMGCEWgweUJ6IhzgHYpE4zIujb3k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=microchip.com; spf=pass smtp.mailfrom=microchip.com; dkim=pass (2048-bit key) header.d=microchip.com header.i=@microchip.com header.b=qdvUwHU6; arc=none smtp.client-ip=68.232.153.233 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=microchip.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=microchip.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=microchip.com header.i=@microchip.com header.b="qdvUwHU6" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1744723702; x=1776259702; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=I5HEUK6GDAgzz1al1NoxKGJFGaTV1dZt33bpL9WlF/M=; b=qdvUwHU6K8Jo72SCl7kEzdN5G2HaeWlO9aFjaV2NNSKDgZPBzRtU7Lzl OpkhMMwTDD4xQJ8Cohp2Gn4NMaqjLj8+nThHIzD7F+OsFG458+RxLopLq 3pbPR3i256P1zwEzqtjE6anadqTTXfFuRw5IWrfjlNLYxGLwDNz3fetkn mMk2BG3BJxk+KbbBe5KoX8D0WlLRj4xCDCT3cf5vpedUMRgIRy9DayIPv tSfHBF8kyO+5GXTaNHkYJoPtjFKZj4lPIglLrtng9CChcGtm5lPvmddML 2N5xJ+6k73ulW7mCSmvN+qXFAc7zPUez6fT+hatnjWhdp9BgzkGFqxN70 w==; X-CSE-ConnectionGUID: Ib73720AQlOOLHXW61IHCA== X-CSE-MsgGUID: NjYHdrbgSZCZnSsK81o5WQ== X-IronPort-AV: E=Sophos;i="6.15,213,1739862000"; d="scan'208";a="271861953" X-Amp-Result: SKIPPED(no attachment in message) Received: from unknown (HELO email.microchip.com) ([170.129.1.10]) by esa5.microchip.iphmx.com with ESMTP/TLS/ECDHE-RSA-AES128-GCM-SHA256; 15 Apr 2025 06:27:12 -0700 Received: from chn-vm-ex04.mchp-main.com (10.10.85.152) by chn-vm-ex04.mchp-main.com (10.10.85.152) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.44; Tue, 15 Apr 2025 06:27:04 -0700 Received: from vduicu-Virtual-Machine.mshome.net (10.10.85.11) by chn-vm-ex04.mchp-main.com (10.10.85.152) with Microsoft SMTP Server id 15.1.2507.44 via Frontend Transport; Tue, 15 Apr 2025 06:27:02 -0700 From: To: CC: , , , , , , Subject: [PATCH v1 2/2] iio: temperature: add support for MCP998X Date: Tue, 15 Apr 2025 16:26:23 +0300 Message-ID: <20250415132623.14913-3-victor.duicu@microchip.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20250415132623.14913-1-victor.duicu@microchip.com> References: <20250415132623.14913-1-victor.duicu@microchip.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Victor Duicu This is the driver for Microchip MCP998X/33 and MCP998XD/33D Multichannel Automotive Monitor Family. Signed-off-by: Victor Duicu --- .../testing/sysfs-bus-iio-temperature-mcp9982 | 17 + MAINTAINERS | 7 + drivers/iio/temperature/Kconfig | 10 + drivers/iio/temperature/Makefile | 1 + drivers/iio/temperature/mcp9982.c | 794 ++++++++++++++++++ 5 files changed, 829 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-temperature-mcp= 9982 create mode 100644 drivers/iio/temperature/mcp9982.c diff --git a/Documentation/ABI/testing/sysfs-bus-iio-temperature-mcp9982 b/= Documentation/ABI/testing/sysfs-bus-iio-temperature-mcp9982 new file mode 100644 index 000000000000..de3360fb05be --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-iio-temperature-mcp9982 @@ -0,0 +1,17 @@ +What: /sys/bus/iio/devices/iio:deviceX/running_average_window +KernelVersion: 6.14 +Contact: linux-iio@vger.kernel.org +Description: + This attribute controls the number of samples for the=20 + running average window applied to External Channel 1. + Using this method the temperature spikes are reduced. + X is the IIO index of the device. + +What: /sys/bus/iio/devices/iio:deviceX/running_average_window_available +KernelVersion: 6.14 +Contact: linux-iio@vger.kernel.org +Description: + Reading returns a list with the possible number of samples used + in the running average window. The window can be composed of 1, + 4 or 8 previous samples. X is the IIO index of the device. + diff --git a/MAINTAINERS b/MAINTAINERS index 01079a189c93..2cbad9beb182 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -15863,6 +15863,13 @@ S: Maintained F: Documentation/devicetree/bindings/iio/adc/microchip,mcp3911.yaml F: drivers/iio/adc/mcp3911.c =20 +MICROCHIP MCP9982 TEMPERATURE DRIVER +M: Victor Duicu +L: linux-iio@vger.kernel.org +S: Supported +F: Documentation/devicetree/bindings/iio/temperature/microchip,mcp9982.yaml +F: drivers/iio/temperature/mcp9982.c + MICROCHIP MMC/SD/SDIO MCI DRIVER M: Aubin Constans S: Maintained diff --git a/drivers/iio/temperature/Kconfig b/drivers/iio/temperature/Kcon= fig index 1244d8e17d50..10b0967c1749 100644 --- a/drivers/iio/temperature/Kconfig +++ b/drivers/iio/temperature/Kconfig @@ -182,4 +182,14 @@ config MCP9600 This driver can also be built as a module. If so, the module will be called mcp9600. =20 +config MCP9982 + tristate "Microchip Technology MCP9982 driver" + depends on I2C + help + Say yes here to build support for Microchip Technology's MCP998X/33 + and MCP998XD/33D Multichannel Automotive Temperature Monitor Family. + + This driver can also be built as a module. If so, the module + will be called mcp9982. + endmenu diff --git a/drivers/iio/temperature/Makefile b/drivers/iio/temperature/Mak= efile index 07d6e65709f7..83f5f4bb4ff3 100644 --- a/drivers/iio/temperature/Makefile +++ b/drivers/iio/temperature/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_MAX30208) +=3D max30208.o obj-$(CONFIG_MAX31856) +=3D max31856.o obj-$(CONFIG_MAX31865) +=3D max31865.o obj-$(CONFIG_MCP9600) +=3D mcp9600.o +obj-$(CONFIG_MCP9982) +=3D mcp9982.o obj-$(CONFIG_MLX90614) +=3D mlx90614.o obj-$(CONFIG_MLX90632) +=3D mlx90632.o obj-$(CONFIG_MLX90632) +=3D mlx90635.o diff --git a/drivers/iio/temperature/mcp9982.c b/drivers/iio/temperature/mc= p9982.c new file mode 100644 index 000000000000..f4edc7b6a437 --- /dev/null +++ b/drivers/iio/temperature/mcp9982.c @@ -0,0 +1,794 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * IIO driver for MCP998X/33 and MCP998XD/33D Multichannel Automotive Temp= erature Monitor Family + * + * Copyright (C) 2025 Microchip Technology Inc. and its subsidiaries + * + * Author: Victor Duicu + * + * Datasheet can be found here: + * https://ww1.microchip.com/downloads/aemDocuments/documents/MSLD/Product= Documents/DataSheets/MCP998X-Family-Data-Sheet-DS20006827.pdf + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* MCP9982 Registers */ +#define MCP9982_INT_HIGH_BYTE_ADDR(index) (2 * (index)) +#define MCP9982_INT_LOW_BYTE_ADDR(index) (2 * (index) + 1) +#define MCP9982_ONE_SHOT_ADDR 0x0A +#define MCP9982_INT_HIGH_LIMIT_ADDR 0x0B +#define MCP9982_INT_LOW_LIMIT_ADDR 0x0C +#define MCP9982_EXT1_HIGH_LIMIT_HIGH_BYTE_ADDR 0x0D +#define MCP9982_EXT1_HIGH_LIMIT_LOW_BYTE_ADDR 0x0E +#define MCP9982_EXT1_LOW_LIMIT_HIGH_BYTE_ADDR 0x0F +#define MCP9982_EXT1_LOW_LIMIT_LOW_BYTE_ADDR 0x10 +#define MCP9982_INT_THERM_LIMIT_ADDR 0x1D +#define MCP9982_EXT1_THERM_LIMIT_ADDR 0x1E +#define MCP9982_CFG_ADDR 0x22 +#define MCP9982_CONV_ADDR 0x24 +#define MCP9982_HYS_ADDR 0x25 +#define MCP9982_CONSEC_ALRT_ADDR 0x26 +#define MCP9982_ALRT_CFG_ADDR 0x27 +#define MCP9982_RUNNING_AVG_ADDR 0x28 +#define MCP9982_HOTTEST_CFG_ADDR 0x29 +#define MCP9982_STATUS_ADDR 0x2A +#define MCP9982_EXT_FAULT_STATUS_ADDR 0x2B +#define MCP9982_HIGH_LIMIT_STATUS_ADDR 0x2C +#define MCP9982_LOW_LIMIT_STATUS_ADDR 0x2D +#define MCP9982_THERM_LIMIT_STATUS_ADDR 0x2E +#define MCP9982_HOTTEST_HIGH_BYTE_ADDR 0x2F +#define MCP9982_HOTTEST_LOW_BYTE_ADDR 0x30 +#define MCP9982_HOTTEST_STATUS_ADDR 0x31 +#define MCP9982_THERM_SHTDWN_CFG_ADDR 0x32 +#define MCP9982_HRDW_THERM_SHTDWN_LIMIT_ADDR 0x33 +#define MCP9982_EXT_BETA_CFG_ADDR(index) ((index) + 52) +#define MCP9982_EXT_IDEAL_ADDR(index) ((index) + 54) + +/* MCP9982 Bits */ +#define MCP9982_CFG_MSKAL BIT(7) +#define MCP9982_CFG_RS BIT(6) +#define MCP9982_CFG_ATTHM BIT(5) +#define MCP9982_CFG_RECD12 BIT(4) +#define MCP9982_CFG_RECD34 BIT(3) +#define MCP9982_CFG_RANGE BIT(2) +#define MCP9982_CFG_DA_ENA BIT(1) +#define MCP9982_CFG_APDD BIT(0) + +/* MCP9982 Default Values */ +#define MCP9982_TEMP_OFFSET 64 +#define MCP9982_CFG_MSKAL_DEFAULT 1 +#define MCP9982_CFG_RS_DEFAULT 1 +#define MCP9982_CFG_ATTHM_DEFAULT 1 +#define MCP9982_CFG_DA_ENA_DEFAULT 0 +#define MCP9982_CONSEC_ALRT_DEFAULT 112 +#define MCP9982_SAMPLING_FREQ_CODE_DEFAULT 6 +#define MCP9982_BETA_AUTODETECT_ENABLE 16 +#define MCP9982_BETA_MAX_VALUE 15 +#define MCP9982_IDEALITY_MAX_VALUE 63 +#define MCP9982_HYSTERESIS_MAX_VALUE 255 +#define MCP9982_IDEALITY_FACTOR_DEFAULT 18 +#define MCP9982_HYSTERESIS_DEFAULT 10 +#define MCP9982_TEMP_RANGE_DEFAULT 0 +#define MCP9982_APDD_DEFAULT 1 +#define MCP9982_RECD_DEFAULT 1 + +#define MCP9982_NR_CUSTOM_ATTR 2 +#define MCP9982_DEV_ATTR(name) (&iio_dev_attr_##name.dev_attr.attr) + +/* Running average window can be set as: + * - 1 sample + * - 4 samples + * - 8 samples + */ +#define MCP9982_RUNNING_AVERAGE_WINDOW_AVAILABLE "1 4 8" + +/* The maximum number of channels a member of the family can have */ +#define MCP9982_MAX_NUM_CHANNELS 5 + +#define MCP9982_CHAN(index, si, __address) ({ \ + struct iio_chan_spec __chan =3D { \ + .type =3D IIO_TEMP, \ + .info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_all_available =3D BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .info_mask_shared_by_all =3D BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .channel =3D index, \ + .address =3D __address, \ + .scan_index =3D si, \ + .scan_type =3D { \ + .sign =3D 'u', \ + .realbits =3D 8, \ + .storagebits =3D 8, \ + .endianness =3D IIO_CPU \ + }, \ + .indexed =3D 1, \ + }; \ + __chan; \ +}) + +enum mcp9982_ids { + MCP9933, + MCP9933D, + MCP9982, + MCP9982D, + MCP9983, + MCP9983D, + MCP9984, + MCP9984D, + MCP9985, + MCP9985D, +}; + +/* + * struct mcp9982_features - features of a mcp9982 instance + * @phys_channels: number of physical channels supported by the chip + * @name: chip's name + */ +struct mcp9982_features { + u8 phys_channels; + const char *name; +}; + +static const struct mcp9982_features mcp9982_chip_config[] =3D { + [MCP9933] =3D { + .name =3D "mcp9933", + .phys_channels =3D 3, + }, + [MCP9933D] =3D { + .name =3D "mcp9933D", + .phys_channels =3D 3, + }, + [MCP9982] =3D { + .name =3D "mcp9982", + .phys_channels =3D 2, + }, + [MCP9982D] =3D { + .name =3D "mcp9982D", + .phys_channels =3D 2, + }, + [MCP9983] =3D { + .name =3D "mcp9983", + .phys_channels =3D 3, + }, + [MCP9983D] =3D { + .name =3D "mcp9983D", + .phys_channels =3D 3, + }, + [MCP9984] =3D { + .name =3D "mcp9984", + .phys_channels =3D 4, + }, + [MCP9984D] =3D { + .name =3D "mcp9984D", + .phys_channels =3D 4, + }, + [MCP9985] =3D { + .name =3D "mcp9985", + .phys_channels =3D 5, + }, + [MCP9985D] =3D { + .name =3D "mcp9985D", + .phys_channels =3D 5, + }, +}; + +static const int mcp9982_fractional_values[] =3D { + 0, + 125000, + 250000, + 375000, + 500000, + 625000, + 750000, + 875000, +}; + +static const int mcp9982_conv_rate[][2] =3D { + {0, 62500}, + {0, 125000}, + {0, 250000}, + {0, 500000}, + {1, 0}, + {2, 0}, + {4, 0}, + {8, 0}, + {16, 0}, + {32, 0}, + {64, 0}, +}; + +/* mcp9982 regmap configuration */ +static const struct regmap_range mcp9982_regmap_wr_ranges[] =3D { + regmap_reg_range(MCP9982_ONE_SHOT_ADDR, MCP9982_EXT1_LOW_LIMIT_LOW_BYTE_A= DDR), + regmap_reg_range(MCP9982_INT_THERM_LIMIT_ADDR, MCP9982_EXT1_THERM_LIMIT_A= DDR), + regmap_reg_range(MCP9982_CFG_ADDR, MCP9982_CFG_ADDR), + regmap_reg_range(MCP9982_CONV_ADDR, MCP9982_HOTTEST_CFG_ADDR), + regmap_reg_range(MCP9982_THERM_SHTDWN_CFG_ADDR, MCP9982_THERM_SHTDWN_CFG_= ADDR), + regmap_reg_range(MCP9982_EXT_BETA_CFG_ADDR(0), MCP9982_EXT_IDEAL_ADDR(3)), +}; + +static const struct regmap_access_table mcp9982_regmap_wr_table =3D { + .yes_ranges =3D mcp9982_regmap_wr_ranges, + .n_yes_ranges =3D ARRAY_SIZE(mcp9982_regmap_wr_ranges), +}; + +static const struct regmap_range mcp9982_regmap_rd_ranges[] =3D { + regmap_reg_range(MCP9982_INT_HIGH_BYTE_ADDR(0), MCP9982_EXT1_LOW_LIMIT_LO= W_BYTE_ADDR), + regmap_reg_range(MCP9982_INT_THERM_LIMIT_ADDR, MCP9982_EXT1_THERM_LIMIT_A= DDR), + regmap_reg_range(MCP9982_CFG_ADDR, MCP9982_CFG_ADDR), + regmap_reg_range(MCP9982_CONV_ADDR, MCP9982_EXT_IDEAL_ADDR(3)), +}; + +static const struct regmap_access_table mcp9982_regmap_rd_table =3D { + .yes_ranges =3D mcp9982_regmap_rd_ranges, + .n_yes_ranges =3D ARRAY_SIZE(mcp9982_regmap_rd_ranges), +}; + +static const struct regmap_config mcp9982_regmap_config =3D { + .reg_bits =3D 8, + .val_bits =3D 8, + .rd_table =3D &mcp9982_regmap_rd_table, + .wr_table =3D &mcp9982_regmap_wr_table, +}; + +enum mcp9982_channels { + MCP9982_CHAN_INT =3D 0, + MCP9982_CHAN_EXT1 =3D 1, + MCP9982_CHAN_EXT2 =3D 2, + MCP9982_CHAN_EXT3 =3D 3, + MCP9982_CHAN_EXT4 =3D 4, +}; + +/** + * struct mcp9992_priv - information about chip parameters + * @client: the i2c-client attached to the device + * @regmap: device register map + * @iio_info iio_info + * @iio_chan specifications of channels + * @num_channels number of physical channels + * @lock synchronize access to driver's state members + * @running_avg number of samples in the running average window + * @hysteresis value of temperature hysteresis + * @temp_range_code coded value representing the set temperature range + * @labels labels of the channels + * @chip_name name of the chip present + * @beta_user_value value given by the user for beta on channel 1 and 2 + * @apdd state of anti-parallel diode mode + * @recd12 state of REC on channels 1 and 2 + * @recd34 state of REC on channels 3 and 4 + * @ideality_user_value values given by user to ideality factor for all c= hannels + */ + +struct mcp9982_priv { + struct i2c_client *client; + struct regmap *regmap; + struct iio_info iio_info; + + struct iio_chan_spec *iio_chan; + u8 num_channels; + + /* + * Synchronize access to private members, and ensure + * atomicity of consecutive regmap operations. + */ + struct mutex lock; + + int running_avg; + int hysteresis; + int temp_range_code; + char *labels[MCP9982_MAX_NUM_CHANNELS]; + char *chip_name; + int beta_user_value[2]; + int apdd; + int recd12; + int recd34; + int ideality_user_value[4]; +}; + +static int mcp9982_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, int *type, int *length, long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + *type =3D IIO_VAL_INT_PLUS_MICRO; + *vals =3D mcp9982_conv_rate[0]; + *length =3D ARRAY_SIZE(mcp9982_conv_rate) * 2; + return IIO_AVAIL_LIST; + default: + return -EINVAL; + } +} + +static int mcp9982_read_raw(struct iio_dev *indio_dev, struct iio_chan_spe= c const *chan, + int *val, int *val2, long mask) +{ + struct mcp9982_priv *priv =3D iio_priv(indio_dev); + int ret, val3, HIGH_BYTE, LOW_BYTE; + + /* Write in ONESHOT register to take a new reading */ + ret =3D regmap_write(priv->regmap, MCP9982_ONE_SHOT_ADDR, 1); + if (ret) + return ret; + + guard(mutex)(&priv->lock); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + HIGH_BYTE =3D MCP9982_INT_HIGH_BYTE_ADDR(chan->channel); + LOW_BYTE =3D MCP9982_INT_LOW_BYTE_ADDR(chan->channel); + + ret =3D regmap_read(priv->regmap, HIGH_BYTE, val); + if (ret) + return ret; + + if (priv->temp_range_code) + *val -=3D MCP9982_TEMP_OFFSET; + + ret =3D regmap_read(priv->regmap, LOW_BYTE, val2); + if (ret) + return ret; + + *val2 =3D mcp9982_fractional_values[*val2 >> 5]; + + return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_SAMP_FREQ: + ret =3D regmap_read(priv->regmap, MCP9982_CONV_ADDR, &val3); + if (ret) + return ret; + + *val =3D mcp9982_conv_rate[val3][0]; + *val2 =3D mcp9982_conv_rate[val3][1]; + + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } +} + +static int mcp9982_read_label(struct iio_dev *indio_dev, struct iio_chan_s= pec const *chan, + char *label) +{ + struct mcp9982_priv *priv =3D iio_priv(indio_dev); + + if (chan->channel < 0 || chan->channel > 4) + return -EINVAL; + + return sprintf(label, "%s\n", priv->labels[chan->channel]); +} + +static int mcp9982_write_raw_get_fmt(struct iio_dev *indio_dev, struct iio= _chan_spec const *chan, + long info) +{ + switch (info) { + case IIO_CHAN_INFO_SAMP_FREQ: + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } +} + +static int mcp9982_write_raw(struct iio_dev *indio_dev, struct iio_chan_sp= ec const *chan, + int val, int val2, long mask) +{ + struct mcp9982_priv *priv =3D iio_priv(indio_dev); + struct device *dev =3D &priv->client->dev; + int i; + int status =3D 0; + + guard(mutex)(&priv->lock); + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + for (i =3D 0; i < ARRAY_SIZE(mcp9982_conv_rate); i++) { + if (val =3D=3D mcp9982_conv_rate[i][0] && + val2 =3D=3D mcp9982_conv_rate[i][1]){ + status =3D 1; + break; + } + } + if (!status) + return dev_err_probe(dev, -EINVAL, "Sampling Frequency is invalid\n"); + + return regmap_write(priv->regmap, MCP9982_CONV_ADDR, i); + default: + return -EINVAL; + } +} + +static ssize_t mcp9982_running_average_window_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iio_dev *indio_dev =3D dev_to_iio_dev(dev); + struct mcp9982_priv *priv =3D iio_priv(indio_dev); + + return sprintf(buf, "%u sample(s)\n", priv->running_avg); +} + +static ssize_t mcp9982_running_average_window_avail_show(struct device *de= v, + struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%s\n", MCP9982_RUNNING_AVERAGE_WINDOW_AVAILABLE); +} + +static ssize_t mcp9982_running_average_window_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct iio_dev *indio_dev =3D dev_to_iio_dev(dev); + struct mcp9982_priv *priv =3D iio_priv(indio_dev); + int val, ret, reg_val; + + if (kstrtouint(buf, 10, &val)) { + dev_err(dev, "Value is not a number\n"); + return -EINVAL; + } + + switch (val) { + case 1: + reg_val =3D 0; + break; + case 4: + reg_val =3D 1; + break; + case 8: + reg_val =3D 3; + break; + default: + dev_err(dev, "Value is invalid\n"); + return -EINVAL; + } + + guard(mutex)(&priv->lock); + + ret =3D regmap_write(priv->regmap, MCP9982_RUNNING_AVG_ADDR, reg_val); + priv->running_avg =3D val; + + return count; +} + +static IIO_DEVICE_ATTR(running_average_window, 0644, mcp9982_running_avera= ge_window_show, + mcp9982_running_average_window_store, 0); + +static IIO_DEVICE_ATTR(running_average_window_available, 0444, + mcp9982_running_average_window_avail_show, NULL, 1); + +static int mcp9982_prep_custom_attributes(struct mcp9982_priv *priv, struc= t iio_dev *indio_dev) +{ + struct attribute **mcp9982_custom_attr; + struct attribute_group *mcp9982_group; + struct device *dev =3D &priv->client->dev; + + mcp9982_group =3D devm_kzalloc(dev, sizeof(*mcp9982_group), GFP_KERNEL); + if (!mcp9982_group) + return -ENOMEM; + + mcp9982_custom_attr =3D devm_kzalloc(dev, MCP9982_NR_CUSTOM_ATTR * + sizeof(*mcp9982_group) + 1, GFP_KERNEL); + if (!mcp9982_custom_attr) + return -ENOMEM; + + mcp9982_custom_attr[0] =3D MCP9982_DEV_ATTR(running_average_window); + mcp9982_custom_attr[1] =3D MCP9982_DEV_ATTR(running_average_window_availa= ble); + + mcp9982_group->attrs =3D mcp9982_custom_attr; + priv->iio_info.attrs =3D mcp9982_group; + + return 0; +} + +static const struct iio_info mcp9982_info =3D { + .read_raw =3D mcp9982_read_raw, + .read_label =3D mcp9982_read_label, + .read_avail =3D mcp9982_read_avail, + .write_raw_get_fmt =3D mcp9982_write_raw_get_fmt, + .write_raw =3D mcp9982_write_raw, +}; + +static int mcp9982_init(struct mcp9982_priv *priv) +{ + int ret, i; + u8 val; + + val =3D FIELD_PREP(MCP9982_CFG_MSKAL, MCP9982_CFG_MSKAL_DEFAULT) | + FIELD_PREP(MCP9982_CFG_RS, MCP9982_CFG_RS_DEFAULT) | + FIELD_PREP(MCP9982_CFG_ATTHM, MCP9982_CFG_ATTHM_DEFAULT) | + FIELD_PREP(MCP9982_CFG_RECD12, priv->recd12) | + FIELD_PREP(MCP9982_CFG_RECD34, priv->recd34) | + FIELD_PREP(MCP9982_CFG_RANGE, priv->temp_range_code) | + FIELD_PREP(MCP9982_CFG_DA_ENA, MCP9982_CFG_DA_ENA_DEFAULT) | + FIELD_PREP(MCP9982_CFG_APDD, priv->apdd); + ret =3D regmap_write(priv->regmap, MCP9982_CFG_ADDR, val); + if (ret) + return ret; + + ret =3D regmap_write(priv->regmap, MCP9982_CONV_ADDR, MCP9982_SAMPLING_FR= EQ_CODE_DEFAULT); + if (ret) + return ret; + + ret =3D regmap_write(priv->regmap, MCP9982_HYS_ADDR, priv->hysteresis); + if (ret) + return ret; + + ret =3D regmap_write(priv->regmap, MCP9982_CONSEC_ALRT_ADDR, MCP9982_CONS= EC_ALRT_DEFAULT); + if (ret) + return ret; + + /* RUNNING AVG DEFAULT is 0 */ + ret =3D regmap_write(priv->regmap, MCP9982_RUNNING_AVG_ADDR, 0); + if (ret) + return ret; + priv->running_avg =3D 1; + + /* HOTTEST CFG DEFAULT is 0 */ + ret =3D regmap_write(priv->regmap, MCP9982_HOTTEST_CFG_ADDR, 0); + if (ret) + return ret; + + /* Set beta compensation for all channels */ + for (i =3D 0; i < 2; i++) { + ret =3D regmap_write(priv->regmap, MCP9982_EXT_BETA_CFG_ADDR(i), + priv->beta_user_value[i]); + if (ret) + return ret; + } + + /* Set ideality factor for all channels */ + for (i =3D 0; i < 4; i++) { + ret =3D regmap_write(priv->regmap, MCP9982_EXT_IDEAL_ADDR(i), + priv->ideality_user_value[i]); + if (ret) + return ret; + } + + return 0; +} + +static int mcp9982_parse_of_fw(struct iio_dev *indio_dev) +{ + struct mcp9982_priv *priv =3D iio_priv(indio_dev); + struct device *dev =3D &priv->client->dev; + int ret, reg_nr, iio_idx, i; + + if (device_property_present(dev, "microchip,temp-hysteresis")) { + ret =3D device_property_read_u32(dev, "microchip,temp-hysteresis", &priv= ->hysteresis); + if (ret) + return dev_err_probe(dev, ret, "Cannot read hysteresis property\n"); + + if (priv->hysteresis > MCP9982_HYSTERESIS_MAX_VALUE) + return dev_err_probe(dev, ret, + "Hysteresis value is higher than maximum\n"); + } else { + priv->hysteresis =3D MCP9982_HYSTERESIS_DEFAULT; + } + + if (device_property_present(dev, "microchip,extended-temp-range")) + priv->temp_range_code =3D 1; + else + priv->temp_range_code =3D MCP9982_TEMP_RANGE_DEFAULT; + + if (device_property_present(dev, "microchip,beta-channel1")) { + ret =3D device_property_read_u32(dev, "microchip,beta-channel1", + &priv->beta_user_value[0]); + if (ret) + return ret; + + if (priv->beta_user_value[0] > MCP9982_BETA_MAX_VALUE) + return dev_err_probe(dev, -EINVAL, "Beta 1 value is higher than max\n"); + } else { + priv->beta_user_value[0] =3D MCP9982_BETA_AUTODETECT_ENABLE; + } + + if (device_property_present(dev, "microchip,beta-channel2")) { + ret =3D device_property_read_u32(dev, "microchip,beta-channel2", + &priv->beta_user_value[1]); + if (ret) + return ret; + + if (priv->beta_user_value[1] > MCP9982_BETA_MAX_VALUE) + return dev_err_probe(dev, -EINVAL, "Beta 2 value is higher than max\n"); + } else { + priv->beta_user_value[1] =3D MCP9982_BETA_AUTODETECT_ENABLE; + } + + if (device_property_present(dev, "microchip,apdd-state")) + priv->apdd =3D 0; + else + priv->apdd =3D MCP9982_APDD_DEFAULT; + + if (device_property_present(dev, "microchip,recd12")) + priv->recd12 =3D 0; + else + priv->recd12 =3D MCP9982_RECD_DEFAULT; + + if (device_property_present(dev, "microchip,recd34")) + priv->recd34 =3D 0; + else + priv->recd34 =3D MCP9982_RECD_DEFAULT; + + ret =3D device_property_read_string(dev, "compatible", (const char **)&pr= iv->chip_name); + if (ret) + return dev_err_probe(dev, ret, "Cannot read compatible property\n"); + + priv->chip_name =3D &priv->chip_name[10]; + priv->num_channels =3D device_get_child_node_count(dev) + 1; + + for (i =3D 0; i < 10; i++) + if (strcmp(priv->chip_name, mcp9982_chip_config[i].name) =3D=3D 0) + break; + if (priv->num_channels > mcp9982_chip_config[i].phys_channels) + return dev_err_probe(dev, -EINVAL, + "The number of channels does not match the chip\n"); + + priv->iio_chan =3D devm_kzalloc(dev, priv->num_channels * sizeof(*priv->i= io_chan), + GFP_KERNEL); + if (!priv->iio_chan) + return -ENOMEM; + + /* first channel is internal and always present */ + priv->iio_chan[0] =3D MCP9982_CHAN(MCP9982_CHAN_INT, MCP9982_CHAN_INT, + MCP9982_INT_HIGH_BYTE_ADDR(0)); + priv->labels[0] =3D "internal diode"; + iio_idx++; + device_for_each_child_node_scoped(dev, child) { + ret =3D fwnode_property_read_u32(child, "reg", ®_nr); + if (reg_nr >=3D mcp9982_chip_config[i].phys_channels) + return dev_err_probe(dev, -EINVAL, + "The index of the channels does not match the chip\n"); + + if (fwnode_property_present(child, "microchip,ideality-factor")) { + ret =3D fwnode_property_read_u32(child, "microchip,ideality-factor", + &priv->ideality_user_value[reg_nr - 1]); + if (priv->ideality_user_value[reg_nr - 1] > MCP9982_IDEALITY_MAX_VALUE) + return dev_err_probe(dev, -EINVAL, + "The ideality value is higher than maximum\n"); + } else { + priv->ideality_user_value[reg_nr - 1] =3D MCP9982_IDEALITY_FACTOR_DEFAU= LT; + } + + ret =3D fwnode_property_read_string(child, "label", + (const char **)&priv->labels[reg_nr]); + + priv->iio_chan[iio_idx++] =3D MCP9982_CHAN(reg_nr, reg_nr, + MCP9982_INT_HIGH_BYTE_ADDR(reg_nr)); + } + + return 0; +} + +static int mcp9982_probe(struct i2c_client *client) +{ + struct device *dev =3D &client->dev; + struct mcp9982_priv *priv; + struct iio_dev *indio_dev; + int ret; + + indio_dev =3D devm_iio_device_alloc(dev, sizeof(*priv)); + if (!indio_dev) + return -ENOMEM; + + priv =3D iio_priv(indio_dev); + priv->client =3D client; + i2c_set_clientdata(client, indio_dev); + + priv->regmap =3D devm_regmap_init_i2c(client, &mcp9982_regmap_config); + if (IS_ERR(priv->regmap)) + return dev_err_probe(dev, PTR_ERR(priv->regmap), + "Cannot initialize register map\n"); + + ret =3D devm_mutex_init(dev, &priv->lock); + if (ret) + return ret; + + ret =3D mcp9982_parse_of_fw(indio_dev); + if (ret) + return dev_err_probe(dev, ret, "Parameter parsing error\n"); + + ret =3D mcp9982_init(priv); + if (ret) + return dev_err_probe(dev, ret, "Cannot initialize device\n"); + + priv->iio_info =3D mcp9982_info; + + indio_dev->name =3D priv->chip_name; + indio_dev->info =3D &priv->iio_info; + indio_dev->modes =3D INDIO_DIRECT_MODE; + indio_dev->channels =3D priv->iio_chan; + indio_dev->num_channels =3D priv->num_channels; + + ret =3D mcp9982_prep_custom_attributes(priv, indio_dev); + if (ret < 0) + return dev_err_probe(&client->dev, ret, + "Can't configure custom attributes for MCP9982 device\n"); + + ret =3D devm_iio_device_register(dev, indio_dev); + if (ret) + return dev_err_probe(dev, ret, "Cannot register IIO device\n"); + + return 0; +} + +static const struct i2c_device_id mcp9982_id[] =3D { + { .name =3D "mcp9933", .driver_data =3D (kernel_ulong_t)&mcp9982_chip_con= fig[MCP9933] }, + { .name =3D "mcp9933D", .driver_data =3D (kernel_ulong_t)&mcp9982_chip_co= nfig[MCP9933D] }, + { .name =3D "mcp9982", .driver_data =3D (kernel_ulong_t)&mcp9982_chip_con= fig[MCP9982] }, + { .name =3D "mcp9982D", .driver_data =3D (kernel_ulong_t)&mcp9982_chip_co= nfig[MCP9982D] }, + { .name =3D "mcp9983", .driver_data =3D (kernel_ulong_t)&mcp9982_chip_con= fig[MCP9983] }, + { .name =3D "mcp9983D", .driver_data =3D (kernel_ulong_t)&mcp9982_chip_co= nfig[MCP9983D] }, + { .name =3D "mcp9984", .driver_data =3D (kernel_ulong_t)&mcp9982_chip_con= fig[MCP9984] }, + { .name =3D "mcp9984D", .driver_data =3D (kernel_ulong_t)&mcp9982_chip_co= nfig[MCP9984D] }, + { .name =3D "mcp9985", .driver_data =3D (kernel_ulong_t)&mcp9982_chip_con= fig[MCP9985] }, + { .name =3D "mcp9985D", .driver_data =3D (kernel_ulong_t)&mcp9982_chip_co= nfig[MCP9985D] }, + { } +}; +MODULE_DEVICE_TABLE(i2c, mcp9982_id); + +static const struct of_device_id mcp9982_of_match[] =3D { + { + .compatible =3D "microchip,mcp9933", + .data =3D &mcp9982_chip_config[MCP9933] + }, + { + .compatible =3D "microchip,mcp9933D", + .data =3D &mcp9982_chip_config[MCP9933D] + }, + { + .compatible =3D "microchip,mcp9982", + .data =3D &mcp9982_chip_config[MCP9982] + }, + { + .compatible =3D "microchip,mcp9982D", + .data =3D &mcp9982_chip_config[MCP9982D] + }, + { + .compatible =3D "microchip,mcp9983", + .data =3D &mcp9982_chip_config[MCP9983] + }, + { + .compatible =3D "microchip,mcp9983D", + .data =3D &mcp9982_chip_config[MCP9983D] + }, + { + .compatible =3D "microchip,mcp9984", + .data =3D &mcp9982_chip_config[MCP9984] + }, + { + .compatible =3D "microchip,mcp9984D", + .data =3D &mcp9982_chip_config[MCP9984D] + }, + { + .compatible =3D "microchip,mcp9985", + .data =3D &mcp9982_chip_config[MCP9985] + }, + { + .compatible =3D "microchip,mcp9985D", + .data =3D &mcp9982_chip_config[MCP9985D] + }, + { } +}; +MODULE_DEVICE_TABLE(of, mcp9982_of_match); + +static struct i2c_driver mcp9982_driver =3D { + .driver =3D { + .name =3D "mcp9982", + .of_match_table =3D mcp9982_of_match, + }, + .probe =3D mcp9982_probe, + .id_table =3D mcp9982_id, +}; + +module_i2c_driver(mcp9982_driver); + +MODULE_AUTHOR("Victor Duicu "); +MODULE_DESCRIPTION("MCP998X/33 and MCP998XD/33D Multichannel Automotive Te= mperature Monitor Driver"); +MODULE_LICENSE("GPL"); --=20 2.45.2