diff --git a/arch/risc-v/src/hpmicro/hpm6750/Kconfig b/arch/risc-v/src/hpmicro/hpm6750/Kconfig index 6dc2244bd17c5..a94070c3f4cce 100644 --- a/arch/risc-v/src/hpmicro/hpm6750/Kconfig +++ b/arch/risc-v/src/hpmicro/hpm6750/Kconfig @@ -883,8 +883,415 @@ config HPM6750_TIMER7 default n select HPM_GPTMR_DRV + +config HPM_ADC12_DRV + bool + default n + +config HPM_ADC16_DRV + bool + default n + +config HPM_ADC0 + bool "ADC0" + default n + select HPM_ADC12_DRV + + menu "ADC0 device driver options" + depends on HPM_ADC0 + + # Channel Value Setting + config HPM_ADC0_CH + int + default 7 + depends on HPM6750EVK_ADC0_CH7 + + config HPM_ADC0_CH + int + default 10 + depends on HPM6750EVK_ADC0_CH10 + + config HPM_ADC0_CH + int + default 11 + depends on HPM6750EVK_ADC0_CH11 + # End Of Channel Value Setting + + # Channel Setting + choice + prompt "ADC0 Channel" + default HPM6750EVK_ADC0_CH11 + + config HPM6750EVK_ADC0_CH7 + bool "CH7" + + config HPM6750EVK_ADC0_CH10 + bool "CH10" + + config HPM6750EVK_ADC0_CH11 + bool "CH11" + endchoice + # End Of Chanenl Setting + + # Conversion Mode Setting + config HPM_ADC0_CONV_MODE + int "ADC0 Conversion Mode" + range 0 3 + default 0 + comment "0: oneshot mode" + comment "1: period mode" + comment "2: sequence mode" + comment "3: preemption mode" + # End Of Conversion Mode Setting + + # Blocking Read Setting + if HPM_ADC0_CONV_MODE=0 + config HPM_ADC0_NON_BLOCKING_READ + bool "ADC0 Non-Blocking Read " + default y + endif + # End Of Blocking Read Setting + + # Trigger Source Setting + config HPM6750_ADC0_TRIG_SOURCE + int "ADC0 Trigger Source" + range 0 11 + default 0 + comment "0: TRG0A" + comment "1: TRG0B" + comment "2: TRG0C" + comment "3: TRG1A" + comment "4: TRG1B" + comment "5: TRG1C" + comment "6: TRG2A" + comment "7: TRG2B" + comment "8: TRG2C" + comment "9: TRG3A" + comment "10: TRG3B" + comment "11: TRG3C" + # End Of Trigger Source Setting + + # Resolution Setting + config HPM_ADC0_RES + int "ADC0 Resolution" + range 0 3 + default 3 + comment "0: 6-bit resolution" + comment "1: 8-bit resolution" + comment "2: 10-bit resolution" + comment "3: 12-bit resolution" + # Endi Of Resolution Setting + + # Signal Type Setting + config HPM_ADC0_DIFF_SEL + int "ADC0 Signal Type" + range 0 1 + default 0 + comment "0: signal-ended signal" + comment "1: differential signal" + # Endi Of Signal Type Setting + endmenu # ADC0 device driver options + +config HPM_ADC1 + bool "ADC1" + default n + select HPM_ADC12_DRV + + menu "ADC1 device driver options" + depends on HPM_ADC1 + + # Channel Value Setting + config HPM_ADC1_CH + int + default 7 + depends on HPM6750EVK_ADC1_CH7 + + config HPM_ADC1_CH + int + default 10 + depends on HPM6750EVK_ADC1_CH10 + + config HPM_ADC1_CH + int + default 11 + depends on HPM6750EVK_ADC1_CH11 + # End Of Channel Value Setting + + # Channel Setting + choice + prompt "ADC1 Channel" + default HPM6750EVK_ADC1_CH11 + + config HPM6750EVK_ADC1_CH7 + bool "CH7" + + config HPM6750EVK_ADC1_CH10 + bool "CH10" + + config HPM6750EVK_ADC1_CH11 + bool "CH11" + endchoice + # End Of Chanenl Setting + + # Conversion Mode Setting + config HPM_ADC1_CONV_MODE + int "ADC1 Conversion Mode" + range 0 3 + default 0 + comment "0: oneshot mode" + comment "1: period mode" + comment "2: sequence mode" + comment "3: preemption mode" + # End Of Conversion Mode Setting + + # Blocking Read Setting + if HPM_ADC1_CONV_MODE=0 + config HPM_ADC1_NON_BLOCKING_READ + bool "ADC1 Non-Blocking Read " + default y + endif + # End Of Blocking Read Setting + + # Trigger Source Setting + config HPM6750_ADC1_TRIG_SOURCE + int "ADC1 Trigger Source" + range 0 11 + default 0 + comment "0: TRG0A" + comment "1: TRG0B" + comment "2: TRG0C" + comment "3: TRG1A" + comment "4: TRG1B" + comment "5: TRG1C" + comment "6: TRG2A" + comment "7: TRG2B" + comment "8: TRG2C" + comment "9: TRG3A" + comment "10: TRG3B" + comment "11: TRG3C" + # End Of Trigger Source Setting + + # Resolution Setting + config HPM_ADC1_RES + int "ADC1 Resolution" + range 0 3 + default 3 + comment "0: 6-bit resolution" + comment "1: 8-bit resolution" + comment "2: 10-bit resolution" + comment "3: 12-bit resolution" + # Endi Of Resolution Setting + + # Signal Type Setting + config HPM_ADC1_DIFF_SEL + int "ADC1 Signal Type" + range 0 1 + default 0 + comment "0: signal-ended signal" + comment "1: differential signal" + # Endi Of Signal Type Setting + endmenu # ADC1 device driver options + +config HPM_ADC2 + bool "ADC2" + default n + select HPM_ADC12_DRV + + menu "ADC2 device driver options" + depends on HPM_ADC2 + + # Channel Value Setting + config HPM_ADC2_CH + int + default 7 + depends on HPM6750EVK_ADC2_CH7 + + config HPM_ADC2_CH + int + default 10 + depends on HPM6750EVK_ADC2_CH10 + + config HPM_ADC2_CH + int + default 11 + depends on HPM6750EVK_ADC2_CH11 + # End Of Channel Value Setting + + # Channel Setting + choice + prompt "ADC2 Channel" + default HPM6750EVK_ADC2_CH11 + + config HPM6750EVK_ADC2_CH7 + bool "CH7" + + config HPM6750EVK_ADC2_CH10 + bool "CH10" + + config HPM6750EVK_ADC2_CH11 + bool "CH11" + endchoice + # End Of Chanenl Setting + + # Conversion Mode Setting + config HPM_ADC2_CONV_MODE + int "ADC2 Conversion Mode" + range 0 3 + default 0 + comment "0: oneshot mode" + comment "1: period mode" + comment "2: sequence mode" + comment "3: preemption mode" + # End Of Conversion Mode Setting + + # Blocking Read Setting + if HPM_ADC2_CONV_MODE=0 + config HPM_ADC2_NON_BLOCKING_READ + bool "ADC2 Non-Blocking Read " + default y + endif + # End Of Blocking Read Setting + + # Trigger Source Setting + config HPM6750_ADC2_TRIG_SOURCE + int "ADC2 Trigger Source" + range 0 11 + default 0 + comment "0: TRG0A" + comment "1: TRG0B" + comment "2: TRG0C" + comment "3: TRG1A" + comment "4: TRG1B" + comment "5: TRG1C" + comment "6: TRG2A" + comment "7: TRG2B" + comment "8: TRG2C" + comment "9: TRG3A" + comment "10: TRG3B" + comment "11: TRG3C" + # End Of Trigger Source Setting + + # Resolution Setting + config HPM_ADC2_RES + int "ADC2 Resolution" + range 0 3 + default 3 + comment "0: 6-bit resolution" + comment "1: 8-bit resolution" + comment "2: 10-bit resolution" + comment "3: 12-bit resolution" + # Endi Of Resolution Setting + + # Signal Type Setting + config HPM_ADC2_DIFF_SEL + int "ADC2 Signal Type" + range 0 1 + default 0 + comment "0: signal-ended signal" + comment "1: differential signal" + # End Of Signal Type Setting + endmenu # ADC2 device driver options + +config HPM_ADC3 + bool "ADC3" + default n + select HPM_ADC16_DRV + + menu "ADC3 device driver options" + depends on HPM_ADC3 + # Channel Setting + config HPM_ADC3_CH + int + default 2 + depends on HPM6750EVK_ADC3_CH2 + + choice + prompt "ADC3 Channel" + default HPM6750EVK_ADC3_CH2 + + config HPM6750EVK_ADC3_CH2 + bool "CH2" + endchoice + # End Of Chanenl Setting + + # Conversion Mode Setting + config HPM_ADC3_CONV_MODE + int "ADC3 Conversion Mode" + range 0 3 + default 0 + comment "0: oneshot mode" + comment "1: period mode" + comment "2: sequence mode" + comment "3: preemption mode" + # End Of Conversion Mode Setting + + # Blocking Read Setting + if HPM_ADC3_CONV_MODE=0 + config HPM_ADC3_NON_BLOCKING_READ + bool "ADC3 Non-Blocking Read " + default y + endif + # End Of Blocking Read Setting + + # Trigger Source Setting + config HPM6750_ADC3_TRIG_SOURCE + int "ADC3 Trigger Source" + range 0 11 + default 0 + comment "0: TRG0A" + comment "1: TRG0B" + comment "2: TRG0C" + comment "3: TRG1A" + comment "4: TRG1B" + comment "5: TRG1C" + comment "6: TRG2A" + comment "7: TRG2B" + comment "8: TRG2C" + comment "9: TRG3A" + comment "10: TRG3B" + comment "11: TRG3C" + # End Of Trigger Source Setting + + # Resolution Value Setting + config HPM_ADC3_RES + int + default 9 + depends on ADC3_RES_8BIT + + config HPM_ADC3_RES + int + default 11 + depends on ADC3_RES_10BIT + + config HPM_ADC3_RES + int + default 14 + depends on ADC3_RES_12BIT + + config HPM_ADC3_RES + int + default 21 + depends on ADC3_RES_16BIT + # End Of Resolution Value Setting + + # Resolution Setting + choice + prompt "ADC3 Resolution" + default ADC3_RES_16BIT + + config ADC3_RES_8BIT + bool "8-bit resolution" + + config ADC3_RES_10BIT + bool "10-bit resolution" + + config ADC3_RES_12BIT + bool "12-bit resolution" + + config ADC3_RES_16BIT + bool "16-bit resolution" + endchoice + # Endi Of Resolution Setting + endmenu # ADC3 device driver options endmenu - - - diff --git a/arch/risc-v/src/hpmicro/hpm6750/Make.defs b/arch/risc-v/src/hpmicro/hpm6750/Make.defs index cbd706b84d102..206950c26fbbd 100644 --- a/arch/risc-v/src/hpmicro/hpm6750/Make.defs +++ b/arch/risc-v/src/hpmicro/hpm6750/Make.defs @@ -37,4 +37,11 @@ ifeq ($(CONFIG_HPM_CAN_SOCKET),y) CHIP_CSRCS += hpmicro$(DELIM)hpm6750$(DELIM)hpm_can_sock.c endif +ifeq ($(CONFIG_HPM_ADC12_DRV),y) + CHIP_CSRCS += hpmicro$(DELIM)hpm6750$(DELIM)hpm_adc12.c +endif + +ifeq ($(CONFIG_HPM_ADC16_DRV),y) + CHIP_CSRCS += hpmicro$(DELIM)hpm6750$(DELIM)hpm_adc16.c +endif diff --git a/arch/risc-v/src/hpmicro/hpm6750/hpm_adc12.c b/arch/risc-v/src/hpmicro/hpm6750/hpm_adc12.c new file mode 100644 index 0000000000000..e94ad9c739037 --- /dev/null +++ b/arch/risc-v/src/hpmicro/hpm6750/hpm_adc12.c @@ -0,0 +1,860 @@ +/**************************************************************************** + * arch/risc-v/src/hpmicro/hpm6750/hpm_adc12.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "board.h" +#include "hpm_adc12_drv.h" + +#if CONFIG_HPM_ADC12_DRV + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef BOARD_APP_CORE +#define BOARD_APP_CORE HPM_CORE0 +#endif + +#define BOARD_APP_ADC_SEQ_DMA_BUFF_LEN_IN_4BYTES (1024U) +#define BOARD_APP_ADC_PMT_DMA_BUFF_LEN_IN_4BYTES (48U) +#define BOARD_APP_SEQ_START_POS (0U) +#define BOARD_APP_PMT_START_POS CONFIG_HPM6750_ADC0_TRIG_SOURCE + +#if defined(CONFIG_HPM_ADC0) && CONFIG_HPM_ADC0 +#define HPM_IRQn_ADC0 (IRQn_ADC0 + HPM_IRQ_PERI_START) +#endif + +#if defined(CONFIG_HPM_ADC1) && CONFIG_HPM_ADC1 +#define HPM_IRQn_ADC1 (IRQn_ADC1 + HPM_IRQ_PERI_START) +#endif + +#if defined(CONFIG_HPM_ADC2) && CONFIG_HPM_ADC2 +#define HPM_IRQn_ADC2 (IRQn_ADC2 + HPM_IRQ_PERI_START) +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct up_dev_s +{ + const struct adc_callback_s *cb; + char *name; + char *path; + ADC12_Type *base; + int irq; + xcpt_t isr; + uint32_t mask; + adc12_config_t cfg; + adc12_channel_config_t ch_cfg; + adc12_prd_config_t prd_cfg; + adc12_seq_config_t seq_cfg; + adc12_dma_config_t dma_cfg; + adc12_pmt_config_t pmt_cfg; + uint32_t *seq_buff; + uint32_t *pmt_buff; + uint8_t *seq_channel_list; + uint8_t *trig_channel_list; + __IO uint8_t seq_full_complete_flag; + __IO uint8_t trig_complete_flag; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* ADC methods */ +static int adc_bind(struct adc_dev_s *dev, const struct adc_callback_s *callback); +static void adc_reset(struct adc_dev_s *dev); +static int adc_setup(struct adc_dev_s *dev); +static void adc_shutdown(struct adc_dev_s *dev); +static void adc_rxint(struct adc_dev_s *dev, bool enable); +static int adc_ioctl(struct adc_dev_s *dev, int cmd, unsigned long arg); + +/* ADC Interrupt Handler */ +static int adc_interrupt(int irq, void *context, void *arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#if defined(CONFIG_HPM_ADC0) && CONFIG_HPM_ADC0 + #if defined(CONFIG_HPM_ADC0_CONV_MODE) && (CONFIG_HPM_ADC0_CONV_MODE == 2) + static uint8_t adc0_seq_channel_list[] = {CONFIG_HPM_ADC0_CH}; + static ATTR_PLACE_AT_NONCACHEABLE_WITH_ALIGNMENT(ADC_SOC_DMA_ADDR_ALIGNMENT) uint32_t adc0_seq_buff[BOARD_APP_ADC_SEQ_DMA_BUFF_LEN_IN_4BYTES]; + #elif defined(CONFIG_HPM_ADC0_CONV_MODE) && (CONFIG_HPM_ADC0_CONV_MODE == 3) + static uint8_t adc0_trig_channel_list[] = {CONFIG_HPM_ADC0_CH}; + static ATTR_PLACE_AT_NONCACHEABLE_WITH_ALIGNMENT(ADC_SOC_DMA_ADDR_ALIGNMENT) uint32_t adc0_pmt_buff[BOARD_APP_ADC_PMT_DMA_BUFF_LEN_IN_4BYTES]; + #endif +#endif + +#if defined(CONFIG_HPM_ADC1) && CONFIG_HPM_ADC1 + #if defined(CONFIG_HPM_ADC1_CONV_MODE) && (CONFIG_HPM_ADC1_CONV_MODE == 2) + static uint8_t adc1_seq_channel_list[] = {CONFIG_HPM_ADC1_CH}; + static ATTR_PLACE_AT_NONCACHEABLE_WITH_ALIGNMENT(ADC_SOC_DMA_ADDR_ALIGNMENT) uint32_t adc1_seq_buff[BOARD_APP_ADC_SEQ_DMA_BUFF_LEN_IN_4BYTES]; + #elif defined(CONFIG_HPM_ADC1_CONV_MODE) && (CONFIG_HPM_ADC1_CONV_MODE == 3) + static uint8_t adc1_trig_channel_list[] = {CONFIG_HPM_ADC1_CH}; + static ATTR_PLACE_AT_NONCACHEABLE_WITH_ALIGNMENT(ADC_SOC_DMA_ADDR_ALIGNMENT) uint32_t adc1_pmt_buff[BOARD_APP_ADC_PMT_DMA_BUFF_LEN_IN_4BYTES]; + #endif +#endif + +#if defined(CONFIG_HPM_ADC2) && CONFIG_HPM_ADC2 + #if defined(CONFIG_HPM_ADC2_CONV_MODE) && (CONFIG_HPM_ADC2_CONV_MODE == 2) + static uint8_t adc2_seq_channel_list[] = {CONFIG_HPM_ADC2_CH}; + static ATTR_PLACE_AT_NONCACHEABLE_WITH_ALIGNMENT(ADC_SOC_DMA_ADDR_ALIGNMENT) uint32_t adc2_seq_buff[BOARD_APP_ADC_SEQ_DMA_BUFF_LEN_IN_4BYTES]; + #elif defined(CONFIG_HPM_ADC2_CONV_MODE) && (CONFIG_HPM_ADC2_CONV_MODE == 3) + static uint8_t adc2_trig_channel_list[] = {CONFIG_HPM_ADC2_CH}; + static ATTR_PLACE_AT_NONCACHEABLE_WITH_ALIGNMENT(ADC_SOC_DMA_ADDR_ALIGNMENT) uint32_t adc2_pmt_buff[BOARD_APP_ADC_PMT_DMA_BUFF_LEN_IN_4BYTES]; + #endif +#endif + +static const struct adc_ops_s g_adc_ops = +{ + .ao_bind = adc_bind, + .ao_reset = adc_reset, + .ao_setup = adc_setup, + .ao_shutdown = adc_shutdown, + .ao_rxint = adc_rxint, + .ao_ioctl = adc_ioctl, +}; + +#if defined(CONFIG_HPM_ADC0) && CONFIG_HPM_ADC0 +static struct up_dev_s g_adc0_priv = +{ + /* instance name */ + .name = "ADC0", + /* device path */ + .path = "/dev/adc0", + /* instance base */ + .base = HPM_ADC0, + /* interrupt config */ + .irq = HPM_IRQn_ADC0, + .isr = adc_interrupt, + .mask = 0, + /* common config */ + .cfg = { .res = CONFIG_HPM_ADC0_RES, + .conv_mode = CONFIG_HPM_ADC0_CONV_MODE, + .adc_clk_div = 2, + .sel_sync_ahb = false, + .wait_dis = true, + .adc_ahb_en = false, + }, + /* channel config */ + .ch_cfg = { + .ch = CONFIG_HPM_ADC0_CH, + .diff_sel = CONFIG_HPM_ADC0_DIFF_SEL, + .thshdh = 0, + .thshdl = 0, + .sample_cycle_shift = 0, + .sample_cycle = 20 + }, + /* oneshot mode */ + #if CONFIG_HPM_ADC0_CONV_MODE == 0 + + /* period mode */ + #elif CONFIG_HPM_ADC0_CONV_MODE == 1 + .prd_cfg = { + .ch = CONFIG_HPM_ADC0_CH, + .prescale = 22, + .period_count = 1 + }, + /* sequence mode */ + #elif CONFIG_HPM_ADC0_CONV_MODE == 2 + .seq_cfg = { + .seq_len = sizeof(adc0_seq_channel_list), + .restart_en = false, + .cont_en = true, + .sw_trig_en = true, + .hw_trig_en = true + }, + .dma_cfg = { + .start_addr = (uint32_t)adc0_seq_buff, + .buff_len_in_4bytes = sizeof(adc0_seq_channel_list), + .stop_en = false, + .stop_pos = 0 + }, + .seq_buff = adc0_seq_buff, + .seq_channel_list = adc0_seq_channel_list, + /* preemption mode */ + #elif CONFIG_HPM_ADC0_CONV_MODE == 3 + .pmt_cfg = { + .trig_ch = BOARD_APP_PMT_START_POS, + .trig_len = sizeof(adc0_trig_channel_list) + }, + .pmt_buff = adc0_pmt_buff, + .trig_channel_list = adc0_trig_channel_list + #else + #error "Not supported mode!" + #endif +}; +#endif + +#if defined(CONFIG_HPM_ADC1) && CONFIG_HPM_ADC1 +static struct up_dev_s g_adc1_priv = +{ + /* instance name */ + .name = "ADC1", + /* device path */ + .path = "/dev/adc1", + /* instance base */ + .base = HPM_ADC1, + /* interrupt config */ + .irq = HPM_IRQn_ADC1, + .isr = adc_interrupt, + .mask = 0, + /* common config */ + .cfg = { .res = CONFIG_HPM_ADC1_RES, + .conv_mode = CONFIG_HPM_ADC1_CONV_MODE, + .adc_clk_div = 2, + .sel_sync_ahb = false, + .wait_dis = true, + .adc_ahb_en = false, + }, + /* channel config */ + .ch_cfg = { + .ch = CONFIG_HPM_ADC1_CH, + .diff_sel = CONFIG_HPM_ADC1_DIFF_SEL, + .thshdh = 0, + .thshdl = 0, + .sample_cycle_shift = 0, + .sample_cycle = 20 + }, + /* oneshot mode */ + #if CONFIG_HPM_ADC1_CONV_MODE == 0 + + /* period mode */ + #elif CONFIG_HPM_ADC1_CONV_MODE == 1 + .prd_cfg = { + .ch = CONFIG_HPM_ADC1_CH, + .prescale = 22, + .period_count = 1 + }, + /* sequence mode */ + #elif CONFIG_HPM_ADC1_CONV_MODE == 2 + .seq_cfg = { + .seq_len = sizeof(adc1_seq_channel_list), + .restart_en = false, + .cont_en = true, + .sw_trig_en = true, + .hw_trig_en = true + }, + .dma_cfg = { + .start_addr = (uint32_t)adc1_seq_buff, + .buff_len_in_4bytes = sizeof(adc1_seq_channel_list), + .stop_en = false, + .stop_pos = 0 + }, + .seq_buff = adc1_seq_buff, + .seq_channel_list = adc1_seq_channel_list, + /* preemption mode */ + #elif CONFIG_HPM_ADC1_CONV_MODE == 3 + .pmt_cfg = { + .trig_ch = BOARD_APP_PMT_START_POS, + .trig_len = sizeof(adc1_trig_channel_list) + }, + .pmt_buff = adc1_pmt_buff, + .trig_channel_list = adc1_trig_channel_list + #else + #error "Not supported mode!" + #endif +}; +#endif + +#if defined(CONFIG_HPM_ADC2) && CONFIG_HPM_ADC2 +static struct up_dev_s g_adc2_priv = +{ + /* instance name */ + .name = "ADC2", + /* device path */ + .path = "/dev/adc2", + /* instance base */ + .base = HPM_ADC2, + /* interrupt config */ + .irq = HPM_IRQn_ADC2, + .isr = adc_interrupt, + .mask = 0, + /* common config */ + .cfg = { .res = CONFIG_HPM_ADC2_RES, + .conv_mode = CONFIG_HPM_ADC2_CONV_MODE, + .adc_clk_div = adc12_clock_divider_3, + .sel_sync_ahb = false, + .wait_dis = true, + .adc_ahb_en = false, + }, + /* channel config */ + .ch_cfg = { + .ch = CONFIG_HPM_ADC2_CH, + .diff_sel = CONFIG_HPM_ADC2_DIFF_SEL, + .thshdh = 0, + .thshdl = 0, + .sample_cycle_shift = 0, + .sample_cycle = 20 + }, + /* oneshot mode */ + #if CONFIG_HPM_ADC2_CONV_MODE == 0 + + /* period mode */ + #elif CONFIG_HPM_ADC2_CONV_MODE == 1 + .prd_cfg = { + .ch = CONFIG_HPM_ADC2_CH, + .prescale = 22, + .period_count = 5 + }, + /* sequence mode */ + #elif CONFIG_HPM_ADC2_CONV_MODE == 2 + .seq_cfg = { + .seq_len = sizeof(adc2_seq_channel_list), + .restart_en = false, + .cont_en = true, + .sw_trig_en = true, + .hw_trig_en = true + }, + .dma_cfg = { + .start_addr = (uint32_t)adc2_seq_buff, + .buff_len_in_4bytes = sizeof(adc2_seq_channel_list), + .stop_en = false, + .stop_pos = 0 + }, + .seq_buff = adc2_seq_buff, + .seq_channel_list = adc2_seq_channel_list, + /* preemption mode */ + #elif CONFIG_HPM_ADC2_CONV_MODE == 3 + .pmt_cfg = { + .trig_ch = BOARD_APP_PMT_START_POS, + .trig_len = sizeof(adc2_trig_channel_list) + }, + .pmt_buff = adc2_pmt_buff, + .trig_channel_list = adc2_trig_channel_list + #else + #error "Not supported mode!" + #endif +}; +#endif + +static struct adc_dev_s g_adc_dev[] = +{ + #if defined(CONFIG_HPM_ADC0) && CONFIG_HPM_ADC0 + { + .ad_ops = &g_adc_ops, + .ad_priv = &g_adc0_priv + }, + #endif + + #if defined(CONFIG_HPM_ADC1) && CONFIG_HPM_ADC1 + { + .ad_ops = &g_adc_ops, + .ad_priv = &g_adc1_priv + }, + #endif + + #if defined(CONFIG_HPM_ADC2) && CONFIG_HPM_ADC2 + { + .ad_ops = &g_adc_ops, + .ad_priv = &g_adc2_priv + }, + #endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void init_trigger_cfg(struct adc_dev_s *dev, uint8_t trig_ch, bool inten) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->ad_priv; + + for (int i = 0; i < priv->pmt_cfg.trig_len; i++) { + priv->pmt_cfg.adc_ch[i] = priv->trig_channel_list[i]; + priv->pmt_cfg.inten[i] = false; + } + + priv->pmt_cfg.inten[priv->pmt_cfg.trig_len - 1] = inten; + + adc12_set_pmt_config(priv->base, &priv->pmt_cfg); +} + +static void init_common_config(struct adc_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->ad_priv; + + if (priv->cfg.conv_mode == adc12_conv_mode_sequence || priv->cfg.conv_mode == adc12_conv_mode_preemption) { + priv->cfg.adc_ahb_en = true; + } + + if (priv->base == HPM_ADC0) { + #if defined(CONFIG_HPM_ADC0_NON_BLOCKING_READ) && CONFIG_HPM_ADC0_NON_BLOCKING_READ + priv->cfg.wait_dis = true; + #else + priv->cfg.wait_dis = false; + #endif + } else if (priv->base == HPM_ADC1) { + #if defined(CONFIG_HPM_ADC1_NON_BLOCKING_READ) && CONFIG_HPM_ADC1_NON_BLOCKING_READ + priv->cfg.wait_dis = true; + #else + priv->cfg.wait_dis = false; + #endif + } else if (priv->base == HPM_ADC2) { + #if defined(CONFIG_HPM_ADC2_NON_BLOCKING_READ) && CONFIG_HPM_ADC2_NON_BLOCKING_READ + priv->cfg.wait_dis = true; + #else + priv->cfg.wait_dis = false; + #endif + } else { + + } + + adc12_init(priv->base, &priv->cfg); + up_enable_irq(priv->irq); +} + +static void init_oneshot_config(struct adc_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->ad_priv; + + adc12_init_channel(priv->base, &priv->ch_cfg); +} + +static void init_period_config(struct adc_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->ad_priv; + + adc12_init_channel(priv->base, &priv->ch_cfg); + adc12_set_prd_config(priv->base, &priv->prd_cfg); +} + +static void init_sequence_config(struct adc_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->ad_priv; + + for (int i = 0; i < priv->seq_cfg.seq_len; i++) { + priv->ch_cfg.ch = priv->seq_channel_list[i]; + adc12_init_channel(priv->base, &priv->ch_cfg); + } + + for (int i = 0; i < priv->seq_cfg.seq_len; i++) { + priv->seq_cfg.queue[i].seq_int_en = 0; + priv->seq_cfg.queue[i].ch = priv->seq_channel_list[i]; + } + + /* Initialize a sequence */ + adc12_set_seq_config(priv->base, &priv->seq_cfg); + + /* Set DMA config */ + priv->dma_cfg.start_addr = (uint32_t *)core_local_mem_to_sys_address(BOARD_APP_CORE, (uint32_t)priv->seq_buff); + + /* Initialize DMA for the sequence mode */ + adc12_init_seq_dma(priv->base, &priv->dma_cfg); + + /* Set interrupt mask */ + priv->mask = adc12_event_seq_full_complete; +} + +static void init_preemption_config(struct adc_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->ad_priv; + + for (int i = 0; i < priv->pmt_cfg.trig_len; i++) { + priv->ch_cfg.ch = priv->trig_channel_list[i]; + adc12_init_channel(priv->base, &priv->ch_cfg); + } + + /* Trigger config initialization */ + init_trigger_cfg(dev, priv->pmt_cfg.trig_ch, true); + + /* Set DMA start address for preemption mode */ + adc12_init_pmt_dma(priv->base, core_local_mem_to_sys_address(BOARD_APP_CORE, (uint32_t)priv->pmt_buff)); + + /* Set interrupt mask */ + priv->mask = adc12_event_trig_complete; +} + + +static hpm_stat_t process_seq_data(struct adc_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->ad_priv; + adc12_seq_dma_data_t *dma_data = (adc12_seq_dma_data_t *)priv->seq_buff; + uint32_t len = priv->seq_cfg.seq_len; + + if (ADC12_IS_SEQ_DMA_BUFF_LEN_INVLAID(len)) { + return status_invalid_argument; + } + + for (int i = 0; i < len; i++) { + ainfo("Sequence Mode - %s - ", priv->name); + ainfo("Sequence Number:%02d ", dma_data[i].seq_num); + ainfo("Cycle Bit: %02d ", dma_data[i].cycle_bit); + ainfo("ADC Channel: %02d ", dma_data[i].adc_ch); + ainfo("Result: 0x%04x\n", dma_data[i].result); + } + + return status_success; +} + +static hpm_stat_t process_pmt_data(struct adc_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->ad_priv; + adc12_pmt_dma_data_t *dma_data = (adc12_pmt_dma_data_t *)priv->pmt_buff; + int start_pos = priv->pmt_cfg.trig_ch * sizeof(adc12_pmt_dma_data_t); + uint32_t len = priv->pmt_cfg.trig_len; + + if (ADC12_IS_PMT_DMA_BUFF_LEN_INVLAID(len)) { + return status_invalid_argument; + } + + for (int i = start_pos; i < start_pos + len; i++) { + ainfo("Cycle Bit: %02d ", dma_data[i].cycle_bit); + if (dma_data[i].cycle_bit) { + ainfo("Preemption Mode - %s - ", priv->name); + ainfo("ADC Channel: %02d ", dma_data[i].adc_ch); + ainfo("Trig Index: %02d ", dma_data[i].trig_index); + ainfo("Trig Channel: %02d ", dma_data[i].trig_ch); + ainfo("Result: 0x%04x\n", dma_data[i].result); + dma_data[i].cycle_bit = 0; + } else { + ainfo("invalid data\n"); + } + } + + return status_success; +} + +static void sequence_handler(struct adc_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->ad_priv; + + /* SW trigger */ + adc12_trigger_seq_by_sw(priv->base); + + while (priv->seq_full_complete_flag == 0) { + + } + /* Process data */ + process_seq_data(dev); + + /* Clear the flag */ + priv->seq_full_complete_flag = 0; +} + +static void preemption_handler(struct adc_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->ad_priv; + + /* SW trigger */ + adc12_trigger_pmt_by_sw(priv->base, priv->pmt_cfg.trig_ch); + + /* Wait for a complete of conversion */ + while (priv->trig_complete_flag == 0) { + + } + + /* Process data */ + process_pmt_data(dev); + + /* Clear the flag */ + priv->trig_complete_flag = 0; +} + +static int adc_interrupt_handler(struct adc_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->ad_priv; + uint32_t status; + + status = adc12_get_status_flags(priv->base); + + if (ADC12_INT_STS_SEQ_CMPT_GET(status)) { + /* Clear seq_complete status */ + adc12_clear_status_flags(priv->base, adc12_event_seq_full_complete); + /* Set flag to read memory data */ + priv->seq_full_complete_flag = 1; + } + + if (ADC12_INT_STS_TRIG_CMPT_GET(status)) { + /* Clear trig_cmpt status */ + adc12_clear_status_flags(priv->base, adc12_event_trig_complete); + /* Set flag to read memory data */ + priv->trig_complete_flag = 1; + } + + return OK; +} + +/**************************************************************************** + * Name: adc_bind + * + * Description: + * Bind the upper-half driver callbacks to the lower-half implementation. + * This must be called early in order to receive ADC event notifications. + * + ****************************************************************************/ + +static int adc_bind(struct adc_dev_s *dev, const struct adc_callback_s *callback) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->ad_priv; + + DEBUGASSERT(priv != NULL); + if (priv == NULL) { + return -ENOBUFS; + } + priv->cb = callback; + + return OK; +} + +/**************************************************************************** + * Name: adc_reset + * + * Description: + * Reset the ADC device. Called early to initialize the hardware. This + * is called, before adc_setup() and on error conditions. + * + ****************************************************************************/ + +static void adc_reset(struct adc_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->ad_priv; + irqstate_t flags; + + flags = enter_critical_section(); + + /* ADC pin initialization */ + board_init_adc12_pins(); + + /* ADC clock initialization */ + board_init_adc12_clock(priv->base); + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: adc_setup + * + * Description: + * Configure the ADC. This method is called the first time that the ADC + * device is opened. This will occur when the port is first opened. + * This setup includes configuring and attaching ADC interrupts. + * Interrupts are all disabled upon return. + * + ****************************************************************************/ + +static int adc_setup(struct adc_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->ad_priv; + + /* Attach the ADC interrupt */ + int ret = irq_attach(priv->irq, priv->isr, dev); + if (ret < 0) { + ainfo("irq_attach failed: %d\n", ret); + return ret; + } + + up_enable_irq(priv->irq); + + /* ADC12 common initialization */ + init_common_config(dev); + + /* ADC12 read patter and DMA initialization */ + switch (priv->cfg.conv_mode) { + case adc12_conv_mode_oneshot: + init_oneshot_config(dev); + break; + + case adc12_conv_mode_period: + init_period_config(dev); + break; + + case adc12_conv_mode_sequence: + init_sequence_config(dev); + break; + + case adc12_conv_mode_preemption: + init_preemption_config(dev); + break; + + default: + break; + } + + return ret; +} + +/**************************************************************************** + * Name: adc_shutdown + * + * Description: + * Disable the ADC. This method is called when the ADC device is closed. + * This method reverses the operation the setup method. + * + ****************************************************************************/ + +static void adc_shutdown(struct adc_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->ad_priv; + + /* Disable ADC interrupts */ + up_disable_irq(priv->irq); + + /* Then detach the ADC interrupt handler. */ + irq_detach(priv->irq); +} + +/**************************************************************************** + * Name: adc_rxint + * + * Description: + * Call to enable or disable RX interrupts + * + ****************************************************************************/ + +static void adc_rxint(struct adc_dev_s *dev, bool enable) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->ad_priv; + + if (enable == true) { + priv->base->INT_EN |= priv->mask; + } else { + priv->base->INT_EN &= ~priv->mask; + } +} + +/**************************************************************************** + * Name: adc_ioctl + * + * Description: + * All ioctl calls will be routed through this method + * + ****************************************************************************/ + +static int adc_ioctl(struct adc_dev_s *dev, int cmd, unsigned long arg) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->ad_priv; + uint16_t result; + int cnt = 0; + int ret = OK; + + switch (cmd) { + case ANIOC_TRIGGER: + { + if (priv->cfg.conv_mode == adc12_conv_mode_oneshot) { + while (cnt++ < 10) { + if (adc12_get_oneshot_result(priv->base, priv->ch_cfg.ch, &result) == status_success) { + ainfo("oneshot mode: read result\n"); + priv->cb->au_receive(dev, priv->ch_cfg.ch, (int32_t)result); + break; + } + } + ret = cnt > 10 ? -EAGAIN : OK; + } else if (priv->cfg.conv_mode == adc12_conv_mode_period) { + ainfo("period mode: read result\n"); + up_mdelay(120); + adc12_get_prd_result(priv->base, priv->ch_cfg.ch, &result); + priv->cb->au_receive(dev, priv->ch_cfg.ch, (int32_t)result); + } else if (priv->cfg.conv_mode == adc12_conv_mode_sequence){ + adc12_seq_dma_data_t *dma_data = (adc12_seq_dma_data_t *)priv->seq_buff; + ainfo("sequence mode: read reuslt\n"); + sequence_handler(dev); + priv->cb->au_receive(dev, dma_data[BOARD_APP_SEQ_START_POS].adc_ch, (int32_t)dma_data[BOARD_APP_SEQ_START_POS].result); + } else if (priv->cfg.conv_mode == adc12_conv_mode_preemption) { + adc12_pmt_dma_data_t *dma_data = (adc12_pmt_dma_data_t *)priv->pmt_buff; + uint32_t offset = priv->pmt_cfg.trig_ch * sizeof(adc12_pmt_dma_data_t); + ainfo("preemption mode: read reuslt\n"); + preemption_handler(dev); + priv->cb->au_receive(dev, dma_data[offset].adc_ch, (int32_t)dma_data[offset].result); + } else { + ret = -EINVAL; + } + break; + } + default: break; + } + + return ret; +} + +/**************************************************************************** + * Name: adc_interrupt + * + * Description: + * ADC interrupt handler + * + ****************************************************************************/ + +static int adc_interrupt(int irq, void *context, void *arg) +{ + struct adc_dev_s *dev = (struct adc_dev_s *)arg; + adc_interrupt_handler(dev); + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: hpm_adcinitialize + * + * Description: + * Initialize the adc + * + * Returned Value: + * Valid adc device structure reference on success; a NULL on failure + * + ****************************************************************************/ +int hpm_adc12_setup(void) +{ + static bool initialized = false; + int ret; + + /* Check if we have already initialized */ + if (!initialized) + { + /* Register the ADC driver at "/dev/adcx" */ + for (int i = 0; i < sizeof(g_adc_dev) / sizeof(g_adc_dev[0]); i++) { + ret = adc_register(((struct up_dev_s *)(g_adc_dev[i].ad_priv))->path, &g_adc_dev[i]); + if (ret < 0) + { + aerr("ERROR: adc_register failed: %d\n", ret); + return ret; + } + } + /* Now we are initialized */ + initialized = true; + } + + return OK; +} + +#endif \ No newline at end of file diff --git a/arch/risc-v/src/hpmicro/hpm6750/hpm_adc12.h b/arch/risc-v/src/hpmicro/hpm6750/hpm_adc12.h new file mode 100644 index 0000000000000..87d96e797ebda --- /dev/null +++ b/arch/risc-v/src/hpmicro/hpm6750/hpm_adc12.h @@ -0,0 +1,60 @@ +/**************************************************************************** + * arch/risc-v/src/hpmicro/hpm6750/hpm_adc12.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_SRC_HPMICRO_HPM6750_HPM_ADC12_H +#define __ARCH_RISCV_SRC_HPMICRO_HPM6750_HPM_ADC12_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +EXTERN int hpm_adc12_setup(void); +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ +#if defined(__cplusplus) +} +#endif +#undef EXTERN + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_RISCV_SRC_HPMICRO_HPM6750_HPM_ADC12_H */ diff --git a/arch/risc-v/src/hpmicro/hpm6750/hpm_adc16.c b/arch/risc-v/src/hpmicro/hpm6750/hpm_adc16.c new file mode 100644 index 0000000000000..0717d7fc339b5 --- /dev/null +++ b/arch/risc-v/src/hpmicro/hpm6750/hpm_adc16.c @@ -0,0 +1,661 @@ +/**************************************************************************** + * arch/risc-v/src/hpmicro/hpm6750/hpm_adc16.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "board.h" +#include "hpm_adc16_drv.h" + +#if CONFIG_HPM_ADC16_DRV + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef BOARD_APP_CORE +#define BOARD_APP_CORE HPM_CORE0 +#endif + +#define BOARD_APP_ADC_SEQ_DMA_BUFF_LEN_IN_4BYTES (1024U) +#define BOARD_APP_ADC_PMT_DMA_BUFF_LEN_IN_4BYTES (48U) +#define BOARD_APP_SEQ_START_POS (0U) +#define BOARD_APP_PMT_START_POS CONFIG_HPM6750_ADC3_TRIG_SOURCE + +#if defined(CONFIG_HPM_ADC3) && CONFIG_HPM_ADC3 +#define HPM_IRQn_ADC3 (IRQn_ADC3 + HPM_IRQ_PERI_START) +#endif + + + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct up_dev_s +{ + const struct adc_callback_s *cb; + char *name; + char *path; + ADC16_Type *base; + int irq; + xcpt_t isr; + uint32_t mask; + adc16_config_t cfg; + adc16_channel_config_t ch_cfg; + adc16_prd_config_t prd_cfg; + adc16_seq_config_t seq_cfg; + adc16_dma_config_t dma_cfg; + adc16_pmt_config_t pmt_cfg; + uint32_t *seq_buff; + uint32_t *pmt_buff; + uint8_t *seq_channel_list; + uint8_t *trig_channel_list; + __IO uint8_t seq_full_complete_flag; + __IO uint8_t trig_complete_flag; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* ADC methods */ +static int adc_bind(struct adc_dev_s *dev, const struct adc_callback_s *callback); +static void adc_reset(struct adc_dev_s *dev); +static int adc_setup(struct adc_dev_s *dev); +static void adc_shutdown(struct adc_dev_s *dev); +static void adc_rxint(struct adc_dev_s *dev, bool enable); +static int adc_ioctl(struct adc_dev_s *dev, int cmd, unsigned long arg); + +/* ADC Interrupt Handler */ +static int adc_interrupt(int irq, void *context, void *arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#if defined(CONFIG_HPM_ADC3) && CONFIG_HPM_ADC3 + #if defined(CONFIG_HPM_ADC3_CONV_MODE) && (CONFIG_HPM_ADC3_CONV_MODE == 2) + static uint8_t adc3_seq_channel_list[] = {CONFIG_HPM_ADC3_CH}; + static ATTR_PLACE_AT_NONCACHEABLE_WITH_ALIGNMENT(ADC_SOC_DMA_ADDR_ALIGNMENT) uint32_t adc3_seq_buff[BOARD_APP_ADC_SEQ_DMA_BUFF_LEN_IN_4BYTES]; + #elif defined(CONFIG_HPM_ADC3_CONV_MODE) && (CONFIG_HPM_ADC3_CONV_MODE == 3) + static uint8_t adc3_trig_channel_list[] = {CONFIG_HPM_ADC3_CH}; + static ATTR_PLACE_AT_NONCACHEABLE_WITH_ALIGNMENT(ADC_SOC_DMA_ADDR_ALIGNMENT) uint32_t adc3_pmt_buff[BOARD_APP_ADC_PMT_DMA_BUFF_LEN_IN_4BYTES]; + #endif +#endif + +static const struct adc_ops_s g_adc_ops = +{ + .ao_bind = adc_bind, + .ao_reset = adc_reset, + .ao_setup = adc_setup, + .ao_shutdown = adc_shutdown, + .ao_rxint = adc_rxint, + .ao_ioctl = adc_ioctl, +}; + +#if defined(CONFIG_HPM_ADC3) && CONFIG_HPM_ADC3 +static struct up_dev_s g_adc3_priv = +{ + /* instance name */ + .name = "ADC3", + /* device path */ + .path = "/dev/adc3", + /* instance base */ + .base = HPM_ADC3, + /* interrupt config */ + .irq = HPM_IRQn_ADC3, + .isr = adc_interrupt, + .mask = 0, + /* common config */ + .cfg = { .res = CONFIG_HPM_ADC3_RES, + .conv_mode = CONFIG_HPM_ADC3_CONV_MODE, + .adc_clk_div = adc16_clock_divider_4, + .sel_sync_ahb = false, + .wait_dis = true, + .adc_ahb_en = false, + }, + /* channel config */ + .ch_cfg = { + .ch = CONFIG_HPM_ADC3_CH, + .thshdh = 0, + .thshdl = 0, + .sample_cycle_shift = 0, + .sample_cycle = 20 + }, + /* oneshot mode */ + #if CONFIG_HPM_ADC3_CONV_MODE == 0 + + /* period mode */ + #elif CONFIG_HPM_ADC3_CONV_MODE == 1 + .prd_cfg = { + .ch = CONFIG_HPM_ADC3_CH, + .prescale = 22, + .period_count = 5 + }, + /* sequence mode */ + #elif CONFIG_HPM_ADC3_CONV_MODE == 2 + .seq_cfg = { + .seq_len = sizeof(adc3_seq_channel_list), + .restart_en = false, + .cont_en = true, + .sw_trig_en = true, + .hw_trig_en = true + }, + .dma_cfg = { + .start_addr = (uint32_t)adc3_seq_buff, + .buff_len_in_4bytes = sizeof(adc3_seq_channel_list), + .stop_en = false, + .stop_pos = 0 + }, + .seq_buff = adc3_seq_buff, + .seq_channel_list = adc3_seq_channel_list, + /* preemption mode */ + #elif CONFIG_HPM_ADC3_CONV_MODE == 3 + .pmt_cfg = { + .trig_ch = BOARD_APP_PMT_START_POS, + .trig_len = sizeof(adc3_trig_channel_list) + }, + .pmt_buff = adc3_pmt_buff, + .trig_channel_list = adc3_trig_channel_list + #else + #error "Not supported mode!" + #endif +}; +#endif + +static struct adc_dev_s g_adc_dev[] = +{ + #if defined(CONFIG_HPM_ADC3) && CONFIG_HPM_ADC3 + { + .ad_ops = &g_adc_ops, + .ad_priv = &g_adc3_priv + }, + #endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void init_trigger_cfg(struct adc_dev_s *dev, uint8_t trig_ch, bool inten) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->ad_priv; + + for (int i = 0; i < priv->pmt_cfg.trig_len; i++) { + priv->pmt_cfg.adc_ch[i] = priv->trig_channel_list[i]; + priv->pmt_cfg.inten[i] = false; + } + + priv->pmt_cfg.inten[priv->pmt_cfg.trig_len - 1] = inten; + + adc16_set_pmt_config(priv->base, &priv->pmt_cfg); +} + +static void init_common_config(struct adc_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->ad_priv; + + if (priv->cfg.conv_mode == adc16_conv_mode_sequence || priv->cfg.conv_mode == adc16_conv_mode_preemption) { + priv->cfg.adc_ahb_en = true; + } + + #if defined(CONFIG_HPM_ADC3_NON_BLOCKING_READ) && CONFIG_HPM_ADC3_NON_BLOCKING_READ + priv->cfg.wait_dis = true; + #else + priv->cfg.wait_dis = false; + #endif + + adc16_init(priv->base, &priv->cfg); + up_enable_irq(priv->irq); +} + +static void init_oneshot_config(struct adc_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->ad_priv; + + adc16_init_channel(priv->base, &priv->ch_cfg); +} + +static void init_period_config(struct adc_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->ad_priv; + + adc16_init_channel(priv->base, &priv->ch_cfg); + adc16_set_prd_config(priv->base, &priv->prd_cfg); +} + +static void init_sequence_config(struct adc_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->ad_priv; + + for (int i = 0; i < priv->seq_cfg.seq_len; i++) { + priv->ch_cfg.ch = priv->seq_channel_list[i]; + adc16_init_channel(priv->base, &priv->ch_cfg); + } + + for (int i = 0; i < priv->seq_cfg.seq_len; i++) { + priv->seq_cfg.queue[i].seq_int_en = 0; + priv->seq_cfg.queue[i].ch = priv->seq_channel_list[i]; + } + + /* Initialize a sequence */ + adc16_set_seq_config(priv->base, &priv->seq_cfg); + + /* Set DMA config */ + priv->dma_cfg.start_addr = (uint32_t *)core_local_mem_to_sys_address(BOARD_APP_CORE, (uint32_t)priv->seq_buff); + + /* Initialize DMA for the sequence mode */ + adc16_init_seq_dma(priv->base, &priv->dma_cfg); + + /* Set interrupt mask */ + priv->mask = adc16_event_seq_full_complete; +} + +static void init_preemption_config(struct adc_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->ad_priv; + + for (int i = 0; i < priv->pmt_cfg.trig_len; i++) { + priv->ch_cfg.ch = priv->trig_channel_list[i]; + adc16_init_channel(priv->base, &priv->ch_cfg); + } + + /* Trigger config initialization */ + init_trigger_cfg(dev, priv->pmt_cfg.trig_ch, true); + + /* Set DMA start address for preemption mode */ + adc16_init_pmt_dma(priv->base, core_local_mem_to_sys_address(BOARD_APP_CORE, (uint32_t)priv->pmt_buff)); + + /* Set interrupt mask */ + priv->mask = adc16_event_trig_complete; +} + + +static hpm_stat_t process_seq_data(struct adc_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->ad_priv; + adc16_seq_dma_data_t *dma_data = (adc16_seq_dma_data_t *)priv->seq_buff; + uint32_t len = priv->seq_cfg.seq_len; + + if (ADC16_IS_SEQ_DMA_BUFF_LEN_INVLAID(len)) { + return status_invalid_argument; + } + + for (int i = 0; i < len; i++) { + ainfo("Sequence Mode - %s - ", priv->name); + ainfo("Sequence Number:%02d ", dma_data[i].seq_num); + ainfo("Cycle Bit: %02d ", dma_data[i].cycle_bit); + ainfo("ADC Channel: %02d ", dma_data[i].adc_ch); + ainfo("Result: 0x%04x\n", dma_data[i].result); + } + + return status_success; +} + +static hpm_stat_t process_pmt_data(struct adc_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->ad_priv; + adc16_pmt_dma_data_t *dma_data = (adc16_pmt_dma_data_t *)priv->pmt_buff; + int start_pos = priv->pmt_cfg.trig_ch * sizeof(adc16_pmt_dma_data_t); + uint32_t len = priv->pmt_cfg.trig_len; + + if (ADC16_IS_PMT_DMA_BUFF_LEN_INVLAID(len)) { + return status_invalid_argument; + } + + for (int i = start_pos; i < start_pos + len; i++) { + ainfo("Cycle Bit: %02d ", dma_data[i].cycle_bit); + if (dma_data[i].cycle_bit) { + ainfo("Preemption Mode - %s - ", priv->name); + ainfo("ADC Channel: %02d ", dma_data[i].adc_ch); + ainfo("Trig Index: %02d ", dma_data[i].trig_index); + ainfo("Trig Channel: %02d ", dma_data[i].trig_ch); + ainfo("Result: 0x%04x\n", dma_data[i].result); + dma_data[i].cycle_bit = 0; + } else { + ainfo("invalid data\n"); + } + } + + return status_success; +} + +static void sequence_handler(struct adc_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->ad_priv; + + /* SW trigger */ + adc16_trigger_seq_by_sw(priv->base); + + while (priv->seq_full_complete_flag == 0) { + + } + /* Process data */ + process_seq_data(dev); + + /* Clear the flag */ + priv->seq_full_complete_flag = 0; +} + +static void preemption_handler(struct adc_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->ad_priv; + + /* SW trigger */ + adc16_trigger_pmt_by_sw(priv->base, priv->pmt_cfg.trig_ch); + + /* Wait for a complete of conversion */ + while (priv->trig_complete_flag == 0) { + + } + + /* Process data */ + process_pmt_data(dev); + + /* Clear the flag */ + priv->trig_complete_flag = 0; +} + +static int adc_interrupt_handler(struct adc_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->ad_priv; + uint32_t status; + + status = adc16_get_status_flags(priv->base); + + if (ADC16_INT_STS_SEQ_CMPT_GET(status)) { + /* Clear seq_complete status */ + adc16_clear_status_flags(priv->base, adc16_event_seq_full_complete); + /* Set flag to read memory data */ + priv->seq_full_complete_flag = 1; + } + + if (ADC16_INT_STS_TRIG_CMPT_GET(status)) { + /* Clear trig_cmpt status */ + adc16_clear_status_flags(priv->base, adc16_event_trig_complete); + /* Set flag to read memory data */ + priv->trig_complete_flag = 1; + } + + return OK; +} + +/**************************************************************************** + * Name: adc_bind + * + * Description: + * Bind the upper-half driver callbacks to the lower-half implementation. + * This must be called early in order to receive ADC event notifications. + * + ****************************************************************************/ + +static int adc_bind(struct adc_dev_s *dev, const struct adc_callback_s *callback) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->ad_priv; + + DEBUGASSERT(priv != NULL); + if (priv == NULL) { + return -ENOBUFS; + } + priv->cb = callback; + + return OK; +} + +/**************************************************************************** + * Name: adc_reset + * + * Description: + * Reset the ADC device. Called early to initialize the hardware. This + * is called, before adc_setup() and on error conditions. + * + ****************************************************************************/ + +static void adc_reset(struct adc_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->ad_priv; + irqstate_t flags; + + flags = enter_critical_section(); + + /* ADC pin initialization */ + board_init_adc16_pins(); + + /* ADC clock initialization */ + board_init_adc16_clock(priv->base); + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: adc_setup + * + * Description: + * Configure the ADC. This method is called the first time that the ADC + * device is opened. This will occur when the port is first opened. + * This setup includes configuring and attaching ADC interrupts. + * Interrupts are all disabled upon return. + * + ****************************************************************************/ + +static int adc_setup(struct adc_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->ad_priv; + + /* Attach the ADC interrupt */ + int ret = irq_attach(priv->irq, priv->isr, dev); + if (ret < 0) { + ainfo("irq_attach failed: %d\n", ret); + return ret; + } + + up_enable_irq(priv->irq); + + /* ADC16 common initialization */ + init_common_config(dev); + + /* ADC16 read patter and DMA initialization */ + switch (priv->cfg.conv_mode) { + case adc16_conv_mode_oneshot: + init_oneshot_config(dev); + break; + + case adc16_conv_mode_period: + init_period_config(dev); + break; + + case adc16_conv_mode_sequence: + init_sequence_config(dev); + break; + + case adc16_conv_mode_preemption: + init_preemption_config(dev); + break; + + default: + break; + } + + return ret; +} + +/**************************************************************************** + * Name: adc_shutdown + * + * Description: + * Disable the ADC. This method is called when the ADC device is closed. + * This method reverses the operation the setup method. + * + ****************************************************************************/ + +static void adc_shutdown(struct adc_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->ad_priv; + + /* Disable ADC interrupts */ + up_disable_irq(priv->irq); + + /* Then detach the ADC interrupt handler. */ + irq_detach(priv->irq); +} + +/**************************************************************************** + * Name: adc_rxint + * + * Description: + * Call to enable or disable RX interrupts + * + ****************************************************************************/ + +static void adc_rxint(struct adc_dev_s *dev, bool enable) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->ad_priv; + + if (enable == true) { + priv->base->INT_EN |= priv->mask; + } else { + priv->base->INT_EN &= ~priv->mask; + } +} + +/**************************************************************************** + * Name: adc_ioctl + * + * Description: + * All ioctl calls will be routed through this method + * + ****************************************************************************/ + +static int adc_ioctl(struct adc_dev_s *dev, int cmd, unsigned long arg) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->ad_priv; + uint16_t result; + int cnt = 0; + int ret = OK; + + switch (cmd) { + case ANIOC_TRIGGER: + { + if (priv->cfg.conv_mode == adc16_conv_mode_oneshot) { + while (cnt++ < 10) { + if (adc16_get_oneshot_result(priv->base, priv->ch_cfg.ch, &result) == status_success) { + ainfo("oneshot mode: read result\n"); + priv->cb->au_receive(dev, priv->ch_cfg.ch, (int32_t)result); + break; + } + } + ret = cnt > 10 ? -EAGAIN : OK; + } else if (priv->cfg.conv_mode == adc16_conv_mode_period) { + ainfo("period mode: read result\n"); + up_mdelay(120); + adc16_get_prd_result(priv->base, priv->ch_cfg.ch, &result); + priv->cb->au_receive(dev, priv->ch_cfg.ch, (int32_t)result); + } else if (priv->cfg.conv_mode == adc16_conv_mode_sequence){ + adc16_seq_dma_data_t *dma_data = (adc16_seq_dma_data_t *)priv->seq_buff; + ainfo("sequence mode: read reuslt\n"); + sequence_handler(dev); + priv->cb->au_receive(dev, dma_data[BOARD_APP_SEQ_START_POS].adc_ch, (int32_t)dma_data[BOARD_APP_SEQ_START_POS].result); + } else if (priv->cfg.conv_mode == adc16_conv_mode_preemption) { + adc16_pmt_dma_data_t *dma_data = (adc16_pmt_dma_data_t *)priv->pmt_buff; + uint32_t offset = priv->pmt_cfg.trig_ch * sizeof(adc16_pmt_dma_data_t); + ainfo("preemption mode: read reuslt\n"); + preemption_handler(dev); + priv->cb->au_receive(dev, dma_data[offset].adc_ch, (int32_t)dma_data[offset].result); + } else { + ret = -EINVAL; + } + break; + } + default: break; + } + + return ret; +} + +/**************************************************************************** + * Name: adc_interrupt + * + * Description: + * ADC interrupt handler + * + ****************************************************************************/ + +static int adc_interrupt(int irq, void *context, void *arg) +{ + struct adc_dev_s *dev = (struct adc_dev_s *)arg; + adc_interrupt_handler(dev); + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: hpm_adcinitialize + * + * Description: + * Initialize the adc + * + * Returned Value: + * Valid adc device structure reference on success; a NULL on failure + * + ****************************************************************************/ +int hpm_adc16_setup(void) +{ + static bool initialized = false; + int ret; + + /* Check if we have already initialized */ + if (!initialized) + { + /* Register the ADC driver at "/dev/adcx" */ + for (int i = 0; i < sizeof(g_adc_dev) / sizeof(g_adc_dev[0]); i++) { + ret = adc_register(((struct up_dev_s *)(g_adc_dev[i].ad_priv))->path, &g_adc_dev[i]); + if (ret < 0) + { + aerr("ERROR: adc_register failed: %d\n", ret); + return ret; + } + } + /* Now we are initialized */ + initialized = true; + } + + return OK; +} + +#endif \ No newline at end of file diff --git a/arch/risc-v/src/hpmicro/hpm6750/hpm_adc16.h b/arch/risc-v/src/hpmicro/hpm6750/hpm_adc16.h new file mode 100644 index 0000000000000..3bf7dd0f8a73f --- /dev/null +++ b/arch/risc-v/src/hpmicro/hpm6750/hpm_adc16.h @@ -0,0 +1,60 @@ +/**************************************************************************** + * arch/risc-v/src/hpmicro/hpm6750/hpm_adc16.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_SRC_HPMICRO_HPM6750_HPM_ADC16_H +#define __ARCH_RISCV_SRC_HPMICRO_HPM6750_HPM_ADC16_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +EXTERN int hpm_adc16_setup(void); +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ +#if defined(__cplusplus) +} +#endif +#undef EXTERN + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_RISCV_SRC_HPMICRO_HPM6750_HPM_ADC16_H */ diff --git a/boards/risc-v/hpmicro/hpm6750evk2-sdk/configs/adc/defconfig b/boards/risc-v/hpmicro/hpm6750evk2-sdk/configs/adc/defconfig new file mode 100644 index 0000000000000..daee5f2c4bd1b --- /dev/null +++ b/boards/risc-v/hpmicro/hpm6750evk2-sdk/configs/adc/defconfig @@ -0,0 +1,99 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_ARCH_LEDS is not set +# CONFIG_DISABLE_ENVIRON is not set +# CONFIG_DISABLE_PTHREAD is not set +# CONFIG_FS_PROCFS_EXCLUDE_BLOCKS is not set +# CONFIG_FS_PROCFS_EXCLUDE_ENVIRON is not set +# CONFIG_FS_PROCFS_EXCLUDE_MEMDUMP is not set +# CONFIG_FS_PROCFS_EXCLUDE_MEMINFO is not set +# CONFIG_FS_PROCFS_EXCLUDE_MOUNT is not set +# CONFIG_FS_PROCFS_EXCLUDE_MOUNTS is not set +# CONFIG_FS_PROCFS_EXCLUDE_PROCESS is not set +# CONFIG_FS_PROCFS_EXCLUDE_UPTIME is not set +# CONFIG_FS_PROCFS_EXCLUDE_USAGE is not set +# CONFIG_FS_PROCFS_EXCLUDE_VERSION is not set +# CONFIG_HPM_SDP is not set +# CONFIG_NSH_DISABLEBG is not set +# CONFIG_NSH_DISABLE_CAT is not set +# CONFIG_NSH_DISABLE_CD is not set +# CONFIG_NSH_DISABLE_ECHO is not set +# CONFIG_NSH_DISABLE_ENV is not set +# CONFIG_NSH_DISABLE_EXEC is not set +# CONFIG_NSH_DISABLE_FREE is not set +# CONFIG_NSH_DISABLE_HELP is not set +# CONFIG_NSH_DISABLE_KILL is not set +# CONFIG_NSH_DISABLE_LOSMART is not set +# CONFIG_NSH_DISABLE_LS is not set +# CONFIG_NSH_DISABLE_MOUNT is not set +# CONFIG_NSH_DISABLE_PRINTF is not set +# CONFIG_NSH_DISABLE_PS is not set +# CONFIG_NSH_DISABLE_PWD is not set +# CONFIG_NSH_DISABLE_SLEEP is not set +# CONFIG_NSH_DISABLE_UNAME is not set +# CONFIG_NSH_DISABLE_USLEEP is not set +# CONFIG_STANDARD_SERIAL is not set +CONFIG_ADC=y +CONFIG_ANALOG=y +CONFIG_ARCH="risc-v" +CONFIG_ARCH_BOARD="hpm6750evk2-sdk" +CONFIG_ARCH_BOARD_HPM6750EVK2_SDK=y +CONFIG_ARCH_CHIP="hpmicro" +CONFIG_ARCH_CHIP_HPM6750=y +CONFIG_ARCH_CHIP_HPMICRO=y +CONFIG_ARCH_INTERRUPTSTACK=8192 +CONFIG_ARCH_RISCV=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BOARD_LOOPSPERMSEC=10000 +CONFIG_BUILTIN=y +CONFIG_CAN=y +CONFIG_DEBUG_ANALOG=y +CONFIG_DEBUG_ANALOG_ERROR=y +CONFIG_DEBUG_ANALOG_INFO=y +CONFIG_DEBUG_ANALOG_WARN=y +CONFIG_DEBUG_ERROR=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEBUG_WARN=y +CONFIG_DEFAULT_SMALL=y +CONFIG_EXAMPLES_ADC=y +CONFIG_EXAMPLES_ADC_GROUPSIZE=1 +CONFIG_EXAMPLES_ADC_NSAMPLES=1 +CONFIG_EXAMPLES_ADC_SWTRIG=y +CONFIG_FS_BINFS=y +CONFIG_FS_PROCFS=y +CONFIG_HPM_ADC0=y +CONFIG_HPM_BUILD_TYPE_FLASH_XIP=y +CONFIG_HPM_FEMC=y +CONFIG_I2C=y +CONFIG_I2C_DRIVER=y +CONFIG_IDLETHREAD_STACKSIZE=8192 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INIT_STACKSIZE=8192 +CONFIG_INTELHEX_BINARY=y +CONFIG_LIBC_ENVPATH=y +CONFIG_LIBC_PERROR_STDOUT=y +CONFIG_LIBC_STRERROR=y +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=64 +CONFIG_NSH_STRERROR=y +CONFIG_PATH_INITIAL="/bin" +CONFIG_READLINE_CMD_HISTORY=y +CONFIG_READLINE_CMD_HISTORY_LEN=10 +CONFIG_READLINE_TABCOMPLETION=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_WAITPID=y +CONFIG_START_DAY=13 +CONFIG_START_MONTH=3 +CONFIG_START_YEAR=2023 +CONFIG_SYSTEM_NSH=y +CONFIG_UART0_RXBUFSIZE=128 +CONFIG_UART0_SERIAL_CONSOLE=y +CONFIG_UART0_TXBUFSIZE=128 diff --git a/boards/risc-v/hpmicro/hpm6750evk2-sdk/src/hpm6750_bringup.c b/boards/risc-v/hpmicro/hpm6750evk2-sdk/src/hpm6750_bringup.c index fe1b5ea83f679..0380181c3db9a 100644 --- a/boards/risc-v/hpmicro/hpm6750evk2-sdk/src/hpm6750_bringup.c +++ b/boards/risc-v/hpmicro/hpm6750evk2-sdk/src/hpm6750_bringup.c @@ -65,6 +65,14 @@ # include "hpm_rtc.h" #endif +#ifdef CONFIG_HPM_ADC12_DRV +# include "hpm_adc12.h" +#endif + +#ifdef CONFIG_HPM_ADC16_DRV +# include "hpm_adc16.h" +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -332,6 +340,23 @@ int hpm6750_bringup(void) rtc_initialize(0, lower); #endif +#ifdef CONFIG_HPM_ADC12_DRV + /* Initialize ADC12 and register the ADC driver. */ + ret = hpm_adc12_setup(); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: hpm_adc12_setup failed: %d\n", ret); + } +#endif + +#ifdef CONFIG_HPM_ADC16_DRV + /* Initialize ADC16 and register the ADC driver. */ + ret = hpm_adc16_setup(); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: hpm_adc16_setup failed: %d\n", ret); + } +#endif return ret; }