Lines Matching +full:0 +full:- +full:1023
1 // SPDX-License-Identifier: GPL-2.0-only
8 * Copyright (C) 2009-2010 Motorola, Inc.
27 #include <linux/mfd/motorola-cpcap.h>
45 #define CPCAP_BIT_ADEN BIT(0) /* Currently unused */
67 #define CPCAP_BIT_TS_M0 BIT(0) /* Currently unused */
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
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
222 [CPCAP_ADC_AD0] = {0, 0x80, 0x80, 0, 1023},
223 [CPCAP_ADC_BATTP] = {0, 0x80, 0x80, 0, 1023},
224 [CPCAP_ADC_VBUS] = {0, 0x80, 0x80, 0, 1023},
225 [CPCAP_ADC_AD3] = {0, 0x80, 0x80, 0, 1023},
226 [CPCAP_ADC_BPLUS_AD4] = {0, 0x80, 0x80, 0, 1023},
227 [CPCAP_ADC_CHG_ISENSE] = {0, 0x80, 0x80, -512, 511},
228 [CPCAP_ADC_BATTI] = {0, 0x80, 0x80, -512, 511},
229 [CPCAP_ADC_USB_ID] = {0, 0x80, 0x80, 0, 1023},
232 [CPCAP_ADC_AD8] = {0, 0x80, 0x80, 0, 1023},
233 [CPCAP_ADC_AD9] = {0, 0x80, 0x80, 0, 1023},
234 [CPCAP_ADC_LICELL] = {0, 0x80, 0x80, 0, 1023},
235 [CPCAP_ADC_HV_BATTP] = {0, 0x80, 0x80, 0, 1023},
236 [CPCAP_ADC_TSX1_AD12] = {0, 0x80, 0x80, 0, 1023},
237 [CPCAP_ADC_TSX2_AD13] = {0, 0x80, 0x80, 0, 1023},
238 [CPCAP_ADC_TSY1_AD14] = {0, 0x80, 0x80, 0, 1023},
239 [CPCAP_ADC_TSY2_AD15] = {0, 0x80, 0x80, 0, 1023},
249 IIO_CHAN_INFO_PROCESSED, 0, 0, 0, 1, 1,
252 IIO_CHAN_INFO_PROCESSED, 0, 2400, 0, 2300, 1023,
255 IIO_CHAN_INFO_PROCESSED, 0, 0, 0, 10000, 1023,
258 IIO_CHAN_INFO_PROCESSED, 0, 0, 0, 1, 1,
261 IIO_CHAN_INFO_PROCESSED, 0, 2400, 0, 2300, 1023,
264 IIO_CHAN_INFO_PROCESSED, -512, 2, 0, 5000, 1023,
267 IIO_CHAN_INFO_PROCESSED, -512, 2, 0, 5000, 1023,
270 IIO_CHAN_INFO_RAW, 0, 0, 0, 1, 1,
275 IIO_CHAN_INFO_RAW, 0, 0, 0, 1, 1,
278 IIO_CHAN_INFO_RAW, 0, 0, 0, 1, 1,
281 IIO_CHAN_INFO_PROCESSED, 0, 0, 0, 3400, 1023,
284 IIO_CHAN_INFO_RAW, 0, 0, 0, 1, 1,
287 IIO_CHAN_INFO_RAW, 0, 0, 0, 1, 1,
290 IIO_CHAN_INFO_RAW, 0, 0, 0, 1, 1,
293 IIO_CHAN_INFO_RAW, 0, 0, 0, 1, 1,
296 IIO_CHAN_INFO_RAW, 0, 0, 0, 1, 1,
302 * REVISIT: Check the duplicate 0x3ff entry in a freezer
305 { 0x03ff, -40000 },
306 { 0x03ff, -35000 },
307 { 0x03ef, -30000 },
308 { 0x03b2, -25000 },
309 { 0x036c, -20000 },
310 { 0x0320, -15000 },
311 { 0x02d0, -10000 },
312 { 0x027f, -5000 },
313 { 0x022f, 0 },
314 { 0x01e4, 5000 },
315 { 0x019f, 10000 },
316 { 0x0161, 15000 },
317 { 0x012b, 20000 },
318 { 0x00fc, 25000 },
319 { 0x00d4, 30000 },
320 { 0x00b2, 35000 },
321 { 0x0095, 40000 },
322 { 0x007d, 45000 },
323 { 0x0069, 50000 },
324 { 0x0059, 55000 },
325 { 0x004b, 60000 },
326 { 0x003f, 65000 },
327 { 0x0036, 70000 },
328 { 0x002e, 75000 },
329 { 0x0027, 80000 },
330 { 0x0022, 85000 },
331 { 0x001d, 90000 },
358 CPCAP_CHAN(IIO_TEMP, 0, CPCAP_REG_ADCD0, "battdetb"),
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()
403 unsigned int value = 0; in cpcap_adc_setup_calibrate()
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()
469 for (i = 0; i < CPCAP_ADC_MAX_RETRIES; i++) { in cpcap_adc_calibrate_one()
470 calibration_data[0] = 0; in cpcap_adc_calibrate_one()
471 calibration_data[1] = 0; in cpcap_adc_calibrate_one()
474 error = regmap_read(ddata->reg, calibration_register, in cpcap_adc_calibrate_one()
475 &calibration_data[0]); in cpcap_adc_calibrate_one()
479 error = regmap_read(ddata->reg, calibration_register, in cpcap_adc_calibrate_one()
484 if (calibration_data[0] > calibration_data[1]) 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()
504 return 0; in cpcap_adc_calibrate_one()
525 return 0; in cpcap_adc_calibrate()
532 const struct cpcap_adc_ato *ato = ddata->ato; in cpcap_adc_setup_bank()
533 unsigned short value1 = 0; in cpcap_adc_setup_bank()
534 unsigned short value2 = 0; 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()
630 for (i = 0; i < CPCAP_ADC_MAX_RETRIES; i++) { 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()
635 if (error > 0) in cpcap_adc_start_bank()
636 return 0; in cpcap_adc_start_bank()
638 if (error == 0) { in cpcap_adc_start_bank()
639 error = -ETIMEDOUT; in cpcap_adc_start_bank()
643 if (error < 0) in cpcap_adc_start_bank()
654 error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC1, in cpcap_adc_stop_bank()
655 0xffff, in cpcap_adc_stop_bank()
660 return regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2, in cpcap_adc_stop_bank()
661 0xffff, 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()
679 if (phase_tbl[index].divider == 0) 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()
691 if (phase_tbl[index].divider == 0) 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()
707 int i, result = 0, alpha; in cpcap_adc_table_to_millicelcius()
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()
712 if (value >= temp_map[0][0]) in cpcap_adc_table_to_millicelcius()
713 return temp_map[0][1]; in cpcap_adc_table_to_millicelcius()
715 for (i = 0; i < CPCAP_MAX_TEMP_LVL - 1; i++) { in cpcap_adc_table_to_millicelcius()
716 if ((value <= temp_map[i][0]) && in cpcap_adc_table_to_millicelcius()
717 (value >= temp_map[i + 1][0])) { in cpcap_adc_table_to_millicelcius()
718 if (value == temp_map[i][0]) { in cpcap_adc_table_to_millicelcius()
720 } else if (value == temp_map[i + 1][0]) { 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()
769 if (conv_tbl[index].divider == 0) 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()
810 return 0; 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()
837 return 0; 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()
853 return 0; 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()
927 .ato_in = 0x0480,
928 .atox_in = 0,
929 .adc_ps_factor_in = 0x0200,
930 .atox_ps_factor_in = 0,
931 .ato_out = 0,
932 .atox_out = 0,
933 .adc_ps_factor_out = 0,
934 .atox_ps_factor_out = 0,
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()