Linux Audio

Check our new training course

Loading...
  1/* SPDX-License-Identifier: GPL-2.0-only */
  2/*
  3 * Copyright (C) 2020 Synopsys, Inc. (www.synopsys.com)
  4 *
  5 * Author: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
  6 */
  7#ifndef __ASM_ARC_DSP_IMPL_H
  8#define __ASM_ARC_DSP_IMPL_H
  9
 10#include <asm/dsp.h>
 11
 12#define DSP_CTRL_DISABLED_ALL		0
 13
 14#ifdef __ASSEMBLY__
 15
 16/* clobbers r5 register */
 17.macro DSP_EARLY_INIT
 18#ifdef CONFIG_ISA_ARCV2
 19	lr	r5, [ARC_AUX_DSP_BUILD]
 20	bmsk	r5, r5, 7
 21	breq    r5, 0, 1f
 22	mov	r5, DSP_CTRL_DISABLED_ALL
 23	sr	r5, [ARC_AUX_DSP_CTRL]
 241:
 25#endif
 26.endm
 27
 28/* clobbers r10, r11 registers pair */
 29.macro DSP_SAVE_REGFILE_IRQ
 30#if defined(CONFIG_ARC_DSP_KERNEL)
 31	/*
 32	 * Drop any changes to DSP_CTRL made by userspace so userspace won't be
 33	 * able to break kernel - reset it to DSP_CTRL_DISABLED_ALL value
 34	 */
 35	mov	r10, DSP_CTRL_DISABLED_ALL
 36	sr	r10, [ARC_AUX_DSP_CTRL]
 37
 38#elif defined(CONFIG_ARC_DSP_SAVE_RESTORE_REGS)
 39	/*
 40	 * Save DSP_CTRL register and reset it to value suitable for kernel
 41	 * (DSP_CTRL_DISABLED_ALL)
 42	 */
 43	mov	r10, DSP_CTRL_DISABLED_ALL
 44	aex	r10, [ARC_AUX_DSP_CTRL]
 45	st	r10, [sp, PT_DSP_CTRL]
 46
 47#endif
 48.endm
 49
 50/* clobbers r10, r11 registers pair */
 51.macro DSP_RESTORE_REGFILE_IRQ
 52#if defined(CONFIG_ARC_DSP_SAVE_RESTORE_REGS)
 53	ld	r10, [sp, PT_DSP_CTRL]
 54	sr	r10, [ARC_AUX_DSP_CTRL]
 55
 56#endif
 57.endm
 58
 59#else /* __ASEMBLY__ */
 60
 61#include <linux/sched.h>
 62#include <asm/asserts.h>
 63#include <asm/switch_to.h>
 64
 65#ifdef CONFIG_ARC_DSP_SAVE_RESTORE_REGS
 66
 67/*
 68 * As we save new and restore old AUX register value in the same place we
 69 * can optimize a bit and use AEX instruction (swap contents of an auxiliary
 70 * register with a core register) instead of LR + SR pair.
 71 */
 72#define AUX_SAVE_RESTORE(_saveto, _readfrom, _offt, _aux)		\
 73do {									\
 74	long unsigned int _scratch;					\
 75									\
 76	__asm__ __volatile__(						\
 77		"ld	%0, [%2, %4]			\n"		\
 78		"aex	%0, [%3]			\n"		\
 79		"st	%0, [%1, %4]			\n"		\
 80		:							\
 81		  "=&r" (_scratch)	/* must be early clobber */	\
 82		:							\
 83		   "r" (_saveto),					\
 84		   "r" (_readfrom),					\
 85		   "Ir" (_aux),						\
 86		   "Ir" (_offt)						\
 87		:							\
 88		  "memory"						\
 89	);								\
 90} while (0)
 91
 92#define DSP_AUX_SAVE_RESTORE(_saveto, _readfrom, _aux)			\
 93	AUX_SAVE_RESTORE(_saveto, _readfrom,				\
 94		offsetof(struct dsp_callee_regs, _aux),			\
 95		ARC_AUX_##_aux)
 96
 97static inline void dsp_save_restore(struct task_struct *prev,
 98					struct task_struct *next)
 99{
100	long unsigned int *saveto = &prev->thread.dsp.ACC0_GLO;
101	long unsigned int *readfrom = &next->thread.dsp.ACC0_GLO;
102
103	DSP_AUX_SAVE_RESTORE(saveto, readfrom, ACC0_GLO);
104	DSP_AUX_SAVE_RESTORE(saveto, readfrom, ACC0_GHI);
105
106	DSP_AUX_SAVE_RESTORE(saveto, readfrom, DSP_BFLY0);
107	DSP_AUX_SAVE_RESTORE(saveto, readfrom, DSP_FFT_CTRL);
108
109#ifdef CONFIG_ARC_DSP_AGU_USERSPACE
110	DSP_AUX_SAVE_RESTORE(saveto, readfrom, AGU_AP0);
111	DSP_AUX_SAVE_RESTORE(saveto, readfrom, AGU_AP1);
112	DSP_AUX_SAVE_RESTORE(saveto, readfrom, AGU_AP2);
113	DSP_AUX_SAVE_RESTORE(saveto, readfrom, AGU_AP3);
114
115	DSP_AUX_SAVE_RESTORE(saveto, readfrom, AGU_OS0);
116	DSP_AUX_SAVE_RESTORE(saveto, readfrom, AGU_OS1);
117
118	DSP_AUX_SAVE_RESTORE(saveto, readfrom, AGU_MOD0);
119	DSP_AUX_SAVE_RESTORE(saveto, readfrom, AGU_MOD1);
120	DSP_AUX_SAVE_RESTORE(saveto, readfrom, AGU_MOD2);
121	DSP_AUX_SAVE_RESTORE(saveto, readfrom, AGU_MOD3);
122#endif /* CONFIG_ARC_DSP_AGU_USERSPACE */
123}
124
125#else /* !CONFIG_ARC_DSP_SAVE_RESTORE_REGS */
126#define dsp_save_restore(p, n)
127#endif /* CONFIG_ARC_DSP_SAVE_RESTORE_REGS */
128
129static inline bool dsp_exist(void)
130{
131	struct bcr_generic bcr;
132
133	READ_BCR(ARC_AUX_DSP_BUILD, bcr);
134	return !!bcr.ver;
135}
136
137static inline bool agu_exist(void)
138{
139	struct bcr_generic bcr;
140
141	READ_BCR(ARC_AUX_AGU_BUILD, bcr);
142	return !!bcr.ver;
143}
144
145static inline void dsp_config_check(void)
146{
147	CHK_OPT_STRICT(CONFIG_ARC_DSP_HANDLED, dsp_exist());
148	CHK_OPT_WEAK(CONFIG_ARC_DSP_AGU_USERSPACE, agu_exist());
149}
150
151#endif /* __ASEMBLY__ */
152#endif /* __ASM_ARC_DSP_IMPL_H */