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