First Support on Ginger and OMAP TI
[linux-ginger.git] / arch / powerpc / platforms / cell / spufs / spu_save.c
blobae95cc1701e9f8236cdd5ede575742f2ff22435c
1 /*
2 * spu_save.c
4 * (C) Copyright IBM Corp. 2005
6 * SPU-side context save sequence outlined in
7 * Synergistic Processor Element Book IV
9 * Author: Mark Nutter <mnutter@us.ibm.com>
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2, or (at your option)
14 * any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 #ifndef LS_SIZE
29 #define LS_SIZE 0x40000 /* 256K (in bytes) */
30 #endif
32 typedef unsigned int u32;
33 typedef unsigned long long u64;
35 #include <spu_intrinsics.h>
36 #include <asm/spu_csa.h>
37 #include "spu_utils.h"
39 static inline void save_event_mask(void)
41 unsigned int offset;
43 /* Save, Step 2:
44 * Read the SPU_RdEventMsk channel and save to the LSCSA.
46 offset = LSCSA_QW_OFFSET(event_mask);
47 regs_spill[offset].slot[0] = spu_readch(SPU_RdEventMask);
50 static inline void save_tag_mask(void)
52 unsigned int offset;
54 /* Save, Step 3:
55 * Read the SPU_RdTagMsk channel and save to the LSCSA.
57 offset = LSCSA_QW_OFFSET(tag_mask);
58 regs_spill[offset].slot[0] = spu_readch(MFC_RdTagMask);
61 static inline void save_upper_240kb(addr64 lscsa_ea)
63 unsigned int ls = 16384;
64 unsigned int list = (unsigned int)&dma_list[0];
65 unsigned int size = sizeof(dma_list);
66 unsigned int tag_id = 0;
67 unsigned int cmd = 0x24; /* PUTL */
69 /* Save, Step 7:
70 * Enqueue the PUTL command (tag 0) to the MFC SPU command
71 * queue to transfer the remaining 240 kb of LS to CSA.
73 spu_writech(MFC_LSA, ls);
74 spu_writech(MFC_EAH, lscsa_ea.ui[0]);
75 spu_writech(MFC_EAL, list);
76 spu_writech(MFC_Size, size);
77 spu_writech(MFC_TagID, tag_id);
78 spu_writech(MFC_Cmd, cmd);
81 static inline void save_fpcr(void)
83 // vector unsigned int fpcr;
84 unsigned int offset;
86 /* Save, Step 9:
87 * Issue the floating-point status and control register
88 * read instruction, and save to the LSCSA.
90 offset = LSCSA_QW_OFFSET(fpcr);
91 regs_spill[offset].v = spu_mffpscr();
94 static inline void save_decr(void)
96 unsigned int offset;
98 /* Save, Step 10:
99 * Read and save the SPU_RdDec channel data to
100 * the LSCSA.
102 offset = LSCSA_QW_OFFSET(decr);
103 regs_spill[offset].slot[0] = spu_readch(SPU_RdDec);
106 static inline void save_srr0(void)
108 unsigned int offset;
110 /* Save, Step 11:
111 * Read and save the SPU_WSRR0 channel data to
112 * the LSCSA.
114 offset = LSCSA_QW_OFFSET(srr0);
115 regs_spill[offset].slot[0] = spu_readch(SPU_RdSRR0);
118 static inline void spill_regs_to_mem(addr64 lscsa_ea)
120 unsigned int ls = (unsigned int)&regs_spill[0];
121 unsigned int size = sizeof(regs_spill);
122 unsigned int tag_id = 0;
123 unsigned int cmd = 0x20; /* PUT */
125 /* Save, Step 13:
126 * Enqueue a PUT command (tag 0) to send the LSCSA
127 * to the CSA.
129 spu_writech(MFC_LSA, ls);
130 spu_writech(MFC_EAH, lscsa_ea.ui[0]);
131 spu_writech(MFC_EAL, lscsa_ea.ui[1]);
132 spu_writech(MFC_Size, size);
133 spu_writech(MFC_TagID, tag_id);
134 spu_writech(MFC_Cmd, cmd);
137 static inline void enqueue_sync(addr64 lscsa_ea)
139 unsigned int tag_id = 0;
140 unsigned int cmd = 0xCC;
142 /* Save, Step 14:
143 * Enqueue an MFC_SYNC command (tag 0).
145 spu_writech(MFC_TagID, tag_id);
146 spu_writech(MFC_Cmd, cmd);
149 static inline void save_complete(void)
151 /* Save, Step 18:
152 * Issue a stop-and-signal instruction indicating
153 * "save complete". Note: This function will not
154 * return!!
156 spu_stop(SPU_SAVE_COMPLETE);
160 * main - entry point for SPU-side context save.
162 * This code deviates from the documented sequence as follows:
164 * 1. The EA for LSCSA is passed from PPE in the
165 * signal notification channels.
166 * 2. All 128 registers are saved by crt0.o.
168 int main()
170 addr64 lscsa_ea;
172 lscsa_ea.ui[0] = spu_readch(SPU_RdSigNotify1);
173 lscsa_ea.ui[1] = spu_readch(SPU_RdSigNotify2);
175 /* Step 1: done by exit(). */
176 save_event_mask(); /* Step 2. */
177 save_tag_mask(); /* Step 3. */
178 set_event_mask(); /* Step 4. */
179 set_tag_mask(); /* Step 5. */
180 build_dma_list(lscsa_ea); /* Step 6. */
181 save_upper_240kb(lscsa_ea); /* Step 7. */
182 /* Step 8: done by exit(). */
183 save_fpcr(); /* Step 9. */
184 save_decr(); /* Step 10. */
185 save_srr0(); /* Step 11. */
186 enqueue_putllc(lscsa_ea); /* Step 12. */
187 spill_regs_to_mem(lscsa_ea); /* Step 13. */
188 enqueue_sync(lscsa_ea); /* Step 14. */
189 set_tag_update(); /* Step 15. */
190 read_tag_status(); /* Step 16. */
191 read_llar_status(); /* Step 17. */
192 save_complete(); /* Step 18. */
194 return 0;