aboutsummaryrefslogtreecommitdiff
path: root/drivers/i2c/busses/i2c-scmi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c/busses/i2c-scmi.c')
-rw-r--r--drivers/i2c/busses/i2c-scmi.c55
1 files changed, 29 insertions, 26 deletions
diff --git a/drivers/i2c/busses/i2c-scmi.c b/drivers/i2c/busses/i2c-scmi.c
index 365e0becaf1..dfc98df7b1b 100644
--- a/drivers/i2c/busses/i2c-scmi.c
+++ b/drivers/i2c/busses/i2c-scmi.c
@@ -12,7 +12,6 @@
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/stddef.h>
-#include <linux/init.h>
#include <linux/i2c.h>
#include <linux/acpi.h>
@@ -33,6 +32,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,10 +41,19 @@ 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}
};
+MODULE_DEVICE_TABLE(acpi, acpi_smbus_cmi_ids);
#define ACPI_SMBUS_STATUS_OK 0x00
#define ACPI_SMBUS_STATUS_FAIL 0x07
@@ -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;
}
@@ -213,7 +222,7 @@ acpi_smbus_cmi_access(struct i2c_adapter *adap, u16 addr, unsigned short flags,
goto out;
obj = pkg->package.elements + 1;
- if (obj == NULL || obj->type != ACPI_TYPE_INTEGER) {
+ if (obj->type != ACPI_TYPE_INTEGER) {
ACPI_ERROR((AE_INFO, "Invalid argument type"));
result = -EIO;
goto out;
@@ -225,7 +234,7 @@ acpi_smbus_cmi_access(struct i2c_adapter *adap, u16 addr, unsigned short flags,
case I2C_SMBUS_BYTE:
case I2C_SMBUS_BYTE_DATA:
case I2C_SMBUS_WORD_DATA:
- if (obj == NULL || obj->type != ACPI_TYPE_INTEGER) {
+ if (obj->type != ACPI_TYPE_INTEGER) {
ACPI_ERROR((AE_INFO, "Invalid argument type"));
result = -EIO;
goto out;
@@ -236,7 +245,7 @@ acpi_smbus_cmi_access(struct i2c_adapter *adap, u16 addr, unsigned short flags,
data->byte = obj->integer.value;
break;
case I2C_SMBUS_BLOCK_DATA:
- if (obj == NULL || obj->type != ACPI_TYPE_BUFFER) {
+ if (obj->type != ACPI_TYPE_BUFFER) {
ACPI_ERROR((AE_INFO, "Invalid argument type"));
result = -EIO;
goto out;
@@ -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);
@@ -390,7 +405,7 @@ err:
return -EIO;
}
-static int acpi_smbus_cmi_remove(struct acpi_device *device, int type)
+static int acpi_smbus_cmi_remove(struct acpi_device *device)
{
struct acpi_smbus_cmi *smbus_cmi = acpi_driver_data(device);
@@ -410,19 +425,7 @@ static struct acpi_driver acpi_smbus_cmi_driver = {
.remove = acpi_smbus_cmi_remove,
},
};
-
-static int __init acpi_smbus_cmi_init(void)
-{
- return acpi_bus_register_driver(&acpi_smbus_cmi_driver);
-}
-
-static void __exit acpi_smbus_cmi_exit(void)
-{
- acpi_bus_unregister_driver(&acpi_smbus_cmi_driver);
-}
-
-module_init(acpi_smbus_cmi_init);
-module_exit(acpi_smbus_cmi_exit);
+module_acpi_driver(acpi_smbus_cmi_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Crane Cai <crane.cai@amd.com>");