xref: /openbmc/linux/arch/powerpc/platforms/cell/spufs/spu_utils.h (revision 75bf465f0bc33e9b776a46d6a1b9b990f5fb7c37)
1*de6cc651SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-or-later */
205b84117SMark Nutter /*
305b84117SMark Nutter  * utils.h: Utilities for SPU-side of the context switch operation.
405b84117SMark Nutter  *
505b84117SMark Nutter  * (C) Copyright IBM 2005
605b84117SMark Nutter  */
705b84117SMark Nutter 
805b84117SMark Nutter #ifndef _SPU_CONTEXT_UTILS_H_
905b84117SMark Nutter #define _SPU_CONTEXT_UTILS_H_
1005b84117SMark Nutter 
1105b84117SMark Nutter /*
1205b84117SMark Nutter  * 64-bit safe EA.
1305b84117SMark Nutter  */
1405b84117SMark Nutter typedef union {
1505b84117SMark Nutter 	unsigned long long ull;
1605b84117SMark Nutter 	unsigned int ui[2];
1705b84117SMark Nutter } addr64;
1805b84117SMark Nutter 
1905b84117SMark Nutter /*
2005b84117SMark Nutter  * 128-bit register template.
2105b84117SMark Nutter  */
2205b84117SMark Nutter typedef union {
2305b84117SMark Nutter 	unsigned int slot[4];
2405b84117SMark Nutter 	vector unsigned int v;
2505b84117SMark Nutter } spu_reg128v;
2605b84117SMark Nutter 
2705b84117SMark Nutter /*
2805b84117SMark Nutter  * DMA list structure.
2905b84117SMark Nutter  */
3005b84117SMark Nutter struct dma_list_elem {
3105b84117SMark Nutter 	unsigned int size;
3205b84117SMark Nutter 	unsigned int ea_low;
3305b84117SMark Nutter };
3405b84117SMark Nutter 
3505b84117SMark Nutter /*
3605b84117SMark Nutter  * Declare storage for 8-byte aligned DMA list.
3705b84117SMark Nutter  */
3805b84117SMark Nutter struct dma_list_elem dma_list[15] __attribute__ ((aligned(8)));
3905b84117SMark Nutter 
4005b84117SMark Nutter /*
4105b84117SMark Nutter  * External definition for storage
4205b84117SMark Nutter  * declared in crt0.
4305b84117SMark Nutter  */
4405b84117SMark Nutter extern spu_reg128v regs_spill[NR_SPU_SPILL_REGS];
4505b84117SMark Nutter 
4605b84117SMark Nutter /*
4705b84117SMark Nutter  * Compute LSCSA byte offset for a given field.
4805b84117SMark Nutter  */
4905b84117SMark Nutter static struct spu_lscsa *dummy = (struct spu_lscsa *)0;
5005b84117SMark Nutter #define LSCSA_BYTE_OFFSET(_field)  \
5105b84117SMark Nutter 	((char *)(&(dummy->_field)) - (char *)(&(dummy->gprs[0].slot[0])))
5205b84117SMark Nutter #define LSCSA_QW_OFFSET(_field)  (LSCSA_BYTE_OFFSET(_field) >> 4)
5305b84117SMark Nutter 
set_event_mask(void)5405b84117SMark Nutter static inline void set_event_mask(void)
5505b84117SMark Nutter {
5605b84117SMark Nutter 	unsigned int event_mask = 0;
5705b84117SMark Nutter 
5805b84117SMark Nutter 	/* Save, Step 4:
5905b84117SMark Nutter 	 * Restore, Step 1:
6005b84117SMark Nutter 	 *    Set the SPU_RdEventMsk channel to zero to mask
6105b84117SMark Nutter 	 *    all events.
6205b84117SMark Nutter 	 */
6305b84117SMark Nutter 	spu_writech(SPU_WrEventMask, event_mask);
6405b84117SMark Nutter }
6505b84117SMark Nutter 
set_tag_mask(void)6605b84117SMark Nutter static inline void set_tag_mask(void)
6705b84117SMark Nutter {
6805b84117SMark Nutter 	unsigned int tag_mask = 1;
6905b84117SMark Nutter 
7005b84117SMark Nutter 	/* Save, Step 5:
7105b84117SMark Nutter 	 * Restore, Step 2:
7205b84117SMark Nutter 	 *    Set the SPU_WrTagMsk channel to '01' to unmask
7305b84117SMark Nutter 	 *    only tag group 0.
7405b84117SMark Nutter 	 */
7505b84117SMark Nutter 	spu_writech(MFC_WrTagMask, tag_mask);
7605b84117SMark Nutter }
7705b84117SMark Nutter 
build_dma_list(addr64 lscsa_ea)7805b84117SMark Nutter static inline void build_dma_list(addr64 lscsa_ea)
7905b84117SMark Nutter {
8005b84117SMark Nutter 	unsigned int ea_low;
8105b84117SMark Nutter 	int i;
8205b84117SMark Nutter 
8305b84117SMark Nutter 	/* Save, Step 6:
8405b84117SMark Nutter 	 * Restore, Step 3:
8505b84117SMark Nutter 	 *    Update the effective address for the CSA in the
8605b84117SMark Nutter 	 *    pre-canned DMA-list in local storage.
8705b84117SMark Nutter 	 */
8805b84117SMark Nutter 	ea_low = lscsa_ea.ui[1];
8905b84117SMark Nutter 	ea_low += LSCSA_BYTE_OFFSET(ls[16384]);
9005b84117SMark Nutter 
9105b84117SMark Nutter 	for (i = 0; i < 15; i++, ea_low += 16384) {
9205b84117SMark Nutter 		dma_list[i].size = 16384;
9305b84117SMark Nutter 		dma_list[i].ea_low = ea_low;
9405b84117SMark Nutter 	}
9505b84117SMark Nutter }
9605b84117SMark Nutter 
enqueue_putllc(addr64 lscsa_ea)9705b84117SMark Nutter static inline void enqueue_putllc(addr64 lscsa_ea)
9805b84117SMark Nutter {
9905b84117SMark Nutter 	unsigned int ls = 0;
10005b84117SMark Nutter 	unsigned int size = 128;
10105b84117SMark Nutter 	unsigned int tag_id = 0;
10205b84117SMark Nutter 	unsigned int cmd = 0xB4;	/* PUTLLC */
10305b84117SMark Nutter 
10405b84117SMark Nutter 	/* Save, Step 12:
10505b84117SMark Nutter 	 * Restore, Step 7:
10605b84117SMark Nutter 	 *    Send a PUTLLC (tag 0) command to the MFC using
10705b84117SMark Nutter 	 *    an effective address in the CSA in order to
10805b84117SMark Nutter 	 *    remove any possible lock-line reservation.
10905b84117SMark Nutter 	 */
11005b84117SMark Nutter 	spu_writech(MFC_LSA, ls);
11105b84117SMark Nutter 	spu_writech(MFC_EAH, lscsa_ea.ui[0]);
11205b84117SMark Nutter 	spu_writech(MFC_EAL, lscsa_ea.ui[1]);
11305b84117SMark Nutter 	spu_writech(MFC_Size, size);
11405b84117SMark Nutter 	spu_writech(MFC_TagID, tag_id);
11505b84117SMark Nutter 	spu_writech(MFC_Cmd, cmd);
11605b84117SMark Nutter }
11705b84117SMark Nutter 
set_tag_update(void)11805b84117SMark Nutter static inline void set_tag_update(void)
11905b84117SMark Nutter {
12005b84117SMark Nutter 	unsigned int update_any = 1;
12105b84117SMark Nutter 
12205b84117SMark Nutter 	/* Save, Step 15:
12305b84117SMark Nutter 	 * Restore, Step 8:
12405b84117SMark Nutter 	 *    Write the MFC_TagUpdate channel with '01'.
12505b84117SMark Nutter 	 */
12605b84117SMark Nutter 	spu_writech(MFC_WrTagUpdate, update_any);
12705b84117SMark Nutter }
12805b84117SMark Nutter 
read_tag_status(void)12905b84117SMark Nutter static inline void read_tag_status(void)
13005b84117SMark Nutter {
13105b84117SMark Nutter 	/* Save, Step 16:
13205b84117SMark Nutter 	 * Restore, Step 9:
13305b84117SMark Nutter 	 *    Read the MFC_TagStat channel data.
13405b84117SMark Nutter 	 */
13505b84117SMark Nutter 	spu_readch(MFC_RdTagStat);
13605b84117SMark Nutter }
13705b84117SMark Nutter 
read_llar_status(void)13805b84117SMark Nutter static inline void read_llar_status(void)
13905b84117SMark Nutter {
14005b84117SMark Nutter 	/* Save, Step 17:
14105b84117SMark Nutter 	 * Restore, Step 10:
14205b84117SMark Nutter 	 *    Read the MFC_AtomicStat channel data.
14305b84117SMark Nutter 	 */
14405b84117SMark Nutter 	spu_readch(MFC_RdAtomicStat);
14505b84117SMark Nutter }
14605b84117SMark Nutter 
14705b84117SMark Nutter #endif				/* _SPU_CONTEXT_UTILS_H_ */
148