xref: /rk3399_ARM-atf/services/std_svc/sdei/sdei_state.c (revision 9a207532f8216bf83fed0891fed9ed0bc72ca450)
1b7cb133eSJeenu Viswambharan /*
2fb1198b1SAntonio Nino Diaz  * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
3b7cb133eSJeenu Viswambharan  *
4b7cb133eSJeenu Viswambharan  * SPDX-License-Identifier: BSD-3-Clause
5b7cb133eSJeenu Viswambharan  */
6b7cb133eSJeenu Viswambharan 
7b7cb133eSJeenu Viswambharan #include <assert.h>
8b7cb133eSJeenu Viswambharan #include <stdbool.h>
9*09d40e0eSAntonio Nino Diaz 
10*09d40e0eSAntonio Nino Diaz #include <lib/cassert.h>
11*09d40e0eSAntonio Nino Diaz 
12b7cb133eSJeenu Viswambharan #include "sdei_private.h"
13b7cb133eSJeenu Viswambharan 
14b7cb133eSJeenu Viswambharan /* Aliases for SDEI handler states: 'R'unning, 'E'nabled, and re'G'istered */
15ba6e5ca6SJeenu Viswambharan #define r_		0U
16b7cb133eSJeenu Viswambharan #define R_		(1u << SDEI_STATF_RUNNING)
17b7cb133eSJeenu Viswambharan 
18ba6e5ca6SJeenu Viswambharan #define e_		0U
19b7cb133eSJeenu Viswambharan #define E_		(1u << SDEI_STATF_ENABLED)
20b7cb133eSJeenu Viswambharan 
21ba6e5ca6SJeenu Viswambharan #define g_		0U
22b7cb133eSJeenu Viswambharan #define G_		(1u << SDEI_STATF_REGISTERED)
23b7cb133eSJeenu Viswambharan 
24b7cb133eSJeenu Viswambharan /* All possible composite handler states */
25b7cb133eSJeenu Viswambharan #define reg_		(r_ | e_ | g_)
26b7cb133eSJeenu Viswambharan #define reG_		(r_ | e_ | G_)
27b7cb133eSJeenu Viswambharan #define rEg_		(r_ | E_ | g_)
28b7cb133eSJeenu Viswambharan #define rEG_		(r_ | E_ | G_)
29b7cb133eSJeenu Viswambharan #define Reg_		(R_ | e_ | g_)
30b7cb133eSJeenu Viswambharan #define ReG_		(R_ | e_ | G_)
31b7cb133eSJeenu Viswambharan #define REg_		(R_ | E_ | g_)
32b7cb133eSJeenu Viswambharan #define REG_		(R_ | E_ | G_)
33b7cb133eSJeenu Viswambharan 
34ba6e5ca6SJeenu Viswambharan #define MAX_STATES	(REG_ + 1u)
35b7cb133eSJeenu Viswambharan 
36b7cb133eSJeenu Viswambharan /* Invalid state */
37b7cb133eSJeenu Viswambharan #define	SDEI_STATE_INVALID	((sdei_state_t) (-1))
38b7cb133eSJeenu Viswambharan 
39b7cb133eSJeenu Viswambharan /* No change in state */
40b7cb133eSJeenu Viswambharan #define	SDEI_STATE_NOP		((sdei_state_t) (-2))
41b7cb133eSJeenu Viswambharan 
42b7cb133eSJeenu Viswambharan #define X___		SDEI_STATE_INVALID
43b7cb133eSJeenu Viswambharan #define NOP_		SDEI_STATE_NOP
44b7cb133eSJeenu Viswambharan 
45b7cb133eSJeenu Viswambharan /* Ensure special states don't overlap with valid ones */
46b7cb133eSJeenu Viswambharan CASSERT(X___ > REG_, sdei_state_overlap_invalid);
47b7cb133eSJeenu Viswambharan CASSERT(NOP_ > REG_, sdei_state_overlap_nop);
48b7cb133eSJeenu Viswambharan 
49b7cb133eSJeenu Viswambharan /*
50b7cb133eSJeenu Viswambharan  * SDEI handler state machine: refer to sections 6.1 and 6.1.2 of the SDEI v1.0
51fb1198b1SAntonio Nino Diaz  * specification (ARM DEN0054A).
52b7cb133eSJeenu Viswambharan  *
53b7cb133eSJeenu Viswambharan  * Not all calls contribute to handler state transition. This table is also used
54b7cb133eSJeenu Viswambharan  * to validate whether a call is permissible at a given handler state:
55b7cb133eSJeenu Viswambharan  *
56b7cb133eSJeenu Viswambharan  *  - X___ denotes a forbidden transition;
57b7cb133eSJeenu Viswambharan  *  - NOP_ denotes a permitted transition, but there's no change in state;
58b7cb133eSJeenu Viswambharan  *  - Otherwise, XXX_ gives the new state.
59b7cb133eSJeenu Viswambharan  *
60b7cb133eSJeenu Viswambharan  * DISP[atch] is a transition added for the implementation, but is not mentioned
61b7cb133eSJeenu Viswambharan  * in the spec.
62b7cb133eSJeenu Viswambharan  *
63b7cb133eSJeenu Viswambharan  * Those calls that the spec mentions as can be made any time don't picture in
64b7cb133eSJeenu Viswambharan  * this table.
65b7cb133eSJeenu Viswambharan  */
66b7cb133eSJeenu Viswambharan 
67b7cb133eSJeenu Viswambharan static const sdei_state_t sdei_state_table[MAX_STATES][DO_MAX] = {
68b7cb133eSJeenu Viswambharan /*
69b7cb133eSJeenu Viswambharan  *	Action:		REG     REL	ENA	DISA	UREG	ROUT	CTX	COMP	COMPR	DISP
70b7cb133eSJeenu Viswambharan  *	Notes:			[3]			[1]	[3]	[3][4]			[2]
71b7cb133eSJeenu Viswambharan  */
72b7cb133eSJeenu Viswambharan 	/* Handler unregistered, disabled, and not running. This is the default state. */
73b7cb133eSJeenu Viswambharan /* 0 */	[reg_] = {	reG_,	NOP_,	X___,	X___,	X___,	X___,	X___,	X___,	X___,	X___,	},
74b7cb133eSJeenu Viswambharan 
75b7cb133eSJeenu Viswambharan 	/* Handler unregistered and running */
76b7cb133eSJeenu Viswambharan /* 4 */	[Reg_] = {	X___,	X___,	X___,	X___,	X___,	X___,	NOP_,	reg_,	reg_,	X___,	},
77b7cb133eSJeenu Viswambharan 
78b7cb133eSJeenu Viswambharan 	/* Handler registered */
79b7cb133eSJeenu Viswambharan /* 1 */	[reG_] = {	X___,	X___,	rEG_,	NOP_,	reg_,	NOP_,	X___,	X___,	X___,	X___,	},
80b7cb133eSJeenu Viswambharan 
81b7cb133eSJeenu Viswambharan 	/* Handler registered and running */
82b7cb133eSJeenu Viswambharan /* 5 */	[ReG_] = {	X___,	X___,	REG_,	NOP_,	Reg_,	X___,	NOP_,	reG_,	reG_,	X___,	},
83b7cb133eSJeenu Viswambharan 
84b7cb133eSJeenu Viswambharan 	/* Handler registered and enabled */
85b7cb133eSJeenu Viswambharan /* 3 */	[rEG_] = {	X___,	X___,	NOP_,	reG_,	reg_,	X___,	X___,	X___,	X___,	REG_,	},
86b7cb133eSJeenu Viswambharan 
87b7cb133eSJeenu Viswambharan 	/* Handler registered, enabled, and running */
88b7cb133eSJeenu Viswambharan /* 7 */	[REG_] = {	X___,	X___,	NOP_,	ReG_,	Reg_,	X___,	NOP_,	rEG_,	rEG_,	X___,	},
89b7cb133eSJeenu Viswambharan 
90b7cb133eSJeenu Viswambharan 	/*
91b7cb133eSJeenu Viswambharan 	 * Invalid states: no valid transition would leave the handler in these
92b7cb133eSJeenu Viswambharan 	 * states; and no transition from these states is possible either.
93b7cb133eSJeenu Viswambharan 	 */
94b7cb133eSJeenu Viswambharan 
95b7cb133eSJeenu Viswambharan 	/*
96b7cb133eSJeenu Viswambharan 	 * Handler can't be enabled without being registered. I.e., XEg is
97b7cb133eSJeenu Viswambharan 	 * impossible.
98b7cb133eSJeenu Viswambharan 	 */
99b7cb133eSJeenu Viswambharan /* 2 */	[rEg_] = {	X___,	X___,	X___,	X___,	X___,	X___,	X___,	X___,	X___,	X___,	},
100b7cb133eSJeenu Viswambharan /* 6 */	[REg_] = {	X___,	X___,	X___,	X___,	X___,	X___,	X___,	X___,	X___,	X___,	},
101b7cb133eSJeenu Viswambharan };
102b7cb133eSJeenu Viswambharan 
103b7cb133eSJeenu Viswambharan /*
104b7cb133eSJeenu Viswambharan  * [1] Unregister will always also disable the event, so the new state will have
105b7cb133eSJeenu Viswambharan  *     Xeg.
106b7cb133eSJeenu Viswambharan  * [2] Event is considered for dispatch only when it's both registered and
107b7cb133eSJeenu Viswambharan  *     enabled.
108b7cb133eSJeenu Viswambharan  * [3] Never causes change in state.
109b7cb133eSJeenu Viswambharan  * [4] Only allowed when running.
110b7cb133eSJeenu Viswambharan  */
111b7cb133eSJeenu Viswambharan 
112b7cb133eSJeenu Viswambharan /*
113b7cb133eSJeenu Viswambharan  * Given an action, transition the state of an event by looking up the state
114b7cb133eSJeenu Viswambharan  * table above:
115b7cb133eSJeenu Viswambharan  *
116b7cb133eSJeenu Viswambharan  *  - Return false for invalid transition;
117b7cb133eSJeenu Viswambharan  *  - Return true for valid transition that causes no change in state;
118b7cb133eSJeenu Viswambharan  *  - Otherwise, update state and return true.
119b7cb133eSJeenu Viswambharan  *
120b7cb133eSJeenu Viswambharan  * This function assumes that the caller holds necessary locks. If the
121b7cb133eSJeenu Viswambharan  * transition has constrains other than the state table describes, the caller is
122b7cb133eSJeenu Viswambharan  * expected to restore the previous state. See sdei_event_register() for
123b7cb133eSJeenu Viswambharan  * example.
124b7cb133eSJeenu Viswambharan  */
can_sdei_state_trans(sdei_entry_t * se,sdei_action_t act)125b7cb133eSJeenu Viswambharan bool can_sdei_state_trans(sdei_entry_t *se, sdei_action_t act)
126b7cb133eSJeenu Viswambharan {
127b7cb133eSJeenu Viswambharan 	sdei_state_t next;
128b7cb133eSJeenu Viswambharan 
129b7cb133eSJeenu Viswambharan 	assert(act < DO_MAX);
130b7cb133eSJeenu Viswambharan 	if (se->state >= MAX_STATES) {
131b7cb133eSJeenu Viswambharan 		WARN(" event state invalid: %x\n", se->state);
132b7cb133eSJeenu Viswambharan 		return false;
133b7cb133eSJeenu Viswambharan 	}
134b7cb133eSJeenu Viswambharan 
135b7cb133eSJeenu Viswambharan 	next = sdei_state_table[se->state][act];
136b7cb133eSJeenu Viswambharan 	switch (next) {
137b7cb133eSJeenu Viswambharan 	case SDEI_STATE_INVALID:
138b7cb133eSJeenu Viswambharan 		return false;
139b7cb133eSJeenu Viswambharan 
140b7cb133eSJeenu Viswambharan 	case SDEI_STATE_NOP:
141b7cb133eSJeenu Viswambharan 		return true;
142b7cb133eSJeenu Viswambharan 
143b7cb133eSJeenu Viswambharan 	default:
144b7cb133eSJeenu Viswambharan 		/* Valid transition. Update state. */
145b7cb133eSJeenu Viswambharan 		SDEI_LOG(" event state 0x%x => 0x%x\n", se->state, next);
146b7cb133eSJeenu Viswambharan 		se->state = next;
147b7cb133eSJeenu Viswambharan 
148b7cb133eSJeenu Viswambharan 		return true;
149b7cb133eSJeenu Viswambharan 	}
150b7cb133eSJeenu Viswambharan }
151