xref: /linux/drivers/mfd/macsmc.c (revision fcb117e0758d1462128a50c5788555e03b48833b)
1 // SPDX-License-Identifier: GPL-2.0-only OR MIT
2 /*
3  * Apple SMC (System Management Controller) MFD driver
4  *
5  * Copyright The Asahi Linux Contributors
6  */
7 
8 #include <linux/bitfield.h>
9 #include <linux/delay.h>
10 #include <linux/device.h>
11 #include <linux/io.h>
12 #include <linux/ioport.h>
13 #include <linux/math.h>
14 #include <linux/mfd/core.h>
15 #include <linux/mfd/macsmc.h>
16 #include <linux/notifier.h>
17 #include <linux/of.h>
18 #include <linux/of_platform.h>
19 #include <linux/overflow.h>
20 #include <linux/platform_device.h>
21 #include <linux/soc/apple/rtkit.h>
22 #include <linux/unaligned.h>
23 
24 #define SMC_ENDPOINT			0x20
25 
26 /* We don't actually know the true size here but this seem reasonable */
27 #define SMC_SHMEM_SIZE			0x1000
28 #define SMC_MAX_SIZE			255
29 
30 #define SMC_MSG_READ_KEY		0x10
31 #define SMC_MSG_WRITE_KEY		0x11
32 #define SMC_MSG_GET_KEY_BY_INDEX	0x12
33 #define SMC_MSG_GET_KEY_INFO		0x13
34 #define SMC_MSG_INITIALIZE		0x17
35 #define SMC_MSG_NOTIFICATION		0x18
36 #define SMC_MSG_RW_KEY			0x20
37 
38 #define SMC_DATA			GENMASK_ULL(63, 32)
39 #define SMC_WSIZE			GENMASK_ULL(31, 24)
40 #define SMC_SIZE			GENMASK_ULL(23, 16)
41 #define SMC_ID				GENMASK_ULL(15, 12)
42 #define SMC_MSG				GENMASK_ULL(7, 0)
43 #define SMC_RESULT			SMC_MSG
44 
45 #define SMC_TIMEOUT_MS		500
46 
47 static const struct mfd_cell apple_smc_devs[] = {
48 	MFD_CELL_OF("macsmc-gpio", NULL, NULL, 0, 0, "apple,smc-gpio"),
49 	MFD_CELL_OF("macsmc-reboot", NULL, NULL, 0, 0, "apple,smc-reboot"),
50 };
51 
apple_smc_cmd_locked(struct apple_smc * smc,u64 cmd,u64 arg,u64 size,u64 wsize,u32 * ret_data)52 static int apple_smc_cmd_locked(struct apple_smc *smc, u64 cmd, u64 arg,
53 				  u64 size, u64 wsize, u32 *ret_data)
54 {
55 	u8 result;
56 	int ret;
57 	u64 msg;
58 
59 	lockdep_assert_held(&smc->mutex);
60 
61 	if (smc->boot_stage != APPLE_SMC_INITIALIZED)
62 		return -EIO;
63 	if (smc->atomic_mode)
64 		return -EIO;
65 
66 	reinit_completion(&smc->cmd_done);
67 
68 	smc->msg_id = (smc->msg_id + 1) & 0xf;
69 	msg = (FIELD_PREP(SMC_MSG, cmd) |
70 	       FIELD_PREP(SMC_SIZE, size) |
71 	       FIELD_PREP(SMC_WSIZE, wsize) |
72 	       FIELD_PREP(SMC_ID, smc->msg_id) |
73 	       FIELD_PREP(SMC_DATA, arg));
74 
75 	ret = apple_rtkit_send_message(smc->rtk, SMC_ENDPOINT, msg, NULL, false);
76 	if (ret) {
77 		dev_err(smc->dev, "Failed to send command\n");
78 		return ret;
79 	}
80 
81 	if (wait_for_completion_timeout(&smc->cmd_done, msecs_to_jiffies(SMC_TIMEOUT_MS)) <= 0) {
82 		dev_err(smc->dev, "Command timed out (%llx)", msg);
83 		return -ETIMEDOUT;
84 	}
85 
86 	if (FIELD_GET(SMC_ID, smc->cmd_ret) != smc->msg_id) {
87 		dev_err(smc->dev, "Command sequence mismatch (expected %d, got %d)\n",
88 			smc->msg_id, (unsigned int)FIELD_GET(SMC_ID, smc->cmd_ret));
89 		return -EIO;
90 	}
91 
92 	result = FIELD_GET(SMC_RESULT, smc->cmd_ret);
93 	if (result)
94 		return -EIO;
95 
96 	if (ret_data)
97 		*ret_data = FIELD_GET(SMC_DATA, smc->cmd_ret);
98 
99 	return FIELD_GET(SMC_SIZE, smc->cmd_ret);
100 }
101 
apple_smc_cmd(struct apple_smc * smc,u64 cmd,u64 arg,u64 size,u64 wsize,u32 * ret_data)102 static int apple_smc_cmd(struct apple_smc *smc, u64 cmd, u64 arg,
103 			 u64 size, u64 wsize, u32 *ret_data)
104 {
105 	guard(mutex)(&smc->mutex);
106 
107 	return apple_smc_cmd_locked(smc, cmd, arg, size, wsize, ret_data);
108 }
109 
apple_smc_rw_locked(struct apple_smc * smc,smc_key key,const void * wbuf,size_t wsize,void * rbuf,size_t rsize)110 static int apple_smc_rw_locked(struct apple_smc *smc, smc_key key,
111 				const void *wbuf, size_t wsize,
112 				void *rbuf, size_t rsize)
113 {
114 	u64 smc_size, smc_wsize;
115 	u32 rdata;
116 	int ret;
117 	u64 cmd;
118 
119 	lockdep_assert_held(&smc->mutex);
120 
121 	if (rsize > SMC_MAX_SIZE)
122 		return -EINVAL;
123 	if (wsize > SMC_MAX_SIZE)
124 		return -EINVAL;
125 
126 	if (rsize && wsize) {
127 		cmd = SMC_MSG_RW_KEY;
128 		memcpy_toio(smc->shmem.iomem, wbuf, wsize);
129 		smc_size = rsize;
130 		smc_wsize = wsize;
131 	} else if (wsize && !rsize) {
132 		cmd = SMC_MSG_WRITE_KEY;
133 		memcpy_toio(smc->shmem.iomem, wbuf, wsize);
134 		/*
135 		 * Setting size to the length we want to write and wsize to 0
136 		 * looks silly but that's how the SMC protocol works ¯\_(ツ)_/¯
137 		 */
138 		smc_size = wsize;
139 		smc_wsize = 0;
140 	} else if (!wsize && rsize) {
141 		cmd = SMC_MSG_READ_KEY;
142 		smc_size = rsize;
143 		smc_wsize = 0;
144 	} else {
145 		return -EINVAL;
146 	}
147 
148 	ret = apple_smc_cmd_locked(smc, cmd, key, smc_size, smc_wsize, &rdata);
149 	if (ret < 0)
150 		return ret;
151 
152 	if (rsize) {
153 		/*
154 		 * Small data <= 4 bytes is returned as part of the reply
155 		 * message which is sent over the mailbox FIFO. Everything
156 		 * bigger has to be copied from SRAM which is mapped as
157 		 * Device memory.
158 		 */
159 		if (rsize <= 4)
160 			memcpy(rbuf, &rdata, rsize);
161 		else
162 			memcpy_fromio(rbuf, smc->shmem.iomem, rsize);
163 	}
164 
165 	return ret;
166 }
167 
apple_smc_read(struct apple_smc * smc,smc_key key,void * buf,size_t size)168 int apple_smc_read(struct apple_smc *smc, smc_key key, void *buf, size_t size)
169 {
170 	guard(mutex)(&smc->mutex);
171 
172 	return apple_smc_rw_locked(smc, key, NULL, 0, buf, size);
173 }
174 EXPORT_SYMBOL(apple_smc_read);
175 
apple_smc_write(struct apple_smc * smc,smc_key key,void * buf,size_t size)176 int apple_smc_write(struct apple_smc *smc, smc_key key, void *buf, size_t size)
177 {
178 	guard(mutex)(&smc->mutex);
179 
180 	return apple_smc_rw_locked(smc, key, buf, size, NULL, 0);
181 }
182 EXPORT_SYMBOL(apple_smc_write);
183 
apple_smc_rw(struct apple_smc * smc,smc_key key,void * wbuf,size_t wsize,void * rbuf,size_t rsize)184 int apple_smc_rw(struct apple_smc *smc, smc_key key, void *wbuf, size_t wsize,
185 		 void *rbuf, size_t rsize)
186 {
187 	guard(mutex)(&smc->mutex);
188 
189 	return apple_smc_rw_locked(smc, key, wbuf, wsize, rbuf, rsize);
190 }
191 EXPORT_SYMBOL(apple_smc_rw);
192 
apple_smc_get_key_by_index(struct apple_smc * smc,int index,smc_key * key)193 int apple_smc_get_key_by_index(struct apple_smc *smc, int index, smc_key *key)
194 {
195 	int ret;
196 
197 	ret = apple_smc_cmd(smc, SMC_MSG_GET_KEY_BY_INDEX, index, 0, 0, key);
198 
199 	*key = swab32(*key);
200 	return ret;
201 }
202 EXPORT_SYMBOL(apple_smc_get_key_by_index);
203 
apple_smc_get_key_info(struct apple_smc * smc,smc_key key,struct apple_smc_key_info * info)204 int apple_smc_get_key_info(struct apple_smc *smc, smc_key key, struct apple_smc_key_info *info)
205 {
206 	u8 key_info[6];
207 	int ret;
208 
209 	ret = apple_smc_cmd(smc, SMC_MSG_GET_KEY_INFO, key, 0, 0, NULL);
210 	if (ret >= 0 && info) {
211 		memcpy_fromio(key_info, smc->shmem.iomem, sizeof(key_info));
212 		info->size = key_info[0];
213 		info->type_code = get_unaligned_be32(&key_info[1]);
214 		info->flags = key_info[5];
215 	}
216 	return ret;
217 }
218 EXPORT_SYMBOL(apple_smc_get_key_info);
219 
apple_smc_enter_atomic(struct apple_smc * smc)220 int apple_smc_enter_atomic(struct apple_smc *smc)
221 {
222 	guard(mutex)(&smc->mutex);
223 
224 	/*
225 	 * Disable notifications since this is called before shutdown and no
226 	 * notification handler will be able to handle the notification
227 	 * using atomic operations only. Also ignore any failure here
228 	 * because we're about to shut down or reboot anyway.
229 	 * We can't use apple_smc_write_flag here since that would try to lock
230 	 * smc->mutex again.
231 	 */
232 	const u8 flag = 0;
233 
234 	apple_smc_rw_locked(smc, SMC_KEY(NTAP), &flag, sizeof(flag), NULL, 0);
235 
236 	smc->atomic_mode = true;
237 
238 	return 0;
239 }
240 EXPORT_SYMBOL(apple_smc_enter_atomic);
241 
apple_smc_write_atomic(struct apple_smc * smc,smc_key key,void * buf,size_t size)242 int apple_smc_write_atomic(struct apple_smc *smc, smc_key key, void *buf, size_t size)
243 {
244 	guard(spinlock_irqsave)(&smc->lock);
245 	u8 result;
246 	int ret;
247 	u64 msg;
248 
249 	if (size > SMC_MAX_SIZE || size == 0)
250 		return -EINVAL;
251 
252 	if (smc->boot_stage != APPLE_SMC_INITIALIZED)
253 		return -EIO;
254 	if (!smc->atomic_mode)
255 		return -EIO;
256 
257 	memcpy_toio(smc->shmem.iomem, buf, size);
258 	smc->msg_id = (smc->msg_id + 1) & 0xf;
259 	msg = (FIELD_PREP(SMC_MSG, SMC_MSG_WRITE_KEY) |
260 	       FIELD_PREP(SMC_SIZE, size) |
261 	       FIELD_PREP(SMC_ID, smc->msg_id) |
262 	       FIELD_PREP(SMC_DATA, key));
263 	smc->atomic_pending = true;
264 
265 	ret = apple_rtkit_send_message(smc->rtk, SMC_ENDPOINT, msg, NULL, true);
266 	if (ret < 0) {
267 		dev_err(smc->dev, "Failed to send command (%d)\n", ret);
268 		return ret;
269 	}
270 
271 	while (smc->atomic_pending) {
272 		ret = apple_rtkit_poll(smc->rtk);
273 		if (ret < 0) {
274 			dev_err(smc->dev, "RTKit poll failed (%llx)", msg);
275 			return ret;
276 		}
277 		udelay(100);
278 	}
279 
280 	if (FIELD_GET(SMC_ID, smc->cmd_ret) != smc->msg_id) {
281 		dev_err(smc->dev, "Command sequence mismatch (expected %d, got %d)\n",
282 			smc->msg_id, (unsigned int)FIELD_GET(SMC_ID, smc->cmd_ret));
283 		return -EIO;
284 	}
285 
286 	result = FIELD_GET(SMC_RESULT, smc->cmd_ret);
287 	if (result)
288 		return -EIO;
289 
290 	return FIELD_GET(SMC_SIZE, smc->cmd_ret);
291 }
292 EXPORT_SYMBOL(apple_smc_write_atomic);
293 
apple_smc_rtkit_crashed(void * cookie,const void * bfr,size_t bfr_len)294 static void apple_smc_rtkit_crashed(void *cookie, const void *bfr, size_t bfr_len)
295 {
296 	struct apple_smc *smc = cookie;
297 
298 	smc->boot_stage = APPLE_SMC_ERROR_CRASHED;
299 	dev_err(smc->dev, "SMC crashed! Your system will reboot in a few seconds...\n");
300 }
301 
apple_smc_rtkit_shmem_setup(void * cookie,struct apple_rtkit_shmem * bfr)302 static int apple_smc_rtkit_shmem_setup(void *cookie, struct apple_rtkit_shmem *bfr)
303 {
304 	struct apple_smc *smc = cookie;
305 	size_t bfr_end;
306 
307 	if (!bfr->iova) {
308 		dev_err(smc->dev, "RTKit wants a RAM buffer\n");
309 		return -EIO;
310 	}
311 
312 	if (check_add_overflow(bfr->iova, bfr->size - 1, &bfr_end))
313 		return -EFAULT;
314 
315 	if (bfr->iova < smc->sram->start || bfr->iova > smc->sram->end ||
316 	    bfr_end > smc->sram->end) {
317 		dev_err(smc->dev, "RTKit buffer request outside SRAM region: [0x%llx, 0x%llx]\n",
318 			(unsigned long long)bfr->iova,
319 			(unsigned long long)bfr_end);
320 		return -EFAULT;
321 	}
322 
323 	bfr->iomem = smc->sram_base + (bfr->iova - smc->sram->start);
324 	bfr->is_mapped = true;
325 
326 	return 0;
327 }
328 
apple_smc_rtkit_recv_early(void * cookie,u8 endpoint,u64 message)329 static bool apple_smc_rtkit_recv_early(void *cookie, u8 endpoint, u64 message)
330 {
331 	struct apple_smc *smc = cookie;
332 
333 	if (endpoint != SMC_ENDPOINT) {
334 		dev_warn(smc->dev, "Received message for unknown endpoint 0x%x\n", endpoint);
335 		return false;
336 	}
337 
338 	if (smc->boot_stage == APPLE_SMC_BOOTING) {
339 		int ret;
340 
341 		smc->shmem.iova = message;
342 		smc->shmem.size = SMC_SHMEM_SIZE;
343 		ret = apple_smc_rtkit_shmem_setup(smc, &smc->shmem);
344 		if (ret < 0) {
345 			smc->boot_stage = APPLE_SMC_ERROR_NO_SHMEM;
346 			dev_err(smc->dev, "Failed to initialize shared memory (%d)\n", ret);
347 		} else {
348 			smc->boot_stage = APPLE_SMC_INITIALIZED;
349 		}
350 		complete(&smc->init_done);
351 	} else if (FIELD_GET(SMC_MSG, message) == SMC_MSG_NOTIFICATION) {
352 		/* Handle these in the RTKit worker thread */
353 		return false;
354 	} else {
355 		smc->cmd_ret = message;
356 		if (smc->atomic_pending)
357 			smc->atomic_pending = false;
358 		else
359 			complete(&smc->cmd_done);
360 	}
361 
362 	return true;
363 }
364 
apple_smc_rtkit_recv(void * cookie,u8 endpoint,u64 message)365 static void apple_smc_rtkit_recv(void *cookie, u8 endpoint, u64 message)
366 {
367 	struct apple_smc *smc = cookie;
368 
369 	if (endpoint != SMC_ENDPOINT) {
370 		dev_warn(smc->dev, "Received message for unknown endpoint 0x%x\n", endpoint);
371 		return;
372 	}
373 
374 	if (FIELD_GET(SMC_MSG, message) != SMC_MSG_NOTIFICATION) {
375 		dev_warn(smc->dev, "Received unknown message from worker: 0x%llx\n", message);
376 		return;
377 	}
378 
379 	blocking_notifier_call_chain(&smc->event_handlers, FIELD_GET(SMC_DATA, message), NULL);
380 }
381 
382 static const struct apple_rtkit_ops apple_smc_rtkit_ops = {
383 	.crashed = apple_smc_rtkit_crashed,
384 	.recv_message = apple_smc_rtkit_recv,
385 	.recv_message_early = apple_smc_rtkit_recv_early,
386 	.shmem_setup = apple_smc_rtkit_shmem_setup,
387 };
388 
apple_smc_rtkit_shutdown(void * data)389 static void apple_smc_rtkit_shutdown(void *data)
390 {
391 	struct apple_smc *smc = data;
392 
393 	/* Shut down SMC firmware, if it's not completely wedged */
394 	if (apple_rtkit_is_running(smc->rtk))
395 		apple_rtkit_quiesce(smc->rtk);
396 }
397 
apple_smc_disable_notifications(void * data)398 static void apple_smc_disable_notifications(void *data)
399 {
400 	struct apple_smc *smc = data;
401 
402 	apple_smc_write_flag(smc, SMC_KEY(NTAP), false);
403 }
404 
apple_smc_probe(struct platform_device * pdev)405 static int apple_smc_probe(struct platform_device *pdev)
406 {
407 	struct device *dev = &pdev->dev;
408 	struct apple_smc *smc;
409 	u32 count;
410 	int ret;
411 
412 	smc = devm_kzalloc(dev, sizeof(*smc), GFP_KERNEL);
413 	if (!smc)
414 		return -ENOMEM;
415 
416 	smc->dev = &pdev->dev;
417 	smc->sram_base = devm_platform_get_and_ioremap_resource(pdev, 1, &smc->sram);
418 	if (IS_ERR(smc->sram_base))
419 		return dev_err_probe(dev, PTR_ERR(smc->sram_base), "Failed to map SRAM region");
420 
421 	smc->rtk = devm_apple_rtkit_init(dev, smc, NULL, 0, &apple_smc_rtkit_ops);
422 	if (IS_ERR(smc->rtk))
423 		return dev_err_probe(dev, PTR_ERR(smc->rtk), "Failed to initialize RTKit");
424 
425 	smc->boot_stage = APPLE_SMC_BOOTING;
426 	ret = apple_rtkit_wake(smc->rtk);
427 	if (ret)
428 		return dev_err_probe(dev, ret, "Failed to wake up SMC");
429 
430 	ret = devm_add_action_or_reset(dev, apple_smc_rtkit_shutdown, smc);
431 	if (ret)
432 		return dev_err_probe(dev, ret, "Failed to register rtkit shutdown action");
433 
434 	ret = apple_rtkit_start_ep(smc->rtk, SMC_ENDPOINT);
435 	if (ret)
436 		return dev_err_probe(dev, ret, "Failed to start SMC endpoint");
437 
438 	init_completion(&smc->init_done);
439 	init_completion(&smc->cmd_done);
440 
441 	ret = apple_rtkit_send_message(smc->rtk, SMC_ENDPOINT,
442 				       FIELD_PREP(SMC_MSG, SMC_MSG_INITIALIZE), NULL, false);
443 	if (ret)
444 		return dev_err_probe(dev, ret, "Failed to send init message");
445 
446 	if (wait_for_completion_timeout(&smc->init_done, msecs_to_jiffies(SMC_TIMEOUT_MS)) == 0) {
447 		dev_err(dev, "Timed out initializing SMC");
448 		return -ETIMEDOUT;
449 	}
450 
451 	if (smc->boot_stage != APPLE_SMC_INITIALIZED) {
452 		dev_err(dev, "SMC failed to boot successfully, boot stage=%d\n", smc->boot_stage);
453 		return -EIO;
454 	}
455 
456 	dev_set_drvdata(&pdev->dev, smc);
457 	BLOCKING_INIT_NOTIFIER_HEAD(&smc->event_handlers);
458 
459 	ret = apple_smc_read_u32(smc, SMC_KEY(#KEY), &count);
460 	if (ret)
461 		return dev_err_probe(smc->dev, ret, "Failed to get key count");
462 	smc->key_count = be32_to_cpu(count);
463 
464 	/* Enable notifications */
465 	apple_smc_write_flag(smc, SMC_KEY(NTAP), true);
466 	ret = devm_add_action_or_reset(dev, apple_smc_disable_notifications, smc);
467 	if (ret)
468 		return dev_err_probe(dev, ret, "Failed to register notification disable action");
469 
470 	ret = devm_mfd_add_devices(smc->dev, PLATFORM_DEVID_NONE,
471 				   apple_smc_devs, ARRAY_SIZE(apple_smc_devs),
472 				   NULL, 0, NULL);
473 	if (ret)
474 		return dev_err_probe(smc->dev, ret, "Failed to register sub-devices");
475 
476 
477 	return 0;
478 }
479 
480 static const struct of_device_id apple_smc_of_match[] = {
481 	{ .compatible = "apple,smc" },
482 	{},
483 };
484 MODULE_DEVICE_TABLE(of, apple_smc_of_match);
485 
486 static struct platform_driver apple_smc_driver = {
487 	.driver = {
488 		.name = "macsmc",
489 		.of_match_table = apple_smc_of_match,
490 	},
491 	.probe = apple_smc_probe,
492 };
493 module_platform_driver(apple_smc_driver);
494 
495 MODULE_AUTHOR("Hector Martin <marcan@marcan.st>");
496 MODULE_AUTHOR("Sven Peter <sven@kernel.org>");
497 MODULE_LICENSE("Dual MIT/GPL");
498 MODULE_DESCRIPTION("Apple SMC driver");
499