mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 12:43:29 +02:00
w1/w1.c: w1 address crc quick for DS28E04 eeproms
Onewire addresses are 64bit family(8bit), unique_id(48bit), crc(8bit) (LSBt to MSB) and self-consistent: crc = crc8(family, unique). DS28E04-100 4096-Bit Addressable 1-Wire EEPROM with PIO have strap pins to set 7 LSB of the address, unfortunately without updating the crc part of the address. It is only consistent if all strap pins float high. [see datasheet 19-6134; Rev 12/11 page 6: 64-bit device id number] We therefore introduce a special handling of family 0x1c (DS28E04) to check address consistency with 7 LSBs of the unique_id set to 1. Acked-by: Evgeniy Polyakov <zbr@ioremap.net> Signed-off-by: Christian Vogel <vogelchr@vogel.cx> Link: https://lore.kernel.org/r/20210113195018.7498-2-vogelchr@vogel.cx Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
20612d2428
commit
48b7de6687
@@ -25,6 +25,8 @@
|
|||||||
#include "w1_netlink.h"
|
#include "w1_netlink.h"
|
||||||
|
|
||||||
#define W1_FAMILY_DEFAULT 0
|
#define W1_FAMILY_DEFAULT 0
|
||||||
|
#define W1_FAMILY_DS28E04 0x1C /* for crc quirk */
|
||||||
|
|
||||||
|
|
||||||
static int w1_timeout = 10;
|
static int w1_timeout = 10;
|
||||||
module_param_named(timeout, w1_timeout, int, 0);
|
module_param_named(timeout, w1_timeout, int, 0);
|
||||||
@@ -913,11 +915,44 @@ void w1_reconnect_slaves(struct w1_family *f, int attach)
|
|||||||
mutex_unlock(&w1_mlock);
|
mutex_unlock(&w1_mlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int w1_addr_crc_is_valid(struct w1_master *dev, u64 rn)
|
||||||
|
{
|
||||||
|
u64 rn_le = cpu_to_le64(rn);
|
||||||
|
struct w1_reg_num *tmp = (struct w1_reg_num *)&rn;
|
||||||
|
u8 crc;
|
||||||
|
|
||||||
|
crc = w1_calc_crc8((u8 *)&rn_le, 7);
|
||||||
|
|
||||||
|
/* quirk:
|
||||||
|
* DS28E04 (1w eeprom) has strapping pins to change
|
||||||
|
* address, but will not update the crc. So normal rules
|
||||||
|
* for consistent w1 addresses are violated. We test
|
||||||
|
* with the 7 LSBs of the address forced high.
|
||||||
|
*
|
||||||
|
* (char*)&rn_le = { family, addr_lsb, ..., addr_msb, crc }.
|
||||||
|
*/
|
||||||
|
if (crc != tmp->crc && tmp->family == W1_FAMILY_DS28E04) {
|
||||||
|
u64 corr_le = rn_le;
|
||||||
|
|
||||||
|
((u8 *)&corr_le)[1] |= 0x7f;
|
||||||
|
crc = w1_calc_crc8((u8 *)&corr_le, 7);
|
||||||
|
|
||||||
|
dev_info(&dev->dev, "DS28E04 crc workaround on %02x.%012llx.%02x\n",
|
||||||
|
tmp->family, (unsigned long long)tmp->id, tmp->crc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (crc != tmp->crc) {
|
||||||
|
dev_dbg(&dev->dev, "w1 addr crc mismatch: %02x.%012llx.%02x != 0x%02x.\n",
|
||||||
|
tmp->family, (unsigned long long)tmp->id, tmp->crc, crc);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
void w1_slave_found(struct w1_master *dev, u64 rn)
|
void w1_slave_found(struct w1_master *dev, u64 rn)
|
||||||
{
|
{
|
||||||
struct w1_slave *sl;
|
struct w1_slave *sl;
|
||||||
struct w1_reg_num *tmp;
|
struct w1_reg_num *tmp;
|
||||||
u64 rn_le = cpu_to_le64(rn);
|
|
||||||
|
|
||||||
atomic_inc(&dev->refcnt);
|
atomic_inc(&dev->refcnt);
|
||||||
|
|
||||||
@@ -927,7 +962,7 @@ void w1_slave_found(struct w1_master *dev, u64 rn)
|
|||||||
if (sl) {
|
if (sl) {
|
||||||
set_bit(W1_SLAVE_ACTIVE, &sl->flags);
|
set_bit(W1_SLAVE_ACTIVE, &sl->flags);
|
||||||
} else {
|
} else {
|
||||||
if (rn && tmp->crc == w1_calc_crc8((u8 *)&rn_le, 7))
|
if (rn && w1_addr_crc_is_valid(dev, rn))
|
||||||
w1_attach_slave_device(dev, tmp);
|
w1_attach_slave_device(dev, tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user