blob: 18658dabfa5ba2edba9ac6f304be4b3110bb33e3 [file] [log] [blame]
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Mailbox manager abstracts the mailbox interfaces of user commands.
*
* Copyright (C) 2022 Google LLC
*/
#ifndef __GXP_MAILBOX_MANAGER_H__
#define __GXP_MAILBOX_MANAGER_H__
#include "gxp-internal.h"
struct gxp_mailbox;
typedef void __iomem *(*get_mailbox_base_t)(struct gxp_dev *gxp, uint index);
/*
* Following callbacks will be used for manipulating the mailbox to communicating with the
* firmware. By using this callbacks instead of calling the functions of each interface directly,
* we can abstract the mailbox and reduce effort of updating the codes outside of the mailbox when
* we refactor the mailbox in the future.
*/
/*
* Called when allocates a mailbox. The mailbox will be release by the `release_mailbox_t`.
*
* Return a pointer of allocated mailbox or an error pointer if error occurred.
*
* This callback is required if the device is in direct mode, otherwise it is optional.
*/
typedef struct gxp_mailbox *(*allocate_mailbox_t)(
struct gxp_mailbox_manager *mgr, struct gxp_virtual_device *vd,
uint virt_core, u8 core_id);
/*
* Called to release @mailbox previously allocated by `allocate_mailbox_t`.
*
* This callback is required if the device is in direct mode, otherwise it is optional.
*/
typedef void (*release_mailbox_t)(struct gxp_mailbox_manager *mgr,
struct gxp_virtual_device *vd, uint virt_core,
struct gxp_mailbox *mailbox);
/* Called when resets the @mailbox. */
typedef void (*reset_mailbox_t)(struct gxp_mailbox *mailbox);
/*
* Called when requests synchronous commands. This callback will be called from the
* `debugfs_mailbox_execute_cmd` function. The response will be returned to the @resp_seq,
* @resp_status and `retval` of `struct gxp_response` will be returned as the return value of this
* function.
* You can pass NULL to @resp_seq and @resp_status if you don't need the result. See the
* `struct gxp_response` for the details.
*
* Returns the value `retval` of `struct gxp_response` when the request succeeds. Otherwise,
* returns a negative value as an error.
*
* This callback is always required regardless of the mode of device.
*/
typedef int (*execute_cmd_t)(struct gxp_client *client,
struct gxp_mailbox *mailbox, int virt_core,
u16 cmd_code, u8 cmd_priority, u64 cmd_daddr,
u32 cmd_size, u32 cmd_flags, u8 num_cores,
struct gxp_power_states power_states,
u64 *resp_seq, u16 *resp_status);
/*
* Called when requests asynchronous commands. This callback will be called when
* `GXP_MAILBOX_COMMAND_COMPAT` or `GXP_MAILBOX_COMMAND` ioctls are fired. The sequence number of
* the command will be returned to the @cmd_seq. @eventfd will be signalled when the response
* arrives.
*
* Returns a non-zero value when error occurs while putting the command to the cmd_queue of
* mailbox.
*
* This callback is required if the device is in direct mode, otherwise it is optional.
*/
typedef int (*execute_cmd_async_t)(struct gxp_client *client,
struct gxp_mailbox *mailbox, int virt_core,
u16 cmd_code, u8 cmd_priority, u64 cmd_daddr,
u32 cmd_size, u32 cmd_flags,
struct gxp_power_states power_states,
u64 *cmd_seq);
/*
* Called when waiting for an asynchronous response which is requested by `execute_cmd_async`.
* This callback will be called when `GXP_MAILBOX_RESPONSE` ioctl is fired. The response will be
* returned to the @resp_seq, @resp_status and @resp_retval. You can pass NULL to them if you don't
* need the result. See the `struct gxp_response` for the details. The corresponding error code of
* the response status will be set to the @error_code.
*
* Returns 0 if it succeed to get the response. Otherwise, returns a non-zero value as an error.
*
* This callback is required if the device is in direct mode, otherwise it is optional.
*/
typedef int (*wait_async_resp_t)(struct gxp_client *client, int virt_core,
u64 *resp_seq, u16 *resp_status,
u32 *resp_retval, u16 *error_code);
/*
* Called when cleans up unconsumed async responses in the queue which arrived or timed out.
* This callback will be called when the @vd is released.
*
* This callback is always required regardless of the mode of device.
*/
typedef void (*release_unconsumed_async_resps_t)(struct gxp_virtual_device *vd);
/*
* This structure manages how the mailbox works with user commands.
* The way how the mailbox works is dependent on the what kind of interface is used by the device.
* To minimize the effort of updating the codes outside of the mailbox, it abstracts the interfaces
* by defining the callbacks above.
*/
struct gxp_mailbox_manager {
struct gxp_dev *gxp;
u8 num_cores;
struct gxp_mailbox **mailboxes;
get_mailbox_base_t get_mailbox_csr_base;
get_mailbox_base_t get_mailbox_data_base;
allocate_mailbox_t allocate_mailbox;
release_mailbox_t release_mailbox;
reset_mailbox_t reset_mailbox;
execute_cmd_t execute_cmd;
execute_cmd_async_t execute_cmd_async;
wait_async_resp_t wait_async_resp;
release_unconsumed_async_resps_t release_unconsumed_async_resps;
};
/*
* Allocate the mailbox manager.
*
* In general, only one mailbox manager will be used by @gxp. What kind of mailbox interface will
* be used is decided internally.
*/
struct gxp_mailbox_manager *gxp_mailbox_create_manager(struct gxp_dev *gxp,
uint num_cores);
/* Destroy and free the mailbox manager. */
void gxp_mailbox_destroy_manager(struct gxp_dev *gxp,
struct gxp_mailbox_manager *mgr);
#endif /* __GXP_MAILBOX_MANAGER_H__ */