// SPDX-License-Identifier: GPL-2.0-or-later
/*
* OF helpers for regulator framework
*
* Copyright (C) 2011 Texas Instruments, Inc.
* Rajendra Nayak <rnayak@ti.com>
*/
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/of_regulator.h>
#include "internal.h"
static const char *const regulator_states[PM_SUSPEND_MAX + 1] = {
[PM_SUSPEND_STANDBY] = "regulator-state-standby",
[PM_SUSPEND_MEM] = "regulator-state-mem",
[PM_SUSPEND_MAX] = "regulator-state-disk",
};
static void fill_limit(int *limit, int val)
{
if (val)
if (val == 1)
*limit = REGULATOR_NOTIF_LIMIT_ENABLE;
else
*limit = val;
else
*limit = REGULATOR_NOTIF_LIMIT_DISABLE;
}
static void of_get_regulator_prot_limits(struct device_node *np,
struct regulation_constraints *constraints)
{
u32 pval;
int i;
static const char *const props[] = {
"regulator-oc-%s-microamp",
"regulator-ov-%s-microvolt",
"regulator-temp-%s-kelvin",
"regulator-uv-%s-microvolt",
};
struct notification_limit *limits[] = {
&constraints->over_curr_limits,
&constraints->over_voltage_limits,
&constraints->temp_limits,
&constraints->under_voltage_limits,
};
bool set[4] = {0};
/* Protection limits: */
for (i = 0; i < ARRAY_SIZE(props); i++) {
char prop[255];
bool found;
int j;
static const char *const lvl[] = {
"protection", "error", "warn"
};
int *l[] = {
&limits[i]->prot, &limits[i]->err, &limits[i]->warn,
};
for (j = 0; j < ARRAY_SIZE(lvl); j++) {
snprintf(prop, 255, props[i], lvl[j]);
found = !of_property_read_u32(np, prop, &pval);
if (found)
fill_limit(l[j], pval);
set[i] |= found;
}
}
constraints->over_current_detection = set[0];
constraints->over_voltage_detection = set[1];
constraints->over_temp_detection = set[2];
constraints->under_voltage_detection = set[3];
}
static int of_get_regulation_constraints(struct device *dev,
struct device_node *np,
struct regulator_init_data *init_data,
const struct regulator_desc *desc)
{
struct regulation_constraints *constraints = &init_data->constraints;
struct regulator_state *suspend_state;
struct device_node *suspend_np;
unsigned int mode;
int ret, i, len;
int n_phandles;
u32 pval;
n_phandles = of_count_phandle_with_args(np, "regulator-coupled-with",
NULL);
n_phandles = max(n_phandles, 0);
constraints->name = of_get_property(np, "regulator-name", NULL);
if (!of_property_read_u32(np, "regulator-min-microvolt", &pval))
constraints->min_uV = pval;
if (!of_property_read_u32(np, "regulator-max-microvolt", &pval))
constraints->max_uV = pval;
/* Voltage change possible? */
if (constraints->min_uV != constraints->max_uV)
constraints->valid_ops_mask |= REGULATOR_CHANGE_VOLTAGE;
/* Do we have a voltage range, if so try to apply it? */
if (constraints->min_uV && constraints->max_uV)
constraints->apply_uV = true;
if (!of_property_read_u32(np, "regulator-microvolt-offset", &pval))
constraints->uV_offset = pval;
if (!of_property_read_u32(np, "regulator-min-microamp", &pval))
constraints->min_uA = pval;
if (!of_property_read_u32(np, "regulator-max-microamp", &pval))
constraints->max_uA = pval;
if (!of_property_read_u32(np, &q