/*
 * Copyright (c) 2022, NVIDIA CORPORATION.  All rights reserved.
 *
 * NVIDIA CORPORATION and its licensors retain all intellectual property
 * and proprietary rights in and to this software, related documentation
 * and any modifications thereto.  Any use, reproduction, disclosure or
 * distribution of this software and related documentation without an express
 * license agreement from NVIDIA CORPORATION is strictly prohibited.
 */

#ifndef I2C__I2C_TEGRA_ASYNC_H
#define I2C__I2C_TEGRA_ASYNC_H
#define FSP__I2C__I2C_TEGRA_ASYNC_H                           1

/* Compiler headers */

/* Early FSP headers */

/* Hardware headers */

/* Late FSP headers */

/* Module-specific FSP headers */

/** @file i2c-tegra-async.h */

/* Internal functions between i2c-tegra.c and i2c-tegra-async.c */
/**
 * @addtogroup I2C_TEGRA_INTERNAL_APIS
 * @{
 */
/**
 * @brief Enable clocks for the I2C controller.
 *
 * @param[in] hi2c_tegra    i2c_tegra_handle corresponding to the controller.
 * @retval E_INVALID_STATE  Controller in suspended state.
 * @retval carry_return     Returns error returned by appfw_clk_enable()
 */
error_t tegra_i2c_acquire(const struct i2c_tegra_handle *hi2c_tegra);

/**
 * @brief Disable clocks for the I2C controller.
 *
 * @param[in] hi2c_tegra    i2c_tegra_handle corresponding to the controller.
 * @retval carry_return     Return error returned by appfw_clk_disable()
 */
error_t tegra_i2c_release(const struct i2c_tegra_handle *hi2c_tegra);

/**
 * @brief Initialize the HW controller.
 *
 * @param[in] hi2c_tegra    i2c_tegra_handle corresponding to the controller.
 * @retval carry_return     Return error returned by appfw_clk_reset_pulse()
 * @retval carry_return     Return error returned by tegra_i2c_clock_conf()
 * @retval carry_return     Return error returned by tegra_i2c_conf()
 */
error_t tegra_i2c_hw_init(const struct i2c_tegra_handle *hi2c_tegra);

/**
 * @brief Checks if the input msgs for transfer are valid.
 *
 * @param[in] msgs          messages requested to be transferred.
 * @param[in] num           number of messages being transferred.
 * @retval E_SUCCESS        messages are valid for being transferred.
 * @retval E_INVALID_PARAM  Invalid message parameters
 */
error_t tegra_i2c_validate_msgs(const struct i2c_xfer_msg *msgs, uint32_t num);

/**
 * @brief Transfer a message on the i2c bus.
 *
 * @param[in] hi2c_tegra    i2c_tegra_handle corresponding to the controller.
 * @param[in] this          current message being transferred.
 * @param[in] next          next message to be transferred.
 * @retval 64_bit           time for the message transfer to be initiated on the HW bus.
 */
uint64_t tegra_i2c_xfer_one_msg(struct i2c_tegra_handle *hi2c_tegra,
        const struct i2c_xfer_msg *this, const struct i2c_xfer_msg *next);

/**
 * @brief Check that i2c controller is at expected state before xfer is attempted
 *
 * @param[in] hi2c_tegra      i2c_tegra_handle corresponding to the controller.
 * @retval E_SUCCESS          HW is ready to start transfer.
 * @retval E_I2C_FIFO_STATUS  FIFOS not empty.
 * @retval E_I2C_STALE_INT    Pending interrupts from previous transfer.
 */
error_t tegra_i2c_check_state(const struct i2c_tegra_handle *hi2c_tegra);

/**
 * @brief Return i2c transfer state machine variable.
 *
 * @param[in] hi2c_tegra      i2c_tegra_handle corresponding to the controller.
 * @param[out] msgs_xfered    number of messages transferred till now.
 * @retval 32_bit_value       status value as defined in I2C_XFER_STATUS
 */
uint32_t tegra_i2c_get_xfer_state(const struct i2c_tegra_handle *hi2c_tegra,
                                    uint32_t *msgs_xfered);

/**
 * @brief Tegra implementation for i2c_start_async_xfer
 *
 * @param[in] hi2c_tegra    i2c_tegra_handle corresponding to the controller.
 * @param[in] msgs          Pointer to I2C messages containing the list of
 *                          message to be transferred.
 * @param[in] num_msgs      Number of messages in the msgs parameter.
 * @param[in] client_data   Pointer to client-specific data
 * @param[in] async_xfer_cb Callback pointer to be called when xfer is completed.
 * @retval E_SUCCESS        I2C transfer initiated successfully.
 * @retval carry_return     Return error from tegra_i2c_acquire().
 * @retval carry_return     Return error from tegra_i2c_check_state().
 * @retval carry_return     Return error from tegra_i2c_validate_msgs().
 */
error_t tegra_i2c_start_async_xfer(struct i2c_tegra_handle *hi2c_tegra,
        struct i2c_xfer_msg *msgs, uint32_t num_msgs,
        void *client_data, i2c_async_callback async_xfer_cb);

/**
 * @brief Tegra implementation for i2c_finish_async_xfer
 *
 * @param[in] hi2c_tegra    i2c_tegra_handle corresponding to the controller.
 * @param[in] xfer_ret      Return value from the i2c transfer.
 * @retval E_SUCCESS        I2C transfer initiated successfully.
 * @retval carry_return     Return error from tegra_i2c_hw_init().
 * @retval carry_return     Return error from tegra_i2c_release().
 */
error_t tegra_i2c_finish_async_xfer(const struct i2c_tegra_handle *hi2c_tegra,
        error_t xfer_ret);
/** @} */

#endif        /* FSP_I2C_I2C_TEGRA_ASYNC_H */
