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, &current));
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, &current));
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