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

iio:common:ms_sensors:ms_sensors_i2c: add support for alternative PROM layout

Currently, only the 112bit PROM with 7 words is supported. However the ms58xx
family also have devices with a 128bit PROM on 8 words. See AN520:
C-CODE EXAMPLE FOR MS56XX, MS57XX (EXCEPT ANALOG SENSOR), AND MS58XX SERIES
PRESSURE SENSORS and the various device datasheets.

The difference is that the CRC is the 4 LSBs of word7 instead of being the
4 MSBs of word0.

Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Link: https://lore.kernel.org/r/20210109231148.1168104-6-alexandre.belloni@bootlin.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Alexandre Belloni and committed by
Jonathan Cameron
9ea7c790 7ae7f750

+59 -11
+59 -11
drivers/iio/common/ms_sensors/ms_sensors_i2c.c
··· 488 488 EXPORT_SYMBOL(ms_sensors_ht_read_humidity); 489 489 490 490 /** 491 - * ms_sensors_tp_crc_valid() - CRC check function for 491 + * ms_sensors_tp_crc4() - Calculate PROM CRC for 492 492 * Temperature and pressure devices. 493 493 * This function is only used when reading PROM coefficients 494 494 * 495 495 * @prom: pointer to PROM coefficients array 496 496 * 497 - * Return: True if CRC is ok. 497 + * Return: CRC. 498 498 */ 499 - static bool ms_sensors_tp_crc_valid(u16 *prom) 499 + static u8 ms_sensors_tp_crc4(u16 *prom) 500 500 { 501 501 unsigned int cnt, n_bit; 502 - u16 n_rem = 0x0000, crc_read = prom[0], crc = (*prom & 0xF000) >> 12; 503 - 504 - prom[MS_SENSORS_TP_PROM_WORDS_NB - 1] = 0; 505 - prom[0] &= 0x0FFF; /* Clear the CRC computation part */ 502 + u16 n_rem = 0x0000; 506 503 507 504 for (cnt = 0; cnt < MS_SENSORS_TP_PROM_WORDS_NB * 2; cnt++) { 508 505 if (cnt % 2 == 1) ··· 514 517 n_rem <<= 1; 515 518 } 516 519 } 517 - n_rem >>= 12; 518 - prom[0] = crc_read; 519 520 520 - return n_rem == crc; 521 + return n_rem >> 12; 522 + } 523 + 524 + /** 525 + * ms_sensors_tp_crc_valid_112() - CRC check function for 526 + * Temperature and pressure devices for 112bit PROM. 527 + * This function is only used when reading PROM coefficients 528 + * 529 + * @prom: pointer to PROM coefficients array 530 + * 531 + * Return: True if CRC is ok. 532 + */ 533 + static bool ms_sensors_tp_crc_valid_112(u16 *prom) 534 + { 535 + u16 w0 = prom[0], crc_read = (w0 & 0xF000) >> 12; 536 + u8 crc; 537 + 538 + prom[0] &= 0x0FFF; /* Clear the CRC computation part */ 539 + prom[MS_SENSORS_TP_PROM_WORDS_NB - 1] = 0; 540 + 541 + crc = ms_sensors_tp_crc4(prom); 542 + 543 + prom[0] = w0; 544 + 545 + return crc == crc_read; 546 + } 547 + 548 + /** 549 + * ms_sensors_tp_crc_valid_128() - CRC check function for 550 + * Temperature and pressure devices for 128bit PROM. 551 + * This function is only used when reading PROM coefficients 552 + * 553 + * @prom: pointer to PROM coefficients array 554 + * 555 + * Return: True if CRC is ok. 556 + */ 557 + static bool ms_sensors_tp_crc_valid_128(u16 *prom) 558 + { 559 + u16 w7 = prom[7], crc_read = w7 & 0x000F; 560 + u8 crc; 561 + 562 + prom[7] &= 0xFF00; /* Clear the CRC and LSB part */ 563 + 564 + crc = ms_sensors_tp_crc4(prom); 565 + 566 + prom[7] = w7; 567 + 568 + return crc == crc_read; 521 569 } 522 570 523 571 /** ··· 577 535 int ms_sensors_tp_read_prom(struct ms_tp_dev *dev_data) 578 536 { 579 537 int i, ret; 538 + bool valid; 580 539 581 540 for (i = 0; i < dev_data->hw->prom_len; i++) { 582 541 ret = ms_sensors_read_prom_word( ··· 589 546 return ret; 590 547 } 591 548 592 - if (!ms_sensors_tp_crc_valid(dev_data->prom)) { 549 + if (dev_data->hw->prom_len == 8) 550 + valid = ms_sensors_tp_crc_valid_128(dev_data->prom); 551 + else 552 + valid = ms_sensors_tp_crc_valid_112(dev_data->prom); 553 + 554 + if (!valid) { 593 555 dev_err(&dev_data->client->dev, 594 556 "Calibration coefficients crc check error\n"); 595 557 return -ENODEV;