blob: c985ad02ab6d1feb9f16df69bf0427153a13b6ee [file] [log] [blame]
yu.dongc33b3072024-08-21 23:14:49 -07001/*****************************************************************************
2* Copyright Statement:
3* --------------------
4* This software is protected by Copyright and the information contained
5* herein is confidential. The software may not be copied and the information
6* contained herein may not be used or disclosed except with the written
7* permission of MediaTek Inc. (C) 2018
8*
9* BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
10* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
11* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
12* AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
13* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
14* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
15* NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
16* SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
17* SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
18* THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
19* NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
20* SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
21*
22* BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
23* LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
24* AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
25* OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
26* MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
27*
28* THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
29* WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
30* LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
31* RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
32* THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
33*
34*****************************************************************************/
35/*****************************************************************************
36 *
37 * Filename:
38 * ---------
39 * kal_itc.h
40 *
41 * Project:
42 * --------
43 * UMOLYE
44 *
45 * Description:
46 * ------------
47 * This file provides KAL ITC related APIs
48 *
49 * Author:
50 * -------
51 * -------
52 *
53 *============================================================================
54 * HISTORY
55 * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
56 *------------------------------------------------------------------------------
57 * removed!
58 * removed!
59 * removed!
60 *
61 * removed!
62 * removed!
63 * removed!
64 * removed!
65 *
66 * removed!
67 * removed!
68 * removed!
69 *
70 * removed!
71 * removed!
72 * removed!
73 * removed!
74 *
75 *
76****************************************************************************/
77
78#ifndef _KAL_ITC_H
79#define _KAL_ITC_H
80
81/*******************************************************************************
82 * Include Statements
83 *******************************************************************************/
84#include "kal_general_types.h"
85#include "kal_public_defs.h"
86
87/*******************************************************************************
88 * Definitions and macros
89 *******************************************************************************/
90#ifdef __MTK_TARGET__
91#define KAL_SPINLOCK_CREATEDLIST
92#endif
93
94#ifndef HW_ITC_GRP
95#if defined(__MD93__)
96#define KAL_ITC_GRP 3 /* Context takes ITC */
97#elif defined(__MD95__)
98#define KAL_ITC_GRP 3 /* Context takes ITC */
99#elif defined(__MD97__)
100#define KAL_ITC_GRP 2 /* Context takes ITC, or Critical HRT LISR */
101#elif defined(__MD97P__)
102#define KAL_ITC_GRP 2 /* For now, MD97P defs same as in MD97 */
103#else
104#warning "unknown MDMCU version"
105#endif
106#else
107#define KAL_ITC_GRP HW_ITC_GRP /* Context takes ITC */
108#endif
109
110#define KAL_ITC_MAX_NAME (8)
111#define KAL_SPIN_LOCK_ID 0x53504c4bUL
112
113/* Select correct DI API to use based on the current domain and VPE */
114#define KAL_ITC_DI(ret_addr, is_hrt) \
115 ({ \
116 kal_int32 _irq_state; \
117 if (is_hrt == KAL_TRUE) { \
118 _irq_state = kal_hrt_SaveAndSetIRQMask_ITC(ret_addr); \
119 } else { \
120 _irq_state = SaveAndSetIRQMask(); \
121 } \
122 _irq_state; \
123 })
124
125/* Select correct EI API to use based on the current context and VPE */
126#define KAL_ITC_EI(irq_state, ret_addr, is_hrt) \
127 do { \
128 if (is_hrt == KAL_TRUE) { \
129 kal_hrt_RestoreIRQMask_ITC(irq_state, ret_addr); \
130 } else { \
131 RestoreIRQMask(irq_state); \
132 } \
133 } while (0)
134
135/* Primitive macro for taking the lock, return only after getting the lock */
136#if defined(__mips16) || defined(__nanomips__)
137#define KAL_ITC_LOCK_TAKE(lock) \
138 ({ \
139 kal_status _ret = 0; \
140 __asm__ __volatile__( \
141 "1: ll %1, %2;" \
142 " beqz %1, 2f;" \
143 " pause;" \
144 " b 1b;" \
145 "2: li %1, 1;" \
146 " sc %1, %0;" \
147 " beqz %1, 1b;" \
148 : "=ZC"(lock), "+d"(_ret) \
149 : "ZC"(lock) \
150 : "memory"); \
151 _ret; \
152 })
153#else
154#define KAL_ITC_LOCK_TAKE(lock) \
155 ({ \
156 kal_status _ret = 0; \
157 __asm__ __volatile__( \
158 " .set push;" \
159 " .set noreorder;" \
160 "1: ll %1, %2;" \
161 " beqz %1, 2f;" \
162 " li %1, 1;" \
163 " pause;" \
164 " b 1b;" \
165 " nop;" \
166 "2: sc %1, %0;" \
167 " beqz %1, 1b;" \
168 " nop;" \
169 " .set pop;" \
170 : "=ZC"(lock), "+d"(_ret) \
171 : "ZC"(lock) \
172 : "memory"); \
173 _ret; \
174 })
175#endif
176
177/* Primitive macro for taking the lock, return only after getting the lock,
178 * does disable interrupts.
179 * Old irq status saved in irq_mask */
180#if defined(__mips16) || defined(__nanomips__)
181#define KAL_ITC_LOCK_TAKE_DI(lock, irq_mask) \
182 ({ \
183 kal_status _ret = 0; \
184 __asm__ __volatile__( \
185 " di %2;" \
186 " ehb;" \
187 " ext %2, %2, 0, 1;" \
188 "1: ll %1, %3;" \
189 " beqz %1, 3f;" \
190 " beqz %2, 2f;" \
191 " ei;" \
192 "2: pause;" \
193 " di %2;" \
194 " ehb;" \
195 " ext %2, %2, 0, 1;" \
196 " b 1b;" \
197 "3: li %1, 1;" \
198 " sc %1, %0;" \
199 " beqz %1, 1b;" \
200 : "=ZC"(lock), "+d"(_ret), "+d"(irq_mask) \
201 : "ZC"(lock) \
202 : "memory"); \
203 _ret; \
204 })
205#else
206#define KAL_ITC_LOCK_TAKE_DI(lock, irq_mask) \
207 ({ \
208 kal_status _ret = 0; \
209 __asm__ __volatile__( \
210 " .set push;" \
211 " .set noreorder;" \
212 " di %2;" \
213 " ehb;" \
214 " ext %2, %2, 0, 1;" \
215 "1: ll %1, %3;" \
216 " beqz %1, 3f;" \
217 " li %1, 1;" \
218 " beqz %2, 2f;" \
219 " nop;" \
220 " ei;" \
221 "2: pause;" \
222 " di %2;" \
223 " ehb;" \
224 " ext %2, %2, 0, 1;" \
225 " b 1b;" \
226 " nop;" \
227 "3: sc %1, %0;" \
228 " beqz %1, 1b;" \
229 " nop;" \
230 " .set pop;" \
231 : "=ZC"(lock), "+d"(_ret), "+d"(irq_mask) \
232 : "ZC"(lock) \
233 : "memory"); \
234 _ret; \
235 })
236#endif
237
238/* Primitive macro for trying the lock, return success or fail */
239#if defined(__mips16) || defined(__nanomips__)
240#define KAL_ITC_LOCK_TRY(lock) \
241 ({ \
242 kal_status _ret = 0; \
243 __asm__ __volatile__( \
244 " ll %1, %2;" \
245 " bnez %1, 1f;" \
246 " li %1, 1;" \
247 " sc %1, %0;" \
248 " b 2f;" \
249 "1: li %1, 0;" \
250 "2: ;" \
251 : "=ZC"(lock), "+d"(_ret) \
252 : "ZC"(lock) \
253 : "memory"); \
254 _ret = _ret != 0 ? KAL_SUCCESS : KAL_ERROR; \
255 _ret; \
256 })
257#else
258#define KAL_ITC_LOCK_TRY(lock) \
259 ({ \
260 kal_status _ret = 0; \
261 __asm__ __volatile__( \
262 " .set push;" \
263 " .set noreorder;" \
264 " ll %1, %2;" \
265 " bnez %1, 1f;" \
266 " li %1, 0;" \
267 " li %1, 1;" \
268 " sc %1, %0;" \
269 "1: ;" \
270 " .set pop;" \
271 : "=ZC"(lock), "+d"(_ret) \
272 : "ZC"(lock) \
273 : "memory"); \
274 _ret = _ret != 0 ? KAL_SUCCESS : KAL_ERROR; \
275 _ret; \
276 })
277#endif
278
279/* Primitive macro for trying the lock, return success or fail,
280 * does disable interrupts if success.
281 * Old irq status saved in irq_mask */
282#if defined(__mips16) || defined(__nanomips__)
283#define KAL_ITC_LOCK_TRY_DI(lock, irq_mask) \
284 ({ \
285 kal_status _ret = 0; \
286 __asm__ __volatile__( \
287 " di %2;" \
288 " ehb;" \
289 " ext %2, %2, 0, 1;" \
290 " ll %1, %3;" \
291 " bnez %1, 1f;" \
292 " li %1, 1;" \
293 " sc %1, %0;" \
294 " b 2f;" \
295 "1: li %1, 0;" \
296 "2: ;" \
297 : "=ZC"(lock), "+d"(_ret), "+d"(irq_mask) \
298 : "ZC"(lock) \
299 : "memory"); \
300 if (_ret != 0) { \
301 _ret = KAL_SUCCESS; \
302 } else { \
303 _ret = KAL_ERROR; \
304 if (irq_mask != 0) { \
305 __asm__ __volatile__("ei; ehb;" ::: "memory"); \
306 } \
307 } \
308 _ret; \
309 })
310#else
311#define KAL_ITC_LOCK_TRY_DI(lock, irq_mask) \
312 ({ \
313 kal_status _ret = 0; \
314 __asm__ __volatile__( \
315 " .set push;" \
316 " .set noreorder;" \
317 " di %2;" \
318 " ehb;" \
319 " ext %2, %2, 0, 1;" \
320 " ll %1, %3;" \
321 " bnez %1, 1f;" \
322 " li %1, 0;" \
323 " li %1, 1;" \
324 " sc %1, %0;" \
325 "1: ;" \
326 " .set pop;" \
327 : "=ZC"(lock), "+d"(_ret), "+d"(irq_mask) \
328 : "ZC"(lock) \
329 : "memory"); \
330 if (_ret != 0) { \
331 _ret = KAL_SUCCESS; \
332 } else { \
333 _ret = KAL_ERROR; \
334 if (irq_mask != 0) { \
335 __asm__ __volatile__("ei; ehb;" ::: "memory"); \
336 } \
337 } \
338 _ret; \
339 })
340#endif
341
342/* Primitive macro for taking the lock, return only after getting the lock,
343 * does disable interrupts and disable MT.
344 * Old irq status saved in irq_mask, old MT status saved in mt_mask */
345#if defined(__mips16) || defined(__nanomips__)
346#define KAL_ITC_LOCK_TAKE_DI_DMT(lock, irq_mask, mt_mask) \
347 ({ \
348 kal_status _ret = 0; \
349 __asm__ __volatile__( \
350 " dmt %3;" \
351 " ehb;" \
352 " di %2;" \
353 " ehb;" \
354 " ext %3, %3, 15, 1;" \
355 " ext %2, %2, 0, 1;" \
356 "1: ll %1, %4;" \
357 " beqz %1, 4f;" \
358 " beqz %2, 2f;" \
359 " ei;" \
360 "2: beqz %3, 3f;" \
361 " emt;" \
362 " ehb;" \
363 "3: pause;" \
364 " dmt %3;" \
365 " ehb;" \
366 " di %2;" \
367 " ehb;" \
368 " ext %3, %3, 15, 1;" \
369 " ext %2, %2, 0, 1;" \
370 " b 1b;" \
371 "4: li %1, 1;" \
372 " sc %1, %0;" \
373 " beqz %1, 1b;" \
374 : "=ZC" (lock), "+d" (_ret), "+d" (irq_mask), "+d" (mt_mask) \
375 : "ZC" (lock) \
376 : "memory" \
377 ); \
378 _ret; \
379 })
380#else
381#define KAL_ITC_LOCK_TAKE_DI_DMT(lock, irq_mask, mt_mask) \
382 ({ \
383 kal_status _ret = 0; \
384 __asm__ __volatile__( \
385 " .set push;" \
386 " .set noreorder;" \
387 " dmt %3;" \
388 " ehb;" \
389 " di %2;" \
390 " ehb;" \
391 " ext %3, %3, 15, 1;" \
392 " ext %2, %2, 0, 1;" \
393 "1: ll %1, %4;" \
394 " beqz %1, 4f;" \
395 " li %1, 1;" \
396 " beqz %2, 2f;" \
397 " nop;" \
398 " ei;" \
399 "2: beqz %2, 3f;" \
400 " nop;" \
401 " emt;" \
402 " ehb;" \
403 "3: pause;" \
404 " dmt %3;" \
405 " ehb;" \
406 " di %2;" \
407 " ehb;" \
408 " ext %3, %3, 15, 1;" \
409 " ext %2, %2, 0, 1;" \
410 " b 1b;" \
411 " nop;" \
412 "4: sc %1, %0;" \
413 " beqz %1, 1b;" \
414 " nop;" \
415 " .set pop;" \
416 : "=ZC" (lock), "+d" (_ret), "+d" (irq_mask), "+d" (mt_mask) \
417 : "ZC" (lock) \
418 : "memory" \
419 ); \
420 _ret; \
421 })
422#endif
423
424/* Primitive macro for trying the lock, return success or fail,
425 * does disable interrupts and MT if success.
426 * Old irq status saved in irq_mask, old MT status saved in mt_mask */
427#if defined(__mips16) || defined(__nanomips__)
428#define KAL_ITC_LOCK_TRY_DI_DMT(lock, irq_maski, mt_mask) \
429 ({ \
430 kal_status _ret = 0; \
431 __asm__ __volatile__( \
432 " dmt %3;" \
433 " ehb;" \
434 " di %2;" \
435 " ehb;" \
436 " ext %3, %3, 15, 1;" \
437 " ext %2, %2, 0, 1;" \
438 " ll %1, %4;" \
439 " bnez %1, 1f;" \
440 " li %1, 1;" \
441 " sc %1, %0;" \
442 " b 2f;" \
443 "1: li %1, 0;" \
444 "2: ;" \
445 : "=ZC" (lock), "+d" (_ret), "+d" (irq_mask), "+d" (mt_mask) \
446 : "ZC" (lock) \
447 : "memory" \
448 ); \
449 if (_ret != 0) { \
450 _ret = KAL_SUCCESS; \
451 } else { \
452 _ret = KAL_ERROR; \
453 if (irq_mask != 0) { \
454 __asm__ __volatile__("ei; ehb;":::"memory"); \
455 } \
456 if (mt_mask != 0) { \
457 __asm__ __volatile__("emt; ehb;":::"memory"); \
458 } \
459 } \
460 _ret; \
461 })
462#else
463#define KAL_ITC_LOCK_TRY_DI_DMT(lock, irq_mask, mt_mask) \
464 ({ \
465 kal_status _ret = 0; \
466 __asm__ __volatile__( \
467 " .set push;" \
468 " .set noreorder;" \
469 " dmt %3;" \
470 " ehb;" \
471 " di %2;" \
472 " ehb;" \
473 " ext %3, %3, 15, 1;" \
474 " ext %2, %2, 0, 1;" \
475 " ll %1, %4;" \
476 " bnez %1, 1f;" \
477 " li %1, 0;" \
478 " li %1, 1;" \
479 " sc %1, %0;" \
480 "1: ;" \
481 " .set pop;" \
482 : "=ZC" (lock), "+d" (_ret), "+d" (irq_mask), "+d" (mt_mask) \
483 : "ZC" (lock) \
484 : "memory" \
485 ); \
486 if (_ret != 0) { \
487 _ret = KAL_SUCCESS; \
488 } else { \
489 _ret = KAL_ERROR; \
490 if (irq_mask != 0) { \
491 __asm__ __volatile__("ei; ehb;":::"memory"); \
492 } \
493 if (mt_mask != 0) { \
494 __asm__ __volatile__("emt; ehb;":::"memory"); \
495 } \
496 } \
497 _ret; \
498 })
499#endif
500
501/* Primitive macro for taking the lock, return only after getting the lock,
502 * does disable interrupts, disable MT, and raise prio to HW_ITC_GRP.
503 * Old irq status saved in irq_mask, old MT status saved in mt_mask,
504 * old prio saved in prio. */
505#if defined(__nanomips__)
506#define KAL_ITC_LOCK_TAKE_DI_DMT_PRIO(lock, irq_mask, mt_mask, prio) \
507 ({ \
508 kal_status _ret = 0; \
509 kal_uint32 _new_prio = KAL_ITC_GRP; \
510 __asm__ __volatile__( \
511 " mfc0 %4, $2, 6;" \
512 " move %1, %4;" \
513 " ins %1, %6, 2, 2;" \
514 " ext %4, %4, 2, 2;" \
515 " dmt %3;" \
516 " ehb;" \
517 " mtc0 %1, $2, 6;" \
518 " ehb;" \
519 " di %2;" \
520 " ehb;" \
521 " ext %3, %3, 15, 1;" \
522 " ext %2, %2, 0, 1;" \
523 "1: ll %1, %5;" \
524 " beqz %1, 4f;" \
525 " beqz %2, 2f;" \
526 " ei;" \
527 " ehb;" \
528 "2: beqz %3, 3f;" \
529 " emt;" \
530 " ehb;" \
531 "3: pause;" \
532 " dmt %3;" \
533 " ehb;" \
534 " di %2;" \
535 " ehb;" \
536 " ext %3, %3, 15, 1;" \
537 " ext %2, %2, 0, 1;" \
538 " b 1b;" \
539 "4: li %1, 1;" \
540 " sc %1, %0;" \
541 " beqz %1, 1b;" \
542 : "=ZC" (lock), "+d" (_ret), "+d" (irq_mask), "+d" (mt_mask), "+d" (prio) \
543 : "ZC" (lock), "d" (_new_prio) \
544 : "memory" \
545 ); \
546 _ret; \
547 })
548#elif defined(__mips16)
549#define KAL_ITC_LOCK_TAKE_DI_DMT_PRIO(lock, irq_mask, mt_mask, prio) \
550 ({ \
551 kal_status _ret = 0; \
552 kal_uint32 _new_prio = KAL_ITC_GRP; \
553 __asm__ __volatile__( \
554 " mfc0 %4, $2, 6;" \
555 " move %1, %4;" \
556 " ins %1, %6, 0, 2;" \
557 " ext %4, %4, 0, 2;" \
558 " dmt %3;" \
559 " ehb;" \
560 " mtc0 %1, $2, 6;" \
561 " ehb;" \
562 " di %2;" \
563 " ehb;" \
564 " ext %3, %3, 15, 1;" \
565 " ext %2, %2, 0, 1;" \
566 "1: ll %1, %5;" \
567 " beqz %1, 4f;" \
568 " beqz %2, 2f;" \
569 " ei;" \
570 " ehb;" \
571 "2: beqz %3, 3f;" \
572 " emt;" \
573 " ehb;" \
574 "3: pause;" \
575 " dmt %3;" \
576 " ehb;" \
577 " di %2;" \
578 " ehb;" \
579 " ext %3, %3, 15, 1;" \
580 " ext %2, %2, 0, 1;" \
581 " b 1b;" \
582 "4: li %1, 1;" \
583 " sc %1, %0;" \
584 " beqz %1, 1b;" \
585 : "=ZC" (lock), "+d" (_ret), "+d" (irq_mask), "+d" (mt_mask), "+d" (prio) \
586 : "ZC" (lock), "d" (_new_prio) \
587 : "memory" \
588 ); \
589 _ret; \
590 })
591#else
592#define KAL_ITC_LOCK_TAKE_DI_DMT_PRIO(lock, irq_mask, mt_mask, prio) \
593 ({ \
594 kal_status _ret = 0; \
595 kal_uint32 _new_prio = KAL_ITC_GRP; \
596 __asm__ __volatile__( \
597 " .set push;" \
598 " .set noreorder;" \
599 " mfc0 %4, $2, 6;" \
600 " move %1, %4;" \
601 " ins %1, %6, 0, 2;" \
602 " ext %4, %4, 0, 2;" \
603 " dmt %3;" \
604 " ehb;" \
605 " mtc0 %1, $2, 6;" \
606 " ehb;" \
607 " di %2;" \
608 " ehb;" \
609 " ext %3, %3, 15, 1;" \
610 " ext %2, %2, 0, 1;" \
611 "1: ll %1, %5;" \
612 " beqz %1, 4f;" \
613 " li %1, 1;" \
614 " beqz %2, 2f;" \
615 " nop;" \
616 " ei;" \
617 " ehb;" \
618 "2: beqz %2, 3f;" \
619 " nop;" \
620 " emt;" \
621 " ehb;" \
622 "3: pause;" \
623 " dmt %3;" \
624 " ehb;" \
625 " di %2;" \
626 " ehb;" \
627 " ext %3, %3, 15, 1;" \
628 " ext %2, %2, 0, 1;" \
629 " b 1b;" \
630 " nop;" \
631 "4: sc %1, %0;" \
632 " beqz %1, 1b;" \
633 " nop;" \
634 " .set pop;" \
635 : "=ZC" (lock), "+d" (_ret), "+d" (irq_mask), "+d" (mt_mask), "+d" (prio) \
636 : "ZC" (lock), "d" (_new_prio) \
637 : "memory" \
638 ); \
639 _ret; \
640 })
641#endif
642
643/* Primitive macro for trying the lock, return success or fail,
644 * does disable interrupts and MT, and raise prio to HW_ITC_GRP if success.
645 * Old irq status saved in irq_mask, old MT status saved in mt_mask,
646 * old prio saved in prio. */
647#if defined(__nanomips__)
648#define KAL_ITC_LOCK_TRY_DI_DMT_PRIO(lock, irq_maski, mt_mask, prio) \
649 ({ \
650 kal_status _ret = 0; \
651 kal_uint32 _new_prio = KAL_ITC_GRP; \
652 __asm__ __volatile__( \
653 " mfc0 %4, $2, 6;" \
654 " move %1, %4;" \
655 " ins %1, %6, 2, 2;" \
656 " ext %4, %4, 2, 2;" \
657 " dmt %3;" \
658 " ehb;" \
659 " mtc0 %1, $2, 6;" \
660 " ehb;" \
661 " di %2;" \
662 " ehb;" \
663 " ext %3, %3, 15, 1;" \
664 " ext %2, %2, 0, 1;" \
665 " ll %1, %5;" \
666 " bnez %1, 1f;" \
667 " li %1, 1;" \
668 " sc %1, %0;" \
669 " b 2f;" \
670 "1: li %1, 0;" \
671 "2: ;" \
672 : "=ZC" (lock), "+d" (_ret), "+d" (irq_mask), "+d" (mt_mask), "+d" (prio) \
673 : "ZC" (lock), "d" (_new_prio) \
674 : "memory" \
675 ); \
676 if (_ret != 0) { \
677 _ret = KAL_SUCCESS; \
678 } else { \
679 _ret = KAL_ERROR; \
680 if (irq_mask != 0) { \
681 __asm__ __volatile__("ei; ehb;":::"memory"); \
682 } \
683 if (prio != KAL_ITC_GRP) { \
684 kal_uint32 _tc_schedule = 0; \
685 __asm__ __volatile__( \
686 " mfc0 %0, $2, 6;" \
687 " ins %0, %1, 2, 2;" \
688 " mtc0 %0, $2, 6;" \
689 " ehb;" \
690 : "+d" (_tc_schedule) \
691 : "d" (prio) \
692 : \
693 ); \
694 } \
695 if (mt_mask != 0) { \
696 __asm__ __volatile__("emt; ehb;":::"memory"); \
697 } \
698 } \
699 _ret; \
700 })
701#elif defined(__mips16)
702#define KAL_ITC_LOCK_TRY_DI_DMT_PRIO(lock, irq_maski, mt_mask, prio) \
703 ({ \
704 kal_status _ret = 0; \
705 kal_uint32 _new_prio = KAL_ITC_GRP; \
706 __asm__ __volatile__( \
707 " mfc0 %4, $2, 6;" \
708 " move %1, %4;" \
709 " ins %1, %6, 0, 2;" \
710 " ext %4, %4, 0, 2;" \
711 " dmt %3;" \
712 " ehb;" \
713 " mtc0 %1, $2, 6;" \
714 " ehb;" \
715 " di %2;" \
716 " ehb;" \
717 " ext %3, %3, 15, 1;" \
718 " ext %2, %2, 0, 1;" \
719 " ll %1, %5;" \
720 " bnez %1, 1f;" \
721 " li %1, 1;" \
722 " sc %1, %0;" \
723 " b 2f;" \
724 "1: li %1, 0;" \
725 "2: ;" \
726 : "=ZC" (lock), "+d" (_ret), "+d" (irq_mask), "+d" (mt_mask), "+d" (prio) \
727 : "ZC" (lock), "d" (_new_prio) \
728 : "memory" \
729 ); \
730 if (_ret != 0) { \
731 _ret = KAL_SUCCESS; \
732 } else { \
733 _ret = KAL_ERROR; \
734 if (irq_mask != 0) { \
735 __asm__ __volatile__("ei; ehb;":::"memory"); \
736 } \
737 if (prio != KAL_ITC_GRP) { \
738 kal_uint32 _tc_schedule = 0; \
739 __asm__ __volatile__( \
740 " mfc0 %0, $2, 6;" \
741 " ins %0, %1, 0, 2;" \
742 " mtc0 %0, $2, 6;" \
743 " ehb;" \
744 : "+d" (_tc_schedule) \
745 : "d" (prio) \
746 : \
747 ); \
748 } \
749 if (mt_mask != 0) { \
750 __asm__ __volatile__("emt; ehb;":::"memory"); \
751 } \
752 } \
753 _ret; \
754 })
755#else
756#define KAL_ITC_LOCK_TRY_DI_DMT_PRIO(lock, irq_maski, mt_mask, prio) \
757 ({ \
758 kal_status _ret = 0; \
759 kal_uint32 _new_prio = KAL_ITC_GRP; \
760 __asm__ __volatile__( \
761 " .set push;" \
762 " .set noreorder;" \
763 " mfc0 %4, $2, 6;" \
764 " move %1, %4;" \
765 " ins %1, %6, 0, 2;" \
766 " ext %4, %4, 0, 2;" \
767 " dmt %3;" \
768 " ehb;" \
769 " mtc0 %1, $2, 6;" \
770 " ehb;" \
771 " di %2;" \
772 " ehb;" \
773 " ext %3, %3, 15, 1;" \
774 " ext %2, %2, 0, 1;" \
775 " ll %1, %5;" \
776 " bnez %1, 1f;" \
777 " li %1, 0;" \
778 " li %1, 1;" \
779 " sc %1, %0;" \
780 "1: ;" \
781 " .set pop;" \
782 : "=ZC" (lock), "+d" (_ret), "+d" (irq_mask), "+d" (mt_mask), "+d" (prio) \
783 : "ZC" (lock), "d" (_new_prio) \
784 : "memory" \
785 ); \
786 if (_ret != 0) { \
787 _ret = KAL_SUCCESS; \
788 } else { \
789 _ret = KAL_ERROR; \
790 if (irq_mask != 0) { \
791 __asm__ __volatile__("ei; ehb;":::"memory"); \
792 } \
793 if (prio != KAL_ITC_GRP) { \
794 kal_uint32 _tc_schedule = 0; \
795 __asm__ __volatile__( \
796 " mfc0 %0, $2, 6;" \
797 " ins %0, %1, 0, 2;" \
798 " mtc0 %0, $2, 6;" \
799 " ehb;" \
800 : "+d" (_tc_schedule) \
801 : "d" (prio) \
802 : \
803 ); \
804 } \
805 if (mt_mask != 0) { \
806 __asm__ __volatile__("emt; ehb;":::"memory"); \
807 } \
808 } \
809 _ret; \
810 })
811#endif
812/* Primitive macro for trying the lock ticket based, return success or fail */
813#if defined(__mips16) || defined(__nanomips__)
814#define KAL_ITC_LOCK_TRY_FIFO(lock, ticket) \
815 ({ \
816 kal_status _ret = 0; \
817 __asm__ __volatile__( \
818 " ll $a3, %2;" \
819 " li %0, %3;" \
820 " bne %1, $a3, 1f;" \
821 " li %0, %4;" \
822 "1: ;" \
823 : "=d"(_ret), "+d"(ticket) \
824 : "ZC"(lock), "I"(KAL_ERROR), "I"(KAL_SUCCESS) \
825 : "$a3", "memory"); \
826 _ret; \
827 })
828#else
829#define KAL_ITC_LOCK_TRY_FIFO(lock, ticket) \
830 ({ \
831 kal_status _ret = 0; \
832 __asm__ __volatile__( \
833 " .set push;" \
834 " .set noreorder;" \
835 " ll $a3, %2;" \
836 " bne %1, $a3, 1f;" \
837 " li %0, %3;" \
838 " li %0, %4;" \
839 "1: ;" \
840 " .set pop;" \
841 : "=d"(_ret), "+d"(ticket) \
842 : "ZC"(lock), "I"(KAL_ERROR), "I"(KAL_SUCCESS) \
843 : "$a3", "memory"); \
844 _ret; \
845 })
846#endif
847
848/* Primitive macro for releasing the lock */
849#if defined(__mips16)
850#define KAL_ITC_LOCK_GIVE(lock) \
851 do { \
852 __asm__ __volatile__( \
853 " sync 0x10;" \
854 " li $a3, 0;" \
855 " sw $a3, %0;" \
856 : "=ZC"(lock) \
857 : \
858 : "$a3", "memory"); \
859 } while (0)
860#else
861#define KAL_ITC_LOCK_GIVE(lock) \
862 do { \
863 __asm__ __volatile__( \
864 " sync 0x10;" \
865 " sw $zero, %0;" \
866 : "=ZC"(lock) \
867 : \
868 : "memory"); \
869 } while (0)
870#endif
871
872/* Primitive macro for releasing the lock,
873 * does enable interrupts based on irq_mask*/
874#if defined(__mips16)
875#define KAL_ITC_LOCK_GIVE_EI(lock, irq_mask) \
876 do { \
877 __asm__ __volatile__( \
878 " sync 0x10;" \
879 " li $a3, 0;" \
880 " sw $a3, %0;" \
881 : "=ZC"(lock) \
882 : \
883 : "$a3", "memory"); \
884 if (irq_mask != 0) { \
885 __asm__ __volatile__("ei; ehb;" ::: "memory"); \
886 } \
887 } while (0)
888#else
889#define KAL_ITC_LOCK_GIVE_EI(lock, irq_mask) \
890 do { \
891 __asm__ __volatile__( \
892 " sync 0x10;" \
893 " sw $zero, %0;" \
894 : "=ZC"(lock) \
895 : \
896 : "memory"); \
897 if (irq_mask != 0) { \
898 __asm__ __volatile__("ei; ehb;" ::: "memory"); \
899 } \
900 } while (0)
901#endif
902
903/* Primitive macro for releasing the lock,
904 * does enable interrupts based on irq_mask, and MT based on mt_mask*/
905#if defined(__mips16)
906#define KAL_ITC_LOCK_GIVE_EI_EMT(lock, irq_mask, mt_mask) \
907 do { \
908 __asm__ __volatile__( \
909 " sync 0x10;" \
910 " li $a3, 0;" \
911 " sw $a3, %0;" \
912 : "=ZC" (lock) \
913 : \
914 : "$a3", "memory" \
915 ); \
916 if (irq_mask != 0) { \
917 __asm__ __volatile__("ei; ehb;":::"memory"); \
918 } \
919 if (mt_mask != 0) { \
920 __asm__ __volatile__("emt; ehb;":::"memory"); \
921 } \
922 } while(0)
923#else
924#define KAL_ITC_LOCK_GIVE_EI_EMT(lock, irq_mask, mt_mask) \
925 do { \
926 __asm__ __volatile__( \
927 " sync 0x10;" \
928 " sw $zero, %0;" \
929 : "=ZC" (lock) \
930 : \
931 : "memory" \
932 ); \
933 if (irq_mask != 0) { \
934 __asm__ __volatile__("ei; ehb;":::"memory"); \
935 } \
936 if (mt_mask != 0) { \
937 __asm__ __volatile__("emt; ehb;":::"memory"); \
938 } \
939 } while(0)
940#endif
941
942/* Primitive macro for releasing the lock,
943 * does enable interrupts based on irq_mask, MT based on mt_mask, and TC priority based
944 * on old_prio*/
945#if defined(__nanomips__)
946#define KAL_ITC_LOCK_GIVE_EI_EMT_PRIO(lock, irq_mask, mt_mask, old_prio) \
947 do { \
948 __asm__ __volatile__( \
949 " sync 0x10;" \
950 " sw $zero, %0;" \
951 : "=ZC" (lock) \
952 : \
953 : "memory" \
954 ); \
955 if (irq_mask != 0) { \
956 __asm__ __volatile__("ei; ehb;":::"memory"); \
957 } \
958 if (old_prio != KAL_ITC_GRP) { \
959 kal_uint32 _tc_schedule = 0; \
960 __asm__ __volatile__( \
961 " mfc0 %0, $2, 6;" \
962 " ins %0, %1, 2, 2;" \
963 " mtc0 %0, $2, 6;" \
964 " ehb;" \
965 : "+d" (_tc_schedule) \
966 : "d" (old_prio) \
967 : \
968 ); \
969 } \
970 if (mt_mask != 0) { \
971 __asm__ __volatile__("emt; ehb;":::"memory"); \
972 } \
973 } while(0)
974#elif defined(__mips16)
975#define KAL_ITC_LOCK_GIVE_EI_EMT_PRIO(lock, irq_mask, mt_mask, old_prio) \
976 do { \
977 __asm__ __volatile__( \
978 " sync 0x10;" \
979 " li $a3, 0;" \
980 " sw $a3, %0;" \
981 : "=ZC" (lock) \
982 : \
983 : "$a3", "memory" \
984 ); \
985 if (irq_mask != 0) { \
986 __asm__ __volatile__("ei; ehb;":::"memory"); \
987 } \
988 if (old_prio != KAL_ITC_GRP) { \
989 kal_uint32 _tc_schedule = 0; \
990 __asm__ __volatile__( \
991 " mfc0 %0, $2, 6;" \
992 " ins %0, %1, 0, 2;" \
993 " mtc0 %0, $2, 6;" \
994 " ehb;" \
995 : "+d" (_tc_schedule) \
996 : "d" (old_prio) \
997 : \
998 ); \
999 } \
1000 if (mt_mask != 0) { \
1001 __asm__ __volatile__("emt; ehb;":::"memory"); \
1002 } \
1003 } while(0)
1004#else
1005#define KAL_ITC_LOCK_GIVE_EI_EMT_PRIO(lock, irq_mask, mt_mask, old_prio) \
1006 do { \
1007 __asm__ __volatile__( \
1008 " sync 0x10;" \
1009 " sw $zero, %0;" \
1010 : "=ZC" (lock) \
1011 : \
1012 : "memory" \
1013 ); \
1014 if (irq_mask != 0) { \
1015 __asm__ __volatile__("ei; ehb;":::"memory"); \
1016 } \
1017 if (old_prio != KAL_ITC_GRP) { \
1018 kal_uint32 _tc_schedule = 0; \
1019 __asm__ __volatile__( \
1020 " mfc0 %0, $2, 6;" \
1021 " ins %0, %1, 0, 2;" \
1022 " mtc0 %0, $2, 6;" \
1023 " ehb;" \
1024 : "+d" (_tc_schedule) \
1025 : "d" (old_prio) \
1026 : \
1027 ); \
1028 } \
1029 if (mt_mask != 0) { \
1030 __asm__ __volatile__("emt; ehb;":::"memory"); \
1031 } \
1032 } while(0)
1033#endif
1034
1035/* Primitive macro for releasing the lock ticket based */
1036#define KAL_ITC_LOCK_GIVE_FIFO(lock) \
1037 do { \
1038 __asm__ __volatile__("sync 0x10;" ::: "memory"); \
1039 (lock)++; \
1040 } while (0)
1041
1042#define KAL_ITC_PAUSE() \
1043 do { \
1044 __asm__ __volatile__("pause;" ::: "memory"); \
1045 } while (0)
1046
1047/*******************************************************************************
1048 * Types
1049 *******************************************************************************/
1050typedef struct kal_itc_node_struct {
1051 struct kal_itc_node_struct *next;
1052 struct kal_itc_node_struct *prev;
1053} kal_itc_node_s;
1054
1055typedef struct {
1056 kal_itc_node_s lock_node;
1057 kal_uint32 lock_id;
1058 kal_uint32 lock;
1059 kal_uint32 interrupt_mask;
1060 kal_char name[KAL_ITC_MAX_NAME];
1061 void * owner_context;
1062 kal_uint32 nesting_level;
1063#if defined(DEBUG_KAL)
1064 kal_uint32 lock_start_time;
1065 kal_uint32 lock_taker;
1066 kal_uint32 max_lock_hold_time;
1067 kal_uint32 max_lock_taker;
1068#endif
1069} kal_itc_lock_s;
1070
1071/*******************************************************************************
1072 * Variables
1073 *******************************************************************************/
1074extern kal_itc_lock_s *kal_itc_tbl[KAL_ITC_NUM];
1075extern kal_uint32 kal_tc_prio_count[SYS_MCU_NUM_TC];
1076extern kal_uint32 kal_tc_prio_save[SYS_MCU_NUM_TC];
1077
1078#endif //_KAL_ITC_H