/*
 * All Rights Reserved (C) 2021-2025
 * Exoligent SARL (Colombes, France)
 * Website: www.exoligent.com
 * Author : Maxime Coroyer <maxime.coroyer@exoligent.com>
 */

#ifndef _MBOX_COMMON_H
#define _MBOX_COMMON_H

/**
 * To use the following macros, the user must provide:
 *  - MBOX_WSZ: Size (32-bit) of one mailbox
 *	  (config/status/data_wsz registers (3 words) + data buffer size)
 */
#if defined(MBOX_WSZ)
	#define MBOX_BSZ ((MBOX_WSZ) * 4)
	#define MBOX_BASE_ADDR(x) ((x) * (MBOX_BSZ))
	#define MBOX_CONFIG_ADDR(x) (MBOX_BASE_ADDR(x))
	#define MBOX_STATUS_ADDR(x) ((MBOX_BASE_ADDR(x)) + (0x04u))
	#define MBOX_DATA_WSZ_ADDR(x) ((MBOX_BASE_ADDR(x)) + (0x08u))
	#define MBOX_DATA_ADDR(x) ((MBOX_BASE_ADDR(x)) + (0x0Cu))
#endif

/**
 * MBOX_CONFIG register
 */
/** MASK & SHIFT **/
/* enable interrupt for host */
#define MBOX_HOST_IT_ENA_MASK       0x01u
#define MBOX_HOST_IT_ENA_SHIFT      0u
/* enable interrupt for cpu (riscv) */
#define MBOX_RISC_IT_ENA_MASK       0x01u
#define MBOX_RISC_IT_ENA_SHIFT      1u
/* communication direction */
/* 0: host -> riscv, 1: riscv -> host */
#define MBOX_COM_DIR_MASK           0x01u
#define MBOX_COM_DIR_SHIFT          8u

enum mbox_cfg_flags {
    MBOX_HOST_IT_ENA = ((1u & (MBOX_HOST_IT_ENA_MASK)) << (MBOX_HOST_IT_ENA_SHIFT)),
    MBOX_RISC_IT_ENA = ((1u & (MBOX_RISC_IT_ENA_MASK)) << (MBOX_RISC_IT_ENA_SHIFT)),
    MBOX_DIR_TO_HOST = ((1u & (MBOX_COM_DIR_MASK)) << (MBOX_COM_DIR_SHIFT)),
};

/**
 * MBOX_STATUS register
 */
/** MASK & SHIFT **/
/* acknowledgment code filled by responder entity */
#define MBOX_STATUS_ACK_CODE_MASK   0xFFu
#define MBOX_STATUS_ACK_CODE_SHIFT  0u
/* ready code filled by initiator entity */
#define MBOX_STATUS_RDY_CODE_MASK   0xFFu
#define MBOX_STATUS_RDY_CODE_SHIFT  8u
/* acknowledgment flag: mailbox have been processed */
#define MBOX_STATUS_ACK_MASK        0x01u
#define MBOX_STATUS_ACK_SHIFT       30u
/* ready flag: mailbox ready to be processed */
#define MBOX_STATUS_RDY_MASK        0x01u
#define MBOX_STATUS_RDY_SHIFT       31u
enum mbox_status_flags {
    MBOX_ACK = ((1u & (MBOX_STATUS_ACK_MASK)) << (MBOX_STATUS_ACK_SHIFT)),
    MBOX_RDY = ((1u & (MBOX_STATUS_RDY_MASK)) << (MBOX_STATUS_RDY_SHIFT)),
};

/**
 * Error codes
 */
enum mbox_error_code {
    MBOX_ERR_OK = 0, /* no error */
    /* offset to avoid to overwrite system errors */
    /* trick: we choose offset at 257 = 0x101
     * so err_code is maskable to 8-bit err_code
     * if necessary.
     */
    _MBOX_ERR_CODE_MIN = 257,
    MBOX_ERR_DIR_UNKNOWN = _MBOX_ERR_CODE_MIN,
    MBOX_ERR_NOT_OUTBOX,
    MBOX_ERR_NOT_INBOX,
    MBOX_ERR_INVAL, /* invalid argument */
    MBOX_ERR_TMO,
    MBOX_ERR_BUSY,
    MBOX_ERR_NO_PKT,
    MBOX_ERR_PKT_BAD_SZ,
    MBOX_ERR_PKT_BAD_CMD,
    MBOX_ERR_PKT_RES_FAILED, /* note: used for command (outbox) pending
                              * for result (inbox) packet */
    MBOX_ERR_DMA_BAD_OP,
    _MBOX_ERR_CODE_MAX,
};

#endif /* _MBOX_COMMON_H */
