]>
Commit | Line | Data |
---|---|---|
4827d0cf EP |
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 | ||
7321e2ea EP |
10 | #include <asm/dsp.h> |
11 | ||
4827d0cf EP |
12 | #define DSP_CTRL_DISABLED_ALL 0 |
13 | ||
14 | #ifdef __ASSEMBLY__ | |
15 | ||
16 | /* clobbers r5 register */ | |
17 | .macro DSP_EARLY_INIT | |
40db9367 | 18 | #ifdef CONFIG_ISA_ARCV2 |
4827d0cf EP |
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] | |
24 | 1: | |
40db9367 | 25 | #endif |
4827d0cf EP |
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] | |
7321e2ea EP |
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 | |
4827d0cf EP |
57 | .endm |
58 | ||
59 | #else /* __ASEMBLY__ */ | |
60 | ||
7321e2ea | 61 | #include <linux/sched.h> |
4827d0cf | 62 | #include <asm/asserts.h> |
7321e2ea EP |
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) \ | |
73 | do { \ | |
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 | ||
97 | static 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); | |
f09d3174 EP |
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 */ | |
7321e2ea EP |
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 */ | |
4827d0cf EP |
128 | |
129 | static 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 | ||
f09d3174 EP |
137 | static 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 | ||
4827d0cf EP |
145 | static inline void dsp_config_check(void) |
146 | { | |
147 | CHK_OPT_STRICT(CONFIG_ARC_DSP_HANDLED, dsp_exist()); | |
f09d3174 | 148 | CHK_OPT_WEAK(CONFIG_ARC_DSP_AGU_USERSPACE, agu_exist()); |
4827d0cf EP |
149 | } |
150 | ||
151 | #endif /* __ASEMBLY__ */ | |
152 | #endif /* __ASM_ARC_DSP_IMPL_H */ |