source: asp3_tinet_ecnl_arm/trunk/asp3_dcre/mbed/targets/TARGET_RENESAS/TARGET_RZ_A1H/spi_api.c@ 364

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

TINETとSocket APIなどを更新

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