/* * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2024 Ventana Micro Systems Inc. * * Authors: * Anup Patel */ #ifndef __MAILBOX_H__ #define __MAILBOX_H__ #include #include #include /** Representation of a mailbox channel */ struct mbox_chan { /** List head */ struct sbi_dlist node; /** Pointer to the mailbox controller */ struct mbox_controller *mbox; /** * Arguments (or parameters) to identify a mailbox channel * within a mailbox controller. */ #define MBOX_CHAN_MAX_ARGS 2 u32 chan_args[MBOX_CHAN_MAX_ARGS]; }; #define to_mbox_chan(__node) \ container_of((__node), struct mbox_chan, node) /** * Representation of a mailbox data transfer * * NOTE: If both "tx" and "rx" are non-NULL then Tx is done before Rx. */ struct mbox_xfer { #define MBOX_XFER_SEQ (1UL << 0) /** Transfer flags */ unsigned long flags; /** Transfer arguments (or parameters) */ void *args; /** * Sequence number * * If MBOX_XFER_SEQ is not set in flags then mbox_chan_xfer() * will generate a unique sequence number and update this field * else mbox_chan_xfer() will blindly use the sequence number * specified by this field. */ long seq; /** Send data pointer */ void *tx; /** Send data length (valid only if tx != NULL) */ unsigned long tx_len; /** * Send timeout milliseconds (valid only if tx != NULL) * * If this field is non-zero along with tx != NULL then the * mailbox controller driver will wait specified milliseconds * for send data transfer to complete else the mailbox controller * driver will not wait. */ unsigned long tx_timeout; /** Receive data pointer */ void *rx; /** Receive data length (valid only if rx != NULL) */ unsigned long rx_len; /** * Receive timeout milliseconds (valid only if rx != NULL) * * If this field is non-zero along with rx != NULL then the * mailbox controller driver will wait specified milliseconds * for receive data transfer to complete else the mailbox * controller driver will not wait. */ unsigned long rx_timeout; }; #define mbox_xfer_init_tx(__p, __a, __t, __t_len, __t_tim) \ do { \ (__p)->flags = 0; \ (__p)->args = (__a); \ (__p)->tx = (__t); \ (__p)->tx_len = (__t_len); \ (__p)->tx_timeout = (__t_tim); \ (__p)->rx = NULL; \ (__p)->rx_len = 0; \ (__p)->rx_timeout = 0; \ } while (0) #define mbox_xfer_init_rx(__p, __a, __r, __r_len, __r_tim) \ do { \ (__p)->flags = 0; \ (__p)->args = (__a); \ (__p)->tx = NULL; \ (__p)->tx_len = 0; \ (__p)->tx_timeout = 0; \ (__p)->rx = (__r); \ (__p)->rx_len = (__r_len); \ (__p)->rx_timeout = (__r_tim); \ } while (0) #define mbox_xfer_init_txrx(__p, __a, __t, __t_len, __t_tim, __r, __r_len, __r_tim)\ do { \ (__p)->flags = 0; \ (__p)->args = (__a); \ (__p)->tx = (__t); \ (__p)->tx_len = (__t_len); \ (__p)->tx_timeout = (__t_tim); \ (__p)->rx = (__r); \ (__p)->rx_len = (__r_len); \ (__p)->rx_timeout = (__r_tim); \ } while (0) #define mbox_xfer_set_sequence(__p, __seq) \ do { \ (__p)->flags |= MBOX_XFER_SEQ; \ (__p)->seq = (__seq); \ } while (0) /** Representation of a mailbox controller */ struct mbox_controller { /** List head */ struct sbi_dlist node; /** Next sequence atomic counter */ atomic_t xfer_next_seq; /* List of mailbox channels */ struct sbi_dlist chan_list; /** Unique ID of the mailbox controller assigned by the driver */ unsigned int id; /** Maximum length of transfer supported by the mailbox controller */ unsigned int max_xfer_len; /** Pointer to mailbox driver owning this mailbox controller */ void *driver; /** Request a mailbox channel from the mailbox controller */ struct mbox_chan *(*request_chan)(struct mbox_controller *mbox, u32 *chan_args); /** Free a mailbox channel from the mailbox controller */ void (*free_chan)(struct mbox_controller *mbox, struct mbox_chan *chan); /** Transfer data over mailbox channel */ int (*xfer)(struct mbox_chan *chan, struct mbox_xfer *xfer); /** Get an attribute of mailbox channel */ int (*get_attribute)(struct mbox_chan *chan, int attr_id, void *out_value); /** Set an attribute of mailbox channel */ int (*set_attribute)(struct mbox_chan *chan, int attr_id, void *new_value); }; #define to_mbox_controller(__node) \ container_of((__node), struct mbox_controller, node) /** Find a registered mailbox controller */ struct mbox_controller *mbox_controller_find(unsigned int id); /** Register mailbox controller */ int mbox_controller_add(struct mbox_controller *mbox); /** Un-register mailbox controller */ void mbox_controller_remove(struct mbox_controller *mbox); /** Request a mailbox channel */ struct mbox_chan *mbox_controller_request_chan(struct mbox_controller *mbox, u32 *chan_args); /** Free a mailbox channel */ void mbox_controller_free_chan(struct mbox_chan *chan); /** Data transfer over mailbox channel */ int mbox_chan_xfer(struct mbox_chan *chan, struct mbox_xfer *xfer); /** Get an attribute of mailbox channel */ int mbox_chan_get_attribute(struct mbox_chan *chan, int attr_id, void *out_value); /** Set an attribute of mailbox channel */ int mbox_chan_set_attribute(struct mbox_chan *chan, int attr_id, void *new_value); #endif