linux/arch/arc/include/asm/dsp-impl.h
<<
>>
Prefs
   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 */
 153