at v6.18 279 lines 9.1 kB view raw
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 */ 31typedef 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 45#define APPLE_SMC_READABLE BIT(7) 46#define APPLE_SMC_WRITABLE BIT(6) 47#define APPLE_SMC_FUNCTION BIT(4) 48 49/** 50 * struct apple_smc_key_info - Information for a SMC key as returned by SMC 51 * @type_code: FourCC code indicating the type for this key. 52 * Known types: 53 * ch8*: ASCII string 54 * flag: Boolean, 1 or 0 55 * flt: 32-bit single-precision IEEE 754 float 56 * hex: Binary data 57 * ioft: 64bit Unsigned fixed-point intger (48.16) 58 * {si,ui}{8,16,32,64}: Signed/Unsigned 8-/16-/32-/64-bit integer 59 * @size: Size of the buffer associated with this key 60 * @flags: Bitfield encoding flags (APPLE_SMC_{READABLE,WRITABLE,FUNCTION}) 61 */ 62struct apple_smc_key_info { 63 u32 type_code; 64 u8 size; 65 u8 flags; 66}; 67 68/** 69 * enum apple_smc_boot_stage - SMC boot stage 70 * @APPLE_SMC_BOOTING: SMC is booting 71 * @APPLE_SMC_INITIALIZED: SMC is initialized and ready to use 72 * @APPLE_SMC_ERROR_NO_SHMEM: Shared memory could not be initialized during boot 73 * @APPLE_SMC_ERROR_CRASHED: SMC has crashed 74 */ 75enum apple_smc_boot_stage { 76 APPLE_SMC_BOOTING, 77 APPLE_SMC_INITIALIZED, 78 APPLE_SMC_ERROR_NO_SHMEM, 79 APPLE_SMC_ERROR_CRASHED 80}; 81 82/** 83 * struct apple_smc 84 * @dev: Underlying device struct for the physical backend device 85 * @key_count: Number of available SMC keys 86 * @first_key: First valid SMC key 87 * @last_key: Last valid SMC key 88 * @event_handlers: Notifier call chain for events received from SMC 89 * @rtk: Pointer to Apple RTKit instance 90 * @init_done: Completion for initialization 91 * @boot_stage: Current boot stage of SMC 92 * @sram: Pointer to SRAM resource 93 * @sram_base: SRAM base address 94 * @shmem: RTKit shared memory structure for SRAM 95 * @msg_id: Current message id for commands, will be incremented for each command 96 * @atomic_mode: Flag set when atomic mode is entered 97 * @atomic_pending: Flag indicating pending atomic command 98 * @cmd_done: Completion for command execution in non-atomic mode 99 * @cmd_ret: Return value from SMC for last command 100 * @mutex: Mutex for non-atomic mode 101 * @lock: Spinlock for atomic mode 102 */ 103struct apple_smc { 104 struct device *dev; 105 106 u32 key_count; 107 smc_key first_key; 108 smc_key last_key; 109 110 struct blocking_notifier_head event_handlers; 111 112 struct apple_rtkit *rtk; 113 114 struct completion init_done; 115 enum apple_smc_boot_stage boot_stage; 116 117 struct resource *sram; 118 void __iomem *sram_base; 119 struct apple_rtkit_shmem shmem; 120 121 unsigned int msg_id; 122 123 bool atomic_mode; 124 bool atomic_pending; 125 struct completion cmd_done; 126 u64 cmd_ret; 127 128 struct mutex mutex; 129 spinlock_t lock; 130}; 131 132/** 133 * apple_smc_read - Read size bytes from given SMC key into buf 134 * @smc: Pointer to apple_smc struct 135 * @key: smc_key to be read 136 * @buf: Buffer into which size bytes of data will be read from SMC 137 * @size: Number of bytes to be read into buf 138 * 139 * Return: Zero on success, negative errno on error 140 */ 141int apple_smc_read(struct apple_smc *smc, smc_key key, void *buf, size_t size); 142 143/** 144 * apple_smc_write - Write size bytes into given SMC key from buf 145 * @smc: Pointer to apple_smc struct 146 * @key: smc_key data will be written to 147 * @buf: Buffer from which size bytes of data will be written to SMC 148 * @size: Number of bytes to be written 149 * 150 * Return: Zero on success, negative errno on error 151 */ 152int apple_smc_write(struct apple_smc *smc, smc_key key, void *buf, size_t size); 153 154/** 155 * apple_smc_enter_atomic - Enter atomic mode to be able to use apple_smc_write_atomic 156 * @smc: Pointer to apple_smc struct 157 * 158 * This function switches the SMC backend to atomic mode which allows the 159 * use of apple_smc_write_atomic while disabling *all* other functions. 160 * This is only used for shutdown/reboot which requires writing to a SMC 161 * key from atomic context. 162 * 163 * Return: Zero on success, negative errno on error 164 */ 165int apple_smc_enter_atomic(struct apple_smc *smc); 166 167/** 168 * apple_smc_write_atomic - Write size bytes into given SMC key from buf without sleeping 169 * @smc: Pointer to apple_smc struct 170 * @key: smc_key data will be written to 171 * @buf: Buffer from which size bytes of data will be written to SMC 172 * @size: Number of bytes to be written 173 * 174 * Note that this function will fail if apple_smc_enter_atomic hasn't been 175 * called before. 176 * 177 * Return: Zero on success, negative errno on error 178 */ 179int apple_smc_write_atomic(struct apple_smc *smc, smc_key key, void *buf, size_t size); 180 181/** 182 * apple_smc_rw - Write and then read using the given SMC key 183 * @smc: Pointer to apple_smc struct 184 * @key: smc_key data will be written to 185 * @wbuf: Buffer from which size bytes of data will be written to SMC 186 * @wsize: Number of bytes to be written 187 * @rbuf: Buffer to which size bytes of data will be read from SMC 188 * @rsize: Number of bytes to be read 189 * 190 * Return: Zero on success, negative errno on error 191 */ 192int apple_smc_rw(struct apple_smc *smc, smc_key key, void *wbuf, size_t wsize, 193 void *rbuf, size_t rsize); 194 195/** 196 * apple_smc_get_key_by_index - Given an index return the corresponding SMC key 197 * @smc: Pointer to apple_smc struct 198 * @index: Index to be resolved 199 * @key: Buffer for SMC key to be returned 200 * 201 * Return: Zero on success, negative errno on error 202 */ 203int apple_smc_get_key_by_index(struct apple_smc *smc, int index, smc_key *key); 204 205/** 206 * apple_smc_get_key_info - Get key information from SMC 207 * @smc: Pointer to apple_smc struct 208 * @key: Key to acquire information for 209 * @info: Pointer to struct apple_smc_key_info which will be filled 210 * 211 * Return: Zero on success, negative errno on error 212 */ 213int apple_smc_get_key_info(struct apple_smc *smc, smc_key key, struct apple_smc_key_info *info); 214 215/** 216 * apple_smc_key_exists - Check if the given SMC key exists 217 * @smc: Pointer to apple_smc struct 218 * @key: smc_key to be checked 219 * 220 * Return: True if the key exists, false otherwise 221 */ 222static inline bool apple_smc_key_exists(struct apple_smc *smc, smc_key key) 223{ 224 return apple_smc_get_key_info(smc, key, NULL) >= 0; 225} 226 227#define APPLE_SMC_TYPE_OPS(type) \ 228 static inline int apple_smc_read_##type(struct apple_smc *smc, smc_key key, type *p) \ 229 { \ 230 int ret = apple_smc_read(smc, key, p, sizeof(*p)); \ 231 return (ret < 0) ? ret : ((ret != sizeof(*p)) ? -EINVAL : 0); \ 232 } \ 233 static inline int apple_smc_write_##type(struct apple_smc *smc, smc_key key, type p) \ 234 { \ 235 return apple_smc_write(smc, key, &p, sizeof(p)); \ 236 } \ 237 static inline int apple_smc_write_##type##_atomic(struct apple_smc *smc, smc_key key, type p) \ 238 { \ 239 return apple_smc_write_atomic(smc, key, &p, sizeof(p)); \ 240 } \ 241 static inline int apple_smc_rw_##type(struct apple_smc *smc, smc_key key, \ 242 type w, type *r) \ 243 { \ 244 int ret = apple_smc_rw(smc, key, &w, sizeof(w), r, sizeof(*r)); \ 245 return (ret < 0) ? ret : ((ret != sizeof(*r)) ? -EINVAL : 0); \ 246 } 247 248APPLE_SMC_TYPE_OPS(u64) 249APPLE_SMC_TYPE_OPS(u32) 250APPLE_SMC_TYPE_OPS(u16) 251APPLE_SMC_TYPE_OPS(u8) 252APPLE_SMC_TYPE_OPS(s64) 253APPLE_SMC_TYPE_OPS(s32) 254APPLE_SMC_TYPE_OPS(s16) 255APPLE_SMC_TYPE_OPS(s8) 256 257static inline int apple_smc_read_flag(struct apple_smc *smc, smc_key key, bool *flag) 258{ 259 u8 val; 260 int ret = apple_smc_read_u8(smc, key, &val); 261 262 if (ret < 0) 263 return ret; 264 265 *flag = val ? true : false; 266 return ret; 267} 268 269static inline int apple_smc_write_flag(struct apple_smc *smc, smc_key key, bool state) 270{ 271 return apple_smc_write_u8(smc, key, state ? 1 : 0); 272} 273 274static inline int apple_smc_write_flag_atomic(struct apple_smc *smc, smc_key key, bool state) 275{ 276 return apple_smc_write_u8_atomic(smc, key, state ? 1 : 0); 277} 278 279#endif