1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - PXI - libraries
3   File:     pxi_fifo.c
4 
5   Copyright 2003-2008 Nintendo.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Date:: 2008-09-18#$
14   $Rev: 8573 $
15   $Author: okubata_ryoma $
16  *---------------------------------------------------------------------------*/
17 #ifdef SDK_TWL
18 #include  <twl.h>
19 #else
20 #include  <nitro.h>
21 #endif
22 
23 static u16 FifoCtrlInit = 0;
24 static PXIFifoCallback FifoRecvCallbackTable[PXI_MAX_FIFO_TAG];
25 
26 /*********** function prototypes ******************/
27 static inline PXIFifoStatus PXIi_GetFromFifo(u32 *data_buf);
28 static inline PXIFifoStatus PXIi_SetToFifo(u32 data);
29 
30 
31 /*---------------------------------------------------------------------------*
32   Name:         PXI_InitFifo
33 
34   Description:  initialize FIFO system
35 
36   Arguments:    None.
37 
38   Returns:      None.
39  *---------------------------------------------------------------------------*/
PXI_InitFifo(void)40 void PXI_InitFifo(void)
41 {
42     int     i;
43     OSIntrMode enabled;
44     OSSystemWork *p = OS_GetSystemWork();
45 
46     enabled = OS_DisableInterrupts();
47 
48     if (!FifoCtrlInit)
49     {
50         FifoCtrlInit = TRUE;
51 
52         p->pxiHandleChecker[PXI_PROC_ARM] = 0UL;
53 
54         for (i = 0; i < PXI_MAX_FIFO_TAG; i++)
55         {
56             FifoRecvCallbackTable[i] = NULL;
57         }
58 
59         reg_PXI_FIFO_CNT =
60             (REG_PXI_FIFO_CNT_SEND_CL_MASK |
61              REG_PXI_FIFO_CNT_RECV_RI_MASK | REG_PXI_FIFO_CNT_E_MASK | REG_PXI_FIFO_CNT_ERR_MASK);
62 
63         (void)OS_ResetRequestIrqMask(OS_IE_FIFO_RECV);
64         (void)OS_SetIrqFunction(OS_IE_FIFO_RECV, PXIi_HandlerRecvFifoNotEmpty);
65         (void)OS_EnableIrqMask(OS_IE_FIFO_RECV);
66 
67 #ifndef SDK_FINALROM
68         //
69         // Send signal to let ensata know the time of PXI initialized
70         //              Requested by ensata dev team 04/03/10
71         //
72         if (OSi_DetectEmulator())
73         {
74             reg_PXI_INTF = 0x100;
75         }
76         else
77 #endif
78 #ifdef  SDK_ARM7
79         {
80             //-------------------------------
81             // PXI_INTF
82             //   d14     RW  IE
83             //   d13     W   IREQ
84             //   d11-d08 RW  OUT Status
85             //   d03-d00 R   IN  Status
86             //-------------------------------
87             for (i = 8; i >= 0; i--)
88             {
89                 reg_PXI_INTF = (u16)(i << 8);
90                 OS_SpinWait(1000);     // Yield main bus to ARM9
91 
92                 if ((reg_PXI_INTF & 15) != i)
93                 {
94                     i = 8;
95                 }
96             }
97         }
98 #else
99         {
100             int     timeout;
101             s32     c;
102 
103             for (i = 0;; i++)
104             {
105                 c = reg_PXI_INTF & 15;
106                 reg_PXI_INTF = (u16)(c << 8);
107 
108                 if (c == 0 && i > 4)
109                 {
110                     break;
111                 }
112 
113                 for (timeout = 1000; (reg_PXI_INTF & 15) == c; timeout--)
114                 {
115                     if (timeout == 0)
116                     {
117                         i = 0;
118                         break;
119                     }
120                 }
121             }
122         }
123 #endif
124     }
125     (void)OS_RestoreInterrupts(enabled);
126 }
127 
128 
129 /*---------------------------------------------------------------------------*
130   Name:         PXI_SetFifoRecvCallback
131 
132   Description:  set callback function when data arrive via FIFO
133 
134   Arguments:    fifotag    fifo tag NO (0-31)
135                 callback   callback function to be called
136 
137   Returns:      None.
138  *---------------------------------------------------------------------------*/
PXI_SetFifoRecvCallback(int fifotag,PXIFifoCallback callback)139 void PXI_SetFifoRecvCallback(int fifotag, PXIFifoCallback callback)
140 {
141     OSIntrMode enabled;
142     OSSystemWork *p = OS_GetSystemWork();
143 
144     SDK_WARNING(callback == NULL ||
145                 FifoRecvCallbackTable[fifotag] == NULL ||
146                 FifoRecvCallbackTable[fifotag] == callback,
147                 "Fifo Callback overridden [fifotag=%d]\n", fifotag);
148 
149     enabled = OS_DisableInterrupts();
150 
151     FifoRecvCallbackTable[fifotag] = callback;
152     if (callback)
153     {
154         p->pxiHandleChecker[PXI_PROC_ARM] |= (1UL << fifotag);
155     }
156     else
157     {
158         p->pxiHandleChecker[PXI_PROC_ARM] &= ~(1UL << fifotag);
159     }
160     (void)OS_RestoreInterrupts(enabled);
161 }
162 
163 /*---------------------------------------------------------------------------*
164   Name:         PXI_IsCallbackReady
165 
166   Description:  check if callback is ready
167 
168   Arguments:    fifotag    fifo tag NO (0-31)
169                 proc       processor name PXI_PROC_ARM9 or PXI_PROC_ARM7
170 
171   Returns:      True if callback is ready
172  *---------------------------------------------------------------------------*/
PXI_IsCallbackReady(int fifotag,PXIProc proc)173 BOOL PXI_IsCallbackReady(int fifotag, PXIProc proc)
174 {
175     OSSystemWork *p = OS_GetSystemWork();
176 
177     return (p->pxiHandleChecker[proc] & (1UL << fifotag)) ? TRUE : FALSE;
178 }
179 
180 /*---------------------------------------------------------------------------*
181   Name:         PXI_SetFifoSendCallback
182 
183   Description:  set callback function when FIFO empty
184 
185   Arguments:    callback   callback function to be called
186 
187   Returns:      None.
188  *---------------------------------------------------------------------------*/
PXI_SetFifoSendCallback(PXIFifoEmtpyCallback callback)189 void PXI_SetFifoSendCallback(PXIFifoEmtpyCallback callback)
190 {
191     OSIntrMode enabled;
192 
193     enabled = OS_DisableInterrupts();
194 
195     (void)OS_SetIrqFunction(OS_IE_FIFO_SEND, callback);
196     (void)OS_EnableIrqMask(OS_IE_FIFO_SEND);
197 
198     reg_PXI_FIFO_CNT |= REG_PXI_FIFO_CNT_SEND_TI_MASK;
199 
200     (void)OS_RestoreInterrupts(enabled);
201 }
202 
203 
204 /*---------------------------------------------------------------------------*
205   Name:         PXI_SendWordByFifo
206 
207   Description:  Send 32bit-word to anothre CPU via FIFO
208 
209   Arguments:    fifotag  fifo tag NO (0-31)
210                 data     data(26-bit) whichi is sent
211                 err      1 on error
212 
213   Returns:      if error occured, returns minus value
214  *---------------------------------------------------------------------------*/
PXI_SendWordByFifo(int fifotag,u32 data,BOOL err)215 int PXI_SendWordByFifo(int fifotag, u32 data, BOOL err)
216 {
217     PXIFifoMessage fifomsg;
218 
219     SDK_ASSERTMSG(0 <= fifotag && fifotag < PXI_MAX_FIFO_TAG, "[FifoTag] out of range");
220     SDK_ASSERTMSG(data < (1UL << PXI_FIFOMESSAGE_BITSZ_DATA), "[data] out of range");
221 
222     fifomsg.e.tag = (PXIFifoTag)fifotag;
223     fifomsg.e.err = (u32)err;
224     fifomsg.e.data = data;
225 
226     return PXIi_SetToFifo(fifomsg.raw);
227 }
228 
229 
230 //======================================================================
231 //                      Write Send-FIFO reg.
232 //======================================================================
PXIi_SetToFifo(u32 data)233 static inline PXIFifoStatus PXIi_SetToFifo(u32 data)
234 {
235     OSIntrMode enabled;
236 
237     if (reg_PXI_FIFO_CNT & REG_PXI_FIFO_CNT_ERR_MASK)
238     {
239         reg_PXI_FIFO_CNT |= (REG_PXI_FIFO_CNT_E_MASK | REG_PXI_FIFO_CNT_ERR_MASK);
240         return PXI_FIFO_FAIL_SEND_ERR;
241     }
242 
243     enabled = OS_DisableInterrupts();
244     if (reg_PXI_FIFO_CNT & REG_PXI_FIFO_CNT_SEND_FULL_MASK)
245     {
246         (void)OS_RestoreInterrupts(enabled);
247         return PXI_FIFO_FAIL_SEND_FULL;
248     }
249 
250     reg_PXI_SEND_FIFO = data;
251     (void)OS_RestoreInterrupts(enabled);
252     return PXI_FIFO_SUCCESS;
253 }
254 
255 
256 //======================================================================
257 //                      Read Send-FIFO reg.
258 //======================================================================
PXIi_GetFromFifo(u32 * data_buf)259 static inline PXIFifoStatus PXIi_GetFromFifo(u32 *data_buf)
260 {
261 
262     OSIntrMode enabled;
263 
264     if (reg_PXI_FIFO_CNT & REG_PXI_FIFO_CNT_ERR_MASK)
265     {
266         reg_PXI_FIFO_CNT |= (REG_PXI_FIFO_CNT_E_MASK | REG_PXI_FIFO_CNT_ERR_MASK);
267         return PXI_FIFO_FAIL_RECV_ERR;
268     }
269 
270     enabled = OS_DisableInterrupts();
271     if (reg_PXI_FIFO_CNT & REG_PXI_FIFO_CNT_RECV_EMP_MASK)
272     {
273         (void)OS_RestoreInterrupts(enabled);
274         return PXI_FIFO_FAIL_RECV_EMPTY;
275     }
276 
277     *data_buf = reg_PXI_RECV_FIFO;
278     (void)OS_RestoreInterrupts(enabled);
279 
280     return PXI_FIFO_SUCCESS;
281 }
282 
283 
284 //======================================================================
285 //      Interrupt handler called when SEND FIFO empty
286 //======================================================================
PXIi_HandlerSendFifoEmpty(void)287 static void PXIi_HandlerSendFifoEmpty(void)
288 {
289 }
290 
291 //======================================================================
292 //              Interrupt handler called when RECV FIFO not empty
293 //======================================================================
294 #ifdef  SDK_CW_WA_OPT_BLX
295 #pragma     optimization_level  1      // for BLX problem
296 #endif
297 
PXIi_HandlerRecvFifoNotEmpty(void)298 void PXIi_HandlerRecvFifoNotEmpty(void)
299 {
300     PXIFifoMessage fifomsg;
301     PXIFifoStatus ret_code;
302     PXIFifoTag tag;
303 
304     while (1)
305     {
306         ret_code = PXIi_GetFromFifo(&fifomsg.raw);
307 
308         if (ret_code == PXI_FIFO_FAIL_RECV_EMPTY)
309             break;
310         if (ret_code == PXI_FIFO_FAIL_RECV_ERR)
311             continue;
312 
313         tag = (PXIFifoTag)fifomsg.e.tag;
314 
315         if (tag)
316         {
317             if (FifoRecvCallbackTable[tag])
318             {
319                 (FifoRecvCallbackTable[tag]) (tag, fifomsg.e.data, (BOOL)fifomsg.e.err);
320             }
321             else
322             {
323                 if (fifomsg.e.err)     /* reject if ping-pong message */
324                 {
325                 }
326                 else
327                 {
328                     fifomsg.e.err = TRUE;       /* Set error & block send */
329                     (void)PXIi_SetToFifo(fifomsg.raw);
330                 }
331             }
332         }
333         else
334         {
335             /* Extended FIFO command */
336         }
337     }
338 }
339 
340 #ifdef  SDK_CW_WA_OPT_BLX
341 #pragma     optimization_level  4
342 #endif
343