File Index
Files and directories
Sign in
FILE

macsmc.h

File preview with syntax highlighting.

linux-6.19.14/include/linux/mfd/macsmc.h C
  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
~/ Read-only file preview.