1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - RTC - libraries
3   File:     external_ex.c
4 
5   Copyright 2007-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 
18 #include    <nitro/os.h>
19 #include    <nitro/rtc.h>
20 #include    <twl/rtc/common/type_ex.h>
21 #include    <twl/rtc/ARM9/api_ex.h>
22 #include    "private.h"
23 
24 /*---------------------------------------------------------------------------*
25     Internal Function Definitions
26  *---------------------------------------------------------------------------*/
27 static void     RtcexGetResultCallback(RTCResult result, void* arg);
28 static void     RtcexWaitBusy(u32* lock);
29 
30 /*---------------------------------------------------------------------------*
31   Name:         RTCEXi_GetCounterAsync
32 
33   Description:  Asynchronously reads the Up Counter value from the RTC.
34 
35   Arguments:    count: Specifies the buffer to store the Up Counter value.
36                 callback: Specifies the function to be called when the asynchronous process is completed.
37                 arg: Specifies the argument used when calling the callback function.
38 
39   Returns:      RTCResult: Returns the result of the process that starts the asynchronous device operation.
40  *---------------------------------------------------------------------------*/
41 RTCResult
RTCEXi_GetCounterAsync(u32 * count,RTCCallback callback,void * arg)42 RTCEXi_GetCounterAsync(u32* count, RTCCallback callback, void* arg)
43 {
44     OSIntrMode  enabled;
45     RTCWork*    w   =   RTCi_GetSysWork();
46 
47     SDK_NULL_ASSERT(count);
48     SDK_NULL_ASSERT(callback);
49 
50     /* Check lock */
51     enabled =   OS_DisableInterrupts();
52     if (w->lock != RTC_LOCK_OFF)
53     {
54         (void)OS_RestoreInterrupts(enabled);
55         return RTC_RESULT_BUSY;
56     }
57     w->lock =   RTC_LOCK_ON;
58     (void)OS_RestoreInterrupts(enabled);
59 
60     /* Send the Up Counter read command */
61     w->sequence =   RTC_SEQ_GET_COUNTER;
62     w->index    =   0;
63     w->buffer[0]    =   (void*)count;
64     w->callback =   callback;
65     w->callbackArg  =   arg;
66     if (RTCEXi_ReadRawCounterAsync() == TRUE)
67     {
68         return RTC_RESULT_SUCCESS;
69     }
70     else
71     {
72         w->lock =   RTC_LOCK_OFF;
73         return RTC_RESULT_SEND_ERROR;
74     }
75 }
76 
77 /*---------------------------------------------------------------------------*
78   Name:         RTCEXi_GetCounter
79 
80   Description:  Reads the Up Counter value from the RTC.
81 
82   Arguments:    count: Specifies the buffer to store the Up Counter value.
83 
84   Returns:      RTCResult: Returns the device operation processing result.
85  *---------------------------------------------------------------------------*/
86 RTCResult
RTCEXi_GetCounter(u32 * count)87 RTCEXi_GetCounter(u32* count)
88 {
89     RTCWork*    w   =   RTCi_GetSysWork();
90 
91     w->commonResult =   RTCEXi_GetCounterAsync(count, RtcexGetResultCallback, NULL);
92     if (w->commonResult == RTC_RESULT_SUCCESS)
93     {
94         RtcexWaitBusy(&(w->lock));
95     }
96     return w->commonResult;
97 }
98 
99 /*---------------------------------------------------------------------------*
100   Name:         RTCEXi_GetFoutAsync
101 
102   Description:  Asynchronously reads FOUT setting values from the RTC.
103 
104   Arguments:    fout: Specifies a buffer for storing FOUT setting values.
105                 callback: Specifies the function to be called when the asynchronous process is completed.
106                 arg: Specifies the argument used when calling the callback function.
107 
108   Returns:      RTCResult: Returns the result of the process that starts the asynchronous device operation.
109  *---------------------------------------------------------------------------*/
110 RTCResult
RTCEXi_GetFoutAsync(u16 * fout,RTCCallback callback,void * arg)111 RTCEXi_GetFoutAsync(u16* fout, RTCCallback callback, void* arg)
112 {
113     OSIntrMode  enabled;
114     RTCWork*    w   =   RTCi_GetSysWork();
115 
116     SDK_NULL_ASSERT(fout);
117     SDK_NULL_ASSERT(callback);
118 
119     /* Check lock */
120     enabled =   OS_DisableInterrupts();
121     if (w->lock != RTC_LOCK_OFF)
122     {
123         (void)OS_RestoreInterrupts(enabled);
124         return RTC_RESULT_BUSY;
125     }
126     w->lock =   RTC_LOCK_ON;
127     (void)OS_RestoreInterrupts(enabled);
128 
129     /* Send the FOUT setting value read command */
130     w->sequence =   RTC_SEQ_GET_FOUT;
131     w->index    =   0;
132     w->buffer[0]    =   (void*)fout;
133     w->callback =   callback;
134     w->callbackArg  =   arg;
135     if (RTCEXi_ReadRawFoutAsync() == TRUE)
136     {
137         return RTC_RESULT_SUCCESS;
138     }
139     else
140     {
141         w->lock =   RTC_LOCK_OFF;
142         return RTC_RESULT_SEND_ERROR;
143     }
144 }
145 
146 /*---------------------------------------------------------------------------*
147   Name:         RTCEXi_GetFout
148 
149   Description:  Asynchronously reads FOUT setting values from the RTC.
150 
151   Arguments:    fout: Specifies a buffer for storing FOUT setting values.
152 
153   Returns:      RTCResult: Returns the device operation processing result.
154  *---------------------------------------------------------------------------*/
155 RTCResult
RTCEXi_GetFout(u16 * fout)156 RTCEXi_GetFout(u16* fout)
157 {
158     RTCWork*    w   =   RTCi_GetSysWork();
159 
160     w->commonResult =   RTCEXi_GetFoutAsync(fout, RtcexGetResultCallback, NULL);
161     if (w->commonResult == RTC_RESULT_SUCCESS)
162     {
163         RtcexWaitBusy(&(w->lock));
164     }
165     return w->commonResult;
166 }
167 
168 /*---------------------------------------------------------------------------*
169   Name:         RTCEXi_SetFoutAsync
170 
171   Description:  Asynchronously writes FOUT settings to the RTC.
172 
173   Arguments:    fout: Specifies the buffer storing FOUT setting values.
174                 callback: Specifies the function to be called when the asynchronous process is completed.
175                 arg: Specifies the argument used when calling the callback function.
176 
177   Returns:      RTCResult: Returns the result of the process that starts the asynchronous device operation.
178  *---------------------------------------------------------------------------*/
179 RTCResult
RTCEXi_SetFoutAsync(const u16 * fout,RTCCallback callback,void * arg)180 RTCEXi_SetFoutAsync(const u16* fout, RTCCallback callback, void* arg)
181 {
182     OSIntrMode  enabled;
183     RTCWork*    w   =   RTCi_GetSysWork();
184 
185     SDK_NULL_ASSERT(fout);
186     SDK_NULL_ASSERT(callback);
187 
188     /* Check lock */
189     enabled =   OS_DisableInterrupts();
190     if (w->lock != RTC_LOCK_OFF)
191     {
192         (void)OS_RestoreInterrupts(enabled);
193         return RTC_RESULT_BUSY;
194     }
195     w->lock =   RTC_LOCK_ON;
196     (void)OS_RestoreInterrupts(enabled);
197 
198     /* Edit the data to set. */
199     ((RTCRawDataEx*)(OS_GetSystemWork()->real_time_clock))->a.fout.fout =   *fout;
200 
201     /* Send the FOUT setting value write command */
202     w->sequence =   RTC_SEQ_SET_FOUT;
203     w->index    =   0;
204     w->callback =   callback;
205     w->callbackArg  =   arg;
206     if (RTCEXi_WriteRawFoutAsync() == TRUE)
207     {
208         return RTC_RESULT_SUCCESS;
209     }
210     else
211     {
212         w->lock =   RTC_LOCK_OFF;
213         return RTC_RESULT_SEND_ERROR;
214     }
215 }
216 
217 /*---------------------------------------------------------------------------*
218   Name:         RTCEXi_SetFout
219 
220   Description:  Writes FOUT settings values to the RTC.
221 
222   Arguments:    fout: Specifies the buffer storing FOUT setting values.
223 
224   Returns:      RTCResult: Returns the device operation processing result.
225  *---------------------------------------------------------------------------*/
226 RTCResult
RTCEXi_SetFout(const u16 * fout)227 RTCEXi_SetFout(const u16* fout)
228 {
229     RTCWork*    w   =   RTCi_GetSysWork();
230 
231     w->commonResult =   RTCEXi_SetFoutAsync(fout, RtcexGetResultCallback, NULL);
232     if (w->commonResult == RTC_RESULT_SUCCESS)
233     {
234         RtcexWaitBusy(&(w->lock));
235     }
236     return w->commonResult;
237 }
238 
239 /*---------------------------------------------------------------------------*
240   Name:         RTCEXi_CommonCallback
241 
242   Description:  Shared callback function corresponding to additional commands used by asynchronous RTC functions.
243 
244   Arguments:    tag:   PXI tag that shows the message type.
245                 data:  Message from ARM7.
246                 err:   PXI transfer error flag.
247 
248   Returns:      RTCResult: Returns the asynchronous device operation processing result.
249  *---------------------------------------------------------------------------*/
250 RTCResult
RTCEXi_CommonCallback(void)251 RTCEXi_CommonCallback(void)
252 {
253     RTCWork*    w   =   RTCi_GetSysWork();
254     RTCResult   result  =   RTC_RESULT_SUCCESS;
255 
256     /* Various types of postprocessing according to the internal status  */
257     switch(w->sequence)
258     {
259     /* Sequence to get the Up Counter value  */
260     case RTC_SEQ_GET_COUNTER:
261         {
262             u32*    pDst    =   (u32*)(w->buffer[0]);
263             RTCRawCounter*  pSrc    =
264                 &(((RTCRawDataEx*)(OS_GetSystemWork()->real_time_clock))->a.counter);
265             /* Change the endianness */
266             *pDst   =   (u32)(pSrc->bytes[0] | (pSrc->bytes[1] << 8) | (pSrc->bytes[2] << 16));
267         }
268         break;
269     /* Sequence to get the FOUT setting value */
270     case RTC_SEQ_GET_FOUT:
271         {
272             u16*    pDst    =   (u16*)(w->buffer[0]);
273             RTCRawFout* pSrc    =
274                 &(((RTCRawDataEx*)(OS_GetSystemWork()->real_time_clock))->a.fout);
275             *pDst   =   (u16)(pSrc->fout);
276         }
277         break;
278     /* Sequence to change the FOUT setting value  */
279     case RTC_SEQ_SET_FOUT:
280         /* No processing in particular. */
281         break;
282     default:
283         /* Other unknown sequences  */
284         w->index    =   0;
285         result  =   RTC_RESULT_INVALID_COMMAND;
286     }
287     return result;
288 }
289 
290 /*---------------------------------------------------------------------------*
291   Name:         RtcexGetResultCallback
292 
293   Description:  Called when asynchronous processing completes. Updates the processing results of internal variables.
294 
295   Arguments:    result: The processing results from the asynchronous function.
296                 arg: Not used.
297 
298   Returns:      None.
299  *---------------------------------------------------------------------------*/
300 static void
RtcexGetResultCallback(RTCResult result,void * arg)301 RtcexGetResultCallback(RTCResult result, void* arg)
302 {
303 #pragma unused(arg)
304 
305     RTCi_GetSysWork()->commonResult =   result;
306 }
307 
308 #include    <nitro/code32.h>
309 /*---------------------------------------------------------------------------*
310   Name:         RtcWaitBusy
311 
312   Description:  Wait while the RTC's asynchronous processing is locked.
313 
314   Arguments:    r0: Pointer to the lock control member in the library's shared work buffer.
315 
316   Returns:      None.
317  *---------------------------------------------------------------------------*/
318 static asm void
RtcexWaitBusy(u32 * lock)319 RtcexWaitBusy(u32* lock)
320 {
321 loop:
322     ldr     r1, [r0]
323     cmp     r1, #RTC_LOCK_ON
324     beq     loop
325     bx      lr
326 }
327 #include    <nitro/codereset.h>
328