1 /*
2  * Copyright (c) 2022 Google LLC
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /* PI3USB9201 USB BC 1.2 Charger Detector driver. */
8 
9 #define DT_DRV_COMPAT diodes_pi3usb9201
10 
11 #include <zephyr/device.h>
12 #include <zephyr/drivers/gpio.h>
13 #include <zephyr/drivers/i2c.h>
14 #include <zephyr/drivers/usb/usb_bc12.h>
15 #include <zephyr/logging/log.h>
16 #include "bc12_pi3usb9201.h"
17 
18 LOG_MODULE_REGISTER(PI3USB9201, CONFIG_USB_BC12_LOG_LEVEL);
19 
20 /* Constant configuration data */
21 struct pi3usb9201_config {
22 	struct i2c_dt_spec i2c;
23 
24 	struct gpio_dt_spec intb_gpio;
25 
26 	enum bc12_type charging_mode;
27 };
28 
29 /* Run-time configuration data */
30 struct pi3usb9201_data {
31 	const struct device *dev;
32 	struct k_work work;
33 	struct bc12_partner_state partner_state;
34 	struct gpio_callback gpio_cb;
35 
36 	bc12_callback_t result_cb;
37 	void *result_cb_data;
38 };
39 
40 enum pi3usb9201_client_sts {
41 	CHG_OTHER = 0,
42 	CHG_2_4A = 1,
43 	CHG_2_0A = 2,
44 	CHG_1_0A = 3,
45 	CHG_RESERVED = 4,
46 	CHG_CDP = 5,
47 	CHG_SDP = 6,
48 	CHG_DCP = 7,
49 };
50 
51 struct bc12_status {
52 	enum bc12_type partner_type;
53 	int current_limit;
54 };
55 
56 /*
57  * The USB Type-C specification limits the maximum amount of current from BC 1.2
58  * suppliers to 1.5A.  Technically, proprietary methods are not allowed, but we
59  * will continue to allow those.
60  */
61 static const struct bc12_status bc12_chg_limits[] = {
62 	/* For unknown chargers return Isusp. */
63 	[CHG_OTHER] = {BC12_TYPE_PROPRIETARY, BC12_CURR_UA(BC12_CHARGER_MIN_CURR_UA)},
64 	[CHG_2_4A] = {BC12_TYPE_PROPRIETARY, BC12_CURR_UA(2400000)},
65 	[CHG_2_0A] = {BC12_TYPE_PROPRIETARY, BC12_CURR_UA(2000000)},
66 	[CHG_1_0A] = {BC12_TYPE_PROPRIETARY, BC12_CURR_UA(1000000)},
67 	[CHG_RESERVED] = {BC12_TYPE_NONE, 0},
68 	[CHG_CDP] = {BC12_TYPE_CDP, BC12_CURR_UA(1500000)},
69 	/* BC1.2 driver contract specifies to return Isusp for SDP ports. */
70 	[CHG_SDP] = {BC12_TYPE_SDP, BC12_CURR_UA(BC12_CHARGER_MIN_CURR_UA)},
71 	[CHG_DCP] = {BC12_TYPE_DCP, BC12_CURR_UA(1500000)},
72 };
73 
74 static const enum pi3usb9201_mode charging_mode_to_host_mode[] = {
75 	[BC12_TYPE_NONE] = PI3USB9201_POWER_DOWN,
76 	[BC12_TYPE_SDP] = PI3USB9201_SDP_HOST_MODE,
77 	[BC12_TYPE_DCP] = PI3USB9201_DCP_HOST_MODE,
78 	[BC12_TYPE_CDP] = PI3USB9201_CDP_HOST_MODE,
79 
80 	/* Invalid modes configured to power down the device. */
81 	[BC12_TYPE_PROPRIETARY] = PI3USB9201_POWER_DOWN,
82 	[BC12_TYPE_UNKNOWN] = PI3USB9201_POWER_DOWN,
83 };
84 BUILD_ASSERT(ARRAY_SIZE(charging_mode_to_host_mode) == BC12_TYPE_COUNT);
85 
pi3usb9201_interrupt_enable(const struct device * dev,const bool enable)86 static int pi3usb9201_interrupt_enable(const struct device *dev, const bool enable)
87 {
88 	const struct pi3usb9201_config *cfg = dev->config;
89 
90 	/* Clear the interrupt mask bit to enable the interrupt */
91 	return i2c_reg_update_byte_dt(&cfg->i2c, PI3USB9201_REG_CTRL_1,
92 				      PI3USB9201_REG_CTRL_1_INT_MASK,
93 				      enable ? 0 : PI3USB9201_REG_CTRL_1_INT_MASK);
94 }
95 
pi3usb9201_bc12_detect_ctrl(const struct device * dev,const bool enable)96 static int pi3usb9201_bc12_detect_ctrl(const struct device *dev, const bool enable)
97 {
98 	const struct pi3usb9201_config *cfg = dev->config;
99 
100 	return i2c_reg_update_byte_dt(&cfg->i2c, PI3USB9201_REG_CTRL_2,
101 				      PI3USB9201_REG_CTRL_2_START_DET,
102 				      enable ? PI3USB9201_REG_CTRL_2_START_DET : 0);
103 }
104 
pi3usb9201_bc12_usb_switch(const struct device * dev,bool enable)105 static int pi3usb9201_bc12_usb_switch(const struct device *dev, bool enable)
106 {
107 	const struct pi3usb9201_config *cfg = dev->config;
108 
109 	/* USB data switch enabled when PI3USB9201_REG_CTRL_2_AUTO_SW is clear */
110 	return i2c_reg_update_byte_dt(&cfg->i2c, PI3USB9201_REG_CTRL_2,
111 				      PI3USB9201_REG_CTRL_2_START_DET,
112 				      enable ? 0 : PI3USB9201_REG_CTRL_2_AUTO_SW);
113 }
114 
pi3usb9201_set_mode(const struct device * dev,enum pi3usb9201_mode mode)115 static int pi3usb9201_set_mode(const struct device *dev, enum pi3usb9201_mode mode)
116 {
117 	const struct pi3usb9201_config *cfg = dev->config;
118 
119 	return i2c_reg_update_byte_dt(&cfg->i2c, PI3USB9201_REG_CTRL_1,
120 				      PI3USB9201_REG_CTRL_1_MODE_MASK
121 					      << PI3USB9201_REG_CTRL_1_MODE_SHIFT,
122 				      mode << PI3USB9201_REG_CTRL_1_MODE_SHIFT);
123 }
124 
pi3usb9201_get_mode(const struct device * dev,enum pi3usb9201_mode * const mode)125 static int pi3usb9201_get_mode(const struct device *dev, enum pi3usb9201_mode *const mode)
126 {
127 	const struct pi3usb9201_config *cfg = dev->config;
128 	int rv;
129 	uint8_t ctrl1;
130 
131 	rv = i2c_reg_read_byte_dt(&cfg->i2c, PI3USB9201_REG_CTRL_1, &ctrl1);
132 	if (rv < 0) {
133 		return rv;
134 	}
135 
136 	ctrl1 >>= PI3USB9201_REG_CTRL_1_MODE_SHIFT;
137 	ctrl1 &= PI3USB9201_REG_CTRL_1_MODE_MASK;
138 	*mode = ctrl1;
139 
140 	return 0;
141 }
142 
pi3usb9201_get_status(const struct device * dev,uint8_t * const client,uint8_t * const host)143 static int pi3usb9201_get_status(const struct device *dev, uint8_t *const client,
144 				 uint8_t *const host)
145 {
146 	const struct pi3usb9201_config *cfg = dev->config;
147 	uint8_t status;
148 	int rv;
149 
150 	rv = i2c_reg_read_byte_dt(&cfg->i2c, PI3USB9201_REG_CLIENT_STS, &status);
151 	if (rv < 0) {
152 		return rv;
153 	}
154 
155 	if (client != NULL) {
156 		*client = status;
157 	}
158 
159 	rv = i2c_reg_read_byte_dt(&cfg->i2c, PI3USB9201_REG_HOST_STS, &status);
160 	if (rv < 0) {
161 		return rv;
162 	}
163 
164 	if (host != NULL) {
165 		*host = status;
166 	}
167 
168 	return 0;
169 }
170 
pi3usb9201_notify_callback(const struct device * dev,struct bc12_partner_state * const state)171 static void pi3usb9201_notify_callback(const struct device *dev,
172 				       struct bc12_partner_state *const state)
173 {
174 	struct pi3usb9201_data *pi3usb9201_data = dev->data;
175 
176 	if (pi3usb9201_data->result_cb) {
177 		pi3usb9201_data->result_cb(dev, state, pi3usb9201_data->result_cb_data);
178 	}
179 }
180 
pi3usb9201_partner_has_changed(const struct device * dev,struct bc12_partner_state * const state)181 static bool pi3usb9201_partner_has_changed(const struct device *dev,
182 					   struct bc12_partner_state *const state)
183 {
184 	struct pi3usb9201_data *pi3usb9201_data = dev->data;
185 
186 	/* Always notify when clearing out partner state */
187 	if (!state) {
188 		return true;
189 	}
190 
191 	if (state->bc12_role != pi3usb9201_data->partner_state.bc12_role) {
192 		return true;
193 	}
194 
195 	if (state->bc12_role == BC12_PORTABLE_DEVICE &&
196 	    pi3usb9201_data->partner_state.type != state->type) {
197 		return true;
198 	}
199 
200 	if (state->bc12_role == BC12_CHARGING_PORT &&
201 	    pi3usb9201_data->partner_state.pd_partner_connected != state->pd_partner_connected) {
202 		return true;
203 	}
204 
205 	return false;
206 }
207 
208 /**
209  * @brief Notify the application about changes to the BC1.2 partner.
210  *
211  * @param dev BC1.2 device instance
212  * @param state New partner state information.  Set to NULL to indicate no
213  * partner is connected.
214  */
pi3usb9201_update_charging_partner(const struct device * dev,struct bc12_partner_state * const state)215 static void pi3usb9201_update_charging_partner(const struct device *dev,
216 					       struct bc12_partner_state *const state)
217 {
218 	struct pi3usb9201_data *pi3usb9201_data = dev->data;
219 
220 	if (!pi3usb9201_partner_has_changed(dev, state)) {
221 		/* No change to the partner */
222 		return;
223 	}
224 
225 	if (state) {
226 		/* Now update callback with the new partner type. */
227 		pi3usb9201_data->partner_state = *state;
228 		pi3usb9201_notify_callback(dev, state);
229 	} else {
230 		pi3usb9201_data->partner_state.bc12_role = BC12_DISCONNECTED;
231 		pi3usb9201_notify_callback(dev, NULL);
232 	}
233 }
234 
pi3usb9201_client_detect_start(const struct device * dev)235 static int pi3usb9201_client_detect_start(const struct device *dev)
236 {
237 	int rv;
238 
239 	/*
240 	 * Read both status registers to ensure that all interrupt indications
241 	 * are cleared prior to starting bc1.2 detection.
242 	 */
243 	pi3usb9201_get_status(dev, NULL, NULL);
244 
245 	/* Put pi3usb9201 into client mode */
246 	rv = pi3usb9201_set_mode(dev, PI3USB9201_CLIENT_MODE);
247 	if (rv < 0) {
248 		return rv;
249 	}
250 
251 	/* Have pi3usb9201 start bc1.2 detection */
252 	rv = pi3usb9201_bc12_detect_ctrl(dev, true);
253 	if (rv < 0) {
254 		return rv;
255 	}
256 
257 	/* Enable interrupt to wake task when detection completes */
258 	return pi3usb9201_interrupt_enable(dev, true);
259 }
260 
pi3usb9201_client_detect_finish(const struct device * dev,const int status)261 static void pi3usb9201_client_detect_finish(const struct device *dev, const int status)
262 {
263 	struct bc12_partner_state new_partner_state;
264 	int bit_pos;
265 	bool enable_usb_data;
266 
267 	new_partner_state.bc12_role = BC12_PORTABLE_DEVICE;
268 
269 	/* Set charge voltage to 5V */
270 	new_partner_state.voltage_uv = BC12_CHARGER_VOLTAGE_UV;
271 
272 	/*
273 	 * Find set bit position. Note that this function is only called if a
274 	 * bit was set in client_status, so bit_pos won't be negative.
275 	 */
276 	bit_pos = __builtin_ffs(status) - 1;
277 
278 	new_partner_state.current_ua = bc12_chg_limits[bit_pos].current_limit;
279 	new_partner_state.type = bc12_chg_limits[bit_pos].partner_type;
280 
281 	LOG_DBG("client status = 0x%x, current = %d mA, type = %d",
282 		status, new_partner_state.current_ua, new_partner_state.type);
283 
284 	/* bc1.2 is complete and start bit does not auto clear */
285 	if (pi3usb9201_bc12_detect_ctrl(dev, false) < 0) {
286 		LOG_ERR("failed to clear client detect");
287 	}
288 
289 	/* If DCP mode, disable USB swtich */
290 	if (status & BIT(CHG_DCP)) {
291 		enable_usb_data = false;
292 	} else {
293 		enable_usb_data = true;
294 	}
295 	if (pi3usb9201_bc12_usb_switch(dev, enable_usb_data) < 0) {
296 		LOG_ERR("failed to set USB data mode");
297 	}
298 
299 	/* Inform charge manager of new supplier type and current limit */
300 	pi3usb9201_update_charging_partner(dev, &new_partner_state);
301 }
302 
pi3usb9201_host_interrupt(const struct device * dev,uint8_t host_status)303 static void pi3usb9201_host_interrupt(const struct device *dev, uint8_t host_status)
304 {
305 	const struct pi3usb9201_config *pi3usb9201_config = dev->config;
306 	struct bc12_partner_state partner_state;
307 
308 	switch (pi3usb9201_config->charging_mode) {
309 	case BC12_TYPE_NONE:
310 		/*
311 		 * For USB-C connections, enable the USB data path
312 		 * TODO - Provide a devicetree property indicating
313 		 * whether the USB data path is supported.
314 		 */
315 		pi3usb9201_set_mode(dev, PI3USB9201_USB_PATH_ON);
316 		break;
317 	case BC12_TYPE_CDP:
318 		if (IS_ENABLED(CONFIG_USB_BC12_PI3USB9201_CDP_ERRATA)) {
319 			/*
320 			 * Switch to SDP after device is plugged in to avoid
321 			 * noise (pulse on D-) causing USB disconnect
322 			 */
323 			if (host_status & PI3USB9201_REG_HOST_STS_DEV_PLUG) {
324 				pi3usb9201_set_mode(dev, PI3USB9201_SDP_HOST_MODE);
325 			}
326 			/*
327 			 * Switch to CDP after device is unplugged so we
328 			 * advertise higher power available for next device.
329 			 */
330 			if (host_status & PI3USB9201_REG_HOST_STS_DEV_UNPLUG) {
331 				pi3usb9201_set_mode(dev, PI3USB9201_CDP_HOST_MODE);
332 			}
333 		}
334 		__fallthrough;
335 	case BC12_TYPE_SDP:
336 		/* Plug/unplug events only valid for CDP and SDP modes */
337 		if (host_status & PI3USB9201_REG_HOST_STS_DEV_PLUG) {
338 			partner_state.bc12_role = BC12_CHARGING_PORT;
339 			partner_state.pd_partner_connected = true;
340 			pi3usb9201_update_charging_partner(dev, &partner_state);
341 		}
342 		if (host_status & PI3USB9201_REG_HOST_STS_DEV_UNPLUG) {
343 			partner_state.bc12_role = BC12_CHARGING_PORT;
344 			partner_state.pd_partner_connected = false;
345 			pi3usb9201_update_charging_partner(dev, &partner_state);
346 		}
347 		break;
348 	default:
349 		break;
350 	}
351 }
352 
pi3usb9201_disconnect(const struct device * dev)353 static int pi3usb9201_disconnect(const struct device *dev)
354 {
355 	int rv;
356 
357 	/* Ensure USB switch auto-on is enabled */
358 	rv = pi3usb9201_bc12_usb_switch(dev, true);
359 	if (rv < 0) {
360 		return rv;
361 	}
362 
363 	/* Put pi3usb9201 into its power down mode */
364 	rv = pi3usb9201_set_mode(dev, PI3USB9201_POWER_DOWN);
365 	if (rv < 0) {
366 		return rv;
367 	}
368 
369 	/* The start bc1.2 bit does not auto clear */
370 	rv = pi3usb9201_bc12_detect_ctrl(dev, false);
371 	if (rv < 0) {
372 		return rv;
373 	}
374 
375 	/* Mask interrupts until next bc1.2 detection event */
376 	rv = pi3usb9201_interrupt_enable(dev, false);
377 	if (rv < 0) {
378 		return rv;
379 	}
380 
381 	/*
382 	 * Let the application know there's no more charge available for the
383 	 * supplier type that was most recently detected.
384 	 */
385 	pi3usb9201_update_charging_partner(dev, NULL);
386 
387 	return 0;
388 }
389 
pi3usb9201_set_portable_device(const struct device * dev)390 static int pi3usb9201_set_portable_device(const struct device *dev)
391 {
392 	int rv;
393 
394 	/* Disable interrupts during mode change */
395 	rv = pi3usb9201_interrupt_enable(dev, false);
396 	if (rv < 0) {
397 		return rv;
398 	}
399 
400 	if (pi3usb9201_client_detect_start(dev) < 0) {
401 		struct bc12_partner_state partner_state;
402 
403 		/*
404 		 * VBUS is present, but starting bc1.2 detection failed
405 		 * for some reason. Set the partner type to unknown limit
406 		 * current to the minimum allowed for a suspended USB device.
407 		 */
408 		partner_state.bc12_role = BC12_PORTABLE_DEVICE;
409 		partner_state.voltage_uv = BC12_CHARGER_VOLTAGE_UV;
410 		partner_state.current_ua = BC12_CHARGER_MIN_CURR_UA;
411 		partner_state.type = BC12_TYPE_UNKNOWN;
412 		/* Save supplier type and notify callbacks */
413 		pi3usb9201_update_charging_partner(dev, &partner_state);
414 		LOG_ERR("bc1.2 detection failed, using defaults");
415 
416 		return -EIO;
417 	}
418 
419 	return 0;
420 }
421 
pi3usb9201_set_charging_mode(const struct device * dev)422 static int pi3usb9201_set_charging_mode(const struct device *dev)
423 {
424 	const struct pi3usb9201_config *pi3usb9201_config = dev->config;
425 	struct bc12_partner_state partner_state;
426 	enum pi3usb9201_mode current_mode;
427 	enum pi3usb9201_mode desired_mode;
428 	int rv;
429 
430 	if (pi3usb9201_config->charging_mode == BC12_TYPE_NONE) {
431 		/*
432 		 * For USB-C connections, enable the USB data path when configured
433 		 * as a downstream facing port but charging is disabled.
434 		 *
435 		 * TODO - Provide a devicetree property indicating
436 		 * whether the USB data path is supported.
437 		 */
438 		return pi3usb9201_set_mode(dev, PI3USB9201_USB_PATH_ON);
439 	}
440 
441 	/*
442 	 * When enabling charging mode for this port, clear out information
443 	 * regarding any charging partners.
444 	 */
445 	partner_state.bc12_role = BC12_CHARGING_PORT;
446 	partner_state.pd_partner_connected = false;
447 
448 	pi3usb9201_update_charging_partner(dev, &partner_state);
449 
450 	rv = pi3usb9201_interrupt_enable(dev, false);
451 	if (rv < 0) {
452 		return rv;
453 	}
454 
455 	rv = pi3usb9201_get_mode(dev, &current_mode);
456 	if (rv < 0) {
457 		return rv;
458 	}
459 
460 	desired_mode = charging_mode_to_host_mode[pi3usb9201_config->charging_mode];
461 
462 	if (current_mode != desired_mode) {
463 		LOG_DBG("Set host mode to %d", desired_mode);
464 
465 		/*
466 		 * Read both status registers to ensure that all
467 		 * interrupt indications are cleared prior to starting
468 		 * charging port (host) mode.
469 		 */
470 		rv = pi3usb9201_get_status(dev, NULL, NULL);
471 		if (rv < 0) {
472 			return rv;
473 		}
474 
475 		rv = pi3usb9201_set_mode(dev, desired_mode);
476 		if (rv < 0) {
477 			return rv;
478 		}
479 	}
480 
481 	rv = pi3usb9201_interrupt_enable(dev, true);
482 	if (rv < 0) {
483 		return rv;
484 	}
485 
486 	return 0;
487 }
488 
pi3usb9201_isr_work(struct k_work * item)489 static void pi3usb9201_isr_work(struct k_work *item)
490 {
491 	struct pi3usb9201_data *pi3usb9201_data = CONTAINER_OF(item, struct pi3usb9201_data, work);
492 	const struct device *dev = pi3usb9201_data->dev;
493 	uint8_t client;
494 	uint8_t host;
495 	int rv;
496 
497 	rv = pi3usb9201_get_status(dev, &client, &host);
498 	if (rv < 0) {
499 		LOG_ERR("Failed to get host/client status");
500 		return;
501 	}
502 
503 	if (client != 0) {
504 		/*
505 		 * Any bit set in client status register indicates that
506 		 * BC1.2 detection has completed.
507 		 */
508 		pi3usb9201_client_detect_finish(dev, client);
509 	}
510 
511 	if (host != 0) {
512 		pi3usb9201_host_interrupt(dev, host);
513 	}
514 }
515 
pi3usb9201_gpio_callback(const struct device * dev,struct gpio_callback * cb,uint32_t pins)516 static void pi3usb9201_gpio_callback(const struct device *dev, struct gpio_callback *cb,
517 				     uint32_t pins)
518 {
519 	struct pi3usb9201_data *pi3usb9201_data = CONTAINER_OF(cb, struct pi3usb9201_data, gpio_cb);
520 
521 	k_work_submit(&pi3usb9201_data->work);
522 }
523 
pi3usb9201_set_role(const struct device * dev,const enum bc12_role role)524 static int pi3usb9201_set_role(const struct device *dev, const enum bc12_role role)
525 {
526 	switch (role) {
527 	case BC12_DISCONNECTED:
528 		return pi3usb9201_disconnect(dev);
529 	case BC12_PORTABLE_DEVICE:
530 		return pi3usb9201_set_portable_device(dev);
531 	case BC12_CHARGING_PORT:
532 		return pi3usb9201_set_charging_mode(dev);
533 	default:
534 		LOG_ERR("unsupported BC12 role: %d", role);
535 		return -EINVAL;
536 	}
537 
538 	return 0;
539 }
540 
pi3usb9201_set_result_cb(const struct device * dev,bc12_callback_t cb,void * const user_data)541 int pi3usb9201_set_result_cb(const struct device *dev, bc12_callback_t cb, void *const user_data)
542 {
543 	struct pi3usb9201_data *pi3usb9201_data = dev->data;
544 
545 	pi3usb9201_data->result_cb = cb;
546 	pi3usb9201_data->result_cb_data = user_data;
547 
548 	return 0;
549 }
550 
551 static DEVICE_API(bc12, pi3usb9201_driver_api) = {
552 	.set_role = pi3usb9201_set_role,
553 	.set_result_cb = pi3usb9201_set_result_cb,
554 };
555 
pi3usb9201_init(const struct device * dev)556 static int pi3usb9201_init(const struct device *dev)
557 {
558 	const struct pi3usb9201_config *cfg = dev->config;
559 	struct pi3usb9201_data *pi3usb9201_data = dev->data;
560 	int rv;
561 
562 	if (!i2c_is_ready_dt(&cfg->i2c)) {
563 		LOG_ERR("Bus device is not ready.");
564 		return -ENODEV;
565 	}
566 
567 	if (!gpio_is_ready_dt(&cfg->intb_gpio)) {
568 		LOG_ERR("intb_gpio device is not ready.");
569 		return -ENODEV;
570 	}
571 
572 	pi3usb9201_data->dev = dev;
573 
574 	/*
575 	 * Set most recent bc1.2 detection type result to
576 	 * BC12_DISCONNECTED for the port.
577 	 */
578 	pi3usb9201_data->partner_state.bc12_role = BC12_DISCONNECTED;
579 
580 	rv = gpio_pin_configure_dt(&cfg->intb_gpio, GPIO_INPUT);
581 	if (rv < 0) {
582 		LOG_DBG("Failed to set gpio callback.");
583 		return rv;
584 	}
585 
586 	gpio_init_callback(&pi3usb9201_data->gpio_cb, pi3usb9201_gpio_callback,
587 			   BIT(cfg->intb_gpio.pin));
588 	k_work_init(&pi3usb9201_data->work, pi3usb9201_isr_work);
589 
590 	rv = gpio_add_callback(cfg->intb_gpio.port, &pi3usb9201_data->gpio_cb);
591 	if (rv < 0) {
592 		LOG_DBG("Failed to set gpio callback.");
593 		return rv;
594 	}
595 
596 	rv = gpio_pin_interrupt_configure_dt(&cfg->intb_gpio, GPIO_INT_EDGE_FALLING);
597 	if (rv < 0) {
598 		LOG_DBG("Failed to configure gpio interrupt.");
599 		return rv;
600 	}
601 
602 	/*
603 	 * The is no specific initialization required for the pi3usb9201 other
604 	 * than disabling the interrupt.
605 	 */
606 	return pi3usb9201_interrupt_enable(dev, false);
607 }
608 
609 #define PI2USB9201_DEFINE(inst)                                                                    \
610 	static struct pi3usb9201_data pi3usb9201_data_##inst;                                      \
611                                                                                                    \
612 	static const struct pi3usb9201_config pi3usb9201_config_##inst = {                         \
613 		.i2c = I2C_DT_SPEC_INST_GET(inst),                                                 \
614 		.intb_gpio = GPIO_DT_SPEC_INST_GET(inst, intb_gpios),                              \
615 		.charging_mode = DT_INST_STRING_UPPER_TOKEN(inst, charging_mode),                  \
616 	};                                                                                         \
617                                                                                                    \
618 	DEVICE_DT_INST_DEFINE(inst, pi3usb9201_init, NULL, &pi3usb9201_data_##inst,                \
619 			      &pi3usb9201_config_##inst, POST_KERNEL,                              \
620 			      CONFIG_APPLICATION_INIT_PRIORITY, &pi3usb9201_driver_api);
621 
622 DT_INST_FOREACH_STATUS_OKAY(PI2USB9201_DEFINE)
623