Skip to content

Commit 66e92e2

Browse files
vishnuocvij-intel
authored andcommitted
platform/x86: thinkpad_acpi: fix for incorrect fan reporting on some ThinkPad systems
Some ThinkPad systems ECFW use non-standard addresses for fan control and reporting. This patch adds support for such ECFW so that it can report the correct fan values. Tested on Thinkpads L13 Yoga Gen 2 and X13 Yoga Gen 2. Suggested-by: Mark Pearson <[email protected]> Signed-off-by: Vishnu Sankar <[email protected]> Reviewed-by: Hans de Goede <[email protected]> Reviewed-by: Ilpo Järvinen <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Ilpo Järvinen <[email protected]>
1 parent 7bcd032 commit 66e92e2

File tree

1 file changed

+85
-13
lines changed

1 file changed

+85
-13
lines changed

drivers/platform/x86/thinkpad_acpi.c

Lines changed: 85 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7948,15 +7948,31 @@ static struct ibm_struct volume_driver_data = {
79487948
* TPACPI_FAN_WR_TPEC is also available and should be used to
79497949
* command the fan. The X31/X40/X41 seems to have 8 fan levels,
79507950
* but the ACPI tables just mention level 7.
7951+
*
7952+
* TPACPI_FAN_RD_TPEC_NS:
7953+
* This mode is used for a few ThinkPads (L13 Yoga Gen2, X13 Yoga Gen2 etc.)
7954+
* that are using non-standard EC locations for reporting fan speeds.
7955+
* Currently these platforms only provide fan rpm reporting.
7956+
*
79517957
*/
79527958

7959+
#define FAN_RPM_CAL_CONST 491520 /* FAN RPM calculation offset for some non-standard ECFW */
7960+
7961+
#define FAN_NS_CTRL_STATUS BIT(2) /* Bit which determines control is enabled or not */
7962+
#define FAN_NS_CTRL BIT(4) /* Bit which determines control is by host or EC */
7963+
79537964
enum { /* Fan control constants */
79547965
fan_status_offset = 0x2f, /* EC register 0x2f */
79557966
fan_rpm_offset = 0x84, /* EC register 0x84: LSB, 0x85 MSB (RPM)
79567967
* 0x84 must be read before 0x85 */
79577968
fan_select_offset = 0x31, /* EC register 0x31 (Firmware 7M)
79587969
bit 0 selects which fan is active */
79597970

7971+
fan_status_offset_ns = 0x93, /* Special status/control offset for non-standard EC Fan1 */
7972+
fan2_status_offset_ns = 0x96, /* Special status/control offset for non-standard EC Fan2 */
7973+
fan_rpm_status_ns = 0x95, /* Special offset for Fan1 RPM status for non-standard EC */
7974+
fan2_rpm_status_ns = 0x98, /* Special offset for Fan2 RPM status for non-standard EC */
7975+
79607976
TP_EC_FAN_FULLSPEED = 0x40, /* EC fan mode: full speed */
79617977
TP_EC_FAN_AUTO = 0x80, /* EC fan mode: auto fan control */
79627978

@@ -7967,6 +7983,7 @@ enum fan_status_access_mode {
79677983
TPACPI_FAN_NONE = 0, /* No fan status or control */
79687984
TPACPI_FAN_RD_ACPI_GFAN, /* Use ACPI GFAN */
79697985
TPACPI_FAN_RD_TPEC, /* Use ACPI EC regs 0x2f, 0x84-0x85 */
7986+
TPACPI_FAN_RD_TPEC_NS, /* Use non-standard ACPI EC regs (eg: L13 Yoga gen2 etc.) */
79707987
};
79717988

79727989
enum fan_control_access_mode {
@@ -7994,6 +8011,8 @@ static u8 fan_control_desired_level;
79948011
static u8 fan_control_resume_level;
79958012
static int fan_watchdog_maxinterval;
79968013

8014+
static bool fan_with_ns_addr;
8015+
79978016
static struct mutex fan_mutex;
79988017

79998018
static void fan_watchdog_fire(struct work_struct *ignored);
@@ -8123,6 +8142,15 @@ static int fan_get_status(u8 *status)
81238142
}
81248143

81258144
break;
8145+
case TPACPI_FAN_RD_TPEC_NS:
8146+
/* Default mode is AUTO which means controlled by EC */
8147+
if (!acpi_ec_read(fan_status_offset_ns, &s))
8148+
return -EIO;
8149+
8150+
if (status)
8151+
*status = s;
8152+
8153+
break;
81268154

81278155
default:
81288156
return -ENXIO;
@@ -8139,7 +8167,8 @@ static int fan_get_status_safe(u8 *status)
81398167
if (mutex_lock_killable(&fan_mutex))
81408168
return -ERESTARTSYS;
81418169
rc = fan_get_status(&s);
8142-
if (!rc)
8170+
/* NS EC doesn't have register with level settings */
8171+
if (!rc && !fan_with_ns_addr)
81438172
fan_update_desired_level(s);
81448173
mutex_unlock(&fan_mutex);
81458174

@@ -8166,7 +8195,13 @@ static int fan_get_speed(unsigned int *speed)
81668195

81678196
if (likely(speed))
81688197
*speed = (hi << 8) | lo;
8198+
break;
8199+
case TPACPI_FAN_RD_TPEC_NS:
8200+
if (!acpi_ec_read(fan_rpm_status_ns, &lo))
8201+
return -EIO;
81698202

8203+
if (speed)
8204+
*speed = lo ? FAN_RPM_CAL_CONST / lo : 0;
81708205
break;
81718206

81728207
default:
@@ -8178,7 +8213,7 @@ static int fan_get_speed(unsigned int *speed)
81788213

81798214
static int fan2_get_speed(unsigned int *speed)
81808215
{
8181-
u8 hi, lo;
8216+
u8 hi, lo, status;
81828217
bool rc;
81838218

81848219
switch (fan_status_access_mode) {
@@ -8194,7 +8229,21 @@ static int fan2_get_speed(unsigned int *speed)
81948229

81958230
if (likely(speed))
81968231
*speed = (hi << 8) | lo;
8232+
break;
81978233

8234+
case TPACPI_FAN_RD_TPEC_NS:
8235+
rc = !acpi_ec_read(fan2_status_offset_ns, &status);
8236+
if (rc)
8237+
return -EIO;
8238+
if (!(status & FAN_NS_CTRL_STATUS)) {
8239+
pr_info("secondary fan control not supported\n");
8240+
return -EIO;
8241+
}
8242+
rc = !acpi_ec_read(fan2_rpm_status_ns, &lo);
8243+
if (rc)
8244+
return -EIO;
8245+
if (speed)
8246+
*speed = lo ? FAN_RPM_CAL_CONST / lo : 0;
81988247
break;
81998248

82008249
default:
@@ -8697,6 +8746,7 @@ static const struct attribute_group fan_driver_attr_group = {
86978746
#define TPACPI_FAN_2FAN 0x0002 /* EC 0x31 bit 0 selects fan2 */
86988747
#define TPACPI_FAN_2CTL 0x0004 /* selects fan2 control */
86998748
#define TPACPI_FAN_NOFAN 0x0008 /* no fan available */
8749+
#define TPACPI_FAN_NS 0x0010 /* For EC with non-Standard register addresses */
87008750

87018751
static const struct tpacpi_quirk fan_quirk_table[] __initconst = {
87028752
TPACPI_QEC_IBM('1', 'Y', TPACPI_FAN_Q1),
@@ -8715,6 +8765,8 @@ static const struct tpacpi_quirk fan_quirk_table[] __initconst = {
87158765
TPACPI_Q_LNV3('N', '2', 'O', TPACPI_FAN_2CTL), /* P1 / X1 Extreme (2nd gen) */
87168766
TPACPI_Q_LNV3('N', '3', '0', TPACPI_FAN_2CTL), /* P15 (1st gen) / P15v (1st gen) */
87178767
TPACPI_Q_LNV3('N', '3', '7', TPACPI_FAN_2CTL), /* T15g (2nd gen) */
8768+
TPACPI_Q_LNV3('R', '1', 'F', TPACPI_FAN_NS), /* L13 Yoga Gen 2 */
8769+
TPACPI_Q_LNV3('N', '2', 'U', TPACPI_FAN_NS), /* X13 Yoga Gen 2*/
87188770
TPACPI_Q_LNV3('N', '1', 'O', TPACPI_FAN_NOFAN), /* X1 Tablet (2nd gen) */
87198771
};
87208772

@@ -8749,18 +8801,27 @@ static int __init fan_init(struct ibm_init_struct *iibm)
87498801
return -ENODEV;
87508802
}
87518803

8804+
if (quirks & TPACPI_FAN_NS) {
8805+
pr_info("ECFW with non-standard fan reg control found\n");
8806+
fan_with_ns_addr = 1;
8807+
/* Fan ctrl support from host is undefined for now */
8808+
tp_features.fan_ctrl_status_undef = 1;
8809+
}
8810+
87528811
if (gfan_handle) {
87538812
/* 570, 600e/x, 770e, 770x */
87548813
fan_status_access_mode = TPACPI_FAN_RD_ACPI_GFAN;
87558814
} else {
87568815
/* all other ThinkPads: note that even old-style
87578816
* ThinkPad ECs supports the fan control register */
8758-
if (likely(acpi_ec_read(fan_status_offset,
8759-
&fan_control_initial_status))) {
8817+
if (fan_with_ns_addr ||
8818+
likely(acpi_ec_read(fan_status_offset, &fan_control_initial_status))) {
87608819
int res;
87618820
unsigned int speed;
87628821

8763-
fan_status_access_mode = TPACPI_FAN_RD_TPEC;
8822+
fan_status_access_mode = fan_with_ns_addr ?
8823+
TPACPI_FAN_RD_TPEC_NS : TPACPI_FAN_RD_TPEC;
8824+
87648825
if (quirks & TPACPI_FAN_Q1)
87658826
fan_quirk1_setup();
87668827
/* Try and probe the 2nd fan */
@@ -8769,7 +8830,8 @@ static int __init fan_init(struct ibm_init_struct *iibm)
87698830
if (res >= 0 && speed != FAN_NOT_PRESENT) {
87708831
/* It responded - so let's assume it's there */
87718832
tp_features.second_fan = 1;
8772-
tp_features.second_fan_ctl = 1;
8833+
/* fan control not currently available for ns ECFW */
8834+
tp_features.second_fan_ctl = !fan_with_ns_addr;
87738835
pr_info("secondary fan control detected & enabled\n");
87748836
} else {
87758837
/* Fan not auto-detected */
@@ -8944,6 +9006,7 @@ static int fan_read(struct seq_file *m)
89449006
str_enabled_disabled(status), status);
89459007
break;
89469008

9009+
case TPACPI_FAN_RD_TPEC_NS:
89479010
case TPACPI_FAN_RD_TPEC:
89489011
/* all except 570, 600e/x, 770e, 770x */
89499012
rc = fan_get_status_safe(&status);
@@ -8958,13 +9021,22 @@ static int fan_read(struct seq_file *m)
89589021

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

8961-
if (status & TP_EC_FAN_FULLSPEED)
8962-
/* Disengaged mode takes precedence */
8963-
seq_printf(m, "level:\t\tdisengaged\n");
8964-
else if (status & TP_EC_FAN_AUTO)
8965-
seq_printf(m, "level:\t\tauto\n");
8966-
else
8967-
seq_printf(m, "level:\t\t%d\n", status);
9024+
if (fan_status_access_mode == TPACPI_FAN_RD_TPEC_NS) {
9025+
/*
9026+
* No full speed bit in NS EC
9027+
* EC Auto mode is set by default.
9028+
* No other levels settings available
9029+
*/
9030+
seq_printf(m, "level:\t\t%s\n", status & FAN_NS_CTRL ? "unknown" : "auto");
9031+
} else {
9032+
if (status & TP_EC_FAN_FULLSPEED)
9033+
/* Disengaged mode takes precedence */
9034+
seq_printf(m, "level:\t\tdisengaged\n");
9035+
else if (status & TP_EC_FAN_AUTO)
9036+
seq_printf(m, "level:\t\tauto\n");
9037+
else
9038+
seq_printf(m, "level:\t\t%d\n", status);
9039+
}
89689040
break;
89699041

89709042
case TPACPI_FAN_NONE:

0 commit comments

Comments
 (0)