mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-15 16:24:13 +08:00
platform-drivers-x86 for v6.7-5
Fixes: - Fan reporting on some ThinkPads - Laptop 13 spurious keypresses while suspended - Intel PMC correction to avoid crash The following is an automated shortlog grouped by driver: amd/pmc: - Disable keyboard wakeup on AMD Framework 13 - Move keyboard wakeup disablement detection to pmc-quirks - Move platform defines to header - Only run IRQ1 firmware version check on Cezanne intel/pmc: - Fix hang in pmc_core_send_ltr_ignore() thinkpad_acpi: - fix for incorrect fan reporting on some ThinkPad systems -----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQSCSUwRdwTNL2MhaBlZrE9hU+XOMQUCZYLGKQAKCRBZrE9hU+XO MXs/APoCNjjwrIo1l8yR9hiOQeKm5nRZdg7CPsjzxTyzvtG04gEAvWlsv3K5TG5F D6+T62Q4Qs92sbSG7ccwu3Z7icQjNAc= =218L -----END PGP SIGNATURE----- Merge tag 'platform-drivers-x86-v6.7-5' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86 Pull x86 platform drivers fixes from Ilpo Järvinen: - Fan reporting on some ThinkPads - Laptop 13 spurious keypresses while suspended - Intel PMC correction to avoid crash * tag 'platform-drivers-x86-v6.7-5' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86: platform/x86/amd/pmc: Disable keyboard wakeup on AMD Framework 13 platform/x86/amd/pmc: Move keyboard wakeup disablement detection to pmc-quirks platform/x86/amd/pmc: Only run IRQ1 firmware version check on Cezanne platform/x86/amd/pmc: Move platform defines to header platform/x86/intel/pmc: Fix hang in pmc_core_send_ltr_ignore() platform/x86: thinkpad_acpi: fix for incorrect fan reporting on some ThinkPad systems
This commit is contained in:
commit
1bddd45b5c
@ -16,12 +16,17 @@
|
||||
|
||||
struct quirk_entry {
|
||||
u32 s2idle_bug_mmio;
|
||||
bool spurious_8042;
|
||||
};
|
||||
|
||||
static struct quirk_entry quirk_s2idle_bug = {
|
||||
.s2idle_bug_mmio = 0xfed80380,
|
||||
};
|
||||
|
||||
static struct quirk_entry quirk_spurious_8042 = {
|
||||
.spurious_8042 = true,
|
||||
};
|
||||
|
||||
static const struct dmi_system_id fwbug_list[] = {
|
||||
{
|
||||
.ident = "L14 Gen2 AMD",
|
||||
@ -193,6 +198,16 @@ static const struct dmi_system_id fwbug_list[] = {
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "HP Laptop 15s-eq2xxx"),
|
||||
}
|
||||
},
|
||||
/* https://community.frame.work/t/tracking-framework-amd-ryzen-7040-series-lid-wakeup-behavior-feedback/39128 */
|
||||
{
|
||||
.ident = "Framework Laptop 13 (Phoenix)",
|
||||
.driver_data = &quirk_spurious_8042,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Framework"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Laptop 13 (AMD Ryzen 7040Series)"),
|
||||
DMI_MATCH(DMI_BIOS_VERSION, "03.03"),
|
||||
}
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
@ -235,6 +250,9 @@ void amd_pmc_quirks_init(struct amd_pmc_dev *dev)
|
||||
{
|
||||
const struct dmi_system_id *dmi_id;
|
||||
|
||||
if (dev->cpu_id == AMD_CPU_ID_CZN)
|
||||
dev->disable_8042_wakeup = true;
|
||||
|
||||
dmi_id = dmi_first_match(fwbug_list);
|
||||
if (!dmi_id)
|
||||
return;
|
||||
@ -242,4 +260,6 @@ void amd_pmc_quirks_init(struct amd_pmc_dev *dev)
|
||||
if (dev->quirks->s2idle_bug_mmio)
|
||||
pr_info("Using s2idle quirk to avoid %s platform firmware bug\n",
|
||||
dmi_id->ident);
|
||||
if (dev->quirks->spurious_8042)
|
||||
dev->disable_8042_wakeup = true;
|
||||
}
|
||||
|
@ -91,16 +91,6 @@
|
||||
#define SMU_MSG_LOG_RESET 0x07
|
||||
#define SMU_MSG_LOG_DUMP_DATA 0x08
|
||||
#define SMU_MSG_GET_SUP_CONSTRAINTS 0x09
|
||||
/* List of supported CPU ids */
|
||||
#define AMD_CPU_ID_RV 0x15D0
|
||||
#define AMD_CPU_ID_RN 0x1630
|
||||
#define AMD_CPU_ID_PCO AMD_CPU_ID_RV
|
||||
#define AMD_CPU_ID_CZN AMD_CPU_ID_RN
|
||||
#define AMD_CPU_ID_YC 0x14B5
|
||||
#define AMD_CPU_ID_CB 0x14D8
|
||||
#define AMD_CPU_ID_PS 0x14E8
|
||||
#define AMD_CPU_ID_SP 0x14A4
|
||||
#define PCI_DEVICE_ID_AMD_1AH_M20H_ROOT 0x1507
|
||||
|
||||
#define PMC_MSG_DELAY_MIN_US 50
|
||||
#define RESPONSE_REGISTER_LOOP_MAX 20000
|
||||
@ -766,19 +756,22 @@ static int amd_pmc_get_os_hint(struct amd_pmc_dev *dev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int amd_pmc_czn_wa_irq1(struct amd_pmc_dev *pdev)
|
||||
static int amd_pmc_wa_irq1(struct amd_pmc_dev *pdev)
|
||||
{
|
||||
struct device *d;
|
||||
int rc;
|
||||
|
||||
if (!pdev->major) {
|
||||
rc = amd_pmc_get_smu_version(pdev);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
/* cezanne platform firmware has a fix in 64.66.0 */
|
||||
if (pdev->cpu_id == AMD_CPU_ID_CZN) {
|
||||
if (!pdev->major) {
|
||||
rc = amd_pmc_get_smu_version(pdev);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (pdev->major > 64 || (pdev->major == 64 && pdev->minor > 65))
|
||||
return 0;
|
||||
if (pdev->major > 64 || (pdev->major == 64 && pdev->minor > 65))
|
||||
return 0;
|
||||
}
|
||||
|
||||
d = bus_find_device_by_name(&serio_bus, NULL, "serio0");
|
||||
if (!d)
|
||||
@ -937,8 +930,8 @@ static int amd_pmc_suspend_handler(struct device *dev)
|
||||
{
|
||||
struct amd_pmc_dev *pdev = dev_get_drvdata(dev);
|
||||
|
||||
if (pdev->cpu_id == AMD_CPU_ID_CZN && !disable_workarounds) {
|
||||
int rc = amd_pmc_czn_wa_irq1(pdev);
|
||||
if (pdev->disable_8042_wakeup && !disable_workarounds) {
|
||||
int rc = amd_pmc_wa_irq1(pdev);
|
||||
|
||||
if (rc) {
|
||||
dev_err(pdev->dev, "failed to adjust keyboard wakeup: %d\n", rc);
|
||||
|
@ -36,9 +36,21 @@ struct amd_pmc_dev {
|
||||
struct mutex lock; /* generic mutex lock */
|
||||
struct dentry *dbgfs_dir;
|
||||
struct quirk_entry *quirks;
|
||||
bool disable_8042_wakeup;
|
||||
};
|
||||
|
||||
void amd_pmc_process_restore_quirks(struct amd_pmc_dev *dev);
|
||||
void amd_pmc_quirks_init(struct amd_pmc_dev *dev);
|
||||
|
||||
/* List of supported CPU ids */
|
||||
#define AMD_CPU_ID_RV 0x15D0
|
||||
#define AMD_CPU_ID_RN 0x1630
|
||||
#define AMD_CPU_ID_PCO AMD_CPU_ID_RV
|
||||
#define AMD_CPU_ID_CZN AMD_CPU_ID_RN
|
||||
#define AMD_CPU_ID_YC 0x14B5
|
||||
#define AMD_CPU_ID_CB 0x14D8
|
||||
#define AMD_CPU_ID_PS 0x14E8
|
||||
#define AMD_CPU_ID_SP 0x14A4
|
||||
#define PCI_DEVICE_ID_AMD_1AH_M20H_ROOT 0x1507
|
||||
|
||||
#endif /* PMC_H */
|
||||
|
@ -472,7 +472,7 @@ int pmc_core_send_ltr_ignore(struct pmc_dev *pmcdev, u32 value)
|
||||
* is based on the contiguous indexes from ltr_show output.
|
||||
* pmc index and ltr index needs to be calculated from it.
|
||||
*/
|
||||
for (pmc_index = 0; pmc_index < ARRAY_SIZE(pmcdev->pmcs) && ltr_index > 0; pmc_index++) {
|
||||
for (pmc_index = 0; pmc_index < ARRAY_SIZE(pmcdev->pmcs) && ltr_index >= 0; pmc_index++) {
|
||||
pmc = pmcdev->pmcs[pmc_index];
|
||||
|
||||
if (!pmc)
|
||||
|
@ -7948,8 +7948,19 @@ static struct ibm_struct volume_driver_data = {
|
||||
* TPACPI_FAN_WR_TPEC is also available and should be used to
|
||||
* command the fan. The X31/X40/X41 seems to have 8 fan levels,
|
||||
* but the ACPI tables just mention level 7.
|
||||
*
|
||||
* TPACPI_FAN_RD_TPEC_NS:
|
||||
* This mode is used for a few ThinkPads (L13 Yoga Gen2, X13 Yoga Gen2 etc.)
|
||||
* that are using non-standard EC locations for reporting fan speeds.
|
||||
* Currently these platforms only provide fan rpm reporting.
|
||||
*
|
||||
*/
|
||||
|
||||
#define FAN_RPM_CAL_CONST 491520 /* FAN RPM calculation offset for some non-standard ECFW */
|
||||
|
||||
#define FAN_NS_CTRL_STATUS BIT(2) /* Bit which determines control is enabled or not */
|
||||
#define FAN_NS_CTRL BIT(4) /* Bit which determines control is by host or EC */
|
||||
|
||||
enum { /* Fan control constants */
|
||||
fan_status_offset = 0x2f, /* EC register 0x2f */
|
||||
fan_rpm_offset = 0x84, /* EC register 0x84: LSB, 0x85 MSB (RPM)
|
||||
@ -7957,6 +7968,11 @@ enum { /* Fan control constants */
|
||||
fan_select_offset = 0x31, /* EC register 0x31 (Firmware 7M)
|
||||
bit 0 selects which fan is active */
|
||||
|
||||
fan_status_offset_ns = 0x93, /* Special status/control offset for non-standard EC Fan1 */
|
||||
fan2_status_offset_ns = 0x96, /* Special status/control offset for non-standard EC Fan2 */
|
||||
fan_rpm_status_ns = 0x95, /* Special offset for Fan1 RPM status for non-standard EC */
|
||||
fan2_rpm_status_ns = 0x98, /* Special offset for Fan2 RPM status for non-standard EC */
|
||||
|
||||
TP_EC_FAN_FULLSPEED = 0x40, /* EC fan mode: full speed */
|
||||
TP_EC_FAN_AUTO = 0x80, /* EC fan mode: auto fan control */
|
||||
|
||||
@ -7967,6 +7983,7 @@ enum fan_status_access_mode {
|
||||
TPACPI_FAN_NONE = 0, /* No fan status or control */
|
||||
TPACPI_FAN_RD_ACPI_GFAN, /* Use ACPI GFAN */
|
||||
TPACPI_FAN_RD_TPEC, /* Use ACPI EC regs 0x2f, 0x84-0x85 */
|
||||
TPACPI_FAN_RD_TPEC_NS, /* Use non-standard ACPI EC regs (eg: L13 Yoga gen2 etc.) */
|
||||
};
|
||||
|
||||
enum fan_control_access_mode {
|
||||
@ -7994,6 +8011,8 @@ static u8 fan_control_desired_level;
|
||||
static u8 fan_control_resume_level;
|
||||
static int fan_watchdog_maxinterval;
|
||||
|
||||
static bool fan_with_ns_addr;
|
||||
|
||||
static struct mutex fan_mutex;
|
||||
|
||||
static void fan_watchdog_fire(struct work_struct *ignored);
|
||||
@ -8123,6 +8142,15 @@ static int fan_get_status(u8 *status)
|
||||
}
|
||||
|
||||
break;
|
||||
case TPACPI_FAN_RD_TPEC_NS:
|
||||
/* Default mode is AUTO which means controlled by EC */
|
||||
if (!acpi_ec_read(fan_status_offset_ns, &s))
|
||||
return -EIO;
|
||||
|
||||
if (status)
|
||||
*status = s;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return -ENXIO;
|
||||
@ -8139,7 +8167,8 @@ static int fan_get_status_safe(u8 *status)
|
||||
if (mutex_lock_killable(&fan_mutex))
|
||||
return -ERESTARTSYS;
|
||||
rc = fan_get_status(&s);
|
||||
if (!rc)
|
||||
/* NS EC doesn't have register with level settings */
|
||||
if (!rc && !fan_with_ns_addr)
|
||||
fan_update_desired_level(s);
|
||||
mutex_unlock(&fan_mutex);
|
||||
|
||||
@ -8166,7 +8195,13 @@ static int fan_get_speed(unsigned int *speed)
|
||||
|
||||
if (likely(speed))
|
||||
*speed = (hi << 8) | lo;
|
||||
break;
|
||||
case TPACPI_FAN_RD_TPEC_NS:
|
||||
if (!acpi_ec_read(fan_rpm_status_ns, &lo))
|
||||
return -EIO;
|
||||
|
||||
if (speed)
|
||||
*speed = lo ? FAN_RPM_CAL_CONST / lo : 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -8178,7 +8213,7 @@ static int fan_get_speed(unsigned int *speed)
|
||||
|
||||
static int fan2_get_speed(unsigned int *speed)
|
||||
{
|
||||
u8 hi, lo;
|
||||
u8 hi, lo, status;
|
||||
bool rc;
|
||||
|
||||
switch (fan_status_access_mode) {
|
||||
@ -8194,7 +8229,21 @@ static int fan2_get_speed(unsigned int *speed)
|
||||
|
||||
if (likely(speed))
|
||||
*speed = (hi << 8) | lo;
|
||||
break;
|
||||
|
||||
case TPACPI_FAN_RD_TPEC_NS:
|
||||
rc = !acpi_ec_read(fan2_status_offset_ns, &status);
|
||||
if (rc)
|
||||
return -EIO;
|
||||
if (!(status & FAN_NS_CTRL_STATUS)) {
|
||||
pr_info("secondary fan control not supported\n");
|
||||
return -EIO;
|
||||
}
|
||||
rc = !acpi_ec_read(fan2_rpm_status_ns, &lo);
|
||||
if (rc)
|
||||
return -EIO;
|
||||
if (speed)
|
||||
*speed = lo ? FAN_RPM_CAL_CONST / lo : 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -8697,6 +8746,7 @@ static const struct attribute_group fan_driver_attr_group = {
|
||||
#define TPACPI_FAN_2FAN 0x0002 /* EC 0x31 bit 0 selects fan2 */
|
||||
#define TPACPI_FAN_2CTL 0x0004 /* selects fan2 control */
|
||||
#define TPACPI_FAN_NOFAN 0x0008 /* no fan available */
|
||||
#define TPACPI_FAN_NS 0x0010 /* For EC with non-Standard register addresses */
|
||||
|
||||
static const struct tpacpi_quirk fan_quirk_table[] __initconst = {
|
||||
TPACPI_QEC_IBM('1', 'Y', TPACPI_FAN_Q1),
|
||||
@ -8715,6 +8765,8 @@ static const struct tpacpi_quirk fan_quirk_table[] __initconst = {
|
||||
TPACPI_Q_LNV3('N', '2', 'O', TPACPI_FAN_2CTL), /* P1 / X1 Extreme (2nd gen) */
|
||||
TPACPI_Q_LNV3('N', '3', '0', TPACPI_FAN_2CTL), /* P15 (1st gen) / P15v (1st gen) */
|
||||
TPACPI_Q_LNV3('N', '3', '7', TPACPI_FAN_2CTL), /* T15g (2nd gen) */
|
||||
TPACPI_Q_LNV3('R', '1', 'F', TPACPI_FAN_NS), /* L13 Yoga Gen 2 */
|
||||
TPACPI_Q_LNV3('N', '2', 'U', TPACPI_FAN_NS), /* X13 Yoga Gen 2*/
|
||||
TPACPI_Q_LNV3('N', '1', 'O', TPACPI_FAN_NOFAN), /* X1 Tablet (2nd gen) */
|
||||
};
|
||||
|
||||
@ -8749,18 +8801,27 @@ static int __init fan_init(struct ibm_init_struct *iibm)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (quirks & TPACPI_FAN_NS) {
|
||||
pr_info("ECFW with non-standard fan reg control found\n");
|
||||
fan_with_ns_addr = 1;
|
||||
/* Fan ctrl support from host is undefined for now */
|
||||
tp_features.fan_ctrl_status_undef = 1;
|
||||
}
|
||||
|
||||
if (gfan_handle) {
|
||||
/* 570, 600e/x, 770e, 770x */
|
||||
fan_status_access_mode = TPACPI_FAN_RD_ACPI_GFAN;
|
||||
} else {
|
||||
/* all other ThinkPads: note that even old-style
|
||||
* ThinkPad ECs supports the fan control register */
|
||||
if (likely(acpi_ec_read(fan_status_offset,
|
||||
&fan_control_initial_status))) {
|
||||
if (fan_with_ns_addr ||
|
||||
likely(acpi_ec_read(fan_status_offset, &fan_control_initial_status))) {
|
||||
int res;
|
||||
unsigned int speed;
|
||||
|
||||
fan_status_access_mode = TPACPI_FAN_RD_TPEC;
|
||||
fan_status_access_mode = fan_with_ns_addr ?
|
||||
TPACPI_FAN_RD_TPEC_NS : TPACPI_FAN_RD_TPEC;
|
||||
|
||||
if (quirks & TPACPI_FAN_Q1)
|
||||
fan_quirk1_setup();
|
||||
/* Try and probe the 2nd fan */
|
||||
@ -8769,7 +8830,8 @@ static int __init fan_init(struct ibm_init_struct *iibm)
|
||||
if (res >= 0 && speed != FAN_NOT_PRESENT) {
|
||||
/* It responded - so let's assume it's there */
|
||||
tp_features.second_fan = 1;
|
||||
tp_features.second_fan_ctl = 1;
|
||||
/* fan control not currently available for ns ECFW */
|
||||
tp_features.second_fan_ctl = !fan_with_ns_addr;
|
||||
pr_info("secondary fan control detected & enabled\n");
|
||||
} else {
|
||||
/* Fan not auto-detected */
|
||||
@ -8944,6 +9006,7 @@ static int fan_read(struct seq_file *m)
|
||||
str_enabled_disabled(status), status);
|
||||
break;
|
||||
|
||||
case TPACPI_FAN_RD_TPEC_NS:
|
||||
case TPACPI_FAN_RD_TPEC:
|
||||
/* all except 570, 600e/x, 770e, 770x */
|
||||
rc = fan_get_status_safe(&status);
|
||||
@ -8958,13 +9021,22 @@ static int fan_read(struct seq_file *m)
|
||||
|
||||
seq_printf(m, "speed:\t\t%d\n", speed);
|
||||
|
||||
if (status & TP_EC_FAN_FULLSPEED)
|
||||
/* Disengaged mode takes precedence */
|
||||
seq_printf(m, "level:\t\tdisengaged\n");
|
||||
else if (status & TP_EC_FAN_AUTO)
|
||||
seq_printf(m, "level:\t\tauto\n");
|
||||
else
|
||||
seq_printf(m, "level:\t\t%d\n", status);
|
||||
if (fan_status_access_mode == TPACPI_FAN_RD_TPEC_NS) {
|
||||
/*
|
||||
* No full speed bit in NS EC
|
||||
* EC Auto mode is set by default.
|
||||
* No other levels settings available
|
||||
*/
|
||||
seq_printf(m, "level:\t\t%s\n", status & FAN_NS_CTRL ? "unknown" : "auto");
|
||||
} else {
|
||||
if (status & TP_EC_FAN_FULLSPEED)
|
||||
/* Disengaged mode takes precedence */
|
||||
seq_printf(m, "level:\t\tdisengaged\n");
|
||||
else if (status & TP_EC_FAN_AUTO)
|
||||
seq_printf(m, "level:\t\tauto\n");
|
||||
else
|
||||
seq_printf(m, "level:\t\t%d\n", status);
|
||||
}
|
||||
break;
|
||||
|
||||
case TPACPI_FAN_NONE:
|
||||
|
Loading…
Reference in New Issue
Block a user