blob: fe0f1e523ad00281583542513ce1f9b5c15db03f [file] [log] [blame]
Rodrigo Caballero3010de92016-02-06 16:18:22 -06001/**
2 * @file
3 *
4 * @brief Generic low-level inter-processor mailbox communication API.
5 */
Andrew Boie35896952015-11-12 14:00:47 -08006
7/*
8 * Copyright (c) 2015 Intel Corporation
9 *
David B. Kinderac74d8b2017-01-18 17:01:01 -080010 * SPDX-License-Identifier: Apache-2.0
Andrew Boie35896952015-11-12 14:00:47 -080011 */
12
13#ifndef __INCipmh
14#define __INCipmh
15
16/**
17 * @brief IPM Interface
18 * @defgroup ipm_interface IPM Interface
19 * @ingroup io_interfaces
20 * @{
21 */
22
Anas Nashifea8c6aad2016-12-23 07:32:56 -050023#include <kernel.h>
Andrew Boie35896952015-11-12 14:00:47 -080024#include <device.h>
25
Peter Mitsisa0e45682016-01-22 12:38:49 -050026#ifdef __cplusplus
27extern "C" {
28#endif
29
Andrew Boie35896952015-11-12 14:00:47 -080030/**
Inaky Perez-Gonzalez05180632016-06-15 14:18:38 -070031 * @typedef ipm_callback_t
Rodrigo Caballero3010de92016-02-06 16:18:22 -060032 * @brief Callback API for incoming IPM messages
Andrew Boie35896952015-11-12 14:00:47 -080033 *
Rodrigo Caballero3010de92016-02-06 16:18:22 -060034 * These callbacks execute in interrupt context. Therefore, use only
35 * interrupt-safe APIS. Registration of callbacks is done via
36 * @a ipm_register_callback
Andrew Boie35896952015-11-12 14:00:47 -080037 *
Inaky Perez-Gonzalez05180632016-06-15 14:18:38 -070038 * @param "void *context" Arbitrary context pointer provided at
39 * registration time.
Kumar Galacc334c72017-04-21 10:55:34 -050040 * @param "u32_t id" Message type identifier.
Inaky Perez-Gonzalez05180632016-06-15 14:18:38 -070041 * @param "volatile void *data" Message data pointer. The correct
42 * amount of data to read out
Rodrigo Caballero3010de92016-02-06 16:18:22 -060043 * must be inferred using the message id/upper level protocol.
Andrew Boie35896952015-11-12 14:00:47 -080044 */
Kumar Galacc334c72017-04-21 10:55:34 -050045typedef void (*ipm_callback_t)(void *context, u32_t id, volatile void *data);
Andrew Boie35896952015-11-12 14:00:47 -080046
Inaky Perez-Gonzalez05180632016-06-15 14:18:38 -070047/**
48 * @typedef ipm_send_t
49 * @brief Callback API to send IPM messages
50 *
51 * See @a ipm_send() for argument definitions.
52 */
Kumar Galacc334c72017-04-21 10:55:34 -050053typedef int (*ipm_send_t)(struct device *ipmdev, int wait, u32_t id,
Andrew Boie35896952015-11-12 14:00:47 -080054 const void *data, int size);
Inaky Perez-Gonzalez05180632016-06-15 14:18:38 -070055/**
56 * @typedef ipm_max_data_size_get_t
57 * @brief Callback API to get maximum data size
58 *
59 * See @a ipm_max_data_size_get() for argument definitions.
60 */
Andrew Boie35896952015-11-12 14:00:47 -080061typedef int (*ipm_max_data_size_get_t)(struct device *ipmdev);
Inaky Perez-Gonzalez05180632016-06-15 14:18:38 -070062
63/**
64 * @typedef ipm_max_id_val_get_t
65 * @brief Callback API to get the ID's maximum value
66 *
67 * See @a ipm_max_id_val_get() for argument definitions.
68 */
Kumar Galacc334c72017-04-21 10:55:34 -050069typedef u32_t (*ipm_max_id_val_get_t)(struct device *ipmdev);
Inaky Perez-Gonzalez05180632016-06-15 14:18:38 -070070
71/**
72 * @typedef ipm_register_callback_t
73 * @brief Callback API upon registration
74 *
75 * See @a ipm_register_callback() for argument definitions.
76 */
Andrew Boie35896952015-11-12 14:00:47 -080077typedef void (*ipm_register_callback_t)(struct device *port, ipm_callback_t cb,
78 void *cb_context);
Inaky Perez-Gonzalez05180632016-06-15 14:18:38 -070079
80/**
81 * @typedef ipm_set_enabled_t
David B. Kinder8b986d72017-04-18 15:56:26 -070082 * @brief Callback API upon enablement of interrupts
Inaky Perez-Gonzalez05180632016-06-15 14:18:38 -070083 *
84 * See @a ipm_set_enabled() for argument definitions.
85 */
Andrew Boie35896952015-11-12 14:00:47 -080086typedef int (*ipm_set_enabled_t)(struct device *ipmdev, int enable);
87
88struct ipm_driver_api {
89 ipm_send_t send;
90 ipm_register_callback_t register_callback;
91 ipm_max_data_size_get_t max_data_size_get;
92 ipm_max_id_val_get_t max_id_val_get;
93 ipm_set_enabled_t set_enabled;
94};
95
96/**
Rodrigo Caballero3010de92016-02-06 16:18:22 -060097 * @brief Try to send a message over the IPM device.
Andrew Boie35896952015-11-12 14:00:47 -080098 *
Rodrigo Caballero3010de92016-02-06 16:18:22 -060099 * A message is considered consumed once the remote interrupt handler
100 * finishes. If there is deferred processing on the remote side,
101 * or if outgoing messages must be queued and wait on an
102 * event/semaphore, a high-level driver can implement that.
Andrew Boie35896952015-11-12 14:00:47 -0800103 *
104 * There are constraints on how much data can be sent or the maximum value
Rodrigo Caballero3010de92016-02-06 16:18:22 -0600105 * of id. Use the @a ipm_max_data_size_get and @a ipm_max_id_val_get routines
106 * to determine them.
Andrew Boie35896952015-11-12 14:00:47 -0800107 *
Rodrigo Caballero3010de92016-02-06 16:18:22 -0600108 * The @a size parameter is used only on the sending side to determine
109 * the amount of data to put in the message registers. It is not passed along
110 * to the receiving side. The upper-level protocol dictates the amount of
111 * data read back.
Andrew Boie35896952015-11-12 14:00:47 -0800112 *
Rodrigo Caballero3010de92016-02-06 16:18:22 -0600113 * @param ipmdev Driver instance
Andrew Boiea4a33232016-09-14 09:53:59 -0700114 * @param wait If nonzero, busy-wait for remote to consume the message. The
115 * message is considered consumed once the remote interrupt handler
116 * finishes. If there is deferred processing on the remote side,
117 * or you would like to queue outgoing messages and wait on an
118 * event/semaphore, you can implement that in a high-level driver
Rodrigo Caballero3010de92016-02-06 16:18:22 -0600119 * @param id Message identifier. Values are constrained by
David B. Kinderd7485772016-08-17 16:33:08 -0700120 * @a ipm_max_data_size_get since many boards only allow for a
Rodrigo Caballero3010de92016-02-06 16:18:22 -0600121 * subset of bits in a 32-bit register to store the ID.
122 * @param data Pointer to the data sent in the message.
123 * @param size Size of the data.
124 *
125 * @retval EBUSY If the remote hasn't yet read the last data sent.
126 * @retval EMSGSIZE If the supplied data size is unsupported by the driver.
127 * @retval EINVAL If there was a bad parameter, such as: too-large id value.
128 * or the device isn't an outbound IPM channel.
129 * @retval 0 On success.
Andrew Boie35896952015-11-12 14:00:47 -0800130 */
Andrew Boie2e60b242017-10-25 13:14:49 -0700131__syscall int ipm_send(struct device *ipmdev, int wait, u32_t id,
132 const void *data, int size);
133
134static inline int _impl_ipm_send(struct device *ipmdev, int wait, u32_t id,
Andrew Boie53e62752016-03-08 10:53:45 -0800135 const void *data, int size)
Andrew Boie35896952015-11-12 14:00:47 -0800136{
Marcus Shawcroftbb4d03b2016-10-22 10:02:27 +0100137 const struct ipm_driver_api *api = ipmdev->driver_api;
Andrew Boie35896952015-11-12 14:00:47 -0800138
Andrew Boie35896952015-11-12 14:00:47 -0800139 return api->send(ipmdev, wait, id, data, size);
140}
141
142/**
Rodrigo Caballero3010de92016-02-06 16:18:22 -0600143 * @brief Register a callback function for incoming messages.
Andrew Boie35896952015-11-12 14:00:47 -0800144 *
Rodrigo Caballero3010de92016-02-06 16:18:22 -0600145 * @param ipmdev Driver instance pointer.
146 * @param cb Callback function to execute on incoming message interrupts.
Andrew Boie35896952015-11-12 14:00:47 -0800147 * @param context Application-specific context pointer which will be passed
148 * to the callback function when executed.
149 */
150static inline void ipm_register_callback(struct device *ipmdev,
151 ipm_callback_t cb, void *context)
152{
Marcus Shawcroftbb4d03b2016-10-22 10:02:27 +0100153 const struct ipm_driver_api *api = ipmdev->driver_api;
Andrew Boie35896952015-11-12 14:00:47 -0800154
Andrew Boie35896952015-11-12 14:00:47 -0800155 api->register_callback(ipmdev, cb, context);
156}
157
158/**
Rodrigo Caballero3010de92016-02-06 16:18:22 -0600159 * @brief Return the maximum number of bytes possible in an outbound message.
Andrew Boie35896952015-11-12 14:00:47 -0800160 *
Rodrigo Caballero3010de92016-02-06 16:18:22 -0600161 * IPM implementations vary on the amount of data that can be sent in a
162 * single message since the data payload is typically stored in registers.
Andrew Boie35896952015-11-12 14:00:47 -0800163 *
Rodrigo Caballero3010de92016-02-06 16:18:22 -0600164 * @param ipmdev Driver instance pointer.
Andrew Boie35896952015-11-12 14:00:47 -0800165 *
Rodrigo Caballero3010de92016-02-06 16:18:22 -0600166 * @return Maximum possible size of a message in bytes.
Andrew Boie35896952015-11-12 14:00:47 -0800167 */
Andrew Boie2e60b242017-10-25 13:14:49 -0700168__syscall int ipm_max_data_size_get(struct device *ipmdev);
169
170static inline int _impl_ipm_max_data_size_get(struct device *ipmdev)
Andrew Boie35896952015-11-12 14:00:47 -0800171{
Marcus Shawcroftbb4d03b2016-10-22 10:02:27 +0100172 const struct ipm_driver_api *api = ipmdev->driver_api;
Andrew Boie35896952015-11-12 14:00:47 -0800173
Andrew Boie35896952015-11-12 14:00:47 -0800174 return api->max_data_size_get(ipmdev);
175}
176
177
178/**
Rodrigo Caballero3010de92016-02-06 16:18:22 -0600179 * @brief Return the maximum id value possible in an outbound message.
Andrew Boie35896952015-11-12 14:00:47 -0800180 *
Rodrigo Caballero3010de92016-02-06 16:18:22 -0600181 * Many IPM implementations store the message's ID in a register with
182 * some bits reserved for other uses.
Andrew Boie35896952015-11-12 14:00:47 -0800183 *
Rodrigo Caballero3010de92016-02-06 16:18:22 -0600184 * @param ipmdev Driver instance pointer.
Andrew Boie35896952015-11-12 14:00:47 -0800185 *
Rodrigo Caballero3010de92016-02-06 16:18:22 -0600186 * @return Maximum possible value of a message ID.
Andrew Boie35896952015-11-12 14:00:47 -0800187 */
Andrew Boie2e60b242017-10-25 13:14:49 -0700188__syscall u32_t ipm_max_id_val_get(struct device *ipmdev);
189
190static inline u32_t _impl_ipm_max_id_val_get(struct device *ipmdev)
Andrew Boie35896952015-11-12 14:00:47 -0800191{
Marcus Shawcroftbb4d03b2016-10-22 10:02:27 +0100192 const struct ipm_driver_api *api = ipmdev->driver_api;
Andrew Boie35896952015-11-12 14:00:47 -0800193
Andrew Boie35896952015-11-12 14:00:47 -0800194 return api->max_id_val_get(ipmdev);
195}
196
197/**
Rodrigo Caballero3010de92016-02-06 16:18:22 -0600198 * @brief Enable interrupts and callbacks for inbound channels.
Andrew Boie35896952015-11-12 14:00:47 -0800199 *
Rodrigo Caballero3010de92016-02-06 16:18:22 -0600200 * @param ipmdev Driver instance pointer.
201 * @param enable Set to 0 to disable and to nonzero to enable.
Andrew Boie35896952015-11-12 14:00:47 -0800202 *
Rodrigo Caballero3010de92016-02-06 16:18:22 -0600203 * @retval 0 On success.
204 * @retval EINVAL If it isn't an inbound channel.
Andrew Boie35896952015-11-12 14:00:47 -0800205 */
Andrew Boie2e60b242017-10-25 13:14:49 -0700206__syscall int ipm_set_enabled(struct device *ipmdev, int enable);
207
208static inline int _impl_ipm_set_enabled(struct device *ipmdev, int enable)
Andrew Boie35896952015-11-12 14:00:47 -0800209{
Marcus Shawcroftbb4d03b2016-10-22 10:02:27 +0100210 const struct ipm_driver_api *api = ipmdev->driver_api;
Andrew Boie35896952015-11-12 14:00:47 -0800211
Andrew Boie35896952015-11-12 14:00:47 -0800212 return api->set_enabled(ipmdev, enable);
213}
214
Peter Mitsisa0e45682016-01-22 12:38:49 -0500215#ifdef __cplusplus
216}
217#endif
218
Andrew Boie35896952015-11-12 14:00:47 -0800219/**
220 * @}
221 */
Andrew Boie2e60b242017-10-25 13:14:49 -0700222
223#include <syscalls/ipm.h>
224
Andrew Boie35896952015-11-12 14:00:47 -0800225#endif /* __INCipmh */