Lines Matching +full:cpcap +full:- +full:battery
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
88 * Unfortunately no cpcap documentation available, please document when
103 * struct cpcap_adc - cpcap adc device driver data
104 * @reg: cpcap regmap
106 * @vendor: cpcap vendor
125 * enum cpcap_adc_channel - cpcap adc channels
129 CPCAP_ADC_AD0, /* Battery temperature */
130 CPCAP_ADC_BATTP, /* Battery voltage */
133 CPCAP_ADC_BPLUS_AD4, /* Another battery or system voltage */
142 CPCAP_ADC_HV_BATTP, /* Another battery detection? */
156 * enum cpcap_adc_timing - cpcap adc timing options
168 * struct cpcap_adc_phasing_tbl - cpcap phasing table
184 * struct cpcap_adc_conversion_tbl - cpcap conversion table
202 * struct cpcap_adc_request - cpcap adc request
227 [CPCAP_ADC_CHG_ISENSE] = {0, 0x80, 0x80, -512, 511},
228 [CPCAP_ADC_BATTI] = {0, 0x80, 0x80, -512, 511},
264 IIO_CHAN_INFO_PROCESSED, -512, 2, 0, 5000, 1023,
267 IIO_CHAN_INFO_PROCESSED, -512, 2, 0, 5000, 1023,
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_set_bits(ddata->reg, CPCAP_REG_ADCC2, in cpcap_adc_irq_thread()
393 ddata->done = true; in cpcap_adc_irq_thread()
394 wake_up_interruptible(&ddata->wq_data_avail); in cpcap_adc_irq_thread()
415 error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC1, in cpcap_adc_setup_calibrate()
426 error = regmap_clear_bits(ddata->reg, CPCAP_REG_ADCC2, in cpcap_adc_setup_calibrate()
433 error = regmap_set_bits(ddata->reg, CPCAP_REG_ADCC2, in cpcap_adc_setup_calibrate()
438 error = regmap_set_bits(ddata->reg, CPCAP_REG_ADCC2, CPCAP_BIT_ASC); in cpcap_adc_setup_calibrate()
444 error = regmap_read(ddata->reg, CPCAP_REG_ADCC2, &value); in cpcap_adc_setup_calibrate()
450 dev_err(ddata->dev, in cpcap_adc_setup_calibrate()
453 error = regmap_clear_bits(ddata->reg, CPCAP_REG_ADCC1, in cpcap_adc_setup_calibrate()
474 error = regmap_read(ddata->reg, calibration_register, in cpcap_adc_calibrate_one()
479 error = regmap_read(ddata->reg, calibration_register, in cpcap_adc_calibrate_one()
486 calibration_data[0] - calibration_data[1]; in cpcap_adc_calibrate_one()
489 calibration_data[1] - calibration_data[0]; in cpcap_adc_calibrate_one()
494 (ddata->vendor == CPCAP_VENDOR_TI)) { in cpcap_adc_calibrate_one()
496 ((short)calibration_data[1] * -1) + 512; in cpcap_adc_calibrate_one()
497 dev_dbg(ddata->dev, "ch%i calibration complete: %i\n", in cpcap_adc_calibrate_one()
532 const struct cpcap_adc_ato *ato = ddata->ato; in cpcap_adc_setup_bank()
540 switch (req->channel) { in cpcap_adc_setup_bank()
543 error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2, in cpcap_adc_setup_bank()
560 switch (req->timing) { in cpcap_adc_setup_bank()
562 value1 |= ato->ato_in; in cpcap_adc_setup_bank()
563 value1 |= ato->atox_in; in cpcap_adc_setup_bank()
564 value2 |= ato->adc_ps_factor_in; in cpcap_adc_setup_bank()
565 value2 |= ato->atox_ps_factor_in; in cpcap_adc_setup_bank()
568 value1 |= ato->ato_out; in cpcap_adc_setup_bank()
569 value1 |= ato->atox_out; in cpcap_adc_setup_bank()
570 value2 |= ato->adc_ps_factor_out; in cpcap_adc_setup_bank()
571 value2 |= ato->atox_ps_factor_out; in cpcap_adc_setup_bank()
579 error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC1, in cpcap_adc_setup_bank()
590 error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2, in cpcap_adc_setup_bank()
599 if (req->timing == CPCAP_ADC_TIMING_IMM) { in cpcap_adc_setup_bank()
600 error = regmap_set_bits(ddata->reg, CPCAP_REG_ADCC2, in cpcap_adc_setup_bank()
605 error = regmap_set_bits(ddata->reg, CPCAP_REG_ADCC2, in cpcap_adc_setup_bank()
610 error = regmap_set_bits(ddata->reg, CPCAP_REG_ADCC2, in cpcap_adc_setup_bank()
615 error = regmap_clear_bits(ddata->reg, CPCAP_REG_ADCC2, in cpcap_adc_setup_bank()
627 req->timing = CPCAP_ADC_TIMING_IMM; in cpcap_adc_start_bank()
628 ddata->done = false; in cpcap_adc_start_bank()
632 error = wait_event_interruptible_timeout(ddata->wq_data_avail, in cpcap_adc_start_bank()
633 ddata->done, in cpcap_adc_start_bank()
639 error = -ETIMEDOUT; in cpcap_adc_start_bank()
654 error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC1, in cpcap_adc_stop_bank()
660 return regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2, in cpcap_adc_stop_bank()
667 const struct cpcap_adc_conversion_tbl *conv_tbl = req->conv_tbl; in cpcap_adc_phase()
668 const struct cpcap_adc_phasing_tbl *phase_tbl = req->phase_tbl; in cpcap_adc_phase()
669 int index = req->channel; in cpcap_adc_phase()
672 switch (req->channel) { in cpcap_adc_phase()
675 index = req->bank_index; in cpcap_adc_phase()
676 req->result -= phase_tbl[index].offset; in cpcap_adc_phase()
677 req->result -= CPCAP_FOUR_POINT_TWO_ADC; in cpcap_adc_phase()
678 req->result *= phase_tbl[index].multiplier; in cpcap_adc_phase()
681 req->result /= phase_tbl[index].divider; in cpcap_adc_phase()
682 req->result += CPCAP_FOUR_POINT_TWO_ADC; in cpcap_adc_phase()
685 index = req->bank_index; in cpcap_adc_phase()
688 req->result += conv_tbl[index].cal_offset; in cpcap_adc_phase()
689 req->result += conv_tbl[index].align_offset; in cpcap_adc_phase()
690 req->result *= phase_tbl[index].multiplier; in cpcap_adc_phase()
693 req->result /= phase_tbl[index].divider; in cpcap_adc_phase()
694 req->result += phase_tbl[index].offset; in cpcap_adc_phase()
698 if (req->result < phase_tbl[index].min) in cpcap_adc_phase()
699 req->result = phase_tbl[index].min; in cpcap_adc_phase()
700 else if (req->result > phase_tbl[index].max) in cpcap_adc_phase()
701 req->result = phase_tbl[index].max; in cpcap_adc_phase()
709 if (value <= temp_map[CPCAP_MAX_TEMP_LVL - 1][0]) in cpcap_adc_table_to_millicelcius()
710 return temp_map[CPCAP_MAX_TEMP_LVL - 1][1]; in cpcap_adc_table_to_millicelcius()
715 for (i = 0; i < CPCAP_MAX_TEMP_LVL - 1; i++) { in cpcap_adc_table_to_millicelcius()
723 alpha = ((value - temp_map[i][0]) * 1000) / in cpcap_adc_table_to_millicelcius()
724 (temp_map[i + 1][0] - temp_map[i][0]); in cpcap_adc_table_to_millicelcius()
727 ((alpha * (temp_map[i + 1][1] - in cpcap_adc_table_to_millicelcius()
739 const struct cpcap_adc_conversion_tbl *conv_tbl = req->conv_tbl; in cpcap_adc_convert()
740 int index = req->channel; in cpcap_adc_convert()
743 switch (req->channel) { in cpcap_adc_convert()
759 if ((req->channel == CPCAP_ADC_AD0) || in cpcap_adc_convert()
760 (req->channel == CPCAP_ADC_AD3)) { in cpcap_adc_convert()
761 req->result = in cpcap_adc_convert()
762 cpcap_adc_table_to_millicelcius(req->result); in cpcap_adc_convert()
768 req->result *= conv_tbl[index].multiplier; in cpcap_adc_convert()
771 req->result /= conv_tbl[index].divider; in cpcap_adc_convert()
772 req->result += conv_tbl[index].conv_offset; in cpcap_adc_convert()
784 if (ddata->vendor == CPCAP_VENDOR_TI) { in cpcap_adc_read_bank_scaled()
785 error = regmap_read(ddata->reg, CPCAP_REG_ADCAL1, in cpcap_adc_read_bank_scaled()
790 ((short)calibration_data * -1) + 512; in cpcap_adc_read_bank_scaled()
792 error = regmap_read(ddata->reg, CPCAP_REG_ADCAL2, in cpcap_adc_read_bank_scaled()
797 ((short)calibration_data * -1) + 512; in cpcap_adc_read_bank_scaled()
800 addr = CPCAP_REG_ADCD0 + req->bank_index * 4; in cpcap_adc_read_bank_scaled()
802 error = regmap_read(ddata->reg, addr, &req->result); in cpcap_adc_read_bank_scaled()
806 req->result &= 0x3ff; in cpcap_adc_read_bank_scaled()
816 req->channel = channel; in cpcap_adc_init_request()
817 req->phase_tbl = bank_phasing; in cpcap_adc_init_request()
818 req->conv_tbl = bank_conversion; in cpcap_adc_init_request()
822 req->bank_index = channel; in cpcap_adc_init_request()
825 req->bank_index = channel - 8; in cpcap_adc_init_request()
828 req->bank_index = CPCAP_ADC_BATTP; in cpcap_adc_init_request()
831 req->bank_index = CPCAP_ADC_BATTI; in cpcap_adc_init_request()
834 return -EINVAL; in cpcap_adc_init_request()
845 error = regmap_read(ddata->reg, addr, val); in cpcap_adc_read_st_die_temp()
849 *val -= 282; in cpcap_adc_read_st_die_temp()
864 error = cpcap_adc_init_request(&req, chan->channel); in cpcap_adc_read()
870 mutex_lock(&ddata->lock); in cpcap_adc_read()
874 error = regmap_read(ddata->reg, chan->address, val); in cpcap_adc_read()
880 mutex_unlock(&ddata->lock); in cpcap_adc_read()
883 mutex_lock(&ddata->lock); in cpcap_adc_read()
887 if ((ddata->vendor == CPCAP_VENDOR_ST) && in cpcap_adc_read()
888 (chan->channel == CPCAP_ADC_AD3)) { in cpcap_adc_read()
890 chan->address, in cpcap_adc_read()
902 mutex_unlock(&ddata->lock); in cpcap_adc_read()
906 return -EINVAL; in cpcap_adc_read()
912 mutex_unlock(&ddata->lock); in cpcap_adc_read()
913 dev_err(ddata->dev, "error reading ADC: %i\n", error); in cpcap_adc_read()
939 .compatible = "motorola,cpcap-adc",
942 .compatible = "motorola,mapphone-cpcap-adc",
955 indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*ddata)); in cpcap_adc_probe()
957 dev_err(&pdev->dev, "failed to allocate iio device\n"); in cpcap_adc_probe()
959 return -ENOMEM; in cpcap_adc_probe()
962 ddata->ato = device_get_match_data(&pdev->dev); in cpcap_adc_probe()
963 if (!ddata->ato) in cpcap_adc_probe()
964 return -ENODEV; in cpcap_adc_probe()
965 ddata->dev = &pdev->dev; in cpcap_adc_probe()
967 mutex_init(&ddata->lock); in cpcap_adc_probe()
968 init_waitqueue_head(&ddata->wq_data_avail); in cpcap_adc_probe()
970 indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE; in cpcap_adc_probe()
971 indio_dev->channels = cpcap_adc_channels; in cpcap_adc_probe()
972 indio_dev->num_channels = ARRAY_SIZE(cpcap_adc_channels); in cpcap_adc_probe()
973 indio_dev->name = dev_name(&pdev->dev); in cpcap_adc_probe()
974 indio_dev->info = &cpcap_adc_info; in cpcap_adc_probe()
976 ddata->reg = dev_get_regmap(pdev->dev.parent, NULL); in cpcap_adc_probe()
977 if (!ddata->reg) in cpcap_adc_probe()
978 return -ENODEV; in cpcap_adc_probe()
980 error = cpcap_get_vendor(ddata->dev, ddata->reg, &ddata->vendor); in cpcap_adc_probe()
986 ddata->irq = platform_get_irq_byname(pdev, "adcdone"); in cpcap_adc_probe()
987 if (ddata->irq < 0) in cpcap_adc_probe()
988 return -ENODEV; in cpcap_adc_probe()
990 error = devm_request_threaded_irq(&pdev->dev, ddata->irq, NULL, in cpcap_adc_probe()
993 "cpcap-adc", indio_dev); in cpcap_adc_probe()
995 dev_err(&pdev->dev, "could not get irq: %i\n", in cpcap_adc_probe()
1005 dev_info(&pdev->dev, "CPCAP ADC device probed\n"); in cpcap_adc_probe()
1007 return devm_iio_device_register(&pdev->dev, indio_dev); in cpcap_adc_probe()
1021 MODULE_DESCRIPTION("CPCAP ADC driver");