From patchwork Thu Mar 10 17:34:46 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Michael_B=C3=BCsch?= X-Patchwork-Id: 595886 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from mail-lb0-x23a.google.com (mail-lb0-x23a.google.com [IPv6:2a00:1450:4010:c04::23a]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 30C83140779 for ; Fri, 11 Mar 2016 04:37:36 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=googlegroups.com header.i=@googlegroups.com header.b=AzpE56fW; dkim-atps=neutral Received: by mail-lb0-x23a.google.com with SMTP id wn5sf26098631lbb.0 for ; Thu, 10 Mar 2016 09:37:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlegroups.com; s=20120806; h=sender:date:from:to:cc:subject:message-id:in-reply-to:references :mime-version:x-original-sender:x-original-authentication-results :reply-to:precedence:mailing-list:list-id:x-spam-checked-in-group :list-post:list-help:list-archive:list-subscribe:list-unsubscribe; bh=FVoyxvaPWGBrSJ7rL8lpCnvD/UndmSWdxHoXuZ1mRSs=; b=AzpE56fWYPYhG67JeVDrWcJPKC0WJRX2lPQHk+5bMqFBpumC+1DsnczRzJl1rkBAJ7 kndLXNzpbEcOLQonJhCWMXPoYlgOcNW7w6X8pifobSCuHjCUuAVKz1eYnKdt4QE/IZLE AnjkZ+I6mvokRaCrJpwOWEqIsWQUukz7EQrVCeK5Fu5Ke4U8any8fMMMFONA7836ZeDs J6txJcHN+v/jNNbjE0qcDbcCf9DTGi/Butf6L5SssARA56/ESX83wsu7T8/jdYHSfRbI KSCssduFL+6ukAVsW5VHUNkoyR4nLQyoyM9e03r/gM7TW+SPlz1vH/KEq1o8tbSFTQDb xI1g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=sender:x-gm-message-state:date:from:to:cc:subject:message-id :in-reply-to:references:mime-version:x-original-sender :x-original-authentication-results:reply-to:precedence:mailing-list :list-id:x-spam-checked-in-group:list-post:list-help:list-archive :list-subscribe:list-unsubscribe; bh=FVoyxvaPWGBrSJ7rL8lpCnvD/UndmSWdxHoXuZ1mRSs=; b=Tfb+ezapS9Jn9HIMEAWshQ165UI7/c6Ny4k19j8LGgl6OUT48WuzJiVtAsAhK5+8/g KZ2EvPvltLbIdpINLEMEF7hIorsXdIxPKrimwCGWBuXYCZ1rdCI+ngGgspMTvpI1sb5M mAm8E0o8KB3P5jyZpsHlcs+oD/bJTOioP1YSfjWYUV2csqx4PjoJgq3GsVBnP6nPkBJy YlV8ORWkbCeJ4e49ZC6v5+ASSChtf9sqVJQCpjE6aTdODHWyJuCi6sTj+zFRYfvcMQV9 NchmhM1bVRMEWo6fS/Pql65W8MtzCBgvfb2yHPFVmkiReOWE45KLtvhmFsa5pUEZG/rC 5kfQ== Sender: rtc-linux@googlegroups.com X-Gm-Message-State: AD7BkJITkXLOO8lZaqTG0hTpzphuIkBuC9BBlCIwsUzisXjDVC8mQmZfWZowYoU82RjBgw== X-Received: by 10.28.217.67 with SMTP id q64mr19021wmg.17.1457631452710; Thu, 10 Mar 2016 09:37:32 -0800 (PST) X-BeenThere: rtc-linux@googlegroups.com Received: by 10.28.184.71 with SMTP id i68ls212955wmf.0.canary; Thu, 10 Mar 2016 09:37:32 -0800 (PST) X-Received: by 10.28.85.137 with SMTP id j131mr686896wmb.1.1457631452305; Thu, 10 Mar 2016 09:37:32 -0800 (PST) Received: from bues.ch (bues.ch. [2a01:138:9005::1:4]) by gmr-mx.google.com with ESMTPS id c140si195232wmh.1.2016.03.10.09.37.32 for (version=TLS1_2 cipher=AES128-SHA bits=128/128); Thu, 10 Mar 2016 09:37:32 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of m@bues.ch designates 2a01:138:9005::1:4 as permitted sender) client-ip=2a01:138:9005::1:4; Received: by bues.ch with esmtpsa (Exim 4.80) (envelope-from ) id 1ae4Wh-0004EL-Pw; Thu, 10 Mar 2016 18:37:31 +0100 Date: Thu, 10 Mar 2016 18:34:46 +0100 From: Michael =?UTF-8?B?QsO8c2No?= To: Alexandre Belloni Cc: Gregory Hermant , rtc-linux@googlegroups.com Subject: [rtc-linux] [PATCH 2/2] rtc: rv3029: Add thermometer hwmon support Message-ID: <20160310183446.073c4b0e@wiggum> In-Reply-To: <20160310183346.73aa0f24@wiggum> References: <20160310183346.73aa0f24@wiggum> X-Mailer: Claws Mail 3.13.2 (GTK+ 2.24.30; x86_64-pc-linux-gnu) MIME-Version: 1.0 X-Original-Sender: m@bues.ch X-Original-Authentication-Results: gmr-mx.google.com; spf=pass (google.com: best guess record for domain of m@bues.ch designates 2a01:138:9005::1:4 as permitted sender) smtp.mailfrom=m@bues.ch Reply-To: rtc-linux@googlegroups.com Precedence: list Mailing-list: list rtc-linux@googlegroups.com; contact rtc-linux+owners@googlegroups.com List-ID: X-Spam-Checked-In-Group: rtc-linux@googlegroups.com X-Google-Group-Id: 712029733259 List-Post: , List-Help: , List-Archive: , List-Unsubscribe: , This adds support to - enable/disable the thermometer - set the temperature scanning interval - read the current temperature that is used for temp compensation. via hwmon interface Signed-off-by: Michael Buesch --- drivers/rtc/Kconfig | 9 ++++ drivers/rtc/rtc-rv3029c2.c | 120 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 129 insertions(+) diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index e593c55..b4fda4c 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -601,6 +601,15 @@ config RTC_DRV_RV3029C2 This driver can also be built as a module. If so, the module will be called rtc-rv3029c2. +config RTC_DRV_RV3029_HWMON + bool "HWMON support for RV3029" + depends on RTC_DRV_RV3029C2 && HWMON + depends on !(RTC_DRV_RV3029C2=y && HWMON=m) + default y + help + Say Y here if you want to expose temperature sensor data on + rtc-rv3029c2. + config RTC_DRV_RV8803 tristate "Micro Crystal RV8803" help diff --git a/drivers/rtc/rtc-rv3029c2.c b/drivers/rtc/rtc-rv3029c2.c index 3bbb581..d0cbf08 100644 --- a/drivers/rtc/rtc-rv3029c2.c +++ b/drivers/rtc/rtc-rv3029c2.c @@ -18,6 +18,8 @@ #include #include #include +#include +#include /* Register map */ @@ -637,6 +639,123 @@ static void rv3029_trickle_config(struct i2c_client *client) } } +#ifdef CONFIG_RTC_DRV_RV3029_HWMON + +static int rv3029_read_temp(struct i2c_client *client, int *temp_mC) +{ + int ret; + u8 temp; + + ret = rv3029_i2c_read_regs(client, RV3029_TEMP_PAGE, &temp, 1); + if (ret < 0) + return ret; + + *temp_mC = ((int)temp - 60) * 1000; + + return 0; +} + +static ssize_t rv3029_hwmon_show_temp(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct i2c_client *client = dev_get_drvdata(dev); + int ret, temp_mC; + + ret = rv3029_read_temp(client, &temp_mC); + if (ret < 0) + return ret; + + return sprintf(buf, "%d\n", temp_mC); +} + +static ssize_t rv3029_hwmon_set_update_interval(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct i2c_client *client = dev_get_drvdata(dev); + unsigned long interval_ms; + int ret; + u8 th_set_bits = 0; + + ret = kstrtoul(buf, 10, &interval_ms); + if (ret < 0) + return ret; + + if (interval_ms != 0) { + th_set_bits |= RV3029_EECTRL_THE; + if (interval_ms >= 16000) + th_set_bits |= RV3029_EECTRL_THP; + } + ret = rv3029_eeprom_update_bits(client, RV3029_CONTROL_E2P_EECTRL, + RV3029_EECTRL_THE | RV3029_EECTRL_THP, + th_set_bits); + if (ret < 0) + return ret; + + return count; +} + +static ssize_t rv3029_hwmon_show_update_interval(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct i2c_client *client = dev_get_drvdata(dev); + int ret, interval_ms; + u8 eectrl; + + ret = rv3029_eeprom_read(client, RV3029_CONTROL_E2P_EECTRL, + &eectrl, 1); + if (ret < 0) + return ret; + + if (eectrl & RV3029_EECTRL_THE) { + if (eectrl & RV3029_EECTRL_THP) + interval_ms = 16000; + else + interval_ms = 1000; + } else { + interval_ms = 0; + } + + return sprintf(buf, "%d\n", interval_ms); +} + +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, rv3029_hwmon_show_temp, + NULL, 0); +static SENSOR_DEVICE_ATTR(update_interval, S_IWUSR | S_IRUGO, + rv3029_hwmon_show_update_interval, + rv3029_hwmon_set_update_interval, 0); + +static struct attribute *rv3029_hwmon_attrs[] = { + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_update_interval.dev_attr.attr, + NULL, +}; +ATTRIBUTE_GROUPS(rv3029_hwmon); + +static void rv3029_hwmon_register(struct i2c_client *client) +{ + struct device *hwmon_dev; + + hwmon_dev = devm_hwmon_device_register_with_groups( + &client->dev, client->name, client, rv3029_hwmon_groups); + if (IS_ERR(hwmon_dev)) { + dev_warn(&client->dev, + "unable to register hwmon device %ld\n", + PTR_ERR(hwmon_dev)); + } +} + +#else /* CONFIG_RTC_DRV_RV3029_HWMON */ + +static void rv3029_hwmon_register(struct i2c_client *client) +{ +} + +#endif /* CONFIG_RTC_DRV_RV3029_HWMON */ + static const struct rtc_class_ops rv3029_rtc_ops = { .read_time = rv3029_rtc_read_time, .set_time = rv3029_rtc_set_time, @@ -668,6 +787,7 @@ static int rv3029_probe(struct i2c_client *client, } rv3029_trickle_config(client); + rv3029_hwmon_register(client); rtc = devm_rtc_device_register(&client->dev, client->name, &rv3029_rtc_ops, THIS_MODULE);