1
1
/*
2
- * Copyright 2023 NXP
2
+ * Copyright 2023-2024 NXP
3
3
* Copyright (c) 2020 Toby Firth
4
4
*
5
5
* Based on adc_mcux_adc16.c and adc_mcux_adc12.c, which are:
14
14
#include <errno.h>
15
15
#include <zephyr/drivers/adc.h>
16
16
#include <zephyr/sys/util.h>
17
- #include <fsl_lpadc.h>
18
17
#include <zephyr/drivers/regulator.h>
19
-
18
+ #include <zephyr/drivers/clock_control.h>
20
19
#include <zephyr/drivers/pinctrl.h>
21
20
22
21
#define LOG_LEVEL CONFIG_ADC_LOG_LEVEL
23
22
#include <zephyr/logging/log.h>
24
23
#include <zephyr/irq.h>
24
+ #include <fsl_lpadc.h>
25
25
LOG_MODULE_REGISTER (nxp_mcux_lpadc );
26
26
27
27
/*
@@ -35,7 +35,6 @@ LOG_MODULE_REGISTER(nxp_mcux_lpadc);
35
35
#define ADC_CONTEXT_USES_KERNEL_TIMER
36
36
#include "adc_context.h"
37
37
38
-
39
38
struct mcux_lpadc_config {
40
39
ADC_Type * base ;
41
40
lpadc_reference_voltage_source_t voltage_ref ;
@@ -46,6 +45,8 @@ struct mcux_lpadc_config {
46
45
void (* irq_config_func )(const struct device * dev );
47
46
const struct pinctrl_dev_config * pincfg ;
48
47
const struct device * * ref_supplies ;
48
+ const struct device * clock_dev ;
49
+ clock_control_subsys_t clock_subsys ;
49
50
};
50
51
51
52
struct mcux_lpadc_data {
@@ -57,13 +58,70 @@ struct mcux_lpadc_data {
57
58
lpadc_conv_command_config_t cmd_config [CONFIG_LPADC_CHANNEL_COUNT ];
58
59
};
59
60
61
+ static int mcux_lpadc_acquisition_time_setup (const struct device * dev , uint16_t acq_time ,
62
+ lpadc_conv_command_config_t * cmd )
63
+ {
64
+ const struct mcux_lpadc_config * config = dev -> config ;
65
+ uint32_t adc_freq_hz = 0 ;
66
+ uint32_t conversion_factor = 0 ;
67
+ uint32_t acquisition_time_value = ADC_ACQ_TIME_VALUE (acq_time );
68
+ uint8_t acquisition_time_unit = ADC_ACQ_TIME_UNIT (acq_time );
69
+
70
+ if (ADC_ACQ_TIME_DEFAULT == acquisition_time_value ) {
71
+ return 0 ;
72
+ }
73
+
74
+ /* If the acquisition time is expressed in ADC ticks, then directly compare
75
+ * the acquisition time with configuration items (3, 5, 7, etc. ADC ticks)
76
+ * supported by the LPADC. The conversion factor is set to 1 (means do not need
77
+ * to convert configuration items from ADC ticks to nanoseconds).
78
+ * If the acquisition time is expressed in microseconds or nanoseconds, First
79
+ * calculate the ADC cycle based on the ADC clock, then convert the configuration
80
+ * items supported by LPADC into nanoseconds, and finally compare the acquisition
81
+ * time with configuration items. The conversion factor is equal to the ADC cycle
82
+ * (means convert configuration items from ADC ticks to nanoseconds).
83
+ */
84
+ if (ADC_ACQ_TIME_TICKS == acquisition_time_unit ) {
85
+ conversion_factor = 1 ;
86
+ } else {
87
+ if (clock_control_get_rate (config -> clock_dev , config -> clock_subsys , & adc_freq_hz )) {
88
+ LOG_ERR ("Get clock rate failed" );
89
+ return - EINVAL ;
90
+ }
91
+
92
+ conversion_factor = 1000000000 / adc_freq_hz ;
93
+
94
+ if (ADC_ACQ_TIME_MICROSECONDS == acquisition_time_unit ) {
95
+ acquisition_time_value *= 1000 ;
96
+ }
97
+ }
98
+
99
+ if ((3 * conversion_factor ) >= acquisition_time_value ) {
100
+ cmd -> sampleTimeMode = kLPADC_SampleTimeADCK3 ;
101
+ } else if ((5 * conversion_factor ) >= acquisition_time_value ) {
102
+ cmd -> sampleTimeMode = kLPADC_SampleTimeADCK5 ;
103
+ } else if ((7 * conversion_factor ) >= acquisition_time_value ) {
104
+ cmd -> sampleTimeMode = kLPADC_SampleTimeADCK7 ;
105
+ } else if ((11 * conversion_factor ) >= acquisition_time_value ) {
106
+ cmd -> sampleTimeMode = kLPADC_SampleTimeADCK11 ;
107
+ } else if ((19 * conversion_factor ) >= acquisition_time_value ) {
108
+ cmd -> sampleTimeMode = kLPADC_SampleTimeADCK19 ;
109
+ } else if ((35 * conversion_factor ) >= acquisition_time_value ) {
110
+ cmd -> sampleTimeMode = kLPADC_SampleTimeADCK35 ;
111
+ } else if ((67 * conversion_factor ) >= acquisition_time_value ) {
112
+ cmd -> sampleTimeMode = kLPADC_SampleTimeADCK67 ;
113
+ } else if ((131 * conversion_factor ) >= acquisition_time_value ) {
114
+ cmd -> sampleTimeMode = kLPADC_SampleTimeADCK131 ;
115
+ } else {
116
+ return - EINVAL ;
117
+ }
60
118
119
+ return 0 ;
120
+ }
61
121
62
122
static int mcux_lpadc_channel_setup (const struct device * dev ,
63
123
const struct adc_channel_cfg * channel_cfg )
64
124
{
65
-
66
-
67
125
struct mcux_lpadc_data * data = dev -> data ;
68
126
lpadc_conv_command_config_t * cmd ;
69
127
uint8_t channel_side ;
@@ -75,11 +133,6 @@ static int mcux_lpadc_channel_setup(const struct device *dev,
75
133
return - EINVAL ;
76
134
}
77
135
78
- if (channel_cfg -> acquisition_time != ADC_ACQ_TIME_DEFAULT ) {
79
- LOG_ERR ("Invalid channel acquisition time" );
80
- return - EINVAL ;
81
- }
82
-
83
136
/* Select ADC CMD register to configure based off channel ID */
84
137
cmd = & data -> cmd_config [channel_cfg -> channel_id ];
85
138
@@ -93,6 +146,12 @@ static int mcux_lpadc_channel_setup(const struct device *dev,
93
146
94
147
LPADC_GetDefaultConvCommandConfig (cmd );
95
148
149
+ /* Configure LPADC acquisition time. */
150
+ if (mcux_lpadc_acquisition_time_setup (dev , channel_cfg -> acquisition_time , cmd )) {
151
+ LOG_ERR ("LPADC acquisition time setting failed" );
152
+ return - EINVAL ;
153
+ }
154
+
96
155
if (channel_cfg -> differential ) {
97
156
/* Channel pairs must match in differential mode */
98
157
if ((ADC_CMDL_ADCH (channel_cfg -> input_positive )) !=
@@ -493,6 +552,8 @@ static const struct adc_driver_api mcux_lpadc_driver_api = {
493
552
.irq_config_func = mcux_lpadc_config_func_##n, \
494
553
.pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \
495
554
.ref_supplies = mcux_lpadc_ref_supplies_##n, \
555
+ .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \
556
+ .clock_subsys = (clock_control_subsys_t)DT_INST_CLOCKS_CELL(n, name),\
496
557
}; \
497
558
static struct mcux_lpadc_data mcux_lpadc_data_##n = { \
498
559
ADC_CONTEXT_INIT_TIMER(mcux_lpadc_data_##n, ctx), \
0 commit comments