1 /*
2 * Copyright (c) 2012-2013, Texas Instruments Incorporated
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the name of Texas Instruments Incorporated nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32 /**
33 * @file ti/ipc/Notify.h
34 *
35 * @brief Notification manager for IPC
36 *
37 * @note Notify is currently only available for SYS/BIOS.
38 *
39 * The Notify module manages the multiplexing/demultiplexing of software
40 * interrupts over hardware interrupts. In order to receive notifications,
41 * a processor registers one or more callback functions to an eventId
42 * using Notify_registerEvent(). The Notify_registerEvent()
43 * call (like most other Notify APIs) uses a MultiProc id and
44 * line id to target a specific interrupt line to/from a specific processor
45 * on a device. The Notify_eventAvailable() API may be used to query whether
46 * an event id is available for use before registration.
47 *
48 * Once an event has been registered, a remote processor may send an event
49 * using the Notify_sendEvent() call. If the event and the interrupt line
50 * are both enabled, all callback functions registered to the event will
51 * be called sequentially.
52 *
53 * A specific event may be disabled or enabled using the Notify_disableEvent()
54 * and Notify_enableEvent() calls. An entire interrupt line may be disabled
55 * or restored using the Notify_disable() or Notify_restore() calls.
56 * Notify_disable() does not alter the state of individual events.
57 * Instead, it just disables the ability of the Notify module to receive
58 * events on the interrupt line.
59 *
60 * Notify APIs should never be called within an Hwi context. All API calls
61 * should be made within main(), a Task or a Swi with the exception of
62 * Notify_sendEvent() which may also be called within a Hwi.
63 *
64 * "Loopback" functionality allows Notifications to be registered
65 * and sent locally. This is accomplished by supplying our own MultiProc id
66 * to Notify APIs. Line id #0 is always used for local notifications. It is
67 * important to be aware of some subtle (but important) differences between
68 * remote and local notifications:
69 * - Loopback callback functions will execute in the same thread in which
70 * Notify_sendEvent() is called. This is in contrast to callback
71 * functions that are called due to another processor's sent
72 * notification- these 'remote' callback functions will execute in an
73 * ISR context.
74 * - Loopback callback functions will execute with interrupts disabled
75 * - Disabling the local interrupt line will cause all notifications that
76 * are sent to the local processor to be lost. By contrast, a
77 * notification sent to an enabled event on a remote processor that has
78 * called Notify_disable() results in a pending notifications until the
79 * disabled processor has called Notify_restore().
80 * - Local notifications do not support events of different priorities.
81 * By contrast, Notify driver implementations may correlate event ids
82 * with varying priorities.
83 *
84 * In order to use any Notify APIs all necessary Notify drivers, shared memory
85 * and interprocessor interrupts must be initialized. This is typically done
86 * by Ipc_start(), which internally call Notify_attach().
87 * It is possible for a user application to call Notify_attach() directly
88 * (before Ipc_attach() or Ipc_start()) if notifications must be set up prior
89 * to runtime SharedRegion initialization. Refer to the documentation for
90 * Notify_attach() for more information.
91 *
92 * The Notify header should be included in an application as follows:
93 * @code
94 * #include <ti/ipc/Notify.h>
95 * @endcode
96 */
98 #ifndef ti_ipc_Notify__include
99 #define ti_ipc_Notify__include
101 #if defined (__cplusplus)
102 extern "C" {
103 #endif
105 /* =============================================================================
106 * All success and failure codes for the module
107 * =============================================================================
108 */
110 /*!
111 * @brief The resource is still in use
112 */
113 #define Notify_S_BUSY (2)
115 /*!
116 * @brief Module already set up
117 */
118 #define Notify_S_ALREADYSETUP (1)
120 /*!
121 * @brief Operation is successful.
122 */
123 #define Notify_S_SUCCESS (0)
125 /*!
126 * @brief Generic failure.
127 */
128 #define Notify_E_FAIL (-1)
130 /*!
131 * @brief Argument passed to function is invalid.
132 */
133 #define Notify_E_INVALIDARG (-2)
135 /*!
136 * @brief Operation resulted in memory failure.
137 */
138 #define Notify_E_MEMORY (-3)
140 /*!
141 * @brief The specified entity already exists.
142 */
143 #define Notify_E_ALREADYEXISTS (-4)
145 /*!
146 * @brief Unable to find the specified entity.
147 */
148 #define Notify_E_NOTFOUND (-5)
150 /*!
151 * @brief Operation timed out.
152 */
153 #define Notify_E_TIMEOUT (-6)
155 /*!
156 * @brief Module is not initialized.
157 */
158 #define Notify_E_INVALIDSTATE (-7)
160 /*!
161 * @brief A failure occurred in an OS-specific call
162 */
163 #define Notify_E_OSFAILURE (-8)
165 /*!
166 * @brief The module has been already setup
167 */
168 #define Notify_E_ALREADYSETUP (-9)
170 /*!
171 * @brief Specified resource is not available
172 */
173 #define Notify_E_RESOURCE (-10)
175 /*!
176 * @brief Operation was interrupted. Please restart the operation
177 */
178 #define Notify_E_RESTART (-11)
180 /*!
181 * @brief The resource is still in use
182 */
183 #define Notify_E_BUSY (-12)
185 /*!
186 * @brief Driver corresponding to the specified eventId is not registered
187 */
188 #define Notify_E_DRIVERNOTREGISTERED (-13)
190 /*!
191 * @brief Event not registered
192 */
193 #define Notify_E_EVTNOTREGISTERED (-14)
195 /*!
196 * @brief Event is disabled
197 */
198 #define Notify_E_EVTDISABLED (-15)
200 /*!
201 * @brief Remote notification is not initialized
202 */
203 #define Notify_E_NOTINITIALIZED (-16)
205 /*!
206 * @brief Trying to illegally use a reserved event
207 */
208 #define Notify_E_EVTRESERVED (-17)
210 /* =============================================================================
211 * Macros
212 * =============================================================================
213 */
215 /*!
216 * @brief Maximum number of events supported by the Notify module
217 */
218 #define Notify_MAXEVENTS (UInt16)32
220 /*!
221 * @brief Maximum number of IPC interrupt lines for any pair of processors
222 */
223 #define Notify_MAX_INTLINES 4u
225 /*!
226 * @brief This key must be provided as the upper 16 bits of the eventId when
227 * registering for an event, if any reserved event numbers are to be
228 * used.
229 */
230 #define Notify_SYSTEMKEY ((UInt16)0xC1D2)
232 /* =============================================================================
233 * Structures & Enums
234 * =============================================================================
235 */
237 /*!
238 * @var Notify_FnNotifyCbck
239 * @brief Signature of any callback function that can be registered with the
240 * Notify component.
241 *
242 * @param[in] procId Remote processor id
243 * @param[in] lineId Line id
244 * @param[in] eventId Event id (minus system key if reserved event)
245 * @param[in] arg Argument specified in the registerEvent
246 * @param[in] payload Payload specified in the sendEvent
247 */
248 typedef Void (*Notify_FnNotifyCbck)(UInt16 , UInt16, UInt32, UArg, UInt32);
250 /* =============================================================================
251 * Notify Module-wide Functions
252 * =============================================================================
253 */
255 /*!
256 * @brief Creates notify drivers and registers them with Notify
257 *
258 * This function must be called before other Notify API calls are
259 * invoked. Performing a attach invokes a device-specific Notify
260 * initialization routine that creates required drivers and
261 * registers those drivers with the Notify module. If the drivers
262 * require shared memory, a shared address must be supplied.
263 *
264 * Notify_attach() is typically called internally as part of the IPC
265 * initialization sequence. Any memory required for Notify drivers
266 * is reserved by SharedRegion and passed to Notify_attach(). However, if it
267 * is necessary to pass a specific base address to Notify_attach() (i.e. if
268 * the shared region is not valid yet), then Notify_attach() should be called
269 * before Ipc_start() with this address. When Ipc_start() is eventually
270 * called, Notify_attach() will be internally bypassed since it was directly
271 * called by the user.
272 *
273 * @param[in] remoteProcId Remote processor id
274 * @param[in] sharedAddr Shared address to use if any driver requires
275 * shared memory
276 * @return Notify status:
277 * - #Notify_E_FAIL: failed to attach to remote processor
278 * - #Notify_S_SUCCESS: successfully attach to remote processor
279 */
280 Int Notify_attach(UInt16 remoteProcId, Ptr sharedAddr);
282 /*!
283 * @brief Disable ability to receive interrupts on an interrupt line
284 *
285 * This function disables a NotifyDriver from processing received
286 * events. The key that is returned from this call must be used
287 * in the Notify_restore() function.
288 *
289 * Notify supports nested disable/restore calls. The value of the returned
290 * key is the nesting depth.
291 *
292 * If Notify_disable() is called upon an interrupt line that is already
293 * disabled, then the corresponding Notify_restore() will not re-enable
294 * notifications. Only the restore call that corresponds to the
295 * Notify_disable() that actually disabled notifications will re-enable
296 * notifications on the interrupt line.
297 *
298 * @param[in] procId Remote processor id
299 * @param[in] lineId Line id
300 *
301 * @return Key that must be used in Notify_restore()
302 *
303 * @sa Notify_restore()
304 */
305 UInt Notify_disable(UInt16 procId, UInt16 lineId);
307 /*!
308 * @brief Disable an event
309 *
310 * This function allows the disabling of a single event number
311 * from the specified source processor. Sending to a disabled event
312 * will return #Notify_E_EVTDISABLED on the sender if waitClear is false.
313 * Notify_disableEvent() and Notify_enableEvent() may not be supported by all
314 * Notify drivers. Consult the documentation for the Notify driver to determine
315 * whether it supports this API call.
316 *
317 * An event is, by default, enabled upon driver initialization.
318 * Calling Notify_disableEvent() upon an event that is already disabled
319 * results in no change in state.
320 *
321 * Note that callbacks may be registered to an event or removed
322 * from the event even while the event has been disabled.
323 *
324 * @param[in] procId Remote processor id
325 * @param[in] lineId Line id
326 * @param[in] eventId Event id
327 *
328 * @sa Notify_enableEvent()
329 */
330 Void Notify_disableEvent(UInt16 procId, UInt16 lineId, UInt32 eventId);
332 /*!
333 * @brief Enable an event
334 *
335 * This function re-enables an event that has been previously disabled
336 * using disableEvent(). Calling Notify_enableEvent() upon an event that is
337 * already enabled results in no change in state. An event is,
338 * by default, enabled upon driver initialization.
339 *
340 * Notify_disableEvent() and Notify_enableEvent() may not be supported by all
341 * Notify drivers. Consult the documentation for the Notify driver to determine
342 * whether it supports this API call.
343 *
344 * @param[in] procId Remote processor id
345 * @param[in] lineId Line id
346 * @param[in] eventId Event id
347 *
348 * @sa Notify_disableEvent()
349 */
350 Void Notify_enableEvent(UInt16 procId, UInt16 lineId, UInt32 eventId);
352 /*!
353 * @brief Whether an unused event is available on an interrupt line
354 *
355 * This function can be used to determine whether an unused eventId for a
356 * specific interrupt line is available for use in Notify_registerEvent()
357 * or Notify_registerEventSingle(). This function will return TRUE if and only
358 * if the following conditions are simultaneously TRUE:
359 * - The corresponding interrupt line is available. Notifications over an
360 * interrupt line to a remote processor are typically made available by
361 * calling Notify_attach() or Ipc_attach().
362 * - The event is not a reserved event
363 * - The event is a reserved event and #Notify_SYSTEMKEY has been passed
364 * as the upper 16 bits of the 32-bit eventId argument
365 * - No callback functions have been registered to the event
366 * If any of the above conditions is false, this function will return FALSE.
367 * Note that an event may still be registered using Notify_registerEvent()
368 * while the last condition is false if the existing callback function(s)
369 * were registered using Notify_registerEvent() (not
370 * Notify_registerEventSingle()).
371 *
372 * @param[in] procId Remote processor id
373 * @param[in] lineId Line id
374 * @param[in] eventId Event id
375 *
376 * @return TRUE if an unused event is available, FALSE otherwise
377 */
378 Bool Notify_eventAvailable(UInt16 procId, UInt16 lineId, UInt32 eventId);
380 /*!
381 * @brief Whether notification via interrupt line has been registered.
382 *
383 * This function will return TRUE if and only if a notify driver has been
384 * registered for the interrupt line identified by the supplied procId and
385 * lineId. The interrupt line corresponding to loopback functionality is
386 * always registered. A value of FALSE indicates that either
387 * Notify_attach() has not yet been called or that notification to the
388 * remote processor is unsupported.
389 *
390 * @param[in] procId Remote processor id
391 * @param[in] lineId Line id
392 *
393 * @return TRUE if registered, FALSE otherwise
394 */
395 Bool Notify_intLineRegistered(UInt16 procId, UInt16 lineId);
397 /*!
398 * @brief Returns number of interrupt lines to remote processor
399 *
400 * This function returns the number of available interrupt lines to a remote
401 * processor.
402 *
403 * @param[in] procId Remote processor id
404 *
405 * @return Number of interrupt lines
406 */
407 UInt16 Notify_numIntLines(UInt16 procId);
409 /*! @cond */
410 /*!
411 * @brief Returns the amount of shared memory used by one Notify instance.
412 *
413 * This will typically be used internally by other IPC modules during system
414 * initialization. The return value depends upon the base address because
415 * of cache alignment settings.
416 *
417 * @param[in] sharedAddr Base address that will be passed to
418 * Notify_attach()
419 *
420 * @return Shared memory required (in MAUs)
421 */
422 SizeT Notify_sharedMemReq(UInt16 procId, Ptr sharedAddr);
424 /*! @endcond */
426 /*!
427 * @brief Register a callback for an event (supports multiple callbacks)
428 *
429 * This function registers a callback to a specific event number,
430 * processor id and interrupt line. When the event is received by the
431 * specified processor, the callback is called.
432 *
433 * The callback function prototype is of type #Notify_FnNotifyCbck.
434 * This function must be non-blocking.
435 *
436 * It is important to note that multiple callbacks may be registered with
437 * a single event. This is accomplished by simply calling
438 * Notify_registerEvent() for each combination of callback functions and
439 * callback arguments as needed.
440 *
441 * It is important to note that interrupts are disabled during the entire
442 * duration of this function's execution.
443 *
444 * @param[in] procId Remote processor id
445 * @param[in] lineId Line id (0 for most systems)
446 * @param[in] eventId Event id
447 * @param[in] fnNotifyCbck Pointer to callback function
448 * @param[in] cbckArg Callback function argument
449 *
450 * @return Notify status:
451 * - #Notify_S_SUCCESS: Event successfully registered
452 * - #Notify_E_MEMORY: Failed to register due to memory error
453 *
454 * @sa Notify_unregisterEvent()
455 */
456 Int Notify_registerEvent(UInt16 procId,
457 UInt16 lineId,
458 UInt32 eventId,
459 Notify_FnNotifyCbck fnNotifyCbck,
460 UArg cbckArg);
462 /*!
463 * @brief Register a single callback for an event
464 *
465 * This function registers a callback to a specific event number,
466 * processor id and interrupt line. When the event is received by the
467 * specified processor, the callback is called.
468 *
469 * The callback function prototype is of type #Notify_FnNotifyCbck.
470 * The callback function must be non-blocking.
471 *
472 * Only one callback may be registered with this API.
473 *
474 * Use Notify_registerEvent() to register multiple callbacks for a single event.
475 *
476 * @param[in] procId Remote processor id
477 * @param[in] lineId Line id (0 for most systems)
478 * @param[in] eventId Event id
479 * @param[in] fnNotifyCbck Pointer to callback function
480 * @param[in] cbckArg Callback function argument
481 *
482 * @return Notify status:
483 * - #Notify_E_ALREADYEXISTS: Event already registered
484 * - #Notify_S_SUCCESS: Event successfully registered
485 *
486 * @sa Notify_unregisterEventSingle()
487 */
488 Int Notify_registerEventSingle(UInt16 procId,
489 UInt16 lineId,
490 UInt32 eventId,
491 Notify_FnNotifyCbck fnNotifyCbck,
492 UArg cbckArg);
494 /*!
495 * @brief Restore ability to receive interrupts on an interrupt line
496 *
497 * This function re-enables receiving notifications on a specific interrupt
498 * line.
499 *
500 * Notify supports nested disable/restore calls. The last restore call
501 * will re-enable Notifications.
502 *
503 * @param[in] procId Remote processor id
504 * @param[in] lineId Line id
505 * @param[in] key Key returned by Notify_disable()
506 *
507 * @sa Notify_disable()
508 */
509 Void Notify_restore(UInt16 procId, UInt16 lineId, UInt key);
511 /*!
512 * @brief Send an event on an interrupt line
513 *
514 * This function sends an event to a processor via an interrupt line
515 * identified by a processor id and line id. A payload may be optionally
516 * sent to the the remote processor if supported by the device.
517 *
518 * On the destination processor, the callback functions registered
519 * with Notify with the associated eventId and source
520 * processor id are called.
521 *
522 * For example, when using 'NotifyDriverShm', a @c waitClear value of 'TRUE'
523 * indicates that, if an event was previously sent to the same eventId,
524 * sendEvent should spin until the previous event has been acknowledged by the
525 * remote processor. If @c waitClear is FALSE, a pending event with the same
526 * eventId will be overwritten by the event currently being sent. When in
527 * doubt, a value of TRUE should be used because notifications may be
528 * potentially dropped when FALSE is used. When using NotifyDriverShm, a
529 * payload should never be sent with 'waitClear = FALSE.'
530 *
531 * On the other hand, other notify drivers that use a FIFO to transmit events
532 * will spin if @c waitClear is TRUE until the FIFO has enough room to accept
533 * the event being sent. If @c waitClear is FALSE, Notify_sendEvent() will
534 * return #Notify_E_FAIL if the FIFO does not have room for the event.
535 *
536 * Refer to the documentation for the Notify drivers for more information
537 * about the effect of the @c waitClear flag in Notify_sendEvent().
538 *
539 * Notify_sendEvent can be called from a Hwi context unlike other Notify APIs.
540 *
541 * @param[in] procId Remote processor id
542 * @param[in] lineId Line id
543 * @param[in] eventId Event id
544 * @param[in] payload Payload to be sent along with the event.
545 * @param[in] waitClear Indicates whether to spin waiting for the remote
546 * core to process previous events
547 *
548 * @return Notify status:
549 * - #Notify_E_EVTNOTREGISTERED: event has no registered callback
550 * functions
551 * - #Notify_E_NOTINITIALIZED: remote driver has not yet been
552 * initialized
553 * - #Notify_E_EVTDISABLED: remote event is disabled
554 * - #Notify_E_TIMEOUT: timeout occurred (when waitClear is TRUE)
555 * - #Notify_S_SUCCESS: event successfully sent
556 */
557 Int Notify_sendEvent(UInt16 procId, UInt16 lineId, UInt32 eventId,
558 UInt32 payload, Bool waitClear);
560 /*!
561 * @brief Remove an event listener from an event
562 *
563 * This function unregisters a single callback that was registered to an event
564 * using Notify_registerEvent(). The @c procId, @c lineId, @c eventId,
565 * @c fnNotifyCbck and @c cbckArg must exactly match with the registered one.
566 *
567 * This API is used to unregister events that were registered with
568 * Notify_registerEvent(). If this is the last event, then
569 * Notify_unregisterEventSingle() is called to completely remove the event.
570 *
571 * @param[in] procId Remote processor id
572 * @param[in] lineId Line id
573 * @param[in] eventId Event id
574 * @param[in] fnNotifyCbck Pointer to callback function
575 * @param[in] cbckArg Callback function argument
576 *
577 * @return Notify status:
578 * - #Notify_E_NOTFOUND: event listener not found
579 * - #Notify_S_SUCCESS: event listener unregistered
580 *
581 * @sa Notify_registerEvent()
582 */
583 Int Notify_unregisterEvent(UInt16 procId, UInt16 lineId, UInt32 eventId,
584 Notify_FnNotifyCbck fnNotifyCbck, UArg cbckArg);
586 /*!
587 * @brief Remove an event listener from an event
588 *
589 * This function removes a previously registered callback registered with
590 * Notify_registerEventSingle(). The @c procId, @c lineId, and @c eventId
591 * must exactly match the registered one.
592 *
593 * @param[in] procId Remote processor id
594 * @param[in] lineId Line id
595 * @param[in] eventId Event id that is being unregistered
596 *
597 * @return Notify status:
598 * - #Notify_S_SUCCESS: event unregistered
599 * - #Notify_E_FAIL: fail to unregister event
600 *
601 * @sa Notify_registerEventSingle()
602 */
603 Int Notify_unregisterEventSingle(UInt16 procId, UInt16 lineId, UInt32 eventId);
605 #if defined (__cplusplus)
606 }
607 #endif /* defined (__cplusplus) */
608 #endif /* ti_ipc_Notify__include */