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