1*de6cc651SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
205b84117SMark Nutter /*
305b84117SMark Nutter * spu_save.c
405b84117SMark Nutter *
505b84117SMark Nutter * (C) Copyright IBM Corp. 2005
605b84117SMark Nutter *
705b84117SMark Nutter * SPU-side context save sequence outlined in
805b84117SMark Nutter * Synergistic Processor Element Book IV
905b84117SMark Nutter *
1005b84117SMark Nutter * Author: Mark Nutter <mnutter@us.ibm.com>
1105b84117SMark Nutter */
1205b84117SMark Nutter
1305b84117SMark Nutter
1405b84117SMark Nutter #ifndef LS_SIZE
1505b84117SMark Nutter #define LS_SIZE 0x40000 /* 256K (in bytes) */
1605b84117SMark Nutter #endif
1705b84117SMark Nutter
1805b84117SMark Nutter typedef unsigned int u32;
1905b84117SMark Nutter typedef unsigned long long u64;
2005b84117SMark Nutter
2105b84117SMark Nutter #include <spu_intrinsics.h>
2205b84117SMark Nutter #include <asm/spu_csa.h>
2305b84117SMark Nutter #include "spu_utils.h"
2405b84117SMark Nutter
save_event_mask(void)2505b84117SMark Nutter static inline void save_event_mask(void)
2605b84117SMark Nutter {
2705b84117SMark Nutter unsigned int offset;
2805b84117SMark Nutter
2905b84117SMark Nutter /* Save, Step 2:
3005b84117SMark Nutter * Read the SPU_RdEventMsk channel and save to the LSCSA.
3105b84117SMark Nutter */
3205b84117SMark Nutter offset = LSCSA_QW_OFFSET(event_mask);
337a896dc5SSebastian Siewior regs_spill[offset].slot[0] = spu_readch(SPU_RdEventMask);
3405b84117SMark Nutter }
3505b84117SMark Nutter
save_tag_mask(void)3605b84117SMark Nutter static inline void save_tag_mask(void)
3705b84117SMark Nutter {
3805b84117SMark Nutter unsigned int offset;
3905b84117SMark Nutter
4005b84117SMark Nutter /* Save, Step 3:
4105b84117SMark Nutter * Read the SPU_RdTagMsk channel and save to the LSCSA.
4205b84117SMark Nutter */
4305b84117SMark Nutter offset = LSCSA_QW_OFFSET(tag_mask);
4405b84117SMark Nutter regs_spill[offset].slot[0] = spu_readch(MFC_RdTagMask);
4505b84117SMark Nutter }
4605b84117SMark Nutter
save_upper_240kb(addr64 lscsa_ea)4705b84117SMark Nutter static inline void save_upper_240kb(addr64 lscsa_ea)
4805b84117SMark Nutter {
4905b84117SMark Nutter unsigned int ls = 16384;
5005b84117SMark Nutter unsigned int list = (unsigned int)&dma_list[0];
5105b84117SMark Nutter unsigned int size = sizeof(dma_list);
5205b84117SMark Nutter unsigned int tag_id = 0;
5305b84117SMark Nutter unsigned int cmd = 0x24; /* PUTL */
5405b84117SMark Nutter
5505b84117SMark Nutter /* Save, Step 7:
5605b84117SMark Nutter * Enqueue the PUTL command (tag 0) to the MFC SPU command
5705b84117SMark Nutter * queue to transfer the remaining 240 kb of LS to CSA.
5805b84117SMark Nutter */
5905b84117SMark Nutter spu_writech(MFC_LSA, ls);
6005b84117SMark Nutter spu_writech(MFC_EAH, lscsa_ea.ui[0]);
6105b84117SMark Nutter spu_writech(MFC_EAL, list);
6205b84117SMark Nutter spu_writech(MFC_Size, size);
6305b84117SMark Nutter spu_writech(MFC_TagID, tag_id);
6405b84117SMark Nutter spu_writech(MFC_Cmd, cmd);
6505b84117SMark Nutter }
6605b84117SMark Nutter
save_fpcr(void)6705b84117SMark Nutter static inline void save_fpcr(void)
6805b84117SMark Nutter {
6905b84117SMark Nutter // vector unsigned int fpcr;
7005b84117SMark Nutter unsigned int offset;
7105b84117SMark Nutter
7205b84117SMark Nutter /* Save, Step 9:
7305b84117SMark Nutter * Issue the floating-point status and control register
7405b84117SMark Nutter * read instruction, and save to the LSCSA.
7505b84117SMark Nutter */
7605b84117SMark Nutter offset = LSCSA_QW_OFFSET(fpcr);
7705b84117SMark Nutter regs_spill[offset].v = spu_mffpscr();
7805b84117SMark Nutter }
7905b84117SMark Nutter
save_decr(void)8005b84117SMark Nutter static inline void save_decr(void)
8105b84117SMark Nutter {
8205b84117SMark Nutter unsigned int offset;
8305b84117SMark Nutter
8405b84117SMark Nutter /* Save, Step 10:
8505b84117SMark Nutter * Read and save the SPU_RdDec channel data to
8605b84117SMark Nutter * the LSCSA.
8705b84117SMark Nutter */
8805b84117SMark Nutter offset = LSCSA_QW_OFFSET(decr);
8905b84117SMark Nutter regs_spill[offset].slot[0] = spu_readch(SPU_RdDec);
9005b84117SMark Nutter }
9105b84117SMark Nutter
save_srr0(void)9205b84117SMark Nutter static inline void save_srr0(void)
9305b84117SMark Nutter {
9405b84117SMark Nutter unsigned int offset;
9505b84117SMark Nutter
9605b84117SMark Nutter /* Save, Step 11:
9705b84117SMark Nutter * Read and save the SPU_WSRR0 channel data to
9805b84117SMark Nutter * the LSCSA.
9905b84117SMark Nutter */
10005b84117SMark Nutter offset = LSCSA_QW_OFFSET(srr0);
10105b84117SMark Nutter regs_spill[offset].slot[0] = spu_readch(SPU_RdSRR0);
10205b84117SMark Nutter }
10305b84117SMark Nutter
spill_regs_to_mem(addr64 lscsa_ea)10405b84117SMark Nutter static inline void spill_regs_to_mem(addr64 lscsa_ea)
10505b84117SMark Nutter {
10605b84117SMark Nutter unsigned int ls = (unsigned int)®s_spill[0];
10705b84117SMark Nutter unsigned int size = sizeof(regs_spill);
10805b84117SMark Nutter unsigned int tag_id = 0;
10905b84117SMark Nutter unsigned int cmd = 0x20; /* PUT */
11005b84117SMark Nutter
11105b84117SMark Nutter /* Save, Step 13:
11205b84117SMark Nutter * Enqueue a PUT command (tag 0) to send the LSCSA
11305b84117SMark Nutter * to the CSA.
11405b84117SMark Nutter */
11505b84117SMark Nutter spu_writech(MFC_LSA, ls);
11605b84117SMark Nutter spu_writech(MFC_EAH, lscsa_ea.ui[0]);
11705b84117SMark Nutter spu_writech(MFC_EAL, lscsa_ea.ui[1]);
11805b84117SMark Nutter spu_writech(MFC_Size, size);
11905b84117SMark Nutter spu_writech(MFC_TagID, tag_id);
12005b84117SMark Nutter spu_writech(MFC_Cmd, cmd);
12105b84117SMark Nutter }
12205b84117SMark Nutter
enqueue_sync(addr64 lscsa_ea)12305b84117SMark Nutter static inline void enqueue_sync(addr64 lscsa_ea)
12405b84117SMark Nutter {
12505b84117SMark Nutter unsigned int tag_id = 0;
12605b84117SMark Nutter unsigned int cmd = 0xCC;
12705b84117SMark Nutter
12805b84117SMark Nutter /* Save, Step 14:
12905b84117SMark Nutter * Enqueue an MFC_SYNC command (tag 0).
13005b84117SMark Nutter */
13105b84117SMark Nutter spu_writech(MFC_TagID, tag_id);
13205b84117SMark Nutter spu_writech(MFC_Cmd, cmd);
13305b84117SMark Nutter }
13405b84117SMark Nutter
save_complete(void)13505b84117SMark Nutter static inline void save_complete(void)
13605b84117SMark Nutter {
13705b84117SMark Nutter /* Save, Step 18:
13805b84117SMark Nutter * Issue a stop-and-signal instruction indicating
13905b84117SMark Nutter * "save complete". Note: This function will not
14005b84117SMark Nutter * return!!
14105b84117SMark Nutter */
14205b84117SMark Nutter spu_stop(SPU_SAVE_COMPLETE);
14305b84117SMark Nutter }
14405b84117SMark Nutter
14505b84117SMark Nutter /**
14605b84117SMark Nutter * main - entry point for SPU-side context save.
14705b84117SMark Nutter *
14805b84117SMark Nutter * This code deviates from the documented sequence as follows:
14905b84117SMark Nutter *
15005b84117SMark Nutter * 1. The EA for LSCSA is passed from PPE in the
15105b84117SMark Nutter * signal notification channels.
15205b84117SMark Nutter * 2. All 128 registers are saved by crt0.o.
15305b84117SMark Nutter */
main()15405b84117SMark Nutter int main()
15505b84117SMark Nutter {
15605b84117SMark Nutter addr64 lscsa_ea;
15705b84117SMark Nutter
15805b84117SMark Nutter lscsa_ea.ui[0] = spu_readch(SPU_RdSigNotify1);
15905b84117SMark Nutter lscsa_ea.ui[1] = spu_readch(SPU_RdSigNotify2);
16005b84117SMark Nutter
16105b84117SMark Nutter /* Step 1: done by exit(). */
16205b84117SMark Nutter save_event_mask(); /* Step 2. */
16305b84117SMark Nutter save_tag_mask(); /* Step 3. */
16405b84117SMark Nutter set_event_mask(); /* Step 4. */
16505b84117SMark Nutter set_tag_mask(); /* Step 5. */
16605b84117SMark Nutter build_dma_list(lscsa_ea); /* Step 6. */
16705b84117SMark Nutter save_upper_240kb(lscsa_ea); /* Step 7. */
16805b84117SMark Nutter /* Step 8: done by exit(). */
16905b84117SMark Nutter save_fpcr(); /* Step 9. */
17005b84117SMark Nutter save_decr(); /* Step 10. */
17105b84117SMark Nutter save_srr0(); /* Step 11. */
17205b84117SMark Nutter enqueue_putllc(lscsa_ea); /* Step 12. */
17305b84117SMark Nutter spill_regs_to_mem(lscsa_ea); /* Step 13. */
17405b84117SMark Nutter enqueue_sync(lscsa_ea); /* Step 14. */
17505b84117SMark Nutter set_tag_update(); /* Step 15. */
17605b84117SMark Nutter read_tag_status(); /* Step 16. */
17705b84117SMark Nutter read_llar_status(); /* Step 17. */
17805b84117SMark Nutter save_complete(); /* Step 18. */
17905b84117SMark Nutter
18005b84117SMark Nutter return 0;
18105b84117SMark Nutter }
182