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