1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - library - dsp
3   File:     dsp_byteaccess.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-17#$
14   $Rev: 8556 $
15   $Author: okubata_ryoma $
16  *---------------------------------------------------------------------------*/
17 
18 #include <twl.h>
19 #include <twl/dsp.h>
20 #include <twl/dsp/common/byteaccess.h>
21 
22 
23 /*---------------------------------------------------------------------------*/
24 /* Functions */
25 
26 /*---------------------------------------------------------------------------*
27   Name:         DSP_Load16
28 
29   Description:  Reads 16 bits from the DSP data memory space.
30 
31   Arguments:    offset: Transfer source DSP address (in bytes)
32 
33   Returns:      The 16-bit data that was read.
34  *---------------------------------------------------------------------------*/
DSP_Load16(DSPAddrInARM offset)35 u16 DSP_Load16(DSPAddrInARM offset)
36 {
37     OSIntrMode  cpsr = OS_DisableInterrupts();
38     u16     result = DSP_LoadWord(DSP_WORD_TO_DSP(offset));
39     if ((offset & 1) != 0)
40     {
41         result = (u16)((DSP_LoadWord(DSP_WORD_TO_DSP(offset + 2)) << (16 - 8)) | (result >> 8));
42     }
43     (void)OS_RestoreInterrupts(cpsr);
44     return result;
45 }
46 
47 /*---------------------------------------------------------------------------*
48   Name:         DSP_Load32
49 
50   Description:  Reads 32 bits from the DSP data memory space.
51 
52   Arguments:    offset: Transfer source DSP address (in bytes)
53 
54   Returns:      The 32-bit data that was read.
55  *---------------------------------------------------------------------------*/
DSP_Load32(DSPAddrInARM offset)56 u32 DSP_Load32(DSPAddrInARM offset)
57 {
58     u32     result = (u32)((DSP_LoadWord(DSP_WORD_TO_DSP(offset + 0)) << 0) |
59                            (DSP_LoadWord(DSP_WORD_TO_DSP(offset + 2)) << 16));
60     if ((offset & 1) != 0)
61     {
62         result = (u32)((DSP_LoadWord(DSP_WORD_TO_DSP(offset + 4)) << (32 - 8)) | (result >> 8));
63     }
64     return result;
65 }
66 
67 /*---------------------------------------------------------------------------*
68   Name:         DSP_LoadData
69 
70   Description:  Reads an arbitrary length of data from the DSP data memory space.
71 
72   Arguments:    offset: Transfer source DSP address (in bytes)
73                 buffer: Transfer destination buffer
74                 length: Size of the transmission
75 
76   Returns:      None.
77  *---------------------------------------------------------------------------*/
DSP_LoadData(DSPAddrInARM offset,void * buffer,u32 length)78 void DSP_LoadData(DSPAddrInARM offset, void *buffer, u32 length)
79 {
80     if (length > 0)
81     {
82         // First, align leading end of transfer source.
83         if ((offset & 1) != 0)
84         {
85             MI_StoreLE8(buffer, DSP_Load8(offset));
86             buffer = (u8 *)buffer + 1;
87             offset += 1;
88             length -= 1;
89         }
90         // If the buffer is aligned, transmit the word as is; if not aligned, repeat word tranmissions repeatedly, although this is inefficient.
91         //
92         // (This support can be implemented in the DSP_RecvFifo function, right?)
93         if (((u32)buffer & 1) == 0)
94         {
95             u32     aligned = (u32)(length & ~1);
96             if (aligned > 0)
97             {
98                 OSIntrMode  cpsr = OS_DisableInterrupts();
99                 DSP_RecvFifo(DSP_FIFO_MEMSEL_DATA,
100                              (u16*)buffer,
101                              DSP_WORD_TO_DSP(offset),
102                              DSP_WORD_TO_DSP(aligned));
103                 reg_DSP_PCFG &= ~(REG_DSP_PCFG_DRS_MASK | REG_DSP_PCFG_AIM_MASK);
104                 (void)OS_RestoreInterrupts(cpsr);
105                 buffer = (u8 *)buffer + aligned;
106                 offset += aligned;
107                 length -= aligned;
108             }
109         }
110         else
111         {
112             while (length >= 2)
113             {
114                 MI_StoreLE16(buffer, DSP_LoadWord(DSP_WORD_TO_DSP(offset)));
115                 buffer = (u8 *)buffer + 2;
116                 offset += 2;
117                 length -= 2;
118             }
119         }
120         // If necessary, load the end
121         if (length > 0)
122         {
123             MI_StoreLE8(buffer, DSP_Load8(offset));
124         }
125     }
126 }
127 
128 /*---------------------------------------------------------------------------*
129   Name:         DSP_Store8
130 
131   Description:  Writes 8 bits to the DSP data memory space.
132 
133   Arguments:    offset: Transfer source DSP address (in bytes)
134                 value: The 8-bit value to write
135 
136   Returns:      None.
137  *---------------------------------------------------------------------------*/
DSP_Store8(DSPAddrInARM offset,u8 value)138 void DSP_Store8(DSPAddrInARM offset, u8 value)
139 {
140     if ((offset & 1) == 0)
141     {
142         u16     tmp = DSP_LoadWord(DSP_WORD_TO_DSP(offset));
143         tmp = (u16)((tmp & 0xFF00) | ((value << 0) & 0x00FF));
144         DSP_StoreWord(DSP_WORD_TO_DSP(offset), tmp);
145     }
146     else
147     {
148         u16     tmp = DSP_LoadWord(DSP_WORD_TO_DSP(offset));
149         tmp = (u16)((tmp & 0x00FF) | ((value << 8) & 0xFF00));
150         DSP_StoreWord(DSP_WORD_TO_DSP(offset), tmp);
151     }
152 }
153 
154 /*---------------------------------------------------------------------------*
155   Name:         DSP_Store16
156 
157   Description:  Writes 16 bits to the DSP data memory space.
158 
159   Arguments:    offset: Transfer source DSP address (in bytes)
160                 value: The 16-bit value to write
161 
162   Returns:      None.
163  *---------------------------------------------------------------------------*/
DSP_Store16(DSPAddrInARM offset,u16 value)164 void DSP_Store16(DSPAddrInARM offset, u16 value)
165 {
166     if ((offset & 1) == 0)
167     {
168         DSP_StoreWord(DSP_WORD_TO_DSP(offset), value);
169     }
170     else
171     {
172         DSP_Store8(offset + 0, (u8)(value >> 0));
173         DSP_Store8(offset + 1, (u8)(value >> 8));
174     }
175 }
176 
177 /*---------------------------------------------------------------------------*
178   Name:         DSP_Store32
179 
180   Description:  Writes 32 bits to the DSP data memory space.
181 
182   Arguments:    offset: Transfer source DSP address (in bytes)
183                 value: The 32-bit value to write
184 
185   Returns:      None.
186  *---------------------------------------------------------------------------*/
DSP_Store32(DSPAddrInARM offset,u32 value)187 void DSP_Store32(DSPAddrInARM offset, u32 value)
188 {
189     if ((offset & 1) == 0)
190     {
191         DSP_StoreWord(DSP_WORD_TO_DSP(offset + 0), (u16)(value >> 0));
192         DSP_StoreWord(DSP_WORD_TO_DSP(offset + 2), (u16)(value >> 16));
193     }
194     else
195     {
196         DSP_Store8(offset + 0, (u8)(value >> 0));
197         DSP_StoreWord(DSP_WORD_TO_DSP(offset + 1), (u16)(value >> 8));
198         DSP_Store8(offset + 3, (u8)(value >> 24));
199     }
200 }
201 
202 /*---------------------------------------------------------------------------*
203   Name:         DSP_StoreData
204 
205   Description:  Writes arbitrary length data to the DSP data memory space.
206 
207   Arguments:    offset: Transfer source DSP address (in bytes)
208                 buffer: Transfer source buffer
209                 length: Size of the transmission
210 
211   Returns:      None.
212  *---------------------------------------------------------------------------*/
DSP_StoreData(DSPAddrInARM offset,const void * buffer,u32 length)213 void DSP_StoreData(DSPAddrInARM offset, const void *buffer, u32 length)
214 {
215     if (length > 0)
216     {
217         // First, align leading end of transfer destination
218         if ((offset & 1) != 0)
219         {
220             DSP_Store8(offset, MI_LoadLE8(buffer));
221             buffer = (const u8 *)buffer + 1;
222             offset += 1;
223             length -= 1;
224         }
225         // If the buffer is aligned, transmit the word as is; if not aligned, repeat word tranmissions repeatedly, although this is inefficient.
226         //
227         // (This support can be implemented in the DSP_SendFifo function, right?)
228         if (((u32)buffer & 1) == 0)
229         {
230             u32     aligned = (u32)(length & ~1);
231             if (aligned > 0)
232             {
233                 OSIntrMode  cpsr = OS_DisableInterrupts();
234                 DSP_SendFifo(DSP_FIFO_MEMSEL_DATA,
235                              DSP_WORD_TO_DSP(offset),
236                              (const u16 *)buffer,
237                              DSP_WORD_TO_DSP(aligned));
238             //    reg_DSP_PCFG &= ~(REG_DSP_PCFG_DRS_MASK | REG_DSP_PCFG_AIM_MASK);
239                 (void)OS_RestoreInterrupts(cpsr);
240                 buffer = (const u8 *)buffer + aligned;
241                 offset += aligned;
242                 length -= aligned;
243             }
244         }
245         else
246         {
247             while (length >= 2)
248             {
249                 DSP_StoreWord(DSP_WORD_TO_DSP(offset), MI_LoadLE16(buffer));
250                 buffer = (const u8 *)buffer + 2;
251                 offset += 2;
252                 length -= 2;
253             }
254         }
255         // If necessary, write the end
256         if (length > 0)
257         {
258             DSP_Store8(offset, MI_LoadLE8(buffer));
259         }
260     }
261 }
262