1 /*
2 * Copyright 2022 Google LLC
3 * Copyright 2023 Microsoft Corporation
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #include <zephyr/device.h>
9 #include <zephyr/drivers/emul.h>
10 #include <zephyr/drivers/emul_fuel_gauge.h>
11 #include <zephyr/drivers/fuel_gauge.h>
12 #include <zephyr/drivers/i2c.h>
13 #include <zephyr/logging/log.h>
14 #include <zephyr/sys/byteorder.h>
15 #include <zephyr/sys/util.h>
16 #include <zephyr/ztest.h>
17 #include <zephyr/ztest_assert.h>
18
19 #include "test_sbs_gauge.h"
20
sbs_gauge_new_api_setup(void)21 static void *sbs_gauge_new_api_setup(void)
22 {
23 static ZTEST_DMEM struct sbs_gauge_new_api_fixture fixture;
24
25 fixture.dev = DEVICE_DT_GET_ANY(sbs_sbs_gauge_new_api);
26 fixture.sbs_fuel_gauge = EMUL_DT_GET(DT_NODELABEL(smartbattery0));
27
28 k_object_access_all_grant(fixture.dev);
29
30 zassert_true(device_is_ready(fixture.dev), "Fuel Gauge not found");
31
32 return &fixture;
33 }
34
ZTEST_USER_F(sbs_gauge_new_api,test_get_some_props_failed_returns_bad_status)35 ZTEST_USER_F(sbs_gauge_new_api, test_get_some_props_failed_returns_bad_status)
36 {
37 fuel_gauge_prop_t prop_types[] = {
38 /* First invalid property */
39 FUEL_GAUGE_PROP_MAX,
40 /* Second invalid property */
41 FUEL_GAUGE_PROP_MAX,
42 /* Valid property */
43 FUEL_GAUGE_VOLTAGE,
44 };
45 union fuel_gauge_prop_val props[ARRAY_SIZE(prop_types)] = {0};
46
47 int ret = fuel_gauge_get_props(fixture->dev, prop_types, props, ARRAY_SIZE(props));
48
49 zassert_equal(ret, -ENOTSUP, "Getting bad property has a good status.");
50 }
51
ZTEST_USER_F(sbs_gauge_new_api,test_set_all_props_failed_returns_err)52 ZTEST_USER_F(sbs_gauge_new_api, test_set_all_props_failed_returns_err)
53 {
54 fuel_gauge_prop_t prop_types[] = {
55 /* Invalid property */
56 FUEL_GAUGE_PROP_MAX,
57 };
58 union fuel_gauge_prop_val props[ARRAY_SIZE(prop_types)] = {0};
59
60 int ret = fuel_gauge_set_props(fixture->dev, prop_types, props, ARRAY_SIZE(props));
61
62 zassert_equal(ret, -ENOTSUP);
63 }
64
ZTEST_USER_F(sbs_gauge_new_api,test_set_some_props_failed_returns_err)65 ZTEST_USER_F(sbs_gauge_new_api, test_set_some_props_failed_returns_err)
66 {
67 fuel_gauge_prop_t prop_types[] = {
68 /* First invalid property */
69 FUEL_GAUGE_PROP_MAX,
70 /* Second invalid property */
71 FUEL_GAUGE_PROP_MAX,
72 /* Valid property */
73 FUEL_GAUGE_SBS_MFR_ACCESS,
74 /* Set Manufacturer's Access to arbitrary word */
75
76 };
77
78 union fuel_gauge_prop_val props[] = {
79 /* First invalid property */
80 {0},
81 /* Second invalid property */
82 {0},
83 /* Valid property */
84 /* Set Manufacturer's Access to arbitrary word */
85 {.sbs_mfr_access_word = 1},
86 };
87
88 int ret = fuel_gauge_set_props(fixture->dev, prop_types, props, ARRAY_SIZE(props));
89
90 zassert_equal(ret, -ENOTSUP);
91 }
92
ZTEST_USER_F(sbs_gauge_new_api,test_set_prop_can_be_get)93 ZTEST_USER_F(sbs_gauge_new_api, test_set_prop_can_be_get)
94 {
95 uint16_t word = BIT(15) | BIT(0);
96
97 fuel_gauge_prop_t prop_types[] = {
98 FUEL_GAUGE_SBS_MFR_ACCESS,
99 FUEL_GAUGE_SBS_REMAINING_CAPACITY_ALARM,
100 FUEL_GAUGE_SBS_REMAINING_TIME_ALARM,
101 FUEL_GAUGE_SBS_MODE,
102 FUEL_GAUGE_SBS_ATRATE,
103 };
104
105 union fuel_gauge_prop_val set_props[] = {
106 {
107 .sbs_mfr_access_word = word,
108 },
109 {
110 .sbs_remaining_capacity_alarm = word,
111 },
112 {
113 .sbs_remaining_time_alarm = word,
114 },
115 {
116 .sbs_mode = word,
117 },
118 {
119 .sbs_at_rate = (int16_t)word,
120 },
121 };
122
123 union fuel_gauge_prop_val get_props[ARRAY_SIZE(prop_types)];
124
125 zassert_ok(
126 fuel_gauge_set_props(fixture->dev, prop_types, set_props, ARRAY_SIZE(set_props)));
127
128 zassert_ok(
129 fuel_gauge_get_props(fixture->dev, prop_types, get_props, ARRAY_SIZE(get_props)));
130
131 zassert_equal(get_props[0].sbs_mfr_access_word, word);
132 zassert_equal(get_props[1].sbs_remaining_capacity_alarm, word);
133 zassert_equal(get_props[2].sbs_remaining_time_alarm, word);
134 zassert_equal(get_props[3].sbs_mode, word);
135 zassert_equal(get_props[4].sbs_at_rate, (int16_t)word);
136 }
137
ZTEST_USER_F(sbs_gauge_new_api,test_get_props__returns_ok)138 ZTEST_USER_F(sbs_gauge_new_api, test_get_props__returns_ok)
139 {
140 /* Validate what props are supported by the driver */
141
142 fuel_gauge_prop_t prop_types[] = {
143 FUEL_GAUGE_VOLTAGE,
144 FUEL_GAUGE_CURRENT,
145 FUEL_GAUGE_AVG_CURRENT,
146 FUEL_GAUGE_TEMPERATURE,
147 FUEL_GAUGE_ABSOLUTE_STATE_OF_CHARGE,
148 FUEL_GAUGE_RELATIVE_STATE_OF_CHARGE,
149 FUEL_GAUGE_RUNTIME_TO_FULL,
150 FUEL_GAUGE_RUNTIME_TO_EMPTY,
151 FUEL_GAUGE_REMAINING_CAPACITY,
152 FUEL_GAUGE_FULL_CHARGE_CAPACITY,
153 FUEL_GAUGE_CYCLE_COUNT,
154 FUEL_GAUGE_SBS_MFR_ACCESS,
155 FUEL_GAUGE_SBS_MODE,
156 FUEL_GAUGE_CHARGE_CURRENT,
157 FUEL_GAUGE_CHARGE_VOLTAGE,
158 FUEL_GAUGE_STATUS,
159 FUEL_GAUGE_DESIGN_CAPACITY,
160 FUEL_GAUGE_DESIGN_VOLTAGE,
161 FUEL_GAUGE_SBS_ATRATE,
162 FUEL_GAUGE_SBS_ATRATE_TIME_TO_FULL,
163 FUEL_GAUGE_SBS_ATRATE_TIME_TO_EMPTY,
164 FUEL_GAUGE_SBS_ATRATE_OK,
165 FUEL_GAUGE_SBS_REMAINING_CAPACITY_ALARM,
166 FUEL_GAUGE_SBS_REMAINING_TIME_ALARM,
167 };
168
169 union fuel_gauge_prop_val props[ARRAY_SIZE(prop_types)] = {0};
170
171 zassert_ok(fuel_gauge_get_props(fixture->dev, prop_types, props, ARRAY_SIZE(props)));
172 }
173
ZTEST_USER_F(sbs_gauge_new_api,test_set_props__returns_ok)174 ZTEST_USER_F(sbs_gauge_new_api, test_set_props__returns_ok)
175 {
176 fuel_gauge_prop_t prop_types[] = {
177 FUEL_GAUGE_SBS_MFR_ACCESS,
178 FUEL_GAUGE_SBS_MODE,
179 FUEL_GAUGE_SBS_ATRATE,
180 FUEL_GAUGE_SBS_REMAINING_TIME_ALARM,
181 FUEL_GAUGE_SBS_REMAINING_CAPACITY_ALARM,
182
183 };
184 union fuel_gauge_prop_val props[ARRAY_SIZE(prop_types)] = {0};
185
186 zassert_ok(fuel_gauge_set_props(fixture->dev, prop_types, props, ARRAY_SIZE(props)));
187 }
188
ZTEST_USER_F(sbs_gauge_new_api,test_get_buffer_props__returns_ok)189 ZTEST_USER_F(sbs_gauge_new_api, test_get_buffer_props__returns_ok)
190 {
191 /* Validate what properties are supported by the driver */
192 struct sbs_gauge_manufacturer_name mfg_name;
193 struct sbs_gauge_device_name dev_name;
194 struct sbs_gauge_device_chemistry chem;
195
196 zassert_ok(fuel_gauge_get_buffer_prop(fixture->dev, FUEL_GAUGE_MANUFACTURER_NAME, &mfg_name,
197 sizeof(mfg_name)));
198
199 zassert_ok(fuel_gauge_get_buffer_prop(fixture->dev, FUEL_GAUGE_DEVICE_NAME, &dev_name,
200 sizeof(dev_name)));
201
202 zassert_ok(fuel_gauge_get_buffer_prop(fixture->dev, FUEL_GAUGE_DEVICE_CHEMISTRY, &chem,
203 sizeof(chem)));
204 }
205
ZTEST_USER_F(sbs_gauge_new_api,test_charging_5v_3a)206 ZTEST_USER_F(sbs_gauge_new_api, test_charging_5v_3a)
207 {
208 uint32_t expected_uV = 5000 * 1000;
209 int32_t expected_uA = 3000 * 1000;
210
211 union fuel_gauge_prop_val voltage;
212 union fuel_gauge_prop_val current;
213
214 zassume_ok(emul_fuel_gauge_set_battery_charging(fixture->sbs_fuel_gauge, expected_uV,
215 expected_uA));
216 zassert_ok(fuel_gauge_get_prop(fixture->dev, FUEL_GAUGE_VOLTAGE, &voltage));
217 zassert_ok(fuel_gauge_get_prop(fixture->dev, FUEL_GAUGE_CURRENT, ¤t));
218
219 zassert_equal(voltage.voltage, expected_uV, "Got %d instead of %d", voltage, expected_uV);
220 zassert_equal(current.current, expected_uA, "Got %d instead of %d", current, expected_uA);
221 }
222
ZTEST_USER_F(sbs_gauge_new_api,test_charging_5v_neg_1a)223 ZTEST_USER_F(sbs_gauge_new_api, test_charging_5v_neg_1a)
224 {
225 uint32_t expected_uV = 5000 * 1000;
226 int32_t expected_uA = -1000 * 1000;
227
228 union fuel_gauge_prop_val voltage;
229 union fuel_gauge_prop_val current;
230
231 zassume_ok(emul_fuel_gauge_set_battery_charging(fixture->sbs_fuel_gauge, expected_uV,
232 expected_uA));
233 zassert_ok(fuel_gauge_get_prop(fixture->dev, FUEL_GAUGE_VOLTAGE, &voltage));
234 zassert_ok(fuel_gauge_get_prop(fixture->dev, FUEL_GAUGE_CURRENT, ¤t));
235
236 zassert_equal(voltage.voltage, expected_uV, "Got %d instead of %d", voltage, expected_uV);
237 zassert_equal(current.current, expected_uA, "Got %d instead of %d", current, expected_uA);
238 }
239
ZTEST_USER_F(sbs_gauge_new_api,test_set_get_single_prop)240 ZTEST_USER_F(sbs_gauge_new_api, test_set_get_single_prop)
241 {
242 uint16_t test_value = 0x1001;
243
244 union fuel_gauge_prop_val mfr_acc_set = {
245 .sbs_mfr_access_word = test_value,
246 };
247 union fuel_gauge_prop_val mfr_acc_get;
248
249 zassert_ok(fuel_gauge_set_prop(fixture->dev, FUEL_GAUGE_SBS_MFR_ACCESS, mfr_acc_set));
250 zassert_ok(fuel_gauge_get_prop(fixture->dev, FUEL_GAUGE_SBS_MFR_ACCESS, &mfr_acc_get));
251 zassert_equal(mfr_acc_get.sbs_mfr_access_word, test_value);
252 }
253
254 ZTEST_SUITE(sbs_gauge_new_api, NULL, sbs_gauge_new_api_setup, NULL, NULL, NULL);
255