.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
---|
1 | 2 | /* |
---|
2 | 3 | * AD7280A Lithium Ion Battery Monitoring System |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright 2011 Analog Devices Inc. |
---|
5 | | - * |
---|
6 | | - * Licensed under the GPL-2. |
---|
7 | 6 | */ |
---|
8 | 7 | |
---|
| 8 | +#include <linux/crc8.h> |
---|
9 | 9 | #include <linux/device.h> |
---|
10 | 10 | #include <linux/kernel.h> |
---|
11 | 11 | #include <linux/slab.h> |
---|
.. | .. |
---|
96 | 96 | #define AD7280A_NUM_CH (AD7280A_AUX_ADC_6 - \ |
---|
97 | 97 | AD7280A_CELL_VOLTAGE_1 + 1) |
---|
98 | 98 | |
---|
| 99 | +#define AD7280A_CALC_VOLTAGE_CHAN_NUM(d, c) (((d) * AD7280A_CELLS_PER_DEV) + \ |
---|
| 100 | + (c)) |
---|
| 101 | +#define AD7280A_CALC_TEMP_CHAN_NUM(d, c) (((d) * AD7280A_CELLS_PER_DEV) + \ |
---|
| 102 | + (c) - AD7280A_CELLS_PER_DEV) |
---|
| 103 | + |
---|
99 | 104 | #define AD7280A_DEVADDR_MASTER 0 |
---|
100 | 105 | #define AD7280A_DEVADDR_ALL 0x1F |
---|
101 | 106 | /* 5-bit device address is sent LSB first */ |
---|
102 | 107 | static unsigned int ad7280a_devaddr(unsigned int addr) |
---|
103 | 108 | { |
---|
104 | 109 | return ((addr & 0x1) << 4) | |
---|
105 | | - ((addr & 0x2) << 3) | |
---|
| 110 | + ((addr & 0x2) << 2) | |
---|
106 | 111 | (addr & 0x4) | |
---|
107 | | - ((addr & 0x8) >> 3) | |
---|
| 112 | + ((addr & 0x8) >> 2) | |
---|
108 | 113 | ((addr & 0x10) >> 4); |
---|
109 | 114 | } |
---|
110 | 115 | |
---|
.. | .. |
---|
121 | 126 | * P(x) = x^8 + x^5 + x^3 + x^2 + x^1 + x^0 = 0b100101111 => 0x2F |
---|
122 | 127 | */ |
---|
123 | 128 | #define POLYNOM 0x2F |
---|
124 | | -#define POLYNOM_ORDER 8 |
---|
125 | | -#define HIGHBIT (1 << (POLYNOM_ORDER - 1)) |
---|
126 | 129 | |
---|
127 | 130 | struct ad7280_state { |
---|
128 | 131 | struct spi_device *spi; |
---|
.. | .. |
---|
131 | 134 | int slave_num; |
---|
132 | 135 | int scan_cnt; |
---|
133 | 136 | int readback_delay_us; |
---|
134 | | - unsigned char crc_tab[256]; |
---|
| 137 | + unsigned char crc_tab[CRC8_TABLE_SIZE]; |
---|
135 | 138 | unsigned char ctrl_hb; |
---|
136 | 139 | unsigned char ctrl_lb; |
---|
137 | 140 | unsigned char cell_threshhigh; |
---|
.. | .. |
---|
143 | 146 | |
---|
144 | 147 | __be32 buf[2] ____cacheline_aligned; |
---|
145 | 148 | }; |
---|
146 | | - |
---|
147 | | -static void ad7280_crc8_build_table(unsigned char *crc_tab) |
---|
148 | | -{ |
---|
149 | | - unsigned char bit, crc; |
---|
150 | | - int cnt, i; |
---|
151 | | - |
---|
152 | | - for (cnt = 0; cnt < 256; cnt++) { |
---|
153 | | - crc = cnt; |
---|
154 | | - for (i = 0; i < 8; i++) { |
---|
155 | | - bit = crc & HIGHBIT; |
---|
156 | | - crc <<= 1; |
---|
157 | | - if (bit) |
---|
158 | | - crc ^= POLYNOM; |
---|
159 | | - } |
---|
160 | | - crc_tab[cnt] = crc; |
---|
161 | | - } |
---|
162 | | -} |
---|
163 | 149 | |
---|
164 | 150 | static unsigned char ad7280_calc_crc8(unsigned char *crc_tab, unsigned int val) |
---|
165 | 151 | { |
---|
.. | .. |
---|
348 | 334 | return sum; |
---|
349 | 335 | } |
---|
350 | 336 | |
---|
| 337 | +static void ad7280_sw_power_down(void *data) |
---|
| 338 | +{ |
---|
| 339 | + struct ad7280_state *st = data; |
---|
| 340 | + |
---|
| 341 | + ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CONTROL_HB, 1, |
---|
| 342 | + AD7280A_CTRL_HB_PWRDN_SW | st->ctrl_hb); |
---|
| 343 | +} |
---|
| 344 | + |
---|
351 | 345 | static int ad7280_chain_setup(struct ad7280_state *st) |
---|
352 | 346 | { |
---|
353 | 347 | unsigned int val, n; |
---|
.. | .. |
---|
368 | 362 | AD7280A_CTRL_LB_MUST_SET | |
---|
369 | 363 | st->ctrl_lb); |
---|
370 | 364 | if (ret) |
---|
371 | | - return ret; |
---|
| 365 | + goto error_power_down; |
---|
372 | 366 | |
---|
373 | 367 | ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_READ, 1, |
---|
374 | 368 | AD7280A_CONTROL_LB << 2); |
---|
375 | 369 | if (ret) |
---|
376 | | - return ret; |
---|
| 370 | + goto error_power_down; |
---|
377 | 371 | |
---|
378 | 372 | for (n = 0; n <= AD7280A_MAX_CHAIN; n++) { |
---|
379 | 373 | ret = __ad7280_read32(st, &val); |
---|
380 | 374 | if (ret) |
---|
381 | | - return ret; |
---|
| 375 | + goto error_power_down; |
---|
382 | 376 | |
---|
383 | 377 | if (val == 0) |
---|
384 | 378 | return n - 1; |
---|
385 | 379 | |
---|
386 | | - if (ad7280_check_crc(st, val)) |
---|
387 | | - return -EIO; |
---|
| 380 | + if (ad7280_check_crc(st, val)) { |
---|
| 381 | + ret = -EIO; |
---|
| 382 | + goto error_power_down; |
---|
| 383 | + } |
---|
388 | 384 | |
---|
389 | | - if (n != ad7280a_devaddr(val >> 27)) |
---|
390 | | - return -EIO; |
---|
| 385 | + if (n != ad7280a_devaddr(val >> 27)) { |
---|
| 386 | + ret = -EIO; |
---|
| 387 | + goto error_power_down; |
---|
| 388 | + } |
---|
391 | 389 | } |
---|
| 390 | + ret = -EFAULT; |
---|
392 | 391 | |
---|
393 | | - return -EFAULT; |
---|
| 392 | +error_power_down: |
---|
| 393 | + ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CONTROL_HB, 1, |
---|
| 394 | + AD7280A_CTRL_HB_PWRDN_SW | st->ctrl_hb); |
---|
| 395 | + |
---|
| 396 | + return ret; |
---|
394 | 397 | } |
---|
395 | 398 | |
---|
396 | 399 | static ssize_t ad7280_show_balance_sw(struct device *dev, |
---|
.. | .. |
---|
497 | 500 | .attrs = ad7280_attributes, |
---|
498 | 501 | }; |
---|
499 | 502 | |
---|
| 503 | +static void ad7280_voltage_channel_init(struct iio_chan_spec *chan, int i) |
---|
| 504 | +{ |
---|
| 505 | + chan->type = IIO_VOLTAGE; |
---|
| 506 | + chan->differential = 1; |
---|
| 507 | + chan->channel = i; |
---|
| 508 | + chan->channel2 = chan->channel + 1; |
---|
| 509 | +} |
---|
| 510 | + |
---|
| 511 | +static void ad7280_temp_channel_init(struct iio_chan_spec *chan, int i) |
---|
| 512 | +{ |
---|
| 513 | + chan->type = IIO_TEMP; |
---|
| 514 | + chan->channel = i; |
---|
| 515 | +} |
---|
| 516 | + |
---|
| 517 | +static void ad7280_common_fields_init(struct iio_chan_spec *chan, int addr, |
---|
| 518 | + int cnt) |
---|
| 519 | +{ |
---|
| 520 | + chan->indexed = 1; |
---|
| 521 | + chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW); |
---|
| 522 | + chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE); |
---|
| 523 | + chan->address = addr; |
---|
| 524 | + chan->scan_index = cnt; |
---|
| 525 | + chan->scan_type.sign = 'u'; |
---|
| 526 | + chan->scan_type.realbits = 12; |
---|
| 527 | + chan->scan_type.storagebits = 32; |
---|
| 528 | +} |
---|
| 529 | + |
---|
| 530 | +static void ad7280_total_voltage_channel_init(struct iio_chan_spec *chan, |
---|
| 531 | + int cnt, int dev) |
---|
| 532 | +{ |
---|
| 533 | + chan->type = IIO_VOLTAGE; |
---|
| 534 | + chan->differential = 1; |
---|
| 535 | + chan->channel = 0; |
---|
| 536 | + chan->channel2 = dev * AD7280A_CELLS_PER_DEV; |
---|
| 537 | + chan->address = AD7280A_ALL_CELLS; |
---|
| 538 | + chan->indexed = 1; |
---|
| 539 | + chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW); |
---|
| 540 | + chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE); |
---|
| 541 | + chan->scan_index = cnt; |
---|
| 542 | + chan->scan_type.sign = 'u'; |
---|
| 543 | + chan->scan_type.realbits = 32; |
---|
| 544 | + chan->scan_type.storagebits = 32; |
---|
| 545 | +} |
---|
| 546 | + |
---|
| 547 | +static void ad7280_timestamp_channel_init(struct iio_chan_spec *chan, int cnt) |
---|
| 548 | +{ |
---|
| 549 | + chan->type = IIO_TIMESTAMP; |
---|
| 550 | + chan->channel = -1; |
---|
| 551 | + chan->scan_index = cnt; |
---|
| 552 | + chan->scan_type.sign = 's'; |
---|
| 553 | + chan->scan_type.realbits = 64; |
---|
| 554 | + chan->scan_type.storagebits = 64; |
---|
| 555 | +} |
---|
| 556 | + |
---|
| 557 | +static void ad7280_init_dev_channels(struct ad7280_state *st, int dev, int *cnt) |
---|
| 558 | +{ |
---|
| 559 | + int addr, ch, i; |
---|
| 560 | + struct iio_chan_spec *chan; |
---|
| 561 | + |
---|
| 562 | + for (ch = AD7280A_CELL_VOLTAGE_1; ch <= AD7280A_AUX_ADC_6; ch++) { |
---|
| 563 | + chan = &st->channels[*cnt]; |
---|
| 564 | + |
---|
| 565 | + if (ch < AD7280A_AUX_ADC_1) { |
---|
| 566 | + i = AD7280A_CALC_VOLTAGE_CHAN_NUM(dev, ch); |
---|
| 567 | + ad7280_voltage_channel_init(chan, i); |
---|
| 568 | + } else { |
---|
| 569 | + i = AD7280A_CALC_TEMP_CHAN_NUM(dev, ch); |
---|
| 570 | + ad7280_temp_channel_init(chan, i); |
---|
| 571 | + } |
---|
| 572 | + |
---|
| 573 | + addr = ad7280a_devaddr(dev) << 8 | ch; |
---|
| 574 | + ad7280_common_fields_init(chan, addr, *cnt); |
---|
| 575 | + |
---|
| 576 | + (*cnt)++; |
---|
| 577 | + } |
---|
| 578 | +} |
---|
| 579 | + |
---|
500 | 580 | static int ad7280_channel_init(struct ad7280_state *st) |
---|
501 | 581 | { |
---|
502 | | - int dev, ch, cnt; |
---|
| 582 | + int dev, cnt = 0; |
---|
503 | 583 | |
---|
504 | | - st->channels = kcalloc((st->slave_num + 1) * 12 + 2, |
---|
505 | | - sizeof(*st->channels), GFP_KERNEL); |
---|
| 584 | + st->channels = devm_kcalloc(&st->spi->dev, (st->slave_num + 1) * 12 + 2, |
---|
| 585 | + sizeof(*st->channels), GFP_KERNEL); |
---|
506 | 586 | if (!st->channels) |
---|
507 | 587 | return -ENOMEM; |
---|
508 | 588 | |
---|
509 | | - for (dev = 0, cnt = 0; dev <= st->slave_num; dev++) |
---|
510 | | - for (ch = AD7280A_CELL_VOLTAGE_1; ch <= AD7280A_AUX_ADC_6; |
---|
511 | | - ch++, cnt++) { |
---|
512 | | - if (ch < AD7280A_AUX_ADC_1) { |
---|
513 | | - st->channels[cnt].type = IIO_VOLTAGE; |
---|
514 | | - st->channels[cnt].differential = 1; |
---|
515 | | - st->channels[cnt].channel = (dev * 6) + ch; |
---|
516 | | - st->channels[cnt].channel2 = |
---|
517 | | - st->channels[cnt].channel + 1; |
---|
518 | | - } else { |
---|
519 | | - st->channels[cnt].type = IIO_TEMP; |
---|
520 | | - st->channels[cnt].channel = (dev * 6) + ch - 6; |
---|
521 | | - } |
---|
522 | | - st->channels[cnt].indexed = 1; |
---|
523 | | - st->channels[cnt].info_mask_separate = |
---|
524 | | - BIT(IIO_CHAN_INFO_RAW); |
---|
525 | | - st->channels[cnt].info_mask_shared_by_type = |
---|
526 | | - BIT(IIO_CHAN_INFO_SCALE); |
---|
527 | | - st->channels[cnt].address = |
---|
528 | | - ad7280a_devaddr(dev) << 8 | ch; |
---|
529 | | - st->channels[cnt].scan_index = cnt; |
---|
530 | | - st->channels[cnt].scan_type.sign = 'u'; |
---|
531 | | - st->channels[cnt].scan_type.realbits = 12; |
---|
532 | | - st->channels[cnt].scan_type.storagebits = 32; |
---|
533 | | - st->channels[cnt].scan_type.shift = 0; |
---|
534 | | - } |
---|
| 589 | + for (dev = 0; dev <= st->slave_num; dev++) |
---|
| 590 | + ad7280_init_dev_channels(st, dev, &cnt); |
---|
535 | 591 | |
---|
536 | | - st->channels[cnt].type = IIO_VOLTAGE; |
---|
537 | | - st->channels[cnt].differential = 1; |
---|
538 | | - st->channels[cnt].channel = 0; |
---|
539 | | - st->channels[cnt].channel2 = dev * 6; |
---|
540 | | - st->channels[cnt].address = AD7280A_ALL_CELLS; |
---|
541 | | - st->channels[cnt].indexed = 1; |
---|
542 | | - st->channels[cnt].info_mask_separate = BIT(IIO_CHAN_INFO_RAW); |
---|
543 | | - st->channels[cnt].info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE); |
---|
544 | | - st->channels[cnt].scan_index = cnt; |
---|
545 | | - st->channels[cnt].scan_type.sign = 'u'; |
---|
546 | | - st->channels[cnt].scan_type.realbits = 32; |
---|
547 | | - st->channels[cnt].scan_type.storagebits = 32; |
---|
548 | | - st->channels[cnt].scan_type.shift = 0; |
---|
| 592 | + ad7280_total_voltage_channel_init(&st->channels[cnt], cnt, dev); |
---|
549 | 593 | cnt++; |
---|
550 | | - st->channels[cnt].type = IIO_TIMESTAMP; |
---|
551 | | - st->channels[cnt].channel = -1; |
---|
552 | | - st->channels[cnt].scan_index = cnt; |
---|
553 | | - st->channels[cnt].scan_type.sign = 's'; |
---|
554 | | - st->channels[cnt].scan_type.realbits = 64; |
---|
555 | | - st->channels[cnt].scan_type.storagebits = 64; |
---|
556 | | - st->channels[cnt].scan_type.shift = 0; |
---|
| 594 | + ad7280_timestamp_channel_init(&st->channels[cnt], cnt); |
---|
557 | 595 | |
---|
558 | 596 | return cnt + 1; |
---|
559 | 597 | } |
---|
560 | 598 | |
---|
| 599 | +static int ad7280_balance_switch_attr_init(struct iio_dev_attr *attr, |
---|
| 600 | + struct device *dev, int addr, int i) |
---|
| 601 | +{ |
---|
| 602 | + attr->address = addr; |
---|
| 603 | + attr->dev_attr.attr.mode = 0644; |
---|
| 604 | + attr->dev_attr.show = ad7280_show_balance_sw; |
---|
| 605 | + attr->dev_attr.store = ad7280_store_balance_sw; |
---|
| 606 | + attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL, |
---|
| 607 | + "in%d-in%d_balance_switch_en", |
---|
| 608 | + i, i + 1); |
---|
| 609 | + if (!attr->dev_attr.attr.name) |
---|
| 610 | + return -ENOMEM; |
---|
| 611 | + |
---|
| 612 | + return 0; |
---|
| 613 | +} |
---|
| 614 | + |
---|
| 615 | +static int ad7280_balance_timer_attr_init(struct iio_dev_attr *attr, |
---|
| 616 | + struct device *dev, int addr, int i) |
---|
| 617 | +{ |
---|
| 618 | + attr->address = addr; |
---|
| 619 | + attr->dev_attr.attr.mode = 0644; |
---|
| 620 | + attr->dev_attr.show = ad7280_show_balance_timer; |
---|
| 621 | + attr->dev_attr.store = ad7280_store_balance_timer; |
---|
| 622 | + attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL, |
---|
| 623 | + "in%d-in%d_balance_timer", |
---|
| 624 | + i, i + 1); |
---|
| 625 | + if (!attr->dev_attr.attr.name) |
---|
| 626 | + return -ENOMEM; |
---|
| 627 | + |
---|
| 628 | + return 0; |
---|
| 629 | +} |
---|
| 630 | + |
---|
| 631 | +static int ad7280_init_dev_attrs(struct ad7280_state *st, int dev, int *cnt) |
---|
| 632 | +{ |
---|
| 633 | + int addr, ch, i, ret; |
---|
| 634 | + struct iio_dev_attr *iio_attr; |
---|
| 635 | + struct device *sdev = &st->spi->dev; |
---|
| 636 | + |
---|
| 637 | + for (ch = AD7280A_CELL_VOLTAGE_1; ch <= AD7280A_CELL_VOLTAGE_6; ch++) { |
---|
| 638 | + iio_attr = &st->iio_attr[*cnt]; |
---|
| 639 | + addr = ad7280a_devaddr(dev) << 8 | ch; |
---|
| 640 | + i = dev * AD7280A_CELLS_PER_DEV + ch; |
---|
| 641 | + |
---|
| 642 | + ret = ad7280_balance_switch_attr_init(iio_attr, sdev, addr, i); |
---|
| 643 | + if (ret < 0) |
---|
| 644 | + return ret; |
---|
| 645 | + |
---|
| 646 | + ad7280_attributes[*cnt] = &iio_attr->dev_attr.attr; |
---|
| 647 | + |
---|
| 648 | + (*cnt)++; |
---|
| 649 | + iio_attr = &st->iio_attr[*cnt]; |
---|
| 650 | + addr = ad7280a_devaddr(dev) << 8 | (AD7280A_CB1_TIMER + ch); |
---|
| 651 | + |
---|
| 652 | + ret = ad7280_balance_timer_attr_init(iio_attr, sdev, addr, i); |
---|
| 653 | + if (ret < 0) |
---|
| 654 | + return ret; |
---|
| 655 | + |
---|
| 656 | + ad7280_attributes[*cnt] = &iio_attr->dev_attr.attr; |
---|
| 657 | + (*cnt)++; |
---|
| 658 | + } |
---|
| 659 | + |
---|
| 660 | + ad7280_attributes[*cnt] = NULL; |
---|
| 661 | + |
---|
| 662 | + return 0; |
---|
| 663 | +} |
---|
| 664 | + |
---|
561 | 665 | static int ad7280_attr_init(struct ad7280_state *st) |
---|
562 | 666 | { |
---|
563 | | - int dev, ch, cnt; |
---|
| 667 | + int dev, cnt = 0, ret; |
---|
564 | 668 | |
---|
565 | | - st->iio_attr = kcalloc(2, sizeof(*st->iio_attr) * |
---|
566 | | - (st->slave_num + 1) * AD7280A_CELLS_PER_DEV, |
---|
567 | | - GFP_KERNEL); |
---|
| 669 | + st->iio_attr = devm_kcalloc(&st->spi->dev, 2, sizeof(*st->iio_attr) * |
---|
| 670 | + (st->slave_num + 1) * AD7280A_CELLS_PER_DEV, |
---|
| 671 | + GFP_KERNEL); |
---|
568 | 672 | if (!st->iio_attr) |
---|
569 | 673 | return -ENOMEM; |
---|
570 | 674 | |
---|
571 | | - for (dev = 0, cnt = 0; dev <= st->slave_num; dev++) |
---|
572 | | - for (ch = AD7280A_CELL_VOLTAGE_1; ch <= AD7280A_CELL_VOLTAGE_6; |
---|
573 | | - ch++, cnt++) { |
---|
574 | | - st->iio_attr[cnt].address = |
---|
575 | | - ad7280a_devaddr(dev) << 8 | ch; |
---|
576 | | - st->iio_attr[cnt].dev_attr.attr.mode = |
---|
577 | | - 0644; |
---|
578 | | - st->iio_attr[cnt].dev_attr.show = |
---|
579 | | - ad7280_show_balance_sw; |
---|
580 | | - st->iio_attr[cnt].dev_attr.store = |
---|
581 | | - ad7280_store_balance_sw; |
---|
582 | | - st->iio_attr[cnt].dev_attr.attr.name = |
---|
583 | | - kasprintf(GFP_KERNEL, |
---|
584 | | - "in%d-in%d_balance_switch_en", |
---|
585 | | - dev * AD7280A_CELLS_PER_DEV + ch, |
---|
586 | | - dev * AD7280A_CELLS_PER_DEV + ch + 1); |
---|
587 | | - ad7280_attributes[cnt] = |
---|
588 | | - &st->iio_attr[cnt].dev_attr.attr; |
---|
589 | | - cnt++; |
---|
590 | | - st->iio_attr[cnt].address = |
---|
591 | | - ad7280a_devaddr(dev) << 8 | |
---|
592 | | - (AD7280A_CB1_TIMER + ch); |
---|
593 | | - st->iio_attr[cnt].dev_attr.attr.mode = |
---|
594 | | - 0644; |
---|
595 | | - st->iio_attr[cnt].dev_attr.show = |
---|
596 | | - ad7280_show_balance_timer; |
---|
597 | | - st->iio_attr[cnt].dev_attr.store = |
---|
598 | | - ad7280_store_balance_timer; |
---|
599 | | - st->iio_attr[cnt].dev_attr.attr.name = |
---|
600 | | - kasprintf(GFP_KERNEL, |
---|
601 | | - "in%d-in%d_balance_timer", |
---|
602 | | - dev * AD7280A_CELLS_PER_DEV + ch, |
---|
603 | | - dev * AD7280A_CELLS_PER_DEV + ch + 1); |
---|
604 | | - ad7280_attributes[cnt] = |
---|
605 | | - &st->iio_attr[cnt].dev_attr.attr; |
---|
606 | | - } |
---|
607 | | - |
---|
608 | | - ad7280_attributes[cnt] = NULL; |
---|
| 675 | + for (dev = 0; dev <= st->slave_num; dev++) { |
---|
| 676 | + ret = ad7280_init_dev_attrs(st, dev, &cnt); |
---|
| 677 | + if (ret < 0) |
---|
| 678 | + return ret; |
---|
| 679 | + } |
---|
609 | 680 | |
---|
610 | 681 | return 0; |
---|
611 | 682 | } |
---|
.. | .. |
---|
619 | 690 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); |
---|
620 | 691 | unsigned int val; |
---|
621 | 692 | |
---|
622 | | - switch ((u32)this_attr->address) { |
---|
| 693 | + switch (this_attr->address) { |
---|
623 | 694 | case AD7280A_CELL_OVERVOLTAGE: |
---|
624 | 695 | val = 1000 + (st->cell_threshhigh * 1568) / 100; |
---|
625 | 696 | break; |
---|
.. | .. |
---|
655 | 726 | if (ret) |
---|
656 | 727 | return ret; |
---|
657 | 728 | |
---|
658 | | - switch ((u32)this_attr->address) { |
---|
| 729 | + switch (this_attr->address) { |
---|
659 | 730 | case AD7280A_CELL_OVERVOLTAGE: |
---|
660 | 731 | case AD7280A_CELL_UNDERVOLTAGE: |
---|
661 | 732 | val = ((val - 1000) * 100) / 1568; /* LSB 15.68mV */ |
---|
.. | .. |
---|
671 | 742 | val = clamp(val, 0L, 0xFFL); |
---|
672 | 743 | |
---|
673 | 744 | mutex_lock(&st->lock); |
---|
674 | | - switch ((u32)this_attr->address) { |
---|
| 745 | + switch (this_attr->address) { |
---|
675 | 746 | case AD7280A_CELL_OVERVOLTAGE: |
---|
676 | 747 | st->cell_threshhigh = val; |
---|
677 | 748 | break; |
---|
.. | .. |
---|
712 | 783 | for (i = 0; i < st->scan_cnt; i++) { |
---|
713 | 784 | if (((channels[i] >> 23) & 0xF) <= AD7280A_CELL_VOLTAGE_6) { |
---|
714 | 785 | if (((channels[i] >> 11) & 0xFFF) >= |
---|
715 | | - st->cell_threshhigh) |
---|
716 | | - iio_push_event(indio_dev, |
---|
717 | | - IIO_EVENT_CODE(IIO_VOLTAGE, |
---|
718 | | - 1, |
---|
719 | | - 0, |
---|
720 | | - IIO_EV_DIR_RISING, |
---|
721 | | - IIO_EV_TYPE_THRESH, |
---|
722 | | - 0, 0, 0), |
---|
| 786 | + st->cell_threshhigh) { |
---|
| 787 | + u64 tmp = IIO_EVENT_CODE(IIO_VOLTAGE, 1, 0, |
---|
| 788 | + IIO_EV_DIR_RISING, |
---|
| 789 | + IIO_EV_TYPE_THRESH, |
---|
| 790 | + 0, 0, 0); |
---|
| 791 | + iio_push_event(indio_dev, tmp, |
---|
723 | 792 | iio_get_time_ns(indio_dev)); |
---|
724 | | - else if (((channels[i] >> 11) & 0xFFF) <= |
---|
725 | | - st->cell_threshlow) |
---|
726 | | - iio_push_event(indio_dev, |
---|
727 | | - IIO_EVENT_CODE(IIO_VOLTAGE, |
---|
728 | | - 1, |
---|
729 | | - 0, |
---|
730 | | - IIO_EV_DIR_FALLING, |
---|
731 | | - IIO_EV_TYPE_THRESH, |
---|
732 | | - 0, 0, 0), |
---|
| 793 | + } else if (((channels[i] >> 11) & 0xFFF) <= |
---|
| 794 | + st->cell_threshlow) { |
---|
| 795 | + u64 tmp = IIO_EVENT_CODE(IIO_VOLTAGE, 1, 0, |
---|
| 796 | + IIO_EV_DIR_FALLING, |
---|
| 797 | + IIO_EV_TYPE_THRESH, |
---|
| 798 | + 0, 0, 0); |
---|
| 799 | + iio_push_event(indio_dev, tmp, |
---|
733 | 800 | iio_get_time_ns(indio_dev)); |
---|
| 801 | + } |
---|
734 | 802 | } else { |
---|
735 | | - if (((channels[i] >> 11) & 0xFFF) >= st->aux_threshhigh) |
---|
736 | | - iio_push_event(indio_dev, |
---|
737 | | - IIO_UNMOD_EVENT_CODE( |
---|
738 | | - IIO_TEMP, |
---|
739 | | - 0, |
---|
| 803 | + if (((channels[i] >> 11) & 0xFFF) >= |
---|
| 804 | + st->aux_threshhigh) { |
---|
| 805 | + u64 tmp = IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0, |
---|
740 | 806 | IIO_EV_TYPE_THRESH, |
---|
741 | | - IIO_EV_DIR_RISING), |
---|
| 807 | + IIO_EV_DIR_RISING); |
---|
| 808 | + iio_push_event(indio_dev, tmp, |
---|
742 | 809 | iio_get_time_ns(indio_dev)); |
---|
743 | | - else if (((channels[i] >> 11) & 0xFFF) <= |
---|
744 | | - st->aux_threshlow) |
---|
745 | | - iio_push_event(indio_dev, |
---|
746 | | - IIO_UNMOD_EVENT_CODE( |
---|
747 | | - IIO_TEMP, |
---|
748 | | - 0, |
---|
| 810 | + } else if (((channels[i] >> 11) & 0xFFF) <= |
---|
| 811 | + st->aux_threshlow) { |
---|
| 812 | + u64 tmp = IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0, |
---|
749 | 813 | IIO_EV_TYPE_THRESH, |
---|
750 | | - IIO_EV_DIR_FALLING), |
---|
| 814 | + IIO_EV_DIR_FALLING); |
---|
| 815 | + iio_push_event(indio_dev, tmp, |
---|
751 | 816 | iio_get_time_ns(indio_dev)); |
---|
| 817 | + } |
---|
752 | 818 | } |
---|
753 | 819 | } |
---|
754 | 820 | |
---|
.. | .. |
---|
758 | 824 | return IRQ_HANDLED; |
---|
759 | 825 | } |
---|
760 | 826 | |
---|
| 827 | +/* Note: No need to fix checkpatch warning that reads: |
---|
| 828 | + * CHECK: spaces preferred around that '-' (ctx:VxV) |
---|
| 829 | + * The function argument is stringified and doesn't need a fix |
---|
| 830 | + */ |
---|
761 | 831 | static IIO_DEVICE_ATTR_NAMED(in_thresh_low_value, |
---|
762 | | - in_voltage-voltage_thresh_low_value, |
---|
763 | | - 0644, |
---|
764 | | - ad7280_read_channel_config, |
---|
765 | | - ad7280_write_channel_config, |
---|
766 | | - AD7280A_CELL_UNDERVOLTAGE); |
---|
| 832 | + in_voltage-voltage_thresh_low_value, |
---|
| 833 | + 0644, |
---|
| 834 | + ad7280_read_channel_config, |
---|
| 835 | + ad7280_write_channel_config, |
---|
| 836 | + AD7280A_CELL_UNDERVOLTAGE); |
---|
767 | 837 | |
---|
768 | 838 | static IIO_DEVICE_ATTR_NAMED(in_thresh_high_value, |
---|
769 | | - in_voltage-voltage_thresh_high_value, |
---|
770 | | - 0644, |
---|
771 | | - ad7280_read_channel_config, |
---|
772 | | - ad7280_write_channel_config, |
---|
773 | | - AD7280A_CELL_OVERVOLTAGE); |
---|
| 839 | + in_voltage-voltage_thresh_high_value, |
---|
| 840 | + 0644, |
---|
| 841 | + ad7280_read_channel_config, |
---|
| 842 | + ad7280_write_channel_config, |
---|
| 843 | + AD7280A_CELL_OVERVOLTAGE); |
---|
774 | 844 | |
---|
775 | 845 | static IIO_DEVICE_ATTR(in_temp_thresh_low_value, |
---|
776 | | - 0644, |
---|
777 | | - ad7280_read_channel_config, |
---|
778 | | - ad7280_write_channel_config, |
---|
779 | | - AD7280A_AUX_ADC_UNDERVOLTAGE); |
---|
| 846 | + 0644, |
---|
| 847 | + ad7280_read_channel_config, |
---|
| 848 | + ad7280_write_channel_config, |
---|
| 849 | + AD7280A_AUX_ADC_UNDERVOLTAGE); |
---|
780 | 850 | |
---|
781 | 851 | static IIO_DEVICE_ATTR(in_temp_thresh_high_value, |
---|
782 | | - 0644, |
---|
783 | | - ad7280_read_channel_config, |
---|
784 | | - ad7280_write_channel_config, |
---|
785 | | - AD7280A_AUX_ADC_OVERVOLTAGE); |
---|
| 852 | + 0644, |
---|
| 853 | + ad7280_read_channel_config, |
---|
| 854 | + ad7280_write_channel_config, |
---|
| 855 | + AD7280A_AUX_ADC_OVERVOLTAGE); |
---|
786 | 856 | |
---|
787 | 857 | static struct attribute *ad7280_event_attributes[] = { |
---|
788 | 858 | &iio_dev_attr_in_thresh_low_value.dev_attr.attr, |
---|
.. | .. |
---|
850 | 920 | const struct ad7280_platform_data *pdata = dev_get_platdata(&spi->dev); |
---|
851 | 921 | struct ad7280_state *st; |
---|
852 | 922 | int ret; |
---|
853 | | - const unsigned short tACQ_ns[4] = {465, 1010, 1460, 1890}; |
---|
854 | | - const unsigned short nAVG[4] = {1, 2, 4, 8}; |
---|
| 923 | + const unsigned short t_acq_ns[4] = {465, 1010, 1460, 1890}; |
---|
| 924 | + const unsigned short n_avg[4] = {1, 2, 4, 8}; |
---|
855 | 925 | struct iio_dev *indio_dev; |
---|
856 | 926 | |
---|
857 | 927 | indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); |
---|
.. | .. |
---|
866 | 936 | if (!pdata) |
---|
867 | 937 | pdata = &ad7793_default_pdata; |
---|
868 | 938 | |
---|
869 | | - ad7280_crc8_build_table(st->crc_tab); |
---|
| 939 | + crc8_populate_msb(st->crc_tab, POLYNOM); |
---|
870 | 940 | |
---|
871 | 941 | st->spi->max_speed_hz = AD7280A_MAX_SPI_CLK_HZ; |
---|
872 | 942 | st->spi->mode = SPI_MODE_1; |
---|
.. | .. |
---|
886 | 956 | st->cell_threshhigh = 0xFF; |
---|
887 | 957 | st->aux_threshhigh = 0xFF; |
---|
888 | 958 | |
---|
| 959 | + ret = devm_add_action_or_reset(&spi->dev, ad7280_sw_power_down, st); |
---|
| 960 | + if (ret) |
---|
| 961 | + return ret; |
---|
| 962 | + |
---|
889 | 963 | /* |
---|
890 | 964 | * Total Conversion Time = ((tACQ + tCONV) * |
---|
891 | 965 | * (Number of Conversions per Part)) − |
---|
.. | .. |
---|
895 | 969 | */ |
---|
896 | 970 | |
---|
897 | 971 | st->readback_delay_us = |
---|
898 | | - ((tACQ_ns[pdata->acquisition_time & 0x3] + 695) * |
---|
899 | | - (AD7280A_NUM_CH * nAVG[pdata->conversion_averaging & 0x3])) |
---|
900 | | - - tACQ_ns[pdata->acquisition_time & 0x3] + |
---|
901 | | - st->slave_num * 250; |
---|
| 972 | + ((t_acq_ns[pdata->acquisition_time & 0x3] + 695) * |
---|
| 973 | + (AD7280A_NUM_CH * n_avg[pdata->conversion_averaging & 0x3])) - |
---|
| 974 | + t_acq_ns[pdata->acquisition_time & 0x3] + st->slave_num * 250; |
---|
902 | 975 | |
---|
903 | 976 | /* Convert to usecs */ |
---|
904 | 977 | st->readback_delay_us = DIV_ROUND_UP(st->readback_delay_us, 1000); |
---|
905 | 978 | st->readback_delay_us += 5; /* Add tWAIT */ |
---|
906 | 979 | |
---|
907 | 980 | indio_dev->name = spi_get_device_id(spi)->name; |
---|
908 | | - indio_dev->dev.parent = &spi->dev; |
---|
909 | 981 | indio_dev->modes = INDIO_DIRECT_MODE; |
---|
910 | 982 | |
---|
911 | 983 | ret = ad7280_channel_init(st); |
---|
.. | .. |
---|
918 | 990 | |
---|
919 | 991 | ret = ad7280_attr_init(st); |
---|
920 | 992 | if (ret < 0) |
---|
921 | | - goto error_free_channels; |
---|
| 993 | + return ret; |
---|
922 | 994 | |
---|
923 | | - ret = iio_device_register(indio_dev); |
---|
| 995 | + ret = devm_iio_device_register(&spi->dev, indio_dev); |
---|
924 | 996 | if (ret) |
---|
925 | | - goto error_free_attr; |
---|
| 997 | + return ret; |
---|
926 | 998 | |
---|
927 | 999 | if (spi->irq > 0) { |
---|
928 | 1000 | ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, |
---|
929 | 1001 | AD7280A_ALERT, 1, |
---|
930 | 1002 | AD7280A_ALERT_RELAY_SIG_CHAIN_DOWN); |
---|
931 | 1003 | if (ret) |
---|
932 | | - goto error_unregister; |
---|
| 1004 | + return ret; |
---|
933 | 1005 | |
---|
934 | 1006 | ret = ad7280_write(st, ad7280a_devaddr(st->slave_num), |
---|
935 | 1007 | AD7280A_ALERT, 0, |
---|
936 | 1008 | AD7280A_ALERT_GEN_STATIC_HIGH | |
---|
937 | 1009 | (pdata->chain_last_alert_ignore & 0xF)); |
---|
938 | 1010 | if (ret) |
---|
939 | | - goto error_unregister; |
---|
| 1011 | + return ret; |
---|
940 | 1012 | |
---|
941 | | - ret = request_threaded_irq(spi->irq, |
---|
942 | | - NULL, |
---|
943 | | - ad7280_event_handler, |
---|
944 | | - IRQF_TRIGGER_FALLING | |
---|
945 | | - IRQF_ONESHOT, |
---|
946 | | - indio_dev->name, |
---|
947 | | - indio_dev); |
---|
| 1013 | + ret = devm_request_threaded_irq(&spi->dev, spi->irq, |
---|
| 1014 | + NULL, |
---|
| 1015 | + ad7280_event_handler, |
---|
| 1016 | + IRQF_TRIGGER_FALLING | |
---|
| 1017 | + IRQF_ONESHOT, |
---|
| 1018 | + indio_dev->name, |
---|
| 1019 | + indio_dev); |
---|
948 | 1020 | if (ret) |
---|
949 | | - goto error_unregister; |
---|
| 1021 | + return ret; |
---|
950 | 1022 | } |
---|
951 | | - |
---|
952 | | - return 0; |
---|
953 | | -error_unregister: |
---|
954 | | - iio_device_unregister(indio_dev); |
---|
955 | | - |
---|
956 | | -error_free_attr: |
---|
957 | | - kfree(st->iio_attr); |
---|
958 | | - |
---|
959 | | -error_free_channels: |
---|
960 | | - kfree(st->channels); |
---|
961 | | - |
---|
962 | | - return ret; |
---|
963 | | -} |
---|
964 | | - |
---|
965 | | -static int ad7280_remove(struct spi_device *spi) |
---|
966 | | -{ |
---|
967 | | - struct iio_dev *indio_dev = spi_get_drvdata(spi); |
---|
968 | | - struct ad7280_state *st = iio_priv(indio_dev); |
---|
969 | | - |
---|
970 | | - if (spi->irq > 0) |
---|
971 | | - free_irq(spi->irq, indio_dev); |
---|
972 | | - iio_device_unregister(indio_dev); |
---|
973 | | - |
---|
974 | | - ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CONTROL_HB, 1, |
---|
975 | | - AD7280A_CTRL_HB_PWRDN_SW | st->ctrl_hb); |
---|
976 | | - |
---|
977 | | - kfree(st->channels); |
---|
978 | | - kfree(st->iio_attr); |
---|
979 | 1023 | |
---|
980 | 1024 | return 0; |
---|
981 | 1025 | } |
---|
.. | .. |
---|
991 | 1035 | .name = "ad7280", |
---|
992 | 1036 | }, |
---|
993 | 1037 | .probe = ad7280_probe, |
---|
994 | | - .remove = ad7280_remove, |
---|
995 | 1038 | .id_table = ad7280_id, |
---|
996 | 1039 | }; |
---|
997 | 1040 | module_spi_driver(ad7280_driver); |
---|
998 | 1041 | |
---|
999 | | -MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); |
---|
| 1042 | +MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>"); |
---|
1000 | 1043 | MODULE_DESCRIPTION("Analog Devices AD7280A"); |
---|
1001 | 1044 | MODULE_LICENSE("GPL v2"); |
---|