Lines Matching +full:period +full:- +full:scale
1 // SPDX-License-Identifier: GPL-2.0+
3 * IIO driver for PAC1921 High-Side Power/Current Monitor
63 /* Time from Sleep State to Start of Integration Period (tSLEEP_TO_INT) */
74 /* f7bb9932-86ee-4516-a236-7a7a742e55cb */
80 * Pre-computed scale factors for BUS voltage
84 * Vbus scale (mV) = max_vbus (mV) / dv_gain / resolution
96 * Pre-computed scales for SENSE voltage
100 * Vsense scale (mV) = max_vsense (mV) / di_gain / resolution
115 * integration period.
117 * Changing the number of samples affects the integration period: higher the
118 * number of samples, longer the integration period.
127 * The integration period depends on the configuration of number of integration
129 * contains integration periods, in microsecs unit, based on table 4-5 from
130 * datasheet considering power integration mode, 14-Bit resolution and post
223 if (!priv->first_integr_started) in pac1921_data_ready()
226 if (!priv->first_integr_done) { in pac1921_data_ready()
232 * and completed the first integration period. in pac1921_data_ready()
234 t_ready = priv->integr_started_time_jiffies + in pac1921_data_ready()
236 usecs_to_jiffies(priv->integr_period_usecs); in pac1921_data_ready()
241 priv->first_integr_done = true; in pac1921_data_ready()
257 * Fill the table of scale factors for current
262 * Current scale (mA) = Vsense LSB (nV) / shunt (uOhm)
268 for (unsigned int i = 0; i < ARRAY_SIZE(priv->current_scales); i++) { in pac1921_calc_current_scales()
272 pac1921_calc_scale(vsense_lsb, priv->rshunt_uohm, in pac1921_calc_current_scales()
273 &priv->current_scales[i][0], in pac1921_calc_current_scales()
274 &priv->current_scales[i][1]); in pac1921_calc_current_scales()
289 ret = regmap_read(priv->regmap, PAC1921_REG_OVERFLOW_STS, &flags); in pac1921_check_push_overflow()
294 !(priv->prev_ovf_flags & PAC1921_OVERFLOW_VBOV) && in pac1921_check_push_overflow()
295 priv->ovf_enabled_events & PAC1921_OVERFLOW_VBOV) { in pac1921_check_push_overflow()
303 !(priv->prev_ovf_flags & PAC1921_OVERFLOW_VSOV) && in pac1921_check_push_overflow()
304 priv->ovf_enabled_events & PAC1921_OVERFLOW_VSOV) { in pac1921_check_push_overflow()
317 !(priv->prev_ovf_flags & PAC1921_OVERFLOW_VPOV) && in pac1921_check_push_overflow()
318 priv->ovf_enabled_events & PAC1921_OVERFLOW_VPOV) { in pac1921_check_push_overflow()
326 priv->prev_ovf_flags = flags; in pac1921_check_push_overflow()
341 int ret = regmap_bulk_read(priv->regmap, reg, val, sizeof(*val)); in pac1921_read_res()
356 guard(mutex)(&priv->lock); in pac1921_read_raw()
365 return -EBUSY; in pac1921_read_raw()
373 ret = pac1921_read_res(priv, chan->address, &res_val); in pac1921_read_raw()
382 switch (chan->channel) { in pac1921_read_raw()
384 *val = pac1921_vbus_scales[priv->dv_gain][0]; in pac1921_read_raw()
385 *val2 = pac1921_vbus_scales[priv->dv_gain][1]; in pac1921_read_raw()
389 *val = pac1921_vsense_scales[priv->di_gain][0]; in pac1921_read_raw()
390 *val2 = pac1921_vsense_scales[priv->di_gain][1]; in pac1921_read_raw()
394 *val = priv->current_scales[priv->di_gain][0]; in pac1921_read_raw()
395 *val2 = priv->current_scales[priv->di_gain][1]; in pac1921_read_raw()
400 * Power scale factor in mW: in pac1921_read_raw()
401 * Current scale (mA) * max_vbus (V) / dv_gain in pac1921_read_raw()
404 /* Get current scale based on di_gain */ in pac1921_read_raw()
405 int *curr_scale = priv->current_scales[priv->di_gain]; in pac1921_read_raw()
411 tmp *= PAC1921_MAX_VBUS_V >> priv->dv_gain; in pac1921_read_raw()
419 return -EINVAL; in pac1921_read_raw()
423 *val = pac1921_int_num_samples[priv->n_samples]; in pac1921_read_raw()
428 * The sampling frequency (Hz) is read-only and corresponds to in pac1921_read_raw()
431 * The integration period depends on the number of integration in pac1921_read_raw()
437 *val2 = priv->integr_period_usecs; in pac1921_read_raw()
441 return -EINVAL; in pac1921_read_raw()
457 return -EINVAL; in pac1921_read_avail()
473 int ret = regmap_update_bits(priv->regmap, PAC1921_REG_INT_CFG, in pac1921_update_cfg_reg()
479 ret = regmap_update_bits(priv->regmap, reg, mask, val); in pac1921_update_cfg_reg()
483 /* Re-enable integration */ in pac1921_update_cfg_reg()
484 ret = regmap_update_bits(priv->regmap, PAC1921_REG_INT_CFG, in pac1921_update_cfg_reg()
490 * Reset integration started time and mark this integration period as in pac1921_update_cfg_reg()
492 * only at the end of this integration period. in pac1921_update_cfg_reg()
494 priv->integr_started_time_jiffies = jiffies; in pac1921_update_cfg_reg()
495 priv->first_integr_done = false; in pac1921_update_cfg_reg()
501 * Retrieve the index of the given scale (represented by scale_val and
503 * the gain corresponding to the given scale.
516 return -EINVAL; in pac1921_lookup_scale()
544 * Given a scale factor represented by scale_val and scale_val2 with format
556 switch (chan->channel) { in pac1921_update_gain_from_scale()
564 return pac1921_update_gain(priv, &priv->dv_gain, ret, in pac1921_update_gain_from_scale()
573 return pac1921_update_gain(priv, &priv->di_gain, ret, in pac1921_update_gain_from_scale()
576 ret = pac1921_lookup_scale(priv->current_scales, in pac1921_update_gain_from_scale()
577 ARRAY_SIZE(priv->current_scales), in pac1921_update_gain_from_scale()
582 return pac1921_update_gain(priv, &priv->di_gain, ret, in pac1921_update_gain_from_scale()
585 return -EINVAL; in pac1921_update_gain_from_scale()
599 return -EINVAL; in pac1921_lookup_int_num_samples()
620 if (priv->n_samples == n_samples) in pac1921_update_int_num_samples()
630 priv->n_samples = n_samples; in pac1921_update_int_num_samples()
632 priv->integr_period_usecs = pac1921_int_periods_usecs[priv->n_samples]; in pac1921_update_int_num_samples()
647 return -EINVAL; in pac1921_write_raw_get_fmt()
657 guard(mutex)(&priv->lock); in pac1921_write_raw()
665 return -EINVAL; in pac1921_write_raw()
672 switch (chan->channel) { in pac1921_read_label()
682 return -EINVAL; in pac1921_read_label()
693 guard(mutex)(&priv->lock); in pac1921_read_event_config()
695 switch (chan->channel) { in pac1921_read_event_config()
697 return !!(priv->ovf_enabled_events & PAC1921_OVERFLOW_VBOV); in pac1921_read_event_config()
700 return !!(priv->ovf_enabled_events & PAC1921_OVERFLOW_VSOV); in pac1921_read_event_config()
702 return !!(priv->ovf_enabled_events & PAC1921_OVERFLOW_VPOV); in pac1921_read_event_config()
704 return -EINVAL; in pac1921_read_event_config()
717 guard(mutex)(&priv->lock); in pac1921_write_event_config()
719 switch (chan->channel) { in pac1921_write_event_config()
731 return -EINVAL; in pac1921_write_event_config()
735 priv->ovf_enabled_events |= ovf_bit; in pac1921_write_event_config()
737 priv->ovf_enabled_events &= ~ovf_bit; in pac1921_write_event_config()
754 return -EINVAL; in pac1921_read_event_value()
777 if (chan->channel != PAC1921_CHAN_CURRENT) in pac1921_read_shunt_resistor()
778 return -EINVAL; in pac1921_read_shunt_resistor()
780 guard(mutex)(&priv->lock); in pac1921_read_shunt_resistor()
782 vals[0] = priv->rshunt_uohm; in pac1921_read_shunt_resistor()
798 if (chan->channel != PAC1921_CHAN_CURRENT) in pac1921_write_shunt_resistor()
799 return -EINVAL; in pac1921_write_shunt_resistor()
812 return -EINVAL; in pac1921_write_shunt_resistor()
816 guard(mutex)(&priv->lock); in pac1921_write_shunt_resistor()
818 priv->rshunt_uohm = rshunt_uohm; in pac1921_write_shunt_resistor()
843 return -EFBIG; in pac1921_format_scale_avail()
848 return -EFBIG; in pac1921_format_scale_avail()
872 switch (chan->channel) { in pac1921_read_scale_avail()
884 guard(mutex)(&priv->lock); in pac1921_read_scale_avail()
885 scales_tbl = priv->current_scales; in pac1921_read_scale_avail()
886 size = ARRAY_SIZE(priv->current_scales); in pac1921_read_scale_avail()
890 return -EINVAL; in pac1921_read_scale_avail()
1021 struct iio_dev *idev = pf->indio_dev; in pac1921_trigger_handler()
1027 guard(mutex)(&priv->lock); in pac1921_trigger_handler()
1032 ret = pac1921_check_push_overflow(idev, pf->timestamp); in pac1921_trigger_handler()
1039 ret = pac1921_read_res(priv, idev->channels[ch].address, &val); in pac1921_trigger_handler()
1043 priv->scan.chan[ch++] = val; in pac1921_trigger_handler()
1046 iio_push_to_buffers_with_timestamp(idev, &priv->scan, pf->timestamp); in pac1921_trigger_handler()
1049 iio_trigger_notify_done(idev->trig); in pac1921_trigger_handler()
1067 ret = regmap_update_bits(priv->regmap, PAC1921_REG_INT_CFG, in pac1921_init()
1072 /* Configure gains, use 14-bits measurement resolution (HW default) */ in pac1921_init()
1073 val = FIELD_PREP(PAC1921_GAIN_DI_GAIN_MASK, priv->di_gain) | in pac1921_init()
1074 FIELD_PREP(PAC1921_GAIN_DV_GAIN_MASK, priv->dv_gain); in pac1921_init()
1075 ret = regmap_write(priv->regmap, PAC1921_REG_GAIN_CFG, val); in pac1921_init()
1081 * - num of integration samples in pac1921_init()
1082 * - filters enabled (HW default) in pac1921_init()
1083 * - set READ/INT pin override (RIOV) to control operation mode via in pac1921_init()
1086 val = FIELD_PREP(PAC1921_INT_CFG_SMPL_MASK, priv->n_samples) | in pac1921_init()
1089 ret = regmap_write(priv->regmap, PAC1921_REG_INT_CFG, val); in pac1921_init()
1095 * - VPower free run integration mode in pac1921_init()
1096 * - OUT pin full scale range: 3V (HW default) in pac1921_init()
1097 * - no timeout, no sleep, no sleep override, no recalc (HW defaults) in pac1921_init()
1101 ret = regmap_write(priv->regmap, PAC1921_REG_CONTROL, val); in pac1921_init()
1106 ret = regmap_update_bits(priv->regmap, PAC1921_REG_INT_CFG, in pac1921_init()
1111 priv->first_integr_started = true; in pac1921_init()
1112 priv->integr_started_time_jiffies = jiffies; in pac1921_init()
1113 priv->integr_period_usecs = pac1921_int_periods_usecs[priv->n_samples]; in pac1921_init()
1124 guard(mutex)(&priv->lock); in pac1921_suspend()
1126 priv->first_integr_started = false; in pac1921_suspend()
1127 priv->first_integr_done = false; in pac1921_suspend()
1129 ret = regmap_update_bits(priv->regmap, PAC1921_REG_INT_CFG, in pac1921_suspend()
1134 ret = regmap_update_bits(priv->regmap, PAC1921_REG_CONTROL, in pac1921_suspend()
1139 return regulator_disable(priv->vdd); in pac1921_suspend()
1149 guard(mutex)(&priv->lock); in pac1921_resume()
1151 ret = regulator_enable(priv->vdd); in pac1921_resume()
1172 …plicationNotes/ApplicationNotes/PAC193X-Integration-Notes-for-Microsoft-Windows-10-and-Windows-11-…
1180 struct device *dev = &priv->client->dev; in pac1921_match_acpi_device()
1187 return dev_err_probe(dev, -EINVAL, in pac1921_match_acpi_device()
1190 priv->rshunt_uohm = status->package.elements[0].integer.value; in pac1921_match_acpi_device()
1196 return dev_err_probe(dev, -EINVAL, in pac1921_match_acpi_device()
1199 label = devm_kstrdup(dev, status->package.elements[0].string.pointer, in pac1921_match_acpi_device()
1203 return -ENOMEM; in pac1921_match_acpi_device()
1205 indio_dev->label = label; in pac1921_match_acpi_device()
1214 struct device *dev = &priv->client->dev; in pac1921_parse_of_fw()
1216 ret = device_property_read_u32(dev, "shunt-resistor-micro-ohms", in pac1921_parse_of_fw()
1217 &priv->rshunt_uohm); in pac1921_parse_of_fw()
1227 struct device *dev = &client->dev; in pac1921_probe()
1234 return -ENOMEM; in pac1921_probe()
1237 priv->client = client; in pac1921_probe()
1240 priv->regmap = devm_regmap_init_i2c(client, &pac1921_regmap_config); in pac1921_probe()
1241 if (IS_ERR(priv->regmap)) in pac1921_probe()
1242 return dev_err_probe(dev, PTR_ERR(priv->regmap), in pac1921_probe()
1245 ret = devm_mutex_init(dev, &priv->lock); in pac1921_probe()
1249 priv->dv_gain = PAC1921_DEFAULT_DV_GAIN; in pac1921_probe()
1250 priv->di_gain = PAC1921_DEFAULT_DI_GAIN; in pac1921_probe()
1251 priv->n_samples = PAC1921_DEFAULT_NUM_SAMPLES; in pac1921_probe()
1253 if (is_acpi_device_node(dev->fwnode)) in pac1921_probe()
1261 if (priv->rshunt_uohm == 0 || priv->rshunt_uohm > INT_MAX) in pac1921_probe()
1262 return dev_err_probe(dev, -EINVAL, in pac1921_probe()
1264 priv->rshunt_uohm); in pac1921_probe()
1268 priv->vdd = devm_regulator_get(dev, "vdd"); in pac1921_probe()
1269 if (IS_ERR(priv->vdd)) in pac1921_probe()
1270 return dev_err_probe(dev, PTR_ERR(priv->vdd), in pac1921_probe()
1273 ret = regulator_enable(priv->vdd); in pac1921_probe()
1278 priv->vdd); in pac1921_probe()
1289 priv->iio_info = pac1921_iio; in pac1921_probe()
1291 indio_dev->name = "pac1921"; in pac1921_probe()
1292 indio_dev->info = &priv->iio_info; in pac1921_probe()
1293 indio_dev->modes = INDIO_DIRECT_MODE; in pac1921_probe()
1294 indio_dev->channels = pac1921_channels; in pac1921_probe()
1295 indio_dev->num_channels = ARRAY_SIZE(pac1921_channels); in pac1921_probe()
1343 MODULE_DESCRIPTION("IIO driver for PAC1921 High-Side Power/Current Monitor");