e99abadabd34287d7fa9055d0e33d999457ccdd2
[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     UInt32 i;
109     volatile UInt32 *memcnf  = (volatile UInt32 *)IpcMgr_MEMCNF;
110     volatile UInt32 *msmsel  = (volatile UInt32 *)IpcMgr_MSxMSEL;
111     volatile UInt32 *mssrcr  = (volatile UInt32 *)IpcMgr_MSxSRCR;
112     volatile UInt32 *set = (volatile UInt32 *)MTOCIPCSET;
113     volatile UInt32 *stat = (volatile UInt32 *)CTOMIPCSTS;
114     volatile UInt32 *ack = (volatile UInt32 *)CTOMIPCACK;
115 #else
116     volatile UInt32 *set = (volatile UInt32 *)CTOMIPCSET;
117     volatile UInt32 *stat = (volatile UInt32 *)MTOCIPCSTS;
118     volatile UInt32 *ack = (volatile UInt32 *)MTOCIPCACK;
119 #endif
121     /*
122      *  This code assumes that the device's C28 and M3 MultiProc Ids
123      *  are next to each other (e.g. n and n + 1) and that the first
124      *  one is even (e.g. n is even).
125      */
126     if (MultiProc_self() & 1) {
127         /* I'm odd */
128         remoteProcId = MultiProc_self() - 1;
129     }
130     else {
131         /* I'm even */
132         remoteProcId = MultiProc_self() + 1;
133     }
135     /* wait for Hwi module to initialize first because of NotifyDriverCirc  */
136     if (!Hwi_Module_startupDone()) {
137         return Startup_NOTDONE;
138     }
140 #ifdef xdc_target__isaCompatible_v7M
141     /*
142      *  The M3 writes the shared memory enable and owner select
143      *  registers before either processor starts using shared memory.
144      */
146     /* write the shared memory configuration register */
147     *memcnf = IpcMgr_sharedMemoryEnable;
149     /* write the owner select register */
150     *msmsel = IpcMgr_sharedMemoryOwnerMask;
152     /* init the owner write access registers */
153     for (i = 0; i < 2; i++) {
154         mssrcr[i] = (IpcMgr_sharedMemoryAccess[(i * 4)])           |
155                     (IpcMgr_sharedMemoryAccess[(i * 4) + 1] << 8)  |
156                     (IpcMgr_sharedMemoryAccess[(i * 4) + 2] << 16) |
157                     (IpcMgr_sharedMemoryAccess[(i * 4) + 3] << 24);
158     }
160 #else
162     /* wait for M3 to set C28's IPC flag */
163     while (!(*stat & (1 << C28_IPCFLAG))) {
164     }
166     /* clear own IPC flag */
167     *ack = 1 << C28_IPCFLAG;
169 #endif
171     /* determine the amount of memory required for NotifyDriverCirc */
172     NotifyDriverCirc_Params_init(&notifyDrvParams);
173     notifyDrvParams.writeAddr = writeAddr;
174     memReq = NotifyDriverCirc_sharedMemReq(&notifyDrvParams);
176     /* call NotifyCircSetup attach to remote processor */
177     status = IpcMgr_notifyCircAttach(remoteProcId,
178                  writeAddr, readAddr);
180     Assert_isTrue(status >= 0, IpcMgr_A_internal);
182     /* update the read/write address */
183     writeAddr = (Ptr)((UInt32)writeAddr + memReq);
184     readAddr = (Ptr)((UInt32)readAddr + memReq);
186     /* determine the amount of memory required for NameServerBlock */
187     memReq = NameServerBlock_sharedMemReq(NULL);
189     /* call NameServerBlock attach to remote processor */
190     status = IpcMgr_nameServerAttach(remoteProcId, writeAddr, readAddr);
192     Assert_isTrue(status >= 0, IpcMgr_A_internal);
194     /* update the read/write address */
195     writeAddr = (Ptr)((UInt32)writeAddr + memReq);
196     readAddr = (Ptr)((UInt32)readAddr + memReq);
198     /* determine the amount of memory required for TransportCirc */
199     TransportCirc_Params_init(&transportParams);
200     transportParams.writeAddr = writeAddr;
201     memReq = TransportCirc_sharedMemReq(&transportParams);
203     /* call TransportCircSetup attach to remote processor */
204     status = IpcMgr_transportCircAttach(remoteProcId,
205                  writeAddr, readAddr);
207     Assert_isTrue(status >= 0, IpcMgr_A_internal);
209 #ifdef xdc_target__isaCompatible_v7M
211     /* set C28 IPC flag to tell C28 to proceed */
212     *set = 1 << C28_IPCFLAG;
214     /* wait for C28 to set M3's IPC flag */
215     while (!(*stat & (1 << M3_IPCFLAG))) {
216     }
218     /* clear own IPC flag */
219     *ack = 1 << M3_IPCFLAG;
221 #else
223     /* set M3's IPC flag to tell M3 to proceed */
224     *set = 1 << M3_IPCFLAG;
226 #endif
228     return (Startup_DONE);
231 /*
232  *  ======== IpcMgr_init ========
233  *  Init CTOMMSGRAM and MTOCMSGRAM
234  */
235 Void IpcMgr_init()
237 #ifdef xdc_target__isaCompatible_v7M
238     volatile UInt32 *mwrallow  = (volatile UInt32 *)IpcMgr_MWRALLOW;
239     volatile UInt32 *mtocrTestInit = (volatile UInt32 *)IpcMgr_MTOCRTESTINIT;
240     volatile UInt32 *mtocrInitDone = (volatile UInt32 *)IpcMgr_MTOCRINITDONE;
242     /* allow writes to protected registers. */
243     *mwrallow = 0xA5A5A5A5;
245     /* init MtoCMsgRam */
246     *mtocrTestInit |= 0x1;
248     /* make sure init is done */
249     while ((*mtocrInitDone & 0x1) != 0x1) {
250     }
252     /* Disable writes to protected registers. */
253     *mwrallow = 0;
255 #else
257     volatile UInt32 *c28rTestInit = (volatile UInt32 *)IpcMgr_C28RTESTINIT;
258     volatile UInt32 *c28rInitDone = (volatile UInt32 *)IpcMgr_C28RINITDONE;
260     asm(" EALLOW");
262     /* init CtoMMsgRam */
263     *c28rTestInit |= (0x1 << 4);
265     /* make sure init is done */
266     while ((*c28rInitDone & (0x1 << 4)) != (0x1 << 4)) {
267     }
269     asm(" EDIS");
271 #endif
275 /*
276  *  ======== IpcMgr_notifyCircAttach ========
277  *  Initialize interrupt
278  */
279 Int IpcMgr_notifyCircAttach(UInt16 remoteProcId, Ptr writeAddr, Ptr readAddr)
281     NotifyDriverCirc_Params notifyDrvParams;
282     NotifyDriverCirc_Handle notifyDrvHandle;
283     ti_sdo_ipc_Notify_Handle notifyHandle;
284     Error_Block eb;
285     Int status = Notify_S_SUCCESS;
287     /* Initialize the error block */
288     Error_init(&eb);
290     /* Setup the notify driver to the remote processor */
291     NotifyDriverCirc_Params_init(&notifyDrvParams);
293     /* set the read/write address of the param */
294     notifyDrvParams.readAddr = readAddr;
295     notifyDrvParams.writeAddr = writeAddr;
297     /* create the notify driver instance */
298     notifyDrvHandle = NotifyDriverCirc_create(&notifyDrvParams, &eb);
299     if (notifyDrvHandle == NULL) {
300         return (Notify_E_FAIL);
301     }
303     /* create the notify instance */
304     notifyHandle = ti_sdo_ipc_Notify_create(
305                        NotifyDriverCirc_Handle_upCast(notifyDrvHandle),
306                        remoteProcId, 0, NULL, &eb);
308     if (notifyHandle == NULL) {
309         NotifyDriverCirc_delete(&notifyDrvHandle);
310         status = Notify_E_FAIL;
311     }
313     return (status);
316 /*
317  *  ======== IpcMgr_nameServerAttach ========
318  */
319 Int IpcMgr_nameServerAttach(UInt16 remoteProcId, Ptr writeAddr, Ptr readAddr)
321     NameServerBlock_Params nsbParams;
322     NameServerBlock_Handle handle;
323     Int status = NameServerBlock_E_FAIL;
324     Error_Block eb;
326     Error_init(&eb);
328     /* Init the param */
329     NameServerBlock_Params_init(&nsbParams);
331     /* set the read/write addresses */
332     nsbParams.readAddr  = readAddr;
333     nsbParams.writeAddr = writeAddr;
335     /* create only if notify driver has been created to remote proc */
336     if (Notify_intLineRegistered(remoteProcId, 0)) {
337         handle = NameServerBlock_create(remoteProcId,
338                                         &nsbParams,
339                                         &eb);
340         if (handle != NULL) {
341             status = NameServerBlock_S_SUCCESS;
342         }
343     }
345     return (status);
348 /*
349  *  ======== IpcMgr_transportCircAttach ========
350  */
351 Int IpcMgr_transportCircAttach(UInt16 remoteProcId, Ptr writeAddr,
352     Ptr readAddr)
354     TransportCirc_Handle handle;
355     TransportCirc_Params params;
356     Int status = MessageQ_E_FAIL;
357     Error_Block eb;
359     Error_init(&eb);
361     /* init the transport parameters */
362     TransportCirc_Params_init(&params);
363     params.readAddr = readAddr;
364     params.writeAddr = writeAddr;
366     /* make sure notify driver has been created */
367     if (Notify_intLineRegistered(remoteProcId, 0)) {
368         handle = TransportCirc_create(remoteProcId, &params, &eb);
370         if (handle != NULL) {
371             status = MessageQ_S_SUCCESS;
372         }
373     }
375     return (status);