Commit 1bddd45b authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'platform-drivers-x86-v6.7-5' of...

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
parents 1a44b007 a55bdad5
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -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;
}
+13 −20
Original line number Diff line number Diff line
@@ -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,11 +756,13 @@ 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;

	/* 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)
@@ -779,6 +771,7 @@ static int amd_pmc_czn_wa_irq1(struct amd_pmc_dev *pdev)

		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);
+12 −0
Original line number Diff line number Diff line
@@ -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 */
+1 −1
Original line number Diff line number Diff line
@@ -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)
+85 −13
Original line number Diff line number Diff line
@@ -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,6 +9021,14 @@ static int fan_read(struct seq_file *m)

		seq_printf(m, "speed:\t\t%d\n", speed);

		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");
@@ -8965,6 +9036,7 @@ static int fan_read(struct seq_file *m)
				seq_printf(m, "level:\t\tauto\n");
			else
				seq_printf(m, "level:\t\t%d\n", status);
		}
		break;

	case TPACPI_FAN_NONE: