mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 17:25:35 +03:00
rtcpu: Add Doxygen documentation to RTCPU subsystem
Add detailed Doxygen documentation across all files in the RTCPU subsystem. This documentation effort follows SWUD Doxygen guidelines and provides complete API documentation for the entire RTCPU codebase. Use Cursor Agent to generate SWUD doxygen headers Jira CAMERASW-31120 Change-Id: I3095ff2e321402e72f0f8f5762bad798ea0ecf19 Signed-off-by: Mohit Ingale <mohiti@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3332472 Reviewed-by: Semi Malinen <smalinen@nvidia.com> Reviewed-by: Vincent Chung <vincentc@nvidia.com> GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com> Reviewed-by: Frank Chen <frankc@nvidia.com>
This commit is contained in:
@@ -23,6 +23,30 @@
|
||||
|
||||
#include "capture-ivc-priv.h"
|
||||
|
||||
/**
|
||||
* @brief Transmit a message over IVC channel with mutex protection
|
||||
*
|
||||
* This function transmits a message over the specified IVC channel with mutex
|
||||
* protection.
|
||||
* - Validates that the channel is valid and ready
|
||||
* - Acquires the write lock to ensure exclusive access to the channel using
|
||||
* @ref mutex_lock_interruptible()
|
||||
* - Waits for the channel to be available for writing using @ref wait_event_interruptible()
|
||||
* - Calls @ref tegra_ivc_write() to write the message to the channel
|
||||
* - Releases the write lock using @ref mutex_unlock()
|
||||
*
|
||||
* @param[in] civc Pointer to the capture IVC context
|
||||
* Valid value: non-NULL
|
||||
* @param[in] req Pointer to the message to be transmitted
|
||||
* Valid value: non-NULL
|
||||
* @param[in] len Length of the message in bytes
|
||||
* Valid range: > 0
|
||||
*
|
||||
* @retval -EIO If channel is NULL or not ready
|
||||
* @retval -ERESTARTSYS If signal received while waiting for the write queue
|
||||
* @retval (int) Return code propagated from @ref mutex_lock_interruptible() or
|
||||
* @ref tegra_ivc_write() or @ref wait_event_interruptible()
|
||||
*/
|
||||
static int tegra_capture_ivc_tx_(struct tegra_capture_ivc *civc,
|
||||
const void *req, size_t len)
|
||||
{
|
||||
@@ -52,6 +76,28 @@ static int tegra_capture_ivc_tx_(struct tegra_capture_ivc *civc,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transmit a message over IVC channel with tracing
|
||||
*
|
||||
* This function wraps @ref tegra_capture_ivc_tx_() to provide tracing
|
||||
* functionality for IVC transmissions.
|
||||
* - Gets the channel name using @ref dev_name()
|
||||
* - If len is less than the header length, sets the header to zero and
|
||||
* copies the message header using @ref memcpy()
|
||||
* - Otherwise, copies the header from the message using @ref memcpy()
|
||||
* - Calls @ref tegra_capture_ivc_tx_() to transmit the message
|
||||
* - Records the transmission via trace events for debugging and monitoring
|
||||
* using @ref trace_capture_ivc_send() or @ref trace_capture_ivc_send_error()
|
||||
* based on the return value of @ref tegra_capture_ivc_tx_()
|
||||
* @param[in] civc Pointer to the capture IVC context
|
||||
* Valid value: non-NULL
|
||||
* @param[in] req Pointer to the message to be transmitted
|
||||
* Valid value: non-NULL
|
||||
* @param[in] len Length of the message in bytes
|
||||
* Valid range: > 0
|
||||
*
|
||||
* @retval (int) Value returned by @ref tegra_capture_ivc_tx_()
|
||||
*/
|
||||
static int tegra_capture_ivc_tx(struct tegra_capture_ivc *civc,
|
||||
const void *req, size_t len)
|
||||
{
|
||||
@@ -80,6 +126,21 @@ static int tegra_capture_ivc_tx(struct tegra_capture_ivc *civc,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Submit a control message over the capture-control IVC channel
|
||||
*
|
||||
* This function submits a control message to the capture-control IVC channel.
|
||||
* - Verifies that the capture-control IVC context is initialized
|
||||
* - Calls @ref tegra_capture_ivc_tx() to transmit the control message
|
||||
*
|
||||
* @param[in] control_desc Pointer to the control message descriptor
|
||||
* Valid value: non-NULL
|
||||
* @param[in] len Length of the control message in bytes
|
||||
* Valid range: > 0
|
||||
*
|
||||
* @retval (int) Value returned by @ref tegra_capture_ivc_tx()
|
||||
* @retval -ENODEV If the control IVC context is not initialized
|
||||
*/
|
||||
int tegra_capture_ivc_control_submit(const void *control_desc, size_t len)
|
||||
{
|
||||
if (WARN_ON(__scivc_control == NULL))
|
||||
@@ -89,6 +150,21 @@ int tegra_capture_ivc_control_submit(const void *control_desc, size_t len)
|
||||
}
|
||||
EXPORT_SYMBOL(tegra_capture_ivc_control_submit);
|
||||
|
||||
/**
|
||||
* @brief Submit a capture message over the capture IVC channel
|
||||
*
|
||||
* This function submits a capture message to the capture IVC channel.
|
||||
* - Verifies that the capture IVC context is initialized
|
||||
* - Calls @ref tegra_capture_ivc_tx() to transmit the capture message
|
||||
*
|
||||
* @param[in] capture_desc Pointer to the capture message descriptor
|
||||
* Valid value: non-NULL
|
||||
* @param[in] len Length of the capture message in bytes
|
||||
* Valid range: > 0
|
||||
*
|
||||
* @retval (int) Value returned by @ref tegra_capture_ivc_tx()
|
||||
* @retval -ENODEV If the capture IVC context is not initialized
|
||||
*/
|
||||
int tegra_capture_ivc_capture_submit(const void *capture_desc, size_t len)
|
||||
{
|
||||
if (WARN_ON(__scivc_capture == NULL))
|
||||
@@ -98,6 +174,40 @@ int tegra_capture_ivc_capture_submit(const void *capture_desc, size_t len)
|
||||
}
|
||||
EXPORT_SYMBOL(tegra_capture_ivc_capture_submit);
|
||||
|
||||
/**
|
||||
* @brief Register a callback function for capture-control IVC responses
|
||||
*
|
||||
* This function registers a callback function that will be invoked when a
|
||||
* response is received on the capture-control IVC channel.
|
||||
* - Validates input parameters
|
||||
* - Gets a runtime reference to the IVC channel using @ref tegra_ivc_channel_runtime_get()
|
||||
* - Acquires the callback context list lock using @ref spin_lock()
|
||||
* - Checks if the list is empty using @ref list_empty()
|
||||
* - If the list is empty, releases the lock using @ref spin_unlock().
|
||||
* - Otherwise, acquires an available callback context from the list using @ref list_first_entry()
|
||||
* - Removes the callback context from the list using @ref list_del()
|
||||
* - Releases the callback context list lock using @ref spin_unlock()
|
||||
* - Acquires the callback context lock using @ref mutex_lock()
|
||||
* - Checks if the callback function is already registered using @ref cb_ctx->cb_func
|
||||
* - If the callback function is already registered, releases the callback context lock using
|
||||
* @ref mutex_unlock()
|
||||
* - Otherwise, associates the callback function with the context using @ref cb_ctx->cb_func
|
||||
* - Releases the callback context lock using @ref mutex_unlock()
|
||||
* - Adds back the channel using @ref tegra_ivc_channel_runtime_put()
|
||||
*
|
||||
* @param[in] control_resp_cb Callback function to be invoked for responses
|
||||
* Valid value: non-NULL
|
||||
* @param[out] trans_id Pointer to store the transaction ID
|
||||
* Valid value: non-NULL
|
||||
* @param[in] priv_context Private context to be passed to the callback
|
||||
* Valid value: any value
|
||||
*
|
||||
* @retval 0 On successful registration
|
||||
* @retval -EINVAL If input validation fails
|
||||
* @retval -ENODEV If control IVC context is not initialized
|
||||
* @retval -EAGAIN If no callback contexts are available
|
||||
* @retval -EIO If an internal error occurs during registration
|
||||
*/
|
||||
int tegra_capture_ivc_register_control_cb(
|
||||
tegra_capture_ivc_cb_func control_resp_cb,
|
||||
uint32_t *trans_id, const void *priv_context)
|
||||
@@ -167,6 +277,37 @@ fail:
|
||||
}
|
||||
EXPORT_SYMBOL(tegra_capture_ivc_register_control_cb);
|
||||
|
||||
/**
|
||||
* @brief Update callback context from transaction ID to channel ID
|
||||
*
|
||||
* This function updates the callback context from a temporary transaction ID to
|
||||
* a permanent channel ID. This is typically called after the RTCPU has assigned
|
||||
* a channel ID in response to a channel setup request.
|
||||
* - Validates input parameters
|
||||
* - Gets the channel ID and transaction ID using @ref array_index_nospec()
|
||||
* - Gets the capture IVC context using @ref __scivc_control
|
||||
* - Locks the callback context lock using @ref mutex_lock()
|
||||
* - Validates the transaction context using @ref civc->cb_ctx[trans_id].cb_func
|
||||
* - Validates the channel context using @ref civc->cb_ctx[chan_id].cb_func
|
||||
* - Moves the callback function from the transaction context to the channel context
|
||||
* - Adds the transaction context back to the available list
|
||||
* - Releases the callback context lock using @ref mutex_unlock()
|
||||
* - Locks the callback context list lock using @ref spin_lock()
|
||||
* - Adds the transaction context back to the available list using @ref list_add_tail()
|
||||
* - Releases the callback context list lock using @ref spin_unlock()
|
||||
*
|
||||
* @param[in] chan_id Channel ID assigned by RTCPU
|
||||
* Valid range: [0, @ref NUM_CAPTURE_CHANNELS-1]
|
||||
* @param[in] trans_id Transaction ID previously returned by
|
||||
* @ref tegra_capture_ivc_register_control_cb()
|
||||
* Valid range: [@ref TRANS_ID_START_IDX, @ref TOTAL_CHANNELS-1]
|
||||
*
|
||||
* @retval 0 On successful notification
|
||||
* @retval -EINVAL If input validation fails
|
||||
* @retval -ENODEV If control IVC context is not initialized
|
||||
* @retval -EBADF If transaction context is idle
|
||||
* @retval -EBUSY If channel context is busy
|
||||
*/
|
||||
int tegra_capture_ivc_notify_chan_id(uint32_t chan_id, uint32_t trans_id)
|
||||
{
|
||||
struct tegra_capture_ivc *civc;
|
||||
@@ -217,6 +358,34 @@ int tegra_capture_ivc_notify_chan_id(uint32_t chan_id, uint32_t trans_id)
|
||||
}
|
||||
EXPORT_SYMBOL(tegra_capture_ivc_notify_chan_id);
|
||||
|
||||
/**
|
||||
* @brief Register a callback function for capture IVC status indications
|
||||
*
|
||||
* This function registers a callback function that will be invoked when a
|
||||
* status indication is received on the capture IVC channel for a specific
|
||||
* channel ID.
|
||||
* - Validates input parameters
|
||||
* - Gets a runtime reference to the IVC channel using @ref tegra_ivc_channel_runtime_get()
|
||||
* - Gets lock to the callback context lock using @ref mutex_lock()
|
||||
* - Checks if the channel ID already has a registered callback using @ref cb_ctx->cb_func
|
||||
* - If the channel ID already has a registered callback, releases the callback context lock using
|
||||
* @ref mutex_unlock()
|
||||
* - Otherwise, associates the callback function with the channel ID using @ref cb_ctx->cb_func
|
||||
* - Releases the callback context lock using @ref mutex_unlock()
|
||||
* - Releases the runtime reference to the IVC channel using @ref tegra_ivc_channel_runtime_put()
|
||||
*
|
||||
* @param[in] capture_status_ind_cb Callback function to be invoked for status indications
|
||||
* Valid value: non-NULL
|
||||
* @param[in] chan_id Channel ID for which to register the callback
|
||||
* Valid range: [0, @ref NUM_CAPTURE_CHANNELS-1]
|
||||
* @param[in] priv_context Private context to be passed to the callback
|
||||
* Valid value: any value
|
||||
*
|
||||
* @retval 0 On successful registration
|
||||
* @retval -EINVAL If input validation fails
|
||||
* @retval -ENODEV If capture IVC context is not initialized
|
||||
* @retval -EBUSY If channel ID already has a registered callback
|
||||
*/
|
||||
int tegra_capture_ivc_register_capture_cb(
|
||||
tegra_capture_ivc_cb_func capture_status_ind_cb,
|
||||
uint32_t chan_id, const void *priv_context)
|
||||
@@ -262,6 +431,30 @@ fail:
|
||||
}
|
||||
EXPORT_SYMBOL(tegra_capture_ivc_register_capture_cb);
|
||||
|
||||
/**
|
||||
* @brief Unregister a control callback function for a specified ID
|
||||
*
|
||||
* This function unregisters a previously registered callback function from
|
||||
* either a transaction ID or a channel ID.
|
||||
* - Validates the input ID
|
||||
* - Gets the capture IVC context using @ref __scivc_control
|
||||
* - Gets the id using @ref array_index_nospec()
|
||||
* - Locks the callback context lock using @ref mutex_lock()
|
||||
* - Clears the callback function and context from the specified ID using @ref cb_ctx->cb_func
|
||||
* - Acquires the callback context list lock using @ref spin_lock()
|
||||
* - If the ID is a transaction ID, adds it back to the available list using @ref list_add_tail()
|
||||
* - Releases the callback context list lock using @ref spin_unlock()
|
||||
* - Releases the callback context lock using @ref mutex_unlock()
|
||||
* - Releases the runtime reference to the IVC channel using @ref tegra_ivc_channel_runtime_put()
|
||||
*
|
||||
* @param[in] id Transaction ID or channel ID to unregister
|
||||
* Valid range: [0, @ref TOTAL_CHANNELS-1]
|
||||
*
|
||||
* @retval 0 On successful unregistration
|
||||
* @retval -EINVAL If ID validation fails
|
||||
* @retval -ENODEV If control IVC context is not initialized
|
||||
* @retval -EBADF If the specified ID has no registered callback
|
||||
*/
|
||||
int tegra_capture_ivc_unregister_control_cb(uint32_t id)
|
||||
{
|
||||
struct tegra_capture_ivc *civc;
|
||||
@@ -306,6 +499,26 @@ int tegra_capture_ivc_unregister_control_cb(uint32_t id)
|
||||
}
|
||||
EXPORT_SYMBOL(tegra_capture_ivc_unregister_control_cb);
|
||||
|
||||
/**
|
||||
* @brief Unregister a capture callback function for a specified channel ID
|
||||
*
|
||||
* This function unregisters a previously registered capture callback function.
|
||||
* - Validates the channel ID
|
||||
* - Gets the capture IVC context using @ref __scivc_capture
|
||||
* - Locks the callback context lock using @ref mutex_lock()
|
||||
* - Clears the callback function and context from the specified channel ID using
|
||||
* @ref cb_ctx->cb_func
|
||||
* - Releases the callback context lock using @ref mutex_unlock()
|
||||
* - Releases the runtime reference to the IVC channel using @ref tegra_ivc_channel_runtime_put()
|
||||
*
|
||||
* @param[in] chan_id Channel ID to unregister
|
||||
* Valid range: [0, @ref NUM_CAPTURE_CHANNELS-1]
|
||||
*
|
||||
* @retval 0 On successful unregistration
|
||||
* @retval -EINVAL If channel ID validation fails
|
||||
* @retval -ENODEV If capture IVC context is not initialized
|
||||
* @retval -EBADF If the specified channel ID has no registered callback
|
||||
*/
|
||||
int tegra_capture_ivc_unregister_capture_cb(uint32_t chan_id)
|
||||
{
|
||||
struct tegra_capture_ivc *civc;
|
||||
@@ -339,6 +552,23 @@ int tegra_capture_ivc_unregister_capture_cb(uint32_t chan_id)
|
||||
}
|
||||
EXPORT_SYMBOL(tegra_capture_ivc_unregister_capture_cb);
|
||||
|
||||
/**
|
||||
* @brief Process an IVC message by invoking the appropriate callback
|
||||
*
|
||||
* This inline function processes an incoming IVC message by invoking the registered
|
||||
* callback function for the specified channel ID.
|
||||
* - Checks if a callback function is registered for the channel ID using
|
||||
* @ref civc->cb_ctx[id].cb_func
|
||||
* - If registered, invokes the callback with the message and private context using
|
||||
* @ref civc->cb_ctx[id].cb_func()
|
||||
*
|
||||
* @param[in] civc Pointer to the capture IVC context
|
||||
* Valid value: non-NULL
|
||||
* @param[in] id Channel ID associated with the message
|
||||
* Valid range: [0, @ref TOTAL_CHANNELS-1]
|
||||
* @param[in] msg Pointer to the received message
|
||||
* Valid value: non-NULL
|
||||
*/
|
||||
static inline void tegra_capture_ivc_recv_msg(
|
||||
struct tegra_capture_ivc *civc,
|
||||
uint32_t id,
|
||||
@@ -355,6 +585,22 @@ static inline void tegra_capture_ivc_recv_msg(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Process all pending received IVC messages
|
||||
*
|
||||
* This inline function processes all pending messages in the IVC receive queue.
|
||||
* - Loops while messages are available for reading using @ref tegra_ivc_can_read()
|
||||
* - Retrieves the next message from the queue using @ref tegra_ivc_read_get_next_frame()
|
||||
* - Extracts the channel ID from the message header using @ref hdr->channel_id
|
||||
* - Records the message reception via trace events using @ref trace_capture_ivc_recv()
|
||||
* - Gets the id using @ref array_index_nospec()
|
||||
* - Validates the channel ID and dispatches the message to the appropriate callback using
|
||||
* @ref tegra_capture_ivc_recv_msg()
|
||||
* - Advances the IVC read queue to the next message using @ref tegra_ivc_read_advance()
|
||||
*
|
||||
* @param[in] civc Pointer to the capture IVC context
|
||||
* Valid value: non-NULL
|
||||
*/
|
||||
static inline void tegra_capture_ivc_recv(struct tegra_capture_ivc *civc)
|
||||
{
|
||||
struct tegra_ivc *ivc = &civc->chan->ivc;
|
||||
@@ -393,6 +639,21 @@ static inline void tegra_capture_ivc_recv(struct tegra_capture_ivc *civc)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Worker function to process IVC notifications
|
||||
*
|
||||
* This function is invoked when an IVC notification is received from the RTCPU.
|
||||
* - Retrieves the capture IVC context from the work structure using @ref container_of()
|
||||
* - Acquires a runtime PM reference to prevent suspended operation using
|
||||
* @ref pm_runtime_get_if_in_use()
|
||||
* - If channel is not ready, logs a warning using @ref WARN_ON()
|
||||
* - Verifies that the channel is ready using @ref chan->is_ready
|
||||
* - Calls @ref tegra_capture_ivc_recv() to process all pending messages
|
||||
* - Releases the runtime PM reference using @ref pm_runtime_put()
|
||||
*
|
||||
* @param[in] work Pointer to the kthread work structure
|
||||
* Valid value: non-NULL
|
||||
*/
|
||||
static void tegra_capture_ivc_worker(struct kthread_work *work)
|
||||
{
|
||||
struct tegra_capture_ivc *civc;
|
||||
@@ -417,6 +678,20 @@ static void tegra_capture_ivc_worker(struct kthread_work *work)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief IVC notification callback from the IVC subsystem
|
||||
*
|
||||
* This function is called by the IVC subsystem when a notification is received
|
||||
* from the remote processor (RTCPU).
|
||||
* - Retrieves the capture IVC context from the channel driver data using
|
||||
* @ref tegra_ivc_channel_get_drvdata()
|
||||
* - Records the notification via trace events using @ref trace_capture_ivc_notify()
|
||||
* - Wakes up any threads waiting to write to the IVC channel using @ref wake_up()
|
||||
* - Queues the worker to process any received messages using @ref kthread_queue_work()
|
||||
*
|
||||
* @param[in] chan Pointer to the IVC channel that received the notification
|
||||
* Valid value: non-NULL
|
||||
*/
|
||||
static void tegra_capture_ivc_notify(struct tegra_ivc_channel *chan)
|
||||
{
|
||||
struct tegra_capture_ivc *civc = tegra_ivc_channel_get_drvdata(chan);
|
||||
@@ -430,6 +705,44 @@ static void tegra_capture_ivc_notify(struct tegra_ivc_channel *chan)
|
||||
|
||||
#define NV(x) "nvidia," #x
|
||||
|
||||
/**
|
||||
* @brief Probe function for the tegra capture IVC driver
|
||||
*
|
||||
* This function is called when a matching IVC channel is found.
|
||||
* - Allocates and initializes the capture IVC context using @ref devm_kzalloc()
|
||||
* - Reads the service type from device tree using @ref of_property_read_string()
|
||||
* - Stores the channel reference in the IVC context (civc->chan = chan)
|
||||
* - Initializes synchronization primitives using @ref mutex_init()
|
||||
* - Initializes the work structure for processing IVC notifications using @ref kthread_init_work()
|
||||
* - Initializes the worker thread using @ref kthread_init_worker()
|
||||
* - Creates a kernel worker thread using @ref kthread_create()
|
||||
* - Sets the worker thread to FIFO scheduling using @ref sched_set_fifo_low()
|
||||
* - Wakes up the worker thread using @ref wake_up_process()
|
||||
* - Initializes the IVC write queue using @ref init_waitqueue_head()
|
||||
* - Initializes the spinlock for available context list using @ref spin_lock_init()
|
||||
* - Initializes the transaction context list using @ref INIT_LIST_HEAD()
|
||||
* - Locks the callback context lock using @ref mutex_lock()
|
||||
* - Adds the transaction contexts to the available list using @ref list_add_tail()
|
||||
* - Unlocks the callback context lock using @ref mutex_unlock()
|
||||
* - Associates the context with the IVC channel using @ref tegra_ivc_channel_set_drvdata()
|
||||
* - Checks if the service type is "capture-control" using @ref strcmp()
|
||||
* - Verifies that no control channel already exists using @ref WARN_ON()
|
||||
* - Registers the context as a control service by setting @ref __scivc_control
|
||||
* - If not control, checks if service type is "capture" using @ref strcmp()
|
||||
* - Verifies that no capture channel already exists using @ref WARN_ON()
|
||||
* - Registers the context as a capture service by setting @ref __scivc_capture
|
||||
* - Returns error if service type is neither control nor capture
|
||||
* - Stops the worker thread using @ref kthread_stop() if an error occurs
|
||||
*
|
||||
* @param[in] chan Pointer to the IVC channel to be probed
|
||||
* Valid value: non-NULL
|
||||
*
|
||||
* @retval 0 On successful probe
|
||||
* @retval -ENOMEM If memory allocation fails
|
||||
* @retval -EEXIST If a channel for the same service already exists
|
||||
* @retval -EINVAL If the service type is invalid or missing
|
||||
* @retval (int) Value returned by @ref of_property_read_string() or @ref kthread_create()
|
||||
*/
|
||||
static int tegra_capture_ivc_probe(struct tegra_ivc_channel *chan)
|
||||
{
|
||||
struct device *dev = &chan->dev;
|
||||
@@ -510,6 +823,21 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Remove function for the tegra capture IVC driver
|
||||
*
|
||||
* This function is called when an IVC channel is being removed.
|
||||
* - Gets the capture IVC context from the channel driver data using
|
||||
* @ref tegra_ivc_channel_get_drvdata()
|
||||
* - Ensures any pending work on the worker thread is complete using
|
||||
* @ref kthread_flush_worker()
|
||||
* - Stops the worker thread using @ref kthread_stop()
|
||||
* - Unregisters the IVC context from the global context using
|
||||
* @ref __scivc_control or @ref __scivc_capture
|
||||
*
|
||||
* @param[in] chan Pointer to the IVC channel to be removed
|
||||
* Valid value: non-NULL
|
||||
*/
|
||||
static void tegra_capture_ivc_remove(struct tegra_ivc_channel *chan)
|
||||
{
|
||||
struct tegra_capture_ivc *civc = tegra_ivc_channel_get_drvdata(chan);
|
||||
|
||||
@@ -24,6 +24,19 @@ struct camrtc_clk_group {
|
||||
} clocks[];
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Release function for the camera RTCPU clock group
|
||||
*
|
||||
* This function releases all the clocks in the clock group.
|
||||
* - Iterates through all clocks in the group
|
||||
* - Puts back each clock using @ref clk_put()
|
||||
* - Puts back the parent clocks (slow and fast)
|
||||
*
|
||||
* @param[in] dev Pointer to the device
|
||||
* Valid value: non-NULL
|
||||
* @param[in] res Pointer to the clock group resource
|
||||
* Valid value: non-NULL
|
||||
*/
|
||||
static void camrtc_clk_group_release(struct device *dev, void *res)
|
||||
{
|
||||
const struct camrtc_clk_group *grp = res;
|
||||
@@ -40,6 +53,28 @@ static void camrtc_clk_group_release(struct device *dev, void *res)
|
||||
clk_put(grp->parents.fast);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieve a parent clock from device tree
|
||||
*
|
||||
* This function retrieves a parent clock using the device tree.
|
||||
* - Validates the input index
|
||||
* - Parses a phandle with arguments using @ref of_parse_phandle_with_args()
|
||||
* - Gets the clock from the provider using @ref of_clk_get_from_provider()
|
||||
* - Releases the node pointer using @ref of_node_put()
|
||||
* - Returns the clock via the return_clk parameter
|
||||
*
|
||||
* @param[in] np Pointer to device node
|
||||
* Valid value: non-NULL
|
||||
* @param[in] index Index of the parent clock
|
||||
* Valid range: >= 0
|
||||
* @param[out] return_clk Pointer to store the retrieved clock
|
||||
* Valid value: non-NULL
|
||||
*
|
||||
* @retval 0 On successful retrieval
|
||||
* @retval -EINVAL If index is negative
|
||||
* @retval (int) Error value returned by @ref of_parse_phandle_with_args()
|
||||
* or @ref of_clk_get_from_provider()
|
||||
*/
|
||||
static int camrtc_clk_group_get_parent(
|
||||
struct device_node *np,
|
||||
int index,
|
||||
@@ -69,6 +104,29 @@ static int camrtc_clk_group_get_parent(
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a clock group for a device
|
||||
*
|
||||
* This function creates and initializes a clock group for a device.
|
||||
* - Validates the input device
|
||||
* - Gets the device node
|
||||
* - Counts the number of clocks, clock rates, and parent clocks
|
||||
* - Allocates memory for the clock group using @ref devres_alloc()
|
||||
* - Gets each clock using @ref of_clk_get()
|
||||
* - Gets the clock rates for each clock
|
||||
* - Gets the parent clocks using @ref camrtc_clk_group_get_parent()
|
||||
* - Registers the resource with the device using @ref devres_add()
|
||||
*
|
||||
* @param[in] dev Pointer to the device
|
||||
* Valid value: non-NULL
|
||||
*
|
||||
* @retval (struct camrtc_clk_group*) Pointer to the clock group on success
|
||||
* @retval ERR_PTR(-EINVAL) If device is invalid or does not have a device node
|
||||
* @retval ERR_PTR(-ENOENT) If no clocks are found
|
||||
* @retval ERR_PTR(-ENOMEM) If memory allocation fails
|
||||
* @retval ERR_PTR(ret) Error returned by @ref camrtc_clk_group_get_parent()
|
||||
* or @ref of_clk_get()
|
||||
*/
|
||||
struct camrtc_clk_group *camrtc_clk_group_get(
|
||||
struct device *dev)
|
||||
{
|
||||
@@ -152,6 +210,22 @@ error:
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(camrtc_clk_group_get);
|
||||
|
||||
/**
|
||||
* @brief Reports an error related to a clock in a clock group
|
||||
*
|
||||
* This function reports an error related to a specific clock in a clock group.
|
||||
* - Attempts to get the clock name from the device tree using @ref of_property_read_string_index()
|
||||
* - Prints a warning message about the operation that failed using @ref dev_warn()
|
||||
*
|
||||
* @param[in] grp Pointer to the clock group
|
||||
* Valid value: non-NULL
|
||||
* @param[in] op String describing the operation that failed
|
||||
* Valid value: non-NULL
|
||||
* @param[in] index Index of the clock in the clock group
|
||||
* Valid range: [0, grp->nclocks-1]
|
||||
* @param[in] error Error code
|
||||
* Valid value: any
|
||||
*/
|
||||
static void camrtc_clk_group_error(
|
||||
const struct camrtc_clk_group *grp,
|
||||
char const *op,
|
||||
@@ -171,6 +245,22 @@ static void camrtc_clk_group_error(
|
||||
op, name, index, error);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable all clocks in a clock group
|
||||
*
|
||||
* This function enables all clocks in the specified clock group.
|
||||
* - Checks if the clock group is valid using @ref IS_ERR_OR_NULL()
|
||||
* - Iterates through all clocks in the group
|
||||
* - Prepares and enables each clock using @ref clk_prepare_enable()
|
||||
* - Reports errors using @ref camrtc_clk_group_error() if a clock fails to enable
|
||||
*
|
||||
* @param[in] grp Pointer to the clock group
|
||||
* Valid value: non-NULL and not an error pointer
|
||||
*
|
||||
* @retval 0 On successful enablement of all clocks
|
||||
* @retval -ENODEV If the clock group is invalid
|
||||
* @retval (int) Error returned by @ref clk_prepare_enable()
|
||||
*/
|
||||
int camrtc_clk_group_enable(const struct camrtc_clk_group *grp)
|
||||
{
|
||||
int index, err;
|
||||
@@ -190,6 +280,17 @@ int camrtc_clk_group_enable(const struct camrtc_clk_group *grp)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(camrtc_clk_group_enable);
|
||||
|
||||
/**
|
||||
* @brief Disable all clocks in a clock group
|
||||
*
|
||||
* This function disables all clocks in the specified clock group.
|
||||
* - Checks if the clock group is valid using @ref IS_ERR_OR_NULL()
|
||||
* - Iterates through all clocks in the group
|
||||
* - Disables and unprepares each clock using @ref clk_disable_unprepare()
|
||||
*
|
||||
* @param[in] grp Pointer to the clock group
|
||||
* Valid value: non-NULL and not an error pointer
|
||||
*/
|
||||
void camrtc_clk_group_disable(const struct camrtc_clk_group *grp)
|
||||
{
|
||||
int index;
|
||||
@@ -202,6 +303,20 @@ void camrtc_clk_group_disable(const struct camrtc_clk_group *grp)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(camrtc_clk_group_disable);
|
||||
|
||||
/**
|
||||
* @brief Set the parent clock for all clocks in a clock group
|
||||
*
|
||||
* This function sets the specified parent clock for all clocks in the group.
|
||||
* - Checks if the parent clock is valid using @ref IS_ERR_OR_NULL()
|
||||
* - Iterates through all clocks in the group
|
||||
* - Sets the parent clock for each clock using @ref clk_set_parent()
|
||||
* - Reports errors using @ref pr_err() if parent clock cannot be set
|
||||
*
|
||||
* @param[in] grp Pointer to the clock group
|
||||
* Valid value: non-NULL
|
||||
* @param[in] parent Pointer to the parent clock
|
||||
* Valid value: non-NULL and not an error pointer
|
||||
*/
|
||||
static void camrtc_clk_group_set_parent(const struct camrtc_clk_group *grp,
|
||||
struct clk *parent)
|
||||
{
|
||||
@@ -219,6 +334,23 @@ static void camrtc_clk_group_set_parent(const struct camrtc_clk_group *grp,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adjust clocks in a clock group to slow mode
|
||||
*
|
||||
* This function adjusts all clocks in the specified clock group to their slow
|
||||
* rates and sets the slow parent clock.
|
||||
* - Checks if the clock group is valid using @ref IS_ERR_OR_NULL()
|
||||
* - Iterates through all clocks in the group
|
||||
* - Sets the rate of each clock to its slow rate using @ref clk_set_rate() if
|
||||
* the slow rate is non-zero
|
||||
* - Sets the parent clock to the slow parent using @ref camrtc_clk_group_set_parent()
|
||||
*
|
||||
* @param[in] grp Pointer to the clock group
|
||||
* Valid value: non-NULL and not an error pointer
|
||||
*
|
||||
* @retval 0 On successful adjustment
|
||||
* @retval -ENODEV If the clock group is invalid
|
||||
*/
|
||||
int camrtc_clk_group_adjust_slow(const struct camrtc_clk_group *grp)
|
||||
{
|
||||
int index;
|
||||
@@ -239,6 +371,22 @@ int camrtc_clk_group_adjust_slow(const struct camrtc_clk_group *grp)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(camrtc_clk_group_adjust_slow);
|
||||
|
||||
/**
|
||||
* @brief Adjusts all clocks in a clock group to their fast rates
|
||||
*
|
||||
* This function adjusts all clocks in the specified clock group to their fast rates
|
||||
* and sets the fast parent clock. It performs the following operations:
|
||||
* - Validates the clock group using @ref IS_ERR_OR_NULL()
|
||||
* - Sets the parent clock to the fast parent using @ref camrtc_clk_group_set_parent()
|
||||
* - Iterates through all clocks in the group
|
||||
* - Sets the rate of each clock to its fast rate using @ref clk_set_rate() if the fast rate is non-zero
|
||||
*
|
||||
* @param[in] grp Pointer to the clock group
|
||||
* Valid value: non-NULL and not an error pointer
|
||||
*
|
||||
* @retval 0 On successful adjustment
|
||||
* @retval -ENODEV If the clock group is invalid
|
||||
*/
|
||||
int camrtc_clk_group_adjust_fast(const struct camrtc_clk_group *grp)
|
||||
{
|
||||
int index;
|
||||
|
||||
@@ -17,6 +17,27 @@ struct camrtc_device_group {
|
||||
struct platform_device *devices[];
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Gets a platform device from a device tree node
|
||||
*
|
||||
* This function retrieves a platform device from a device tree node specified by
|
||||
* a phandle property. It performs the following operations:
|
||||
* 1. Gets the device node using @ref of_parse_phandle()
|
||||
* 2. Checks if the device is available using @ref of_device_is_available()
|
||||
* 3. Finds the platform device using @ref of_find_device_by_node()
|
||||
* 4. Stores the device in the group's device array
|
||||
*
|
||||
* @param[in] grp Pointer to the device group
|
||||
* Valid value: non-NULL
|
||||
* @param[in] dev Pointer to the parent device
|
||||
* Valid value: non-NULL
|
||||
* @param[in] name Name of the phandle property
|
||||
* Valid value: non-NULL
|
||||
* @param[in] index Index in the phandle array
|
||||
* Valid range: >= 0
|
||||
*
|
||||
* @retval 0 Device retrieved successfully or skipped if disabled
|
||||
*/
|
||||
static int get_grouped_device(struct camrtc_device_group *grp,
|
||||
struct device *dev, char const *name, int index)
|
||||
{
|
||||
@@ -46,6 +67,20 @@ static int get_grouped_device(struct camrtc_device_group *grp,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Releases resources associated with a device group
|
||||
*
|
||||
* This function is called to release resources when a device group is being destroyed.
|
||||
* It performs the following operations:
|
||||
* 1. Releases the reference to the parent device using @ref put_device()
|
||||
* 2. Iterates through all devices in the group
|
||||
* 3. Releases each platform device using @ref platform_device_put()
|
||||
*
|
||||
* @param[in] dev Pointer to the parent device
|
||||
* Valid value: non-NULL
|
||||
* @param[in] res Pointer to the device group resource
|
||||
* Valid value: non-NULL
|
||||
*/
|
||||
static void camrtc_device_group_release(struct device *dev, void *res)
|
||||
{
|
||||
const struct camrtc_device_group *grp = res;
|
||||
@@ -57,6 +92,31 @@ static void camrtc_device_group_release(struct device *dev, void *res)
|
||||
platform_device_put(grp->devices[i]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets a device group based on device tree properties
|
||||
*
|
||||
* This function creates and initializes a device group based on device tree properties.
|
||||
* It performs the following operations:
|
||||
* 1. Validates the device and its device tree node
|
||||
* 2. Counts phandle arguments using @ref of_count_phandle_with_args()
|
||||
* 3. Allocates memory for the device group using @ref devres_alloc()
|
||||
* 4. Gets device references using @ref get_device()
|
||||
* 5. Retrieves each device in the group using @ref get_grouped_device()
|
||||
* 6. Adds the device group to device resources using @ref devres_add()
|
||||
*
|
||||
* @param[in] dev Pointer to the parent device
|
||||
* Valid value: non-NULL with valid device tree node
|
||||
* @param[in] property_name Name of the device tree property containing device phandles
|
||||
* Valid value: non-NULL
|
||||
* @param[in] names_property_name Name of the device tree property containing device names
|
||||
* Valid value: non-NULL
|
||||
*
|
||||
* @retval struct camrtc_device_group* Device group on success
|
||||
* @retval ERR_PTR(-EINVAL) If device or device tree node is invalid
|
||||
* @retval ERR_PTR(-ENOENT) If no devices are found
|
||||
* @retval ERR_PTR(-ENOMEM) If memory allocation fails
|
||||
* @retval ERR_PTR(err) If device retrieval fails
|
||||
*/
|
||||
struct camrtc_device_group *camrtc_device_group_get(
|
||||
struct device *dev,
|
||||
char const *property_name,
|
||||
@@ -97,6 +157,17 @@ struct camrtc_device_group *camrtc_device_group_get(
|
||||
}
|
||||
EXPORT_SYMBOL(camrtc_device_group_get);
|
||||
|
||||
/**
|
||||
* @brief Gets a reference to a platform device
|
||||
*
|
||||
* This function gets a reference to a platform device by incrementing its
|
||||
* reference count using @ref get_device() if the device is not NULL.
|
||||
*
|
||||
* @param[in] pdev Pointer to the platform device
|
||||
* Valid value: any value including NULL
|
||||
*
|
||||
* @retval struct platform_device* The input platform device pointer
|
||||
*/
|
||||
static inline struct platform_device *platform_device_get(
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
@@ -105,6 +176,26 @@ static inline struct platform_device *platform_device_get(
|
||||
return pdev;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets a platform device from a device group by name
|
||||
*
|
||||
* This function retrieves a platform device from a device group by matching
|
||||
* the device name in the device tree property. It performs the following operations:
|
||||
* 1. Validates the device group
|
||||
* 2. Checks if the names property exists
|
||||
* 3. Finds the device index using @ref of_property_match_string()
|
||||
* 4. Gets a reference to the device using @ref platform_device_get()
|
||||
*
|
||||
* @param[in] grp Pointer to the device group
|
||||
* Valid value: non-NULL
|
||||
* @param[in] device_name Name of the device to find
|
||||
* Valid value: non-NULL
|
||||
*
|
||||
* @retval struct platform_device* Device pointer on success
|
||||
* @retval ERR_PTR(-EINVAL) If device group is NULL
|
||||
* @retval ERR_PTR(-ENOENT) If names property is not found
|
||||
* @retval ERR_PTR(-ENODEV) If device is not found or index is invalid
|
||||
*/
|
||||
struct platform_device *camrtc_device_get_byname(
|
||||
struct camrtc_device_group *grp,
|
||||
const char *device_name)
|
||||
|
||||
@@ -54,6 +54,26 @@ struct camrtc_hsp_op {
|
||||
int (*set_operating_point)(struct camrtc_hsp *, u32 operating_point, long *timeout);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Sends a request message over the HSP mailbox
|
||||
*
|
||||
* This function sends a request message over the HSP mailbox and handles error reporting.
|
||||
* It acts as a wrapper for the implementation-specific send operation.
|
||||
* - Calls the implementation-specific send operation using @ref camhsp->op->send()
|
||||
* - Performs error reporting using @ref dev_err() or @ref dev_dbg() based on the return value
|
||||
*
|
||||
* @param[in] camhsp Pointer to the camera HSP context
|
||||
* Valid value: non-NULL
|
||||
* @param[in] request Request message to send
|
||||
* Valid value: any integer value
|
||||
* @param[in,out] timeout Pointer to timeout value in jiffies
|
||||
* Valid value: non-NULL
|
||||
*
|
||||
* @retval >=0 On successful transmission
|
||||
* @retval -ETIME If the mailbox is not empty within the timeout period
|
||||
* @retval -EINVAL If the mailbox channel is invalid
|
||||
* @retval -ENOBUFS If there is no space left in the mailbox message queue
|
||||
*/
|
||||
static int camrtc_hsp_send(struct camrtc_hsp *camhsp,
|
||||
int request, long *timeout)
|
||||
{
|
||||
@@ -75,6 +95,26 @@ static int camrtc_hsp_send(struct camrtc_hsp *camhsp,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receives a response message from the HSP mailbox
|
||||
*
|
||||
* This function waits for a response message from the HSP mailbox within
|
||||
* the specified timeout period.
|
||||
* - Waits for a response using @ref wait_event_timeout()
|
||||
* - Atomically exchanges the response value using @ref atomic_xchg()
|
||||
* - Reports a timeout error using @ref dev_err() if no response is received
|
||||
* - Logs the response using @ref dev_dbg()
|
||||
*
|
||||
* @param[in] camhsp Pointer to the camera HSP context
|
||||
* Valid value: non-NULL
|
||||
* @param[in] command The original command sent
|
||||
* Valid value: any integer value
|
||||
* @param[in,out] timeout Pointer to timeout value in jiffies
|
||||
* Valid value: non-NULL
|
||||
*
|
||||
* @retval >=0 The response value on success
|
||||
* @retval -ETIMEDOUT If no response is received within the timeout period
|
||||
*/
|
||||
static int camrtc_hsp_recv(struct camrtc_hsp *camhsp,
|
||||
int command, long *timeout)
|
||||
{
|
||||
@@ -96,6 +136,23 @@ static int camrtc_hsp_recv(struct camrtc_hsp *camhsp,
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sends a command and waits for a response from the HSP mailbox
|
||||
*
|
||||
* This function combines sending a command and receiving a response in a single call.
|
||||
* - Sends the command using @ref camrtc_hsp_send()
|
||||
* - If the send operation is successful, waits for a response using @ref camrtc_hsp_recv()
|
||||
*
|
||||
* @param[in] camhsp Pointer to the camera HSP context
|
||||
* Valid value: non-NULL
|
||||
* @param[in] command Command to send
|
||||
* Valid value: any integer value
|
||||
* @param[in,out] timeout Pointer to timeout value in jiffies
|
||||
* Valid value: non-NULL
|
||||
*
|
||||
* @retval >=0 The response value on success
|
||||
* @retval <0 Error code from @ref camrtc_hsp_send() or @ref camrtc_hsp_recv()
|
||||
*/
|
||||
static int camrtc_hsp_sendrecv(struct camrtc_hsp *camhsp,
|
||||
int command, long *timeout)
|
||||
{
|
||||
@@ -110,6 +167,23 @@ static int camrtc_hsp_sendrecv(struct camrtc_hsp *camhsp,
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Protocol nvidia,tegra-camrtc-hsp-vm */
|
||||
|
||||
/**
|
||||
* @brief Handles notification of mailbox receive events
|
||||
*
|
||||
* This function is called by the mailbox framework when data is received.
|
||||
* It processes the received message and performs the appropriate action:
|
||||
* - Retrieves the HSP context using @ref dev_get_drvdata()
|
||||
* - Extracts status and group information from the message
|
||||
* - Validates the HSP context using @ref WARN_ON()
|
||||
* - Handles unknown messages using @ref dev_dbg()
|
||||
* - Calls the group notification callback if a group notification is received
|
||||
* - For response messages, sets the response and wakes up waiters using @ref atomic_set() and @ref wake_up()
|
||||
*
|
||||
* @param[in] cl Pointer to the mailbox client
|
||||
* Valid value: non-NULL
|
||||
* @param[in] data Received message data
|
||||
* Valid value: any value
|
||||
*/
|
||||
static void camrtc_hsp_rx_full_notify(mbox_client *cl, void *data)
|
||||
{
|
||||
struct camrtc_hsp *camhsp = dev_get_drvdata(cl->dev);
|
||||
@@ -142,6 +216,20 @@ static void camrtc_hsp_rx_full_notify(mbox_client *cl, void *data)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handles notification of mailbox transmit completion
|
||||
*
|
||||
* This function is called by the mailbox framework when the transmit queue
|
||||
* is emptied. It signals completion to any waiting threads.
|
||||
* - Completes the "emptied" completion using @ref complete()
|
||||
*
|
||||
* @param[in] cl Pointer to the mailbox client
|
||||
* Valid value: non-NULL
|
||||
* @param[in] data Data from the mailbox controller
|
||||
* Valid value: any value
|
||||
* @param[in] empty_value Completion status
|
||||
* Valid value: any value
|
||||
*/
|
||||
static void camrtc_hsp_tx_empty_notify(mbox_client *cl, void *data, int empty_value)
|
||||
{
|
||||
struct camrtc_hsp *camhsp = dev_get_drvdata(cl->dev);
|
||||
@@ -183,6 +271,25 @@ static const struct camrtc_hsp_op camrtc_hsp_vm_ops = {
|
||||
.set_operating_point = camrtc_hsp_vm_set_operating_point,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Sends a message over the VM HSP mailbox
|
||||
*
|
||||
* This function sends a message over the VM HSP mailbox using the provided channel.
|
||||
* It performs the following operations:
|
||||
* - Acquires the send lock using @ref spin_lock_irqsave()
|
||||
* - Clears any previous response using @ref atomic_set()
|
||||
* - Sends the message using @ref mbox_send_message()
|
||||
* - Releases the send lock using @ref spin_unlock_irqrestore()
|
||||
*
|
||||
* @param[in] camhsp Pointer to the camera HSP context
|
||||
* Valid value: non-NULL
|
||||
* @param[in] request Message to send
|
||||
* Valid value: any integer value
|
||||
* @param[in,out] timeout Pointer to timeout value in jiffies
|
||||
* Valid value: non-NULL
|
||||
*
|
||||
* @retval (int) response from @ref mbox_send_message()
|
||||
*/
|
||||
static int camrtc_hsp_vm_send(struct camrtc_hsp *camhsp,
|
||||
int request, long *timeout)
|
||||
{
|
||||
@@ -197,12 +304,37 @@ static int camrtc_hsp_vm_send(struct camrtc_hsp *camhsp,
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Rings a group doorbell by sending an IRQ message
|
||||
*
|
||||
* This function rings a group doorbell by sending an IRQ message to the RTCPU.
|
||||
* It performs the following operations:
|
||||
* - Calls @ref camrtc_hsp_vm_send_irqmsg() to send an IRQ message
|
||||
*
|
||||
* @param[in] camhsp Pointer to the camera HSP context
|
||||
* Valid value: non-NULL
|
||||
* @param[in] group Group identifier to ring the doorbell for
|
||||
* Valid value: any 16-bit value
|
||||
*/
|
||||
static void camrtc_hsp_vm_group_ring(struct camrtc_hsp *camhsp,
|
||||
u16 group)
|
||||
{
|
||||
camrtc_hsp_vm_send_irqmsg(camhsp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sends an IRQ message to the RTCPU via HSP
|
||||
*
|
||||
* This function sends an interrupt request message to the RTCPU over the HSP
|
||||
* mailbox. It performs the following operations:
|
||||
* - Creates an IRQ message with parameter value 1 using @ref CAMRTC_HSP_MSG()
|
||||
* - Acquires a spinlock to ensure thread safety using @ref spin_lock_irqsave()
|
||||
* - Sends the message using @ref mbox_send_message()
|
||||
* - Releases the spinlock using @ref spin_unlock_irqrestore()
|
||||
*
|
||||
* @param[in] camhsp Pointer to the camera HSP context
|
||||
* Valid value: non-NULL
|
||||
*/
|
||||
static void camrtc_hsp_vm_send_irqmsg(struct camrtc_hsp *camhsp)
|
||||
{
|
||||
int irqmsg = CAMRTC_HSP_MSG(CAMRTC_HSP_IRQ, 1);
|
||||
@@ -214,6 +346,28 @@ static void camrtc_hsp_vm_send_irqmsg(struct camrtc_hsp *camhsp)
|
||||
spin_unlock_irqrestore(&camhsp->sendlock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sends a message and waits for a response over the VM HSP mailbox
|
||||
*
|
||||
* This function sends a message and waits for a response using the common
|
||||
* send/receive function. It performs additional validation on the response
|
||||
* message to ensure it matches the request. The operations include:
|
||||
* - Calls @ref camrtc_hsp_sendrecv() to send the message and receive a response
|
||||
* - Validates that the message ID in the response matches the request using @ref CAMRTC_HSP_MSG_ID()
|
||||
* - Reports errors using @ref dev_err() if the response doesn't match the request
|
||||
* - Extracts and returns only the parameter portion of the response using @ref CAMRTC_HSP_MSG_PARAM()
|
||||
*
|
||||
* @param[in] camhsp Pointer to the camera HSP context
|
||||
* Valid value: non-NULL
|
||||
* @param[in] request Request message to send
|
||||
* Valid value: any integer value
|
||||
* @param[in,out] timeout Pointer to timeout value in jiffies
|
||||
* Valid value: non-NULL
|
||||
*
|
||||
* @retval >=0 The parameter portion of the response message
|
||||
* @retval <0 Error code from @ref camrtc_hsp_sendrecv()
|
||||
* @retval -EIO If the response message ID doesn't match the request
|
||||
*/
|
||||
static int camrtc_hsp_vm_sendrecv(struct camrtc_hsp *camhsp,
|
||||
int request, long *timeout)
|
||||
{
|
||||
@@ -233,6 +387,23 @@ static int camrtc_hsp_vm_sendrecv(struct camrtc_hsp *camhsp,
|
||||
return CAMRTC_HSP_MSG_PARAM(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reads boot log messages from the RTCPU
|
||||
*
|
||||
* This function reads and processes boot log messages from the RTCPU during
|
||||
* the initialization process. It performs the following operations:
|
||||
* - Validates the HSP context using @ref WARN_ON()
|
||||
* - Uses @ref camrtc_hsp_recv() to wait for and receive boot log messages
|
||||
* - Processes different types of boot messages (complete, stage, error)
|
||||
* - Logs messages at appropriate log levels using @ref dev_info(), @ref dev_dbg(), and @ref dev_err()
|
||||
*
|
||||
* @param[in] camhsp Pointer to the camera HSP context
|
||||
* Valid value: non-NULL
|
||||
*
|
||||
* @retval 0 On successful completion of the boot log reading
|
||||
* @retval -ETIMEDOUT If timed out waiting for boot messages
|
||||
* @retval -EINVAL If received a boot error message or invalid HSP context
|
||||
*/
|
||||
static int camrtc_hsp_vm_read_boot_log(struct camrtc_hsp *camhsp)
|
||||
{
|
||||
uint32_t boot_log;
|
||||
@@ -273,6 +444,25 @@ static int camrtc_hsp_vm_read_boot_log(struct camrtc_hsp *camhsp)
|
||||
return 0U;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Synchronizes with the RTCPU via HSP
|
||||
*
|
||||
* This function performs the initial handshake with the RTCPU by reading
|
||||
* boot logs and establishing communication. It performs the following operations:
|
||||
* - Reads boot logs using @ref camrtc_hsp_vm_read_boot_log()
|
||||
* - Logs a warning if boot logs cannot be read but continues with handshake
|
||||
* - Sends a hello message using @ref camrtc_hsp_vm_hello() to establish communication
|
||||
* - Stores the cookie (response) returned from hello message
|
||||
* - Negotiates protocol version using @ref camrtc_hsp_vm_protocol()
|
||||
*
|
||||
* @param[in] camhsp Pointer to the camera HSP context
|
||||
* Valid value: non-NULL
|
||||
* @param[in,out] timeout Pointer to timeout value in jiffies
|
||||
* Valid value: non-NULL
|
||||
*
|
||||
* @retval >=0 On successful synchronization (protocol version)
|
||||
* @retval <0 Error code from @ref camrtc_hsp_vm_hello() or @ref camrtc_hsp_vm_protocol()
|
||||
*/
|
||||
static int camrtc_hsp_vm_sync(struct camrtc_hsp *camhsp, long *timeout)
|
||||
{
|
||||
int response;
|
||||
@@ -295,6 +485,18 @@ static int camrtc_hsp_vm_sync(struct camrtc_hsp *camhsp, long *timeout)
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Generates a cookie value for HSP handshake
|
||||
*
|
||||
* This function generates a 24-bit cookie value used for handshake and
|
||||
* subsequent communication with the RTCPU. The cookie serves as an
|
||||
* identifier for the session. It performs the following operations:
|
||||
* - Uses @ref sched_clock() to get a timestamp
|
||||
* - Extracts the lower bits using @ref CAMRTC_HSP_MSG_PARAM()
|
||||
* - Ensures the cookie is never zero by incrementing if needed
|
||||
*
|
||||
* @return u32 Cookie value (non-zero 24-bit value)
|
||||
*/
|
||||
static u32 camrtc_hsp_vm_cookie(void)
|
||||
{
|
||||
u32 value = CAMRTC_HSP_MSG_PARAM(sched_clock() >> 5U);
|
||||
@@ -305,6 +507,24 @@ static u32 camrtc_hsp_vm_cookie(void)
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sends a HELLO message to the RTCPU and waits for echo
|
||||
*
|
||||
* This function initiates communication with the RTCPU by sending a HELLO
|
||||
* message with a unique cookie and waiting for the same message to be echoed
|
||||
* back. It performs the following operations:
|
||||
* - Creates a HELLO message with a unique cookie using @ref CAMRTC_HSP_MSG() and @ref camrtc_hsp_vm_cookie()
|
||||
* - Sends the message using @ref camrtc_hsp_send()
|
||||
* - Repeatedly calls @ref camrtc_hsp_recv() until the echoed message is received or timeout
|
||||
*
|
||||
* @param[in] camhsp Pointer to the camera HSP context
|
||||
* Valid value: non-NULL
|
||||
* @param[in,out] timeout Pointer to timeout value in jiffies
|
||||
* Valid value: non-NULL
|
||||
*
|
||||
* @retval request On successful handshake (value of the HELLO message with cookie)
|
||||
* @retval <0 Error code from @ref camrtc_hsp_send() or @ref camrtc_hsp_recv()
|
||||
*/
|
||||
static int camrtc_hsp_vm_hello(struct camrtc_hsp *camhsp, long *timeout)
|
||||
{
|
||||
int request = CAMRTC_HSP_MSG(CAMRTC_HSP_HELLO, camrtc_hsp_vm_cookie());
|
||||
@@ -328,6 +548,22 @@ static int camrtc_hsp_vm_hello(struct camrtc_hsp *camhsp, long *timeout)
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Negotiates protocol version with RTCPU
|
||||
*
|
||||
* This function negotiates the protocol version to use for communication with
|
||||
* the RTCPU. It performs the following operations:
|
||||
* - Creates a protocol message with the driver's version using @ref CAMRTC_HSP_MSG()
|
||||
* - Sends the message and waits for response using @ref camrtc_hsp_vm_sendrecv()
|
||||
*
|
||||
* @param[in] camhsp Pointer to the camera HSP context
|
||||
* Valid value: non-NULL
|
||||
* @param[in,out] timeout Pointer to timeout value in jiffies
|
||||
* Valid value: non-NULL
|
||||
*
|
||||
* @retval >=0 On successful negotiation (protocol version)
|
||||
* @retval <0 Error code from @ref camrtc_hsp_vm_sendrecv()
|
||||
*/
|
||||
static int camrtc_hsp_vm_protocol(struct camrtc_hsp *camhsp, long *timeout)
|
||||
{
|
||||
int request = CAMRTC_HSP_MSG(CAMRTC_HSP_PROTOCOL,
|
||||
@@ -336,6 +572,21 @@ static int camrtc_hsp_vm_protocol(struct camrtc_hsp *camhsp, long *timeout)
|
||||
return camrtc_hsp_vm_sendrecv(camhsp, request, timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resumes the RTCPU firmware
|
||||
*
|
||||
* This function resumes the RTCPU firmware by sending a RESUME message with
|
||||
* the current cookie value. It performs the following operations:
|
||||
* - Creates a RESUME message with the current cookie using @ref CAMRTC_HSP_MSG()
|
||||
* - Sends the message and waits for response using @ref camrtc_hsp_vm_sendrecv()
|
||||
*
|
||||
* @param[in] camhsp Pointer to the camera HSP context
|
||||
* Valid value: non-NULL
|
||||
* @param[in,out] timeout Pointer to timeout value in jiffies
|
||||
* Valid value: non-NULL
|
||||
*
|
||||
* @retval (int) Error code from @ref camrtc_hsp_vm_sendrecv()
|
||||
*/
|
||||
static int camrtc_hsp_vm_resume(struct camrtc_hsp *camhsp, long *timeout)
|
||||
{
|
||||
int request = CAMRTC_HSP_MSG(CAMRTC_HSP_RESUME, camhsp->cookie);
|
||||
@@ -343,6 +594,21 @@ static int camrtc_hsp_vm_resume(struct camrtc_hsp *camhsp, long *timeout)
|
||||
return camrtc_hsp_vm_sendrecv(camhsp, request, timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Suspends the RTCPU firmware
|
||||
*
|
||||
* This function suspends the RTCPU firmware by sending a SUSPEND message with
|
||||
* a zero cookie value. It performs the following operations:
|
||||
* - Creates a SUSPEND message with a zero cookie using @ref CAMRTC_HSP_MSG()
|
||||
* - Sends the message and waits for response using @ref camrtc_hsp_vm_sendrecv()
|
||||
*
|
||||
* @param[in] camhsp Pointer to the camera HSP context
|
||||
* Valid value: non-NULL
|
||||
* @param[in,out] timeout Pointer to timeout value in jiffies
|
||||
* Valid value: non-NULL
|
||||
*
|
||||
* @retval (int) Error code from @ref camrtc_hsp_vm_sendrecv()
|
||||
*/
|
||||
static int camrtc_hsp_vm_suspend(struct camrtc_hsp *camhsp, long *timeout)
|
||||
{
|
||||
u32 request = CAMRTC_HSP_MSG(CAMRTC_HSP_SUSPEND, 0);
|
||||
@@ -350,6 +616,21 @@ static int camrtc_hsp_vm_suspend(struct camrtc_hsp *camhsp, long *timeout)
|
||||
return camrtc_hsp_vm_sendrecv(camhsp, request, timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sends a BYE message to the RTCPU
|
||||
*
|
||||
* This function sends a BYE message to the RTCPU to terminate the communication
|
||||
* session. It performs the following operations:
|
||||
* - Creates a BYE message with a zero cookie using @ref CAMRTC_HSP_MSG()
|
||||
* - Sends the message and waits for response using @ref camrtc_hsp_vm_sendrecv()
|
||||
*
|
||||
* @param[in] camhsp Pointer to the camera HSP context
|
||||
* Valid value: non-NULL
|
||||
* @param[in,out] timeout Pointer to timeout value in jiffies
|
||||
* Valid value: non-NULL
|
||||
*
|
||||
* @retval (int) Error code from @ref camrtc_hsp_vm_sendrecv()
|
||||
*/
|
||||
static int camrtc_hsp_vm_bye(struct camrtc_hsp *camhsp, long *timeout)
|
||||
{
|
||||
u32 request = CAMRTC_HSP_MSG(CAMRTC_HSP_BYE, 0);
|
||||
@@ -359,6 +640,23 @@ static int camrtc_hsp_vm_bye(struct camrtc_hsp *camhsp, long *timeout)
|
||||
return camrtc_hsp_vm_sendrecv(camhsp, request, timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets up the channel for communication with the RTCPU
|
||||
*
|
||||
* This function sets up the channel for communication with the RTCPU by sending
|
||||
* a CH_SETUP message with the provided IOVA value. It performs the following operations:
|
||||
* - Creates a CH_SETUP message with the IOVA value using @ref CAMRTC_HSP_MSG()
|
||||
* - Sends the message and waits for response using @ref camrtc_hsp_vm_sendrecv()
|
||||
*
|
||||
* @param[in] camhsp Pointer to the camera HSP context
|
||||
* Valid value: non-NULL
|
||||
* @param[in] iova IOVA value to set up the channel with
|
||||
* Valid value: any DMA address
|
||||
* @param[in,out] timeout Pointer to timeout value in jiffies
|
||||
* Valid value: non-NULL
|
||||
*
|
||||
* @retval (int) Error code from @ref camrtc_hsp_vm_sendrecv()
|
||||
*/
|
||||
static int camrtc_hsp_vm_ch_setup(struct camrtc_hsp *camhsp,
|
||||
dma_addr_t iova, long *timeout)
|
||||
{
|
||||
@@ -367,6 +665,23 @@ static int camrtc_hsp_vm_ch_setup(struct camrtc_hsp *camhsp,
|
||||
return camrtc_hsp_vm_sendrecv(camhsp, request, timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Pings the RTCPU
|
||||
*
|
||||
* This function pings the RTCPU by sending a PING message with the provided data.
|
||||
* It performs the following operations:
|
||||
* - Creates a PING message with the provided data using @ref CAMRTC_HSP_MSG()
|
||||
* - Sends the message and waits for response using @ref camrtc_hsp_vm_sendrecv()
|
||||
*
|
||||
* @param[in] camhsp Pointer to the camera HSP context
|
||||
* Valid value: non-NULL
|
||||
* @param[in] data Data to send in the PING message
|
||||
* Valid value: any 32-bit value
|
||||
* @param[in,out] timeout Pointer to timeout value in jiffies
|
||||
* Valid value: non-NULL
|
||||
*
|
||||
* @retval (int) Error code from @ref camrtc_hsp_vm_sendrecv()
|
||||
*/
|
||||
static int camrtc_hsp_vm_ping(struct camrtc_hsp *camhsp, u32 data,
|
||||
long *timeout)
|
||||
{
|
||||
@@ -375,6 +690,23 @@ static int camrtc_hsp_vm_ping(struct camrtc_hsp *camhsp, u32 data,
|
||||
return camrtc_hsp_vm_sendrecv(camhsp, request, timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the firmware hash from the RTCPU
|
||||
*
|
||||
* This function gets the firmware hash from the RTCPU by sending a FW_HASH
|
||||
* message with the provided index. It performs the following operations:
|
||||
* - Creates a FW_HASH message with the provided index using @ref CAMRTC_HSP_MSG()
|
||||
* - Sends the message and waits for response using @ref camrtc_hsp_vm_sendrecv()
|
||||
*
|
||||
* @param[in] camhsp Pointer to the camera HSP context
|
||||
* Valid value: non-NULL
|
||||
* @param[in] index Index of the firmware hash to get
|
||||
* Valid value: any 32-bit value
|
||||
* @param[in,out] timeout Pointer to timeout value in jiffies
|
||||
* Valid value: non-NULL
|
||||
*
|
||||
* @retval (int) Error code from @ref camrtc_hsp_vm_sendrecv()
|
||||
*/
|
||||
static int camrtc_hsp_vm_get_fw_hash(struct camrtc_hsp *camhsp, u32 index,
|
||||
long *timeout)
|
||||
{
|
||||
@@ -383,6 +715,23 @@ static int camrtc_hsp_vm_get_fw_hash(struct camrtc_hsp *camhsp, u32 index,
|
||||
return camrtc_hsp_vm_sendrecv(camhsp, request, timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the operating point for the RTCPU
|
||||
*
|
||||
* This function sets the operating point for the RTCPU by sending a SET_OP_POINT
|
||||
* message with the provided operating point value. It performs the following operations:
|
||||
* - Creates a SET_OP_POINT message with the provided operating point value using @ref CAMRTC_HSP_MSG()
|
||||
* - Sends the message and waits for response using @ref camrtc_hsp_vm_sendrecv()
|
||||
*
|
||||
* @param[in] camhsp Pointer to the camera HSP context
|
||||
* Valid value: non-NULL
|
||||
* @param[in] operating_point Operating point value to set
|
||||
* Valid value: any 32-bit value
|
||||
* @param[in,out] timeout Pointer to timeout value in jiffies
|
||||
* Valid value: non-NULL
|
||||
*
|
||||
* @retval (int) Error code from @ref camrtc_hsp_vm_sendrecv()
|
||||
*/
|
||||
static int camrtc_hsp_vm_set_operating_point(struct camrtc_hsp *camhsp, u32 operating_point,
|
||||
long *timeout)
|
||||
{
|
||||
@@ -391,6 +740,23 @@ static int camrtc_hsp_vm_set_operating_point(struct camrtc_hsp *camhsp, u32 oper
|
||||
return camrtc_hsp_vm_sendrecv(camhsp, request, timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Probes for a VM HSP device
|
||||
*
|
||||
* This function probes for a VM HSP device by searching through the device tree
|
||||
* for a compatible node with the name "nvidia,tegra-camrtc-hsp-vm". It performs
|
||||
* the following operations:
|
||||
* - Gets the parent device node using @ref of_node_get()
|
||||
* - Searches for a child node with the compatible string "nvidia,tegra-camrtc-hsp-vm"
|
||||
* - Returns the first available child node if found
|
||||
* - Returns NULL if no compatible node is found
|
||||
*
|
||||
* @param[in] parent Pointer to the parent device node
|
||||
* Valid value: non-NULL
|
||||
*
|
||||
* @retval Pointer to the available child node if found
|
||||
* @retval NULL if no compatible node is found
|
||||
*/
|
||||
static struct device_node *hsp_vm_get_available(const struct device_node *parent)
|
||||
{
|
||||
const char *compatible = "nvidia,tegra-camrtc-hsp-vm";
|
||||
@@ -404,6 +770,24 @@ static struct device_node *hsp_vm_get_available(const struct device_node *parent
|
||||
return child;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Probes and initializes an HSP VM device
|
||||
*
|
||||
* This function probes and initializes a VM HSP device. It performs the following operations:
|
||||
* - Gets an available HSP VM device node using @ref hsp_vm_get_available()
|
||||
* - Requests mailbox channels for RX and TX using @ref mbox_request_channel_byname()
|
||||
* - Sets up the operations structure and device name using @ref dev_set_name()
|
||||
* - Reports errors using @ref dev_err() if channel requests fail
|
||||
* - Releases resources on failure using @ref of_node_put()
|
||||
*
|
||||
* @param[in] camhsp Pointer to the camera HSP context
|
||||
* Valid value: non-NULL
|
||||
*
|
||||
* @retval 0 On successful probe
|
||||
* @retval -ENOTSUPP If no compatible HSP VM device is found
|
||||
* @retval -EPROBE_DEFER If probe should be deferred
|
||||
* @retval (int) Error code from @ref mbox_request_channel_byname()
|
||||
*/
|
||||
static int camrtc_hsp_vm_probe(struct camrtc_hsp *camhsp)
|
||||
{
|
||||
struct device_node *np = camhsp->dev.parent->of_node;
|
||||
@@ -450,6 +834,19 @@ fail:
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Public interface */
|
||||
|
||||
/**
|
||||
* @brief Rings a group doorbell
|
||||
*
|
||||
* This function rings a group doorbell by calling the group_ring operation
|
||||
* on the HSP context. It performs the following operations:
|
||||
* - Validates the HSP context using @ref WARN_ON()
|
||||
* - Calls the group_ring operation on the HSP context using @ref group_ring()
|
||||
*
|
||||
* @param[in] camhsp Pointer to the camera HSP context
|
||||
* Valid value: non-NULL
|
||||
* @param[in] group Group identifier to ring the doorbell for
|
||||
* Valid value: any 16-bit value
|
||||
*/
|
||||
void camrtc_hsp_group_ring(struct camrtc_hsp *camhsp,
|
||||
u16 group)
|
||||
{
|
||||
@@ -458,8 +855,21 @@ void camrtc_hsp_group_ring(struct camrtc_hsp *camhsp,
|
||||
}
|
||||
EXPORT_SYMBOL(camrtc_hsp_group_ring);
|
||||
|
||||
/*
|
||||
* Synchronize the HSP
|
||||
/**
|
||||
* @brief Synchronizes the HSP
|
||||
*
|
||||
* This function synchronizes the HSP by calling the sync operation
|
||||
* on the HSP context. It performs the following operations:
|
||||
* - Validates the HSP context using @ref WARN_ON()
|
||||
* - Locks the mutex using @ref mutex_lock()
|
||||
* - Calls the sync operation on the HSP context using @ref sync()
|
||||
* - Unlocks the mutex using @ref mutex_unlock()
|
||||
*
|
||||
* @param[in] camhsp Pointer to the camera HSP context
|
||||
* Valid value: non-NULL
|
||||
*
|
||||
* @retval (int) Return code from @ref sync()
|
||||
* @retval -EINVAL If the HSP context is NULL
|
||||
*/
|
||||
int camrtc_hsp_sync(struct camrtc_hsp *camhsp)
|
||||
{
|
||||
@@ -478,8 +888,21 @@ int camrtc_hsp_sync(struct camrtc_hsp *camhsp)
|
||||
}
|
||||
EXPORT_SYMBOL(camrtc_hsp_sync);
|
||||
|
||||
/*
|
||||
* Resume: resume the firmware
|
||||
/**
|
||||
* @brief Resumes the HSP
|
||||
*
|
||||
* This function resumes the HSP by calling the resume operation
|
||||
* on the HSP context. It performs the following operations:
|
||||
* - Validates the HSP context using @ref WARN_ON()
|
||||
* - Locks the mutex using @ref mutex_lock()
|
||||
* - Calls the resume operation on the HSP context using @ref resume()
|
||||
* - Unlocks the mutex using @ref mutex_unlock()
|
||||
*
|
||||
* @param[in] camhsp Pointer to the camera HSP context
|
||||
* Valid value: non-NULL
|
||||
*
|
||||
* @retval (int) Return code from @ref resume()
|
||||
* @retval -EINVAL If the HSP context is NULL
|
||||
*/
|
||||
int camrtc_hsp_resume(struct camrtc_hsp *camhsp)
|
||||
{
|
||||
@@ -498,8 +921,22 @@ int camrtc_hsp_resume(struct camrtc_hsp *camhsp)
|
||||
}
|
||||
EXPORT_SYMBOL(camrtc_hsp_resume);
|
||||
|
||||
/*
|
||||
* Suspend: set firmware to idle.
|
||||
/**
|
||||
* @brief Suspends the HSP
|
||||
*
|
||||
* This function suspends the HSP by calling the suspend operation
|
||||
* on the HSP context. It performs the following operations:
|
||||
* - Validates the HSP context using @ref WARN_ON()
|
||||
* - Locks the mutex using @ref mutex_lock()
|
||||
* - Calls the suspend operation on the HSP context using @ref suspend()
|
||||
* - Unlocks the mutex using @ref mutex_unlock()
|
||||
*
|
||||
* @param[in] camhsp Pointer to the camera HSP context
|
||||
* Valid value: non-NULL
|
||||
*
|
||||
* @retval (int) Return code from @ref suspend()
|
||||
* @retval -EINVAL If the HSP context is NULL
|
||||
* @retval -EIO If the suspend operation fails
|
||||
*/
|
||||
int camrtc_hsp_suspend(struct camrtc_hsp *camhsp)
|
||||
{
|
||||
@@ -522,8 +959,24 @@ int camrtc_hsp_suspend(struct camrtc_hsp *camhsp)
|
||||
}
|
||||
EXPORT_SYMBOL(camrtc_hsp_suspend);
|
||||
|
||||
/*
|
||||
* Set Operating Point: set operating point
|
||||
/**
|
||||
* @brief Sets the operating point for the HSP
|
||||
*
|
||||
* This function sets the operating point for the HSP by calling the set_operating_point
|
||||
* operation on the HSP context. It performs the following operations:
|
||||
* - Validates the HSP context using @ref WARN_ON()
|
||||
* - Locks the mutex using @ref mutex_lock()
|
||||
* - Calls the set_operating_point operation on the HSP context using @ref set_operating_point()
|
||||
* - Unlocks the mutex using @ref mutex_unlock()
|
||||
*
|
||||
* @param[in] camhsp Pointer to the camera HSP context
|
||||
* Valid value: non-NULL
|
||||
* @param[in] operating_point Operating point value to set
|
||||
* Valid value: any 32-bit value
|
||||
*
|
||||
* @retval (int) Return code from @ref set_operating_point()
|
||||
* @retval -EINVAL If the HSP context is NULL
|
||||
* @retval -EIO If the set_operating_point operation fails
|
||||
*/
|
||||
int camrtc_hsp_set_operating_point(struct camrtc_hsp *camhsp, uint32_t operating_point)
|
||||
{
|
||||
@@ -546,8 +999,21 @@ int camrtc_hsp_set_operating_point(struct camrtc_hsp *camhsp, uint32_t operating
|
||||
}
|
||||
EXPORT_SYMBOL(camrtc_hsp_set_operating_point);
|
||||
|
||||
/*
|
||||
* Bye: tell firmware that VM mappings are going away
|
||||
/**
|
||||
* @brief Sends a BYE message to the HSP
|
||||
*
|
||||
* This function sends a BYE message to the HSP by calling the bye operation
|
||||
* on the HSP context. It performs the following operations:
|
||||
* - Validates the HSP context using @ref WARN_ON()
|
||||
* - Locks the mutex using @ref mutex_lock()
|
||||
* - Calls the bye operation on the HSP context using @ref bye()
|
||||
* - Unlocks the mutex using @ref mutex_unlock()
|
||||
*
|
||||
* @param[in] camhsp Pointer to the camera HSP context
|
||||
* Valid value: non-NULL
|
||||
*
|
||||
* @retval (int) Return code from @ref bye()
|
||||
* @retval -EINVAL If the HSP context is NULL
|
||||
*/
|
||||
int camrtc_hsp_bye(struct camrtc_hsp *camhsp)
|
||||
{
|
||||
@@ -569,6 +1035,24 @@ int camrtc_hsp_bye(struct camrtc_hsp *camhsp)
|
||||
}
|
||||
EXPORT_SYMBOL(camrtc_hsp_bye);
|
||||
|
||||
/**
|
||||
* @brief Sets up the HSP channel
|
||||
*
|
||||
* This function sets up the HSP channel by calling the ch_setup operation
|
||||
* on the HSP context. It performs the following operations:
|
||||
* - Validates the HSP context using @ref WARN_ON()
|
||||
* - Locks the mutex using @ref mutex_lock()
|
||||
* - Calls the ch_setup operation on the HSP context using @ref ch_setup()
|
||||
* - Unlocks the mutex using @ref mutex_unlock()
|
||||
*
|
||||
* @param[in] camhsp Pointer to the camera HSP context
|
||||
* Valid value: non-NULL
|
||||
* @param[in] iova IOVA value to set
|
||||
* Valid value: any 32-bit value
|
||||
*
|
||||
* @retval (int) Error code from @ref ch_setup()
|
||||
* @retval -EINVAL If the HSP context is NULL or the IOVA is invalid
|
||||
*/
|
||||
int camrtc_hsp_ch_setup(struct camrtc_hsp *camhsp, dma_addr_t iova)
|
||||
{
|
||||
long timeout;
|
||||
@@ -595,6 +1079,26 @@ int camrtc_hsp_ch_setup(struct camrtc_hsp *camhsp, dma_addr_t iova)
|
||||
}
|
||||
EXPORT_SYMBOL(camrtc_hsp_ch_setup);
|
||||
|
||||
/**
|
||||
* @brief Pings the HSP
|
||||
*
|
||||
* This function pings the HSP by calling the ping operation
|
||||
* on the HSP context. It performs the following operations:
|
||||
* - Validates the HSP context using @ref WARN_ON()
|
||||
* - Locks the mutex using @ref mutex_lock()
|
||||
* - Calls the ping operation on the HSP context using @ref ping()
|
||||
* - Unlocks the mutex using @ref mutex_unlock()
|
||||
*
|
||||
* @param[in] camhsp Pointer to the camera HSP context
|
||||
* Valid value: non-NULL
|
||||
* @param[in] data Data value to ping
|
||||
* Valid value: any 32-bit value
|
||||
* @param[in] timeout Timeout value to use
|
||||
* Valid value: any 32-bit value
|
||||
*
|
||||
* @retval (int) Error code from @ref ping()
|
||||
* @retval -EINVAL If the HSP context is NULL
|
||||
*/
|
||||
int camrtc_hsp_ping(struct camrtc_hsp *camhsp, u32 data, long timeout)
|
||||
{
|
||||
long left = timeout;
|
||||
@@ -614,6 +1118,28 @@ int camrtc_hsp_ping(struct camrtc_hsp *camhsp, u32 data, long timeout)
|
||||
}
|
||||
EXPORT_SYMBOL(camrtc_hsp_ping);
|
||||
|
||||
/**
|
||||
* @brief Gets the firmware hash for the HSP
|
||||
*
|
||||
* This function gets the firmware hash for the HSP by calling the get_fw_hash operation
|
||||
* on the HSP context. It performs the following operations:
|
||||
* - Validates the HSP context using @ref WARN_ON()
|
||||
* - Locks the mutex using @ref mutex_lock()
|
||||
* - Calls the get_fw_hash operation on the HSP context using @ref get_fw_hash()
|
||||
* - Unlocks the mutex using @ref mutex_unlock()
|
||||
*
|
||||
* @param[in] camhsp Pointer to the camera HSP context
|
||||
* Valid value: non-NULL
|
||||
* @param[in] hash Hash value to get
|
||||
* Valid value: any 32-bit value
|
||||
* @param[in] hash_size Size of the hash value
|
||||
* Valid value: any 32-bit value
|
||||
*
|
||||
* @retval (int) Error code from @ref get_fw_hash()
|
||||
* @retval -EINVAL If the HSP context is NULL
|
||||
* @retval -EIO If the get_fw_hash operation fails
|
||||
* @retval 0 On success
|
||||
*/
|
||||
int camrtc_hsp_get_fw_hash(struct camrtc_hsp *camhsp,
|
||||
u8 hash[], size_t hash_size)
|
||||
{
|
||||
@@ -652,6 +1178,19 @@ static const struct device_type camrtc_hsp_combo_dev_type = {
|
||||
.name = "camrtc-hsp-protocol",
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Releases resources for a camera HSP combo device
|
||||
*
|
||||
* This function is called when a camera HSP combo device is being destroyed.
|
||||
* It performs the following operations:
|
||||
* - Gets the camera HSP context using @ref container_of()
|
||||
* - Frees the RX and TX mailbox channels using @ref mbox_free_channel() if they exist
|
||||
* - Releases the device node using @ref of_node_put()
|
||||
* - Frees the camera HSP context using @ref kfree()
|
||||
*
|
||||
* @param[in] dev Pointer to the device being released
|
||||
* Valid value: non-NULL
|
||||
*/
|
||||
static void camrtc_hsp_combo_dev_release(struct device *dev)
|
||||
{
|
||||
struct camrtc_hsp *camhsp = container_of(dev, struct camrtc_hsp, dev);
|
||||
@@ -665,6 +1204,23 @@ static void camrtc_hsp_combo_dev_release(struct device *dev)
|
||||
kfree(camhsp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Probes for a camera HSP device
|
||||
*
|
||||
* This function attempts to probe for a camera HSP device by trying different
|
||||
* probe methods. Currently, it only tries the VM HSP probe method.
|
||||
* It performs the following operations:
|
||||
* - Calls @ref camrtc_hsp_vm_probe() to attempt VM HSP probe
|
||||
* - Returns success if VM probe succeeds
|
||||
* - Returns -ENODEV if no supported HSP device is found
|
||||
*
|
||||
* @param[in] camhsp Pointer to the camera HSP context
|
||||
* Valid value: non-NULL
|
||||
*
|
||||
* @retval 0 On successful probe
|
||||
* @retval -ENODEV If no supported HSP device is found
|
||||
* @retval (int) Error code from @ref camrtc_hsp_vm_probe()
|
||||
*/
|
||||
static int camrtc_hsp_probe(struct camrtc_hsp *camhsp)
|
||||
{
|
||||
int ret;
|
||||
@@ -676,6 +1232,47 @@ static int camrtc_hsp_probe(struct camrtc_hsp *camhsp)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Creates a camera HSP device
|
||||
*
|
||||
* This function creates a camera HSP device by allocating memory for the HSP context
|
||||
* and initializing its fields. It performs the following operations:
|
||||
* - Allocates memory for the HSP context using @ref kzalloc()
|
||||
* - Initializes the HSP context fields
|
||||
* - Sets the parent device using @ref dev_set_parent()
|
||||
* - Sets the group notify function using @ref camrtc_hsp_set_group_notify()
|
||||
* - Sets the command timeout using @ref camrtc_hsp_set_cmd_timeout()
|
||||
* - Initializes the mutex using @ref mutex_init()
|
||||
* - Initializes the send lock using @ref spin_lock_init()
|
||||
* - Initializes the response wait queue using @ref init_waitqueue_head()
|
||||
* - Initializes the emptied completion using @ref init_completion()
|
||||
* - Sets the response atomic variable to -1 using @ref atomic_set()
|
||||
* - Sets the device type using @ref camrtc_hsp_combo_dev_type
|
||||
* - Sets the device release function using @ref camrtc_hsp_combo_dev_release()
|
||||
* - Initializes the device using @ref device_initialize()
|
||||
* - Sets the device name using @ref dev_set_name()
|
||||
* - Disables runtime PM using @ref pm_runtime_no_callbacks()
|
||||
* - Enables runtime PM using @ref pm_runtime_enable()
|
||||
* - Sets the TX client block flag to false
|
||||
* - Sets the RX callback function using @ref camrtc_hsp_rx_full_notify()
|
||||
* - Sets the TX done function using @ref camrtc_hsp_tx_empty_notify()
|
||||
* - Sets the TX and RX client device using @ref camhsp->tx.client.dev
|
||||
* - Sets the device driver data using @ref dev_set_drvdata()
|
||||
* - Calls @ref camrtc_hsp_probe() to attempt HSP probe
|
||||
* - Adds the device using @ref device_add()
|
||||
*
|
||||
* @param[in] dev Pointer to the device creating the HSP
|
||||
* Valid value: non-NULL
|
||||
* @param[in] group_notify Function pointer to the group notify function
|
||||
* Valid value: non-NULL
|
||||
* @param[in] cmd_timeout Command timeout value
|
||||
* Valid value: any 32-bit value
|
||||
*
|
||||
* @retval (struct camrtc_hsp *) Pointer to the HSP context on success
|
||||
* @retval ERR_PTR(-ENOMEM) If memory allocation fails
|
||||
* @retval ERR_PTR(-EINVAL) If the HSP context is NULL
|
||||
* @retval ERR_PTR(int) Error code from @ref camrtc_hsp_probe() or @ref device_add()
|
||||
*/
|
||||
struct camrtc_hsp *camrtc_hsp_create(
|
||||
struct device *dev,
|
||||
void (*group_notify)(struct device *dev, u16 group),
|
||||
@@ -728,6 +1325,20 @@ fail:
|
||||
}
|
||||
EXPORT_SYMBOL(camrtc_hsp_create);
|
||||
|
||||
/**
|
||||
* @brief Frees a camera HSP device
|
||||
*
|
||||
* This function frees a camera HSP device by disabling runtime PM, unregistering
|
||||
* the device, and releasing the device structure. It performs the following operations:
|
||||
* - Checks if the HSP context is valid using @ref IS_ERR_OR_NULL()
|
||||
* - Disables runtime PM using @ref pm_runtime_disable()
|
||||
* - Checks if the device driver data is not NULL using @ref dev_get_drvdata()
|
||||
* - Unregisters the device using @ref device_unregister()
|
||||
* - Releases the device using @ref put_device()
|
||||
*
|
||||
* @param[in] camhsp Pointer to the camera HSP context
|
||||
* Valid value: non-NULL
|
||||
*/
|
||||
void camrtc_hsp_free(struct camrtc_hsp *camhsp)
|
||||
{
|
||||
if (IS_ERR_OR_NULL(camhsp))
|
||||
|
||||
@@ -42,6 +42,19 @@ struct tegra_ivc_bus {
|
||||
struct tegra_ivc_region regions[];
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Notification callback for IVC channel ring events
|
||||
*
|
||||
* This function is called when an IVC ring event occurs. It retrieves the channel
|
||||
* context and notifies the HSP group.
|
||||
* - Gets the channel context using @ref container_of()
|
||||
* - Notifies the HSP group using @ref camrtc_hsp_group_ring()
|
||||
*
|
||||
* @param[in] ivc Pointer to the IVC channel
|
||||
* Valid value: non-NULL
|
||||
* @param[in] data Pointer to the HSP context
|
||||
* Valid value: non-NULL
|
||||
*/
|
||||
static void tegra_ivc_channel_ring(struct tegra_ivc *ivc, void *data)
|
||||
{
|
||||
struct tegra_ivc_channel *chan =
|
||||
@@ -56,6 +69,19 @@ struct device_type tegra_ivc_channel_type = {
|
||||
};
|
||||
EXPORT_SYMBOL(tegra_ivc_channel_type);
|
||||
|
||||
/**
|
||||
* @brief Gets a runtime PM reference for an IVC channel
|
||||
*
|
||||
* This function gets a runtime PM reference for the specified IVC channel.
|
||||
* It ensures the channel is powered on and ready for use.
|
||||
* - Validates the channel pointer using @ref BUG_ON()
|
||||
* - Gets a runtime PM reference using @ref pm_runtime_get_sync()
|
||||
*
|
||||
* @param[in] ch Pointer to the IVC channel
|
||||
* Valid value: non-NULL
|
||||
*
|
||||
* @retval (int) return value from @ref pm_runtime_get_sync()
|
||||
*/
|
||||
int tegra_ivc_channel_runtime_get(struct tegra_ivc_channel *ch)
|
||||
{
|
||||
BUG_ON(ch == NULL);
|
||||
@@ -64,6 +90,17 @@ int tegra_ivc_channel_runtime_get(struct tegra_ivc_channel *ch)
|
||||
}
|
||||
EXPORT_SYMBOL(tegra_ivc_channel_runtime_get);
|
||||
|
||||
/**
|
||||
* @brief Releases a runtime PM reference for an IVC channel
|
||||
*
|
||||
* This function releases a runtime PM reference for the specified IVC channel.
|
||||
* It allows the channel to be powered down when not in use.
|
||||
* - Validates the channel pointer using @ref BUG_ON()
|
||||
* - Releases the runtime PM reference using @ref pm_runtime_put()
|
||||
*
|
||||
* @param[in] ch Pointer to the IVC channel
|
||||
* Valid value: non-NULL
|
||||
*/
|
||||
void tegra_ivc_channel_runtime_put(struct tegra_ivc_channel *ch)
|
||||
{
|
||||
BUG_ON(ch == NULL);
|
||||
@@ -72,6 +109,18 @@ void tegra_ivc_channel_runtime_put(struct tegra_ivc_channel *ch)
|
||||
}
|
||||
EXPORT_SYMBOL(tegra_ivc_channel_runtime_put);
|
||||
|
||||
/**
|
||||
* @brief Releases resources associated with an IVC channel device
|
||||
*
|
||||
* This function is called when an IVC channel device is being destroyed.
|
||||
* It performs cleanup of allocated resources.
|
||||
* - Gets the channel context using @ref container_of()
|
||||
* - Releases the device node using @ref of_node_put()
|
||||
* - Frees the channel memory using @ref kfree()
|
||||
*
|
||||
* @param[in] dev Pointer to the device being released
|
||||
* Valid value: non-NULL
|
||||
*/
|
||||
static void tegra_ivc_channel_release(struct device *dev)
|
||||
{
|
||||
struct tegra_ivc_channel *chan =
|
||||
@@ -81,6 +130,37 @@ static void tegra_ivc_channel_release(struct device *dev)
|
||||
kfree(chan);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Creates and initializes a new IVC channel
|
||||
*
|
||||
* This function creates and initializes a new IVC channel with the specified parameters.
|
||||
* It performs the following operations:
|
||||
* - Validates the bus, channel node, region, and camhsp pointers
|
||||
* - Sets the device name using @ref dev_set_name()
|
||||
* - Initializes device properties and runtime PM using @ref pm_runtime_no_callbacks() and @ref pm_runtime_enable()
|
||||
* - Reads channel configuration from device tree using @ref of_property_read_string(), @ref of_property_read_u32(), and @ref fls()
|
||||
* - Check for overflows in size calculations using @ref __builtin_add_overflow() and @ref __builtin_mul_overflow()
|
||||
* - Calculates total queue size using @ref tegra_ivc_total_queue_size()
|
||||
* - Checks if buffers exceed IVC region using @ref __builtin_add_overflow()
|
||||
* - Initializes IVC communication using @ref tegra_ivc_init()
|
||||
* - Reset IVC communication using @ref tegra_ivc_reset()
|
||||
* - Add device using @ref device_add()
|
||||
*
|
||||
* @param[in] bus Pointer to the IVC bus
|
||||
* Valid value: non-NULL
|
||||
* @param[in] ch_node Pointer to the device tree node
|
||||
* Valid value: non-NULL
|
||||
* @param[in] region Pointer to the IVC region
|
||||
* Valid value: non-NULL
|
||||
* @param[in] camhsp Pointer to the camera HSP context
|
||||
* Valid value: non-NULL
|
||||
*
|
||||
* @retval (struct tegra_ivc_channel *) Pointer to the created IVC channel on success
|
||||
* @retval ERR_PTR(-ENOMEM) If memory allocation fails
|
||||
* @retval ERR_PTR(-ENOSPC) If buffers exceed IVC region
|
||||
* @retval ERR_PTR(-EOVERFLOW) If size calculations overflow
|
||||
* @retval ERR_PTR(-EIO) If IVC initialization fails
|
||||
*/
|
||||
static struct tegra_ivc_channel *tegra_ivc_channel_create(
|
||||
struct tegra_ivc_bus *bus, struct device_node *ch_node,
|
||||
struct tegra_ivc_region *region,
|
||||
@@ -297,6 +377,20 @@ error:
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Notifies a channel of an IVC event
|
||||
*
|
||||
* This function handles notification of IVC events for a specific channel.
|
||||
* It performs the following operations:
|
||||
* - Checks if the channel has been notified using @ref tegra_ivc_channel_notified() or @ref tegra_ivc_notified()
|
||||
* - Verifies if the channel is ready using @ref chan->is_ready
|
||||
* - Uses RCU locking to safely access channel operations using @ref rcu_read_lock() and @ref rcu_dereference()
|
||||
* - Calls the channel's notify callback if available using @ref ops->notify()
|
||||
* - Unlocks the RCU using @ref rcu_read_unlock()
|
||||
*
|
||||
* @param[in] chan Pointer to the IVC channel
|
||||
* Valid value: non-NULL
|
||||
*/
|
||||
static void tegra_ivc_channel_notify(struct tegra_ivc_channel *chan)
|
||||
{
|
||||
const struct tegra_ivc_channel_ops *ops;
|
||||
@@ -319,6 +413,19 @@ static void tegra_ivc_channel_notify(struct tegra_ivc_channel *chan)
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Notifies all channels in a group of an IVC event
|
||||
*
|
||||
* This function iterates through all channels in the IVC bus and notifies
|
||||
* those belonging to the specified group of an IVC event.
|
||||
* - Iterates through all channels using a linked list
|
||||
* - For each channel in the specified group, calls @ref tegra_ivc_channel_notify()
|
||||
*
|
||||
* @param[in] bus Pointer to the IVC bus
|
||||
* Valid value: non-NULL
|
||||
* @param[in] group Group identifier to notify
|
||||
* Valid value: any 16-bit value
|
||||
*/
|
||||
void tegra_ivc_bus_notify(struct tegra_ivc_bus *bus, u16 group)
|
||||
{
|
||||
struct tegra_ivc_channel *chan;
|
||||
@@ -335,6 +442,19 @@ struct device_type tegra_ivc_bus_dev_type = {
|
||||
};
|
||||
EXPORT_SYMBOL(tegra_ivc_bus_dev_type);
|
||||
|
||||
/**
|
||||
* @brief Releases resources associated with an IVC bus device
|
||||
*
|
||||
* This function is called when an IVC bus device is being destroyed.
|
||||
* It performs cleanup of allocated resources.
|
||||
* - Gets the bus context using @ref container_of()
|
||||
* - Releases the device node using @ref of_node_put()
|
||||
* - Frees DMA memory for each region using @ref dma_free_coherent()
|
||||
* - Frees the bus memory using @ref kfree()
|
||||
*
|
||||
* @param[in] dev Pointer to the device being released
|
||||
* Valid value: non-NULL
|
||||
*/
|
||||
static void tegra_ivc_bus_release(struct device *dev)
|
||||
{
|
||||
struct tegra_ivc_bus *bus =
|
||||
@@ -355,6 +475,23 @@ static void tegra_ivc_bus_release(struct device *dev)
|
||||
kfree(bus);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Matches an IVC bus device with a driver
|
||||
*
|
||||
* This function determines if a driver can handle a specific IVC bus device.
|
||||
* It performs the following operations:
|
||||
* - Gets the IVC driver using @ref to_tegra_ivc_driver()
|
||||
* - Checks if device type matches driver type
|
||||
* - Uses @ref of_driver_match_device() for device tree matching
|
||||
*
|
||||
* @param[in] dev Pointer to the device to match
|
||||
* Valid value: non-NULL
|
||||
* @param[in] drv Pointer to the driver to match
|
||||
* Valid value: non-NULL
|
||||
*
|
||||
* @retval 1 If the driver matches the device
|
||||
* @retval 0 If the driver does not match the device
|
||||
*/
|
||||
#if defined(NV_BUS_TYPE_STRUCT_MATCH_HAS_CONST_DRV_ARG)
|
||||
static int tegra_ivc_bus_match(struct device *dev, const struct device_driver *drv)
|
||||
#else
|
||||
@@ -368,6 +505,19 @@ static int tegra_ivc_bus_match(struct device *dev, struct device_driver *drv)
|
||||
return of_driver_match_device(dev, drv);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops and cleans up all channels in an IVC bus
|
||||
*
|
||||
* This function stops all IVC channels associated with a bus and releases their resources.
|
||||
* It performs the following operations:
|
||||
* - Iterates through all channels in the linked list
|
||||
* - Disables runtime PM for each channel using @ref pm_runtime_disable()
|
||||
* - Unregisters each channel device using @ref device_unregister()
|
||||
* - Updates the linked list as channels are removed
|
||||
*
|
||||
* @param[in] bus Pointer to the IVC bus
|
||||
* Valid value: non-NULL
|
||||
*/
|
||||
static void tegra_ivc_bus_stop(struct tegra_ivc_bus *bus)
|
||||
{
|
||||
while (bus->chans != NULL) {
|
||||
@@ -379,6 +529,25 @@ static void tegra_ivc_bus_stop(struct tegra_ivc_bus *bus)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts all channels in an IVC bus
|
||||
*
|
||||
* This function initializes and starts all IVC channels associated with a bus.
|
||||
* It performs the following operations:
|
||||
* - Iterates through device tree nodes to find channel specifications
|
||||
* - Checks if each channel is enabled in the device tree
|
||||
* - Creates each channel using @ref tegra_ivc_channel_create()
|
||||
* - Adds each channel to the linked list of channels in the bus
|
||||
* - Cleans up on error using @ref tegra_ivc_bus_stop()
|
||||
*
|
||||
* @param[in] bus Pointer to the IVC bus
|
||||
* Valid value: non-NULL
|
||||
* @param[in] camhsp Pointer to the camera HSP context
|
||||
* Valid value: non-NULL
|
||||
*
|
||||
* @retval 0 On successful startup
|
||||
* @retval (int) Error code from @ref tegra_ivc_channel_create()
|
||||
*/
|
||||
static int tegra_ivc_bus_start(struct tegra_ivc_bus *bus,
|
||||
struct camrtc_hsp *camhsp)
|
||||
{
|
||||
@@ -426,9 +595,23 @@ error:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is called during RTCPU boot to synchronize
|
||||
* (or re-synchronize in the case of PM resume).
|
||||
/**
|
||||
* @brief Synchronizes IVC bus during RTCPU boot or PM resume
|
||||
*
|
||||
* This function is called during RTCPU boot to synchronize or re-synchronize
|
||||
* the IVC bus in the case of PM resume. It sets up the IOVM for each
|
||||
* IVC region.
|
||||
* - Checks if the bus is valid using @ref IS_ERR_OR_NULL()
|
||||
* - Iterates through all regions in the bus
|
||||
* - Calls the provided IOVM setup function for each region
|
||||
*
|
||||
* @param[in] bus Pointer to the IVC bus
|
||||
* Valid value: any value including NULL or error pointer
|
||||
* @param[in] iovm_setup Function pointer to set up IOVM mappings
|
||||
* Valid value: non-NULL function pointer
|
||||
*
|
||||
* @retval 0 On successful synchronization or if bus is NULL/error
|
||||
* @retval -EIO If IOVM setup fails
|
||||
*/
|
||||
int tegra_ivc_bus_boot_sync(struct tegra_ivc_bus *bus,
|
||||
int (*iovm_setup)(struct device*, dma_addr_t))
|
||||
@@ -451,6 +634,25 @@ int tegra_ivc_bus_boot_sync(struct tegra_ivc_bus *bus,
|
||||
}
|
||||
EXPORT_SYMBOL(tegra_ivc_bus_boot_sync);
|
||||
|
||||
/**
|
||||
* @brief Probes an IVC bus device
|
||||
*
|
||||
* This function is called when a device is added to the IVC bus.
|
||||
* It initializes the device and calls the driver's probe function.
|
||||
* Currently, it only supports IVC channel devices.
|
||||
* - Checks if the device is an IVC channel using its type
|
||||
* - Gets the driver and channel from the device
|
||||
* - Initializes the channel's mutex
|
||||
* - Calls the driver's probe function if available
|
||||
* - Sets up the RCU-protected operations pointer
|
||||
*
|
||||
* @param[in] dev Pointer to the device to probe
|
||||
* Valid value: non-NULL
|
||||
*
|
||||
* @retval 0 On successful probe
|
||||
* @retval -ENXIO If the device is not supported
|
||||
* @retval (int) Error code from driver's probe function
|
||||
*/
|
||||
static int tegra_ivc_bus_probe(struct device *dev)
|
||||
{
|
||||
int ret = -ENXIO;
|
||||
@@ -477,6 +679,22 @@ static int tegra_ivc_bus_probe(struct device *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Removes an IVC bus device
|
||||
*
|
||||
* This function is called when a device is removed from the IVC bus.
|
||||
* It cleans up the device and calls the driver's remove function.
|
||||
* Currently, it only supports IVC channel devices.
|
||||
* - Checks if the device is an IVC channel using its type
|
||||
* - Gets the driver and channel from the device
|
||||
* - Safely removes the RCU-protected operations pointer
|
||||
* - Calls the driver's remove function if available
|
||||
*
|
||||
* @param[in] dev Pointer to the device to remove
|
||||
* Valid value: non-NULL
|
||||
*
|
||||
* @retval 0 On successful removal (for Linux v5.15+ only)
|
||||
*/
|
||||
#if defined(NV_BUS_TYPE_STRUCT_REMOVE_HAS_INT_RETURN_TYPE) /* Linux v5.15 */
|
||||
static int tegra_ivc_bus_remove(struct device *dev)
|
||||
#else
|
||||
@@ -502,6 +720,26 @@ static void tegra_ivc_bus_remove(struct device *dev)
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the ready state for a child device in the IVC bus
|
||||
*
|
||||
* This function is called for each child device in the IVC bus to set its ready state.
|
||||
* It notifies the driver about the readiness of the device.
|
||||
* - Gets the driver for the device using @ref to_tegra_ivc_driver()
|
||||
* - Processes ready state from the data parameter
|
||||
* - If the device is an IVC channel, gets the channel using @ref to_tegra_ivc_channel()
|
||||
* - Updates the ready flag and resets counter using @ref atomic_inc() and @ref smp_wmb()
|
||||
* - If the driver is not NULL, reads the RCU-protected operations pointer using @ref rcu_read_lock() and @ref rcu_dereference()
|
||||
* - Calls the driver's ready callback if available using @ref ops->ready()
|
||||
* - Releases the RCU read lock using @ref rcu_read_unlock()
|
||||
*
|
||||
* @param[in] dev Pointer to the child device
|
||||
* Valid value: non-NULL
|
||||
* @param[in] data Pointer to the ready state data (boolean)
|
||||
* Valid value: NULL (interpreted as true) or pointer to boolean
|
||||
*
|
||||
* @retval 0 Always returns success
|
||||
*/
|
||||
static int tegra_ivc_bus_ready_child(struct device *dev, void *data)
|
||||
{
|
||||
struct tegra_ivc_driver *drv = to_tegra_ivc_driver(dev->driver);
|
||||
@@ -538,18 +776,60 @@ struct bus_type tegra_ivc_bus_type = {
|
||||
};
|
||||
EXPORT_SYMBOL(tegra_ivc_bus_type);
|
||||
|
||||
/**
|
||||
* @brief Registers an IVC driver with the IVC bus
|
||||
*
|
||||
* This function registers a driver with the IVC bus system.
|
||||
* It allows the driver to handle IVC channel devices.
|
||||
* - Calls @ref driver_register() to register the driver with the kernel
|
||||
*
|
||||
* @param[in] drv Pointer to the IVC driver to register
|
||||
* Valid value: non-NULL
|
||||
*
|
||||
* @retval (int) return value from @ref driver_register()
|
||||
*/
|
||||
int tegra_ivc_driver_register(struct tegra_ivc_driver *drv)
|
||||
{
|
||||
return driver_register(&drv->driver);
|
||||
}
|
||||
EXPORT_SYMBOL(tegra_ivc_driver_register);
|
||||
|
||||
/**
|
||||
* @brief Unregisters an IVC driver from the IVC bus
|
||||
*
|
||||
* This function unregisters a driver from the IVC bus system.
|
||||
* It removes the driver's ability to handle IVC channel devices.
|
||||
* - Calls @ref driver_unregister() to unregister the driver from the kernel
|
||||
*
|
||||
* @param[in] drv Pointer to the IVC driver to unregister
|
||||
* Valid value: non-NULL
|
||||
*/
|
||||
void tegra_ivc_driver_unregister(struct tegra_ivc_driver *drv)
|
||||
{
|
||||
return driver_unregister(&drv->driver);
|
||||
}
|
||||
EXPORT_SYMBOL(tegra_ivc_driver_unregister);
|
||||
|
||||
/**
|
||||
* @brief Parses IVC regions from device tree
|
||||
*
|
||||
* This function parses IVC region specifications from the device tree.
|
||||
* It allocates memory for each region and initializes region parameters.
|
||||
* - Iterates through device tree nodes to find channel specifications
|
||||
* - Validates region specifications
|
||||
* - Counts frames and calculates sizes
|
||||
* - Allocates DMA-coherent memory for each region
|
||||
* - Initializes region parameters
|
||||
*
|
||||
* @param[in] bus Pointer to the IVC bus
|
||||
* Valid value: non-NULL
|
||||
* @param[in] dev_node Pointer to the device tree node
|
||||
* Valid value: non-NULL
|
||||
*
|
||||
* @retval 0 On successful parsing
|
||||
* @retval -EINVAL If region specification is invalid
|
||||
* @retval -ENOMEM If memory allocation fails
|
||||
*/
|
||||
static int tegra_ivc_bus_parse_regions(struct tegra_ivc_bus *bus,
|
||||
struct device_node *dev_node)
|
||||
{
|
||||
@@ -633,6 +913,17 @@ static int tegra_ivc_bus_parse_regions(struct tegra_ivc_bus *bus,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Counts the number of IVC regions in a device tree node
|
||||
*
|
||||
* This function counts the number of IVC regions specified in a device tree node.
|
||||
* It uses @ref of_parse_phandle_with_fixed_args() to iterate through all ivc-channels.
|
||||
*
|
||||
* @param[in] dev_node Pointer to the device tree node
|
||||
* Valid value: non-NULL
|
||||
*
|
||||
* @retval (unsigned) The number of IVC regions found
|
||||
*/
|
||||
static unsigned tegra_ivc_bus_count_regions(const struct device_node *dev_node)
|
||||
{
|
||||
unsigned i;
|
||||
@@ -644,6 +935,27 @@ static unsigned tegra_ivc_bus_count_regions(const struct device_node *dev_node)
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Creates and initializes an IVC bus
|
||||
*
|
||||
* This function creates and initializes an IVC bus with the specified parameters.
|
||||
* It performs the following operations:
|
||||
* - Counts the number of regions using @ref tegra_ivc_bus_count_regions()
|
||||
* - Allocates memory for the bus and regions using @ref kzalloc()
|
||||
* - Initializes bus properties and device parameters
|
||||
* - Parses regions using @ref tegra_ivc_bus_parse_regions()
|
||||
* - Adds the device using @ref device_add()
|
||||
* - Starts the bus using @ref tegra_ivc_bus_start()
|
||||
*
|
||||
* @param[in] dev Pointer to the parent device
|
||||
* Valid value: non-NULL
|
||||
* @param[in] camhsp Pointer to the camera HSP context
|
||||
* Valid value: non-NULL
|
||||
*
|
||||
* @retval struct tegra_ivc_bus* Pointer to the created IVC bus on success
|
||||
* @retval ERR_PTR(-ENOMEM) If memory allocation fails
|
||||
* @retval ERR_PTR(ret) Error code from one of the called functions
|
||||
*/
|
||||
struct tegra_ivc_bus *tegra_ivc_bus_create(struct device *dev,
|
||||
struct camrtc_hsp *camhsp)
|
||||
{
|
||||
@@ -694,8 +1006,19 @@ error:
|
||||
}
|
||||
EXPORT_SYMBOL(tegra_ivc_bus_create);
|
||||
|
||||
/*
|
||||
* Communicate RTCPU UP/DOWN state to IVC devices.
|
||||
/**
|
||||
* @brief Communicates RTCPU UP/DOWN state to IVC devices
|
||||
*
|
||||
* This function communicates the RTCPU UP/DOWN state to IVC devices.
|
||||
* It notifies all child devices of the bus about the RTCPU state.
|
||||
* - Checks if the bus is valid using @ref IS_ERR_OR_NULL()
|
||||
* - Calls @ref device_for_each_child() with @ref tegra_ivc_bus_ready_child()
|
||||
* - If online, notifies all channels using @ref tegra_ivc_bus_notify()
|
||||
*
|
||||
* @param[in] bus Pointer to the IVC bus
|
||||
* Valid value: any value including NULL or error pointer
|
||||
* @param[in] online Boolean indicating if RTCPU is online (true) or offline (false)
|
||||
* Valid value: true or false
|
||||
*/
|
||||
void tegra_ivc_bus_ready(struct tegra_ivc_bus *bus, bool online)
|
||||
{
|
||||
@@ -709,6 +1032,19 @@ void tegra_ivc_bus_ready(struct tegra_ivc_bus *bus, bool online)
|
||||
}
|
||||
EXPORT_SYMBOL(tegra_ivc_bus_ready);
|
||||
|
||||
/**
|
||||
* @brief Destroys an IVC bus
|
||||
*
|
||||
* This function destroys an IVC bus and releases all associated resources.
|
||||
* It performs the following operations:
|
||||
* - Checks if the bus is valid using @ref IS_ERR_OR_NULL() and returns if invalid
|
||||
* - Disables runtime PM for the device using @ref pm_runtime_disable()
|
||||
* - Stops all channels using @ref tegra_ivc_bus_stop()
|
||||
* - Unregisters the device using @ref device_unregister()
|
||||
*
|
||||
* @param[in] bus Pointer to the IVC bus
|
||||
* Valid value: any value including NULL or error pointer
|
||||
*/
|
||||
void tegra_ivc_bus_destroy(struct tegra_ivc_bus *bus)
|
||||
{
|
||||
if (IS_ERR_OR_NULL(bus))
|
||||
@@ -720,11 +1056,26 @@ void tegra_ivc_bus_destroy(struct tegra_ivc_bus *bus)
|
||||
}
|
||||
EXPORT_SYMBOL(tegra_ivc_bus_destroy);
|
||||
|
||||
/**
|
||||
* @brief Initializes the Tegra IVC bus subsystem
|
||||
*
|
||||
* This function initializes the IVC bus subsystem by registering the IVC bus type using
|
||||
* @ref bus_register()
|
||||
* @pre It is called during module initialization.
|
||||
*
|
||||
* @retval (int) return value from @ref bus_register()
|
||||
*/
|
||||
static __init int tegra_ivc_bus_init(void)
|
||||
{
|
||||
return bus_register(&tegra_ivc_bus_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Cleans up the Tegra IVC bus subsystem
|
||||
*
|
||||
* This function performs cleanup of the IVC bus subsystem by unregistering the IVC bus type using @ref bus_unregister()
|
||||
* @pre It is called during module exit.
|
||||
*/
|
||||
static __exit void tegra_ivc_bus_exit(void)
|
||||
{
|
||||
bus_unregister(&tegra_ivc_bus_type);
|
||||
|
||||
@@ -16,6 +16,19 @@ struct camrtc_reset_group {
|
||||
struct reset_control *resets[];
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Releases resources associated with a reset group
|
||||
*
|
||||
* This function is called when a reset group is being destroyed.
|
||||
* It performs the following operations:
|
||||
* - Iterates through all resets in the group
|
||||
* - For each reset, if it exists, calls @ref reset_control_put() to release it
|
||||
*
|
||||
* @param[in] dev Pointer to the device
|
||||
* Valid value: non-NULL
|
||||
* @param[in] res Pointer to the reset group resource
|
||||
* Valid value: non-NULL
|
||||
*/
|
||||
static void camrtc_reset_group_release(struct device *dev, void *res)
|
||||
{
|
||||
const struct camrtc_reset_group *grp = res;
|
||||
@@ -27,6 +40,33 @@ static void camrtc_reset_group_release(struct device *dev, void *res)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets a reset group based on device tree properties
|
||||
*
|
||||
* This function creates and initializes a reset group based on device tree properties.
|
||||
* It performs the following operations:
|
||||
* - Validates the device and its device tree node
|
||||
* - Determines the appropriate property name based on the group_name parameter
|
||||
* - Counts reset strings using @ref of_property_count_strings()
|
||||
* - Checks for size overflows using @ref __builtin_add_overflow()
|
||||
* - Allocates memory for the reset group using @ref devres_alloc()
|
||||
* - Initializes group properties (nresets, device, group_name)
|
||||
* - Iterates through all reset names in the group
|
||||
* - Gets each reset control using @ref of_reset_control_get()
|
||||
* - Adds the reset group to device resources using @ref devres_add()
|
||||
*
|
||||
* @param[in] dev Pointer to the parent device
|
||||
* Valid value: non-NULL with valid device tree node
|
||||
* @param[in] group_name Name of the reset group property
|
||||
* Valid value: NULL (defaults to "reset-names") or a valid string
|
||||
*
|
||||
* @retval struct camrtc_reset_group* Reset group on success
|
||||
* @retval ERR_PTR(-EINVAL) If device or device tree node is invalid
|
||||
* @retval ERR_PTR(-ENOENT) If reset names property is not found
|
||||
* @retval ERR_PTR(-EOVERFLOW) If size calculations overflow
|
||||
* @retval ERR_PTR(-ENOMEM) If memory allocation fails
|
||||
* @retval ERR_PTR(ret) If reset control retrieval fails
|
||||
*/
|
||||
struct camrtc_reset_group *camrtc_reset_group_get(
|
||||
struct device *dev,
|
||||
const char *group_name)
|
||||
@@ -101,6 +141,23 @@ error:
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(camrtc_reset_group_get);
|
||||
|
||||
/**
|
||||
* @brief Reports an error related to a reset in a reset group
|
||||
*
|
||||
* This function reports an error related to a specific reset in a reset group.
|
||||
* It performs the following operations:
|
||||
* - Attempts to get the reset name from the device tree using @ref of_property_read_string_index()
|
||||
* - Prints a warning message about the operation that failed using @ref dev_warn()
|
||||
*
|
||||
* @param[in] grp Pointer to the reset group
|
||||
* Valid value: non-NULL
|
||||
* @param[in] op String describing the operation that failed
|
||||
* Valid value: non-NULL
|
||||
* @param[in] index Index of the reset in the reset group
|
||||
* Valid range: [0, grp->nresets-1]
|
||||
* @param[in] error Error code
|
||||
* Valid value: [INT_MIN, INT_MAX]
|
||||
*/
|
||||
static void camrtc_reset_group_error(
|
||||
const struct camrtc_reset_group *grp,
|
||||
char const *op,
|
||||
@@ -119,6 +176,19 @@ static void camrtc_reset_group_error(
|
||||
op, name, grp->group_name, index, error);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Asserts all resets in a reset group
|
||||
*
|
||||
* This function asserts all resets in the specified reset group in reverse order.
|
||||
* It performs the following operations:
|
||||
* - Checks if the reset group is valid using @ref IS_ERR_OR_NULL()
|
||||
* - Iterates through all resets in the group in reverse order
|
||||
* - Asserts each reset using @ref reset_control_assert()
|
||||
* - Reports errors using @ref camrtc_reset_group_error() if a reset fails to assert
|
||||
*
|
||||
* @param[in] grp Pointer to the reset group
|
||||
* Valid value: any value including NULL or error pointer
|
||||
*/
|
||||
void camrtc_reset_group_assert(const struct camrtc_reset_group *grp)
|
||||
{
|
||||
int index, index0, err;
|
||||
@@ -135,6 +205,24 @@ void camrtc_reset_group_assert(const struct camrtc_reset_group *grp)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(camrtc_reset_group_assert);
|
||||
|
||||
/**
|
||||
* @brief Deasserts all resets in a reset group
|
||||
*
|
||||
* This function deasserts all resets in the specified reset group in forward order.
|
||||
* It performs the following operations:
|
||||
* - Checks if the reset group is valid using null check and @ref IS_ERR()
|
||||
* - Iterates through all resets in the group in forward order
|
||||
* - Deasserts each reset using @ref reset_control_deassert()
|
||||
* - Reports errors using @ref camrtc_reset_group_error() if a reset fails to deassert
|
||||
* - Returns an error code if any reset fails to deassert
|
||||
*
|
||||
* @param[in] grp Pointer to the reset group
|
||||
* Valid value: any value including NULL or error pointer
|
||||
*
|
||||
* @retval 0 On successful deassertion of all resets
|
||||
* @retval -ENODEV If the reset group is an error pointer
|
||||
* @retval (int) Error code from @ref reset_control_deassert()
|
||||
*/
|
||||
int camrtc_reset_group_deassert(const struct camrtc_reset_group *grp)
|
||||
{
|
||||
int index, err;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -17,6 +17,18 @@ struct tegra_camrtc_mon {
|
||||
struct work_struct wdt_work;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Restores the camera RTCPU by rebooting it
|
||||
*
|
||||
* This function reboots the camera RTCPU which broadcasts rtcpu-down and rtcpu-up
|
||||
* events to all IVC channels. It performs the following operations:
|
||||
* - Calls @ref tegra_camrtc_reboot to reboot the camera RTCPU
|
||||
*
|
||||
* @param[in] cam_rtcpu_mon Pointer to the camera RTCPU monitor
|
||||
* Valid value: non-NULL
|
||||
*
|
||||
* @retval (int) return value from @ref tegra_camrtc_reboot
|
||||
*/
|
||||
int tegra_camrtc_mon_restore_rtcpu(struct tegra_camrtc_mon *cam_rtcpu_mon)
|
||||
{
|
||||
/* (Re)boot the rtcpu */
|
||||
@@ -25,6 +37,18 @@ int tegra_camrtc_mon_restore_rtcpu(struct tegra_camrtc_mon *cam_rtcpu_mon)
|
||||
}
|
||||
EXPORT_SYMBOL(tegra_camrtc_mon_restore_rtcpu);
|
||||
|
||||
/**
|
||||
* @brief Handles camera RTCPU watchdog timeout work
|
||||
*
|
||||
* This function is called when the camera RTCPU watchdog timer expires.
|
||||
* It performs the following operations:
|
||||
* - Logs a warning message using @ref dev_info
|
||||
* - Restores the camera RTCPU using @ref tegra_camrtc_mon_restore_rtcpu
|
||||
* - Re-enables the watchdog IRQ using @ref enable_irq
|
||||
*
|
||||
* @param[in] work Pointer to the work structure
|
||||
* Valid value: non-NULL
|
||||
*/
|
||||
static void tegra_camrtc_mon_wdt_worker(struct work_struct *work)
|
||||
{
|
||||
struct tegra_camrtc_mon *cam_rtcpu_mon = container_of(work,
|
||||
@@ -39,6 +63,21 @@ static void tegra_camrtc_mon_wdt_worker(struct work_struct *work)
|
||||
enable_irq(cam_rtcpu_mon->wdt_irq);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief ISR for camera RTCPU watchdog timer
|
||||
*
|
||||
* This function is the interrupt service routine called when the camera RTCPU
|
||||
* watchdog timer expires. It performs the following operations:
|
||||
* - Disables the IRQ using @ref disable_irq_nosync to prevent further interrupts
|
||||
* - Schedules the watchdog worker using @ref schedule_work to handle the timeout
|
||||
*
|
||||
* @param[in] irq Interrupt number
|
||||
* Valid value: any positive integer
|
||||
* @param[in] data Pointer to driver data (tegra_camrtc_mon)
|
||||
* Valid value: non-NULL
|
||||
*
|
||||
* @retval IRQ_HANDLED to indicate the interrupt was handled
|
||||
*/
|
||||
static irqreturn_t tegra_camrtc_mon_wdt_remote_isr(int irq, void *data)
|
||||
{
|
||||
struct tegra_camrtc_mon *cam_rtcpu_mon = data;
|
||||
@@ -50,6 +89,23 @@ static irqreturn_t tegra_camrtc_mon_wdt_remote_isr(int irq, void *data)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets up the camera RTCPU watchdog timer IRQ
|
||||
*
|
||||
* This function sets up the interrupt request handler for the camera RTCPU
|
||||
* watchdog timer. It performs the following operations:
|
||||
* - Gets the platform device pointer using @ref to_platform_device
|
||||
* - Gets the IRQ number using @ref platform_get_irq_byname
|
||||
* - Registers the threaded IRQ handler using @ref devm_request_threaded_irq
|
||||
* - Logs information about the IRQ
|
||||
*
|
||||
* @param[in,out] cam_rtcpu_mon Pointer to the camera RTCPU monitor structure
|
||||
* Valid value: non-NULL
|
||||
*
|
||||
* @retval 0 On successful setup
|
||||
* @retval -ENODEV If the IRQ is not found
|
||||
* @retval (int) Error code from @ref devm_request_threaded_irq
|
||||
*/
|
||||
static int tegra_camrtc_mon_wdt_irq_setup(
|
||||
struct tegra_camrtc_mon *cam_rtcpu_mon)
|
||||
{
|
||||
@@ -75,6 +131,22 @@ static int tegra_camrtc_mon_wdt_irq_setup(
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Creates and initializes a camera RTCPU monitor
|
||||
*
|
||||
* This function creates and initializes a camera RTCPU monitor structure.
|
||||
* It performs the following operations:
|
||||
* - Allocates memory for the monitor structure using @ref devm_kzalloc
|
||||
* - Initializes the RCE device pointer
|
||||
* - Initializes the watchdog work using @ref INIT_WORK
|
||||
* - Sets up the watchdog IRQ using @ref tegra_camrtc_mon_wdt_irq_setup
|
||||
*
|
||||
* @param[in] dev Pointer to the device structure
|
||||
* Valid value: non-NULL
|
||||
*
|
||||
* @retval (struct tegra_camrtc_mon *) Pointer to the created camera RTCPU monitor on success
|
||||
* @retval (ERR_PTR(-ENOMEM)) on failure
|
||||
*/
|
||||
struct tegra_camrtc_mon *tegra_camrtc_mon_create(struct device *dev)
|
||||
{
|
||||
struct tegra_camrtc_mon *cam_rtcpu_mon;
|
||||
@@ -96,6 +168,20 @@ struct tegra_camrtc_mon *tegra_camrtc_mon_create(struct device *dev)
|
||||
}
|
||||
EXPORT_SYMBOL(tegra_camrtc_mon_create);
|
||||
|
||||
/**
|
||||
* @brief Destroys a camera RTCPU monitor
|
||||
*
|
||||
* This function destroys a previously created camera RTCPU monitor structure.
|
||||
* It performs the following operations:
|
||||
* - Validates the input pointer using @ref IS_ERR_OR_NULL
|
||||
* - Frees the allocated memory using @ref devm_kfree
|
||||
*
|
||||
* @param[in] cam_rtcpu_mon Pointer to the camera RTCPU monitor structure
|
||||
* Valid value: any value including NULL or error pointer
|
||||
*
|
||||
* @retval 0 When successfully destroyed or input is NULL
|
||||
* @retval -EINVAL If the input is an error pointer
|
||||
*/
|
||||
int tegra_cam_rtcpu_mon_destroy(struct tegra_camrtc_mon *cam_rtcpu_mon)
|
||||
{
|
||||
if (IS_ERR_OR_NULL(cam_rtcpu_mon))
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user