[RFC PATCH 0/9] Add support for Microsoft Surface System Aggregator Module
From: Maximilian Luz
Date: Wed Sep 23 2020 - 11:15:28 EST
Hello,
The Surface System Aggregator Module (we'll refer to it as Surface
Aggregator or SAM below) is an embedded controller (EC) found on various
Microsoft Surface devices. Specifically, all 4th and later generation
Surface devices, i.e. Surface Pro 4, Surface Book 1 and later, with the
exception of the Surface Go series and the Surface Duo. Notably, it
seems like this EC can also be found on the ARM-based Surface Pro X [1].
Functionality provided by this EC depends on the Surface model and can
(roughly) be broken down by their generations: Starting with 5th
generation devices (Surface Pro 2017/5, Surface Book 2, Surface Laptop
1, and later), the EC provides battery and thermal readings, as well as
access to the real-time clock. On 5th and 6th generations, these
features, specifically, are provided via the ACPI interface of the EC,
referred to as Surface ACPI Notify (SAN), i.e. they act as standard ACPI
devices of that type, but require a driver translating requests written
to an ACPI operation region to requests to the EC. On 7th generation
devices, the ACPI interface is (largely) gone, and has been replaced
with custom battery and thermal drivers, directly querying the EC.
Additionally, HID keyboard and touchpad input for Surface models with
these devices built in can be handled via the EC: On the Surface Laptops
1 and 2, this includes only the keyboard, while on the Surface Laptop 3
and Book 3, this includes both touchpad and keyboard. In this case,
actual input is provided as HID data and the EC connection acts as HID
transport, thus requiring a special transport driver for those devices
to work.
Further, all known devices (5th and later generations) also support
changing of performance/cooling modes, which can influence cooling
capabilities of the device (e.g. prefer silent operation over
performance), and may influence power limits (e.g. of the discrete GPU
found on Surface Books).
While this constitutes all major functionality, some more device
specific functionality is also handled by the EC. For example, on the
Surface Books, the EC handles detaching of the clipboard (i.e. the upper
part with screen and CPU) from the base (the lower part with keyboard
and optional discrete GPU) and can influence its behavior (i.e. it
provides an interface via which detachment can be requested, aborted, or
confirmed). It can also be used to detect if there has been a base
attached to the clipboard, and if so what type.
This patch-series adds the basis for supporting this EC and the features
provided by it, by, first, implementing a communication driver providing
a fundamental API for client drivers, handling specific aspects of the
EC. Additionally, it builds on top of that to provide a dedicated bus
and device type to better manage EC clients (and break it down pseudo-
device-wise), especially in the case when these client devices are not
described in ACPI, i.e. cannot be discovered by conventional means.
Furthermore, it provides support for debugging and prototyping via an
optional DebugFS interface, and, lastly, also support for the
aforementioned ACPI interface, allowing ACPI to communicate with the EC
directly.
This series only addresses 5th and later generation Surface models as
the communication interface has changed substantially from 4th to 5th
generation, and the 4th generation interface has not been reverse-
engineered yet. Specifically, the underlying transport has been changed
from HID feature and input-/output-reports to serial communication via
an UART and a custom protocol. Support for 4th generation devices may be
added in the future, but as currently not much is known about 4th
generation SAM, it yet remains to be seen if this can happen as addition
to this subsystem, or if it will be easier to implement this as separate
platform driver. Especially as the 4th generation EC does not seem to
provide much of the functionality found on 5th and later generations
(e.g. no battery status reporting, no thermal reporting, ..., we assume
it's just clipboard detachment on the Surface Book 1 and performance
mode setting).
In more detail, this series adds a driver for the Surface Serial Hub
(SSH), the 5th- and later-generation communication channel to the EC, a
pseudo-device and driver exposing a DebugFS interface that can be used
to communicate with the EC from user-space, intended for debugging,
testing, and prototyping, as well as a driver for the Surface ACPI
Notify (SAN) device, i.e. the interface between ACPI and EC. Some more
details on those can be found on the individual commit messages.
This series, apart from the SAN and DebugFS drivers, does not add any
client drivers. This will be handled via future patches once the core
has been accepted (and the other client drivers have been cleaned up a
bit).
On the top level, EC communication via the SSH driver can be broken down
into requests (sent from host to EC), corresponding responses (sent from
EC to host, associated with and triggered by a request), and events
(sent from EC to host without association ot a request). The SSH driver
manages all communication (i.e. matches responses to requests, enables
and disables events, and manages event handlers/notifiers installed by
client drivers). On the lower levels, SSH communication is packet-based,
and described in more detail in the documentation added in this series
(specifically ssh.rst).
This set of modules and drivers has been developed out of tree at [2]
and used/tested in the kernel we provide at [3] pretty much since its
beginnings. It has been developed by reverse-engineering the SSH
protocol, mostly through the ACPI interface, communication dumps
obtained from listening in on Windows, and deduction. So things may be
wrong. There have been some attempts at reverse-engineering existing
drivers, which also gave a bit of insight for development, however, I
haven't gotten very far on that front beyond some more higher-level
concepts and detecting a couple of new EC commands/confirming the
functionality of already known commands.
Driver and module names have been chosen to align with Windows driver
names, some field, vairable, and concept names have been chosen to align
with ACPI code (or at least with what I think some of the more cryptic
names could mean and make sense in the respective context, e.g. IID ->
Instance ID, TC -> Target Category).
While I consider this submission complete, I've decided to submit this
as RFC first, mainly due to its size and it being my first submission on
this scale. Any feedback, review, comment, question, etc. is much
appreciated.
This patch-set can also be found at the following respository and
reference, if you prefer to look at a kernel tree instead of these
emails:
https://github.com/linux-surface/kernel tags/s/surface-aggregator/rfc-v1
Thanks,
Max
[1]: The Surface Pro X is, however, currently considered unsupported due
to a lack of test candidates and, as it seems, general lack of
Linux support on other parts. AFAIK there is an issue preventing
serial devices from being registered, on which the core driver in
this series is build on, thus there is no way to even test that at
this point. I'd be happy to work out any issues regarding SAM on
the Pro X at some point in the future, provided someone can/wants
to actually test it.
[2]: https://github.com/linux-surface/surface-aggregator-module
[3]: https://github.com/linux-surface/linux-surface
Maximilian Luz (9):
misc: Add Surface Aggregator subsystem
surface_aggregator: Add control packet allocation chaching
surface_aggregator: Add event item allocation chaching
surface_aggregator: Add trace points
surface_aggregator: Add error injection capabilities
surface_aggregator: Add dedicated bus and device type
docs: driver-api: Add Surface Aggregator subsystem documentation
surface_aggregator: Add DebugFS interface
surface_aggregator: Add Surface ACPI Notify client driver
Documentation/driver-api/index.rst | 1 +
.../surface_aggregator/client-api.rst | 38 +
.../driver-api/surface_aggregator/client.rst | 394 +++
.../surface_aggregator/clients/dbgdev.rst | 130 +
.../surface_aggregator/clients/index.rst | 21 +
.../surface_aggregator/clients/san.rst | 44 +
.../driver-api/surface_aggregator/index.rst | 21 +
.../surface_aggregator/internal-api.rst | 67 +
.../surface_aggregator/internal.rst | 50 +
.../surface_aggregator/overview.rst | 76 +
.../driver-api/surface_aggregator/ssh.rst | 343 +++
MAINTAINERS | 10 +
drivers/misc/Kconfig | 1 +
drivers/misc/Makefile | 1 +
drivers/misc/surface_aggregator/Kconfig | 65 +
drivers/misc/surface_aggregator/Makefile | 17 +
drivers/misc/surface_aggregator/bus.c | 419 +++
drivers/misc/surface_aggregator/bus.h | 22 +
.../misc/surface_aggregator/clients/Kconfig | 38 +
.../misc/surface_aggregator/clients/Makefile | 4 +
.../clients/surface_acpi_notify.c | 882 ++++++
.../clients/surface_aggregator_debugfs.c | 281 ++
drivers/misc/surface_aggregator/controller.c | 2505 +++++++++++++++++
drivers/misc/surface_aggregator/controller.h | 283 ++
drivers/misc/surface_aggregator/core.c | 821 ++++++
drivers/misc/surface_aggregator/ssh_msgb.h | 196 ++
.../surface_aggregator/ssh_packet_layer.c | 2002 +++++++++++++
.../surface_aggregator/ssh_packet_layer.h | 170 ++
drivers/misc/surface_aggregator/ssh_parser.c | 224 ++
drivers/misc/surface_aggregator/ssh_parser.h | 152 +
.../surface_aggregator/ssh_request_layer.c | 1249 ++++++++
.../surface_aggregator/ssh_request_layer.h | 137 +
drivers/misc/surface_aggregator/trace.h | 621 ++++
include/linux/mod_devicetable.h | 18 +
include/linux/surface_acpi_notify.h | 37 +
include/linux/surface_aggregator/controller.h | 812 ++++++
include/linux/surface_aggregator/device.h | 408 +++
include/linux/surface_aggregator/serial_hub.h | 657 +++++
scripts/mod/devicetable-offsets.c | 8 +
scripts/mod/file2alias.c | 23 +
40 files changed, 13248 insertions(+)
create mode 100644 Documentation/driver-api/surface_aggregator/client-api.rst
create mode 100644 Documentation/driver-api/surface_aggregator/client.rst
create mode 100644 Documentation/driver-api/surface_aggregator/clients/dbgdev.rst
create mode 100644 Documentation/driver-api/surface_aggregator/clients/index.rst
create mode 100644 Documentation/driver-api/surface_aggregator/clients/san.rst
create mode 100644 Documentation/driver-api/surface_aggregator/index.rst
create mode 100644 Documentation/driver-api/surface_aggregator/internal-api.rst
create mode 100644 Documentation/driver-api/surface_aggregator/internal.rst
create mode 100644 Documentation/driver-api/surface_aggregator/overview.rst
create mode 100644 Documentation/driver-api/surface_aggregator/ssh.rst
create mode 100644 drivers/misc/surface_aggregator/Kconfig
create mode 100644 drivers/misc/surface_aggregator/Makefile
create mode 100644 drivers/misc/surface_aggregator/bus.c
create mode 100644 drivers/misc/surface_aggregator/bus.h
create mode 100644 drivers/misc/surface_aggregator/clients/Kconfig
create mode 100644 drivers/misc/surface_aggregator/clients/Makefile
create mode 100644 drivers/misc/surface_aggregator/clients/surface_acpi_notify.c
create mode 100644 drivers/misc/surface_aggregator/clients/surface_aggregator_debugfs.c
create mode 100644 drivers/misc/surface_aggregator/controller.c
create mode 100644 drivers/misc/surface_aggregator/controller.h
create mode 100644 drivers/misc/surface_aggregator/core.c
create mode 100644 drivers/misc/surface_aggregator/ssh_msgb.h
create mode 100644 drivers/misc/surface_aggregator/ssh_packet_layer.c
create mode 100644 drivers/misc/surface_aggregator/ssh_packet_layer.h
create mode 100644 drivers/misc/surface_aggregator/ssh_parser.c
create mode 100644 drivers/misc/surface_aggregator/ssh_parser.h
create mode 100644 drivers/misc/surface_aggregator/ssh_request_layer.c
create mode 100644 drivers/misc/surface_aggregator/ssh_request_layer.h
create mode 100644 drivers/misc/surface_aggregator/trace.h
create mode 100644 include/linux/surface_acpi_notify.h
create mode 100644 include/linux/surface_aggregator/controller.h
create mode 100644 include/linux/surface_aggregator/device.h
create mode 100644 include/linux/surface_aggregator/serial_hub.h
--
2.28.0