From f07e572f6447465d8938679533d604e402b0f066 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 --- ...m-fix-reset_select_slave-during-discovery.patch | 149 +++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 target/linux/bcm27xx/patches-5.4/950-0767-w1_therm-fix-reset_select_slave-during-discovery.patch (limited to 'target/linux/bcm27xx/patches-5.4/950-0767-w1_therm-fix-reset_select_slave-during-discovery.patch') diff --git a/target/linux/bcm27xx/patches-5.4/950-0767-w1_therm-fix-reset_select_slave-during-discovery.patch b/target/linux/bcm27xx/patches-5.4/950-0767-w1_therm-fix-reset_select_slave-during-discovery.patch new file mode 100644 index 0000000000..9881f81de4 --- /dev/null +++ b/target/linux/bcm27xx/patches-5.4/950-0767-w1_therm-fix-reset_select_slave-during-discovery.patch @@ -0,0 +1,149 @@ +From dfc9fd0060f9103ca1f9335d529401ee8a105737 Mon Sep 17 00:00:00 2001 +From: Akira Shimahara +Date: Mon, 11 May 2020 22:36:10 +0200 +Subject: [PATCH] w1_therm: fix reset_select_slave during discovery + +commit c8ad65f6fbfdcb9b620674ef456020eef2bfeb36 upstream. + +Fix reset_select_slave issue during devices discovery by the master on +bus. The w1_reset_select_slave() from w1_io.c, which was previously used, +assume that if the slave count is 1 there is only one slave attached on +the bus. This is not always true. For example when discovering devices, +when the first device is discover by the bus master, its slave count is +1, but some other slaves may be on the bus. + +In that case instead of adressing command to the attached slave the +master throw a SKIP ROM command so that all slaves attached on the bus +will answer simultenaously causing data collision. + +A dedicated reset_select_slave() function is implemented here, +it always perform an adressing to each slave using the MATCH ROM +command. + +Signed-off-by: Akira Shimahara +Link: https://lore.kernel.org/r/20200511203610.409975-1-akira215corp@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/w1/slaves/w1_therm.c | 48 ++++++++++++++++++++++++++++++------ + 1 file changed, 41 insertions(+), 7 deletions(-) + +--- a/drivers/w1/slaves/w1_therm.c ++++ b/drivers/w1/slaves/w1_therm.c +@@ -16,6 +16,7 @@ + #include + #include + #include ++#include + + #include + +@@ -90,6 +91,24 @@ struct therm_info { + u8 verdict; + }; + ++/* Hardware Functions declaration */ ++ ++/** ++ * reset_select_slave() - reset and select a slave ++ * @sl: the slave to select ++ * ++ * Resets the bus and select the slave by sending a ROM MATCH cmd ++ * w1_reset_select_slave() from w1_io.c could not be used here because ++ * it sent a SKIP ROM command if only one device is on the line. ++ * At the beginning of the such process, sl->master->slave_count is 1 even if ++ * more devices are on the line, causing collision on the line. ++ * ++ * Context: The w1 master lock must be held. ++ * ++ * Return: 0 if success, negative kernel error code otherwise. ++ */ ++static int reset_select_slave(struct w1_slave *sl); ++ + /* Sysfs interface declaration */ + + static ssize_t w1_slave_show(struct device *device, +@@ -301,7 +320,7 @@ static inline int w1_DS18B20_precision(s + while (max_trying--) { + crc = 0; + +- if (!w1_reset_select_slave(sl)) { ++ if (!reset_select_slave(sl)) { + int count = 0; + + /* read values to only alter precision bits */ +@@ -314,7 +333,7 @@ static inline int w1_DS18B20_precision(s + if (rom[8] == crc) { + rom[4] = (rom[4] & ~mask) | (precision_bits & mask); + +- if (!w1_reset_select_slave(sl)) { ++ if (!reset_select_slave(sl)) { + w1_write_8(dev, W1_WRITE_SCRATCHPAD); + w1_write_8(dev, rom[2]); + w1_write_8(dev, rom[3]); +@@ -460,6 +479,21 @@ static void w1_therm_remove_slave(struct + + /* Hardware Functions */ + ++/* Safe version of reset_select_slave - avoid using the one in w_io.c */ ++static int reset_select_slave(struct w1_slave *sl) ++{ ++ u8 match[9] = { W1_MATCH_ROM, }; ++ u64 rn = le64_to_cpu(*((u64 *)&sl->reg_num)); ++ ++ if (w1_reset_bus(sl->master)) ++ return -ENODEV; ++ ++ memcpy(&match[1], &rn, 8); ++ w1_write_block(sl->master, match, 9); ++ ++ return 0; ++} ++ + static ssize_t read_therm(struct device *device, + struct w1_slave *sl, struct therm_info *info) + { +@@ -487,7 +521,7 @@ static ssize_t read_therm(struct device + info->verdict = 0; + info->crc = 0; + +- if (!w1_reset_select_slave(sl)) { ++ if (!reset_select_slave(sl)) { + int count = 0; + unsigned int tm = 750; + unsigned long sleep_rem; +@@ -495,7 +529,7 @@ static ssize_t read_therm(struct device + w1_write_8(dev, W1_READ_PSUPPLY); + external_power = w1_read_8(dev); + +- if (w1_reset_select_slave(sl)) ++ if (reset_select_slave(sl)) + continue; + + /* 750ms strong pullup (or delay) after the convert */ +@@ -525,7 +559,7 @@ static ssize_t read_therm(struct device + } + } + +- if (!w1_reset_select_slave(sl)) { ++ if (!reset_select_slave(sl)) { + + w1_write_8(dev, W1_READ_SCRATCHPAD); + count = w1_read_block(dev, info->rom, 9); +@@ -577,7 +611,7 @@ static inline int w1_therm_eeprom(struct + memset(rom, 0, sizeof(rom)); + + while (max_trying--) { +- if (!w1_reset_select_slave(sl)) { ++ if (!reset_select_slave(sl)) { + unsigned int tm = 10; + unsigned long sleep_rem; + +@@ -585,7 +619,7 @@ static inline int w1_therm_eeprom(struct + w1_write_8(dev, W1_READ_PSUPPLY); + external_power = w1_read_8(dev); + +- if (w1_reset_select_slave(sl)) ++ if (reset_select_slave(sl)) + continue; + + /* 10ms strong pullup/delay after the copy command */ -- cgit v1.2.3