platform/surface: Add Surface Aggregator subsystem
Add Surface System Aggregator Module core and Surface Serial Hub driver,
required for the embedded controller found on Microsoft Surface devices.
The Surface System Aggregator Module (SSAM, SAM or Surface Aggregator)
is an embedded controller (EC) found on 4th and later generation
Microsoft Surface devices, with the exception of the Surface Go series.
This EC provides various functionality, depending on the device in
question. This can include battery status and thermal reporting (5th and
later generations), but also HID keyboard (6th+) and touchpad input
(7th+) on Surface Laptop and Surface Book 3 series devices.
This patch provides the basic necessities for communication with the SAM
EC on 5th and later generation devices. On these devices, the EC
provides an interface that acts as serial device, called the Surface
Serial Hub (SSH). 4th generation devices, on which the EC interface is
provided via an HID-over-I2C device, are not supported by this patch.
Specifically, this patch adds a driver for the SSH device (device HID
MSHW0084 in ACPI), as well as a controller structure and associated API.
This represents the functional core of the Surface Aggregator kernel
subsystem, introduced with this patch, and will be expanded upon in
subsequent commits.
The SSH driver acts as the main attachment point for this subsystem and
sets-up and manages the controller structure. The controller in turn
provides a basic communication interface, allowing to send requests from
host to EC and receiving the corresponding responses, as well as
managing and receiving events, sent from EC to host. It is structured
into multiple layers, with the top layer presenting the API used by
other kernel drivers and the lower layers modeled after the serial
protocol used for communication.
Said other drivers are then responsible for providing the (Surface model
specific) functionality accessible through the EC (e.g. battery status
reporting, thermal information, ...) via said controller structure and
API, and will be added in future commits.
Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
Link: https://lore.kernel.org/r/20201221183959.1186143-2-luzmaximilian@gmail.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2020-12-22 02:39:51 +08:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0+ */
|
|
|
|
/*
|
|
|
|
* Surface System Aggregator Module (SSAM) controller interface.
|
|
|
|
*
|
|
|
|
* Main communication interface for the SSAM EC. Provides a controller
|
|
|
|
* managing access and communication to and from the SSAM EC, as well as main
|
|
|
|
* communication structures and definitions.
|
|
|
|
*
|
|
|
|
* Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef _LINUX_SURFACE_AGGREGATOR_CONTROLLER_H
|
|
|
|
#define _LINUX_SURFACE_AGGREGATOR_CONTROLLER_H
|
|
|
|
|
|
|
|
#include <linux/completion.h>
|
|
|
|
#include <linux/device.h>
|
|
|
|
#include <linux/types.h>
|
|
|
|
|
|
|
|
#include <linux/surface_aggregator/serial_hub.h>
|
|
|
|
|
|
|
|
|
|
|
|
/* -- Main data types and definitions --------------------------------------- */
|
|
|
|
|
|
|
|
/**
|
|
|
|
* enum ssam_event_flags - Flags for enabling/disabling SAM events
|
|
|
|
* @SSAM_EVENT_SEQUENCED: The event will be sent via a sequenced data frame.
|
|
|
|
*/
|
|
|
|
enum ssam_event_flags {
|
|
|
|
SSAM_EVENT_SEQUENCED = BIT(0),
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* struct ssam_event - SAM event sent from the EC to the host.
|
|
|
|
* @target_category: Target category of the event source. See &enum ssam_ssh_tc.
|
|
|
|
* @target_id: Target ID of the event source.
|
|
|
|
* @command_id: Command ID of the event.
|
|
|
|
* @instance_id: Instance ID of the event source.
|
|
|
|
* @length: Length of the event payload in bytes.
|
|
|
|
* @data: Event payload data.
|
|
|
|
*/
|
|
|
|
struct ssam_event {
|
|
|
|
u8 target_category;
|
|
|
|
u8 target_id;
|
|
|
|
u8 command_id;
|
|
|
|
u8 instance_id;
|
|
|
|
u16 length;
|
|
|
|
u8 data[];
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* enum ssam_request_flags - Flags for SAM requests.
|
|
|
|
*
|
|
|
|
* @SSAM_REQUEST_HAS_RESPONSE:
|
|
|
|
* Specifies that the request expects a response. If not set, the request
|
|
|
|
* will be directly completed after its underlying packet has been
|
|
|
|
* transmitted. If set, the request transport system waits for a response
|
|
|
|
* of the request.
|
|
|
|
*
|
|
|
|
* @SSAM_REQUEST_UNSEQUENCED:
|
|
|
|
* Specifies that the request should be transmitted via an unsequenced
|
|
|
|
* packet. If set, the request must not have a response, meaning that this
|
|
|
|
* flag and the %SSAM_REQUEST_HAS_RESPONSE flag are mutually exclusive.
|
|
|
|
*/
|
|
|
|
enum ssam_request_flags {
|
|
|
|
SSAM_REQUEST_HAS_RESPONSE = BIT(0),
|
|
|
|
SSAM_REQUEST_UNSEQUENCED = BIT(1),
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* struct ssam_request - SAM request description.
|
|
|
|
* @target_category: Category of the request's target. See &enum ssam_ssh_tc.
|
|
|
|
* @target_id: ID of the request's target.
|
|
|
|
* @command_id: Command ID of the request.
|
|
|
|
* @instance_id: Instance ID of the request's target.
|
|
|
|
* @flags: Flags for the request. See &enum ssam_request_flags.
|
|
|
|
* @length: Length of the request payload in bytes.
|
|
|
|
* @payload: Request payload data.
|
|
|
|
*
|
|
|
|
* This struct fully describes a SAM request with payload. It is intended to
|
|
|
|
* help set up the actual transport struct, e.g. &struct ssam_request_sync,
|
|
|
|
* and specifically its raw message data via ssam_request_write_data().
|
|
|
|
*/
|
|
|
|
struct ssam_request {
|
|
|
|
u8 target_category;
|
|
|
|
u8 target_id;
|
|
|
|
u8 command_id;
|
|
|
|
u8 instance_id;
|
|
|
|
u16 flags;
|
|
|
|
u16 length;
|
|
|
|
const u8 *payload;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* struct ssam_response - Response buffer for SAM request.
|
|
|
|
* @capacity: Capacity of the buffer, in bytes.
|
|
|
|
* @length: Length of the actual data stored in the memory pointed to by
|
|
|
|
* @pointer, in bytes. Set by the transport system.
|
|
|
|
* @pointer: Pointer to the buffer's memory, storing the response payload data.
|
|
|
|
*/
|
|
|
|
struct ssam_response {
|
|
|
|
size_t capacity;
|
|
|
|
size_t length;
|
|
|
|
u8 *pointer;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ssam_controller;
|
|
|
|
|
|
|
|
struct ssam_controller *ssam_get_controller(void);
|
|
|
|
struct ssam_controller *ssam_client_bind(struct device *client);
|
|
|
|
int ssam_client_link(struct ssam_controller *ctrl, struct device *client);
|
|
|
|
|
|
|
|
struct device *ssam_controller_device(struct ssam_controller *c);
|
|
|
|
|
|
|
|
struct ssam_controller *ssam_controller_get(struct ssam_controller *c);
|
|
|
|
void ssam_controller_put(struct ssam_controller *c);
|
|
|
|
|
|
|
|
void ssam_controller_statelock(struct ssam_controller *c);
|
|
|
|
void ssam_controller_stateunlock(struct ssam_controller *c);
|
|
|
|
|
|
|
|
ssize_t ssam_request_write_data(struct ssam_span *buf,
|
|
|
|
struct ssam_controller *ctrl,
|
|
|
|
const struct ssam_request *spec);
|
|
|
|
|
|
|
|
|
|
|
|
/* -- Synchronous request interface. ---------------------------------------- */
|
|
|
|
|
|
|
|
/**
|
|
|
|
* struct ssam_request_sync - Synchronous SAM request struct.
|
|
|
|
* @base: Underlying SSH request.
|
|
|
|
* @comp: Completion used to signal full completion of the request. After the
|
|
|
|
* request has been submitted, this struct may only be modified or
|
|
|
|
* deallocated after the completion has been signaled.
|
|
|
|
* request has been submitted,
|
|
|
|
* @resp: Buffer to store the response.
|
|
|
|
* @status: Status of the request, set after the base request has been
|
|
|
|
* completed or has failed.
|
|
|
|
*/
|
|
|
|
struct ssam_request_sync {
|
|
|
|
struct ssh_request base;
|
|
|
|
struct completion comp;
|
|
|
|
struct ssam_response *resp;
|
|
|
|
int status;
|
|
|
|
};
|
|
|
|
|
|
|
|
int ssam_request_sync_alloc(size_t payload_len, gfp_t flags,
|
|
|
|
struct ssam_request_sync **rqst,
|
|
|
|
struct ssam_span *buffer);
|
|
|
|
|
|
|
|
void ssam_request_sync_free(struct ssam_request_sync *rqst);
|
|
|
|
|
|
|
|
int ssam_request_sync_init(struct ssam_request_sync *rqst,
|
|
|
|
enum ssam_request_flags flags);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* ssam_request_sync_set_data - Set message data of a synchronous request.
|
|
|
|
* @rqst: The request.
|
|
|
|
* @ptr: Pointer to the request message data.
|
|
|
|
* @len: Length of the request message data.
|
|
|
|
*
|
|
|
|
* Set the request message data of a synchronous request. The provided buffer
|
|
|
|
* needs to live until the request has been completed.
|
|
|
|
*/
|
|
|
|
static inline void ssam_request_sync_set_data(struct ssam_request_sync *rqst,
|
|
|
|
u8 *ptr, size_t len)
|
|
|
|
{
|
|
|
|
ssh_request_set_data(&rqst->base, ptr, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* ssam_request_sync_set_resp - Set response buffer of a synchronous request.
|
|
|
|
* @rqst: The request.
|
|
|
|
* @resp: The response buffer.
|
|
|
|
*
|
|
|
|
* Sets the response buffer of a synchronous request. This buffer will store
|
|
|
|
* the response of the request after it has been completed. May be %NULL if no
|
|
|
|
* response is expected.
|
|
|
|
*/
|
|
|
|
static inline void ssam_request_sync_set_resp(struct ssam_request_sync *rqst,
|
|
|
|
struct ssam_response *resp)
|
|
|
|
{
|
|
|
|
rqst->resp = resp;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ssam_request_sync_submit(struct ssam_controller *ctrl,
|
|
|
|
struct ssam_request_sync *rqst);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* ssam_request_sync_wait - Wait for completion of a synchronous request.
|
|
|
|
* @rqst: The request to wait for.
|
|
|
|
*
|
|
|
|
* Wait for completion and release of a synchronous request. After this
|
|
|
|
* function terminates, the request is guaranteed to have left the transport
|
|
|
|
* system. After successful submission of a request, this function must be
|
|
|
|
* called before accessing the response of the request, freeing the request,
|
|
|
|
* or freeing any of the buffers associated with the request.
|
|
|
|
*
|
|
|
|
* This function must not be called if the request has not been submitted yet
|
|
|
|
* and may lead to a deadlock/infinite wait if a subsequent request submission
|
|
|
|
* fails in that case, due to the completion never triggering.
|
|
|
|
*
|
|
|
|
* Return: Returns the status of the given request, which is set on completion
|
|
|
|
* of the packet. This value is zero on success and negative on failure.
|
|
|
|
*/
|
|
|
|
static inline int ssam_request_sync_wait(struct ssam_request_sync *rqst)
|
|
|
|
{
|
|
|
|
wait_for_completion(&rqst->comp);
|
|
|
|
return rqst->status;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ssam_request_sync(struct ssam_controller *ctrl,
|
|
|
|
const struct ssam_request *spec,
|
|
|
|
struct ssam_response *rsp);
|
|
|
|
|
|
|
|
int ssam_request_sync_with_buffer(struct ssam_controller *ctrl,
|
|
|
|
const struct ssam_request *spec,
|
|
|
|
struct ssam_response *rsp,
|
|
|
|
struct ssam_span *buf);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* ssam_request_sync_onstack - Execute a synchronous request on the stack.
|
|
|
|
* @ctrl: The controller via which the request is submitted.
|
|
|
|
* @rqst: The request specification.
|
|
|
|
* @rsp: The response buffer.
|
|
|
|
* @payload_len: The (maximum) request payload length.
|
|
|
|
*
|
|
|
|
* Allocates a synchronous request with specified payload length on the stack,
|
|
|
|
* fully initializes it via the provided request specification, submits it,
|
|
|
|
* and finally waits for its completion before returning its status. This
|
|
|
|
* helper macro essentially allocates the request message buffer on the stack
|
|
|
|
* and then calls ssam_request_sync_with_buffer().
|
|
|
|
*
|
|
|
|
* Note: The @payload_len parameter specifies the maximum payload length, used
|
|
|
|
* for buffer allocation. The actual payload length may be smaller.
|
|
|
|
*
|
|
|
|
* Return: Returns the status of the request or any failure during setup, i.e.
|
|
|
|
* zero on success and a negative value on failure.
|
|
|
|
*/
|
|
|
|
#define ssam_request_sync_onstack(ctrl, rqst, rsp, payload_len) \
|
|
|
|
({ \
|
|
|
|
u8 __data[SSH_COMMAND_MESSAGE_LENGTH(payload_len)]; \
|
|
|
|
struct ssam_span __buf = { &__data[0], ARRAY_SIZE(__data) }; \
|
|
|
|
\
|
|
|
|
ssam_request_sync_with_buffer(ctrl, rqst, rsp, &__buf); \
|
|
|
|
})
|
|
|
|
|
|
|
|
/**
|
|
|
|
* __ssam_retry - Retry request in case of I/O errors or timeouts.
|
|
|
|
* @request: The request function to execute. Must return an integer.
|
|
|
|
* @n: Number of tries.
|
|
|
|
* @args: Arguments for the request function.
|
|
|
|
*
|
|
|
|
* Executes the given request function, i.e. calls @request. In case the
|
|
|
|
* request returns %-EREMOTEIO (indicates I/O error) or %-ETIMEDOUT (request
|
|
|
|
* or underlying packet timed out), @request will be re-executed again, up to
|
|
|
|
* @n times in total.
|
|
|
|
*
|
|
|
|
* Return: Returns the return value of the last execution of @request.
|
|
|
|
*/
|
|
|
|
#define __ssam_retry(request, n, args...) \
|
|
|
|
({ \
|
|
|
|
int __i, __s = 0; \
|
|
|
|
\
|
|
|
|
for (__i = (n); __i > 0; __i--) { \
|
|
|
|
__s = request(args); \
|
|
|
|
if (__s != -ETIMEDOUT && __s != -EREMOTEIO) \
|
|
|
|
break; \
|
|
|
|
} \
|
|
|
|
__s; \
|
|
|
|
})
|
|
|
|
|
|
|
|
/**
|
|
|
|
* ssam_retry - Retry request in case of I/O errors or timeouts up to three
|
|
|
|
* times in total.
|
|
|
|
* @request: The request function to execute. Must return an integer.
|
|
|
|
* @args: Arguments for the request function.
|
|
|
|
*
|
|
|
|
* Executes the given request function, i.e. calls @request. In case the
|
|
|
|
* request returns %-EREMOTEIO (indicates I/O error) or -%ETIMEDOUT (request
|
|
|
|
* or underlying packet timed out), @request will be re-executed again, up to
|
|
|
|
* three times in total.
|
|
|
|
*
|
|
|
|
* See __ssam_retry() for a more generic macro for this purpose.
|
|
|
|
*
|
|
|
|
* Return: Returns the return value of the last execution of @request.
|
|
|
|
*/
|
|
|
|
#define ssam_retry(request, args...) \
|
|
|
|
__ssam_retry(request, 3, args)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* struct ssam_request_spec - Blue-print specification of SAM request.
|
|
|
|
* @target_category: Category of the request's target. See &enum ssam_ssh_tc.
|
|
|
|
* @target_id: ID of the request's target.
|
|
|
|
* @command_id: Command ID of the request.
|
|
|
|
* @instance_id: Instance ID of the request's target.
|
|
|
|
* @flags: Flags for the request. See &enum ssam_request_flags.
|
|
|
|
*
|
|
|
|
* Blue-print specification for a SAM request. This struct describes the
|
|
|
|
* unique static parameters of a request (i.e. type) without specifying any of
|
|
|
|
* its instance-specific data (e.g. payload). It is intended to be used as base
|
|
|
|
* for defining simple request functions via the
|
|
|
|
* ``SSAM_DEFINE_SYNC_REQUEST_x()`` family of macros.
|
|
|
|
*/
|
|
|
|
struct ssam_request_spec {
|
|
|
|
u8 target_category;
|
|
|
|
u8 target_id;
|
|
|
|
u8 command_id;
|
|
|
|
u8 instance_id;
|
|
|
|
u8 flags;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* struct ssam_request_spec_md - Blue-print specification for multi-device SAM
|
|
|
|
* request.
|
|
|
|
* @target_category: Category of the request's target. See &enum ssam_ssh_tc.
|
|
|
|
* @command_id: Command ID of the request.
|
|
|
|
* @flags: Flags for the request. See &enum ssam_request_flags.
|
|
|
|
*
|
|
|
|
* Blue-print specification for a multi-device SAM request, i.e. a request
|
|
|
|
* that is applicable to multiple device instances, described by their
|
|
|
|
* individual target and instance IDs. This struct describes the unique static
|
|
|
|
* parameters of a request (i.e. type) without specifying any of its
|
|
|
|
* instance-specific data (e.g. payload) and without specifying any of its
|
|
|
|
* device specific IDs (i.e. target and instance ID). It is intended to be
|
|
|
|
* used as base for defining simple multi-device request functions via the
|
|
|
|
* ``SSAM_DEFINE_SYNC_REQUEST_MD_x()`` and ``SSAM_DEFINE_SYNC_REQUEST_CL_x()``
|
|
|
|
* families of macros.
|
|
|
|
*/
|
|
|
|
struct ssam_request_spec_md {
|
|
|
|
u8 target_category;
|
|
|
|
u8 command_id;
|
|
|
|
u8 flags;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* SSAM_DEFINE_SYNC_REQUEST_N() - Define synchronous SAM request function
|
|
|
|
* with neither argument nor return value.
|
|
|
|
* @name: Name of the generated function.
|
|
|
|
* @spec: Specification (&struct ssam_request_spec) defining the request.
|
|
|
|
*
|
|
|
|
* Defines a function executing the synchronous SAM request specified by
|
|
|
|
* @spec, with the request having neither argument nor return value. The
|
|
|
|
* generated function takes care of setting up the request struct and buffer
|
|
|
|
* allocation, as well as execution of the request itself, returning once the
|
|
|
|
* request has been fully completed. The required transport buffer will be
|
|
|
|
* allocated on the stack.
|
|
|
|
*
|
platform/surface: aggregator: Make SSAM_DEFINE_SYNC_REQUEST_x define static functions
The SSAM_DEFINE_SYNC_REQUEST_x() macros are intended to reduce
boiler-plate code for SSAM request definitions by defining a wrapper
function for the specified request. The client device variants of those
macros, i.e. SSAM_DEFINE_SYNC_REQUEST_CL_x() in particular rely on the
multi-device (MD) variants, e.g.:
#define SSAM_DEFINE_SYNC_REQUEST_CL_R(name, rtype, spec...) \
SSAM_DEFINE_SYNC_REQUEST_MD_R(__raw_##name, rtype, spec) \
int name(struct ssam_device *sdev, rtype *ret) \
{ \
return __raw_##name(sdev->ctrl, sdev->uid.target, \
sdev->uid.instance, ret); \
}
This now creates the problem that it is not possible to declare the
generated functions static via
static SSAM_DEFINE_SYNC_REQUEST_CL_R(...)
as this will only apply to the function defined by the multi-device
macro, i.e. SSAM_DEFINE_SYNC_REQUEST_MD_R(). Thus compiling with
`-Wmissing-prototypes' rightfully complains that there is a 'static'
keyword missing.
To solve this, make all SSAM_DEFINE_SYNC_REQUEST_x() macros define
static functions. Non-client-device macros are also changed for
consistency. In general, we expect those functions to be only used
locally in the respective drivers for the corresponding interfaces, so
having to define a wrapper function to be able to export this should be
the odd case out.
Reported-by: kernel test robot <lkp@intel.com>
Fixes: b78b4982d763 ("platform/surface: Add platform profile driver")
Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
Link: https://lore.kernel.org/r/20210304190524.1172197-1-luzmaximilian@gmail.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2021-03-05 03:05:24 +08:00
|
|
|
* The generated function is defined as ``static int name(struct
|
|
|
|
* ssam_controller *ctrl)``, returning the status of the request, which is
|
|
|
|
* zero on success and negative on failure. The ``ctrl`` parameter is the
|
|
|
|
* controller via which the request is being sent.
|
platform/surface: Add Surface Aggregator subsystem
Add Surface System Aggregator Module core and Surface Serial Hub driver,
required for the embedded controller found on Microsoft Surface devices.
The Surface System Aggregator Module (SSAM, SAM or Surface Aggregator)
is an embedded controller (EC) found on 4th and later generation
Microsoft Surface devices, with the exception of the Surface Go series.
This EC provides various functionality, depending on the device in
question. This can include battery status and thermal reporting (5th and
later generations), but also HID keyboard (6th+) and touchpad input
(7th+) on Surface Laptop and Surface Book 3 series devices.
This patch provides the basic necessities for communication with the SAM
EC on 5th and later generation devices. On these devices, the EC
provides an interface that acts as serial device, called the Surface
Serial Hub (SSH). 4th generation devices, on which the EC interface is
provided via an HID-over-I2C device, are not supported by this patch.
Specifically, this patch adds a driver for the SSH device (device HID
MSHW0084 in ACPI), as well as a controller structure and associated API.
This represents the functional core of the Surface Aggregator kernel
subsystem, introduced with this patch, and will be expanded upon in
subsequent commits.
The SSH driver acts as the main attachment point for this subsystem and
sets-up and manages the controller structure. The controller in turn
provides a basic communication interface, allowing to send requests from
host to EC and receiving the corresponding responses, as well as
managing and receiving events, sent from EC to host. It is structured
into multiple layers, with the top layer presenting the API used by
other kernel drivers and the lower layers modeled after the serial
protocol used for communication.
Said other drivers are then responsible for providing the (Surface model
specific) functionality accessible through the EC (e.g. battery status
reporting, thermal information, ...) via said controller structure and
API, and will be added in future commits.
Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
Link: https://lore.kernel.org/r/20201221183959.1186143-2-luzmaximilian@gmail.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2020-12-22 02:39:51 +08:00
|
|
|
*
|
|
|
|
* Refer to ssam_request_sync_onstack() for more details on the behavior of
|
|
|
|
* the generated function.
|
|
|
|
*/
|
|
|
|
#define SSAM_DEFINE_SYNC_REQUEST_N(name, spec...) \
|
platform/surface: aggregator: Make SSAM_DEFINE_SYNC_REQUEST_x define static functions
The SSAM_DEFINE_SYNC_REQUEST_x() macros are intended to reduce
boiler-plate code for SSAM request definitions by defining a wrapper
function for the specified request. The client device variants of those
macros, i.e. SSAM_DEFINE_SYNC_REQUEST_CL_x() in particular rely on the
multi-device (MD) variants, e.g.:
#define SSAM_DEFINE_SYNC_REQUEST_CL_R(name, rtype, spec...) \
SSAM_DEFINE_SYNC_REQUEST_MD_R(__raw_##name, rtype, spec) \
int name(struct ssam_device *sdev, rtype *ret) \
{ \
return __raw_##name(sdev->ctrl, sdev->uid.target, \
sdev->uid.instance, ret); \
}
This now creates the problem that it is not possible to declare the
generated functions static via
static SSAM_DEFINE_SYNC_REQUEST_CL_R(...)
as this will only apply to the function defined by the multi-device
macro, i.e. SSAM_DEFINE_SYNC_REQUEST_MD_R(). Thus compiling with
`-Wmissing-prototypes' rightfully complains that there is a 'static'
keyword missing.
To solve this, make all SSAM_DEFINE_SYNC_REQUEST_x() macros define
static functions. Non-client-device macros are also changed for
consistency. In general, we expect those functions to be only used
locally in the respective drivers for the corresponding interfaces, so
having to define a wrapper function to be able to export this should be
the odd case out.
Reported-by: kernel test robot <lkp@intel.com>
Fixes: b78b4982d763 ("platform/surface: Add platform profile driver")
Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
Link: https://lore.kernel.org/r/20210304190524.1172197-1-luzmaximilian@gmail.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2021-03-05 03:05:24 +08:00
|
|
|
static int name(struct ssam_controller *ctrl) \
|
platform/surface: Add Surface Aggregator subsystem
Add Surface System Aggregator Module core and Surface Serial Hub driver,
required for the embedded controller found on Microsoft Surface devices.
The Surface System Aggregator Module (SSAM, SAM or Surface Aggregator)
is an embedded controller (EC) found on 4th and later generation
Microsoft Surface devices, with the exception of the Surface Go series.
This EC provides various functionality, depending on the device in
question. This can include battery status and thermal reporting (5th and
later generations), but also HID keyboard (6th+) and touchpad input
(7th+) on Surface Laptop and Surface Book 3 series devices.
This patch provides the basic necessities for communication with the SAM
EC on 5th and later generation devices. On these devices, the EC
provides an interface that acts as serial device, called the Surface
Serial Hub (SSH). 4th generation devices, on which the EC interface is
provided via an HID-over-I2C device, are not supported by this patch.
Specifically, this patch adds a driver for the SSH device (device HID
MSHW0084 in ACPI), as well as a controller structure and associated API.
This represents the functional core of the Surface Aggregator kernel
subsystem, introduced with this patch, and will be expanded upon in
subsequent commits.
The SSH driver acts as the main attachment point for this subsystem and
sets-up and manages the controller structure. The controller in turn
provides a basic communication interface, allowing to send requests from
host to EC and receiving the corresponding responses, as well as
managing and receiving events, sent from EC to host. It is structured
into multiple layers, with the top layer presenting the API used by
other kernel drivers and the lower layers modeled after the serial
protocol used for communication.
Said other drivers are then responsible for providing the (Surface model
specific) functionality accessible through the EC (e.g. battery status
reporting, thermal information, ...) via said controller structure and
API, and will be added in future commits.
Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
Link: https://lore.kernel.org/r/20201221183959.1186143-2-luzmaximilian@gmail.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2020-12-22 02:39:51 +08:00
|
|
|
{ \
|
|
|
|
struct ssam_request_spec s = (struct ssam_request_spec)spec; \
|
|
|
|
struct ssam_request rqst; \
|
|
|
|
\
|
|
|
|
rqst.target_category = s.target_category; \
|
|
|
|
rqst.target_id = s.target_id; \
|
|
|
|
rqst.command_id = s.command_id; \
|
|
|
|
rqst.instance_id = s.instance_id; \
|
|
|
|
rqst.flags = s.flags; \
|
|
|
|
rqst.length = 0; \
|
|
|
|
rqst.payload = NULL; \
|
|
|
|
\
|
|
|
|
return ssam_request_sync_onstack(ctrl, &rqst, NULL, 0); \
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* SSAM_DEFINE_SYNC_REQUEST_W() - Define synchronous SAM request function with
|
|
|
|
* argument.
|
|
|
|
* @name: Name of the generated function.
|
|
|
|
* @atype: Type of the request's argument.
|
|
|
|
* @spec: Specification (&struct ssam_request_spec) defining the request.
|
|
|
|
*
|
|
|
|
* Defines a function executing the synchronous SAM request specified by
|
|
|
|
* @spec, with the request taking an argument of type @atype and having no
|
|
|
|
* return value. The generated function takes care of setting up the request
|
|
|
|
* struct, buffer allocation, as well as execution of the request itself,
|
|
|
|
* returning once the request has been fully completed. The required transport
|
|
|
|
* buffer will be allocated on the stack.
|
|
|
|
*
|
platform/surface: aggregator: Make SSAM_DEFINE_SYNC_REQUEST_x define static functions
The SSAM_DEFINE_SYNC_REQUEST_x() macros are intended to reduce
boiler-plate code for SSAM request definitions by defining a wrapper
function for the specified request. The client device variants of those
macros, i.e. SSAM_DEFINE_SYNC_REQUEST_CL_x() in particular rely on the
multi-device (MD) variants, e.g.:
#define SSAM_DEFINE_SYNC_REQUEST_CL_R(name, rtype, spec...) \
SSAM_DEFINE_SYNC_REQUEST_MD_R(__raw_##name, rtype, spec) \
int name(struct ssam_device *sdev, rtype *ret) \
{ \
return __raw_##name(sdev->ctrl, sdev->uid.target, \
sdev->uid.instance, ret); \
}
This now creates the problem that it is not possible to declare the
generated functions static via
static SSAM_DEFINE_SYNC_REQUEST_CL_R(...)
as this will only apply to the function defined by the multi-device
macro, i.e. SSAM_DEFINE_SYNC_REQUEST_MD_R(). Thus compiling with
`-Wmissing-prototypes' rightfully complains that there is a 'static'
keyword missing.
To solve this, make all SSAM_DEFINE_SYNC_REQUEST_x() macros define
static functions. Non-client-device macros are also changed for
consistency. In general, we expect those functions to be only used
locally in the respective drivers for the corresponding interfaces, so
having to define a wrapper function to be able to export this should be
the odd case out.
Reported-by: kernel test robot <lkp@intel.com>
Fixes: b78b4982d763 ("platform/surface: Add platform profile driver")
Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
Link: https://lore.kernel.org/r/20210304190524.1172197-1-luzmaximilian@gmail.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2021-03-05 03:05:24 +08:00
|
|
|
* The generated function is defined as ``static int name(struct
|
|
|
|
* ssam_controller *ctrl, const atype *arg)``, returning the status of the
|
|
|
|
* request, which is zero on success and negative on failure. The ``ctrl``
|
|
|
|
* parameter is the controller via which the request is sent. The request
|
|
|
|
* argument is specified via the ``arg`` pointer.
|
platform/surface: Add Surface Aggregator subsystem
Add Surface System Aggregator Module core and Surface Serial Hub driver,
required for the embedded controller found on Microsoft Surface devices.
The Surface System Aggregator Module (SSAM, SAM or Surface Aggregator)
is an embedded controller (EC) found on 4th and later generation
Microsoft Surface devices, with the exception of the Surface Go series.
This EC provides various functionality, depending on the device in
question. This can include battery status and thermal reporting (5th and
later generations), but also HID keyboard (6th+) and touchpad input
(7th+) on Surface Laptop and Surface Book 3 series devices.
This patch provides the basic necessities for communication with the SAM
EC on 5th and later generation devices. On these devices, the EC
provides an interface that acts as serial device, called the Surface
Serial Hub (SSH). 4th generation devices, on which the EC interface is
provided via an HID-over-I2C device, are not supported by this patch.
Specifically, this patch adds a driver for the SSH device (device HID
MSHW0084 in ACPI), as well as a controller structure and associated API.
This represents the functional core of the Surface Aggregator kernel
subsystem, introduced with this patch, and will be expanded upon in
subsequent commits.
The SSH driver acts as the main attachment point for this subsystem and
sets-up and manages the controller structure. The controller in turn
provides a basic communication interface, allowing to send requests from
host to EC and receiving the corresponding responses, as well as
managing and receiving events, sent from EC to host. It is structured
into multiple layers, with the top layer presenting the API used by
other kernel drivers and the lower layers modeled after the serial
protocol used for communication.
Said other drivers are then responsible for providing the (Surface model
specific) functionality accessible through the EC (e.g. battery status
reporting, thermal information, ...) via said controller structure and
API, and will be added in future commits.
Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
Link: https://lore.kernel.org/r/20201221183959.1186143-2-luzmaximilian@gmail.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2020-12-22 02:39:51 +08:00
|
|
|
*
|
|
|
|
* Refer to ssam_request_sync_onstack() for more details on the behavior of
|
|
|
|
* the generated function.
|
|
|
|
*/
|
|
|
|
#define SSAM_DEFINE_SYNC_REQUEST_W(name, atype, spec...) \
|
platform/surface: aggregator: Make SSAM_DEFINE_SYNC_REQUEST_x define static functions
The SSAM_DEFINE_SYNC_REQUEST_x() macros are intended to reduce
boiler-plate code for SSAM request definitions by defining a wrapper
function for the specified request. The client device variants of those
macros, i.e. SSAM_DEFINE_SYNC_REQUEST_CL_x() in particular rely on the
multi-device (MD) variants, e.g.:
#define SSAM_DEFINE_SYNC_REQUEST_CL_R(name, rtype, spec...) \
SSAM_DEFINE_SYNC_REQUEST_MD_R(__raw_##name, rtype, spec) \
int name(struct ssam_device *sdev, rtype *ret) \
{ \
return __raw_##name(sdev->ctrl, sdev->uid.target, \
sdev->uid.instance, ret); \
}
This now creates the problem that it is not possible to declare the
generated functions static via
static SSAM_DEFINE_SYNC_REQUEST_CL_R(...)
as this will only apply to the function defined by the multi-device
macro, i.e. SSAM_DEFINE_SYNC_REQUEST_MD_R(). Thus compiling with
`-Wmissing-prototypes' rightfully complains that there is a 'static'
keyword missing.
To solve this, make all SSAM_DEFINE_SYNC_REQUEST_x() macros define
static functions. Non-client-device macros are also changed for
consistency. In general, we expect those functions to be only used
locally in the respective drivers for the corresponding interfaces, so
having to define a wrapper function to be able to export this should be
the odd case out.
Reported-by: kernel test robot <lkp@intel.com>
Fixes: b78b4982d763 ("platform/surface: Add platform profile driver")
Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
Link: https://lore.kernel.org/r/20210304190524.1172197-1-luzmaximilian@gmail.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2021-03-05 03:05:24 +08:00
|
|
|
static int name(struct ssam_controller *ctrl, const atype *arg) \
|
platform/surface: Add Surface Aggregator subsystem
Add Surface System Aggregator Module core and Surface Serial Hub driver,
required for the embedded controller found on Microsoft Surface devices.
The Surface System Aggregator Module (SSAM, SAM or Surface Aggregator)
is an embedded controller (EC) found on 4th and later generation
Microsoft Surface devices, with the exception of the Surface Go series.
This EC provides various functionality, depending on the device in
question. This can include battery status and thermal reporting (5th and
later generations), but also HID keyboard (6th+) and touchpad input
(7th+) on Surface Laptop and Surface Book 3 series devices.
This patch provides the basic necessities for communication with the SAM
EC on 5th and later generation devices. On these devices, the EC
provides an interface that acts as serial device, called the Surface
Serial Hub (SSH). 4th generation devices, on which the EC interface is
provided via an HID-over-I2C device, are not supported by this patch.
Specifically, this patch adds a driver for the SSH device (device HID
MSHW0084 in ACPI), as well as a controller structure and associated API.
This represents the functional core of the Surface Aggregator kernel
subsystem, introduced with this patch, and will be expanded upon in
subsequent commits.
The SSH driver acts as the main attachment point for this subsystem and
sets-up and manages the controller structure. The controller in turn
provides a basic communication interface, allowing to send requests from
host to EC and receiving the corresponding responses, as well as
managing and receiving events, sent from EC to host. It is structured
into multiple layers, with the top layer presenting the API used by
other kernel drivers and the lower layers modeled after the serial
protocol used for communication.
Said other drivers are then responsible for providing the (Surface model
specific) functionality accessible through the EC (e.g. battery status
reporting, thermal information, ...) via said controller structure and
API, and will be added in future commits.
Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
Link: https://lore.kernel.org/r/20201221183959.1186143-2-luzmaximilian@gmail.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2020-12-22 02:39:51 +08:00
|
|
|
{ \
|
|
|
|
struct ssam_request_spec s = (struct ssam_request_spec)spec; \
|
|
|
|
struct ssam_request rqst; \
|
|
|
|
\
|
|
|
|
rqst.target_category = s.target_category; \
|
|
|
|
rqst.target_id = s.target_id; \
|
|
|
|
rqst.command_id = s.command_id; \
|
|
|
|
rqst.instance_id = s.instance_id; \
|
|
|
|
rqst.flags = s.flags; \
|
|
|
|
rqst.length = sizeof(atype); \
|
|
|
|
rqst.payload = (u8 *)arg; \
|
|
|
|
\
|
|
|
|
return ssam_request_sync_onstack(ctrl, &rqst, NULL, \
|
|
|
|
sizeof(atype)); \
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* SSAM_DEFINE_SYNC_REQUEST_R() - Define synchronous SAM request function with
|
|
|
|
* return value.
|
|
|
|
* @name: Name of the generated function.
|
|
|
|
* @rtype: Type of the request's return value.
|
|
|
|
* @spec: Specification (&struct ssam_request_spec) defining the request.
|
|
|
|
*
|
|
|
|
* Defines a function executing the synchronous SAM request specified by
|
|
|
|
* @spec, with the request taking no argument but having a return value of
|
|
|
|
* type @rtype. The generated function takes care of setting up the request
|
|
|
|
* and response structs, buffer allocation, as well as execution of the
|
|
|
|
* request itself, returning once the request has been fully completed. The
|
|
|
|
* required transport buffer will be allocated on the stack.
|
|
|
|
*
|
platform/surface: aggregator: Make SSAM_DEFINE_SYNC_REQUEST_x define static functions
The SSAM_DEFINE_SYNC_REQUEST_x() macros are intended to reduce
boiler-plate code for SSAM request definitions by defining a wrapper
function for the specified request. The client device variants of those
macros, i.e. SSAM_DEFINE_SYNC_REQUEST_CL_x() in particular rely on the
multi-device (MD) variants, e.g.:
#define SSAM_DEFINE_SYNC_REQUEST_CL_R(name, rtype, spec...) \
SSAM_DEFINE_SYNC_REQUEST_MD_R(__raw_##name, rtype, spec) \
int name(struct ssam_device *sdev, rtype *ret) \
{ \
return __raw_##name(sdev->ctrl, sdev->uid.target, \
sdev->uid.instance, ret); \
}
This now creates the problem that it is not possible to declare the
generated functions static via
static SSAM_DEFINE_SYNC_REQUEST_CL_R(...)
as this will only apply to the function defined by the multi-device
macro, i.e. SSAM_DEFINE_SYNC_REQUEST_MD_R(). Thus compiling with
`-Wmissing-prototypes' rightfully complains that there is a 'static'
keyword missing.
To solve this, make all SSAM_DEFINE_SYNC_REQUEST_x() macros define
static functions. Non-client-device macros are also changed for
consistency. In general, we expect those functions to be only used
locally in the respective drivers for the corresponding interfaces, so
having to define a wrapper function to be able to export this should be
the odd case out.
Reported-by: kernel test robot <lkp@intel.com>
Fixes: b78b4982d763 ("platform/surface: Add platform profile driver")
Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
Link: https://lore.kernel.org/r/20210304190524.1172197-1-luzmaximilian@gmail.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2021-03-05 03:05:24 +08:00
|
|
|
* The generated function is defined as ``static int name(struct
|
|
|
|
* ssam_controller *ctrl, rtype *ret)``, returning the status of the request,
|
|
|
|
* which is zero on success and negative on failure. The ``ctrl`` parameter is
|
|
|
|
* the controller via which the request is sent. The request's return value is
|
|
|
|
* written to the memory pointed to by the ``ret`` parameter.
|
platform/surface: Add Surface Aggregator subsystem
Add Surface System Aggregator Module core and Surface Serial Hub driver,
required for the embedded controller found on Microsoft Surface devices.
The Surface System Aggregator Module (SSAM, SAM or Surface Aggregator)
is an embedded controller (EC) found on 4th and later generation
Microsoft Surface devices, with the exception of the Surface Go series.
This EC provides various functionality, depending on the device in
question. This can include battery status and thermal reporting (5th and
later generations), but also HID keyboard (6th+) and touchpad input
(7th+) on Surface Laptop and Surface Book 3 series devices.
This patch provides the basic necessities for communication with the SAM
EC on 5th and later generation devices. On these devices, the EC
provides an interface that acts as serial device, called the Surface
Serial Hub (SSH). 4th generation devices, on which the EC interface is
provided via an HID-over-I2C device, are not supported by this patch.
Specifically, this patch adds a driver for the SSH device (device HID
MSHW0084 in ACPI), as well as a controller structure and associated API.
This represents the functional core of the Surface Aggregator kernel
subsystem, introduced with this patch, and will be expanded upon in
subsequent commits.
The SSH driver acts as the main attachment point for this subsystem and
sets-up and manages the controller structure. The controller in turn
provides a basic communication interface, allowing to send requests from
host to EC and receiving the corresponding responses, as well as
managing and receiving events, sent from EC to host. It is structured
into multiple layers, with the top layer presenting the API used by
other kernel drivers and the lower layers modeled after the serial
protocol used for communication.
Said other drivers are then responsible for providing the (Surface model
specific) functionality accessible through the EC (e.g. battery status
reporting, thermal information, ...) via said controller structure and
API, and will be added in future commits.
Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
Link: https://lore.kernel.org/r/20201221183959.1186143-2-luzmaximilian@gmail.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2020-12-22 02:39:51 +08:00
|
|
|
*
|
|
|
|
* Refer to ssam_request_sync_onstack() for more details on the behavior of
|
|
|
|
* the generated function.
|
|
|
|
*/
|
|
|
|
#define SSAM_DEFINE_SYNC_REQUEST_R(name, rtype, spec...) \
|
platform/surface: aggregator: Make SSAM_DEFINE_SYNC_REQUEST_x define static functions
The SSAM_DEFINE_SYNC_REQUEST_x() macros are intended to reduce
boiler-plate code for SSAM request definitions by defining a wrapper
function for the specified request. The client device variants of those
macros, i.e. SSAM_DEFINE_SYNC_REQUEST_CL_x() in particular rely on the
multi-device (MD) variants, e.g.:
#define SSAM_DEFINE_SYNC_REQUEST_CL_R(name, rtype, spec...) \
SSAM_DEFINE_SYNC_REQUEST_MD_R(__raw_##name, rtype, spec) \
int name(struct ssam_device *sdev, rtype *ret) \
{ \
return __raw_##name(sdev->ctrl, sdev->uid.target, \
sdev->uid.instance, ret); \
}
This now creates the problem that it is not possible to declare the
generated functions static via
static SSAM_DEFINE_SYNC_REQUEST_CL_R(...)
as this will only apply to the function defined by the multi-device
macro, i.e. SSAM_DEFINE_SYNC_REQUEST_MD_R(). Thus compiling with
`-Wmissing-prototypes' rightfully complains that there is a 'static'
keyword missing.
To solve this, make all SSAM_DEFINE_SYNC_REQUEST_x() macros define
static functions. Non-client-device macros are also changed for
consistency. In general, we expect those functions to be only used
locally in the respective drivers for the corresponding interfaces, so
having to define a wrapper function to be able to export this should be
the odd case out.
Reported-by: kernel test robot <lkp@intel.com>
Fixes: b78b4982d763 ("platform/surface: Add platform profile driver")
Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
Link: https://lore.kernel.org/r/20210304190524.1172197-1-luzmaximilian@gmail.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2021-03-05 03:05:24 +08:00
|
|
|
static int name(struct ssam_controller *ctrl, rtype *ret) \
|
platform/surface: Add Surface Aggregator subsystem
Add Surface System Aggregator Module core and Surface Serial Hub driver,
required for the embedded controller found on Microsoft Surface devices.
The Surface System Aggregator Module (SSAM, SAM or Surface Aggregator)
is an embedded controller (EC) found on 4th and later generation
Microsoft Surface devices, with the exception of the Surface Go series.
This EC provides various functionality, depending on the device in
question. This can include battery status and thermal reporting (5th and
later generations), but also HID keyboard (6th+) and touchpad input
(7th+) on Surface Laptop and Surface Book 3 series devices.
This patch provides the basic necessities for communication with the SAM
EC on 5th and later generation devices. On these devices, the EC
provides an interface that acts as serial device, called the Surface
Serial Hub (SSH). 4th generation devices, on which the EC interface is
provided via an HID-over-I2C device, are not supported by this patch.
Specifically, this patch adds a driver for the SSH device (device HID
MSHW0084 in ACPI), as well as a controller structure and associated API.
This represents the functional core of the Surface Aggregator kernel
subsystem, introduced with this patch, and will be expanded upon in
subsequent commits.
The SSH driver acts as the main attachment point for this subsystem and
sets-up and manages the controller structure. The controller in turn
provides a basic communication interface, allowing to send requests from
host to EC and receiving the corresponding responses, as well as
managing and receiving events, sent from EC to host. It is structured
into multiple layers, with the top layer presenting the API used by
other kernel drivers and the lower layers modeled after the serial
protocol used for communication.
Said other drivers are then responsible for providing the (Surface model
specific) functionality accessible through the EC (e.g. battery status
reporting, thermal information, ...) via said controller structure and
API, and will be added in future commits.
Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
Link: https://lore.kernel.org/r/20201221183959.1186143-2-luzmaximilian@gmail.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2020-12-22 02:39:51 +08:00
|
|
|
{ \
|
|
|
|
struct ssam_request_spec s = (struct ssam_request_spec)spec; \
|
|
|
|
struct ssam_request rqst; \
|
|
|
|
struct ssam_response rsp; \
|
|
|
|
int status; \
|
|
|
|
\
|
|
|
|
rqst.target_category = s.target_category; \
|
|
|
|
rqst.target_id = s.target_id; \
|
|
|
|
rqst.command_id = s.command_id; \
|
|
|
|
rqst.instance_id = s.instance_id; \
|
|
|
|
rqst.flags = s.flags | SSAM_REQUEST_HAS_RESPONSE; \
|
|
|
|
rqst.length = 0; \
|
|
|
|
rqst.payload = NULL; \
|
|
|
|
\
|
|
|
|
rsp.capacity = sizeof(rtype); \
|
|
|
|
rsp.length = 0; \
|
|
|
|
rsp.pointer = (u8 *)ret; \
|
|
|
|
\
|
|
|
|
status = ssam_request_sync_onstack(ctrl, &rqst, &rsp, 0); \
|
|
|
|
if (status) \
|
|
|
|
return status; \
|
|
|
|
\
|
|
|
|
if (rsp.length != sizeof(rtype)) { \
|
|
|
|
struct device *dev = ssam_controller_device(ctrl); \
|
|
|
|
dev_err(dev, \
|
|
|
|
"rqst: invalid response length, expected %zu, got %zu (tc: %#04x, cid: %#04x)", \
|
|
|
|
sizeof(rtype), rsp.length, rqst.target_category,\
|
|
|
|
rqst.command_id); \
|
|
|
|
return -EIO; \
|
|
|
|
} \
|
|
|
|
\
|
|
|
|
return 0; \
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* SSAM_DEFINE_SYNC_REQUEST_MD_N() - Define synchronous multi-device SAM
|
|
|
|
* request function with neither argument nor return value.
|
|
|
|
* @name: Name of the generated function.
|
|
|
|
* @spec: Specification (&struct ssam_request_spec_md) defining the request.
|
|
|
|
*
|
|
|
|
* Defines a function executing the synchronous SAM request specified by
|
|
|
|
* @spec, with the request having neither argument nor return value. Device
|
|
|
|
* specifying parameters are not hard-coded, but instead must be provided to
|
|
|
|
* the function. The generated function takes care of setting up the request
|
|
|
|
* struct, buffer allocation, as well as execution of the request itself,
|
|
|
|
* returning once the request has been fully completed. The required transport
|
|
|
|
* buffer will be allocated on the stack.
|
|
|
|
*
|
platform/surface: aggregator: Make SSAM_DEFINE_SYNC_REQUEST_x define static functions
The SSAM_DEFINE_SYNC_REQUEST_x() macros are intended to reduce
boiler-plate code for SSAM request definitions by defining a wrapper
function for the specified request. The client device variants of those
macros, i.e. SSAM_DEFINE_SYNC_REQUEST_CL_x() in particular rely on the
multi-device (MD) variants, e.g.:
#define SSAM_DEFINE_SYNC_REQUEST_CL_R(name, rtype, spec...) \
SSAM_DEFINE_SYNC_REQUEST_MD_R(__raw_##name, rtype, spec) \
int name(struct ssam_device *sdev, rtype *ret) \
{ \
return __raw_##name(sdev->ctrl, sdev->uid.target, \
sdev->uid.instance, ret); \
}
This now creates the problem that it is not possible to declare the
generated functions static via
static SSAM_DEFINE_SYNC_REQUEST_CL_R(...)
as this will only apply to the function defined by the multi-device
macro, i.e. SSAM_DEFINE_SYNC_REQUEST_MD_R(). Thus compiling with
`-Wmissing-prototypes' rightfully complains that there is a 'static'
keyword missing.
To solve this, make all SSAM_DEFINE_SYNC_REQUEST_x() macros define
static functions. Non-client-device macros are also changed for
consistency. In general, we expect those functions to be only used
locally in the respective drivers for the corresponding interfaces, so
having to define a wrapper function to be able to export this should be
the odd case out.
Reported-by: kernel test robot <lkp@intel.com>
Fixes: b78b4982d763 ("platform/surface: Add platform profile driver")
Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
Link: https://lore.kernel.org/r/20210304190524.1172197-1-luzmaximilian@gmail.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2021-03-05 03:05:24 +08:00
|
|
|
* The generated function is defined as ``static int name(struct
|
|
|
|
* ssam_controller *ctrl, u8 tid, u8 iid)``, returning the status of the
|
|
|
|
* request, which is zero on success and negative on failure. The ``ctrl``
|
|
|
|
* parameter is the controller via which the request is sent, ``tid`` the
|
|
|
|
* target ID for the request, and ``iid`` the instance ID.
|
platform/surface: Add Surface Aggregator subsystem
Add Surface System Aggregator Module core and Surface Serial Hub driver,
required for the embedded controller found on Microsoft Surface devices.
The Surface System Aggregator Module (SSAM, SAM or Surface Aggregator)
is an embedded controller (EC) found on 4th and later generation
Microsoft Surface devices, with the exception of the Surface Go series.
This EC provides various functionality, depending on the device in
question. This can include battery status and thermal reporting (5th and
later generations), but also HID keyboard (6th+) and touchpad input
(7th+) on Surface Laptop and Surface Book 3 series devices.
This patch provides the basic necessities for communication with the SAM
EC on 5th and later generation devices. On these devices, the EC
provides an interface that acts as serial device, called the Surface
Serial Hub (SSH). 4th generation devices, on which the EC interface is
provided via an HID-over-I2C device, are not supported by this patch.
Specifically, this patch adds a driver for the SSH device (device HID
MSHW0084 in ACPI), as well as a controller structure and associated API.
This represents the functional core of the Surface Aggregator kernel
subsystem, introduced with this patch, and will be expanded upon in
subsequent commits.
The SSH driver acts as the main attachment point for this subsystem and
sets-up and manages the controller structure. The controller in turn
provides a basic communication interface, allowing to send requests from
host to EC and receiving the corresponding responses, as well as
managing and receiving events, sent from EC to host. It is structured
into multiple layers, with the top layer presenting the API used by
other kernel drivers and the lower layers modeled after the serial
protocol used for communication.
Said other drivers are then responsible for providing the (Surface model
specific) functionality accessible through the EC (e.g. battery status
reporting, thermal information, ...) via said controller structure and
API, and will be added in future commits.
Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
Link: https://lore.kernel.org/r/20201221183959.1186143-2-luzmaximilian@gmail.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2020-12-22 02:39:51 +08:00
|
|
|
*
|
|
|
|
* Refer to ssam_request_sync_onstack() for more details on the behavior of
|
|
|
|
* the generated function.
|
|
|
|
*/
|
|
|
|
#define SSAM_DEFINE_SYNC_REQUEST_MD_N(name, spec...) \
|
platform/surface: aggregator: Make SSAM_DEFINE_SYNC_REQUEST_x define static functions
The SSAM_DEFINE_SYNC_REQUEST_x() macros are intended to reduce
boiler-plate code for SSAM request definitions by defining a wrapper
function for the specified request. The client device variants of those
macros, i.e. SSAM_DEFINE_SYNC_REQUEST_CL_x() in particular rely on the
multi-device (MD) variants, e.g.:
#define SSAM_DEFINE_SYNC_REQUEST_CL_R(name, rtype, spec...) \
SSAM_DEFINE_SYNC_REQUEST_MD_R(__raw_##name, rtype, spec) \
int name(struct ssam_device *sdev, rtype *ret) \
{ \
return __raw_##name(sdev->ctrl, sdev->uid.target, \
sdev->uid.instance, ret); \
}
This now creates the problem that it is not possible to declare the
generated functions static via
static SSAM_DEFINE_SYNC_REQUEST_CL_R(...)
as this will only apply to the function defined by the multi-device
macro, i.e. SSAM_DEFINE_SYNC_REQUEST_MD_R(). Thus compiling with
`-Wmissing-prototypes' rightfully complains that there is a 'static'
keyword missing.
To solve this, make all SSAM_DEFINE_SYNC_REQUEST_x() macros define
static functions. Non-client-device macros are also changed for
consistency. In general, we expect those functions to be only used
locally in the respective drivers for the corresponding interfaces, so
having to define a wrapper function to be able to export this should be
the odd case out.
Reported-by: kernel test robot <lkp@intel.com>
Fixes: b78b4982d763 ("platform/surface: Add platform profile driver")
Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
Link: https://lore.kernel.org/r/20210304190524.1172197-1-luzmaximilian@gmail.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2021-03-05 03:05:24 +08:00
|
|
|
static int name(struct ssam_controller *ctrl, u8 tid, u8 iid) \
|
platform/surface: Add Surface Aggregator subsystem
Add Surface System Aggregator Module core and Surface Serial Hub driver,
required for the embedded controller found on Microsoft Surface devices.
The Surface System Aggregator Module (SSAM, SAM or Surface Aggregator)
is an embedded controller (EC) found on 4th and later generation
Microsoft Surface devices, with the exception of the Surface Go series.
This EC provides various functionality, depending on the device in
question. This can include battery status and thermal reporting (5th and
later generations), but also HID keyboard (6th+) and touchpad input
(7th+) on Surface Laptop and Surface Book 3 series devices.
This patch provides the basic necessities for communication with the SAM
EC on 5th and later generation devices. On these devices, the EC
provides an interface that acts as serial device, called the Surface
Serial Hub (SSH). 4th generation devices, on which the EC interface is
provided via an HID-over-I2C device, are not supported by this patch.
Specifically, this patch adds a driver for the SSH device (device HID
MSHW0084 in ACPI), as well as a controller structure and associated API.
This represents the functional core of the Surface Aggregator kernel
subsystem, introduced with this patch, and will be expanded upon in
subsequent commits.
The SSH driver acts as the main attachment point for this subsystem and
sets-up and manages the controller structure. The controller in turn
provides a basic communication interface, allowing to send requests from
host to EC and receiving the corresponding responses, as well as
managing and receiving events, sent from EC to host. It is structured
into multiple layers, with the top layer presenting the API used by
other kernel drivers and the lower layers modeled after the serial
protocol used for communication.
Said other drivers are then responsible for providing the (Surface model
specific) functionality accessible through the EC (e.g. battery status
reporting, thermal information, ...) via said controller structure and
API, and will be added in future commits.
Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
Link: https://lore.kernel.org/r/20201221183959.1186143-2-luzmaximilian@gmail.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2020-12-22 02:39:51 +08:00
|
|
|
{ \
|
|
|
|
struct ssam_request_spec_md s = (struct ssam_request_spec_md)spec; \
|
|
|
|
struct ssam_request rqst; \
|
|
|
|
\
|
|
|
|
rqst.target_category = s.target_category; \
|
|
|
|
rqst.target_id = tid; \
|
|
|
|
rqst.command_id = s.command_id; \
|
|
|
|
rqst.instance_id = iid; \
|
|
|
|
rqst.flags = s.flags; \
|
|
|
|
rqst.length = 0; \
|
|
|
|
rqst.payload = NULL; \
|
|
|
|
\
|
|
|
|
return ssam_request_sync_onstack(ctrl, &rqst, NULL, 0); \
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* SSAM_DEFINE_SYNC_REQUEST_MD_W() - Define synchronous multi-device SAM
|
|
|
|
* request function with argument.
|
|
|
|
* @name: Name of the generated function.
|
|
|
|
* @atype: Type of the request's argument.
|
|
|
|
* @spec: Specification (&struct ssam_request_spec_md) defining the request.
|
|
|
|
*
|
|
|
|
* Defines a function executing the synchronous SAM request specified by
|
|
|
|
* @spec, with the request taking an argument of type @atype and having no
|
|
|
|
* return value. Device specifying parameters are not hard-coded, but instead
|
|
|
|
* must be provided to the function. The generated function takes care of
|
|
|
|
* setting up the request struct, buffer allocation, as well as execution of
|
|
|
|
* the request itself, returning once the request has been fully completed.
|
|
|
|
* The required transport buffer will be allocated on the stack.
|
|
|
|
*
|
platform/surface: aggregator: Make SSAM_DEFINE_SYNC_REQUEST_x define static functions
The SSAM_DEFINE_SYNC_REQUEST_x() macros are intended to reduce
boiler-plate code for SSAM request definitions by defining a wrapper
function for the specified request. The client device variants of those
macros, i.e. SSAM_DEFINE_SYNC_REQUEST_CL_x() in particular rely on the
multi-device (MD) variants, e.g.:
#define SSAM_DEFINE_SYNC_REQUEST_CL_R(name, rtype, spec...) \
SSAM_DEFINE_SYNC_REQUEST_MD_R(__raw_##name, rtype, spec) \
int name(struct ssam_device *sdev, rtype *ret) \
{ \
return __raw_##name(sdev->ctrl, sdev->uid.target, \
sdev->uid.instance, ret); \
}
This now creates the problem that it is not possible to declare the
generated functions static via
static SSAM_DEFINE_SYNC_REQUEST_CL_R(...)
as this will only apply to the function defined by the multi-device
macro, i.e. SSAM_DEFINE_SYNC_REQUEST_MD_R(). Thus compiling with
`-Wmissing-prototypes' rightfully complains that there is a 'static'
keyword missing.
To solve this, make all SSAM_DEFINE_SYNC_REQUEST_x() macros define
static functions. Non-client-device macros are also changed for
consistency. In general, we expect those functions to be only used
locally in the respective drivers for the corresponding interfaces, so
having to define a wrapper function to be able to export this should be
the odd case out.
Reported-by: kernel test robot <lkp@intel.com>
Fixes: b78b4982d763 ("platform/surface: Add platform profile driver")
Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
Link: https://lore.kernel.org/r/20210304190524.1172197-1-luzmaximilian@gmail.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2021-03-05 03:05:24 +08:00
|
|
|
* The generated function is defined as ``static int name(struct
|
|
|
|
* ssam_controller *ctrl, u8 tid, u8 iid, const atype *arg)``, returning the
|
|
|
|
* status of the request, which is zero on success and negative on failure.
|
|
|
|
* The ``ctrl`` parameter is the controller via which the request is sent,
|
|
|
|
* ``tid`` the target ID for the request, and ``iid`` the instance ID. The
|
|
|
|
* request argument is specified via the ``arg`` pointer.
|
platform/surface: Add Surface Aggregator subsystem
Add Surface System Aggregator Module core and Surface Serial Hub driver,
required for the embedded controller found on Microsoft Surface devices.
The Surface System Aggregator Module (SSAM, SAM or Surface Aggregator)
is an embedded controller (EC) found on 4th and later generation
Microsoft Surface devices, with the exception of the Surface Go series.
This EC provides various functionality, depending on the device in
question. This can include battery status and thermal reporting (5th and
later generations), but also HID keyboard (6th+) and touchpad input
(7th+) on Surface Laptop and Surface Book 3 series devices.
This patch provides the basic necessities for communication with the SAM
EC on 5th and later generation devices. On these devices, the EC
provides an interface that acts as serial device, called the Surface
Serial Hub (SSH). 4th generation devices, on which the EC interface is
provided via an HID-over-I2C device, are not supported by this patch.
Specifically, this patch adds a driver for the SSH device (device HID
MSHW0084 in ACPI), as well as a controller structure and associated API.
This represents the functional core of the Surface Aggregator kernel
subsystem, introduced with this patch, and will be expanded upon in
subsequent commits.
The SSH driver acts as the main attachment point for this subsystem and
sets-up and manages the controller structure. The controller in turn
provides a basic communication interface, allowing to send requests from
host to EC and receiving the corresponding responses, as well as
managing and receiving events, sent from EC to host. It is structured
into multiple layers, with the top layer presenting the API used by
other kernel drivers and the lower layers modeled after the serial
protocol used for communication.
Said other drivers are then responsible for providing the (Surface model
specific) functionality accessible through the EC (e.g. battery status
reporting, thermal information, ...) via said controller structure and
API, and will be added in future commits.
Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
Link: https://lore.kernel.org/r/20201221183959.1186143-2-luzmaximilian@gmail.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2020-12-22 02:39:51 +08:00
|
|
|
*
|
|
|
|
* Refer to ssam_request_sync_onstack() for more details on the behavior of
|
|
|
|
* the generated function.
|
|
|
|
*/
|
|
|
|
#define SSAM_DEFINE_SYNC_REQUEST_MD_W(name, atype, spec...) \
|
platform/surface: aggregator: Make SSAM_DEFINE_SYNC_REQUEST_x define static functions
The SSAM_DEFINE_SYNC_REQUEST_x() macros are intended to reduce
boiler-plate code for SSAM request definitions by defining a wrapper
function for the specified request. The client device variants of those
macros, i.e. SSAM_DEFINE_SYNC_REQUEST_CL_x() in particular rely on the
multi-device (MD) variants, e.g.:
#define SSAM_DEFINE_SYNC_REQUEST_CL_R(name, rtype, spec...) \
SSAM_DEFINE_SYNC_REQUEST_MD_R(__raw_##name, rtype, spec) \
int name(struct ssam_device *sdev, rtype *ret) \
{ \
return __raw_##name(sdev->ctrl, sdev->uid.target, \
sdev->uid.instance, ret); \
}
This now creates the problem that it is not possible to declare the
generated functions static via
static SSAM_DEFINE_SYNC_REQUEST_CL_R(...)
as this will only apply to the function defined by the multi-device
macro, i.e. SSAM_DEFINE_SYNC_REQUEST_MD_R(). Thus compiling with
`-Wmissing-prototypes' rightfully complains that there is a 'static'
keyword missing.
To solve this, make all SSAM_DEFINE_SYNC_REQUEST_x() macros define
static functions. Non-client-device macros are also changed for
consistency. In general, we expect those functions to be only used
locally in the respective drivers for the corresponding interfaces, so
having to define a wrapper function to be able to export this should be
the odd case out.
Reported-by: kernel test robot <lkp@intel.com>
Fixes: b78b4982d763 ("platform/surface: Add platform profile driver")
Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
Link: https://lore.kernel.org/r/20210304190524.1172197-1-luzmaximilian@gmail.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2021-03-05 03:05:24 +08:00
|
|
|
static int name(struct ssam_controller *ctrl, u8 tid, u8 iid, const atype *arg) \
|
platform/surface: Add Surface Aggregator subsystem
Add Surface System Aggregator Module core and Surface Serial Hub driver,
required for the embedded controller found on Microsoft Surface devices.
The Surface System Aggregator Module (SSAM, SAM or Surface Aggregator)
is an embedded controller (EC) found on 4th and later generation
Microsoft Surface devices, with the exception of the Surface Go series.
This EC provides various functionality, depending on the device in
question. This can include battery status and thermal reporting (5th and
later generations), but also HID keyboard (6th+) and touchpad input
(7th+) on Surface Laptop and Surface Book 3 series devices.
This patch provides the basic necessities for communication with the SAM
EC on 5th and later generation devices. On these devices, the EC
provides an interface that acts as serial device, called the Surface
Serial Hub (SSH). 4th generation devices, on which the EC interface is
provided via an HID-over-I2C device, are not supported by this patch.
Specifically, this patch adds a driver for the SSH device (device HID
MSHW0084 in ACPI), as well as a controller structure and associated API.
This represents the functional core of the Surface Aggregator kernel
subsystem, introduced with this patch, and will be expanded upon in
subsequent commits.
The SSH driver acts as the main attachment point for this subsystem and
sets-up and manages the controller structure. The controller in turn
provides a basic communication interface, allowing to send requests from
host to EC and receiving the corresponding responses, as well as
managing and receiving events, sent from EC to host. It is structured
into multiple layers, with the top layer presenting the API used by
other kernel drivers and the lower layers modeled after the serial
protocol used for communication.
Said other drivers are then responsible for providing the (Surface model
specific) functionality accessible through the EC (e.g. battery status
reporting, thermal information, ...) via said controller structure and
API, and will be added in future commits.
Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
Link: https://lore.kernel.org/r/20201221183959.1186143-2-luzmaximilian@gmail.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2020-12-22 02:39:51 +08:00
|
|
|
{ \
|
|
|
|
struct ssam_request_spec_md s = (struct ssam_request_spec_md)spec; \
|
|
|
|
struct ssam_request rqst; \
|
|
|
|
\
|
|
|
|
rqst.target_category = s.target_category; \
|
|
|
|
rqst.target_id = tid; \
|
|
|
|
rqst.command_id = s.command_id; \
|
|
|
|
rqst.instance_id = iid; \
|
|
|
|
rqst.flags = s.flags; \
|
|
|
|
rqst.length = sizeof(atype); \
|
|
|
|
rqst.payload = (u8 *)arg; \
|
|
|
|
\
|
|
|
|
return ssam_request_sync_onstack(ctrl, &rqst, NULL, \
|
|
|
|
sizeof(atype)); \
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* SSAM_DEFINE_SYNC_REQUEST_MD_R() - Define synchronous multi-device SAM
|
|
|
|
* request function with return value.
|
|
|
|
* @name: Name of the generated function.
|
|
|
|
* @rtype: Type of the request's return value.
|
|
|
|
* @spec: Specification (&struct ssam_request_spec_md) defining the request.
|
|
|
|
*
|
|
|
|
* Defines a function executing the synchronous SAM request specified by
|
|
|
|
* @spec, with the request taking no argument but having a return value of
|
|
|
|
* type @rtype. Device specifying parameters are not hard-coded, but instead
|
|
|
|
* must be provided to the function. The generated function takes care of
|
|
|
|
* setting up the request and response structs, buffer allocation, as well as
|
|
|
|
* execution of the request itself, returning once the request has been fully
|
|
|
|
* completed. The required transport buffer will be allocated on the stack.
|
|
|
|
*
|
platform/surface: aggregator: Make SSAM_DEFINE_SYNC_REQUEST_x define static functions
The SSAM_DEFINE_SYNC_REQUEST_x() macros are intended to reduce
boiler-plate code for SSAM request definitions by defining a wrapper
function for the specified request. The client device variants of those
macros, i.e. SSAM_DEFINE_SYNC_REQUEST_CL_x() in particular rely on the
multi-device (MD) variants, e.g.:
#define SSAM_DEFINE_SYNC_REQUEST_CL_R(name, rtype, spec...) \
SSAM_DEFINE_SYNC_REQUEST_MD_R(__raw_##name, rtype, spec) \
int name(struct ssam_device *sdev, rtype *ret) \
{ \
return __raw_##name(sdev->ctrl, sdev->uid.target, \
sdev->uid.instance, ret); \
}
This now creates the problem that it is not possible to declare the
generated functions static via
static SSAM_DEFINE_SYNC_REQUEST_CL_R(...)
as this will only apply to the function defined by the multi-device
macro, i.e. SSAM_DEFINE_SYNC_REQUEST_MD_R(). Thus compiling with
`-Wmissing-prototypes' rightfully complains that there is a 'static'
keyword missing.
To solve this, make all SSAM_DEFINE_SYNC_REQUEST_x() macros define
static functions. Non-client-device macros are also changed for
consistency. In general, we expect those functions to be only used
locally in the respective drivers for the corresponding interfaces, so
having to define a wrapper function to be able to export this should be
the odd case out.
Reported-by: kernel test robot <lkp@intel.com>
Fixes: b78b4982d763 ("platform/surface: Add platform profile driver")
Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
Link: https://lore.kernel.org/r/20210304190524.1172197-1-luzmaximilian@gmail.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2021-03-05 03:05:24 +08:00
|
|
|
* The generated function is defined as ``static int name(struct
|
|
|
|
* ssam_controller *ctrl, u8 tid, u8 iid, rtype *ret)``, returning the status
|
|
|
|
* of the request, which is zero on success and negative on failure. The
|
|
|
|
* ``ctrl`` parameter is the controller via which the request is sent, ``tid``
|
|
|
|
* the target ID for the request, and ``iid`` the instance ID. The request's
|
|
|
|
* return value is written to the memory pointed to by the ``ret`` parameter.
|
platform/surface: Add Surface Aggregator subsystem
Add Surface System Aggregator Module core and Surface Serial Hub driver,
required for the embedded controller found on Microsoft Surface devices.
The Surface System Aggregator Module (SSAM, SAM or Surface Aggregator)
is an embedded controller (EC) found on 4th and later generation
Microsoft Surface devices, with the exception of the Surface Go series.
This EC provides various functionality, depending on the device in
question. This can include battery status and thermal reporting (5th and
later generations), but also HID keyboard (6th+) and touchpad input
(7th+) on Surface Laptop and Surface Book 3 series devices.
This patch provides the basic necessities for communication with the SAM
EC on 5th and later generation devices. On these devices, the EC
provides an interface that acts as serial device, called the Surface
Serial Hub (SSH). 4th generation devices, on which the EC interface is
provided via an HID-over-I2C device, are not supported by this patch.
Specifically, this patch adds a driver for the SSH device (device HID
MSHW0084 in ACPI), as well as a controller structure and associated API.
This represents the functional core of the Surface Aggregator kernel
subsystem, introduced with this patch, and will be expanded upon in
subsequent commits.
The SSH driver acts as the main attachment point for this subsystem and
sets-up and manages the controller structure. The controller in turn
provides a basic communication interface, allowing to send requests from
host to EC and receiving the corresponding responses, as well as
managing and receiving events, sent from EC to host. It is structured
into multiple layers, with the top layer presenting the API used by
other kernel drivers and the lower layers modeled after the serial
protocol used for communication.
Said other drivers are then responsible for providing the (Surface model
specific) functionality accessible through the EC (e.g. battery status
reporting, thermal information, ...) via said controller structure and
API, and will be added in future commits.
Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
Link: https://lore.kernel.org/r/20201221183959.1186143-2-luzmaximilian@gmail.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2020-12-22 02:39:51 +08:00
|
|
|
*
|
|
|
|
* Refer to ssam_request_sync_onstack() for more details on the behavior of
|
|
|
|
* the generated function.
|
|
|
|
*/
|
|
|
|
#define SSAM_DEFINE_SYNC_REQUEST_MD_R(name, rtype, spec...) \
|
platform/surface: aggregator: Make SSAM_DEFINE_SYNC_REQUEST_x define static functions
The SSAM_DEFINE_SYNC_REQUEST_x() macros are intended to reduce
boiler-plate code for SSAM request definitions by defining a wrapper
function for the specified request. The client device variants of those
macros, i.e. SSAM_DEFINE_SYNC_REQUEST_CL_x() in particular rely on the
multi-device (MD) variants, e.g.:
#define SSAM_DEFINE_SYNC_REQUEST_CL_R(name, rtype, spec...) \
SSAM_DEFINE_SYNC_REQUEST_MD_R(__raw_##name, rtype, spec) \
int name(struct ssam_device *sdev, rtype *ret) \
{ \
return __raw_##name(sdev->ctrl, sdev->uid.target, \
sdev->uid.instance, ret); \
}
This now creates the problem that it is not possible to declare the
generated functions static via
static SSAM_DEFINE_SYNC_REQUEST_CL_R(...)
as this will only apply to the function defined by the multi-device
macro, i.e. SSAM_DEFINE_SYNC_REQUEST_MD_R(). Thus compiling with
`-Wmissing-prototypes' rightfully complains that there is a 'static'
keyword missing.
To solve this, make all SSAM_DEFINE_SYNC_REQUEST_x() macros define
static functions. Non-client-device macros are also changed for
consistency. In general, we expect those functions to be only used
locally in the respective drivers for the corresponding interfaces, so
having to define a wrapper function to be able to export this should be
the odd case out.
Reported-by: kernel test robot <lkp@intel.com>
Fixes: b78b4982d763 ("platform/surface: Add platform profile driver")
Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
Link: https://lore.kernel.org/r/20210304190524.1172197-1-luzmaximilian@gmail.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2021-03-05 03:05:24 +08:00
|
|
|
static int name(struct ssam_controller *ctrl, u8 tid, u8 iid, rtype *ret) \
|
platform/surface: Add Surface Aggregator subsystem
Add Surface System Aggregator Module core and Surface Serial Hub driver,
required for the embedded controller found on Microsoft Surface devices.
The Surface System Aggregator Module (SSAM, SAM or Surface Aggregator)
is an embedded controller (EC) found on 4th and later generation
Microsoft Surface devices, with the exception of the Surface Go series.
This EC provides various functionality, depending on the device in
question. This can include battery status and thermal reporting (5th and
later generations), but also HID keyboard (6th+) and touchpad input
(7th+) on Surface Laptop and Surface Book 3 series devices.
This patch provides the basic necessities for communication with the SAM
EC on 5th and later generation devices. On these devices, the EC
provides an interface that acts as serial device, called the Surface
Serial Hub (SSH). 4th generation devices, on which the EC interface is
provided via an HID-over-I2C device, are not supported by this patch.
Specifically, this patch adds a driver for the SSH device (device HID
MSHW0084 in ACPI), as well as a controller structure and associated API.
This represents the functional core of the Surface Aggregator kernel
subsystem, introduced with this patch, and will be expanded upon in
subsequent commits.
The SSH driver acts as the main attachment point for this subsystem and
sets-up and manages the controller structure. The controller in turn
provides a basic communication interface, allowing to send requests from
host to EC and receiving the corresponding responses, as well as
managing and receiving events, sent from EC to host. It is structured
into multiple layers, with the top layer presenting the API used by
other kernel drivers and the lower layers modeled after the serial
protocol used for communication.
Said other drivers are then responsible for providing the (Surface model
specific) functionality accessible through the EC (e.g. battery status
reporting, thermal information, ...) via said controller structure and
API, and will be added in future commits.
Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
Link: https://lore.kernel.org/r/20201221183959.1186143-2-luzmaximilian@gmail.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2020-12-22 02:39:51 +08:00
|
|
|
{ \
|
|
|
|
struct ssam_request_spec_md s = (struct ssam_request_spec_md)spec; \
|
|
|
|
struct ssam_request rqst; \
|
|
|
|
struct ssam_response rsp; \
|
|
|
|
int status; \
|
|
|
|
\
|
|
|
|
rqst.target_category = s.target_category; \
|
|
|
|
rqst.target_id = tid; \
|
|
|
|
rqst.command_id = s.command_id; \
|
|
|
|
rqst.instance_id = iid; \
|
|
|
|
rqst.flags = s.flags | SSAM_REQUEST_HAS_RESPONSE; \
|
|
|
|
rqst.length = 0; \
|
|
|
|
rqst.payload = NULL; \
|
|
|
|
\
|
|
|
|
rsp.capacity = sizeof(rtype); \
|
|
|
|
rsp.length = 0; \
|
|
|
|
rsp.pointer = (u8 *)ret; \
|
|
|
|
\
|
|
|
|
status = ssam_request_sync_onstack(ctrl, &rqst, &rsp, 0); \
|
|
|
|
if (status) \
|
|
|
|
return status; \
|
|
|
|
\
|
|
|
|
if (rsp.length != sizeof(rtype)) { \
|
|
|
|
struct device *dev = ssam_controller_device(ctrl); \
|
|
|
|
dev_err(dev, \
|
|
|
|
"rqst: invalid response length, expected %zu, got %zu (tc: %#04x, cid: %#04x)", \
|
|
|
|
sizeof(rtype), rsp.length, rqst.target_category,\
|
|
|
|
rqst.command_id); \
|
|
|
|
return -EIO; \
|
|
|
|
} \
|
|
|
|
\
|
|
|
|
return 0; \
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* -- Event notifier/callbacks. --------------------------------------------- */
|
|
|
|
|
|
|
|
#define SSAM_NOTIF_STATE_SHIFT 2
|
|
|
|
#define SSAM_NOTIF_STATE_MASK ((1 << SSAM_NOTIF_STATE_SHIFT) - 1)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* enum ssam_notif_flags - Flags used in return values from SSAM notifier
|
|
|
|
* callback functions.
|
|
|
|
*
|
|
|
|
* @SSAM_NOTIF_HANDLED:
|
|
|
|
* Indicates that the notification has been handled. This flag should be
|
|
|
|
* set by the handler if the handler can act/has acted upon the event
|
|
|
|
* provided to it. This flag should not be set if the handler is not a
|
|
|
|
* primary handler intended for the provided event.
|
|
|
|
*
|
|
|
|
* If this flag has not been set by any handler after the notifier chain
|
|
|
|
* has been traversed, a warning will be emitted, stating that the event
|
|
|
|
* has not been handled.
|
|
|
|
*
|
|
|
|
* @SSAM_NOTIF_STOP:
|
|
|
|
* Indicates that the notifier traversal should stop. If this flag is
|
|
|
|
* returned from a notifier callback, notifier chain traversal will
|
|
|
|
* immediately stop and any remaining notifiers will not be called. This
|
|
|
|
* flag is automatically set when ssam_notifier_from_errno() is called
|
|
|
|
* with a negative error value.
|
|
|
|
*/
|
|
|
|
enum ssam_notif_flags {
|
|
|
|
SSAM_NOTIF_HANDLED = BIT(0),
|
|
|
|
SSAM_NOTIF_STOP = BIT(1),
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ssam_event_notifier;
|
|
|
|
|
|
|
|
typedef u32 (*ssam_notifier_fn_t)(struct ssam_event_notifier *nf,
|
|
|
|
const struct ssam_event *event);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* struct ssam_notifier_block - Base notifier block for SSAM event
|
|
|
|
* notifications.
|
|
|
|
* @node: The node for the list of notifiers.
|
|
|
|
* @fn: The callback function of this notifier. This function takes the
|
|
|
|
* respective notifier block and event as input and should return
|
|
|
|
* a notifier value, which can either be obtained from the flags
|
|
|
|
* provided in &enum ssam_notif_flags, converted from a standard
|
|
|
|
* error value via ssam_notifier_from_errno(), or a combination of
|
|
|
|
* both (e.g. ``ssam_notifier_from_errno(e) | SSAM_NOTIF_HANDLED``).
|
|
|
|
* @priority: Priority value determining the order in which notifier callbacks
|
|
|
|
* will be called. A higher value means higher priority, i.e. the
|
|
|
|
* associated callback will be executed earlier than other (lower
|
|
|
|
* priority) callbacks.
|
|
|
|
*/
|
|
|
|
struct ssam_notifier_block {
|
|
|
|
struct list_head node;
|
|
|
|
ssam_notifier_fn_t fn;
|
|
|
|
int priority;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* ssam_notifier_from_errno() - Convert standard error value to notifier
|
|
|
|
* return code.
|
|
|
|
* @err: The error code to convert, must be negative (in case of failure) or
|
|
|
|
* zero (in case of success).
|
|
|
|
*
|
|
|
|
* Return: Returns the notifier return value obtained by converting the
|
|
|
|
* specified @err value. In case @err is negative, the %SSAM_NOTIF_STOP flag
|
|
|
|
* will be set, causing notifier call chain traversal to abort.
|
|
|
|
*/
|
|
|
|
static inline u32 ssam_notifier_from_errno(int err)
|
|
|
|
{
|
|
|
|
if (WARN_ON(err > 0) || err == 0)
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
return ((-err) << SSAM_NOTIF_STATE_SHIFT) | SSAM_NOTIF_STOP;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* ssam_notifier_to_errno() - Convert notifier return code to standard error
|
|
|
|
* value.
|
|
|
|
* @ret: The notifier return value to convert.
|
|
|
|
*
|
|
|
|
* Return: Returns the negative error value encoded in @ret or zero if @ret
|
|
|
|
* indicates success.
|
|
|
|
*/
|
|
|
|
static inline int ssam_notifier_to_errno(u32 ret)
|
|
|
|
{
|
|
|
|
return -(ret >> SSAM_NOTIF_STATE_SHIFT);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* -- Event/notification registry. ------------------------------------------ */
|
|
|
|
|
|
|
|
/**
|
|
|
|
* struct ssam_event_registry - Registry specification used for enabling events.
|
|
|
|
* @target_category: Target category for the event registry requests.
|
|
|
|
* @target_id: Target ID for the event registry requests.
|
|
|
|
* @cid_enable: Command ID for the event-enable request.
|
|
|
|
* @cid_disable: Command ID for the event-disable request.
|
|
|
|
*
|
|
|
|
* This struct describes a SAM event registry via the minimal collection of
|
|
|
|
* SAM IDs specifying the requests to use for enabling and disabling an event.
|
|
|
|
* The individual event to be enabled/disabled itself is specified via &struct
|
|
|
|
* ssam_event_id.
|
|
|
|
*/
|
|
|
|
struct ssam_event_registry {
|
|
|
|
u8 target_category;
|
|
|
|
u8 target_id;
|
|
|
|
u8 cid_enable;
|
|
|
|
u8 cid_disable;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* struct ssam_event_id - Unique event ID used for enabling events.
|
|
|
|
* @target_category: Target category of the event source.
|
|
|
|
* @instance: Instance ID of the event source.
|
|
|
|
*
|
|
|
|
* This struct specifies the event to be enabled/disabled via an externally
|
|
|
|
* provided registry. It does not specify the registry to be used itself, this
|
|
|
|
* is done via &struct ssam_event_registry.
|
|
|
|
*/
|
|
|
|
struct ssam_event_id {
|
|
|
|
u8 target_category;
|
|
|
|
u8 instance;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* enum ssam_event_mask - Flags specifying how events are matched to notifiers.
|
|
|
|
*
|
|
|
|
* @SSAM_EVENT_MASK_NONE:
|
|
|
|
* Run the callback for any event with matching target category. Do not
|
|
|
|
* do any additional filtering.
|
|
|
|
*
|
|
|
|
* @SSAM_EVENT_MASK_TARGET:
|
|
|
|
* In addition to filtering by target category, only execute the notifier
|
|
|
|
* callback for events with a target ID matching to the one of the
|
|
|
|
* registry used for enabling/disabling the event.
|
|
|
|
*
|
|
|
|
* @SSAM_EVENT_MASK_INSTANCE:
|
|
|
|
* In addition to filtering by target category, only execute the notifier
|
|
|
|
* callback for events with an instance ID matching to the instance ID
|
|
|
|
* used when enabling the event.
|
|
|
|
*
|
|
|
|
* @SSAM_EVENT_MASK_STRICT:
|
|
|
|
* Do all the filtering above.
|
|
|
|
*/
|
|
|
|
enum ssam_event_mask {
|
|
|
|
SSAM_EVENT_MASK_TARGET = BIT(0),
|
|
|
|
SSAM_EVENT_MASK_INSTANCE = BIT(1),
|
|
|
|
|
|
|
|
SSAM_EVENT_MASK_NONE = 0,
|
|
|
|
SSAM_EVENT_MASK_STRICT =
|
|
|
|
SSAM_EVENT_MASK_TARGET
|
|
|
|
| SSAM_EVENT_MASK_INSTANCE,
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* SSAM_EVENT_REGISTRY() - Define a new event registry.
|
|
|
|
* @tc: Target category for the event registry requests.
|
|
|
|
* @tid: Target ID for the event registry requests.
|
|
|
|
* @cid_en: Command ID for the event-enable request.
|
|
|
|
* @cid_dis: Command ID for the event-disable request.
|
|
|
|
*
|
|
|
|
* Return: Returns the &struct ssam_event_registry specified by the given
|
|
|
|
* parameters.
|
|
|
|
*/
|
|
|
|
#define SSAM_EVENT_REGISTRY(tc, tid, cid_en, cid_dis) \
|
|
|
|
((struct ssam_event_registry) { \
|
|
|
|
.target_category = (tc), \
|
|
|
|
.target_id = (tid), \
|
|
|
|
.cid_enable = (cid_en), \
|
|
|
|
.cid_disable = (cid_dis), \
|
|
|
|
})
|
|
|
|
|
|
|
|
#define SSAM_EVENT_REGISTRY_SAM \
|
|
|
|
SSAM_EVENT_REGISTRY(SSAM_SSH_TC_SAM, 0x01, 0x0b, 0x0c)
|
|
|
|
|
|
|
|
#define SSAM_EVENT_REGISTRY_KIP \
|
|
|
|
SSAM_EVENT_REGISTRY(SSAM_SSH_TC_KIP, 0x02, 0x27, 0x28)
|
|
|
|
|
|
|
|
#define SSAM_EVENT_REGISTRY_REG \
|
|
|
|
SSAM_EVENT_REGISTRY(SSAM_SSH_TC_REG, 0x02, 0x01, 0x02)
|
|
|
|
|
platform/surface: aggregator: Allow registering notifiers without enabling events
Currently, each SSAM event notifier is directly tied to one group of
events. This makes sense as registering a notifier will automatically
take care of enabling the corresponding event group and normally drivers
only need notifications for a very limited number of events, associated
with different callbacks for each group.
However, there are rare cases, especially for debugging, when we want to
get notifications for a whole event target category instead of just a
single group of events in that category. Registering multiple notifiers,
i.e. one per group, may be infeasible due to two issues: a) we might not
know every event enable/disable specification as some events are
auto-enabled by the EC and b) forwarding this to the same callback will
lead to duplicate events as we might not know the full event
specification to perform the appropriate filtering.
This commit introduces observer-notifiers, which are notifiers that are
not tied to a specific event group and do not attempt to manage any
events. In other words, they can be registered without enabling any
event group or incrementing the corresponding reference count and just
act as silent observers, listening to all currently/previously enabled
events based on their match-specification.
Essentially, this allows us to register one single notifier for a full
event target category, meaning that we can process all events of that
target category in a single callback without duplication. Specifically,
this will be used in the cdev debug interface to forward events to
user-space via a device file from which the events can be read.
Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Link: https://lore.kernel.org/r/20210604134755.535590-2-luzmaximilian@gmail.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2021-06-04 21:47:49 +08:00
|
|
|
/**
|
|
|
|
* enum ssam_event_notifier_flags - Flags for event notifiers.
|
|
|
|
* @SSAM_EVENT_NOTIFIER_OBSERVER:
|
|
|
|
* The corresponding notifier acts as observer. Registering a notifier
|
|
|
|
* with this flag set will not attempt to enable any event. Equally,
|
|
|
|
* unregistering will not attempt to disable any event. Note that a
|
|
|
|
* notifier with this flag may not even correspond to a certain event at
|
|
|
|
* all, only to a specific event target category. Event matching will not
|
|
|
|
* be influenced by this flag.
|
|
|
|
*/
|
|
|
|
enum ssam_event_notifier_flags {
|
|
|
|
SSAM_EVENT_NOTIFIER_OBSERVER = BIT(0),
|
|
|
|
};
|
|
|
|
|
platform/surface: Add Surface Aggregator subsystem
Add Surface System Aggregator Module core and Surface Serial Hub driver,
required for the embedded controller found on Microsoft Surface devices.
The Surface System Aggregator Module (SSAM, SAM or Surface Aggregator)
is an embedded controller (EC) found on 4th and later generation
Microsoft Surface devices, with the exception of the Surface Go series.
This EC provides various functionality, depending on the device in
question. This can include battery status and thermal reporting (5th and
later generations), but also HID keyboard (6th+) and touchpad input
(7th+) on Surface Laptop and Surface Book 3 series devices.
This patch provides the basic necessities for communication with the SAM
EC on 5th and later generation devices. On these devices, the EC
provides an interface that acts as serial device, called the Surface
Serial Hub (SSH). 4th generation devices, on which the EC interface is
provided via an HID-over-I2C device, are not supported by this patch.
Specifically, this patch adds a driver for the SSH device (device HID
MSHW0084 in ACPI), as well as a controller structure and associated API.
This represents the functional core of the Surface Aggregator kernel
subsystem, introduced with this patch, and will be expanded upon in
subsequent commits.
The SSH driver acts as the main attachment point for this subsystem and
sets-up and manages the controller structure. The controller in turn
provides a basic communication interface, allowing to send requests from
host to EC and receiving the corresponding responses, as well as
managing and receiving events, sent from EC to host. It is structured
into multiple layers, with the top layer presenting the API used by
other kernel drivers and the lower layers modeled after the serial
protocol used for communication.
Said other drivers are then responsible for providing the (Surface model
specific) functionality accessible through the EC (e.g. battery status
reporting, thermal information, ...) via said controller structure and
API, and will be added in future commits.
Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
Link: https://lore.kernel.org/r/20201221183959.1186143-2-luzmaximilian@gmail.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2020-12-22 02:39:51 +08:00
|
|
|
/**
|
|
|
|
* struct ssam_event_notifier - Notifier block for SSAM events.
|
|
|
|
* @base: The base notifier block with callback function and priority.
|
|
|
|
* @event: The event for which this block will receive notifications.
|
|
|
|
* @event.reg: Registry via which the event will be enabled/disabled.
|
|
|
|
* @event.id: ID specifying the event.
|
|
|
|
* @event.mask: Flags determining how events are matched to the notifier.
|
|
|
|
* @event.flags: Flags used for enabling the event.
|
platform/surface: aggregator: Allow registering notifiers without enabling events
Currently, each SSAM event notifier is directly tied to one group of
events. This makes sense as registering a notifier will automatically
take care of enabling the corresponding event group and normally drivers
only need notifications for a very limited number of events, associated
with different callbacks for each group.
However, there are rare cases, especially for debugging, when we want to
get notifications for a whole event target category instead of just a
single group of events in that category. Registering multiple notifiers,
i.e. one per group, may be infeasible due to two issues: a) we might not
know every event enable/disable specification as some events are
auto-enabled by the EC and b) forwarding this to the same callback will
lead to duplicate events as we might not know the full event
specification to perform the appropriate filtering.
This commit introduces observer-notifiers, which are notifiers that are
not tied to a specific event group and do not attempt to manage any
events. In other words, they can be registered without enabling any
event group or incrementing the corresponding reference count and just
act as silent observers, listening to all currently/previously enabled
events based on their match-specification.
Essentially, this allows us to register one single notifier for a full
event target category, meaning that we can process all events of that
target category in a single callback without duplication. Specifically,
this will be used in the cdev debug interface to forward events to
user-space via a device file from which the events can be read.
Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Link: https://lore.kernel.org/r/20210604134755.535590-2-luzmaximilian@gmail.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2021-06-04 21:47:49 +08:00
|
|
|
* @flags: Notifier flags (see &enum ssam_event_notifier_flags).
|
platform/surface: Add Surface Aggregator subsystem
Add Surface System Aggregator Module core and Surface Serial Hub driver,
required for the embedded controller found on Microsoft Surface devices.
The Surface System Aggregator Module (SSAM, SAM or Surface Aggregator)
is an embedded controller (EC) found on 4th and later generation
Microsoft Surface devices, with the exception of the Surface Go series.
This EC provides various functionality, depending on the device in
question. This can include battery status and thermal reporting (5th and
later generations), but also HID keyboard (6th+) and touchpad input
(7th+) on Surface Laptop and Surface Book 3 series devices.
This patch provides the basic necessities for communication with the SAM
EC on 5th and later generation devices. On these devices, the EC
provides an interface that acts as serial device, called the Surface
Serial Hub (SSH). 4th generation devices, on which the EC interface is
provided via an HID-over-I2C device, are not supported by this patch.
Specifically, this patch adds a driver for the SSH device (device HID
MSHW0084 in ACPI), as well as a controller structure and associated API.
This represents the functional core of the Surface Aggregator kernel
subsystem, introduced with this patch, and will be expanded upon in
subsequent commits.
The SSH driver acts as the main attachment point for this subsystem and
sets-up and manages the controller structure. The controller in turn
provides a basic communication interface, allowing to send requests from
host to EC and receiving the corresponding responses, as well as
managing and receiving events, sent from EC to host. It is structured
into multiple layers, with the top layer presenting the API used by
other kernel drivers and the lower layers modeled after the serial
protocol used for communication.
Said other drivers are then responsible for providing the (Surface model
specific) functionality accessible through the EC (e.g. battery status
reporting, thermal information, ...) via said controller structure and
API, and will be added in future commits.
Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
Link: https://lore.kernel.org/r/20201221183959.1186143-2-luzmaximilian@gmail.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2020-12-22 02:39:51 +08:00
|
|
|
*/
|
|
|
|
struct ssam_event_notifier {
|
|
|
|
struct ssam_notifier_block base;
|
|
|
|
|
|
|
|
struct {
|
|
|
|
struct ssam_event_registry reg;
|
|
|
|
struct ssam_event_id id;
|
|
|
|
enum ssam_event_mask mask;
|
|
|
|
u8 flags;
|
|
|
|
} event;
|
platform/surface: aggregator: Allow registering notifiers without enabling events
Currently, each SSAM event notifier is directly tied to one group of
events. This makes sense as registering a notifier will automatically
take care of enabling the corresponding event group and normally drivers
only need notifications for a very limited number of events, associated
with different callbacks for each group.
However, there are rare cases, especially for debugging, when we want to
get notifications for a whole event target category instead of just a
single group of events in that category. Registering multiple notifiers,
i.e. one per group, may be infeasible due to two issues: a) we might not
know every event enable/disable specification as some events are
auto-enabled by the EC and b) forwarding this to the same callback will
lead to duplicate events as we might not know the full event
specification to perform the appropriate filtering.
This commit introduces observer-notifiers, which are notifiers that are
not tied to a specific event group and do not attempt to manage any
events. In other words, they can be registered without enabling any
event group or incrementing the corresponding reference count and just
act as silent observers, listening to all currently/previously enabled
events based on their match-specification.
Essentially, this allows us to register one single notifier for a full
event target category, meaning that we can process all events of that
target category in a single callback without duplication. Specifically,
this will be used in the cdev debug interface to forward events to
user-space via a device file from which the events can be read.
Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Link: https://lore.kernel.org/r/20210604134755.535590-2-luzmaximilian@gmail.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2021-06-04 21:47:49 +08:00
|
|
|
|
|
|
|
unsigned long flags;
|
platform/surface: Add Surface Aggregator subsystem
Add Surface System Aggregator Module core and Surface Serial Hub driver,
required for the embedded controller found on Microsoft Surface devices.
The Surface System Aggregator Module (SSAM, SAM or Surface Aggregator)
is an embedded controller (EC) found on 4th and later generation
Microsoft Surface devices, with the exception of the Surface Go series.
This EC provides various functionality, depending on the device in
question. This can include battery status and thermal reporting (5th and
later generations), but also HID keyboard (6th+) and touchpad input
(7th+) on Surface Laptop and Surface Book 3 series devices.
This patch provides the basic necessities for communication with the SAM
EC on 5th and later generation devices. On these devices, the EC
provides an interface that acts as serial device, called the Surface
Serial Hub (SSH). 4th generation devices, on which the EC interface is
provided via an HID-over-I2C device, are not supported by this patch.
Specifically, this patch adds a driver for the SSH device (device HID
MSHW0084 in ACPI), as well as a controller structure and associated API.
This represents the functional core of the Surface Aggregator kernel
subsystem, introduced with this patch, and will be expanded upon in
subsequent commits.
The SSH driver acts as the main attachment point for this subsystem and
sets-up and manages the controller structure. The controller in turn
provides a basic communication interface, allowing to send requests from
host to EC and receiving the corresponding responses, as well as
managing and receiving events, sent from EC to host. It is structured
into multiple layers, with the top layer presenting the API used by
other kernel drivers and the lower layers modeled after the serial
protocol used for communication.
Said other drivers are then responsible for providing the (Surface model
specific) functionality accessible through the EC (e.g. battery status
reporting, thermal information, ...) via said controller structure and
API, and will be added in future commits.
Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
Link: https://lore.kernel.org/r/20201221183959.1186143-2-luzmaximilian@gmail.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2020-12-22 02:39:51 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
int ssam_notifier_register(struct ssam_controller *ctrl,
|
|
|
|
struct ssam_event_notifier *n);
|
|
|
|
|
|
|
|
int ssam_notifier_unregister(struct ssam_controller *ctrl,
|
|
|
|
struct ssam_event_notifier *n);
|
|
|
|
|
platform/surface: aggregator: Allow enabling of events without notifiers
We can already enable and disable SAM events via one of two ways: either
via a (non-observer) notifier tied to a specific event group, or a
generic event enable/disable request. In some instances, however,
neither method may be desirable.
The first method will tie the event enable request to a specific
notifier, however, when we want to receive notifications for multiple
event groups of the same target category and forward this to the same
notifier callback, we may receive duplicate events, i.e. one event per
registered notifier. The second method will bypass the internal
reference counting mechanism, meaning that a disable request will
disable the event regardless of any other client driver using it, which
may break the functionality of that driver.
To address this problem, add new functions that allow enabling and
disabling of events via the event reference counting mechanism built
into the controller, without needing to register a notifier.
This can then be used in combination with observer notifiers to process
multiple events of the same target category without duplication in the
same callback function.
Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
Link: https://lore.kernel.org/r/20210604134755.535590-3-luzmaximilian@gmail.com
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2021-06-04 21:47:50 +08:00
|
|
|
int ssam_controller_event_enable(struct ssam_controller *ctrl,
|
|
|
|
struct ssam_event_registry reg,
|
|
|
|
struct ssam_event_id id, u8 flags);
|
|
|
|
|
|
|
|
int ssam_controller_event_disable(struct ssam_controller *ctrl,
|
|
|
|
struct ssam_event_registry reg,
|
|
|
|
struct ssam_event_id id, u8 flags);
|
|
|
|
|
platform/surface: Add Surface Aggregator subsystem
Add Surface System Aggregator Module core and Surface Serial Hub driver,
required for the embedded controller found on Microsoft Surface devices.
The Surface System Aggregator Module (SSAM, SAM or Surface Aggregator)
is an embedded controller (EC) found on 4th and later generation
Microsoft Surface devices, with the exception of the Surface Go series.
This EC provides various functionality, depending on the device in
question. This can include battery status and thermal reporting (5th and
later generations), but also HID keyboard (6th+) and touchpad input
(7th+) on Surface Laptop and Surface Book 3 series devices.
This patch provides the basic necessities for communication with the SAM
EC on 5th and later generation devices. On these devices, the EC
provides an interface that acts as serial device, called the Surface
Serial Hub (SSH). 4th generation devices, on which the EC interface is
provided via an HID-over-I2C device, are not supported by this patch.
Specifically, this patch adds a driver for the SSH device (device HID
MSHW0084 in ACPI), as well as a controller structure and associated API.
This represents the functional core of the Surface Aggregator kernel
subsystem, introduced with this patch, and will be expanded upon in
subsequent commits.
The SSH driver acts as the main attachment point for this subsystem and
sets-up and manages the controller structure. The controller in turn
provides a basic communication interface, allowing to send requests from
host to EC and receiving the corresponding responses, as well as
managing and receiving events, sent from EC to host. It is structured
into multiple layers, with the top layer presenting the API used by
other kernel drivers and the lower layers modeled after the serial
protocol used for communication.
Said other drivers are then responsible for providing the (Surface model
specific) functionality accessible through the EC (e.g. battery status
reporting, thermal information, ...) via said controller structure and
API, and will be added in future commits.
Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
Link: https://lore.kernel.org/r/20201221183959.1186143-2-luzmaximilian@gmail.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2020-12-22 02:39:51 +08:00
|
|
|
#endif /* _LINUX_SURFACE_AGGREGATOR_CONTROLLER_H */
|