Jetpack/kernel/nvidia/drivers/misc/nvs/nvs_vreg.c

143 lines
3.4 KiB
C

/* Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* 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/device.h>
#include <linux/regulator/consumer.h>
int nvs_vreg_dis(struct device *dev, struct regulator_bulk_data *vreg)
{
int ret = 0;
if (vreg->ret && (vreg->consumer != NULL)) {
ret = regulator_disable(vreg->consumer);
if (ret) {
dev_err(dev, "%s %s ERR\n", __func__, vreg->supply);
} else {
vreg->ret = 0;
dev_dbg(dev, "%s %s\n", __func__, vreg->supply);
}
}
return ret;
}
int nvs_vregs_disable(struct device *dev, struct regulator_bulk_data *vregs,
unsigned int vregs_n)
{
unsigned int i;
int ret = 0;
for (i = vregs_n; i > 0; i--)
ret |= nvs_vreg_dis(dev, &vregs[i - 1]);
return ret;
}
EXPORT_SYMBOL_GPL(nvs_vregs_disable);
int nvs_vreg_en(struct device *dev, struct regulator_bulk_data *vreg)
{
int ret = 0;
if (vreg->consumer != NULL && !vreg->ret) {
ret = regulator_enable(vreg->consumer);
if (ret) {
dev_err(dev, "%s %s ERR\n", __func__, vreg->supply);
} else {
vreg->ret = 1;
dev_dbg(dev, "%s %s\n", __func__, vreg->supply);
ret = 1; /* flag regulator state change */
}
}
return ret;
}
int nvs_vregs_enable(struct device *dev, struct regulator_bulk_data *vregs,
unsigned int vregs_n)
{
unsigned int i;
int ret = 0;
if (vregs_n) {
for (i = 0; i < vregs_n; i++)
ret |= nvs_vreg_en(dev, &vregs[i]);
}
return ret;
}
EXPORT_SYMBOL_GPL(nvs_vregs_enable);
void nvs_vregs_exit(struct device *dev, struct regulator_bulk_data *vregs,
unsigned int vregs_n)
{
unsigned int i;
for (i = 0; i < vregs_n; i++) {
if (vregs[i].consumer != NULL) {
devm_regulator_put(vregs[i].consumer);
vregs[i].consumer = NULL;
dev_dbg(dev, "%s %s\n", __func__, vregs[i].supply);
}
}
}
EXPORT_SYMBOL_GPL(nvs_vregs_exit);
int nvs_vregs_init(struct device *dev, struct regulator_bulk_data *vregs,
unsigned int vregs_n, char **vregs_name)
{
unsigned int i;
int ret = 0;
for (i = 0; i < vregs_n; i++) {
vregs[i].supply = vregs_name[i];
vregs[i].ret = 0;
vregs[i].consumer = devm_regulator_get(dev, vregs[i].supply);
if (IS_ERR(vregs[i].consumer)) {
ret |= PTR_ERR(vregs[i].consumer);
dev_err(dev, "%s %s err=%d\n",
__func__, vregs[i].supply, ret);
vregs[i].consumer = NULL;
} else {
dev_dbg(dev, "%s %s\n", __func__, vregs[i].supply);
}
}
return ret;
}
EXPORT_SYMBOL_GPL(nvs_vregs_init);
int nvs_vregs_sts(struct regulator_bulk_data *vregs, unsigned int vregs_n)
{
unsigned int i;
int ret = 0;
for (i = 0; i < vregs_n; i++) {
if (vregs[i].consumer != NULL)
break;
}
if (i < vregs_n) {
/* ret == number of regulators on */
for (i = 0; i < vregs_n; i++) {
if (vregs[i].ret)
ret++;
}
} else {
/* no regulator support (can assume always on) */
ret = -EINVAL;
}
return ret;
}
EXPORT_SYMBOL_GPL(nvs_vregs_sts);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("NVidia Sensor voltage regulator module");
MODULE_AUTHOR("NVIDIA Corporation");