aboutsummaryrefslogtreecommitdiff
path: root/plat/arm/css/drivers/scmi/scmi_private.h
blob: 20e1e9b8acf51df4ec7177d4097125c195857d9e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/*
 * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#ifndef __CSS_SCMI_PRIVATE_H__
#define __CSS_SCMI_PRIVATE_H__

/*
 * SCMI power domain management protocol message and response lengths. It is
 * calculated as sum of length in bytes of the message header (4) and payload
 * area (the number of bytes of parameters or return values in the payload).
 */
#define SCMI_PROTO_VERSION_MSG_LEN		4
#define SCMI_PROTO_VERSION_RESP_LEN		12

#define SCMI_PROTO_MSG_ATTR_MSG_LEN		8
#define SCMI_PROTO_MSG_ATTR_RESP_LEN		12

#define SCMI_PWR_STATE_SET_MSG_LEN		16
#define SCMI_PWR_STATE_SET_RESP_LEN		8

#define SCMI_PWR_STATE_GET_MSG_LEN		8
#define SCMI_PWR_STATE_GET_RESP_LEN		12

#define SCMI_SYS_PWR_STATE_SET_MSG_LEN		12
#define SCMI_SYS_PWR_STATE_SET_RESP_LEN		8

#define SCMI_SYS_PWR_STATE_GET_MSG_LEN		4
#define SCMI_SYS_PWR_STATE_GET_RESP_LEN		12

/* SCMI message header format bit field */
#define SCMI_MSG_ID_SHIFT		0
#define SCMI_MSG_ID_WIDTH		8
#define SCMI_MSG_ID_MASK		((1 << SCMI_MSG_ID_WIDTH) - 1)

#define SCMI_MSG_TYPE_SHIFT		8
#define SCMI_MSG_TYPE_WIDTH		2
#define SCMI_MSG_TYPE_MASK		((1 << SCMI_MSG_TYPE_WIDTH) - 1)

#define SCMI_MSG_PROTO_ID_SHIFT		10
#define SCMI_MSG_PROTO_ID_WIDTH		8
#define SCMI_MSG_PROTO_ID_MASK		((1 << SCMI_MSG_PROTO_ID_WIDTH) - 1)

#define SCMI_MSG_TOKEN_SHIFT		18
#define SCMI_MSG_TOKEN_WIDTH		10
#define SCMI_MSG_TOKEN_MASK		((1 << SCMI_MSG_TOKEN_WIDTH) - 1)


/* SCMI mailbox flags */
#define SCMI_FLAG_RESP_POLL	0
#define SCMI_FLAG_RESP_INT	1

/* SCMI power domain protocol `POWER_STATE_SET` message flags */
#define SCMI_PWR_STATE_SET_FLAG_SYNC	0
#define SCMI_PWR_STATE_SET_FLAG_ASYNC	1

/*
 * Helper macro to create an SCMI message header given protocol, message id
 * and token.
 */
#define SCMI_MSG_CREATE(protocol, msg_id, token)				\
	((((protocol) & SCMI_MSG_PROTO_ID_MASK) << SCMI_MSG_PROTO_ID_SHIFT) |	\
	(((msg_id) & SCMI_MSG_ID_MASK) << SCMI_MSG_ID_SHIFT) |			\
	(((token) & SCMI_MSG_TOKEN_MASK) << SCMI_MSG_TOKEN_SHIFT))

/* Helper macro to get the token from a SCMI message header */
#define SCMI_MSG_GET_TOKEN(msg)				\
	(((msg) >> SCMI_MSG_TOKEN_SHIFT) & SCMI_MSG_TOKEN_MASK)

/* SCMI Channel Status bit fields */
#define SCMI_CH_STATUS_RES0_MASK	0xFFFFFFFE
#define SCMI_CH_STATUS_FREE_SHIFT	0
#define SCMI_CH_STATUS_FREE_WIDTH	1
#define SCMI_CH_STATUS_FREE_MASK	((1 << SCMI_CH_STATUS_FREE_WIDTH) - 1)

/* Helper macros to check and write the channel status */
#define SCMI_IS_CHANNEL_FREE(status)					\
	(!!(((status) >> SCMI_CH_STATUS_FREE_SHIFT) & SCMI_CH_STATUS_FREE_MASK))

#define SCMI_MARK_CHANNEL_BUSY(status)	do {				\
		assert(SCMI_IS_CHANNEL_FREE(status));			\
		(status) &= ~(SCMI_CH_STATUS_FREE_MASK <<		\
				SCMI_CH_STATUS_FREE_SHIFT);		\
	} while (0)

/* Helper macros to copy arguments to the mailbox payload */
#define SCMI_PAYLOAD_ARG1(payld_arr, arg1)				\
		mmio_write_32((uintptr_t)&payld_arr[0], arg1)

#define SCMI_PAYLOAD_ARG2(payld_arr, arg1, arg2)	do {		\
		SCMI_PAYLOAD_ARG1(payld_arr, arg1);			\
		mmio_write_32((uintptr_t)&payld_arr[1], arg2);		\
	} while (0)

#define SCMI_PAYLOAD_ARG3(payld_arr, arg1, arg2, arg3)	do {		\
		SCMI_PAYLOAD_ARG2(payld_arr, arg1, arg2);		\
		mmio_write_32((uintptr_t)&payld_arr[2], arg3);		\
	} while (0)

/* Helper macros to read return values from the mailbox payload */
#define SCMI_PAYLOAD_RET_VAL1(payld_arr, val1)				\
		(val1) = mmio_read_32((uintptr_t)&payld_arr[0])

#define SCMI_PAYLOAD_RET_VAL2(payld_arr, val1, val2)	do {		\
		SCMI_PAYLOAD_RET_VAL1(payld_arr, val1);			\
		(val2) = mmio_read_32((uintptr_t)&payld_arr[1]);	\
	} while (0)

#define SCMI_PAYLOAD_RET_VAL3(payld_arr, val1, val2, val3)	do {	\
		SCMI_PAYLOAD_RET_VAL2(payld_arr, val1, val2);		\
		(val3) = mmio_read_32((uintptr_t)&payld_arr[2]);	\
	} while (0)

/* Helper macro to ring doorbell */
#define SCMI_RING_DOORBELL(addr, modify_mask, preserve_mask)	do {	\
		uint32_t db = mmio_read_32(addr) & (preserve_mask);	\
		mmio_write_32(addr, db | (modify_mask));		\
	} while (0)

/*
 * Private data structure for representing the mailbox memory layout. Refer
 * the SCMI specification for more details.
 */
typedef struct mailbox_mem {
	uint32_t res_a; /* Reserved */
	volatile uint32_t status;
	uint64_t res_b; /* Reserved */
	uint32_t flags;
	volatile uint32_t len;
	uint32_t msg_header;
	uint32_t payload[];
} mailbox_mem_t;


/* Private APIs for use within SCMI driver */
void scmi_get_channel(scmi_channel_t *ch);
void scmi_send_sync_command(scmi_channel_t *ch);
void scmi_put_channel(scmi_channel_t *ch);

static inline void validate_scmi_channel(scmi_channel_t *ch)
{
	assert(ch && ch->is_initialized);
	assert(ch->info && ch->info->scmi_mbx_mem);
}

#endif	/* __CSS_SCMI_PRIVATE_H__ */