diff options
| author | Crane Cai <crane.cai@amd.com> | 2010-03-24 09:38:38 -0400 |
|---|---|---|
| committer | Jean Delvare <khali@linux-fr.org> | 2010-03-24 09:38:38 -0400 |
| commit | e82e15ddd322e4c5847536f044a40812b7ec12bd (patch) | |
| tree | 580f9dcec81d2494f000cbed13ad41645a0b1eea | |
| parent | 222e82ac9ffbd3b80ab1b0b1d2c8c60ddb47d69d (diff) | |
i2c-scmi: Support IBM SMBus CMI devices
*) add a new HID for IBM SMBus CMI devices
*) add methods for IBM SMBus CMI devices
*) hook different HID with different control methods set
*) minor tweaks as suggested by Jean Delvare
Slightly modified by Darrick to use #define'd IBM SMBUS HID from Darrick's ACPI
scan quirk patch.
Signed-off-by: Crane Cai <crane.cai@amd.com>
Signed-off-by: Darrick J. Wong <djwong@us.ibm.com>
Signed-off-by: Jean Delvare <khali@linux-fr.org>
| -rw-r--r-- | drivers/i2c/busses/i2c-scmi.c | 31 |
1 files changed, 23 insertions, 8 deletions
diff --git a/drivers/i2c/busses/i2c-scmi.c b/drivers/i2c/busses/i2c-scmi.c index 365e0becaf12..4c9fb4cd4bb5 100644 --- a/drivers/i2c/busses/i2c-scmi.c +++ b/drivers/i2c/busses/i2c-scmi.c | |||
| @@ -33,6 +33,7 @@ struct acpi_smbus_cmi { | |||
| 33 | u8 cap_info:1; | 33 | u8 cap_info:1; |
| 34 | u8 cap_read:1; | 34 | u8 cap_read:1; |
| 35 | u8 cap_write:1; | 35 | u8 cap_write:1; |
| 36 | struct smbus_methods_t *methods; | ||
| 36 | }; | 37 | }; |
| 37 | 38 | ||
| 38 | static const struct smbus_methods_t smbus_methods = { | 39 | static const struct smbus_methods_t smbus_methods = { |
| @@ -41,8 +42,16 @@ static const struct smbus_methods_t smbus_methods = { | |||
| 41 | .mt_sbw = "_SBW", | 42 | .mt_sbw = "_SBW", |
| 42 | }; | 43 | }; |
| 43 | 44 | ||
| 45 | /* Some IBM BIOSes omit the leading underscore */ | ||
| 46 | static const struct smbus_methods_t ibm_smbus_methods = { | ||
| 47 | .mt_info = "SBI_", | ||
| 48 | .mt_sbr = "SBR_", | ||
| 49 | .mt_sbw = "SBW_", | ||
| 50 | }; | ||
| 51 | |||
| 44 | static const struct acpi_device_id acpi_smbus_cmi_ids[] = { | 52 | static const struct acpi_device_id acpi_smbus_cmi_ids[] = { |
| 45 | {"SMBUS01", 0}, | 53 | {"SMBUS01", (kernel_ulong_t)&smbus_methods}, |
| 54 | {ACPI_SMBUS_IBM_HID, (kernel_ulong_t)&ibm_smbus_methods}, | ||
| 46 | {"", 0} | 55 | {"", 0} |
| 47 | }; | 56 | }; |
| 48 | 57 | ||
| @@ -150,11 +159,11 @@ acpi_smbus_cmi_access(struct i2c_adapter *adap, u16 addr, unsigned short flags, | |||
| 150 | 159 | ||
| 151 | if (read_write == I2C_SMBUS_READ) { | 160 | if (read_write == I2C_SMBUS_READ) { |
| 152 | protocol |= ACPI_SMBUS_PRTCL_READ; | 161 | protocol |= ACPI_SMBUS_PRTCL_READ; |
| 153 | method = smbus_methods.mt_sbr; | 162 | method = smbus_cmi->methods->mt_sbr; |
| 154 | input.count = 3; | 163 | input.count = 3; |
| 155 | } else { | 164 | } else { |
| 156 | protocol |= ACPI_SMBUS_PRTCL_WRITE; | 165 | protocol |= ACPI_SMBUS_PRTCL_WRITE; |
| 157 | method = smbus_methods.mt_sbw; | 166 | method = smbus_cmi->methods->mt_sbw; |
| 158 | input.count = 5; | 167 | input.count = 5; |
| 159 | } | 168 | } |
| 160 | 169 | ||
| @@ -290,13 +299,13 @@ static int acpi_smbus_cmi_add_cap(struct acpi_smbus_cmi *smbus_cmi, | |||
| 290 | union acpi_object *obj; | 299 | union acpi_object *obj; |
| 291 | acpi_status status; | 300 | acpi_status status; |
| 292 | 301 | ||
| 293 | if (!strcmp(name, smbus_methods.mt_info)) { | 302 | if (!strcmp(name, smbus_cmi->methods->mt_info)) { |
| 294 | status = acpi_evaluate_object(smbus_cmi->handle, | 303 | status = acpi_evaluate_object(smbus_cmi->handle, |
| 295 | smbus_methods.mt_info, | 304 | smbus_cmi->methods->mt_info, |
| 296 | NULL, &buffer); | 305 | NULL, &buffer); |
| 297 | if (ACPI_FAILURE(status)) { | 306 | if (ACPI_FAILURE(status)) { |
| 298 | ACPI_ERROR((AE_INFO, "Evaluating %s: %i", | 307 | ACPI_ERROR((AE_INFO, "Evaluating %s: %i", |
| 299 | smbus_methods.mt_info, status)); | 308 | smbus_cmi->methods->mt_info, status)); |
| 300 | return -EIO; | 309 | return -EIO; |
| 301 | } | 310 | } |
| 302 | 311 | ||
| @@ -319,9 +328,9 @@ static int acpi_smbus_cmi_add_cap(struct acpi_smbus_cmi *smbus_cmi, | |||
| 319 | 328 | ||
| 320 | kfree(buffer.pointer); | 329 | kfree(buffer.pointer); |
| 321 | smbus_cmi->cap_info = 1; | 330 | smbus_cmi->cap_info = 1; |
| 322 | } else if (!strcmp(name, smbus_methods.mt_sbr)) | 331 | } else if (!strcmp(name, smbus_cmi->methods->mt_sbr)) |
| 323 | smbus_cmi->cap_read = 1; | 332 | smbus_cmi->cap_read = 1; |
| 324 | else if (!strcmp(name, smbus_methods.mt_sbw)) | 333 | else if (!strcmp(name, smbus_cmi->methods->mt_sbw)) |
| 325 | smbus_cmi->cap_write = 1; | 334 | smbus_cmi->cap_write = 1; |
| 326 | else | 335 | else |
| 327 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unsupported CMI method: %s\n", | 336 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unsupported CMI method: %s\n", |
| @@ -349,6 +358,7 @@ static acpi_status acpi_smbus_cmi_query_methods(acpi_handle handle, u32 level, | |||
| 349 | static int acpi_smbus_cmi_add(struct acpi_device *device) | 358 | static int acpi_smbus_cmi_add(struct acpi_device *device) |
| 350 | { | 359 | { |
| 351 | struct acpi_smbus_cmi *smbus_cmi; | 360 | struct acpi_smbus_cmi *smbus_cmi; |
| 361 | const struct acpi_device_id *id; | ||
| 352 | 362 | ||
| 353 | smbus_cmi = kzalloc(sizeof(struct acpi_smbus_cmi), GFP_KERNEL); | 363 | smbus_cmi = kzalloc(sizeof(struct acpi_smbus_cmi), GFP_KERNEL); |
| 354 | if (!smbus_cmi) | 364 | if (!smbus_cmi) |
| @@ -362,6 +372,11 @@ static int acpi_smbus_cmi_add(struct acpi_device *device) | |||
| 362 | smbus_cmi->cap_read = 0; | 372 | smbus_cmi->cap_read = 0; |
| 363 | smbus_cmi->cap_write = 0; | 373 | smbus_cmi->cap_write = 0; |
| 364 | 374 | ||
| 375 | for (id = acpi_smbus_cmi_ids; id->id[0]; id++) | ||
| 376 | if (!strcmp(id->id, acpi_device_hid(device))) | ||
| 377 | smbus_cmi->methods = | ||
| 378 | (struct smbus_methods_t *) id->driver_data; | ||
| 379 | |||
| 365 | acpi_walk_namespace(ACPI_TYPE_METHOD, smbus_cmi->handle, 1, | 380 | acpi_walk_namespace(ACPI_TYPE_METHOD, smbus_cmi->handle, 1, |
| 366 | acpi_smbus_cmi_query_methods, NULL, smbus_cmi, NULL); | 381 | acpi_smbus_cmi_query_methods, NULL, smbus_cmi, NULL); |
| 367 | 382 | ||
