diff options
author | Henrique de Moraes Holschuh <hmh@hmh.eng.br> | 2007-07-18 22:45:42 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2007-07-21 23:48:42 -0400 |
commit | d5a2f2f1d68e2da538ac28540cddd9ccc733b001 (patch) | |
tree | 659c3706c386af185581aefecc9fa2ea0f448df8 | |
parent | 86cc9445e86bef9da44f933e3849e6eb43cbf626 (diff) |
ACPI: thinkpad-acpi: store ThinkPad model information
Keep note of ThinkPad model, BIOS and EC firmware information, and log it
on startup. Makes for far more readable code in places, too.
This patch also adds Lenovo's PCI ID to the pci ids table.
Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
Signed-off-by: Len Brown <len.brown@intel.com>
-rw-r--r-- | drivers/misc/thinkpad_acpi.c | 98 | ||||
-rw-r--r-- | drivers/misc/thinkpad_acpi.h | 17 | ||||
-rw-r--r-- | include/linux/pci_ids.h | 2 |
3 files changed, 87 insertions, 30 deletions
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index 44aa8c92f91f..99500af651c1 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c | |||
@@ -717,9 +717,19 @@ static int __init thinkpad_acpi_driver_init(struct ibm_init_struct *iibm) | |||
717 | printk(IBM_INFO "%s v%s\n", IBM_DESC, IBM_VERSION); | 717 | printk(IBM_INFO "%s v%s\n", IBM_DESC, IBM_VERSION); |
718 | printk(IBM_INFO "%s\n", IBM_URL); | 718 | printk(IBM_INFO "%s\n", IBM_URL); |
719 | 719 | ||
720 | if (ibm_thinkpad_ec_found) | 720 | printk(IBM_INFO "ThinkPad BIOS %s, EC %s\n", |
721 | printk(IBM_INFO "ThinkPad EC firmware %s\n", | 721 | (thinkpad_id.bios_version_str) ? |
722 | ibm_thinkpad_ec_found); | 722 | thinkpad_id.bios_version_str : "unknown", |
723 | (thinkpad_id.ec_version_str) ? | ||
724 | thinkpad_id.ec_version_str : "unknown"); | ||
725 | |||
726 | if (thinkpad_id.vendor && thinkpad_id.model_str) | ||
727 | printk(IBM_INFO "%s %s\n", | ||
728 | (thinkpad_id.vendor == PCI_VENDOR_ID_IBM) ? | ||
729 | "IBM" : ((thinkpad_id.vendor == | ||
730 | PCI_VENDOR_ID_LENOVO) ? | ||
731 | "Lenovo" : "Unknown vendor"), | ||
732 | thinkpad_id.model_str); | ||
723 | 733 | ||
724 | return 0; | 734 | return 0; |
725 | } | 735 | } |
@@ -2648,7 +2658,7 @@ static int __init thermal_init(struct ibm_init_struct *iibm) | |||
2648 | 2658 | ||
2649 | acpi_tmp7 = acpi_evalf(ec_handle, NULL, "TMP7", "qv"); | 2659 | acpi_tmp7 = acpi_evalf(ec_handle, NULL, "TMP7", "qv"); |
2650 | 2660 | ||
2651 | if (ibm_thinkpad_ec_found && experimental) { | 2661 | if (thinkpad_id.ec_model && experimental) { |
2652 | /* | 2662 | /* |
2653 | * Direct EC access mode: sensors at registers | 2663 | * Direct EC access mode: sensors at registers |
2654 | * 0x78-0x7F, 0xC0-0xC7. Registers return 0x00 for | 2664 | * 0x78-0x7F, 0xC0-0xC7. Registers return 0x00 for |
@@ -3532,20 +3542,19 @@ static int __init fan_init(struct ibm_init_struct *iibm) | |||
3532 | * Enable for TP-1Y (T43), TP-78 (R51e), | 3542 | * Enable for TP-1Y (T43), TP-78 (R51e), |
3533 | * TP-76 (R52), TP-70 (T43, R52), which are known | 3543 | * TP-76 (R52), TP-70 (T43, R52), which are known |
3534 | * to be buggy. */ | 3544 | * to be buggy. */ |
3535 | if (fan_control_initial_status == 0x07 && | 3545 | if (fan_control_initial_status == 0x07) { |
3536 | ibm_thinkpad_ec_found && | 3546 | switch (thinkpad_id.ec_model) { |
3537 | ((ibm_thinkpad_ec_found[0] == '1' && | 3547 | case 0x5931: /* TP-1Y */ |
3538 | ibm_thinkpad_ec_found[1] == 'Y') || | 3548 | case 0x3837: /* TP-78 */ |
3539 | (ibm_thinkpad_ec_found[0] == '7' && | 3549 | case 0x3637: /* TP-76 */ |
3540 | (ibm_thinkpad_ec_found[1] == '6' || | 3550 | case 0x3037: /* TP-70 */ |
3541 | ibm_thinkpad_ec_found[1] == '8' || | 3551 | printk(IBM_NOTICE |
3542 | ibm_thinkpad_ec_found[1] == '0')) | 3552 | "fan_init: initial fan status is " |
3543 | )) { | 3553 | "unknown, assuming it is in auto " |
3544 | printk(IBM_NOTICE | 3554 | "mode\n"); |
3545 | "fan_init: initial fan status is " | 3555 | tp_features.fan_ctrl_status_undef = 1; |
3546 | "unknown, assuming it is in auto " | 3556 | ;; |
3547 | "mode\n"); | 3557 | } |
3548 | tp_features.fan_ctrl_status_undef = 1; | ||
3549 | } | 3558 | } |
3550 | } else { | 3559 | } else { |
3551 | printk(IBM_ERR | 3560 | printk(IBM_ERR |
@@ -4279,13 +4288,30 @@ static void ibm_exit(struct ibm_struct *ibm) | |||
4279 | 4288 | ||
4280 | /* Probing */ | 4289 | /* Probing */ |
4281 | 4290 | ||
4282 | static char *ibm_thinkpad_ec_found; | 4291 | static void __init get_thinkpad_model_data(struct thinkpad_id_data *tp) |
4283 | |||
4284 | static char* __init check_dmi_for_ec(void) | ||
4285 | { | 4292 | { |
4286 | struct dmi_device *dev = NULL; | 4293 | struct dmi_device *dev = NULL; |
4287 | char ec_fw_string[18]; | 4294 | char ec_fw_string[18]; |
4288 | 4295 | ||
4296 | if (!tp) | ||
4297 | return; | ||
4298 | |||
4299 | memset(tp, 0, sizeof(*tp)); | ||
4300 | |||
4301 | if (dmi_name_in_vendors("IBM")) | ||
4302 | tp->vendor = PCI_VENDOR_ID_IBM; | ||
4303 | else if (dmi_name_in_vendors("LENOVO")) | ||
4304 | tp->vendor = PCI_VENDOR_ID_LENOVO; | ||
4305 | else | ||
4306 | return; | ||
4307 | |||
4308 | tp->bios_version_str = kstrdup(dmi_get_system_info(DMI_BIOS_VERSION), | ||
4309 | GFP_KERNEL); | ||
4310 | if (!tp->bios_version_str) | ||
4311 | return; | ||
4312 | tp->bios_model = tp->bios_version_str[0] | ||
4313 | | (tp->bios_version_str[1] << 8); | ||
4314 | |||
4289 | /* | 4315 | /* |
4290 | * ThinkPad T23 or newer, A31 or newer, R50e or newer, | 4316 | * ThinkPad T23 or newer, A31 or newer, R50e or newer, |
4291 | * X32 or newer, all Z series; Some models must have an | 4317 | * X32 or newer, all Z series; Some models must have an |
@@ -4299,10 +4325,20 @@ static char* __init check_dmi_for_ec(void) | |||
4299 | ec_fw_string) == 1) { | 4325 | ec_fw_string) == 1) { |
4300 | ec_fw_string[sizeof(ec_fw_string) - 1] = 0; | 4326 | ec_fw_string[sizeof(ec_fw_string) - 1] = 0; |
4301 | ec_fw_string[strcspn(ec_fw_string, " ]")] = 0; | 4327 | ec_fw_string[strcspn(ec_fw_string, " ]")] = 0; |
4302 | return kstrdup(ec_fw_string, GFP_KERNEL); | 4328 | |
4329 | tp->ec_version_str = kstrdup(ec_fw_string, GFP_KERNEL); | ||
4330 | tp->ec_model = ec_fw_string[0] | ||
4331 | | (ec_fw_string[1] << 8); | ||
4332 | break; | ||
4303 | } | 4333 | } |
4304 | } | 4334 | } |
4305 | return NULL; | 4335 | |
4336 | tp->model_str = kstrdup(dmi_get_system_info(DMI_PRODUCT_VERSION), | ||
4337 | GFP_KERNEL); | ||
4338 | if (strnicmp(tp->model_str, "ThinkPad", 8) != 0) { | ||
4339 | kfree(tp->model_str); | ||
4340 | tp->model_str = NULL; | ||
4341 | } | ||
4306 | } | 4342 | } |
4307 | 4343 | ||
4308 | static int __init probe_for_thinkpad(void) | 4344 | static int __init probe_for_thinkpad(void) |
@@ -4316,7 +4352,7 @@ static int __init probe_for_thinkpad(void) | |||
4316 | * Non-ancient models have better DMI tagging, but very old models | 4352 | * Non-ancient models have better DMI tagging, but very old models |
4317 | * don't. | 4353 | * don't. |
4318 | */ | 4354 | */ |
4319 | is_thinkpad = dmi_name_in_vendors("ThinkPad"); | 4355 | is_thinkpad = (thinkpad_id.model_str != NULL); |
4320 | 4356 | ||
4321 | /* ec is required because many other handles are relative to it */ | 4357 | /* ec is required because many other handles are relative to it */ |
4322 | IBM_ACPIHANDLE_INIT(ec); | 4358 | IBM_ACPIHANDLE_INIT(ec); |
@@ -4332,7 +4368,7 @@ static int __init probe_for_thinkpad(void) | |||
4332 | * false positives a damn great deal | 4368 | * false positives a damn great deal |
4333 | */ | 4369 | */ |
4334 | if (!is_thinkpad) | 4370 | if (!is_thinkpad) |
4335 | is_thinkpad = dmi_name_in_vendors("IBM"); | 4371 | is_thinkpad = (thinkpad_id.vendor == PCI_VENDOR_ID_IBM); |
4336 | 4372 | ||
4337 | if (!is_thinkpad && !force_load) | 4373 | if (!is_thinkpad && !force_load) |
4338 | return -ENODEV; | 4374 | return -ENODEV; |
@@ -4475,12 +4511,16 @@ static int __init thinkpad_acpi_module_init(void) | |||
4475 | int ret, i; | 4511 | int ret, i; |
4476 | 4512 | ||
4477 | /* Driver-level probe */ | 4513 | /* Driver-level probe */ |
4514 | |||
4515 | get_thinkpad_model_data(&thinkpad_id); | ||
4478 | ret = probe_for_thinkpad(); | 4516 | ret = probe_for_thinkpad(); |
4479 | if (ret) | 4517 | if (ret) { |
4518 | thinkpad_acpi_module_exit(); | ||
4480 | return ret; | 4519 | return ret; |
4520 | } | ||
4481 | 4521 | ||
4482 | /* Driver initialization */ | 4522 | /* Driver initialization */ |
4483 | ibm_thinkpad_ec_found = check_dmi_for_ec(); | 4523 | |
4484 | IBM_ACPIHANDLE_INIT(ecrd); | 4524 | IBM_ACPIHANDLE_INIT(ecrd); |
4485 | IBM_ACPIHANDLE_INIT(ecwr); | 4525 | IBM_ACPIHANDLE_INIT(ecwr); |
4486 | 4526 | ||
@@ -4590,7 +4630,9 @@ static void thinkpad_acpi_module_exit(void) | |||
4590 | if (proc_dir) | 4630 | if (proc_dir) |
4591 | remove_proc_entry(IBM_PROC_DIR, acpi_root_dir); | 4631 | remove_proc_entry(IBM_PROC_DIR, acpi_root_dir); |
4592 | 4632 | ||
4593 | kfree(ibm_thinkpad_ec_found); | 4633 | kfree(thinkpad_id.bios_version_str); |
4634 | kfree(thinkpad_id.ec_version_str); | ||
4635 | kfree(thinkpad_id.model_str); | ||
4594 | } | 4636 | } |
4595 | 4637 | ||
4596 | module_init(thinkpad_acpi_module_init); | 4638 | module_init(thinkpad_acpi_module_init); |
diff --git a/drivers/misc/thinkpad_acpi.h b/drivers/misc/thinkpad_acpi.h index fee04214a10b..09b2282fed0b 100644 --- a/drivers/misc/thinkpad_acpi.h +++ b/drivers/misc/thinkpad_acpi.h | |||
@@ -175,9 +175,7 @@ static void tpacpi_remove_driver_attributes(struct device_driver *drv); | |||
175 | static int experimental; | 175 | static int experimental; |
176 | static u32 dbg_level; | 176 | static u32 dbg_level; |
177 | static int force_load; | 177 | static int force_load; |
178 | static char *ibm_thinkpad_ec_found; | ||
179 | 178 | ||
180 | static char* check_dmi_for_ec(void); | ||
181 | static int thinkpad_acpi_module_init(void); | 179 | static int thinkpad_acpi_module_init(void); |
182 | static void thinkpad_acpi_module_exit(void); | 180 | static void thinkpad_acpi_module_exit(void); |
183 | 181 | ||
@@ -244,6 +242,21 @@ static struct { | |||
244 | u16 input_device_registered:1; | 242 | u16 input_device_registered:1; |
245 | } tp_features; | 243 | } tp_features; |
246 | 244 | ||
245 | struct thinkpad_id_data { | ||
246 | unsigned int vendor; /* ThinkPad vendor: | ||
247 | * PCI_VENDOR_ID_IBM/PCI_VENDOR_ID_LENOVO */ | ||
248 | |||
249 | char *bios_version_str; /* Something like 1ZET51WW (1.03z) */ | ||
250 | char *ec_version_str; /* Something like 1ZHT51WW-1.04a */ | ||
251 | |||
252 | u16 bios_model; /* Big Endian, TP-1Y = 0x5931, 0 = unknown */ | ||
253 | u16 ec_model; | ||
254 | |||
255 | char *model_str; | ||
256 | }; | ||
257 | |||
258 | static struct thinkpad_id_data thinkpad_id; | ||
259 | |||
247 | static struct list_head tpacpi_all_drivers; | 260 | static struct list_head tpacpi_all_drivers; |
248 | 261 | ||
249 | static struct ibm_init_struct ibms_init[]; | 262 | static struct ibm_init_struct ibms_init[]; |
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index b15c6498fe67..ced4d3f76104 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h | |||
@@ -2040,6 +2040,8 @@ | |||
2040 | #define PCI_DEVICE_ID_ALTIMA_AC9100 0x03ea | 2040 | #define PCI_DEVICE_ID_ALTIMA_AC9100 0x03ea |
2041 | #define PCI_DEVICE_ID_ALTIMA_AC1003 0x03eb | 2041 | #define PCI_DEVICE_ID_ALTIMA_AC1003 0x03eb |
2042 | 2042 | ||
2043 | #define PCI_VENDOR_ID_LENOVO 0x17aa | ||
2044 | |||
2043 | #define PCI_VENDOR_ID_ARECA 0x17d3 | 2045 | #define PCI_VENDOR_ID_ARECA 0x17d3 |
2044 | #define PCI_DEVICE_ID_ARECA_1110 0x1110 | 2046 | #define PCI_DEVICE_ID_ARECA_1110 0x1110 |
2045 | #define PCI_DEVICE_ID_ARECA_1120 0x1120 | 2047 | #define PCI_DEVICE_ID_ARECA_1120 0x1120 |