source: asp3_tinet_ecnl_arm/trunk/asp3_dcre/mbed/targets/TARGET_RENESAS/TARGET_RZA1XX/spi_api.c

Last change on this file was 374, checked in by coas-nagasima, 5 years ago

mbed関連を更新
シリアルドライバをmbedのHALを使うよう変更
ファイルディスクリプタの処理を更新

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 15.2 KB
Line 
1/* mbed Microcontroller Library
2 * Copyright (c) 2006-2013 ARM Limited
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#include "mbed_assert.h"
17#include <math.h>
18
19#include "spi_api.h"
20#include "cmsis.h"
21#include "PeripheralPins.h"
22#include "mbed_error.h"
23#include "RZ_A1_Init.h"
24#include "mbed_drv_cfg.h"
25
26static const struct st_rspi *RSPI[] = RSPI_ADDRESS_LIST;
27
28static inline void spi_disable(spi_t *obj);
29static inline void spi_enable(spi_t *obj);
30static inline int spi_readable(spi_t *obj);
31static inline void spi_write(spi_t *obj, int value);
32static inline int spi_read(spi_t *obj);
33
34void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) {
35 // determine the SPI to use
36 volatile uint8_t dummy;
37 uint32_t spi_mosi = pinmap_peripheral(mosi, PinMap_SPI_MOSI);
38 uint32_t spi_miso = pinmap_peripheral(miso, PinMap_SPI_MISO);
39 uint32_t spi_sclk = pinmap_peripheral(sclk, PinMap_SPI_SCLK);
40 uint32_t spi_ssel = pinmap_peripheral(ssel, PinMap_SPI_SSEL);
41 uint32_t spi_data = pinmap_merge(spi_mosi, spi_miso);
42 uint32_t spi_cntl = pinmap_merge(spi_sclk, spi_ssel);
43 uint32_t spi = pinmap_merge(spi_data, spi_cntl);
44
45 MBED_ASSERT((int)spi != NC);
46
47 obj->spi.spi = (struct st_rspi *)RSPI[spi];
48 obj->spi.index = spi;
49
50 // enable power and clocking
51 CPGSTBCR10 &= ~(0x80 >> spi);
52 dummy = CPGSTBCR10;
53 (void)dummy;
54
55 obj->spi.spi->SPCR = 0x00; // CTRL to 0
56 obj->spi.spi->SPSCR = 0x00; // no sequential operation
57 obj->spi.spi->SSLP = 0x00; // SSL 'L' active
58 obj->spi.spi->SPDCR = 0x20; // byte access
59 obj->spi.spi->SPCKD = 0x00; // SSL -> enable CLK delay : 1RSPCK
60 obj->spi.spi->SSLND = 0x00; // CLK end -> SSL neg delay : 1RSPCK
61 obj->spi.spi->SPND = 0x00; // delay between CMD : 1RSPCK + 2P1CLK
62 obj->spi.spi->SPPCR = 0x20; // MOSI Idle fixed value equals 0
63 obj->spi.spi->SPBFCR = 0xf0; // and set trigger count: read 1, write 1
64 obj->spi.spi->SPBFCR = 0x30; // and reset buffer
65
66 // pin out the spi pins
67 pinmap_pinout(mosi, PinMap_SPI_MOSI);
68 pinmap_pinout(miso, PinMap_SPI_MISO);
69 pinmap_pinout(sclk, PinMap_SPI_SCLK);
70 if ((int)ssel != NC) {
71 pinmap_pinout(ssel, PinMap_SPI_SSEL);
72 }
73}
74
75void spi_free(spi_t *obj) {}
76
77void spi_format(spi_t *obj, int bits, int mode, int slave) {
78 int DSS; // DSS (data select size)
79 int polarity = (mode & 0x2) ? 1 : 0;
80 int phase = (mode & 0x1) ? 1 : 0;
81 uint16_t tmp = 0;
82 uint16_t mask = 0xf03;
83 uint16_t wk_spcmd0;
84 uint8_t splw;
85
86 switch (mode) {
87 case 0:
88 case 1:
89 case 2:
90 case 3:
91 // Do Nothing
92 break;
93 default:
94 error("SPI format error");
95 return;
96 }
97
98 switch (bits) {
99 case 8:
100 DSS = 0x7;
101 splw = 0x20;
102 break;
103 case 16:
104 DSS = 0xf;
105 splw = 0x40;
106 break;
107 case 32:
108 DSS = 0x2;
109 splw = 0x60;
110 break;
111 default:
112 error("SPI module don't support other than 8/16/32bits");
113 return;
114 }
115 tmp |= phase;
116 tmp |= (polarity << 1);
117 tmp |= (DSS << 8);
118 obj->spi.bits = bits;
119
120 spi_disable(obj);
121 wk_spcmd0 = obj->spi.spi->SPCMD0;
122 wk_spcmd0 &= ~mask;
123 wk_spcmd0 |= (mask & tmp);
124 obj->spi.spi->SPCMD0 = wk_spcmd0;
125 obj->spi.spi->SPDCR = splw;
126 if (slave) {
127 obj->spi.spi->SPCR &=~(1 << 3); // MSTR to 0
128 } else {
129 obj->spi.spi->SPCR |= (1 << 3); // MSTR to 1
130 }
131 spi_enable(obj);
132}
133
134void spi_frequency(spi_t *obj, int hz) {
135 uint32_t pclk_base;
136 uint32_t div;
137 uint32_t brdv = 0;
138 uint32_t hz_max;
139 uint32_t hz_min;
140 uint16_t mask = 0x000c;
141 uint16_t wk_spcmd0;
142
143 /* set PCLK */
144 if (RZ_A1_IsClockMode0() == false) {
145 pclk_base = CM1_RENESAS_RZ_A1_P1_CLK;
146 } else {
147 pclk_base = CM0_RENESAS_RZ_A1_P1_CLK;
148 }
149
150 hz_min = pclk_base / 2 / 256 / 8;
151 hz_max = pclk_base / 2;
152 if (((uint32_t)hz < hz_min) || ((uint32_t)hz > hz_max)) {
153 error("Couldn't setup requested SPI frequency");
154 return;
155 }
156
157 div = (pclk_base / hz / 2);
158 while (div > 256) {
159 div >>= 1;
160 brdv++;
161 }
162 div -= 1;
163 brdv = (brdv << 2);
164
165 spi_disable(obj);
166 obj->spi.spi->SPBR = div;
167 wk_spcmd0 = obj->spi.spi->SPCMD0;
168 wk_spcmd0 &= ~mask;
169 wk_spcmd0 |= (mask & brdv);
170 obj->spi.spi->SPCMD0 = wk_spcmd0;
171 spi_enable(obj);
172}
173
174static inline void spi_disable(spi_t *obj) {
175 obj->spi.spi->SPCR &= ~(1 << 6); // SPE to 0
176}
177
178static inline void spi_enable(spi_t *obj) {
179 obj->spi.spi->SPCR |= (1 << 6); // SPE to 1
180}
181
182static inline int spi_readable(spi_t *obj) {
183 return obj->spi.spi->SPSR & (1 << 7); // SPRF
184}
185
186static inline int spi_tend(spi_t *obj) {
187 return obj->spi.spi->SPSR & (1 << 6); // TEND
188}
189
190static inline void spi_write(spi_t *obj, int value) {
191 if (obj->spi.bits == 8) {
192 obj->spi.spi->SPDR.UINT8[0] = (uint8_t)value;
193 } else if (obj->spi.bits == 16) {
194 obj->spi.spi->SPDR.UINT16[0] = (uint16_t)value;
195 } else {
196 obj->spi.spi->SPDR.UINT32 = (uint32_t)value;
197 }
198}
199
200static inline int spi_read(spi_t *obj) {
201 int read_data;
202
203 if (obj->spi.bits == 8) {
204 read_data = obj->spi.spi->SPDR.UINT8[0];
205 } else if (obj->spi.bits == 16) {
206 read_data = obj->spi.spi->SPDR.UINT16[0];
207 } else {
208 read_data = obj->spi.spi->SPDR.UINT32;
209 }
210
211 return read_data;
212}
213
214int spi_master_write(spi_t *obj, int value) {
215 spi_write(obj, value);
216 while(!spi_tend(obj));
217 return spi_read(obj);
218}
219
220int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
221 char *rx_buffer, int rx_length, char write_fill) {
222 int total = (tx_length > rx_length) ? tx_length : rx_length;
223
224 for (int i = 0; i < total; i++) {
225 char out = (i < tx_length) ? tx_buffer[i] : write_fill;
226 char in = spi_master_write(obj, out);
227 if (i < rx_length) {
228 rx_buffer[i] = in;
229 }
230 }
231
232 return total;
233}
234
235int spi_slave_receive(spi_t *obj) {
236 return (spi_readable(obj) && !spi_busy(obj)) ? (1) : (0);
237}
238
239int spi_slave_read(spi_t *obj) {
240 return spi_read(obj);
241}
242
243void spi_slave_write(spi_t *obj, int value) {
244 spi_write(obj, value);
245}
246
247int spi_busy(spi_t *obj) {
248 return 0;
249}
250
251#if DEVICE_SPI_ASYNCH
252
253#define SPI_NUM 5
254#define IRQ_NUM 2
255
256static void spi_irqs_set(spi_t *obj, uint32_t enable);
257static void spi_async_write(spi_t *obj);
258static void spi_async_read(spi_t *obj);
259
260static void spi0_rx_irq(void);
261static void spi0_er_irq(void);
262static void spi1_rx_irq(void);
263static void spi1_er_irq(void);
264static void spi2_rx_irq(void);
265static void spi2_er_irq(void);
266static void spi3_rx_irq(void);
267static void spi3_er_irq(void);
268static void spi4_rx_irq(void);
269static void spi4_er_irq(void);
270
271static const IRQn_Type irq_set_tbl[SPI_NUM][IRQ_NUM] = {
272 {RSPISPRI0_IRQn, RSPISPEI0_IRQn},
273 {RSPISPRI1_IRQn, RSPISPEI1_IRQn},
274 {RSPISPRI2_IRQn, RSPISPEI2_IRQn},
275 {RSPISPRI3_IRQn, RSPISPEI3_IRQn},
276 {RSPISPRI4_IRQn, RSPISPEI4_IRQn},
277};
278
279static const IRQHandler hander_set_tbl[SPI_NUM][IRQ_NUM] = {
280 {spi0_rx_irq, spi0_er_irq},
281 {spi1_rx_irq, spi1_er_irq},
282 {spi2_rx_irq, spi2_er_irq},
283 {spi3_rx_irq, spi3_er_irq},
284 {spi4_rx_irq, spi4_er_irq},
285};
286
287struct spi_global_data_s {
288 spi_t *async_obj;
289 uint32_t async_callback, event, wanted_events;
290};
291
292static struct spi_global_data_s spi_data[SPI_NUM];
293
294static void spi_rx_irq(IRQn_Type irq_num, uint32_t index)
295{
296 spi_t *obj = spi_data[index].async_obj;
297 if (obj->rx_buff.buffer && obj->rx_buff.pos < obj->rx_buff.length) {
298 spi_async_read(obj);
299 } else {
300 if (obj->rx_buff.buffer && obj->tx_buff.buffer && obj->tx_buff.pos < obj->tx_buff.length) {
301 spi_data[obj->spi.index].event = SPI_EVENT_INTERNAL_TRANSFER_COMPLETE;
302 if (spi_data[obj->spi.index].wanted_events & SPI_EVENT_COMPLETE) {
303 spi_data[obj->spi.index].event |= SPI_EVENT_COMPLETE;
304 }
305 spi_irqs_set(obj, 0);
306 spi_data[obj->spi.index].async_obj = NULL;
307 ((void (*)())spi_data[obj->spi.index].async_callback)();
308 return;
309 }
310 spi_read(obj);
311 }
312 if (obj->tx_buff.buffer) {
313 if (obj->tx_buff.pos == obj->tx_buff.length) {
314 spi_data[obj->spi.index].event = SPI_EVENT_INTERNAL_TRANSFER_COMPLETE;
315 if (spi_data[obj->spi.index].wanted_events & SPI_EVENT_COMPLETE) {
316 spi_data[obj->spi.index].event |= SPI_EVENT_COMPLETE;
317 }
318 spi_irqs_set(obj, 0);
319 spi_data[obj->spi.index].async_obj = NULL;
320 ((void (*)())spi_data[obj->spi.index].async_callback)();
321 } else {
322 spi_async_write(obj);
323 }
324 } else {
325 if (obj->rx_buff.pos == obj->rx_buff.length) {
326 spi_data[obj->spi.index].event = SPI_EVENT_INTERNAL_TRANSFER_COMPLETE;
327 if (spi_data[obj->spi.index].wanted_events & SPI_EVENT_COMPLETE) {
328 spi_data[obj->spi.index].event |= SPI_EVENT_COMPLETE;
329 }
330 spi_irqs_set(obj, 0);
331 spi_data[obj->spi.index].async_obj = NULL;
332 ((void (*)())spi_data[obj->spi.index].async_callback)();
333 } else {
334 spi_async_write(obj);
335 }
336 }
337}
338
339static void spi_err_irq(IRQn_Type irq_num, uint32_t index)
340{
341 spi_t *obj = spi_data[index].async_obj;
342 spi_abort_asynch(obj);
343 spi_data[index].event = SPI_EVENT_ERROR;
344 if (spi_data[index].wanted_events & SPI_EVENT_ERROR) {
345 ((void (*)())spi_data[index].async_callback)();
346 }
347}
348
349static void spi0_rx_irq(void) {
350 spi_rx_irq(RSPISPRI0_IRQn, 0);
351}
352static void spi0_er_irq(void) {
353 spi_err_irq(RSPISPEI0_IRQn, 0);
354}
355static void spi1_rx_irq(void) {
356 spi_rx_irq(RSPISPRI1_IRQn, 1);
357}
358static void spi1_er_irq(void) {
359 spi_err_irq(RSPISPEI1_IRQn, 1);
360}
361static void spi2_rx_irq(void) {
362 spi_rx_irq(RSPISPRI2_IRQn, 2);
363}
364static void spi2_er_irq(void) {
365 spi_err_irq(RSPISPEI2_IRQn, 2);
366}
367static void spi3_rx_irq(void) {
368 spi_rx_irq(RSPISPRI3_IRQn, 3);
369}
370static void spi3_er_irq(void) {
371 spi_err_irq(RSPISPEI3_IRQn, 3);
372}
373static void spi4_rx_irq(void) {
374 spi_rx_irq(RSPISPRI4_IRQn, 4);
375}
376static void spi4_er_irq(void) {
377 spi_err_irq(RSPISPEI4_IRQn, 4);
378}
379
380static void spi_irqs_set(spi_t *obj, uint32_t enable)
381{
382 int i;
383 const IRQn_Type *irqTable = irq_set_tbl[obj->spi.index];
384 const IRQHandler *handlerTable = hander_set_tbl[obj->spi.index];
385 for (i = 0; i < IRQ_NUM; ++i) {
386 if (enable) {
387 InterruptHandlerRegister(irqTable[i], handlerTable[i]);
388 GIC_SetPriority(irqTable[i], 5);
389 GIC_SetConfiguration(irqTable[i], 1);
390 GIC_EnableIRQ(irqTable[i]);
391 } else {
392 GIC_DisableIRQ(irqTable[i]);
393 }
394 }
395 if (enable) {
396 obj->spi.spi->SPCR |= (1 << 4) | (1 << 7);
397 } else {
398 obj->spi.spi->SPCR &= ~((1 << 4) | (1 << 7));
399 }
400}
401
402static void spi_async_write(spi_t *obj)
403{
404 uint8_t **width8;
405 uint16_t **width16;
406 uint32_t **width32;
407
408 if (obj->tx_buff.buffer) {
409 switch (obj->tx_buff.width) {
410 case 8:
411 width8 = (uint8_t **)&obj->tx_buff.buffer;
412 spi_write(obj, **width8);
413 ++*width8;
414 obj->tx_buff.pos += sizeof(uint8_t);
415 break;
416
417 case 16:
418 width16 = (uint16_t **)&obj->tx_buff.buffer;
419 spi_write(obj, **width16);
420 ++*width16;
421 obj->tx_buff.pos += sizeof(uint16_t);
422 break;
423
424 case 32:
425 width32 = (uint32_t **)&obj->tx_buff.buffer;
426 spi_write(obj, **width32);
427 ++*width32;
428 obj->tx_buff.pos += sizeof(uint32_t);
429 break;
430
431 default:
432 MBED_ASSERT(0);
433 break;
434 }
435 } else {
436 spi_write(obj, SPI_FILL_WORD);
437 }
438}
439
440static void spi_async_read(spi_t *obj)
441{
442 uint8_t **width8;
443 uint16_t **width16;
444 uint32_t **width32;
445
446 switch (obj->rx_buff.width) {
447 case 8:
448 width8 = (uint8_t **)&obj->rx_buff.buffer;
449 **width8 = spi_read(obj);
450 ++*width8;
451 obj->rx_buff.pos += sizeof(uint8_t);
452 break;
453
454 case 16:
455 width16 = (uint16_t **)&obj->rx_buff.buffer;
456 **width16 = spi_read(obj);
457 ++*width16;
458 obj->rx_buff.pos += sizeof(uint16_t);
459 break;
460
461 case 32:
462 width32 = (uint32_t **)&obj->rx_buff.buffer;
463 **width32 = spi_read(obj);
464 ++*width32;
465 obj->rx_buff.pos += sizeof(uint32_t);
466 break;
467
468 default:
469 MBED_ASSERT(0);
470 break;
471 }
472}
473
474/******************************************************************************
475 * ASYNCHRONOUS HAL
476 ******************************************************************************/
477
478void spi_master_transfer(spi_t *obj, const void *tx, size_t tx_length, void *rx, size_t rx_length, uint8_t bit_width, uint32_t handler, uint32_t event, DMAUsage hint)
479{
480 int i;
481 MBED_ASSERT(obj);
482 MBED_ASSERT(tx || rx);
483 MBED_ASSERT(tx && ! rx ? tx_length : 1);
484 MBED_ASSERT(rx && ! tx ? rx_length : 1);
485 MBED_ASSERT(obj->spi.spi->SPCR & (1 << 3)); /* Slave mode */
486 MBED_ASSERT(bit_width == 8 || bit_width == 16 || bit_width == 32);
487
488 if (tx_length) {
489 obj->tx_buff.buffer = (void *)tx;
490 } else {
491 obj->tx_buff.buffer = NULL;
492 }
493 obj->tx_buff.length = tx_length * bit_width / 8;
494 obj->tx_buff.pos = 0;
495 obj->tx_buff.width = bit_width;
496 if (rx_length) {
497 obj->rx_buff.buffer = rx;
498 } else {
499 obj->rx_buff.buffer = NULL;
500 }
501 obj->rx_buff.length = rx_length * bit_width / 8;
502 obj->rx_buff.pos = 0;
503 obj->rx_buff.width = bit_width;
504 for (i = 0; i < (int)obj->rx_buff.length; i++) {
505 ((uint8_t *)obj->rx_buff.buffer)[i] = SPI_FILL_WORD;
506 }
507
508 spi_data[obj->spi.index].async_callback = handler;
509 spi_data[obj->spi.index].async_obj = obj;
510 spi_data[obj->spi.index].event = 0;
511 spi_data[obj->spi.index].wanted_events = event;
512
513 spi_irqs_set(obj, 1);
514
515 spi_async_write(obj);
516}
517
518uint32_t spi_irq_handler_asynch(spi_t *obj)
519{
520 return spi_data[obj->spi.index].event;
521}
522
523uint8_t spi_active(spi_t *obj)
524{
525 return spi_data[obj->spi.index].async_obj != NULL;
526}
527
528void spi_abort_asynch(spi_t *obj)
529{
530 spi_disable(obj);
531 spi_irqs_set(obj, 0);
532 spi_data[obj->spi.index].async_obj = NULL;
533 spi_enable(obj);
534}
535
536#endif
Note: See TracBrowser for help on using the repository browser.