ARC: add support for DSP-enabled userspace applications
[linux-2.6-microblaze.git] / arch / arc / include / asm / dsp-impl.h
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         lr      r5, [ARC_AUX_DSP_BUILD]
19         bmsk    r5, r5, 7
20         breq    r5, 0, 1f
21         mov     r5, DSP_CTRL_DISABLED_ALL
22         sr      r5, [ARC_AUX_DSP_CTRL]
23 1:
24 .endm
25
26 /* clobbers r10, r11 registers pair */
27 .macro DSP_SAVE_REGFILE_IRQ
28 #if defined(CONFIG_ARC_DSP_KERNEL)
29         /*
30          * Drop any changes to DSP_CTRL made by userspace so userspace won't be
31          * able to break kernel - reset it to DSP_CTRL_DISABLED_ALL value
32          */
33         mov     r10, DSP_CTRL_DISABLED_ALL
34         sr      r10, [ARC_AUX_DSP_CTRL]
35
36 #elif defined(CONFIG_ARC_DSP_SAVE_RESTORE_REGS)
37         /*
38          * Save DSP_CTRL register and reset it to value suitable for kernel
39          * (DSP_CTRL_DISABLED_ALL)
40          */
41         mov     r10, DSP_CTRL_DISABLED_ALL
42         aex     r10, [ARC_AUX_DSP_CTRL]
43         st      r10, [sp, PT_DSP_CTRL]
44
45 #endif
46 .endm
47
48 /* clobbers r10, r11 registers pair */
49 .macro DSP_RESTORE_REGFILE_IRQ
50 #if defined(CONFIG_ARC_DSP_SAVE_RESTORE_REGS)
51         ld      r10, [sp, PT_DSP_CTRL]
52         sr      r10, [ARC_AUX_DSP_CTRL]
53
54 #endif
55 .endm
56
57 #else /* __ASEMBLY__ */
58
59 #include <linux/sched.h>
60 #include <asm/asserts.h>
61 #include <asm/switch_to.h>
62
63 #ifdef CONFIG_ARC_DSP_SAVE_RESTORE_REGS
64
65 /*
66  * As we save new and restore old AUX register value in the same place we
67  * can optimize a bit and use AEX instruction (swap contents of an auxiliary
68  * register with a core register) instead of LR + SR pair.
69  */
70 #define AUX_SAVE_RESTORE(_saveto, _readfrom, _offt, _aux)               \
71 do {                                                                    \
72         long unsigned int _scratch;                                     \
73                                                                         \
74         __asm__ __volatile__(                                           \
75                 "ld     %0, [%2, %4]                    \n"             \
76                 "aex    %0, [%3]                        \n"             \
77                 "st     %0, [%1, %4]                    \n"             \
78                 :                                                       \
79                   "=&r" (_scratch)      /* must be early clobber */     \
80                 :                                                       \
81                    "r" (_saveto),                                       \
82                    "r" (_readfrom),                                     \
83                    "Ir" (_aux),                                         \
84                    "Ir" (_offt)                                         \
85                 :                                                       \
86                   "memory"                                              \
87         );                                                              \
88 } while (0)
89
90 #define DSP_AUX_SAVE_RESTORE(_saveto, _readfrom, _aux)                  \
91         AUX_SAVE_RESTORE(_saveto, _readfrom,                            \
92                 offsetof(struct dsp_callee_regs, _aux),                 \
93                 ARC_AUX_##_aux)
94
95 static inline void dsp_save_restore(struct task_struct *prev,
96                                         struct task_struct *next)
97 {
98         long unsigned int *saveto = &prev->thread.dsp.ACC0_GLO;
99         long unsigned int *readfrom = &next->thread.dsp.ACC0_GLO;
100
101         DSP_AUX_SAVE_RESTORE(saveto, readfrom, ACC0_GLO);
102         DSP_AUX_SAVE_RESTORE(saveto, readfrom, ACC0_GHI);
103
104         DSP_AUX_SAVE_RESTORE(saveto, readfrom, DSP_BFLY0);
105         DSP_AUX_SAVE_RESTORE(saveto, readfrom, DSP_FFT_CTRL);
106 }
107
108 #else /* !CONFIG_ARC_DSP_SAVE_RESTORE_REGS */
109 #define dsp_save_restore(p, n)
110 #endif /* CONFIG_ARC_DSP_SAVE_RESTORE_REGS */
111
112 static inline bool dsp_exist(void)
113 {
114         struct bcr_generic bcr;
115
116         READ_BCR(ARC_AUX_DSP_BUILD, bcr);
117         return !!bcr.ver;
118 }
119
120 static inline void dsp_config_check(void)
121 {
122         CHK_OPT_STRICT(CONFIG_ARC_DSP_HANDLED, dsp_exist());
123 }
124
125 #endif /* __ASEMBLY__ */
126 #endif /* __ASM_ARC_DSP_IMPL_H */