1 /*
2 * Arm SCP/MCP Software
3 * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 *
7 * Description:
8 * XR77128 driver
9 */
10
11 #include <mod_cdns_i2c.h>
12 #include <mod_clock.h>
13 #include <mod_psu.h>
14 #include <mod_timer.h>
15 #include <mod_xr77128.h>
16
17 #include <fwk_assert.h>
18 #include <fwk_core.h>
19 #include <fwk_event.h>
20 #include <fwk_interrupt.h>
21 #include <fwk_io.h>
22 #include <fwk_log.h>
23 #include <fwk_mm.h>
24 #include <fwk_module.h>
25 #include <fwk_module_idx.h>
26 #include <fwk_notification.h>
27 #include <fwk_status.h>
28
29 #define XR77128_CHANNEL_ENABLED 0x1
30 #define XR77128_CHANNEL_DISABLED 0x0
31
32 /*
33 * PSU properties
34 */
35 #define XR77128_PSU_VOUT_PRESCALE_UV 2500 /* Low range */
36 #define XR77128_PSU_VOUT_STEP_COARSE_UV (5 * XR77128_PSU_VOUT_PRESCALE_UV)
37 #define XR77128_PSU_VOUT_STEP_FINE_UV XR77128_PSU_VOUT_PRESCALE_UV
38 #define XR77128_PSU_MVOUT_SCALE_READ 15
39
40 /* Ramping/Settling time when changing voltage in ms */
41 #define XR77128_PSU_RAMP_DELAY_SET_MS 1
42
43 /* Ramping/Settling time when enabling a channel in ms */
44 #define XR77128_PSU_RAMP_DELAY_ENABLE_MS 2
45
46 enum xr77128_event_idx {
47 XR77128_EVENT_IDX_REQUEST,
48 XR77128_EVENT_IDX_COUNT,
49 };
50
51 enum xr77128_psu_request {
52 XR77128_PSU_REQUEST_IDLE,
53 XR77128_PSU_REQUEST_WAIT_FOR_IDLE,
54 XR77128_PSU_REQUEST_GET_VOLTAGE,
55 XR77128_PSU_REQUEST_CONVERT_VOLTAGE,
56 XR77128_PSU_REQUEST_SET_VOLTAGE,
57 XR77128_PSU_REQUEST_WAIT_FOR_VOLTAGE,
58 XR77128_PSU_REQUEST_DONE_SET_VOLTAGE,
59 XR77128_PSU_REQUEST_SET_ENABLED,
60 XR77128_PSU_REQUEST_WAIT_FOR_ENABLED,
61 XR77128_PSU_REQUEST_DONE_ENABLED,
62 };
63
64 struct psu_set_enabled_param {
65 bool enabled;
66 };
67
68 struct psu_set_voltage_param {
69 uint32_t voltage;
70 uint16_t set_value;
71 };
72
73 /*! Identifier of the PSU (PMIC) driver API */
74 static const fwk_id_t mod_xr77128_api_id_psu =
75 FWK_ID_API_INIT(FWK_MODULE_IDX_XR77128, MOD_XR77128_API_IDX_PSU);
76
77 static const fwk_id_t xr77128_event_id_request =
78 FWK_ID_EVENT_INIT(FWK_MODULE_IDX_XR77128, XR77128_EVENT_IDX_REQUEST);
79
80 struct xr77128_module_ctx {
81 /* Table of device contexts */
82 struct xr77128_dev_ctx *dev_ctx_table;
83
84 /* Number of devices */
85 unsigned int device_count;
86 };
87
88 struct xr77128_dev_ctx {
89 /* Pointer to device configuration */
90 const struct mod_xr77128_dev_config *config;
91
92 /* Table of channel contexts */
93 struct xr77128_channel_ctx *channel_ctx_table;
94
95 /* Number of channels */
96 unsigned int channel_count;
97
98 /* I2C API */
99 const struct mod_cdns_i2c_controller_api_polled *i2c_api;
100
101 /* Response API to the PSU driver */
102 const struct mod_psu_driver_response_api *psu_driver_response_api;
103
104 /* Alarm API for voltage ramp-up delay */
105 const struct mod_timer_alarm_api *alarm_api;
106
107 /* Device state - set if any of the device channels is NOT idle */
108 volatile bool device_busy;
109
110 /* Storage for transmit data in I2C controller mode */
111 uint8_t transmit_data[XR77128_DATA_SIZE_MAX];
112
113 /* Storage for received data in I2C controller mode */
114 uint8_t receive_data[XR77128_DATA_SIZE_MAX];
115 };
116
117 struct xr77128_channel_ctx {
118 /* Pointer to channel configuration */
119 const struct mod_xr77128_channel_config *config;
120
121 /* Required for generating event after alarm callback */
122 fwk_id_t id;
123
124 /* Indicate for a PSU driver whether the driver is enabled */
125 bool psu_set_enabled;
126
127 /* Indicates whether a given channel is enabled */
128 bool is_channel_enabled;
129
130 /* Cache for the voltage of the PSU element */
131 uint32_t current_voltage;
132
133 /*
134 * This field is used when doing a set_voltage request to propagate the
135 * voltage parameter through the processing of the request
136 */
137 uint32_t psu_set_voltage;
138
139 /* PSU operation requested */
140 enum xr77128_psu_request psu_request;
141
142 /*
143 * Backed-up PSU request if any device channel is busy.
144 *
145 * This is required because occasionally the interleaved voltage change
146 * requests targeted to two different channels go unhonoured. So, we save
147 * the request if any of the channels is busy (hence the PSU), and send the
148 * saved request once the PSU is idle again.
149 */
150 enum xr77128_psu_request saved_psu_request;
151 };
152
153 /* Module context */
154 static struct xr77128_module_ctx module_ctx;
155
156 /* Module helpers */
get_dev_ctx(fwk_id_t id)157 static struct xr77128_dev_ctx *get_dev_ctx(fwk_id_t id)
158 {
159 fwk_assert(fwk_module_is_valid_element_id(id));
160
161 return &(module_ctx.dev_ctx_table[fwk_id_get_element_idx(id)]);
162 }
163
get_channel_ctx(fwk_id_t id)164 static struct xr77128_channel_ctx *get_channel_ctx(fwk_id_t id)
165 {
166 fwk_assert(fwk_module_is_valid_sub_element_id(id));
167
168 struct xr77128_dev_ctx *dev_ctx = get_dev_ctx(id);
169
170 return &(dev_ctx->channel_ctx_table[fwk_id_get_sub_element_idx(id)]);
171 }
172
xr77128_controller_tx_command(struct xr77128_dev_ctx * ctx,uint16_t length)173 static int xr77128_controller_tx_command(
174 struct xr77128_dev_ctx *ctx,
175 uint16_t length)
176 {
177 int status;
178
179 status = ctx->i2c_api->write(
180 ctx->config->i2c_hal_id,
181 ctx->config->target_addr,
182 (char *)&ctx->transmit_data[0],
183 length,
184 true);
185
186 if (status != FWK_SUCCESS) {
187 FWK_LOG_ERR("[XR77128] Error transmitting data! %d", status);
188 return status;
189 }
190
191 return FWK_SUCCESS;
192 }
193
xr77128_controller_rx_response(struct xr77128_dev_ctx * ctx,uint16_t length)194 static int xr77128_controller_rx_response(
195 struct xr77128_dev_ctx *ctx,
196 uint16_t length)
197 {
198 int status;
199
200 status = ctx->i2c_api->read(
201 ctx->config->i2c_hal_id,
202 ctx->config->target_addr,
203 (char *)&ctx->receive_data[0],
204 length);
205
206 if (status != FWK_SUCCESS) {
207 FWK_LOG_ERR("[XR77128] Error receiving data! %d", status);
208 }
209
210 return status;
211 }
212
calculate_pmic_set_voltage_val(uint32_t millivolt)213 static uint16_t calculate_pmic_set_voltage_val(uint32_t millivolt)
214 {
215 uint16_t mvref;
216 uint8_t fine_adj;
217 uint16_t coarse_val;
218
219 /* Compute the number of coarse voltage steps */
220 coarse_val = (millivolt * 1000) / XR77128_PSU_VOUT_STEP_COARSE_UV;
221
222 /* Compute the resulting voltage in mV */
223 mvref = (coarse_val * XR77128_PSU_VOUT_STEP_COARSE_UV) / 1000;
224
225 /*
226 * Compute the number of fine steps required to reduce the error.
227 * The truncation means in the worst case, we get just under 2.5mV of
228 * undervoltage.
229 */
230 fine_adj = ((millivolt - mvref) * 1000) / XR77128_PSU_VOUT_STEP_FINE_UV;
231
232 if (fine_adj > XR77128_MAX_FINE_ADJUST) {
233 fine_adj = XR77128_MAX_FINE_ADJUST;
234 }
235
236 return (fine_adj << XR77128_FINE_ADJUST_POS) | coarse_val;
237 }
238
set_psu_request(fwk_id_t id,struct xr77128_channel_ctx * channel_ctx,enum xr77128_psu_request request)239 static void set_psu_request(
240 fwk_id_t id,
241 struct xr77128_channel_ctx *channel_ctx,
242 enum xr77128_psu_request request)
243 {
244 struct xr77128_dev_ctx *ctx;
245 ctx = get_dev_ctx(id);
246
247 if (ctx->device_busy) {
248 channel_ctx->saved_psu_request = request;
249 channel_ctx->psu_request = XR77128_PSU_REQUEST_WAIT_FOR_IDLE;
250 } else {
251 ctx->device_busy = true;
252 channel_ctx->psu_request = request;
253 }
254 }
255
256 /*
257 * Driver functions for the PSU API
258 */
xr77128_set_enabled(fwk_id_t id,bool enabled)259 static int xr77128_set_enabled(fwk_id_t id, bool enabled)
260 {
261 int status;
262 struct fwk_event event;
263 struct xr77128_channel_ctx *channel_ctx;
264 struct psu_set_enabled_param *param =
265 (struct psu_set_enabled_param *)event.params;
266
267 channel_ctx = get_channel_ctx(id);
268
269 if (channel_ctx->psu_request != XR77128_PSU_REQUEST_IDLE) {
270 return FWK_E_BUSY;
271 }
272
273 event = (struct fwk_event){
274 .target_id = id,
275 .id = xr77128_event_id_request,
276 };
277
278 param->enabled = enabled;
279
280 status = fwk_put_event(&event);
281 if (status != FWK_SUCCESS) {
282 return status;
283 }
284
285 set_psu_request(id, channel_ctx, XR77128_PSU_REQUEST_SET_ENABLED);
286
287 return FWK_PENDING;
288 }
289
xr77128_get_enabled(fwk_id_t id,bool * enabled)290 static int xr77128_get_enabled(fwk_id_t id, bool *enabled)
291 {
292 struct xr77128_channel_ctx *channel_ctx;
293
294 if (enabled == NULL) {
295 return FWK_E_PARAM;
296 }
297
298 channel_ctx = get_channel_ctx(id);
299
300 *enabled = channel_ctx->is_channel_enabled;
301
302 return FWK_SUCCESS;
303 }
304
xr77128_set_voltage(fwk_id_t id,uint32_t voltage)305 static int xr77128_set_voltage(fwk_id_t id, uint32_t voltage)
306 {
307 int status;
308 struct fwk_event event;
309 struct xr77128_channel_ctx *channel_ctx;
310 struct psu_set_voltage_param *param =
311 (struct psu_set_voltage_param *)event.params;
312
313 channel_ctx = get_channel_ctx(id);
314
315 if (voltage > channel_ctx->config->psu_max_vout) {
316 return FWK_E_RANGE;
317 }
318
319 if (!channel_ctx->is_channel_enabled) {
320 FWK_LOG_ERR("[XR77128] PSU has not been enabled yet");
321 return FWK_E_STATE;
322 }
323
324 if ((channel_ctx->current_voltage != 0) &&
325 (channel_ctx->current_voltage == voltage)) {
326 return FWK_SUCCESS;
327 }
328
329 if (channel_ctx->psu_request != XR77128_PSU_REQUEST_IDLE) {
330 return FWK_E_BUSY;
331 }
332
333 event = (struct fwk_event){
334 .target_id = id,
335 .id = xr77128_event_id_request,
336 };
337
338 param->set_value = calculate_pmic_set_voltage_val(voltage);
339 param->voltage = voltage;
340
341 status = fwk_put_event(&event);
342 if (status != FWK_SUCCESS) {
343 return status;
344 }
345
346 set_psu_request(id, channel_ctx, XR77128_PSU_REQUEST_SET_VOLTAGE);
347
348 return FWK_PENDING;
349 }
350
xr77128_get_voltage(fwk_id_t id,uint32_t * voltage)351 static int xr77128_get_voltage(fwk_id_t id, uint32_t *voltage)
352 {
353 int status;
354 struct xr77128_channel_ctx *channel_ctx;
355
356 if (voltage == NULL) {
357 return FWK_E_PARAM;
358 }
359
360 channel_ctx = get_channel_ctx(id);
361
362 if (channel_ctx->current_voltage != 0) {
363 *voltage = channel_ctx->current_voltage;
364 return FWK_SUCCESS;
365 }
366
367 if (channel_ctx->psu_request != XR77128_PSU_REQUEST_IDLE) {
368 return FWK_E_BUSY;
369 }
370
371 struct fwk_event_light event = (struct fwk_event_light){
372 .target_id = id,
373 .id = xr77128_event_id_request,
374 };
375
376 status = fwk_put_event(&event);
377 if (status != FWK_SUCCESS) {
378 return status;
379 }
380
381 set_psu_request(id, channel_ctx, XR77128_PSU_REQUEST_GET_VOLTAGE);
382
383 return FWK_PENDING;
384 }
385
386 static struct mod_psu_driver_api psu_driver_api = {
387 .set_enabled = xr77128_set_enabled,
388 .get_enabled = xr77128_get_enabled,
389 .set_voltage = xr77128_set_voltage,
390 .get_voltage = xr77128_get_voltage,
391 };
392
mod_xr77128_init(fwk_id_t module_id,unsigned int element_count,const void * unused)393 static int mod_xr77128_init(
394 fwk_id_t module_id,
395 unsigned int element_count,
396 const void *unused)
397 {
398 if (element_count == 0) {
399 return FWK_E_DATA;
400 }
401
402 module_ctx.device_count = element_count;
403 module_ctx.dev_ctx_table =
404 fwk_mm_calloc(element_count, sizeof(struct xr77128_dev_ctx));
405
406 return FWK_SUCCESS;
407 }
408
mod_xr77128_element_init(fwk_id_t element_id,unsigned int sub_element_count,const void * data)409 static int mod_xr77128_element_init(
410 fwk_id_t element_id,
411 unsigned int sub_element_count,
412 const void *data)
413 {
414 struct xr77128_dev_ctx *ctx;
415 struct xr77128_channel_ctx *channel_ctx;
416 unsigned int channel_idx;
417
418 if (data == NULL) {
419 return FWK_E_DATA;
420 }
421
422 ctx = get_dev_ctx(element_id);
423
424 ctx->config = (struct mod_xr77128_dev_config *)data;
425 ctx->channel_count = sub_element_count;
426 ctx->channel_ctx_table =
427 fwk_mm_calloc(sub_element_count, sizeof(ctx->channel_ctx_table[0]));
428
429 /* Initialize the channels built as sub-elements here */
430 for (channel_idx = 0; channel_idx < sub_element_count; channel_idx++) {
431 channel_ctx = &(ctx->channel_ctx_table[channel_idx]);
432 channel_ctx->config = &(ctx->config->channels[channel_idx]);
433
434 if (channel_ctx->config->psu_bus_idx >= XR77128_CHANNEL_COUNT) {
435 return FWK_E_DATA;
436 }
437
438 channel_ctx->is_channel_enabled = channel_ctx->config->enabled;
439
440 channel_ctx->id = fwk_id_build_sub_element_id(element_id, channel_idx);
441 }
442
443 return FWK_SUCCESS;
444 }
445
mod_xr77128_bind(fwk_id_t id,unsigned int round)446 static int mod_xr77128_bind(fwk_id_t id, unsigned int round)
447 {
448 int status;
449 const struct mod_xr77128_dev_config *config;
450 const struct xr77128_dev_ctx *ctx;
451 struct xr77128_channel_ctx *channel_ctx;
452 unsigned int channel_idx;
453
454 if (round > 0) {
455 return FWK_SUCCESS;
456 }
457
458 if (fwk_id_is_type(id, FWK_ID_TYPE_ELEMENT)) {
459 ctx = get_dev_ctx(id);
460 config = ctx->config;
461
462 /* Bind to I2C HAL */
463 status = fwk_module_bind(
464 config->i2c_hal_id, config->i2c_api_id, &ctx->i2c_api);
465 if (status != FWK_SUCCESS) {
466 return FWK_E_HANDLER;
467 }
468
469 /* Bind sub-elements (PSU channels) */
470 for (channel_idx = 0; channel_idx < ctx->channel_count; channel_idx++) {
471 channel_ctx = &(ctx->channel_ctx_table[channel_idx]);
472
473 status = fwk_module_bind(
474 channel_ctx->config->driver_response_id,
475 channel_ctx->config->driver_response_api_id,
476 &ctx->psu_driver_response_api);
477 if (status != FWK_SUCCESS) {
478 return FWK_E_HANDLER;
479 }
480
481 /* Bind to the alarm HAL */
482 status = fwk_module_bind(
483 channel_ctx->config->alarm_hal_id,
484 MOD_TIMER_API_ID_ALARM,
485 &ctx->alarm_api);
486 if (status != FWK_SUCCESS) {
487 return FWK_E_HANDLER;
488 }
489 }
490 }
491
492 return FWK_SUCCESS;
493 }
494
mod_xr77128_process_bind_request(fwk_id_t requester_id,fwk_id_t id,fwk_id_t api_id,const void ** api)495 static int mod_xr77128_process_bind_request(
496 fwk_id_t requester_id,
497 fwk_id_t id,
498 fwk_id_t api_id,
499 const void **api)
500 {
501 if (!fwk_id_is_type(id, FWK_ID_TYPE_SUB_ELEMENT)) {
502 return FWK_E_ACCESS;
503 }
504
505 if (fwk_id_is_equal(api_id, mod_xr77128_api_id_psu)) {
506 *api = &psu_driver_api;
507 } else {
508 return FWK_E_PARAM;
509 }
510
511 return FWK_SUCCESS;
512 }
513
514 /* Helper function for the PSU API */
alarm_callback(uintptr_t param)515 static void alarm_callback(uintptr_t param)
516 {
517 int status;
518 struct xr77128_dev_ctx *ctx;
519 struct xr77128_channel_ctx *channel_ctx =
520 (struct xr77128_channel_ctx *)param;
521
522 struct fwk_event_light event = (struct fwk_event_light){
523 .source_id = channel_ctx->id,
524 .target_id = channel_ctx->id,
525 .id = xr77128_event_id_request,
526 };
527
528 ctx = get_dev_ctx(channel_ctx->id);
529 ctx->device_busy = false;
530
531 status = fwk_put_event(&event);
532 if (status != FWK_SUCCESS) {
533 FWK_LOG_ERR("[XR77128] %s @%d", __func__, __LINE__);
534 }
535 }
536
537 /* PSU request functions for event calls */
request_get_voltage(struct xr77128_dev_ctx * ctx,struct xr77128_channel_ctx * channel_ctx)538 static int request_get_voltage(
539 struct xr77128_dev_ctx *ctx,
540 struct xr77128_channel_ctx *channel_ctx)
541 {
542 int status;
543 struct mod_psu_driver_response driver_response;
544
545 ctx->transmit_data[0] =
546 XR77128_PWR_READ_VOLTAGE_CHx + channel_ctx->config->psu_bus_idx;
547
548 status = xr77128_controller_tx_command(ctx, 1);
549
550 if (status != FWK_SUCCESS) {
551 FWK_LOG_ERR("[XR77128] %s @%d", __func__, __LINE__);
552 return status;
553 }
554
555 status = xr77128_controller_rx_response(ctx, XR77128_RECEIVE_DATA_MAX);
556
557 if (status != FWK_SUCCESS) {
558 FWK_LOG_ERR("[XR77128] %s @%d", __func__, __LINE__);
559 return status;
560 }
561
562 driver_response.voltage = (uint32_t)(
563 (((uint16_t)ctx->receive_data[0] << 8) | ctx->receive_data[1]) *
564 XR77128_PSU_MVOUT_SCALE_READ);
565
566 channel_ctx->current_voltage = driver_response.voltage;
567
568 return FWK_SUCCESS;
569 }
570
request_set_voltage(const uint8_t * event_params,struct xr77128_dev_ctx * ctx,struct xr77128_channel_ctx * channel_ctx)571 static int request_set_voltage(
572 const uint8_t *event_params,
573 struct xr77128_dev_ctx *ctx,
574 struct xr77128_channel_ctx *channel_ctx)
575 {
576 int status;
577 uint16_t set_value;
578
579 set_value = ((struct psu_set_voltage_param *)event_params)->set_value;
580 channel_ctx->psu_set_voltage =
581 ((struct psu_set_voltage_param *)event_params)->voltage;
582
583 ctx->transmit_data[0] =
584 XR77128_PWR_SET_VOLTAGE_CHx + channel_ctx->config->psu_bus_idx;
585 ctx->transmit_data[1] = (unsigned int)(set_value) >> 8;
586 ctx->transmit_data[2] = (unsigned int)(set_value)&0xFFU;
587
588 status = xr77128_controller_tx_command(ctx, XR77128_TRANSMIT_DATA_MAX);
589
590 if (status != FWK_SUCCESS) {
591 return status;
592 }
593
594 /*
595 * The voltage will ramp to the new value and it is necessary to wait
596 * for it to stabilize before checking the final output voltage using
597 * the board's ADC.
598 */
599 status = ctx->alarm_api->start(
600 channel_ctx->config->alarm_hal_id,
601 XR77128_PSU_RAMP_DELAY_SET_MS,
602 MOD_TIMER_ALARM_TYPE_ONCE,
603 alarm_callback,
604 (uintptr_t)channel_ctx);
605
606 return status;
607 }
608
request_set_enabled(const uint8_t * event_params,struct xr77128_dev_ctx * ctx,struct xr77128_channel_ctx * channel_ctx)609 static int request_set_enabled(
610 const uint8_t *event_params,
611 struct xr77128_dev_ctx *ctx,
612 struct xr77128_channel_ctx *channel_ctx)
613 {
614 int status;
615
616 channel_ctx->psu_set_enabled =
617 ((struct psu_set_enabled_param *)event_params)->enabled;
618 ctx->transmit_data[0] = XR77128_PWR_ENABLE_SUP,
619 ctx->transmit_data[1] = channel_ctx->config->psu_bus_idx;
620 ctx->transmit_data[2] = channel_ctx->psu_set_enabled ?
621 XR77128_CHANNEL_ENABLED :
622 XR77128_CHANNEL_DISABLED;
623
624 status = xr77128_controller_tx_command(ctx, XR77128_TRANSMIT_DATA_MAX);
625
626 if (status != FWK_SUCCESS) {
627 return status;
628 }
629
630 /*
631 * The transaction was successful so the stored channel
632 * status can be updated.
633 */
634 channel_ctx->is_channel_enabled = channel_ctx->psu_set_enabled;
635
636 /*
637 * Wait a fixed time for the voltage to stabilize.
638 */
639 if (channel_ctx->is_channel_enabled) {
640 status = ctx->alarm_api->start(
641 channel_ctx->config->alarm_hal_id,
642 XR77128_PSU_RAMP_DELAY_ENABLE_MS,
643 MOD_TIMER_ALARM_TYPE_ONCE,
644 alarm_callback,
645 (uintptr_t)channel_ctx);
646 }
647
648 return status;
649 }
650
651 /*
652 * This function is called when a request event is received for the XR77128 and
653 * when an I2C transaction is completed.
654 */
xr77128_process_event(const struct fwk_event * event,struct fwk_event * resp_event)655 static int xr77128_process_event(
656 const struct fwk_event *event,
657 struct fwk_event *resp_event)
658 {
659 int status = FWK_SUCCESS;
660 struct xr77128_dev_ctx *ctx;
661 struct xr77128_channel_ctx *channel_ctx;
662 struct mod_psu_driver_response driver_response;
663
664 ctx = get_dev_ctx(event->target_id);
665 channel_ctx = get_channel_ctx(event->target_id);
666
667 switch (channel_ctx->psu_request) {
668 case XR77128_PSU_REQUEST_WAIT_FOR_IDLE:
669 /*
670 * If either of the PSU channels has been freed up, update the
671 * psu_request with the saved request and mark the PSU busy.
672 * Else, we simply enqueue the event again and hope to find the PSU
673 * channels free in the next event run.
674 */
675 if (!ctx->device_busy) {
676 /* Get the saved PSU request and set the PSU busy. */
677 channel_ctx->psu_request = channel_ctx->saved_psu_request;
678 ctx->device_busy = true;
679 }
680
681 status = fwk_put_event((struct fwk_event *)event);
682 if (status == FWK_SUCCESS) {
683 return status;
684 }
685
686 break;
687
688 case XR77128_PSU_REQUEST_GET_VOLTAGE:
689 status = request_get_voltage(ctx, channel_ctx);
690 break;
691
692 case XR77128_PSU_REQUEST_SET_VOLTAGE:
693 channel_ctx->psu_request = XR77128_PSU_REQUEST_DONE_SET_VOLTAGE;
694 status = request_set_voltage(event->params, ctx, channel_ctx);
695 if (status == FWK_SUCCESS) {
696 return status;
697 }
698 break;
699
700 case XR77128_PSU_REQUEST_DONE_SET_VOLTAGE:
701 /*
702 * Voltage ramp up complete, nothing more to do.
703 */
704 channel_ctx->current_voltage = channel_ctx->psu_set_voltage;
705
706 status = FWK_SUCCESS;
707
708 break;
709
710 case XR77128_PSU_REQUEST_SET_ENABLED:
711 channel_ctx->psu_request = XR77128_PSU_REQUEST_DONE_ENABLED;
712 status = request_set_enabled(event->params, ctx, channel_ctx);
713 if (status == FWK_SUCCESS) {
714 return status;
715 }
716 break;
717
718 case XR77128_PSU_REQUEST_DONE_ENABLED:
719 status = FWK_SUCCESS;
720 break;
721
722 default:
723 status = FWK_E_SUPPORT;
724 break;
725 }
726
727 driver_response.status = status;
728 channel_ctx->psu_request = XR77128_PSU_REQUEST_IDLE;
729 channel_ctx->saved_psu_request = XR77128_PSU_REQUEST_IDLE;
730
731 ctx->device_busy = false;
732
733 ctx->psu_driver_response_api->respond(
734 channel_ctx->config->driver_response_id, driver_response);
735
736 return FWK_SUCCESS;
737 }
738
739 const struct fwk_module module_xr77128 = {
740 .type = FWK_MODULE_TYPE_DRIVER,
741 .api_count = (unsigned int)MOD_XR77128_API_COUNT,
742 .init = mod_xr77128_init,
743 .element_init = mod_xr77128_element_init,
744 .bind = mod_xr77128_bind,
745 .process_bind_request = mod_xr77128_process_bind_request,
746 .process_event = xr77128_process_event,
747 .event_count = (unsigned int)XR77128_EVENT_IDX_COUNT,
748 };
749