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