drivers: regulator: Add NXP VREF driver
Add binding, include header, and driver for NXP VREF IP block. NXP VREF is an internal voltage reference generator on some SOCs that fits well with the regulator API in zephyr. Signed-off-by: Declan Snyder <declan.snyder@nxp.com>
This commit is contained in:
parent
4a556a925c
commit
b1d2a8a9b6
|
@ -15,3 +15,4 @@ zephyr_library_sources_ifdef(CONFIG_REGULATOR_NPM6001 regulator_npm6001.c)
|
|||
zephyr_library_sources_ifdef(CONFIG_REGULATOR_PCA9420 regulator_pca9420.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_REGULATOR_SHELL regulator_shell.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_REGULATOR_RPI_PICO regulator_rpi_pico.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_REGULATOR_NXP_VREF regulator_nxp_vref.c)
|
||||
|
|
|
@ -37,5 +37,6 @@ source "drivers/regulator/Kconfig.npm1300"
|
|||
source "drivers/regulator/Kconfig.npm6001"
|
||||
source "drivers/regulator/Kconfig.pca9420"
|
||||
source "drivers/regulator/Kconfig.rpi_pico"
|
||||
source "drivers/regulator/Kconfig.nxp_vref"
|
||||
|
||||
endif # REGULATOR
|
||||
|
|
14
drivers/regulator/Kconfig.nxp_vref
Normal file
14
drivers/regulator/Kconfig.nxp_vref
Normal file
|
@ -0,0 +1,14 @@
|
|||
# Copyright 2023 NXP
|
||||
# SPDX -License-Identifier: Apache-2.0
|
||||
|
||||
config REGULATOR_NXP_VREF
|
||||
bool "NXP VREF peripheral driver"
|
||||
default y if DT_HAS_NXP_VREF_ENABLED
|
||||
help
|
||||
Enable the NXP VREF driver
|
||||
|
||||
config REGULATOR_NXP_VREF_INIT_PRIORITY
|
||||
int "NXP VREF peripheral driver init priority"
|
||||
default 45
|
||||
help
|
||||
Init priority for the NXP VREF peripheral.
|
221
drivers/regulator/regulator_nxp_vref.c
Normal file
221
drivers/regulator/regulator_nxp_vref.c
Normal file
|
@ -0,0 +1,221 @@
|
|||
/*
|
||||
* Copyright 2023 NXP
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT nxp_vref
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <zephyr/drivers/regulator.h>
|
||||
#include <zephyr/dt-bindings/regulator/nxp_vref.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/sys/linear_range.h>
|
||||
#include <zephyr/sys/util.h>
|
||||
|
||||
#include <fsl_device_registers.h>
|
||||
|
||||
static const struct linear_range utrim_range = LINEAR_RANGE_INIT(1000000, 100000U, 0x0U, 0xBU);
|
||||
|
||||
struct regulator_nxp_vref_data {
|
||||
struct regulator_common_data common;
|
||||
};
|
||||
|
||||
struct regulator_nxp_vref_config {
|
||||
struct regulator_common_config common;
|
||||
VREF_Type *base;
|
||||
uint8_t gnd_sel;
|
||||
uint16_t buf_start_delay;
|
||||
uint16_t bg_start_time;
|
||||
};
|
||||
|
||||
static int regulator_nxp_vref_enable(const struct device *dev)
|
||||
{
|
||||
const struct regulator_nxp_vref_config *config = dev->config;
|
||||
VREF_Type *const base = config->base;
|
||||
|
||||
volatile uint32_t *const csr = &base->CSR;
|
||||
|
||||
*csr |= VREF_CSR_LPBGEN_MASK | VREF_CSR_LPBG_BUF_EN_MASK;
|
||||
/* Wait for bandgap startup */
|
||||
k_busy_wait(config->bg_start_time);
|
||||
|
||||
/* Enable high accuracy bandgap */
|
||||
*csr |= VREF_CSR_HCBGEN_MASK;
|
||||
|
||||
/* Monitor until stable */
|
||||
while (!(*csr & VREF_CSR_VREFST_MASK))
|
||||
;
|
||||
|
||||
/* Enable output buffer */
|
||||
*csr |= VREF_CSR_BUF21EN_MASK;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int regulator_nxp_vref_disable(const struct device *dev)
|
||||
{
|
||||
const struct regulator_nxp_vref_config *config = dev->config;
|
||||
VREF_Type *const base = config->base;
|
||||
|
||||
/*
|
||||
* Disable HC Bandgap, LP Bandgap, and Buf21
|
||||
* to achieve "Off" mode of VREF
|
||||
*/
|
||||
base->CSR &= ~(VREF_CSR_BUF21EN_MASK | VREF_CSR_HCBGEN_MASK | VREF_CSR_LPBGEN_MASK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int regulator_nxp_vref_set_mode(const struct device *dev, regulator_mode_t mode)
|
||||
{
|
||||
const struct regulator_nxp_vref_config *config = dev->config;
|
||||
VREF_Type *const base = config->base;
|
||||
uint32_t csr = base->CSR;
|
||||
|
||||
if (mode == NXP_VREF_MODE_STANDBY) {
|
||||
csr &= ~VREF_CSR_REGEN_MASK &
|
||||
~VREF_CSR_CHOPEN_MASK &
|
||||
~VREF_CSR_HI_PWR_LV_MASK &
|
||||
~VREF_CSR_BUF21EN_MASK;
|
||||
} else if (mode == NXP_VREF_MODE_LOW_POWER) {
|
||||
csr &= ~VREF_CSR_REGEN_MASK &
|
||||
~VREF_CSR_CHOPEN_MASK &
|
||||
~VREF_CSR_HI_PWR_LV_MASK;
|
||||
csr |= VREF_CSR_BUF21EN_MASK;
|
||||
} else if (mode == NXP_VREF_MODE_HIGH_POWER) {
|
||||
csr &= ~VREF_CSR_REGEN_MASK &
|
||||
~VREF_CSR_CHOPEN_MASK;
|
||||
csr |= VREF_CSR_HI_PWR_LV_MASK &
|
||||
VREF_CSR_BUF21EN_MASK;
|
||||
} else if (mode == NXP_VREF_MODE_INTERNAL_REGULATOR) {
|
||||
csr |= VREF_CSR_REGEN_MASK &
|
||||
VREF_CSR_CHOPEN_MASK &
|
||||
VREF_CSR_HI_PWR_LV_MASK &
|
||||
VREF_CSR_BUF21EN_MASK;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
base->CSR = csr;
|
||||
|
||||
k_busy_wait(config->buf_start_delay);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int regulator_nxp_vref_get_mode(const struct device *dev, regulator_mode_t *mode)
|
||||
{
|
||||
const struct regulator_nxp_vref_config *config = dev->config;
|
||||
VREF_Type *const base = config->base;
|
||||
uint32_t csr = base->CSR;
|
||||
|
||||
/* Check bits to determine mode */
|
||||
if (csr & VREF_CSR_REGEN_MASK) {
|
||||
*mode = NXP_VREF_MODE_INTERNAL_REGULATOR;
|
||||
} else if (csr & VREF_CSR_HI_PWR_LV_MASK) {
|
||||
*mode = NXP_VREF_MODE_HIGH_POWER;
|
||||
} else if (csr & VREF_CSR_BUF21EN_MASK) {
|
||||
*mode = NXP_VREF_MODE_LOW_POWER;
|
||||
} else {
|
||||
*mode = NXP_VREF_MODE_STANDBY;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline unsigned int regulator_nxp_vref_count_voltages(const struct device *dev)
|
||||
{
|
||||
return linear_range_values_count(&utrim_range);
|
||||
}
|
||||
|
||||
static int regulator_nxp_vref_list_voltage(const struct device *dev,
|
||||
unsigned int idx, int32_t *volt_uv)
|
||||
{
|
||||
return linear_range_get_value(&utrim_range, idx, volt_uv);
|
||||
}
|
||||
|
||||
static int regulator_nxp_vref_set_voltage(const struct device *dev,
|
||||
int32_t min_uv, int32_t max_uv)
|
||||
{
|
||||
const struct regulator_nxp_vref_config *config = dev->config;
|
||||
VREF_Type *const base = config->base;
|
||||
uint16_t idx;
|
||||
int ret;
|
||||
|
||||
ret = linear_range_get_win_index(&utrim_range, min_uv, max_uv, &idx);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
base->UTRIM &= ~VREF_UTRIM_TRIM2V1_MASK;
|
||||
base->UTRIM |= VREF_UTRIM_TRIM2V1_MASK & idx;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int regulator_nxp_vref_get_voltage(const struct device *dev,
|
||||
int32_t *volt_uv)
|
||||
{
|
||||
const struct regulator_nxp_vref_config *config = dev->config;
|
||||
VREF_Type *const base = config->base;
|
||||
uint16_t idx;
|
||||
int ret;
|
||||
|
||||
/* Linear range index is the register value */
|
||||
idx = (base->UTRIM & VREF_UTRIM_TRIM2V1_MASK) >> VREF_UTRIM_TRIM2V1_SHIFT;
|
||||
|
||||
ret = linear_range_get_value(&utrim_range, base->UTRIM, volt_uv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct regulator_driver_api api = {
|
||||
.enable = regulator_nxp_vref_enable,
|
||||
.disable = regulator_nxp_vref_disable,
|
||||
.set_mode = regulator_nxp_vref_set_mode,
|
||||
.get_mode = regulator_nxp_vref_get_mode,
|
||||
.set_voltage = regulator_nxp_vref_set_voltage,
|
||||
.get_voltage = regulator_nxp_vref_get_voltage,
|
||||
.list_voltage = regulator_nxp_vref_list_voltage,
|
||||
.count_voltages = regulator_nxp_vref_count_voltages,
|
||||
};
|
||||
|
||||
static int regulator_nxp_vref_init(const struct device *dev)
|
||||
{
|
||||
const struct regulator_nxp_vref_config *config = dev->config;
|
||||
VREF_Type *base = config->base;
|
||||
int ret;
|
||||
|
||||
regulator_common_data_init(dev);
|
||||
|
||||
/* Select ground */
|
||||
base->CSR &= ~VREF_CSR_REFL_GRD_SEL_MASK;
|
||||
base->CSR |= config->gnd_sel;
|
||||
|
||||
ret = regulator_nxp_vref_disable(dev);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return regulator_common_init(dev, false);
|
||||
}
|
||||
|
||||
#define REGULATOR_NXP_VREF_DEFINE(inst) \
|
||||
static struct regulator_nxp_vref_data data_##inst; \
|
||||
\
|
||||
static const struct regulator_nxp_vref_config config_##inst = { \
|
||||
.common = REGULATOR_DT_INST_COMMON_CONFIG_INIT(inst), \
|
||||
.base = (VREF_Type *) DT_INST_REG_ADDR(inst), \
|
||||
.gnd_sel = DT_INST_ENUM_IDX_OR(inst, nxp_ground_select, 0), \
|
||||
.buf_start_delay = DT_INST_PROP(inst, \
|
||||
nxp_buffer_startup_delay_us), \
|
||||
.bg_start_time = DT_INST_PROP(inst, \
|
||||
nxp_bandgap_startup_time_us), \
|
||||
}; \
|
||||
\
|
||||
DEVICE_DT_INST_DEFINE(inst, regulator_nxp_vref_init, NULL, &data_##inst,\
|
||||
&config_##inst, POST_KERNEL, \
|
||||
CONFIG_REGULATOR_NXP_VREF_INIT_PRIORITY, &api); \
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(REGULATOR_NXP_VREF_DEFINE)
|
41
dts/bindings/regulator/nxp,vref.yaml
Normal file
41
dts/bindings/regulator/nxp,vref.yaml
Normal file
|
@ -0,0 +1,41 @@
|
|||
# Copyright 2023 NXP
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: NXP VREF SOC peripheral
|
||||
|
||||
compatible: "nxp,vref"
|
||||
|
||||
include:
|
||||
- name: base.yaml
|
||||
- name: regulator.yaml
|
||||
property-allowlist:
|
||||
- regulator-name
|
||||
- regulator-init-microvolt
|
||||
- regulator-min-microvolt
|
||||
- regulator-max-microvolt
|
||||
- regulator-initial-mode
|
||||
- regulator-allowed-modes
|
||||
|
||||
properties:
|
||||
reg:
|
||||
required: true
|
||||
|
||||
nxp,ground-select:
|
||||
type: string
|
||||
enum:
|
||||
- "VREFL3V" # 0
|
||||
- "VSSA" # 1
|
||||
|
||||
nxp,buffer-startup-delay-us:
|
||||
type: int
|
||||
required: true
|
||||
description: |
|
||||
Buffer startup delay as specified in the
|
||||
appropriate device data sheet, in microseconds.
|
||||
|
||||
nxp,bandgap-startup-time-us:
|
||||
type: int
|
||||
required: true
|
||||
description: |
|
||||
Maximum bandgap startup time as specified in the
|
||||
appropriate device data sheet, in microseconds.
|
29
include/zephyr/dt-bindings/regulator/nxp_vref.h
Normal file
29
include/zephyr/dt-bindings/regulator/nxp_vref.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright 2023 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_REGULATOR_NXP_VREF_H
|
||||
#define ZEPHYR_INCLUDE_DT_BINDINGS_REGULATOR_NXP_VREF_H
|
||||
|
||||
/**
|
||||
* @defgroup regulator_nxp_vref Devicetree helpers
|
||||
* @ingroup regulator_interface
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @name NXP VREF Regulator API Modes
|
||||
* @{
|
||||
*/
|
||||
#define NXP_VREF_MODE_STANDBY 0
|
||||
#define NXP_VREF_MODE_LOW_POWER 1
|
||||
#define NXP_VREF_MODE_HIGH_POWER 2
|
||||
#define NXP_VREF_MODE_INTERNAL_REGULATOR 3
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_REGULATOR_NXP_VREF_H */
|
Loading…
Reference in a new issue