Lines Matching +full:temperature +full:- +full:lookup +full:- +full:table
1 // SPDX-License-Identifier: GPL-2.0-only
8 * Copyright (C) 2009-2010 Motorola, Inc.
27 #include <linux/mfd/motorola-cpcap.h>
86 * struct cpcap_adc_ato - timing settings for cpcap adc
103 * struct cpcap_adc - cpcap adc device driver data
125 * enum cpcap_adc_channel - cpcap adc channels
129 CPCAP_ADC_AD0, /* Battery temperature */
132 CPCAP_ADC_AD3, /* Die temperature when charging */
156 * enum cpcap_adc_timing - cpcap adc timing options
168 * struct cpcap_adc_phasing_tbl - cpcap phasing table
169 * @offset: offset in the phasing table
170 * @multiplier: multiplier in the phasing table
171 * @divider: divider in the phasing table
184 * struct cpcap_adc_conversion_tbl - cpcap conversion table
202 * struct cpcap_adc_request - cpcap adc request
204 * @phase_tbl: channel phasing table
205 * @conv_tbl: channel conversion table
219 /* Phasing table for channels. Note that channels 16 & 17 use BATTP and BATTI */
227 [CPCAP_ADC_CHG_ISENSE] = {0, 0x80, 0x80, -512, 511},
228 [CPCAP_ADC_BATTI] = {0, 0x80, 0x80, -512, 511},
243 * Conversion table for channels. Updated during init based on calibration.
264 IIO_CHAN_INFO_PROCESSED, -512, 2, 0, 5000, 1023,
267 IIO_CHAN_INFO_PROCESSED, -512, 2, 0, 5000, 1023,
301 * Temperature lookup table of register values to milliCelcius.
305 { 0x03ff, -40000 },
306 { 0x03ff, -35000 },
307 { 0x03ef, -30000 },
308 { 0x03b2, -25000 },
309 { 0x036c, -20000 },
310 { 0x0320, -15000 },
311 { 0x02d0, -10000 },
312 { 0x027f, -5000 },
388 error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2, in cpcap_adc_irq_thread()
394 ddata->done = true; in cpcap_adc_irq_thread()
395 wake_up_interruptible(&ddata->wq_data_avail); in cpcap_adc_irq_thread()
416 error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC1, in cpcap_adc_setup_calibrate()
427 error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2, in cpcap_adc_setup_calibrate()
435 error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2, in cpcap_adc_setup_calibrate()
441 error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2, in cpcap_adc_setup_calibrate()
449 error = regmap_read(ddata->reg, CPCAP_REG_ADCC2, &value); in cpcap_adc_setup_calibrate()
455 dev_err(ddata->dev, in cpcap_adc_setup_calibrate()
458 error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC1, in cpcap_adc_setup_calibrate()
479 error = regmap_read(ddata->reg, calibration_register, in cpcap_adc_calibrate_one()
484 error = regmap_read(ddata->reg, calibration_register, in cpcap_adc_calibrate_one()
491 calibration_data[0] - calibration_data[1]; in cpcap_adc_calibrate_one()
494 calibration_data[1] - calibration_data[0]; in cpcap_adc_calibrate_one()
499 (ddata->vendor == CPCAP_VENDOR_TI)) { in cpcap_adc_calibrate_one()
501 ((short)calibration_data[1] * -1) + 512; in cpcap_adc_calibrate_one()
502 dev_dbg(ddata->dev, "ch%i calibration complete: %i\n", in cpcap_adc_calibrate_one()
537 const struct cpcap_adc_ato *ato = ddata->ato; in cpcap_adc_setup_bank()
545 switch (req->channel) { in cpcap_adc_setup_bank()
548 error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2, in cpcap_adc_setup_bank()
565 switch (req->timing) { in cpcap_adc_setup_bank()
567 value1 |= ato->ato_in; in cpcap_adc_setup_bank()
568 value1 |= ato->atox_in; in cpcap_adc_setup_bank()
569 value2 |= ato->adc_ps_factor_in; in cpcap_adc_setup_bank()
570 value2 |= ato->atox_ps_factor_in; in cpcap_adc_setup_bank()
573 value1 |= ato->ato_out; in cpcap_adc_setup_bank()
574 value1 |= ato->atox_out; in cpcap_adc_setup_bank()
575 value2 |= ato->adc_ps_factor_out; in cpcap_adc_setup_bank()
576 value2 |= ato->atox_ps_factor_out; in cpcap_adc_setup_bank()
584 error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC1, in cpcap_adc_setup_bank()
595 error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2, in cpcap_adc_setup_bank()
604 if (req->timing == CPCAP_ADC_TIMING_IMM) { in cpcap_adc_setup_bank()
605 error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2, in cpcap_adc_setup_bank()
611 error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2, in cpcap_adc_setup_bank()
617 error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2, in cpcap_adc_setup_bank()
623 error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2, in cpcap_adc_setup_bank()
635 req->timing = CPCAP_ADC_TIMING_IMM; in cpcap_adc_start_bank()
636 ddata->done = false; in cpcap_adc_start_bank()
640 error = wait_event_interruptible_timeout(ddata->wq_data_avail, in cpcap_adc_start_bank()
641 ddata->done, in cpcap_adc_start_bank()
647 error = -ETIMEDOUT; in cpcap_adc_start_bank()
662 error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC1, in cpcap_adc_stop_bank()
668 return regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2, in cpcap_adc_stop_bank()
675 const struct cpcap_adc_conversion_tbl *conv_tbl = req->conv_tbl; in cpcap_adc_phase()
676 const struct cpcap_adc_phasing_tbl *phase_tbl = req->phase_tbl; in cpcap_adc_phase()
677 int index = req->channel; in cpcap_adc_phase()
680 switch (req->channel) { in cpcap_adc_phase()
683 index = req->bank_index; in cpcap_adc_phase()
684 req->result -= phase_tbl[index].offset; in cpcap_adc_phase()
685 req->result -= CPCAP_FOUR_POINT_TWO_ADC; in cpcap_adc_phase()
686 req->result *= phase_tbl[index].multiplier; in cpcap_adc_phase()
689 req->result /= phase_tbl[index].divider; in cpcap_adc_phase()
690 req->result += CPCAP_FOUR_POINT_TWO_ADC; in cpcap_adc_phase()
693 index = req->bank_index; in cpcap_adc_phase()
696 req->result += conv_tbl[index].cal_offset; in cpcap_adc_phase()
697 req->result += conv_tbl[index].align_offset; in cpcap_adc_phase()
698 req->result *= phase_tbl[index].multiplier; in cpcap_adc_phase()
701 req->result /= phase_tbl[index].divider; in cpcap_adc_phase()
702 req->result += phase_tbl[index].offset; in cpcap_adc_phase()
706 if (req->result < phase_tbl[index].min) in cpcap_adc_phase()
707 req->result = phase_tbl[index].min; in cpcap_adc_phase()
708 else if (req->result > phase_tbl[index].max) in cpcap_adc_phase()
709 req->result = phase_tbl[index].max; in cpcap_adc_phase()
712 /* Looks up temperatures in a table and calculates averages if needed */
717 if (value <= temp_map[CPCAP_MAX_TEMP_LVL - 1][0]) in cpcap_adc_table_to_millicelcius()
718 return temp_map[CPCAP_MAX_TEMP_LVL - 1][1]; in cpcap_adc_table_to_millicelcius()
723 for (i = 0; i < CPCAP_MAX_TEMP_LVL - 1; i++) { in cpcap_adc_table_to_millicelcius()
731 alpha = ((value - temp_map[i][0]) * 1000) / in cpcap_adc_table_to_millicelcius()
732 (temp_map[i + 1][0] - temp_map[i][0]); in cpcap_adc_table_to_millicelcius()
735 ((alpha * (temp_map[i + 1][1] - in cpcap_adc_table_to_millicelcius()
747 const struct cpcap_adc_conversion_tbl *conv_tbl = req->conv_tbl; in cpcap_adc_convert()
748 int index = req->channel; in cpcap_adc_convert()
751 switch (req->channel) { in cpcap_adc_convert()
766 /* Temperatures use a lookup table instead of conversion table */ in cpcap_adc_convert()
767 if ((req->channel == CPCAP_ADC_AD0) || in cpcap_adc_convert()
768 (req->channel == CPCAP_ADC_AD3)) { in cpcap_adc_convert()
769 req->result = in cpcap_adc_convert()
770 cpcap_adc_table_to_millicelcius(req->result); in cpcap_adc_convert()
775 /* All processed channels use a conversion table */ in cpcap_adc_convert()
776 req->result *= conv_tbl[index].multiplier; in cpcap_adc_convert()
779 req->result /= conv_tbl[index].divider; in cpcap_adc_convert()
780 req->result += conv_tbl[index].conv_offset; in cpcap_adc_convert()
792 if (ddata->vendor == CPCAP_VENDOR_TI) { in cpcap_adc_read_bank_scaled()
793 error = regmap_read(ddata->reg, CPCAP_REG_ADCAL1, in cpcap_adc_read_bank_scaled()
798 ((short)calibration_data * -1) + 512; in cpcap_adc_read_bank_scaled()
800 error = regmap_read(ddata->reg, CPCAP_REG_ADCAL2, in cpcap_adc_read_bank_scaled()
805 ((short)calibration_data * -1) + 512; in cpcap_adc_read_bank_scaled()
808 addr = CPCAP_REG_ADCD0 + req->bank_index * 4; in cpcap_adc_read_bank_scaled()
810 error = regmap_read(ddata->reg, addr, &req->result); in cpcap_adc_read_bank_scaled()
814 req->result &= 0x3ff; in cpcap_adc_read_bank_scaled()
824 req->channel = channel; in cpcap_adc_init_request()
825 req->phase_tbl = bank_phasing; in cpcap_adc_init_request()
826 req->conv_tbl = bank_conversion; in cpcap_adc_init_request()
830 req->bank_index = channel; in cpcap_adc_init_request()
833 req->bank_index = channel - 8; in cpcap_adc_init_request()
836 req->bank_index = CPCAP_ADC_BATTP; in cpcap_adc_init_request()
839 req->bank_index = CPCAP_ADC_BATTI; in cpcap_adc_init_request()
842 return -EINVAL; in cpcap_adc_init_request()
853 error = regmap_read(ddata->reg, addr, val); in cpcap_adc_read_st_die_temp()
857 *val -= 282; in cpcap_adc_read_st_die_temp()
872 error = cpcap_adc_init_request(&req, chan->channel); in cpcap_adc_read()
878 mutex_lock(&ddata->lock); in cpcap_adc_read()
882 error = regmap_read(ddata->reg, chan->address, val); in cpcap_adc_read()
888 mutex_unlock(&ddata->lock); in cpcap_adc_read()
891 mutex_lock(&ddata->lock); in cpcap_adc_read()
895 if ((ddata->vendor == CPCAP_VENDOR_ST) && in cpcap_adc_read()
896 (chan->channel == CPCAP_ADC_AD3)) { in cpcap_adc_read()
898 chan->address, in cpcap_adc_read()
910 mutex_unlock(&ddata->lock); in cpcap_adc_read()
914 return -EINVAL; in cpcap_adc_read()
920 mutex_unlock(&ddata->lock); in cpcap_adc_read()
921 dev_err(ddata->dev, "error reading ADC: %i\n", error); in cpcap_adc_read()
947 .compatible = "motorola,cpcap-adc",
950 .compatible = "motorola,mapphone-cpcap-adc",
963 indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*ddata)); in cpcap_adc_probe()
965 dev_err(&pdev->dev, "failed to allocate iio device\n"); in cpcap_adc_probe()
967 return -ENOMEM; in cpcap_adc_probe()
970 ddata->ato = device_get_match_data(&pdev->dev); in cpcap_adc_probe()
971 if (!ddata->ato) in cpcap_adc_probe()
972 return -ENODEV; in cpcap_adc_probe()
973 ddata->dev = &pdev->dev; in cpcap_adc_probe()
975 mutex_init(&ddata->lock); in cpcap_adc_probe()
976 init_waitqueue_head(&ddata->wq_data_avail); in cpcap_adc_probe()
978 indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE; in cpcap_adc_probe()
979 indio_dev->channels = cpcap_adc_channels; in cpcap_adc_probe()
980 indio_dev->num_channels = ARRAY_SIZE(cpcap_adc_channels); in cpcap_adc_probe()
981 indio_dev->name = dev_name(&pdev->dev); in cpcap_adc_probe()
982 indio_dev->info = &cpcap_adc_info; in cpcap_adc_probe()
984 ddata->reg = dev_get_regmap(pdev->dev.parent, NULL); in cpcap_adc_probe()
985 if (!ddata->reg) in cpcap_adc_probe()
986 return -ENODEV; in cpcap_adc_probe()
988 error = cpcap_get_vendor(ddata->dev, ddata->reg, &ddata->vendor); in cpcap_adc_probe()
994 ddata->irq = platform_get_irq_byname(pdev, "adcdone"); in cpcap_adc_probe()
995 if (ddata->irq < 0) in cpcap_adc_probe()
996 return -ENODEV; in cpcap_adc_probe()
998 error = devm_request_threaded_irq(&pdev->dev, ddata->irq, NULL, in cpcap_adc_probe()
1001 "cpcap-adc", indio_dev); in cpcap_adc_probe()
1003 dev_err(&pdev->dev, "could not get irq: %i\n", in cpcap_adc_probe()
1013 dev_info(&pdev->dev, "CPCAP ADC device probed\n"); in cpcap_adc_probe()
1015 return devm_iio_device_register(&pdev->dev, indio_dev); in cpcap_adc_probe()