at master 9.2 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#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 */ 63struct 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 */ 76enum 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 */ 104struct 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 */ 142int 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 */ 153int 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 */ 166int 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 */ 180int 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 */ 193int 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 */ 204int 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 */ 214int 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 */ 223static 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 249APPLE_SMC_TYPE_OPS(u64) 250APPLE_SMC_TYPE_OPS(u32) 251APPLE_SMC_TYPE_OPS(u16) 252APPLE_SMC_TYPE_OPS(u8) 253APPLE_SMC_TYPE_OPS(s64) 254APPLE_SMC_TYPE_OPS(s32) 255APPLE_SMC_TYPE_OPS(s16) 256APPLE_SMC_TYPE_OPS(s8) 257 258static 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 270static 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 275static 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