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

misc: eeprom_93xx46: Remove hardcoded bit lengths

This avoids using magic numbers based on the length of an address or a
command, while we only want to differentiate between 8-bit and 16-bit.

The driver was previously wrapping around the offset in the write
operation, this now returns -EINVAL instead (but should never happen in
the first place).

If two pointer indirections are too many, we could move the flags to the
main struct instead, but I doubt it’s going to make any sensible
difference on any hardware.

Reviewed-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
Signed-off-by: Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
Link: https://lore.kernel.org/r/20210511210727.24895-2-linkmauve@linkmauve.fr
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Emmanuel Gil Peyrot and committed by
Greg Kroah-Hartman
4a5ff99b 9ac78c8a

+32 -25
+32 -25
drivers/misc/eeprom/eeprom_93xx46.c
··· 9 9 #include <linux/device.h> 10 10 #include <linux/gpio/consumer.h> 11 11 #include <linux/kernel.h> 12 + #include <linux/log2.h> 12 13 #include <linux/module.h> 13 14 #include <linux/mutex.h> 14 15 #include <linux/of.h> ··· 71 70 struct eeprom_93xx46_dev *edev = priv; 72 71 char *buf = val; 73 72 int err = 0; 73 + int bits; 74 74 75 75 if (unlikely(off >= edev->size)) 76 76 return 0; ··· 85 83 if (edev->pdata->prepare) 86 84 edev->pdata->prepare(edev); 87 85 86 + /* The opcode in front of the address is three bits. */ 87 + bits = edev->addrlen + 3; 88 + 88 89 while (count) { 89 90 struct spi_message m; 90 91 struct spi_transfer t[2] = { { 0 } }; 91 92 u16 cmd_addr = OP_READ << edev->addrlen; 92 93 size_t nbytes = count; 93 - int bits; 94 94 95 - if (edev->addrlen == 7) { 96 - cmd_addr |= off & 0x7f; 97 - bits = 10; 95 + if (edev->pdata->flags & EE_ADDR8) { 96 + cmd_addr |= off; 98 97 if (has_quirk_single_word_read(edev)) 99 98 nbytes = 1; 100 99 } else { 101 - cmd_addr |= (off >> 1) & 0x3f; 102 - bits = 9; 100 + cmd_addr |= (off >> 1); 103 101 if (has_quirk_single_word_read(edev)) 104 102 nbytes = 2; 105 103 } ··· 154 152 int bits, ret; 155 153 u16 cmd_addr; 156 154 155 + /* The opcode in front of the address is three bits. */ 156 + bits = edev->addrlen + 3; 157 + 157 158 cmd_addr = OP_START << edev->addrlen; 158 - if (edev->addrlen == 7) { 159 + if (edev->pdata->flags & EE_ADDR8) 159 160 cmd_addr |= (is_on ? ADDR_EWEN : ADDR_EWDS) << 1; 160 - bits = 10; 161 - } else { 161 + else 162 162 cmd_addr |= (is_on ? ADDR_EWEN : ADDR_EWDS); 163 - bits = 9; 164 - } 165 163 166 164 if (has_quirk_instruction_length(edev)) { 167 165 cmd_addr <<= 2; ··· 207 205 int bits, data_len, ret; 208 206 u16 cmd_addr; 209 207 208 + if (unlikely(off >= edev->size)) 209 + return -EINVAL; 210 + 211 + /* The opcode in front of the address is three bits. */ 212 + bits = edev->addrlen + 3; 213 + 210 214 cmd_addr = OP_WRITE << edev->addrlen; 211 215 212 - if (edev->addrlen == 7) { 213 - cmd_addr |= off & 0x7f; 214 - bits = 10; 216 + if (edev->pdata->flags & EE_ADDR8) { 217 + cmd_addr |= off; 215 218 data_len = 1; 216 219 } else { 217 - cmd_addr |= (off >> 1) & 0x3f; 218 - bits = 9; 220 + cmd_addr |= (off >> 1); 219 221 data_len = 2; 220 222 } 221 223 ··· 259 253 return count; 260 254 261 255 /* only write even number of bytes on 16-bit devices */ 262 - if (edev->addrlen == 6) { 256 + if (edev->pdata->flags & EE_ADDR16) { 263 257 step = 2; 264 258 count &= ~1; 265 259 } ··· 301 295 int bits, ret; 302 296 u16 cmd_addr; 303 297 298 + /* The opcode in front of the address is three bits. */ 299 + bits = edev->addrlen + 3; 300 + 304 301 cmd_addr = OP_START << edev->addrlen; 305 - if (edev->addrlen == 7) { 302 + if (edev->pdata->flags & EE_ADDR8) 306 303 cmd_addr |= ADDR_ERAL << 1; 307 - bits = 10; 308 - } else { 304 + else 309 305 cmd_addr |= ADDR_ERAL; 310 - bits = 9; 311 - } 312 306 313 307 if (has_quirk_instruction_length(edev)) { 314 308 cmd_addr <<= 2; ··· 461 455 if (!edev) 462 456 return -ENOMEM; 463 457 458 + edev->size = 128; 459 + 464 460 if (pd->flags & EE_ADDR8) 465 - edev->addrlen = 7; 461 + edev->addrlen = ilog2(edev->size); 466 462 else if (pd->flags & EE_ADDR16) 467 - edev->addrlen = 6; 463 + edev->addrlen = ilog2(edev->size) - 1; 468 464 else { 469 465 dev_err(&spi->dev, "unspecified address type\n"); 470 466 return -EINVAL; ··· 477 469 edev->spi = spi; 478 470 edev->pdata = pd; 479 471 480 - edev->size = 128; 481 472 edev->nvmem_config.type = NVMEM_TYPE_EEPROM; 482 473 edev->nvmem_config.name = dev_name(&spi->dev); 483 474 edev->nvmem_config.dev = &spi->dev;