1 /*
2  * Copyright (C) 2018-2019, STMicroelectronics - All Rights Reserved
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #ifndef STM32MP_SHRES_HELPERS_H
8 #define STM32MP_SHRES_HELPERS_H
9 
10 #include <stdint.h>
11 
12 #include <common/debug.h>
13 
14 /*
15  * Shared reference counter: increments by 2 on secure increment
16  * request, decrements by 2 on secure decrement request. Bit #0
17  * is set to 1 on non-secure increment request and reset to 0 on
18  * non-secure decrement request. The counter initializes to
19  * either 0, 1 or 2 upon their expect default state.
20  * Counters saturates once above UINT_MAX / 2.
21  */
22 #define SHREFCNT_NONSECURE_FLAG		0x1UL
23 #define SHREFCNT_SECURE_STEP		0x2UL
24 #define SHREFCNT_MAX			(UINT32_MAX / 2)
25 
26 /* Return 1 if refcnt increments from 0, else return 0 */
stm32mp_incr_shrefcnt(unsigned int * refcnt,bool secure)27 static inline int stm32mp_incr_shrefcnt(unsigned int *refcnt, bool secure)
28 {
29 	int rc = !*refcnt;
30 
31 	if (secure) {
32 		*refcnt += SHREFCNT_SECURE_STEP;
33 		if (*refcnt >= SHREFCNT_MAX) {
34 			panic();
35 		}
36 	} else {
37 		*refcnt |= SHREFCNT_NONSECURE_FLAG;
38 	}
39 
40 	return rc;
41 }
42 
43 /* Return 1 if refcnt decrements to 0, else return 0 */
stm32mp_decr_shrefcnt(unsigned int * refcnt,bool secure)44 static inline int stm32mp_decr_shrefcnt(unsigned int *refcnt, bool secure)
45 {
46 	int  rc = 0;
47 
48 	if (secure) {
49 		if (*refcnt < SHREFCNT_MAX) {
50 			if (*refcnt < SHREFCNT_SECURE_STEP) {
51 				panic();
52 			}
53 			*refcnt -= SHREFCNT_SECURE_STEP;
54 			rc = !*refcnt;
55 		}
56 	} else {
57 		rc = (*refcnt == SHREFCNT_NONSECURE_FLAG) ? 1 : 0;
58 		*refcnt &= ~SHREFCNT_NONSECURE_FLAG;
59 	}
60 
61 	return rc;
62 }
63 
stm32mp_incr_refcnt(unsigned int * refcnt)64 static inline int stm32mp_incr_refcnt(unsigned int *refcnt)
65 {
66 	return stm32mp_incr_shrefcnt(refcnt, true);
67 }
68 
stm32mp_decr_refcnt(unsigned int * refcnt)69 static inline int stm32mp_decr_refcnt(unsigned int *refcnt)
70 {
71 	return stm32mp_decr_shrefcnt(refcnt, true);
72 }
73 
74 #endif /* STM32MP_SHRES_HELPERS_H */
75