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