Commit 3c942804 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

Merge branches 'acpi-x86', 'acpi-bus', 'acpi-ec' and 'acpi-apei'

Merge ACPI x86-specific changes, core updates, EC driver updates and
APEI support updates for 4.19.

These add a special platform driver for handling multiple I2C devices
hooked up to the same device object in the ACPI tables, add some new
quirks and remove one that is not needed any more.

* acpi-x86:
  platform/x86: Add ACPI i2c-multi-instantiate pseudo driver
  ACPI / x86: utils: Remove status workaround from acpi_device_always_present()
  ACPI / x86: enable touchscreen on Dell Venue Pro 7139

* acpi-bus:
  ACPI: bus: Fix a pointer coding style issue
  Revert "ACPI / bus: Parse tables as term_list for Dell XPS 9570 and Precision M5530"

* acpi-ec:
  ACPI / EC: Add another entry for Thinkpad X1 Carbon 6th
  ACPI / EC: Use ec_no_wakeup on ThinkPad X1 Yoga 3rd

* acpi-apei:
  arm64 / ACPI: clean the additional checks before calling ghes_notify_sea()
......@@ -367,6 +367,12 @@ L: linux-acpi@vger.kernel.org
S: Maintained
F: drivers/acpi/arm64
ACPI I2C MULTI INSTANTIATE DRIVER
M: Hans de Goede <hdegoede@redhat.com>
L: platform-driver-x86@vger.kernel.org
S: Maintained
F: drivers/platform/x86/i2c-multi-instantiate.c
ACPI PMIC DRIVERS
M: "Rafael J. Wysocki" <rjw@rjwysocki.net>
M: Len Brown <lenb@kernel.org>
......
......@@ -727,12 +727,7 @@ static const struct fault_info fault_info[] = {
int handle_guest_sea(phys_addr_t addr, unsigned int esr)
{
int ret = -ENOENT;
if (IS_ENABLED(CONFIG_ACPI_APEI_SEA))
ret = ghes_notify_sea();
return ret;
return ghes_notify_sea();
}
asmlinkage void __exception do_mem_abort(unsigned long addr, unsigned int esr,
......
......@@ -66,37 +66,10 @@ static int set_copy_dsdt(const struct dmi_system_id *id)
return 0;
}
#endif
static int set_gbl_term_list(const struct dmi_system_id *id)
{
acpi_gbl_execute_tables_as_methods = 1;
return 0;
}
static const struct dmi_system_id acpi_quirks_dmi_table[] __initconst = {
/*
* Touchpad on Dell XPS 9570/Precision M5530 doesn't work under I2C
* mode.
* https://bugzilla.kernel.org/show_bug.cgi?id=198515
*/
{
.callback = set_gbl_term_list,
.ident = "Dell Precision M5530",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Precision M5530"),
},
},
{
.callback = set_gbl_term_list,
.ident = "Dell XPS 15 9570",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "XPS 15 9570"),
},
},
static const struct dmi_system_id dsdt_dmi_table[] __initconst = {
/*
* Invoke DSDT corruption work-around on all Toshiba Satellite.
* DSDT will be copied to memory.
* https://bugzilla.kernel.org/show_bug.cgi?id=14679
*/
{
......@@ -110,7 +83,7 @@ static const struct dmi_system_id acpi_quirks_dmi_table[] __initconst = {
{}
};
#else
static const struct dmi_system_id acpi_quirks_dmi_table[] __initconst = {
static const struct dmi_system_id dsdt_dmi_table[] __initconst = {
{}
};
#endif
......@@ -962,7 +935,7 @@ static int acpi_device_probe(struct device *dev)
return 0;
}
static int acpi_device_remove(struct device * dev)
static int acpi_device_remove(struct device *dev)
{
struct acpi_device *acpi_dev = to_acpi_device(dev);
struct acpi_driver *acpi_drv = acpi_dev->driver;
......@@ -1060,8 +1033,11 @@ void __init acpi_early_init(void)
acpi_permanent_mmap = true;
/* Check machine-specific quirks */
dmi_check_system(acpi_quirks_dmi_table);
/*
* If the machine falls into the DMI check table,
* DSDT will be copied to memory
*/
dmi_check_system(dsdt_dmi_table);
status = acpi_reallocate_root_table();
if (ACPI_FAILURE(status)) {
......
......@@ -2045,6 +2045,20 @@ static const struct dmi_system_id acpi_ec_no_wakeup[] = {
DMI_MATCH(DMI_PRODUCT_FAMILY, "Thinkpad X1 Carbon 6th"),
},
},
{
.ident = "ThinkPad X1 Carbon 6th",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_FAMILY, "ThinkPad X1 Carbon 6th"),
},
},
{
.ident = "ThinkPad X1 Yoga 3rd",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_FAMILY, "ThinkPad X1 Yoga 3rd"),
},
},
{ },
};
......
......@@ -62,14 +62,20 @@ static const struct always_present_id always_present_ids[] = {
*/
ENTRY("INT0002", "1", ICPU(INTEL_FAM6_ATOM_AIRMONT), {}),
/*
* On the Dell Venue 11 Pro 7130 the DSDT hides the touchscreen ACPI
* device until a certain time after _SB.PCI0.GFX0.LCD.LCD1._ON gets
* called has passed *and* _STA has been called at least 3 times since.
* On the Dell Venue 11 Pro 7130 and 7139, the DSDT hides
* the touchscreen ACPI device until a certain time
* after _SB.PCI0.GFX0.LCD.LCD1._ON gets called has passed
* *and* _STA has been called at least 3 times since.
*/
ENTRY("SYNA7500", "1", ICPU(INTEL_FAM6_HASWELL_ULT), {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Venue 11 Pro 7130"),
}),
ENTRY("SYNA7500", "1", ICPU(INTEL_FAM6_HASWELL_ULT), {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Venue 11 Pro 7139"),
}),
/*
* The GPD win BIOS dated 20170221 has disabled the accelerometer, the
* drivers sometimes cause crashes under Windows and this is how the
......@@ -103,13 +109,9 @@ static const struct always_present_id always_present_ids[] = {
bool acpi_device_always_present(struct acpi_device *adev)
{
u32 *status = (u32 *)&adev->status;
u32 old_status = *status;
bool ret = false;
unsigned int i;
/* acpi_match_device_ids checks status, so set it to default */
*status = ACPI_STA_DEFAULT;
for (i = 0; i < ARRAY_SIZE(always_present_ids); i++) {
if (acpi_match_device_ids(adev, always_present_ids[i].hid))
continue;
......@@ -125,15 +127,9 @@ bool acpi_device_always_present(struct acpi_device *adev)
!dmi_check_system(always_present_ids[i].dmi_ids))
continue;
if (old_status != ACPI_STA_DEFAULT) /* Log only once */
dev_info(&adev->dev,
"Device [%s] is in always present list\n",
adev->pnp.bus_id);
ret = true;
break;
}
*status = old_status;
return ret;
}
......@@ -1218,6 +1218,17 @@ config INTEL_CHTDC_TI_PWRBTN
To compile this driver as a module, choose M here: the module
will be called intel_chtdc_ti_pwrbtn.
config I2C_MULTI_INSTANTIATE
tristate "I2C multi instantiate pseudo device driver"
depends on I2C && ACPI
help
Some ACPI-based systems list multiple i2c-devices in a single ACPI
firmware-node. This driver will instantiate separate i2c-clients
for each device in the firmware-node.
To compile this driver as a module, choose M here: the module
will be called i2c-multi-instantiate.
endif # X86_PLATFORM_DEVICES
config PMC_ATOM
......
......@@ -91,3 +91,4 @@ obj-$(CONFIG_PMC_ATOM) += pmc_atom.o
obj-$(CONFIG_MLX_PLATFORM) += mlx-platform.o
obj-$(CONFIG_INTEL_TURBO_MAX_3) += intel_turbo_max_3.o
obj-$(CONFIG_INTEL_CHTDC_TI_PWRBTN) += intel_chtdc_ti_pwrbtn.o
obj-$(CONFIG_I2C_MULTI_INSTANTIATE) += i2c-multi-instantiate.o
// SPDX-License-Identifier: GPL-2.0+
/*
* I2C multi-instantiate driver, pseudo driver to instantiate multiple
* i2c-clients from a single fwnode.
*
* Copyright 2018 Hans de Goede <hdegoede@redhat.com>
*/
#include <linux/acpi.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
struct i2c_inst_data {
const char *type;
int gpio_irq_idx;
};
struct i2c_multi_inst_data {
int num_clients;
struct i2c_client *clients[0];
};
static int i2c_multi_inst_probe(struct platform_device *pdev)
{
struct i2c_multi_inst_data *multi;
const struct acpi_device_id *match;
const struct i2c_inst_data *inst_data;
struct i2c_board_info board_info = {};
struct device *dev = &pdev->dev;
struct acpi_device *adev;
char name[32];
int i, ret;
match = acpi_match_device(dev->driver->acpi_match_table, dev);
if (!match) {
dev_err(dev, "Error ACPI match data is missing\n");
return -ENODEV;
}
inst_data = (const struct i2c_inst_data *)match->driver_data;
adev = ACPI_COMPANION(dev);
/* Count number of clients to instantiate */
for (i = 0; inst_data[i].type; i++) {}
multi = devm_kmalloc(dev,
offsetof(struct i2c_multi_inst_data, clients[i]),
GFP_KERNEL);
if (!multi)
return -ENOMEM;
multi->num_clients = i;
for (i = 0; i < multi->num_clients; i++) {
memset(&board_info, 0, sizeof(board_info));
strlcpy(board_info.type, inst_data[i].type, I2C_NAME_SIZE);
snprintf(name, sizeof(name), "%s-%s", match->id,
inst_data[i].type);
board_info.dev_name = name;
board_info.irq = 0;
if (inst_data[i].gpio_irq_idx != -1) {
ret = acpi_dev_gpio_irq_get(adev,
inst_data[i].gpio_irq_idx);
if (ret < 0) {
dev_err(dev, "Error requesting irq at index %d: %d\n",
inst_data[i].gpio_irq_idx, ret);
goto error;
}
board_info.irq = ret;
}
multi->clients[i] = i2c_acpi_new_device(dev, i, &board_info);
if (!multi->clients[i]) {
dev_err(dev, "Error creating i2c-client, idx %d\n", i);
ret = -ENODEV;
goto error;
}
}
platform_set_drvdata(pdev, multi);
return 0;
error:
while (--i >= 0)
i2c_unregister_device(multi->clients[i]);
return ret;
}
static int i2c_multi_inst_remove(struct platform_device *pdev)
{
struct i2c_multi_inst_data *multi = platform_get_drvdata(pdev);
int i;
for (i = 0; i < multi->num_clients; i++)
i2c_unregister_device(multi->clients[i]);
return 0;
}
static const struct i2c_inst_data bsg1160_data[] = {
{ "bmc150_accel", 0 },
{ "bmc150_magn", -1 },
{ "bmg160", -1 },
{}
};
/*
* Note new device-ids must also be added to i2c_multi_instantiate_ids in
* drivers/acpi/scan.c: acpi_device_enumeration_by_parent().
*/
static const struct acpi_device_id i2c_multi_inst_acpi_ids[] = {
{ "BSG1160", (unsigned long)bsg1160_data },
{ }
};
MODULE_DEVICE_TABLE(acpi, i2c_multi_inst_acpi_ids);
static struct platform_driver i2c_multi_inst_driver = {
.driver = {
.name = "I2C multi instantiate pseudo device driver",
.acpi_match_table = ACPI_PTR(i2c_multi_inst_acpi_ids),
},
.probe = i2c_multi_inst_probe,
.remove = i2c_multi_inst_remove,
};
module_platform_driver(i2c_multi_inst_driver);
MODULE_DESCRIPTION("I2C multi instantiate pseudo device driver");
MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
MODULE_LICENSE("GPL");
......@@ -118,6 +118,10 @@ static inline void *acpi_hest_get_next(struct acpi_hest_generic_data *gdata)
(void *)section - (void *)(estatus + 1) < estatus->data_length; \
section = acpi_hest_get_next(section))
#ifdef CONFIG_ACPI_APEI_SEA
int ghes_notify_sea(void);
#else
static inline int ghes_notify_sea(void) { return -ENOENT; }
#endif
#endif /* GHES_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment