summaryrefslogtreecommitdiff
path: root/drivers/iio/light/isl29018.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/iio/light/isl29018.c')
-rw-r--r--drivers/iio/light/isl29018.c109
1 files changed, 61 insertions, 48 deletions
diff --git a/drivers/iio/light/isl29018.c b/drivers/iio/light/isl29018.c
index b45400f8fef4..1b4c18423048 100644
--- a/drivers/iio/light/isl29018.c
+++ b/drivers/iio/light/isl29018.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* A iio driver for the light sensor ISL 29018/29023/29035.
*
@@ -5,28 +6,20 @@
* sensing and infrared sensing.
*
* Copyright (c) 2010, NVIDIA Corporation.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
*/
-#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/err.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/delay.h>
#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
#include <linux/slab.h>
+
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
-#include <linux/acpi.h>
#define ISL29018_CONV_TIME_MS 100
@@ -95,6 +88,7 @@ struct isl29018_chip {
struct isl29018_scale scale;
int prox_scheme;
bool suspended;
+ struct regulator *vcc_reg;
};
static int isl29018_set_integration_time(struct isl29018_chip *chip,
@@ -557,9 +551,9 @@ static int isl29018_chip_init(struct isl29018_chip *chip)
return -ENODEV;
/* Clear brownout bit */
- status = regmap_update_bits(chip->regmap,
- ISL29035_REG_DEVICE_ID,
- ISL29035_BOUT_MASK, 0);
+ status = regmap_clear_bits(chip->regmap,
+ ISL29035_REG_DEVICE_ID,
+ ISL29035_BOUT_MASK);
if (status < 0)
return status;
}
@@ -694,28 +688,25 @@ static const struct isl29018_chip_info isl29018_chip_info_tbl[] = {
},
};
-static const char *isl29018_match_acpi_device(struct device *dev, int *data)
+static void isl29018_disable_regulator_action(void *_data)
{
- const struct acpi_device_id *id;
-
- id = acpi_match_device(dev->driver->acpi_match_table, dev);
-
- if (!id)
- return NULL;
-
- *data = (int)id->driver_data;
+ struct isl29018_chip *chip = _data;
+ int err;
- return dev_name(dev);
+ err = regulator_disable(chip->vcc_reg);
+ if (err)
+ pr_err("failed to disable isl29018's VCC regulator!\n");
}
-static int isl29018_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int isl29018_probe(struct i2c_client *client)
{
+ const struct i2c_device_id *id = i2c_client_get_device_id(client);
struct isl29018_chip *chip;
struct iio_dev *indio_dev;
+ const void *ddata = NULL;
+ const char *name;
+ int dev_id;
int err;
- const char *name = NULL;
- int dev_id = 0;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip));
if (!indio_dev)
@@ -728,11 +719,11 @@ static int isl29018_probe(struct i2c_client *client,
if (id) {
name = id->name;
dev_id = id->driver_data;
+ } else {
+ name = iio_get_acpi_device_name_and_data(&client->dev, &ddata);
+ dev_id = (intptr_t)ddata;
}
- if (ACPI_HANDLE(&client->dev))
- name = isl29018_match_acpi_device(&client->dev, &dev_id);
-
mutex_init(&chip->lock);
chip->type = dev_id;
@@ -742,6 +733,24 @@ static int isl29018_probe(struct i2c_client *client,
chip->scale = isl29018_scales[chip->int_time][0];
chip->suspended = false;
+ chip->vcc_reg = devm_regulator_get(&client->dev, "vcc");
+ if (IS_ERR(chip->vcc_reg))
+ return dev_err_probe(&client->dev, PTR_ERR(chip->vcc_reg),
+ "failed to get VCC regulator!\n");
+
+ err = regulator_enable(chip->vcc_reg);
+ if (err) {
+ dev_err(&client->dev, "failed to enable VCC regulator!\n");
+ return err;
+ }
+
+ err = devm_add_action_or_reset(&client->dev, isl29018_disable_regulator_action,
+ chip);
+ if (err) {
+ dev_err(&client->dev, "failed to setup regulator cleanup action!\n");
+ return err;
+ }
+
chip->regmap = devm_regmap_init_i2c(client,
isl29018_chip_info_tbl[dev_id].regmap_cfg);
if (IS_ERR(chip->regmap)) {
@@ -758,16 +767,15 @@ static int isl29018_probe(struct i2c_client *client,
indio_dev->channels = isl29018_chip_info_tbl[dev_id].channels;
indio_dev->num_channels = isl29018_chip_info_tbl[dev_id].num_channels;
indio_dev->name = name;
- indio_dev->dev.parent = &client->dev;
indio_dev->modes = INDIO_DIRECT_MODE;
return devm_iio_device_register(&client->dev, indio_dev);
}
-#ifdef CONFIG_PM_SLEEP
static int isl29018_suspend(struct device *dev)
{
struct isl29018_chip *chip = iio_priv(dev_get_drvdata(dev));
+ int ret;
mutex_lock(&chip->lock);
@@ -777,10 +785,13 @@ static int isl29018_suspend(struct device *dev)
* So we do not have much to do here.
*/
chip->suspended = true;
+ ret = regulator_disable(chip->vcc_reg);
+ if (ret)
+ dev_err(dev, "failed to disable VCC regulator\n");
mutex_unlock(&chip->lock);
- return 0;
+ return ret;
}
static int isl29018_resume(struct device *dev)
@@ -790,6 +801,13 @@ static int isl29018_resume(struct device *dev)
mutex_lock(&chip->lock);
+ err = regulator_enable(chip->vcc_reg);
+ if (err) {
+ dev_err(dev, "failed to enable VCC regulator\n");
+ mutex_unlock(&chip->lock);
+ return err;
+ }
+
err = isl29018_chip_init(chip);
if (!err)
chip->suspended = false;
@@ -799,27 +817,22 @@ static int isl29018_resume(struct device *dev)
return err;
}
-static SIMPLE_DEV_PM_OPS(isl29018_pm_ops, isl29018_suspend, isl29018_resume);
-#define ISL29018_PM_OPS (&isl29018_pm_ops)
-#else
-#define ISL29018_PM_OPS NULL
-#endif
+static DEFINE_SIMPLE_DEV_PM_OPS(isl29018_pm_ops, isl29018_suspend,
+ isl29018_resume);
-#ifdef CONFIG_ACPI
static const struct acpi_device_id isl29018_acpi_match[] = {
{"ISL29018", isl29018},
{"ISL29023", isl29023},
{"ISL29035", isl29035},
- {},
+ { }
};
MODULE_DEVICE_TABLE(acpi, isl29018_acpi_match);
-#endif
static const struct i2c_device_id isl29018_id[] = {
{"isl29018", isl29018},
{"isl29023", isl29023},
{"isl29035", isl29035},
- {}
+ { }
};
MODULE_DEVICE_TABLE(i2c, isl29018_id);
@@ -827,18 +840,18 @@ static const struct of_device_id isl29018_of_match[] = {
{ .compatible = "isil,isl29018", },
{ .compatible = "isil,isl29023", },
{ .compatible = "isil,isl29035", },
- { },
+ { }
};
MODULE_DEVICE_TABLE(of, isl29018_of_match);
static struct i2c_driver isl29018_driver = {
.driver = {
.name = "isl29018",
- .acpi_match_table = ACPI_PTR(isl29018_acpi_match),
- .pm = ISL29018_PM_OPS,
+ .acpi_match_table = isl29018_acpi_match,
+ .pm = pm_sleep_ptr(&isl29018_pm_ops),
.of_match_table = isl29018_of_match,
},
- .probe = isl29018_probe,
+ .probe = isl29018_probe,
.id_table = isl29018_id,
};
module_i2c_driver(isl29018_driver);