diff --git a/arch/arm/soc/nxp_kinetis/Kconfig b/arch/arm/soc/nxp_kinetis/Kconfig index f74c8a5f477..1b9e101013b 100644 --- a/arch/arm/soc/nxp_kinetis/Kconfig +++ b/arch/arm/soc/nxp_kinetis/Kconfig @@ -64,6 +64,12 @@ config HAS_LPSCI help Set if the low power uart (LPSCI) module is present in the SoC. +config HAS_ADC16 + bool + default n + help + Set if the 16-bit ADC (ADC16) module is present in the SoC. + config HAS_SYSMPU bool "Enable MPU" depends on CPU_HAS_MPU diff --git a/drivers/adc/Kconfig b/drivers/adc/Kconfig index 4d790ecb7f6..32adbf3e394 100644 --- a/drivers/adc/Kconfig +++ b/drivers/adc/Kconfig @@ -303,4 +303,12 @@ endif endif # ADC_QMSI || ADC_QMSI_SS +config ADC_MCUX_ADC16 + bool "MCUX ADC16 driver" + depends on HAS_MCUX && HAS_ADC16 + select HAS_DTS_ADC + default n + help + Enable the MCUX ADC16 driver. + endif # ADC diff --git a/drivers/adc/Makefile b/drivers/adc/Makefile index 34a22585476..4d60bc9dd93 100644 --- a/drivers/adc/Makefile +++ b/drivers/adc/Makefile @@ -1,4 +1,5 @@ obj-$(CONFIG_ADC_DW) += adc_dw.o +obj-$(CONFIG_ADC_MCUX_ADC16) += adc_mcux_adc16.o obj-$(CONFIG_ADC_TI_ADC108S102) += adc_ti_adc108s102.o obj-$(CONFIG_ADC_QMSI) += adc_qmsi.o obj-$(CONFIG_ADC_QMSI_SS) += adc_qmsi_ss.o diff --git a/drivers/adc/adc_mcux_adc16.c b/drivers/adc/adc_mcux_adc16.c new file mode 100644 index 00000000000..c13cd2c6b63 --- /dev/null +++ b/drivers/adc/adc_mcux_adc16.c @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2017, NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +struct mcux_adc16_config { + ADC_Type *base; + void (*irq_config_func)(struct device *dev); +}; + +struct mcux_adc16_data { + struct k_sem sync; + u32_t channel_group; + u32_t result; +}; + +static void mcux_adc16_enable(struct device *dev) +{ + ARG_UNUSED(dev); +} + +static void mcux_adc16_disable(struct device *dev) +{ + ARG_UNUSED(dev); +} + +static int mcux_adc16_read(struct device *dev, struct adc_seq_table *seq_table) +{ + const struct mcux_adc16_config *config = dev->config->config_info; + struct mcux_adc16_data *data = dev->driver_data; + ADC_Type *base = config->base; + + struct adc_seq_entry *entry = seq_table->entries; + adc16_channel_config_t channel_config; + u32_t channel_group = 0; + int i; + + channel_config.enableInterruptOnConversionCompleted = true; +#if defined(FSL_FEATURE_ADC16_HAS_DIFF_MODE) && FSL_FEATURE_ADC16_HAS_DIFF_MODE + channel_config.enableDifferentialConversion = false; +#endif + + for (i = 0; i < seq_table->num_entries; i++) { + if (entry->buffer_length < sizeof(data->result)) { + return -EINVAL; + } + + channel_config.channelNumber = entry->channel_id; + ADC16_SetChannelConfig(base, channel_group, &channel_config); + + data->channel_group = channel_group; + + k_sem_take(&data->sync, K_FOREVER); + + memcpy(entry->buffer, &data->result, sizeof(data->result)); + + entry++; + } + + return 0; +} + +static void mcux_adc16_isr(void *arg) +{ + struct device *dev = (struct device *)arg; + const struct mcux_adc16_config *config = dev->config->config_info; + struct mcux_adc16_data *data = dev->driver_data; + ADC_Type *base = config->base; + u32_t channel_group = data->channel_group; + + data->result = ADC16_GetChannelConversionValue(base, channel_group); + + k_sem_give(&data->sync); +} + +static int mcux_adc16_init(struct device *dev) +{ + const struct mcux_adc16_config *config = dev->config->config_info; + struct mcux_adc16_data *data = dev->driver_data; + ADC_Type *base = config->base; + adc16_config_t adc_config; + + k_sem_init(&data->sync, 0, UINT_MAX); + + ADC16_GetDefaultConfig(&adc_config); + ADC16_Init(base, &adc_config); + + ADC16_EnableHardwareTrigger(base, false); + ADC16_SetHardwareAverage(base, kADC16_HardwareAverageCount4); + + config->irq_config_func(dev); + + return 0; +} + +static const struct adc_driver_api mcux_adc16_driver_api = { + .enable = mcux_adc16_enable, + .disable = mcux_adc16_disable, + .read = mcux_adc16_read, +}; + +#if CONFIG_ADC_0 +static void mcux_adc16_config_func_0(struct device *dev); + +static const struct mcux_adc16_config mcux_adc16_config_0 = { + .base = (ADC_Type *)CONFIG_ADC_0_BASE_ADDRESS, + .irq_config_func = mcux_adc16_config_func_0, +}; + +static struct mcux_adc16_data mcux_adc16_data_0; + +DEVICE_AND_API_INIT(mcux_adc16_0, CONFIG_ADC_0_NAME, &mcux_adc16_init, + &mcux_adc16_data_0, &mcux_adc16_config_0, + POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, + &mcux_adc16_driver_api); + +static void mcux_adc16_config_func_0(struct device *dev) +{ + IRQ_CONNECT(CONFIG_ADC_0_IRQ, CONFIG_ADC_0_IRQ_PRI, + mcux_adc16_isr, DEVICE_GET(mcux_adc16_0), 0); + + irq_enable(CONFIG_ADC_0_IRQ); +} +#endif /* CONFIG_ADC_0 */ + +#if CONFIG_ADC_1 +static void mcux_adc16_config_func_1(struct device *dev); + +static const struct mcux_adc16_config mcux_adc16_config_1 = { + .base = (ADC_Type *)CONFIG_ADC_1_BASE_ADDRESS, + .irq_config_func = mcux_adc16_config_func_1, +}; + +static struct mcux_adc16_data mcux_adc16_data_1; + +DEVICE_AND_API_INIT(mcux_adc16_1, CONFIG_ADC_1_NAME, &mcux_adc16_init, + &mcux_adc16_data_1, &mcux_adc16_config_1, + POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, + &mcux_adc16_driver_api); + +static void mcux_adc16_config_func_1(struct device *dev) +{ + IRQ_CONNECT(CONFIG_ADC_1_IRQ, CONFIG_ADC_1_IRQ_PRI, + mcux_adc16_isr, DEVICE_GET(mcux_adc16_1), 0); + + irq_enable(CONFIG_ADC_1_IRQ); +} +#endif /* CONFIG_ADC_1 */ diff --git a/ext/hal/nxp/mcux/drivers/Makefile b/ext/hal/nxp/mcux/drivers/Makefile index 305d76e4ebb..48ce5e7ea4c 100644 --- a/ext/hal/nxp/mcux/drivers/Makefile +++ b/ext/hal/nxp/mcux/drivers/Makefile @@ -4,6 +4,7 @@ # # SPDX-License-Identifier: Apache-2.0 +obj-$(CONFIG_ADC_MCUX_ADC16) += fsl_adc16.o obj-$(CONFIG_ETH_MCUX) += fsl_enet.o obj-$(CONFIG_I2C_MCUX) += fsl_i2c.o obj-$(CONFIG_RANDOM_MCUX_RNGA) += fsl_rnga.o