xref: /arm-trusted-firmware/include/lib/bakery_lock.h (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2013-2018, Arm Limited and Contributors. All rights reserved.
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  */
6*91f16700Schasinglulu 
7*91f16700Schasinglulu #ifndef BAKERY_LOCK_H
8*91f16700Schasinglulu #define BAKERY_LOCK_H
9*91f16700Schasinglulu 
10*91f16700Schasinglulu #include <platform_def.h>
11*91f16700Schasinglulu 
12*91f16700Schasinglulu #define BAKERY_LOCK_MAX_CPUS		PLATFORM_CORE_COUNT
13*91f16700Schasinglulu 
14*91f16700Schasinglulu #ifndef __ASSEMBLER__
15*91f16700Schasinglulu #include <cdefs.h>
16*91f16700Schasinglulu #include <stdbool.h>
17*91f16700Schasinglulu #include <stdint.h>
18*91f16700Schasinglulu 
19*91f16700Schasinglulu #include <lib/utils_def.h>
20*91f16700Schasinglulu 
21*91f16700Schasinglulu /*****************************************************************************
22*91f16700Schasinglulu  * Internal helpers used by the bakery lock implementation.
23*91f16700Schasinglulu  ****************************************************************************/
24*91f16700Schasinglulu 
25*91f16700Schasinglulu /* Convert a ticket to priority */
26*91f16700Schasinglulu static inline unsigned int bakery_get_priority(unsigned int t, unsigned int pos)
27*91f16700Schasinglulu {
28*91f16700Schasinglulu 	return (t << 8) | pos;
29*91f16700Schasinglulu }
30*91f16700Schasinglulu 
31*91f16700Schasinglulu #define CHOOSING_TICKET		U(0x1)
32*91f16700Schasinglulu #define CHOSEN_TICKET		U(0x0)
33*91f16700Schasinglulu 
34*91f16700Schasinglulu static inline bool bakery_is_choosing(unsigned int info)
35*91f16700Schasinglulu {
36*91f16700Schasinglulu 	return (info & 1U) == CHOOSING_TICKET;
37*91f16700Schasinglulu }
38*91f16700Schasinglulu 
39*91f16700Schasinglulu static inline unsigned int bakery_ticket_number(unsigned int info)
40*91f16700Schasinglulu {
41*91f16700Schasinglulu 	return (info >> 1) & 0x7FFFU;
42*91f16700Schasinglulu }
43*91f16700Schasinglulu 
44*91f16700Schasinglulu static inline uint16_t make_bakery_data(unsigned int choosing, unsigned int num)
45*91f16700Schasinglulu {
46*91f16700Schasinglulu 	unsigned int val = (choosing & 0x1U) | (num << 1);
47*91f16700Schasinglulu 
48*91f16700Schasinglulu 	return (uint16_t) val;
49*91f16700Schasinglulu }
50*91f16700Schasinglulu 
51*91f16700Schasinglulu /*****************************************************************************
52*91f16700Schasinglulu  * External bakery lock interface.
53*91f16700Schasinglulu  ****************************************************************************/
54*91f16700Schasinglulu #if USE_COHERENT_MEM
55*91f16700Schasinglulu /*
56*91f16700Schasinglulu  * Bakery locks are stored in coherent memory
57*91f16700Schasinglulu  *
58*91f16700Schasinglulu  * Each lock's data is contiguous and fully allocated by the compiler
59*91f16700Schasinglulu  */
60*91f16700Schasinglulu 
61*91f16700Schasinglulu typedef struct bakery_lock {
62*91f16700Schasinglulu 	/*
63*91f16700Schasinglulu 	 * The lock_data is a bit-field of 2 members:
64*91f16700Schasinglulu 	 * Bit[0]       : choosing. This field is set when the CPU is
65*91f16700Schasinglulu 	 *                choosing its bakery number.
66*91f16700Schasinglulu 	 * Bits[1 - 15] : number. This is the bakery number allocated.
67*91f16700Schasinglulu 	 */
68*91f16700Schasinglulu 	volatile uint16_t lock_data[BAKERY_LOCK_MAX_CPUS];
69*91f16700Schasinglulu } bakery_lock_t;
70*91f16700Schasinglulu 
71*91f16700Schasinglulu #else
72*91f16700Schasinglulu /*
73*91f16700Schasinglulu  * Bakery locks are stored in normal .bss memory
74*91f16700Schasinglulu  *
75*91f16700Schasinglulu  * Each lock's data is spread across multiple cache lines, one per CPU,
76*91f16700Schasinglulu  * but multiple locks can share the same cache line.
77*91f16700Schasinglulu  * The compiler will allocate enough memory for one CPU's bakery locks,
78*91f16700Schasinglulu  * the remaining cache lines are allocated by the linker script
79*91f16700Schasinglulu  */
80*91f16700Schasinglulu 
81*91f16700Schasinglulu typedef struct bakery_info {
82*91f16700Schasinglulu 	/*
83*91f16700Schasinglulu 	 * The lock_data is a bit-field of 2 members:
84*91f16700Schasinglulu 	 * Bit[0]       : choosing. This field is set when the CPU is
85*91f16700Schasinglulu 	 *                choosing its bakery number.
86*91f16700Schasinglulu 	 * Bits[1 - 15] : number. This is the bakery number allocated.
87*91f16700Schasinglulu 	 */
88*91f16700Schasinglulu 	volatile uint16_t lock_data;
89*91f16700Schasinglulu } bakery_info_t;
90*91f16700Schasinglulu 
91*91f16700Schasinglulu typedef bakery_info_t bakery_lock_t;
92*91f16700Schasinglulu 
93*91f16700Schasinglulu #endif /* __USE_COHERENT_MEM__ */
94*91f16700Schasinglulu 
95*91f16700Schasinglulu static inline void bakery_lock_init(bakery_lock_t *bakery) {}
96*91f16700Schasinglulu void bakery_lock_get(bakery_lock_t *bakery);
97*91f16700Schasinglulu void bakery_lock_release(bakery_lock_t *bakery);
98*91f16700Schasinglulu 
99*91f16700Schasinglulu #define DEFINE_BAKERY_LOCK(_name) bakery_lock_t _name __section(".bakery_lock")
100*91f16700Schasinglulu 
101*91f16700Schasinglulu #define DECLARE_BAKERY_LOCK(_name) extern bakery_lock_t _name
102*91f16700Schasinglulu 
103*91f16700Schasinglulu 
104*91f16700Schasinglulu #endif /* __ASSEMBLER__ */
105*91f16700Schasinglulu #endif /* BAKERY_LOCK_H */
106