e629aa275e7711270911baa91445ed89480e43fe
[ipc/ipcdev.git] / packages / ti / ipc / Notify.h
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)
607 #endif /* defined (__cplusplus) */
608 #endif /* ti_ipc_Notify__include */