Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e82e15dd authored by Crane Cai's avatar Crane Cai Committed by Jean Delvare
Browse files

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: default avatarCrane Cai <crane.cai@amd.com>
Signed-off-by: default avatarDarrick J. Wong <djwong@us.ibm.com>
Signed-off-by: default avatarJean Delvare <khali@linux-fr.org>
parent 222e82ac
Loading
Loading
Loading
Loading
+23 −8
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ struct acpi_smbus_cmi {
	u8 cap_info:1;
	u8 cap_read:1;
	u8 cap_write:1;
	struct smbus_methods_t *methods;
};

static const struct smbus_methods_t smbus_methods = {
@@ -41,8 +42,16 @@ static const struct smbus_methods_t smbus_methods = {
	.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[] = {
	{"SMBUS01", 0},
	{"SMBUS01", (kernel_ulong_t)&smbus_methods},
	{ACPI_SMBUS_IBM_HID, (kernel_ulong_t)&ibm_smbus_methods},
	{"", 0}
};

@@ -150,11 +159,11 @@ acpi_smbus_cmi_access(struct i2c_adapter *adap, u16 addr, unsigned short flags,

	if (read_write == I2C_SMBUS_READ) {
		protocol |= ACPI_SMBUS_PRTCL_READ;
		method = smbus_methods.mt_sbr;
		method = smbus_cmi->methods->mt_sbr;
		input.count = 3;
	} else {
		protocol |= ACPI_SMBUS_PRTCL_WRITE;
		method = smbus_methods.mt_sbw;
		method = smbus_cmi->methods->mt_sbw;
		input.count = 5;
	}

@@ -290,13 +299,13 @@ static int acpi_smbus_cmi_add_cap(struct acpi_smbus_cmi *smbus_cmi,
	union acpi_object *obj;
	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,
					smbus_methods.mt_info,
					smbus_cmi->methods->mt_info,
					NULL, &buffer);
		if (ACPI_FAILURE(status)) {
			ACPI_ERROR((AE_INFO, "Evaluating %s: %i",
				   smbus_methods.mt_info, status));
				   smbus_cmi->methods->mt_info, status));
			return -EIO;
		}

@@ -319,9 +328,9 @@ static int acpi_smbus_cmi_add_cap(struct acpi_smbus_cmi *smbus_cmi,

		kfree(buffer.pointer);
		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;
	else if (!strcmp(name, smbus_methods.mt_sbw))
	else if (!strcmp(name, smbus_cmi->methods->mt_sbw))
		smbus_cmi->cap_write = 1;
	else
		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)
{
	struct acpi_smbus_cmi *smbus_cmi;
	const struct acpi_device_id *id;

	smbus_cmi = kzalloc(sizeof(struct acpi_smbus_cmi), GFP_KERNEL);
	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_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_smbus_cmi_query_methods, NULL, smbus_cmi, NULL);