From 2f7d7ea44adbe7497b225bbb7bfc29e3c792094d Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Tue, 19 Mar 2024 09:30:15 +0100 Subject: ACPI: NHLT: Reintroduce types the table consists of ACPICA commit 32260f5ce519e854546ce907fc0cc449e1fe51fe Non HDAudio Link Table (NHLT) is designed to separate hardware-related description (registers) from AudioDSP firmware-related one i.e.: pipelines and modules that together make up the audio stream on Intel DSPs. This task is important as same set of hardware registers can be used with different topologies and vice versa, same topology could be utilized with different set of hardware. As the hardware registers description is directly tied to specific platform, intention is to have such description part of low-level firmware e.g.: BIOS. The initial design has been provided in early Sky Lake (SKL) days. The audio architecture goes by the name cAVS. SKL is a representative of cAVS 1.5. The table helps describe endpoint capabilities ever since. While Raptor Lake (RPL) is the last of cAVS architecture - cAVS 2.5 to be precise - its successor, the ACE architecture which begun with Meteor Lake (MTL) inherited the design for all I2S and PDM configurations. These two configurations are the primary targets for NHLT table. Due to naming conflicts with existing code, several structs are named 'nhlt2' rather than 'nhlt'. Follow up changes clean this up once existing code has no users and is removed. Link: https://github.com/acpica/acpica/pull/912 Signed-off-by: Cezary Rojewski Signed-off-by: Rafael J. Wysocki --- include/acpi/actbl2.h | 189 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 189 insertions(+) diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h index 9775384d61c6..8030a1743100 100644 --- a/include/acpi/actbl2.h +++ b/include/acpi/actbl2.h @@ -2141,6 +2141,195 @@ struct acpi_nhlt_device_info { u8 device_port_id; }; +/******************************************************************************* + * + * NHLT - Non HDAudio Link Table + * Version 1 + * + ******************************************************************************/ + +struct acpi_table_nhlt2 { + struct acpi_table_header header; /* Common ACPI table header */ + u8 endpoints_count; + /* + * struct acpi_nhlt_endpoint endpoints[]; + * struct acpi_nhlt_config oed_config; + */ +}; + +struct acpi_nhlt2_endpoint { + u32 length; + u8 link_type; + u8 instance_id; + u16 vendor_id; + u16 device_id; + u16 revision_id; + u32 subsystem_id; + u8 device_type; + u8 direction; + u8 virtual_bus_id; + /* + * struct acpi_nhlt_config device_config; + * struct acpi_nhlt_formats_config formats_config; + * struct acpi_nhlt_devices_info devices_info; + */ +}; + +/* + * Values for link_type field above + * + * Only types PDM and SSP are used + */ +#define ACPI_NHLT_LINKTYPE_HDA 0 +#define ACPI_NHLT_LINKTYPE_DSP 1 +#define ACPI_NHLT_LINKTYPE_PDM 2 +#define ACPI_NHLT_LINKTYPE_SSP 3 +#define ACPI_NHLT_LINKTYPE_SLIMBUS 4 +#define ACPI_NHLT_LINKTYPE_SDW 5 +#define ACPI_NHLT_LINKTYPE_UAOL 6 + +/* Values for device_id field above */ + +#define ACPI_NHLT_DEVICEID_DMIC 0xAE20 +#define ACPI_NHLT_DEVICEID_BT 0xAE30 +#define ACPI_NHLT_DEVICEID_I2S 0xAE34 + +/* Values for device_type field above */ + +/* + * Device types unique to endpoint of link_type=PDM + * + * Type PDM used for all SKL+ platforms + */ +#define ACPI_NHLT_DEVICETYPE_PDM 0 +#define ACPI_NHLT_DEVICETYPE_PDM_SKL 1 +/* Device types unique to endpoint of link_type=SSP */ +#define ACPI_NHLT_DEVICETYPE_BT 0 +#define ACPI_NHLT_DEVICETYPE_FM 1 +#define ACPI_NHLT_DEVICETYPE_MODEM 2 +#define ACPI_NHLT_DEVICETYPE_CODEC 4 + +/* Values for Direction field above */ + +#define ACPI_NHLT_DIR_RENDER 0 +#define ACPI_NHLT_DIR_CAPTURE 1 + +struct acpi_nhlt_config { + u32 capabilities_size; + u8 capabilities[]; +}; + +struct acpi_nhlt_gendevice_config { + u8 virtual_slot; + u8 config_type; +}; + +/* Values for config_type field above */ + +#define ACPI_NHLT_CONFIGTYPE_GENERIC 0 +#define ACPI_NHLT_CONFIGTYPE_MICARRAY 1 + +struct acpi_nhlt_micdevice_config { + u8 virtual_slot; + u8 config_type; + u8 array_type; +}; + +/* Values for array_type field above */ + +#define ACPI_NHLT_ARRAYTYPE_LINEAR2_SMALL 0xA +#define ACPI_NHLT_ARRAYTYPE_LINEAR2_BIG 0xB +#define ACPI_NHLT_ARRAYTYPE_LINEAR4_GEO1 0xC +#define ACPI_NHLT_ARRAYTYPE_PLANAR4_LSHAPED 0xD +#define ACPI_NHLT_ARRAYTYPE_LINEAR4_GEO2 0xE +#define ACPI_NHLT_ARRAYTYPE_VENDOR 0xF + +struct acpi_nhlt2_vendor_mic_config { + u8 type; + u8 panel; + u16 speaker_position_distance; /* mm */ + u16 horizontal_offset; /* mm */ + u16 vertical_offset; /* mm */ + u8 frequency_low_band; /* 5*Hz */ + u8 frequency_high_band; /* 500*Hz */ + u16 direction_angle; /* -180 - +180 */ + u16 elevation_angle; /* -180 - +180 */ + u16 work_vertical_angle_begin; /* -180 - +180 with 2 deg step */ + u16 work_vertical_angle_end; /* -180 - +180 with 2 deg step */ + u16 work_horizontal_angle_begin; /* -180 - +180 with 2 deg step */ + u16 work_horizontal_angle_end; /* -180 - +180 with 2 deg step */ +}; + +/* Values for Type field above */ + +#define ACPI_NHLT_MICTYPE_OMNIDIRECTIONAL 0 +#define ACPI_NHLT_MICTYPE_SUBCARDIOID 1 +#define ACPI_NHLT_MICTYPE_CARDIOID 2 +#define ACPI_NHLT_MICTYPE_SUPERCARDIOID 3 +#define ACPI_NHLT_MICTYPE_HYPERCARDIOID 4 +#define ACPI_NHLT_MICTYPE_8SHAPED 5 +#define ACPI_NHLT_MICTYPE_RESERVED 6 +#define ACPI_NHLT_MICTYPE_VENDORDEFINED 7 + +/* Values for Panel field above */ + +#define ACPI_NHLT_MICLOCATION_TOP 0 +#define ACPI_NHLT_MICLOCATION_BOTTOM 1 +#define ACPI_NHLT_MICLOCATION_LEFT 2 +#define ACPI_NHLT_MICLOCATION_RIGHT 3 +#define ACPI_NHLT_MICLOCATION_FRONT 4 +#define ACPI_NHLT_MICLOCATION_REAR 5 + +struct acpi_nhlt_vendor_micdevice_config { + u8 virtual_slot; + u8 config_type; + u8 array_type; + u8 mics_count; + struct acpi_nhlt2_vendor_mic_config mics[]; +}; + +union acpi_nhlt_device_config { + u8 virtual_slot; + struct acpi_nhlt_gendevice_config gen; + struct acpi_nhlt_micdevice_config mic; + struct acpi_nhlt_vendor_micdevice_config vendor_mic; +}; + +/* Inherited from Microsoft's WAVEFORMATEXTENSIBLE. */ +struct acpi_nhlt2_wave_formatext { + u16 format_tag; + u16 channel_count; + u32 samples_per_sec; + u32 avg_bytes_per_sec; + u16 block_align; + u16 bits_per_sample; + u16 extra_format_size; + u16 valid_bits_per_sample; + u32 channel_mask; + u8 subformat[16]; +}; + +struct acpi_nhlt2_format_config { + struct acpi_nhlt2_wave_formatext format; + struct acpi_nhlt_config config; +}; + +struct acpi_nhlt2_formats_config { + u8 formats_count; + struct acpi_nhlt2_format_config formats[]; +}; + +struct acpi_nhlt2_device_info { + u8 id[16]; + u8 instance_id; + u8 port_id; +}; + +struct acpi_nhlt_devices_info { + u8 devices_count; + struct acpi_nhlt2_device_info devices[]; +}; + /******************************************************************************* * * PCCT - Platform Communications Channel Table (ACPI 5.0) -- cgit v1.2.3 From 82b8acc06ea48b69c2482ac2ac994656c3740d08 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Tue, 19 Mar 2024 09:30:16 +0100 Subject: ACPI: NHLT: Introduce API for the table The table is composed of a range of endpoints with each describing audio formats they support. Most of the operations involve iterating over elements of the table and filtering them. Simplify the process by implementing range of getters. While the acpi_nhlt_endpoint_mic_count() stands out a bit, it is a critical component for any AudioDSP driver to know how many digital microphones it is dealing with. Signed-off-by: Cezary Rojewski Signed-off-by: Rafael J. Wysocki --- drivers/acpi/Kconfig | 3 + drivers/acpi/Makefile | 1 + drivers/acpi/nhlt.c | 289 ++++++++++++++++++++++++++++++++++++++++++++++++++ include/acpi/nhlt.h | 181 +++++++++++++++++++++++++++++++ 4 files changed, 474 insertions(+) create mode 100644 drivers/acpi/nhlt.c create mode 100644 include/acpi/nhlt.h diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index ff1689bb3124..e3a7c2aedd5f 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -469,6 +469,9 @@ config ACPI_REDUCED_HARDWARE_ONLY If you are unsure what to do, do not enable this option. +config ACPI_NHLT + bool + source "drivers/acpi/nfit/Kconfig" source "drivers/acpi/numa/Kconfig" source "drivers/acpi/apei/Kconfig" diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 8cc8c0d9c873..d69d5444acdb 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -93,6 +93,7 @@ obj-$(CONFIG_ACPI_THERMAL_LIB) += thermal_lib.o obj-$(CONFIG_ACPI_THERMAL) += thermal.o obj-$(CONFIG_ACPI_PLATFORM_PROFILE) += platform_profile.o obj-$(CONFIG_ACPI_NFIT) += nfit/ +obj-$(CONFIG_ACPI_NHLT) += nhlt.o obj-$(CONFIG_ACPI_NUMA) += numa/ obj-$(CONFIG_ACPI) += acpi_memhotplug.o obj-$(CONFIG_ACPI_HOTPLUG_IOAPIC) += ioapic.o diff --git a/drivers/acpi/nhlt.c b/drivers/acpi/nhlt.c new file mode 100644 index 000000000000..ab722a95cbb5 --- /dev/null +++ b/drivers/acpi/nhlt.c @@ -0,0 +1,289 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright(c) 2023-2024 Intel Corporation + * + * Authors: Cezary Rojewski + * Amadeusz Slawinski + */ + +#define pr_fmt(fmt) "ACPI: NHLT: " fmt + +#include +#include +#include +#include +#include +#include +#include + +static struct acpi_table_nhlt2 *acpi_gbl_nhlt; + +static struct acpi_table_nhlt2 empty_nhlt = { + .header = { + .signature = ACPI_SIG_NHLT, + }, +}; + +/** + * acpi_nhlt_get_gbl_table - Retrieve a pointer to the first NHLT table. + * + * If there is no NHLT in the system, acpi_gbl_nhlt will instead point to an + * empty table. + * + * Return: ACPI status code of the operation. + */ +acpi_status acpi_nhlt_get_gbl_table(void) +{ + acpi_status status; + + status = acpi_get_table(ACPI_SIG_NHLT, 0, (struct acpi_table_header **)(&acpi_gbl_nhlt)); + if (!acpi_gbl_nhlt) + acpi_gbl_nhlt = &empty_nhlt; + return status; +} +EXPORT_SYMBOL_GPL(acpi_nhlt_get_gbl_table); + +/** + * acpi_nhlt_put_gbl_table - Release the global NHLT table. + */ +void acpi_nhlt_put_gbl_table(void) +{ + acpi_put_table((struct acpi_table_header *)acpi_gbl_nhlt); +} +EXPORT_SYMBOL_GPL(acpi_nhlt_put_gbl_table); + +/** + * acpi_nhlt_endpoint_match - Verify if an endpoint matches criteria. + * @ep: the endpoint to check. + * @link_type: the hardware link type, e.g.: PDM or SSP. + * @dev_type: the device type. + * @dir: stream direction. + * @bus_id: the ID of virtual bus hosting the endpoint. + * + * Either of @link_type, @dev_type, @dir or @bus_id may be set to a negative + * value to ignore the parameter when matching. + * + * Return: %true if endpoint matches specified criteria or %false otherwise. + */ +bool acpi_nhlt_endpoint_match(const struct acpi_nhlt2_endpoint *ep, + int link_type, int dev_type, int dir, int bus_id) +{ + return ep && + (link_type < 0 || ep->link_type == link_type) && + (dev_type < 0 || ep->device_type == dev_type) && + (bus_id < 0 || ep->virtual_bus_id == bus_id) && + (dir < 0 || ep->direction == dir); +} +EXPORT_SYMBOL_GPL(acpi_nhlt_endpoint_match); + +/** + * acpi_nhlt_tb_find_endpoint - Search a NHLT table for an endpoint. + * @tb: the table to search. + * @link_type: the hardware link type, e.g.: PDM or SSP. + * @dev_type: the device type. + * @dir: stream direction. + * @bus_id: the ID of virtual bus hosting the endpoint. + * + * Either of @link_type, @dev_type, @dir or @bus_id may be set to a negative + * value to ignore the parameter during the search. + * + * Return: A pointer to endpoint matching the criteria, %NULL if not found or + * an ERR_PTR() otherwise. + */ +struct acpi_nhlt2_endpoint * +acpi_nhlt_tb_find_endpoint(const struct acpi_table_nhlt2 *tb, + int link_type, int dev_type, int dir, int bus_id) +{ + struct acpi_nhlt2_endpoint *ep; + + for_each_nhlt_endpoint(tb, ep) + if (acpi_nhlt_endpoint_match(ep, link_type, dev_type, dir, bus_id)) + return ep; + return NULL; +} +EXPORT_SYMBOL_GPL(acpi_nhlt_tb_find_endpoint); + +/** + * acpi_nhlt_find_endpoint - Search all NHLT tables for an endpoint. + * @link_type: the hardware link type, e.g.: PDM or SSP. + * @dev_type: the device type. + * @dir: stream direction. + * @bus_id: the ID of virtual bus hosting the endpoint. + * + * Either of @link_type, @dev_type, @dir or @bus_id may be set to a negative + * value to ignore the parameter during the search. + * + * Return: A pointer to endpoint matching the criteria, %NULL if not found or + * an ERR_PTR() otherwise. + */ +struct acpi_nhlt2_endpoint * +acpi_nhlt_find_endpoint(int link_type, int dev_type, int dir, int bus_id) +{ + /* TODO: Currently limited to table of index 0. */ + return acpi_nhlt_tb_find_endpoint(acpi_gbl_nhlt, link_type, dev_type, dir, bus_id); +} +EXPORT_SYMBOL_GPL(acpi_nhlt_find_endpoint); + +/** + * acpi_nhlt_endpoint_find_fmtcfg - Search endpoint's formats configuration space + * for a specific format. + * @ep: the endpoint to search. + * @ch: number of channels. + * @rate: samples per second. + * @vbps: valid bits per sample. + * @bps: bits per sample. + * + * Return: A pointer to format matching the criteria, %NULL if not found or + * an ERR_PTR() otherwise. + */ +struct acpi_nhlt2_format_config * +acpi_nhlt_endpoint_find_fmtcfg(const struct acpi_nhlt2_endpoint *ep, + u16 ch, u32 rate, u16 vbps, u16 bps) +{ + struct acpi_nhlt2_wave_formatext *wav; + struct acpi_nhlt2_format_config *fmt; + + for_each_nhlt_endpoint_fmtcfg(ep, fmt) { + wav = &fmt->format; + + if (wav->valid_bits_per_sample == vbps && + wav->samples_per_sec == rate && + wav->bits_per_sample == bps && + wav->channel_count == ch) + return fmt; + } + + return NULL; +} +EXPORT_SYMBOL_GPL(acpi_nhlt_endpoint_find_fmtcfg); + +/** + * acpi_nhlt_tb_find_fmtcfg - Search a NHLT table for a specific format. + * @tb: the table to search. + * @link_type: the hardware link type, e.g.: PDM or SSP. + * @dev_type: the device type. + * @dir: stream direction. + * @bus_id: the ID of virtual bus hosting the endpoint. + * + * @ch: number of channels. + * @rate: samples per second. + * @vbps: valid bits per sample. + * @bps: bits per sample. + * + * Either of @link_type, @dev_type, @dir or @bus_id may be set to a negative + * value to ignore the parameter during the search. + * + * Return: A pointer to format matching the criteria, %NULL if not found or + * an ERR_PTR() otherwise. + */ +struct acpi_nhlt2_format_config * +acpi_nhlt_tb_find_fmtcfg(const struct acpi_table_nhlt2 *tb, + int link_type, int dev_type, int dir, int bus_id, + u16 ch, u32 rate, u16 vbps, u16 bps) +{ + struct acpi_nhlt2_format_config *fmt; + struct acpi_nhlt2_endpoint *ep; + + for_each_nhlt_endpoint(tb, ep) { + if (!acpi_nhlt_endpoint_match(ep, link_type, dev_type, dir, bus_id)) + continue; + + fmt = acpi_nhlt_endpoint_find_fmtcfg(ep, ch, rate, vbps, bps); + if (fmt) + return fmt; + } + + return NULL; +} +EXPORT_SYMBOL_GPL(acpi_nhlt_tb_find_fmtcfg); + +/** + * acpi_nhlt_find_fmtcfg - Search all NHLT tables for a specific format. + * @link_type: the hardware link type, e.g.: PDM or SSP. + * @dev_type: the device type. + * @dir: stream direction. + * @bus_id: the ID of virtual bus hosting the endpoint. + * + * @ch: number of channels. + * @rate: samples per second. + * @vbps: valid bits per sample. + * @bps: bits per sample. + * + * Either of @link_type, @dev_type, @dir or @bus_id may be set to a negative + * value to ignore the parameter during the search. + * + * Return: A pointer to format matching the criteria, %NULL if not found or + * an ERR_PTR() otherwise. + */ +struct acpi_nhlt2_format_config * +acpi_nhlt_find_fmtcfg(int link_type, int dev_type, int dir, int bus_id, + u16 ch, u32 rate, u16 vbps, u16 bps) +{ + /* TODO: Currently limited to table of index 0. */ + return acpi_nhlt_tb_find_fmtcfg(acpi_gbl_nhlt, link_type, dev_type, dir, bus_id, + ch, rate, vbps, bps); +} +EXPORT_SYMBOL_GPL(acpi_nhlt_find_fmtcfg); + +static bool acpi_nhlt_config_is_micdevice(struct acpi_nhlt_config *cfg) +{ + return cfg->capabilities_size >= sizeof(struct acpi_nhlt_micdevice_config); +} + +static bool acpi_nhlt_config_is_vendor_micdevice(struct acpi_nhlt_config *cfg) +{ + struct acpi_nhlt_vendor_micdevice_config *devcfg = __acpi_nhlt_config_caps(cfg); + + return cfg->capabilities_size >= sizeof(*devcfg) && + cfg->capabilities_size == struct_size(devcfg, mics, devcfg->mics_count); +} + +/** + * acpi_nhlt_endpoint_mic_count - Retrieve number of digital microphones for a PDM endpoint. + * @ep: the endpoint to return microphones count for. + * + * Return: A number of microphones or an error code if an invalid endpoint is provided. + */ +int acpi_nhlt_endpoint_mic_count(const struct acpi_nhlt2_endpoint *ep) +{ + union acpi_nhlt_device_config *devcfg; + struct acpi_nhlt2_format_config *fmt; + struct acpi_nhlt_config *cfg; + u16 max_ch = 0; + + if (!ep || ep->link_type != ACPI_NHLT_LINKTYPE_PDM) + return -EINVAL; + + /* Find max number of channels based on formats configuration. */ + for_each_nhlt_endpoint_fmtcfg(ep, fmt) + max_ch = max(fmt->format.channel_count, max_ch); + + cfg = __acpi_nhlt_endpoint_config(ep); + devcfg = __acpi_nhlt_config_caps(cfg); + + /* If @ep is not a mic array, fallback to channels count. */ + if (!acpi_nhlt_config_is_micdevice(cfg) || + devcfg->gen.config_type != ACPI_NHLT_CONFIGTYPE_MICARRAY) + return max_ch; + + switch (devcfg->mic.array_type) { + case ACPI_NHLT_ARRAYTYPE_LINEAR2_SMALL: + case ACPI_NHLT_ARRAYTYPE_LINEAR2_BIG: + return 2; + + case ACPI_NHLT_ARRAYTYPE_LINEAR4_GEO1: + case ACPI_NHLT_ARRAYTYPE_PLANAR4_LSHAPED: + case ACPI_NHLT_ARRAYTYPE_LINEAR4_GEO2: + return 4; + + case ACPI_NHLT_ARRAYTYPE_VENDOR: + if (!acpi_nhlt_config_is_vendor_micdevice(cfg)) + return -EINVAL; + return devcfg->vendor_mic.mics_count; + + default: + pr_warn("undefined mic array type: %#x\n", devcfg->mic.array_type); + return max_ch; + } +} +EXPORT_SYMBOL_GPL(acpi_nhlt_endpoint_mic_count); diff --git a/include/acpi/nhlt.h b/include/acpi/nhlt.h new file mode 100644 index 000000000000..7c394e7bc2bb --- /dev/null +++ b/include/acpi/nhlt.h @@ -0,0 +1,181 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright(c) 2023-2024 Intel Corporation + * + * Authors: Cezary Rojewski + * Amadeusz Slawinski + */ + +#ifndef __ACPI_NHLT_H__ +#define __ACPI_NHLT_H__ + +#include +#include +#include +#include + +#define __acpi_nhlt_endpoint_config(ep) ((void *)((ep) + 1)) +#define __acpi_nhlt_config_caps(cfg) ((void *)((cfg) + 1)) + +/** + * acpi_nhlt_endpoint_fmtscfg - Get the formats configuration space. + * @ep: the endpoint to retrieve the space for. + * + * Return: A pointer to the formats configuration space. + */ +static inline struct acpi_nhlt2_formats_config * +acpi_nhlt_endpoint_fmtscfg(const struct acpi_nhlt2_endpoint *ep) +{ + struct acpi_nhlt_config *cfg = __acpi_nhlt_endpoint_config(ep); + + return (struct acpi_nhlt2_formats_config *)((u8 *)(cfg + 1) + cfg->capabilities_size); +} + +#define __acpi_nhlt_first_endpoint(tb) \ + ((void *)(tb + 1)) + +#define __acpi_nhlt_next_endpoint(ep) \ + ((void *)((u8 *)(ep) + (ep)->length)) + +#define __acpi_nhlt_get_endpoint(tb, ep, i) \ + ((i) ? __acpi_nhlt_next_endpoint(ep) : __acpi_nhlt_first_endpoint(tb)) + +#define __acpi_nhlt_first_fmtcfg(fmts) \ + ((void *)(fmts + 1)) + +#define __acpi_nhlt_next_fmtcfg(fmt) \ + ((void *)((u8 *)((fmt) + 1) + (fmt)->config.capabilities_size)) + +#define __acpi_nhlt_get_fmtcfg(fmts, fmt, i) \ + ((i) ? __acpi_nhlt_next_fmtcfg(fmt) : __acpi_nhlt_first_fmtcfg(fmts)) + +/* + * The for_each_nhlt_*() macros rely on an iterator to deal with the + * variable length of each endpoint structure and the possible presence + * of an OED-Config used by Windows only. + */ + +/** + * for_each_nhlt_endpoint - Iterate over endpoints in a NHLT table. + * @tb: the pointer to a NHLT table. + * @ep: the pointer to endpoint to use as loop cursor. + */ +#define for_each_nhlt_endpoint(tb, ep) \ + for (unsigned int __i = 0; \ + __i < (tb)->endpoints_count && \ + (ep = __acpi_nhlt_get_endpoint(tb, ep, __i)); \ + __i++) + +/** + * for_each_nhlt_fmtcfg - Iterate over format configurations. + * @fmts: the pointer to formats configuration space. + * @fmt: the pointer to format to use as loop cursor. + */ +#define for_each_nhlt_fmtcfg(fmts, fmt) \ + for (unsigned int __i = 0; \ + __i < (fmts)->formats_count && \ + (fmt = __acpi_nhlt_get_fmtcfg(fmts, fmt, __i)); \ + __i++) + +/** + * for_each_nhlt_endpoint_fmtcfg - Iterate over format configurations in an endpoint. + * @ep: the pointer to an endpoint. + * @fmt: the pointer to format to use as loop cursor. + */ +#define for_each_nhlt_endpoint_fmtcfg(ep, fmt) \ + for_each_nhlt_fmtcfg(acpi_nhlt_endpoint_fmtscfg(ep), fmt) + +#if IS_ENABLED(CONFIG_ACPI_NHLT) + +/* + * System-wide pointer to the first NHLT table. + * + * A sound driver may utilize acpi_nhlt_get/put_gbl_table() on its + * initialization and removal respectively to avoid excessive mapping + * and unmapping of the memory occupied by the table between streaming + * operations. + */ + +acpi_status acpi_nhlt_get_gbl_table(void); +void acpi_nhlt_put_gbl_table(void); + +bool acpi_nhlt_endpoint_match(const struct acpi_nhlt2_endpoint *ep, + int link_type, int dev_type, int dir, int bus_id); +struct acpi_nhlt2_endpoint * +acpi_nhlt_tb_find_endpoint(const struct acpi_table_nhlt2 *tb, + int link_type, int dev_type, int dir, int bus_id); +struct acpi_nhlt2_endpoint * +acpi_nhlt_find_endpoint(int link_type, int dev_type, int dir, int bus_id); +struct acpi_nhlt2_format_config * +acpi_nhlt_endpoint_find_fmtcfg(const struct acpi_nhlt2_endpoint *ep, + u16 ch, u32 rate, u16 vbps, u16 bps); +struct acpi_nhlt2_format_config * +acpi_nhlt_tb_find_fmtcfg(const struct acpi_table_nhlt2 *tb, + int link_type, int dev_type, int dir, int bus_id, + u16 ch, u32 rate, u16 vpbs, u16 bps); +struct acpi_nhlt2_format_config * +acpi_nhlt_find_fmtcfg(int link_type, int dev_type, int dir, int bus_id, + u16 ch, u32 rate, u16 vpbs, u16 bps); +int acpi_nhlt_endpoint_mic_count(const struct acpi_nhlt2_endpoint *ep); + +#else /* !CONFIG_ACPI_NHLT */ + +static inline acpi_status acpi_nhlt_get_gbl_table(void) +{ + return AE_NOT_FOUND; +} + +static inline void acpi_nhlt_put_gbl_table(void) +{ +} + +static inline bool +acpi_nhlt_endpoint_match(const struct acpi_nhlt2_endpoint *ep, + int link_type, int dev_type, int dir, int bus_id) +{ + return false; +} + +static inline struct acpi_nhlt2_endpoint * +acpi_nhlt_tb_find_endpoint(const struct acpi_table_nhlt2 *tb, + int link_type, int dev_type, int dir, int bus_id) +{ + return NULL; +} + +static inline struct acpi_nhlt2_format_config * +acpi_nhlt_endpoint_find_fmtcfg(const struct acpi_nhlt2_endpoint *ep, + u16 ch, u32 rate, u16 vbps, u16 bps) +{ + return NULL; +} + +static inline struct acpi_nhlt2_format_config * +acpi_nhlt_tb_find_fmtcfg(const struct acpi_table_nhlt2 *tb, + int link_type, int dev_type, int dir, int bus_id, + u16 ch, u32 rate, u16 vpbs, u16 bps) +{ + return NULL; +} + +static inline int acpi_nhlt_endpoint_mic_count(const struct acpi_nhlt2_endpoint *ep) +{ + return 0; +} + +static inline struct acpi_nhlt2_endpoint * +acpi_nhlt_find_endpoint(int link_type, int dev_type, int dir, int bus_id) +{ + return NULL; +} + +static inline struct acpi_nhlt2_format_config * +acpi_nhlt_find_fmtcfg(int link_type, int dev_type, int dir, int bus_id, + u16 ch, u32 rate, u16 vpbs, u16 bps) +{ + return NULL; +} + +#endif /* CONFIG_ACPI_NHLT */ + +#endif /* __ACPI_NHLT_H__ */ -- cgit v1.2.3 From 659a9490ccfbfad4aa5ab351f8a6f5f83ce5ed6c Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Tue, 19 Mar 2024 09:30:17 +0100 Subject: ACPI: NHLT: Drop redundant types ACPICA commit 0c7379eae2a0342bfc36d6b7db0bb90ad13a5a3e There are no users for the duplicated NHLT table components. Link: https://github.com/acpica/acpica/pull/890 Signed-off-by: Cezary Rojewski Signed-off-by: Rafael J. Wysocki --- include/acpi/actbl2.h | 254 -------------------------------------------------- 1 file changed, 254 deletions(-) diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h index 8030a1743100..31a716a74340 100644 --- a/include/acpi/actbl2.h +++ b/include/acpi/actbl2.h @@ -1887,260 +1887,6 @@ struct nfit_device_handle { #define ACPI_NFIT_GET_NODE_ID(handle) \ (((handle) & ACPI_NFIT_NODE_ID_MASK) >> ACPI_NFIT_NODE_ID_OFFSET) -/******************************************************************************* - * - * NHLT - Non HD Audio Link Table - * - * Conforms to: Intel Smart Sound Technology NHLT Specification - * Version 0.8.1, January 2020. - * - ******************************************************************************/ - -/* Main table */ - -struct acpi_table_nhlt { - struct acpi_table_header header; /* Common ACPI table header */ - u8 endpoint_count; -}; - -struct acpi_nhlt_endpoint { - u32 descriptor_length; - u8 link_type; - u8 instance_id; - u16 vendor_id; - u16 device_id; - u16 revision_id; - u32 subsystem_id; - u8 device_type; - u8 direction; - u8 virtual_bus_id; -}; - -/* Types for link_type field above */ - -#define ACPI_NHLT_RESERVED_HD_AUDIO 0 -#define ACPI_NHLT_RESERVED_DSP 1 -#define ACPI_NHLT_PDM 2 -#define ACPI_NHLT_SSP 3 -#define ACPI_NHLT_RESERVED_SLIMBUS 4 -#define ACPI_NHLT_RESERVED_SOUNDWIRE 5 -#define ACPI_NHLT_TYPE_RESERVED 6 /* 6 and above are reserved */ - -/* All other values above are reserved */ - -/* Values for device_id field above */ - -#define ACPI_NHLT_PDM_DMIC 0xAE20 -#define ACPI_NHLT_BT_SIDEBAND 0xAE30 -#define ACPI_NHLT_I2S_TDM_CODECS 0xAE23 - -/* Values for device_type field above */ - -/* SSP Link */ - -#define ACPI_NHLT_LINK_BT_SIDEBAND 0 -#define ACPI_NHLT_LINK_FM 1 -#define ACPI_NHLT_LINK_MODEM 2 -/* 3 is reserved */ -#define ACPI_NHLT_LINK_SSP_ANALOG_CODEC 4 - -/* PDM Link */ - -#define ACPI_NHLT_PDM_ON_CAVS_1P8 0 -#define ACPI_NHLT_PDM_ON_CAVS_1P5 1 - -/* Values for Direction field above */ - -#define ACPI_NHLT_DIR_RENDER 0 -#define ACPI_NHLT_DIR_CAPTURE 1 -#define ACPI_NHLT_DIR_RENDER_LOOPBACK 2 -#define ACPI_NHLT_DIR_RENDER_FEEDBACK 3 -#define ACPI_NHLT_DIR_RESERVED 4 /* 4 and above are reserved */ - -struct acpi_nhlt_device_specific_config { - u32 capabilities_size; - u8 virtual_slot; - u8 config_type; -}; - -struct acpi_nhlt_device_specific_config_a { - u32 capabilities_size; - u8 virtual_slot; - u8 config_type; - u8 array_type; -}; - -/* Values for Config Type above */ - -#define ACPI_NHLT_CONFIG_TYPE_GENERIC 0x00 -#define ACPI_NHLT_CONFIG_TYPE_MIC_ARRAY 0x01 -#define ACPI_NHLT_CONFIG_TYPE_RENDER_FEEDBACK 0x03 -#define ACPI_NHLT_CONFIG_TYPE_RESERVED 0x04 /* 4 and above are reserved */ - -struct acpi_nhlt_device_specific_config_b { - u32 capabilities_size; -}; - -struct acpi_nhlt_device_specific_config_c { - u32 capabilities_size; - u8 virtual_slot; -}; - -struct acpi_nhlt_render_device_specific_config { - u32 capabilities_size; - u8 virtual_slot; -}; - -struct acpi_nhlt_wave_extensible { - u16 format_tag; - u16 channel_count; - u32 samples_per_sec; - u32 avg_bytes_per_sec; - u16 block_align; - u16 bits_per_sample; - u16 extra_format_size; - u16 valid_bits_per_sample; - u32 channel_mask; - u8 sub_format_guid[16]; -}; - -/* Values for channel_mask above */ - -#define ACPI_NHLT_SPKR_FRONT_LEFT 0x1 -#define ACPI_NHLT_SPKR_FRONT_RIGHT 0x2 -#define ACPI_NHLT_SPKR_FRONT_CENTER 0x4 -#define ACPI_NHLT_SPKR_LOW_FREQ 0x8 -#define ACPI_NHLT_SPKR_BACK_LEFT 0x10 -#define ACPI_NHLT_SPKR_BACK_RIGHT 0x20 -#define ACPI_NHLT_SPKR_FRONT_LEFT_OF_CENTER 0x40 -#define ACPI_NHLT_SPKR_FRONT_RIGHT_OF_CENTER 0x80 -#define ACPI_NHLT_SPKR_BACK_CENTER 0x100 -#define ACPI_NHLT_SPKR_SIDE_LEFT 0x200 -#define ACPI_NHLT_SPKR_SIDE_RIGHT 0x400 -#define ACPI_NHLT_SPKR_TOP_CENTER 0x800 -#define ACPI_NHLT_SPKR_TOP_FRONT_LEFT 0x1000 -#define ACPI_NHLT_SPKR_TOP_FRONT_CENTER 0x2000 -#define ACPI_NHLT_SPKR_TOP_FRONT_RIGHT 0x4000 -#define ACPI_NHLT_SPKR_TOP_BACK_LEFT 0x8000 -#define ACPI_NHLT_SPKR_TOP_BACK_CENTER 0x10000 -#define ACPI_NHLT_SPKR_TOP_BACK_RIGHT 0x20000 - -struct acpi_nhlt_format_config { - struct acpi_nhlt_wave_extensible format; - u32 capability_size; - u8 capabilities[]; -}; - -struct acpi_nhlt_formats_config { - u8 formats_count; -}; - -struct acpi_nhlt_device_specific_hdr { - u8 virtual_slot; - u8 config_type; -}; - -/* Types for config_type above */ - -#define ACPI_NHLT_GENERIC 0 -#define ACPI_NHLT_MIC 1 -#define ACPI_NHLT_RENDER 3 - -struct acpi_nhlt_mic_device_specific_config { - struct acpi_nhlt_device_specific_hdr device_config; - u8 array_type_ext; -}; - -/* Values for array_type_ext above */ - -#define ACPI_NHLT_ARRAY_TYPE_RESERVED 0x09 /* 9 and below are reserved */ -#define ACPI_NHLT_SMALL_LINEAR_2ELEMENT 0x0A -#define ACPI_NHLT_BIG_LINEAR_2ELEMENT 0x0B -#define ACPI_NHLT_FIRST_GEOMETRY_LINEAR_4ELEMENT 0x0C -#define ACPI_NHLT_PLANAR_LSHAPED_4ELEMENT 0x0D -#define ACPI_NHLT_SECOND_GEOMETRY_LINEAR_4ELEMENT 0x0E -#define ACPI_NHLT_VENDOR_DEFINED 0x0F -#define ACPI_NHLT_ARRAY_TYPE_MASK 0x0F -#define ACPI_NHLT_ARRAY_TYPE_EXT_MASK 0x10 - -#define ACPI_NHLT_NO_EXTENSION 0x0 -#define ACPI_NHLT_MIC_SNR_SENSITIVITY_EXT (1<<4) - -struct acpi_nhlt_vendor_mic_count { - u8 microphone_count; -}; - -struct acpi_nhlt_vendor_mic_config { - u8 type; - u8 panel; - u16 speaker_position_distance; /* mm */ - u16 horizontal_offset; /* mm */ - u16 vertical_offset; /* mm */ - u8 frequency_low_band; /* 5*Hz */ - u8 frequency_high_band; /* 500*Hz */ - u16 direction_angle; /* -180 - + 180 */ - u16 elevation_angle; /* -180 - + 180 */ - u16 work_vertical_angle_begin; /* -180 - + 180 with 2 deg step */ - u16 work_vertical_angle_end; /* -180 - + 180 with 2 deg step */ - u16 work_horizontal_angle_begin; /* -180 - + 180 with 2 deg step */ - u16 work_horizontal_angle_end; /* -180 - + 180 with 2 deg step */ -}; - -/* Values for Type field above */ - -#define ACPI_NHLT_MIC_OMNIDIRECTIONAL 0 -#define ACPI_NHLT_MIC_SUBCARDIOID 1 -#define ACPI_NHLT_MIC_CARDIOID 2 -#define ACPI_NHLT_MIC_SUPER_CARDIOID 3 -#define ACPI_NHLT_MIC_HYPER_CARDIOID 4 -#define ACPI_NHLT_MIC_8_SHAPED 5 -#define ACPI_NHLT_MIC_RESERVED6 6 /* 6 is reserved */ -#define ACPI_NHLT_MIC_VENDOR_DEFINED 7 -#define ACPI_NHLT_MIC_RESERVED 8 /* 8 and above are reserved */ - -/* Values for Panel field above */ - -#define ACPI_NHLT_MIC_POSITION_TOP 0 -#define ACPI_NHLT_MIC_POSITION_BOTTOM 1 -#define ACPI_NHLT_MIC_POSITION_LEFT 2 -#define ACPI_NHLT_MIC_POSITION_RIGHT 3 -#define ACPI_NHLT_MIC_POSITION_FRONT 4 -#define ACPI_NHLT_MIC_POSITION_BACK 5 -#define ACPI_NHLT_MIC_POSITION_RESERVED 6 /* 6 and above are reserved */ - -struct acpi_nhlt_vendor_mic_device_specific_config { - struct acpi_nhlt_mic_device_specific_config mic_array_device_config; - u8 number_of_microphones; - struct acpi_nhlt_vendor_mic_config mic_config[]; /* Indexed by number_of_microphones */ -}; - -/* Microphone SNR and Sensitivity extension */ - -struct acpi_nhlt_mic_snr_sensitivity_extension { - u32 SNR; - u32 sensitivity; -}; - -/* Render device with feedback */ - -struct acpi_nhlt_render_feedback_device_specific_config { - u8 feedback_virtual_slot; /* Render slot in case of capture */ - u16 feedback_channels; /* Informative only */ - u16 feedback_valid_bits_per_sample; -}; - -/* Non documented structures */ - -struct acpi_nhlt_device_info_count { - u8 structure_count; -}; - -struct acpi_nhlt_device_info { - u8 device_id[16]; - u8 device_instance_id; - u8 device_port_id; -}; - /******************************************************************************* * * NHLT - Non HDAudio Link Table -- cgit v1.2.3 From a640acab545b21ed1f347376f34d34e461ea92ba Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Tue, 19 Mar 2024 09:30:18 +0100 Subject: ACPI: NHLT: Streamline struct naming Few recently introduced structs are named 'nhlt2' instead of 'nhlt' to avoid naming conflicts. With duplicate types gone, the conflicts are no more. Signed-off-by: Cezary Rojewski Signed-off-by: Rafael J. Wysocki --- drivers/acpi/nhlt.c | 36 ++++++++++++++++++------------------ include/acpi/actbl2.h | 22 +++++++++++----------- include/acpi/nhlt.h | 46 +++++++++++++++++++++++----------------------- 3 files changed, 52 insertions(+), 52 deletions(-) diff --git a/drivers/acpi/nhlt.c b/drivers/acpi/nhlt.c index ab722a95cbb5..dc1bd0df9228 100644 --- a/drivers/acpi/nhlt.c +++ b/drivers/acpi/nhlt.c @@ -16,9 +16,9 @@ #include #include -static struct acpi_table_nhlt2 *acpi_gbl_nhlt; +static struct acpi_table_nhlt *acpi_gbl_nhlt; -static struct acpi_table_nhlt2 empty_nhlt = { +static struct acpi_table_nhlt empty_nhlt = { .header = { .signature = ACPI_SIG_NHLT, }, @@ -65,7 +65,7 @@ EXPORT_SYMBOL_GPL(acpi_nhlt_put_gbl_table); * * Return: %true if endpoint matches specified criteria or %false otherwise. */ -bool acpi_nhlt_endpoint_match(const struct acpi_nhlt2_endpoint *ep, +bool acpi_nhlt_endpoint_match(const struct acpi_nhlt_endpoint *ep, int link_type, int dev_type, int dir, int bus_id) { return ep && @@ -90,11 +90,11 @@ EXPORT_SYMBOL_GPL(acpi_nhlt_endpoint_match); * Return: A pointer to endpoint matching the criteria, %NULL if not found or * an ERR_PTR() otherwise. */ -struct acpi_nhlt2_endpoint * -acpi_nhlt_tb_find_endpoint(const struct acpi_table_nhlt2 *tb, +struct acpi_nhlt_endpoint * +acpi_nhlt_tb_find_endpoint(const struct acpi_table_nhlt *tb, int link_type, int dev_type, int dir, int bus_id) { - struct acpi_nhlt2_endpoint *ep; + struct acpi_nhlt_endpoint *ep; for_each_nhlt_endpoint(tb, ep) if (acpi_nhlt_endpoint_match(ep, link_type, dev_type, dir, bus_id)) @@ -116,7 +116,7 @@ EXPORT_SYMBOL_GPL(acpi_nhlt_tb_find_endpoint); * Return: A pointer to endpoint matching the criteria, %NULL if not found or * an ERR_PTR() otherwise. */ -struct acpi_nhlt2_endpoint * +struct acpi_nhlt_endpoint * acpi_nhlt_find_endpoint(int link_type, int dev_type, int dir, int bus_id) { /* TODO: Currently limited to table of index 0. */ @@ -136,12 +136,12 @@ EXPORT_SYMBOL_GPL(acpi_nhlt_find_endpoint); * Return: A pointer to format matching the criteria, %NULL if not found or * an ERR_PTR() otherwise. */ -struct acpi_nhlt2_format_config * -acpi_nhlt_endpoint_find_fmtcfg(const struct acpi_nhlt2_endpoint *ep, +struct acpi_nhlt_format_config * +acpi_nhlt_endpoint_find_fmtcfg(const struct acpi_nhlt_endpoint *ep, u16 ch, u32 rate, u16 vbps, u16 bps) { - struct acpi_nhlt2_wave_formatext *wav; - struct acpi_nhlt2_format_config *fmt; + struct acpi_nhlt_wave_formatext *wav; + struct acpi_nhlt_format_config *fmt; for_each_nhlt_endpoint_fmtcfg(ep, fmt) { wav = &fmt->format; @@ -176,13 +176,13 @@ EXPORT_SYMBOL_GPL(acpi_nhlt_endpoint_find_fmtcfg); * Return: A pointer to format matching the criteria, %NULL if not found or * an ERR_PTR() otherwise. */ -struct acpi_nhlt2_format_config * -acpi_nhlt_tb_find_fmtcfg(const struct acpi_table_nhlt2 *tb, +struct acpi_nhlt_format_config * +acpi_nhlt_tb_find_fmtcfg(const struct acpi_table_nhlt *tb, int link_type, int dev_type, int dir, int bus_id, u16 ch, u32 rate, u16 vbps, u16 bps) { - struct acpi_nhlt2_format_config *fmt; - struct acpi_nhlt2_endpoint *ep; + struct acpi_nhlt_format_config *fmt; + struct acpi_nhlt_endpoint *ep; for_each_nhlt_endpoint(tb, ep) { if (!acpi_nhlt_endpoint_match(ep, link_type, dev_type, dir, bus_id)) @@ -215,7 +215,7 @@ EXPORT_SYMBOL_GPL(acpi_nhlt_tb_find_fmtcfg); * Return: A pointer to format matching the criteria, %NULL if not found or * an ERR_PTR() otherwise. */ -struct acpi_nhlt2_format_config * +struct acpi_nhlt_format_config * acpi_nhlt_find_fmtcfg(int link_type, int dev_type, int dir, int bus_id, u16 ch, u32 rate, u16 vbps, u16 bps) { @@ -244,10 +244,10 @@ static bool acpi_nhlt_config_is_vendor_micdevice(struct acpi_nhlt_config *cfg) * * Return: A number of microphones or an error code if an invalid endpoint is provided. */ -int acpi_nhlt_endpoint_mic_count(const struct acpi_nhlt2_endpoint *ep) +int acpi_nhlt_endpoint_mic_count(const struct acpi_nhlt_endpoint *ep) { union acpi_nhlt_device_config *devcfg; - struct acpi_nhlt2_format_config *fmt; + struct acpi_nhlt_format_config *fmt; struct acpi_nhlt_config *cfg; u16 max_ch = 0; diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h index 31a716a74340..f237269bd1cb 100644 --- a/include/acpi/actbl2.h +++ b/include/acpi/actbl2.h @@ -1894,7 +1894,7 @@ struct nfit_device_handle { * ******************************************************************************/ -struct acpi_table_nhlt2 { +struct acpi_table_nhlt { struct acpi_table_header header; /* Common ACPI table header */ u8 endpoints_count; /* @@ -1903,7 +1903,7 @@ struct acpi_table_nhlt2 { */ }; -struct acpi_nhlt2_endpoint { +struct acpi_nhlt_endpoint { u32 length; u8 link_type; u8 instance_id; @@ -1990,7 +1990,7 @@ struct acpi_nhlt_micdevice_config { #define ACPI_NHLT_ARRAYTYPE_LINEAR4_GEO2 0xE #define ACPI_NHLT_ARRAYTYPE_VENDOR 0xF -struct acpi_nhlt2_vendor_mic_config { +struct acpi_nhlt_vendor_mic_config { u8 type; u8 panel; u16 speaker_position_distance; /* mm */ @@ -2031,7 +2031,7 @@ struct acpi_nhlt_vendor_micdevice_config { u8 config_type; u8 array_type; u8 mics_count; - struct acpi_nhlt2_vendor_mic_config mics[]; + struct acpi_nhlt_vendor_mic_config mics[]; }; union acpi_nhlt_device_config { @@ -2042,7 +2042,7 @@ union acpi_nhlt_device_config { }; /* Inherited from Microsoft's WAVEFORMATEXTENSIBLE. */ -struct acpi_nhlt2_wave_formatext { +struct acpi_nhlt_wave_formatext { u16 format_tag; u16 channel_count; u32 samples_per_sec; @@ -2055,17 +2055,17 @@ struct acpi_nhlt2_wave_formatext { u8 subformat[16]; }; -struct acpi_nhlt2_format_config { - struct acpi_nhlt2_wave_formatext format; +struct acpi_nhlt_format_config { + struct acpi_nhlt_wave_formatext format; struct acpi_nhlt_config config; }; -struct acpi_nhlt2_formats_config { +struct acpi_nhlt_formats_config { u8 formats_count; - struct acpi_nhlt2_format_config formats[]; + struct acpi_nhlt_format_config formats[]; }; -struct acpi_nhlt2_device_info { +struct acpi_nhlt_device_info { u8 id[16]; u8 instance_id; u8 port_id; @@ -2073,7 +2073,7 @@ struct acpi_nhlt2_device_info { struct acpi_nhlt_devices_info { u8 devices_count; - struct acpi_nhlt2_device_info devices[]; + struct acpi_nhlt_device_info devices[]; }; /******************************************************************************* diff --git a/include/acpi/nhlt.h b/include/acpi/nhlt.h index 7c394e7bc2bb..2108aa6d0207 100644 --- a/include/acpi/nhlt.h +++ b/include/acpi/nhlt.h @@ -23,12 +23,12 @@ * * Return: A pointer to the formats configuration space. */ -static inline struct acpi_nhlt2_formats_config * -acpi_nhlt_endpoint_fmtscfg(const struct acpi_nhlt2_endpoint *ep) +static inline struct acpi_nhlt_formats_config * +acpi_nhlt_endpoint_fmtscfg(const struct acpi_nhlt_endpoint *ep) { struct acpi_nhlt_config *cfg = __acpi_nhlt_endpoint_config(ep); - return (struct acpi_nhlt2_formats_config *)((u8 *)(cfg + 1) + cfg->capabilities_size); + return (struct acpi_nhlt_formats_config *)((u8 *)(cfg + 1) + cfg->capabilities_size); } #define __acpi_nhlt_first_endpoint(tb) \ @@ -99,24 +99,24 @@ acpi_nhlt_endpoint_fmtscfg(const struct acpi_nhlt2_endpoint *ep) acpi_status acpi_nhlt_get_gbl_table(void); void acpi_nhlt_put_gbl_table(void); -bool acpi_nhlt_endpoint_match(const struct acpi_nhlt2_endpoint *ep, +bool acpi_nhlt_endpoint_match(const struct acpi_nhlt_endpoint *ep, int link_type, int dev_type, int dir, int bus_id); -struct acpi_nhlt2_endpoint * -acpi_nhlt_tb_find_endpoint(const struct acpi_table_nhlt2 *tb, +struct acpi_nhlt_endpoint * +acpi_nhlt_tb_find_endpoint(const struct acpi_table_nhlt *tb, int link_type, int dev_type, int dir, int bus_id); -struct acpi_nhlt2_endpoint * +struct acpi_nhlt_endpoint * acpi_nhlt_find_endpoint(int link_type, int dev_type, int dir, int bus_id); -struct acpi_nhlt2_format_config * -acpi_nhlt_endpoint_find_fmtcfg(const struct acpi_nhlt2_endpoint *ep, +struct acpi_nhlt_format_config * +acpi_nhlt_endpoint_find_fmtcfg(const struct acpi_nhlt_endpoint *ep, u16 ch, u32 rate, u16 vbps, u16 bps); -struct acpi_nhlt2_format_config * -acpi_nhlt_tb_find_fmtcfg(const struct acpi_table_nhlt2 *tb, +struct acpi_nhlt_format_config * +acpi_nhlt_tb_find_fmtcfg(const struct acpi_table_nhlt *tb, int link_type, int dev_type, int dir, int bus_id, u16 ch, u32 rate, u16 vpbs, u16 bps); -struct acpi_nhlt2_format_config * +struct acpi_nhlt_format_config * acpi_nhlt_find_fmtcfg(int link_type, int dev_type, int dir, int bus_id, u16 ch, u32 rate, u16 vpbs, u16 bps); -int acpi_nhlt_endpoint_mic_count(const struct acpi_nhlt2_endpoint *ep); +int acpi_nhlt_endpoint_mic_count(const struct acpi_nhlt_endpoint *ep); #else /* !CONFIG_ACPI_NHLT */ @@ -130,46 +130,46 @@ static inline void acpi_nhlt_put_gbl_table(void) } static inline bool -acpi_nhlt_endpoint_match(const struct acpi_nhlt2_endpoint *ep, +acpi_nhlt_endpoint_match(const struct acpi_nhlt_endpoint *ep, int link_type, int dev_type, int dir, int bus_id) { return false; } -static inline struct acpi_nhlt2_endpoint * -acpi_nhlt_tb_find_endpoint(const struct acpi_table_nhlt2 *tb, +static inline struct acpi_nhlt_endpoint * +acpi_nhlt_tb_find_endpoint(const struct acpi_table_nhlt *tb, int link_type, int dev_type, int dir, int bus_id) { return NULL; } -static inline struct acpi_nhlt2_format_config * -acpi_nhlt_endpoint_find_fmtcfg(const struct acpi_nhlt2_endpoint *ep, +static inline struct acpi_nhlt_format_config * +acpi_nhlt_endpoint_find_fmtcfg(const struct acpi_nhlt_endpoint *ep, u16 ch, u32 rate, u16 vbps, u16 bps) { return NULL; } -static inline struct acpi_nhlt2_format_config * -acpi_nhlt_tb_find_fmtcfg(const struct acpi_table_nhlt2 *tb, +static inline struct acpi_nhlt_format_config * +acpi_nhlt_tb_find_fmtcfg(const struct acpi_table_nhlt *tb, int link_type, int dev_type, int dir, int bus_id, u16 ch, u32 rate, u16 vpbs, u16 bps) { return NULL; } -static inline int acpi_nhlt_endpoint_mic_count(const struct acpi_nhlt2_endpoint *ep) +static inline int acpi_nhlt_endpoint_mic_count(const struct acpi_nhlt_endpoint *ep) { return 0; } -static inline struct acpi_nhlt2_endpoint * +static inline struct acpi_nhlt_endpoint * acpi_nhlt_find_endpoint(int link_type, int dev_type, int dir, int bus_id) { return NULL; } -static inline struct acpi_nhlt2_format_config * +static inline struct acpi_nhlt_format_config * acpi_nhlt_find_fmtcfg(int link_type, int dev_type, int dir, int bus_id, u16 ch, u32 rate, u16 vpbs, u16 bps) { -- cgit v1.2.3 From 95d43290f1e476b3be782dd17642e452d0436266 Mon Sep 17 00:00:00 2001 From: Armin Wolf Date: Sat, 9 Mar 2024 21:13:06 +0100 Subject: ACPI: bus: Indicate support for _TFP thru _OSC The ACPI thermal driver already uses the _TPF ACPI method to retrieve precise sampling time values, but this is not reported thru _OSC. Fix this by setting bit 9 ("Fast Thermal Sampling support") when evaluating _OSC. Fixes: a2ee7581afd5 ("ACPI: thermal: Add Thermal fast Sampling Period (_TFP) support") Signed-off-by: Armin Wolf Signed-off-by: Rafael J. Wysocki --- drivers/acpi/bus.c | 2 ++ include/linux/acpi.h | 1 + 2 files changed, 3 insertions(+) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index d9fa730416f1..9c13a4e43fa8 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -316,6 +316,8 @@ static void acpi_bus_osc_negotiate_platform_control(void) capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PAD_SUPPORT; if (IS_ENABLED(CONFIG_ACPI_PROCESSOR)) capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PPC_OST_SUPPORT; + if (IS_ENABLED(CONFIG_ACPI_THERMAL)) + capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_FAST_THERMAL_SAMPLING_SUPPORT; capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_HOTPLUG_OST_SUPPORT; capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PCLPI_SUPPORT; diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 34829f2c517a..51bdd9e08f6d 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -573,6 +573,7 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context); #define OSC_SB_CPCV2_SUPPORT 0x00000040 #define OSC_SB_PCLPI_SUPPORT 0x00000080 #define OSC_SB_OSLPI_SUPPORT 0x00000100 +#define OSC_SB_FAST_THERMAL_SAMPLING_SUPPORT 0x00000200 #define OSC_SB_CPC_DIVERSE_HIGH_SUPPORT 0x00001000 #define OSC_SB_GENERIC_INITIATOR_SUPPORT 0x00002000 #define OSC_SB_CPC_FLEXIBLE_ADR_SPACE 0x00004000 -- cgit v1.2.3 From 6e8345f23ca37d6d41bb76be5d6a705ddf542817 Mon Sep 17 00:00:00 2001 From: Armin Wolf Date: Sat, 9 Mar 2024 21:13:07 +0100 Subject: ACPI: bus: Indicate support for more than 16 p-states thru _OSC The code responsible for parsing the available p-states should have no problems handling more than 16 p-states. Indicate this by setting bit 10 ("Greater Than 16 p-state support") when evaluating _OSC. Signed-off-by: Armin Wolf Signed-off-by: Rafael J. Wysocki --- drivers/acpi/bus.c | 1 + include/linux/acpi.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 9c13a4e43fa8..d5b0e80dc48e 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -321,6 +321,7 @@ static void acpi_bus_osc_negotiate_platform_control(void) capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_HOTPLUG_OST_SUPPORT; capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PCLPI_SUPPORT; + capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_OVER_16_PSTATES_SUPPORT; if (IS_ENABLED(CONFIG_ACPI_PRMT)) capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PRM_SUPPORT; if (IS_ENABLED(CONFIG_ACPI_FFH)) diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 51bdd9e08f6d..0e0b027e27e2 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -574,6 +574,7 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context); #define OSC_SB_PCLPI_SUPPORT 0x00000080 #define OSC_SB_OSLPI_SUPPORT 0x00000100 #define OSC_SB_FAST_THERMAL_SAMPLING_SUPPORT 0x00000200 +#define OSC_SB_OVER_16_PSTATES_SUPPORT 0x00000400 #define OSC_SB_CPC_DIVERSE_HIGH_SUPPORT 0x00001000 #define OSC_SB_GENERIC_INITIATOR_SUPPORT 0x00002000 #define OSC_SB_CPC_FLEXIBLE_ADR_SPACE 0x00004000 -- cgit v1.2.3 From a8a967a243d71dd635ede076020f665a4df51c63 Mon Sep 17 00:00:00 2001 From: Armin Wolf Date: Sat, 9 Mar 2024 21:13:08 +0100 Subject: ACPI: bus: Indicate support for the Generic Event Device thru _OSC A device driver for the Generic Event Device (ACPI0013) already exists for quite some time, but support for it was never reported thru _OSC. Fix this by setting bit 11 ("Generic Event Device support") when evaluating _OSC. Fixes: 3db80c230da1 ("ACPI: implement Generic Event Device") Signed-off-by: Armin Wolf Signed-off-by: Rafael J. Wysocki --- drivers/acpi/bus.c | 1 + include/linux/acpi.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index d5b0e80dc48e..0c48b603098a 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -322,6 +322,7 @@ static void acpi_bus_osc_negotiate_platform_control(void) capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_HOTPLUG_OST_SUPPORT; capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PCLPI_SUPPORT; capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_OVER_16_PSTATES_SUPPORT; + capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_GED_SUPPORT; if (IS_ENABLED(CONFIG_ACPI_PRMT)) capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PRM_SUPPORT; if (IS_ENABLED(CONFIG_ACPI_FFH)) diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 0e0b027e27e2..b0d909d1f5fc 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -575,6 +575,7 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context); #define OSC_SB_OSLPI_SUPPORT 0x00000100 #define OSC_SB_FAST_THERMAL_SAMPLING_SUPPORT 0x00000200 #define OSC_SB_OVER_16_PSTATES_SUPPORT 0x00000400 +#define OSC_SB_GED_SUPPORT 0x00000800 #define OSC_SB_CPC_DIVERSE_HIGH_SUPPORT 0x00001000 #define OSC_SB_GENERIC_INITIATOR_SUPPORT 0x00002000 #define OSC_SB_CPC_FLEXIBLE_ADR_SPACE 0x00004000 -- cgit v1.2.3 From d0d4f1474e36b195eaad477373127ae621334c01 Mon Sep 17 00:00:00 2001 From: Armin Wolf Date: Sat, 9 Mar 2024 21:13:09 +0100 Subject: ACPI: Fix Generic Initiator Affinity _OSC bit The ACPI spec says bit 17 should be used to indicate support for Generic Initiator Affinity Structure in SRAT, but we currently set bit 13 ("Interrupt ResourceSource support"). Fix this by actually setting bit 17 when evaluating _OSC. Fixes: 01aabca2fd54 ("ACPI: Let ACPI know we support Generic Initiator Affinity Structures") Signed-off-by: Armin Wolf Signed-off-by: Rafael J. Wysocki --- include/linux/acpi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/acpi.h b/include/linux/acpi.h index b0d909d1f5fc..e77783e101c3 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -577,8 +577,8 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context); #define OSC_SB_OVER_16_PSTATES_SUPPORT 0x00000400 #define OSC_SB_GED_SUPPORT 0x00000800 #define OSC_SB_CPC_DIVERSE_HIGH_SUPPORT 0x00001000 -#define OSC_SB_GENERIC_INITIATOR_SUPPORT 0x00002000 #define OSC_SB_CPC_FLEXIBLE_ADR_SPACE 0x00004000 +#define OSC_SB_GENERIC_INITIATOR_SUPPORT 0x00020000 #define OSC_SB_NATIVE_USB4_SUPPORT 0x00040000 #define OSC_SB_PRM_SUPPORT 0x00200000 #define OSC_SB_FFH_OPR_SUPPORT 0x00400000 -- cgit v1.2.3 From 403ad17c06509794fdf6e4d4b3070bd5b56e2a8e Mon Sep 17 00:00:00 2001 From: Armin Wolf Date: Sat, 9 Mar 2024 21:13:10 +0100 Subject: ACPI: bus: Indicate support for IRQ ResourceSource thru _OSC The ACPI IRQ mapping code supports parsing of ResourceSource, but this is not reported thru _OSC. Fix this by setting bit 13 ("Interrupt ResourceSource support") when evaluating _OSC. Fixes: d44fa3d46079 ("ACPI: Add support for ResourceSource/IRQ domain mapping") Signed-off-by: Armin Wolf Signed-off-by: Rafael J. Wysocki --- drivers/acpi/bus.c | 1 + include/linux/acpi.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 0c48b603098a..a87b10eef77d 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -323,6 +323,7 @@ static void acpi_bus_osc_negotiate_platform_control(void) capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PCLPI_SUPPORT; capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_OVER_16_PSTATES_SUPPORT; capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_GED_SUPPORT; + capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_IRQ_RESOURCE_SOURCE_SUPPORT; if (IS_ENABLED(CONFIG_ACPI_PRMT)) capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PRM_SUPPORT; if (IS_ENABLED(CONFIG_ACPI_FFH)) diff --git a/include/linux/acpi.h b/include/linux/acpi.h index e77783e101c3..168201e4c782 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -577,6 +577,7 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context); #define OSC_SB_OVER_16_PSTATES_SUPPORT 0x00000400 #define OSC_SB_GED_SUPPORT 0x00000800 #define OSC_SB_CPC_DIVERSE_HIGH_SUPPORT 0x00001000 +#define OSC_SB_IRQ_RESOURCE_SOURCE_SUPPORT 0x00002000 #define OSC_SB_CPC_FLEXIBLE_ADR_SPACE 0x00004000 #define OSC_SB_GENERIC_INITIATOR_SUPPORT 0x00020000 #define OSC_SB_NATIVE_USB4_SUPPORT 0x00040000 -- cgit v1.2.3 From 32666d9cb3ddcf0041b6377cbab68f4c2d7c4171 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 25 Mar 2024 14:32:57 +0200 Subject: ACPI: bus: Make container_of() no-op where it makes sense Move list head node to be the first member in a few data structures in order to make container_of() no-op at compile time. On x86_64 with a custom (default + a few dozens of drivers enabled) configuration: add/remove: 0/0 grow/shrink: 5/12 up/down: 21/-124 (-103) ... Total: Before=39924675, After=39924572, chg -0.00% Signed-off-by: Andy Shevchenko Signed-off-by: Rafael J. Wysocki --- include/acpi/acpi_bus.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 5de954e2b18a..e4d8d48bba1f 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -124,8 +124,8 @@ static inline struct acpi_hotplug_profile *to_acpi_hotplug_profile( } struct acpi_scan_handler { - const struct acpi_device_id *ids; struct list_head list_node; + const struct acpi_device_id *ids; bool (*match)(const char *idstr, const struct acpi_device_id **matchid); int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id); void (*detach)(struct acpi_device *dev); @@ -269,6 +269,7 @@ struct acpi_device_power_flags { }; struct acpi_device_power_state { + struct list_head resources; /* Power resources referenced */ struct { u8 valid:1; u8 explicit_set:1; /* _PSx present? */ @@ -276,7 +277,6 @@ struct acpi_device_power_state { } flags; int power; /* % Power (compared to D0) */ int latency; /* Dx->D0 time (microseconds) */ - struct list_head resources; /* Power resources referenced */ }; struct acpi_device_power { @@ -342,16 +342,16 @@ struct acpi_device_wakeup { }; struct acpi_device_physical_node { - unsigned int node_id; struct list_head node; struct device *dev; + unsigned int node_id; bool put_online:1; }; struct acpi_device_properties { + struct list_head list; const guid_t *guid; union acpi_object *properties; - struct list_head list; void **bufs; }; @@ -488,12 +488,12 @@ struct acpi_device { /* Non-device subnode */ struct acpi_data_node { + struct list_head sibling; const char *name; acpi_handle handle; struct fwnode_handle fwnode; struct fwnode_handle *parent; struct acpi_device_data data; - struct list_head sibling; struct kobject kobj; struct completion kobj_done; }; -- cgit v1.2.3 From 336153053293a090400cfdd4ae724b6b8a4beb98 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 25 Mar 2024 14:32:58 +0200 Subject: ACPI: bus: Don't use "proxy" headers Update header inclusions to follow the IWYU (Include What You Use) principle. Signed-off-by: Andy Shevchenko Signed-off-by: Rafael J. Wysocki --- include/acpi/acpi_bus.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index e4d8d48bba1f..a6ced88a08f3 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -9,8 +9,13 @@ #ifndef __ACPI_BUS_H__ #define __ACPI_BUS_H__ +#include +#include #include +#include +#include #include +#include struct acpi_handle_list { u32 count; -- cgit v1.2.3 From 2649a0f29a39f455ff39eb2296269e20df3bba0d Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 25 Mar 2024 14:33:00 +0200 Subject: ACPI: scan: Use list_first_entry_or_null() in acpi_device_hid() To replace list_empty() + list_first_entry() pair to simplify code. Signed-off-by: Andy Shevchenko Signed-off-by: Rafael J. Wysocki --- drivers/acpi/scan.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 7c157bf92695..dc625653b198 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1298,10 +1298,10 @@ const char *acpi_device_hid(struct acpi_device *device) { struct acpi_hardware_id *hid; - if (list_empty(&device->pnp.ids)) + hid = list_first_entry_or_null(&device->pnp.ids, struct acpi_hardware_id, list); + if (!hid) return dummy_hid; - hid = list_first_entry(&device->pnp.ids, struct acpi_hardware_id, list); return hid->id; } EXPORT_SYMBOL(acpi_device_hid); -- cgit v1.2.3 From e80d4122df9c707ebc9cfe20ab60be302fc9b833 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 25 Mar 2024 14:33:01 +0200 Subject: ACPI: scan: Move misleading comment to acpi_dma_configure_id() The acpi_iommu_configure_id() implementation has a misleading comment since after it the flow does something different to what it states. Move the commit to the caller and with that unshadow the error code inside acpi_iommu_configure_id(). Signed-off-by: Andy Shevchenko Signed-off-by: Rafael J. Wysocki --- drivers/acpi/scan.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index dc625653b198..e64e1ec626b3 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1625,12 +1625,11 @@ static int acpi_iommu_configure_id(struct device *dev, const u32 *id_in) if (!err && dev->bus) err = iommu_probe_device(dev); - /* Ignore all other errors apart from EPROBE_DEFER */ - if (err == -EPROBE_DEFER) { + if (err == -EPROBE_DEFER) return err; - } else if (err) { + if (err) { dev_dbg(dev, "Adding to IOMMU failed: %d\n", err); - return -ENODEV; + return err; } if (!acpi_iommu_fwspec_ops(dev)) return -ENODEV; @@ -1671,13 +1670,14 @@ int acpi_dma_configure_id(struct device *dev, enum dev_dma_attr attr, acpi_arch_dma_setup(dev); + /* Ignore all other errors apart from EPROBE_DEFER */ ret = acpi_iommu_configure_id(dev, input_id); if (ret == -EPROBE_DEFER) return -EPROBE_DEFER; /* * Historically this routine doesn't fail driver probing due to errors - * in acpi_iommu_configure_id() + * in acpi_iommu_configure_id(). */ arch_setup_dma_ops(dev, 0, U64_MAX, attr == DEV_DMA_COHERENT); -- cgit v1.2.3 From 602401e32847f90c513df4a34bcac4dd6b02dd8d Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 25 Mar 2024 14:33:02 +0200 Subject: ACPI: scan: Use standard error checking pattern Check for an error and return it as it's the usual way to handle this. Signed-off-by: Andy Shevchenko Signed-off-by: Rafael J. Wysocki --- drivers/acpi/scan.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index e64e1ec626b3..b9a33364e553 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1581,12 +1581,13 @@ int acpi_iommu_fwspec_init(struct device *dev, u32 id, struct fwnode_handle *fwnode, const struct iommu_ops *ops) { - int ret = iommu_fwspec_init(dev, fwnode, ops); + int ret; - if (!ret) - ret = iommu_fwspec_add_ids(dev, &id, 1); + ret = iommu_fwspec_init(dev, fwnode, ops); + if (ret) + return ret; - return ret; + return iommu_fwspec_add_ids(dev, &id, 1); } static inline const struct iommu_ops *acpi_iommu_fwspec_ops(struct device *dev) -- cgit v1.2.3 From f5c519fc3628915c2eccd65f86d7ee2ce5cc8645 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 25 Mar 2024 14:33:03 +0200 Subject: ACPI: scan: Introduce typedef:s for struct acpi_hotplug_context members Follow the struct acpi_device_ops approach and introduce typedef:s for the members. It makes code less verbose and more particular on what parameters we take or types we use. Signed-off-by: Andy Shevchenko Signed-off-by: Rafael J. Wysocki --- drivers/acpi/dock.c | 48 +++++++++++++++++------------------------------- drivers/acpi/scan.c | 5 ++--- include/acpi/acpi_bus.h | 13 ++++++++----- 3 files changed, 27 insertions(+), 39 deletions(-) diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index a7c00ef78086..34affbda295e 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -88,43 +88,29 @@ static void dock_hotplug_event(struct dock_dependent_device *dd, u32 event, enum dock_callback_type cb_type) { struct acpi_device *adev = dd->adev; + acpi_hp_fixup fixup = NULL; + acpi_hp_uevent uevent = NULL; + acpi_hp_notify notify = NULL; acpi_lock_hp_context(); - if (!adev->hp) - goto out; - - if (cb_type == DOCK_CALL_FIXUP) { - void (*fixup)(struct acpi_device *); - - fixup = adev->hp->fixup; - if (fixup) { - acpi_unlock_hp_context(); - fixup(adev); - return; - } - } else if (cb_type == DOCK_CALL_UEVENT) { - void (*uevent)(struct acpi_device *, u32); - - uevent = adev->hp->uevent; - if (uevent) { - acpi_unlock_hp_context(); - uevent(adev, event); - return; - } - } else { - int (*notify)(struct acpi_device *, u32); - - notify = adev->hp->notify; - if (notify) { - acpi_unlock_hp_context(); - notify(adev, event); - return; - } + if (adev->hp) { + if (cb_type == DOCK_CALL_FIXUP) + fixup = adev->hp->fixup; + else if (cb_type == DOCK_CALL_UEVENT) + uevent = adev->hp->uevent; + else + notify = adev->hp->notify; } - out: acpi_unlock_hp_context(); + + if (fixup) + fixup(adev); + else if (uevent) + uevent(adev, event); + else if (notify) + notify(adev, event); } static struct dock_station *find_dock_station(acpi_handle handle) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index b9a33364e553..f06d92b1183f 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -73,8 +73,7 @@ void acpi_unlock_hp_context(void) void acpi_initialize_hp_context(struct acpi_device *adev, struct acpi_hotplug_context *hp, - int (*notify)(struct acpi_device *, u32), - void (*uevent)(struct acpi_device *, u32)) + acpi_hp_notify notify, acpi_hp_uevent uevent) { acpi_lock_hp_context(); hp->notify = notify; @@ -428,7 +427,7 @@ void acpi_device_hotplug(struct acpi_device *adev, u32 src) } else if (adev->flags.hotplug_notify) { error = acpi_generic_hotplug_event(adev, src); } else { - int (*notify)(struct acpi_device *, u32); + acpi_hp_notify notify; acpi_lock_hp_context(); notify = adev->hp ? adev->hp->notify : NULL; diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index a6ced88a08f3..6f8cc4cc61be 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -144,11 +144,15 @@ struct acpi_scan_handler { * -------------------- */ +typedef int (*acpi_hp_notify) (struct acpi_device *, u32); +typedef void (*acpi_hp_uevent) (struct acpi_device *, u32); +typedef void (*acpi_hp_fixup) (struct acpi_device *); + struct acpi_hotplug_context { struct acpi_device *self; - int (*notify)(struct acpi_device *, u32); - void (*uevent)(struct acpi_device *, u32); - void (*fixup)(struct acpi_device *); + acpi_hp_notify notify; + acpi_hp_uevent uevent; + acpi_hp_fixup fixup; }; /* @@ -583,8 +587,7 @@ static inline void acpi_set_hp_context(struct acpi_device *adev, void acpi_initialize_hp_context(struct acpi_device *adev, struct acpi_hotplug_context *hp, - int (*notify)(struct acpi_device *, u32), - void (*uevent)(struct acpi_device *, u32)); + acpi_hp_notify notify, acpi_hp_uevent uevent); /* acpi_device.dev.bus == &acpi_bus_type */ extern const struct bus_type acpi_bus_type; -- cgit v1.2.3 From 79b510c49207489f7e019b4c397b04d22b4dfd8d Mon Sep 17 00:00:00 2001 From: Sumeet Pawnikar Date: Fri, 5 Apr 2024 17:48:19 +0530 Subject: ACPI: DPTF: Add Lunar Lake support Add Lunar Lake ACPI IDs for DPTF devices. Signed-off-by: Sumeet Pawnikar Signed-off-by: Rafael J. Wysocki --- drivers/acpi/dptf/dptf_pch_fivr.c | 1 + drivers/acpi/dptf/dptf_power.c | 2 ++ drivers/acpi/dptf/int340x_thermal.c | 6 ++++++ drivers/acpi/fan.h | 1 + drivers/thermal/intel/int340x_thermal/int3400_thermal.c | 1 + drivers/thermal/intel/int340x_thermal/int3403_thermal.c | 1 + 6 files changed, 12 insertions(+) diff --git a/drivers/acpi/dptf/dptf_pch_fivr.c b/drivers/acpi/dptf/dptf_pch_fivr.c index 654aaa53c67f..d202730fafd8 100644 --- a/drivers/acpi/dptf/dptf_pch_fivr.c +++ b/drivers/acpi/dptf/dptf_pch_fivr.c @@ -150,6 +150,7 @@ static const struct acpi_device_id pch_fivr_device_ids[] = { {"INTC1045", 0}, {"INTC1049", 0}, {"INTC1064", 0}, + {"INTC106B", 0}, {"INTC10A3", 0}, {"", 0}, }; diff --git a/drivers/acpi/dptf/dptf_power.c b/drivers/acpi/dptf/dptf_power.c index b8187babbbbb..8023b3e23315 100644 --- a/drivers/acpi/dptf/dptf_power.c +++ b/drivers/acpi/dptf/dptf_power.c @@ -232,6 +232,8 @@ static const struct acpi_device_id int3407_device_ids[] = { {"INTC1061", 0}, {"INTC1065", 0}, {"INTC1066", 0}, + {"INTC106C", 0}, + {"INTC106D", 0}, {"INTC10A4", 0}, {"INTC10A5", 0}, {"", 0}, diff --git a/drivers/acpi/dptf/int340x_thermal.c b/drivers/acpi/dptf/int340x_thermal.c index b7113fa92fa6..014ada759954 100644 --- a/drivers/acpi/dptf/int340x_thermal.c +++ b/drivers/acpi/dptf/int340x_thermal.c @@ -43,6 +43,12 @@ static const struct acpi_device_id int340x_thermal_device_ids[] = { {"INTC1064"}, {"INTC1065"}, {"INTC1066"}, + {"INTC1068"}, + {"INTC1069"}, + {"INTC106A"}, + {"INTC106B"}, + {"INTC106C"}, + {"INTC106D"}, {"INTC10A0"}, {"INTC10A1"}, {"INTC10A2"}, diff --git a/drivers/acpi/fan.h b/drivers/acpi/fan.h index e7b4b4e4a55e..f89d19c922dc 100644 --- a/drivers/acpi/fan.h +++ b/drivers/acpi/fan.h @@ -15,6 +15,7 @@ {"INTC1044", }, /* Fan for Tiger Lake generation */ \ {"INTC1048", }, /* Fan for Alder Lake generation */ \ {"INTC1063", }, /* Fan for Meteor Lake generation */ \ + {"INTC106A", }, /* Fan for Lunar Lake generation */ \ {"INTC10A2", }, /* Fan for Raptor Lake generation */ \ {"PNP0C0B", } /* Generic ACPI fan */ diff --git a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c index 427d370648d5..f8ebdd19d340 100644 --- a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c +++ b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c @@ -705,6 +705,7 @@ static const struct acpi_device_id int3400_thermal_match[] = { {"INTC1040", 0}, {"INTC1041", 0}, {"INTC1042", 0}, + {"INTC1068", 0}, {"INTC10A0", 0}, {} }; diff --git a/drivers/thermal/intel/int340x_thermal/int3403_thermal.c b/drivers/thermal/intel/int340x_thermal/int3403_thermal.c index 9b33fd3a66da..86901f9f54d8 100644 --- a/drivers/thermal/intel/int340x_thermal/int3403_thermal.c +++ b/drivers/thermal/intel/int340x_thermal/int3403_thermal.c @@ -284,6 +284,7 @@ static const struct acpi_device_id int3403_device_ids[] = { {"INTC1043", 0}, {"INTC1046", 0}, {"INTC1062", 0}, + {"INTC1069", 0}, {"INTC10A1", 0}, {"", 0}, }; -- cgit v1.2.3 From 48b9c4862bd303628b2e772591f2ef958e02a316 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 28 Mar 2024 20:49:11 +0100 Subject: ACPI: store owner from modules with acpi_bus_register_driver() Modules registering driver with acpi_bus_register_driver() often forget to set .owner field. The field is used by some of other kernel parts for reference counting (try_module_get()), so it is expected that drivers will set it. Solve the problem by moving this task away from the drivers to the core ACPI bus code, just like we did for platform_driver in commit 9447057eaff8 ("platform_device: use a macro instead of platform_driver_register"). Acked-by: Rafael J. Wysocki Signed-off-by: Krzysztof Kozlowski Signed-off-by: Rafael J. Wysocki --- drivers/acpi/bus.c | 9 +++++---- include/acpi/acpi_bus.h | 7 ++++++- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index a87b10eef77d..844c46447914 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -995,25 +995,26 @@ EXPORT_SYMBOL_GPL(acpi_driver_match_device); -------------------------------------------------------------------------- */ /** - * acpi_bus_register_driver - register a driver with the ACPI bus + * __acpi_bus_register_driver - register a driver with the ACPI bus * @driver: driver being registered + * @owner: owning module/driver * * Registers a driver with the ACPI bus. Searches the namespace for all * devices that match the driver's criteria and binds. Returns zero for * success or a negative error status for failure. */ -int acpi_bus_register_driver(struct acpi_driver *driver) +int __acpi_bus_register_driver(struct acpi_driver *driver, struct module *owner) { if (acpi_disabled) return -ENODEV; driver->drv.name = driver->name; driver->drv.bus = &acpi_bus_type; - driver->drv.owner = driver->owner; + driver->drv.owner = owner; return driver_register(&driver->drv); } -EXPORT_SYMBOL(acpi_bus_register_driver); +EXPORT_SYMBOL(__acpi_bus_register_driver); /** * acpi_bus_unregister_driver - unregisters a driver with the ACPI bus diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 5de954e2b18a..7453be56f855 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -656,7 +656,12 @@ void acpi_scan_lock_release(void); void acpi_lock_hp_context(void); void acpi_unlock_hp_context(void); int acpi_scan_add_handler(struct acpi_scan_handler *handler); -int acpi_bus_register_driver(struct acpi_driver *driver); +/* + * use a macro to avoid include chaining to get THIS_MODULE + */ +#define acpi_bus_register_driver(drv) \ + __acpi_bus_register_driver(drv, THIS_MODULE) +int __acpi_bus_register_driver(struct acpi_driver *driver, struct module *owner); void acpi_bus_unregister_driver(struct acpi_driver *driver); int acpi_bus_scan(acpi_handle handle); void acpi_bus_trim(struct acpi_device *start); -- cgit v1.2.3 From 726c149e079898214f5e7fb303c6d0c2b5ac6459 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 28 Mar 2024 20:49:12 +0100 Subject: Input: atlas - drop owner assignment ACPI bus core already sets the .owner, so driver does not need to. Acked-by: Dmitry Torokhov Acked-by: Rafael J. Wysocki Signed-off-by: Krzysztof Kozlowski Signed-off-by: Rafael J. Wysocki --- drivers/input/misc/atlas_btns.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/input/misc/atlas_btns.c b/drivers/input/misc/atlas_btns.c index 3c9bbd04e143..5b9be2957746 100644 --- a/drivers/input/misc/atlas_btns.c +++ b/drivers/input/misc/atlas_btns.c @@ -127,7 +127,6 @@ MODULE_DEVICE_TABLE(acpi, atlas_device_ids); static struct acpi_driver atlas_acpi_driver = { .name = ACPI_ATLAS_NAME, .class = ACPI_ATLAS_CLASS, - .owner = THIS_MODULE, .ids = atlas_device_ids, .ops = { .add = atlas_acpi_button_add, -- cgit v1.2.3 From 3bdef399d00e27a26bfc55b8ce6f9a142718a402 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 28 Mar 2024 20:49:13 +0100 Subject: net: fjes: drop owner assignment ACPI bus core already sets the .owner, so driver does not need to. Acked-by: Rafael J. Wysocki Signed-off-by: Krzysztof Kozlowski Signed-off-by: Rafael J. Wysocki --- drivers/net/fjes/fjes_main.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c index 5fbe33a09bb0..324b34f3ac93 100644 --- a/drivers/net/fjes/fjes_main.c +++ b/drivers/net/fjes/fjes_main.c @@ -156,7 +156,6 @@ static void fjes_acpi_remove(struct acpi_device *device) static struct acpi_driver fjes_acpi_driver = { .name = DRV_NAME, .class = DRV_NAME, - .owner = THIS_MODULE, .ids = fjes_acpi_ids, .ops = { .add = fjes_acpi_add, -- cgit v1.2.3 From 245d97ff34734f5236fd82fb66b8c97a1dd4b136 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 28 Mar 2024 20:49:14 +0100 Subject: platform/chrome: wilco_ec: drop owner assignment ACPI bus core already sets the .owner, so driver does not need to. Acked-by: Tzung-Bi Shih Acked-by: Rafael J. Wysocki Signed-off-by: Krzysztof Kozlowski Signed-off-by: Rafael J. Wysocki --- drivers/platform/chrome/wilco_ec/event.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/platform/chrome/wilco_ec/event.c b/drivers/platform/chrome/wilco_ec/event.c index 13291fb4214e..ae34e81c5d18 100644 --- a/drivers/platform/chrome/wilco_ec/event.c +++ b/drivers/platform/chrome/wilco_ec/event.c @@ -523,7 +523,6 @@ static struct acpi_driver event_driver = { .notify = event_device_notify, .remove = event_device_remove, }, - .owner = THIS_MODULE, }; static int __init event_module_init(void) -- cgit v1.2.3 From eda8304c74f0211325ab0472a3ac5b4f5aca2c49 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 28 Mar 2024 20:49:15 +0100 Subject: platform: asus-laptop: drop owner assignment ACPI bus core already sets the .owner, so driver does not need to. Acked-by: Hans de Goede Acked-by: Rafael J. Wysocki Signed-off-by: Krzysztof Kozlowski Signed-off-by: Rafael J. Wysocki --- drivers/platform/x86/asus-laptop.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index bf03ea1b1274..78c42767295a 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -1925,7 +1925,6 @@ MODULE_DEVICE_TABLE(acpi, asus_device_ids); static struct acpi_driver asus_acpi_driver = { .name = ASUS_LAPTOP_NAME, .class = ASUS_LAPTOP_CLASS, - .owner = THIS_MODULE, .ids = asus_device_ids, .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS, .ops = { -- cgit v1.2.3 From be24e9a0933707f46d568911060dbeb5bcc28578 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 28 Mar 2024 20:49:16 +0100 Subject: platform: classmate-laptop: drop owner assignment ACPI bus core already sets the .owner, so driver does not need to. Acked-by: Thadeu Lima de Souza Cascardo Acked-by: Hans de Goede Acked-by: Rafael J. Wysocki Signed-off-by: Krzysztof Kozlowski Signed-off-by: Rafael J. Wysocki --- drivers/platform/x86/classmate-laptop.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/platform/x86/classmate-laptop.c b/drivers/platform/x86/classmate-laptop.c index 2edaea2492df..87462e7c6219 100644 --- a/drivers/platform/x86/classmate-laptop.c +++ b/drivers/platform/x86/classmate-laptop.c @@ -434,7 +434,6 @@ static const struct acpi_device_id cmpc_accel_device_ids_v4[] = { }; static struct acpi_driver cmpc_accel_acpi_driver_v4 = { - .owner = THIS_MODULE, .name = "cmpc_accel_v4", .class = "cmpc_accel_v4", .ids = cmpc_accel_device_ids_v4, @@ -660,7 +659,6 @@ static const struct acpi_device_id cmpc_accel_device_ids[] = { }; static struct acpi_driver cmpc_accel_acpi_driver = { - .owner = THIS_MODULE, .name = "cmpc_accel", .class = "cmpc_accel", .ids = cmpc_accel_device_ids, @@ -754,7 +752,6 @@ static const struct acpi_device_id cmpc_tablet_device_ids[] = { }; static struct acpi_driver cmpc_tablet_acpi_driver = { - .owner = THIS_MODULE, .name = "cmpc_tablet", .class = "cmpc_tablet", .ids = cmpc_tablet_device_ids, @@ -996,7 +993,6 @@ static const struct acpi_device_id cmpc_ipml_device_ids[] = { }; static struct acpi_driver cmpc_ipml_acpi_driver = { - .owner = THIS_MODULE, .name = "cmpc", .class = "cmpc", .ids = cmpc_ipml_device_ids, @@ -1064,7 +1060,6 @@ static const struct acpi_device_id cmpc_keys_device_ids[] = { }; static struct acpi_driver cmpc_keys_acpi_driver = { - .owner = THIS_MODULE, .name = "cmpc_keys", .class = "cmpc_keys", .ids = cmpc_keys_device_ids, -- cgit v1.2.3 From 1baad72e9026a8d4a03cec7eace3b4c1c53b5653 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 28 Mar 2024 20:49:17 +0100 Subject: platform/x86/dell: drop owner assignment ACPI bus core already sets the .owner, so driver does not need to. Acked-by: Hans de Goede Acked-by: Rafael J. Wysocki Signed-off-by: Krzysztof Kozlowski Signed-off-by: Rafael J. Wysocki --- drivers/platform/x86/dell/dell-rbtn.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/platform/x86/dell/dell-rbtn.c b/drivers/platform/x86/dell/dell-rbtn.c index c8fcb537fd65..a415c432d4c3 100644 --- a/drivers/platform/x86/dell/dell-rbtn.c +++ b/drivers/platform/x86/dell/dell-rbtn.c @@ -295,7 +295,6 @@ static struct acpi_driver rbtn_driver = { .remove = rbtn_remove, .notify = rbtn_notify, }, - .owner = THIS_MODULE, }; -- cgit v1.2.3 From 4313188f8128e9207eeb6808201b121cdaed1861 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 28 Mar 2024 20:49:18 +0100 Subject: platform/x86/eeepc: drop owner assignment ACPI bus core already sets the .owner, so driver does not need to. Acked-by: Hans de Goede Acked-by: Rafael J. Wysocki Signed-off-by: Krzysztof Kozlowski Signed-off-by: Rafael J. Wysocki --- drivers/platform/x86/eeepc-laptop.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index ff1b70269ccb..447364bed249 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -1463,7 +1463,6 @@ MODULE_DEVICE_TABLE(acpi, eeepc_device_ids); static struct acpi_driver eeepc_acpi_driver = { .name = EEEPC_LAPTOP_NAME, .class = EEEPC_ACPI_CLASS, - .owner = THIS_MODULE, .ids = eeepc_device_ids, .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS, .ops = { -- cgit v1.2.3 From 68370cc2e32aa811c841b109a34c92ae56c03caa Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 28 Mar 2024 20:49:19 +0100 Subject: platform/x86/intel/rst: drop owner assignment ACPI bus core already sets the .owner, so driver does not need to. Acked-by: Hans de Goede Acked-by: Rafael J. Wysocki Signed-off-by: Krzysztof Kozlowski Signed-off-by: Rafael J. Wysocki --- drivers/platform/x86/intel/rst.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/platform/x86/intel/rst.c b/drivers/platform/x86/intel/rst.c index 35814a7707af..6bc9c4a603e0 100644 --- a/drivers/platform/x86/intel/rst.c +++ b/drivers/platform/x86/intel/rst.c @@ -125,7 +125,6 @@ static const struct acpi_device_id irst_ids[] = { }; static struct acpi_driver irst_driver = { - .owner = THIS_MODULE, .name = "intel_rapid_start", .class = "intel_rapid_start", .ids = irst_ids, -- cgit v1.2.3 From e84a761f121524103df7b3674a8cde67a4f78fa6 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 28 Mar 2024 20:49:20 +0100 Subject: platform/x86/intel/smartconnect: drop owner assignment ACPI bus core already sets the .owner, so driver does not need to. Acked-by: Hans de Goede Acked-by: Rafael J. Wysocki Signed-off-by: Krzysztof Kozlowski Signed-off-by: Rafael J. Wysocki --- drivers/platform/x86/intel/smartconnect.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/platform/x86/intel/smartconnect.c b/drivers/platform/x86/intel/smartconnect.c index 64c2dc93472f..cd25d0585324 100644 --- a/drivers/platform/x86/intel/smartconnect.c +++ b/drivers/platform/x86/intel/smartconnect.c @@ -32,7 +32,6 @@ static const struct acpi_device_id smartconnect_ids[] = { MODULE_DEVICE_TABLE(acpi, smartconnect_ids); static struct acpi_driver smartconnect_driver = { - .owner = THIS_MODULE, .name = "intel_smart_connect", .class = "intel_smart_connect", .ids = smartconnect_ids, -- cgit v1.2.3 From 2929a735d92e232f92517b0c7a7e4ac8c8fa669b Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 28 Mar 2024 20:49:21 +0100 Subject: platform/x86/lg-laptop: drop owner assignment ACPI bus core already sets the .owner, so driver does not need to. Acked-by: Hans de Goede Acked-by: Rafael J. Wysocki Signed-off-by: Krzysztof Kozlowski Signed-off-by: Rafael J. Wysocki --- drivers/platform/x86/lg-laptop.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/platform/x86/lg-laptop.c b/drivers/platform/x86/lg-laptop.c index ad3c39e9e9f5..36e88b9d59ea 100644 --- a/drivers/platform/x86/lg-laptop.c +++ b/drivers/platform/x86/lg-laptop.c @@ -790,7 +790,6 @@ static struct acpi_driver acpi_driver = { .remove = acpi_remove, .notify = acpi_notify, }, - .owner = THIS_MODULE, }; static int __init acpi_init(void) -- cgit v1.2.3 From 562231f34ceade26c540121cba16b02f9a0f1d9f Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 28 Mar 2024 20:49:22 +0100 Subject: platform/x86/sony-laptop: drop owner assignment ACPI bus core already sets the .owner, so driver does not need to. Acked-by: Hans de Goede Acked-by: Rafael J. Wysocki Signed-off-by: Krzysztof Kozlowski Signed-off-by: Rafael J. Wysocki --- drivers/platform/x86/sony-laptop.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 40878e327afd..3e94fdd1ea52 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -3303,7 +3303,6 @@ static struct acpi_driver sony_nc_driver = { .name = SONY_NC_DRIVER_NAME, .class = SONY_NC_CLASS, .ids = sony_nc_device_ids, - .owner = THIS_MODULE, .ops = { .add = sony_nc_add, .remove = sony_nc_remove, @@ -4844,7 +4843,6 @@ static struct acpi_driver sony_pic_driver = { .name = SONY_PIC_DRIVER_NAME, .class = SONY_PIC_CLASS, .ids = sony_pic_device_ids, - .owner = THIS_MODULE, .ops = { .add = sony_pic_add, .remove = sony_pic_remove, -- cgit v1.2.3 From b655cda9f08915f07a057c6e6ea052a6645b55d4 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 28 Mar 2024 20:49:23 +0100 Subject: platform/x86/toshiba_acpi: drop owner assignment ACPI bus core already sets the .owner, so driver does not need to. Acked-by: Hans de Goede Acked-by: Rafael J. Wysocki Signed-off-by: Krzysztof Kozlowski Signed-off-by: Rafael J. Wysocki --- drivers/platform/x86/toshiba_acpi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index 291f14ef6702..6f9bd675f044 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -3581,7 +3581,6 @@ static SIMPLE_DEV_PM_OPS(toshiba_acpi_pm, static struct acpi_driver toshiba_acpi_driver = { .name = "Toshiba ACPI driver", - .owner = THIS_MODULE, .ids = toshiba_device_ids, .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS, .ops = { -- cgit v1.2.3 From ce69eeb2ccb76155a9a34572250764a1e625c7c7 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 28 Mar 2024 20:49:24 +0100 Subject: platform/x86/toshiba_bluetooth: drop owner assignment ACPI bus core already sets the .owner, so driver does not need to. Acked-by: Hans de Goede Acked-by: Rafael J. Wysocki Signed-off-by: Krzysztof Kozlowski Signed-off-by: Rafael J. Wysocki --- drivers/platform/x86/toshiba_bluetooth.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/platform/x86/toshiba_bluetooth.c b/drivers/platform/x86/toshiba_bluetooth.c index d8f81962a240..dad2c3e55904 100644 --- a/drivers/platform/x86/toshiba_bluetooth.c +++ b/drivers/platform/x86/toshiba_bluetooth.c @@ -59,7 +59,6 @@ static struct acpi_driver toshiba_bt_rfkill_driver = { .remove = toshiba_bt_rfkill_remove, .notify = toshiba_bt_rfkill_notify, }, - .owner = THIS_MODULE, .drv.pm = &toshiba_bt_pm, }; -- cgit v1.2.3 From eb22f3ba0c2efc8f036f645b5e2ff699115a5109 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 28 Mar 2024 20:49:25 +0100 Subject: platform/x86/toshiba_haps: drop owner assignment ACPI bus core already sets the .owner, so driver does not need to. Acked-by: Hans de Goede Acked-by: Rafael J. Wysocki Signed-off-by: Krzysztof Kozlowski Signed-off-by: Rafael J. Wysocki --- drivers/platform/x86/toshiba_haps.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/platform/x86/toshiba_haps.c b/drivers/platform/x86/toshiba_haps.c index 8c9f76286b08..03dfddeee0c0 100644 --- a/drivers/platform/x86/toshiba_haps.c +++ b/drivers/platform/x86/toshiba_haps.c @@ -251,7 +251,6 @@ MODULE_DEVICE_TABLE(acpi, haps_device_ids); static struct acpi_driver toshiba_haps_driver = { .name = "Toshiba HAPS", - .owner = THIS_MODULE, .ids = haps_device_ids, .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS, .ops = { -- cgit v1.2.3 From d49c09ddfbd5566f0071aa482093dc0c2153223b Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 28 Mar 2024 20:49:26 +0100 Subject: platform/x86/wireless-hotkey: drop owner assignment ACPI bus core already sets the .owner, so driver does not need to. Acked-by: Hans de Goede Acked-by: Rafael J. Wysocki Signed-off-by: Krzysztof Kozlowski Signed-off-by: Rafael J. Wysocki --- drivers/platform/x86/wireless-hotkey.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/platform/x86/wireless-hotkey.c b/drivers/platform/x86/wireless-hotkey.c index 4422863f47bb..e95cdbbfb708 100644 --- a/drivers/platform/x86/wireless-hotkey.c +++ b/drivers/platform/x86/wireless-hotkey.c @@ -110,7 +110,6 @@ static void wl_remove(struct acpi_device *device) static struct acpi_driver wl_driver = { .name = "wireless-hotkey", - .owner = THIS_MODULE, .ids = wl_ids, .ops = { .add = wl_add, -- cgit v1.2.3 From cd3eda2e35082094db5643553035f7169b006883 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 28 Mar 2024 20:49:27 +0100 Subject: ptp: vmw: drop owner assignment ACPI bus core already sets the .owner, so driver does not need to. Acked-by: Rafael J. Wysocki Signed-off-by: Krzysztof Kozlowski Signed-off-by: Rafael J. Wysocki --- drivers/ptp/ptp_vmw.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/ptp/ptp_vmw.c b/drivers/ptp/ptp_vmw.c index 27c5547aa8a9..7ec90359428a 100644 --- a/drivers/ptp/ptp_vmw.c +++ b/drivers/ptp/ptp_vmw.c @@ -120,7 +120,6 @@ static struct acpi_driver ptp_vmw_acpi_driver = { .add = ptp_vmw_acpi_add, .remove = ptp_vmw_acpi_remove }, - .owner = THIS_MODULE }; static int __init ptp_vmw_init(void) -- cgit v1.2.3 From 00e8b52bf9f9fdf991274cd1b140316305edb040 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 28 Mar 2024 20:49:28 +0100 Subject: virt: vmgenid: drop owner assignment ACPI bus core already sets the .owner, so driver does not need to. Acked-by: Rafael J. Wysocki Signed-off-by: Krzysztof Kozlowski Signed-off-by: Rafael J. Wysocki --- drivers/virt/vmgenid.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/virt/vmgenid.c b/drivers/virt/vmgenid.c index b67a28da4702..8f6880c3a87f 100644 --- a/drivers/virt/vmgenid.c +++ b/drivers/virt/vmgenid.c @@ -88,7 +88,6 @@ static const struct acpi_device_id vmgenid_ids[] = { static struct acpi_driver vmgenid_driver = { .name = "vmgenid", .ids = vmgenid_ids, - .owner = THIS_MODULE, .ops = { .add = vmgenid_add, .notify = vmgenid_notify -- cgit v1.2.3 From cc85f9c05bba23eb525497b42ac5b74801ccbd87 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 28 Mar 2024 20:49:29 +0100 Subject: ACPI: drop redundant owner from acpi_driver Once all .owner is removed from all acpi_driver instances, drop it from the structure. Acked-by: Rafael J. Wysocki Signed-off-by: Krzysztof Kozlowski Signed-off-by: Rafael J. Wysocki --- include/acpi/acpi_bus.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 7453be56f855..32aae3ee99ac 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -170,7 +170,6 @@ struct acpi_driver { unsigned int flags; struct acpi_device_ops ops; struct device_driver drv; - struct module *owner; }; /* -- cgit v1.2.3 From 5a87e0020d53f21965adf42420766e4d8719a229 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 29 Mar 2024 11:02:01 +0100 Subject: ACPI: APEI: EINJ: mark remove callback as __exit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The einj_driver driver is registered using platform_driver_probe(). In this case it cannot get unbound via sysfs and it's ok to put the remove callback into an exit section. To prevent the modpost warning about einj_driver referencing .exit.text, mark the driver struct with __refdata and explain the situation in a comment. This is an improvement over commit a24118a8a687 ("ACPI: APEI: EINJ: mark remove callback as non-__exit") which recently addressed the same issue, but picked a less optimal variant. Signed-off-by: Uwe Kleine-König Reviewed-by: Dan Williams Acked-by: Arnd Bergmann Signed-off-by: Rafael J. Wysocki --- drivers/acpi/apei/einj-core.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/acpi/apei/einj-core.c b/drivers/acpi/apei/einj-core.c index 01faca3a238a..9515bcfe5e97 100644 --- a/drivers/acpi/apei/einj-core.c +++ b/drivers/acpi/apei/einj-core.c @@ -851,7 +851,7 @@ err_put_table: return rc; } -static void einj_remove(struct platform_device *pdev) +static void __exit einj_remove(struct platform_device *pdev) { struct apei_exec_context ctx; @@ -873,8 +873,14 @@ static void einj_remove(struct platform_device *pdev) } static struct platform_device *einj_dev; -static struct platform_driver einj_driver = { - .remove_new = einj_remove, +/* + * einj_remove() lives in .exit.text. For drivers registered via + * platform_driver_probe() this is ok because they cannot get unbound at + * runtime. So mark the driver struct with __refdata to prevent modpost + * triggering a section mismatch warning. + */ +static struct platform_driver einj_driver __refdata = { + .remove_new = __exit_p(einj_remove), .driver = { .name = "acpi-einj", }, -- cgit v1.2.3 From 07b73ee599428b41d0240f2f7b31b524eba07dd0 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 4 Apr 2024 15:06:58 +0300 Subject: ACPI: LPSS: Advertise number of chip selects via property Advertise number of chip selects via property for Intel Braswell. Fixes: 620c803f42de ("ACPI: LPSS: Provide an SSP type to the driver") Signed-off-by: Andy Shevchenko Reviewed-by: Kuppuswamy Sathyanarayanan Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_lpss.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index 04e273167e92..8e01792228d1 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -325,6 +325,7 @@ static const struct lpss_device_desc bsw_i2c_dev_desc = { static const struct property_entry bsw_spi_properties[] = { PROPERTY_ENTRY_U32("intel,spi-pxa2xx-type", LPSS_BSW_SSP), + PROPERTY_ENTRY_U32("num-cs", 2), { } }; -- cgit v1.2.3 From 1b2a34f20bf0bfe4c86781fd6d7b323ec786ba1a Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 4 Apr 2024 15:06:59 +0300 Subject: ACPI: LPSS: Remove nested ifdeffery for CONFIG_PM There is no need to have the ifdef CONFIG_PM to be nested. The second and so on will obviously become a no-op. Remove redundant nested ifdeffery. Signed-off-by: Andy Shevchenko Reviewed-by: Kuppuswamy Sathyanarayanan Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_lpss.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index 8e01792228d1..a3d2d94be5c0 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -887,10 +887,8 @@ static int acpi_lpss_activate(struct device *dev) if (pdata->dev_desc->flags & (LPSS_SAVE_CTX | LPSS_SAVE_CTX_ONCE)) lpss_deassert_reset(pdata); -#ifdef CONFIG_PM if (pdata->dev_desc->flags & LPSS_SAVE_CTX_ONCE) acpi_lpss_save_ctx(dev, pdata); -#endif return 0; } -- cgit v1.2.3 From d85eb4152bce8ce1f0e4f4c5b4226142de6220bd Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 4 Apr 2024 21:23:39 +0300 Subject: ACPI: x86: Introduce a Makefile There will be more modules coming here, so, introduce a separate Makefile and include it in parent one via obj-$(CONFIG_X86). Signed-off-by: Andy Shevchenko Signed-off-by: Rafael J. Wysocki --- drivers/acpi/Makefile | 4 +--- drivers/acpi/x86/Makefile | 4 ++++ 2 files changed, 5 insertions(+), 3 deletions(-) create mode 100644 drivers/acpi/x86/Makefile diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 8cc8c0d9c873..f84de92b0713 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -56,9 +56,6 @@ acpi-y += evged.o acpi-y += sysfs.o acpi-y += property.o acpi-$(CONFIG_X86) += acpi_cmos_rtc.o -acpi-$(CONFIG_X86) += x86/apple.o -acpi-$(CONFIG_X86) += x86/utils.o -acpi-$(CONFIG_X86) += x86/s2idle.o acpi-$(CONFIG_DEBUG_FS) += debugfs.o acpi-y += acpi_lpat.o acpi-$(CONFIG_ACPI_FPDT) += acpi_fpdt.o @@ -132,3 +129,4 @@ obj-$(CONFIG_ARM64) += arm64/ obj-$(CONFIG_ACPI_VIOT) += viot.o obj-$(CONFIG_RISCV) += riscv/ +obj-$(CONFIG_X86) += x86/ diff --git a/drivers/acpi/x86/Makefile b/drivers/acpi/x86/Makefile new file mode 100644 index 000000000000..bd17dd2c2c5b --- /dev/null +++ b/drivers/acpi/x86/Makefile @@ -0,0 +1,4 @@ +obj-$(CONFIG_ACPI) += acpi-x86.o +acpi-x86-y += apple.o +acpi-x86-y += s2idle.o +acpi-x86-y += utils.o -- cgit v1.2.3 From 49db108391e231ed11fec937b00a2a8c46522a11 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 4 Apr 2024 21:23:40 +0300 Subject: ACPI: x86: Move acpi_cmos_rtc to x86 folder acpi_cmos_rtc is built solely for x86, move it to the respective folder. Signed-off-by: Andy Shevchenko Signed-off-by: Rafael J. Wysocki --- drivers/acpi/Makefile | 1 - drivers/acpi/acpi_cmos_rtc.c | 98 -------------------------------------------- drivers/acpi/x86/Makefile | 1 + drivers/acpi/x86/cmos_rtc.c | 98 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 99 insertions(+), 99 deletions(-) delete mode 100644 drivers/acpi/acpi_cmos_rtc.c create mode 100644 drivers/acpi/x86/cmos_rtc.c diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index f84de92b0713..5e14aa11c2cb 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -55,7 +55,6 @@ acpi-y += event.o acpi-y += evged.o acpi-y += sysfs.o acpi-y += property.o -acpi-$(CONFIG_X86) += acpi_cmos_rtc.o acpi-$(CONFIG_DEBUG_FS) += debugfs.o acpi-y += acpi_lpat.o acpi-$(CONFIG_ACPI_FPDT) += acpi_fpdt.o diff --git a/drivers/acpi/acpi_cmos_rtc.c b/drivers/acpi/acpi_cmos_rtc.c deleted file mode 100644 index 9b55d1593d16..000000000000 --- a/drivers/acpi/acpi_cmos_rtc.c +++ /dev/null @@ -1,98 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * ACPI support for CMOS RTC Address Space access - * - * Copyright (C) 2013, Intel Corporation - * Authors: Lan Tianyu - */ - -#define pr_fmt(fmt) "ACPI: " fmt - -#include -#include -#include -#include -#include -#include - -#include "internal.h" - -static const struct acpi_device_id acpi_cmos_rtc_ids[] = { - { "PNP0B00" }, - { "PNP0B01" }, - { "PNP0B02" }, - {} -}; - -static acpi_status -acpi_cmos_rtc_space_handler(u32 function, acpi_physical_address address, - u32 bits, u64 *value64, - void *handler_context, void *region_context) -{ - int i; - u8 *value = (u8 *)value64; - - if (address > 0xff || !value64) - return AE_BAD_PARAMETER; - - if (function != ACPI_WRITE && function != ACPI_READ) - return AE_BAD_PARAMETER; - - spin_lock_irq(&rtc_lock); - - for (i = 0; i < DIV_ROUND_UP(bits, 8); ++i, ++address, ++value) - if (function == ACPI_READ) - *value = CMOS_READ(address); - else - CMOS_WRITE(*value, address); - - spin_unlock_irq(&rtc_lock); - - return AE_OK; -} - -int acpi_install_cmos_rtc_space_handler(acpi_handle handle) -{ - acpi_status status; - - status = acpi_install_address_space_handler(handle, - ACPI_ADR_SPACE_CMOS, - &acpi_cmos_rtc_space_handler, - NULL, NULL); - if (ACPI_FAILURE(status)) { - pr_err("Error installing CMOS-RTC region handler\n"); - return -ENODEV; - } - - return 1; -} -EXPORT_SYMBOL_GPL(acpi_install_cmos_rtc_space_handler); - -void acpi_remove_cmos_rtc_space_handler(acpi_handle handle) -{ - if (ACPI_FAILURE(acpi_remove_address_space_handler(handle, - ACPI_ADR_SPACE_CMOS, &acpi_cmos_rtc_space_handler))) - pr_err("Error removing CMOS-RTC region handler\n"); -} -EXPORT_SYMBOL_GPL(acpi_remove_cmos_rtc_space_handler); - -static int acpi_cmos_rtc_attach_handler(struct acpi_device *adev, const struct acpi_device_id *id) -{ - return acpi_install_cmos_rtc_space_handler(adev->handle); -} - -static void acpi_cmos_rtc_detach_handler(struct acpi_device *adev) -{ - acpi_remove_cmos_rtc_space_handler(adev->handle); -} - -static struct acpi_scan_handler cmos_rtc_handler = { - .ids = acpi_cmos_rtc_ids, - .attach = acpi_cmos_rtc_attach_handler, - .detach = acpi_cmos_rtc_detach_handler, -}; - -void __init acpi_cmos_rtc_init(void) -{ - acpi_scan_add_handler(&cmos_rtc_handler); -} diff --git a/drivers/acpi/x86/Makefile b/drivers/acpi/x86/Makefile index bd17dd2c2c5b..b97b1bcf8404 100644 --- a/drivers/acpi/x86/Makefile +++ b/drivers/acpi/x86/Makefile @@ -1,4 +1,5 @@ obj-$(CONFIG_ACPI) += acpi-x86.o acpi-x86-y += apple.o +acpi-x86-y += cmos_rtc.o acpi-x86-y += s2idle.o acpi-x86-y += utils.o diff --git a/drivers/acpi/x86/cmos_rtc.c b/drivers/acpi/x86/cmos_rtc.c new file mode 100644 index 000000000000..51643ff6fe5f --- /dev/null +++ b/drivers/acpi/x86/cmos_rtc.c @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * ACPI support for CMOS RTC Address Space access + * + * Copyright (C) 2013, Intel Corporation + * Authors: Lan Tianyu + */ + +#define pr_fmt(fmt) "ACPI: " fmt + +#include +#include +#include +#include +#include +#include + +#include "../internal.h" + +static const struct acpi_device_id acpi_cmos_rtc_ids[] = { + { "PNP0B00" }, + { "PNP0B01" }, + { "PNP0B02" }, + {} +}; + +static acpi_status +acpi_cmos_rtc_space_handler(u32 function, acpi_physical_address address, + u32 bits, u64 *value64, + void *handler_context, void *region_context) +{ + int i; + u8 *value = (u8 *)value64; + + if (address > 0xff || !value64) + return AE_BAD_PARAMETER; + + if (function != ACPI_WRITE && function != ACPI_READ) + return AE_BAD_PARAMETER; + + spin_lock_irq(&rtc_lock); + + for (i = 0; i < DIV_ROUND_UP(bits, 8); ++i, ++address, ++value) + if (function == ACPI_READ) + *value = CMOS_READ(address); + else + CMOS_WRITE(*value, address); + + spin_unlock_irq(&rtc_lock); + + return AE_OK; +} + +int acpi_install_cmos_rtc_space_handler(acpi_handle handle) +{ + acpi_status status; + + status = acpi_install_address_space_handler(handle, + ACPI_ADR_SPACE_CMOS, + &acpi_cmos_rtc_space_handler, + NULL, NULL); + if (ACPI_FAILURE(status)) { + pr_err("Error installing CMOS-RTC region handler\n"); + return -ENODEV; + } + + return 1; +} +EXPORT_SYMBOL_GPL(acpi_install_cmos_rtc_space_handler); + +void acpi_remove_cmos_rtc_space_handler(acpi_handle handle) +{ + if (ACPI_FAILURE(acpi_remove_address_space_handler(handle, + ACPI_ADR_SPACE_CMOS, &acpi_cmos_rtc_space_handler))) + pr_err("Error removing CMOS-RTC region handler\n"); +} +EXPORT_SYMBOL_GPL(acpi_remove_cmos_rtc_space_handler); + +static int acpi_cmos_rtc_attach_handler(struct acpi_device *adev, const struct acpi_device_id *id) +{ + return acpi_install_cmos_rtc_space_handler(adev->handle); +} + +static void acpi_cmos_rtc_detach_handler(struct acpi_device *adev) +{ + acpi_remove_cmos_rtc_space_handler(adev->handle); +} + +static struct acpi_scan_handler cmos_rtc_handler = { + .ids = acpi_cmos_rtc_ids, + .attach = acpi_cmos_rtc_attach_handler, + .detach = acpi_cmos_rtc_detach_handler, +}; + +void __init acpi_cmos_rtc_init(void) +{ + acpi_scan_add_handler(&cmos_rtc_handler); +} -- cgit v1.2.3 From 3d26b94fa11e5e7aa46aef5ee7748d5015900acd Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 4 Apr 2024 21:23:41 +0300 Subject: ACPI: x86: Move blacklist to x86 folder blacklist is built solely for x86, move it to the respective folder. Signed-off-by: Andy Shevchenko Signed-off-by: Rafael J. Wysocki --- drivers/acpi/Makefile | 1 - drivers/acpi/blacklist.c | 140 ------------------------------------------- drivers/acpi/x86/Makefile | 2 + drivers/acpi/x86/blacklist.c | 140 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 142 insertions(+), 141 deletions(-) delete mode 100644 drivers/acpi/blacklist.c create mode 100644 drivers/acpi/x86/blacklist.c diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 5e14aa11c2cb..0f73a6b953b3 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -14,7 +14,6 @@ tables.o: $(src)/../../include/$(CONFIG_ACPI_CUSTOM_DSDT_FILE) ; endif obj-$(CONFIG_ACPI) += tables.o -obj-$(CONFIG_X86) += blacklist.o # # ACPI Core Subsystem (Interpreter) diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c deleted file mode 100644 index a558d24fb788..000000000000 --- a/drivers/acpi/blacklist.c +++ /dev/null @@ -1,140 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * blacklist.c - * - * Check to see if the given machine has a known bad ACPI BIOS - * or if the BIOS is too old. - * Check given machine against acpi_rev_dmi_table[]. - * - * Copyright (C) 2004 Len Brown - * Copyright (C) 2002 Andy Grover - */ - -#define pr_fmt(fmt) "ACPI: " fmt - -#include -#include -#include -#include - -#include "internal.h" - -#ifdef CONFIG_DMI -static const struct dmi_system_id acpi_rev_dmi_table[] __initconst; -#endif - -/* - * POLICY: If *anything* doesn't work, put it on the blacklist. - * If they are critical errors, mark it critical, and abort driver load. - */ -static struct acpi_platform_list acpi_blacklist[] __initdata = { - /* Compaq Presario 1700 */ - {"PTLTD ", " DSDT ", 0x06040000, ACPI_SIG_DSDT, less_than_or_equal, - "Multiple problems", 1}, - /* Sony FX120, FX140, FX150? */ - {"SONY ", "U0 ", 0x20010313, ACPI_SIG_DSDT, less_than_or_equal, - "ACPI driver problem", 1}, - /* Compaq Presario 800, Insyde BIOS */ - {"INT440", "SYSFexxx", 0x00001001, ACPI_SIG_DSDT, less_than_or_equal, - "Does not use _REG to protect EC OpRegions", 1}, - /* IBM 600E - _ADR should return 7, but it returns 1 */ - {"IBM ", "TP600E ", 0x00000105, ACPI_SIG_DSDT, less_than_or_equal, - "Incorrect _ADR", 1}, - - { } -}; - -int __init acpi_blacklisted(void) -{ - int i; - int blacklisted = 0; - - i = acpi_match_platform_list(acpi_blacklist); - if (i >= 0) { - pr_err("Vendor \"%6.6s\" System \"%8.8s\" Revision 0x%x has a known ACPI BIOS problem.\n", - acpi_blacklist[i].oem_id, - acpi_blacklist[i].oem_table_id, - acpi_blacklist[i].oem_revision); - - pr_err("Reason: %s. This is a %s error\n", - acpi_blacklist[i].reason, - (acpi_blacklist[i].data ? - "non-recoverable" : "recoverable")); - - blacklisted = acpi_blacklist[i].data; - } - - (void)early_acpi_osi_init(); -#ifdef CONFIG_DMI - dmi_check_system(acpi_rev_dmi_table); -#endif - - return blacklisted; -} -#ifdef CONFIG_DMI -#ifdef CONFIG_ACPI_REV_OVERRIDE_POSSIBLE -static int __init dmi_enable_rev_override(const struct dmi_system_id *d) -{ - pr_notice("DMI detected: %s (force ACPI _REV to 5)\n", d->ident); - acpi_rev_override_setup(NULL); - return 0; -} -#endif - -static const struct dmi_system_id acpi_rev_dmi_table[] __initconst = { -#ifdef CONFIG_ACPI_REV_OVERRIDE_POSSIBLE - /* - * DELL XPS 13 (2015) switches sound between HDA and I2S - * depending on the ACPI _REV callback. If userspace supports - * I2S sufficiently (or if you do not care about sound), you - * can safely disable this quirk. - */ - { - .callback = dmi_enable_rev_override, - .ident = "DELL XPS 13 (2015)", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "XPS 13 9343"), - }, - }, - { - .callback = dmi_enable_rev_override, - .ident = "DELL Precision 5520", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Precision 5520"), - }, - }, - { - .callback = dmi_enable_rev_override, - .ident = "DELL Precision 3520", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Precision 3520"), - }, - }, - /* - * Resolves a quirk with the Dell Latitude 3350 that - * causes the ethernet adapter to not function. - */ - { - .callback = dmi_enable_rev_override, - .ident = "DELL Latitude 3350", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Latitude 3350"), - }, - }, - { - .callback = dmi_enable_rev_override, - .ident = "DELL Inspiron 7537", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7537"), - }, - }, -#endif - {} -}; - -#endif /* CONFIG_DMI */ diff --git a/drivers/acpi/x86/Makefile b/drivers/acpi/x86/Makefile index b97b1bcf8404..1f3c5fa84f9e 100644 --- a/drivers/acpi/x86/Makefile +++ b/drivers/acpi/x86/Makefile @@ -3,3 +3,5 @@ acpi-x86-y += apple.o acpi-x86-y += cmos_rtc.o acpi-x86-y += s2idle.o acpi-x86-y += utils.o + +obj-$(CONFIG_X86) += blacklist.o diff --git a/drivers/acpi/x86/blacklist.c b/drivers/acpi/x86/blacklist.c new file mode 100644 index 000000000000..55214d0a12b1 --- /dev/null +++ b/drivers/acpi/x86/blacklist.c @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * blacklist.c + * + * Check to see if the given machine has a known bad ACPI BIOS + * or if the BIOS is too old. + * Check given machine against acpi_rev_dmi_table[]. + * + * Copyright (C) 2004 Len Brown + * Copyright (C) 2002 Andy Grover + */ + +#define pr_fmt(fmt) "ACPI: " fmt + +#include +#include +#include +#include + +#include "../internal.h" + +#ifdef CONFIG_DMI +static const struct dmi_system_id acpi_rev_dmi_table[] __initconst; +#endif + +/* + * POLICY: If *anything* doesn't work, put it on the blacklist. + * If they are critical errors, mark it critical, and abort driver load. + */ +static struct acpi_platform_list acpi_blacklist[] __initdata = { + /* Compaq Presario 1700 */ + {"PTLTD ", " DSDT ", 0x06040000, ACPI_SIG_DSDT, less_than_or_equal, + "Multiple problems", 1}, + /* Sony FX120, FX140, FX150? */ + {"SONY ", "U0 ", 0x20010313, ACPI_SIG_DSDT, less_than_or_equal, + "ACPI driver problem", 1}, + /* Compaq Presario 800, Insyde BIOS */ + {"INT440", "SYSFexxx", 0x00001001, ACPI_SIG_DSDT, less_than_or_equal, + "Does not use _REG to protect EC OpRegions", 1}, + /* IBM 600E - _ADR should return 7, but it returns 1 */ + {"IBM ", "TP600E ", 0x00000105, ACPI_SIG_DSDT, less_than_or_equal, + "Incorrect _ADR", 1}, + + { } +}; + +int __init acpi_blacklisted(void) +{ + int i; + int blacklisted = 0; + + i = acpi_match_platform_list(acpi_blacklist); + if (i >= 0) { + pr_err("Vendor \"%6.6s\" System \"%8.8s\" Revision 0x%x has a known ACPI BIOS problem.\n", + acpi_blacklist[i].oem_id, + acpi_blacklist[i].oem_table_id, + acpi_blacklist[i].oem_revision); + + pr_err("Reason: %s. This is a %s error\n", + acpi_blacklist[i].reason, + (acpi_blacklist[i].data ? + "non-recoverable" : "recoverable")); + + blacklisted = acpi_blacklist[i].data; + } + + (void)early_acpi_osi_init(); +#ifdef CONFIG_DMI + dmi_check_system(acpi_rev_dmi_table); +#endif + + return blacklisted; +} +#ifdef CONFIG_DMI +#ifdef CONFIG_ACPI_REV_OVERRIDE_POSSIBLE +static int __init dmi_enable_rev_override(const struct dmi_system_id *d) +{ + pr_notice("DMI detected: %s (force ACPI _REV to 5)\n", d->ident); + acpi_rev_override_setup(NULL); + return 0; +} +#endif + +static const struct dmi_system_id acpi_rev_dmi_table[] __initconst = { +#ifdef CONFIG_ACPI_REV_OVERRIDE_POSSIBLE + /* + * DELL XPS 13 (2015) switches sound between HDA and I2S + * depending on the ACPI _REV callback. If userspace supports + * I2S sufficiently (or if you do not care about sound), you + * can safely disable this quirk. + */ + { + .callback = dmi_enable_rev_override, + .ident = "DELL XPS 13 (2015)", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "XPS 13 9343"), + }, + }, + { + .callback = dmi_enable_rev_override, + .ident = "DELL Precision 5520", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Precision 5520"), + }, + }, + { + .callback = dmi_enable_rev_override, + .ident = "DELL Precision 3520", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Precision 3520"), + }, + }, + /* + * Resolves a quirk with the Dell Latitude 3350 that + * causes the ethernet adapter to not function. + */ + { + .callback = dmi_enable_rev_override, + .ident = "DELL Latitude 3350", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Latitude 3350"), + }, + }, + { + .callback = dmi_enable_rev_override, + .ident = "DELL Inspiron 7537", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7537"), + }, + }, +#endif + {} +}; + +#endif /* CONFIG_DMI */ -- cgit v1.2.3 From 2d5d5abebf1a342d672f738b60ea930ebc1070b0 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 4 Apr 2024 21:23:42 +0300 Subject: ACPI: x86: Move LPSS to x86 folder LPSS is built solely for x86, move it to the respective folder. Signed-off-by: Andy Shevchenko Signed-off-by: Rafael J. Wysocki --- drivers/acpi/Makefile | 1 - drivers/acpi/acpi_lpss.c | 1355 --------------------------------------------- drivers/acpi/internal.h | 3 +- drivers/acpi/x86/Makefile | 1 + drivers/acpi/x86/lpss.c | 1355 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 1358 insertions(+), 1357 deletions(-) delete mode 100644 drivers/acpi/acpi_lpss.c create mode 100644 drivers/acpi/x86/lpss.c diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 0f73a6b953b3..2046f108a91a 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -45,7 +45,6 @@ acpi-y += ec.o acpi-$(CONFIG_ACPI_DOCK) += dock.o acpi-$(CONFIG_PCI) += pci_root.o pci_link.o pci_irq.o obj-$(CONFIG_ACPI_MCFG) += pci_mcfg.o -acpi-$(CONFIG_PCI) += acpi_lpss.o acpi-y += acpi_apd.o acpi-y += acpi_platform.o acpi-y += acpi_pnp.o diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c deleted file mode 100644 index a3d2d94be5c0..000000000000 --- a/drivers/acpi/acpi_lpss.c +++ /dev/null @@ -1,1355 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * ACPI support for Intel Lynxpoint LPSS. - * - * Copyright (C) 2013, Intel Corporation - * Authors: Mika Westerberg - * Rafael J. Wysocki - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "internal.h" - -#ifdef CONFIG_X86_INTEL_LPSS - -#include -#include -#include - -#define LPSS_ADDR(desc) ((unsigned long)&desc) - -#define LPSS_CLK_SIZE 0x04 -#define LPSS_LTR_SIZE 0x18 - -/* Offsets relative to LPSS_PRIVATE_OFFSET */ -#define LPSS_CLK_DIVIDER_DEF_MASK (BIT(1) | BIT(16)) -#define LPSS_RESETS 0x04 -#define LPSS_RESETS_RESET_FUNC BIT(0) -#define LPSS_RESETS_RESET_APB BIT(1) -#define LPSS_GENERAL 0x08 -#define LPSS_GENERAL_LTR_MODE_SW BIT(2) -#define LPSS_GENERAL_UART_RTS_OVRD BIT(3) -#define LPSS_SW_LTR 0x10 -#define LPSS_AUTO_LTR 0x14 -#define LPSS_LTR_SNOOP_REQ BIT(15) -#define LPSS_LTR_SNOOP_MASK 0x0000FFFF -#define LPSS_LTR_SNOOP_LAT_1US 0x800 -#define LPSS_LTR_SNOOP_LAT_32US 0xC00 -#define LPSS_LTR_SNOOP_LAT_SHIFT 5 -#define LPSS_LTR_SNOOP_LAT_CUTOFF 3000 -#define LPSS_LTR_MAX_VAL 0x3FF -#define LPSS_TX_INT 0x20 -#define LPSS_TX_INT_MASK BIT(1) - -#define LPSS_PRV_REG_COUNT 9 - -/* LPSS Flags */ -#define LPSS_CLK BIT(0) -#define LPSS_CLK_GATE BIT(1) -#define LPSS_CLK_DIVIDER BIT(2) -#define LPSS_LTR BIT(3) -#define LPSS_SAVE_CTX BIT(4) -/* - * For some devices the DSDT AML code for another device turns off the device - * before our suspend handler runs, causing us to read/save all 1-s (0xffffffff) - * as ctx register values. - * Luckily these devices always use the same ctx register values, so we can - * work around this by saving the ctx registers once on activation. - */ -#define LPSS_SAVE_CTX_ONCE BIT(5) -#define LPSS_NO_D3_DELAY BIT(6) - -struct lpss_private_data; - -struct lpss_device_desc { - unsigned int flags; - const char *clk_con_id; - unsigned int prv_offset; - size_t prv_size_override; - const struct property_entry *properties; - void (*setup)(struct lpss_private_data *pdata); - bool resume_from_noirq; -}; - -static const struct lpss_device_desc lpss_dma_desc = { - .flags = LPSS_CLK, -}; - -struct lpss_private_data { - struct acpi_device *adev; - void __iomem *mmio_base; - resource_size_t mmio_size; - unsigned int fixed_clk_rate; - struct clk *clk; - const struct lpss_device_desc *dev_desc; - u32 prv_reg_ctx[LPSS_PRV_REG_COUNT]; -}; - -/* Devices which need to be in D3 before lpss_iosf_enter_d3_state() proceeds */ -static u32 pmc_atom_d3_mask = 0xfe000ffe; - -/* LPSS run time quirks */ -static unsigned int lpss_quirks; - -/* - * LPSS_QUIRK_ALWAYS_POWER_ON: override power state for LPSS DMA device. - * - * The LPSS DMA controller has neither _PS0 nor _PS3 method. Moreover - * it can be powered off automatically whenever the last LPSS device goes down. - * In case of no power any access to the DMA controller will hang the system. - * The behaviour is reproduced on some HP laptops based on Intel BayTrail as - * well as on ASuS T100TA transformer. - * - * This quirk overrides power state of entire LPSS island to keep DMA powered - * on whenever we have at least one other device in use. - */ -#define LPSS_QUIRK_ALWAYS_POWER_ON BIT(0) - -/* UART Component Parameter Register */ -#define LPSS_UART_CPR 0xF4 -#define LPSS_UART_CPR_AFCE BIT(4) - -static void lpss_uart_setup(struct lpss_private_data *pdata) -{ - unsigned int offset; - u32 val; - - offset = pdata->dev_desc->prv_offset + LPSS_TX_INT; - val = readl(pdata->mmio_base + offset); - writel(val | LPSS_TX_INT_MASK, pdata->mmio_base + offset); - - val = readl(pdata->mmio_base + LPSS_UART_CPR); - if (!(val & LPSS_UART_CPR_AFCE)) { - offset = pdata->dev_desc->prv_offset + LPSS_GENERAL; - val = readl(pdata->mmio_base + offset); - val |= LPSS_GENERAL_UART_RTS_OVRD; - writel(val, pdata->mmio_base + offset); - } -} - -static void lpss_deassert_reset(struct lpss_private_data *pdata) -{ - unsigned int offset; - u32 val; - - offset = pdata->dev_desc->prv_offset + LPSS_RESETS; - val = readl(pdata->mmio_base + offset); - val |= LPSS_RESETS_RESET_APB | LPSS_RESETS_RESET_FUNC; - writel(val, pdata->mmio_base + offset); -} - -/* - * BYT PWM used for backlight control by the i915 driver on systems without - * the Crystal Cove PMIC. - */ -static struct pwm_lookup byt_pwm_lookup[] = { - PWM_LOOKUP_WITH_MODULE("80860F09:00", 0, "0000:00:02.0", - "pwm_soc_backlight", 0, PWM_POLARITY_NORMAL, - "pwm-lpss-platform"), -}; - -static void byt_pwm_setup(struct lpss_private_data *pdata) -{ - /* Only call pwm_add_table for the first PWM controller */ - if (acpi_dev_uid_match(pdata->adev, 1)) - pwm_add_table(byt_pwm_lookup, ARRAY_SIZE(byt_pwm_lookup)); -} - -#define LPSS_I2C_ENABLE 0x6c - -static void byt_i2c_setup(struct lpss_private_data *pdata) -{ - acpi_handle handle = pdata->adev->handle; - unsigned long long shared_host = 0; - acpi_status status; - u64 uid; - - /* Expected to always be successfull, but better safe then sorry */ - if (!acpi_dev_uid_to_integer(pdata->adev, &uid) && uid) { - /* Detect I2C bus shared with PUNIT and ignore its d3 status */ - status = acpi_evaluate_integer(handle, "_SEM", NULL, &shared_host); - if (ACPI_SUCCESS(status) && shared_host) - pmc_atom_d3_mask &= ~(BIT_LPSS2_F1_I2C1 << (uid - 1)); - } - - lpss_deassert_reset(pdata); - - if (readl(pdata->mmio_base + pdata->dev_desc->prv_offset)) - pdata->fixed_clk_rate = 133000000; - - writel(0, pdata->mmio_base + LPSS_I2C_ENABLE); -} - -/* - * BSW PWM1 is used for backlight control by the i915 driver - * BSW PWM2 is used for backlight control for fixed (etched into the glass) - * touch controls on some models. These touch-controls have specialized - * drivers which know they need the "pwm_soc_lpss_2" con-id. - */ -static struct pwm_lookup bsw_pwm_lookup[] = { - PWM_LOOKUP_WITH_MODULE("80862288:00", 0, "0000:00:02.0", - "pwm_soc_backlight", 0, PWM_POLARITY_NORMAL, - "pwm-lpss-platform"), - PWM_LOOKUP_WITH_MODULE("80862289:00", 0, NULL, - "pwm_soc_lpss_2", 0, PWM_POLARITY_NORMAL, - "pwm-lpss-platform"), -}; - -static void bsw_pwm_setup(struct lpss_private_data *pdata) -{ - /* Only call pwm_add_table for the first PWM controller */ - if (acpi_dev_uid_match(pdata->adev, 1)) - pwm_add_table(bsw_pwm_lookup, ARRAY_SIZE(bsw_pwm_lookup)); -} - -static const struct property_entry lpt_spi_properties[] = { - PROPERTY_ENTRY_U32("intel,spi-pxa2xx-type", LPSS_LPT_SSP), - { } -}; - -static const struct lpss_device_desc lpt_spi_dev_desc = { - .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_LTR - | LPSS_SAVE_CTX, - .prv_offset = 0x800, - .properties = lpt_spi_properties, -}; - -static const struct lpss_device_desc lpt_i2c_dev_desc = { - .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_LTR | LPSS_SAVE_CTX, - .prv_offset = 0x800, -}; - -static struct property_entry uart_properties[] = { - PROPERTY_ENTRY_U32("reg-io-width", 4), - PROPERTY_ENTRY_U32("reg-shift", 2), - PROPERTY_ENTRY_BOOL("snps,uart-16550-compatible"), - { }, -}; - -static const struct lpss_device_desc lpt_uart_dev_desc = { - .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_LTR - | LPSS_SAVE_CTX, - .clk_con_id = "baudclk", - .prv_offset = 0x800, - .setup = lpss_uart_setup, - .properties = uart_properties, -}; - -static const struct lpss_device_desc lpt_sdio_dev_desc = { - .flags = LPSS_LTR, - .prv_offset = 0x1000, - .prv_size_override = 0x1018, -}; - -static const struct lpss_device_desc byt_pwm_dev_desc = { - .flags = LPSS_SAVE_CTX, - .prv_offset = 0x800, - .setup = byt_pwm_setup, -}; - -static const struct lpss_device_desc bsw_pwm_dev_desc = { - .flags = LPSS_SAVE_CTX_ONCE | LPSS_NO_D3_DELAY, - .prv_offset = 0x800, - .setup = bsw_pwm_setup, - .resume_from_noirq = true, -}; - -static const struct lpss_device_desc bsw_pwm2_dev_desc = { - .flags = LPSS_SAVE_CTX_ONCE | LPSS_NO_D3_DELAY, - .prv_offset = 0x800, - .resume_from_noirq = true, -}; - -static const struct lpss_device_desc byt_uart_dev_desc = { - .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX, - .clk_con_id = "baudclk", - .prv_offset = 0x800, - .setup = lpss_uart_setup, - .properties = uart_properties, -}; - -static const struct lpss_device_desc bsw_uart_dev_desc = { - .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX - | LPSS_NO_D3_DELAY, - .clk_con_id = "baudclk", - .prv_offset = 0x800, - .setup = lpss_uart_setup, - .properties = uart_properties, -}; - -static const struct property_entry byt_spi_properties[] = { - PROPERTY_ENTRY_U32("intel,spi-pxa2xx-type", LPSS_BYT_SSP), - { } -}; - -static const struct lpss_device_desc byt_spi_dev_desc = { - .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX, - .prv_offset = 0x400, - .properties = byt_spi_properties, -}; - -static const struct lpss_device_desc byt_sdio_dev_desc = { - .flags = LPSS_CLK, -}; - -static const struct lpss_device_desc byt_i2c_dev_desc = { - .flags = LPSS_CLK | LPSS_SAVE_CTX, - .prv_offset = 0x800, - .setup = byt_i2c_setup, - .resume_from_noirq = true, -}; - -static const struct lpss_device_desc bsw_i2c_dev_desc = { - .flags = LPSS_CLK | LPSS_SAVE_CTX | LPSS_NO_D3_DELAY, - .prv_offset = 0x800, - .setup = byt_i2c_setup, - .resume_from_noirq = true, -}; - -static const struct property_entry bsw_spi_properties[] = { - PROPERTY_ENTRY_U32("intel,spi-pxa2xx-type", LPSS_BSW_SSP), - PROPERTY_ENTRY_U32("num-cs", 2), - { } -}; - -static const struct lpss_device_desc bsw_spi_dev_desc = { - .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX - | LPSS_NO_D3_DELAY, - .prv_offset = 0x400, - .setup = lpss_deassert_reset, - .properties = bsw_spi_properties, -}; - -static const struct x86_cpu_id lpss_cpu_ids[] = { - X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT, NULL), - X86_MATCH_INTEL_FAM6_MODEL(ATOM_AIRMONT, NULL), - {} -}; - -#else - -#define LPSS_ADDR(desc) (0UL) - -#endif /* CONFIG_X86_INTEL_LPSS */ - -static const struct acpi_device_id acpi_lpss_device_ids[] = { - /* Generic LPSS devices */ - { "INTL9C60", LPSS_ADDR(lpss_dma_desc) }, - - /* Lynxpoint LPSS devices */ - { "INT33C0", LPSS_ADDR(lpt_spi_dev_desc) }, - { "INT33C1", LPSS_ADDR(lpt_spi_dev_desc) }, - { "INT33C2", LPSS_ADDR(lpt_i2c_dev_desc) }, - { "INT33C3", LPSS_ADDR(lpt_i2c_dev_desc) }, - { "INT33C4", LPSS_ADDR(lpt_uart_dev_desc) }, - { "INT33C5", LPSS_ADDR(lpt_uart_dev_desc) }, - { "INT33C6", LPSS_ADDR(lpt_sdio_dev_desc) }, - - /* BayTrail LPSS devices */ - { "80860F09", LPSS_ADDR(byt_pwm_dev_desc) }, - { "80860F0A", LPSS_ADDR(byt_uart_dev_desc) }, - { "80860F0E", LPSS_ADDR(byt_spi_dev_desc) }, - { "80860F14", LPSS_ADDR(byt_sdio_dev_desc) }, - { "80860F41", LPSS_ADDR(byt_i2c_dev_desc) }, - - /* Braswell LPSS devices */ - { "80862286", LPSS_ADDR(lpss_dma_desc) }, - { "80862288", LPSS_ADDR(bsw_pwm_dev_desc) }, - { "80862289", LPSS_ADDR(bsw_pwm2_dev_desc) }, - { "8086228A", LPSS_ADDR(bsw_uart_dev_desc) }, - { "8086228E", LPSS_ADDR(bsw_spi_dev_desc) }, - { "808622C0", LPSS_ADDR(lpss_dma_desc) }, - { "808622C1", LPSS_ADDR(bsw_i2c_dev_desc) }, - - /* Broadwell LPSS devices */ - { "INT3430", LPSS_ADDR(lpt_spi_dev_desc) }, - { "INT3431", LPSS_ADDR(lpt_spi_dev_desc) }, - { "INT3432", LPSS_ADDR(lpt_i2c_dev_desc) }, - { "INT3433", LPSS_ADDR(lpt_i2c_dev_desc) }, - { "INT3434", LPSS_ADDR(lpt_uart_dev_desc) }, - { "INT3435", LPSS_ADDR(lpt_uart_dev_desc) }, - { "INT3436", LPSS_ADDR(lpt_sdio_dev_desc) }, - - /* Wildcat Point LPSS devices */ - { "INT3438", LPSS_ADDR(lpt_spi_dev_desc) }, - - { } -}; - -#ifdef CONFIG_X86_INTEL_LPSS - -/* LPSS main clock device. */ -static struct platform_device *lpss_clk_dev; - -static inline void lpt_register_clock_device(void) -{ - lpss_clk_dev = platform_device_register_simple("clk-lpss-atom", - PLATFORM_DEVID_NONE, - NULL, 0); -} - -static int register_device_clock(struct acpi_device *adev, - struct lpss_private_data *pdata) -{ - const struct lpss_device_desc *dev_desc = pdata->dev_desc; - const char *devname = dev_name(&adev->dev); - struct clk *clk; - struct lpss_clk_data *clk_data; - const char *parent, *clk_name; - void __iomem *prv_base; - - if (!lpss_clk_dev) - lpt_register_clock_device(); - - if (IS_ERR(lpss_clk_dev)) - return PTR_ERR(lpss_clk_dev); - - clk_data = platform_get_drvdata(lpss_clk_dev); - if (!clk_data) - return -ENODEV; - clk = clk_data->clk; - - if (!pdata->mmio_base - || pdata->mmio_size < dev_desc->prv_offset + LPSS_CLK_SIZE) - return -ENODATA; - - parent = clk_data->name; - prv_base = pdata->mmio_base + dev_desc->prv_offset; - - if (pdata->fixed_clk_rate) { - clk = clk_register_fixed_rate(NULL, devname, parent, 0, - pdata->fixed_clk_rate); - goto out; - } - - if (dev_desc->flags & LPSS_CLK_GATE) { - clk = clk_register_gate(NULL, devname, parent, 0, - prv_base, 0, 0, NULL); - parent = devname; - } - - if (dev_desc->flags & LPSS_CLK_DIVIDER) { - /* Prevent division by zero */ - if (!readl(prv_base)) - writel(LPSS_CLK_DIVIDER_DEF_MASK, prv_base); - - clk_name = kasprintf(GFP_KERNEL, "%s-div", devname); - if (!clk_name) - return -ENOMEM; - clk = clk_register_fractional_divider(NULL, clk_name, parent, - 0, prv_base, 1, 15, 16, 15, - CLK_FRAC_DIVIDER_POWER_OF_TWO_PS, - NULL); - parent = clk_name; - - clk_name = kasprintf(GFP_KERNEL, "%s-update", devname); - if (!clk_name) { - kfree(parent); - return -ENOMEM; - } - clk = clk_register_gate(NULL, clk_name, parent, - CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, - prv_base, 31, 0, NULL); - kfree(parent); - kfree(clk_name); - } -out: - if (IS_ERR(clk)) - return PTR_ERR(clk); - - pdata->clk = clk; - clk_register_clkdev(clk, dev_desc->clk_con_id, devname); - return 0; -} - -struct lpss_device_links { - const char *supplier_hid; - const char *supplier_uid; - const char *consumer_hid; - const char *consumer_uid; - u32 flags; - const struct dmi_system_id *dep_missing_ids; -}; - -/* Please keep this list sorted alphabetically by vendor and model */ -static const struct dmi_system_id i2c1_dep_missing_dmi_ids[] = { - { - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), - DMI_MATCH(DMI_PRODUCT_NAME, "T200TA"), - }, - }, - {} -}; - -/* - * The _DEP method is used to identify dependencies but instead of creating - * device links for every handle in _DEP, only links in the following list are - * created. That is necessary because, in the general case, _DEP can refer to - * devices that might not have drivers, or that are on different buses, or where - * the supplier is not enumerated until after the consumer is probed. - */ -static const struct lpss_device_links lpss_device_links[] = { - /* CHT External sdcard slot controller depends on PMIC I2C ctrl */ - {"808622C1", "7", "80860F14", "3", DL_FLAG_PM_RUNTIME}, - /* CHT iGPU depends on PMIC I2C controller */ - {"808622C1", "7", "LNXVIDEO", NULL, DL_FLAG_PM_RUNTIME}, - /* BYT iGPU depends on the Embedded Controller I2C controller (UID 1) */ - {"80860F41", "1", "LNXVIDEO", NULL, DL_FLAG_PM_RUNTIME, - i2c1_dep_missing_dmi_ids}, - /* BYT CR iGPU depends on PMIC I2C controller (UID 5 on CR) */ - {"80860F41", "5", "LNXVIDEO", NULL, DL_FLAG_PM_RUNTIME}, - /* BYT iGPU depends on PMIC I2C controller (UID 7 on non CR) */ - {"80860F41", "7", "LNXVIDEO", NULL, DL_FLAG_PM_RUNTIME}, -}; - -static bool acpi_lpss_is_supplier(struct acpi_device *adev, - const struct lpss_device_links *link) -{ - return acpi_dev_hid_uid_match(adev, link->supplier_hid, link->supplier_uid); -} - -static bool acpi_lpss_is_consumer(struct acpi_device *adev, - const struct lpss_device_links *link) -{ - return acpi_dev_hid_uid_match(adev, link->consumer_hid, link->consumer_uid); -} - -struct hid_uid { - const char *hid; - const char *uid; -}; - -static int match_hid_uid(struct device *dev, const void *data) -{ - struct acpi_device *adev = ACPI_COMPANION(dev); - const struct hid_uid *id = data; - - if (!adev) - return 0; - - return acpi_dev_hid_uid_match(adev, id->hid, id->uid); -} - -static struct device *acpi_lpss_find_device(const char *hid, const char *uid) -{ - struct device *dev; - - struct hid_uid data = { - .hid = hid, - .uid = uid, - }; - - dev = bus_find_device(&platform_bus_type, NULL, &data, match_hid_uid); - if (dev) - return dev; - - return bus_find_device(&pci_bus_type, NULL, &data, match_hid_uid); -} - -static void acpi_lpss_link_consumer(struct device *dev1, - const struct lpss_device_links *link) -{ - struct device *dev2; - - dev2 = acpi_lpss_find_device(link->consumer_hid, link->consumer_uid); - if (!dev2) - return; - - if ((link->dep_missing_ids && dmi_check_system(link->dep_missing_ids)) - || acpi_device_dep(ACPI_HANDLE(dev2), ACPI_HANDLE(dev1))) - device_link_add(dev2, dev1, link->flags); - - put_device(dev2); -} - -static void acpi_lpss_link_supplier(struct device *dev1, - const struct lpss_device_links *link) -{ - struct device *dev2; - - dev2 = acpi_lpss_find_device(link->supplier_hid, link->supplier_uid); - if (!dev2) - return; - - if ((link->dep_missing_ids && dmi_check_system(link->dep_missing_ids)) - || acpi_device_dep(ACPI_HANDLE(dev1), ACPI_HANDLE(dev2))) - device_link_add(dev1, dev2, link->flags); - - put_device(dev2); -} - -static void acpi_lpss_create_device_links(struct acpi_device *adev, - struct platform_device *pdev) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(lpss_device_links); i++) { - const struct lpss_device_links *link = &lpss_device_links[i]; - - if (acpi_lpss_is_supplier(adev, link)) - acpi_lpss_link_consumer(&pdev->dev, link); - - if (acpi_lpss_is_consumer(adev, link)) - acpi_lpss_link_supplier(&pdev->dev, link); - } -} - -static int acpi_lpss_create_device(struct acpi_device *adev, - const struct acpi_device_id *id) -{ - const struct lpss_device_desc *dev_desc; - struct lpss_private_data *pdata; - struct resource_entry *rentry; - struct list_head resource_list; - struct platform_device *pdev; - int ret; - - dev_desc = (const struct lpss_device_desc *)id->driver_data; - if (!dev_desc) - return -EINVAL; - - pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); - if (!pdata) - return -ENOMEM; - - INIT_LIST_HEAD(&resource_list); - ret = acpi_dev_get_memory_resources(adev, &resource_list); - if (ret < 0) - goto err_out; - - rentry = list_first_entry_or_null(&resource_list, struct resource_entry, node); - if (rentry) { - if (dev_desc->prv_size_override) - pdata->mmio_size = dev_desc->prv_size_override; - else - pdata->mmio_size = resource_size(rentry->res); - pdata->mmio_base = ioremap(rentry->res->start, pdata->mmio_size); - } - - acpi_dev_free_resource_list(&resource_list); - - if (!pdata->mmio_base) { - /* Avoid acpi_bus_attach() instantiating a pdev for this dev. */ - adev->pnp.type.platform_id = 0; - goto out_free; - } - - pdata->adev = adev; - pdata->dev_desc = dev_desc; - - if (dev_desc->setup) - dev_desc->setup(pdata); - - if (dev_desc->flags & LPSS_CLK) { - ret = register_device_clock(adev, pdata); - if (ret) - goto out_free; - } - - /* - * This works around a known issue in ACPI tables where LPSS devices - * have _PS0 and _PS3 without _PSC (and no power resources), so - * acpi_bus_init_power() will assume that the BIOS has put them into D0. - */ - acpi_device_fix_up_power(adev); - - adev->driver_data = pdata; - pdev = acpi_create_platform_device(adev, dev_desc->properties); - if (IS_ERR_OR_NULL(pdev)) { - adev->driver_data = NULL; - ret = PTR_ERR(pdev); - goto err_out; - } - - acpi_lpss_create_device_links(adev, pdev); - return 1; - -out_free: - /* Skip the device, but continue the namespace scan */ - ret = 0; -err_out: - kfree(pdata); - return ret; -} - -static u32 __lpss_reg_read(struct lpss_private_data *pdata, unsigned int reg) -{ - return readl(pdata->mmio_base + pdata->dev_desc->prv_offset + reg); -} - -static void __lpss_reg_write(u32 val, struct lpss_private_data *pdata, - unsigned int reg) -{ - writel(val, pdata->mmio_base + pdata->dev_desc->prv_offset + reg); -} - -static int lpss_reg_read(struct device *dev, unsigned int reg, u32 *val) -{ - struct acpi_device *adev = ACPI_COMPANION(dev); - struct lpss_private_data *pdata; - unsigned long flags; - int ret; - - if (WARN_ON(!adev)) - return -ENODEV; - - spin_lock_irqsave(&dev->power.lock, flags); - if (pm_runtime_suspended(dev)) { - ret = -EAGAIN; - goto out; - } - pdata = acpi_driver_data(adev); - if (WARN_ON(!pdata || !pdata->mmio_base)) { - ret = -ENODEV; - goto out; - } - *val = __lpss_reg_read(pdata, reg); - ret = 0; - - out: - spin_unlock_irqrestore(&dev->power.lock, flags); - return ret; -} - -static ssize_t lpss_ltr_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - u32 ltr_value = 0; - unsigned int reg; - int ret; - - reg = strcmp(attr->attr.name, "auto_ltr") ? LPSS_SW_LTR : LPSS_AUTO_LTR; - ret = lpss_reg_read(dev, reg, <r_value); - if (ret) - return ret; - - return sysfs_emit(buf, "%08x\n", ltr_value); -} - -static ssize_t lpss_ltr_mode_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - u32 ltr_mode = 0; - char *outstr; - int ret; - - ret = lpss_reg_read(dev, LPSS_GENERAL, <r_mode); - if (ret) - return ret; - - outstr = (ltr_mode & LPSS_GENERAL_LTR_MODE_SW) ? "sw" : "auto"; - return sprintf(buf, "%s\n", outstr); -} - -static DEVICE_ATTR(auto_ltr, S_IRUSR, lpss_ltr_show, NULL); -static DEVICE_ATTR(sw_ltr, S_IRUSR, lpss_ltr_show, NULL); -static DEVICE_ATTR(ltr_mode, S_IRUSR, lpss_ltr_mode_show, NULL); - -static struct attribute *lpss_attrs[] = { - &dev_attr_auto_ltr.attr, - &dev_attr_sw_ltr.attr, - &dev_attr_ltr_mode.attr, - NULL, -}; - -static const struct attribute_group lpss_attr_group = { - .attrs = lpss_attrs, - .name = "lpss_ltr", -}; - -static void acpi_lpss_set_ltr(struct device *dev, s32 val) -{ - struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); - u32 ltr_mode, ltr_val; - - ltr_mode = __lpss_reg_read(pdata, LPSS_GENERAL); - if (val < 0) { - if (ltr_mode & LPSS_GENERAL_LTR_MODE_SW) { - ltr_mode &= ~LPSS_GENERAL_LTR_MODE_SW; - __lpss_reg_write(ltr_mode, pdata, LPSS_GENERAL); - } - return; - } - ltr_val = __lpss_reg_read(pdata, LPSS_SW_LTR) & ~LPSS_LTR_SNOOP_MASK; - if (val >= LPSS_LTR_SNOOP_LAT_CUTOFF) { - ltr_val |= LPSS_LTR_SNOOP_LAT_32US; - val = LPSS_LTR_MAX_VAL; - } else if (val > LPSS_LTR_MAX_VAL) { - ltr_val |= LPSS_LTR_SNOOP_LAT_32US | LPSS_LTR_SNOOP_REQ; - val >>= LPSS_LTR_SNOOP_LAT_SHIFT; - } else { - ltr_val |= LPSS_LTR_SNOOP_LAT_1US | LPSS_LTR_SNOOP_REQ; - } - ltr_val |= val; - __lpss_reg_write(ltr_val, pdata, LPSS_SW_LTR); - if (!(ltr_mode & LPSS_GENERAL_LTR_MODE_SW)) { - ltr_mode |= LPSS_GENERAL_LTR_MODE_SW; - __lpss_reg_write(ltr_mode, pdata, LPSS_GENERAL); - } -} - -#ifdef CONFIG_PM -/** - * acpi_lpss_save_ctx() - Save the private registers of LPSS device - * @dev: LPSS device - * @pdata: pointer to the private data of the LPSS device - * - * Most LPSS devices have private registers which may loose their context when - * the device is powered down. acpi_lpss_save_ctx() saves those registers into - * prv_reg_ctx array. - */ -static void acpi_lpss_save_ctx(struct device *dev, - struct lpss_private_data *pdata) -{ - unsigned int i; - - for (i = 0; i < LPSS_PRV_REG_COUNT; i++) { - unsigned long offset = i * sizeof(u32); - - pdata->prv_reg_ctx[i] = __lpss_reg_read(pdata, offset); - dev_dbg(dev, "saving 0x%08x from LPSS reg at offset 0x%02lx\n", - pdata->prv_reg_ctx[i], offset); - } -} - -/** - * acpi_lpss_restore_ctx() - Restore the private registers of LPSS device - * @dev: LPSS device - * @pdata: pointer to the private data of the LPSS device - * - * Restores the registers that were previously stored with acpi_lpss_save_ctx(). - */ -static void acpi_lpss_restore_ctx(struct device *dev, - struct lpss_private_data *pdata) -{ - unsigned int i; - - for (i = 0; i < LPSS_PRV_REG_COUNT; i++) { - unsigned long offset = i * sizeof(u32); - - __lpss_reg_write(pdata->prv_reg_ctx[i], pdata, offset); - dev_dbg(dev, "restoring 0x%08x to LPSS reg at offset 0x%02lx\n", - pdata->prv_reg_ctx[i], offset); - } -} - -static void acpi_lpss_d3_to_d0_delay(struct lpss_private_data *pdata) -{ - /* - * The following delay is needed or the subsequent write operations may - * fail. The LPSS devices are actually PCI devices and the PCI spec - * expects 10ms delay before the device can be accessed after D3 to D0 - * transition. However some platforms like BSW does not need this delay. - */ - unsigned int delay = 10; /* default 10ms delay */ - - if (pdata->dev_desc->flags & LPSS_NO_D3_DELAY) - delay = 0; - - msleep(delay); -} - -static int acpi_lpss_activate(struct device *dev) -{ - struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); - int ret; - - ret = acpi_dev_resume(dev); - if (ret) - return ret; - - acpi_lpss_d3_to_d0_delay(pdata); - - /* - * This is called only on ->probe() stage where a device is either in - * known state defined by BIOS or most likely powered off. Due to this - * we have to deassert reset line to be sure that ->probe() will - * recognize the device. - */ - if (pdata->dev_desc->flags & (LPSS_SAVE_CTX | LPSS_SAVE_CTX_ONCE)) - lpss_deassert_reset(pdata); - - if (pdata->dev_desc->flags & LPSS_SAVE_CTX_ONCE) - acpi_lpss_save_ctx(dev, pdata); - - return 0; -} - -static void acpi_lpss_dismiss(struct device *dev) -{ - acpi_dev_suspend(dev, false); -} - -/* IOSF SB for LPSS island */ -#define LPSS_IOSF_UNIT_LPIOEP 0xA0 -#define LPSS_IOSF_UNIT_LPIO1 0xAB -#define LPSS_IOSF_UNIT_LPIO2 0xAC - -#define LPSS_IOSF_PMCSR 0x84 -#define LPSS_PMCSR_D0 0 -#define LPSS_PMCSR_D3hot 3 -#define LPSS_PMCSR_Dx_MASK GENMASK(1, 0) - -#define LPSS_IOSF_GPIODEF0 0x154 -#define LPSS_GPIODEF0_DMA1_D3 BIT(2) -#define LPSS_GPIODEF0_DMA2_D3 BIT(3) -#define LPSS_GPIODEF0_DMA_D3_MASK GENMASK(3, 2) -#define LPSS_GPIODEF0_DMA_LLP BIT(13) - -static DEFINE_MUTEX(lpss_iosf_mutex); -static bool lpss_iosf_d3_entered = true; - -static void lpss_iosf_enter_d3_state(void) -{ - u32 value1 = 0; - u32 mask1 = LPSS_GPIODEF0_DMA_D3_MASK | LPSS_GPIODEF0_DMA_LLP; - u32 value2 = LPSS_PMCSR_D3hot; - u32 mask2 = LPSS_PMCSR_Dx_MASK; - /* - * PMC provides an information about actual status of the LPSS devices. - * Here we read the values related to LPSS power island, i.e. LPSS - * devices, excluding both LPSS DMA controllers, along with SCC domain. - */ - u32 func_dis, d3_sts_0, pmc_status; - int ret; - - ret = pmc_atom_read(PMC_FUNC_DIS, &func_dis); - if (ret) - return; - - mutex_lock(&lpss_iosf_mutex); - - ret = pmc_atom_read(PMC_D3_STS_0, &d3_sts_0); - if (ret) - goto exit; - - /* - * Get the status of entire LPSS power island per device basis. - * Shutdown both LPSS DMA controllers if and only if all other devices - * are already in D3hot. - */ - pmc_status = (~(d3_sts_0 | func_dis)) & pmc_atom_d3_mask; - if (pmc_status) - goto exit; - - iosf_mbi_modify(LPSS_IOSF_UNIT_LPIO1, MBI_CFG_WRITE, - LPSS_IOSF_PMCSR, value2, mask2); - - iosf_mbi_modify(LPSS_IOSF_UNIT_LPIO2, MBI_CFG_WRITE, - LPSS_IOSF_PMCSR, value2, mask2); - - iosf_mbi_modify(LPSS_IOSF_UNIT_LPIOEP, MBI_CR_WRITE, - LPSS_IOSF_GPIODEF0, value1, mask1); - - lpss_iosf_d3_entered = true; - -exit: - mutex_unlock(&lpss_iosf_mutex); -} - -static void lpss_iosf_exit_d3_state(void) -{ - u32 value1 = LPSS_GPIODEF0_DMA1_D3 | LPSS_GPIODEF0_DMA2_D3 | - LPSS_GPIODEF0_DMA_LLP; - u32 mask1 = LPSS_GPIODEF0_DMA_D3_MASK | LPSS_GPIODEF0_DMA_LLP; - u32 value2 = LPSS_PMCSR_D0; - u32 mask2 = LPSS_PMCSR_Dx_MASK; - - mutex_lock(&lpss_iosf_mutex); - - if (!lpss_iosf_d3_entered) - goto exit; - - lpss_iosf_d3_entered = false; - - iosf_mbi_modify(LPSS_IOSF_UNIT_LPIOEP, MBI_CR_WRITE, - LPSS_IOSF_GPIODEF0, value1, mask1); - - iosf_mbi_modify(LPSS_IOSF_UNIT_LPIO2, MBI_CFG_WRITE, - LPSS_IOSF_PMCSR, value2, mask2); - - iosf_mbi_modify(LPSS_IOSF_UNIT_LPIO1, MBI_CFG_WRITE, - LPSS_IOSF_PMCSR, value2, mask2); - -exit: - mutex_unlock(&lpss_iosf_mutex); -} - -static int acpi_lpss_suspend(struct device *dev, bool wakeup) -{ - struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); - int ret; - - if (pdata->dev_desc->flags & LPSS_SAVE_CTX) - acpi_lpss_save_ctx(dev, pdata); - - ret = acpi_dev_suspend(dev, wakeup); - - /* - * This call must be last in the sequence, otherwise PMC will return - * wrong status for devices being about to be powered off. See - * lpss_iosf_enter_d3_state() for further information. - */ - if (acpi_target_system_state() == ACPI_STATE_S0 && - lpss_quirks & LPSS_QUIRK_ALWAYS_POWER_ON && iosf_mbi_available()) - lpss_iosf_enter_d3_state(); - - return ret; -} - -static int acpi_lpss_resume(struct device *dev) -{ - struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); - int ret; - - /* - * This call is kept first to be in symmetry with - * acpi_lpss_runtime_suspend() one. - */ - if (lpss_quirks & LPSS_QUIRK_ALWAYS_POWER_ON && iosf_mbi_available()) - lpss_iosf_exit_d3_state(); - - ret = acpi_dev_resume(dev); - if (ret) - return ret; - - acpi_lpss_d3_to_d0_delay(pdata); - - if (pdata->dev_desc->flags & (LPSS_SAVE_CTX | LPSS_SAVE_CTX_ONCE)) - acpi_lpss_restore_ctx(dev, pdata); - - return 0; -} - -#ifdef CONFIG_PM_SLEEP -static int acpi_lpss_do_suspend_late(struct device *dev) -{ - int ret; - - if (dev_pm_skip_suspend(dev)) - return 0; - - ret = pm_generic_suspend_late(dev); - return ret ? ret : acpi_lpss_suspend(dev, device_may_wakeup(dev)); -} - -static int acpi_lpss_suspend_late(struct device *dev) -{ - struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); - - if (pdata->dev_desc->resume_from_noirq) - return 0; - - return acpi_lpss_do_suspend_late(dev); -} - -static int acpi_lpss_suspend_noirq(struct device *dev) -{ - struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); - int ret; - - if (pdata->dev_desc->resume_from_noirq) { - /* - * The driver's ->suspend_late callback will be invoked by - * acpi_lpss_do_suspend_late(), with the assumption that the - * driver really wanted to run that code in ->suspend_noirq, but - * it could not run after acpi_dev_suspend() and the driver - * expected the latter to be called in the "late" phase. - */ - ret = acpi_lpss_do_suspend_late(dev); - if (ret) - return ret; - } - - return acpi_subsys_suspend_noirq(dev); -} - -static int acpi_lpss_do_resume_early(struct device *dev) -{ - int ret = acpi_lpss_resume(dev); - - return ret ? ret : pm_generic_resume_early(dev); -} - -static int acpi_lpss_resume_early(struct device *dev) -{ - struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); - - if (pdata->dev_desc->resume_from_noirq) - return 0; - - if (dev_pm_skip_resume(dev)) - return 0; - - return acpi_lpss_do_resume_early(dev); -} - -static int acpi_lpss_resume_noirq(struct device *dev) -{ - struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); - int ret; - - /* Follow acpi_subsys_resume_noirq(). */ - if (dev_pm_skip_resume(dev)) - return 0; - - ret = pm_generic_resume_noirq(dev); - if (ret) - return ret; - - if (!pdata->dev_desc->resume_from_noirq) - return 0; - - /* - * The driver's ->resume_early callback will be invoked by - * acpi_lpss_do_resume_early(), with the assumption that the driver - * really wanted to run that code in ->resume_noirq, but it could not - * run before acpi_dev_resume() and the driver expected the latter to be - * called in the "early" phase. - */ - return acpi_lpss_do_resume_early(dev); -} - -static int acpi_lpss_do_restore_early(struct device *dev) -{ - int ret = acpi_lpss_resume(dev); - - return ret ? ret : pm_generic_restore_early(dev); -} - -static int acpi_lpss_restore_early(struct device *dev) -{ - struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); - - if (pdata->dev_desc->resume_from_noirq) - return 0; - - return acpi_lpss_do_restore_early(dev); -} - -static int acpi_lpss_restore_noirq(struct device *dev) -{ - struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); - int ret; - - ret = pm_generic_restore_noirq(dev); - if (ret) - return ret; - - if (!pdata->dev_desc->resume_from_noirq) - return 0; - - /* This is analogous to what happens in acpi_lpss_resume_noirq(). */ - return acpi_lpss_do_restore_early(dev); -} - -static int acpi_lpss_do_poweroff_late(struct device *dev) -{ - int ret = pm_generic_poweroff_late(dev); - - return ret ? ret : acpi_lpss_suspend(dev, device_may_wakeup(dev)); -} - -static int acpi_lpss_poweroff_late(struct device *dev) -{ - struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); - - if (dev_pm_skip_suspend(dev)) - return 0; - - if (pdata->dev_desc->resume_from_noirq) - return 0; - - return acpi_lpss_do_poweroff_late(dev); -} - -static int acpi_lpss_poweroff_noirq(struct device *dev) -{ - struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); - - if (dev_pm_skip_suspend(dev)) - return 0; - - if (pdata->dev_desc->resume_from_noirq) { - /* This is analogous to the acpi_lpss_suspend_noirq() case. */ - int ret = acpi_lpss_do_poweroff_late(dev); - - if (ret) - return ret; - } - - return pm_generic_poweroff_noirq(dev); -} -#endif /* CONFIG_PM_SLEEP */ - -static int acpi_lpss_runtime_suspend(struct device *dev) -{ - int ret = pm_generic_runtime_suspend(dev); - - return ret ? ret : acpi_lpss_suspend(dev, true); -} - -static int acpi_lpss_runtime_resume(struct device *dev) -{ - int ret = acpi_lpss_resume(dev); - - return ret ? ret : pm_generic_runtime_resume(dev); -} -#endif /* CONFIG_PM */ - -static struct dev_pm_domain acpi_lpss_pm_domain = { -#ifdef CONFIG_PM - .activate = acpi_lpss_activate, - .dismiss = acpi_lpss_dismiss, -#endif - .ops = { -#ifdef CONFIG_PM -#ifdef CONFIG_PM_SLEEP - .prepare = acpi_subsys_prepare, - .complete = acpi_subsys_complete, - .suspend = acpi_subsys_suspend, - .suspend_late = acpi_lpss_suspend_late, - .suspend_noirq = acpi_lpss_suspend_noirq, - .resume_noirq = acpi_lpss_resume_noirq, - .resume_early = acpi_lpss_resume_early, - .freeze = acpi_subsys_freeze, - .poweroff = acpi_subsys_poweroff, - .poweroff_late = acpi_lpss_poweroff_late, - .poweroff_noirq = acpi_lpss_poweroff_noirq, - .restore_noirq = acpi_lpss_restore_noirq, - .restore_early = acpi_lpss_restore_early, -#endif - .runtime_suspend = acpi_lpss_runtime_suspend, - .runtime_resume = acpi_lpss_runtime_resume, -#endif - }, -}; - -static int acpi_lpss_platform_notify(struct notifier_block *nb, - unsigned long action, void *data) -{ - struct platform_device *pdev = to_platform_device(data); - struct lpss_private_data *pdata; - struct acpi_device *adev; - const struct acpi_device_id *id; - - id = acpi_match_device(acpi_lpss_device_ids, &pdev->dev); - if (!id || !id->driver_data) - return 0; - - adev = ACPI_COMPANION(&pdev->dev); - if (!adev) - return 0; - - pdata = acpi_driver_data(adev); - if (!pdata) - return 0; - - if (pdata->mmio_base && - pdata->mmio_size < pdata->dev_desc->prv_offset + LPSS_LTR_SIZE) { - dev_err(&pdev->dev, "MMIO size insufficient to access LTR\n"); - return 0; - } - - switch (action) { - case BUS_NOTIFY_BIND_DRIVER: - dev_pm_domain_set(&pdev->dev, &acpi_lpss_pm_domain); - break; - case BUS_NOTIFY_DRIVER_NOT_BOUND: - case BUS_NOTIFY_UNBOUND_DRIVER: - dev_pm_domain_set(&pdev->dev, NULL); - break; - case BUS_NOTIFY_ADD_DEVICE: - dev_pm_domain_set(&pdev->dev, &acpi_lpss_pm_domain); - if (pdata->dev_desc->flags & LPSS_LTR) - return sysfs_create_group(&pdev->dev.kobj, - &lpss_attr_group); - break; - case BUS_NOTIFY_DEL_DEVICE: - if (pdata->dev_desc->flags & LPSS_LTR) - sysfs_remove_group(&pdev->dev.kobj, &lpss_attr_group); - dev_pm_domain_set(&pdev->dev, NULL); - break; - default: - break; - } - - return 0; -} - -static struct notifier_block acpi_lpss_nb = { - .notifier_call = acpi_lpss_platform_notify, -}; - -static void acpi_lpss_bind(struct device *dev) -{ - struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); - - if (!pdata || !pdata->mmio_base || !(pdata->dev_desc->flags & LPSS_LTR)) - return; - - if (pdata->mmio_size >= pdata->dev_desc->prv_offset + LPSS_LTR_SIZE) - dev->power.set_latency_tolerance = acpi_lpss_set_ltr; - else - dev_err(dev, "MMIO size insufficient to access LTR\n"); -} - -static void acpi_lpss_unbind(struct device *dev) -{ - dev->power.set_latency_tolerance = NULL; -} - -static struct acpi_scan_handler lpss_handler = { - .ids = acpi_lpss_device_ids, - .attach = acpi_lpss_create_device, - .bind = acpi_lpss_bind, - .unbind = acpi_lpss_unbind, -}; - -void __init acpi_lpss_init(void) -{ - const struct x86_cpu_id *id; - int ret; - - ret = lpss_atom_clk_init(); - if (ret) - return; - - id = x86_match_cpu(lpss_cpu_ids); - if (id) - lpss_quirks |= LPSS_QUIRK_ALWAYS_POWER_ON; - - bus_register_notifier(&platform_bus_type, &acpi_lpss_nb); - acpi_scan_add_handler(&lpss_handler); -} - -#else - -static struct acpi_scan_handler lpss_handler = { - .ids = acpi_lpss_device_ids, -}; - -void __init acpi_lpss_init(void) -{ - acpi_scan_add_handler(&lpss_handler); -} - -#endif /* CONFIG_X86_INTEL_LPSS */ diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index ca72a0dc5715..60c483836756 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -69,7 +69,8 @@ void acpi_debugfs_init(void); #else static inline void acpi_debugfs_init(void) { return; } #endif -#ifdef CONFIG_PCI + +#if defined(CONFIG_X86) && defined(CONFIG_PCI) void acpi_lpss_init(void); #else static inline void acpi_lpss_init(void) {} diff --git a/drivers/acpi/x86/Makefile b/drivers/acpi/x86/Makefile index 1f3c5fa84f9e..63c99509ed9d 100644 --- a/drivers/acpi/x86/Makefile +++ b/drivers/acpi/x86/Makefile @@ -1,6 +1,7 @@ obj-$(CONFIG_ACPI) += acpi-x86.o acpi-x86-y += apple.o acpi-x86-y += cmos_rtc.o +acpi-x86-$(CONFIG_PCI) += lpss.o acpi-x86-y += s2idle.o acpi-x86-y += utils.o diff --git a/drivers/acpi/x86/lpss.c b/drivers/acpi/x86/lpss.c new file mode 100644 index 000000000000..148e29c2c526 --- /dev/null +++ b/drivers/acpi/x86/lpss.c @@ -0,0 +1,1355 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * ACPI support for Intel Lynxpoint LPSS. + * + * Copyright (C) 2013, Intel Corporation + * Authors: Mika Westerberg + * Rafael J. Wysocki + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../internal.h" + +#ifdef CONFIG_X86_INTEL_LPSS + +#include +#include +#include + +#define LPSS_ADDR(desc) ((unsigned long)&desc) + +#define LPSS_CLK_SIZE 0x04 +#define LPSS_LTR_SIZE 0x18 + +/* Offsets relative to LPSS_PRIVATE_OFFSET */ +#define LPSS_CLK_DIVIDER_DEF_MASK (BIT(1) | BIT(16)) +#define LPSS_RESETS 0x04 +#define LPSS_RESETS_RESET_FUNC BIT(0) +#define LPSS_RESETS_RESET_APB BIT(1) +#define LPSS_GENERAL 0x08 +#define LPSS_GENERAL_LTR_MODE_SW BIT(2) +#define LPSS_GENERAL_UART_RTS_OVRD BIT(3) +#define LPSS_SW_LTR 0x10 +#define LPSS_AUTO_LTR 0x14 +#define LPSS_LTR_SNOOP_REQ BIT(15) +#define LPSS_LTR_SNOOP_MASK 0x0000FFFF +#define LPSS_LTR_SNOOP_LAT_1US 0x800 +#define LPSS_LTR_SNOOP_LAT_32US 0xC00 +#define LPSS_LTR_SNOOP_LAT_SHIFT 5 +#define LPSS_LTR_SNOOP_LAT_CUTOFF 3000 +#define LPSS_LTR_MAX_VAL 0x3FF +#define LPSS_TX_INT 0x20 +#define LPSS_TX_INT_MASK BIT(1) + +#define LPSS_PRV_REG_COUNT 9 + +/* LPSS Flags */ +#define LPSS_CLK BIT(0) +#define LPSS_CLK_GATE BIT(1) +#define LPSS_CLK_DIVIDER BIT(2) +#define LPSS_LTR BIT(3) +#define LPSS_SAVE_CTX BIT(4) +/* + * For some devices the DSDT AML code for another device turns off the device + * before our suspend handler runs, causing us to read/save all 1-s (0xffffffff) + * as ctx register values. + * Luckily these devices always use the same ctx register values, so we can + * work around this by saving the ctx registers once on activation. + */ +#define LPSS_SAVE_CTX_ONCE BIT(5) +#define LPSS_NO_D3_DELAY BIT(6) + +struct lpss_private_data; + +struct lpss_device_desc { + unsigned int flags; + const char *clk_con_id; + unsigned int prv_offset; + size_t prv_size_override; + const struct property_entry *properties; + void (*setup)(struct lpss_private_data *pdata); + bool resume_from_noirq; +}; + +static const struct lpss_device_desc lpss_dma_desc = { + .flags = LPSS_CLK, +}; + +struct lpss_private_data { + struct acpi_device *adev; + void __iomem *mmio_base; + resource_size_t mmio_size; + unsigned int fixed_clk_rate; + struct clk *clk; + const struct lpss_device_desc *dev_desc; + u32 prv_reg_ctx[LPSS_PRV_REG_COUNT]; +}; + +/* Devices which need to be in D3 before lpss_iosf_enter_d3_state() proceeds */ +static u32 pmc_atom_d3_mask = 0xfe000ffe; + +/* LPSS run time quirks */ +static unsigned int lpss_quirks; + +/* + * LPSS_QUIRK_ALWAYS_POWER_ON: override power state for LPSS DMA device. + * + * The LPSS DMA controller has neither _PS0 nor _PS3 method. Moreover + * it can be powered off automatically whenever the last LPSS device goes down. + * In case of no power any access to the DMA controller will hang the system. + * The behaviour is reproduced on some HP laptops based on Intel BayTrail as + * well as on ASuS T100TA transformer. + * + * This quirk overrides power state of entire LPSS island to keep DMA powered + * on whenever we have at least one other device in use. + */ +#define LPSS_QUIRK_ALWAYS_POWER_ON BIT(0) + +/* UART Component Parameter Register */ +#define LPSS_UART_CPR 0xF4 +#define LPSS_UART_CPR_AFCE BIT(4) + +static void lpss_uart_setup(struct lpss_private_data *pdata) +{ + unsigned int offset; + u32 val; + + offset = pdata->dev_desc->prv_offset + LPSS_TX_INT; + val = readl(pdata->mmio_base + offset); + writel(val | LPSS_TX_INT_MASK, pdata->mmio_base + offset); + + val = readl(pdata->mmio_base + LPSS_UART_CPR); + if (!(val & LPSS_UART_CPR_AFCE)) { + offset = pdata->dev_desc->prv_offset + LPSS_GENERAL; + val = readl(pdata->mmio_base + offset); + val |= LPSS_GENERAL_UART_RTS_OVRD; + writel(val, pdata->mmio_base + offset); + } +} + +static void lpss_deassert_reset(struct lpss_private_data *pdata) +{ + unsigned int offset; + u32 val; + + offset = pdata->dev_desc->prv_offset + LPSS_RESETS; + val = readl(pdata->mmio_base + offset); + val |= LPSS_RESETS_RESET_APB | LPSS_RESETS_RESET_FUNC; + writel(val, pdata->mmio_base + offset); +} + +/* + * BYT PWM used for backlight control by the i915 driver on systems without + * the Crystal Cove PMIC. + */ +static struct pwm_lookup byt_pwm_lookup[] = { + PWM_LOOKUP_WITH_MODULE("80860F09:00", 0, "0000:00:02.0", + "pwm_soc_backlight", 0, PWM_POLARITY_NORMAL, + "pwm-lpss-platform"), +}; + +static void byt_pwm_setup(struct lpss_private_data *pdata) +{ + /* Only call pwm_add_table for the first PWM controller */ + if (acpi_dev_uid_match(pdata->adev, 1)) + pwm_add_table(byt_pwm_lookup, ARRAY_SIZE(byt_pwm_lookup)); +} + +#define LPSS_I2C_ENABLE 0x6c + +static void byt_i2c_setup(struct lpss_private_data *pdata) +{ + acpi_handle handle = pdata->adev->handle; + unsigned long long shared_host = 0; + acpi_status status; + u64 uid; + + /* Expected to always be successfull, but better safe then sorry */ + if (!acpi_dev_uid_to_integer(pdata->adev, &uid) && uid) { + /* Detect I2C bus shared with PUNIT and ignore its d3 status */ + status = acpi_evaluate_integer(handle, "_SEM", NULL, &shared_host); + if (ACPI_SUCCESS(status) && shared_host) + pmc_atom_d3_mask &= ~(BIT_LPSS2_F1_I2C1 << (uid - 1)); + } + + lpss_deassert_reset(pdata); + + if (readl(pdata->mmio_base + pdata->dev_desc->prv_offset)) + pdata->fixed_clk_rate = 133000000; + + writel(0, pdata->mmio_base + LPSS_I2C_ENABLE); +} + +/* + * BSW PWM1 is used for backlight control by the i915 driver + * BSW PWM2 is used for backlight control for fixed (etched into the glass) + * touch controls on some models. These touch-controls have specialized + * drivers which know they need the "pwm_soc_lpss_2" con-id. + */ +static struct pwm_lookup bsw_pwm_lookup[] = { + PWM_LOOKUP_WITH_MODULE("80862288:00", 0, "0000:00:02.0", + "pwm_soc_backlight", 0, PWM_POLARITY_NORMAL, + "pwm-lpss-platform"), + PWM_LOOKUP_WITH_MODULE("80862289:00", 0, NULL, + "pwm_soc_lpss_2", 0, PWM_POLARITY_NORMAL, + "pwm-lpss-platform"), +}; + +static void bsw_pwm_setup(struct lpss_private_data *pdata) +{ + /* Only call pwm_add_table for the first PWM controller */ + if (acpi_dev_uid_match(pdata->adev, 1)) + pwm_add_table(bsw_pwm_lookup, ARRAY_SIZE(bsw_pwm_lookup)); +} + +static const struct property_entry lpt_spi_properties[] = { + PROPERTY_ENTRY_U32("intel,spi-pxa2xx-type", LPSS_LPT_SSP), + { } +}; + +static const struct lpss_device_desc lpt_spi_dev_desc = { + .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_LTR + | LPSS_SAVE_CTX, + .prv_offset = 0x800, + .properties = lpt_spi_properties, +}; + +static const struct lpss_device_desc lpt_i2c_dev_desc = { + .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_LTR | LPSS_SAVE_CTX, + .prv_offset = 0x800, +}; + +static struct property_entry uart_properties[] = { + PROPERTY_ENTRY_U32("reg-io-width", 4), + PROPERTY_ENTRY_U32("reg-shift", 2), + PROPERTY_ENTRY_BOOL("snps,uart-16550-compatible"), + { }, +}; + +static const struct lpss_device_desc lpt_uart_dev_desc = { + .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_LTR + | LPSS_SAVE_CTX, + .clk_con_id = "baudclk", + .prv_offset = 0x800, + .setup = lpss_uart_setup, + .properties = uart_properties, +}; + +static const struct lpss_device_desc lpt_sdio_dev_desc = { + .flags = LPSS_LTR, + .prv_offset = 0x1000, + .prv_size_override = 0x1018, +}; + +static const struct lpss_device_desc byt_pwm_dev_desc = { + .flags = LPSS_SAVE_CTX, + .prv_offset = 0x800, + .setup = byt_pwm_setup, +}; + +static const struct lpss_device_desc bsw_pwm_dev_desc = { + .flags = LPSS_SAVE_CTX_ONCE | LPSS_NO_D3_DELAY, + .prv_offset = 0x800, + .setup = bsw_pwm_setup, + .resume_from_noirq = true, +}; + +static const struct lpss_device_desc bsw_pwm2_dev_desc = { + .flags = LPSS_SAVE_CTX_ONCE | LPSS_NO_D3_DELAY, + .prv_offset = 0x800, + .resume_from_noirq = true, +}; + +static const struct lpss_device_desc byt_uart_dev_desc = { + .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX, + .clk_con_id = "baudclk", + .prv_offset = 0x800, + .setup = lpss_uart_setup, + .properties = uart_properties, +}; + +static const struct lpss_device_desc bsw_uart_dev_desc = { + .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX + | LPSS_NO_D3_DELAY, + .clk_con_id = "baudclk", + .prv_offset = 0x800, + .setup = lpss_uart_setup, + .properties = uart_properties, +}; + +static const struct property_entry byt_spi_properties[] = { + PROPERTY_ENTRY_U32("intel,spi-pxa2xx-type", LPSS_BYT_SSP), + { } +}; + +static const struct lpss_device_desc byt_spi_dev_desc = { + .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX, + .prv_offset = 0x400, + .properties = byt_spi_properties, +}; + +static const struct lpss_device_desc byt_sdio_dev_desc = { + .flags = LPSS_CLK, +}; + +static const struct lpss_device_desc byt_i2c_dev_desc = { + .flags = LPSS_CLK | LPSS_SAVE_CTX, + .prv_offset = 0x800, + .setup = byt_i2c_setup, + .resume_from_noirq = true, +}; + +static const struct lpss_device_desc bsw_i2c_dev_desc = { + .flags = LPSS_CLK | LPSS_SAVE_CTX | LPSS_NO_D3_DELAY, + .prv_offset = 0x800, + .setup = byt_i2c_setup, + .resume_from_noirq = true, +}; + +static const struct property_entry bsw_spi_properties[] = { + PROPERTY_ENTRY_U32("intel,spi-pxa2xx-type", LPSS_BSW_SSP), + PROPERTY_ENTRY_U32("num-cs", 2), + { } +}; + +static const struct lpss_device_desc bsw_spi_dev_desc = { + .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX + | LPSS_NO_D3_DELAY, + .prv_offset = 0x400, + .setup = lpss_deassert_reset, + .properties = bsw_spi_properties, +}; + +static const struct x86_cpu_id lpss_cpu_ids[] = { + X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT, NULL), + X86_MATCH_INTEL_FAM6_MODEL(ATOM_AIRMONT, NULL), + {} +}; + +#else + +#define LPSS_ADDR(desc) (0UL) + +#endif /* CONFIG_X86_INTEL_LPSS */ + +static const struct acpi_device_id acpi_lpss_device_ids[] = { + /* Generic LPSS devices */ + { "INTL9C60", LPSS_ADDR(lpss_dma_desc) }, + + /* Lynxpoint LPSS devices */ + { "INT33C0", LPSS_ADDR(lpt_spi_dev_desc) }, + { "INT33C1", LPSS_ADDR(lpt_spi_dev_desc) }, + { "INT33C2", LPSS_ADDR(lpt_i2c_dev_desc) }, + { "INT33C3", LPSS_ADDR(lpt_i2c_dev_desc) }, + { "INT33C4", LPSS_ADDR(lpt_uart_dev_desc) }, + { "INT33C5", LPSS_ADDR(lpt_uart_dev_desc) }, + { "INT33C6", LPSS_ADDR(lpt_sdio_dev_desc) }, + + /* BayTrail LPSS devices */ + { "80860F09", LPSS_ADDR(byt_pwm_dev_desc) }, + { "80860F0A", LPSS_ADDR(byt_uart_dev_desc) }, + { "80860F0E", LPSS_ADDR(byt_spi_dev_desc) }, + { "80860F14", LPSS_ADDR(byt_sdio_dev_desc) }, + { "80860F41", LPSS_ADDR(byt_i2c_dev_desc) }, + + /* Braswell LPSS devices */ + { "80862286", LPSS_ADDR(lpss_dma_desc) }, + { "80862288", LPSS_ADDR(bsw_pwm_dev_desc) }, + { "80862289", LPSS_ADDR(bsw_pwm2_dev_desc) }, + { "8086228A", LPSS_ADDR(bsw_uart_dev_desc) }, + { "8086228E", LPSS_ADDR(bsw_spi_dev_desc) }, + { "808622C0", LPSS_ADDR(lpss_dma_desc) }, + { "808622C1", LPSS_ADDR(bsw_i2c_dev_desc) }, + + /* Broadwell LPSS devices */ + { "INT3430", LPSS_ADDR(lpt_spi_dev_desc) }, + { "INT3431", LPSS_ADDR(lpt_spi_dev_desc) }, + { "INT3432", LPSS_ADDR(lpt_i2c_dev_desc) }, + { "INT3433", LPSS_ADDR(lpt_i2c_dev_desc) }, + { "INT3434", LPSS_ADDR(lpt_uart_dev_desc) }, + { "INT3435", LPSS_ADDR(lpt_uart_dev_desc) }, + { "INT3436", LPSS_ADDR(lpt_sdio_dev_desc) }, + + /* Wildcat Point LPSS devices */ + { "INT3438", LPSS_ADDR(lpt_spi_dev_desc) }, + + { } +}; + +#ifdef CONFIG_X86_INTEL_LPSS + +/* LPSS main clock device. */ +static struct platform_device *lpss_clk_dev; + +static inline void lpt_register_clock_device(void) +{ + lpss_clk_dev = platform_device_register_simple("clk-lpss-atom", + PLATFORM_DEVID_NONE, + NULL, 0); +} + +static int register_device_clock(struct acpi_device *adev, + struct lpss_private_data *pdata) +{ + const struct lpss_device_desc *dev_desc = pdata->dev_desc; + const char *devname = dev_name(&adev->dev); + struct clk *clk; + struct lpss_clk_data *clk_data; + const char *parent, *clk_name; + void __iomem *prv_base; + + if (!lpss_clk_dev) + lpt_register_clock_device(); + + if (IS_ERR(lpss_clk_dev)) + return PTR_ERR(lpss_clk_dev); + + clk_data = platform_get_drvdata(lpss_clk_dev); + if (!clk_data) + return -ENODEV; + clk = clk_data->clk; + + if (!pdata->mmio_base + || pdata->mmio_size < dev_desc->prv_offset + LPSS_CLK_SIZE) + return -ENODATA; + + parent = clk_data->name; + prv_base = pdata->mmio_base + dev_desc->prv_offset; + + if (pdata->fixed_clk_rate) { + clk = clk_register_fixed_rate(NULL, devname, parent, 0, + pdata->fixed_clk_rate); + goto out; + } + + if (dev_desc->flags & LPSS_CLK_GATE) { + clk = clk_register_gate(NULL, devname, parent, 0, + prv_base, 0, 0, NULL); + parent = devname; + } + + if (dev_desc->flags & LPSS_CLK_DIVIDER) { + /* Prevent division by zero */ + if (!readl(prv_base)) + writel(LPSS_CLK_DIVIDER_DEF_MASK, prv_base); + + clk_name = kasprintf(GFP_KERNEL, "%s-div", devname); + if (!clk_name) + return -ENOMEM; + clk = clk_register_fractional_divider(NULL, clk_name, parent, + 0, prv_base, 1, 15, 16, 15, + CLK_FRAC_DIVIDER_POWER_OF_TWO_PS, + NULL); + parent = clk_name; + + clk_name = kasprintf(GFP_KERNEL, "%s-update", devname); + if (!clk_name) { + kfree(parent); + return -ENOMEM; + } + clk = clk_register_gate(NULL, clk_name, parent, + CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, + prv_base, 31, 0, NULL); + kfree(parent); + kfree(clk_name); + } +out: + if (IS_ERR(clk)) + return PTR_ERR(clk); + + pdata->clk = clk; + clk_register_clkdev(clk, dev_desc->clk_con_id, devname); + return 0; +} + +struct lpss_device_links { + const char *supplier_hid; + const char *supplier_uid; + const char *consumer_hid; + const char *consumer_uid; + u32 flags; + const struct dmi_system_id *dep_missing_ids; +}; + +/* Please keep this list sorted alphabetically by vendor and model */ +static const struct dmi_system_id i2c1_dep_missing_dmi_ids[] = { + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "T200TA"), + }, + }, + {} +}; + +/* + * The _DEP method is used to identify dependencies but instead of creating + * device links for every handle in _DEP, only links in the following list are + * created. That is necessary because, in the general case, _DEP can refer to + * devices that might not have drivers, or that are on different buses, or where + * the supplier is not enumerated until after the consumer is probed. + */ +static const struct lpss_device_links lpss_device_links[] = { + /* CHT External sdcard slot controller depends on PMIC I2C ctrl */ + {"808622C1", "7", "80860F14", "3", DL_FLAG_PM_RUNTIME}, + /* CHT iGPU depends on PMIC I2C controller */ + {"808622C1", "7", "LNXVIDEO", NULL, DL_FLAG_PM_RUNTIME}, + /* BYT iGPU depends on the Embedded Controller I2C controller (UID 1) */ + {"80860F41", "1", "LNXVIDEO", NULL, DL_FLAG_PM_RUNTIME, + i2c1_dep_missing_dmi_ids}, + /* BYT CR iGPU depends on PMIC I2C controller (UID 5 on CR) */ + {"80860F41", "5", "LNXVIDEO", NULL, DL_FLAG_PM_RUNTIME}, + /* BYT iGPU depends on PMIC I2C controller (UID 7 on non CR) */ + {"80860F41", "7", "LNXVIDEO", NULL, DL_FLAG_PM_RUNTIME}, +}; + +static bool acpi_lpss_is_supplier(struct acpi_device *adev, + const struct lpss_device_links *link) +{ + return acpi_dev_hid_uid_match(adev, link->supplier_hid, link->supplier_uid); +} + +static bool acpi_lpss_is_consumer(struct acpi_device *adev, + const struct lpss_device_links *link) +{ + return acpi_dev_hid_uid_match(adev, link->consumer_hid, link->consumer_uid); +} + +struct hid_uid { + const char *hid; + const char *uid; +}; + +static int match_hid_uid(struct device *dev, const void *data) +{ + struct acpi_device *adev = ACPI_COMPANION(dev); + const struct hid_uid *id = data; + + if (!adev) + return 0; + + return acpi_dev_hid_uid_match(adev, id->hid, id->uid); +} + +static struct device *acpi_lpss_find_device(const char *hid, const char *uid) +{ + struct device *dev; + + struct hid_uid data = { + .hid = hid, + .uid = uid, + }; + + dev = bus_find_device(&platform_bus_type, NULL, &data, match_hid_uid); + if (dev) + return dev; + + return bus_find_device(&pci_bus_type, NULL, &data, match_hid_uid); +} + +static void acpi_lpss_link_consumer(struct device *dev1, + const struct lpss_device_links *link) +{ + struct device *dev2; + + dev2 = acpi_lpss_find_device(link->consumer_hid, link->consumer_uid); + if (!dev2) + return; + + if ((link->dep_missing_ids && dmi_check_system(link->dep_missing_ids)) + || acpi_device_dep(ACPI_HANDLE(dev2), ACPI_HANDLE(dev1))) + device_link_add(dev2, dev1, link->flags); + + put_device(dev2); +} + +static void acpi_lpss_link_supplier(struct device *dev1, + const struct lpss_device_links *link) +{ + struct device *dev2; + + dev2 = acpi_lpss_find_device(link->supplier_hid, link->supplier_uid); + if (!dev2) + return; + + if ((link->dep_missing_ids && dmi_check_system(link->dep_missing_ids)) + || acpi_device_dep(ACPI_HANDLE(dev1), ACPI_HANDLE(dev2))) + device_link_add(dev1, dev2, link->flags); + + put_device(dev2); +} + +static void acpi_lpss_create_device_links(struct acpi_device *adev, + struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(lpss_device_links); i++) { + const struct lpss_device_links *link = &lpss_device_links[i]; + + if (acpi_lpss_is_supplier(adev, link)) + acpi_lpss_link_consumer(&pdev->dev, link); + + if (acpi_lpss_is_consumer(adev, link)) + acpi_lpss_link_supplier(&pdev->dev, link); + } +} + +static int acpi_lpss_create_device(struct acpi_device *adev, + const struct acpi_device_id *id) +{ + const struct lpss_device_desc *dev_desc; + struct lpss_private_data *pdata; + struct resource_entry *rentry; + struct list_head resource_list; + struct platform_device *pdev; + int ret; + + dev_desc = (const struct lpss_device_desc *)id->driver_data; + if (!dev_desc) + return -EINVAL; + + pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + INIT_LIST_HEAD(&resource_list); + ret = acpi_dev_get_memory_resources(adev, &resource_list); + if (ret < 0) + goto err_out; + + rentry = list_first_entry_or_null(&resource_list, struct resource_entry, node); + if (rentry) { + if (dev_desc->prv_size_override) + pdata->mmio_size = dev_desc->prv_size_override; + else + pdata->mmio_size = resource_size(rentry->res); + pdata->mmio_base = ioremap(rentry->res->start, pdata->mmio_size); + } + + acpi_dev_free_resource_list(&resource_list); + + if (!pdata->mmio_base) { + /* Avoid acpi_bus_attach() instantiating a pdev for this dev. */ + adev->pnp.type.platform_id = 0; + goto out_free; + } + + pdata->adev = adev; + pdata->dev_desc = dev_desc; + + if (dev_desc->setup) + dev_desc->setup(pdata); + + if (dev_desc->flags & LPSS_CLK) { + ret = register_device_clock(adev, pdata); + if (ret) + goto out_free; + } + + /* + * This works around a known issue in ACPI tables where LPSS devices + * have _PS0 and _PS3 without _PSC (and no power resources), so + * acpi_bus_init_power() will assume that the BIOS has put them into D0. + */ + acpi_device_fix_up_power(adev); + + adev->driver_data = pdata; + pdev = acpi_create_platform_device(adev, dev_desc->properties); + if (IS_ERR_OR_NULL(pdev)) { + adev->driver_data = NULL; + ret = PTR_ERR(pdev); + goto err_out; + } + + acpi_lpss_create_device_links(adev, pdev); + return 1; + +out_free: + /* Skip the device, but continue the namespace scan */ + ret = 0; +err_out: + kfree(pdata); + return ret; +} + +static u32 __lpss_reg_read(struct lpss_private_data *pdata, unsigned int reg) +{ + return readl(pdata->mmio_base + pdata->dev_desc->prv_offset + reg); +} + +static void __lpss_reg_write(u32 val, struct lpss_private_data *pdata, + unsigned int reg) +{ + writel(val, pdata->mmio_base + pdata->dev_desc->prv_offset + reg); +} + +static int lpss_reg_read(struct device *dev, unsigned int reg, u32 *val) +{ + struct acpi_device *adev = ACPI_COMPANION(dev); + struct lpss_private_data *pdata; + unsigned long flags; + int ret; + + if (WARN_ON(!adev)) + return -ENODEV; + + spin_lock_irqsave(&dev->power.lock, flags); + if (pm_runtime_suspended(dev)) { + ret = -EAGAIN; + goto out; + } + pdata = acpi_driver_data(adev); + if (WARN_ON(!pdata || !pdata->mmio_base)) { + ret = -ENODEV; + goto out; + } + *val = __lpss_reg_read(pdata, reg); + ret = 0; + + out: + spin_unlock_irqrestore(&dev->power.lock, flags); + return ret; +} + +static ssize_t lpss_ltr_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + u32 ltr_value = 0; + unsigned int reg; + int ret; + + reg = strcmp(attr->attr.name, "auto_ltr") ? LPSS_SW_LTR : LPSS_AUTO_LTR; + ret = lpss_reg_read(dev, reg, <r_value); + if (ret) + return ret; + + return sysfs_emit(buf, "%08x\n", ltr_value); +} + +static ssize_t lpss_ltr_mode_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + u32 ltr_mode = 0; + char *outstr; + int ret; + + ret = lpss_reg_read(dev, LPSS_GENERAL, <r_mode); + if (ret) + return ret; + + outstr = (ltr_mode & LPSS_GENERAL_LTR_MODE_SW) ? "sw" : "auto"; + return sprintf(buf, "%s\n", outstr); +} + +static DEVICE_ATTR(auto_ltr, S_IRUSR, lpss_ltr_show, NULL); +static DEVICE_ATTR(sw_ltr, S_IRUSR, lpss_ltr_show, NULL); +static DEVICE_ATTR(ltr_mode, S_IRUSR, lpss_ltr_mode_show, NULL); + +static struct attribute *lpss_attrs[] = { + &dev_attr_auto_ltr.attr, + &dev_attr_sw_ltr.attr, + &dev_attr_ltr_mode.attr, + NULL, +}; + +static const struct attribute_group lpss_attr_group = { + .attrs = lpss_attrs, + .name = "lpss_ltr", +}; + +static void acpi_lpss_set_ltr(struct device *dev, s32 val) +{ + struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); + u32 ltr_mode, ltr_val; + + ltr_mode = __lpss_reg_read(pdata, LPSS_GENERAL); + if (val < 0) { + if (ltr_mode & LPSS_GENERAL_LTR_MODE_SW) { + ltr_mode &= ~LPSS_GENERAL_LTR_MODE_SW; + __lpss_reg_write(ltr_mode, pdata, LPSS_GENERAL); + } + return; + } + ltr_val = __lpss_reg_read(pdata, LPSS_SW_LTR) & ~LPSS_LTR_SNOOP_MASK; + if (val >= LPSS_LTR_SNOOP_LAT_CUTOFF) { + ltr_val |= LPSS_LTR_SNOOP_LAT_32US; + val = LPSS_LTR_MAX_VAL; + } else if (val > LPSS_LTR_MAX_VAL) { + ltr_val |= LPSS_LTR_SNOOP_LAT_32US | LPSS_LTR_SNOOP_REQ; + val >>= LPSS_LTR_SNOOP_LAT_SHIFT; + } else { + ltr_val |= LPSS_LTR_SNOOP_LAT_1US | LPSS_LTR_SNOOP_REQ; + } + ltr_val |= val; + __lpss_reg_write(ltr_val, pdata, LPSS_SW_LTR); + if (!(ltr_mode & LPSS_GENERAL_LTR_MODE_SW)) { + ltr_mode |= LPSS_GENERAL_LTR_MODE_SW; + __lpss_reg_write(ltr_mode, pdata, LPSS_GENERAL); + } +} + +#ifdef CONFIG_PM +/** + * acpi_lpss_save_ctx() - Save the private registers of LPSS device + * @dev: LPSS device + * @pdata: pointer to the private data of the LPSS device + * + * Most LPSS devices have private registers which may loose their context when + * the device is powered down. acpi_lpss_save_ctx() saves those registers into + * prv_reg_ctx array. + */ +static void acpi_lpss_save_ctx(struct device *dev, + struct lpss_private_data *pdata) +{ + unsigned int i; + + for (i = 0; i < LPSS_PRV_REG_COUNT; i++) { + unsigned long offset = i * sizeof(u32); + + pdata->prv_reg_ctx[i] = __lpss_reg_read(pdata, offset); + dev_dbg(dev, "saving 0x%08x from LPSS reg at offset 0x%02lx\n", + pdata->prv_reg_ctx[i], offset); + } +} + +/** + * acpi_lpss_restore_ctx() - Restore the private registers of LPSS device + * @dev: LPSS device + * @pdata: pointer to the private data of the LPSS device + * + * Restores the registers that were previously stored with acpi_lpss_save_ctx(). + */ +static void acpi_lpss_restore_ctx(struct device *dev, + struct lpss_private_data *pdata) +{ + unsigned int i; + + for (i = 0; i < LPSS_PRV_REG_COUNT; i++) { + unsigned long offset = i * sizeof(u32); + + __lpss_reg_write(pdata->prv_reg_ctx[i], pdata, offset); + dev_dbg(dev, "restoring 0x%08x to LPSS reg at offset 0x%02lx\n", + pdata->prv_reg_ctx[i], offset); + } +} + +static void acpi_lpss_d3_to_d0_delay(struct lpss_private_data *pdata) +{ + /* + * The following delay is needed or the subsequent write operations may + * fail. The LPSS devices are actually PCI devices and the PCI spec + * expects 10ms delay before the device can be accessed after D3 to D0 + * transition. However some platforms like BSW does not need this delay. + */ + unsigned int delay = 10; /* default 10ms delay */ + + if (pdata->dev_desc->flags & LPSS_NO_D3_DELAY) + delay = 0; + + msleep(delay); +} + +static int acpi_lpss_activate(struct device *dev) +{ + struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); + int ret; + + ret = acpi_dev_resume(dev); + if (ret) + return ret; + + acpi_lpss_d3_to_d0_delay(pdata); + + /* + * This is called only on ->probe() stage where a device is either in + * known state defined by BIOS or most likely powered off. Due to this + * we have to deassert reset line to be sure that ->probe() will + * recognize the device. + */ + if (pdata->dev_desc->flags & (LPSS_SAVE_CTX | LPSS_SAVE_CTX_ONCE)) + lpss_deassert_reset(pdata); + + if (pdata->dev_desc->flags & LPSS_SAVE_CTX_ONCE) + acpi_lpss_save_ctx(dev, pdata); + + return 0; +} + +static void acpi_lpss_dismiss(struct device *dev) +{ + acpi_dev_suspend(dev, false); +} + +/* IOSF SB for LPSS island */ +#define LPSS_IOSF_UNIT_LPIOEP 0xA0 +#define LPSS_IOSF_UNIT_LPIO1 0xAB +#define LPSS_IOSF_UNIT_LPIO2 0xAC + +#define LPSS_IOSF_PMCSR 0x84 +#define LPSS_PMCSR_D0 0 +#define LPSS_PMCSR_D3hot 3 +#define LPSS_PMCSR_Dx_MASK GENMASK(1, 0) + +#define LPSS_IOSF_GPIODEF0 0x154 +#define LPSS_GPIODEF0_DMA1_D3 BIT(2) +#define LPSS_GPIODEF0_DMA2_D3 BIT(3) +#define LPSS_GPIODEF0_DMA_D3_MASK GENMASK(3, 2) +#define LPSS_GPIODEF0_DMA_LLP BIT(13) + +static DEFINE_MUTEX(lpss_iosf_mutex); +static bool lpss_iosf_d3_entered = true; + +static void lpss_iosf_enter_d3_state(void) +{ + u32 value1 = 0; + u32 mask1 = LPSS_GPIODEF0_DMA_D3_MASK | LPSS_GPIODEF0_DMA_LLP; + u32 value2 = LPSS_PMCSR_D3hot; + u32 mask2 = LPSS_PMCSR_Dx_MASK; + /* + * PMC provides an information about actual status of the LPSS devices. + * Here we read the values related to LPSS power island, i.e. LPSS + * devices, excluding both LPSS DMA controllers, along with SCC domain. + */ + u32 func_dis, d3_sts_0, pmc_status; + int ret; + + ret = pmc_atom_read(PMC_FUNC_DIS, &func_dis); + if (ret) + return; + + mutex_lock(&lpss_iosf_mutex); + + ret = pmc_atom_read(PMC_D3_STS_0, &d3_sts_0); + if (ret) + goto exit; + + /* + * Get the status of entire LPSS power island per device basis. + * Shutdown both LPSS DMA controllers if and only if all other devices + * are already in D3hot. + */ + pmc_status = (~(d3_sts_0 | func_dis)) & pmc_atom_d3_mask; + if (pmc_status) + goto exit; + + iosf_mbi_modify(LPSS_IOSF_UNIT_LPIO1, MBI_CFG_WRITE, + LPSS_IOSF_PMCSR, value2, mask2); + + iosf_mbi_modify(LPSS_IOSF_UNIT_LPIO2, MBI_CFG_WRITE, + LPSS_IOSF_PMCSR, value2, mask2); + + iosf_mbi_modify(LPSS_IOSF_UNIT_LPIOEP, MBI_CR_WRITE, + LPSS_IOSF_GPIODEF0, value1, mask1); + + lpss_iosf_d3_entered = true; + +exit: + mutex_unlock(&lpss_iosf_mutex); +} + +static void lpss_iosf_exit_d3_state(void) +{ + u32 value1 = LPSS_GPIODEF0_DMA1_D3 | LPSS_GPIODEF0_DMA2_D3 | + LPSS_GPIODEF0_DMA_LLP; + u32 mask1 = LPSS_GPIODEF0_DMA_D3_MASK | LPSS_GPIODEF0_DMA_LLP; + u32 value2 = LPSS_PMCSR_D0; + u32 mask2 = LPSS_PMCSR_Dx_MASK; + + mutex_lock(&lpss_iosf_mutex); + + if (!lpss_iosf_d3_entered) + goto exit; + + lpss_iosf_d3_entered = false; + + iosf_mbi_modify(LPSS_IOSF_UNIT_LPIOEP, MBI_CR_WRITE, + LPSS_IOSF_GPIODEF0, value1, mask1); + + iosf_mbi_modify(LPSS_IOSF_UNIT_LPIO2, MBI_CFG_WRITE, + LPSS_IOSF_PMCSR, value2, mask2); + + iosf_mbi_modify(LPSS_IOSF_UNIT_LPIO1, MBI_CFG_WRITE, + LPSS_IOSF_PMCSR, value2, mask2); + +exit: + mutex_unlock(&lpss_iosf_mutex); +} + +static int acpi_lpss_suspend(struct device *dev, bool wakeup) +{ + struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); + int ret; + + if (pdata->dev_desc->flags & LPSS_SAVE_CTX) + acpi_lpss_save_ctx(dev, pdata); + + ret = acpi_dev_suspend(dev, wakeup); + + /* + * This call must be last in the sequence, otherwise PMC will return + * wrong status for devices being about to be powered off. See + * lpss_iosf_enter_d3_state() for further information. + */ + if (acpi_target_system_state() == ACPI_STATE_S0 && + lpss_quirks & LPSS_QUIRK_ALWAYS_POWER_ON && iosf_mbi_available()) + lpss_iosf_enter_d3_state(); + + return ret; +} + +static int acpi_lpss_resume(struct device *dev) +{ + struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); + int ret; + + /* + * This call is kept first to be in symmetry with + * acpi_lpss_runtime_suspend() one. + */ + if (lpss_quirks & LPSS_QUIRK_ALWAYS_POWER_ON && iosf_mbi_available()) + lpss_iosf_exit_d3_state(); + + ret = acpi_dev_resume(dev); + if (ret) + return ret; + + acpi_lpss_d3_to_d0_delay(pdata); + + if (pdata->dev_desc->flags & (LPSS_SAVE_CTX | LPSS_SAVE_CTX_ONCE)) + acpi_lpss_restore_ctx(dev, pdata); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int acpi_lpss_do_suspend_late(struct device *dev) +{ + int ret; + + if (dev_pm_skip_suspend(dev)) + return 0; + + ret = pm_generic_suspend_late(dev); + return ret ? ret : acpi_lpss_suspend(dev, device_may_wakeup(dev)); +} + +static int acpi_lpss_suspend_late(struct device *dev) +{ + struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); + + if (pdata->dev_desc->resume_from_noirq) + return 0; + + return acpi_lpss_do_suspend_late(dev); +} + +static int acpi_lpss_suspend_noirq(struct device *dev) +{ + struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); + int ret; + + if (pdata->dev_desc->resume_from_noirq) { + /* + * The driver's ->suspend_late callback will be invoked by + * acpi_lpss_do_suspend_late(), with the assumption that the + * driver really wanted to run that code in ->suspend_noirq, but + * it could not run after acpi_dev_suspend() and the driver + * expected the latter to be called in the "late" phase. + */ + ret = acpi_lpss_do_suspend_late(dev); + if (ret) + return ret; + } + + return acpi_subsys_suspend_noirq(dev); +} + +static int acpi_lpss_do_resume_early(struct device *dev) +{ + int ret = acpi_lpss_resume(dev); + + return ret ? ret : pm_generic_resume_early(dev); +} + +static int acpi_lpss_resume_early(struct device *dev) +{ + struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); + + if (pdata->dev_desc->resume_from_noirq) + return 0; + + if (dev_pm_skip_resume(dev)) + return 0; + + return acpi_lpss_do_resume_early(dev); +} + +static int acpi_lpss_resume_noirq(struct device *dev) +{ + struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); + int ret; + + /* Follow acpi_subsys_resume_noirq(). */ + if (dev_pm_skip_resume(dev)) + return 0; + + ret = pm_generic_resume_noirq(dev); + if (ret) + return ret; + + if (!pdata->dev_desc->resume_from_noirq) + return 0; + + /* + * The driver's ->resume_early callback will be invoked by + * acpi_lpss_do_resume_early(), with the assumption that the driver + * really wanted to run that code in ->resume_noirq, but it could not + * run before acpi_dev_resume() and the driver expected the latter to be + * called in the "early" phase. + */ + return acpi_lpss_do_resume_early(dev); +} + +static int acpi_lpss_do_restore_early(struct device *dev) +{ + int ret = acpi_lpss_resume(dev); + + return ret ? ret : pm_generic_restore_early(dev); +} + +static int acpi_lpss_restore_early(struct device *dev) +{ + struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); + + if (pdata->dev_desc->resume_from_noirq) + return 0; + + return acpi_lpss_do_restore_early(dev); +} + +static int acpi_lpss_restore_noirq(struct device *dev) +{ + struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); + int ret; + + ret = pm_generic_restore_noirq(dev); + if (ret) + return ret; + + if (!pdata->dev_desc->resume_from_noirq) + return 0; + + /* This is analogous to what happens in acpi_lpss_resume_noirq(). */ + return acpi_lpss_do_restore_early(dev); +} + +static int acpi_lpss_do_poweroff_late(struct device *dev) +{ + int ret = pm_generic_poweroff_late(dev); + + return ret ? ret : acpi_lpss_suspend(dev, device_may_wakeup(dev)); +} + +static int acpi_lpss_poweroff_late(struct device *dev) +{ + struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); + + if (dev_pm_skip_suspend(dev)) + return 0; + + if (pdata->dev_desc->resume_from_noirq) + return 0; + + return acpi_lpss_do_poweroff_late(dev); +} + +static int acpi_lpss_poweroff_noirq(struct device *dev) +{ + struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); + + if (dev_pm_skip_suspend(dev)) + return 0; + + if (pdata->dev_desc->resume_from_noirq) { + /* This is analogous to the acpi_lpss_suspend_noirq() case. */ + int ret = acpi_lpss_do_poweroff_late(dev); + + if (ret) + return ret; + } + + return pm_generic_poweroff_noirq(dev); +} +#endif /* CONFIG_PM_SLEEP */ + +static int acpi_lpss_runtime_suspend(struct device *dev) +{ + int ret = pm_generic_runtime_suspend(dev); + + return ret ? ret : acpi_lpss_suspend(dev, true); +} + +static int acpi_lpss_runtime_resume(struct device *dev) +{ + int ret = acpi_lpss_resume(dev); + + return ret ? ret : pm_generic_runtime_resume(dev); +} +#endif /* CONFIG_PM */ + +static struct dev_pm_domain acpi_lpss_pm_domain = { +#ifdef CONFIG_PM + .activate = acpi_lpss_activate, + .dismiss = acpi_lpss_dismiss, +#endif + .ops = { +#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP + .prepare = acpi_subsys_prepare, + .complete = acpi_subsys_complete, + .suspend = acpi_subsys_suspend, + .suspend_late = acpi_lpss_suspend_late, + .suspend_noirq = acpi_lpss_suspend_noirq, + .resume_noirq = acpi_lpss_resume_noirq, + .resume_early = acpi_lpss_resume_early, + .freeze = acpi_subsys_freeze, + .poweroff = acpi_subsys_poweroff, + .poweroff_late = acpi_lpss_poweroff_late, + .poweroff_noirq = acpi_lpss_poweroff_noirq, + .restore_noirq = acpi_lpss_restore_noirq, + .restore_early = acpi_lpss_restore_early, +#endif + .runtime_suspend = acpi_lpss_runtime_suspend, + .runtime_resume = acpi_lpss_runtime_resume, +#endif + }, +}; + +static int acpi_lpss_platform_notify(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct platform_device *pdev = to_platform_device(data); + struct lpss_private_data *pdata; + struct acpi_device *adev; + const struct acpi_device_id *id; + + id = acpi_match_device(acpi_lpss_device_ids, &pdev->dev); + if (!id || !id->driver_data) + return 0; + + adev = ACPI_COMPANION(&pdev->dev); + if (!adev) + return 0; + + pdata = acpi_driver_data(adev); + if (!pdata) + return 0; + + if (pdata->mmio_base && + pdata->mmio_size < pdata->dev_desc->prv_offset + LPSS_LTR_SIZE) { + dev_err(&pdev->dev, "MMIO size insufficient to access LTR\n"); + return 0; + } + + switch (action) { + case BUS_NOTIFY_BIND_DRIVER: + dev_pm_domain_set(&pdev->dev, &acpi_lpss_pm_domain); + break; + case BUS_NOTIFY_DRIVER_NOT_BOUND: + case BUS_NOTIFY_UNBOUND_DRIVER: + dev_pm_domain_set(&pdev->dev, NULL); + break; + case BUS_NOTIFY_ADD_DEVICE: + dev_pm_domain_set(&pdev->dev, &acpi_lpss_pm_domain); + if (pdata->dev_desc->flags & LPSS_LTR) + return sysfs_create_group(&pdev->dev.kobj, + &lpss_attr_group); + break; + case BUS_NOTIFY_DEL_DEVICE: + if (pdata->dev_desc->flags & LPSS_LTR) + sysfs_remove_group(&pdev->dev.kobj, &lpss_attr_group); + dev_pm_domain_set(&pdev->dev, NULL); + break; + default: + break; + } + + return 0; +} + +static struct notifier_block acpi_lpss_nb = { + .notifier_call = acpi_lpss_platform_notify, +}; + +static void acpi_lpss_bind(struct device *dev) +{ + struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); + + if (!pdata || !pdata->mmio_base || !(pdata->dev_desc->flags & LPSS_LTR)) + return; + + if (pdata->mmio_size >= pdata->dev_desc->prv_offset + LPSS_LTR_SIZE) + dev->power.set_latency_tolerance = acpi_lpss_set_ltr; + else + dev_err(dev, "MMIO size insufficient to access LTR\n"); +} + +static void acpi_lpss_unbind(struct device *dev) +{ + dev->power.set_latency_tolerance = NULL; +} + +static struct acpi_scan_handler lpss_handler = { + .ids = acpi_lpss_device_ids, + .attach = acpi_lpss_create_device, + .bind = acpi_lpss_bind, + .unbind = acpi_lpss_unbind, +}; + +void __init acpi_lpss_init(void) +{ + const struct x86_cpu_id *id; + int ret; + + ret = lpss_atom_clk_init(); + if (ret) + return; + + id = x86_match_cpu(lpss_cpu_ids); + if (id) + lpss_quirks |= LPSS_QUIRK_ALWAYS_POWER_ON; + + bus_register_notifier(&platform_bus_type, &acpi_lpss_nb); + acpi_scan_add_handler(&lpss_handler); +} + +#else + +static struct acpi_scan_handler lpss_handler = { + .ids = acpi_lpss_device_ids, +}; + +void __init acpi_lpss_init(void) +{ + acpi_scan_add_handler(&lpss_handler); +} + +#endif /* CONFIG_X86_INTEL_LPSS */ -- cgit v1.2.3 From bfd1a492b56082034cdf560d66c26b3b636fad18 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 6 Apr 2024 15:56:24 +0200 Subject: ACPI: x86: utils: Mark SMO8810 accel on Dell XPS 15 9550 as always present The Dell XPS 15 9550 has a SMO8110 accelerometer / HDD freefall sensor which is wrongly marked as not present. Mark this as always present so that the dell-smo8800 driver can bind to it. Signed-off-by: Hans de Goede Signed-off-by: Rafael J. Wysocki --- drivers/acpi/x86/utils.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/acpi/x86/utils.c b/drivers/acpi/x86/utils.c index 90c3d2eab9e9..c7af2d2986fd 100644 --- a/drivers/acpi/x86/utils.c +++ b/drivers/acpi/x86/utils.c @@ -100,6 +100,15 @@ static const struct override_status_id override_status_ids[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Venue 11 Pro 7139"), }), + /* + * The Dell XPS 15 9550 has a SMO8110 accelerometer / + * HDD freefall sensor which is wrongly marked as not present. + */ + PRESENT_ENTRY_HID("SMO8810", "1", SKYLAKE, { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "XPS 15 9550"), + }), + /* * The GPD win BIOS dated 20170221 has disabled the accelerometer, the * drivers sometimes cause crashes under Windows and this is how the -- cgit v1.2.3 From d8f20383a2fc3a3844b08a4999cf0e81164a0e56 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 6 Apr 2024 15:56:25 +0200 Subject: ACPI: x86: Add PNP_UART1_SKIP quirk for Lenovo Blade2 tablets The x86 Android tablets on which quirks to skip looking for a matching UartSerialBus resource and instead unconditionally create a serial bus device (serdev) are necessary there are 2 sorts of serialports: ACPI enumerated highspeed designware UARTs, these are the ones which typcially need to be skipped since they need a serdev for the attached BT HCI. A PNP enumerated UART which is part of the PCU. So far the existing quirks have ignored this. But on the Lenovo Yoga Tablet 2 Pro 1380 models this is used for a custom fastcharging protocol. There is a Micro USB switch which can switch the USB data lines to this uart and then a 600 baud protocol is used to configure the charger for a voltage higher then 5V. Add a new ACPI_QUIRK_PNP_UART1_SKIP quirk type and set this for the existing entry for the Lenovo Yoga Tablet 2 830 / 1050 models. Note this will lead to unnecessarily also creating a serdev for the PCU UART on the 830 / 1050 which don't need this, but the UART is not used otherwise there so that is not a problem. Signed-off-by: Hans de Goede Signed-off-by: Rafael J. Wysocki --- drivers/acpi/x86/utils.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/acpi/x86/utils.c b/drivers/acpi/x86/utils.c index c7af2d2986fd..7dca73417e2b 100644 --- a/drivers/acpi/x86/utils.c +++ b/drivers/acpi/x86/utils.c @@ -269,9 +269,10 @@ bool force_storage_d3(void) #define ACPI_QUIRK_SKIP_I2C_CLIENTS BIT(0) #define ACPI_QUIRK_UART1_SKIP BIT(1) #define ACPI_QUIRK_UART1_TTY_UART2_SKIP BIT(2) -#define ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY BIT(3) -#define ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY BIT(4) -#define ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS BIT(5) +#define ACPI_QUIRK_PNP_UART1_SKIP BIT(3) +#define ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY BIT(4) +#define ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY BIT(5) +#define ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS BIT(6) static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = { /* @@ -351,6 +352,7 @@ static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = { DMI_MATCH(DMI_BIOS_VERSION, "BLADE_21"), }, .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS | + ACPI_QUIRK_PNP_UART1_SKIP | ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY), }, { @@ -449,14 +451,18 @@ static int acpi_dmi_skip_serdev_enumeration(struct device *controller_parent, bo if (ret) return 0; - /* to not match on PNP enumerated debug UARTs */ - if (!dev_is_platform(controller_parent)) - return 0; - dmi_id = dmi_first_match(acpi_quirk_skip_dmi_ids); if (dmi_id) quirks = (unsigned long)dmi_id->driver_data; + if (!dev_is_platform(controller_parent)) { + /* PNP enumerated UARTs */ + if ((quirks & ACPI_QUIRK_PNP_UART1_SKIP) && uid == 1) + *skip = true; + + return 0; + } + if ((quirks & ACPI_QUIRK_UART1_SKIP) && uid == 1) *skip = true; -- cgit v1.2.3 From a3403d304708f60565582d60af4316289d0316a0 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 9 Apr 2024 16:00:55 +0200 Subject: ACPI: disable -Wstringop-truncation gcc -Wstringop-truncation warns about copying a string that results in a missing nul termination: drivers/acpi/acpica/tbfind.c: In function 'acpi_tb_find_table': drivers/acpi/acpica/tbfind.c:60:9: error: 'strncpy' specified bound 6 equals destination size [-Werror=stringop-truncation] 60 | strncpy(header.oem_id, oem_id, ACPI_OEM_ID_SIZE); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/acpi/acpica/tbfind.c:61:9: error: 'strncpy' specified bound 8 equals destination size [-Werror=stringop-truncation] 61 | strncpy(header.oem_table_id, oem_table_id, ACPI_OEM_TABLE_ID_SIZE); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The code works as intended, and the warning could be addressed by using a memcpy(), but turning the warning off for this file works equally well and may be easier to merge. Fixes: 47c08729bf1c ("ACPICA: Fix for LoadTable operator, input strings") Link: https://lore.kernel.org/lkml/CAJZ5v0hoUfv54KW7y4223Mn9E7D4xvR7whRFNLTBqCZMUxT50Q@mail.gmail.com/#t Signed-off-by: Arnd Bergmann Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile index 30f3fc13c29d..8d18af396de9 100644 --- a/drivers/acpi/acpica/Makefile +++ b/drivers/acpi/acpica/Makefile @@ -5,6 +5,7 @@ ccflags-y := -D_LINUX -DBUILDING_ACPICA ccflags-$(CONFIG_ACPI_DEBUG) += -DACPI_DEBUG_OUTPUT +CFLAGS_tbfind.o += $(call cc-disable-warning, stringop-truncation) # use acpi.o to put all files here into acpi.o modparam namespace obj-y += acpi.o -- cgit v1.2.3 From cd1b30824ff270201c43c41b9b829a369cb4e944 Mon Sep 17 00:00:00 2001 From: Ben Cheatham Date: Thu, 20 Jul 2023 14:46:14 -0500 Subject: ACPICA: actbl1.h: Add EINJ CXL error types ACPICA commit c7171588a9f684afafc83c6c18ed0bab9274e5e6 Add EINJ CXL error types added in ACPI v6.5. Link: https://github.com/acpica/acpica/commit/c7171588 Signed-off-by: Ben Cheatham Signed-off-by: Rafael J. Wysocki --- include/acpi/actbl1.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/acpi/actbl1.h b/include/acpi/actbl1.h index a33375e055ad..1f58c5d86869 100644 --- a/include/acpi/actbl1.h +++ b/include/acpi/actbl1.h @@ -1096,6 +1096,12 @@ enum acpi_einj_command_status { #define ACPI_EINJ_PLATFORM_CORRECTABLE (1<<9) #define ACPI_EINJ_PLATFORM_UNCORRECTABLE (1<<10) #define ACPI_EINJ_PLATFORM_FATAL (1<<11) +#define ACPI_EINJ_CXL_CACHE_CORRECTABLE (1<<12) +#define ACPI_EINJ_CXL_CACHE_UNCORRECTABLE (1<<13) +#define ACPI_EINJ_CXL_CACHE_FATAL (1<<14) +#define ACPI_EINJ_CXL_MEM_CORRECTABLE (1<<15) +#define ACPI_EINJ_CXL_MEM_UNCORRECTABLE (1<<16) +#define ACPI_EINJ_CXL_MEM_FATAL (1<<17) #define ACPI_EINJ_VENDOR_DEFINED (1<<31) /******************************************************************************* -- cgit v1.2.3 From 2e94dc11898042eb528eda3e09db242529722916 Mon Sep 17 00:00:00 2001 From: Shiju Jose Date: Wed, 27 Sep 2023 17:41:52 +0100 Subject: ACPICA: ACPI 6.5: RAS2: Add support for RAS2 table ACPICA commit c581606cf49b7574d29c02b1a3bc144650375e32 Add support for ACPI RAS2 feature table(RAS2) defined in the ACPI 6.5 Specification & upwards revision, section 5.2.21. The RAS2 table provides interfaces for platform RAS features. RAS2 offers the same services as RASF, but is more scalable than the latter. RAS2 supports independent RAS controls and capabilities for a given RAS feature for multiple instances of the same component in a given system. The platform can support either RAS2 or RASF but not both. Link: https://github.com/acpica/acpica/commit/c581606c Signed-off-by: Shiju Jose Signed-off-by: Rafael J. Wysocki --- include/acpi/actbl2.h | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h index 9775384d61c6..64a3f9ae2641 100644 --- a/include/acpi/actbl2.h +++ b/include/acpi/actbl2.h @@ -47,6 +47,7 @@ #define ACPI_SIG_PPTT "PPTT" /* Processor Properties Topology Table */ #define ACPI_SIG_PRMT "PRMT" /* Platform Runtime Mechanism Table */ #define ACPI_SIG_RASF "RASF" /* RAS Feature table */ +#define ACPI_SIG_RAS2 "RAS2" /* RAS2 Feature table */ #define ACPI_SIG_RGRT "RGRT" /* Regulatory Graphics Resource Table */ #define ACPI_SIG_RHCT "RHCT" /* RISC-V Hart Capabilities Table */ #define ACPI_SIG_SBST "SBST" /* Smart Battery Specification Table */ @@ -2751,6 +2752,134 @@ enum acpi_rasf_status { #define ACPI_RASF_ERROR (1<<2) #define ACPI_RASF_STATUS (0x1F<<3) +/******************************************************************************* + * + * RAS2 - RAS2 Feature Table (ACPI 6.5) + * Version 1 + * + * + ******************************************************************************/ + +struct acpi_table_ras2 { + struct acpi_table_header header; /* Common ACPI table header */ + u16 reserved; + u16 num_pcc_descs; +}; + +/* RAS2 Platform Communication Channel Descriptor */ + +struct acpi_ras2_pcc_desc { + u8 channel_id; + u16 reserved; + u8 feature_type; + u32 instance; +}; + +/* RAS2 Platform Communication Channel Shared Memory Region */ + +struct acpi_ras2_shared_memory { + u32 signature; + u16 command; + u16 status; + u16 version; + u8 features[16]; + u8 set_capabilities[16]; + u16 num_parameter_blocks; + u32 set_capabilities_status; +}; + +/* RAS2 Parameter Block Structure for PATROL_SCRUB */ + +struct acpi_ras2_parameter_block { + u16 type; + u16 version; + u16 length; +}; + +/* RAS2 Parameter Block Structure for PATROL_SCRUB */ + +struct acpi_ras2_patrol_scrub_parameter { + struct acpi_ras2_parameter_block header; + u16 patrol_scrub_command; + u64 requested_address_range[2]; + u64 actual_address_range[2]; + u32 flags; + u32 scrub_params_out; + u32 scrub_params_in; +}; + +/* Masks for Flags field above */ + +#define ACPI_RAS2_SCRUBBER_RUNNING 1 + +/* RAS2 Parameter Block Structure for LA2PA_TRANSLATION */ + +struct acpi_ras2_la2pa_translation_parameter { + struct acpi_ras2_parameter_block header; + u16 addr_translation_command; + u64 sub_inst_id; + u64 logical_address; + u64 physical_address; + u32 status; +}; + +/* Channel Commands */ + +enum acpi_ras2_commands { + ACPI_RAS2_EXECUTE_RAS2_COMMAND = 1 +}; + +/* Platform RAS2 Features */ + +enum acpi_ras2_features { + ACPI_RAS2_PATROL_SCRUB_SUPPORTED = 0, + ACPI_RAS2_LA2PA_TRANSLATION = 1 +}; + +/* RAS2 Patrol Scrub Commands */ + +enum acpi_ras2_patrol_scrub_commands { + ACPI_RAS2_GET_PATROL_PARAMETERS = 1, + ACPI_RAS2_START_PATROL_SCRUBBER = 2, + ACPI_RAS2_STOP_PATROL_SCRUBBER = 3 +}; + +/* RAS2 LA2PA Translation Commands */ + +enum acpi_ras2_la2_pa_translation_commands { + ACPI_RAS2_GET_LA2PA_TRANSLATION = 1, +}; + +/* RAS2 LA2PA Translation Status values */ + +enum acpi_ras2_la2_pa_translation_status { + ACPI_RAS2_LA2PA_TRANSLATION_SUCCESS = 0, + ACPI_RAS2_LA2PA_TRANSLATION_FAIL = 1, +}; + +/* Channel Command flags */ + +#define ACPI_RAS2_GENERATE_SCI (1<<15) + +/* Status values */ + +enum acpi_ras2_status { + ACPI_RAS2_SUCCESS = 0, + ACPI_RAS2_NOT_VALID = 1, + ACPI_RAS2_NOT_SUPPORTED = 2, + ACPI_RAS2_BUSY = 3, + ACPI_RAS2_FAILED = 4, + ACPI_RAS2_ABORTED = 5, + ACPI_RAS2_INVALID_DATA = 6 +}; + +/* Status flags */ + +#define ACPI_RAS2_COMMAND_COMPLETE (1) +#define ACPI_RAS2_SCI_DOORBELL (1<<1) +#define ACPI_RAS2_ERROR (1<<2) +#define ACPI_RAS2_STATUS (0x1F<<3) + /******************************************************************************* * * RGRT - Regulatory Graphics Resource Table -- cgit v1.2.3 From c15fe3916b77bc809577898c0d5037b1bfd4183b Mon Sep 17 00:00:00 2001 From: Saket Dumbre Date: Wed, 18 Oct 2023 15:30:43 -0700 Subject: ACPICA: Attempt 1 to fix issue #900 ACPICA commit f5910dd1ab60780b95eed16d36860f18b01bc156 Link: https://github.com/acpica/acpica/commit/f5910dd1 Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/utdebug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/acpica/utdebug.c b/drivers/acpi/acpica/utdebug.c index c5f6c85a3a09..2f37d673e285 100644 --- a/drivers/acpi/acpica/utdebug.c +++ b/drivers/acpi/acpica/utdebug.c @@ -42,7 +42,6 @@ void acpi_ut_init_stack_ptr_trace(void) #pragma GCC diagnostic ignored "-Wdangling-pointer=" #endif acpi_gbl_entry_stack_pointer = ¤t_sp; -#pragma GCC diagnostic pop } /******************************************************************************* @@ -63,6 +62,7 @@ void acpi_ut_track_stack_ptr(void) if (¤t_sp < acpi_gbl_lowest_stack_pointer) { acpi_gbl_lowest_stack_pointer = ¤t_sp; +#pragma GCC diagnostic pop } if (acpi_gbl_nesting_level > acpi_gbl_deepest_nesting) { -- cgit v1.2.3 From 86645830e665cc0cd96ffff3ed2bd72237eb0378 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sun, 26 Nov 2023 17:38:33 +0000 Subject: ACPICA: Fix various spelling mistakes in text files and code comments ACPICA commit 6cd47047aca6e273c84a5ce95d2f6d8485f958d1 There are a handful of spelling mistakes in various files as found using codespell. Fix these. No code changes. Link: https://github.com/acpica/acpica/commit/6cd47047 Signed-off-by: Colin Ian King Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/aclocal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index 82563b44af35..02012168a087 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -547,7 +547,7 @@ struct acpi_field_info { struct acpi_ged_handler_info { struct acpi_ged_handler_info *next; - u32 int_id; /* The interrupt ID that triggers the execution ofthe evt_method. */ + u32 int_id; /* The interrupt ID that triggers the execution of the evt_method. */ struct acpi_namespace_node *evt_method; /* The _EVT method to be executed when an interrupt with ID = int_ID is received */ }; -- cgit v1.2.3 From 5a02527783caae57535e0742262cd96b7167f983 Mon Sep 17 00:00:00 2001 From: Saket Dumbre Date: Tue, 26 Dec 2023 13:32:56 -0800 Subject: ACPICA: Clean up the fix for Issue #900 ACPICA commit b6b38edb0c18017af0bd2aff4eaa502810c8873f Link: https://github.com/acpica/acpica/commit/b6b38edb Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/utdebug.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/acpica/utdebug.c b/drivers/acpi/acpica/utdebug.c index 2f37d673e285..98027d2f7bfb 100644 --- a/drivers/acpi/acpica/utdebug.c +++ b/drivers/acpi/acpica/utdebug.c @@ -42,6 +42,7 @@ void acpi_ut_init_stack_ptr_trace(void) #pragma GCC diagnostic ignored "-Wdangling-pointer=" #endif acpi_gbl_entry_stack_pointer = ¤t_sp; +#pragma GCC diagnostic pop } /******************************************************************************* @@ -61,8 +62,12 @@ void acpi_ut_track_stack_ptr(void) acpi_size current_sp; if (¤t_sp < acpi_gbl_lowest_stack_pointer) { +#pragma GCC diagnostic push +#if defined(__GNUC__) && __GNUC__ >= 12 +#pragma GCC diagnostic ignored "-Wdangling-pointer=" +#endif acpi_gbl_lowest_stack_pointer = ¤t_sp; -#pragma GCC diagnostic pop +#pragma GCC diagnostic popmake } if (acpi_gbl_nesting_level > acpi_gbl_deepest_nesting) { -- cgit v1.2.3 From ed5addd09827566df237df16357c514e2f18a9cb Mon Sep 17 00:00:00 2001 From: Saket Dumbre Date: Tue, 26 Dec 2023 13:36:14 -0800 Subject: ACPICA: Fix spelling and typos ACPICA commit a6a236c44c7d3eb54562fb5ddde4144d8347e0ac Clean up the fix for Issue #900. Link: https://github.com/acpica/acpica/commit/a6a236c4 Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/utdebug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/acpica/utdebug.c b/drivers/acpi/acpica/utdebug.c index 98027d2f7bfb..3d71bd9245c7 100644 --- a/drivers/acpi/acpica/utdebug.c +++ b/drivers/acpi/acpica/utdebug.c @@ -67,7 +67,7 @@ void acpi_ut_track_stack_ptr(void) #pragma GCC diagnostic ignored "-Wdangling-pointer=" #endif acpi_gbl_lowest_stack_pointer = ¤t_sp; -#pragma GCC diagnostic popmake +#pragma GCC diagnostic pop } if (acpi_gbl_nesting_level > acpi_gbl_deepest_nesting) { -- cgit v1.2.3 From 66536b86c57365840cd468d9c608b7833a7a0890 Mon Sep 17 00:00:00 2001 From: lijun Date: Wed, 3 Jan 2024 13:39:35 +0800 Subject: ACPICA: Modify ACPI_OBJECT_COMMON_HEADER ACPICA commit 9788e0dc955b8d439c05ee369e43865e6f106caa modify 4 macros: ACPI_OBJECT_COMMON_HEADER, ACPI_COMMON_BUFFER_INFO, ACPI_COMMON_NOTIFY_INFO, ACPI_COMMON_FIELD_INFO they cause poor readability.so del the last ";" and when use them in a single line with the ";"in the end. Link: https://github.com/acpica/acpica/commit/9788e0dc Signed-off-by: lijun Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/acobject.h | 107 +++++++++++++++++++++++++++-------------- 1 file changed, 71 insertions(+), 36 deletions(-) diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h index 1bdfeee5d7c5..8fc02946d3cd 100644 --- a/drivers/acpi/acpica/acobject.h +++ b/drivers/acpi/acpica/acobject.h @@ -48,7 +48,7 @@ u8 descriptor_type; /* To differentiate various internal objs */\ u8 type; /* acpi_object_type */\ u16 reference_count; /* For object deletion management */\ - u8 flags; + u8 flags /* * Note: There are 3 bytes available here before the * next natural alignment boundary (for both 32/64 cases) @@ -71,10 +71,12 @@ *****************************************************************************/ struct acpi_object_common { -ACPI_OBJECT_COMMON_HEADER}; + ACPI_OBJECT_COMMON_HEADER; +}; struct acpi_object_integer { - ACPI_OBJECT_COMMON_HEADER u8 fill[3]; /* Prevent warning on some compilers */ + ACPI_OBJECT_COMMON_HEADER; + u8 fill[3]; /* Prevent warning on some compilers */ u64 value; }; @@ -86,23 +88,26 @@ struct acpi_object_integer { */ #define ACPI_COMMON_BUFFER_INFO(_type) \ _type *pointer; \ - u32 length; + u32 length /* Null terminated, ASCII characters only */ struct acpi_object_string { - ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_BUFFER_INFO(char) /* String in AML stream or allocated string */ + ACPI_OBJECT_COMMON_HEADER; + ACPI_COMMON_BUFFER_INFO(char); /* String in AML stream or allocated string */ }; struct acpi_object_buffer { - ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_BUFFER_INFO(u8) /* Buffer in AML stream or allocated buffer */ + ACPI_OBJECT_COMMON_HEADER; + ACPI_COMMON_BUFFER_INFO(u8); /* Buffer in AML stream or allocated buffer */ u32 aml_length; u8 *aml_start; struct acpi_namespace_node *node; /* Link back to parent node */ }; struct acpi_object_package { - ACPI_OBJECT_COMMON_HEADER struct acpi_namespace_node *node; /* Link back to parent node */ + ACPI_OBJECT_COMMON_HEADER; + struct acpi_namespace_node *node; /* Link back to parent node */ union acpi_operand_object **elements; /* Array of pointers to acpi_objects */ u8 *aml_start; u32 aml_length; @@ -116,11 +121,13 @@ struct acpi_object_package { *****************************************************************************/ struct acpi_object_event { - ACPI_OBJECT_COMMON_HEADER acpi_semaphore os_semaphore; /* Actual OS synchronization object */ + ACPI_OBJECT_COMMON_HEADER; + acpi_semaphore os_semaphore; /* Actual OS synchronization object */ }; struct acpi_object_mutex { - ACPI_OBJECT_COMMON_HEADER u8 sync_level; /* 0-15, specified in Mutex() call */ + ACPI_OBJECT_COMMON_HEADER; + u8 sync_level; /* 0-15, specified in Mutex() call */ u16 acquisition_depth; /* Allow multiple Acquires, same thread */ acpi_mutex os_mutex; /* Actual OS synchronization object */ acpi_thread_id thread_id; /* Current owner of the mutex */ @@ -132,7 +139,8 @@ struct acpi_object_mutex { }; struct acpi_object_region { - ACPI_OBJECT_COMMON_HEADER u8 space_id; + ACPI_OBJECT_COMMON_HEADER; + u8 space_id; struct acpi_namespace_node *node; /* Containing namespace node */ union acpi_operand_object *handler; /* Handler for region access */ union acpi_operand_object *next; @@ -142,7 +150,8 @@ struct acpi_object_region { }; struct acpi_object_method { - ACPI_OBJECT_COMMON_HEADER u8 info_flags; + ACPI_OBJECT_COMMON_HEADER; + u8 info_flags; u8 param_count; u8 sync_level; union acpi_operand_object *mutex; @@ -178,33 +187,43 @@ struct acpi_object_method { */ #define ACPI_COMMON_NOTIFY_INFO \ union acpi_operand_object *notify_list[2]; /* Handlers for system/device notifies */\ - union acpi_operand_object *handler; /* Handler for Address space */ + union acpi_operand_object *handler /* Handler for Address space */ /* COMMON NOTIFY for POWER, PROCESSOR, DEVICE, and THERMAL */ struct acpi_object_notify_common { -ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_NOTIFY_INFO}; + ACPI_OBJECT_COMMON_HEADER; + ACPI_COMMON_NOTIFY_INFO; +}; struct acpi_object_device { - ACPI_OBJECT_COMMON_HEADER - ACPI_COMMON_NOTIFY_INFO struct acpi_gpe_block_info *gpe_block; + ACPI_OBJECT_COMMON_HEADER; + ACPI_COMMON_NOTIFY_INFO; + struct acpi_gpe_block_info *gpe_block; }; struct acpi_object_power_resource { - ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_NOTIFY_INFO u32 system_level; + ACPI_OBJECT_COMMON_HEADER; + ACPI_COMMON_NOTIFY_INFO; + u32 system_level; u32 resource_order; }; struct acpi_object_processor { - ACPI_OBJECT_COMMON_HEADER - /* The next two fields take advantage of the 3-byte space before NOTIFY_INFO */ + ACPI_OBJECT_COMMON_HEADER; + + /* The next two fields take advantage of the 3-byte space before NOTIFY_INFO */ + u8 proc_id; u8 length; - ACPI_COMMON_NOTIFY_INFO acpi_io_address address; + ACPI_COMMON_NOTIFY_INFO; + acpi_io_address address; }; struct acpi_object_thermal_zone { -ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_NOTIFY_INFO}; + ACPI_OBJECT_COMMON_HEADER; + ACPI_COMMON_NOTIFY_INFO; +}; /****************************************************************************** * @@ -226,17 +245,21 @@ ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_NOTIFY_INFO}; u32 base_byte_offset; /* Byte offset within containing object */\ u32 value; /* Value to store into the Bank or Index register */\ u8 start_field_bit_offset;/* Bit offset within first field datum (0-63) */\ - u8 access_length; /* For serial regions/fields */ + u8 access_length /* For serial regions/fields */ /* COMMON FIELD (for BUFFER, REGION, BANK, and INDEX fields) */ struct acpi_object_field_common { - ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO union acpi_operand_object *region_obj; /* Parent Operation Region object (REGION/BANK fields only) */ + ACPI_OBJECT_COMMON_HEADER; + ACPI_COMMON_FIELD_INFO; + union acpi_operand_object *region_obj; /* Parent Operation Region object (REGION/BANK fields only) */ }; struct acpi_object_region_field { - ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO u16 resource_length; + ACPI_OBJECT_COMMON_HEADER; + ACPI_COMMON_FIELD_INFO; + u16 resource_length; union acpi_operand_object *region_obj; /* Containing op_region object */ u8 *resource_buffer; /* resource_template for serial regions/fields */ u16 pin_number_index; /* Index relative to previous Connection/Template */ @@ -244,16 +267,20 @@ struct acpi_object_region_field { }; struct acpi_object_bank_field { - ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO union acpi_operand_object *region_obj; /* Containing op_region object */ + ACPI_OBJECT_COMMON_HEADER; + ACPI_COMMON_FIELD_INFO; + union acpi_operand_object *region_obj; /* Containing op_region object */ union acpi_operand_object *bank_obj; /* bank_select Register object */ }; struct acpi_object_index_field { - ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO - /* - * No "RegionObj" pointer needed since the Index and Data registers - * are each field definitions unto themselves. - */ + ACPI_OBJECT_COMMON_HEADER; + ACPI_COMMON_FIELD_INFO; + + /* + * No "RegionObj" pointer needed since the Index and Data registers + * are each field definitions unto themselves. + */ union acpi_operand_object *index_obj; /* Index register */ union acpi_operand_object *data_obj; /* Data register */ }; @@ -261,7 +288,9 @@ struct acpi_object_index_field { /* The buffer_field is different in that it is part of a Buffer, not an op_region */ struct acpi_object_buffer_field { - ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO u8 is_create_field; /* Special case for objects created by create_field() */ + ACPI_OBJECT_COMMON_HEADER; + ACPI_COMMON_FIELD_INFO; + u8 is_create_field; /* Special case for objects created by create_field() */ union acpi_operand_object *buffer_obj; /* Containing Buffer object */ }; @@ -272,7 +301,8 @@ struct acpi_object_buffer_field { *****************************************************************************/ struct acpi_object_notify_handler { - ACPI_OBJECT_COMMON_HEADER struct acpi_namespace_node *node; /* Parent device */ + ACPI_OBJECT_COMMON_HEADER; + struct acpi_namespace_node *node; /* Parent device */ u32 handler_type; /* Type: Device/System/Both */ acpi_notify_handler handler; /* Handler address */ void *context; @@ -280,7 +310,8 @@ struct acpi_object_notify_handler { }; struct acpi_object_addr_handler { - ACPI_OBJECT_COMMON_HEADER u8 space_id; + ACPI_OBJECT_COMMON_HEADER; + u8 space_id; u8 handler_flags; acpi_adr_space_handler handler; struct acpi_namespace_node *node; /* Parent device */ @@ -307,7 +338,8 @@ struct acpi_object_addr_handler { * The Reference.Class differentiates these types. */ struct acpi_object_reference { - ACPI_OBJECT_COMMON_HEADER u8 class; /* Reference Class */ + ACPI_OBJECT_COMMON_HEADER; + u8 class; /* Reference Class */ u8 target_type; /* Used for Index Op */ u8 resolved; /* Reference has been resolved to a value */ void *object; /* name_op=>HANDLE to obj, index_op=>union acpi_operand_object */ @@ -340,7 +372,8 @@ typedef enum { * Currently: Region and field_unit types */ struct acpi_object_extra { - ACPI_OBJECT_COMMON_HEADER struct acpi_namespace_node *method_REG; /* _REG method for this region (if any) */ + ACPI_OBJECT_COMMON_HEADER; + struct acpi_namespace_node *method_REG; /* _REG method for this region (if any) */ struct acpi_namespace_node *scope_node; void *region_context; /* Region-specific data */ u8 *aml_start; @@ -350,14 +383,16 @@ struct acpi_object_extra { /* Additional data that can be attached to namespace nodes */ struct acpi_object_data { - ACPI_OBJECT_COMMON_HEADER acpi_object_handler handler; + ACPI_OBJECT_COMMON_HEADER; + acpi_object_handler handler; void *pointer; }; /* Structure used when objects are cached for reuse */ struct acpi_object_cache_list { - ACPI_OBJECT_COMMON_HEADER union acpi_operand_object *next; /* Link for object cache and internal lists */ + ACPI_OBJECT_COMMON_HEADER; + union acpi_operand_object *next; /* Link for object cache and internal lists */ }; /****************************************************************************** -- cgit v1.2.3 From fe1c408d50604f6013ca273d14b0ffeb845f23b1 Mon Sep 17 00:00:00 2001 From: Haibo Xu Date: Wed, 17 Jan 2024 21:06:43 +0800 Subject: ACPICA: SRAT: Add RISC-V RINTC affinity structure ACPICA commit 93caddbf2f620769052c59ec471f018281dc3a24 Add definition of RISC-V Interrupt Controller(RINTC) affinity structure which was approved by UEFI forum and will be part of next ACPI spec version(6.6). Link: https://github.com/acpica/acpica/commit/93caddbf Signed-off-by: Haibo Xu Signed-off-by: Rafael J. Wysocki --- include/acpi/actbl3.h | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/include/acpi/actbl3.h b/include/acpi/actbl3.h index c080d579a546..e32149d605dc 100644 --- a/include/acpi/actbl3.h +++ b/include/acpi/actbl3.h @@ -192,7 +192,8 @@ enum acpi_srat_type { ACPI_SRAT_TYPE_GIC_ITS_AFFINITY = 4, /* ACPI 6.2 */ ACPI_SRAT_TYPE_GENERIC_AFFINITY = 5, /* ACPI 6.3 */ ACPI_SRAT_TYPE_GENERIC_PORT_AFFINITY = 6, /* ACPI 6.4 */ - ACPI_SRAT_TYPE_RESERVED = 7 /* 7 and greater are reserved */ + ACPI_SRAT_TYPE_RINTC_AFFINITY = 7, /* ACPI 6.6 */ + ACPI_SRAT_TYPE_RESERVED = 8 /* 8 and greater are reserved */ }; /* @@ -296,6 +297,21 @@ struct acpi_srat_generic_affinity { #define ACPI_SRAT_GENERIC_AFFINITY_ENABLED (1) /* 00: Use affinity structure */ #define ACPI_SRAT_ARCHITECTURAL_TRANSACTIONS (1<<1) /* ACPI 6.4 */ +/* 7: RINTC Affinity Structure(ACPI 6.6) */ + +struct acpi_srat_rintc_affinity { + struct acpi_subtable_header header; + u16 reserved; + u32 proximity_domain; + u32 acpi_processor_uid; + u32 flags; + u32 clock_domain; +}; + +/* Flags for ACPI_SRAT_RINTC_AFFINITY */ + +#define ACPI_SRAT_RINTC_ENABLED (1) /* 00: Use affinity structure */ + /******************************************************************************* * * STAO - Status Override Table (_STA override) - ACPI 6.0 -- cgit v1.2.3 From e19481071d0afe3b05cbb6602d7a53599e3e8506 Mon Sep 17 00:00:00 2001 From: Haibo Xu Date: Wed, 17 Jan 2024 21:17:35 +0800 Subject: ACPICA: SRAT: Add dump and compiler support for RINTC affinity structure ACPICA commit b9423c1d35b072c8f2acf97a5842b9f144449eaa After adding RISC-V RINTC affinity structure definition, enable corresponding dump and compiler support. Link: https://github.com/acpica/acpica/commit/b9423c1d Signed-off-by: Haibo Xu Signed-off-by: Rafael J. Wysocki --- include/acpi/actbl3.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/acpi/actbl3.h b/include/acpi/actbl3.h index e32149d605dc..8f775e3a08fd 100644 --- a/include/acpi/actbl3.h +++ b/include/acpi/actbl3.h @@ -308,7 +308,7 @@ struct acpi_srat_rintc_affinity { u32 clock_domain; }; -/* Flags for ACPI_SRAT_RINTC_AFFINITY */ +/* Flags for struct acpi_srat_rintc_affinity */ #define ACPI_SRAT_RINTC_ENABLED (1) /* 00: Use affinity structure */ -- cgit v1.2.3 From 7f35712c2da2b92e03baf618fe469c64591d96fd Mon Sep 17 00:00:00 2001 From: Hojin Nam Date: Mon, 19 Feb 2024 10:06:52 +0900 Subject: ACPICA: Fix CXL 3.0 structure (RDPAS) in the CEDT table ACPICA commit a0ad1ed5105fb8a15f6f8384b8ab0a2157efaf23 struct acpi_cedt_rdpas does not match with CXL r3.0 9.17.1.5 Table 9-24. reserved1 and length fields are already added by struct acpi_cedt_header. Link: https://github.com/acpica/acpica/commit/a0ad1ed5 Signed-off-by: Hojin Nam Signed-off-by: Rafael J. Wysocki --- include/acpi/actbl1.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/acpi/actbl1.h b/include/acpi/actbl1.h index 1f58c5d86869..841ef9f22795 100644 --- a/include/acpi/actbl1.h +++ b/include/acpi/actbl1.h @@ -571,8 +571,6 @@ struct acpi_cedt_cxims { struct acpi_cedt_rdpas { struct acpi_cedt_header header; - u8 reserved1; - u16 length; u16 segment; u16 bdf; u8 protocol; -- cgit v1.2.3 From a210accc067ad18d55ea19b6d7a9d9176d809a74 Mon Sep 17 00:00:00 2001 From: Daniil Tatianin <99danilt@gmail.com> Date: Thu, 21 Mar 2024 21:57:12 +0300 Subject: ACPICA: events/evgpeinit: don't forget to increment registered GPE count ACPICA commit ba8a36b5c7343cb56af6b331362e97b25e898eb2 This was used to log the number of newly discovered GPEs post table load in acpi_ev_update_gpes(), but we never incremented the number inside acpi_ev_match_gpe_method(), so that was never logged. Link: https://github.com/acpica/acpica/commit/ba8a36b5 Signed-off-by: Daniil Tatianin <99danilt@gmail.com> Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/evgpeinit.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/acpi/acpica/evgpeinit.c b/drivers/acpi/acpica/evgpeinit.c index 0dbc4d88919a..38f408cf13ce 100644 --- a/drivers/acpi/acpica/evgpeinit.c +++ b/drivers/acpi/acpica/evgpeinit.c @@ -413,6 +413,7 @@ acpi_ev_match_gpe_method(acpi_handle obj_handle, gpe_event_info->flags &= ~(ACPI_GPE_DISPATCH_MASK); gpe_event_info->flags |= (u8)(type | ACPI_GPE_DISPATCH_METHOD); gpe_event_info->dispatch.method_node = method_node; + walk_info->count++; ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "Registered GPE method %s as GPE number 0x%.2X\n", -- cgit v1.2.3 From e1d3f9d46f17e762d2dd4027456386509a6e6774 Mon Sep 17 00:00:00 2001 From: Saket Dumbre Date: Thu, 21 Mar 2024 22:00:09 -0700 Subject: ACPICA: Update acpixf.h for new ACPICA release 20240322 ACPICA commit 718374cd1bc21d08960b61069c8ac62b0cf67c0c Link: https://github.com/acpica/acpica/commit/718374cd Signed-off-by: Rafael J. Wysocki --- include/acpi/acpixf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 3d90716f9522..94d0fc3bd412 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -12,7 +12,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20230628 +#define ACPI_CA_VERSION 0x20240322 #include #include -- cgit v1.2.3 From 6eaf375a5a98642ba4c327f79673f4f308e0ac03 Mon Sep 17 00:00:00 2001 From: Guenter Schafranek Date: Mon, 15 Apr 2024 20:51:18 +0200 Subject: ACPI: resource: Do IRQ override on GMxBGxx (XMG APEX 17 M23) The XM APEX 17 M23 (TongFang?) GMxBGxx (got using `sudo dmidecode -s baseboard-product-name`) needs IRQ overriding for the keyboard to work. Adding an entry for this laptop to the override_table makes the internal keyboard functional [1]. Successfully tested with Arch Linux Kernel v6.8 under Manjaro Linux v23.1.4. Link: https://www.reddit.com/r/XMG_gg/comments/15kd5pg/xmg_apex_17_m23_keyboard_not_working_on_linux/ # [1] Signed-off-by: Guenter Schafranek Signed-off-by: Rafael J. Wysocki --- drivers/acpi/resource.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index 59423fe9d0f2..c9af5d2f4d2d 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -533,6 +533,12 @@ static const struct dmi_system_id irq1_level_low_skip_override[] = { * to have a working keyboard. */ static const struct dmi_system_id irq1_edge_low_force_override[] = { + { + /* XMG APEX 17 (M23) */ + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "GMxBGxx"), + }, + }, { /* TongFang GMxRGxx/XMG CORE 15 (M22)/TUXEDO Stellaris 15 Gen4 AMD */ .matches = { -- cgit v1.2.3 From c81bf14f9db68311c2e75428eea070d97d603975 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Mon, 22 Apr 2024 10:04:36 +0200 Subject: ACPI: resource: Do IRQ override on TongFang GXxHRXx and GMxHGxx Listed devices need the override for the keyboard to work. Signed-off-by: Christoffer Sandberg Signed-off-by: Werner Sembach Cc: All applicable Signed-off-by: Rafael J. Wysocki --- drivers/acpi/resource.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index c9af5d2f4d2d..65fa94729d9d 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -636,6 +636,18 @@ static const struct dmi_system_id irq1_edge_low_force_override[] = { DMI_MATCH(DMI_BOARD_NAME, "X565"), }, }, + { + /* TongFang GXxHRXx/TUXEDO InfinityBook Pro Gen9 AMD */ + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "GXxHRXx"), + }, + }, + { + /* TongFang GMxHGxx/TUXEDO Stellaris Slim Gen1 AMD */ + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "GMxHGxx"), + }, + }, { } }; -- cgit v1.2.3 From 59c9450b881190b497a0a61ab793a5a1b6bd006d Mon Sep 17 00:00:00 2001 From: Niklas Schnelle Date: Fri, 5 Apr 2024 16:22:26 +0200 Subject: PNP: add HAS_IOPORT dependencies In a future patch HAS_IOPORT=n will disable inb()/outb() and friends at compile time. We thus need to depend on HAS_IOPORT even when compile testing only. Acked-by: Rafael J. Wysocki Co-developed-by: Arnd Bergmann Signed-off-by: Arnd Bergmann Signed-off-by: Niklas Schnelle Signed-off-by: Rafael J. Wysocki --- drivers/pnp/isapnp/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pnp/isapnp/Kconfig b/drivers/pnp/isapnp/Kconfig index 8b5f2e461a80..8e5dec59e342 100644 --- a/drivers/pnp/isapnp/Kconfig +++ b/drivers/pnp/isapnp/Kconfig @@ -4,7 +4,7 @@ # config ISAPNP bool "ISA Plug and Play support" - depends on ISA || COMPILE_TEST + depends on ISA || (HAS_IOPORT && COMPILE_TEST) help Say Y here if you would like support for ISA Plug and Play devices. Some information is in . -- cgit v1.2.3 From e97d05b5e1bdaab61489942d1492bcd5eca9f0d5 Mon Sep 17 00:00:00 2001 From: John Watts Date: Wed, 24 Apr 2024 08:16:43 +1000 Subject: Documentation: firmware-guide: ACPI: Fix namespace typo The ACPI namespace has always started with LNXSYSTM, not LNXSYSTEM. Fix the documentation accordingly. Signed-off-by: John Watts Signed-off-by: Rafael J. Wysocki --- Documentation/firmware-guide/acpi/namespace.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/firmware-guide/acpi/namespace.rst b/Documentation/firmware-guide/acpi/namespace.rst index 4ef963679a3d..5021843b526b 100644 --- a/Documentation/firmware-guide/acpi/namespace.rst +++ b/Documentation/firmware-guide/acpi/namespace.rst @@ -15,7 +15,7 @@ ACPI Device Tree - Representation of ACPI Namespace Abstract ======== The Linux ACPI subsystem converts ACPI namespace objects into a Linux -device tree under the /sys/devices/LNXSYSTEM:00 and updates it upon +device tree under the /sys/devices/LNXSYSTM:00 and updates it upon receiving ACPI hotplug notification events. For each device object in this hierarchy there is a corresponding symbolic link in the /sys/bus/acpi/devices. @@ -326,7 +326,7 @@ example ACPI namespace illustrated in Figure 2 with the addition of fixed PWR_BUTTON/SLP_BUTTON devices is shown below:: +--------------+---+-----------------+ - | LNXSYSTEM:00 | \ | acpi:LNXSYSTEM: | + | LNXSYSTM:00 | \ | acpi:LNXSYSTM: | +--------------+---+-----------------+ | | +-------------+-----+----------------+ -- cgit v1.2.3 From 49c192d2af8cf1364a8130652cfc9ec5cda775f2 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Mon, 22 Apr 2024 21:13:42 +0300 Subject: ACPI: property: Add reference to UEFI DSD Guide The UEFI DSD Guide specifies a number of GUIDs supported by the _DSD parser. Point to the DSD Guide in the documentation. Signed-off-by: Sakari Ailus Reviewed-by: Andy Shevchenko Signed-off-by: Rafael J. Wysocki --- drivers/acpi/property.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c index 2b73580c9f36..80a52a4e66dd 100644 --- a/drivers/acpi/property.c +++ b/drivers/acpi/property.c @@ -31,9 +31,14 @@ static int acpi_data_get_property_array(const struct acpi_device_data *data, * not defined without a warning. For instance if any of the properties * from different GUID appear in a property list of another, it will be * accepted by the kernel. Firmware validation tools should catch these. + * + * References: + * + * [1] UEFI DSD Guide. + * https://github.com/UEFI/DSD-Guide/blob/main/src/dsd-guide.adoc */ static const guid_t prp_guids[] = { - /* ACPI _DSD device properties GUID: daffd814-6eba-4d8c-8a91-bc9bbf4aa301 */ + /* ACPI _DSD device properties GUID [1]: daffd814-6eba-4d8c-8a91-bc9bbf4aa301 */ GUID_INIT(0xdaffd814, 0x6eba, 0x4d8c, 0x8a, 0x91, 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01), /* Hotplug in D3 GUID: 6211e2c0-58a3-4af3-90e1-927a4e0c55a4 */ @@ -53,12 +58,12 @@ static const guid_t prp_guids[] = { 0xa5, 0x61, 0x99, 0xa5, 0x18, 0x97, 0x62, 0xd0), }; -/* ACPI _DSD data subnodes GUID: dbb8e3e6-5886-4ba6-8795-1319f52a966b */ +/* ACPI _DSD data subnodes GUID [1]: dbb8e3e6-5886-4ba6-8795-1319f52a966b */ static const guid_t ads_guid = GUID_INIT(0xdbb8e3e6, 0x5886, 0x4ba6, 0x87, 0x95, 0x13, 0x19, 0xf5, 0x2a, 0x96, 0x6b); -/* ACPI _DSD data buffer GUID: edb12dd0-363d-4085-a3d2-49522ca160c4 */ +/* ACPI _DSD data buffer GUID [1]: edb12dd0-363d-4085-a3d2-49522ca160c4 */ static const guid_t buffer_prop_guid = GUID_INIT(0xedb12dd0, 0x363d, 0x4085, 0xa3, 0xd2, 0x49, 0x52, 0x2c, 0xa1, 0x60, 0xc4); -- cgit v1.2.3 From d7bd0aeb5ab6609b71ca87db4ec6d8bba24b2209 Mon Sep 17 00:00:00 2001 From: Chen Yu Date: Fri, 26 Apr 2024 17:48:50 +0800 Subject: ACPI: tools: pfrut: Print the update_cap field during capability query There is request from the end user to print this field to better query what type of update capability is supported on this platform. Signed-off-by: Chen Yu Signed-off-by: Rafael J. Wysocki --- tools/power/acpi/tools/pfrut/pfrut.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/power/acpi/tools/pfrut/pfrut.c b/tools/power/acpi/tools/pfrut/pfrut.c index 388c9e3ad040..44a9ecbd91e8 100644 --- a/tools/power/acpi/tools/pfrut/pfrut.c +++ b/tools/power/acpi/tools/pfrut/pfrut.c @@ -174,6 +174,8 @@ void print_cap(struct pfru_update_cap_info *cap) exit(1); } + printf("update capability:%d\n", cap->update_cap); + uuid_unparse(cap->code_type, uuid); printf("code injection image type:%s\n", uuid); printf("fw_version:%d\n", cap->fw_version); -- cgit v1.2.3 From e049249013b13297817a1b0a33bbedec0ebca293 Mon Sep 17 00:00:00 2001 From: Ruidong Tian Date: Thu, 25 Apr 2024 17:34:26 +0800 Subject: ACPICA: AEST: Add support for the AEST V2 table ACPICA commit ebb49799c78891cbe370f1264844664a3d8b6f35 AEST V2 was published[1], add V2 support based on AEST V1. [1]: https://developer.arm.com/documentation/den0085/latest/ Link: https://github.com/acpica/acpica/commit/ebb4979 Signed-off-by: Ruidong Tian Signed-off-by: Rafael J. Wysocki --- include/acpi/actbl2.h | 88 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 82 insertions(+), 6 deletions(-) diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h index 64a3f9ae2641..fdfe87fc523c 100644 --- a/include/acpi/actbl2.h +++ b/include/acpi/actbl2.h @@ -78,8 +78,8 @@ * * AEST - Arm Error Source Table * - * Conforms to: ACPI for the Armv8 RAS Extensions 1.1 Platform Design Document - * September 2020. + * Conforms to: ACPI for the Armv8 RAS Extensions 1.1(Sep 2020) and + * 2.0(May 2023) Platform Design Document. * ******************************************************************************/ @@ -109,7 +109,9 @@ struct acpi_aest_hdr { #define ACPI_AEST_SMMU_ERROR_NODE 2 #define ACPI_AEST_VENDOR_ERROR_NODE 3 #define ACPI_AEST_GIC_ERROR_NODE 4 -#define ACPI_AEST_NODE_TYPE_RESERVED 5 /* 5 and above are reserved */ +#define ACPI_AEST_PCIE_ERROR_NODE 5 +#define ACPI_AEST_PROXY_ERROR_NODE 6 +#define ACPI_AEST_NODE_TYPE_RESERVED 7 /* 7 and above are reserved */ /* * AEST subtables (Error nodes) @@ -188,6 +190,12 @@ typedef struct acpi_aest_vendor { } acpi_aest_vendor; +struct acpi_aest_vendor_v2 { + char acpi_hid[8]; + u32 acpi_uid; + u8 vendor_specific_data[16]; +}; + /* 4: Gic Error */ typedef struct acpi_aest_gic { @@ -204,6 +212,18 @@ typedef struct acpi_aest_gic { #define ACPI_AEST_GIC_ITS 3 #define ACPI_AEST_GIC_RESERVED 4 /* 4 and above are reserved */ +/* 5: PCIe Error */ + +struct acpi_aest_pcie { + u32 iort_node_reference; +}; + +/* 6: Proxy Error */ + +struct acpi_aest_proxy { + u64 node_address; +}; + /* Node Interface Structure */ typedef struct acpi_aest_node_interface { @@ -219,11 +239,57 @@ typedef struct acpi_aest_node_interface { } acpi_aest_node_interface; +/* Node Interface Structure V2 */ + +struct acpi_aest_node_interface_header { + u8 type; + u8 group_format; + u8 reserved[2]; + u32 flags; + u64 address; + u32 error_record_index; + u32 error_record_count; +}; + +#define ACPI_AEST_NODE_GROUP_FORMAT_4K 0 +#define ACPI_AEST_NODE_GROUP_FORMAT_16K 1 +#define ACPI_AEST_NODE_GROUP_FORMAT_64K 2 + +struct acpi_aest_node_interface_common { + u32 error_node_device; + u32 processor_affinity; + u64 error_group_register_base; + u64 fault_inject_register_base; + u64 interrupt_config_register_base; +}; + +struct acpi_aest_node_interface_4k { + u64 error_record_implemented; + u64 error_status_reporting; + u64 addressing_mode; + struct acpi_aest_node_interface_common common; +}; + +struct acpi_aest_node_interface_16k { + u64 error_record_implemented[4]; + u64 error_status_reporting[4]; + u64 addressing_mode[4]; + struct acpi_aest_node_interface_common common; +}; + +struct acpi_aest_node_interface_64k { + u64 error_record_implemented[14]; + u64 error_status_reporting[14]; + u64 addressing_mode[14]; + struct acpi_aest_node_interface_common common; +}; + /* Values for Type field above */ -#define ACPI_AEST_NODE_SYSTEM_REGISTER 0 -#define ACPI_AEST_NODE_MEMORY_MAPPED 1 -#define ACPI_AEST_XFACE_RESERVED 2 /* 2 and above are reserved */ +#define ACPI_AEST_NODE_SYSTEM_REGISTER 0 +#define ACPI_AEST_NODE_MEMORY_MAPPED 1 +#define ACPI_AEST_NODE_SINGLE_RECORD_MEMORY_MAPPED 2 +#define ACPI_AEST_XFACE_RESERVED 3 /* 2 and above are reserved */ /* Node Interrupt Structure */ @@ -237,6 +303,16 @@ typedef struct acpi_aest_node_interrupt { } acpi_aest_node_interrupt; +/* Node Interrupt Structure V2 */ + +struct acpi_aest_node_interrupt_v2 { + u8 type; + u8 reserved[2]; + u8 flags; + u32 gsiv; + u8 reserved1[4]; +}; + /* Values for Type field above */ #define ACPI_AEST_NODE_FAULT_HANDLING 0 -- cgit v1.2.3 From 7c52c7071bd403acee8cb0064627d46c6c2a1ea3 Mon Sep 17 00:00:00 2001 From: Tamim Khan Date: Sun, 28 Apr 2024 13:08:12 -0400 Subject: ACPI: resource: Skip IRQ override on Asus Vivobook Pro N6506MV Like various other Asus Vivobook and Expertbook laptops, the Asus Vivobook Pro N6506MV has a DSDT table that describes IRQ 1 as ActiveLow while the kernel is overriding it to Edge_High. This prevents the internal keyboard from working. This patch prevents this issue by adding this laptop to the override table that prevents the kernel from overriding this IRQ Link: https://bugzilla.kernel.org/show_bug.cgi?id=218745 Tested-by: Gianni Signed-off-by: Tamim Khan Signed-off-by: Rafael J. Wysocki --- drivers/acpi/resource.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index 65fa94729d9d..b5bf8b81a050 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -517,6 +517,13 @@ static const struct dmi_system_id irq1_level_low_skip_override[] = { DMI_MATCH(DMI_BOARD_NAME, "E1504GAB"), }, }, + { + /* Asus Vivobook Pro N6506MV */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_BOARD_NAME, "N6506MV"), + }, + }, { /* LG Electronics 17U70P */ .matches = { -- cgit v1.2.3 From dfac21b1eeefe8ae472e3fee511cfdcf7d03bb4b Mon Sep 17 00:00:00 2001 From: Kuppuswamy Sathyanarayanan Date: Sun, 28 Apr 2024 21:04:41 -0700 Subject: ACPI: Move acpi_blacklisted() declaration to asm/acpi.h The function acpi_blacklisted() is defined only when CONFIG_X86 is enabled and is only used by X86 arch code. To align with its usage and definition conditions, move its declaration to asm/acpi.h Signed-off-by: Kuppuswamy Sathyanarayanan Reviewed-by: Andy Shevchenko [ rjw: Added empty code line in a header file ] Signed-off-by: Rafael J. Wysocki --- arch/x86/include/asm/acpi.h | 2 ++ include/linux/acpi.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h index f896eed4516c..5af926c050f0 100644 --- a/arch/x86/include/asm/acpi.h +++ b/arch/x86/include/asm/acpi.h @@ -56,6 +56,8 @@ static inline void disable_acpi(void) extern int acpi_gsi_to_irq(u32 gsi, unsigned int *irq); +extern int acpi_blacklisted(void); + static inline void acpi_noirq_set(void) { acpi_noirq = 1; } static inline void acpi_disable_pci(void) { diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 34829f2c517a..2009f7ea5963 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -421,7 +421,7 @@ extern char *wmi_get_acpi_device_uid(const char *guid); extern char acpi_video_backlight_string[]; extern long acpi_is_video_device(acpi_handle handle); -extern int acpi_blacklisted(void); + extern void acpi_osi_setup(char *str); extern bool acpi_osi_is_win8(void); -- cgit v1.2.3 From d4aa921eb85a74bf0502eff64f0b9e06fe17081b Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 30 Apr 2024 18:02:20 +0200 Subject: ACPI: scan: Avoid enumerating devices with clearly invalid _STA values The return value of _STA with the "present" bit unset and the "enabled" bit set is clearly invalid as per the ACPI specification, Section 6.3.7 "_STA (Device Status)", so make the ACPI device enumeration code disregard devices with such _STA return values. Also, because this implies that status.enabled will only be set if status.present is set too, acpi_device_is_enabled() can be modified to simply return the value of the former. Link: https://uefi.org/specs/ACPI/6.5/06_Device_Configuration.html#sta-device-status Link: https://lore.kernel.org/linux-acpi/88179311a503493099028c12ca37d430@huawei.com/ Suggested-by: Salil Mehta Signed-off-by: Rafael J. Wysocki Reviewed-by: Jonathan Cameron Reviewed-by: Sudeep Holla --- drivers/acpi/bus.c | 11 +++++++++++ drivers/acpi/scan.c | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index d9fa730416f1..18d50448ae1c 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -112,6 +112,17 @@ int acpi_bus_get_status(struct acpi_device *device) if (ACPI_FAILURE(status)) return -ENODEV; + if (!device->status.present && device->status.enabled) { + pr_info(FW_BUG "Device [%s] status [%08x]: not present and enabled\n", + device->pnp.bus_id, (u32)sta); + device->status.enabled = 0; + /* + * The status is clearly invalid, so clear the functional bit as + * well to avoid attempting to use the device. + */ + device->status.functional = 0; + } + acpi_set_device_status(device, sta); if (device->status.functional && !device->status.present) { diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 68f101323f53..e41fb5716bc0 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1962,7 +1962,7 @@ bool acpi_device_is_present(const struct acpi_device *adev) bool acpi_device_is_enabled(const struct acpi_device *adev) { - return adev->status.present && adev->status.enabled; + return adev->status.enabled; } static bool acpi_scan_handler_matching(struct acpi_scan_handler *handler, -- cgit v1.2.3 From c901f63dc142c48326931f164f787dfff69273d9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 6 May 2024 16:08:50 +0200 Subject: ACPI: video: Add backlight=native quirk for Lenovo Slim 7 16ARH7 Lenovo Slim 7 16ARH7 is a machine with switchable graphics between AMD and Nvidia, and the backlight can't be adjusted properly unless acpi_backlight=native is passed. Although nvidia-wmi-backlight is present and loaded, this doesn't work as expected at all. For making it working as default, add the corresponding quirk entry with a DMI matching "LENOVO" "82UX". Link: https://bugzilla.suse.com/show_bug.cgi?id=1217750 Signed-off-by: Takashi Iwai Signed-off-by: Rafael J. Wysocki --- drivers/acpi/video_detect.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index 9fdcc620c652..2cc3821b2b16 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -497,6 +497,14 @@ static const struct dmi_system_id video_detect_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "82BK"), }, }, + { + .callback = video_detect_force_native, + /* Lenovo Slim 7 16ARH7 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "82UX"), + }, + }, { .callback = video_detect_force_native, /* Lenovo ThinkPad X131e (3371 AMD version) */ -- cgit v1.2.3 From f9f67e5adc8dc2e1cc51ab2d3d6382fa97f074d4 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Thu, 2 May 2024 15:10:09 +0200 Subject: x86/numa: Fix SRAT lookup of CFMWS ranges with numa_fill_memblks() For configurations that have the kconfig option NUMA_KEEP_MEMINFO disabled, numa_fill_memblks() only returns with NUMA_NO_MEMBLK (-1). SRAT lookup fails then because an existing SRAT memory range cannot be found for a CFMWS address range. This causes the addition of a duplicate numa_memblk with a different node id and a subsequent page fault and kernel crash during boot. Fix this by making numa_fill_memblks() always available regardless of NUMA_KEEP_MEMINFO. As Dan suggested, the fix is implemented to remove numa_fill_memblks() from sparsemem.h and alos using __weak for the function. Note that the issue was initially introduced with [1]. But since phys_to_target_node() was originally used that returned the valid node 0, an additional numa_memblk was not added. Though, the node id was wrong too, a message is seen then in the logs: kernel/numa.c: pr_info_once("Unknown target node for memory at 0x%llx, assuming node 0\n", [1] commit fd49f99c1809 ("ACPI: NUMA: Add a node and memblk for each CFMWS not in SRAT") Suggested-by: Dan Williams Link: https://lore.kernel.org/all/66271b0072317_69102944c@dwillia2-xfh.jf.intel.com.notmuch/ Fixes: 8f1004679987 ("ACPI/NUMA: Apply SRAT proximity domain to entire CFMWS window") Reviewed-by: Jonathan Cameron Reviewed-by: Alison Schofield Reviewed-by: Dan Williams Signed-off-by: Robert Richter Acked-by: Borislav Petkov (AMD) Signed-off-by: Rafael J. Wysocki --- arch/x86/include/asm/sparsemem.h | 2 -- arch/x86/mm/numa.c | 4 ++-- drivers/acpi/numa/srat.c | 5 +++++ include/linux/numa.h | 7 +------ 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/arch/x86/include/asm/sparsemem.h b/arch/x86/include/asm/sparsemem.h index 1be13b2dfe8b..64df897c0ee3 100644 --- a/arch/x86/include/asm/sparsemem.h +++ b/arch/x86/include/asm/sparsemem.h @@ -37,8 +37,6 @@ extern int phys_to_target_node(phys_addr_t start); #define phys_to_target_node phys_to_target_node extern int memory_add_physaddr_to_nid(u64 start); #define memory_add_physaddr_to_nid memory_add_physaddr_to_nid -extern int numa_fill_memblks(u64 start, u64 end); -#define numa_fill_memblks numa_fill_memblks #endif #endif /* __ASSEMBLY__ */ diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c index 65e9a6e391c0..ce84ba86e69e 100644 --- a/arch/x86/mm/numa.c +++ b/arch/x86/mm/numa.c @@ -929,6 +929,8 @@ int memory_add_physaddr_to_nid(u64 start) } EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid); +#endif + static int __init cmp_memblk(const void *a, const void *b) { const struct numa_memblk *ma = *(const struct numa_memblk **)a; @@ -1001,5 +1003,3 @@ int __init numa_fill_memblks(u64 start, u64 end) } return 0; } - -#endif diff --git a/drivers/acpi/numa/srat.c b/drivers/acpi/numa/srat.c index e45e64993c50..3b09fd39eeb4 100644 --- a/drivers/acpi/numa/srat.c +++ b/drivers/acpi/numa/srat.c @@ -208,6 +208,11 @@ int __init srat_disabled(void) return acpi_numa < 0; } +__weak int __init numa_fill_memblks(u64 start, u64 end) +{ + return NUMA_NO_MEMBLK; +} + #if defined(CONFIG_X86) || defined(CONFIG_ARM64) || defined(CONFIG_LOONGARCH) /* * Callback for SLIT parsing. pxm_to_node() returns NUMA_NO_NODE for diff --git a/include/linux/numa.h b/include/linux/numa.h index 915033a75731..1d43371fafd2 100644 --- a/include/linux/numa.h +++ b/include/linux/numa.h @@ -36,12 +36,7 @@ int memory_add_physaddr_to_nid(u64 start); int phys_to_target_node(u64 start); #endif -#ifndef numa_fill_memblks -static inline int __init numa_fill_memblks(u64 start, u64 end) -{ - return NUMA_NO_MEMBLK; -} -#endif +int numa_fill_memblks(u64 start, u64 end); #else /* !CONFIG_NUMA */ static inline int numa_nearest_node(int node, unsigned int state) -- cgit v1.2.3 From 3a785e19f432672b9ef53f07c506d5e698439033 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Thu, 2 May 2024 15:10:10 +0200 Subject: ACPI/NUMA: Remove architecture dependent remainings With the removal of the Itanium architecture [1] the last architecture dependent functions: acpi_numa_slit_init(), acpi_numa_memory_affinity_init() were removed. Remove its remainings in the header files too and make them static. [1] commit cf8e8658100d ("arch: Remove Itanium (IA-64) architecture") Reviewed-by: Dan Williams Reviewed-by: Jonathan Cameron Reviewed-by: Alison Schofield Signed-off-by: Robert Richter Signed-off-by: Rafael J. Wysocki --- drivers/acpi/numa/srat.c | 16 ++-------------- include/linux/acpi.h | 5 ----- 2 files changed, 2 insertions(+), 19 deletions(-) diff --git a/drivers/acpi/numa/srat.c b/drivers/acpi/numa/srat.c index 3b09fd39eeb4..e4d53e3660fd 100644 --- a/drivers/acpi/numa/srat.c +++ b/drivers/acpi/numa/srat.c @@ -213,13 +213,12 @@ __weak int __init numa_fill_memblks(u64 start, u64 end) return NUMA_NO_MEMBLK; } -#if defined(CONFIG_X86) || defined(CONFIG_ARM64) || defined(CONFIG_LOONGARCH) /* * Callback for SLIT parsing. pxm_to_node() returns NUMA_NO_NODE for * I/O localities since SRAT does not list them. I/O localities are * not supported at this point. */ -void __init acpi_numa_slit_init(struct acpi_table_slit *slit) +static void __init acpi_numa_slit_init(struct acpi_table_slit *slit) { int i, j; @@ -241,11 +240,7 @@ void __init acpi_numa_slit_init(struct acpi_table_slit *slit) } } -/* - * Default callback for parsing of the Proximity Domain <-> Memory - * Area mappings - */ -int __init +static int __init acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma) { u64 start, end; @@ -345,13 +340,6 @@ static int __init acpi_parse_cfmws(union acpi_subtable_headers *header, (*fake_pxm)++; return 0; } -#else -static int __init acpi_parse_cfmws(union acpi_subtable_headers *header, - void *arg, const unsigned long table_end) -{ - return 0; -} -#endif /* defined(CONFIG_X86) || defined (CONFIG_ARM64) */ static int __init acpi_parse_slit(struct acpi_table_header *table) { diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 34829f2c517a..2c227b61a452 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -242,9 +242,6 @@ static inline bool acpi_gicc_is_usable(struct acpi_madt_generic_interrupt *gicc) return gicc->flags & ACPI_MADT_ENABLED; } -/* the following numa functions are architecture-dependent */ -void acpi_numa_slit_init (struct acpi_table_slit *slit); - #if defined(CONFIG_X86) || defined(CONFIG_LOONGARCH) void acpi_numa_processor_affinity_init (struct acpi_srat_cpu_affinity *pa); #else @@ -267,8 +264,6 @@ static inline void acpi_numa_gicc_affinity_init(struct acpi_srat_gicc_affinity *pa) { } #endif -int acpi_numa_memory_affinity_init (struct acpi_srat_mem_affinity *ma); - #ifndef PHYS_CPUID_INVALID typedef u32 phys_cpuid_t; #define PHYS_CPUID_INVALID (phys_cpuid_t)(-1) -- cgit v1.2.3 From f4469879ea5c9c8c6fa51fd7764f7eaeb71c07f5 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Thu, 2 May 2024 15:10:11 +0200 Subject: ACPI/NUMA: Squash acpi_numa_slit_init() into acpi_parse_slit() After removing architectural code the helper function acpi_numa_slit_init() is no longer needed. Squash it into acpi_parse_slit(). No functional changes intended. Reviewed-by: Dan Williams Reviewed-by: Jonathan Cameron Reviewed-by: Alison Schofield Signed-off-by: Robert Richter Signed-off-by: Rafael J. Wysocki --- drivers/acpi/numa/srat.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/drivers/acpi/numa/srat.c b/drivers/acpi/numa/srat.c index e4d53e3660fd..430ddcfb8312 100644 --- a/drivers/acpi/numa/srat.c +++ b/drivers/acpi/numa/srat.c @@ -218,10 +218,16 @@ __weak int __init numa_fill_memblks(u64 start, u64 end) * I/O localities since SRAT does not list them. I/O localities are * not supported at this point. */ -static void __init acpi_numa_slit_init(struct acpi_table_slit *slit) +static int __init acpi_parse_slit(struct acpi_table_header *table) { + struct acpi_table_slit *slit = (struct acpi_table_slit *)table; int i, j; + if (!slit_valid(slit)) { + pr_info("SLIT table looks invalid. Not used.\n"); + return -EINVAL; + } + for (i = 0; i < slit->locality_count; i++) { const int from_node = pxm_to_node(i); @@ -238,6 +244,8 @@ static void __init acpi_numa_slit_init(struct acpi_table_slit *slit) slit->entry[slit->locality_count * i + j]); } } + + return 0; } static int __init @@ -341,19 +349,6 @@ static int __init acpi_parse_cfmws(union acpi_subtable_headers *header, return 0; } -static int __init acpi_parse_slit(struct acpi_table_header *table) -{ - struct acpi_table_slit *slit = (struct acpi_table_slit *)table; - - if (!slit_valid(slit)) { - pr_info("SLIT table looks invalid. Not used.\n"); - return -EINVAL; - } - acpi_numa_slit_init(slit); - - return 0; -} - void __init __weak acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa) { -- cgit v1.2.3 From 57ba79e865e5b50a6ad15a98ea4b2cf808f19c0c Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Thu, 2 May 2024 15:10:12 +0200 Subject: ACPI/NUMA: Squash acpi_numa_memory_affinity_init() into acpi_parse_memory_affinity() After removing architectural code the helper function acpi_numa_memory_affinity_init() is no longer needed. Squash it into acpi_parse_memory_affinity(). No functional changes intended. While at it, fixing checkpatch complaints in code moved. Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-lkp/202403220943.96dde419-oliver.sang@intel.com Reviewed-by: Dan Williams Reviewed-by: Jonathan Cameron Reviewed-by: Alison Schofield Signed-off-by: Robert Richter Signed-off-by: Rafael J. Wysocki --- drivers/acpi/numa/srat.c | 40 +++++++++++++++++----------------------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/drivers/acpi/numa/srat.c b/drivers/acpi/numa/srat.c index 430ddcfb8312..e3f26e71637a 100644 --- a/drivers/acpi/numa/srat.c +++ b/drivers/acpi/numa/srat.c @@ -248,22 +248,30 @@ static int __init acpi_parse_slit(struct acpi_table_header *table) return 0; } +static int parsed_numa_memblks __initdata; + static int __init -acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma) +acpi_parse_memory_affinity(union acpi_subtable_headers *header, + const unsigned long table_end) { + struct acpi_srat_mem_affinity *ma; u64 start, end; u32 hotpluggable; int node, pxm; + ma = (struct acpi_srat_mem_affinity *)header; + + acpi_table_print_srat_entry(&header->common); + if (srat_disabled()) - goto out_err; + return 0; if (ma->header.length < sizeof(struct acpi_srat_mem_affinity)) { pr_err("SRAT: Unexpected header length: %d\n", ma->header.length); goto out_err_bad_srat; } if ((ma->flags & ACPI_SRAT_MEM_ENABLED) == 0) - goto out_err; + return 0; hotpluggable = IS_ENABLED(CONFIG_MEMORY_HOTPLUG) && (ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE); @@ -301,11 +309,15 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma) max_possible_pfn = max(max_possible_pfn, PFN_UP(end - 1)); + parsed_numa_memblks++; + return 0; + out_err_bad_srat: + /* Just disable SRAT, but do not fail and ignore errors. */ bad_srat(); -out_err: - return -EINVAL; + + return 0; } static int __init acpi_parse_cfmws(union acpi_subtable_headers *header, @@ -438,24 +450,6 @@ acpi_parse_gi_affinity(union acpi_subtable_headers *header, } #endif /* defined(CONFIG_X86) || defined (CONFIG_ARM64) */ -static int __initdata parsed_numa_memblks; - -static int __init -acpi_parse_memory_affinity(union acpi_subtable_headers * header, - const unsigned long end) -{ - struct acpi_srat_mem_affinity *memory_affinity; - - memory_affinity = (struct acpi_srat_mem_affinity *)header; - - acpi_table_print_srat_entry(&header->common); - - /* let architecture-dependent part to do it */ - if (!acpi_numa_memory_affinity_init(memory_affinity)) - parsed_numa_memblks++; - return 0; -} - static int __init acpi_parse_srat(struct acpi_table_header *table) { struct acpi_table_srat *srat = (struct acpi_table_srat *)table; -- cgit v1.2.3