zephyr/drivers/regulator/regulator_fixed.c
Gerard Marull-Paretas a29bdc262c drivers: regulator: drop async enable
Drop the async enable function. This feature is rarely/never used,
complicates driver design, and doesn't really follow the sync/async API
design/naming used in other areas. In the future we can introduce
regulator_enable_async if needed, with support from the driver class (no
onoff). Note that drivers like PCA9420 did not implement any
asynchronous behavior. regulator-fixed implemented in the past
asynchronous behavior using work queues, an overkill for most GPIO
driven regulators. Let's keep things simple for now and extend the API
when needed, based on specific usecases.

In the current implementation, reference counting is managed by the
driver class. \isr-ok attribute is dropped, since calls are potentially
blocking. Note that drivers like PCA9420 already violated such rule.

Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
2022-11-30 15:49:30 +01:00

119 lines
3.2 KiB
C

/*
* Copyright 2019-2020 Peter Bigot Consulting, LLC
* Copyright 2022 Nordic Semiconductor ASA
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT regulator_fixed
#include <stdint.h>
#include <zephyr/kernel.h>
#include <zephyr/drivers/regulator.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(regulator_fixed, CONFIG_REGULATOR_LOG_LEVEL);
#define OPTION_ALWAYS_ON_POS 0
#define OPTION_ALWAYS_ON BIT(OPTION_ALWAYS_ON_POS)
#define OPTION_BOOT_ON_POS 1
#define OPTION_BOOT_ON BIT(OPTION_BOOT_ON_POS)
struct regulator_fixed_config {
uint32_t startup_delay_us;
uint32_t off_on_delay_us;
struct gpio_dt_spec enable;
uint8_t options;
};
struct regulator_fixed_data {
struct regulator_common_data common;
};
static int regulator_fixed_enable(const struct device *dev)
{
const struct regulator_fixed_config *cfg = dev->config;
int ret;
if ((cfg->options & OPTION_ALWAYS_ON) != 0) {
return 0;
}
ret = gpio_pin_set_dt(&cfg->enable, 1);
if (ret < 0) {
return ret;
}
if (cfg->off_on_delay_us > 0U) {
k_sleep(K_USEC(cfg->off_on_delay_us));
}
return 0;
}
static int regulator_fixed_disable(const struct device *dev)
{
const struct regulator_fixed_config *cfg = dev->config;
if ((cfg->options & OPTION_ALWAYS_ON) != 0) {
return 0;
}
return gpio_pin_set_dt(&cfg->enable, 0);
}
static const struct regulator_driver_api regulator_fixed_api = {
.enable = regulator_fixed_enable,
.disable = regulator_fixed_disable,
};
static int regulator_fixed_init(const struct device *dev)
{
const struct regulator_fixed_config *cfg = dev->config;
int ret;
regulator_common_data_init(dev);
if (!device_is_ready(cfg->enable.port)) {
LOG_ERR("GPIO port: %s not ready", cfg->enable.port->name);
return -ENODEV;
}
if ((cfg->options & (OPTION_ALWAYS_ON | OPTION_BOOT_ON)) != 0U) {
ret = gpio_pin_configure_dt(&cfg->enable, GPIO_OUTPUT_ACTIVE);
if (ret < 0) {
return ret;
}
k_busy_wait(cfg->startup_delay_us);
} else {
ret = gpio_pin_configure_dt(&cfg->enable, GPIO_OUTPUT_INACTIVE);
if (ret < 0) {
return ret;
}
}
return 0;
}
#define REGULATOR_FIXED_DEFINE(inst) \
static struct regulator_fixed_data data##inst; \
\
static const struct regulator_fixed_config config##inst = { \
.startup_delay_us = DT_INST_PROP(inst, startup_delay_us), \
.off_on_delay_us = DT_INST_PROP(inst, off_on_delay_us), \
.enable = GPIO_DT_SPEC_INST_GET(inst, enable_gpios), \
.options = (DT_INST_PROP(inst, regulator_boot_on) \
<< OPTION_BOOT_ON_POS) | \
(DT_INST_PROP(inst, regulator_always_on) \
<< OPTION_ALWAYS_ON_POS), \
}; \
\
DEVICE_DT_INST_DEFINE(inst, regulator_fixed_init, NULL, &data##inst, \
&config##inst, POST_KERNEL, \
CONFIG_REGULATOR_FIXED_INIT_PRIORITY, \
&regulator_fixed_api);
DT_INST_FOREACH_STATUS_OKAY(REGULATOR_FIXED_DEFINE)