aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorCrane Cai <crane.cai@amd.com>2010-03-24 09:38:38 -0400
committerJean Delvare <khali@linux-fr.org>2010-03-24 09:38:38 -0400
commite82e15ddd322e4c5847536f044a40812b7ec12bd (patch)
tree580f9dcec81d2494f000cbed13ad41645a0b1eea /drivers/i2c
parent222e82ac9ffbd3b80ab1b0b1d2c8c60ddb47d69d (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.c31
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
38static const struct smbus_methods_t smbus_methods = { 39static 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 */
46static const struct smbus_methods_t ibm_smbus_methods = {
47 .mt_info = "SBI_",
48 .mt_sbr = "SBR_",
49 .mt_sbw = "SBW_",
50};
51
44static const struct acpi_device_id acpi_smbus_cmi_ids[] = { 52static 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,
349static int acpi_smbus_cmi_add(struct acpi_device *device) 358static 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