aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJerome Oufella <jerome.oufella@savoirfairelinux.com>2011-04-12 15:34:39 -0400
committerGuenter Roeck <guenter.roeck@ericsson.com>2011-05-19 11:19:36 -0400
commit82c7465b4dd013d19858bfeac084849ae17682c0 (patch)
treeaf6828f4e6cac12153100b30fbe126fe0989e1a8 /drivers
parentcc15c7ebb424e45ba2c5ceecbe52d025219ee970 (diff)
hwmon: (sht15) add support for CRC validation
The sht15 sensor allows validating exchanges to and from the device using a crc8 function. An utility function to reverse a byte has also been added. Signed-off-by: Jerome Oufella <jerome.oufella@savoirfairelinux.com> Acked-by: Jonathan Cameron <jic23@cam.ac.uk> Signed-off-by: Guenter Roeck <guenter.roeck@ericsson.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/hwmon/sht15.c192
1 files changed, 173 insertions, 19 deletions
diff --git a/drivers/hwmon/sht15.c b/drivers/hwmon/sht15.c
index 49da089b5de9..cf4330b352ef 100644
--- a/drivers/hwmon/sht15.c
+++ b/drivers/hwmon/sht15.c
@@ -2,6 +2,7 @@
2 * sht15.c - support for the SHT15 Temperature and Humidity Sensor 2 * sht15.c - support for the SHT15 Temperature and Humidity Sensor
3 * 3 *
4 * Portions Copyright (c) 2010-2011 Savoir-faire Linux Inc. 4 * Portions Copyright (c) 2010-2011 Savoir-faire Linux Inc.
5 * Jerome Oufella <jerome.oufella@savoirfairelinux.com>
5 * Vivien Didelot <vivien.didelot@savoirfairelinux.com> 6 * Vivien Didelot <vivien.didelot@savoirfairelinux.com>
6 * 7 *
7 * Copyright (c) 2009 Jonathan Cameron 8 * Copyright (c) 2009 Jonathan Cameron
@@ -78,6 +79,42 @@ static const struct sht15_temppair temppoints[] = {
78 { 5000000, -40100 }, 79 { 5000000, -40100 },
79}; 80};
80 81
82/* Table from CRC datasheet, section 2.4 */
83static const u8 sht15_crc8_table[] = {
84 0, 49, 98, 83, 196, 245, 166, 151,
85 185, 136, 219, 234, 125, 76, 31, 46,
86 67, 114, 33, 16, 135, 182, 229, 212,
87 250, 203, 152, 169, 62, 15, 92, 109,
88 134, 183, 228, 213, 66, 115, 32, 17,
89 63, 14, 93, 108, 251, 202, 153, 168,
90 197, 244, 167, 150, 1, 48, 99, 82,
91 124, 77, 30, 47, 184, 137, 218, 235,
92 61, 12, 95, 110, 249, 200, 155, 170,
93 132, 181, 230, 215, 64, 113, 34, 19,
94 126, 79, 28, 45, 186, 139, 216, 233,
95 199, 246, 165, 148, 3, 50, 97, 80,
96 187, 138, 217, 232, 127, 78, 29, 44,
97 2, 51, 96, 81, 198, 247, 164, 149,
98 248, 201, 154, 171, 60, 13, 94, 111,
99 65, 112, 35, 18, 133, 180, 231, 214,
100 122, 75, 24, 41, 190, 143, 220, 237,
101 195, 242, 161, 144, 7, 54, 101, 84,
102 57, 8, 91, 106, 253, 204, 159, 174,
103 128, 177, 226, 211, 68, 117, 38, 23,
104 252, 205, 158, 175, 56, 9, 90, 107,
105 69, 116, 39, 22, 129, 176, 227, 210,
106 191, 142, 221, 236, 123, 74, 25, 40,
107 6, 55, 100, 85, 194, 243, 160, 145,
108 71, 118, 37, 20, 131, 178, 225, 208,
109 254, 207, 156, 173, 58, 11, 88, 105,
110 4, 53, 102, 87, 192, 241, 162, 147,
111 189, 140, 223, 238, 121, 72, 27, 42,
112 193, 240, 163, 146, 5, 52, 103, 86,
113 120, 73, 26, 43, 188, 141, 222, 239,
114 130, 179, 224, 209, 70, 119, 36, 21,
115 59, 10, 89, 104, 255, 206, 157, 172
116};
117
81/** 118/**
82 * struct sht15_data - device instance specific data 119 * struct sht15_data - device instance specific data
83 * @pdata: platform data (gpio's etc). 120 * @pdata: platform data (gpio's etc).
@@ -86,6 +123,8 @@ static const struct sht15_temppair temppoints[] = {
86 * @val_temp: last temperature value read from device. 123 * @val_temp: last temperature value read from device.
87 * @val_humid: last humidity value read from device. 124 * @val_humid: last humidity value read from device.
88 * @val_status: last status register value read from device. 125 * @val_status: last status register value read from device.
126 * @checksum_ok: last value read from the device passed CRC validation.
127 * @checksumming: flag used to enable the data validation with CRC.
89 * @state: state identifying the action the driver is doing. 128 * @state: state identifying the action the driver is doing.
90 * @measurements_valid: are the current stored measures valid (start condition). 129 * @measurements_valid: are the current stored measures valid (start condition).
91 * @status_valid: is the current stored status valid (start condition). 130 * @status_valid: is the current stored status valid (start condition).
@@ -112,6 +151,8 @@ struct sht15_data {
112 uint16_t val_temp; 151 uint16_t val_temp;
113 uint16_t val_humid; 152 uint16_t val_humid;
114 u8 val_status; 153 u8 val_status;
154 bool checksum_ok;
155 bool checksumming;
115 enum sht15_state state; 156 enum sht15_state state;
116 bool measurements_valid; 157 bool measurements_valid;
117 bool status_valid; 158 bool status_valid;
@@ -129,6 +170,40 @@ struct sht15_data {
129}; 170};
130 171
131/** 172/**
173 * sht15_reverse() - reverse a byte
174 * @byte: byte to reverse.
175 */
176static u8 sht15_reverse(u8 byte)
177{
178 u8 i, c;
179
180 for (c = 0, i = 0; i < 8; i++)
181 c |= (!!(byte & (1 << i))) << (7 - i);
182 return c;
183}
184
185/**
186 * sht15_crc8() - compute crc8
187 * @data: sht15 specific data.
188 * @value: sht15 retrieved data.
189 *
190 * This implements section 2 of the CRC datasheet.
191 */
192static u8 sht15_crc8(struct sht15_data *data,
193 const u8 *value,
194 int len)
195{
196 u8 crc = sht15_reverse(data->val_status & 0x0F);
197
198 while (len--) {
199 crc = sht15_crc8_table[*value ^ crc];
200 value++;
201 }
202
203 return crc;
204}
205
206/**
132 * sht15_connection_reset() - reset the comms interface 207 * sht15_connection_reset() - reset the comms interface
133 * @data: sht15 specific data 208 * @data: sht15 specific data
134 * 209 *
@@ -268,6 +343,26 @@ static int sht15_soft_reset(struct sht15_data *data)
268} 343}
269 344
270/** 345/**
346 * sht15_ack() - send a ack
347 * @data: sht15 specific data.
348 *
349 * Each byte of data is acknowledged by pulling the data line
350 * low for one clock pulse.
351 */
352static void sht15_ack(struct sht15_data *data)
353{
354 gpio_direction_output(data->pdata->gpio_data, 0);
355 ndelay(SHT15_TSU);
356 gpio_set_value(data->pdata->gpio_sck, 1);
357 ndelay(SHT15_TSU);
358 gpio_set_value(data->pdata->gpio_sck, 0);
359 ndelay(SHT15_TSU);
360 gpio_set_value(data->pdata->gpio_data, 1);
361
362 gpio_direction_input(data->pdata->gpio_data);
363}
364
365/**
271 * sht15_end_transmission() - notify device of end of transmission 366 * sht15_end_transmission() - notify device of end of transmission
272 * @data: device state. 367 * @data: device state.
273 * 368 *
@@ -338,6 +433,9 @@ static int sht15_update_status(struct sht15_data *data)
338{ 433{
339 int ret = 0; 434 int ret = 0;
340 u8 status; 435 u8 status;
436 u8 previous_config;
437 u8 dev_checksum = 0;
438 u8 checksum_vals[2];
341 int timeout = HZ; 439 int timeout = HZ;
342 440
343 mutex_lock(&data->read_lock); 441 mutex_lock(&data->read_lock);
@@ -348,8 +446,40 @@ static int sht15_update_status(struct sht15_data *data)
348 goto error_ret; 446 goto error_ret;
349 status = sht15_read_byte(data); 447 status = sht15_read_byte(data);
350 448
449 if (data->checksumming) {
450 sht15_ack(data);
451 dev_checksum = sht15_reverse(sht15_read_byte(data));
452 checksum_vals[0] = SHT15_READ_STATUS;
453 checksum_vals[1] = status;
454 data->checksum_ok = (sht15_crc8(data, checksum_vals, 2)
455 == dev_checksum);
456 }
457
351 sht15_end_transmission(data); 458 sht15_end_transmission(data);
352 459
460 /*
461 * Perform checksum validation on the received data.
462 * Specification mentions that in case a checksum verification
463 * fails, a soft reset command must be sent to the device.
464 */
465 if (data->checksumming && !data->checksum_ok) {
466 previous_config = data->val_status & 0x07;
467 ret = sht15_soft_reset(data);
468 if (ret)
469 goto error_ret;
470 if (previous_config) {
471 ret = sht15_send_status(data, previous_config);
472 if (ret) {
473 dev_err(data->dev,
474 "CRC validation failed, unable "
475 "to restore device settings\n");
476 goto error_ret;
477 }
478 }
479 ret = -EAGAIN;
480 goto error_ret;
481 }
482
353 data->val_status = status; 483 data->val_status = status;
354 data->status_valid = true; 484 data->status_valid = true;
355 data->last_status = jiffies; 485 data->last_status = jiffies;
@@ -372,6 +502,7 @@ static int sht15_measurement(struct sht15_data *data,
372 int timeout_msecs) 502 int timeout_msecs)
373{ 503{
374 int ret; 504 int ret;
505 u8 previous_config;
375 506
376 ret = sht15_send_cmd(data, command); 507 ret = sht15_send_cmd(data, command);
377 if (ret) 508 if (ret)
@@ -395,6 +526,29 @@ static int sht15_measurement(struct sht15_data *data,
395 sht15_connection_reset(data); 526 sht15_connection_reset(data);
396 return -ETIME; 527 return -ETIME;
397 } 528 }
529
530 /*
531 * Perform checksum validation on the received data.
532 * Specification mentions that in case a checksum verification fails,
533 * a soft reset command must be sent to the device.
534 */
535 if (data->checksumming && !data->checksum_ok) {
536 previous_config = data->val_status & 0x07;
537 ret = sht15_soft_reset(data);
538 if (ret)
539 return ret;
540 if (previous_config) {
541 ret = sht15_send_status(data, previous_config);
542 if (ret) {
543 dev_err(data->dev,
544 "CRC validation failed, unable "
545 "to restore device settings\n");
546 return ret;
547 }
548 }
549 return -EAGAIN;
550 }
551
398 return 0; 552 return 0;
399} 553}
400 554
@@ -635,28 +789,11 @@ static irqreturn_t sht15_interrupt_fired(int irq, void *d)
635 return IRQ_HANDLED; 789 return IRQ_HANDLED;
636} 790}
637 791
638/**
639 * sht15_ack() - Send an ack to the device
640 *
641 * Each byte of data is acknowledged by pulling the data line
642 * low for one clock pulse.
643 */
644static void sht15_ack(struct sht15_data *data)
645{
646 gpio_direction_output(data->pdata->gpio_data, 0);
647 ndelay(SHT15_TSU);
648 gpio_set_value(data->pdata->gpio_sck, 1);
649 ndelay(SHT15_TSU);
650 gpio_set_value(data->pdata->gpio_sck, 0);
651 ndelay(SHT15_TSU);
652 gpio_set_value(data->pdata->gpio_data, 1);
653
654 gpio_direction_input(data->pdata->gpio_data);
655}
656
657static void sht15_bh_read_data(struct work_struct *work_s) 792static void sht15_bh_read_data(struct work_struct *work_s)
658{ 793{
659 uint16_t val = 0; 794 uint16_t val = 0;
795 u8 dev_checksum = 0;
796 u8 checksum_vals[3];
660 struct sht15_data *data 797 struct sht15_data *data
661 = container_of(work_s, struct sht15_data, 798 = container_of(work_s, struct sht15_data,
662 read_work); 799 read_work);
@@ -681,6 +818,21 @@ static void sht15_bh_read_data(struct work_struct *work_s)
681 sht15_ack(data); 818 sht15_ack(data);
682 val |= sht15_read_byte(data); 819 val |= sht15_read_byte(data);
683 820
821 if (data->checksumming) {
822 /*
823 * Ask the device for a checksum and read it back.
824 * Note: the device sends the checksum byte reversed.
825 */
826 sht15_ack(data);
827 dev_checksum = sht15_reverse(sht15_read_byte(data));
828 checksum_vals[0] = (data->state == SHT15_READING_TEMP) ?
829 SHT15_MEASURE_TEMP : SHT15_MEASURE_RH;
830 checksum_vals[1] = (u8) (val >> 8);
831 checksum_vals[2] = (u8) val;
832 data->checksum_ok
833 = (sht15_crc8(data, checksum_vals, 3) == dev_checksum);
834 }
835
684 /* Tell the device we are done */ 836 /* Tell the device we are done */
685 sht15_end_transmission(data); 837 sht15_end_transmission(data);
686 838
@@ -754,6 +906,8 @@ static int __devinit sht15_probe(struct platform_device *pdev)
754 } 906 }
755 data->pdata = pdev->dev.platform_data; 907 data->pdata = pdev->dev.platform_data;
756 data->supply_uV = data->pdata->supply_mv * 1000; 908 data->supply_uV = data->pdata->supply_mv * 1000;
909 if (data->pdata->checksum)
910 data->checksumming = true;
757 if (data->pdata->no_otp_reload) 911 if (data->pdata->no_otp_reload)
758 status |= SHT15_STATUS_NO_OTP_RELOAD; 912 status |= SHT15_STATUS_NO_OTP_RELOAD;
759 if (data->pdata->low_resolution) 913 if (data->pdata->low_resolution)