drivers: lpadc/adc_mcux_lpadc/: enable nxp lpadc acquisition time feature

Enable nxp lpadc driver acquisition time feature

Signed-off-by: Zhaoxiang Jin <Zhaoxiang.Jin_1@nxp.com>
This commit is contained in:
Zhaoxiang Jin 2024-03-21 10:14:34 +08:00 committed by Alberto Escolar
commit fefb472700

View file

@ -1,5 +1,5 @@
/*
* Copyright 2023 NXP
* Copyright 2023-2024 NXP
* Copyright (c) 2020 Toby Firth
*
* Based on adc_mcux_adc16.c and adc_mcux_adc12.c, which are:
@ -14,14 +14,14 @@
#include <errno.h>
#include <zephyr/drivers/adc.h>
#include <zephyr/sys/util.h>
#include <fsl_lpadc.h>
#include <zephyr/drivers/regulator.h>
#include <zephyr/drivers/clock_control.h>
#include <zephyr/drivers/pinctrl.h>
#define LOG_LEVEL CONFIG_ADC_LOG_LEVEL
#include <zephyr/logging/log.h>
#include <zephyr/irq.h>
#include <fsl_lpadc.h>
LOG_MODULE_REGISTER(nxp_mcux_lpadc);
/*
@ -35,7 +35,6 @@ LOG_MODULE_REGISTER(nxp_mcux_lpadc);
#define ADC_CONTEXT_USES_KERNEL_TIMER
#include "adc_context.h"
struct mcux_lpadc_config {
ADC_Type *base;
lpadc_reference_voltage_source_t voltage_ref;
@ -46,6 +45,8 @@ struct mcux_lpadc_config {
void (*irq_config_func)(const struct device *dev);
const struct pinctrl_dev_config *pincfg;
const struct device **ref_supplies;
const struct device *clock_dev;
clock_control_subsys_t clock_subsys;
};
struct mcux_lpadc_data {
@ -57,13 +58,70 @@ struct mcux_lpadc_data {
lpadc_conv_command_config_t cmd_config[CONFIG_LPADC_CHANNEL_COUNT];
};
static int mcux_lpadc_acquisition_time_setup(const struct device *dev, uint16_t acq_time,
lpadc_conv_command_config_t *cmd)
{
const struct mcux_lpadc_config *config = dev->config;
uint32_t adc_freq_hz = 0;
uint32_t conversion_factor = 0;
uint32_t acquisition_time_value = ADC_ACQ_TIME_VALUE(acq_time);
uint8_t acquisition_time_unit = ADC_ACQ_TIME_UNIT(acq_time);
if (ADC_ACQ_TIME_DEFAULT == acquisition_time_value) {
return 0;
}
/* If the acquisition time is expressed in ADC ticks, then directly compare
* the acquisition time with configuration items (3, 5, 7, etc. ADC ticks)
* supported by the LPADC. The conversion factor is set to 1 (means do not need
* to convert configuration items from ADC ticks to nanoseconds).
* If the acquisition time is expressed in microseconds or nanoseconds, First
* calculate the ADC cycle based on the ADC clock, then convert the configuration
* items supported by LPADC into nanoseconds, and finally compare the acquisition
* time with configuration items. The conversion factor is equal to the ADC cycle
* (means convert configuration items from ADC ticks to nanoseconds).
*/
if (ADC_ACQ_TIME_TICKS == acquisition_time_unit) {
conversion_factor = 1;
} else {
if (clock_control_get_rate(config->clock_dev, config->clock_subsys, &adc_freq_hz)) {
LOG_ERR("Get clock rate failed");
return -EINVAL;
}
conversion_factor = 1000000000 / adc_freq_hz;
if (ADC_ACQ_TIME_MICROSECONDS == acquisition_time_unit) {
acquisition_time_value *= 1000;
}
}
if ((3 * conversion_factor) >= acquisition_time_value) {
cmd->sampleTimeMode = kLPADC_SampleTimeADCK3;
} else if ((5 * conversion_factor) >= acquisition_time_value) {
cmd->sampleTimeMode = kLPADC_SampleTimeADCK5;
} else if ((7 * conversion_factor) >= acquisition_time_value) {
cmd->sampleTimeMode = kLPADC_SampleTimeADCK7;
} else if ((11 * conversion_factor) >= acquisition_time_value) {
cmd->sampleTimeMode = kLPADC_SampleTimeADCK11;
} else if ((19 * conversion_factor) >= acquisition_time_value) {
cmd->sampleTimeMode = kLPADC_SampleTimeADCK19;
} else if ((35 * conversion_factor) >= acquisition_time_value) {
cmd->sampleTimeMode = kLPADC_SampleTimeADCK35;
} else if ((67 * conversion_factor) >= acquisition_time_value) {
cmd->sampleTimeMode = kLPADC_SampleTimeADCK67;
} else if ((131 * conversion_factor) >= acquisition_time_value) {
cmd->sampleTimeMode = kLPADC_SampleTimeADCK131;
} else {
return -EINVAL;
}
return 0;
}
static int mcux_lpadc_channel_setup(const struct device *dev,
const struct adc_channel_cfg *channel_cfg)
{
struct mcux_lpadc_data *data = dev->data;
lpadc_conv_command_config_t *cmd;
uint8_t channel_side;
@ -75,11 +133,6 @@ static int mcux_lpadc_channel_setup(const struct device *dev,
return -EINVAL;
}
if (channel_cfg->acquisition_time != ADC_ACQ_TIME_DEFAULT) {
LOG_ERR("Invalid channel acquisition time");
return -EINVAL;
}
/* Select ADC CMD register to configure based off channel ID */
cmd = &data->cmd_config[channel_cfg->channel_id];
@ -93,6 +146,12 @@ static int mcux_lpadc_channel_setup(const struct device *dev,
LPADC_GetDefaultConvCommandConfig(cmd);
/* Configure LPADC acquisition time. */
if (mcux_lpadc_acquisition_time_setup(dev, channel_cfg->acquisition_time, cmd)) {
LOG_ERR("LPADC acquisition time setting failed");
return -EINVAL;
}
if (channel_cfg->differential) {
/* Channel pairs must match in differential mode */
if ((ADC_CMDL_ADCH(channel_cfg->input_positive)) !=
@ -493,6 +552,8 @@ static const struct adc_driver_api mcux_lpadc_driver_api = {
.irq_config_func = mcux_lpadc_config_func_##n, \
.pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \
.ref_supplies = mcux_lpadc_ref_supplies_##n, \
.clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \
.clock_subsys = (clock_control_subsys_t)DT_INST_CLOCKS_CELL(n, name),\
}; \
static struct mcux_lpadc_data mcux_lpadc_data_##n = { \
ADC_CONTEXT_INIT_TIMER(mcux_lpadc_data_##n, ctx), \