diff options
Diffstat (limited to 'target/linux/bcm27xx/patches-5.4/950-0771-w1_therm-optimizing-temperature-read-timings.patch')
-rw-r--r-- | target/linux/bcm27xx/patches-5.4/950-0771-w1_therm-optimizing-temperature-read-timings.patch | 528 |
1 files changed, 0 insertions, 528 deletions
diff --git a/target/linux/bcm27xx/patches-5.4/950-0771-w1_therm-optimizing-temperature-read-timings.patch b/target/linux/bcm27xx/patches-5.4/950-0771-w1_therm-optimizing-temperature-read-timings.patch deleted file mode 100644 index 142560c6da..0000000000 --- a/target/linux/bcm27xx/patches-5.4/950-0771-w1_therm-optimizing-temperature-read-timings.patch +++ /dev/null @@ -1,528 +0,0 @@ -From 23769ad113407ceb21a4285a8194c7d788149269 Mon Sep 17 00:00:00 2001 -From: Akira Shimahara <akira215corp@gmail.com> -Date: Mon, 11 May 2020 22:37:42 +0200 -Subject: [PATCH] w1_therm: optimizing temperature read timings - -commit 67b392f7b8edfa6f427fecd98722acab34c1c99f upstream. - -Optimizing temperature reading by reducing waiting conversion time -according to device resolution settings, as per device specification. -This is device dependent as not all the devices supports resolution -setting, so it has been added in device family structures. - -The process to read the temperature on the device has been adapted in a -new function 'convert_t()', which replace the former 'read_therm()', is -introduce to deal with this timing. Strong pull up is also applied during -the required time, according to device power status needs and -'strong_pullup' module parameter. - -'temperature_from_RAM()' function is introduced to get the correct -temperature computation (device dependent) from device RAM data. - -An new sysfs entry has been added to ouptut only temperature. The old -entry w1_slave has been kept for compatibility, without changing its -output format. - -Updating Documentation/ABI/testing/sysfs-driver-w1_therm accordingly. - -Signed-off-by: Akira Shimahara <akira215corp@gmail.com> -Link: https://lore.kernel.org/r/20200511203742.411039-1-akira215corp@gmail.com -Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> ---- - .../ABI/testing/sysfs-driver-w1_therm | 12 + - drivers/w1/slaves/w1_therm.c | 286 +++++++++++------- - 2 files changed, 197 insertions(+), 101 deletions(-) - ---- a/Documentation/ABI/testing/sysfs-driver-w1_therm -+++ b/Documentation/ABI/testing/sysfs-driver-w1_therm -@@ -41,6 +41,18 @@ Users: any user space application which - w1_term device - - -+What: /sys/bus/w1/devices/.../temperature -+Date: May 2020 -+Contact: Akira Shimahara <akira215corp@gmail.com> -+Description: -+ (RO) return the temperature in 1/1000 degC. -+ Note that the conversion duration depend on the resolution (if -+ device support this feature). It takes 94ms in 9bits -+ resolution, 750ms for 12bits. -+Users: any user space application which wants to communicate with -+ w1_term device -+ -+ - What: /sys/bus/w1/devices/.../w1_slave - Date: May 2020 - Contact: Akira Shimahara <akira215corp@gmail.com> ---- a/drivers/w1/slaves/w1_therm.c -+++ b/drivers/w1/slaves/w1_therm.c -@@ -93,6 +93,7 @@ module_param_named(strong_pullup, w1_str - * @reserved: not used here - * @f: pointer to the device binding structure - * @convert: pointer to the device conversion function -+ * @get_conversion_time: pointer to the device conversion time function - * @set_resolution: pointer to the device set_resolution function - * @get_resolution: pointer to the device get_resolution function - */ -@@ -101,6 +102,7 @@ struct w1_therm_family_converter { - u16 reserved; - struct w1_family *f; - int (*convert)(u8 rom[9]); -+ int (*get_conversion_time)(struct w1_slave *sl); - int (*set_resolution)(struct w1_slave *sl, int val); - int (*get_resolution)(struct w1_slave *sl); - }; -@@ -154,6 +156,15 @@ struct therm_info { - static int reset_select_slave(struct w1_slave *sl); - - /** -+ * convert_t() - Query the device for temperature conversion and read -+ * @sl: pointer to the slave to read -+ * @info: pointer to a structure to store the read results -+ * -+ * Return: 0 if success, -kernel error code otherwise -+ */ -+static int convert_t(struct w1_slave *sl, struct therm_info *info); -+ -+/** - * read_scratchpad() - read the data in device RAM - * @sl: pointer to the slave to read - * @info: pointer to a structure to store the read results -@@ -213,6 +224,9 @@ static ssize_t w1_slave_store(struct dev - static ssize_t w1_seq_show(struct device *device, - struct device_attribute *attr, char *buf); - -+static ssize_t temperature_show(struct device *device, -+ struct device_attribute *attr, char *buf); -+ - static ssize_t ext_power_show(struct device *device, - struct device_attribute *attr, char *buf); - -@@ -229,6 +243,7 @@ static ssize_t eeprom_store(struct devic - - static DEVICE_ATTR_RW(w1_slave); - static DEVICE_ATTR_RO(w1_seq); -+static DEVICE_ATTR_RO(temperature); - static DEVICE_ATTR_RO(ext_power); - static DEVICE_ATTR_RW(resolution); - static DEVICE_ATTR_WO(eeprom); -@@ -259,6 +274,7 @@ static void w1_therm_remove_slave(struct - - static struct attribute *w1_therm_attrs[] = { - &dev_attr_w1_slave.attr, -+ &dev_attr_temperature.attr, - &dev_attr_ext_power.attr, - &dev_attr_resolution.attr, - &dev_attr_eeprom.attr, -@@ -267,6 +283,7 @@ static struct attribute *w1_therm_attrs[ - - static struct attribute *w1_ds18s20_attrs[] = { - &dev_attr_w1_slave.attr, -+ &dev_attr_temperature.attr, - &dev_attr_ext_power.attr, - &dev_attr_eeprom.attr, - NULL, -@@ -275,6 +292,7 @@ static struct attribute *w1_ds18s20_attr - static struct attribute *w1_ds28ea00_attrs[] = { - &dev_attr_w1_slave.attr, - &dev_attr_w1_seq.attr, -+ &dev_attr_temperature.attr, - &dev_attr_ext_power.attr, - &dev_attr_resolution.attr, - &dev_attr_eeprom.attr, -@@ -389,6 +407,37 @@ static struct w1_family w1_therm_family_ - - /* Device dependent func */ - -+static inline int w1_DS18B20_convert_time(struct w1_slave *sl) -+{ -+ int ret; -+ -+ if (!sl->family_data) -+ return -ENODEV; /* device unknown */ -+ -+ /* return time in ms for conversion operation */ -+ switch (SLAVE_RESOLUTION(sl)) { -+ case 9: -+ ret = 95; -+ break; -+ case 10: -+ ret = 190; -+ break; -+ case 11: -+ ret = 375; -+ break; -+ case 12: -+ default: -+ ret = 750; -+ } -+ return ret; -+} -+ -+static inline int w1_DS18S20_convert_time(struct w1_slave *sl) -+{ -+ (void)(sl); -+ return 750; /* always 750ms for DS18S20 */ -+} -+ - static inline int w1_DS18B20_write_data(struct w1_slave *sl, - const u8 *data) - { -@@ -480,8 +529,10 @@ static inline int w1_DS18S20_convert_tem - { - int t, h; - -- if (!rom[7]) -+ if (!rom[7]) { -+ pr_debug("%s: Invalid argument for conversion\n", __func__); - return 0; -+ } - - if (rom[1] == 0) - t = ((s32)rom[0] >> 1)*1000; -@@ -500,34 +551,39 @@ static inline int w1_DS18S20_convert_tem - - static struct w1_therm_family_converter w1_therm_families[] = { - { -- .f = &w1_therm_family_DS18S20, -- .convert = w1_DS18S20_convert_temp, -- .set_resolution = NULL, /* no config register */ -- .get_resolution = NULL, /* no config register */ -+ .f = &w1_therm_family_DS18S20, -+ .convert = w1_DS18S20_convert_temp, -+ .get_conversion_time = w1_DS18S20_convert_time, -+ .set_resolution = NULL, /* no config register */ -+ .get_resolution = NULL, /* no config register */ - }, - { -- .f = &w1_therm_family_DS1822, -- .convert = w1_DS18B20_convert_temp, -- .set_resolution = w1_DS18B20_set_resolution, -- .get_resolution = w1_DS18B20_get_resolution, -+ .f = &w1_therm_family_DS1822, -+ .convert = w1_DS18B20_convert_temp, -+ .get_conversion_time = w1_DS18B20_convert_time, -+ .set_resolution = w1_DS18B20_set_resolution, -+ .get_resolution = w1_DS18B20_get_resolution, - }, - { -- .f = &w1_therm_family_DS18B20, -- .convert = w1_DS18B20_convert_temp, -- .set_resolution = w1_DS18B20_set_resolution, -- .get_resolution = w1_DS18B20_get_resolution, -+ .f = &w1_therm_family_DS18B20, -+ .convert = w1_DS18B20_convert_temp, -+ .get_conversion_time = w1_DS18B20_convert_time, -+ .set_resolution = w1_DS18B20_set_resolution, -+ .get_resolution = w1_DS18B20_get_resolution, - }, - { -- .f = &w1_therm_family_DS28EA00, -- .convert = w1_DS18B20_convert_temp, -- .set_resolution = w1_DS18B20_set_resolution, -- .get_resolution = w1_DS18B20_get_resolution, -+ .f = &w1_therm_family_DS28EA00, -+ .convert = w1_DS18B20_convert_temp, -+ .get_conversion_time = w1_DS18B20_convert_time, -+ .set_resolution = w1_DS18B20_set_resolution, -+ .get_resolution = w1_DS18B20_get_resolution, - }, - { -- .f = &w1_therm_family_DS1825, -- .convert = w1_DS18B20_convert_temp, -- .set_resolution = w1_DS18B20_set_resolution, -- .get_resolution = w1_DS18B20_get_resolution, -+ .f = &w1_therm_family_DS1825, -+ .convert = w1_DS18B20_convert_temp, -+ .get_conversion_time = w1_DS18B20_convert_time, -+ .set_resolution = w1_DS18B20_set_resolution, -+ .get_resolution = w1_DS18B20_get_resolution, - } - }; - -@@ -582,24 +638,44 @@ static inline bool bus_mutex_lock(struct - } - - /** -- * w1_convert_temp() - temperature conversion binding function -- * @rom: data read from device RAM (8 data bytes + 1 CRC byte) -- * @fid: device family id -+ * conversion_time() - get the Tconv for the slave -+ * @sl: device to get the conversion time - * -- * The function call the temperature computation function according to -- * device family. -+ * On device supporting resolution settings, conversion time depend -+ * on the resolution setting. This helper function get the slave timing, -+ * depending on its current setting. - * -- * Return: value in millidegrees Celsius. -+ * Return: conversion time in ms, negative values are kernel error code - */ --static inline int w1_convert_temp(u8 rom[9], u8 fid) -+static inline int conversion_time(struct w1_slave *sl) - { -- int i; -+ if (SLAVE_SPECIFIC_FUNC(sl)) -+ return SLAVE_SPECIFIC_FUNC(sl)->get_conversion_time(sl); - -- for (i = 0; i < ARRAY_SIZE(w1_therm_families); ++i) -- if (w1_therm_families[i].f->fid == fid) -- return w1_therm_families[i].convert(rom); -+ dev_info(&sl->dev, -+ "%s: Device not supported by the driver\n", __func__); - -- return 0; -+ return -ENODEV; /* No device family */ -+} -+ -+/** -+ * temperature_from_RAM() - Convert the read info to temperature -+ * @sl: device that sent the RAM data -+ * @rom: read value on the slave device RAM -+ * -+ * Device dependent, the function bind the correct computation method. -+ * -+ * Return: temperature in 1/1000degC, 0 on error. -+ */ -+static inline int temperature_from_RAM(struct w1_slave *sl, u8 rom[9]) -+{ -+ if (SLAVE_SPECIFIC_FUNC(sl)) -+ return SLAVE_SPECIFIC_FUNC(sl)->convert(rom); -+ -+ dev_info(&sl->dev, -+ "%s: Device not supported by the driver\n", __func__); -+ -+ return 0; /* No device family */ - } - - /* Interface Functions */ -@@ -679,96 +755,74 @@ static int reset_select_slave(struct w1_ - return 0; - } - --static ssize_t read_therm(struct device *device, -- struct w1_slave *sl, struct therm_info *info) -+static int convert_t(struct w1_slave *sl, struct therm_info *info) - { -- struct w1_master *dev = sl->master; -- u8 external_power; -- int ret, max_trying = 10; -- u8 *family_data = sl->family_data; -+ struct w1_master *dev_master = sl->master; -+ int max_trying = W1_THERM_MAX_TRY; -+ int t_conv; -+ int ret = -ENODEV; -+ bool strong_pullup; - -- if (!family_data) { -- ret = -ENODEV; -+ if (!sl->family_data) - goto error; -- } - -- /* prevent the slave from going away in sleep */ -- atomic_inc(THERM_REFCNT(family_data)); -+ strong_pullup = (w1_strong_pullup == 2 || -+ (!SLAVE_POWERMODE(sl) && -+ w1_strong_pullup)); - -- ret = mutex_lock_interruptible(&dev->bus_mutex); -- if (ret != 0) -- goto dec_refcnt; -+ /* get conversion duration device and id dependent */ -+ t_conv = conversion_time(sl); - - memset(info->rom, 0, sizeof(info->rom)); - -- while (max_trying--) { -+ /* prevent the slave from going away in sleep */ -+ atomic_inc(THERM_REFCNT(sl->family_data)); -+ -+ if (!bus_mutex_lock(&dev_master->bus_mutex)) { -+ ret = -EAGAIN; /* Didn't acquire the mutex */ -+ goto dec_refcnt; -+ } -+ -+ while (max_trying-- && ret) { /* ret should be 0 */ - - info->verdict = 0; - info->crc = 0; -- -+ /* safe version to select slave */ - if (!reset_select_slave(sl)) { -- int count = 0; -- unsigned int tm = 750; - unsigned long sleep_rem; - -- w1_write_8(dev, W1_READ_PSUPPLY); -- external_power = w1_read_8(dev); -- -- if (reset_select_slave(sl)) -- continue; -- - /* 750ms strong pullup (or delay) after the convert */ -- if (w1_strong_pullup == 2 || -- (!external_power && w1_strong_pullup)) -- w1_next_pullup(dev, tm); -- -- w1_write_8(dev, W1_CONVERT_TEMP); -+ if (strong_pullup) -+ w1_next_pullup(dev_master, t_conv); - -- if (external_power) { -- mutex_unlock(&dev->bus_mutex); -+ w1_write_8(dev_master, W1_CONVERT_TEMP); - -- sleep_rem = msleep_interruptible(tm); -+ if (strong_pullup) { /*some device need pullup */ -+ sleep_rem = msleep_interruptible(t_conv); - if (sleep_rem != 0) { - ret = -EINTR; -- goto dec_refcnt; -+ goto mt_unlock; - } -+ mutex_unlock(&dev_master->bus_mutex); -+ } else { /*no device need pullup */ -+ mutex_unlock(&dev_master->bus_mutex); - -- ret = mutex_lock_interruptible(&dev->bus_mutex); -- if (ret != 0) -- goto dec_refcnt; -- } else if (!w1_strong_pullup) { -- sleep_rem = msleep_interruptible(tm); -+ sleep_rem = msleep_interruptible(t_conv); - if (sleep_rem != 0) { - ret = -EINTR; -- goto mt_unlock; -+ goto dec_refcnt; - } - } -- -- if (!reset_select_slave(sl)) { -- -- w1_write_8(dev, W1_READ_SCRATCHPAD); -- count = w1_read_block(dev, info->rom, 9); -- if (count != 9) { -- dev_warn(device, "w1_read_block() " -- "returned %u instead of 9.\n", -- count); -- } -- -- info->crc = w1_calc_crc8(info->rom, 8); -- -- if (info->rom[8] == info->crc) -- info->verdict = 1; -- } -+ ret = read_scratchpad(sl, info); -+ goto dec_refcnt; - } - -- if (info->verdict) -- break; - } - - mt_unlock: -- mutex_unlock(&dev->bus_mutex); -+ mutex_unlock(&dev_master->bus_mutex); - dec_refcnt: -- atomic_dec(THERM_REFCNT(family_data)); -+ atomic_dec(THERM_REFCNT(sl->family_data)); - error: - return ret; - } -@@ -1000,27 +1054,33 @@ static ssize_t w1_slave_show(struct devi - 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; -+ ret = convert_t(sl, &info); -+ -+ if (ret < 0) { -+ dev_dbg(device, -+ "%s: Temperature data may be corrupted. err=%d\n", -+ __func__, ret); -+ return 0; -+ } - - for (i = 0; i < 9; ++i) - c -= snprintf(buf + PAGE_SIZE - c, c, "%02x ", info.rom[i]); - c -= snprintf(buf + PAGE_SIZE - c, c, ": crc=%02x %s\n", - 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"); -+ dev_warn(device, "%s:Read failed CRC check\n", __func__); - - for (i = 0; i < 9; ++i) - c -= snprintf(buf + PAGE_SIZE - c, c, "%02x ", - ((u8 *)family_data)[i]); - - c -= snprintf(buf + PAGE_SIZE - c, c, "t=%d\n", -- w1_convert_temp(info.rom, fid)); -+ temperature_from_RAM(sl, info.rom)); -+ - ret = PAGE_SIZE - c; - return ret; - } -@@ -1063,6 +1123,31 @@ static ssize_t w1_slave_store(struct dev - return size; /* always return size to avoid infinite calling */ - } - -+static ssize_t temperature_show(struct device *device, -+ struct device_attribute *attr, char *buf) -+{ -+ struct w1_slave *sl = dev_to_w1_slave(device); -+ struct therm_info info; -+ int ret = 0; -+ -+ if ((!sl->family_data) || (!SLAVE_SPECIFIC_FUNC(sl))) { -+ dev_info(device, -+ "%s: Device not supported by the driver\n", __func__); -+ return 0; /* No device family */ -+ } -+ -+ ret = convert_t(sl, &info); -+ -+ if (ret < 0) { -+ dev_dbg(device, -+ "%s: Temperature data may be corrupted. err=%d\n", -+ __func__, ret); -+ return 0; -+ } -+ -+ return sprintf(buf, "%d\n", temperature_from_RAM(sl, info.rom)); -+} -+ - static ssize_t ext_power_show(struct device *device, - struct device_attribute *attr, char *buf) - { -@@ -1172,12 +1257,11 @@ static int w1_read_temp(struct device *d - { - 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); -+ ret = convert_t(sl, &info); - if (ret) - return ret; - -@@ -1186,7 +1270,7 @@ static int w1_read_temp(struct device *d - return ret; - } - -- *val = w1_convert_temp(info.rom, fid); -+ *val = temperature_from_RAM(sl, info.rom); - ret = 0; - break; - default: |