From patchwork Thu Jun 29 12:13:54 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Looijmans X-Patchwork-Id: 9816605 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id B6DD0603D7 for ; Thu, 29 Jun 2017 12:14:17 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A963928703 for ; Thu, 29 Jun 2017 12:14:17 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9BE5028706; Thu, 29 Jun 2017 12:14:17 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2C1BB28703 for ; Thu, 29 Jun 2017 12:14:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752829AbdF2MON (ORCPT ); Thu, 29 Jun 2017 08:14:13 -0400 Received: from atl4mhob14.registeredsite.com ([209.17.115.52]:36812 "EHLO atl4mhob14.registeredsite.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752803AbdF2MOJ (ORCPT ); Thu, 29 Jun 2017 08:14:09 -0400 Received: from mailpod.hostingplatform.com ([10.30.71.204]) by atl4mhob14.registeredsite.com (8.14.4/8.14.4) with ESMTP id v5TCDxC6017169 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL) for ; Thu, 29 Jun 2017 08:13:59 -0400 Received: (qmail 27472 invoked by uid 0); 29 Jun 2017 12:13:59 -0000 X-TCPREMOTEIP: 37.74.225.130 X-Authenticated-UID: mike@milosoftware.com Received: from unknown (HELO mikebuntu.TOPIC.LOCAL) (mike@milosoftware.com@37.74.225.130) by 0 with ESMTPA; 29 Jun 2017 12:13:59 -0000 From: Mike Looijmans To: linux-hwmon@vger.kernel.org Cc: linux-kernel@vger.kernel.org, linux@roeck-us.net, jdelvare@suse.com, Mike Looijmans Subject: [PATCH v2] hwmon: Add LTC2471/LTC2473 driver Date: Thu, 29 Jun 2017 14:13:54 +0200 Message-Id: <1498738434-18252-1-git-send-email-mike.looijmans@topic.nl> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1498733135-4729-1-git-send-email-mike.looijmans@topic.nl> References: <1498733135-4729-1-git-send-email-mike.looijmans@topic.nl> Sender: linux-hwmon-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-hwmon@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The LTC2741 and LTC2473 are single voltage monitoring chips. The LTC2473 is similar to the LTC2471 but outputs a signed differential value. Datasheet: http://cds.linear.com/docs/en/datasheet/24713fb.pdf Signed-off-by: Mike Looijmans --- v2: Use sizeof(*data) instead of struct name Use octal permissions drivers/hwmon/Kconfig | 10 ++++ drivers/hwmon/Makefile | 1 + drivers/hwmon/ltc2471.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 138 insertions(+) create mode 100644 drivers/hwmon/ltc2471.c diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 5ef2814..5acaa2d 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -696,6 +696,16 @@ config SENSORS_LINEAGE This driver can also be built as a module. If so, the module will be called lineage-pem. +config SENSORS_LTC2471 + tristate "Linear Technology LTC2471 and LTC2473" + depends on I2C + help + If you say yes here you get support for Linear Technology LTC2471 + and LTC2473 voltage monitors. + + This driver can also be built as a module. If so, the module will + be called ltc2471. + config SENSORS_LTC2945 tristate "Linear Technology LTC2945" depends on I2C diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index d4641a9..49badff 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -102,6 +102,7 @@ obj-$(CONFIG_SENSORS_LM93) += lm93.o obj-$(CONFIG_SENSORS_LM95234) += lm95234.o obj-$(CONFIG_SENSORS_LM95241) += lm95241.o obj-$(CONFIG_SENSORS_LM95245) += lm95245.o +obj-$(CONFIG_SENSORS_LTC2471) += ltc2471.o obj-$(CONFIG_SENSORS_LTC2945) += ltc2945.o obj-$(CONFIG_SENSORS_LTC2990) += ltc2990.o obj-$(CONFIG_SENSORS_LTC4151) += ltc4151.o diff --git a/drivers/hwmon/ltc2471.c b/drivers/hwmon/ltc2471.c new file mode 100644 index 0000000..f77f7b5 --- /dev/null +++ b/drivers/hwmon/ltc2471.c @@ -0,0 +1,127 @@ +/* + * Driver for Linear Technology LTC2471 and LTC2473 voltage monitors + * The LTC2473 is identical to the 2471, but reports a differential signal. + * + * Copyright (C) 2017 Topic Embedded Products + * Author: Mike Looijmans + * + * License: GPLv2 + */ + +#include +#include +#include +#include +#include +#include + +enum chips { + ltc2471, + ltc2473 +}; + +struct ltc2471_data { + struct i2c_client *i2c; + bool differential; +}; + +/* Reference voltage is 1.25V */ +#define LTC2471_VREF 1250 + +/* Read two bytes from the I2C bus to obtain the ADC result */ +static int ltc2471_get_value(struct i2c_client *i2c) +{ + int ret; + __be16 buf; + + ret = i2c_master_recv(i2c, (char *)&buf, 2); + if (ret < 0) + return ret; + if (ret != 2) + return -EIO; + + /* MSB first */ + return be16_to_cpu(buf); +} + +static ssize_t ltc2471_show_value(struct device *dev, + struct device_attribute *da, char *buf) +{ + struct ltc2471_data *data = dev_get_drvdata(dev); + int value; + + value = ltc2471_get_value(data->i2c); + if (unlikely(value < 0)) + return value; + + if (data->differential) + /* Ranges from -VREF to +VREF with "0" at 0x8000 */ + value = ((s32)LTC2471_VREF * (s32)(value - 0x8000)) >> 15; + else + /* Ranges from 0 to +VREF */ + value = ((u32)LTC2471_VREF * (u32)value) >> 16; + + return snprintf(buf, PAGE_SIZE, "%d\n", value); +} + +static SENSOR_DEVICE_ATTR(in0_input, 0444, ltc2471_show_value, NULL, 0); + +static struct attribute *ltc2471_attrs[] = { + &sensor_dev_attr_in0_input.dev_attr.attr, + NULL +}; + +ATTRIBUTE_GROUPS(ltc2471); + +static int ltc2471_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + int ret; + struct device *hwmon_dev; + struct ltc2471_data *data; + + if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C)) + return -ENODEV; + + data = devm_kzalloc(&i2c->dev, sizeof(*data), GFP_KERNEL); + if (unlikely(!data)) + return -ENOMEM; + + data->i2c = i2c; + data->differential = (id->driver_data == ltc2473); + + /* Trigger once to start conversion and check if chip is there */ + ret = ltc2471_get_value(i2c); + if (ret < 0) { + dev_err(&i2c->dev, "Cannot read from device.\n"); + return ret; + } + + hwmon_dev = devm_hwmon_device_register_with_groups(&i2c->dev, + i2c->name, + data, + ltc2471_groups); + + return PTR_ERR_OR_ZERO(hwmon_dev); +} + +static const struct i2c_device_id ltc2471_i2c_id[] = { + { "ltc2471", ltc2471 }, + { "ltc2473", ltc2473 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, ltc2471_i2c_id); + +static struct i2c_driver ltc2471_i2c_driver = { + .driver = { + .name = "ltc2471", + }, + .probe = ltc2471_i2c_probe, + .id_table = ltc2471_i2c_id, +}; + +module_i2c_driver(ltc2471_i2c_driver); + +MODULE_DESCRIPTION("LTC2471/LTC2473 Sensor Driver"); +MODULE_AUTHOR("Topic Embedded Products"); +MODULE_LICENSE("GPL v2");