• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 HPMicro
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #include "hpm_ffa_drv.h"
9 #include <assert.h>
10 
11 #define FFA_ERROR_MASKS (FFA_STATUS_FIR_OV_MASK | FFA_STATUS_FFT_OV_MASK | FFA_STATUS_WR_ERR_MASK | FFA_STATUS_RD_NXT_ERR_MASK | FFA_STATUS_RD_ERR_MASK)
12 
13 static bool is_point_num_valid(uint16_t num_point);
14 static uint32_t get_fft_misc_reg_fft_len(uint16_t num_point);
15 static hpm_stat_t get_fft_error_kind(uint32_t ffa_status);
16 
is_point_num_valid(uint16_t num_point)17 static bool is_point_num_valid(uint16_t num_point)
18 {
19     return ((num_point & (num_point - 1U)) == 0U) && (num_point >= 8U);
20 }
21 
get_fft_misc_reg_fft_len(uint16_t num_point)22 static uint32_t get_fft_misc_reg_fft_len(uint16_t num_point)
23 {
24     uint32_t count = 0U;
25     num_point /= 8;
26     while (num_point > 0) {
27         count++;
28         num_point >>= 1U;
29     }
30 
31     return (count - 1U);
32 }
33 
ffa_start_fft(FFA_Type * ptr,fft_xfer_t * fft_xfer)34 void ffa_start_fft(FFA_Type *ptr, fft_xfer_t *fft_xfer)
35 {
36 
37     assert((ptr != NULL) && (fft_xfer != NULL) && is_point_num_valid(fft_xfer->num_points));
38 
39     ffa_disable(ptr);
40 
41     ffa_enable_interrupt(ptr, fft_xfer->interrupt_mask);
42 
43     ptr->OP_CTRL = FFA_OP_CTRL_EN_MASK;
44 
45     uint32_t op_cmd = FFA_OP_CMD_CMD_SET(FFA_OPCMD_FFT) | FFA_OP_CMD_IND_TYPE_SET(fft_xfer->src_data_type) |
46         FFA_OP_CMD_OUTD_TYPE_SET(fft_xfer->dst_data_type);
47     ptr->OP_CMD = op_cmd;
48 
49     uint32_t fft_len = get_fft_misc_reg_fft_len(fft_xfer->num_points);
50     uint32_t fft_misc =
51         FFA_OP_FFT_MISC_FFT_LEN_SET(fft_len) | FFA_OP_FFT_MISC_TMP_BLK_SET(1) | FFA_OP_FFT_MISC_IND_BLK_SET(0);
52     if (fft_xfer->is_ifft) {
53         fft_misc |= FFA_OP_FFT_MISC_IFFT_MASK;
54     }
55     ptr->OP_REG0 = fft_misc;
56 
57     ptr->OP_REG1 = 0;
58     ptr->OP_REG2 = (uint32_t) fft_xfer->src;
59     ptr->OP_REG4 = (uint32_t) fft_xfer->dst;
60 
61     ffa_enable(ptr);
62 }
63 
ffa_start_fir(FFA_Type * ptr,fir_xfer_t * fir_xfer)64 void ffa_start_fir(FFA_Type *ptr, fir_xfer_t *fir_xfer)
65 {
66     assert((ptr != NULL) && (fir_xfer != NULL));
67 
68     ffa_disable(ptr);
69 
70     ffa_enable_interrupt(ptr, fir_xfer->interrupt_mask);
71 
72     ptr->OP_CTRL = FFA_OP_CTRL_EN_MASK;
73 
74     uint32_t op_cmd = FFA_OP_CMD_CMD_SET(FFA_OPCMD_FIR) | FFA_OP_CMD_IND_TYPE_SET(fir_xfer->data_type) |
75         FFA_OP_CMD_OUTD_TYPE_SET(fir_xfer->data_type) | FFA_OP_CMD_COEF_TYPE_SET(fir_xfer->data_type);
76     ptr->OP_CMD = op_cmd;
77 
78     uint32_t fir_misc = FFA_OP_FIR_MISC_FIR_COEF_TAPS_SET(fir_xfer->coef_taps);
79     ptr->OP_REG0 = fir_misc;
80 
81     uint32_t fir_misc1 = FFA_OP_FIR_MISC1_OUTD_MEM_BLK_SET(0) | FFA_OP_FIR_MISC1_COEF_MEM_BLK_SET(1) |
82         FFA_OP_FIR_MISC1_IND_MEM_BLK_SET(2) | FFA_OP_FIR_MISC1_FIR_DATA_TAPS_SET(fir_xfer->input_taps);
83 
84     ptr->OP_REG1 = fir_misc1;
85     ptr->OP_REG2 = 0xFFFFFFFFUL;
86     ptr->OP_REG3 = (uint32_t) fir_xfer->src;
87     ptr->OP_REG4 = (uint32_t) fir_xfer->coeff;
88     ptr->OP_REG5 = (uint32_t) fir_xfer->dst;
89 
90     ffa_enable(ptr);
91 }
92 
get_fft_error_kind(uint32_t ffa_status)93 static hpm_stat_t get_fft_error_kind(uint32_t ffa_status)
94 {
95     hpm_stat_t status;
96     if (IS_HPM_BITMASK_SET(ffa_status, FFA_ERROR_MASKS)) {
97         if (IS_HPM_BITMASK_SET(ffa_status, FFA_STATUS_FIR_OV_MASK)) {
98             status = status_ffa_fir_overflow;
99         } else if (IS_HPM_BITMASK_SET(ffa_status, FFA_STATUS_FFT_OV_MASK)) {
100             status = status_ffa_fft_overflow;
101         } else if (IS_HPM_BITMASK_SET(ffa_status, FFA_STATUS_WR_ERR_MASK)) {
102             status = status_ffa_write_error;
103         } else if (IS_HPM_BITMASK_SET(ffa_status, FFA_STATUS_RD_NXT_ERR_MASK)) {
104             status = status_ffa_read_next_error;
105         } else {
106             status = status_ffa_read_error;
107         }
108     } else {
109         status = status_success;
110     }
111     return status;
112 }
113 
ffa_calculate_fft_blocking(FFA_Type * ptr,fft_xfer_t * fft_xfer)114 hpm_stat_t ffa_calculate_fft_blocking(FFA_Type *ptr, fft_xfer_t *fft_xfer)
115 {
116     hpm_stat_t status = status_invalid_argument;
117     do {
118         HPM_BREAK_IF((ptr == NULL) || (fft_xfer == NULL) || !is_point_num_valid(fft_xfer->num_points));
119 
120         fft_xfer->interrupt_mask = 0;
121 
122         ffa_start_fft(ptr, fft_xfer);
123 
124         while (!IS_HPM_BITMASK_SET(ptr->STATUS, FFA_STATUS_OP_CMD_DONE_MASK)) {
125         }
126 
127         uint32_t ffa_status = ptr->STATUS;
128         status = get_fft_error_kind(ffa_status);
129     } while (false);
130 
131     return status;
132 }
133 
ffa_calculate_fir_blocking(FFA_Type * ptr,fir_xfer_t * fir_xfer)134 hpm_stat_t ffa_calculate_fir_blocking(FFA_Type *ptr, fir_xfer_t *fir_xfer)
135 {
136     hpm_stat_t status = status_invalid_argument;
137     do {
138         HPM_BREAK_IF((ptr == NULL) || (fir_xfer == NULL));
139 
140         fir_xfer->interrupt_mask = 0;
141 
142         ffa_start_fir(ptr, fir_xfer);
143 
144         while (!IS_HPM_BITMASK_SET(ptr->STATUS, FFA_STATUS_OP_CMD_DONE_MASK)) {
145         }
146 
147         uint32_t ffa_status = ptr->STATUS;
148         status = get_fft_error_kind(ffa_status);
149     } while (false);
150 
151     return status;
152 }
153