Lines Matching +full:vbus +full:- +full:divider
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
131 CPCAP_ADC_VBUS, /* USB VBUS voltage */
156 * enum cpcap_adc_timing - cpcap adc timing options
168 * struct cpcap_adc_phasing_tbl - cpcap phasing table
171 * @divider: divider in the phasing table
178 unsigned short divider; member
184 * struct cpcap_adc_conversion_tbl - cpcap conversion table
190 * @divider: conversion divider
198 int divider; member
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 },
360 CPCAP_CHAN(IIO_VOLTAGE, 2, CPCAP_REG_ADCD2, "vbus"),
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()
564 switch (req->timing) { in cpcap_adc_setup_bank()
566 value1 |= ato->ato_in; in cpcap_adc_setup_bank()
567 value1 |= ato->atox_in; in cpcap_adc_setup_bank()
568 value2 |= ato->adc_ps_factor_in; in cpcap_adc_setup_bank()
569 value2 |= ato->atox_ps_factor_in; in cpcap_adc_setup_bank()
572 value1 |= ato->ato_out; in cpcap_adc_setup_bank()
573 value1 |= ato->atox_out; in cpcap_adc_setup_bank()
574 value2 |= ato->adc_ps_factor_out; in cpcap_adc_setup_bank()
575 value2 |= ato->atox_ps_factor_out; in cpcap_adc_setup_bank()
583 error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC1, in cpcap_adc_setup_bank()
594 error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2, in cpcap_adc_setup_bank()
603 if (req->timing == CPCAP_ADC_TIMING_IMM) { in cpcap_adc_setup_bank()
604 error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2, in cpcap_adc_setup_bank()
610 error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2, in cpcap_adc_setup_bank()
616 error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2, in cpcap_adc_setup_bank()
622 error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2, in cpcap_adc_setup_bank()
634 req->timing = CPCAP_ADC_TIMING_IMM; in cpcap_adc_start_bank()
635 ddata->done = false; in cpcap_adc_start_bank()
639 error = wait_event_interruptible_timeout(ddata->wq_data_avail, in cpcap_adc_start_bank()
640 ddata->done, in cpcap_adc_start_bank()
646 error = -ETIMEDOUT; in cpcap_adc_start_bank()
661 error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC1, in cpcap_adc_stop_bank()
667 return regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2, in cpcap_adc_stop_bank()
674 const struct cpcap_adc_conversion_tbl *conv_tbl = req->conv_tbl; in cpcap_adc_phase()
675 const struct cpcap_adc_phasing_tbl *phase_tbl = req->phase_tbl; in cpcap_adc_phase()
676 int index = req->channel; in cpcap_adc_phase()
679 switch (req->channel) { in cpcap_adc_phase()
682 index = req->bank_index; in cpcap_adc_phase()
683 req->result -= phase_tbl[index].offset; in cpcap_adc_phase()
684 req->result -= CPCAP_FOUR_POINT_TWO_ADC; in cpcap_adc_phase()
685 req->result *= phase_tbl[index].multiplier; in cpcap_adc_phase()
686 if (phase_tbl[index].divider == 0) in cpcap_adc_phase()
688 req->result /= phase_tbl[index].divider; in cpcap_adc_phase()
689 req->result += CPCAP_FOUR_POINT_TWO_ADC; in cpcap_adc_phase()
692 index = req->bank_index; in cpcap_adc_phase()
695 req->result += conv_tbl[index].cal_offset; in cpcap_adc_phase()
696 req->result += conv_tbl[index].align_offset; in cpcap_adc_phase()
697 req->result *= phase_tbl[index].multiplier; in cpcap_adc_phase()
698 if (phase_tbl[index].divider == 0) in cpcap_adc_phase()
700 req->result /= phase_tbl[index].divider; in cpcap_adc_phase()
701 req->result += phase_tbl[index].offset; in cpcap_adc_phase()
705 if (req->result < phase_tbl[index].min) in cpcap_adc_phase()
706 req->result = phase_tbl[index].min; in cpcap_adc_phase()
707 else if (req->result > phase_tbl[index].max) in cpcap_adc_phase()
708 req->result = phase_tbl[index].max; in cpcap_adc_phase()
716 if (value <= temp_map[CPCAP_MAX_TEMP_LVL - 1][0]) in cpcap_adc_table_to_millicelcius()
717 return temp_map[CPCAP_MAX_TEMP_LVL - 1][1]; in cpcap_adc_table_to_millicelcius()
722 for (i = 0; i < CPCAP_MAX_TEMP_LVL - 1; i++) { in cpcap_adc_table_to_millicelcius()
730 alpha = ((value - temp_map[i][0]) * 1000) / in cpcap_adc_table_to_millicelcius()
731 (temp_map[i + 1][0] - temp_map[i][0]); in cpcap_adc_table_to_millicelcius()
734 ((alpha * (temp_map[i + 1][1] - in cpcap_adc_table_to_millicelcius()
746 const struct cpcap_adc_conversion_tbl *conv_tbl = req->conv_tbl; in cpcap_adc_convert()
747 int index = req->channel; in cpcap_adc_convert()
750 switch (req->channel) { in cpcap_adc_convert()
766 if ((req->channel == CPCAP_ADC_AD0) || in cpcap_adc_convert()
767 (req->channel == CPCAP_ADC_AD3)) { in cpcap_adc_convert()
768 req->result = in cpcap_adc_convert()
769 cpcap_adc_table_to_millicelcius(req->result); in cpcap_adc_convert()
775 req->result *= conv_tbl[index].multiplier; in cpcap_adc_convert()
776 if (conv_tbl[index].divider == 0) in cpcap_adc_convert()
778 req->result /= conv_tbl[index].divider; in cpcap_adc_convert()
779 req->result += conv_tbl[index].conv_offset; in cpcap_adc_convert()
791 if (ddata->vendor == CPCAP_VENDOR_TI) { in cpcap_adc_read_bank_scaled()
792 error = regmap_read(ddata->reg, CPCAP_REG_ADCAL1, in cpcap_adc_read_bank_scaled()
797 ((short)calibration_data * -1) + 512; in cpcap_adc_read_bank_scaled()
799 error = regmap_read(ddata->reg, CPCAP_REG_ADCAL2, in cpcap_adc_read_bank_scaled()
804 ((short)calibration_data * -1) + 512; in cpcap_adc_read_bank_scaled()
807 addr = CPCAP_REG_ADCD0 + req->bank_index * 4; in cpcap_adc_read_bank_scaled()
809 error = regmap_read(ddata->reg, addr, &req->result); in cpcap_adc_read_bank_scaled()
813 req->result &= 0x3ff; in cpcap_adc_read_bank_scaled()
823 req->channel = channel; in cpcap_adc_init_request()
824 req->phase_tbl = bank_phasing; in cpcap_adc_init_request()
825 req->conv_tbl = bank_conversion; in cpcap_adc_init_request()
829 req->bank_index = channel; in cpcap_adc_init_request()
832 req->bank_index = channel - 8; in cpcap_adc_init_request()
835 req->bank_index = CPCAP_ADC_BATTP; in cpcap_adc_init_request()
838 req->bank_index = CPCAP_ADC_BATTI; in cpcap_adc_init_request()
841 return -EINVAL; in cpcap_adc_init_request()
852 error = regmap_read(ddata->reg, addr, val); in cpcap_adc_read_st_die_temp()
856 *val -= 282; in cpcap_adc_read_st_die_temp()
871 error = cpcap_adc_init_request(&req, chan->channel); in cpcap_adc_read()
877 mutex_lock(&ddata->lock); in cpcap_adc_read()
881 error = regmap_read(ddata->reg, chan->address, val); in cpcap_adc_read()
887 mutex_unlock(&ddata->lock); in cpcap_adc_read()
890 mutex_lock(&ddata->lock); in cpcap_adc_read()
894 if ((ddata->vendor == CPCAP_VENDOR_ST) && in cpcap_adc_read()
895 (chan->channel == CPCAP_ADC_AD3)) { in cpcap_adc_read()
897 chan->address, in cpcap_adc_read()
909 mutex_unlock(&ddata->lock); in cpcap_adc_read()
913 return -EINVAL; in cpcap_adc_read()
919 mutex_unlock(&ddata->lock); in cpcap_adc_read()
920 dev_err(ddata->dev, "error reading ADC: %i\n", error); in cpcap_adc_read()
946 .compatible = "motorola,cpcap-adc",
949 .compatible = "motorola,mapphone-cpcap-adc",
962 indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*ddata)); in cpcap_adc_probe()
964 dev_err(&pdev->dev, "failed to allocate iio device\n"); in cpcap_adc_probe()
966 return -ENOMEM; in cpcap_adc_probe()
969 ddata->ato = device_get_match_data(&pdev->dev); in cpcap_adc_probe()
970 if (!ddata->ato) in cpcap_adc_probe()
971 return -ENODEV; in cpcap_adc_probe()
972 ddata->dev = &pdev->dev; in cpcap_adc_probe()
974 mutex_init(&ddata->lock); in cpcap_adc_probe()
975 init_waitqueue_head(&ddata->wq_data_avail); in cpcap_adc_probe()
977 indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE; in cpcap_adc_probe()
978 indio_dev->channels = cpcap_adc_channels; in cpcap_adc_probe()
979 indio_dev->num_channels = ARRAY_SIZE(cpcap_adc_channels); in cpcap_adc_probe()
980 indio_dev->name = dev_name(&pdev->dev); in cpcap_adc_probe()
981 indio_dev->info = &cpcap_adc_info; in cpcap_adc_probe()
983 ddata->reg = dev_get_regmap(pdev->dev.parent, NULL); in cpcap_adc_probe()
984 if (!ddata->reg) in cpcap_adc_probe()
985 return -ENODEV; in cpcap_adc_probe()
987 error = cpcap_get_vendor(ddata->dev, ddata->reg, &ddata->vendor); in cpcap_adc_probe()
993 ddata->irq = platform_get_irq_byname(pdev, "adcdone"); in cpcap_adc_probe()
994 if (ddata->irq < 0) in cpcap_adc_probe()
995 return -ENODEV; in cpcap_adc_probe()
997 error = devm_request_threaded_irq(&pdev->dev, ddata->irq, NULL, in cpcap_adc_probe()
1000 "cpcap-adc", indio_dev); in cpcap_adc_probe()
1002 dev_err(&pdev->dev, "could not get irq: %i\n", in cpcap_adc_probe()
1012 dev_info(&pdev->dev, "CPCAP ADC device probed\n"); in cpcap_adc_probe()
1014 return devm_iio_device_register(&pdev->dev, indio_dev); in cpcap_adc_probe()