Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Christian Vogel and committed by
Greg Kroah-Hartman
48b7de66 20612d24

+37 -2
+37 -2
drivers/w1/w1.c
··· 25 25 #include "w1_netlink.h" 26 26 27 27 #define W1_FAMILY_DEFAULT 0 28 + #define W1_FAMILY_DS28E04 0x1C /* for crc quirk */ 29 + 28 30 29 31 static int w1_timeout = 10; 30 32 module_param_named(timeout, w1_timeout, int, 0); ··· 915 913 mutex_unlock(&w1_mlock); 916 914 } 917 915 916 + static int w1_addr_crc_is_valid(struct w1_master *dev, u64 rn) 917 + { 918 + u64 rn_le = cpu_to_le64(rn); 919 + struct w1_reg_num *tmp = (struct w1_reg_num *)&rn; 920 + u8 crc; 921 + 922 + crc = w1_calc_crc8((u8 *)&rn_le, 7); 923 + 924 + /* quirk: 925 + * DS28E04 (1w eeprom) has strapping pins to change 926 + * address, but will not update the crc. So normal rules 927 + * for consistent w1 addresses are violated. We test 928 + * with the 7 LSBs of the address forced high. 929 + * 930 + * (char*)&rn_le = { family, addr_lsb, ..., addr_msb, crc }. 931 + */ 932 + if (crc != tmp->crc && tmp->family == W1_FAMILY_DS28E04) { 933 + u64 corr_le = rn_le; 934 + 935 + ((u8 *)&corr_le)[1] |= 0x7f; 936 + crc = w1_calc_crc8((u8 *)&corr_le, 7); 937 + 938 + dev_info(&dev->dev, "DS28E04 crc workaround on %02x.%012llx.%02x\n", 939 + tmp->family, (unsigned long long)tmp->id, tmp->crc); 940 + } 941 + 942 + if (crc != tmp->crc) { 943 + dev_dbg(&dev->dev, "w1 addr crc mismatch: %02x.%012llx.%02x != 0x%02x.\n", 944 + tmp->family, (unsigned long long)tmp->id, tmp->crc, crc); 945 + return 0; 946 + } 947 + return 1; 948 + } 949 + 918 950 void w1_slave_found(struct w1_master *dev, u64 rn) 919 951 { 920 952 struct w1_slave *sl; 921 953 struct w1_reg_num *tmp; 922 - u64 rn_le = cpu_to_le64(rn); 923 954 924 955 atomic_inc(&dev->refcnt); 925 956 ··· 962 927 if (sl) { 963 928 set_bit(W1_SLAVE_ACTIVE, &sl->flags); 964 929 } else { 965 - if (rn && tmp->crc == w1_calc_crc8((u8 *)&rn_le, 7)) 930 + if (rn && w1_addr_crc_is_valid(dev, rn)) 966 931 w1_attach_slave_device(dev, tmp); 967 932 } 968 933