1 /*
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <hi3861_platform_base.h>
17 #include <hi_event.h>
18 #include <hi_isr.h>
19 #include <hi_mem.h>
20 #include <hi_sem.h>
21 #include <hi_spi.h>
22 #include <hi_stdlib.h>
23 #include <hi_time.h>
24 #include <hi_types_base.h>
25 #ifdef CONFIG_SPI_DMA_SUPPORT
26 #include <hi_dma.h>
27 #endif
28 #include <time.h>
29
30 #include "spi.h"
31
32 #define SPI_HOST_OPT_BASE (SPI_OPT_ENABLE_SPI | \
33 SPI_OPT_SET_CFG | \
34 SPI_OPT_DISABLE_SPI | \
35 SPI_OPT_WAIT_SIGNAL | \
36 SPI_OPT_FREE_SIGNAL)
37
38 #define SPI_SLAVE_OPT_READ (SPI_OPT_ENABLE_SPI | \
39 SPI_OPT_SET_CFG)
40
41 #define SPI_SLAVE_OPT_WRITE (SPI_OPT_ENABLE_SPI | \
42 SPI_OPT_SET_CFG | \
43 SPI_OPT_WAIT_SIGNAL | \
44 SPI_OPT_FREE_SIGNAL)
45
46 #define CLKEN_SPI0 5
47 #define CLKEN_SPI1 0
48
49 hi_u32 g_spi_clk = SPI_DEFAULT_CLK;
50
spi_get_clk(hi_void)51 static hi_u32 spi_get_clk(hi_void)
52 {
53 hi_reg_write16(W_CTL_W_TCXO_SEL_REG, 1);
54 hi_udelay(1);
55 return g_spi_clk;
56 }
57
spi_write_data(hi_spi_idx id,hi_u32 timeout_ms)58 static hi_u32 spi_write_data(hi_spi_idx id, hi_u32 timeout_ms)
59 {
60 hi_u32 event_bit;
61 hi_u32 ret;
62 spi_isr_enable(g_spi_ctrl[id]->reg_base, SPI_INT_BIT_TX_FIFO_WATER_LINE);
63 event_bit = 0;
64 ret = hi_event_wait(g_spi_ctrl[id]->event_id, HI_EVENT_BIT_TX_DATA, &event_bit, timeout_ms,
65 HI_EVENT_WAITMODE_OR | HI_EVENT_WAITMODE_CLR);
66 if (ret == HI_ERR_EVENT_WAIT_TIME_OUT) {
67 spi_process_printf("write time out");
68 return HI_ERR_SPI_WRITE_TIMEOUT;
69 } else {
70 return HI_ERR_SUCCESS;
71 }
72 }
73
spi_read_data(hi_spi_idx id,hi_u32 timeout_ms)74 static hi_u32 spi_read_data(hi_spi_idx id, hi_u32 timeout_ms)
75 {
76 hi_u32 event_bit = 0;
77 hi_u32 ret;
78
79 for (;;) {
80 if (g_spi_ctrl[id]->rx_buf.cur_cnt >= g_spi_ctrl[id]->trans_len) {
81 g_spi_ctrl[id]->rx_buf.cur_cnt = 0;
82 return HI_ERR_SUCCESS;
83 }
84 spi_isr_enable(g_spi_ctrl[id]->reg_base,
85 SPI_INT_BIT_RX_FIFO_WATER_LINE | SPI_INT_BIT_RX_FIFO_TIME_OUT | SPI_INT_BIT_RX_FIFO_OVER_FLOW);
86
87 ret = hi_event_wait(g_spi_ctrl[id]->event_id,
88 HI_EVENT_BIT_RX_DATA | HI_EVENT_BIT_RX_DATA_TIME_OUT | HI_EVENT_BIT_RX_FIFO_OVER_FLOW,
89 &event_bit, timeout_ms, HI_EVENT_WAITMODE_OR | HI_EVENT_WAITMODE_CLR);
90 if (ret == HI_ERR_SUCCESS) {
91 continue;
92 } else if (ret == HI_ERR_EVENT_WAIT_TIME_OUT) {
93 return HI_ERR_SPI_READ_TIMEOUT;
94 } else {
95 return ret;
96 }
97 }
98 }
spi_host_transfer(hi_spi_idx id,const spi_trans_attr * trans_attr,hi_u32 total_len,hi_u32 read_write)99 static hi_u32 spi_host_transfer(hi_spi_idx id, const spi_trans_attr *trans_attr, hi_u32 total_len, hi_u32 read_write)
100 {
101 hi_u32 ret;
102 hi_u16 threshold = (id == HI_SPI_ID_0 ? SPI0_FIFO_THRESHOLD : SPI1_FIFO_THRESHOLD);
103 hi_u32 len = total_len;
104 while (len) {
105 if (len > threshold) {
106 g_spi_ctrl[id]->single_len = threshold;
107 g_spi_ctrl[id]->trans_len = threshold;
108 } else {
109 g_spi_ctrl[id]->single_len = len;
110 g_spi_ctrl[id]->trans_len = len;
111 }
112 if (read_write & SPI_WRITE_FLAG) {
113 ret = spi_write_data(id, trans_attr->time_out_ms);
114 if (ret != HI_ERR_SUCCESS) {
115 return ret;
116 }
117 }
118 /* if too fast, there should be delay 50-100 us to wait slave */
119 if (read_write & SPI_READ_FLAG) {
120 ret = spi_read_data(id, trans_attr->time_out_ms);
121 if (ret != HI_ERR_SUCCESS) {
122 return ret;
123 }
124 }
125 if (len < g_spi_ctrl[id]->single_len) {
126 return HI_ERR_FAILURE;
127 }
128 len -= g_spi_ctrl[id]->single_len;
129 }
130 return HI_ERR_SUCCESS;
131 }
132
spi_slave_transfer(hi_spi_idx id,const spi_trans_attr * trans_attr,hi_u32 read_write)133 static hi_u32 spi_slave_transfer(hi_spi_idx id, const spi_trans_attr *trans_attr, hi_u32 read_write)
134 {
135 hi_u32 ret;
136 hi_u16 threshold = (id == HI_SPI_ID_0 ? SPI0_FIFO_THRESHOLD : SPI1_FIFO_THRESHOLD);
137 hi_u32 len = g_spi_ctrl[id]->trans_len;
138 if (read_write & SPI_WRITE_FLAG) {
139 while (len) {
140 if (len > threshold) {
141 g_spi_ctrl[id]->single_len = threshold;
142 } else {
143 g_spi_ctrl[id]->single_len = len;
144 }
145 ret = spi_write_data(id, trans_attr->time_out_ms);
146 if (ret != HI_ERR_SUCCESS) {
147 return ret;
148 }
149 len -= g_spi_ctrl[id]->single_len;
150 }
151 }
152 if (read_write & SPI_READ_FLAG) {
153 g_spi_ctrl[id]->single_len = threshold;
154 ret = spi_read_data(id, trans_attr->time_out_ms);
155 if (ret != HI_ERR_SUCCESS) {
156 return ret;
157 }
158 }
159 return HI_ERR_SUCCESS;
160 }
161
162 #ifdef CONFIG_SPI_DMA_SUPPORT
163 /* slave using dma transfer data, use read or write, can't use both methods of work at the same time */
spi_slave_dma_transfer(hi_spi_idx id,const spi_trans_attr * trans_attr,hi_u32 read_write)164 static hi_u32 spi_slave_dma_transfer(hi_spi_idx id, const spi_trans_attr *trans_attr, hi_u32 read_write)
165 {
166 hi_u32 ret;
167 if (read_write & SPI_WRITE_FLAG) {
168 spi_dma_enable(g_spi_ctrl[id]->reg_base, SPI_TX_DMAE);
169 ret = spi_hd_dma_write_fifo(g_spi_ctrl[id], trans_attr->time_out_ms);
170 spi_dma_disable(g_spi_ctrl[id]->reg_base, SPI_TX_DMAE);
171 } else {
172 spi_dma_enable(g_spi_ctrl[id]->reg_base, SPI_RX_DMAE);
173 ret = spi_hd_dma_read_fifo(g_spi_ctrl[id], trans_attr->time_out_ms);
174 spi_dma_disable(g_spi_ctrl[id]->reg_base, SPI_RX_DMAE);
175 }
176 return ret;
177 }
178 #endif
179
spi_get_data_len(hi_u32 data_width,hi_u32 byte_len)180 static hi_u32 spi_get_data_len(hi_u32 data_width, hi_u32 byte_len)
181 {
182 if (data_width > HI_SPI_CFG_DATA_WIDTH_E_8BIT) {
183 if ((byte_len % SPI_DATA_WIDTH_2BYTES) != 0) {
184 return 0;
185 }
186 return (byte_len / SPI_DATA_WIDTH_2BYTES);
187 } else {
188 return byte_len;
189 }
190 }
191
spi_host_writeread(hi_spi_idx id,hi_pvoid write_data,hi_pvoid read_data,hi_u32 byte_len,hi_u32 options)192 static hi_u32 spi_host_writeread(hi_spi_idx id, hi_pvoid write_data, hi_pvoid read_data, hi_u32 byte_len,
193 hi_u32 options)
194 {
195 hi_u32 data_len;
196 hi_u32 ret;
197 if ((hi_u32)id > HI_SPI_ID_1 || byte_len == 0 ||
198 (!(options & SPI_OPT_SEND_FIX_DATA) && (write_data == HI_NULL)) ||
199 (!(options & SPI_OPT_RCV_FIX_DATA) && (read_data == HI_NULL))) {
200 return HI_ERR_SPI_PARAMETER_WRONG;
201 }
202 if (g_spi_ctrl[id] == HI_NULL) {
203 return HI_ERR_SPI_NOT_INIT;
204 }
205 if (g_spi_ctrl[id]->spi_cfg.is_slave == SPI_CFG_ROLE_SLAVE) {
206 return HI_ERR_SPI_PARAMETER_WRONG;
207 }
208 if (g_spi_ctrl[id]->transferring) {
209 return HI_ERR_SPI_BUSY;
210 }
211 data_len = spi_get_data_len(g_spi_ctrl[id]->spi_cfg.data_width, byte_len);
212 if (data_len == 0) {
213 return HI_ERR_SPI_PARAMETER_WRONG;
214 }
215 spi_trans_attr trans_attr = { SPI_HOST_TIMEOUT_MS, options };
216 g_spi_ctrl[id]->single_len = 0;
217 g_spi_ctrl[id]->trans_len = data_len;
218 g_spi_ctrl[id]->tx_buf.buf = write_data;
219 g_spi_ctrl[id]->tx_buf.cur_pos = 0;
220 g_spi_ctrl[id]->tx_buf.cur_cnt = 0;
221 g_spi_ctrl[id]->rx_buf.buf = read_data;
222 g_spi_ctrl[id]->rx_buf.cur_pos = 0;
223 g_spi_ctrl[id]->rx_buf.cur_cnt = 0;
224 ret = spi_trans_prepare(g_spi_ctrl[id], &trans_attr);
225 if (ret != HI_ERR_SUCCESS) {
226 spi_trans_restore(g_spi_ctrl[id], &trans_attr);
227 return ret;
228 }
229 spi_flush_fifo(g_spi_ctrl[id]->reg_base);
230 if (!g_spi_ctrl[id]->use_irq) {
231 if (g_spi_ctrl[id]->spi_cfg.data_width < HI_SPI_CFG_DATA_WIDTH_E_9BIT) {
232 ret = spi_transfer_8bits_block(g_spi_ctrl[id], options);
233 } else {
234 ret = spi_transfer_16bits_block(g_spi_ctrl[id], options);
235 }
236 } else {
237 ret = spi_host_transfer(id, &trans_attr, data_len, SPI_WRITE_FLAG | SPI_READ_FLAG);
238 }
239
240 spi_trans_restore(g_spi_ctrl[id], &trans_attr);
241 return ret;
242 }
243
hi_spi_set_loop_back_mode(hi_spi_idx id,hi_bool lb_en)244 hi_u32 hi_spi_set_loop_back_mode(hi_spi_idx id, hi_bool lb_en)
245 {
246 hi_u16 reg_val = 0;
247 if (id > HI_SPI_ID_1 || id < HI_SPI_ID_0) {
248 return HI_ERR_SPI_PARAMETER_WRONG;
249 }
250 if (g_spi_ctrl[id] == HI_NULL) {
251 return HI_ERR_SPI_NOT_INIT;
252 }
253 if ((g_spi_ctrl[id]->spi_cfg.fram_mode == HI_SPI_CFG_FRAM_MODE_MICROWIRE ||
254 g_spi_ctrl[id]->spi_cfg.is_slave == SPI_CFG_ROLE_SLAVE) && lb_en) {
255 return HI_ERR_SPI_PARAMETER_WRONG;
256 }
257 if (lb_en) {
258 hi_reg_read16(g_spi_ctrl[id]->reg_base + REG_SPI_CR1, reg_val);
259 reg_val |= (1 << SPI_CR1_ST_BIT_LBM);
260 hi_reg_write16(g_spi_ctrl[id]->reg_base + REG_SPI_CR1, reg_val);
261 g_spi_ctrl[id]->spi_cfg.loop_back = 1;
262 } else {
263 g_spi_ctrl[id]->spi_cfg.loop_back = 0;
264 }
265 return HI_ERR_SUCCESS;
266 }
267
hi_spi_slave_write(hi_spi_idx id,hi_pvoid write_data,hi_u32 byte_len,hi_u32 time_out_ms)268 hi_u32 hi_spi_slave_write(hi_spi_idx id, hi_pvoid write_data, hi_u32 byte_len, hi_u32 time_out_ms)
269 {
270 hi_u32 ret;
271 hi_u32 data_len;
272 if ((hi_u32)id > HI_SPI_ID_1 || write_data == HI_NULL || byte_len == 0 || id < HI_SPI_ID_0) {
273 return HI_ERR_SPI_PARAMETER_WRONG;
274 }
275 if (g_spi_ctrl[id] == HI_NULL) {
276 return HI_ERR_SPI_NOT_INIT;
277 }
278 if (g_spi_ctrl[id]->spi_cfg.is_slave != SPI_CFG_ROLE_SLAVE) {
279 return HI_ERR_SPI_PARAMETER_WRONG;
280 }
281 data_len = spi_get_data_len(g_spi_ctrl[id]->spi_cfg.data_width, byte_len);
282 if (data_len == 0) {
283 return HI_ERR_SPI_PARAMETER_WRONG;
284 }
285 spi_trans_attr trans_attr = { time_out_ms, SPI_SLAVE_OPT_WRITE };
286 g_spi_ctrl[id]->single_len = 0;
287 g_spi_ctrl[id]->trans_len = data_len;
288 g_spi_ctrl[id]->tx_buf.buf = write_data;
289 g_spi_ctrl[id]->tx_buf.cur_pos = 0;
290 g_spi_ctrl[id]->tx_buf.cur_cnt = 0;
291 ret = spi_trans_prepare(g_spi_ctrl[id], &trans_attr);
292 if (ret != HI_ERR_SUCCESS) {
293 spi_trans_restore(g_spi_ctrl[id], &trans_attr);
294 return ret;
295 }
296 #ifdef CONFIG_SPI_DMA_SUPPORT
297 if (g_spi_ctrl[id]->use_dma) { /* transfer less fifo size data, use isr modle first */
298 ret = spi_slave_dma_transfer(id, &trans_attr, SPI_WRITE_FLAG);
299 } else {
300 ret = spi_slave_transfer(id, &trans_attr, SPI_WRITE_FLAG);
301 }
302 #else
303 ret = spi_slave_transfer(id, &trans_attr, SPI_WRITE_FLAG);
304 #endif
305
306 spi_trans_restore(g_spi_ctrl[id], &trans_attr);
307 return ret;
308 }
309
hi_spi_slave_read(hi_spi_idx id,hi_pvoid read_data,hi_u32 byte_len,hi_u32 time_out_ms)310 hi_u32 hi_spi_slave_read(hi_spi_idx id, hi_pvoid read_data, hi_u32 byte_len, hi_u32 time_out_ms)
311 {
312 hi_u32 ret;
313 hi_u32 data_len;
314 if ((hi_u32)id > HI_SPI_ID_1 || read_data == HI_NULL || byte_len == 0 || id < HI_SPI_ID_0) {
315 return HI_ERR_SPI_PARAMETER_WRONG;
316 }
317 if (g_spi_ctrl[id] == HI_NULL) {
318 return HI_ERR_SPI_NOT_INIT;
319 }
320 if (g_spi_ctrl[id]->spi_cfg.is_slave != SPI_CFG_ROLE_SLAVE) {
321 return HI_ERR_SPI_PARAMETER_WRONG;
322 }
323 data_len = spi_get_data_len(g_spi_ctrl[id]->spi_cfg.data_width, byte_len);
324 if (data_len == 0) {
325 return HI_ERR_SPI_PARAMETER_WRONG;
326 }
327 spi_trans_attr trans_attr = { time_out_ms, SPI_SLAVE_OPT_READ };
328 g_spi_ctrl[id]->single_len = 0;
329 g_spi_ctrl[id]->trans_len = data_len;
330 g_spi_ctrl[id]->rx_buf.buf = read_data;
331 g_spi_ctrl[id]->rx_buf.cur_pos = 0;
332 g_spi_ctrl[id]->rx_buf.cur_cnt = 0;
333 spi_flush_fifo(g_spi_ctrl[id]->reg_base);
334 ret = spi_trans_prepare(g_spi_ctrl[id], &trans_attr);
335 if (ret != HI_ERR_SUCCESS) {
336 spi_trans_restore(g_spi_ctrl[id], &trans_attr);
337 return ret;
338 }
339 #ifdef CONFIG_SPI_DMA_SUPPORT
340 if (g_spi_ctrl[id]->use_dma) {
341 ret = spi_slave_dma_transfer(id, &trans_attr, SPI_READ_FLAG);
342 } else {
343 ret = spi_slave_transfer(id, &trans_attr, SPI_READ_FLAG);
344 }
345 #else
346 ret = spi_slave_transfer(id, &trans_attr, SPI_READ_FLAG);
347 #endif
348
349 spi_trans_restore(g_spi_ctrl[id], &trans_attr);
350 return ret;
351 }
352
hi_spi_host_writeread(hi_spi_idx id,hi_pvoid write_data,hi_pvoid read_data,hi_u32 byte_len)353 hi_u32 hi_spi_host_writeread(hi_spi_idx id, hi_pvoid write_data, hi_pvoid read_data, hi_u32 byte_len)
354 {
355 if ((id > HI_SPI_ID_1) || (id < HI_SPI_ID_0) || byte_len == 0 ||
356 (write_data == HI_NULL) || (read_data == HI_NULL)) {
357 return HI_ERR_SPI_PARAMETER_WRONG;
358 }
359 return spi_host_writeread(id, write_data, read_data, byte_len, SPI_HOST_OPT_BASE);
360 }
361
hi_spi_host_read(hi_spi_idx id,hi_pvoid read_data,hi_u32 byte_len)362 hi_u32 hi_spi_host_read(hi_spi_idx id, hi_pvoid read_data, hi_u32 byte_len)
363 {
364 if ((id > HI_SPI_ID_1) || (id < HI_SPI_ID_0) || (byte_len == 0) || (read_data == HI_NULL)) {
365 return HI_ERR_SPI_PARAMETER_WRONG;
366 }
367 return spi_host_writeread(id, HI_NULL, read_data, byte_len, (SPI_HOST_OPT_BASE) | SPI_OPT_SEND_FIX_DATA);
368 }
369
hi_spi_host_write(hi_spi_idx id,hi_pvoid write_data,hi_u32 byte_len)370 hi_u32 hi_spi_host_write(hi_spi_idx id, hi_pvoid write_data, hi_u32 byte_len)
371 {
372 if ((id > HI_SPI_ID_1) || (id < HI_SPI_ID_0) || (byte_len == 0) || (write_data == HI_NULL)) {
373 return HI_ERR_SPI_PARAMETER_WRONG;
374 }
375 return spi_host_writeread(id, write_data, HI_NULL, byte_len, (SPI_HOST_OPT_BASE) | SPI_OPT_RCV_FIX_DATA);
376 }
377
hi_spi_set_irq_mode(hi_spi_idx id,hi_bool irq_en)378 hi_u32 hi_spi_set_irq_mode(hi_spi_idx id, hi_bool irq_en)
379 {
380 if ((id > HI_SPI_ID_1) || (id < HI_SPI_ID_0)) {
381 return HI_ERR_SPI_PARAMETER_WRONG;
382 }
383 if (g_spi_ctrl[id] == HI_NULL) {
384 return HI_ERR_SPI_NOT_INIT;
385 }
386 if (g_spi_ctrl[id]->transferring) {
387 return HI_ERR_SPI_BUSY;
388 }
389 g_spi_ctrl[id]->use_irq = irq_en;
390 if (!irq_en) {
391 spi_isr_disable(g_spi_ctrl[id]->reg_base, SPI_INT_BIT_TX_FIFO_WATER_LINE |
392 SPI_INT_BIT_RX_FIFO_WATER_LINE |
393 SPI_INT_BIT_RX_FIFO_TIME_OUT);
394 }
395 return HI_ERR_SUCCESS;
396 }
397
hi_spi_set_dma_mode(hi_spi_idx id,hi_bool dma_en)398 hi_u32 hi_spi_set_dma_mode(hi_spi_idx id, hi_bool dma_en)
399 {
400 if (id > HI_SPI_ID_1) {
401 return HI_ERR_SPI_PARAMETER_WRONG;
402 }
403 if (g_spi_ctrl[id] == HI_NULL) {
404 return HI_ERR_SPI_NOT_INIT;
405 }
406 if (g_spi_ctrl[id]->transferring) {
407 return HI_ERR_SPI_BUSY;
408 }
409 #ifdef CONFIG_SPI_DMA_SUPPORT
410 g_spi_ctrl[id]->use_dma = dma_en;
411 #else
412 hi_unref_param(dma_en);
413 return HI_ERR_SPI_NOT_SUPPORT_DMA;
414 #endif
415 return HI_ERR_SUCCESS;
416 }
417
hi_spi_register_usr_func(hi_spi_idx id,hi_spi_usr_func prepare_func,hi_spi_usr_func restore_func)418 hi_u32 hi_spi_register_usr_func(hi_spi_idx id, hi_spi_usr_func prepare_func, hi_spi_usr_func restore_func)
419 {
420 if ((id > HI_SPI_ID_1) || (id < HI_SPI_ID_0)) {
421 return HI_ERR_SPI_PARAMETER_WRONG;
422 }
423 if (g_spi_ctrl[id] == HI_NULL) {
424 return HI_ERR_SPI_NOT_INIT;
425 }
426
427 if (g_spi_ctrl[id]->transferring) {
428 return HI_ERR_SPI_BUSY;
429 }
430 g_spi_ctrl[id]->prepare_func = prepare_func;
431 g_spi_ctrl[id]->restore_func = restore_func;
432 return HI_ERR_SUCCESS;
433 }
434
hi_spi_set_basic_info(hi_spi_idx id,const hi_spi_cfg_basic_info * param)435 hi_u32 hi_spi_set_basic_info(hi_spi_idx id, const hi_spi_cfg_basic_info *param)
436 {
437 hi_u32 ret;
438 hi_u32 spi_clk = spi_get_clk();
439 if (((hi_u32)id > HI_SPI_ID_1) || (param == HI_NULL) || (id < HI_SPI_ID_0)) {
440 return HI_ERR_SPI_PARAMETER_WRONG;
441 }
442
443 if (g_spi_ctrl[id] == HI_NULL) {
444 return HI_ERR_SPI_NOT_INIT;
445 }
446
447 if (g_spi_ctrl[id]->transferring) {
448 return HI_ERR_SPI_BUSY;
449 }
450
451 if (param->fram_mode > HI_SPI_CFG_FRAM_MODE_MICROWIRE || param->data_width < HI_SPI_CFG_DATA_WIDTH_E_4BIT ||
452 param->freq > spi_max_speed(spi_clk) || param->freq < spi_min_speed(spi_clk)) {
453 return HI_ERR_SPI_PARAMETER_WRONG;
454 }
455 if (g_spi_ctrl[id]->spi_cfg.loop_back == HI_TRUE && (param->fram_mode == HI_SPI_CFG_FRAM_MODE_MICROWIRE ||
456 g_spi_ctrl[id]->spi_cfg.is_slave == SPI_CFG_ROLE_SLAVE)) {
457 return HI_ERR_SPI_PARAMETER_WRONG;
458 }
459
460 /* compute spi speed, speed=clk/(cpsdvsr*(scr+1)) */
461 hi_u32 tmp = spi_clk / param->freq;
462 if (tmp < CPSDVSR_MIN) {
463 g_spi_ctrl[id]->spi_cfg.cpsdvsr = CPSDVSR_MIN;
464 g_spi_ctrl[id]->spi_cfg.scr = 0;
465 } else if (tmp <= CPSDVSR_MAX) {
466 g_spi_ctrl[id]->spi_cfg.cpsdvsr = (hi_u16)(tmp & (~0x1));
467 g_spi_ctrl[id]->spi_cfg.scr = (tmp / g_spi_ctrl[id]->spi_cfg.cpsdvsr) - 1;
468 } else {
469 g_spi_ctrl[id]->spi_cfg.cpsdvsr = CPSDVSR_MAX;
470 g_spi_ctrl[id]->spi_cfg.scr = (tmp / g_spi_ctrl[id]->spi_cfg.cpsdvsr) - 1;
471 }
472
473 g_spi_ctrl[id]->spi_cfg.data_width = param->data_width;
474 g_spi_ctrl[id]->spi_cfg.fram_mode = param->fram_mode;
475 g_spi_ctrl[id]->spi_cfg.cpol = param->cpol;
476 g_spi_ctrl[id]->spi_cfg.cpha = param->cpha;
477 g_spi_ctrl[id]->spi_cfg.endian = param->endian;
478 /* write reg */
479 ret = spi_config(g_spi_ctrl[id]);
480 return ret;
481 }
482
spi_ctrl_init(hi_spi_idx id,hi_spi_cfg_init_param init_param)483 static hi_void spi_ctrl_init(hi_spi_idx id, hi_spi_cfg_init_param init_param)
484 {
485 g_spi_ctrl[id]->spi_cfg.loop_back = HI_FALSE;
486 hi_u16 reg_val;
487 hi_reg_read16(CLDO_CTL_CLKEN_REG, reg_val);
488 if (id == HI_SPI_ID_0) {
489 g_spi_ctrl[id]->spi_cfg.tx_fifo_line = SPI0_TX_FIFO_WATER_LINE;
490 g_spi_ctrl[id]->spi_cfg.rx_fifo_line = SPI0_RX_FIFO_WATER_LINE;
491 g_spi_ctrl[id]->spi_cfg.tx_fifo_dma_line = SPI0_TX_FIFO_DMA_WLINE_64;
492 g_spi_ctrl[id]->spi_cfg.rx_fifo_dma_line = SPI0_RX_FIFO_DMA_WLINE_128;
493 reg_val |= 1 << CLKEN_SPI0;
494 } else {
495 g_spi_ctrl[id]->spi_cfg.tx_fifo_line = SPI1_TX_FIFO_WATER_LINE;
496 g_spi_ctrl[id]->spi_cfg.rx_fifo_line = SPI1_RX_FIFO_WATER_LINE;
497 g_spi_ctrl[id]->spi_cfg.tx_fifo_dma_line = SPI1_TX_FIFO_DMA_WLINE_16;
498 g_spi_ctrl[id]->spi_cfg.rx_fifo_dma_line = SPI1_RX_FIFO_DMA_WLINE_32;
499 reg_val |= 1 << CLKEN_SPI1;
500 }
501 hi_reg_write16(CLDO_CTL_CLKEN_REG, reg_val); /* enable spix clk bus */
502 g_spi_ctrl[id]->spi_cfg.is_slave = init_param.is_slave ? SPI_CFG_ROLE_SLAVE : SPI_CFG_ROLE_MASTER;
503 spi_reset(g_spi_ctrl[id]);
504 spi_set_fifo_line(g_spi_ctrl[id]);
505 #ifdef CONFIG_SPI_DMA_SUPPORT
506 spi_set_dma_fifo_line(g_spi_ctrl[id]);
507 #endif
508 spi_isr_disable(g_spi_ctrl[id]->reg_base,
509 SPI_INT_BIT_RX_FIFO_WATER_LINE | SPI_INT_BIT_RX_FIFO_TIME_OUT | SPI_INT_BIT_RX_FIFO_OVER_FLOW);
510 }
511
512 #ifdef CONFIG_SPI_DMA_SUPPORT
spi_dma_init(hi_void)513 static hi_u32 spi_dma_init(hi_void)
514 {
515 hi_u32 ret = HI_ERR_SUCCESS;
516 if (hi_dma_is_init() == HI_FALSE) {
517 ret = hi_dma_init();
518 }
519 return ret;
520 }
521 #endif
522
hi_spi_init(hi_spi_idx id,hi_spi_cfg_init_param init_param,const hi_spi_cfg_basic_info * param)523 hi_u32 hi_spi_init(hi_spi_idx id, hi_spi_cfg_init_param init_param, const hi_spi_cfg_basic_info *param)
524 {
525 if ((id > HI_SPI_ID_1) || (param == HI_NULL) || (id < HI_SPI_ID_0)) {
526 return HI_ERR_SPI_PARAMETER_WRONG;
527 }
528 hi_u32 ret;
529 if (g_spi_ctrl[id] != HI_NULL) {
530 return HI_ERR_SPI_REINIT;
531 }
532
533 g_spi_ctrl[id] = (spi_ctrl *)hi_malloc(HI_MOD_ID_DRV_SPI, sizeof(spi_ctrl));
534 if (g_spi_ctrl[id] == HI_NULL) {
535 return HI_ERR_MALLOC_FAILUE;
536 }
537 memset_s(g_spi_ctrl[id], sizeof(spi_ctrl), 0x0, sizeof(spi_ctrl));
538 g_spi_ctrl[id]->reg_base = (id == HI_SPI_ID_0) ? HI_SSP0_REG_BASE : HI_SSP1_REG_BASE;
539
540 ret = hi_sem_bcreate(&g_spi_ctrl[id]->sem_id, 1);
541 if (ret != HI_ERR_SUCCESS) {
542 goto init_fail;
543 }
544
545 ret = hi_event_create(&g_spi_ctrl[id]->event_id);
546 if (ret != HI_ERR_SUCCESS) {
547 goto init_fail2;
548 }
549
550 g_spi_ctrl[id]->irq_num = (id == HI_SPI_ID_0) ? SSP_0_IRQ : SSP_1_IRQ;
551 ret = hi_irq_request(g_spi_ctrl[id]->irq_num, HI_IRQ_FLAG_PRI2, (irq_routine)spi_isr, (uintptr_t)g_spi_ctrl[id]);
552 if (ret != HI_ERR_SUCCESS) {
553 goto init_fail3;
554 }
555 spi_ctrl_init(id, init_param);
556 ret = (hi_u32)hi_spi_set_basic_info(id, param);
557 if (ret != HI_ERR_SUCCESS) {
558 goto init_fail4;
559 }
560
561 #ifdef CONFIG_SPI_DMA_SUPPORT
562 return spi_dma_init();
563 #endif
564
565 return HI_ERR_SUCCESS;
566
567 init_fail4:
568 (hi_void) hi_irq_free(g_spi_ctrl[id]->irq_num);
569 init_fail3:
570 (hi_void) hi_event_delete(g_spi_ctrl[id]->event_id);
571 init_fail2:
572 (hi_void) hi_sem_delete(g_spi_ctrl[id]->sem_id);
573 init_fail:
574 hi_free(HI_MOD_ID_DRV_SPI, g_spi_ctrl[id]);
575 g_spi_ctrl[id] = HI_NULL;
576 return ret;
577 }
578
hi_spi_deinit(hi_spi_idx id)579 hi_u32 hi_spi_deinit(hi_spi_idx id)
580 {
581 hi_u16 reg_val;
582 if ((id > HI_SPI_ID_1) || (id < HI_SPI_ID_0)) {
583 return HI_ERR_SPI_PARAMETER_WRONG;
584 }
585 if (g_spi_ctrl[id] == HI_NULL) {
586 return HI_ERR_SUCCESS; /* HI_ERR_SPI_NOT_INIT return success */
587 }
588 if (g_spi_ctrl[id]->transferring) {
589 return HI_ERR_SPI_BUSY;
590 }
591
592 spi_isr_disable(g_spi_ctrl[id]->reg_base,
593 SPI_INT_BIT_RX_FIFO_WATER_LINE | SPI_INT_BIT_RX_FIFO_TIME_OUT | SPI_INT_BIT_RX_FIFO_OVER_FLOW);
594 hi_irq_disable(g_spi_ctrl[id]->irq_num);
595 (hi_void) hi_irq_free(g_spi_ctrl[id]->irq_num);
596
597 (hi_void) hi_sem_delete(g_spi_ctrl[id]->sem_id);
598 (hi_void) hi_event_delete(g_spi_ctrl[id]->event_id);
599 /* disable spi */
600 spi_disable(g_spi_ctrl[id]);
601 hi_free(HI_MOD_ID_DRV_SPI, g_spi_ctrl[id]);
602 g_spi_ctrl[id] = HI_NULL;
603 hi_reg_read16(CLDO_CTL_CLKEN_REG, reg_val);
604 reg_val &= (id == HI_SPI_ID_0) ? ~(1 << CLKEN_SPI0) : ~(1 << CLKEN_SPI1);
605 hi_reg_write16(CLDO_CTL_CLKEN_REG, reg_val); /* disable spix clk bus */
606 return HI_ERR_SUCCESS;
607 }
608