* [PATCH linux v3 1/3] drivers: w1: add hwmon support structures
2017-07-13 21:06 [PATCH linux v3 0/3] Export 1-wire thermal sensors as hwmon device Jaghathiswari Rankappagounder Natarajan
@ 2017-07-13 21:06 ` Jaghathiswari Rankappagounder Natarajan
2017-07-13 21:45 ` Guenter Roeck
2017-07-13 21:06 ` [PATCH linux v3 2/3] drivers: w1: refactor w1_slave_show to make the temp reading functionality separate Jaghathiswari Rankappagounder Natarajan
2017-07-13 21:06 ` [PATCH linux v3 3/3] drivers: w1: add hwmon temp support for w1_therm Jaghathiswari Rankappagounder Natarajan
2 siblings, 1 reply; 7+ messages in thread
From: Jaghathiswari Rankappagounder Natarajan @ 2017-07-13 21:06 UTC (permalink / raw)
To: zbr, linux-kernel, linux, jdelvare, linux-hwmon
Cc: Jaghathiswari Rankappagounder Natarajan
This patch has changes to w1.h/w1.c/w1_family.h generic files to
add (optional) hwmon support structures.
Signed-off-by: Jaghathiswari Rankappagounder Natarajan <jaghu@google.com>
Acked-by: Evgeniy Polyakov <zbr@ioremap.net>
---
v2
- made changes to support hwmon_device_register_with_info mentioned by Guenter.
v3
- used IS_REACHABLE(CONFIG_HWMON)
- removed hwmon device first before removing slave.
drivers/w1/w1.c | 18 +++++++++++++++++-
drivers/w1/w1.h | 2 ++
drivers/w1/w1_family.h | 2 ++
3 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
index e213c678bbfe..0e5423c1d31c 100644
--- a/drivers/w1/w1.c
+++ b/drivers/w1/w1.c
@@ -32,6 +32,7 @@
#include <linux/sched.h>
#include <linux/kthread.h>
#include <linux/freezer.h>
+#include <linux/hwmon.h>
#include <linux/atomic.h>
@@ -659,9 +660,24 @@ static int w1_family_notify(unsigned long action, struct w1_slave *sl)
return err;
}
}
-
+ if (IS_REACHABLE(CONFIG_HWMON) && fops->chip_info) {
+ struct device *hwmon
+ = hwmon_device_register_with_info(&sl->dev,
+ "w1_slave_temp", sl,
+ fops->chip_info,
+ NULL);
+ if (IS_ERR(hwmon)) {
+ dev_warn(&sl->dev,
+ "could not create hwmon device\n");
+ } else {
+ sl->hwmon = hwmon;
+ }
+ }
break;
case BUS_NOTIFY_DEL_DEVICE:
+ if (IS_REACHABLE(CONFIG_HWMON) && fops->chip_info
+ && sl->hwmon)
+ hwmon_device_unregister(sl->hwmon);
if (fops->remove_slave)
sl->family->fops->remove_slave(sl);
if (fops->groups)
diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h
index 129895f562b0..74ef1a543856 100644
--- a/drivers/w1/w1.h
+++ b/drivers/w1/w1.h
@@ -83,6 +83,7 @@ struct w1_reg_num
* @family: module for device family type
* @family_data: pointer for use by the family module
* @dev: kernel device identifier
+ * @hwmon: pointer to hwmon device
*
*/
struct w1_slave
@@ -99,6 +100,7 @@ struct w1_slave
struct w1_family *family;
void *family_data;
struct device dev;
+ struct device *hwmon;
};
typedef void (*w1_slave_found_callback)(struct w1_master *, u64);
diff --git a/drivers/w1/w1_family.h b/drivers/w1/w1_family.h
index 10a7a0767187..9001851e1316 100644
--- a/drivers/w1/w1_family.h
+++ b/drivers/w1/w1_family.h
@@ -55,12 +55,14 @@ struct w1_slave;
* @add_slave: add_slave
* @remove_slave: remove_slave
* @groups: sysfs group
+ * @chip_info: pointer to struct hwmon_chip_info
*/
struct w1_family_ops
{
int (* add_slave)(struct w1_slave *);
void (* remove_slave)(struct w1_slave *);
const struct attribute_group **groups;
+ const struct hwmon_chip_info *chip_info;
};
/**
--
2.13.2.932.g7449e964c-goog
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH linux v3 1/3] drivers: w1: add hwmon support structures
2017-07-13 21:06 ` [PATCH linux v3 1/3] drivers: w1: add hwmon support structures Jaghathiswari Rankappagounder Natarajan
@ 2017-07-13 21:45 ` Guenter Roeck
0 siblings, 0 replies; 7+ messages in thread
From: Guenter Roeck @ 2017-07-13 21:45 UTC (permalink / raw)
To: Jaghathiswari Rankappagounder Natarajan
Cc: zbr, linux-kernel, jdelvare, linux-hwmon
On Thu, Jul 13, 2017 at 02:06:47PM -0700, Jaghathiswari Rankappagounder Natarajan wrote:
> This patch has changes to w1.h/w1.c/w1_family.h generic files to
> add (optional) hwmon support structures.
>
> Signed-off-by: Jaghathiswari Rankappagounder Natarajan <jaghu@google.com>
> Acked-by: Evgeniy Polyakov <zbr@ioremap.net>
Acked-by: Guenter Roeck <linux@roeck-us.net>
> ---
> v2
> - made changes to support hwmon_device_register_with_info mentioned by Guenter.
>
> v3
> - used IS_REACHABLE(CONFIG_HWMON)
> - removed hwmon device first before removing slave.
>
> drivers/w1/w1.c | 18 +++++++++++++++++-
> drivers/w1/w1.h | 2 ++
> drivers/w1/w1_family.h | 2 ++
> 3 files changed, 21 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
> index e213c678bbfe..0e5423c1d31c 100644
> --- a/drivers/w1/w1.c
> +++ b/drivers/w1/w1.c
> @@ -32,6 +32,7 @@
> #include <linux/sched.h>
> #include <linux/kthread.h>
> #include <linux/freezer.h>
> +#include <linux/hwmon.h>
>
> #include <linux/atomic.h>
>
> @@ -659,9 +660,24 @@ static int w1_family_notify(unsigned long action, struct w1_slave *sl)
> return err;
> }
> }
> -
> + if (IS_REACHABLE(CONFIG_HWMON) && fops->chip_info) {
> + struct device *hwmon
> + = hwmon_device_register_with_info(&sl->dev,
> + "w1_slave_temp", sl,
> + fops->chip_info,
> + NULL);
> + if (IS_ERR(hwmon)) {
> + dev_warn(&sl->dev,
> + "could not create hwmon device\n");
> + } else {
> + sl->hwmon = hwmon;
> + }
> + }
> break;
> case BUS_NOTIFY_DEL_DEVICE:
> + if (IS_REACHABLE(CONFIG_HWMON) && fops->chip_info
> + && sl->hwmon)
Nitpick: checkpatch prefers && to be in the previous line.
> + hwmon_device_unregister(sl->hwmon);
> if (fops->remove_slave)
> sl->family->fops->remove_slave(sl);
> if (fops->groups)
> diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h
> index 129895f562b0..74ef1a543856 100644
> --- a/drivers/w1/w1.h
> +++ b/drivers/w1/w1.h
> @@ -83,6 +83,7 @@ struct w1_reg_num
> * @family: module for device family type
> * @family_data: pointer for use by the family module
> * @dev: kernel device identifier
> + * @hwmon: pointer to hwmon device
> *
> */
> struct w1_slave
> @@ -99,6 +100,7 @@ struct w1_slave
> struct w1_family *family;
> void *family_data;
> struct device dev;
> + struct device *hwmon;
> };
>
> typedef void (*w1_slave_found_callback)(struct w1_master *, u64);
> diff --git a/drivers/w1/w1_family.h b/drivers/w1/w1_family.h
> index 10a7a0767187..9001851e1316 100644
> --- a/drivers/w1/w1_family.h
> +++ b/drivers/w1/w1_family.h
> @@ -55,12 +55,14 @@ struct w1_slave;
> * @add_slave: add_slave
> * @remove_slave: remove_slave
> * @groups: sysfs group
> + * @chip_info: pointer to struct hwmon_chip_info
> */
> struct w1_family_ops
> {
> int (* add_slave)(struct w1_slave *);
> void (* remove_slave)(struct w1_slave *);
> const struct attribute_group **groups;
> + const struct hwmon_chip_info *chip_info;
> };
>
> /**
> --
> 2.13.2.932.g7449e964c-goog
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH linux v3 2/3] drivers: w1: refactor w1_slave_show to make the temp reading functionality separate
2017-07-13 21:06 [PATCH linux v3 0/3] Export 1-wire thermal sensors as hwmon device Jaghathiswari Rankappagounder Natarajan
2017-07-13 21:06 ` [PATCH linux v3 1/3] drivers: w1: add hwmon support structures Jaghathiswari Rankappagounder Natarajan
@ 2017-07-13 21:06 ` Jaghathiswari Rankappagounder Natarajan
2017-07-13 21:48 ` Guenter Roeck
2017-07-13 21:06 ` [PATCH linux v3 3/3] drivers: w1: add hwmon temp support for w1_therm Jaghathiswari Rankappagounder Natarajan
2 siblings, 1 reply; 7+ messages in thread
From: Jaghathiswari Rankappagounder Natarajan @ 2017-07-13 21:06 UTC (permalink / raw)
To: zbr, linux-kernel, linux, jdelvare, linux-hwmon
Cc: Jaghathiswari Rankappagounder Natarajan
Inside the w1_slave_show function refactor the code to read the temp
into a separate function.
Signed-off-by: Jaghathiswari Rankappagounder Natarajan <jaghu@google.com>
Acked-by: Evgeniy Polyakov <zbr@ioremap.net>
---
v2
- no changes
v3
- changed code so that the refcount is incremented with the bus mutex locked.
drivers/w1/slaves/w1_therm.c | 82 +++++++++++++++++++++++++++-----------------
1 file changed, 51 insertions(+), 31 deletions(-)
diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c
index 82611f197b0a..64e6a8f38410 100644
--- a/drivers/w1/slaves/w1_therm.c
+++ b/drivers/w1/slaves/w1_therm.c
@@ -64,6 +64,12 @@ struct w1_therm_family_data {
atomic_t refcnt;
};
+struct therm_info {
+ u8 rom[9];
+ u8 crc;
+ u8 verdict;
+};
+
/* return the address of the refcnt in the family data */
#define THERM_REFCNT(family_data) \
(&((struct w1_therm_family_data *)family_data)->refcnt)
@@ -427,33 +433,31 @@ static ssize_t w1_slave_store(struct device *device,
return ret ? : size;
}
-static ssize_t w1_slave_show(struct device *device,
- struct device_attribute *attr, char *buf)
+static ssize_t read_therm(struct device *device,
+ struct w1_slave *sl, struct therm_info *info)
{
- struct w1_slave *sl = dev_to_w1_slave(device);
struct w1_master *dev = sl->master;
- u8 rom[9], crc, verdict, external_power;
- int i, ret, max_trying = 10;
- ssize_t c = PAGE_SIZE;
+ u8 external_power;
+ int ret, max_trying = 10;
u8 *family_data = sl->family_data;
ret = mutex_lock_interruptible(&dev->bus_mutex);
if (ret != 0)
- goto post_unlock;
+ goto error;
- if (!sl->family_data) {
+ if (!family_data) {
ret = -ENODEV;
- goto pre_unlock;
+ goto mt_unlock;
}
/* prevent the slave from going away in sleep */
atomic_inc(THERM_REFCNT(family_data));
- memset(rom, 0, sizeof(rom));
+ memset(info->rom, 0, sizeof(info->rom));
while (max_trying--) {
- verdict = 0;
- crc = 0;
+ info->verdict = 0;
+ info->crc = 0;
if (!w1_reset_select_slave(sl)) {
int count = 0;
@@ -479,47 +483,69 @@ static ssize_t w1_slave_show(struct device *device,
sleep_rem = msleep_interruptible(tm);
if (sleep_rem != 0) {
ret = -EINTR;
- goto post_unlock;
+ goto dec_refcnt;
}
ret = mutex_lock_interruptible(&dev->bus_mutex);
if (ret != 0)
- goto post_unlock;
+ goto dec_refcnt;
} else if (!w1_strong_pullup) {
sleep_rem = msleep_interruptible(tm);
if (sleep_rem != 0) {
ret = -EINTR;
- goto pre_unlock;
+ goto dec_refcnt;
}
}
if (!w1_reset_select_slave(sl)) {
w1_write_8(dev, W1_READ_SCRATCHPAD);
- count = w1_read_block(dev, rom, 9);
+ count = w1_read_block(dev, info->rom, 9);
if (count != 9) {
dev_warn(device, "w1_read_block() "
"returned %u instead of 9.\n",
count);
}
- crc = w1_calc_crc8(rom, 8);
+ info->crc = w1_calc_crc8(info->rom, 8);
- if (rom[8] == crc)
- verdict = 1;
+ if (info->rom[8] == info->crc)
+ info->verdict = 1;
}
}
- if (verdict)
+ if (info->verdict)
break;
}
+dec_refcnt:
+ atomic_dec(THERM_REFCNT(family_data));
+mt_unlock:
+ mutex_unlock(&dev->bus_mutex);
+error:
+ return ret;
+}
+
+static ssize_t w1_slave_show(struct device *device,
+ struct device_attribute *attr, char *buf)
+{
+ struct w1_slave *sl = dev_to_w1_slave(device);
+ struct therm_info info;
+ u8 *family_data = sl->family_data;
+ int ret, i;
+ ssize_t c = PAGE_SIZE;
+ u8 fid = sl->family->fid;
+
+ ret = read_therm(device, sl, &info);
+ if (ret)
+ return ret;
+
for (i = 0; i < 9; ++i)
- c -= snprintf(buf + PAGE_SIZE - c, c, "%02x ", rom[i]);
+ c -= snprintf(buf + PAGE_SIZE - c, c, "%02x ", info.rom[i]);
c -= snprintf(buf + PAGE_SIZE - c, c, ": crc=%02x %s\n",
- crc, (verdict) ? "YES" : "NO");
- if (verdict)
- memcpy(family_data, rom, sizeof(rom));
+ info.crc, (info.verdict) ? "YES" : "NO");
+ if (info.verdict)
+ memcpy(family_data, info.rom, sizeof(info.rom));
else
dev_warn(device, "Read failed CRC check\n");
@@ -528,14 +554,8 @@ static ssize_t w1_slave_show(struct device *device,
((u8 *)family_data)[i]);
c -= snprintf(buf + PAGE_SIZE - c, c, "t=%d\n",
- w1_convert_temp(rom, sl->family->fid));
+ w1_convert_temp(info.rom, fid));
ret = PAGE_SIZE - c;
-
-pre_unlock:
- mutex_unlock(&dev->bus_mutex);
-
-post_unlock:
- atomic_dec(THERM_REFCNT(family_data));
return ret;
}
--
2.13.2.932.g7449e964c-goog
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH linux v3 2/3] drivers: w1: refactor w1_slave_show to make the temp reading functionality separate
2017-07-13 21:06 ` [PATCH linux v3 2/3] drivers: w1: refactor w1_slave_show to make the temp reading functionality separate Jaghathiswari Rankappagounder Natarajan
@ 2017-07-13 21:48 ` Guenter Roeck
0 siblings, 0 replies; 7+ messages in thread
From: Guenter Roeck @ 2017-07-13 21:48 UTC (permalink / raw)
To: Jaghathiswari Rankappagounder Natarajan
Cc: zbr, linux-kernel, jdelvare, linux-hwmon
On Thu, Jul 13, 2017 at 02:06:48PM -0700, Jaghathiswari Rankappagounder Natarajan wrote:
> Inside the w1_slave_show function refactor the code to read the temp
> into a separate function.
>
> Signed-off-by: Jaghathiswari Rankappagounder Natarajan <jaghu@google.com>
> Acked-by: Evgeniy Polyakov <zbr@ioremap.net>
Acked-by: Guenter Roeck <linux@roeck-us.net>
> ---
> v2
> - no changes
>
> v3
> - changed code so that the refcount is incremented with the bus mutex locked.
>
> drivers/w1/slaves/w1_therm.c | 82 +++++++++++++++++++++++++++-----------------
> 1 file changed, 51 insertions(+), 31 deletions(-)
>
> diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c
> index 82611f197b0a..64e6a8f38410 100644
> --- a/drivers/w1/slaves/w1_therm.c
> +++ b/drivers/w1/slaves/w1_therm.c
> @@ -64,6 +64,12 @@ struct w1_therm_family_data {
> atomic_t refcnt;
> };
>
> +struct therm_info {
> + u8 rom[9];
> + u8 crc;
> + u8 verdict;
> +};
> +
> /* return the address of the refcnt in the family data */
> #define THERM_REFCNT(family_data) \
> (&((struct w1_therm_family_data *)family_data)->refcnt)
> @@ -427,33 +433,31 @@ static ssize_t w1_slave_store(struct device *device,
> return ret ? : size;
> }
>
> -static ssize_t w1_slave_show(struct device *device,
> - struct device_attribute *attr, char *buf)
> +static ssize_t read_therm(struct device *device,
> + struct w1_slave *sl, struct therm_info *info)
> {
> - struct w1_slave *sl = dev_to_w1_slave(device);
> struct w1_master *dev = sl->master;
> - u8 rom[9], crc, verdict, external_power;
> - int i, ret, max_trying = 10;
> - ssize_t c = PAGE_SIZE;
> + u8 external_power;
> + int ret, max_trying = 10;
> u8 *family_data = sl->family_data;
>
> ret = mutex_lock_interruptible(&dev->bus_mutex);
> if (ret != 0)
> - goto post_unlock;
> + goto error;
>
> - if (!sl->family_data) {
> + if (!family_data) {
> ret = -ENODEV;
> - goto pre_unlock;
> + goto mt_unlock;
> }
>
> /* prevent the slave from going away in sleep */
> atomic_inc(THERM_REFCNT(family_data));
> - memset(rom, 0, sizeof(rom));
> + memset(info->rom, 0, sizeof(info->rom));
>
> while (max_trying--) {
>
> - verdict = 0;
> - crc = 0;
> + info->verdict = 0;
> + info->crc = 0;
>
> if (!w1_reset_select_slave(sl)) {
> int count = 0;
> @@ -479,47 +483,69 @@ static ssize_t w1_slave_show(struct device *device,
> sleep_rem = msleep_interruptible(tm);
> if (sleep_rem != 0) {
> ret = -EINTR;
> - goto post_unlock;
> + goto dec_refcnt;
> }
>
> ret = mutex_lock_interruptible(&dev->bus_mutex);
> if (ret != 0)
> - goto post_unlock;
> + goto dec_refcnt;
> } else if (!w1_strong_pullup) {
> sleep_rem = msleep_interruptible(tm);
> if (sleep_rem != 0) {
> ret = -EINTR;
> - goto pre_unlock;
> + goto dec_refcnt;
> }
> }
>
> if (!w1_reset_select_slave(sl)) {
>
> w1_write_8(dev, W1_READ_SCRATCHPAD);
> - count = w1_read_block(dev, rom, 9);
> + count = w1_read_block(dev, info->rom, 9);
> if (count != 9) {
> dev_warn(device, "w1_read_block() "
> "returned %u instead of 9.\n",
> count);
> }
>
> - crc = w1_calc_crc8(rom, 8);
> + info->crc = w1_calc_crc8(info->rom, 8);
>
> - if (rom[8] == crc)
> - verdict = 1;
> + if (info->rom[8] == info->crc)
> + info->verdict = 1;
> }
> }
>
> - if (verdict)
> + if (info->verdict)
> break;
> }
>
> +dec_refcnt:
> + atomic_dec(THERM_REFCNT(family_data));
> +mt_unlock:
> + mutex_unlock(&dev->bus_mutex);
> +error:
> + return ret;
> +}
> +
> +static ssize_t w1_slave_show(struct device *device,
> + struct device_attribute *attr, char *buf)
> +{
> + struct w1_slave *sl = dev_to_w1_slave(device);
> + struct therm_info info;
> + u8 *family_data = sl->family_data;
> + int ret, i;
> + ssize_t c = PAGE_SIZE;
> + u8 fid = sl->family->fid;
> +
> + ret = read_therm(device, sl, &info);
> + if (ret)
> + return ret;
> +
> for (i = 0; i < 9; ++i)
> - c -= snprintf(buf + PAGE_SIZE - c, c, "%02x ", rom[i]);
> + c -= snprintf(buf + PAGE_SIZE - c, c, "%02x ", info.rom[i]);
> c -= snprintf(buf + PAGE_SIZE - c, c, ": crc=%02x %s\n",
> - crc, (verdict) ? "YES" : "NO");
> - if (verdict)
> - memcpy(family_data, rom, sizeof(rom));
> + info.crc, (info.verdict) ? "YES" : "NO");
> + if (info.verdict)
> + memcpy(family_data, info.rom, sizeof(info.rom));
> else
> dev_warn(device, "Read failed CRC check\n");
>
> @@ -528,14 +554,8 @@ static ssize_t w1_slave_show(struct device *device,
> ((u8 *)family_data)[i]);
>
> c -= snprintf(buf + PAGE_SIZE - c, c, "t=%d\n",
> - w1_convert_temp(rom, sl->family->fid));
> + w1_convert_temp(info.rom, fid));
> ret = PAGE_SIZE - c;
> -
> -pre_unlock:
> - mutex_unlock(&dev->bus_mutex);
> -
> -post_unlock:
> - atomic_dec(THERM_REFCNT(family_data));
> return ret;
> }
>
> --
> 2.13.2.932.g7449e964c-goog
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH linux v3 3/3] drivers: w1: add hwmon temp support for w1_therm
2017-07-13 21:06 [PATCH linux v3 0/3] Export 1-wire thermal sensors as hwmon device Jaghathiswari Rankappagounder Natarajan
2017-07-13 21:06 ` [PATCH linux v3 1/3] drivers: w1: add hwmon support structures Jaghathiswari Rankappagounder Natarajan
2017-07-13 21:06 ` [PATCH linux v3 2/3] drivers: w1: refactor w1_slave_show to make the temp reading functionality separate Jaghathiswari Rankappagounder Natarajan
@ 2017-07-13 21:06 ` Jaghathiswari Rankappagounder Natarajan
2017-07-13 21:40 ` Guenter Roeck
2 siblings, 1 reply; 7+ messages in thread
From: Jaghathiswari Rankappagounder Natarajan @ 2017-07-13 21:06 UTC (permalink / raw)
To: zbr, linux-kernel, linux, jdelvare, linux-hwmon
Cc: Jaghathiswari Rankappagounder Natarajan
This change adds hwmon temp support for w1_therm.
Signed-off-by: Jaghathiswari Rankappagounder Natarajan <jaghu@google.com>
Acked-by: Evgeniy Polyakov <zbr@ioremap.net>
---
v2
- make changes to support hwmon_device_register_with_info mentioned by Guenter.
v3
- used IS_REACHABLE()
- rearranged the code to not require forward declarations
- used family_data
- incremented the reference count with the bus mutex locked
- corrected indentation
- removed dev_warn message
- simplified returning mode
- removed write function
drivers/w1/slaves/w1_therm.c | 91 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 91 insertions(+)
diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c
index 64e6a8f38410..b7d13220dd8f 100644
--- a/drivers/w1/slaves/w1_therm.c
+++ b/drivers/w1/slaves/w1_therm.c
@@ -29,6 +29,7 @@
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/delay.h>
+#include <linux/hwmon.h>
#include "../w1.h"
#include "../w1_int.h"
@@ -118,19 +119,77 @@ static struct attribute *w1_ds28ea00_attrs[] = {
&dev_attr_w1_seq.attr,
NULL,
};
+
ATTRIBUTE_GROUPS(w1_therm);
ATTRIBUTE_GROUPS(w1_ds28ea00);
+#if IS_REACHABLE(CONFIG_HWMON)
+static int w1_read_temp(struct device *dev, u32 attr, int channel,
+ long *val);
+
+static umode_t w1_is_visible(const void *_data, enum hwmon_sensor_types type,
+ u32 attr, int channel)
+{
+ return attr == hwmon_temp_input ? 0444 : 0;
+}
+
+static int w1_read(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long *val)
+{
+ switch (type) {
+ case hwmon_temp:
+ return w1_read_temp(dev, attr, channel, val);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static const u32 w1_temp_config[] = {
+ HWMON_T_INPUT,
+ 0
+};
+
+static const struct hwmon_channel_info w1_temp = {
+ .type = hwmon_temp,
+ .config = w1_temp_config,
+};
+
+static const struct hwmon_channel_info *w1_info[] = {
+ &w1_temp,
+ NULL
+};
+
+static const struct hwmon_ops w1_hwmon_ops = {
+ .is_visible = w1_is_visible,
+ .read = w1_read,
+};
+
+static const struct hwmon_chip_info w1_chip_info = {
+ .ops = &w1_hwmon_ops,
+ .info = w1_info,
+};
+#endif
+
static struct w1_family_ops w1_therm_fops = {
.add_slave = w1_therm_add_slave,
.remove_slave = w1_therm_remove_slave,
.groups = w1_therm_groups,
+#if IS_REACHABLE(CONFIG_HWMON)
+ .chip_info = &w1_chip_info,
+#else
+ .chip_info = NULL,
+#endif
};
static struct w1_family_ops w1_ds28ea00_fops = {
.add_slave = w1_therm_add_slave,
.remove_slave = w1_therm_remove_slave,
.groups = w1_ds28ea00_groups,
+#if IS_REACHABLE(CONFIG_HWMON)
+ .chip_info = &w1_chip_info,
+#else
+ .chip_info = NULL,
+#endif
};
static struct w1_family w1_therm_family_DS18S20 = {
@@ -559,6 +618,38 @@ static ssize_t w1_slave_show(struct device *device,
return ret;
}
+#if IS_REACHABLE(CONFIG_HWMON)
+static int w1_read_temp(struct device *device, u32 attr, int channel,
+ long *val)
+{
+ struct w1_slave *sl = dev_get_drvdata(device);
+ struct therm_info info;
+ u8 fid = sl->family->fid;
+ int ret;
+
+ switch (attr) {
+ case hwmon_temp_input:
+ ret = read_therm(device, sl, &info);
+ if (ret)
+ return ret;
+
+ if (!info.verdict) {
+ ret = -EIO;
+ return ret;
+ }
+
+ *val = w1_convert_temp(info.rom, fid);
+ ret = 0;
+ break;
+ default:
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ return ret;
+}
+#endif
+
#define W1_42_CHAIN 0x99
#define W1_42_CHAIN_OFF 0x3C
#define W1_42_CHAIN_OFF_INV 0xC3
--
2.13.2.932.g7449e964c-goog
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH linux v3 3/3] drivers: w1: add hwmon temp support for w1_therm
2017-07-13 21:06 ` [PATCH linux v3 3/3] drivers: w1: add hwmon temp support for w1_therm Jaghathiswari Rankappagounder Natarajan
@ 2017-07-13 21:40 ` Guenter Roeck
0 siblings, 0 replies; 7+ messages in thread
From: Guenter Roeck @ 2017-07-13 21:40 UTC (permalink / raw)
To: Jaghathiswari Rankappagounder Natarajan
Cc: zbr, linux-kernel, jdelvare, linux-hwmon
On Thu, Jul 13, 2017 at 02:06:49PM -0700, Jaghathiswari Rankappagounder Natarajan wrote:
> This change adds hwmon temp support for w1_therm.
>
> Signed-off-by: Jaghathiswari Rankappagounder Natarajan <jaghu@google.com>
> Acked-by: Evgeniy Polyakov <zbr@ioremap.net>
> ---
> v2
> - make changes to support hwmon_device_register_with_info mentioned by Guenter.
>
> v3
> - used IS_REACHABLE()
> - rearranged the code to not require forward declarations
> - used family_data
> - incremented the reference count with the bus mutex locked
> - corrected indentation
> - removed dev_warn message
> - simplified returning mode
> - removed write function
>
> drivers/w1/slaves/w1_therm.c | 91 ++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 91 insertions(+)
>
> diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c
> index 64e6a8f38410..b7d13220dd8f 100644
> --- a/drivers/w1/slaves/w1_therm.c
> +++ b/drivers/w1/slaves/w1_therm.c
> @@ -29,6 +29,7 @@
> #include <linux/types.h>
> #include <linux/slab.h>
> #include <linux/delay.h>
> +#include <linux/hwmon.h>
>
> #include "../w1.h"
> #include "../w1_int.h"
> @@ -118,19 +119,77 @@ static struct attribute *w1_ds28ea00_attrs[] = {
> &dev_attr_w1_seq.attr,
> NULL,
> };
> +
> ATTRIBUTE_GROUPS(w1_therm);
> ATTRIBUTE_GROUPS(w1_ds28ea00);
>
> +#if IS_REACHABLE(CONFIG_HWMON)
> +static int w1_read_temp(struct device *dev, u32 attr, int channel,
> + long *val);
> +
> +static umode_t w1_is_visible(const void *_data, enum hwmon_sensor_types type,
> + u32 attr, int channel)
> +{
> + return attr == hwmon_temp_input ? 0444 : 0;
> +}
> +
> +static int w1_read(struct device *dev, enum hwmon_sensor_types type,
> + u32 attr, int channel, long *val)
> +{
> + switch (type) {
> + case hwmon_temp:
> + return w1_read_temp(dev, attr, channel, val);
> + default:
> + return -EOPNOTSUPP;
> + }
> +}
> +
> +static const u32 w1_temp_config[] = {
> + HWMON_T_INPUT,
> + 0
> +};
> +
> +static const struct hwmon_channel_info w1_temp = {
> + .type = hwmon_temp,
> + .config = w1_temp_config,
> +};
> +
> +static const struct hwmon_channel_info *w1_info[] = {
> + &w1_temp,
> + NULL
> +};
> +
> +static const struct hwmon_ops w1_hwmon_ops = {
> + .is_visible = w1_is_visible,
> + .read = w1_read,
> +};
> +
> +static const struct hwmon_chip_info w1_chip_info = {
> + .ops = &w1_hwmon_ops,
> + .info = w1_info,
> +};
#define W1_CHIPINFO (&w1_chip_info)
#else
#define W1_CHIPINFO NULL
[saves you a couple of ifdefs]
> +#endif
> +
> static struct w1_family_ops w1_therm_fops = {
> .add_slave = w1_therm_add_slave,
> .remove_slave = w1_therm_remove_slave,
> .groups = w1_therm_groups,
> +#if IS_REACHABLE(CONFIG_HWMON)
> + .chip_info = &w1_chip_info,
> +#else
> + .chip_info = NULL,
> +#endif
.chip_info = W1_CHIP_INFO,
> };
>
> static struct w1_family_ops w1_ds28ea00_fops = {
> .add_slave = w1_therm_add_slave,
> .remove_slave = w1_therm_remove_slave,
> .groups = w1_ds28ea00_groups,
> +#if IS_REACHABLE(CONFIG_HWMON)
> + .chip_info = &w1_chip_info,
> +#else
> + .chip_info = NULL,
> +#endif
.chip_info = W1_CHIP_INFO,
> };
>
> static struct w1_family w1_therm_family_DS18S20 = {
> @@ -559,6 +618,38 @@ static ssize_t w1_slave_show(struct device *device,
> return ret;
> }
>
> +#if IS_REACHABLE(CONFIG_HWMON)
> +static int w1_read_temp(struct device *device, u32 attr, int channel,
> + long *val)
> +{
> + struct w1_slave *sl = dev_get_drvdata(device);
> + struct therm_info info;
> + u8 fid = sl->family->fid;
> + int ret;
> +
> + switch (attr) {
> + case hwmon_temp_input:
> + ret = read_therm(device, sl, &info);
> + if (ret)
> + return ret;
> +
> + if (!info.verdict) {
> + ret = -EIO;
> + return ret;
> + }
> +
> + *val = w1_convert_temp(info.rom, fid);
> + ret = 0;
> + break;
> + default:
> + ret = -EOPNOTSUPP;
Formatting ?
> + break;
> + }
> +
> + return ret;
> +}
> +#endif
> +
> #define W1_42_CHAIN 0x99
> #define W1_42_CHAIN_OFF 0x3C
> #define W1_42_CHAIN_OFF_INV 0xC3
> --
> 2.13.2.932.g7449e964c-goog
>
^ permalink raw reply [flat|nested] 7+ messages in thread