1
0
Fork 0

thinkpad-acpi: add quirklist engine

Add a quirklist engine suitable for matching ThinkPad firmware,
and change the code to use it.

Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
Signed-off-by: Len Brown <len.brown@intel.com>
hifive-unleashed-5.1
Henrique de Moraes Holschuh 2009-05-30 13:25:06 -03:00 committed by Len Brown
parent 050df107c4
commit 7d95a3d564
1 changed files with 98 additions and 21 deletions

View File

@ -364,6 +364,73 @@ static void tpacpi_log_usertask(const char * const what)
} \
} while (0)
/*
* Quirk handling helpers
*
* ThinkPad IDs and versions seen in the field so far
* are two-characters from the set [0-9A-Z], i.e. base 36.
*
* We use values well outside that range as specials.
*/
#define TPACPI_MATCH_ANY 0xffffU
#define TPACPI_MATCH_UNKNOWN 0U
/* TPID('1', 'Y') == 0x5931 */
#define TPID(__c1, __c2) (((__c2) << 8) | (__c1))
#define TPACPI_Q_IBM(__id1, __id2, __quirk) \
{ .vendor = PCI_VENDOR_ID_IBM, \
.bios = TPID(__id1, __id2), \
.ec = TPACPI_MATCH_ANY, \
.quirks = (__quirk) }
#define TPACPI_Q_LNV(__id1, __id2, __quirk) \
{ .vendor = PCI_VENDOR_ID_LENOVO, \
.bios = TPID(__id1, __id2), \
.ec = TPACPI_MATCH_ANY, \
.quirks = (__quirk) }
struct tpacpi_quirk {
unsigned int vendor;
u16 bios;
u16 ec;
unsigned long quirks;
};
/**
* tpacpi_check_quirks() - search BIOS/EC version on a list
* @qlist: array of &struct tpacpi_quirk
* @qlist_size: number of elements in @qlist
*
* Iterates over a quirks list until one is found that matches the
* ThinkPad's vendor, BIOS and EC model.
*
* Returns 0 if nothing matches, otherwise returns the quirks field of
* the matching &struct tpacpi_quirk entry.
*
* The match criteria is: vendor, ec and bios much match.
*/
static unsigned long __init tpacpi_check_quirks(
const struct tpacpi_quirk *qlist,
unsigned int qlist_size)
{
while (qlist_size) {
if ((qlist->vendor == thinkpad_id.vendor ||
qlist->vendor == TPACPI_MATCH_ANY) &&
(qlist->bios == thinkpad_id.bios_model ||
qlist->bios == TPACPI_MATCH_ANY) &&
(qlist->ec == thinkpad_id.ec_model ||
qlist->ec == TPACPI_MATCH_ANY))
return qlist->quirks;
qlist_size--;
qlist++;
}
return 0;
}
/****************************************************************************
****************************************************************************
*
@ -6223,30 +6290,18 @@ TPACPI_HANDLE(sfan, ec, "SFAN", /* 570 */
* We assume 0x07 really means auto mode while this quirk is active,
* as this is far more likely than the ThinkPad being in level 7,
* which is only used by the firmware during thermal emergencies.
*
* Enable for TP-1Y (T43), TP-78 (R51e), TP-76 (R52),
* TP-70 (T43, R52), which are known to be buggy.
*/
static void fan_quirk1_detect(void)
static void fan_quirk1_setup(void)
{
/* In some ThinkPads, neither the EC nor the ACPI
* DSDT initialize the HFSP register, and it ends up
* being initially set to 0x07 when it *could* be
* either 0x07 or 0x80.
*
* Enable for TP-1Y (T43), TP-78 (R51e),
* TP-76 (R52), TP-70 (T43, R52), which are known
* to be buggy. */
if (fan_control_initial_status == 0x07) {
switch (thinkpad_id.ec_model) {
case 0x5931: /* TP-1Y */
case 0x3837: /* TP-78 */
case 0x3637: /* TP-76 */
case 0x3037: /* TP-70 */
printk(TPACPI_NOTICE
"fan_init: initial fan status is unknown, "
"assuming it is in auto mode\n");
tp_features.fan_ctrl_status_undef = 1;
;;
}
printk(TPACPI_NOTICE
"fan_init: initial fan status is unknown, "
"assuming it is in auto mode\n");
tp_features.fan_ctrl_status_undef = 1;
}
}
@ -6804,9 +6859,27 @@ static const struct attribute_group fan_attr_group = {
.attrs = fan_attributes,
};
#define TPACPI_FAN_Q1 0x0001
#define TPACPI_FAN_QI(__id1, __id2, __quirks) \
{ .vendor = PCI_VENDOR_ID_IBM, \
.bios = TPACPI_MATCH_ANY, \
.ec = TPID(__id1, __id2), \
.quirks = __quirks }
static const struct tpacpi_quirk fan_quirk_table[] __initconst = {
TPACPI_FAN_QI('1', 'Y', TPACPI_FAN_Q1),
TPACPI_FAN_QI('7', '8', TPACPI_FAN_Q1),
TPACPI_FAN_QI('7', '6', TPACPI_FAN_Q1),
TPACPI_FAN_QI('7', '0', TPACPI_FAN_Q1),
};
#undef TPACPI_FAN_QI
static int __init fan_init(struct ibm_init_struct *iibm)
{
int rc;
unsigned long quirks;
vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_FAN,
"initializing fan subdriver\n");
@ -6823,6 +6896,9 @@ static int __init fan_init(struct ibm_init_struct *iibm)
TPACPI_ACPIHANDLE_INIT(gfan);
TPACPI_ACPIHANDLE_INIT(sfan);
quirks = tpacpi_check_quirks(fan_quirk_table,
ARRAY_SIZE(fan_quirk_table));
if (gfan_handle) {
/* 570, 600e/x, 770e, 770x */
fan_status_access_mode = TPACPI_FAN_RD_ACPI_GFAN;
@ -6832,7 +6908,8 @@ static int __init fan_init(struct ibm_init_struct *iibm)
if (likely(acpi_ec_read(fan_status_offset,
&fan_control_initial_status))) {
fan_status_access_mode = TPACPI_FAN_RD_TPEC;
fan_quirk1_detect();
if (quirks & TPACPI_FAN_Q1)
fan_quirk1_setup();
} else {
printk(TPACPI_ERR
"ThinkPad ACPI EC access misbehaving, "