1 /*
2  * Copyright (c) 2023 The ChromiumOS Authors
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <stdio.h>
8 #include <zephyr/kernel.h>
9 #include <zephyr/drivers/adc.h>
10 #include <zephyr/drivers/adc/voltage_divider.h>
11 #include <zephyr/drivers/adc/current_sense_amplifier.h>
12 
13 /* The devicetree node identifier for the adc aliases. */
14 #define VBUS_V_MEAS_NODE DT_ALIAS(vbus)
15 #define VBUS_C_MEAS_NODE DT_ALIAS(cbus)
16 
17 static const struct voltage_divider_dt_spec adc_vbus_v =
18 	VOLTAGE_DIVIDER_DT_SPEC_GET(VBUS_V_MEAS_NODE);
19 static const struct current_sense_amplifier_dt_spec adc_vbus_c =
20 	CURRENT_SENSE_AMPLIFIER_DT_SPEC_GET(VBUS_C_MEAS_NODE);
21 
meas_vbus_v(int32_t * v)22 int meas_vbus_v(int32_t *v)
23 {
24 	int ret;
25 	int32_t sample_buffer = 0;
26 
27 	/* Structure defining an ADC sampling sequence */
28 	struct adc_sequence sequence = {
29 		.buffer = &sample_buffer,
30 		/* buffer size in bytes, not number of samples */
31 		.buffer_size = sizeof(sample_buffer),
32 		.calibrate = true,
33 	};
34 	adc_sequence_init_dt(&adc_vbus_v.port, &sequence);
35 
36 	ret = adc_read_dt(&adc_vbus_v.port, &sequence);
37 	if (ret != 0) {
38 		return ret;
39 	}
40 
41 	*v = sample_buffer;
42 	ret = adc_raw_to_millivolts_dt(&adc_vbus_v.port, v);
43 	if (ret != 0) {
44 		return ret;
45 	}
46 
47 	ret = voltage_divider_scale_dt(&adc_vbus_v, v);
48 	if (ret != 0) {
49 		return ret;
50 	}
51 
52 	return 0;
53 }
54 
meas_vbus_c(int32_t * c)55 int meas_vbus_c(int32_t *c)
56 {
57 	int ret;
58 	int32_t sample_buffer = 0;
59 
60 	/* Structure defining an ADC sampling sequence */
61 	struct adc_sequence sequence = {
62 		.buffer = &sample_buffer,
63 		/* buffer size in bytes, not number of samples */
64 		.buffer_size = sizeof(sample_buffer),
65 		.calibrate = true,
66 	};
67 	adc_sequence_init_dt(&adc_vbus_c.port, &sequence);
68 
69 	ret = adc_read(adc_vbus_c.port.dev, &sequence);
70 	if (ret != 0) {
71 		return ret;
72 	}
73 
74 	*c = sample_buffer;
75 	ret = adc_raw_to_millivolts_dt(&adc_vbus_c.port, c);
76 	if (ret != 0) {
77 		return ret;
78 	}
79 
80 	/* prescaling the voltage offset */
81 	*c -= adc_vbus_c.port.vref_mv / 2;
82 	current_sense_amplifier_scale_dt(&adc_vbus_c, c);
83 
84 	return 0;
85 }
86 
meas_init(void)87 int meas_init(void)
88 {
89 	int ret;
90 
91 	ret = adc_channel_setup_dt(&adc_vbus_v.port);
92 	if (ret != 0) {
93 		return ret;
94 	}
95 
96 	ret = adc_channel_setup_dt(&adc_vbus_c.port);
97 	if (ret != 0) {
98 		return ret;
99 	}
100 
101 	return 0;
102 }
103