SDOCM00100662: Move code to config shared RAMs to Boot module
[ipc/ipcdev.git] / packages / ti / sdo / ipc / family / f28m35x / IpcMgr.c
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  *  ======== IpcMgr.c ========
34  */
36 #include <xdc/std.h>
37 #include <xdc/runtime/Assert.h>
38 #include <xdc/runtime/Error.h>
39 #include <xdc/runtime/Startup.h>
41 #include <ti/sysbios/hal/Hwi.h>
42 #include <ti/sdo/ipc/family/f28m35x/NotifyDriverCirc.h>
43 #include <ti/sdo/ipc/family/f28m35x/NameServerBlock.h>
44 #include <ti/sdo/ipc/family/f28m35x/TransportCirc.h>
45 #include <ti/sdo/ipc/_MessageQ.h>
46 #include <ti/sdo/ipc/_Notify.h>
47 #include <ti/sdo/utils/_MultiProc.h>
49 #include "package/internal/IpcMgr.xdc.h"
51 /* For the M3 */
52 #define CTOMIPCACK  (0x400FB700)
53 #define CTOMIPCSTS  (CTOMIPCACK + 0x4)
54 #define MTOCIPCSET  (CTOMIPCACK + 0x8)
55 #define MTOCIPCCLR  (CTOMIPCACK + 0xC)
56 #define MTOCIPCFLG  (CTOMIPCACK + 0x10)
58 /* For the C28 */
59 #define CTOMIPCSET  (0x00004E00)
60 #define CTOMIPCCLR  (CTOMIPCSET + 0x2)
61 #define CTOMIPCFLG  (CTOMIPCSET + 0x4)
62 #define MTOCIPCACK  (CTOMIPCSET + 0x6)
63 #define MTOCIPCSTS  (CTOMIPCSET + 0x8)
65 #define M3_IPCFLAG  10
66 #define C28_IPCFLAG 11
68 /*
69  *  ======== IpcMgr_Module_startup ========
70  *  In this function the M3 processors is used to enable shared memory.
71  *  In addition, the owner of each block of memory is initialized and
72  *  the write access set based on the static configuration parameters.
73  *  IPC flags are used by the M3 and C28 respectively for synchronization.
74  *
75  *  The M3 starts by creating its driver instances and then sets the
76  *  C28's IPC flag to let the C28 proceed.  Then the M3 waits for its
77  *  IPC flag to be set before proceeding.  Once its IPC flag is set
78  *  by the C28, the M3 clears its IPC flag and continues.
79  *
80  *  The C28 starts by waiting for its IPC flag to be set by the M3.
81  *  Once its IPC flag is set by the M3, the C28 clears its IPC flag and
82  *  proceeds to create its driver instances.  The C28 then sets the M3's
83  *  IPC flag to let the M3 proceed.
84  *
85  *  The shared memory usage looks like the following:
86  *
87  *      |--------------------|
88  *      | Notify Driver      |
89  *      |                    |
90  *      |--------------------|
91  *      | NameServer         |
92  *      | Remote Driver      |
93  *      |--------------------|
94  *      | MessageQ Transport |
95  *      |                    |
96  *      |--------------------|
97  */
98 Int IpcMgr_Module_startup(Int phase)
99 {
100     Int status;
101     SizeT memReq;
102     Ptr writeAddr = (UInt32 *)IpcMgr_writeAddr;
103     Ptr readAddr = (UInt32 *)IpcMgr_readAddr;
104     UInt16 remoteProcId;
105     NotifyDriverCirc_Params notifyDrvParams;
106     TransportCirc_Params transportParams;
107 #ifdef xdc_target__isaCompatible_v7M
108     volatile UInt32 *set = (volatile UInt32 *)MTOCIPCSET;
109     volatile UInt32 *stat = (volatile UInt32 *)CTOMIPCSTS;
110     volatile UInt32 *ack = (volatile UInt32 *)CTOMIPCACK;
111 #else
112     volatile UInt32 *set = (volatile UInt32 *)CTOMIPCSET;
113     volatile UInt32 *stat = (volatile UInt32 *)MTOCIPCSTS;
114     volatile UInt32 *ack = (volatile UInt32 *)MTOCIPCACK;
115 #endif
117     /*
118      *  This code assumes that the device's C28 and M3 MultiProc Ids
119      *  are next to each other (e.g. n and n + 1) and that the first
120      *  one is even (e.g. n is even).
121      */
122     if (MultiProc_self() & 1) {
123         /* I'm odd */
124         remoteProcId = MultiProc_self() - 1;
125     }
126     else {
127         /* I'm even */
128         remoteProcId = MultiProc_self() + 1;
129     }
131     /* wait for Hwi module to initialize first because of NotifyDriverCirc  */
132     if (!Hwi_Module_startupDone()) {
133         return Startup_NOTDONE;
134     }
136 #ifdef xdc_target__isaCompatible_v7M
138 #else
140     /* wait for M3 to set C28's IPC flag */
141     while (!(*stat & (1 << C28_IPCFLAG))) {
142     }
144     /* clear own IPC flag */
145     *ack = 1 << C28_IPCFLAG;
147 #endif
149     /* determine the amount of memory required for NotifyDriverCirc */
150     NotifyDriverCirc_Params_init(&notifyDrvParams);
151     notifyDrvParams.writeAddr = writeAddr;
152     memReq = NotifyDriverCirc_sharedMemReq(&notifyDrvParams);
154     /* call NotifyCircSetup attach to remote processor */
155     status = IpcMgr_notifyCircAttach(remoteProcId,
156                  writeAddr, readAddr);
158     Assert_isTrue(status >= 0, IpcMgr_A_internal);
160     /* update the read/write address */
161     writeAddr = (Ptr)((UInt32)writeAddr + memReq);
162     readAddr = (Ptr)((UInt32)readAddr + memReq);
164     /* determine the amount of memory required for NameServerBlock */
165     memReq = NameServerBlock_sharedMemReq(NULL);
167     /* call NameServerBlock attach to remote processor */
168     status = IpcMgr_nameServerAttach(remoteProcId, writeAddr, readAddr);
170     Assert_isTrue(status >= 0, IpcMgr_A_internal);
172     /* update the read/write address */
173     writeAddr = (Ptr)((UInt32)writeAddr + memReq);
174     readAddr = (Ptr)((UInt32)readAddr + memReq);
176     /* determine the amount of memory required for TransportCirc */
177     TransportCirc_Params_init(&transportParams);
178     transportParams.writeAddr = writeAddr;
179     memReq = TransportCirc_sharedMemReq(&transportParams);
181     /* call TransportCircSetup attach to remote processor */
182     status = IpcMgr_transportCircAttach(remoteProcId,
183                  writeAddr, readAddr);
185     Assert_isTrue(status >= 0, IpcMgr_A_internal);
187 #ifdef xdc_target__isaCompatible_v7M
189     /* set C28 IPC flag to tell C28 to proceed */
190     *set = 1 << C28_IPCFLAG;
192     /* wait for C28 to set M3's IPC flag */
193     while (!(*stat & (1 << M3_IPCFLAG))) {
194     }
196     /* clear own IPC flag */
197     *ack = 1 << M3_IPCFLAG;
199 #else
201     /* set M3's IPC flag to tell M3 to proceed */
202     *set = 1 << M3_IPCFLAG;
204 #endif
206     return (Startup_DONE);
209 /*
210  *  ======== IpcMgr_init ========
211  *  Init CTOMMSGRAM and MTOCMSGRAM
212  */
213 Void IpcMgr_init()
215 #ifdef xdc_target__isaCompatible_v7M
217 #else
219     volatile UInt32 *c28rTestInit = (volatile UInt32 *)IpcMgr_C28RTESTINIT;
220     volatile UInt32 *c28rInitDone = (volatile UInt32 *)IpcMgr_C28RINITDONE;
222     asm(" EALLOW");
224     /* init CtoMMsgRam */
225     *c28rTestInit |= (0x1 << 4);
227     /* make sure init is done */
228     while ((*c28rInitDone & (0x1 << 4)) != (0x1 << 4)) {
229     }
231     asm(" EDIS");
233 #endif
237 /*
238  *  ======== IpcMgr_notifyCircAttach ========
239  *  Initialize interrupt
240  */
241 Int IpcMgr_notifyCircAttach(UInt16 remoteProcId, Ptr writeAddr, Ptr readAddr)
243     NotifyDriverCirc_Params notifyDrvParams;
244     NotifyDriverCirc_Handle notifyDrvHandle;
245     ti_sdo_ipc_Notify_Handle notifyHandle;
246     Error_Block eb;
247     Int status = Notify_S_SUCCESS;
249     /* Initialize the error block */
250     Error_init(&eb);
252     /* Setup the notify driver to the remote processor */
253     NotifyDriverCirc_Params_init(&notifyDrvParams);
255     /* set the read/write address of the param */
256     notifyDrvParams.readAddr = readAddr;
257     notifyDrvParams.writeAddr = writeAddr;
259     /* create the notify driver instance */
260     notifyDrvHandle = NotifyDriverCirc_create(&notifyDrvParams, &eb);
261     if (notifyDrvHandle == NULL) {
262         return (Notify_E_FAIL);
263     }
265     /* create the notify instance */
266     notifyHandle = ti_sdo_ipc_Notify_create(
267                        NotifyDriverCirc_Handle_upCast(notifyDrvHandle),
268                        remoteProcId, 0, NULL, &eb);
270     if (notifyHandle == NULL) {
271         NotifyDriverCirc_delete(&notifyDrvHandle);
272         status = Notify_E_FAIL;
273     }
275     return (status);
278 /*
279  *  ======== IpcMgr_nameServerAttach ========
280  */
281 Int IpcMgr_nameServerAttach(UInt16 remoteProcId, Ptr writeAddr, Ptr readAddr)
283     NameServerBlock_Params nsbParams;
284     NameServerBlock_Handle handle;
285     Int status = NameServerBlock_E_FAIL;
286     Error_Block eb;
288     Error_init(&eb);
290     /* Init the param */
291     NameServerBlock_Params_init(&nsbParams);
293     /* set the read/write addresses */
294     nsbParams.readAddr  = readAddr;
295     nsbParams.writeAddr = writeAddr;
297     /* create only if notify driver has been created to remote proc */
298     if (Notify_intLineRegistered(remoteProcId, 0)) {
299         handle = NameServerBlock_create(remoteProcId,
300                                         &nsbParams,
301                                         &eb);
302         if (handle != NULL) {
303             status = NameServerBlock_S_SUCCESS;
304         }
305     }
307     return (status);
310 /*
311  *  ======== IpcMgr_transportCircAttach ========
312  */
313 Int IpcMgr_transportCircAttach(UInt16 remoteProcId, Ptr writeAddr,
314     Ptr readAddr)
316     TransportCirc_Handle handle;
317     TransportCirc_Params params;
318     Int status = MessageQ_E_FAIL;
319     Error_Block eb;
321     Error_init(&eb);
323     /* init the transport parameters */
324     TransportCirc_Params_init(&params);
325     params.readAddr = readAddr;
326     params.writeAddr = writeAddr;
328     /* make sure notify driver has been created */
329     if (Notify_intLineRegistered(remoteProcId, 0)) {
330         handle = TransportCirc_create(remoteProcId, &params, &eb);
332         if (handle != NULL) {
333             status = MessageQ_S_SUCCESS;
334         }
335     }
337     return (status);