1 /*
2  * Copyright (c) 2024 SILA Embedded Solutions GmbH
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT infineon_tle9104
8 
9 #include <errno.h>
10 #include <zephyr/kernel.h>
11 #include <zephyr/device.h>
12 #include <zephyr/init.h>
13 #include <zephyr/drivers/gpio.h>
14 #include <zephyr/drivers/mfd/tle9104.h>
15 #include <zephyr/drivers/spi.h>
16 #include <zephyr/logging/log.h>
17 #include <zephyr/sys/byteorder.h>
18 
19 /*
20  * The values for the defines below as well as the register definitions were
21  * taken from the datasheet, which can be found at:
22  * https://www.infineon.com/dgdl/Infineon-TLE9104SH-DataSheet-v01_31-EN.pdf?fileId=5546d462766cbe86017676144d76581b
23  */
24 #define TLE9104_RESET_DURATION_TIME_US                    10
25 #define TLE9104_RESET_DURATION_WAIT_TIME_SAFETY_MARGIN_US 200
26 #define TLE9104_RESET_DURATION_WAIT_TIME_US               10
27 #define TLE9104_INITIALIZATION_TIMEOUT_MS                 1
28 #define TLE9104_ICVERSIONID                               0xB1
29 
30 #define TLE9104_FRAME_RW_POS                 15
31 #define TLE9104_FRAME_PARITY_POS             14
32 #define TLE9104_FRAME_FAULTCOMMUNICATION_POS 13
33 #define TLE9104_FRAME_FAULTGLOBAL_POS        12
34 #define TLE9104_FRAME_ADDRESS_POS            8
35 #define TLE9104_FRAME_DATA_POS               0
36 
37 #define TLE9104_CFG_CWDTIME_LENGTH 2
38 #define TLE9104_CFG_CWDTIME_POS    6
39 #define TLE9104_CFG_OUT34PAR_POS   5
40 #define TLE9104_CFG_OUT12PAR_POS   4
41 
42 #define TLE9104_OFFDIAGCFG_DIAGFILTCFG_LENGTH 2
43 #define TLE9104_OFFDIAGCFG_DIAGFILTCFG_POS    4
44 #define TLE9104_OFFDIAGCFG_OUT4DIAGEN_BIT     BIT(3)
45 #define TLE9104_OFFDIAGCFG_OUT3DIAGEN_BIT     BIT(2)
46 #define TLE9104_OFFDIAGCFG_OUT2DIAGEN_BIT     BIT(1)
47 #define TLE9104_OFFDIAGCFG_OUT1DIAGEN_BIT     BIT(0)
48 
49 #define TLE9104_ONDIAGCFG_OCFILTCFG_LENGTH 3
50 #define TLE9104_ONDIAGCFG_OCFILTCFG_POS    2
51 #define TLE9104_ONDIAGCFG_OCTH_LENGTH      2
52 #define TLE9104_ONDIAGCFG_OCTH_POS         0
53 
54 #define TLE9104_DIAGOUT12ON_OUT2STAT_BIT     BIT(7)
55 #define TLE9104_DIAGOUT12ON_OUT1STAT_BIT     BIT(6)
56 #define TLE9104_DIAGOUT12ON_DIAGCH2ON_LENGTH 3
57 #define TLE9104_DIAGOUT12ON_DIAGCH2ON_POS    3
58 #define TLE9104_DIAGOUT12ON_DIAGCH1ON_LENGTH 3
59 #define TLE9104_DIAGOUT12ON_DIAGCH1ON_POS    0
60 
61 #define TLE9104_DIAGOUT34ON_OUT4STAT_BIT     BIT(7)
62 #define TLE9104_DIAGOUT34ON_OUT3STAT_BIT     BIT(6)
63 #define TLE9104_DIAGOUT34ON_DIAGCH4ON_LENGTH 3
64 #define TLE9104_DIAGOUT34ON_DIAGCH4ON_POS    3
65 #define TLE9104_DIAGOUT34ON_DIAGCH3ON_LENGTH 3
66 #define TLE9104_DIAGOUT34ON_DIAGCH3ON_POS    0
67 
68 #define TLE9104_DIAGOFF_DIAGCH4OFF_LENGTH 2
69 #define TLE9104_DIAGOFF_DIAGCH4OFF_POS    6
70 #define TLE9104_DIAGOFF_DIAGCH3OFF_LENGTH 2
71 #define TLE9104_DIAGOFF_DIAGCH3OFF_POS    4
72 #define TLE9104_DIAGOFF_DIAGCH2OFF_LENGTH 2
73 #define TLE9104_DIAGOFF_DIAGCH2OFF_POS    2
74 #define TLE9104_DIAGOFF_DIAGCH1OFF_LENGTH 2
75 #define TLE9104_DIAGOFF_DIAGCH1OFF_POS    0
76 
77 #define TLE9104_CTRL_OUT1ONS_BIT                BIT(1)
78 #define TLE9104_CTRL_OUT1ONC_BIT                BIT(0)
79 #define TLE9104_CFG_OUT1DD_BIT                  BIT(0)
80 #define TLE9104_GLOBALSTATUS_OUTEN_BIT          BIT(7)
81 #define TLE9104_GLOBALSTATUS_POR_LATCH_BIT      BIT(0)
82 #define TLE9104_SPIFRAME_FAULTCOMMUNICATION_BIT BIT(13)
83 
84 enum tle9104_register {
85 	TLE9104REGISTER_CTRL = 0x00,
86 	TLE9104REGISTER_CFG = 0x01,
87 	TLE9104REGISTER_OFFDIAGCFG = 0x02,
88 	TLE9104REGISTER_ONDIAGCFG = 0x03,
89 	TLE9104REGISTER_DIAGOUT12ON = 0x04,
90 	TLE9104REGISTER_DIAGOUT34ON = 0x05,
91 	TLE9104REGISTER_DIAGOFF = 0x06,
92 	TLE9104REGISTER_GLOBALSTATUS = 0x07,
93 	TLE9104REGISTER_ICVID = 0x08,
94 };
95 
96 LOG_MODULE_REGISTER(infineon_tle9104, CONFIG_MFD_LOG_LEVEL);
97 
98 struct tle9104_config {
99 	struct spi_dt_spec bus;
100 	const struct gpio_dt_spec gpio_reset;
101 	const struct gpio_dt_spec gpio_enable;
102 	const struct gpio_dt_spec gpio_control[TLE9104_GPIO_COUNT];
103 	uint16_t diagnostic_filter_time;
104 	uint16_t overcurrent_shutdown_delay_time;
105 	uint16_t overcurrent_shutdown_threshold;
106 	bool parallel_mode_out12;
107 	bool parallel_mode_out34;
108 };
109 
110 struct tle9104_data {
111 	/* communication watchdog is getting ignored */
112 	bool cwd_ignore;
113 	/* each bit is one output channel, bit 0 = OUT1, ... */
114 	uint8_t previous_state;
115 	struct k_mutex lock;
116 };
117 
tle9104_set_register_bits(uint8_t * destination,uint8_t pos,uint8_t length,uint8_t value)118 static void tle9104_set_register_bits(uint8_t *destination, uint8_t pos, uint8_t length,
119 				      uint8_t value)
120 {
121 	*destination &= ~GENMASK(pos + length - 1, pos);
122 	*destination |= FIELD_PREP(GENMASK(pos + length - 1, pos), value);
123 }
124 
tle9104_get_register_bits(uint8_t value,uint8_t pos,uint8_t length)125 static uint8_t tle9104_get_register_bits(uint8_t value, uint8_t pos, uint8_t length)
126 {
127 	return FIELD_GET(GENMASK(pos + length - 1, pos), value);
128 }
129 
tle9104_calculate_parity(uint16_t value)130 static int tle9104_calculate_parity(uint16_t value)
131 {
132 	int parity = 1 + POPCOUNT(value);
133 
134 	if ((value & BIT(TLE9104_FRAME_PARITY_POS)) != 0) {
135 		parity--;
136 	}
137 
138 	return parity % 2;
139 }
140 
tle9104_apply_parity(uint16_t * value)141 static void tle9104_apply_parity(uint16_t *value)
142 {
143 	int parity = tle9104_calculate_parity(*value);
144 
145 	WRITE_BIT(*value, TLE9104_FRAME_PARITY_POS, parity);
146 }
147 
tle9104_check_parity(uint16_t value)148 static bool tle9104_check_parity(uint16_t value)
149 {
150 	int parity = tle9104_calculate_parity(value);
151 
152 	return ((value & BIT(TLE9104_FRAME_PARITY_POS)) >> TLE9104_FRAME_PARITY_POS) == parity;
153 }
154 
tle9104_transceive_frame(const struct device * dev,bool write,enum tle9104_register write_reg,uint8_t write_data,enum tle9104_register * read_reg,uint8_t * read_data)155 static int tle9104_transceive_frame(const struct device *dev, bool write,
156 				    enum tle9104_register write_reg, uint8_t write_data,
157 				    enum tle9104_register *read_reg, uint8_t *read_data)
158 {
159 	const struct tle9104_config *config = dev->config;
160 	struct tle9104_data *data = dev->data;
161 	uint16_t write_frame;
162 	uint16_t read_frame;
163 	int result;
164 	uint8_t buffer_tx[2];
165 	uint8_t buffer_rx[ARRAY_SIZE(buffer_tx)];
166 	const struct spi_buf tx_buf[] = {{
167 		.buf = buffer_tx,
168 		.len = ARRAY_SIZE(buffer_tx),
169 	}};
170 	const struct spi_buf rx_buf[] = {{
171 		.buf = buffer_rx,
172 		.len = ARRAY_SIZE(buffer_rx),
173 	}};
174 	const struct spi_buf_set tx = {
175 		.buffers = tx_buf,
176 		.count = ARRAY_SIZE(tx_buf),
177 	};
178 	const struct spi_buf_set rx = {
179 		.buffers = rx_buf,
180 		.count = ARRAY_SIZE(rx_buf),
181 	};
182 
183 	write_frame = write_data << TLE9104_FRAME_DATA_POS;
184 	write_frame |= write_reg << TLE9104_FRAME_ADDRESS_POS;
185 	WRITE_BIT(write_frame, TLE9104_FRAME_RW_POS, write);
186 	tle9104_apply_parity(&write_frame);
187 	sys_put_be16(write_frame, buffer_tx);
188 	LOG_DBG("writing in register 0x%02X of TLE9104 value 0x%02X, complete frame 0x%04X",
189 		write_reg, write_data, write_frame);
190 
191 	result = spi_transceive_dt(&config->bus, &tx, &rx);
192 	if (result != 0) {
193 		LOG_ERR("spi_write failed with error %i", result);
194 		return result;
195 	}
196 
197 	read_frame = sys_get_be16(buffer_rx);
198 	LOG_DBG("received complete frame 0x%04X", read_frame);
199 
200 	if (!tle9104_check_parity(read_frame)) {
201 		LOG_ERR("parity check for received frame of TLE9104 failed");
202 		return -EIO;
203 	}
204 
205 	if (!data->cwd_ignore) {
206 		if ((TLE9104_SPIFRAME_FAULTCOMMUNICATION_BIT & read_frame) != 0) {
207 			LOG_WRN("%s: communication fault reported by TLE9104", dev->name);
208 		}
209 	}
210 
211 	*read_reg = FIELD_GET(GENMASK(TLE9104_FRAME_FAULTGLOBAL_POS - 1, TLE9104_FRAME_ADDRESS_POS),
212 			      read_frame);
213 	*read_data = FIELD_GET(GENMASK(TLE9104_FRAME_ADDRESS_POS - 1, TLE9104_FRAME_DATA_POS),
214 			       read_frame);
215 
216 	return 0;
217 }
218 
tle9104_write_register(const struct device * dev,enum tle9104_register reg,uint8_t value)219 static int tle9104_write_register(const struct device *dev, enum tle9104_register reg,
220 				  uint8_t value)
221 {
222 	enum tle9104_register read_reg;
223 	uint8_t read_data;
224 
225 	return tle9104_transceive_frame(dev, true, reg, value, &read_reg, &read_data);
226 }
227 
tle9104_write_state_internal(const struct device * dev,uint8_t state)228 static int tle9104_write_state_internal(const struct device *dev, uint8_t state)
229 {
230 	const struct tle9104_config *config = dev->config;
231 	struct tle9104_data *data = dev->data;
232 	bool spi_update_required = false;
233 	uint8_t register_ctrl = 0x00;
234 	int result;
235 
236 	LOG_DBG("writing state 0x%02X to TLE9104", state);
237 
238 	for (size_t i = 0; i < TLE9104_GPIO_COUNT; ++i) {
239 		uint8_t mask = GENMASK(i, i);
240 		bool current_value = (state & mask) != 0;
241 		bool previous_value = (data->previous_state & mask) != 0;
242 
243 		/*
244 		 * Setting the OUTx_ON bits results in a high impedance output,
245 		 * clearing them pulls the output to ground. Therefore the
246 		 * meaning here is intentionally inverted, as this will then turn
247 		 * out for a low active open drain output to be pulled to ground
248 		 * if set to off.
249 		 */
250 		if (current_value == 0) {
251 			register_ctrl |= TLE9104_CTRL_OUT1ONS_BIT << (2 * i);
252 		} else {
253 			register_ctrl |= TLE9104_CTRL_OUT1ONC_BIT << (2 * i);
254 		}
255 
256 		if (current_value == previous_value) {
257 			continue;
258 		}
259 
260 		if (config->gpio_control[i].port == NULL) {
261 			spi_update_required = true;
262 			continue;
263 		}
264 
265 		result = gpio_pin_set_dt(&config->gpio_control[i], current_value);
266 		if (result != 0) {
267 			LOG_ERR("unable to set control GPIO");
268 			return result;
269 		}
270 	}
271 
272 	if (spi_update_required) {
273 		result = tle9104_write_register(dev, TLE9104REGISTER_CTRL, register_ctrl);
274 		if (result != 0) {
275 			LOG_ERR("unable to set control register");
276 			return result;
277 		}
278 	}
279 
280 	data->previous_state = state;
281 
282 	return 0;
283 }
284 
tle9104_write_state(const struct device * dev,uint8_t state)285 int tle9104_write_state(const struct device *dev, uint8_t state)
286 {
287 	struct tle9104_data *data = dev->data;
288 	int result;
289 
290 	k_mutex_lock(&data->lock, K_FOREVER);
291 	result = tle9104_write_state_internal(dev, state);
292 	k_mutex_unlock(&data->lock);
293 
294 	return result;
295 }
296 
297 static int
tle9104_get_diagnostics_internal(const struct device * dev,struct gpio_tle9104_channel_diagnostics diag[TLE9104_GPIO_COUNT])298 tle9104_get_diagnostics_internal(const struct device *dev,
299 				 struct gpio_tle9104_channel_diagnostics diag[TLE9104_GPIO_COUNT])
300 {
301 	enum tle9104_register read_reg;
302 	uint8_t diag_out12_on;
303 	uint8_t diag_out34_on;
304 	uint8_t diag_off;
305 
306 	int result = tle9104_transceive_frame(dev, false, TLE9104REGISTER_DIAGOUT12ON, 0x00,
307 					      &read_reg, &diag_out12_on);
308 	if (result != 0) {
309 		return result;
310 	}
311 
312 	result = tle9104_transceive_frame(dev, false, TLE9104REGISTER_DIAGOUT34ON, 0x00, &read_reg,
313 					  &diag_out12_on);
314 	if (result != 0) {
315 		return result;
316 	}
317 	if (read_reg != TLE9104REGISTER_DIAGOUT12ON) {
318 		LOG_ERR("expected to read different register");
319 		return -EFAULT;
320 	}
321 
322 	result = tle9104_transceive_frame(dev, false, TLE9104REGISTER_DIAGOFF, 0x00, &read_reg,
323 					  &diag_out34_on);
324 	if (result != 0) {
325 		return result;
326 	}
327 	if (read_reg != TLE9104REGISTER_DIAGOUT34ON) {
328 		LOG_ERR("expected to read different register");
329 		return -EFAULT;
330 	}
331 
332 	result = tle9104_transceive_frame(dev, false, TLE9104REGISTER_DIAGOFF, 0x00, &read_reg,
333 					  &diag_off);
334 	if (result != 0) {
335 		return result;
336 	}
337 	if (read_reg != TLE9104REGISTER_DIAGOFF) {
338 		LOG_ERR("expected to read different register");
339 		return -EFAULT;
340 	}
341 
342 	diag[0].on = tle9104_get_register_bits(diag_out12_on, TLE9104_DIAGOUT12ON_DIAGCH1ON_POS,
343 					       TLE9104_DIAGOUT12ON_DIAGCH1ON_LENGTH);
344 	diag[1].on = tle9104_get_register_bits(diag_out12_on, TLE9104_DIAGOUT12ON_DIAGCH2ON_POS,
345 					       TLE9104_DIAGOUT12ON_DIAGCH2ON_LENGTH);
346 	diag[2].on = tle9104_get_register_bits(diag_out34_on, TLE9104_DIAGOUT34ON_DIAGCH3ON_POS,
347 					       TLE9104_DIAGOUT34ON_DIAGCH3ON_LENGTH);
348 	diag[3].on = tle9104_get_register_bits(diag_out34_on, TLE9104_DIAGOUT34ON_DIAGCH4ON_POS,
349 					       TLE9104_DIAGOUT34ON_DIAGCH4ON_LENGTH);
350 	diag[0].off = tle9104_get_register_bits(diag_off, TLE9104_DIAGOFF_DIAGCH1OFF_POS,
351 						TLE9104_DIAGOFF_DIAGCH1OFF_LENGTH);
352 	diag[1].off = tle9104_get_register_bits(diag_off, TLE9104_DIAGOFF_DIAGCH2OFF_POS,
353 						TLE9104_DIAGOFF_DIAGCH2OFF_LENGTH);
354 	diag[2].off = tle9104_get_register_bits(diag_off, TLE9104_DIAGOFF_DIAGCH3OFF_POS,
355 						TLE9104_DIAGOFF_DIAGCH3OFF_LENGTH);
356 	diag[3].off = tle9104_get_register_bits(diag_off, TLE9104_DIAGOFF_DIAGCH4OFF_POS,
357 						TLE9104_DIAGOFF_DIAGCH4OFF_LENGTH);
358 
359 	return 0;
360 }
361 
tle9104_get_diagnostics(const struct device * dev,struct gpio_tle9104_channel_diagnostics diag[TLE9104_GPIO_COUNT])362 int tle9104_get_diagnostics(const struct device *dev,
363 			    struct gpio_tle9104_channel_diagnostics diag[TLE9104_GPIO_COUNT])
364 {
365 	struct tle9104_data *data = dev->data;
366 	int result;
367 
368 	k_mutex_lock(&data->lock, K_FOREVER);
369 	result = tle9104_get_diagnostics_internal(dev, diag);
370 	k_mutex_unlock(&data->lock);
371 
372 	return result;
373 }
374 
tle9104_clear_diagnostics_internal(const struct device * dev)375 static int tle9104_clear_diagnostics_internal(const struct device *dev)
376 {
377 	enum tle9104_register read_reg;
378 	uint8_t temp;
379 	int result;
380 
381 	result = tle9104_transceive_frame(dev, true, TLE9104REGISTER_DIAGOUT12ON, 0x00, &read_reg,
382 					  &temp);
383 	if (result != 0) {
384 		return result;
385 	}
386 
387 	result = tle9104_transceive_frame(dev, true, TLE9104REGISTER_DIAGOUT34ON, 0x00, &read_reg,
388 					  &temp);
389 	if (result != 0) {
390 		return result;
391 	}
392 
393 	result = tle9104_transceive_frame(dev, true, TLE9104REGISTER_DIAGOFF, 0x00, &read_reg,
394 					  &temp);
395 	if (result != 0) {
396 		return result;
397 	}
398 
399 	return 0;
400 }
401 
tle9104_clear_diagnostics(const struct device * dev)402 int tle9104_clear_diagnostics(const struct device *dev)
403 {
404 	struct tle9104_data *data = dev->data;
405 	int result;
406 
407 	k_mutex_lock(&data->lock, K_FOREVER);
408 	result = tle9104_clear_diagnostics_internal(dev);
409 	k_mutex_unlock(&data->lock);
410 
411 	return result;
412 }
413 
tle9104_init(const struct device * dev)414 static int tle9104_init(const struct device *dev)
415 {
416 	const struct tle9104_config *config = dev->config;
417 	struct tle9104_data *data = dev->data;
418 	uint8_t register_cfg;
419 	uint8_t register_globalstatus;
420 	uint8_t register_icvid;
421 	enum tle9104_register read_reg;
422 	int result;
423 
424 	LOG_DBG("initialize TLE9104 instance %s", dev->name);
425 
426 	data->cwd_ignore = true;
427 
428 	result = k_mutex_init(&data->lock);
429 	if (result != 0) {
430 		LOG_ERR("unable to initialize mutex");
431 		return result;
432 	}
433 
434 	if (!spi_is_ready_dt(&config->bus)) {
435 		LOG_ERR("SPI bus %s is not ready", config->bus.bus->name);
436 		return -ENODEV;
437 	}
438 
439 	register_cfg = 0x00;
440 
441 	for (int i = 0; i < TLE9104_GPIO_COUNT; ++i) {
442 		const struct gpio_dt_spec *current = config->gpio_control + i;
443 
444 		if (current->port == NULL) {
445 			LOG_DBG("got no control port for output %i, will control it via SPI", i);
446 			continue;
447 		}
448 
449 		register_cfg |= TLE9104_CFG_OUT1DD_BIT << i;
450 
451 		if (!gpio_is_ready_dt(current)) {
452 			LOG_ERR("%s: control GPIO is not ready", dev->name);
453 			return -ENODEV;
454 		}
455 
456 		result = gpio_pin_configure_dt(current, GPIO_OUTPUT_INACTIVE);
457 		if (result != 0) {
458 			LOG_ERR("failed to initialize control GPIO %i", i);
459 			return result;
460 		}
461 	}
462 
463 	if (config->gpio_enable.port != NULL) {
464 		if (!gpio_is_ready_dt(&config->gpio_enable)) {
465 			LOG_ERR("%s: enable GPIO is not ready", dev->name);
466 			return -ENODEV;
467 		}
468 
469 		result = gpio_pin_configure_dt(&config->gpio_enable, GPIO_OUTPUT_ACTIVE);
470 		if (result != 0) {
471 			LOG_ERR("failed to enable TLE9104");
472 			return result;
473 		}
474 	}
475 
476 	if (config->gpio_reset.port != NULL) {
477 		if (!gpio_is_ready_dt(&config->gpio_reset)) {
478 			LOG_ERR("%s: reset GPIO is not yet ready", dev->name);
479 			return -ENODEV;
480 		}
481 
482 		result = gpio_pin_configure_dt(&config->gpio_reset, GPIO_OUTPUT_ACTIVE);
483 		if (result != 0) {
484 			LOG_ERR("failed to initialize GPIO for reset");
485 			return result;
486 		}
487 
488 		k_busy_wait(TLE9104_RESET_DURATION_TIME_US);
489 		gpio_pin_set_dt(&config->gpio_reset, 0);
490 		k_busy_wait(TLE9104_RESET_DURATION_WAIT_TIME_US +
491 			    TLE9104_RESET_DURATION_WAIT_TIME_SAFETY_MARGIN_US);
492 	}
493 
494 	/*
495 	 * The first read value should be the ICVID, this acts also as the setup of the
496 	 * global status register address.
497 	 */
498 	result = tle9104_transceive_frame(dev, false, TLE9104REGISTER_GLOBALSTATUS, 0x00, &read_reg,
499 					  &register_icvid);
500 	if (result != 0) {
501 		return result;
502 	}
503 
504 	if (read_reg != TLE9104REGISTER_ICVID) {
505 		LOG_ERR("expected to read register ICVID, got instead 0x%02X", read_reg);
506 		return -EIO;
507 	}
508 
509 	if (register_icvid != TLE9104_ICVERSIONID) {
510 		LOG_ERR("got unexpected IC version id 0x%02X", register_icvid);
511 		return -EIO;
512 	}
513 
514 	result = tle9104_transceive_frame(dev, false, TLE9104REGISTER_GLOBALSTATUS, 0x00, &read_reg,
515 					  &register_globalstatus);
516 	if (result != 0) {
517 		return result;
518 	}
519 
520 	if (read_reg != TLE9104REGISTER_GLOBALSTATUS) {
521 		LOG_ERR("expected to read register GLOBALSTATUS, got instead 0x%02X", read_reg);
522 		return -EIO;
523 	}
524 
525 	if ((register_globalstatus & TLE9104_GLOBALSTATUS_POR_LATCH_BIT) == 0) {
526 		LOG_ERR("no power on reset detected");
527 		return -EIO;
528 	}
529 
530 	/* disable communication watchdog */
531 	tle9104_set_register_bits(&register_cfg, TLE9104_CFG_CWDTIME_POS,
532 				  TLE9104_CFG_CWDTIME_LENGTH, 0);
533 
534 	if (config->parallel_mode_out12) {
535 		LOG_DBG("use parallel mode for OUT1 and OUT2");
536 		register_cfg |= BIT(TLE9104_CFG_OUT12PAR_POS);
537 	}
538 
539 	if (config->parallel_mode_out34) {
540 		LOG_DBG("use parallel mode for OUT3 and OUT4");
541 		register_cfg |= BIT(TLE9104_CFG_OUT34PAR_POS);
542 	}
543 
544 	result = tle9104_write_register(dev, TLE9104REGISTER_CFG, register_cfg);
545 	if (result != 0) {
546 		LOG_ERR("unable to write configuration");
547 		return result;
548 	}
549 
550 	register_cfg = 0x00;
551 	tle9104_set_register_bits(&register_cfg, TLE9104_OFFDIAGCFG_DIAGFILTCFG_POS,
552 				  TLE9104_OFFDIAGCFG_DIAGFILTCFG_LENGTH,
553 				  config->diagnostic_filter_time);
554 	register_cfg |= TLE9104_OFFDIAGCFG_OUT4DIAGEN_BIT;
555 	register_cfg |= TLE9104_OFFDIAGCFG_OUT3DIAGEN_BIT;
556 	register_cfg |= TLE9104_OFFDIAGCFG_OUT2DIAGEN_BIT;
557 	register_cfg |= TLE9104_OFFDIAGCFG_OUT1DIAGEN_BIT;
558 
559 	result = tle9104_write_register(dev, TLE9104REGISTER_OFFDIAGCFG, register_cfg);
560 	if (result != 0) {
561 		LOG_ERR("unable to write OFF-diag configuration");
562 		return result;
563 	}
564 
565 	register_cfg = 0x00;
566 	tle9104_set_register_bits(&register_cfg, TLE9104_ONDIAGCFG_OCFILTCFG_POS,
567 				  TLE9104_ONDIAGCFG_OCFILTCFG_LENGTH,
568 				  config->overcurrent_shutdown_delay_time);
569 	tle9104_set_register_bits(&register_cfg, TLE9104_ONDIAGCFG_OCTH_POS,
570 				  TLE9104_ONDIAGCFG_OCTH_LENGTH,
571 				  config->overcurrent_shutdown_threshold);
572 
573 	result = tle9104_write_register(dev, TLE9104REGISTER_ONDIAGCFG, register_cfg);
574 	if (result != 0) {
575 		LOG_ERR("unable to write ON-diag configuration");
576 		return result;
577 	}
578 
579 	register_globalstatus = 0x00;
580 	/* enable outputs */
581 	register_globalstatus |= TLE9104_GLOBALSTATUS_OUTEN_BIT;
582 
583 	result = tle9104_write_register(dev, TLE9104REGISTER_GLOBALSTATUS, register_globalstatus);
584 	if (result != 0) {
585 		LOG_ERR("unable to write global status");
586 		return result;
587 	}
588 
589 	data->cwd_ignore = false;
590 
591 	return 0;
592 }
593 
594 #define TLE9104_INIT_GPIO_FIELDS(inst, gpio)                                                       \
595 	COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, gpio),                                             \
596 		    (GPIO_DT_SPEC_GET_BY_IDX(DT_DRV_INST(inst), gpio, 0)), ({0}))
597 
598 #define TLE9104_INIT(inst)                                                                         \
599 	static const struct tle9104_config tle9104_##inst##_config = {                             \
600 		.bus = SPI_DT_SPEC_INST_GET(                                                       \
601 			inst, SPI_OP_MODE_MASTER | SPI_MODE_CPHA | SPI_WORD_SET(8), 0),            \
602 		.gpio_enable = TLE9104_INIT_GPIO_FIELDS(inst, en_gpios),                           \
603 		.gpio_reset = TLE9104_INIT_GPIO_FIELDS(inst, resn_gpios),                          \
604 		.gpio_control = {                                                                  \
605 			TLE9104_INIT_GPIO_FIELDS(inst, in1_gpios),                                 \
606 			TLE9104_INIT_GPIO_FIELDS(inst, in2_gpios),                                 \
607 			TLE9104_INIT_GPIO_FIELDS(inst, in3_gpios),                                 \
608 			TLE9104_INIT_GPIO_FIELDS(inst, in4_gpios),                                 \
609 		},                                                                                 \
610 		.diagnostic_filter_time = DT_INST_ENUM_IDX(inst, diagnostic_filter_time),          \
611 		.overcurrent_shutdown_delay_time =                                                 \
612 			DT_INST_ENUM_IDX(inst, overcurrent_shutdown_delay_time),                   \
613 		.overcurrent_shutdown_threshold =                                                  \
614 			DT_INST_ENUM_IDX(inst, overcurrent_shutdown_threshold),                    \
615 		.parallel_mode_out12 = DT_INST_PROP(inst, parallel_out12),                         \
616 		.parallel_mode_out34 = DT_INST_PROP(inst, parallel_out34),                         \
617 	};                                                                                         \
618                                                                                                    \
619 	static struct tle9104_data tle9104_##inst##_data;                                          \
620                                                                                                    \
621 	DEVICE_DT_INST_DEFINE(inst, tle9104_init, NULL, &tle9104_##inst##_data,                    \
622 			      &tle9104_##inst##_config, POST_KERNEL, CONFIG_MFD_INIT_PRIORITY,     \
623 			      NULL);
624 
625 DT_INST_FOREACH_STATUS_OKAY(TLE9104_INIT);
626