From 62b7f5931c54e96fca56dd8761b0e466d355c881 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Thu, 18 Feb 2021 18:04:33 +0100 Subject: bcm27xx: import latest patches from the RPi foundation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bcm2708: boot tested on RPi B+ v1.2 bcm2709: boot tested on RPi 3B v1.2 and RPi 4B v1.1 4G bcm2710: boot tested on RPi 3B v1.2 bcm2711: boot tested on RPi 4B v1.1 4G Signed-off-by: Álvaro Fernández Rojas (cherry-picked from commit f07e572f64) --- ...-adding-code-comments-and-code-reordering.patch | 580 +++++++++++++++++++++ 1 file changed, 580 insertions(+) create mode 100644 target/linux/bcm27xx/patches-5.4/950-0766-w1_therm-adding-code-comments-and-code-reordering.patch (limited to 'target/linux/bcm27xx/patches-5.4/950-0766-w1_therm-adding-code-comments-and-code-reordering.patch') diff --git a/target/linux/bcm27xx/patches-5.4/950-0766-w1_therm-adding-code-comments-and-code-reordering.patch b/target/linux/bcm27xx/patches-5.4/950-0766-w1_therm-adding-code-comments-and-code-reordering.patch new file mode 100644 index 0000000000..5db05123da --- /dev/null +++ b/target/linux/bcm27xx/patches-5.4/950-0766-w1_therm-adding-code-comments-and-code-reordering.patch @@ -0,0 +1,580 @@ +From 7c49e87acd0412ff1fb2490c4ac6fcb5471afd9b Mon Sep 17 00:00:00 2001 +From: Akira Shimahara +Date: Mon, 11 May 2020 22:35:35 +0200 +Subject: [PATCH] w1_therm: adding code comments and code reordering + +commit 92b8d2724464bc1d2e735a84c0da5741dce33485 upstream. + +Adding code comments to split code in dedicated parts. After the global +declarations (defines, macros and function declarations), code is organized +as follow : + - Device and family dependent structures and functions + - Interfaces functions + - Helpers functions + - Hardware functions + - Sysfs interface functions + +Signed-off-by: Akira Shimahara +Link: https://lore.kernel.org/r/20200511203535.409599-1-akira215corp@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/w1/slaves/w1_therm.c | 427 +++++++++++++++++++++-------------- + 1 file changed, 259 insertions(+), 168 deletions(-) + +--- a/drivers/w1/slaves/w1_therm.c ++++ b/drivers/w1/slaves/w1_therm.c +@@ -25,7 +25,8 @@ + #define W1_THERM_DS1825 0x3B + #define W1_THERM_DS28EA00 0x42 + +-/* Allow the strong pullup to be disabled, but default to enabled. ++/* ++ * Allow the strong pullup to be disabled, but default to enabled. + * If it was disabled a parasite powered device might not get the require + * current to do a temperature conversion. If it is enabled parasite powered + * devices have a better chance of getting the current required. +@@ -41,42 +42,55 @@ + static int w1_strong_pullup = 1; + module_param_named(strong_pullup, w1_strong_pullup, int, 0); + ++/* Helpers Macros */ ++ ++/* return the address of the refcnt in the family data */ ++#define THERM_REFCNT(family_data) \ ++ (&((struct w1_therm_family_data *)family_data)->refcnt) ++ ++/* Structs definition */ ++ ++/** ++ * struct w1_therm_family_converter - bind device specific functions ++ * @broken: flag for non-registred families ++ * @reserved: not used here ++ * @f: pointer to the device binding structure ++ * @convert: pointer to the device conversion function ++ * @precision: pointer to the device precision function ++ * @eeprom: pointer to eeprom function ++ */ ++struct w1_therm_family_converter { ++ u8 broken; ++ u16 reserved; ++ struct w1_family *f; ++ int (*convert)(u8 rom[9]); ++ int (*precision)(struct device *device, int val); ++ int (*eeprom)(struct device *device); ++}; ++ ++/** ++ * struct w1_therm_family_data - device data ++ * @rom: ROM device id (64bit Lasered ROM code + 1 CRC byte) ++ * @refcnt: ref count ++ */ + struct w1_therm_family_data { + uint8_t rom[9]; + atomic_t refcnt; + }; + ++/** ++ * struct therm_info - store temperature reading ++ * @rom: read device data (8 data bytes + 1 CRC byte) ++ * @crc: computed crc from rom ++ * @verdict: 1 crc checked, 0 crc not matching ++ */ + 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) +- +-static int w1_therm_add_slave(struct w1_slave *sl) +-{ +- sl->family_data = kzalloc(sizeof(struct w1_therm_family_data), +- GFP_KERNEL); +- if (!sl->family_data) +- return -ENOMEM; +- atomic_set(THERM_REFCNT(sl->family_data), 1); +- return 0; +-} +- +-static void w1_therm_remove_slave(struct w1_slave *sl) +-{ +- int refcnt = atomic_sub_return(1, THERM_REFCNT(sl->family_data)); +- +- while (refcnt) { +- msleep(1000); +- refcnt = atomic_read(THERM_REFCNT(sl->family_data)); +- } +- kfree(sl->family_data); +- sl->family_data = NULL; +-} ++/* Sysfs interface declaration */ + + static ssize_t w1_slave_show(struct device *device, + struct device_attribute *attr, char *buf); +@@ -87,9 +101,35 @@ static ssize_t w1_slave_store(struct dev + static ssize_t w1_seq_show(struct device *device, + struct device_attribute *attr, char *buf); + ++/* Attributes declarations */ ++ + static DEVICE_ATTR_RW(w1_slave); + static DEVICE_ATTR_RO(w1_seq); + ++/* Interface Functions declaration */ ++ ++/** ++ * w1_therm_add_slave() - Called when a new slave is discovered ++ * @sl: slave just discovered by the master. ++ * ++ * Called by the master when the slave is discovered on the bus. Used to ++ * initialize slave state before the beginning of any communication. ++ * ++ * Return: 0 - If success, negative kernel code otherwise ++ */ ++static int w1_therm_add_slave(struct w1_slave *sl); ++ ++/** ++ * w1_therm_remove_slave() - Called when a slave is removed ++ * @sl: slave to be removed. ++ * ++ * Called by the master when the slave is considered not to be on the bus ++ * anymore. Used to free memory. ++ */ ++static void w1_therm_remove_slave(struct w1_slave *sl); ++ ++/* Family attributes */ ++ + static struct attribute *w1_therm_attrs[] = { + &dev_attr_w1_slave.attr, + NULL, +@@ -101,6 +141,8 @@ static struct attribute *w1_ds28ea00_att + NULL, + }; + ++/* Attribute groups */ ++ + ATTRIBUTE_GROUPS(w1_therm); + ATTRIBUTE_GROUPS(w1_ds28ea00); + +@@ -154,6 +196,8 @@ static const struct hwmon_chip_info w1_c + #define W1_CHIPINFO NULL + #endif + ++/* Family operations */ ++ + static struct w1_family_ops w1_therm_fops = { + .add_slave = w1_therm_add_slave, + .remove_slave = w1_therm_remove_slave, +@@ -168,6 +212,8 @@ static struct w1_family_ops w1_ds28ea00_ + .chip_info = W1_CHIPINFO, + }; + ++/* Family binding operations struct */ ++ + static struct w1_family w1_therm_family_DS18S20 = { + .fid = W1_THERM_DS18S20, + .fops = &w1_therm_fops, +@@ -193,138 +239,18 @@ static struct w1_family w1_therm_family_ + .fops = &w1_therm_fops, + }; + +-struct w1_therm_family_converter { +- u8 broken; +- u16 reserved; +- struct w1_family *f; +- int (*convert)(u8 rom[9]); +- int (*precision)(struct device *device, int val); +- int (*eeprom)(struct device *device); +-}; ++/* Device dependent func */ + + /* write configuration to eeprom */ + static inline int w1_therm_eeprom(struct device *device); + +-/* Set precision for conversion */ +-static inline int w1_DS18B20_precision(struct device *device, int val); +-static inline int w1_DS18S20_precision(struct device *device, int val); +- +-/* The return value is millidegrees Centigrade. */ +-static inline int w1_DS18B20_convert_temp(u8 rom[9]); +-static inline int w1_DS18S20_convert_temp(u8 rom[9]); +- +-static struct w1_therm_family_converter w1_therm_families[] = { +- { +- .f = &w1_therm_family_DS18S20, +- .convert = w1_DS18S20_convert_temp, +- .precision = w1_DS18S20_precision, +- .eeprom = w1_therm_eeprom +- }, +- { +- .f = &w1_therm_family_DS1822, +- .convert = w1_DS18B20_convert_temp, +- .precision = w1_DS18S20_precision, +- .eeprom = w1_therm_eeprom +- }, +- { +- .f = &w1_therm_family_DS18B20, +- .convert = w1_DS18B20_convert_temp, +- .precision = w1_DS18B20_precision, +- .eeprom = w1_therm_eeprom +- }, +- { +- .f = &w1_therm_family_DS28EA00, +- .convert = w1_DS18B20_convert_temp, +- .precision = w1_DS18S20_precision, +- .eeprom = w1_therm_eeprom +- }, +- { +- .f = &w1_therm_family_DS1825, +- .convert = w1_DS18B20_convert_temp, +- .precision = w1_DS18S20_precision, +- .eeprom = w1_therm_eeprom +- } +-}; +- +-static inline int w1_therm_eeprom(struct device *device) +-{ +- struct w1_slave *sl = dev_to_w1_slave(device); +- struct w1_master *dev = sl->master; +- u8 rom[9], external_power; +- int ret, max_trying = 10; +- u8 *family_data = sl->family_data; +- +- if (!sl->family_data) { +- ret = -ENODEV; +- goto error; +- } +- +- /* prevent the slave from going away in sleep */ +- atomic_inc(THERM_REFCNT(family_data)); +- +- ret = mutex_lock_interruptible(&dev->bus_mutex); +- if (ret != 0) +- goto dec_refcnt; +- +- memset(rom, 0, sizeof(rom)); +- +- while (max_trying--) { +- if (!w1_reset_select_slave(sl)) { +- unsigned int tm = 10; +- unsigned long sleep_rem; +- +- /* check if in parasite mode */ +- w1_write_8(dev, W1_READ_PSUPPLY); +- external_power = w1_read_8(dev); +- +- if (w1_reset_select_slave(sl)) +- continue; +- +- /* 10ms strong pullup/delay after the copy command */ +- if (w1_strong_pullup == 2 || +- (!external_power && w1_strong_pullup)) +- w1_next_pullup(dev, tm); +- +- w1_write_8(dev, W1_COPY_SCRATCHPAD); +- +- if (external_power) { +- mutex_unlock(&dev->bus_mutex); +- +- sleep_rem = msleep_interruptible(tm); +- if (sleep_rem != 0) { +- ret = -EINTR; +- goto dec_refcnt; +- } +- +- ret = mutex_lock_interruptible(&dev->bus_mutex); +- if (ret != 0) +- goto dec_refcnt; +- } else if (!w1_strong_pullup) { +- sleep_rem = msleep_interruptible(tm); +- if (sleep_rem != 0) { +- ret = -EINTR; +- goto mt_unlock; +- } +- } +- +- break; +- } +- } +- +-mt_unlock: +- mutex_unlock(&dev->bus_mutex); +-dec_refcnt: +- atomic_dec(THERM_REFCNT(family_data)); +-error: +- return ret; +-} +- + /* DS18S20 does not feature configuration register */ + static inline int w1_DS18S20_precision(struct device *device, int val) + { + return 0; + } + ++/* Set precision for conversion */ + static inline int w1_DS18B20_precision(struct device *device, int val) + { + struct w1_slave *sl = dev_to_w1_slave(device); +@@ -407,6 +333,14 @@ error: + return ret; + } + ++/** ++ * w1_DS18B20_convert_temp() - temperature computation for DS18B20 ++ * @rom: data read from device RAM (8 data bytes + 1 CRC byte) ++ * ++ * Can be called for any DS18B20 compliant device. ++ * ++ * Return: value in millidegrees Celsius. ++ */ + static inline int w1_DS18B20_convert_temp(u8 rom[9]) + { + s16 t = le16_to_cpup((__le16 *)rom); +@@ -414,6 +348,14 @@ static inline int w1_DS18B20_convert_tem + return t*1000/16; + } + ++/** ++ * w1_DS18S20_convert_temp() - temperature computation for DS18S20 ++ * @rom: data read from device RAM (8 data bytes + 1 CRC byte) ++ * ++ * Can be called for any DS18S20 compliant device. ++ * ++ * Return: value in millidegrees Celsius. ++ */ + static inline int w1_DS18S20_convert_temp(u8 rom[9]) + { + int t, h; +@@ -434,6 +376,53 @@ static inline int w1_DS18S20_convert_tem + return t; + } + ++/* Device capability description */ ++ ++static struct w1_therm_family_converter w1_therm_families[] = { ++ { ++ .f = &w1_therm_family_DS18S20, ++ .convert = w1_DS18S20_convert_temp, ++ .precision = w1_DS18S20_precision, ++ .eeprom = w1_therm_eeprom ++ }, ++ { ++ .f = &w1_therm_family_DS1822, ++ .convert = w1_DS18B20_convert_temp, ++ .precision = w1_DS18S20_precision, ++ .eeprom = w1_therm_eeprom ++ }, ++ { ++ .f = &w1_therm_family_DS18B20, ++ .convert = w1_DS18B20_convert_temp, ++ .precision = w1_DS18B20_precision, ++ .eeprom = w1_therm_eeprom ++ }, ++ { ++ .f = &w1_therm_family_DS28EA00, ++ .convert = w1_DS18B20_convert_temp, ++ .precision = w1_DS18S20_precision, ++ .eeprom = w1_therm_eeprom ++ }, ++ { ++ .f = &w1_therm_family_DS1825, ++ .convert = w1_DS18B20_convert_temp, ++ .precision = w1_DS18S20_precision, ++ .eeprom = w1_therm_eeprom ++ } ++}; ++ ++/* Helpers Functions */ ++ ++/** ++ * w1_convert_temp() - temperature conversion binding function ++ * @rom: data read from device RAM (8 data bytes + 1 CRC byte) ++ * @fid: device family id ++ * ++ * The function call the temperature computation function according to ++ * device family. ++ * ++ * Return: value in millidegrees Celsius. ++ */ + static inline int w1_convert_temp(u8 rom[9], u8 fid) + { + int i; +@@ -445,31 +434,32 @@ static inline int w1_convert_temp(u8 rom + return 0; + } + +-static ssize_t w1_slave_store(struct device *device, +- struct device_attribute *attr, const char *buf, +- size_t size) ++/* Interface Functions */ ++ ++static int w1_therm_add_slave(struct w1_slave *sl) + { +- int val, ret; +- struct w1_slave *sl = dev_to_w1_slave(device); +- int i; ++ sl->family_data = kzalloc(sizeof(struct w1_therm_family_data), ++ GFP_KERNEL); ++ if (!sl->family_data) ++ return -ENOMEM; ++ atomic_set(THERM_REFCNT(sl->family_data), 1); ++ return 0; ++} + +- ret = kstrtoint(buf, 0, &val); +- if (ret) +- return ret; ++static void w1_therm_remove_slave(struct w1_slave *sl) ++{ ++ int refcnt = atomic_sub_return(1, THERM_REFCNT(sl->family_data)); + +- for (i = 0; i < ARRAY_SIZE(w1_therm_families); ++i) { +- if (w1_therm_families[i].f->fid == sl->family->fid) { +- /* zero value indicates to write current configuration to eeprom */ +- if (val == 0) +- ret = w1_therm_families[i].eeprom(device); +- else +- ret = w1_therm_families[i].precision(device, val); +- break; +- } ++ while (refcnt) { ++ msleep(1000); ++ refcnt = atomic_read(THERM_REFCNT(sl->family_data)); + } +- return ret ? : size; ++ kfree(sl->family_data); ++ sl->family_data = NULL; + } + ++/* Hardware Functions */ ++ + static ssize_t read_therm(struct device *device, + struct w1_slave *sl, struct therm_info *info) + { +@@ -564,6 +554,81 @@ error: + return ret; + } + ++static inline int w1_therm_eeprom(struct device *device) ++{ ++ struct w1_slave *sl = dev_to_w1_slave(device); ++ struct w1_master *dev = sl->master; ++ u8 rom[9], external_power; ++ int ret, max_trying = 10; ++ u8 *family_data = sl->family_data; ++ ++ if (!sl->family_data) { ++ ret = -ENODEV; ++ goto error; ++ } ++ ++ /* prevent the slave from going away in sleep */ ++ atomic_inc(THERM_REFCNT(family_data)); ++ ++ ret = mutex_lock_interruptible(&dev->bus_mutex); ++ if (ret != 0) ++ goto dec_refcnt; ++ ++ memset(rom, 0, sizeof(rom)); ++ ++ while (max_trying--) { ++ if (!w1_reset_select_slave(sl)) { ++ unsigned int tm = 10; ++ unsigned long sleep_rem; ++ ++ /* check if in parasite mode */ ++ w1_write_8(dev, W1_READ_PSUPPLY); ++ external_power = w1_read_8(dev); ++ ++ if (w1_reset_select_slave(sl)) ++ continue; ++ ++ /* 10ms strong pullup/delay after the copy command */ ++ if (w1_strong_pullup == 2 || ++ (!external_power && w1_strong_pullup)) ++ w1_next_pullup(dev, tm); ++ ++ w1_write_8(dev, W1_COPY_SCRATCHPAD); ++ ++ if (external_power) { ++ mutex_unlock(&dev->bus_mutex); ++ ++ sleep_rem = msleep_interruptible(tm); ++ if (sleep_rem != 0) { ++ ret = -EINTR; ++ goto dec_refcnt; ++ } ++ ++ ret = mutex_lock_interruptible(&dev->bus_mutex); ++ if (ret != 0) ++ goto dec_refcnt; ++ } else if (!w1_strong_pullup) { ++ sleep_rem = msleep_interruptible(tm); ++ if (sleep_rem != 0) { ++ ret = -EINTR; ++ goto mt_unlock; ++ } ++ } ++ ++ break; ++ } ++ } ++ ++mt_unlock: ++ mutex_unlock(&dev->bus_mutex); ++dec_refcnt: ++ atomic_dec(THERM_REFCNT(family_data)); ++error: ++ return ret; ++} ++ ++/* Sysfs Interface definition */ ++ + static ssize_t w1_slave_show(struct device *device, + struct device_attribute *attr, char *buf) + { +@@ -597,6 +662,32 @@ static ssize_t w1_slave_show(struct devi + return ret; + } + ++static ssize_t w1_slave_store(struct device *device, ++ struct device_attribute *attr, const char *buf, ++ size_t size) ++{ ++ int val, ret; ++ struct w1_slave *sl = dev_to_w1_slave(device); ++ int i; ++ ++ ret = kstrtoint(buf, 0, &val); ++ if (ret) ++ return ret; ++ ++ for (i = 0; i < ARRAY_SIZE(w1_therm_families); ++i) { ++ if (w1_therm_families[i].f->fid == sl->family->fid) { ++ /* zero value indicates to write current configuration to eeprom */ ++ if (val == 0) ++ ret = w1_therm_families[i].eeprom(device); ++ else ++ ret = w1_therm_families[i].precision(device, ++ val); ++ break; ++ } ++ } ++ return ret ? : size; ++} ++ + #if IS_REACHABLE(CONFIG_HWMON) + static int w1_read_temp(struct device *device, u32 attr, int channel, + long *val) +@@ -666,7 +757,7 @@ static ssize_t w1_seq_show(struct device + if (ack != W1_42_SUCCESS_CONFIRM_BYTE) + goto error; + +- /* In case the bus fails to send 0xFF, limit*/ ++ /* In case the bus fails to send 0xFF, limit */ + for (i = 0; i <= 64; i++) { + if (w1_reset_bus(sl->master)) + goto error; -- cgit v1.2.3