1 /**
2 * \file
3 *
4 * \brief Matrix driver for SAM.
5 *
6 * Copyright (c) 2012-2015 Atmel Corporation. All rights reserved.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 *
22 * 3. The name of Atmel may not be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * 4. This software may only be redistributed and used in connection with an
26 * Atmel microcontroller product.
27 *
28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *
40 * \asf_license_stop
41 *
42 */
43 /*
44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45 */
46
47 #include "matrix.h"
48
49 /* / @cond 0 */
50 /**INDENT-OFF**/
51 #ifdef __cplusplus
52 extern "C" {
53 #endif
54 /**INDENT-ON**/
55 /* / @endcond */
56
57 /**
58 * \defgroup sam_drivers_matrix_group Matrix (MATRIX)
59 *
60 * \par Purpose
61 *
62 * The Bus Matrix implements a multi-layer AHB that enables parallel access
63 * paths between multiple AHB masters and slaves in a system, which increases
64 * the overall bandwidth.
65 *
66 * @{
67 */
68
69 #if SAM4C
70 #ifdef SAM4C_0
71 #define MATRIX MATRIX0
72 #else
73 #define MATRIX MATRIX1
74 #endif
75 #endif
76
77 #if SAM4CP
78 #ifdef SAM4CP_0
79 #define MATRIX MATRIX0
80 #else
81 #define MATRIX MATRIX1
82 #endif
83 #endif
84
85 #if SAM4CM
86 #ifdef SAM4CM_0
87 #define MATRIX MATRIX0
88 #else
89 #define MATRIX MATRIX1
90 #endif
91 #endif
92
93 #ifndef MATRIX_WPMR_WPKEY_PASSWD
94 #define MATRIX_WPMR_WPKEY_PASSWD MATRIX_WPMR_WPKEY(0x4D4154U)
95 #endif
96
97 /**
98 * \brief Set undefined length burst type of the specified master.
99 *
100 * \param ul_id Master index.
101 * \param burst_type Undefined length burst type.
102 */
matrix_set_master_burst_type(uint32_t ul_id,burst_type_t burst_type)103 void matrix_set_master_burst_type(uint32_t ul_id, burst_type_t burst_type)
104 {
105 #if (SAMV70 || SAMS70|| SAME70)
106 Matrix *p_matrix = MATRIX;
107 volatile uint32_t *p_MCFG;
108 volatile uint32_t ul_reg;
109 uint32_t ul_dlt;
110
111 ul_dlt = (uint32_t)&(p_matrix->MATRIX_MCFG1);
112 ul_dlt = ul_dlt - (uint32_t)&(p_matrix->MATRIX_MCFG0);
113
114 p_MCFG = (volatile uint32_t *)((uint32_t)&(p_matrix->MATRIX_MCFG0) +
115 ul_id * ul_dlt);
116
117 ul_reg = *p_MCFG & (~MATRIX_MCFG0_ULBT_Msk);
118 *p_MCFG = ul_reg | (uint32_t)burst_type;
119 #else
120 Matrix *p_matrix = MATRIX;
121 volatile uint32_t ul_reg;
122
123 ul_reg = p_matrix->MATRIX_MCFG[ul_id] & (~MATRIX_MCFG_ULBT_Msk);
124 p_matrix->MATRIX_MCFG[ul_id] = ul_reg | (uint32_t)burst_type;
125 #endif
126 }
127
128 /**
129 * \brief Get undefined length burst type of the specified master.
130 *
131 * \param ul_id Master index.
132 *
133 * \return Undefined length burst type.
134 */
matrix_get_master_burst_type(uint32_t ul_id)135 burst_type_t matrix_get_master_burst_type(uint32_t ul_id)
136 {
137 #if (SAMV70 || SAMS70|| SAME70)
138 Matrix *p_matrix = MATRIX;
139 volatile uint32_t *p_MCFG;
140 volatile uint32_t ul_reg;
141 uint32_t ul_dlt;
142
143 ul_dlt = (uint32_t)&(p_matrix->MATRIX_MCFG1);
144 ul_dlt = ul_dlt - (uint32_t)&(p_matrix->MATRIX_MCFG0);
145
146 p_MCFG = (volatile uint32_t *)((uint32_t)&(p_matrix->MATRIX_MCFG0) +
147 ul_id * ul_dlt);
148
149 ul_reg = *p_MCFG & (~MATRIX_MCFG0_ULBT_Msk);
150 return (burst_type_t)ul_reg;
151 #else
152 Matrix *p_matrix = MATRIX;
153 volatile uint32_t ul_reg;
154
155 ul_reg = p_matrix->MATRIX_MCFG[ul_id] & (MATRIX_MCFG_ULBT_Msk);
156 return (burst_type_t)ul_reg;
157 #endif
158 }
159
160 /**
161 * \brief Set slot cycle of the specified slave.
162 *
163 * \param ul_id Slave index.
164 * \param ul_slot_cycle Number of slot cycle.
165 */
matrix_set_slave_slot_cycle(uint32_t ul_id,uint32_t ul_slot_cycle)166 void matrix_set_slave_slot_cycle(uint32_t ul_id, uint32_t ul_slot_cycle)
167 {
168 Matrix *p_matrix = MATRIX;
169 volatile uint32_t ul_reg;
170
171 ul_reg = p_matrix->MATRIX_SCFG[ul_id] & (~MATRIX_SCFG_SLOT_CYCLE_Msk);
172 p_matrix->MATRIX_SCFG[ul_id] = ul_reg | MATRIX_SCFG_SLOT_CYCLE(
173 ul_slot_cycle);
174 }
175
176 /**
177 * \brief Get slot cycle of the specified slave.
178 *
179 * \param ul_id Slave index.
180 *
181 * \return Number of slot cycle.
182 */
matrix_get_slave_slot_cycle(uint32_t ul_id)183 uint32_t matrix_get_slave_slot_cycle(uint32_t ul_id)
184 {
185 Matrix *p_matrix = MATRIX;
186 volatile uint32_t ul_reg;
187
188 ul_reg = p_matrix->MATRIX_SCFG[ul_id] & (MATRIX_SCFG_SLOT_CYCLE_Msk);
189 return (ul_reg >> MATRIX_SCFG_SLOT_CYCLE_Pos);
190 }
191
192 /**
193 * \brief Set default master type of the specified slave.
194 *
195 * \param ul_id Slave index.
196 * \param type Default master type.
197 */
matrix_set_slave_default_master_type(uint32_t ul_id,defaut_master_t type)198 void matrix_set_slave_default_master_type(uint32_t ul_id, defaut_master_t type)
199 {
200 Matrix *p_matrix = MATRIX;
201 volatile uint32_t ul_reg;
202
203 ul_reg = p_matrix->MATRIX_SCFG[ul_id] & (~MATRIX_SCFG_DEFMSTR_TYPE_Msk);
204 p_matrix->MATRIX_SCFG[ul_id] = ul_reg | (uint32_t)type;
205 }
206
207 /**
208 * \brief Get default master type of the specified slave.
209 *
210 * \param ul_id Slave index.
211 *
212 * \return Default master type.
213 */
matrix_get_slave_default_master_type(uint32_t ul_id)214 defaut_master_t matrix_get_slave_default_master_type(uint32_t ul_id)
215 {
216 Matrix *p_matrix = MATRIX;
217 volatile uint32_t ul_reg;
218
219 ul_reg = p_matrix->MATRIX_SCFG[ul_id] & (MATRIX_SCFG_DEFMSTR_TYPE_Msk);
220 return (defaut_master_t)ul_reg;
221 }
222
223 /**
224 * \brief Set fixed default master of the specified slave.
225 *
226 * \param ul_id Slave index.
227 * \param ul_fixed_id Fixed default master index.
228 */
matrix_set_slave_fixed_default_master(uint32_t ul_id,uint32_t ul_fixed_id)229 void matrix_set_slave_fixed_default_master(uint32_t ul_id, uint32_t ul_fixed_id)
230 {
231 Matrix *p_matrix = MATRIX;
232 volatile uint32_t ul_reg;
233
234 ul_reg = p_matrix->MATRIX_SCFG[ul_id] &
235 (~MATRIX_SCFG_FIXED_DEFMSTR_Msk);
236 p_matrix->MATRIX_SCFG[ul_id]
237 = ul_reg | MATRIX_SCFG_FIXED_DEFMSTR(ul_fixed_id);
238 }
239
240 /**
241 * \brief Get fixed default master of the specified slave.
242 *
243 * \param ul_id Slave index.
244 *
245 * \return Fixed default master index.
246 */
matrix_get_slave_fixed_default_master(uint32_t ul_id)247 uint32_t matrix_get_slave_fixed_default_master(uint32_t ul_id)
248 {
249 Matrix *p_matrix = MATRIX;
250 volatile uint32_t ul_reg;
251
252 ul_reg = p_matrix->MATRIX_SCFG[ul_id] & (MATRIX_SCFG_FIXED_DEFMSTR_Msk);
253 return (ul_reg >> MATRIX_SCFG_FIXED_DEFMSTR_Pos);
254 }
255
256 #if !SAM4E && !SAM4C && !SAM4CP && !SAM4CM && \
257 !SAMV71 && !SAMV70 && !SAMS70 && !SAME70
258 /**
259 * \brief Set slave arbitration type of the specified slave.
260 *
261 * \param ul_id Slave index.
262 * \param type Arbitration type.
263 */
matrix_set_slave_arbitration_type(uint32_t ul_id,arbitration_type_t type)264 void matrix_set_slave_arbitration_type(uint32_t ul_id, arbitration_type_t type)
265 {
266 Matrix *p_matrix = MATRIX;
267 volatile uint32_t ul_reg;
268
269 ul_reg = p_matrix->MATRIX_SCFG[ul_id] & (~MATRIX_SCFG_ARBT_Msk);
270 p_matrix->MATRIX_SCFG[ul_id] = ul_reg | (uint32_t)type;
271 }
272
273 /**
274 * \brief Get slave arbitration type of the specified slave.
275 *
276 * \param ul_id Slave index.
277 *
278 * \return Arbitration type.
279 */
matrix_get_slave_arbitration_type(uint32_t ul_id)280 arbitration_type_t matrix_get_slave_arbitration_type(uint32_t ul_id)
281 {
282 Matrix *p_matrix = MATRIX;
283 volatile uint32_t ul_reg;
284
285 ul_reg = p_matrix->MATRIX_SCFG[ul_id] & (MATRIX_SCFG_ARBT_Msk);
286 return (arbitration_type_t)ul_reg;
287 }
288
289 #endif
290
291 /**
292 * \brief Set priority for the specified slave access.
293 *
294 * \param ul_id Slave index.
295 * \param ul_prio Bitmask OR of priorities of master x.
296 */
matrix_set_slave_priority(uint32_t ul_id,uint32_t ul_prio)297 void matrix_set_slave_priority(uint32_t ul_id, uint32_t ul_prio)
298 {
299 #if (SAMV71 || SAMV70|| SAME70)
300 Matrix *p_matrix = MATRIX;
301 p_matrix->MATRIX_PR[ul_id].MATRIX_PRAS = ul_prio;
302 #else
303 Matrix *p_matrix = MATRIX;
304 volatile uint32_t *p_PRAS;
305 uint32_t ul_dlt;
306
307 ul_dlt = (uint32_t)&(p_matrix->MATRIX_PRAS1);
308 ul_dlt = ul_dlt - (uint32_t)&(p_matrix->MATRIX_PRAS0);
309
310 p_PRAS = (volatile uint32_t *)((uint32_t)&(p_matrix->MATRIX_PRAS0) +
311 ul_id * ul_dlt);
312
313 *p_PRAS = ul_prio;
314 #endif
315 }
316
317 /**
318 * \brief Get priority for the specified slave access.
319 *
320 * \param ul_id Slave index.
321 *
322 * \return Bitmask OR of priorities of master x.
323 */
matrix_get_slave_priority(uint32_t ul_id)324 uint32_t matrix_get_slave_priority(uint32_t ul_id)
325 {
326 #if (SAMV71 || SAMV70|| SAME70)
327 Matrix *p_matrix = MATRIX;
328 return p_matrix->MATRIX_PR[ul_id].MATRIX_PRAS;
329 #else
330 Matrix *p_matrix = MATRIX;
331 volatile uint32_t *p_PRAS;
332 uint32_t ul_dlt;
333
334 ul_dlt = (uint32_t)&(p_matrix->MATRIX_PRAS1);
335 ul_dlt = ul_dlt - (uint32_t)&(p_matrix->MATRIX_PRAS0);
336
337 p_PRAS = (volatile uint32_t *)((uint32_t)&(p_matrix->MATRIX_PRAS0) +
338 ul_id * ul_dlt);
339
340 return (*p_PRAS);
341 #endif
342 }
343
344 #if (SAMV71 || SAMV70|| SAME70 || SAMS70)
345 /**
346 * \brief Set priority for the specified slave access.
347 *
348 * \param ul_id Slave index.
349 * \param ul_prio_b Bitmask OR of priorities of master x.
350 */
matrix_set_slave_priority_b(uint32_t ul_id,uint32_t ul_prio_b)351 void matrix_set_slave_priority_b(uint32_t ul_id, uint32_t ul_prio_b)
352 {
353 #if (SAMV71 || SAMV70|| SAME70)
354 Matrix *p_matrix = MATRIX;
355 p_matrix->MATRIX_PR[ul_id].MATRIX_PRBS = ul_prio_b;
356 #else
357 Matrix *p_matrix = MATRIX;
358 volatile uint32_t *p_PRAS;
359 uint32_t ul_dlt;
360
361 ul_dlt = (uint32_t)&(p_matrix->MATRIX_PRBS1);
362 ul_dlt = ul_dlt - (uint32_t)&(p_matrix->MATRIX_PRBS0);
363
364 p_PRAS = (volatile uint32_t *)((uint32_t)&(p_matrix->MATRIX_PRBS0) +
365 ul_id * ul_dlt);
366
367 *p_PRAS = ul_prio;
368 #endif
369 }
370
371 /**
372 * \brief Get priority for the specified slave access.
373 *
374 * \param ul_id Slave index.
375 *
376 * \return Bitmask OR of priorities of master x.
377 */
matrix_get_slave_priority_b(uint32_t ul_id)378 uint32_t matrix_get_slave_priority_b(uint32_t ul_id)
379 {
380 #if (SAMV71 || SAMV70|| SAME70)
381 Matrix *p_matrix = MATRIX;
382 return p_matrix->MATRIX_PR[ul_id].MATRIX_PRBS;
383 #else
384 Matrix *p_matrix = MATRIX;
385 volatile uint32_t *p_PRAS;
386 uint32_t ul_dlt;
387
388 ul_dlt = (uint32_t)&(p_matrix->MATRIX_PRBS1);
389 ul_dlt = ul_dlt - (uint32_t)&(p_matrix->MATRIX_PRBS0);
390
391 p_PRAS = (volatile uint32_t *)((uint32_t)&(p_matrix->MATRIX_PRBS0) +
392 ul_id * ul_dlt);
393
394 return (*p_PRAS);
395 #endif
396 }
397 #endif
398
399 #if (SAM3XA || SAM3U || SAM4E ||\
400 SAMV71 || SAMV70 || SAMS70 || SAME70)
401 /**
402 * \brief Set bus matrix master remap.
403 *
404 * \param ul_remap Bitmask OR of RCBx: 0 for disable, 1 for enable.
405 */
matrix_set_master_remap(uint32_t ul_remap)406 void matrix_set_master_remap(uint32_t ul_remap)
407 {
408 Matrix *p_matrix = MATRIX;
409
410 p_matrix->MATRIX_MRCR = ul_remap;
411 }
412
413 /**
414 * \brief Get bus matrix master remap.
415 *
416 * \return Bitmask OR of RCBx: 0 for disable, 1 for enable.
417 */
matrix_get_master_remap(void)418 uint32_t matrix_get_master_remap(void)
419 {
420 Matrix *p_matrix = MATRIX;
421
422 return (p_matrix->MATRIX_MRCR);
423 }
424
425 #endif
426
427 #if (SAM3S || SAM3XA || SAM3N || SAM4S || SAM4E || SAM4N || SAM4C || SAMG || SAM4CP || SAM4CM || \
428 SAMV71 || SAMV70 || SAMS70 || SAME70)
429 /**
430 * \brief Set system IO.
431 *
432 * \param ul_io Bitmask OR of SYSIOx.
433 */
matrix_set_system_io(uint32_t ul_io)434 void matrix_set_system_io(uint32_t ul_io)
435 {
436 Matrix *p_matrix = MATRIX;
437
438 #if (SAM4C || SAM4CP || SAM4CM)
439
440 p_matrix->MATRIX_SYSIO = ul_io;
441
442 #elif (SAMV71 || SAMV70 || SAMS70 || SAME70)
443
444 p_matrix->CCFG_SYSIO &= 0xFFFF0000;
445 p_matrix->CCFG_SYSIO |= (ul_io & 0xFFFF);
446
447 #else
448
449 p_matrix->CCFG_SYSIO = ul_io;
450
451 #endif
452
453 }
454
455 /**
456 * \brief Get system IO.
457 *
458 * \return Bitmask OR of SYSIOx.
459 */
matrix_get_system_io(void)460 uint32_t matrix_get_system_io(void)
461 {
462 Matrix *p_matrix = MATRIX;
463
464 #if (SAM4C || SAM4CP || SAM4CM)
465
466 return (p_matrix->MATRIX_SYSIO);
467
468 #elif (SAMV71 || SAMV70 || SAMS70 || SAME70)
469
470 return (p_matrix->CCFG_SYSIO & 0xFFFF);
471
472 #else
473
474 return (p_matrix->CCFG_SYSIO);
475
476 #endif
477 }
478
479 #endif
480
481 #if (SAM3S || SAM4S || SAM4E || SAM4C || SAM4CP || SAM4CM || \
482 SAMV71 || SAMV70 || SAMS70 || SAME70)
483 /**
484 * \brief Set NAND Flash Chip Select configuration register.
485 *
486 * \param ul_cs Bitmask OR of SMC_NFCSx: 0 if NCSx is not assigned,
487 * 1 if NCSx is assigned.
488 */
matrix_set_nandflash_cs(uint32_t ul_cs)489 void matrix_set_nandflash_cs(uint32_t ul_cs)
490 {
491 Matrix *p_matrix = MATRIX;
492
493
494 #if (SAM4C || SAM4CP || SAM4CM)
495
496 p_matrix->MATRIX_SMCNFCS = ul_cs;
497
498 #else
499
500 p_matrix->CCFG_SMCNFCS = ul_cs;
501
502 #endif
503 }
504
505 /**
506 * \brief Get NAND Flash Chip Select configuration register.
507 *
508 * \return Bitmask OR of SMC_NFCSx.
509 */
matrix_get_nandflash_cs(void)510 uint32_t matrix_get_nandflash_cs(void)
511 {
512 Matrix *p_matrix = MATRIX;
513
514 #if (SAM4C || SAM4CP || SAM4CM)
515
516 return (p_matrix->MATRIX_SMCNFCS);
517
518 #else
519
520 return (p_matrix->CCFG_SMCNFCS);
521
522 #endif
523 }
524
525 #endif
526
527 #if (!SAMG)
528 /**
529 * \brief Enable or disable write protect of MATRIX registers.
530 *
531 * \param ul_enable 1 to enable, 0 to disable.
532 */
matrix_set_writeprotect(uint32_t ul_enable)533 void matrix_set_writeprotect(uint32_t ul_enable)
534 {
535 Matrix *p_matrix = MATRIX;
536
537 if (ul_enable) {
538 p_matrix->MATRIX_WPMR = MATRIX_WPMR_WPKEY_PASSWD | MATRIX_WPMR_WPEN;
539 } else {
540 p_matrix->MATRIX_WPMR = MATRIX_WPMR_WPKEY_PASSWD;
541 }
542 }
543
544 /**
545 * \brief Get write protect status.
546 *
547 * \return Write protect status.
548 */
matrix_get_writeprotect_status(void)549 uint32_t matrix_get_writeprotect_status(void)
550 {
551 Matrix *p_matrix = MATRIX;
552
553 return (p_matrix->MATRIX_WPSR);
554 }
555 #endif
556
557 #if SAMG55
558 /**
559 * \brief Set USB device mode.
560 *
561 */
matrix_set_usb_device(void)562 void matrix_set_usb_device(void)
563 {
564 Matrix *p_matrix = MATRIX;
565
566 p_matrix->CCFG_SYSIO &= ~(CCFG_SYSIO_SYSIO10 | CCFG_SYSIO_SYSIO11);
567
568 p_matrix->CCFG_USBMR |= CCFG_USBMR_DEVICE;
569 }
570
571 /**
572 * \brief Set USB device mode.
573 *
574 */
matrix_set_usb_host(void)575 void matrix_set_usb_host(void)
576 {
577 Matrix *p_matrix = MATRIX;
578
579 p_matrix->CCFG_SYSIO &= ~(CCFG_SYSIO_SYSIO10 | CCFG_SYSIO_SYSIO11);
580
581 p_matrix->CCFG_USBMR &= ~CCFG_USBMR_DEVICE;
582 }
583 #endif
584
585 #if (SAMV71 || SAMV70|| SAME70)
586 /**
587 * \brief Set CAN0 DMA base address.
588 *
589 * \param base_addr the 16-bit MSB of the CAN0 DMA base address.
590 */
matrix_set_can0_addr(uint32_t base_addr)591 void matrix_set_can0_addr(uint32_t base_addr)
592 {
593 Matrix *p_matrix = MATRIX;
594 p_matrix->CCFG_CAN0 = CCFG_CAN0_CAN0DMABA(base_addr);
595 }
596
597 /**
598 * \brief Set CAN1 DMA base address.
599 *
600 * \param base_addr the 16-bit MSB of the CAN1 DMA base address.
601 */
matrix_set_can1_addr(uint32_t base_addr)602 void matrix_set_can1_addr(uint32_t base_addr)
603 {
604 Matrix *p_matrix = MATRIX;
605 volatile uint32_t ul_reg;
606
607 ul_reg = p_matrix->CCFG_SYSIO & (~CCFG_SYSIO_CAN1DMABA_Msk);
608 p_matrix->CCFG_SYSIO = ul_reg | CCFG_SYSIO_CAN1DMABA(base_addr);
609 }
610 #endif
611
612 /* @} */
613
614 /* / @cond 0 */
615 /**INDENT-OFF**/
616 #ifdef __cplusplus
617 }
618 #endif
619 /**INDENT-ON**/
620 /* / @endcond */
621