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 Parkstatic 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 Parkstatic 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 Parkstatic 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 Parkstatic 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 Parkstatic 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