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