Received: by 10.223.164.221 with SMTP id h29csp3042172wrb; Fri, 3 Nov 2017 00:13:19 -0700 (PDT) X-Google-Smtp-Source: ABhQp+Slzd7bCMKCcJI4WomYz7n5Q8NCx5EfzgDkG8GwXjIXNvVQBncVFxO1IH0FUEul6vHRqY5L X-Received: by 10.84.242.12 with SMTP id ba12mr5620669plb.28.1509693199621; Fri, 03 Nov 2017 00:13:19 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1509693199; cv=none; d=google.com; s=arc-20160816; b=iis7hOA5hb0wpPorAXzfe6HFEHv6k4AQlbcRlx7GplzjEgGaw9XQnoIOzxCtK/AZzz UqiGGSE8sktaQnG9iG/1CtDCEP3J1sL0OnfEYRNsMwsg7kG1ADG1ff5k6uvfaJQBaKnf /KzUfWJlSNxIz+E8p9ZAaOR0ZBCVPSiUgedcvzOz+7dduTFQUH/0U9VVHnYk4v9FKLbW 4dgq/FYQ8qrejIZHaP5rVGZAfTAHAZCSXtUp1ounA+dQgEPVuPQfEtDYUBrdb8doS7gA 8Z6fDXZkE03MS+aiLcoNJQaKLsL4yYdCHL2gIy48Fi0UFF9qxFHG9rDJANAoh5uTM02Z exyw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:cc:to:subject:message-id:date:from :references:in-reply-to:mime-version:dkim-signature :arc-authentication-results; bh=n6sebEbgxTT+79yooT0odzC47vAyBG55OHKBBSYWHhI=; b=IypluBZke1UN+cQ+VWD/aspXIoUFL/C49oGcIZJqUtBHbRQQCp1xRzJnluIe6RBe6t yNTlAcC+ET4Ny56xBtnINtjMMQlBOSPmmGqCErTSkZexkN/IMWzZqpF3i8aD5/XAa9OK qbyc+glNYt1SbE9DkkPhhIEs3Ldv+ai2eBOswPOcwM9xcxKIiii8ZQrE7EszuX2FHmkh 3Q6+mzogetVpB/wSol9crmIUVk4KOZAMZNpf+2YKoQw5Oep2mAVHjcWUeEfKiWs2jGTx 2+VeP5WsjGoR8/vbF7wGdQH4N7F7ADr7vQnk0wMgkP6sj+gD0IlgTz6a41/0nI8b44Ix Xsew== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=eUMiiqKM; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id w27si5840467pfl.9.2017.11.03.00.13.06; Fri, 03 Nov 2017 00:13:19 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=eUMiiqKM; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754722AbdKCHMR (ORCPT + 96 others); Fri, 3 Nov 2017 03:12:17 -0400 Received: from mail-io0-f193.google.com ([209.85.223.193]:43042 "EHLO mail-io0-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754474AbdKCHMP (ORCPT ); Fri, 3 Nov 2017 03:12:15 -0400 Received: by mail-io0-f193.google.com with SMTP id 134so4286010ioo.0; Fri, 03 Nov 2017 00:12:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=n6sebEbgxTT+79yooT0odzC47vAyBG55OHKBBSYWHhI=; b=eUMiiqKMT8GBTEa9CXBAb4zVadnbn5xh93adupIkkXmtCKomzlPIdy7dO2TpF/uRrv v3O3SF34+qi6knVg3ocQhv+otZe+R4sZhtSevebtFbgR1yGJslMOyZLyybjWxBuI2Z2L GY2R4PqwK3Zrk4T4D8WtHMGNOnFxFnbS9WMbpOD6jzzrFDh4UBbtUugtD01XHcaTPvUU UtcOvNIUaxuD5xgqMKuyokJbsbvx0aTijIbKlzDlJWaBnWgkyj9MEyOXdczBPKwXkhGv rm7oGMrcL7ZBw8dQHP9UGq5xElY7pEbPEB2NUoszY0YAF9WKZ8UJDZc5uDcZycdWQdEZ lLow== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=n6sebEbgxTT+79yooT0odzC47vAyBG55OHKBBSYWHhI=; b=igPLI1XK8vo0SfkTUDrXEW+mZI20sf35DIZz7UrEzjMkwhdE9gnYt07awCn1tXLdFm sCVhDjpWJUGQC5PRxblTafSI1O7dVpqAyMXht6v98f7Y9Y7lKTFOnesS2WPyw6VOFOgL FKGnTRws1oA2P/rIB0TinlWU8zJ01cmekCkWj+DULhrF2OYfsvxECwptHWhyFENsZyjb QEeajM7geK5f1a5yKcaDFh9F7oz1WkqdT7KVbIJ4HTokho7VKaiH+w4BdzSbVyp+uW9l w4Yr9mUfv6viOu8kzkaaHFFHfcy2cycoUt8aKW6fsfYJjNIij3ZqgI8nJTOnYjmccBjm wXUw== X-Gm-Message-State: AMCzsaUHk+9qMsXl5TMvIH36BvFDdppkQhU3Ahk7Y5rrxVITHI4qRq+0 Ejt4KHeLTHZ7yZVZYJ4Pf4w/4MgilDF7pshwtQxUAckh5gs= X-Received: by 10.36.125.76 with SMTP id b73mr6161052itc.10.1509693134290; Fri, 03 Nov 2017 00:12:14 -0700 (PDT) MIME-Version: 1.0 Received: by 10.79.196.9 with HTTP; Fri, 3 Nov 2017 00:12:13 -0700 (PDT) In-Reply-To: <29316836-0b3e-c22b-7c28-949708638674@roeck-us.net> References: <1509604438-19959-1-git-send-email-mine260309@gmail.com> <1509604438-19959-2-git-send-email-mine260309@gmail.com> <29316836-0b3e-c22b-7c28-949708638674@roeck-us.net> From: Lei YU Date: Fri, 3 Nov 2017 15:12:13 +0800 Message-ID: Subject: Re: [PATCH 1/2] drivers: hwmon: Add W83773G driver To: Guenter Roeck Cc: Jean Delvare , linux-kernel@vger.kernel.org, linux-hwmon@vger.kernel.org, Joel Stanley , Andrew Jeffery Content-Type: text/plain; charset="UTF-8" Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Thu, Nov 2, 2017 at 10:04 PM, Guenter Roeck wrote: > On 11/01/2017 11:33 PM, Lei YU wrote: >> >> Nuvoton W83773G is a hardware monitor IC providing one local >> temperature and two remote temperature sensors. >> > This chip is pretty close to LM90. Have you explored adding support for it > to the LM90 driver ? Thanks for the info. After checking the driver of lm90, I find several differences: 1. Most of devices in lm90.c have one local and one remote sensor; Only MAX6695/MAX6696 support two remote sensors; 2. Most of the devices in lm90.c support ALERT, Hight/Low limit. Especially for 1. MAX6695/6696 needs to write config register to switch between the two remote sensors by lm90_select_remote_channel(); While W83773G has two set of registers for the two remote sensors; The code to support two remote sensors would be different. So I would prefer to have a separated driver code for this. What do you think? Thanks! > > >> Signed-off-by: Lei YU >> --- >> drivers/hwmon/Kconfig | 11 ++ >> drivers/hwmon/Makefile | 1 + >> drivers/hwmon/w83773g.c | 276 >> ++++++++++++++++++++++++++++++++++++++++++++++++ >> 3 files changed, 288 insertions(+) >> create mode 100644 drivers/hwmon/w83773g.c >> >> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig >> index d654314..d148b70 100644 >> --- a/drivers/hwmon/Kconfig >> +++ b/drivers/hwmon/Kconfig >> @@ -1710,6 +1710,17 @@ config SENSORS_VT8231 >> This driver can also be built as a module. If so, the module >> will be called vt8231. >> +config SENSORS_W83773G >> + tristate "Nuvoton W83773G" >> + depends on I2C >> + select HWMON_VID >> + help >> + If you say yes here you get support for the Nuvoton W83773G >> hardware >> + monitoring chip. >> + >> + This driver can also be built as a module. If so, the module >> + will be called w83773g. >> + >> config SENSORS_W83781D >> tristate "Winbond W83781D, W83782D, W83783S, Asus AS99127F" >> depends on I2C >> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile >> index c84d978..0649ad8 100644 >> --- a/drivers/hwmon/Makefile >> +++ b/drivers/hwmon/Makefile >> @@ -13,6 +13,7 @@ obj-$(CONFIG_SENSORS_ATK0110) += asus_atk0110.o >> # asb100, then w83781d go first, as they can override other drivers' >> addresses. >> obj-$(CONFIG_SENSORS_ASB100) += asb100.o >> obj-$(CONFIG_SENSORS_W83627HF) += w83627hf.o >> +obj-$(CONFIG_SENSORS_W83773G) += w83773g.o >> obj-$(CONFIG_SENSORS_W83792D) += w83792d.o >> obj-$(CONFIG_SENSORS_W83793) += w83793.o >> obj-$(CONFIG_SENSORS_W83795) += w83795.o >> diff --git a/drivers/hwmon/w83773g.c b/drivers/hwmon/w83773g.c >> new file mode 100644 >> index 0000000..16d5fa0 >> --- /dev/null >> +++ b/drivers/hwmon/w83773g.c >> @@ -0,0 +1,276 @@ >> +/* >> + * Copyright (C) 2017 IBM Corp. >> + * >> + * This program is free software; you can redistribute it and/or modify >> + * it under the terms of the GNU General Public License as published by >> + * the Free Software Foundation; either version 2 of the License, or >> + * (at your option) any later version. >> + * >> + */ >> + >> +/* >> + * Driver for the Nuvoton W83773G SMBus temperature sensor IC. >> + * Supported models: W83773G >> + */ >> + >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +/* Addresses to scan */ >> +static const unsigned short normal_i2c[] = { 0x4c, 0x4d, I2C_CLIENT_END >> }; >> + >> +enum chips { w83773g }; >> + >> +/* The W83773 registers */ >> +#define W83773_CONVERSION_RATE_REG_READ 0x04 >> +#define W83773_CONVERSION_RATE_REG_WRITE 0x0A >> +#define W83773_MANUFACTURER_ID_REG 0xFE >> +#define W83773_LOCAL_TEMP 0x00 >> + >> +static const u8 W83773_STATUS[2] = { 0x02, 0x17 }; >> + >> +static const u8 W83773_TEMP_LSB[2] = { 0x10, 0x25 }; >> +static const u8 W83773_TEMP_MSB[2] = { 0x01, 0x24 }; >> + >> +static const u8 W83773_OFFSET_LSB[2] = { 0x12, 0x16 }; >> +static const u8 W83773_OFFSET_MSB[2] = { 0x11, 0x15 }; >> + >> +/* Manufacturer / Device ID's */ >> +#define W83773_MANUFACTURER_ID 0x5c >> + >> + >> +/* this is the number of sensors in the device */ >> +static const struct i2c_device_id w83773_id[] = { >> + { "w83773g", 3 }, >> + { } >> +}; >> + >> +MODULE_DEVICE_TABLE(i2c, w83773_id); >> + >> +static const struct of_device_id w83773_of_match[] = { >> + { >> + .compatible = "nuvoton,w83773g", >> + .data = (void *)3 >> + }, >> + >> + { }, >> +}; >> +MODULE_DEVICE_TABLE(of, w83773_of_match); >> + >> +/* >> + * W83773G has 3 temp sensors: >> + * Channel 0 is the local sensor >> + * Channel 1-2 are two remote sensors >> + */ >> +struct w83773_data { >> + struct i2c_client *client; >> + struct mutex update_lock; >> + u32 temp_config[4]; >> + struct hwmon_channel_info temp_info; >> + const struct hwmon_channel_info *info[2]; >> + struct hwmon_chip_info chip; >> + bool valid; >> + unsigned long last_updated; >> + int channels; >> + s8 temp_local; >> + s8 status[2]; >> + s8 temp_hb[2]; >> + s8 temp_lb[2]; >> + s8 offset_hb[2]; >> + s8 offset_lb[2]; >> +}; >> + >> +static long temp_of_local(s8 reg) >> +{ >> + return reg * 1000; >> +} >> + >> +static long temp_of_remote(s8 hb, s8 lb, s8 offset_hb, s8 offset_lb) >> +{ >> + return (hb + offset_hb) * 1000 + ((u8)(lb + offset_lb) >> 5) * >> 125; >> +} >> + >> + >> +static struct w83773_data *w83773_update_device(struct device *dev) >> +{ >> + struct w83773_data *data = dev_get_drvdata(dev); >> + struct i2c_client *client = data->client; >> + int i; >> + >> + mutex_lock(&data->update_lock); >> + >> + if (time_after(jiffies, data->last_updated + 2 * HZ) || >> !data->valid) { >> + data->temp_local = i2c_smbus_read_byte_data(client, >> W83773_LOCAL_TEMP); >> + for (i = 0; i < data->channels - 1; i++) { >> + data->status[i] = i2c_smbus_read_byte_data(client, >> W83773_STATUS[i]); >> + data->temp_hb[i] = >> i2c_smbus_read_byte_data(client, W83773_TEMP_MSB[i]); >> + data->temp_lb[i] = >> i2c_smbus_read_byte_data(client, W83773_TEMP_LSB[i]); >> + data->offset_hb[i] = >> i2c_smbus_read_byte_data(client, W83773_OFFSET_MSB[i]); >> + data->offset_lb[i] = >> i2c_smbus_read_byte_data(client, W83773_OFFSET_LSB[i]); >> + } >> + data->last_updated = jiffies; >> + data->valid = true; >> + } >> + >> + mutex_unlock(&data->update_lock); >> + >> + return data; >> +} >> + >> +static int w83773_read(struct device *dev, enum hwmon_sensor_types type, >> + u32 attr, int channel, long *val) >> +{ >> + struct w83773_data *w83773 = w83773_update_device(dev); >> + >> + switch (attr) { >> + case hwmon_temp_input: >> + if (channel == 0) { >> + /* channel 0 is the local temp */ >> + *val = temp_of_local(w83773->temp_local); >> + } >> + else { >> + /* channel 1-2 are the remote temps */ >> + channel--; >> + *val = temp_of_remote( >> + w83773->temp_hb[channel], >> + w83773->temp_lb[channel], >> + w83773->offset_hb[channel], >> + w83773->offset_lb[channel]); >> + } >> + return 0; >> + case hwmon_temp_fault: >> + if (channel == 0) >> + *val = 0; >> + else >> + /* Check the status register bit 2 for faults */ >> + *val = (w83773->status[channel - 1] & 0x04) >> 2; >> + return 0; >> + default: >> + return -EOPNOTSUPP; >> + } >> + >> +} >> + >> +static umode_t w83773_is_visible(const void *data, enum >> hwmon_sensor_types type, >> + u32 attr, int channel) >> +{ >> + switch (attr) { >> + case hwmon_temp_fault: >> + if (channel == 0) >> + return 0; >> + return S_IRUGO; >> + case hwmon_temp_input: >> + return S_IRUGO; >> + default: >> + return 0; >> + } >> +} >> + >> +static int w83773_init_client(struct i2c_client *client) >> +{ >> + /* Set the conversion rate to 2 Hz */ >> + i2c_smbus_write_byte_data(client, >> W83773_CONVERSION_RATE_REG_WRITE, 0x05); >> + >> + return 0; >> +} >> + >> +static int w83773_detect(struct i2c_client *client, >> + struct i2c_board_info *info) >> +{ >> + enum chips kind; >> + struct i2c_adapter *adapter = client->adapter; >> + const char * const names[] = { "W83773G" }; >> + u8 reg; >> + >> + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) >> + return -ENODEV; >> + >> + reg = i2c_smbus_read_byte_data(client, >> W83773_MANUFACTURER_ID_REG); >> + if (reg != W83773_MANUFACTURER_ID) >> + return -ENODEV; >> + >> + reg = i2c_smbus_read_byte_data(client, >> W83773_CONVERSION_RATE_REG_READ); >> + if (reg & 0xf8) >> + return -ENODEV; >> + >> + kind = w83773g; >> + >> + strlcpy(info->type, w83773_id[kind].name, I2C_NAME_SIZE); >> + dev_info(&adapter->dev, "Detected Nuvoton %s chip at 0x%02x\n", >> + names[kind], client->addr); >> + >> + return 0; >> +} >> + >> +static const struct hwmon_ops w83773_ops = { >> + .is_visible = w83773_is_visible, >> + .read = w83773_read, >> +}; >> + >> +static int w83773_probe(struct i2c_client *client, >> + const struct i2c_device_id *id) >> +{ >> + struct device *dev = &client->dev; >> + struct device *hwmon_dev; >> + struct w83773_data *data; >> + int i, err; >> + >> + data = devm_kzalloc(dev, sizeof(struct w83773_data), GFP_KERNEL); >> + if (!data) >> + return -ENOMEM; >> + >> + mutex_init(&data->update_lock); >> + if (client->dev.of_node) >> + data->channels = >> (int)of_device_get_match_data(&client->dev); >> + else >> + data->channels = id->driver_data; >> + data->client = client; >> + >> + err = w83773_init_client(client); >> + if (err) >> + return err; >> + >> + for (i = 0; i < data->channels; i++) >> + data->temp_config[i] = HWMON_T_INPUT | HWMON_T_FAULT; >> + >> + data->chip.ops = &w83773_ops; >> + data->chip.info = data->info; >> + >> + data->info[0] = &data->temp_info; >> + >> + data->temp_info.type = hwmon_temp; >> + data->temp_info.config = data->temp_config; >> + >> + hwmon_dev = devm_hwmon_device_register_with_info(dev, >> client->name, >> + data, >> + &data->chip, >> + NULL); >> + return PTR_ERR_OR_ZERO(hwmon_dev); >> +} >> + >> +static struct i2c_driver w83773_driver = { >> + .class = I2C_CLASS_HWMON, >> + .driver = { >> + .name = "w83773g", >> + .of_match_table = of_match_ptr(w83773_of_match), >> + }, >> + .probe = w83773_probe, >> + .id_table = w83773_id, >> + .detect = w83773_detect, >> + .address_list = normal_i2c, >> +}; >> + >> +module_i2c_driver(w83773_driver); >> + >> +MODULE_AUTHOR("Nickolaus Gruendler "); >> +MODULE_DESCRIPTION("W83773G temperature sensor driver"); >> +MODULE_LICENSE("GPL"); >> > From 1582963379079935530@xxx Thu Nov 02 14:05:18 +0000 2017 X-GM-THRID: 1582935156102145204 X-Gmail-Labels: Inbox,Category Forums,HistoricalUnread