source: azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/spi.c@ 453

Last change on this file since 453 was 453, checked in by coas-nagasima, 4 years ago

ファイルを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 25.2 KB
Line 
1/*
2 * TOPPERS/ASP Kernel
3 * Toyohashi Open Platform for Embedded Real-Time Systems/
4 * Advanced Standard Profile Kernel
5 *
6 * Copyright (C) 2008-2011 by Embedded and Real-Time Systems Laboratory
7 * Graduate School of Information Science, Nagoya Univ., JAPAN
8 * Copyright (C) 2015-2019 by TOPPERS PROJECT Educational Working Group.
9 *
10 * 上記著作権者は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
11 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
12 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
13 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
14 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
15 * スコード中に含まれていること.
16 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
17 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
18 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
19 * の無保証規定を掲載すること.
20 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
21 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
22 * と.
23 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
24 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
25 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
26 * 報告すること.
27 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
28 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
29 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
30 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
31 * 免責すること.
32 *
33 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
34 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
35 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
36 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
37 * の責任を負わない.
38 *
39 * @(#) $Id$
40 */
41/*
42 *
43 * SPIドライバ関数群
44 *
45 */
46#include "kernel_impl.h"
47#include <t_syslog.h>
48#include <t_stdlib.h>
49#include <string.h>
50#include <sil.h>
51#include <target_syssvc.h>
52#include "device.h"
53#include "spi.h"
54
55Inline uint64_t
56sil_rel_mem(const uint64_t *mem)
57{
58 uint64_t data;
59
60 data = *((const volatile uint64_t *) mem);
61 return(data);
62}
63
64#define sil_orw_mem(a, b) sil_wrw_mem((a), sil_rew_mem(a) | (b))
65#define sil_andw_mem(a, b) sil_wrw_mem((a), sil_rew_mem(a) & ~(b))
66#define sil_modw_mem(a, b, c) sil_wrw_mem((a), (sil_rew_mem(a) & (~b)) | (c))
67
68/*
69 * SPIOポートIDから管理ブロックを取り出すためのマクロ
70 */
71#define INDEX_SPI(spiid) ((uint_t)((spiid) - 1))
72
73#define get_framewidth(l) (((l)+7)/8)
74
75#define SPI_SSIENR_DISABLE 0x00000000
76#define SPI_SSIENR_ENABLE 0x00000001
77
78#define SPI_DMACR_RXENABLE 0x00000001
79#define SPI_DMACR_TXENABLE 0x00000002
80
81/*
82 * SPIハードウェア設定構造体
83 */
84
85typedef struct _SPI_PortControlBlock{
86 unsigned long base;
87 int16_t func_data;
88 int16_t func_ss;
89 int16_t func_arb;
90 int16_t func_sclk;
91} SPI_PortControlBlock;
92
93static const SPI_PortControlBlock spi_pcb[NUM_SPIPORT] = {
94 {TADR_SPI0_BASE, FUNC_SPI0_D0, FUNC_SPI0_SS0, FUNC_SPI0_ARB, FUNC_SPI0_SCLK },
95 {TADR_SPI1_BASE, FUNC_SPI1_D0, FUNC_SPI1_SS0, FUNC_SPI1_ARB, FUNC_SPI1_SCLK },
96 {TADR_SPIS_BASE, FUNC_SPI_SLAVE_D0, FUNC_SPI_SLAVE_SS, -1, FUNC_SPI_SLAVE_SCLK},
97 {TADR_SPI2_BASE, -1, -1, -1, -1 }
98};
99
100SPI_Handle_t SpiHandle[NUM_SPIPORT];
101DMA_Handle_t spi_dma_handle[NUM_SPIPORT][2];
102
103
104/*
105 * 転送モード設定
106 */
107static ER
108spi_set_tmod(SPI_Handle_t *hspi, uint32_t tmod)
109{
110 SPI_Init_t *init;
111 uint32_t inst_l = 4;
112 uint32_t addr_l;
113
114 init = &hspi->Init;
115 switch (init->InstLength){
116 case 0:
117 inst_l = 0;
118 break;
119 case 4:
120 inst_l = 1;
121 break;
122 case 8:
123 inst_l = 2;
124 break;
125 case 16:
126 inst_l = 3;
127 break;
128 default:
129 break;
130 }
131 if(inst_l == 4)
132 return E_PAR;
133
134 addr_l = init->AddrLength / 4;
135 sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_CTRLR0), (init->WorkMode << hspi->work_mode_offset) | \
136 (init->FrameFormat << hspi->frf_offset) | ((init->DataSize - 1) << hspi->dfs_offset));
137 sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_SPI_CTRLR0),
138 ((init->WaitCycles << 11) | (inst_l << 8) | (addr_l << 2) | init->IATransMode));
139 sil_modw_mem((uint32_t *)(hspi->base+TOFF_SPI_CTRLR0), (3 << hspi->tmod_offset), (tmod << hspi->tmod_offset));
140 return E_OK;
141}
142
143/*
144 * DMAコールバック関数
145 */
146static void
147spi_dma_comp(DMA_Handle_t *hdma)
148{
149 SPI_Handle_t *hspi = (SPI_Handle_t *)hdma->localdata;
150 if(hspi != NULL && hspi->Init.semdmaid != 0){
151 isig_sem(hspi->Init.semdmaid);
152 }
153}
154
155/*
156 * DMA転送開始関数
157 */
158DMA_Handle_t *
159spi_dmac_set_single_mode(SPI_Handle_t *hspi, uint8_t rtx,
160 int8_t ss_no, const void *src, void *dest,
161 uint8_t src_inc, uint8_t dest_inc,
162 uint8_t dmac_burst_size, uint8_t dmac_trans_width,
163 size_t block_size)
164{
165 DMA_Handle_t *hdma;
166 int mem_type_src, mem_type_dest;
167 uint8_t flow_control;
168
169 if(rtx == 0){
170 hdma = hspi->hdmatx;
171 flow_control = DMA_MEMORY_TO_PERIPH;
172 mem_type_src = 1;
173 mem_type_dest = 0;
174 }
175 else{
176 hdma = hspi->hdmarx;
177 flow_control = DMA_PERIPH_TO_MEMORY;
178 mem_type_src = 0;
179 mem_type_dest = 1;
180 }
181 if(ss_no < 0)
182 ss_no = 0;
183
184 hdma->Init.Direction = flow_control; /* DMA転送方向 */
185 hdma->Init.SrcHandShake = (mem_type_src ? DMAC_HS_SOFTWARE : DMAC_HS_HARDWARE); /* ソースハンドシェイク */
186 hdma->Init.DrcHandShake = (mem_type_dest ? DMAC_HS_SOFTWARE : DMAC_HS_HARDWARE); /* デスティネーションハンドシェイク */
187 hdma->Init.SrcInc = src_inc; /* ソースインクリメント設定 */
188 hdma->Init.DstInc = dest_inc; /* デスティネーションインクリメント設定 */
189 hdma->Init.SrcTransWidth = dmac_trans_width; /* ソース転送幅 */
190 hdma->Init.DstTransWidth = dmac_trans_width; /* デスティネーション転送幅 */
191 hdma->Init.SrcBurstSize = dmac_burst_size; /* ソースバーストサイズ */
192 hdma->Init.DstBurstSize = dmac_burst_size; /* デスティネーションバーストサイズ */
193 dma_reset(hdma);
194 sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_SER), (1 << ss_no));
195 dma_start(hdma, (uintptr_t)src, (uintptr_t)dest, block_size);
196 return hdma;
197}
198
199/*
200 * SPI-DMA転送終了待ち
201 */
202ER
203spi_dmac_wait_done(DMA_Handle_t * hdma)
204{
205 SPI_Handle_t *hspi = (SPI_Handle_t *)hdma->localdata;
206 ER ercd = E_OK;
207 int tick = DMA_TRS_TIMEOUT;
208
209 while((hdma->status == DMA_STATUS_BUSY) && tick > 0){
210 if(hspi != NULL && hspi->Init.semdmaid != 0){
211 ercd = twai_sem(hspi->Init.semdmaid, 5);
212 }
213 else
214 dly_tsk(1);
215 tick--;
216 }
217 dma_end(hdma);
218 if(hdma->ErrorCode != 0)
219 ercd = E_OBJ;
220 else if(tick == 0)
221 ercd = E_TMOUT;
222 return ercd;
223}
224
225/*
226 * SPI内部転送終了待ち
227 */
228ER
229spi_inwait(SPI_Handle_t *hspi, uint32_t timeout)
230{
231 ER ercd = E_OK;
232 int tick = timeout;
233
234 sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_IMR), 0x0011);
235 while((sil_rew_mem((uint32_t *)(hspi->base+TOFF_SPI_SR)) & 0x05) != 0x04 && tick > 0){
236 if(hspi->Init.semid != 0)
237 twai_sem(hspi->Init.semid, 5);
238 else
239 dly_tsk(1);
240 tick--;
241 }
242 sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_SER), 0x00000000);
243 sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_SSIENR), SPI_SSIENR_DISABLE);
244
245 if(hspi->ErrorCode != 0)
246 ercd = E_OBJ;
247 else if(tick == 0)
248 ercd = E_TMOUT;
249 hspi->TxXferCount = 0;
250 hspi->RxXferCount = 0;
251 return ercd;
252}
253
254
255/*
256 * SPI初期設定
257 * parameter1 port: SPIポート番号
258 * parameter2 spii: SPI初期設定構造体へのポインタ
259 * return SPIハンドラへのポインタ、NULLでエラー
260 */
261SPI_Handle_t *
262spi_init(ID port, const SPI_Init_t *init)
263{
264 SPI_Handle_t *hspi;
265 DMA_Handle_t *hdma;
266 const SPI_PortControlBlock *spcb;
267 unsigned long base;
268 uint8_t spi_num;
269 uint32_t spi_baudr, clk_th1, threshold;
270 uint8_t dfs_offset, frf_offset, work_mode_offset, tmod_offset;
271 uint32_t dsize_err = 0;
272 uint32_t inst_l = 4;
273 uint32_t addr_l;
274
275 if(port < SPI1_PORTID || port > NUM_SPIPORT)
276 return NULL;
277 spi_num = INDEX_SPI(port);
278 if(init == NULL)
279 return NULL;
280 if(init->DataSize < 4 && init->DataSize > 32)
281 return NULL;
282 if(init->AddrLength % 4 != 0 && init->AddrLength > 60)
283 return NULL;
284
285 /*
286 * クロック設定
287 */
288 if(spi_num == 3){
289 sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_CLK_SEL0), SYSCTL_CLK_SEL0_SPI3_CLK_SEL);
290 }
291 if(spi_num < 2)
292 sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_EN_CENT), SYSCTL_CLK_EN_CENT_APB2_CLK_EN);
293 else if(spi_num == 2)
294 sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_EN_CENT), SYSCTL_CLK_EN_CENT_APB0_CLK_EN);
295 sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_EN_PERI), (SYSCTL_CLK_EN_PERI_SPI0_CLK_EN<<spi_num));
296 sil_andw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_TH1), 0xFF << (spi_num*8));
297
298 /*
299 * ピンファンクション設定
300 */
301 spcb = &spi_pcb[spi_num];
302 if(spcb->func_ss >= 0 && init->SsPin >= 0)
303 fpioa_set_function(init->SsPin, (uint8_t)(spcb->func_ss + init->SsNo));
304 if(spcb->func_sclk >= 0 && init->SclkPin >= 0)
305 fpioa_set_function(init->SclkPin, (uint8_t)(spcb->func_sclk));
306 if(spcb->func_data >= 0){
307 if(init->MosiPin >= 0)
308 fpioa_set_function(init->MosiPin, (uint8_t)(spcb->func_data));
309 if(init->MisoPin >= 0)
310 fpioa_set_function(init->MisoPin, (uint8_t)(spcb->func_data+1));
311
312 }
313 hspi = &SpiHandle[spi_num];
314 base = spcb->base;
315
316 switch(spi_num){
317 case 0:
318 case 1:
319 dfs_offset = 16;
320 frf_offset = 21;
321 work_mode_offset = 6;
322 tmod_offset = 8;
323 break;
324 case 3:
325 default:
326 dfs_offset = 0;
327 frf_offset = 22;
328 work_mode_offset = 8;
329 tmod_offset = 10;
330 break;
331 }
332
333 switch(init->FrameFormat){
334 case SPI_FF_DUAL:
335 if(init->DataSize % 2 != 0)
336 dsize_err = 1;
337 break;
338 case SPI_FF_QUAD:
339 if(init->DataSize % 4 != 0)
340 dsize_err = 1;
341 break;
342 case SPI_FF_OCTAL:
343 if(init->DataSize % 8 != 0)
344 dsize_err = 1;
345 break;
346 default:
347 break;
348 }
349
350 switch(init->InstLength){
351 case 0:
352 inst_l = 0;
353 break;
354 case 4:
355 inst_l = 1;
356 break;
357 case 8:
358 inst_l = 2;
359 break;
360 case 16:
361 inst_l = 3;
362 break;
363 default:
364 break;
365 }
366 if(inst_l == 4 || dsize_err){
367 syslog_0(LOG_ERROR, "Invalid instruction length");
368 return NULL;
369 }
370 addr_l = init->AddrLength / 4;
371
372 memcpy(&hspi->Init, init, sizeof(SPI_Init_t));
373
374 if(sil_rew_mem((uint32_t *)(base+TOFF_SPI_BAUDR)) == 0)
375 sil_wrw_mem((uint32_t *)(base+TOFF_SPI_BAUDR), 0x14);
376 /*
377 * 割込み不許可
378 */
379 sil_wrw_mem((uint32_t *)(base+TOFF_SPI_IMR), 0x00000000);
380
381 sil_wrw_mem((uint32_t *)(base+TOFF_SPI_DMACR), 0x00000000);
382 sil_wrw_mem((uint32_t *)(base+TOFF_SPI_DMATDLR), 0x00000010);
383 sil_wrw_mem((uint32_t *)(base+TOFF_SPI_DMARDLR), 0x00000000);
384 sil_wrw_mem((uint32_t *)(base+TOFF_SPI_SER), 0x00000000);
385 sil_wrw_mem((uint32_t *)(base+TOFF_SPI_SSIENR), SPI_SSIENR_DISABLE);
386 sil_wrw_mem((uint32_t *)(base+TOFF_SPI_CTRLR0), (init->WorkMode << work_mode_offset) | \
387 (init->FrameFormat << frf_offset) | ((init->DataSize - 1) << dfs_offset));
388 sil_wrw_mem((uint32_t *)(base+TOFF_SPI_SPI_CTRLR0),
389 ((init->WaitCycles << 11) | (inst_l << 8) | (addr_l << 2) | init->IATransMode));
390 sil_wrw_mem((uint32_t *)(base+TOFF_SPI_ENDIAN), init->SignBit);
391
392 /*
393 * 転送クロック設定
394 */
395 clk_th1 = sil_rew_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_TH1));
396 threshold = (clk_th1 >> (spi_num * 8)) & 0xff;
397 spi_baudr = (get_pll_clock(0) / ((threshold + 1) * 2)) / init->Prescaler;
398
399
400 if(spi_baudr < 2 ){
401 spi_baudr = 2;
402 }
403 else if(spi_baudr > 65534){
404 spi_baudr = 65534;
405 }
406 sil_wrw_mem((uint32_t *)(base+TOFF_SPI_BAUDR), spi_baudr);
407
408 /*
409 * ハンドラ初期化
410 */
411 hspi->base = base;
412 hspi->spi_num = spi_num;
413 hspi->dfs_offset = dfs_offset;
414 hspi->frf_offset = frf_offset;
415 hspi->work_mode_offset = work_mode_offset;
416 hspi->tmod_offset = tmod_offset;
417 hspi->hdmatx = NULL;
418 hspi->hdmarx = NULL;
419 if(init->TxDMAChannel >= 0){
420 hdma = &spi_dma_handle[init->TxDMAChannel][0];
421 hdma->chnum = init->TxDMAChannel;
422 if(init->RxDMAChannel >= 0)
423 hdma->xfercallback = NULL;
424 else
425 hdma->xfercallback = spi_dma_comp;
426 hdma->errorcallback = NULL;
427 hdma->Init.Request = DMA_SELECT_SSI0_TX_REQ + spi_num * 2; /* DMA選択 */
428 hdma->Init.Direction = DMA_MEMORY_TO_PERIPH; /* DMA転送方向 */
429 hdma->Init.SrcMultBlock = DMAC_MULTBLOCK_CONT; /* ソースマルチブロックタイプ */
430 hdma->Init.DrcMultBlock = DMAC_MULTBLOCK_CONT; /* デスティネーションマルチブロックタイプ */
431 hdma->Init.SrcHandShake = DMAC_HS_SOFTWARE; /* ソースハンドシェイク */
432 hdma->Init.DrcHandShake = DMAC_HS_HARDWARE; /* デスティネーションハンドシェイク */
433 hdma->Init.SrcHwhsPol = DMAC_HWHS_POLARITY_LOW; /* ソースハードウェアハンドシェイク極性 */
434 hdma->Init.DrcHwhsPol = DMAC_HWHS_POLARITY_LOW; /* デスティネーションハードウェアハンドシェイク極性 */
435 hdma->Init.Priority = 4; /* 優先度 */
436 hdma->Init.SrcMaster = DMAC_MASTER1; /* ソースマスター設定 */
437 hdma->Init.DstMaster = DMAC_MASTER2; /* デスティネーションマスター設定 */
438 hdma->Init.SrcInc = DMAC_ADDR_INCREMENT; /* ソースインクリメント設定 */
439 hdma->Init.DstInc = DMAC_ADDR_NOCHANGE; /* デスティネーションインクリメント設定 */
440 hdma->Init.SrcTransWidth = DMAC_TRANS_WIDTH_32; /* ソース転送幅 */
441 hdma->Init.DstTransWidth = DMAC_TRANS_WIDTH_32; /* デスティネーション転送幅 */
442 hdma->Init.SrcBurstSize = DMAC_MSIZE_4; /* ソースバーストサイズ */
443 hdma->Init.DstBurstSize = DMAC_MSIZE_4; /* デスティネーションバーストサイズ */
444 hdma->Init.IocBlkTrans = 0; /* IOCブロック転送 */
445 hdma->localdata = (void *)hspi;
446 dma_init(hdma);
447 hspi->hdmatx = hdma;
448 }
449 if(init->RxDMAChannel >= 0){
450 hdma = &spi_dma_handle[init->RxDMAChannel][1];
451 hdma->chnum = init->RxDMAChannel;
452 hdma->xfercallback = spi_dma_comp;
453 hdma->errorcallback = NULL;
454 hdma->Init.Request = DMA_SELECT_SSI0_RX_REQ + spi_num * 2; /* DMA選択 */
455 hdma->Init.Direction = DMA_PERIPH_TO_MEMORY; /* DMA転送方向 */
456 hdma->Init.SrcMultBlock = DMAC_MULTBLOCK_CONT; /* ソースマルチブロックタイプ */
457 hdma->Init.DrcMultBlock = DMAC_MULTBLOCK_CONT; /* デスティネーションマルチブロックタイプ */
458 hdma->Init.SrcHandShake = DMAC_HS_HARDWARE; /* ソースハンドシェイク */
459 hdma->Init.DrcHandShake = DMAC_HS_SOFTWARE; /* デスティネーションハンドシェイク */
460 hdma->Init.SrcHwhsPol = DMAC_HWHS_POLARITY_LOW; /* ソースハードウェアハンドシェイク極性 */
461 hdma->Init.DrcHwhsPol = DMAC_HWHS_POLARITY_LOW; /* デスティネーションハードウェアハンドシェイク極性 */
462 hdma->Init.Priority = 4; /* 優先度 */
463 hdma->Init.SrcMaster = DMAC_MASTER1; /* ソースマスター設定 */
464 hdma->Init.DstMaster = DMAC_MASTER2; /* デスティネーションマスター設定 */
465 hdma->Init.SrcInc = DMAC_ADDR_NOCHANGE; /* ソースインクリメント設定 */
466 hdma->Init.DstInc = DMAC_ADDR_INCREMENT; /* デスティネーションインクリメント設定 */
467 hdma->Init.SrcTransWidth = DMAC_TRANS_WIDTH_32; /* ソース転送幅 */
468 hdma->Init.DstTransWidth = DMAC_TRANS_WIDTH_32; /* デスティネーション転送幅 */
469 hdma->Init.SrcBurstSize = DMAC_MSIZE_4; /* ソースバーストサイズ */
470 hdma->Init.DstBurstSize = DMAC_MSIZE_4; /* デスティネーションバーストサイズ */
471 hdma->Init.IocBlkTrans = 0; /* IOCブロック転送 */
472 hdma->localdata = (void *)hspi;
473 dma_init(hdma);
474 hspi->hdmarx = hdma;
475 }
476 hspi->status = SPI_STATUS_READY;
477 hspi->xmode = 0;
478 return hspi;
479}
480
481/*
482 * SPI終了設定
483 * parameter1 hspi: SPIハンドラへのポインタ
484 * return ERコード
485 */
486ER
487spi_deinit(SPI_Handle_t *hspi)
488{
489 if(hspi == NULL)
490 return E_PAR;
491
492 if(hspi->hdmatx != NULL){
493 dma_deinit(hspi->hdmatx);
494 hspi->hdmatx = NULL;
495 }
496 if(hspi->hdmarx != NULL){
497 dma_deinit(hspi->hdmarx);
498 hspi->hdmarx = NULL;
499 }
500 sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_SSIENR), SPI_SSIENR_DISABLE);
501
502 hspi->ErrorCode = SPI_ERROR_NONE;
503 hspi->status = SPI_STATUS_RESET;
504 return E_OK;
505}
506
507/*
508 * ポーリングデータ送信
509 */
510static void
511spi_send_data_normal2(SPI_Handle_t *hspi, int8_t ss_no, const uint8_t *tx_buff, size_t tx_len)
512{
513 size_t index, fifo_len;
514 uint8_t frame_width = get_framewidth(hspi->Init.DataSize);
515 uint8_t v_misalign_flag = 0;
516 uint32_t v_send_data;
517 uint32_t i = 0;
518
519 if((uintptr_t)tx_buff % frame_width){
520 v_misalign_flag = 1;
521 }
522 if(ss_no < 0)
523 ss_no = 0;
524
525 sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_SSIENR), SPI_SSIENR_ENABLE);
526 sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_SER), (1 << ss_no));
527 while(tx_len > 0){
528 fifo_len = 32 - sil_rew_mem((uint32_t *)(hspi->base+TOFF_SPI_TXFLR));
529 fifo_len = fifo_len < tx_len ? fifo_len : tx_len;
530 switch(frame_width){
531 case SPI_TRANS_INT:
532 fifo_len = fifo_len / 4 * 4;
533 if(v_misalign_flag){
534 for(index = 0; index < fifo_len; index +=4){
535 memcpy(&v_send_data, tx_buff + i , 4);
536 sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_DR), v_send_data);
537 i += 4;
538 }
539 }
540 else{
541 for(index = 0; index < fifo_len / 4; index++)
542 sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_DR), ((uint32_t *)tx_buff)[i++]);
543 }
544 break;
545 case SPI_TRANS_SHORT:
546 fifo_len = fifo_len / 2 * 2;
547 if(v_misalign_flag){
548 for(index = 0; index < fifo_len; index +=2){
549 memcpy(&v_send_data, tx_buff + i, 2);
550 sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_DR), v_send_data);
551 i += 2;
552 }
553 }
554 else{
555 for(index = 0; index < fifo_len / 2; index++)
556 sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_DR), ((uint16_t *)tx_buff)[i++]);
557 }
558 break;
559 default:
560 for(index = 0; index < fifo_len; index++)
561 sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_DR), tx_buff[i++]);
562 break;
563 }
564 tx_len -= fifo_len;
565 }
566}
567
568/*
569 * SPI送信実行関数
570 * parameter1 hspi: SPIハンドラへのポインタ
571 * parameter2 ss_no: SS番号
572 * parameter3 pdata: 送信バッファへのポインタ
573 * parameter4 length: 送信サイズ
574 * return ERコード
575 */
576ER
577spi_core_transmit(SPI_Handle_t *hspi, int8_t ss_no, uint8_t *pdata, uint16_t length)
578{
579 DMA_Handle_t *hdma;
580 ER ercd = E_OK;
581
582 if(hspi == NULL)
583 return E_PAR;
584
585 if(hspi->Init.semlock != 0)
586 wai_sem(hspi->Init.semlock);
587 hspi->xmode = SPI_XMODE_TX;
588 spi_set_tmod(hspi, SPI_TMOD_TRANS);
589 if(hspi->hdmatx != NULL){
590 sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_DMACR), SPI_DMACR_TXENABLE);
591 sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_SSIENR), SPI_SSIENR_ENABLE);
592 hdma = spi_dmac_set_single_mode(hspi, 0, ss_no, (const void *)pdata,
593 (void *)(hspi->base+TOFF_SPI_DR), DMAC_ADDR_INCREMENT, DMAC_ADDR_NOCHANGE,
594 DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, length);
595 spi_dmac_wait_done(hdma);
596 }
597 else{
598 spi_send_data_normal2(hspi, ss_no, (const void *)pdata, length);
599 }
600
601#if SPI_WAIT_TIME != 0
602 ercd = spi_inwait(hspi, SPI_WAIT_TIME * length);
603
604 if(hspi->Init.semlock != 0)
605 sig_sem(hspi->Init.semlock);
606#endif
607 return ercd;
608}
609
610/*
611 * SPIフィル送信実行関数
612 * parameter1 hspi: SPIハンドラへのポインタ
613 * parameter2 ss_no: SS番号
614 * parameter3 pdata: 送信バッファへのポインタ
615 * parameter4 length: 送信サイズ
616 * return ERコード
617 */
618ER
619spi_core_transmit_fill(SPI_Handle_t *hspi, int8_t ss_no, const uint32_t *tx_buff, size_t tx_len)
620{
621 DMA_Handle_t *hdmatx;
622 ER ercd = E_OK;
623
624 if(hspi == NULL)
625 return E_PAR;
626
627 if(hspi->Init.semlock != 0)
628 wai_sem(hspi->Init.semlock);
629
630 hspi->xmode = SPI_XMODE_TX;
631 spi_set_tmod(hspi, SPI_TMOD_TRANS);
632 sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_DMACR), SPI_DMACR_TXENABLE);
633 sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_SSIENR), SPI_SSIENR_ENABLE);
634
635 hdmatx = spi_dmac_set_single_mode(hspi, 0, ss_no, tx_buff, (void *)(hspi->base+TOFF_SPI_DR), DMAC_ADDR_NOCHANGE, DMAC_ADDR_NOCHANGE,
636 DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, tx_len);
637 spi_dmac_wait_done(hdmatx);
638
639#if SPI_WAIT_TIME != 0
640 ercd = spi_inwait(hspi, SPI_WAIT_TIME * tx_len);
641
642 if(hspi->Init.semlock != 0)
643 sig_sem(hspi->Init.semlock);
644#endif
645 return ercd;
646}
647
648/*
649 * SPI受信実行関数
650 * parameter1 hspi: SPIハンドラへのポインタ
651 * parameter2 ss_no: SS番号
652 * parameter3 pdata: 受信バッファへのポインタ
653 * parameter4 length: 受信サイズ
654 * return ERコード
655 */
656ER
657spi_core_receive(SPI_Handle_t *hspi, int8_t ss_no, void *rx_buff, size_t rx_len)
658{
659 DMA_Handle_t * hdmarx;
660 ER ercd = E_OK;
661
662 if(hspi == NULL || hspi->spi_num == 2)
663 return E_PAR;
664
665 if(hspi->Init.semlock != 0)
666 wai_sem(hspi->Init.semlock);
667
668 hspi->xmode = SPI_XMODE_RX;
669 spi_set_tmod(hspi, SPI_TMOD_RECV);
670
671 sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_CTRLR1), (rx_len - 1));
672 sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_DMACR), SPI_DMACR_RXENABLE);
673 sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_SSIENR), SPI_SSIENR_ENABLE);
674
675 hdmarx = spi_dmac_set_single_mode(hspi, 1, ss_no, (void *)(hspi->base+TOFF_SPI_DR), rx_buff, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
676 DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, rx_len);
677 if(hspi->Init.FrameFormat == SPI_FF_STANDARD)
678 sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_DR), 0xFFFFFFFF);
679 spi_dmac_wait_done(hdmarx);
680
681 sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_SER), 0x00000000);
682 sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_SSIENR), SPI_SSIENR_DISABLE);
683
684#if SPI_WAIT_TIME != 0
685 ercd = spi_inwait(hspi, SPI_WAIT_TIME * rx_len);
686
687 if(hspi->Init.semlock != 0)
688 sig_sem(hspi->Init.semlock);
689#endif
690 return ercd;
691}
692
693/*
694 * SPI送受信実行関数
695 * parameter1 hspi: SPIハンドラへのポインタ
696 * parameter2 ss_no: SS番号
697 * parameter3 ptxdata: 送信バッファへのポインタ
698 * parameter4 prxdata: 受信バッファへのポインタ
699 * parameter5 length: 送受信サイズ
700 * return ERコード
701 */
702ER
703spi_core_transrecv(SPI_Handle_t *hspi, int8_t ss_no, const uint8_t *tx_buf, uint8_t *rx_buf, size_t len)
704{
705 DMA_Handle_t * hdmarx, *hdmatx;
706 uint8_t frame_width = get_framewidth(hspi->Init.DataSize);
707 size_t v_len = len / frame_width;
708 ER ercd = E_OK;
709
710 if(hspi == NULL)
711 return E_PAR;
712
713 if(hspi->Init.semlock != 0)
714 wai_sem(hspi->Init.semlock);
715
716 hspi->xmode = SPI_XMODE_TXRX;
717 spi_set_tmod(hspi, SPI_TMOD_TRANS_RECV);
718
719
720 if(hspi->hdmatx != NULL){
721 sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_DMACR), (SPI_DMACR_TXENABLE | SPI_DMACR_RXENABLE));
722 sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_SSIENR), SPI_SSIENR_ENABLE);
723
724 hdmarx = spi_dmac_set_single_mode(hspi, 1, ss_no, (void *)(hspi->base+TOFF_SPI_DR), rx_buf, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
725 DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, v_len);
726 hdmatx = spi_dmac_set_single_mode(hspi, 0, -1, tx_buf, (void *)(hspi->base+TOFF_SPI_DR), DMAC_ADDR_INCREMENT, DMAC_ADDR_NOCHANGE,
727 DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, v_len);
728
729 spi_dmac_wait_done(hdmatx);
730 }
731 else{
732 sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_DMACR), SPI_DMACR_RXENABLE);
733 sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_SSIENR), SPI_SSIENR_ENABLE);
734
735 hdmarx = spi_dmac_set_single_mode(hspi, 1, ss_no, (void *)(hspi->base+TOFF_SPI_DR), rx_buf, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
736 DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, v_len);
737 spi_send_data_normal2(hspi, -1, (const void *)tx_buf, len);
738 }
739 spi_dmac_wait_done(hdmarx);
740
741 sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_SER), 0x00000000);
742 sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_SSIENR), SPI_SSIENR_DISABLE);
743
744#if SPI_WAIT_TIME != 0
745 ercd = spi_inwait(hspi, SPI_WAIT_TIME * len);
746
747 if(hspi->Init.semlock != 0)
748 sig_sem(hspi->Init.semlock);
749#endif
750 return ercd;
751}
752
753/*
754 * SPI転送終了待ち
755 */
756ER
757spi_wait(SPI_Handle_t *hspi, uint32_t timeout)
758{
759 ER ercd = E_OK;
760
761#if SPI_WAIT_TIME == 0
762 if(hspi == NULL)
763 return E_PAR;
764 ercd = spi_inwait(hspi, timeout);
765 if(hspi->Init.semlock != 0)
766 sig_sem(hspi->Init.semlock);
767#endif
768 return ercd;
769}
770
771
772/*
773 * SPI割込みサービスルーチン
774 */
775void
776spi_handler(SPI_Handle_t *hspi)
777{
778 volatile uint32_t imr, isr, tmp;
779
780 imr = sil_rew_mem((uint32_t *)(hspi->base+TOFF_SPI_IMR));
781 isr = sil_rew_mem((uint32_t *)(hspi->base+TOFF_SPI_ISR));
782 sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_IMR), 0);
783
784 syslog_2(LOG_DEBUG, "spi_handler imr[%08x] isr[%08x]", imr, isr);
785 tmp = sil_rew_mem((uint32_t *)(hspi->base+TOFF_SPI_ICR));
786 if(hspi->Init.semid != 0)
787 isig_sem(hspi->Init.semid);
788 (void)(tmp);
789}
790
791/*
792 * SPI割込みサービスルーチン
793 */
794void spi_isr(intptr_t exinf)
795{
796 spi_handler(&SpiHandle[INDEX_SPI((uint32_t)exinf)]);
797}
798
799
Note: See TracBrowser for help on using the repository browser.