summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/input/ak-akm89xx.txt25
-rw-r--r--Documentation/devicetree/bindings/vendor-prefixes.txt1
-rw-r--r--drivers/input/misc/compass/ak8975_input.c75
3 files changed, 95 insertions, 6 deletions
diff --git a/Documentation/devicetree/bindings/input/ak-akm89xx.txt b/Documentation/devicetree/bindings/input/ak-akm89xx.txt
new file mode 100644
index 000000000000..e91c08ee2ebd
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/ak-akm89xx.txt
@@ -0,0 +1,25 @@
+* Asahi Kasei AKM89XX compass sensor
+
+Required properties:
+- compatible: should be one of the following.
+ - "ak,ak8963"
+ - "ak,ak8972"
+ - "ak,ak8975"
+- reg: the I2C address of AKM89XX
+- config: the selection determines the device behavior.
+ - "auto": auto detect connection to MPU
+ - "mpu": connected to MPU
+ - "host": connected to host
+- orientation: the orientation matricies are 3x3 rotation matricies that are
+ applied to the data to rotate from the mounting orientation to the platform
+ orientation. The values must be one of 0, 1, or -1(0xff in byte array) and
+ each row and column should have exactly 1 non-zero value.
+
+Example:
+
+akm8963@0d {
+ compatible = "ak,ak8963";
+ reg = <0x0d>;
+ orientation = [00 01 00 ff 00 00 00 00 01];
+ config = "mpu";
+};
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index d7564379c98a..931243bdfb1c 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -4,6 +4,7 @@ This isn't an exhaustive list, but you should add new prefixes to it before
using them to avoid name-space collisions.
adi Analog Devices, Inc.
+ak Asahi Kasei Corp.
amcc Applied Micro Circuits Corporation (APM, formally AMCC)
apm Applied Micro Circuits Corporation (APM)
arm ARM Ltd.
diff --git a/drivers/input/misc/compass/ak8975_input.c b/drivers/input/misc/compass/ak8975_input.c
index e89455434d73..027bc5a97836 100644
--- a/drivers/input/misc/compass/ak8975_input.c
+++ b/drivers/input/misc/compass/ak8975_input.c
@@ -108,6 +108,11 @@ static char *akm_vregs[] = {
"vid",
};
+static char *akm_configs[] = {
+ "auto",
+ "mpu",
+ "host",
+};
struct akm_asa {
u8 asa[3]; /* axis sensitivity adjustment */
@@ -1119,6 +1124,47 @@ static void akm_shutdown(struct i2c_client *client)
akm_remove(client);
}
+static struct mpu_platform_data *akm_parse_dt(struct i2c_client *client)
+{
+ struct mpu_platform_data *pdata;
+ struct device_node *np = client->dev.of_node;
+ char *pchar;
+ u8 config;
+ int len;
+
+ pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata) {
+ dev_err(&client->dev, "Can't allocate platform data\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ pchar = of_get_property(np, "orientation", &len);
+ if (!pchar || len != sizeof(pdata->orientation)) {
+ dev_err(&client->dev, "Cannot read orientation property\n");
+ return ERR_PTR(-EINVAL);
+ }
+ memcpy(pdata->orientation, pchar, len);
+
+ if (of_property_read_string(np, "config", &pchar)) {
+ dev_err(&client->dev, "Cannot read config property\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ for (config = 0; config < ARRAY_SIZE(akm_configs); config++) {
+ if (!strcasecmp(pchar, akm_configs[config])) {
+ pdata->config = config;
+ break;
+ }
+ }
+
+ if (config == ARRAY_SIZE(akm_configs)) {
+ dev_err(&client->dev, "Invalid config value\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ return pdata;
+}
+
static int akm_probe(struct i2c_client *client,
const struct i2c_device_id *devid)
{
@@ -1128,19 +1174,26 @@ static int akm_probe(struct i2c_client *client,
dev_info(&client->dev, "%s\n", __func__);
inf = kzalloc(sizeof(*inf), GFP_KERNEL);
- if (IS_ERR_OR_NULL(inf)) {
+ if (!inf) {
dev_err(&client->dev, "%s kzalloc ERR\n", __func__);
return -ENOMEM;
}
inf->i2c = client;
i2c_set_clientdata(client, inf);
- pd = (struct mpu_platform_data *)dev_get_platdata(&client->dev);
- if (pd == NULL)
- dev_err(&client->dev, "%s No %s platform data ERR\n",
- __func__, devid->name);
+
+ if (client->dev.of_node)
+ pd = akm_parse_dt(client);
else
- inf->pdata = *pd;
+ pd = (struct mpu_platform_data *)dev_get_platdata(&client->dev);
+
+ if (!pd || IS_ERR(pd)) {
+ kfree(inf);
+ return -EINVAL;
+ }
+
+ inf->pdata = *pd;
+
akm_pm_init(inf);
err = akm_id(inf);
akm_pm(inf, false);
@@ -1185,6 +1238,15 @@ static const struct i2c_device_id akm_i2c_device_id[] = {
MODULE_DEVICE_TABLE(i2c, akm_i2c_device_id);
+static const struct of_device_id akm_of_match[] = {
+ { .compatible = "ak,ak8963", },
+ { .compatible = "ak,ak8972", },
+ { .compatible = "ak,ak8975", },
+ { },
+};
+
+MODULE_DEVICE_TABLE(of, akm_of_match);
+
static struct i2c_driver akm_driver = {
.class = I2C_CLASS_HWMON,
.probe = akm_probe,
@@ -1192,6 +1254,7 @@ static struct i2c_driver akm_driver = {
.driver = {
.name = AKM_NAME,
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(akm_of_match),
},
.id_table = akm_i2c_device_id,
.shutdown = akm_shutdown,