1 /*
2  * Copyright 2024 Cirrus Logic, Inc.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * DRV2605 Datasheet: https://www.ti.com/lit/gpn/drv2605
7  */
8 
9 #define DT_DRV_COMPAT ti_drv2605
10 
11 #include <zephyr/device.h>
12 #include <zephyr/devicetree.h>
13 #include <zephyr/drivers/gpio.h>
14 #include <zephyr/drivers/i2c.h>
15 #include <zephyr/drivers/haptics.h>
16 #include <zephyr/drivers/haptics/drv2605.h>
17 #include <zephyr/kernel.h>
18 #include <zephyr/logging/log.h>
19 #include <zephyr/drivers/haptics.h>
20 #include <zephyr/pm/device.h>
21 #include <zephyr/pm/device_runtime.h>
22 #include <zephyr/sys/util.h>
23 
24 LOG_MODULE_REGISTER(DRV2605, CONFIG_HAPTICS_LOG_LEVEL);
25 
26 #define DRV2605_REG_STATUS         0x0
27 #define DRV2605_DEVICE_ID          GENMASK(7, 5)
28 #define DRV2605_DEVICE_ID_DRV2605  0x3
29 #define DRV2605_DEVICE_ID_DRV2605L 0x7
30 #define DRV2605_DIAG_RESULT        BIT(3)
31 #define DRV2605_FB_STS             BIT(2)
32 #define DRV2605_OVER_TEMP          BIT(1)
33 #define DRV2605_OC_DETECT          BIT(0)
34 
35 #define DRV2605_REG_MODE  0x1
36 #define DRV2605_DEV_RESET BIT(7)
37 #define DRV2605_STANDBY   BIT(6)
38 #define DRV2605_MODE      GENMASK(2, 0)
39 
40 #define DRV2605_REG_RT_PLAYBACK_INPUT 0x2
41 
42 #define DRV2605_REG_UNNAMED 0x3
43 #define DRV2605_HI_Z_OUTPUT BIT(4)
44 #define DRV2605_LIBRARY_SEL GENMASK(2, 0)
45 
46 #define DRV2605_REG_WAVEFORM_SEQUENCER 0x4
47 #define DRV2605_WAIT                   BIT(7)
48 #define DRV2605_WAV_FRM_SEQ            GENMASK(6, 0)
49 
50 #define DRV2605_REG_GO 0xc
51 #define DRV2605_GO     BIT(0)
52 
53 #define DRV2605_REG_OVERDRIVE_TIME_OFFSET 0xd
54 
55 #define DRV2605_REG_SUSTAIN_TIME_OFFSET_POS 0xe
56 
57 #define DRV2605_REG_SUSTAIN_TIME_OFFSET_NEG 0xf
58 
59 #define DRV2605_REG_BRAKE_TIME_OFFSET 0x10
60 
61 #define DRV2605_TIME_STEP_MS 5
62 
63 #define DRV2605_REG_AUDIO_TO_VIBE_CONTROL 0x11
64 #define DRV2605_ATH_PEAK_TIME             GENMASK(3, 2)
65 #define DRV2605_ATH_FILTER                GENMASK(1, 0)
66 
67 #define DRV2605_REG_AUDIO_TO_VIBE_MIN_INPUT_LEVEL 0x12
68 
69 #define DRV2605_REG_AUDIO_TO_VIBE_MAX_INPUT_LEVEL 0x13
70 
71 #define DRV2605_ATH_INPUT_STEP_UV (1800000 / 255)
72 
73 #define DRV2605_REG_AUDIO_TO_VIBE_MIN_OUTPUT_DRIVE 0x14
74 
75 #define DRV2605_REG_AUDIO_TO_VIBE_MAX_OUTPUT_DRIVE 0x15
76 
77 #define DRV2605_ATH_OUTPUT_DRIVE_PCT (100 * 255)
78 
79 #define DRV2605_REG_RATED_VOLTAGE 0x16
80 
81 #define DRV2605_REG_OVERDRIVE_CLAMP_VOLTAGE 0x17
82 
83 #define DRV2605_REG_AUTO_CAL_COMP_RESULT 0x18
84 
85 #define DRV2605_REG_AUTO_CAL_BACK_EMF_RESULT 0x19
86 
87 #define DRV2605_REG_FEEDBACK_CONTROL 0x1a
88 #define DRV2605_N_ERM_LRA            BIT(7)
89 #define DRV2605_FB_BRAKE_FACTOR      GENMASK(6, 4)
90 #define DRV2605_LOOP_GAIN            GENMASK(3, 2)
91 #define DRV2605_BEMF_GAIN            GENMASK(1, 0)
92 
93 #define DRV2605_ACTUATOR_MODE_ERM 0
94 #define DRV2605_ACTUATOR_MODE_LRA 1
95 
96 #define DRV2605_REG_CONTROL1  0x1b
97 #define DRV2605_STARTUP_BOOST BIT(7)
98 #define DRV2605_AC_COUPLE     BIT(5)
99 #define DRV2605_DRIVE_TIME    GENMASK(4, 0)
100 
101 #define DRV2605_REG_CONTROL2     0x1c
102 #define DRV2605_BIDIR_INPUT      BIT(7)
103 #define DRV2605_BRAKE_STABILIZER BIT(6)
104 #define DRV2605_SAMPLE_TIME      GENMASK(5, 4)
105 #define DRV2605_BLANKING_TIME    GENMASK(3, 2)
106 #define DRV2605_IDISS_TIME       GENMASK(1, 0)
107 
108 #define DRV2605_REG_CONTROL3    0x1d
109 #define DRV2605_NG_THRESH       GENMASK(7, 6)
110 #define DRV2605_ERM_OPEN_LOOP   BIT(5)
111 #define DRV2605_SUPPLY_COMP_DIS BIT(4)
112 #define DRV2605_DATA_FORMAT_RTP BIT(3)
113 #define DRV2605_LRA_DRIVE_MODE  BIT(2)
114 #define DRV2605_N_PWM_ANALOG    BIT(1)
115 #define DRV2605_LRA_OPEN_LOOP   BIT(0)
116 
117 #define DRV2605_REG_CONTROL4       0x1e
118 #define DRV2605_ZERO_CROSSING_TIME GENMASK(7, 6)
119 #define DRV2605_AUTO_CAL_TIME      GENMASK(5, 4)
120 #define DRV2605_OTP_STATUS         BIT(2)
121 #define DRV2605_OTP_PROGRAM        BIT(0)
122 
123 #define DRV2605_REG_BATT_VOLTAGE_MONITOR 0x21
124 #define DRV2605_VBAT_STEP_UV             (5600000 / 255)
125 
126 #define DRV2605_REG_LRA_RESONANCE_PERIOD 0x22
127 
128 #define DRV2605_POWER_UP_DELAY_US 250
129 
130 #define DRV2605_VOLTAGE_SCALE_FACTOR_MV 5600
131 
132 #define DRV2605_CALCULATE_VOLTAGE(_volt) ((_volt * 255) / DRV2605_VOLTAGE_SCALE_FACTOR_MV)
133 
134 struct drv2605_config {
135 	struct i2c_dt_spec i2c;
136 	struct gpio_dt_spec en_gpio;
137 	struct gpio_dt_spec in_trig_gpio;
138 	uint8_t feedback_brake_factor;
139 	uint8_t loop_gain;
140 	uint8_t rated_voltage;
141 	uint8_t overdrive_clamp_voltage;
142 	uint8_t auto_cal_time;
143 	uint8_t drive_time;
144 	bool actuator_mode;
145 };
146 
147 struct drv2605_data {
148 	const struct device *dev;
149 	struct k_work rtp_work;
150 	const struct drv2605_rtp_data *rtp_data;
151 	enum drv2605_mode mode;
152 };
153 
drv2605_haptic_config_audio(const struct device * dev)154 static inline int drv2605_haptic_config_audio(const struct device *dev)
155 {
156 	const struct drv2605_config *config = dev->config;
157 	struct drv2605_data *data = dev->data;
158 	int ret;
159 
160 	ret = i2c_reg_update_byte_dt(&config->i2c, DRV2605_REG_CONTROL3, DRV2605_N_PWM_ANALOG,
161 				     DRV2605_N_PWM_ANALOG);
162 	if (ret < 0) {
163 		return ret;
164 	}
165 
166 	ret = i2c_reg_update_byte_dt(&config->i2c, DRV2605_REG_CONTROL1, DRV2605_AC_COUPLE,
167 				     DRV2605_AC_COUPLE);
168 	if (ret < 0) {
169 		return ret;
170 	}
171 
172 	data->mode = DRV2605_MODE_AUDIO_TO_VIBE;
173 
174 	return 0;
175 }
176 
drv2605_haptic_config_pwm_analog(const struct device * dev,const bool analog)177 static inline int drv2605_haptic_config_pwm_analog(const struct device *dev, const bool analog)
178 {
179 	const struct drv2605_config *config = dev->config;
180 	struct drv2605_data *data = dev->data;
181 	uint8_t value = 0;
182 	int ret;
183 
184 	if (analog) {
185 		value = DRV2605_N_PWM_ANALOG;
186 	}
187 
188 	ret = i2c_reg_update_byte_dt(&config->i2c, DRV2605_REG_CONTROL3, DRV2605_N_PWM_ANALOG,
189 				     value);
190 	if (ret < 0) {
191 		return ret;
192 	}
193 
194 	data->mode = DRV2605_MODE_PWM_ANALOG_INPUT;
195 
196 	return 0;
197 }
198 
drv2605_rtp_work_handler(struct k_work * work)199 static void drv2605_rtp_work_handler(struct k_work *work)
200 {
201 	struct drv2605_data *data = CONTAINER_OF(work, struct drv2605_data, rtp_work);
202 	const struct drv2605_rtp_data *rtp_data = data->rtp_data;
203 	const struct drv2605_config *config = data->dev->config;
204 	int i;
205 
206 	for (i = 0; i < rtp_data->size; i++) {
207 		i2c_reg_write_byte_dt(&config->i2c, DRV2605_REG_RT_PLAYBACK_INPUT,
208 				      rtp_data->rtp_input[i]);
209 		k_usleep(rtp_data->rtp_hold_us[i]);
210 	}
211 }
212 
drv2605_haptic_config_rtp(const struct device * dev,const struct drv2605_rtp_data * rtp_data)213 static inline int drv2605_haptic_config_rtp(const struct device *dev,
214 					    const struct drv2605_rtp_data *rtp_data)
215 {
216 	const struct drv2605_config *config = dev->config;
217 	struct drv2605_data *data = dev->data;
218 	int ret;
219 
220 	data->rtp_data = rtp_data;
221 
222 	ret = i2c_reg_write_byte_dt(&config->i2c, DRV2605_REG_RT_PLAYBACK_INPUT, 0);
223 	if (ret < 0) {
224 		return ret;
225 	}
226 
227 	ret = i2c_reg_update_byte_dt(&config->i2c, DRV2605_REG_MODE, DRV2605_MODE,
228 				     (uint8_t)DRV2605_MODE_RTP);
229 	if (ret < 0) {
230 		return ret;
231 	}
232 
233 	data->mode = DRV2605_MODE_RTP;
234 
235 	return 0;
236 }
237 
drv2605_haptic_config_rom(const struct device * dev,const struct drv2605_rom_data * rom_data)238 static inline int drv2605_haptic_config_rom(const struct device *dev,
239 					    const struct drv2605_rom_data *rom_data)
240 {
241 	const struct drv2605_config *config = dev->config;
242 	uint8_t reg_addr = DRV2605_REG_WAVEFORM_SEQUENCER;
243 	struct drv2605_data *data = dev->data;
244 	int i, ret;
245 
246 	switch (rom_data->trigger) {
247 	case DRV2605_MODE_INTERNAL_TRIGGER:
248 	case DRV2605_MODE_EXTERNAL_EDGE_TRIGGER:
249 	case DRV2605_MODE_EXTERNAL_LEVEL_TRIGGER:
250 		ret = i2c_reg_update_byte_dt(&config->i2c, DRV2605_REG_MODE, DRV2605_MODE,
251 					     (uint8_t)rom_data->trigger);
252 		if (ret < 0) {
253 			return ret;
254 		}
255 
256 		data->mode = rom_data->trigger;
257 		break;
258 	default:
259 		return -EINVAL;
260 	}
261 
262 	ret = i2c_reg_update_byte_dt(&config->i2c, DRV2605_REG_UNNAMED, DRV2605_LIBRARY_SEL,
263 				     (uint8_t)rom_data->library);
264 	if (ret < 0) {
265 		return ret;
266 	}
267 
268 	for (i = 0; i < DRV2605_WAVEFORM_SEQUENCER_MAX; i++) {
269 		ret = i2c_reg_write_byte_dt(&config->i2c, reg_addr, rom_data->seq_regs[i]);
270 		if (ret < 0) {
271 			return ret;
272 		}
273 
274 		reg_addr++;
275 
276 		if (rom_data->seq_regs[i] == 0U) {
277 			break;
278 		}
279 	}
280 
281 	ret = i2c_reg_write_byte_dt(&config->i2c, DRV2605_REG_OVERDRIVE_TIME_OFFSET,
282 				    rom_data->overdrive_time);
283 	if (ret < 0) {
284 		return ret;
285 	}
286 
287 	ret = i2c_reg_write_byte_dt(&config->i2c, DRV2605_REG_SUSTAIN_TIME_OFFSET_POS,
288 				    rom_data->sustain_pos_time);
289 	if (ret < 0) {
290 		return ret;
291 	}
292 
293 	ret = i2c_reg_write_byte_dt(&config->i2c, DRV2605_REG_SUSTAIN_TIME_OFFSET_NEG,
294 				    rom_data->sustain_neg_time);
295 	if (ret < 0) {
296 		return ret;
297 	}
298 
299 	ret = i2c_reg_write_byte_dt(&config->i2c, DRV2605_REG_BRAKE_TIME_OFFSET,
300 				    rom_data->brake_time);
301 	if (ret < 0) {
302 		return ret;
303 	}
304 
305 	return 0;
306 }
307 
drv2605_haptic_config(const struct device * dev,enum drv2605_haptics_source source,const union drv2605_config_data * config_data)308 int drv2605_haptic_config(const struct device *dev, enum drv2605_haptics_source source,
309 			  const union drv2605_config_data *config_data)
310 {
311 	switch (source) {
312 	case DRV2605_HAPTICS_SOURCE_ROM:
313 		return drv2605_haptic_config_rom(dev, config_data->rom_data);
314 	case DRV2605_HAPTICS_SOURCE_RTP:
315 		return drv2605_haptic_config_rtp(dev, config_data->rtp_data);
316 	case DRV2605_HAPTICS_SOURCE_AUDIO:
317 		return drv2605_haptic_config_audio(dev);
318 	case DRV2605_HAPTICS_SOURCE_PWM:
319 		return drv2605_haptic_config_pwm_analog(dev, false);
320 	case DRV2605_HAPTICS_SOURCE_ANALOG:
321 		return drv2605_haptic_config_pwm_analog(dev, true);
322 	default:
323 		return -ENOTSUP;
324 	}
325 
326 	return 0;
327 }
328 
drv2605_edge_mode_event(const struct device * dev)329 static inline int drv2605_edge_mode_event(const struct device *dev)
330 {
331 	const struct drv2605_config *config = dev->config;
332 	int ret;
333 
334 	ret = gpio_pin_set_dt(&config->in_trig_gpio, 1);
335 	if (ret < 0) {
336 		return ret;
337 	}
338 
339 	return gpio_pin_set_dt(&config->in_trig_gpio, 0);
340 }
341 
drv2605_stop_output(const struct device * dev)342 static int drv2605_stop_output(const struct device *dev)
343 {
344 	const struct drv2605_config *config = dev->config;
345 	struct drv2605_data *data = dev->data;
346 	uint8_t value;
347 	int ret;
348 
349 	switch (data->mode) {
350 	case DRV2605_MODE_DIAGNOSTICS:
351 	case DRV2605_MODE_AUTO_CAL:
352 		ret = i2c_reg_read_byte_dt(&config->i2c, DRV2605_REG_GO, &value);
353 		if (ret < 0) {
354 			return ret;
355 		}
356 
357 		if (FIELD_GET(DRV2605_GO, value)) {
358 			LOG_DBG("Playback mode: %d is uninterruptible", data->mode);
359 			return -EBUSY;
360 		}
361 
362 		break;
363 	case DRV2605_MODE_INTERNAL_TRIGGER:
364 		return i2c_reg_update_byte_dt(&config->i2c, DRV2605_REG_GO, DRV2605_GO, 0);
365 	case DRV2605_MODE_EXTERNAL_EDGE_TRIGGER:
366 		return drv2605_edge_mode_event(dev);
367 	case DRV2605_MODE_EXTERNAL_LEVEL_TRIGGER:
368 		return gpio_pin_set_dt(&config->in_trig_gpio, 0);
369 	case DRV2605_MODE_PWM_ANALOG_INPUT:
370 	case DRV2605_MODE_AUDIO_TO_VIBE:
371 		ret = i2c_reg_update_byte_dt(&config->i2c, DRV2605_REG_MODE, DRV2605_MODE,
372 					     (uint8_t)DRV2605_MODE_INTERNAL_TRIGGER);
373 		if (ret < 0) {
374 			return ret;
375 		}
376 
377 		return i2c_reg_update_byte_dt(&config->i2c, DRV2605_REG_GO, DRV2605_GO, 0);
378 	case DRV2605_MODE_RTP:
379 		return k_work_cancel(&data->rtp_work);
380 	default:
381 		return -ENOTSUP;
382 	}
383 
384 	return 0;
385 }
386 
drv2605_start_output(const struct device * dev)387 static int drv2605_start_output(const struct device *dev)
388 {
389 	const struct drv2605_config *config = dev->config;
390 	struct drv2605_data *data = dev->data;
391 
392 	switch (data->mode) {
393 	case DRV2605_MODE_DIAGNOSTICS:
394 	case DRV2605_MODE_AUTO_CAL:
395 	case DRV2605_MODE_INTERNAL_TRIGGER:
396 		return i2c_reg_update_byte_dt(&config->i2c, DRV2605_REG_GO, DRV2605_GO, DRV2605_GO);
397 	case DRV2605_MODE_EXTERNAL_EDGE_TRIGGER:
398 		return drv2605_edge_mode_event(dev);
399 	case DRV2605_MODE_EXTERNAL_LEVEL_TRIGGER:
400 		return gpio_pin_set_dt(&config->in_trig_gpio, 1);
401 	case DRV2605_MODE_AUDIO_TO_VIBE:
402 	case DRV2605_MODE_PWM_ANALOG_INPUT:
403 		return i2c_reg_update_byte_dt(&config->i2c, DRV2605_REG_MODE, DRV2605_MODE,
404 					      (uint8_t)data->mode);
405 	case DRV2605_MODE_RTP:
406 		return k_work_submit(&data->rtp_work);
407 	default:
408 		return -ENOTSUP;
409 	}
410 
411 	return 0;
412 }
413 
414 #ifdef CONFIG_PM_DEVICE
drv2605_pm_action(const struct device * dev,enum pm_device_action action)415 static int drv2605_pm_action(const struct device *dev, enum pm_device_action action)
416 {
417 	const struct drv2605_config *config = dev->config;
418 
419 	switch (action) {
420 	case PM_DEVICE_ACTION_RESUME:
421 		return i2c_reg_update_byte_dt(&config->i2c, DRV2605_REG_MODE, DRV2605_STANDBY, 0);
422 	case PM_DEVICE_ACTION_SUSPEND:
423 		return i2c_reg_update_byte_dt(&config->i2c, DRV2605_REG_MODE, DRV2605_STANDBY,
424 					      DRV2605_STANDBY);
425 	case PM_DEVICE_ACTION_TURN_OFF:
426 		if (config->en_gpio.port != NULL) {
427 			gpio_pin_set_dt(&config->en_gpio, 0);
428 		}
429 
430 		break;
431 	case PM_DEVICE_ACTION_TURN_ON:
432 		if (config->en_gpio.port != NULL) {
433 			gpio_pin_set_dt(&config->en_gpio, 1);
434 		}
435 
436 		break;
437 	default:
438 		return -ENOTSUP;
439 	}
440 
441 	return 0;
442 }
443 #endif
444 
drv2605_hw_config(const struct device * dev)445 static int drv2605_hw_config(const struct device *dev)
446 {
447 	const struct drv2605_config *config = dev->config;
448 	uint8_t mask, value;
449 	int ret;
450 
451 	value = FIELD_PREP(DRV2605_N_ERM_LRA, config->actuator_mode) |
452 		FIELD_PREP(DRV2605_FB_BRAKE_FACTOR, config->feedback_brake_factor) |
453 		FIELD_PREP(DRV2605_LOOP_GAIN, config->loop_gain);
454 
455 	mask = DRV2605_N_ERM_LRA | DRV2605_FB_BRAKE_FACTOR | DRV2605_LOOP_GAIN;
456 
457 	ret = i2c_reg_update_byte_dt(&config->i2c, DRV2605_REG_FEEDBACK_CONTROL, mask, value);
458 	if (ret < 0) {
459 		return ret;
460 	}
461 
462 	ret = i2c_reg_write_byte_dt(&config->i2c, DRV2605_REG_RATED_VOLTAGE, config->rated_voltage);
463 	if (ret < 0) {
464 		return ret;
465 	}
466 
467 	ret = i2c_reg_write_byte_dt(&config->i2c, DRV2605_REG_OVERDRIVE_CLAMP_VOLTAGE,
468 				    config->overdrive_clamp_voltage);
469 	if (ret < 0) {
470 		return ret;
471 	}
472 
473 	if (config->actuator_mode == DRV2605_ACTUATOR_MODE_LRA) {
474 		ret = i2c_reg_update_byte_dt(&config->i2c, DRV2605_REG_CONTROL3,
475 					     DRV2605_LRA_OPEN_LOOP, DRV2605_LRA_OPEN_LOOP);
476 		if (ret < 0) {
477 			return ret;
478 		}
479 	}
480 
481 	return 0;
482 }
483 
drv2605_reset(const struct device * dev)484 static int drv2605_reset(const struct device *dev)
485 {
486 	const struct drv2605_config *config = dev->config;
487 	int retries = 5, ret;
488 	uint8_t value;
489 
490 	i2c_reg_update_byte_dt(&config->i2c, DRV2605_REG_MODE, DRV2605_STANDBY, 0);
491 
492 	ret = i2c_reg_update_byte_dt(&config->i2c, DRV2605_REG_MODE, DRV2605_DEV_RESET,
493 				     DRV2605_DEV_RESET);
494 	if (ret < 0) {
495 		return ret;
496 	}
497 
498 	k_msleep(100);
499 
500 	while (retries > 0) {
501 		retries--;
502 
503 		ret = i2c_reg_read_byte_dt(&config->i2c, DRV2605_REG_MODE, &value);
504 		if (ret < 0) {
505 			k_usleep(10000);
506 			continue;
507 		}
508 
509 		if ((value & DRV2605_DEV_RESET) == 0U) {
510 			i2c_reg_update_byte_dt(&config->i2c, DRV2605_REG_MODE, DRV2605_STANDBY, 0);
511 			return 0;
512 		}
513 	}
514 
515 	return -ETIMEDOUT;
516 }
517 
drv2605_check_devid(const struct device * dev)518 static int drv2605_check_devid(const struct device *dev)
519 {
520 	const struct drv2605_config *config = dev->config;
521 	uint8_t value;
522 	int ret;
523 
524 	ret = i2c_reg_read_byte_dt(&config->i2c, DRV2605_REG_STATUS, &value);
525 	if (ret < 0) {
526 		return ret;
527 	}
528 
529 	value = FIELD_GET(DRV2605_DEVICE_ID, value);
530 
531 	switch (value) {
532 	case DRV2605_DEVICE_ID_DRV2605:
533 	case DRV2605_DEVICE_ID_DRV2605L:
534 		break;
535 	default:
536 		LOG_ERR("Invalid device ID found");
537 		return -ENOTSUP;
538 	}
539 
540 	LOG_DBG("Found DRV2605, DEVID: 0x%x", value);
541 
542 	return 0;
543 }
544 
drv2605_gpio_config(const struct device * dev)545 static int drv2605_gpio_config(const struct device *dev)
546 {
547 	const struct drv2605_config *config = dev->config;
548 	int ret;
549 
550 	if (config->en_gpio.port != NULL) {
551 		if (!gpio_is_ready_dt(&config->en_gpio)) {
552 			return -ENODEV;
553 		}
554 
555 		ret = gpio_pin_configure_dt(&config->en_gpio, GPIO_OUTPUT_ACTIVE);
556 		if (ret < 0) {
557 			return ret;
558 		}
559 	}
560 
561 	if (config->in_trig_gpio.port != NULL) {
562 		if (!gpio_is_ready_dt(&config->in_trig_gpio)) {
563 			return -ENODEV;
564 		}
565 
566 		ret = gpio_pin_configure_dt(&config->in_trig_gpio, GPIO_OUTPUT_INACTIVE);
567 		if (ret < 0) {
568 			return ret;
569 		}
570 	}
571 
572 	return 0;
573 }
574 
drv2605_init(const struct device * dev)575 static int drv2605_init(const struct device *dev)
576 {
577 	const struct drv2605_config *config = dev->config;
578 	struct drv2605_data *data = dev->data;
579 	int ret;
580 
581 	data->dev = dev;
582 
583 	k_usleep(DRV2605_POWER_UP_DELAY_US);
584 
585 	if (!i2c_is_ready_dt(&config->i2c)) {
586 		return -ENODEV;
587 	}
588 
589 	k_work_init(&data->rtp_work, drv2605_rtp_work_handler);
590 
591 	ret = drv2605_gpio_config(dev);
592 	if (ret < 0) {
593 		LOG_DBG("Failed to allocate GPIOs: %d", ret);
594 		return ret;
595 	}
596 
597 	ret = drv2605_check_devid(dev);
598 	if (ret < 0) {
599 		return ret;
600 	}
601 
602 	ret = drv2605_reset(dev);
603 	if (ret < 0) {
604 		LOG_DBG("Failed to reset device: %d", ret);
605 		return ret;
606 	}
607 
608 	ret = drv2605_hw_config(dev);
609 	if (ret < 0) {
610 		LOG_DBG("Failed to configure device: %d", ret);
611 		return ret;
612 	}
613 
614 	return 0;
615 }
616 
617 static DEVICE_API(haptics, drv2605_driver_api) = {
618 	.start_output = &drv2605_start_output,
619 	.stop_output = &drv2605_stop_output,
620 };
621 
622 #define HAPTICS_DRV2605_DEFINE(inst)                                                               \
623                                                                                                    \
624 	static const struct drv2605_config drv2605_config_##inst = {                               \
625 		.i2c = I2C_DT_SPEC_INST_GET(inst),                                                 \
626 		.en_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, en_gpios, {}),                           \
627 		.in_trig_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, in_trig_gpios, {}),                 \
628 		.feedback_brake_factor = DT_INST_ENUM_IDX(inst, feedback_brake_factor),            \
629 		.loop_gain = DT_INST_ENUM_IDX(inst, loop_gain),                                    \
630 		.actuator_mode = DT_INST_ENUM_IDX(inst, actuator_mode),                            \
631 		.rated_voltage = DRV2605_CALCULATE_VOLTAGE(DT_INST_PROP(inst, vib_rated_mv)),      \
632 		.overdrive_clamp_voltage =                                                         \
633 			DRV2605_CALCULATE_VOLTAGE(DT_INST_PROP(inst, vib_overdrive_mv)),           \
634 	};                                                                                         \
635                                                                                                    \
636 	static struct drv2605_data drv2605_data_##inst = {                                         \
637 		.mode = DRV2605_MODE_INTERNAL_TRIGGER,                                             \
638 	};                                                                                         \
639                                                                                                    \
640 	PM_DEVICE_DT_INST_DEFINE(inst, drv2605_pm_action);                                         \
641                                                                                                    \
642 	DEVICE_DT_INST_DEFINE(inst, drv2605_init, PM_DEVICE_DT_INST_GET(inst),                     \
643 			      &drv2605_data_##inst, &drv2605_config_##inst, POST_KERNEL,           \
644 			      CONFIG_HAPTICS_INIT_PRIORITY, &drv2605_driver_api);
645 
646 DT_INST_FOREACH_STATUS_OKAY(HAPTICS_DRV2605_DEFINE)
647