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>
This commit is contained in:
Родитель
222e82ac9f
Коммит
e82e15ddd3
|
@ -33,6 +33,7 @@ struct acpi_smbus_cmi {
|
||||||
u8 cap_info:1;
|
u8 cap_info:1;
|
||||||
u8 cap_read:1;
|
u8 cap_read:1;
|
||||||
u8 cap_write:1;
|
u8 cap_write:1;
|
||||||
|
struct smbus_methods_t *methods;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct smbus_methods_t smbus_methods = {
|
static const struct smbus_methods_t smbus_methods = {
|
||||||
|
@ -41,8 +42,16 @@ static const struct smbus_methods_t smbus_methods = {
|
||||||
.mt_sbw = "_SBW",
|
.mt_sbw = "_SBW",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Some IBM BIOSes omit the leading underscore */
|
||||||
|
static const struct smbus_methods_t ibm_smbus_methods = {
|
||||||
|
.mt_info = "SBI_",
|
||||||
|
.mt_sbr = "SBR_",
|
||||||
|
.mt_sbw = "SBW_",
|
||||||
|
};
|
||||||
|
|
||||||
static const struct acpi_device_id acpi_smbus_cmi_ids[] = {
|
static const struct acpi_device_id acpi_smbus_cmi_ids[] = {
|
||||||
{"SMBUS01", 0},
|
{"SMBUS01", (kernel_ulong_t)&smbus_methods},
|
||||||
|
{ACPI_SMBUS_IBM_HID, (kernel_ulong_t)&ibm_smbus_methods},
|
||||||
{"", 0}
|
{"", 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -150,11 +159,11 @@ acpi_smbus_cmi_access(struct i2c_adapter *adap, u16 addr, unsigned short flags,
|
||||||
|
|
||||||
if (read_write == I2C_SMBUS_READ) {
|
if (read_write == I2C_SMBUS_READ) {
|
||||||
protocol |= ACPI_SMBUS_PRTCL_READ;
|
protocol |= ACPI_SMBUS_PRTCL_READ;
|
||||||
method = smbus_methods.mt_sbr;
|
method = smbus_cmi->methods->mt_sbr;
|
||||||
input.count = 3;
|
input.count = 3;
|
||||||
} else {
|
} else {
|
||||||
protocol |= ACPI_SMBUS_PRTCL_WRITE;
|
protocol |= ACPI_SMBUS_PRTCL_WRITE;
|
||||||
method = smbus_methods.mt_sbw;
|
method = smbus_cmi->methods->mt_sbw;
|
||||||
input.count = 5;
|
input.count = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,13 +299,13 @@ static int acpi_smbus_cmi_add_cap(struct acpi_smbus_cmi *smbus_cmi,
|
||||||
union acpi_object *obj;
|
union acpi_object *obj;
|
||||||
acpi_status status;
|
acpi_status status;
|
||||||
|
|
||||||
if (!strcmp(name, smbus_methods.mt_info)) {
|
if (!strcmp(name, smbus_cmi->methods->mt_info)) {
|
||||||
status = acpi_evaluate_object(smbus_cmi->handle,
|
status = acpi_evaluate_object(smbus_cmi->handle,
|
||||||
smbus_methods.mt_info,
|
smbus_cmi->methods->mt_info,
|
||||||
NULL, &buffer);
|
NULL, &buffer);
|
||||||
if (ACPI_FAILURE(status)) {
|
if (ACPI_FAILURE(status)) {
|
||||||
ACPI_ERROR((AE_INFO, "Evaluating %s: %i",
|
ACPI_ERROR((AE_INFO, "Evaluating %s: %i",
|
||||||
smbus_methods.mt_info, status));
|
smbus_cmi->methods->mt_info, status));
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -319,9 +328,9 @@ static int acpi_smbus_cmi_add_cap(struct acpi_smbus_cmi *smbus_cmi,
|
||||||
|
|
||||||
kfree(buffer.pointer);
|
kfree(buffer.pointer);
|
||||||
smbus_cmi->cap_info = 1;
|
smbus_cmi->cap_info = 1;
|
||||||
} else if (!strcmp(name, smbus_methods.mt_sbr))
|
} else if (!strcmp(name, smbus_cmi->methods->mt_sbr))
|
||||||
smbus_cmi->cap_read = 1;
|
smbus_cmi->cap_read = 1;
|
||||||
else if (!strcmp(name, smbus_methods.mt_sbw))
|
else if (!strcmp(name, smbus_cmi->methods->mt_sbw))
|
||||||
smbus_cmi->cap_write = 1;
|
smbus_cmi->cap_write = 1;
|
||||||
else
|
else
|
||||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unsupported CMI method: %s\n",
|
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,
|
||||||
static int acpi_smbus_cmi_add(struct acpi_device *device)
|
static int acpi_smbus_cmi_add(struct acpi_device *device)
|
||||||
{
|
{
|
||||||
struct acpi_smbus_cmi *smbus_cmi;
|
struct acpi_smbus_cmi *smbus_cmi;
|
||||||
|
const struct acpi_device_id *id;
|
||||||
|
|
||||||
smbus_cmi = kzalloc(sizeof(struct acpi_smbus_cmi), GFP_KERNEL);
|
smbus_cmi = kzalloc(sizeof(struct acpi_smbus_cmi), GFP_KERNEL);
|
||||||
if (!smbus_cmi)
|
if (!smbus_cmi)
|
||||||
|
@ -362,6 +372,11 @@ static int acpi_smbus_cmi_add(struct acpi_device *device)
|
||||||
smbus_cmi->cap_read = 0;
|
smbus_cmi->cap_read = 0;
|
||||||
smbus_cmi->cap_write = 0;
|
smbus_cmi->cap_write = 0;
|
||||||
|
|
||||||
|
for (id = acpi_smbus_cmi_ids; id->id[0]; id++)
|
||||||
|
if (!strcmp(id->id, acpi_device_hid(device)))
|
||||||
|
smbus_cmi->methods =
|
||||||
|
(struct smbus_methods_t *) id->driver_data;
|
||||||
|
|
||||||
acpi_walk_namespace(ACPI_TYPE_METHOD, smbus_cmi->handle, 1,
|
acpi_walk_namespace(ACPI_TYPE_METHOD, smbus_cmi->handle, 1,
|
||||||
acpi_smbus_cmi_query_methods, NULL, smbus_cmi, NULL);
|
acpi_smbus_cmi_query_methods, NULL, smbus_cmi, NULL);
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче