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 #if defined(HPM_IP_FEATURE_FFA_FP32) && HPM_IP_FEATURE_FFA_FP32
81 uint32_t fir_misc1 = FFA_OP_FIR_MISC1_OUTD_MEM_BLK_SET(0) | FFA_OP_FIR_MISC1_COEF_MEM_BLK_SET(0) |
82 FFA_OP_FIR_MISC1_IND_MEM_BLK_SET(1) | FFA_OP_FIR_MISC1_FIR_DATA_TAPS_SET(fir_xfer->input_taps);
83 #else
84 uint32_t fir_misc1 = FFA_OP_FIR_MISC1_OUTD_MEM_BLK_SET(0) | FFA_OP_FIR_MISC1_COEF_MEM_BLK_SET(1) |
85 FFA_OP_FIR_MISC1_IND_MEM_BLK_SET(2) | FFA_OP_FIR_MISC1_FIR_DATA_TAPS_SET(fir_xfer->input_taps);
86 #endif
87
88 ptr->OP_REG1 = fir_misc1;
89 ptr->OP_REG2 = 0xFFFFFFFFUL;
90 ptr->OP_REG3 = (uint32_t) fir_xfer->src;
91 ptr->OP_REG4 = (uint32_t) fir_xfer->coeff;
92 ptr->OP_REG5 = (uint32_t) fir_xfer->dst;
93
94 ffa_enable(ptr);
95 }
96
get_fft_error_kind(uint32_t ffa_status)97 static hpm_stat_t get_fft_error_kind(uint32_t ffa_status)
98 {
99 hpm_stat_t status;
100 if (IS_HPM_BITMASK_SET(ffa_status, FFA_ERROR_MASKS)) {
101 if (IS_HPM_BITMASK_SET(ffa_status, FFA_STATUS_FIR_OV_MASK)) {
102 status = status_ffa_fir_overflow;
103 } else if (IS_HPM_BITMASK_SET(ffa_status, FFA_STATUS_FFT_OV_MASK)) {
104 status = status_ffa_fft_overflow;
105 } else if (IS_HPM_BITMASK_SET(ffa_status, FFA_STATUS_WR_ERR_MASK)) {
106 status = status_ffa_write_error;
107 } else if (IS_HPM_BITMASK_SET(ffa_status, FFA_STATUS_RD_NXT_ERR_MASK)) {
108 status = status_ffa_read_next_error;
109 } else {
110 status = status_ffa_read_error;
111 }
112 } else {
113 status = status_success;
114 }
115 return status;
116 }
117
ffa_calculate_fft_blocking(FFA_Type * ptr,fft_xfer_t * fft_xfer)118 hpm_stat_t ffa_calculate_fft_blocking(FFA_Type *ptr, fft_xfer_t *fft_xfer)
119 {
120 hpm_stat_t status = status_invalid_argument;
121 do {
122 HPM_BREAK_IF((ptr == NULL) || (fft_xfer == NULL) || !is_point_num_valid(fft_xfer->num_points));
123
124 fft_xfer->interrupt_mask = 0;
125
126 ffa_start_fft(ptr, fft_xfer);
127
128 while (!IS_HPM_BITMASK_SET(ptr->STATUS, FFA_STATUS_OP_CMD_DONE_MASK)) {
129 }
130
131 uint32_t ffa_status = ptr->STATUS;
132 status = get_fft_error_kind(ffa_status);
133 } while (false);
134
135 return status;
136 }
137
ffa_calculate_fir_blocking(FFA_Type * ptr,fir_xfer_t * fir_xfer)138 hpm_stat_t ffa_calculate_fir_blocking(FFA_Type *ptr, fir_xfer_t *fir_xfer)
139 {
140 hpm_stat_t status = status_invalid_argument;
141 do {
142 HPM_BREAK_IF((ptr == NULL) || (fir_xfer == NULL));
143
144 fir_xfer->interrupt_mask = 0;
145
146 ffa_start_fir(ptr, fir_xfer);
147
148 while (!IS_HPM_BITMASK_SET(ptr->STATUS, FFA_STATUS_OP_CMD_DONE_MASK)) {
149 }
150
151 uint32_t ffa_status = ptr->STATUS;
152 status = get_fft_error_kind(ffa_status);
153 } while (false);
154
155 return status;
156 }
157