1 /* SPDX-License-Identifier: GPL-2.0-only OR MIT */ 2 /* 3 * Apple SMC (System Management Controller) core definitions 4 * 5 * Copyright (C) The Asahi Linux Contributors 6 */ 7 8 #ifndef _LINUX_MFD_MACSMC_H 9 #define _LINUX_MFD_MACSMC_H 10 11 #include <linux/soc/apple/rtkit.h> 12 13 /** 14 * typedef smc_key - Alias for u32 to be used for SMC keys 15 * 16 * SMC keys are 32bit integers containing packed ASCII characters in natural 17 * integer order, i.e. 0xAABBCCDD, which represent the FourCC ABCD. 18 * The SMC driver is designed with this assumption and ensures the right 19 * endianness is used when these are stored to memory and sent to or received 20 * from the actual SMC firmware (which can be done in either shared memory or 21 * as 64bit mailbox message on Apple Silicon). 22 * Internally, SMC stores these keys in a table sorted lexicographically and 23 * allows resolving an index into this table to the corresponding SMC key. 24 * Thus, storing keys as u32 is very convenient as it allows to e.g. use 25 * normal comparison operators which directly map to the natural order used 26 * by SMC firmware. 27 * 28 * This simple type alias is introduced to allow easy recognition of SMC key 29 * variables and arguments. 30 */ 31 typedef u32 smc_key; 32 33 /** 34 * SMC_KEY - Convert FourCC SMC keys in source code to smc_key 35 * 36 * This macro can be used to easily define FourCC SMC keys in source code 37 * and convert these to u32 / smc_key, e.g. SMC_KEY(NTAP) will expand to 38 * 0x4e544150. 39 * 40 * @s: FourCC SMC key to be converted 41 */ 42 #define SMC_KEY(s) (smc_key)(_SMC_KEY(#s)) 43 #define _SMC_KEY(s) (((s)[0] << 24) | ((s)[1] << 16) | ((s)[2] << 8) | (s)[3]) 44 #define __SMC_KEY(a, b, c, d) (((u32)(a) << 24) | ((u32)(b) << 16) | ((u32)(c) << 8) | ((u32)(d))) 45 46 #define APPLE_SMC_READABLE BIT(7) 47 #define APPLE_SMC_WRITABLE BIT(6) 48 #define APPLE_SMC_FUNCTION BIT(4) 49 50 /** 51 * struct apple_smc_key_info - Information for a SMC key as returned by SMC 52 * @type_code: FourCC code indicating the type for this key. 53 * Known types: 54 * ch8*: ASCII string 55 * flag: Boolean, 1 or 0 56 * flt: 32-bit single-precision IEEE 754 float 57 * hex: Binary data 58 * ioft: 64bit Unsigned fixed-point intger (48.16) 59 * {si,ui}{8,16,32,64}: Signed/Unsigned 8-/16-/32-/64-bit integer 60 * @size: Size of the buffer associated with this key 61 * @flags: Bitfield encoding flags (APPLE_SMC_{READABLE,WRITABLE,FUNCTION}) 62 */ 63 struct apple_smc_key_info { 64 u32 type_code; 65 u8 size; 66 u8 flags; 67 }; 68 69 /** 70 * enum apple_smc_boot_stage - SMC boot stage 71 * @APPLE_SMC_BOOTING: SMC is booting 72 * @APPLE_SMC_INITIALIZED: SMC is initialized and ready to use 73 * @APPLE_SMC_ERROR_NO_SHMEM: Shared memory could not be initialized during boot 74 * @APPLE_SMC_ERROR_CRASHED: SMC has crashed 75 */ 76 enum apple_smc_boot_stage { 77 APPLE_SMC_BOOTING, 78 APPLE_SMC_INITIALIZED, 79 APPLE_SMC_ERROR_NO_SHMEM, 80 APPLE_SMC_ERROR_CRASHED 81 }; 82 83 /** 84 * struct apple_smc 85 * @dev: Underlying device struct for the physical backend device 86 * @key_count: Number of available SMC keys 87 * @first_key: First valid SMC key 88 * @last_key: Last valid SMC key 89 * @event_handlers: Notifier call chain for events received from SMC 90 * @rtk: Pointer to Apple RTKit instance 91 * @init_done: Completion for initialization 92 * @boot_stage: Current boot stage of SMC 93 * @sram: Pointer to SRAM resource 94 * @sram_base: SRAM base address 95 * @shmem: RTKit shared memory structure for SRAM 96 * @msg_id: Current message id for commands, will be incremented for each command 97 * @atomic_mode: Flag set when atomic mode is entered 98 * @atomic_pending: Flag indicating pending atomic command 99 * @cmd_done: Completion for command execution in non-atomic mode 100 * @cmd_ret: Return value from SMC for last command 101 * @mutex: Mutex for non-atomic mode 102 * @lock: Spinlock for atomic mode 103 */ 104 struct apple_smc { 105 struct device *dev; 106 107 u32 key_count; 108 smc_key first_key; 109 smc_key last_key; 110 111 struct blocking_notifier_head event_handlers; 112 113 struct apple_rtkit *rtk; 114 115 struct completion init_done; 116 enum apple_smc_boot_stage boot_stage; 117 118 struct resource *sram; 119 void __iomem *sram_base; 120 struct apple_rtkit_shmem shmem; 121 122 unsigned int msg_id; 123 124 bool atomic_mode; 125 bool atomic_pending; 126 struct completion cmd_done; 127 u64 cmd_ret; 128 129 struct mutex mutex; 130 spinlock_t lock; 131 }; 132 133 /** 134 * apple_smc_read - Read size bytes from given SMC key into buf 135 * @smc: Pointer to apple_smc struct 136 * @key: smc_key to be read 137 * @buf: Buffer into which size bytes of data will be read from SMC 138 * @size: Number of bytes to be read into buf 139 * 140 * Return: Zero on success, negative errno on error 141 */ 142 int apple_smc_read(struct apple_smc *smc, smc_key key, void *buf, size_t size); 143 144 /** 145 * apple_smc_write - Write size bytes into given SMC key from buf 146 * @smc: Pointer to apple_smc struct 147 * @key: smc_key data will be written to 148 * @buf: Buffer from which size bytes of data will be written to SMC 149 * @size: Number of bytes to be written 150 * 151 * Return: Zero on success, negative errno on error 152 */ 153 int apple_smc_write(struct apple_smc *smc, smc_key key, const void *buf, size_t size); 154 155 /** 156 * apple_smc_enter_atomic - Enter atomic mode to be able to use apple_smc_write_atomic 157 * @smc: Pointer to apple_smc struct 158 * 159 * This function switches the SMC backend to atomic mode which allows the 160 * use of apple_smc_write_atomic while disabling *all* other functions. 161 * This is only used for shutdown/reboot which requires writing to a SMC 162 * key from atomic context. 163 * 164 * Return: Zero on success, negative errno on error 165 */ 166 int apple_smc_enter_atomic(struct apple_smc *smc); 167 168 /** 169 * apple_smc_write_atomic - Write size bytes into given SMC key from buf without sleeping 170 * @smc: Pointer to apple_smc struct 171 * @key: smc_key data will be written to 172 * @buf: Buffer from which size bytes of data will be written to SMC 173 * @size: Number of bytes to be written 174 * 175 * Note that this function will fail if apple_smc_enter_atomic hasn't been 176 * called before. 177 * 178 * Return: Zero on success, negative errno on error 179 */ 180 int apple_smc_write_atomic(struct apple_smc *smc, smc_key key, const void *buf, size_t size); 181 182 /** 183 * apple_smc_rw - Write and then read using the given SMC key 184 * @smc: Pointer to apple_smc struct 185 * @key: smc_key data will be written to 186 * @wbuf: Buffer from which size bytes of data will be written to SMC 187 * @wsize: Number of bytes to be written 188 * @rbuf: Buffer to which size bytes of data will be read from SMC 189 * @rsize: Number of bytes to be read 190 * 191 * Return: Zero on success, negative errno on error 192 */ 193 int apple_smc_rw(struct apple_smc *smc, smc_key key, const void *wbuf, size_t wsize, 194 void *rbuf, size_t rsize); 195 196 /** 197 * apple_smc_get_key_by_index - Given an index return the corresponding SMC key 198 * @smc: Pointer to apple_smc struct 199 * @index: Index to be resolved 200 * @key: Buffer for SMC key to be returned 201 * 202 * Return: Zero on success, negative errno on error 203 */ 204 int apple_smc_get_key_by_index(struct apple_smc *smc, int index, smc_key *key); 205 206 /** 207 * apple_smc_get_key_info - Get key information from SMC 208 * @smc: Pointer to apple_smc struct 209 * @key: Key to acquire information for 210 * @info: Pointer to struct apple_smc_key_info which will be filled 211 * 212 * Return: Zero on success, negative errno on error 213 */ 214 int apple_smc_get_key_info(struct apple_smc *smc, smc_key key, struct apple_smc_key_info *info); 215 216 /** 217 * apple_smc_key_exists - Check if the given SMC key exists 218 * @smc: Pointer to apple_smc struct 219 * @key: smc_key to be checked 220 * 221 * Return: True if the key exists, false otherwise 222 */ 223 static inline bool apple_smc_key_exists(struct apple_smc *smc, smc_key key) 224 { 225 return apple_smc_get_key_info(smc, key, NULL) >= 0; 226 } 227 228 #define APPLE_SMC_TYPE_OPS(type) \ 229 static inline int apple_smc_read_##type(struct apple_smc *smc, smc_key key, type *p) \ 230 { \ 231 int ret = apple_smc_read(smc, key, p, sizeof(*p)); \ 232 return (ret < 0) ? ret : ((ret != sizeof(*p)) ? -EINVAL : 0); \ 233 } \ 234 static inline int apple_smc_write_##type(struct apple_smc *smc, smc_key key, type p) \ 235 { \ 236 return apple_smc_write(smc, key, &p, sizeof(p)); \ 237 } \ 238 static inline int apple_smc_write_##type##_atomic(struct apple_smc *smc, smc_key key, type p) \ 239 { \ 240 return apple_smc_write_atomic(smc, key, &p, sizeof(p)); \ 241 } \ 242 static inline int apple_smc_rw_##type(struct apple_smc *smc, smc_key key, \ 243 type w, type *r) \ 244 { \ 245 int ret = apple_smc_rw(smc, key, &w, sizeof(w), r, sizeof(*r)); \ 246 return (ret < 0) ? ret : ((ret != sizeof(*r)) ? -EINVAL : 0); \ 247 } 248 249 APPLE_SMC_TYPE_OPS(u64) 250 APPLE_SMC_TYPE_OPS(u32) 251 APPLE_SMC_TYPE_OPS(u16) 252 APPLE_SMC_TYPE_OPS(u8) 253 APPLE_SMC_TYPE_OPS(s64) 254 APPLE_SMC_TYPE_OPS(s32) 255 APPLE_SMC_TYPE_OPS(s16) 256 APPLE_SMC_TYPE_OPS(s8) 257 258 static inline int apple_smc_read_flag(struct apple_smc *smc, smc_key key, bool *flag) 259 { 260 u8 val; 261 int ret = apple_smc_read_u8(smc, key, &val); 262 263 if (ret < 0) 264 return ret; 265 266 *flag = val ? true : false; 267 return ret; 268 } 269 270 static inline int apple_smc_write_flag(struct apple_smc *smc, smc_key key, bool state) 271 { 272 return apple_smc_write_u8(smc, key, state ? 1 : 0); 273 } 274 275 static inline int apple_smc_write_flag_atomic(struct apple_smc *smc, smc_key key, bool state) 276 { 277 return apple_smc_write_u8_atomic(smc, key, state ? 1 : 0); 278 } 279 280 #endif 281