aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/bcm27xx/patches-5.4/950-0773-w1_therm-adding-bulk-read-support-to-trigger-multipl.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/bcm27xx/patches-5.4/950-0773-w1_therm-adding-bulk-read-support-to-trigger-multipl.patch')
-rw-r--r--target/linux/bcm27xx/patches-5.4/950-0773-w1_therm-adding-bulk-read-support-to-trigger-multipl.patch587
1 files changed, 0 insertions, 587 deletions
diff --git a/target/linux/bcm27xx/patches-5.4/950-0773-w1_therm-adding-bulk-read-support-to-trigger-multipl.patch b/target/linux/bcm27xx/patches-5.4/950-0773-w1_therm-adding-bulk-read-support-to-trigger-multipl.patch
deleted file mode 100644
index ad641e1e98..0000000000
--- a/target/linux/bcm27xx/patches-5.4/950-0773-w1_therm-adding-bulk-read-support-to-trigger-multipl.patch
+++ /dev/null
@@ -1,587 +0,0 @@
-From e6585a1d299375740f95f30027b8b3f4b34e7548 Mon Sep 17 00:00:00 2001
-From: Akira Shimahara <akira215corp@gmail.com>
-Date: Mon, 11 May 2020 22:38:20 +0200
-Subject: [PATCH] w1_therm: adding bulk read support to trigger
- multiple conversion on bus
-
-commit 57c76221d5af648c8355a55c09b050c5d8d38189 upstream.
-
-Adding bulk read support:
-Sending a 'trigger' command in the dedicated sysfs entry of bus master
-device send a conversion command for all the slaves on the bus. The sysfs
-entry is added as soon as at least one device supporting this feature
-is detected on the bus.
-
-The behavior of the sysfs reading temperature on the device is as follow:
- * If no bulk read pending, trigger a conversion on the device, wait for
- the conversion to be done, read the temperature in device RAM
- * If a bulk read has been trigger, access directly the device RAM
-This behavior is the same on the 2 sysfs entries ('temperature' and
-'w1_slave').
-
-Reading the therm_bulk_read sysfs give the status of bulk operations:
- * '-1': conversion in progress on at least 1 sensor
- * '1': conversion complete but at least one sensor has not been read yet
- * '0': no bulk operation. Reading temperature on ecah device will trigger
-a conversion
-
-As not all devices support bulk read feature, it has been added in device
-family structure.
-
-The attribute is set at master level as soon as a supporting device is
-discover. It is removed when the last supported device leave the bus.
-The count of supported device is kept with the static counter
-bulk_read_device_counter.
-
-A strong pull up is apply on the line if at least one device required it.
-The duration of the pull up is the max time required by a device on the
-line, which depends on the resolution settings of each device. The strong
-pull up could be adjust with the a module parameter.
-
-Updating documentation in Documentation/ABI/testing/sysfs-driver-w1_therm
-and Documentation/w1/slaves/w1_therm.rst accordingly.
-
-Signed-off-by: Akira Shimahara <akira215corp@gmail.com>
-Link: https://lore.kernel.org/r/20200511203820.411483-1-akira215corp@gmail.com
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../ABI/testing/sysfs-driver-w1_therm | 36 ++-
- Documentation/w1/slaves/w1_therm.rst | 50 +++-
- drivers/w1/slaves/w1_therm.c | 251 +++++++++++++++++-
- 3 files changed, 322 insertions(+), 15 deletions(-)
-
---- a/Documentation/ABI/testing/sysfs-driver-w1_therm
-+++ b/Documentation/ABI/testing/sysfs-driver-w1_therm
-@@ -62,9 +62,16 @@ 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.
-+ * If a bulk read has been triggered, it will directly
-+ return the temperature computed when the bulk read
-+ occurred, if available. If not yet available, nothing
-+ is returned (a debug kernel message is sent), you
-+ should retry later on.
-+ * If no bulk read has been triggered, it will trigger
-+ a conversion and send the result. 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
-
-@@ -85,4 +92,25 @@ Description:
- refer to Documentation/w1/slaves/w1_therm.rst for detailed
- information.
- Users: any user space application which wants to communicate with
-- w1_term device
-\ No newline at end of file
-+ w1_term device
-+
-+
-+What: /sys/bus/w1/devices/w1_bus_masterXX/therm_bulk_read
-+Date: May 2020
-+Contact: Akira Shimahara <akira215corp@gmail.com>
-+Description:
-+ (RW) trigger a bulk read conversion. read the status
-+ *read*:
-+ * '-1': conversion in progress on at least 1 sensor
-+ * '1' : conversion complete but at least one sensor
-+ value has not been read yet
-+ * '0' : no bulk operation. Reading temperature will
-+ trigger a conversion on each device
-+ *write*: 'trigger': trigger a bulk read on all supporting
-+ devices on the bus
-+ Note that if a bulk read is sent but one sensor is not read
-+ immediately, the next access to temperature on this device
-+ will return the temperature measured at the time of issue
-+ of the bulk read command (not the current temperature).
-+Users: any user space application which wants to communicate with
-+ w1_term device
---- a/Documentation/w1/slaves/w1_therm.rst
-+++ b/Documentation/w1/slaves/w1_therm.rst
-@@ -26,20 +26,31 @@ W1_THERM_DS1825 0x3B
- W1_THERM_DS28EA00 0x42
- ==================== ====
-
--Support is provided through the sysfs w1_slave file. Each open and
-+Support is provided through the sysfs w1_slave file. Each open and
- read sequence will initiate a temperature conversion then provide two
--lines of ASCII output. The first line contains the nine hex bytes
-+lines of ASCII output. The first line contains the nine hex bytes
- read along with a calculated crc value and YES or NO if it matched.
--If the crc matched the returned values are retained. The second line
-+If the crc matched the returned values are retained. The second line
- displays the retained values along with a temperature in millidegrees
- Centigrade after t=.
-
--Parasite powered devices are limited to one slave performing a
--temperature conversion at a time. If none of the devices are parasite
--powered it would be possible to convert all the devices at the same
--time and then go back to read individual sensors. That isn't
--currently supported. The driver also doesn't support reduced
--precision (which would also reduce the conversion time) when reading values.
-+Alternatively, temperature can be read using temperature sysfs, it
-+return only temperature in millidegrees Centigrade.
-+
-+A bulk read of all devices on the bus could be done writing 'trigger'
-+in the therm_bulk_read sysfs entry at w1_bus_master level. This will
-+sent the convert command on all devices on the bus, and if parasite
-+powered devices are detected on the bus (and strong pullup is enable
-+in the module), it will drive the line high during the longer conversion
-+time required by parasited powered device on the line. Reading
-+therm_bulk_read will return 0 if no bulk conversion pending,
-+-1 if at least one sensor still in conversion, 1 if conversion is complete
-+but at least one sensor value has not been read yet. Result temperature is
-+then accessed by reading the temperature sysfs entry of each device, which
-+may return empty if conversion is still in progress. Note that if a bulk
-+read is sent but one sensor is not read immediately, the next access to
-+temperature on this device will return the temperature measured at the
-+time of issue of the bulk read command (not the current temperature).
-
- Writing a value between 9 and 12 to the sysfs w1_slave file will change the
- precision of the sensor for the next readings. This value is in (volatile)
-@@ -49,6 +60,27 @@ To store the current precision configura
- has to be written to the sysfs w1_slave file. Since the EEPROM has a limited
- amount of writes (>50k), this command should be used wisely.
-
-+Alternatively, resolution can be set or read (value from 9 to 12) using the
-+dedicated resolution sysfs entry on each device. This sysfs entry is not
-+present for devices not supporting this feature. Driver will adjust the
-+correct conversion time for each device regarding to its resolution setting.
-+In particular, strong pullup will be applied if required during the conversion
-+duration.
-+
-+The write-only sysfs entry eeprom is an alternative for EEPROM operations:
-+ * 'save': will save device RAM to EEPROM
-+ * 'restore': will restore EEPROM data in device RAM.
-+
-+ext_power syfs entry allow tho check the power status of each device.
-+ * '0': device parasite powered
-+ * '1': device externally powered
-+
-+sysfs alarms allow read or write TH and TL (Temperature High an Low) alarms.
-+Values shall be space separated and in the device range (typical -55 degC
-+to 125 degC). Values are integer as they are store in a 8bit register in
-+the device. Lowest value is automatically put to TL.Once set, alarms could
-+be search at master level.
-+
- The module parameter strong_pullup can be set to 0 to disable the
- strong pullup, 1 to enable autodetection or 2 to force strong pullup.
- In case of autodetection, the driver will use the "READ POWER SUPPLY"
---- a/drivers/w1/slaves/w1_therm.c
-+++ b/drivers/w1/slaves/w1_therm.c
-@@ -43,6 +43,9 @@
- static int w1_strong_pullup = 1;
- module_param_named(strong_pullup, w1_strong_pullup, int, 0);
-
-+/* Counter for devices supporting bulk reading */
-+static u16 bulk_read_device_counter; /* =0 as per C standard */
-+
- /* This command should be in public header w1.h but is not */
- #define W1_RECALL_EEPROM 0xB8
-
-@@ -57,6 +60,7 @@ module_param_named(strong_pullup, w1_str
-
- #define EEPROM_CMD_WRITE "save" /* cmd for write eeprom sysfs */
- #define EEPROM_CMD_READ "restore" /* cmd for read eeprom sysfs */
-+#define BULK_TRIGGER_CMD "trigger" /* cmd to trigger a bulk read */
-
- #define MIN_TEMP -55 /* min temperature that can be mesured */
- #define MAX_TEMP 125 /* max temperature that can be mesured */
-@@ -84,6 +88,15 @@ module_param_named(strong_pullup, w1_str
- #define SLAVE_RESOLUTION(sl) \
- (((struct w1_therm_family_data *)(sl->family_data))->resolution)
-
-+/*
-+ * return whether or not a converT command has been issued to the slave
-+ * * 0: no bulk read is pending
-+ * * -1: conversion is in progress
-+ * * 1: conversion done, result to be read
-+ */
-+#define SLAVE_CONVERT_TRIGGERED(sl) \
-+ (((struct w1_therm_family_data *)(sl->family_data))->convert_triggered)
-+
- /* return the address of the refcnt in the family data */
- #define THERM_REFCNT(family_data) \
- (&((struct w1_therm_family_data *)family_data)->refcnt)
-@@ -100,6 +113,7 @@ module_param_named(strong_pullup, w1_str
- * @set_resolution: pointer to the device set_resolution function
- * @get_resolution: pointer to the device get_resolution function
- * @write_data: pointer to the device writing function (2 or 3 bytes)
-+ * @bulk_read: true if device family support bulk read, false otherwise
- */
- struct w1_therm_family_converter {
- u8 broken;
-@@ -110,6 +124,7 @@ struct w1_therm_family_converter {
- int (*set_resolution)(struct w1_slave *sl, int val);
- int (*get_resolution)(struct w1_slave *sl);
- int (*write_data)(struct w1_slave *sl, const u8 *data);
-+ bool bulk_read;
- };
-
- /**
-@@ -120,6 +135,7 @@ struct w1_therm_family_converter {
- * 0 device parasite powered,
- * -x error or undefined
- * @resolution: current device resolution
-+ * @convert_triggered: conversion state of the device
- * @specific_functions: pointer to struct of device specific function
- */
- struct w1_therm_family_data {
-@@ -127,6 +143,7 @@ struct w1_therm_family_data {
- atomic_t refcnt;
- int external_powered;
- int resolution;
-+ int convert_triggered;
- struct w1_therm_family_converter *specific_functions;
- };
-
-@@ -218,6 +235,18 @@ static int recall_eeprom(struct w1_slave
- */
- static int read_powermode(struct w1_slave *sl);
-
-+/**
-+ * trigger_bulk_read() - function to trigger a bulk read on the bus
-+ * @dev_master: the device master of the bus
-+ *
-+ * Send a SKIP ROM follow by a CONVERT T commmand on the bus.
-+ * It also set the status flag in each slave &struct w1_therm_family_data
-+ * to signal that a conversion is in progress.
-+ *
-+ * Return: 0 if success, -kernel error code otherwise
-+ */
-+static int trigger_bulk_read(struct w1_master *dev_master);
-+
- /* Sysfs interface declaration */
-
- static ssize_t w1_slave_show(struct device *device,
-@@ -250,6 +279,12 @@ static ssize_t alarms_store(struct devic
- static ssize_t alarms_show(struct device *device,
- struct device_attribute *attr, char *buf);
-
-+static ssize_t therm_bulk_read_store(struct device *device,
-+ struct device_attribute *attr, const char *buf, size_t size);
-+
-+static ssize_t therm_bulk_read_show(struct device *device,
-+ struct device_attribute *attr, char *buf);
-+
- /* Attributes declarations */
-
- static DEVICE_ATTR_RW(w1_slave);
-@@ -260,6 +295,8 @@ static DEVICE_ATTR_RW(resolution);
- static DEVICE_ATTR_WO(eeprom);
- static DEVICE_ATTR_RW(alarms);
-
-+static DEVICE_ATTR_RW(therm_bulk_read); /* attribut at master level */
-+
- /* Interface Functions declaration */
-
- /**
-@@ -572,6 +609,7 @@ static struct w1_therm_family_converter
- .set_resolution = NULL, /* no config register */
- .get_resolution = NULL, /* no config register */
- .write_data = w1_DS18S20_write_data,
-+ .bulk_read = true
- },
- {
- .f = &w1_therm_family_DS1822,
-@@ -580,6 +618,7 @@ static struct w1_therm_family_converter
- .set_resolution = w1_DS18B20_set_resolution,
- .get_resolution = w1_DS18B20_get_resolution,
- .write_data = w1_DS18B20_write_data,
-+ .bulk_read = true
- },
- {
- .f = &w1_therm_family_DS18B20,
-@@ -588,6 +627,7 @@ static struct w1_therm_family_converter
- .set_resolution = w1_DS18B20_set_resolution,
- .get_resolution = w1_DS18B20_get_resolution,
- .write_data = w1_DS18B20_write_data,
-+ .bulk_read = true
- },
- {
- .f = &w1_therm_family_DS28EA00,
-@@ -596,6 +636,7 @@ static struct w1_therm_family_converter
- .set_resolution = w1_DS18B20_set_resolution,
- .get_resolution = w1_DS18B20_get_resolution,
- .write_data = w1_DS18B20_write_data,
-+ .bulk_read = false
- },
- {
- .f = &w1_therm_family_DS1825,
-@@ -604,6 +645,7 @@ static struct w1_therm_family_converter
- .set_resolution = w1_DS18B20_set_resolution,
- .get_resolution = w1_DS18B20_get_resolution,
- .write_data = w1_DS18B20_write_data,
-+ .bulk_read = true
- }
- };
-
-@@ -658,6 +700,23 @@ static inline bool bus_mutex_lock(struct
- }
-
- /**
-+ * support_bulk_read() - check if slave support bulk read
-+ * @sl: device to check the ability
-+ *
-+ * Return: true if bulk read is supported, false if not or error
-+ */
-+static inline bool bulk_read_support(struct w1_slave *sl)
-+{
-+ if (SLAVE_SPECIFIC_FUNC(sl))
-+ return SLAVE_SPECIFIC_FUNC(sl)->bulk_read;
-+
-+ dev_info(&sl->dev,
-+ "%s: Device not supported by the driver\n", __func__);
-+
-+ return false; /* No device family */
-+}
-+
-+/**
- * conversion_time() - get the Tconv for the slave
- * @sl: device to get the conversion time
- *
-@@ -741,6 +800,24 @@ static int w1_therm_add_slave(struct w1_
- /* save this pointer to the device structure */
- SLAVE_SPECIFIC_FUNC(sl) = sl_family_conv;
-
-+ if (bulk_read_support(sl)) {
-+ /*
-+ * add the sys entry to trigger bulk_read
-+ * at master level only the 1st time
-+ */
-+ if (!bulk_read_device_counter) {
-+ int err = device_create_file(&sl->master->dev,
-+ &dev_attr_therm_bulk_read);
-+
-+ if (err)
-+ dev_warn(&sl->dev,
-+ "%s: Device has been added, but bulk read is unavailable. err=%d\n",
-+ __func__, err);
-+ }
-+ /* Increment the counter */
-+ bulk_read_device_counter++;
-+ }
-+
- /* Getting the power mode of the device {external, parasite} */
- SLAVE_POWERMODE(sl) = read_powermode(sl);
-
-@@ -763,6 +840,9 @@ static int w1_therm_add_slave(struct w1_
- }
- }
-
-+ /* Finally initialize convert_triggered flag */
-+ SLAVE_CONVERT_TRIGGERED(sl) = 0;
-+
- return 0;
- }
-
-@@ -770,6 +850,14 @@ static void w1_therm_remove_slave(struct
- {
- int refcnt = atomic_sub_return(1, THERM_REFCNT(sl->family_data));
-
-+ if (bulk_read_support(sl)) {
-+ bulk_read_device_counter--;
-+ /* Delete the entry if no more device support the feature */
-+ if (!bulk_read_device_counter)
-+ device_remove_file(&sl->master->dev,
-+ &dev_attr_therm_bulk_read);
-+ }
-+
- while (refcnt) {
- msleep(1000);
- refcnt = atomic_read(THERM_REFCNT(sl->family_data));
-@@ -1084,6 +1172,96 @@ error:
- return ret;
- }
-
-+static int trigger_bulk_read(struct w1_master *dev_master)
-+{
-+ struct w1_slave *sl = NULL; /* used to iterate through slaves */
-+ int max_trying = W1_THERM_MAX_TRY;
-+ int t_conv = 0;
-+ int ret = -ENODEV;
-+ bool strong_pullup = false;
-+
-+ /*
-+ * Check whether there are parasite powered device on the bus,
-+ * and compute duration of conversion for these devices
-+ * so we can apply a strong pullup if required
-+ */
-+ list_for_each_entry(sl, &dev_master->slist, w1_slave_entry) {
-+ if (!sl->family_data)
-+ goto error;
-+ if (bulk_read_support(sl)) {
-+ int t_cur = conversion_time(sl);
-+
-+ t_conv = t_cur > t_conv ? t_cur : t_conv;
-+ strong_pullup = strong_pullup ||
-+ (w1_strong_pullup == 2 ||
-+ (!SLAVE_POWERMODE(sl) &&
-+ w1_strong_pullup));
-+ }
-+ }
-+
-+ /*
-+ * t_conv is the max conversion time required on the bus
-+ * If its 0, no device support the bulk read feature
-+ */
-+ if (!t_conv)
-+ goto error;
-+
-+ if (!bus_mutex_lock(&dev_master->bus_mutex)) {
-+ ret = -EAGAIN; /* Didn't acquire the mutex */
-+ goto error;
-+ }
-+
-+ while ((max_trying--) && (ret < 0)) { /* ret should be either 0 */
-+
-+ if (!w1_reset_bus(dev_master)) { /* Just reset the bus */
-+ unsigned long sleep_rem;
-+
-+ w1_write_8(dev_master, W1_SKIP_ROM);
-+
-+ if (strong_pullup) /* Apply pullup if required */
-+ w1_next_pullup(dev_master, t_conv);
-+
-+ w1_write_8(dev_master, W1_CONVERT_TEMP);
-+
-+ /* set a flag to instruct that converT pending */
-+ list_for_each_entry(sl,
-+ &dev_master->slist, w1_slave_entry) {
-+ if (bulk_read_support(sl))
-+ SLAVE_CONVERT_TRIGGERED(sl) = -1;
-+ }
-+
-+ if (strong_pullup) { /* some device need pullup */
-+ sleep_rem = msleep_interruptible(t_conv);
-+ if (sleep_rem != 0) {
-+ ret = -EINTR;
-+ goto mt_unlock;
-+ }
-+ mutex_unlock(&dev_master->bus_mutex);
-+ } else {
-+ mutex_unlock(&dev_master->bus_mutex);
-+ sleep_rem = msleep_interruptible(t_conv);
-+ if (sleep_rem != 0) {
-+ ret = -EINTR;
-+ goto set_flag;
-+ }
-+ }
-+ ret = 0;
-+ goto set_flag;
-+ }
-+ }
-+
-+mt_unlock:
-+ mutex_unlock(&dev_master->bus_mutex);
-+set_flag:
-+ /* set a flag to register convsersion is done */
-+ list_for_each_entry(sl, &dev_master->slist, w1_slave_entry) {
-+ if (bulk_read_support(sl))
-+ SLAVE_CONVERT_TRIGGERED(sl) = 1;
-+ }
-+error:
-+ return ret;
-+}
-+
- /* Sysfs Interface definition */
-
- static ssize_t w1_slave_show(struct device *device,
-@@ -1095,7 +1273,20 @@ static ssize_t w1_slave_show(struct devi
- int ret, i;
- ssize_t c = PAGE_SIZE;
-
-- ret = convert_t(sl, &info);
-+ if (bulk_read_support(sl)) {
-+ if (SLAVE_CONVERT_TRIGGERED(sl) < 0) {
-+ dev_dbg(device,
-+ "%s: Conversion in progress, retry later\n",
-+ __func__);
-+ return 0;
-+ } else if (SLAVE_CONVERT_TRIGGERED(sl) > 0) {
-+ /* A bulk read has been issued, read the device RAM */
-+ ret = read_scratchpad(sl, &info);
-+ SLAVE_CONVERT_TRIGGERED(sl) = 0;
-+ } else
-+ ret = convert_t(sl, &info);
-+ } else
-+ ret = convert_t(sl, &info);
-
- if (ret < 0) {
- dev_dbg(device,
-@@ -1176,7 +1367,20 @@ static ssize_t temperature_show(struct d
- return 0; /* No device family */
- }
-
-- ret = convert_t(sl, &info);
-+ if (bulk_read_support(sl)) {
-+ if (SLAVE_CONVERT_TRIGGERED(sl) < 0) {
-+ dev_dbg(device,
-+ "%s: Conversion in progress, retry later\n",
-+ __func__);
-+ return 0;
-+ } else if (SLAVE_CONVERT_TRIGGERED(sl) > 0) {
-+ /* A bulk read has been issued, read the device RAM */
-+ ret = read_scratchpad(sl, &info);
-+ SLAVE_CONVERT_TRIGGERED(sl) = 0;
-+ } else
-+ ret = convert_t(sl, &info);
-+ } else
-+ ret = convert_t(sl, &info);
-
- if (ret < 0) {
- dev_dbg(device,
-@@ -1412,6 +1616,49 @@ free_m:
- return size;
- }
-
-+static ssize_t therm_bulk_read_store(struct device *device,
-+ struct device_attribute *attr, const char *buf, size_t size)
-+{
-+ struct w1_master *dev_master = dev_to_w1_master(device);
-+ int ret = -EINVAL; /* Invalid argument */
-+
-+ if (size == sizeof(BULK_TRIGGER_CMD))
-+ if (!strncmp(buf, BULK_TRIGGER_CMD,
-+ sizeof(BULK_TRIGGER_CMD)-1))
-+ ret = trigger_bulk_read(dev_master);
-+
-+ if (ret)
-+ dev_info(device,
-+ "%s: unable to trigger a bulk read on the bus. err=%d\n",
-+ __func__, ret);
-+
-+ return size;
-+}
-+
-+static ssize_t therm_bulk_read_show(struct device *device,
-+ struct device_attribute *attr, char *buf)
-+{
-+ struct w1_master *dev_master = dev_to_w1_master(device);
-+ struct w1_slave *sl = NULL;
-+ int ret = 0;
-+
-+ list_for_each_entry(sl, &dev_master->slist, w1_slave_entry) {
-+ if (sl->family_data) {
-+ if (bulk_read_support(sl)) {
-+ if (SLAVE_CONVERT_TRIGGERED(sl) == -1) {
-+ ret = -1;
-+ goto show_result;
-+ }
-+ if (SLAVE_CONVERT_TRIGGERED(sl) == 1)
-+ /* continue to check other slaves */
-+ ret = 1;
-+ }
-+ }
-+ }
-+show_result:
-+ return sprintf(buf, "%d\n", ret);
-+}
-+
- #if IS_REACHABLE(CONFIG_HWMON)
- static int w1_read_temp(struct device *device, u32 attr, int channel,
- long *val)