/* SPDX-License-Identifier: GPL-2.0 */ /* * GXP user command interface. * * Copyright (C) 2022 Google LLC */ #ifndef __GXP_UCI_H__ #define __GXP_UCI_H__ #include #include #include "gxp-client.h" #include "gxp-internal.h" #include "gxp-mailbox.h" #include "gxp-vd.h" #define UCI_RESOURCE_ID 0 struct gxp_mcu; /* Command/Response Structures */ /* Size of `gxp_uci_type` should be u8 to match FW */ enum gxp_uci_type { CORE_COMMAND = 0, WAKELOCK_COMMAND = 1, } __packed; struct gxp_uci_wakelock_command_params { /* DVFS operating point of DSP cores */ uint8_t dsp_operating_point; /* DVFS operating point of memory */ uint8_t memory_operating_point; }; struct gxp_uci_core_command_params { /* iova address of the app command */ uint64_t address; /* size of the app command */ uint32_t size; /* number of dsp cores required for this command */ uint8_t num_cores; /* DVFS operating point of DSP cores */ uint8_t dsp_operating_point; /* DVFS operating point of memory */ uint8_t memory_operating_point; }; struct gxp_uci_command { /* sequence number, should match the corresponding response */ uint64_t seq; /* unique ID for each client that identifies client VM & security realm */ uint32_t client_id; /* type of the command */ enum gxp_uci_type type; /* hint for which core the job should be assigned to */ uint8_t core_id; /* reserved field */ uint8_t reserved[2]; /* All possible command parameters */ union { struct gxp_uci_core_command_params core_command_params; struct gxp_uci_wakelock_command_params wakelock_command_params; uint8_t opaque[48]; }; }; struct gxp_uci_response { /* sequence number, should match the corresponding command */ uint64_t seq; /* unique ID for each client that identifies client VM & security realm*/ uint32_t client_id; /* status code that tells the success or error. */ uint16_t code; /* reserved field */ uint8_t reserved[2]; uint8_t opaque[16]; }; /* * Wrapper struct for responses consumed by a thread other than the one which * sent the command. */ struct gxp_uci_async_response { /* * List entry which will be inserted to the waiting queue of the vd. * It will be pushed into the waiting queue when the response is sent. * (i.e, the `gxp_uci_send_command` function is called) * It will be poped when the response is consumed by the vd. */ struct list_head wait_list_entry; /* * List entry which will be inserted to the dest_queue of the vd. * It will be pushed into the dest_queue when the response is arrived or timed out. * It will be poped when the response is consumed by the vd. */ struct list_head dest_list_entry; /* Stores the response. */ struct gxp_uci_response resp; struct gxp_uci *uci; /* Queue where to be removed from once it is complete or timed out. */ struct list_head *wait_queue; /* Queue to add the response to once it is complete or timed out. */ struct list_head *dest_queue; /* * The lock that protects queues pointed to by `dest_queue` and `wait_queue`. * The mailbox code also uses this lock to protect changes to the `wait_queue` pointer * itself when processing this response. */ spinlock_t *queue_lock; /* Queue of clients to notify when this response is processed. */ wait_queue_head_t *dest_queue_waitq; /* gxp_eventfd to signal when the response completes. May be NULL. */ struct gxp_eventfd *eventfd; /* The request was sent from this virtual device. */ struct gxp_virtual_device *vd; /* Handles arrival, timeout of async response. */ struct gcip_mailbox_resp_awaiter *awaiter; }; struct gxp_uci_wait_list { struct list_head list; struct gxp_uci_response *resp; bool is_async; }; struct gxp_uci { struct gxp_dev *gxp; struct gxp_mcu *mcu; struct gxp_mailbox *mbx; struct gxp_mapped_resource cmd_queue_mem; struct gxp_mapped_resource resp_queue_mem; struct gxp_mapped_resource descriptor_mem; }; /* UCI APIs */ /** * gxp_uci_init() - API for initializing GXP UCI in MCU, should only be * called while initializing MCU * @mcu: The MCU that UCI communicate with * * Return: * * 0 - Initialization finished successfully * * -ENOMEM - Cannot get memory to finish init. */ int gxp_uci_init(struct gxp_mcu *mcu); /** * gxp_uci_exit() - API for releasing the UCI mailbox of MCU. * @uci: The UCI to be released */ void gxp_uci_exit(struct gxp_uci *uci); /* * gxp_uci_send_command() - API for sending @cmd to MCU firmware, and * registering @resp_queue to put the response in after MCU firmware handle the * command. * * Returns 0 on success, a negative errno on failure. */ int gxp_uci_send_command(struct gxp_uci *uci, struct gxp_virtual_device *vd, struct gxp_uci_command *cmd, struct list_head *wait_queue, struct list_head *resp_queue, spinlock_t *queue_lock, wait_queue_head_t *queue_waitq, struct gxp_eventfd *eventfd); /* * gxp_uci_wait_async_response() - API for waiting and fetching a response from * MCU firmware. * * Returns 0 on success, a negative errno on failure. */ int gxp_uci_wait_async_response(struct mailbox_resp_queue *uci_resp_queue, u64 *resp_seq, u16 *error_code, u8 *opaque); #endif /* __GXP_UCI_H__ */