Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: GPL-2.0+
  2/*
  3 * Surface Serial Hub (SSH) driver for communication with the Surface/System
  4 * Aggregator Module (SSAM/SAM).
  5 *
  6 * Provides access to a SAM-over-SSH connected EC via a controller device.
  7 * Handles communication via requests as well as enabling, disabling, and
  8 * relaying of events.
  9 *
 10 * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
 11 */
 12
 13#include <linux/acpi.h>
 14#include <linux/atomic.h>
 15#include <linux/completion.h>
 16#include <linux/gpio/consumer.h>
 17#include <linux/kernel.h>
 18#include <linux/kref.h>
 19#include <linux/module.h>
 20#include <linux/of.h>
 21#include <linux/platform_device.h>
 22#include <linux/pm.h>
 23#include <linux/serdev.h>
 24#include <linux/sysfs.h>
 25#include <linux/units.h>
 26
 27#include <linux/surface_aggregator/controller.h>
 28#include <linux/surface_aggregator/device.h>
 29
 30#include "bus.h"
 31#include "controller.h"
 32
 33#define CREATE_TRACE_POINTS
 34#include "trace.h"
 35
 36
 37/* -- Static controller reference. ------------------------------------------ */
 38
 39/*
 40 * Main controller reference. The corresponding lock must be held while
 41 * accessing (reading/writing) the reference.
 42 */
 43static struct ssam_controller *__ssam_controller;
 44static DEFINE_SPINLOCK(__ssam_controller_lock);
 45
 46/**
 47 * ssam_get_controller() - Get reference to SSAM controller.
 48 *
 49 * Returns a reference to the SSAM controller of the system or %NULL if there
 50 * is none, it hasn't been set up yet, or it has already been unregistered.
 51 * This function automatically increments the reference count of the
 52 * controller, thus the calling party must ensure that ssam_controller_put()
 53 * is called when it doesn't need the controller any more.
 54 */
 55struct ssam_controller *ssam_get_controller(void)
 56{
 57	struct ssam_controller *ctrl;
 58
 59	spin_lock(&__ssam_controller_lock);
 60
 61	ctrl = __ssam_controller;
 62	if (!ctrl)
 63		goto out;
 64
 65	if (WARN_ON(!kref_get_unless_zero(&ctrl->kref)))
 66		ctrl = NULL;
 67
 68out:
 69	spin_unlock(&__ssam_controller_lock);
 70	return ctrl;
 71}
 72EXPORT_SYMBOL_GPL(ssam_get_controller);
 73
 74/**
 75 * ssam_try_set_controller() - Try to set the main controller reference.
 76 * @ctrl: The controller to which the reference should point.
 77 *
 78 * Set the main controller reference to the given pointer if the reference
 79 * hasn't been set already.
 80 *
 81 * Return: Returns zero on success or %-EEXIST if the reference has already
 82 * been set.
 83 */
 84static int ssam_try_set_controller(struct ssam_controller *ctrl)
 85{
 86	int status = 0;
 87
 88	spin_lock(&__ssam_controller_lock);
 89	if (!__ssam_controller)
 90		__ssam_controller = ctrl;
 91	else
 92		status = -EEXIST;
 93	spin_unlock(&__ssam_controller_lock);
 94
 95	return status;
 96}
 97
 98/**
 99 * ssam_clear_controller() - Remove/clear the main controller reference.
100 *
101 * Clears the main controller reference, i.e. sets it to %NULL. This function
102 * should be called before the controller is shut down.
103 */
104static void ssam_clear_controller(void)
105{
106	spin_lock(&__ssam_controller_lock);
107	__ssam_controller = NULL;
108	spin_unlock(&__ssam_controller_lock);
109}
110
111/**
112 * ssam_client_link() - Link an arbitrary client device to the controller.
113 * @c: The controller to link to.
114 * @client: The client device.
115 *
116 * Link an arbitrary client device to the controller by creating a device link
117 * between it as consumer and the controller device as provider. This function
118 * can be used for non-SSAM devices (or SSAM devices not registered as child
119 * under the controller) to guarantee that the controller is valid for as long
120 * as the driver of the client device is bound, and that proper suspend and
121 * resume ordering is guaranteed.
122 *
123 * The device link does not have to be destructed manually. It is removed
124 * automatically once the driver of the client device unbinds.
125 *
126 * Return: Returns zero on success, %-ENODEV if the controller is not ready or
127 * going to be removed soon, or %-ENOMEM if the device link could not be
128 * created for other reasons.
129 */
130int ssam_client_link(struct ssam_controller *c, struct device *client)
131{
132	const u32 flags = DL_FLAG_PM_RUNTIME | DL_FLAG_AUTOREMOVE_CONSUMER;
133	struct device_link *link;
134	struct device *ctrldev;
135
136	ssam_controller_statelock(c);
137
138	if (c->state != SSAM_CONTROLLER_STARTED) {
139		ssam_controller_stateunlock(c);
140		return -ENODEV;
141	}
142
143	ctrldev = ssam_controller_device(c);
144	if (!ctrldev) {
145		ssam_controller_stateunlock(c);
146		return -ENODEV;
147	}
148
149	link = device_link_add(client, ctrldev, flags);
150	if (!link) {
151		ssam_controller_stateunlock(c);
152		return -ENOMEM;
153	}
154
155	/*
156	 * Return -ENODEV if supplier driver is on its way to be removed. In
157	 * this case, the controller won't be around for much longer and the
158	 * device link is not going to save us any more, as unbinding is
159	 * already in progress.
160	 */
161	if (READ_ONCE(link->status) == DL_STATE_SUPPLIER_UNBIND) {
162		ssam_controller_stateunlock(c);
163		return -ENODEV;
164	}
165
166	ssam_controller_stateunlock(c);
167	return 0;
168}
169EXPORT_SYMBOL_GPL(ssam_client_link);
170
171/**
172 * ssam_client_bind() - Bind an arbitrary client device to the controller.
173 * @client: The client device.
174 *
175 * Link an arbitrary client device to the controller by creating a device link
176 * between it as consumer and the main controller device as provider. This
177 * function can be used for non-SSAM devices to guarantee that the controller
178 * returned by this function is valid for as long as the driver of the client
179 * device is bound, and that proper suspend and resume ordering is guaranteed.
180 *
181 * This function does essentially the same as ssam_client_link(), except that
182 * it first fetches the main controller reference, then creates the link, and
183 * finally returns this reference. Note that this function does not increment
184 * the reference counter of the controller, as, due to the link, the
185 * controller lifetime is assured as long as the driver of the client device
186 * is bound.
187 *
188 * It is not valid to use the controller reference obtained by this method
189 * outside of the driver bound to the client device at the time of calling
190 * this function, without first incrementing the reference count of the
191 * controller via ssam_controller_get(). Even after doing this, care must be
192 * taken that requests are only submitted and notifiers are only
193 * (un-)registered when the controller is active and not suspended. In other
194 * words: The device link only lives as long as the client driver is bound and
195 * any guarantees enforced by this link (e.g. active controller state) can
196 * only be relied upon as long as this link exists and may need to be enforced
197 * in other ways afterwards.
198 *
199 * The created device link does not have to be destructed manually. It is
200 * removed automatically once the driver of the client device unbinds.
201 *
202 * Return: Returns the controller on success, an error pointer with %-ENODEV
203 * if the controller is not present, not ready or going to be removed soon, or
204 * %-ENOMEM if the device link could not be created for other reasons.
205 */
206struct ssam_controller *ssam_client_bind(struct device *client)
207{
208	struct ssam_controller *c;
209	int status;
210
211	c = ssam_get_controller();
212	if (!c)
213		return ERR_PTR(-ENODEV);
214
215	status = ssam_client_link(c, client);
216
217	/*
218	 * Note that we can drop our controller reference in both success and
219	 * failure cases: On success, we have bound the controller lifetime
220	 * inherently to the client driver lifetime, i.e. it the controller is
221	 * now guaranteed to outlive the client driver. On failure, we're not
222	 * going to use the controller any more.
223	 */
224	ssam_controller_put(c);
225
226	return status >= 0 ? c : ERR_PTR(status);
227}
228EXPORT_SYMBOL_GPL(ssam_client_bind);
229
230
231/* -- Glue layer (serdev_device -> ssam_controller). ------------------------ */
232
233static size_t ssam_receive_buf(struct serdev_device *dev, const u8 *buf,
234			       size_t n)
235{
236	struct ssam_controller *ctrl;
237	int ret;
238
239	ctrl = serdev_device_get_drvdata(dev);
240	ret = ssam_controller_receive_buf(ctrl, buf, n);
241
242	return ret < 0 ? 0 : ret;
243}
244
245static void ssam_write_wakeup(struct serdev_device *dev)
246{
247	ssam_controller_write_wakeup(serdev_device_get_drvdata(dev));
248}
249
250static const struct serdev_device_ops ssam_serdev_ops = {
251	.receive_buf = ssam_receive_buf,
252	.write_wakeup = ssam_write_wakeup,
253};
254
255
256/* -- SysFS and misc. ------------------------------------------------------- */
257
258static int ssam_log_firmware_version(struct ssam_controller *ctrl)
259{
260	u32 version, a, b, c;
261	int status;
262
263	status = ssam_get_firmware_version(ctrl, &version);
264	if (status)
265		return status;
266
267	a = (version >> 24) & 0xff;
268	b = ((version >> 8) & 0xffff);
269	c = version & 0xff;
270
271	ssam_info(ctrl, "SAM firmware version: %u.%u.%u\n", a, b, c);
272	return 0;
273}
274
275static ssize_t firmware_version_show(struct device *dev,
276				     struct device_attribute *attr, char *buf)
277{
278	struct ssam_controller *ctrl = dev_get_drvdata(dev);
279	u32 version, a, b, c;
280	int status;
281
282	status = ssam_get_firmware_version(ctrl, &version);
283	if (status < 0)
284		return status;
285
286	a = (version >> 24) & 0xff;
287	b = ((version >> 8) & 0xffff);
288	c = version & 0xff;
289
290	return sysfs_emit(buf, "%u.%u.%u\n", a, b, c);
291}
292static DEVICE_ATTR_RO(firmware_version);
293
294static struct attribute *ssam_sam_attrs[] = {
295	&dev_attr_firmware_version.attr,
296	NULL
297};
298
299static const struct attribute_group ssam_sam_group = {
300	.name = "sam",
301	.attrs = ssam_sam_attrs,
302};
303
304
305/* -- Serial device setup. -------------------------------------------------- */
306
307static acpi_status ssam_serdev_setup_via_acpi_crs(struct acpi_resource *rsc,
308						  void *ctx)
309{
310	struct serdev_device *serdev = ctx;
311	struct acpi_resource_uart_serialbus *uart;
312	bool flow_control;
313	int status = 0;
314
315	if (!serdev_acpi_get_uart_resource(rsc, &uart))
316		return AE_OK;
317
318	/* Set up serdev device. */
319	serdev_device_set_baudrate(serdev, uart->default_baud_rate);
320
321	/* serdev currently only supports RTSCTS flow control. */
322	if (uart->flow_control & (~((u8)ACPI_UART_FLOW_CONTROL_HW))) {
323		dev_warn(&serdev->dev, "setup: unsupported flow control (value: %#04x)\n",
324			 uart->flow_control);
325	}
326
327	/* Set RTSCTS flow control. */
328	flow_control = uart->flow_control & ACPI_UART_FLOW_CONTROL_HW;
329	serdev_device_set_flow_control(serdev, flow_control);
330
331	/* serdev currently only supports EVEN/ODD parity. */
332	switch (uart->parity) {
333	case ACPI_UART_PARITY_NONE:
334		status = serdev_device_set_parity(serdev, SERDEV_PARITY_NONE);
335		break;
336	case ACPI_UART_PARITY_EVEN:
337		status = serdev_device_set_parity(serdev, SERDEV_PARITY_EVEN);
338		break;
339	case ACPI_UART_PARITY_ODD:
340		status = serdev_device_set_parity(serdev, SERDEV_PARITY_ODD);
341		break;
342	default:
343		dev_warn(&serdev->dev, "setup: unsupported parity (value: %#04x)\n",
344			 uart->parity);
345		break;
346	}
347
348	if (status) {
349		dev_err(&serdev->dev, "setup: failed to set parity (value: %#04x, error: %d)\n",
350			uart->parity, status);
351		return AE_ERROR;
352	}
353
354	/* We've found the resource and are done. */
355	return AE_CTRL_TERMINATE;
356}
357
358static int ssam_serdev_setup_via_acpi(struct serdev_device *serdev, acpi_handle handle)
359{
360	acpi_status status;
361
362	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
363				     ssam_serdev_setup_via_acpi_crs, serdev);
364
365	return status ? -ENXIO : 0;
366}
367
368static int ssam_serdev_setup(struct acpi_device *ssh, struct serdev_device *serdev)
369{
370	if (ssh)
371		return ssam_serdev_setup_via_acpi(serdev, ssh->handle);
372
373	/* TODO: these values may differ per board/implementation */
374	serdev_device_set_baudrate(serdev, 4 * HZ_PER_MHZ);
375	serdev_device_set_flow_control(serdev, true);
376	serdev_device_set_parity(serdev, SERDEV_PARITY_NONE);
377
378	return 0;
379}
380
381/* -- Power management. ----------------------------------------------------- */
382
383static void ssam_serial_hub_shutdown(struct device *dev)
384{
385	struct ssam_controller *c = dev_get_drvdata(dev);
386	int status;
387
388	/*
389	 * Try to disable notifiers, signal display-off and D0-exit, ignore any
390	 * errors.
391	 *
392	 * Note: It has not been established yet if this is actually
393	 * necessary/useful for shutdown.
394	 */
395
396	status = ssam_notifier_disable_registered(c);
397	if (status) {
398		ssam_err(c, "pm: failed to disable notifiers for shutdown: %d\n",
399			 status);
400	}
401
402	status = ssam_ctrl_notif_display_off(c);
403	if (status)
404		ssam_err(c, "pm: display-off notification failed: %d\n", status);
405
406	status = ssam_ctrl_notif_d0_exit(c);
407	if (status)
408		ssam_err(c, "pm: D0-exit notification failed: %d\n", status);
409}
410
411#ifdef CONFIG_PM_SLEEP
412
413static int ssam_serial_hub_pm_prepare(struct device *dev)
414{
415	struct ssam_controller *c = dev_get_drvdata(dev);
416	int status;
417
418	/*
419	 * Try to signal display-off, This will quiesce events.
420	 *
421	 * Note: Signaling display-off/display-on should normally be done from
422	 * some sort of display state notifier. As that is not available,
423	 * signal it here.
424	 */
425
426	status = ssam_ctrl_notif_display_off(c);
427	if (status)
428		ssam_err(c, "pm: display-off notification failed: %d\n", status);
429
430	return status;
431}
432
433static void ssam_serial_hub_pm_complete(struct device *dev)
434{
435	struct ssam_controller *c = dev_get_drvdata(dev);
436	int status;
437
438	/*
439	 * Try to signal display-on. This will restore events.
440	 *
441	 * Note: Signaling display-off/display-on should normally be done from
442	 * some sort of display state notifier. As that is not available,
443	 * signal it here.
444	 */
445
446	status = ssam_ctrl_notif_display_on(c);
447	if (status)
448		ssam_err(c, "pm: display-on notification failed: %d\n", status);
449}
450
451static int ssam_serial_hub_pm_suspend(struct device *dev)
452{
453	struct ssam_controller *c = dev_get_drvdata(dev);
454	int status;
455
456	/*
457	 * Try to signal D0-exit, enable IRQ wakeup if specified. Abort on
458	 * error.
459	 */
460
461	status = ssam_ctrl_notif_d0_exit(c);
462	if (status) {
463		ssam_err(c, "pm: D0-exit notification failed: %d\n", status);
464		goto err_notif;
465	}
466
467	status = ssam_irq_arm_for_wakeup(c);
468	if (status)
469		goto err_irq;
470
471	WARN_ON(ssam_controller_suspend(c));
472	return 0;
473
474err_irq:
475	ssam_ctrl_notif_d0_entry(c);
476err_notif:
477	ssam_ctrl_notif_display_on(c);
478	return status;
479}
480
481static int ssam_serial_hub_pm_resume(struct device *dev)
482{
483	struct ssam_controller *c = dev_get_drvdata(dev);
484	int status;
485
486	WARN_ON(ssam_controller_resume(c));
487
488	/*
489	 * Try to disable IRQ wakeup (if specified) and signal D0-entry. In
490	 * case of errors, log them and try to restore normal operation state
491	 * as far as possible.
492	 *
493	 * Note: Signaling display-off/display-on should normally be done from
494	 * some sort of display state notifier. As that is not available,
495	 * signal it here.
496	 */
497
498	ssam_irq_disarm_wakeup(c);
499
500	status = ssam_ctrl_notif_d0_entry(c);
501	if (status)
502		ssam_err(c, "pm: D0-entry notification failed: %d\n", status);
503
504	return 0;
505}
506
507static int ssam_serial_hub_pm_freeze(struct device *dev)
508{
509	struct ssam_controller *c = dev_get_drvdata(dev);
510	int status;
511
512	/*
513	 * During hibernation image creation, we only have to ensure that the
514	 * EC doesn't send us any events. This is done via the display-off
515	 * and D0-exit notifications. Note that this sets up the wakeup IRQ
516	 * on the EC side, however, we have disabled it by default on our side
517	 * and won't enable it here.
518	 *
519	 * See ssam_serial_hub_poweroff() for more details on the hibernation
520	 * process.
521	 */
522
523	status = ssam_ctrl_notif_d0_exit(c);
524	if (status) {
525		ssam_err(c, "pm: D0-exit notification failed: %d\n", status);
526		ssam_ctrl_notif_display_on(c);
527		return status;
528	}
529
530	WARN_ON(ssam_controller_suspend(c));
531	return 0;
532}
533
534static int ssam_serial_hub_pm_thaw(struct device *dev)
535{
536	struct ssam_controller *c = dev_get_drvdata(dev);
537	int status;
538
539	WARN_ON(ssam_controller_resume(c));
540
541	status = ssam_ctrl_notif_d0_entry(c);
542	if (status)
543		ssam_err(c, "pm: D0-exit notification failed: %d\n", status);
544
545	return status;
546}
547
548static int ssam_serial_hub_pm_poweroff(struct device *dev)
549{
550	struct ssam_controller *c = dev_get_drvdata(dev);
551	int status;
552
553	/*
554	 * When entering hibernation and powering off the system, the EC, at
555	 * least on some models, may disable events. Without us taking care of
556	 * that, this leads to events not being enabled/restored when the
557	 * system resumes from hibernation, resulting SAM-HID subsystem devices
558	 * (i.e. keyboard, touchpad) not working, AC-plug/AC-unplug events being
559	 * gone, etc.
560	 *
561	 * To avoid these issues, we disable all registered events here (this is
562	 * likely not actually required) and restore them during the drivers PM
563	 * restore callback.
564	 *
565	 * Wakeup from the EC interrupt is not supported during hibernation,
566	 * so don't arm the IRQ here.
567	 */
568
569	status = ssam_notifier_disable_registered(c);
570	if (status) {
571		ssam_err(c, "pm: failed to disable notifiers for hibernation: %d\n",
572			 status);
573		return status;
574	}
575
576	status = ssam_ctrl_notif_d0_exit(c);
577	if (status) {
578		ssam_err(c, "pm: D0-exit notification failed: %d\n", status);
579		ssam_notifier_restore_registered(c);
580		return status;
581	}
582
583	WARN_ON(ssam_controller_suspend(c));
584	return 0;
585}
586
587static int ssam_serial_hub_pm_restore(struct device *dev)
588{
589	struct ssam_controller *c = dev_get_drvdata(dev);
590	int status;
591
592	/*
593	 * Ignore but log errors, try to restore state as much as possible in
594	 * case of failures. See ssam_serial_hub_poweroff() for more details on
595	 * the hibernation process.
596	 */
597
598	WARN_ON(ssam_controller_resume(c));
599
600	status = ssam_ctrl_notif_d0_entry(c);
601	if (status)
602		ssam_err(c, "pm: D0-entry notification failed: %d\n", status);
603
604	ssam_notifier_restore_registered(c);
605	return 0;
606}
607
608static const struct dev_pm_ops ssam_serial_hub_pm_ops = {
609	.prepare  = ssam_serial_hub_pm_prepare,
610	.complete = ssam_serial_hub_pm_complete,
611	.suspend  = ssam_serial_hub_pm_suspend,
612	.resume   = ssam_serial_hub_pm_resume,
613	.freeze   = ssam_serial_hub_pm_freeze,
614	.thaw     = ssam_serial_hub_pm_thaw,
615	.poweroff = ssam_serial_hub_pm_poweroff,
616	.restore  = ssam_serial_hub_pm_restore,
617};
618
619#else /* CONFIG_PM_SLEEP */
620
621static const struct dev_pm_ops ssam_serial_hub_pm_ops = { };
622
623#endif /* CONFIG_PM_SLEEP */
624
625
626/* -- Device/driver setup. -------------------------------------------------- */
627
628static const struct acpi_gpio_params gpio_ssam_wakeup_int = { 0, 0, false };
629static const struct acpi_gpio_params gpio_ssam_wakeup     = { 1, 0, false };
630
631static const struct acpi_gpio_mapping ssam_acpi_gpios[] = {
632	{ "ssam_wakeup-int-gpio", &gpio_ssam_wakeup_int, 1 },
633	{ "ssam_wakeup-gpio",     &gpio_ssam_wakeup,     1 },
634	{ },
635};
636
637static int ssam_serial_hub_probe(struct serdev_device *serdev)
638{
639	struct device *dev = &serdev->dev;
640	struct acpi_device *ssh = ACPI_COMPANION(dev);
641	struct ssam_controller *ctrl;
642	int status;
643
644	if (ssh) {
645		status = gpiod_count(dev, NULL);
646		if (status < 0)
647			return dev_err_probe(dev, status, "no GPIO found\n");
648
649		status = devm_acpi_dev_add_driver_gpios(dev, ssam_acpi_gpios);
650		if (status)
651			return status;
652	}
653
654	/* Allocate controller. */
655	ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
656	if (!ctrl)
657		return -ENOMEM;
658
659	/* Initialize controller. */
660	status = ssam_controller_init(ctrl, serdev);
661	if (status) {
662		dev_err_probe(dev, status, "failed to initialize ssam controller\n");
663		goto err_ctrl_init;
664	}
665
666	ssam_controller_lock(ctrl);
667
668	/* Set up serdev device. */
669	serdev_device_set_drvdata(serdev, ctrl);
670	serdev_device_set_client_ops(serdev, &ssam_serdev_ops);
671	status = serdev_device_open(serdev);
672	if (status) {
673		dev_err_probe(dev, status, "failed to open serdev device\n");
674		goto err_devopen;
675	}
676
677	status = ssam_serdev_setup(ssh, serdev);
678	if (status) {
679		status = dev_err_probe(dev, status, "failed to setup serdev\n");
680		goto err_devinit;
681	}
682
683	/* Start controller. */
684	status = ssam_controller_start(ctrl);
685	if (status)
686		goto err_devinit;
687
688	ssam_controller_unlock(ctrl);
689
690	/*
691	 * Initial SAM requests: Log version and notify default/init power
692	 * states.
693	 */
694	status = ssam_log_firmware_version(ctrl);
695	if (status) {
696		dev_err_probe(dev, status, "failed to get firmware version\n");
697		goto err_initrq;
698	}
699
700	status = ssam_ctrl_notif_d0_entry(ctrl);
701	if (status) {
702		dev_err_probe(dev, status, "D0-entry notification failed\n");
703		goto err_initrq;
704	}
705
706	status = ssam_ctrl_notif_display_on(ctrl);
707	if (status) {
708		dev_err_probe(dev, status, "display-on notification failed\n");
709		goto err_initrq;
710	}
711
712	status = sysfs_create_group(&dev->kobj, &ssam_sam_group);
713	if (status)
714		goto err_initrq;
715
716	/* Set up IRQ. */
717	status = ssam_irq_setup(ctrl);
718	if (status) {
719		dev_err_probe(dev, status, "failed to setup IRQ\n");
720		goto err_irq;
721	}
722
723	/* Finally, set main controller reference. */
724	status = ssam_try_set_controller(ctrl);
725	if (WARN_ON(status))	/* Currently, we're the only provider. */
726		goto err_mainref;
727
728	/*
729	 * TODO: The EC can wake up the system via the associated GPIO interrupt
730	 *       in multiple situations. One of which is the remaining battery
731	 *       capacity falling below a certain threshold. Normally, we should
732	 *       use the device_init_wakeup function, however, the EC also seems
733	 *       to have other reasons for waking up the system and it seems
734	 *       that Windows has additional checks whether the system should be
735	 *       resumed. In short, this causes some spurious unwanted wake-ups.
736	 *       For now let's thus default power/wakeup to false.
737	 */
738	device_set_wakeup_capable(dev, true);
739
740	/*
741	 * When using DT, we have to register the platform hub driver manually,
742	 * as it can't be matched based on top-level board compatible (like it
743	 * does the ACPI case).
744	 */
745	if (!ssh) {
746		struct platform_device *ph_pdev =
747			platform_device_register_simple("surface_aggregator_platform_hub",
748							0, NULL, 0);
749		if (IS_ERR(ph_pdev))
750			return dev_err_probe(dev, PTR_ERR(ph_pdev),
751					     "Failed to register the platform hub driver\n");
752	}
753
754	if (ssh)
755		acpi_dev_clear_dependencies(ssh);
756
757	return 0;
758
759err_mainref:
760	ssam_irq_free(ctrl);
761err_irq:
762	sysfs_remove_group(&dev->kobj, &ssam_sam_group);
763err_initrq:
764	ssam_controller_lock(ctrl);
765	ssam_controller_shutdown(ctrl);
766err_devinit:
767	serdev_device_close(serdev);
768err_devopen:
769	ssam_controller_destroy(ctrl);
770	ssam_controller_unlock(ctrl);
771err_ctrl_init:
772	kfree(ctrl);
773	return status;
774}
775
776static void ssam_serial_hub_remove(struct serdev_device *serdev)
777{
778	struct ssam_controller *ctrl = serdev_device_get_drvdata(serdev);
779	int status;
780
781	/* Clear static reference so that no one else can get a new one. */
782	ssam_clear_controller();
783
784	/* Disable and free IRQ. */
785	ssam_irq_free(ctrl);
786
787	sysfs_remove_group(&serdev->dev.kobj, &ssam_sam_group);
788	ssam_controller_lock(ctrl);
789
790	/* Remove all client devices. */
791	ssam_remove_clients(&serdev->dev);
792
793	/* Act as if suspending to silence events. */
794	status = ssam_ctrl_notif_display_off(ctrl);
795	if (status) {
796		dev_err(&serdev->dev, "display-off notification failed: %d\n",
797			status);
798	}
799
800	status = ssam_ctrl_notif_d0_exit(ctrl);
801	if (status) {
802		dev_err(&serdev->dev, "D0-exit notification failed: %d\n",
803			status);
804	}
805
806	/* Shut down controller and remove serdev device reference from it. */
807	ssam_controller_shutdown(ctrl);
808
809	/* Shut down actual transport. */
810	serdev_device_wait_until_sent(serdev, 0);
811	serdev_device_close(serdev);
812
813	/* Drop our controller reference. */
814	ssam_controller_unlock(ctrl);
815	ssam_controller_put(ctrl);
816
817	device_set_wakeup_capable(&serdev->dev, false);
818}
819
820static const struct acpi_device_id ssam_serial_hub_acpi_match[] = {
821	{ "MSHW0084", 0 },
822	{ },
823};
824MODULE_DEVICE_TABLE(acpi, ssam_serial_hub_acpi_match);
825
826#ifdef CONFIG_OF
827static const struct of_device_id ssam_serial_hub_of_match[] = {
828	{ .compatible = "microsoft,surface-sam", },
829	{ },
830};
831MODULE_DEVICE_TABLE(of, ssam_serial_hub_of_match);
832#endif
833
834static struct serdev_device_driver ssam_serial_hub = {
835	.probe = ssam_serial_hub_probe,
836	.remove = ssam_serial_hub_remove,
837	.driver = {
838		.name = "surface_serial_hub",
839		.acpi_match_table = ACPI_PTR(ssam_serial_hub_acpi_match),
840		.of_match_table = of_match_ptr(ssam_serial_hub_of_match),
841		.pm = &ssam_serial_hub_pm_ops,
842		.shutdown = ssam_serial_hub_shutdown,
843		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
844	},
845};
846
847
848/* -- Module setup. --------------------------------------------------------- */
849
850static int __init ssam_core_init(void)
851{
852	int status;
853
854	status = ssam_bus_register();
855	if (status)
856		goto err_bus;
857
858	status = ssh_ctrl_packet_cache_init();
859	if (status)
860		goto err_cpkg;
861
862	status = ssam_event_item_cache_init();
863	if (status)
864		goto err_evitem;
865
866	status = serdev_device_driver_register(&ssam_serial_hub);
867	if (status)
868		goto err_register;
869
870	return 0;
871
872err_register:
873	ssam_event_item_cache_destroy();
874err_evitem:
875	ssh_ctrl_packet_cache_destroy();
876err_cpkg:
877	ssam_bus_unregister();
878err_bus:
879	return status;
880}
881subsys_initcall(ssam_core_init);
882
883static void __exit ssam_core_exit(void)
884{
885	serdev_device_driver_unregister(&ssam_serial_hub);
886	ssam_event_item_cache_destroy();
887	ssh_ctrl_packet_cache_destroy();
888	ssam_bus_unregister();
889}
890module_exit(ssam_core_exit);
891
892MODULE_AUTHOR("Maximilian Luz <luzmaximilian@gmail.com>");
893MODULE_DESCRIPTION("Subsystem and Surface Serial Hub driver for Surface System Aggregator Module");
894MODULE_LICENSE("GPL");