.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * A iio driver for the light sensor ISL 29018/29023/29035. |
---|
3 | 4 | * |
---|
.. | .. |
---|
5 | 6 | * sensing and infrared sensing. |
---|
6 | 7 | * |
---|
7 | 8 | * Copyright (c) 2010, NVIDIA Corporation. |
---|
8 | | - * |
---|
9 | | - * This program is free software; you can redistribute it and/or modify |
---|
10 | | - * it under the terms of the GNU General Public License as published by |
---|
11 | | - * the Free Software Foundation; either version 2 of the License, or |
---|
12 | | - * (at your option) any later version. |
---|
13 | | - * |
---|
14 | | - * This program is distributed in the hope that it will be useful, but WITHOUT |
---|
15 | | - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
---|
16 | | - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
---|
17 | | - * more details. |
---|
18 | 9 | */ |
---|
19 | 10 | |
---|
20 | 11 | #include <linux/module.h> |
---|
.. | .. |
---|
23 | 14 | #include <linux/mutex.h> |
---|
24 | 15 | #include <linux/delay.h> |
---|
25 | 16 | #include <linux/regmap.h> |
---|
| 17 | +#include <linux/regulator/consumer.h> |
---|
26 | 18 | #include <linux/slab.h> |
---|
27 | 19 | #include <linux/iio/iio.h> |
---|
28 | 20 | #include <linux/iio/sysfs.h> |
---|
.. | .. |
---|
95 | 87 | struct isl29018_scale scale; |
---|
96 | 88 | int prox_scheme; |
---|
97 | 89 | bool suspended; |
---|
| 90 | + struct regulator *vcc_reg; |
---|
98 | 91 | }; |
---|
99 | 92 | |
---|
100 | 93 | static int isl29018_set_integration_time(struct isl29018_chip *chip, |
---|
.. | .. |
---|
708 | 701 | return dev_name(dev); |
---|
709 | 702 | } |
---|
710 | 703 | |
---|
| 704 | +static void isl29018_disable_regulator_action(void *_data) |
---|
| 705 | +{ |
---|
| 706 | + struct isl29018_chip *chip = _data; |
---|
| 707 | + int err; |
---|
| 708 | + |
---|
| 709 | + err = regulator_disable(chip->vcc_reg); |
---|
| 710 | + if (err) |
---|
| 711 | + pr_err("failed to disable isl29018's VCC regulator!\n"); |
---|
| 712 | +} |
---|
| 713 | + |
---|
711 | 714 | static int isl29018_probe(struct i2c_client *client, |
---|
712 | 715 | const struct i2c_device_id *id) |
---|
713 | 716 | { |
---|
.. | .. |
---|
742 | 745 | chip->scale = isl29018_scales[chip->int_time][0]; |
---|
743 | 746 | chip->suspended = false; |
---|
744 | 747 | |
---|
| 748 | + chip->vcc_reg = devm_regulator_get(&client->dev, "vcc"); |
---|
| 749 | + if (IS_ERR(chip->vcc_reg)) |
---|
| 750 | + return dev_err_probe(&client->dev, PTR_ERR(chip->vcc_reg), |
---|
| 751 | + "failed to get VCC regulator!\n"); |
---|
| 752 | + |
---|
| 753 | + err = regulator_enable(chip->vcc_reg); |
---|
| 754 | + if (err) { |
---|
| 755 | + dev_err(&client->dev, "failed to enable VCC regulator!\n"); |
---|
| 756 | + return err; |
---|
| 757 | + } |
---|
| 758 | + |
---|
| 759 | + err = devm_add_action_or_reset(&client->dev, isl29018_disable_regulator_action, |
---|
| 760 | + chip); |
---|
| 761 | + if (err) { |
---|
| 762 | + dev_err(&client->dev, "failed to setup regulator cleanup action!\n"); |
---|
| 763 | + return err; |
---|
| 764 | + } |
---|
| 765 | + |
---|
745 | 766 | chip->regmap = devm_regmap_init_i2c(client, |
---|
746 | 767 | isl29018_chip_info_tbl[dev_id].regmap_cfg); |
---|
747 | 768 | if (IS_ERR(chip->regmap)) { |
---|
.. | .. |
---|
758 | 779 | indio_dev->channels = isl29018_chip_info_tbl[dev_id].channels; |
---|
759 | 780 | indio_dev->num_channels = isl29018_chip_info_tbl[dev_id].num_channels; |
---|
760 | 781 | indio_dev->name = name; |
---|
761 | | - indio_dev->dev.parent = &client->dev; |
---|
762 | 782 | indio_dev->modes = INDIO_DIRECT_MODE; |
---|
763 | 783 | |
---|
764 | 784 | return devm_iio_device_register(&client->dev, indio_dev); |
---|
.. | .. |
---|
768 | 788 | static int isl29018_suspend(struct device *dev) |
---|
769 | 789 | { |
---|
770 | 790 | struct isl29018_chip *chip = iio_priv(dev_get_drvdata(dev)); |
---|
| 791 | + int ret; |
---|
771 | 792 | |
---|
772 | 793 | mutex_lock(&chip->lock); |
---|
773 | 794 | |
---|
.. | .. |
---|
777 | 798 | * So we do not have much to do here. |
---|
778 | 799 | */ |
---|
779 | 800 | chip->suspended = true; |
---|
| 801 | + ret = regulator_disable(chip->vcc_reg); |
---|
| 802 | + if (ret) |
---|
| 803 | + dev_err(dev, "failed to disable VCC regulator\n"); |
---|
780 | 804 | |
---|
781 | 805 | mutex_unlock(&chip->lock); |
---|
782 | 806 | |
---|
783 | | - return 0; |
---|
| 807 | + return ret; |
---|
784 | 808 | } |
---|
785 | 809 | |
---|
786 | 810 | static int isl29018_resume(struct device *dev) |
---|
.. | .. |
---|
790 | 814 | |
---|
791 | 815 | mutex_lock(&chip->lock); |
---|
792 | 816 | |
---|
| 817 | + err = regulator_enable(chip->vcc_reg); |
---|
| 818 | + if (err) { |
---|
| 819 | + dev_err(dev, "failed to enable VCC regulator\n"); |
---|
| 820 | + mutex_unlock(&chip->lock); |
---|
| 821 | + return err; |
---|
| 822 | + } |
---|
| 823 | + |
---|
793 | 824 | err = isl29018_chip_init(chip); |
---|
794 | 825 | if (!err) |
---|
795 | 826 | chip->suspended = false; |
---|