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
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 */
62 struct 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 */
75 enum 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 */
103 struct 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 */
141 int 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 */
152 int 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 */
165 int 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 */
179 int 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 */
192 int 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 */
203 int 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 */
213 int 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 */
apple_smc_key_exists(struct apple_smc * smc,smc_key key)222 static 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
248 APPLE_SMC_TYPE_OPS(u64)
APPLE_SMC_TYPE_OPS(u32)249 APPLE_SMC_TYPE_OPS(u32)
250 APPLE_SMC_TYPE_OPS(u16)
251 APPLE_SMC_TYPE_OPS(u8)
252 APPLE_SMC_TYPE_OPS(s64)
253 APPLE_SMC_TYPE_OPS(s32)
254 APPLE_SMC_TYPE_OPS(s16)
255 APPLE_SMC_TYPE_OPS(s8)
256
257 static 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
apple_smc_write_flag(struct apple_smc * smc,smc_key key,bool state)269 static 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
apple_smc_write_flag_atomic(struct apple_smc * smc,smc_key key,bool state)274 static 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
280