1 /*
2 * Copyright (c) 2017-2018 Texas Instruments Incorporated - http://www.ti.com
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 */
33 /*
34 * ======== NotifySetup.xdc ========
35 */
37 package ti.sdo.ipc.family.am65xx;
39 import xdc.runtime.Assert;
40 import ti.sdo.utils.MultiProc;
42 /*!
43 * ======== NotifySetup ========
44 * Notify driver setup proxy for Vayu
45 *
46 * This module creates and registers the IPC Notify drivers for the AM65XX
47 * device family. There are two types of notify drivers available: 1) shared
48 * memory driver, and 2) mailbox driver. Use the {@link #connections}
49 * configuration parameter to select which driver to use for communicating
50 * with each remote processor.
51 *
52 * The shared memory notify driver is the default driver. It implements the
53 * full Notify API set. This driver uses memory for passing the notify
54 * payload between processors. The memory is allocated from SharedRegion #0.
55 *
56 * The mailbox notify driver uses hardware FIFOs for passing the notify
57 * payload between processors. No shared memory is required. However, this
58 * driver does not implement the full Notify API set. For example, the
59 * `Notify_sendEvent()` API will never return `Notify_E_EVTNOTREGISTERED`
60 * because it does not track this information.
61 *
62 * When configuring the notify driver, you specify which driver to use
63 * for communicating to each remote processor. If not configured, the
64 * shared memory driver will be used by default. Both sides of each connection
65 * must use the same driver. This is an easy mistake to make and there is
66 * no way to check this.
67 *
68 * This module is primarily used by notify driver authors. It is not expected
69 * that any application would ever use this module in its runtime code.
70 * The typical use of this module is simply to configure which notify driver
71 * to use. See the following example for details.
72 *
73 * @a(Configuration Example)
74 *
75 * The following is a three processor example: HOST DSP1 EVE1. In this
76 * example, HOST and DSP1 will communicate using the shared memory driver
77 * and DSP1 and EVE1 will communicate using the mailbox driver. This example
78 * explicitly configures the shared memory driver for HOST and DSP1, but
79 * this is strictly not necessary. If left unconfigured, the shared memory
80 * driver would be used as the default. Also, the connection between HOST
81 * and EVE1 is left undefined as we don't expect to use this connection.
82 *
83 * Notice that each connection configuration specifies the remote processor
84 * name and the driver type. This is how the local processor declares which
85 * driver it will use when communicating to that remote processor. The
86 * corresponding configuration on the remote processor must be complimentary.
87 *
88 * Add the following to your HOST configuration script.
89 *
90 * @p(code)
91 * // configure the notify driver
92 * var NotifySetup = xdc.useModule('ti.sdo.ipc.family.am65xx.NotifySetup');
93 *
94 * NotifySetup.connections.$add(
95 * new NotifySetup.Connection({
96 * driver: NotifySetup.Driver_SHAREDMEMORY,
97 * procName: "DSP1"
98 * })
99 * );
100 * @p
101 * Add the following to your DSP1 configuration script.
102 *
103 * @p(code)
104 * // configure the notify driver
105 * var NotifySetup = xdc.useModule('ti.sdo.ipc.family.am65xx.NotifySetup');
106 *
107 * NotifySetup.connections.$add(
108 * new NotifySetup.Connection({
109 * driver: NotifySetup.Driver_SHAREDMEMORY,
110 * procName: "HOST"
111 * })
112 * );
113 *
114 * NotifySetup.connections.$add(
115 * new NotifySetup.Connection({
116 * driver: NotifySetup.Driver_MAILBOX,
117 * procName: "EVE1"
118 * })
119 * );
120 * @p
121 * Add the following to your EVE1 configuration script.
122 *
123 * @p(code)
124 * // configure the notify driver
125 * var NotifySetup = xdc.useModule('ti.sdo.ipc.family.am65xx.NotifySetup');
126 *
127 * NotifySetup.connections.$add(
128 * new NotifySetup.Connection({
129 * driver: NotifySetup.Driver_MAILBOX,
130 * procName: "DSP1"
131 * })
132 * );
133 * @p
134 */
136 @ModuleStartup
137 @Template("./NotifySetup.xdt")
139 module NotifySetup inherits ti.sdo.ipc.interfaces.INotifySetup
140 {
141 /*! @_nodoc
142 * ======== DriverIsr ========
143 * Notify driver isr function type definition
144 * param1 = mailbox table index
145 */
146 typedef Void (*DriverIsr)(UInt16);
148 /*!
149 * ======== Driver ========
150 * Define the available notify drivers
151 *
152 * For any given connection to a remote processor, one of the
153 * following notify driver types may be used. Each driver has
154 * different characteristics and system requirements.
155 *
156 * @p(html)
157 * <div class="xdocText"><dl>
158 * <dt>Driver_SHAREDMEMORY</dt>
159 * <dd>
160 * This driver uses shared memory for passing the notify payload
161 * between processors. Additional state is also stored in the
162 * shared memory.<br><br>
163 *
164 * There is a separate, cache-aligned block of memory for each
165 * event number. This is necessary to maintain cache coherency.
166 * However, this requires a non-trivial amount of memory.<br><br>
167 * </dd>
168 *
169 * <dt>Driver_MAILBOX</dt>
170 * <dd>
171 * This driver uses a hardware FIFO (provided by the hardware
172 * mailbox) to pass the notify payload between processors. No
173 * shared memory is required by this driver.<br><br>
174 *
175 * This driver does not support the full Notify API set. This
176 * driver has lower delivery latency when compard to the shared
177 * memory driver.<br><br>
178 * </dd>
179 * </dl>
180 * @p
181 */
182 enum Driver {
183 Driver_SHAREDMEMORY = 0x01, /*! shared memory driver */
184 Driver_MAILBOX = 0x02 /*! hardware mailbox driver */
185 };
187 /*!
188 * ======== Connection ========
189 * Define a notify driver connection
190 *
191 * Each IPC connection is defined by two end-points: the local
192 * processor and the remote processor. Each connection supports
193 * only one type of notify driver. In other words, both ends of
194 * the connection must configure the same notify driver type.
195 *
196 * However, when a processor has multiple connections (when
197 * communicating with multiple remote processors), each connection
198 * is configured independently. Therefore, different notify drivers
199 * may be used for different connections. Currently, IPC supports
200 * only one connection for each remote processor.
201 *
202 * The configuration for a given connection must be coordinated with
203 * the remote processor. Each processor is only able to configure its
204 * local end-point for the connection. It is important that the remote
205 * processor use the same notify driver for the connection.
206 *
207 * @field(driver)
208 * The driver to be used for this connection. See the {@link #Driver}
209 * enumeration for details.
210 *
211 * @field(procName)
212 * The name of the remote processor for the given connection.
213 * @p
214 */
215 struct Connection {
216 Driver driver; /*! notify driver */
217 String procName; /*! remote processor name */
218 };
220 /*!
221 * ======== connections ========
222 * Configure the notify driver for each given connection
223 *
224 * Use this configuration parameter to define which notify driver
225 * is to be used when communicating with remote processors. Create
226 * one entry in this array for each connection. Each entry you create,
227 * defines the local end-point of the connection. The remote processor
228 * must have a complimentary entry in its `connections` array.
229 *
230 * Any connection which is undefined, will use the shared memory
231 * notify driver. It is not necessary to define all connections, just
232 * the ones which will not use the default.
233 *
234 * To define a local end-point connection, establish a reference to
235 * this module and add a new entry to this array.
236 *
237 * The following example show how to setup the mailbox driver for
238 * communicating from DSP1 to EVE1 and EVE2.
239 *
240 * Add the following to your DSP1 configuration script.
241 *
242 * @p(code)
243 * // configure the notify driver
244 * var NotifySetup = xdc.useModule('ti.sdo.ipc.family.am65xx.NotifySetup');
245 *
246 * NotifySetup.connections.$add(
247 * new NotifySetup.Connection({
248 * driver: NotifySetup.Driver_MAILBOX,
249 * procName: "EVE1"
250 * })
251 * );
252 *
253 * NotifySetup.connections.$add(
254 * new NotifySetup.Connection({
255 * driver: NotifySetup.Driver_MAILBOX,
256 * procName: "EVE2"
257 * })
258 * );
259 * @p
260 *
261 * Add the following to your EVE1 configuration script.
262 *
263 * @p(code)
264 * // configure the notify driver
265 * var NotifySetup = xdc.useModule('ti.sdo.ipc.family.am65xx.NotifySetup');
266 *
267 * NotifySetup.connections.$add(
268 * new NotifySetup.Connection({
269 * driver: NotifySetup.Driver_MAILBOX,
270 * procName: "DSP1"
271 * })
272 * );
273 * @p
274 *
275 * Add the following to your EVE2 configuration script.
276 *
277 * @p(code)
278 * // configure the notify driver
279 * var NotifySetup = xdc.useModule('ti.sdo.ipc.family.am65xx.NotifySetup');
280 *
281 * NotifySetup.connections.$add(
282 * new NotifySetup.Connection({
283 * driver: NotifySetup.Driver_MAILBOX,
284 * procName: "DSP1"
285 * })
286 * );
287 * @p
288 */
289 metaonly config Connection connections[length];
291 /*! @_nodoc
292 * ======== plugHwi ========
293 * Register an isr for the given interrupt and event.
294 *
295 * @param(remoteProcId) The MutiProc Id of the remote processor
296 * which will raise the given interrupt.
297 *
298 * @param(cpuIntrNum) The interrupt number which will be raised
299 * by the remote processor.
300 *
301 * @param(isr) The ISR which should be invoked to service the
302 * given interrupt.
303 */
304 Void plugHwi(UInt16 remoteProcId, Int cpuIntrNum, DriverIsr isr);
306 /*! @_nodoc
307 * ======== unplugHwi ========
308 * Unregister the isr for the given interrupt.
309 */
310 Void unplugHwi(UInt16 remoteProcId, Int cpuIntrNum);
312 /*! @_nodoc
313 * ======== interruptTable ========
314 * Accessor method to return interrupt id for given virtual proc id
315 */
316 UInt16 interruptTable(Int srcVirtId);
318 internal:
320 /* total number of cores on Am6x SoC */
321 const UInt8 NUM_CORES = 3;
323 /* number of system mailboxes (used by IPC) */
324 const UInt8 NUM_SYS_MBX = 1;
326 /* Mailbox table for storing encoded base address, mailbox user ID,
327 * and sub-mailbox index.
328 */
329 config UInt32 mailboxTable[NUM_CORES * NUM_CORES];
331 /* base address table for the mailbox subsystem */
332 config UInt32 mailboxBaseAddr[NUM_SYS_MBX];
334 /* map procId to discrete processor/core */
335 config UInt r5f_0ProcId = MultiProc.INVALIDID; /* also used for ipu1 */
336 config UInt r5f_1ProcId = MultiProc.INVALIDID;
337 config UInt hostProcId = MultiProc.INVALIDID;
339 /* map MultiProc ID to virtual ID, virtId = procIdTable[procId] */
340 config UInt32 procIdTable[NUM_CORES];
342 /* runtime driver binding structure */
343 struct DrvBind {
344 Driver driver; /* notify driver */
345 UInt16 procId; /* remote processor ID */
346 };
348 /*
349 * ======== A_internal ========
350 * Internal implementation error.
351 */
352 config Assert.Id A_internal = {
353 msg: "A_internal: internal implementation error"
354 };
356 /*
357 * ======== driverType ========
358 */
359 Driver driverType(UInt16 remoteProcId);
361 /*
362 * ======== Shm_attach ========
363 */
364 Int Shm_attach(UInt16 remoteProcId, Ptr sharedAddr);
366 /*
367 * ======== Shm_sharedMemReq ========
368 */
369 SizeT Shm_sharedMemReq(UInt16 remoteProcId, Ptr sharedAddr);
371 /*
372 * ======== Mbx_attach ========
373 */
374 Int Mbx_attach(UInt16 remoteProcId, Ptr sharedAddr);
376 /*
377 * ======== Mbx_sharedMemReq ========
378 */
379 SizeT Mbx_sharedMemReq(UInt16 remoteProcId, Ptr sharedAddr);
381 /*
382 * ======== dispatchIsr ========
383 * Dispatch interrupt to notify driver instance.
384 */
385 Void dispatchIsr(UArg arg);
387 /*
388 * ======== Module_State ========
389 */
390 struct Module_State {
391 /* interrupt plug counter */
392 UInt16 numPlugged[];
394 /* connection array */
395 DrvBind connAry[length];
397 /* Interrupt event IDs used to communicate with this processor.
398 * This table is indexed by virtual processor ID.
399 */
400 UInt16 interruptTable[NUM_CORES];
402 /* Notify driver isr dispatch table. This table is indexed
403 * by virtual processor ID.
404 */
405 DriverIsr isrDispatchTable[NUM_CORES];
406 };
407 }