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 /drivers/i2c | |
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>
Diffstat (limited to 'drivers/i2c')
-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 | ||