1 /* 2 * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #ifndef __CSS_SCMI_PRIVATE_H__ 8 #define __CSS_SCMI_PRIVATE_H__ 9 10 /* 11 * SCMI power domain management protocol message and response lengths. It is 12 * calculated as sum of length in bytes of the message header (4) and payload 13 * area (the number of bytes of parameters or return values in the payload). 14 */ 15 #define SCMI_PROTO_VERSION_MSG_LEN 4 16 #define SCMI_PROTO_VERSION_RESP_LEN 12 17 18 #define SCMI_PROTO_MSG_ATTR_MSG_LEN 8 19 #define SCMI_PROTO_MSG_ATTR_RESP_LEN 12 20 21 #define SCMI_PWR_STATE_SET_MSG_LEN 16 22 #define SCMI_PWR_STATE_SET_RESP_LEN 8 23 24 #define SCMI_PWR_STATE_GET_MSG_LEN 8 25 #define SCMI_PWR_STATE_GET_RESP_LEN 12 26 27 #define SCMI_SYS_PWR_STATE_SET_MSG_LEN 12 28 #define SCMI_SYS_PWR_STATE_SET_RESP_LEN 8 29 30 #define SCMI_SYS_PWR_STATE_GET_MSG_LEN 4 31 #define SCMI_SYS_PWR_STATE_GET_RESP_LEN 12 32 33 /* SCMI message header format bit field */ 34 #define SCMI_MSG_ID_SHIFT 0 35 #define SCMI_MSG_ID_WIDTH 8 36 #define SCMI_MSG_ID_MASK ((1 << SCMI_MSG_ID_WIDTH) - 1) 37 38 #define SCMI_MSG_TYPE_SHIFT 8 39 #define SCMI_MSG_TYPE_WIDTH 2 40 #define SCMI_MSG_TYPE_MASK ((1 << SCMI_MSG_TYPE_WIDTH) - 1) 41 42 #define SCMI_MSG_PROTO_ID_SHIFT 10 43 #define SCMI_MSG_PROTO_ID_WIDTH 8 44 #define SCMI_MSG_PROTO_ID_MASK ((1 << SCMI_MSG_PROTO_ID_WIDTH) - 1) 45 46 #define SCMI_MSG_TOKEN_SHIFT 18 47 #define SCMI_MSG_TOKEN_WIDTH 10 48 #define SCMI_MSG_TOKEN_MASK ((1 << SCMI_MSG_TOKEN_WIDTH) - 1) 49 50 51 /* SCMI mailbox flags */ 52 #define SCMI_FLAG_RESP_POLL 0 53 #define SCMI_FLAG_RESP_INT 1 54 55 /* SCMI power domain protocol `POWER_STATE_SET` message flags */ 56 #define SCMI_PWR_STATE_SET_FLAG_SYNC 0 57 #define SCMI_PWR_STATE_SET_FLAG_ASYNC 1 58 59 /* 60 * Helper macro to create an SCMI message header given protocol, message id 61 * and token. 62 */ 63 #define SCMI_MSG_CREATE(protocol, msg_id, token) \ 64 ((((protocol) & SCMI_MSG_PROTO_ID_MASK) << SCMI_MSG_PROTO_ID_SHIFT) | \ 65 (((msg_id) & SCMI_MSG_ID_MASK) << SCMI_MSG_ID_SHIFT) | \ 66 (((token) & SCMI_MSG_TOKEN_MASK) << SCMI_MSG_TOKEN_SHIFT)) 67 68 /* Helper macro to get the token from a SCMI message header */ 69 #define SCMI_MSG_GET_TOKEN(msg) \ 70 (((msg) >> SCMI_MSG_TOKEN_SHIFT) & SCMI_MSG_TOKEN_MASK) 71 72 /* SCMI Channel Status bit fields */ 73 #define SCMI_CH_STATUS_RES0_MASK 0xFFFFFFFE 74 #define SCMI_CH_STATUS_FREE_SHIFT 0 75 #define SCMI_CH_STATUS_FREE_WIDTH 1 76 #define SCMI_CH_STATUS_FREE_MASK ((1 << SCMI_CH_STATUS_FREE_WIDTH) - 1) 77 78 /* Helper macros to check and write the channel status */ 79 #define SCMI_IS_CHANNEL_FREE(status) \ 80 (!!(((status) >> SCMI_CH_STATUS_FREE_SHIFT) & SCMI_CH_STATUS_FREE_MASK)) 81 82 #define SCMI_MARK_CHANNEL_BUSY(status) do { \ 83 assert(SCMI_IS_CHANNEL_FREE(status)); \ 84 (status) &= ~(SCMI_CH_STATUS_FREE_MASK << \ 85 SCMI_CH_STATUS_FREE_SHIFT); \ 86 } while (0) 87 88 /* Helper macros to copy arguments to the mailbox payload */ 89 #define SCMI_PAYLOAD_ARG1(payld_arr, arg1) \ 90 mmio_write_32((uintptr_t)&payld_arr[0], arg1) 91 92 #define SCMI_PAYLOAD_ARG2(payld_arr, arg1, arg2) do { \ 93 SCMI_PAYLOAD_ARG1(payld_arr, arg1); \ 94 mmio_write_32((uintptr_t)&payld_arr[1], arg2); \ 95 } while (0) 96 97 #define SCMI_PAYLOAD_ARG3(payld_arr, arg1, arg2, arg3) do { \ 98 SCMI_PAYLOAD_ARG2(payld_arr, arg1, arg2); \ 99 mmio_write_32((uintptr_t)&payld_arr[2], arg3); \ 100 } while (0) 101 102 /* Helper macros to read return values from the mailbox payload */ 103 #define SCMI_PAYLOAD_RET_VAL1(payld_arr, val1) \ 104 (val1) = mmio_read_32((uintptr_t)&payld_arr[0]) 105 106 #define SCMI_PAYLOAD_RET_VAL2(payld_arr, val1, val2) do { \ 107 SCMI_PAYLOAD_RET_VAL1(payld_arr, val1); \ 108 (val2) = mmio_read_32((uintptr_t)&payld_arr[1]); \ 109 } while (0) 110 111 #define SCMI_PAYLOAD_RET_VAL3(payld_arr, val1, val2, val3) do { \ 112 SCMI_PAYLOAD_RET_VAL2(payld_arr, val1, val2); \ 113 (val3) = mmio_read_32((uintptr_t)&payld_arr[2]); \ 114 } while (0) 115 116 /* Helper macro to ring doorbell */ 117 #define SCMI_RING_DOORBELL(addr, modify_mask, preserve_mask) do { \ 118 uint32_t db = mmio_read_32(addr) & (preserve_mask); \ 119 mmio_write_32(addr, db | (modify_mask)); \ 120 } while (0) 121 122 /* 123 * Private data structure for representing the mailbox memory layout. Refer 124 * the SCMI specification for more details. 125 */ 126 typedef struct mailbox_mem { 127 uint32_t res_a; /* Reserved */ 128 volatile uint32_t status; 129 uint64_t res_b; /* Reserved */ 130 uint32_t flags; 131 volatile uint32_t len; 132 uint32_t msg_header; 133 uint32_t payload[]; 134 } mailbox_mem_t; 135 136 137 /* Private APIs for use within SCMI driver */ 138 void scmi_get_channel(scmi_channel_t *ch); 139 void scmi_send_sync_command(scmi_channel_t *ch); 140 void scmi_put_channel(scmi_channel_t *ch); 141 142 static inline void validate_scmi_channel(scmi_channel_t *ch) 143 { 144 assert(ch && ch->is_initialized); 145 assert(ch->info && ch->info->scmi_mbx_mem); 146 } 147 148 #endif /* __CSS_SCMI_PRIVATE_H__ */ 149