1 /*
2  * Copyright (c) 2023 The ChromiumOS Authors
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef ZEPHYR_INCLUDE_DRIVERS_ADC_CURRENT_SENSE_AMPLIFIER_H_
8 #define ZEPHYR_INCLUDE_DRIVERS_ADC_CURRENT_SENSE_AMPLIFIER_H_
9 
10 #include <zephyr/drivers/adc.h>
11 #include <zephyr/drivers/gpio.h>
12 
13 struct current_sense_amplifier_dt_spec {
14 	const struct adc_dt_spec port;
15 	uint32_t sense_micro_ohms;
16 	uint32_t sense_gain_mult;
17 	uint32_t sense_gain_div;
18 	struct gpio_dt_spec power_gpio;
19 };
20 
21 /**
22  * @brief Get current sensor information from devicetree.
23  *
24  * This returns a static initializer for a @p current_sense_amplifier_dt_spec structure
25  * given a devicetree node.
26  *
27  * @param node_id Devicetree node identifier.
28  *
29  * @return Static initializer for an current_sense_amplifier_dt_spec structure.
30  */
31 #define CURRENT_SENSE_AMPLIFIER_DT_SPEC_GET(node_id)                                               \
32 	{                                                                                          \
33 		.port = ADC_DT_SPEC_GET(node_id),                                                  \
34 		.sense_micro_ohms = DT_PROP(node_id, sense_resistor_micro_ohms),                   \
35 		.sense_gain_mult = DT_PROP(node_id, sense_gain_mult),                              \
36 		.sense_gain_div = DT_PROP(node_id, sense_gain_div),                                \
37 		.power_gpio = GPIO_DT_SPEC_GET_OR(node_id, power_gpios, {0}),                      \
38 	}
39 
40 /**
41  * @brief Calculates the actual amperage from the measured voltage
42  *
43  * @param[in] spec current sensor specification from Devicetree.
44  * @param[in,out] v_to_i Pointer to the measured voltage in millivolts on input, and the
45  * corresponding scaled current value in milliamps on output.
46  */
47 static inline void
current_sense_amplifier_scale_dt(const struct current_sense_amplifier_dt_spec * spec,int32_t * v_to_i)48 current_sense_amplifier_scale_dt(const struct current_sense_amplifier_dt_spec *spec,
49 				 int32_t *v_to_i)
50 {
51 	/* store in a temporary 64 bit variable to prevent overflow during calculation */
52 	int64_t tmp = *v_to_i;
53 
54 	/* multiplies by 1,000,000 before dividing by sense resistance in micro-ohms. */
55 	tmp = tmp * 1000000 / spec->sense_micro_ohms * spec->sense_gain_div / spec->sense_gain_mult;
56 
57 	*v_to_i = (int32_t)tmp;
58 }
59 
60 #endif /* ZEPHYR_INCLUDE_DRIVERS_ADC_CURRENT_SENSE_AMPLIFIER_H_ */
61