diff --git a/drivers/adc/adc_npcx.c b/drivers/adc/adc_npcx.c index 4bd81c9ef3..119a61f72a 100644 --- a/drivers/adc/adc_npcx.c +++ b/drivers/adc/adc_npcx.c @@ -28,23 +28,24 @@ LOG_MODULE_REGISTER(adc_npcx, CONFIG_ADC_LOG_LEVEL); #define ADC_REGULAR_GENDLY_VAL 0x0100 #define ADC_REGULAR_MEAST_VAL 0x0001 -/* ADC channel number */ -#define NPCX_ADC_CH_COUNT DT_INST_PROP(0, channel_count) - /* ADC targeted operating frequency (2MHz) */ #define NPCX_ADC_CLK 2000000 -/* ADC internal reference voltage (Unit:mV) */ -#define NPCX_ADC_VREF_VOL 2816 - /* ADC conversion mode */ #define NPCX_ADC_CHN_CONVERSION_MODE 0 #define NPCX_ADC_SCAN_CONVERSION_MODE 1 +/* Max channel number to be converted in ADCCS */ +#define NPCX_ADCCS_MAX_CHANNEL_COUNT 16 + #define ADC_NPCX_THRVAL_RESOLUTION 10 #define ADC_NPCX_THRVAL_MAX BIT_MASK(ADC_NPCX_THRVAL_RESOLUTION) +/* ADC threshold detection registers */ #define THRCTL(dev, ctl_no) (*((volatile uint16_t *) npcx_thrctl_reg(dev, ctl_no))) +#ifdef CONFIG_SOC_SERIES_NPCX4 +#define THEN(dev) (*((volatile uint16_t *) npcx_then_reg(dev))) +#endif /* Device config */ struct adc_npcx_config { @@ -52,10 +53,14 @@ struct adc_npcx_config { uintptr_t base; /* clock configuration */ struct npcx_clk_cfg clk_cfg; + /* the number of ADC channels */ + const uint8_t channel_count; /* amount of thresholds supported */ const uint8_t threshold_count; /* threshold control register offset */ const uint16_t threshold_reg_offset; + /* routine for configuring ADC's ISR */ + void (*irq_cfg_func)(void); const struct pinctrl_dev_config *pcfg; }; @@ -88,7 +93,7 @@ struct adc_npcx_threshold_data { * channels being used in repetitive mode in order to set ADC registers * back to threshold detection when adc_npcx_read is completed. */ - uint16_t repetitive_channels; + uint32_t repetitive_channels; /* * While threshold interruption is enabled, adc_npcx_read must disable * all active threshold running to avoid race condition, this variable @@ -98,11 +103,6 @@ struct adc_npcx_threshold_data { /* This array holds current configuration for each threshold. */ struct adc_npcx_threshold_control control[DT_INST_PROP(0, threshold_count)]; - /* - * Pointer of work queue thread to be notified when threshold assertion - * occurs. - */ - struct k_work_q *work_q; }; /* Driver data */ @@ -115,7 +115,7 @@ struct adc_npcx_data { * Bit-mask indicating the channels to be included in each sampling * of this sequence. */ - uint16_t channels; + uint32_t channels; /* ADC Device pointer used in api functions */ const struct device *adc_dev; uint16_t *buffer; @@ -129,6 +129,12 @@ struct adc_npcx_data { #endif }; +/* + * Pointer of internal work queue thread to be notified when threshold assertion + * occurs if CONFIG_ADC_CMP_NPCX_WORKQUEUE is enabled. + */ +struct k_work_q *work_q; + /* Driver convenience defines */ #define HAL_INSTANCE(dev) ((struct adc_reg *)((const struct adc_npcx_config *)(dev)->config)->base) @@ -150,6 +156,20 @@ static void adc_npcx_pm_policy_state_lock_put(struct adc_npcx_data *data) } #endif +static inline void adc_npcx_config_channels(const struct device *dev, uint32_t channels) +{ + const struct adc_npcx_config *config = dev->config; + struct adc_reg *const inst = HAL_INSTANCE(dev); + + inst->ADCCS = channels & BIT_MASK(NPCX_ADCCS_MAX_CHANNEL_COUNT); + + /* Only npcx4 and later series support over 16 ADC channels */ + if (config->channel_count > NPCX_ADCCS_MAX_CHANNEL_COUNT) { + inst->ADCCS2 = (channels >> NPCX_ADCCS_MAX_CHANNEL_COUNT) & + BIT_MASK(NPCX_ADCCS_MAX_CHANNEL_COUNT); + } +} + static inline uint32_t npcx_thrctl_reg(const struct device *dev, uint32_t ctl_no) { @@ -158,6 +178,34 @@ static inline uint32_t npcx_thrctl_reg(const struct device *dev, return (config->base + config->threshold_reg_offset) + (ctl_no - 1) * 2; } +#ifdef CONFIG_SOC_SERIES_NPCX4 +static inline uint32_t npcx_then_reg(const struct device *dev) +{ + const struct adc_npcx_config *config = dev->config; + + return (config->base + config->threshold_reg_offset + 0x10); +} +#endif + +static inline void adc_npcx_enable_threshold_detect(const struct device *dev, uint8_t th_sel, + bool enable) +{ + if (enable) { +#ifdef CONFIG_SOC_SERIES_NPCX4 + THEN(dev) |= BIT(th_sel); +#else + THRCTL(dev, (th_sel + 1)) |= BIT(NPCX_THRCTL_THEN); +#endif + + } else { +#ifdef CONFIG_SOC_SERIES_NPCX4 + THEN(dev) &= ~BIT(th_sel); +#else + THRCTL(dev, (th_sel + 1)) &= ~BIT(NPCX_THRCTL_THEN); +#endif + } +} + static void adc_npcx_isr(const struct device *dev) { const struct adc_npcx_config *config = dev->config; @@ -198,12 +246,12 @@ static void adc_npcx_isr(const struct device *dev) if (IS_ENABLED(CONFIG_ADC_CMP_NPCX) && t_data->active_thresholds) { /* Set repetitive channels back */ - inst->ADCCS = t_data->repetitive_channels; + adc_npcx_config_channels(dev, t_data->repetitive_channels); /* Start conversion */ inst->ADCCNF |= BIT(NPCX_ADCCNF_START); } else { /* Disable all channels */ - inst->ADCCS = 0; + adc_npcx_config_channels(dev, 0); /* Turn off ADC */ inst->ADCCNF &= ~(BIT(NPCX_ADCCNF_ADCEN)); @@ -231,9 +279,8 @@ static void adc_npcx_isr(const struct device *dev) inst->THRCTS = thrcts; if (t_data->control[i].work) { /* Notify work thread */ - k_work_submit_to_queue(t_data->work_q ? - t_data->work_q : &k_sys_work_q, - t_data->control[i].work); + k_work_submit_to_queue(work_q ? work_q : &k_sys_work_q, + t_data->control[i].work); } } } @@ -246,11 +293,12 @@ static void adc_npcx_isr(const struct device *dev) static int adc_npcx_validate_buffer_size(const struct device *dev, const struct adc_sequence *sequence) { + const struct adc_npcx_config *config = dev->config; uint8_t channels = 0; uint32_t mask; size_t needed; - for (mask = BIT(NPCX_ADC_CH_COUNT - 1); mask != 0; mask >>= 1) { + for (mask = BIT(config->channel_count - 1); mask != 0; mask >>= 1) { if (mask & sequence->channels) { channels++; } @@ -270,6 +318,7 @@ static int adc_npcx_validate_buffer_size(const struct device *dev, static void adc_npcx_start_scan(const struct device *dev) { + const struct adc_npcx_config *config = dev->config; struct adc_npcx_data *const data = dev->data; struct adc_reg *const inst = HAL_INSTANCE(dev); @@ -286,7 +335,7 @@ static void adc_npcx_start_scan(const struct device *dev) inst->ADCSTS |= BIT(NPCX_ADCSTS_EOCCEV); /* Update selected channels in scan mode by channels mask */ - inst->ADCCS |= data->channels; + adc_npcx_config_channels(dev, data->channels); /* Select 'Scan' Conversion mode. */ SET_FIELD(inst->ADCCNF, NPCX_ADCCNF_ADCMD_FIELD, @@ -298,18 +347,24 @@ static void adc_npcx_start_scan(const struct device *dev) /* Start conversion */ inst->ADCCNF |= BIT(NPCX_ADCCNF_START); - LOG_DBG("Start ADC scan conversion and ADCCNF,ADCCS are (%04X,%04X)\n", + if (config->channel_count > NPCX_ADCCS_MAX_CHANNEL_COUNT) { + LOG_DBG("Start ADC scan conversion and ADCCNF,ADCCS, ADCCS2 are " + "(%04X,%04X,%04X)\n", inst->ADCCNF, inst->ADCCS, inst->ADCCS2); + } else { + LOG_DBG("Start ADC scan conversion and ADCCNF,ADCCS are (%04X,%04X)\n", inst->ADCCNF, inst->ADCCS); + } } static int adc_npcx_start_read(const struct device *dev, const struct adc_sequence *sequence) { + const struct adc_npcx_config *config = dev->config; struct adc_npcx_data *const data = dev->data; int error = 0; if (!sequence->channels || - (sequence->channels & ~BIT_MASK(NPCX_ADC_CH_COUNT))) { + (sequence->channels & ~BIT_MASK(config->channel_count))) { LOG_ERR("Invalid ADC channels"); return -EINVAL; } @@ -364,9 +419,10 @@ static void adc_context_update_buffer_pointer(struct adc_context *ctx, static int adc_npcx_channel_setup(const struct device *dev, const struct adc_channel_cfg *channel_cfg) { + const struct adc_npcx_config *config = dev->config; uint8_t channel_id = channel_cfg->channel_id; - if (channel_id >= NPCX_ADC_CH_COUNT) { + if (channel_id >= config->channel_count) { LOG_ERR("Invalid channel %d", channel_id); return -EINVAL; } @@ -443,18 +499,21 @@ static void adc_npcx_set_repetitive(const struct device *dev, int chnsel, /* Set ADC conversion code to SW conversion mode */ SET_FIELD(inst->ADCCNF, NPCX_ADCCNF_ADCMD_FIELD, NPCX_ADC_SCAN_CONVERSION_MODE); - /* Update number of channel to be converted */ - inst->ADCCS |= BIT(chnsel); + + /* Add selected ADC channel to be converted */ + t_data->repetitive_channels |= BIT(chnsel); + adc_npcx_config_channels(dev, t_data->repetitive_channels); + /* Set conversion type to repetitive (runs continuously) */ inst->ADCCNF |= BIT(NPCX_ADCCNF_ADCRPTC); - t_data->repetitive_channels |= BIT(chnsel); /* Start conversion */ inst->ADCCNF |= BIT(NPCX_ADCCNF_START); } else { - inst->ADCCS &= ~BIT(chnsel); - + /* Remove selected ADC channel to be converted */ t_data->repetitive_channels &= ~BIT(chnsel); + adc_npcx_config_channels(dev, t_data->repetitive_channels); + if (!t_data->repetitive_channels) { /* No thesholdd active left, disable repetitive mode */ inst->ADCCNF &= ~BIT(NPCX_ADCCNF_ADCRPTC); @@ -493,7 +552,7 @@ int adc_npcx_threshold_ctrl_set_param(const struct device *dev, adc_context_lock(&data->ctx, false, NULL); switch (param->type) { case ADC_NPCX_THRESHOLD_PARAM_CHNSEL: - if (param->val >= NPCX_ADC_CH_COUNT) { + if (param->val >= config->channel_count) { ret = -EINVAL; break; } @@ -530,6 +589,7 @@ static int adc_npcx_threshold_ctrl_setup(const struct device *dev, const uint8_t th_sel) { struct adc_npcx_data *const data = dev->data; + struct adc_driver_api *api = (struct adc_driver_api *)dev->api; struct adc_npcx_threshold_data *const t_data = data->threshold_data; const struct adc_npcx_config *config = dev->config; struct adc_npcx_threshold_control *const t_ctrl = @@ -548,8 +608,8 @@ static int adc_npcx_threshold_ctrl_setup(const struct device *dev, return -EBUSY; } - if (t_ctrl->chnsel >= NPCX_ADC_CH_COUNT || - t_ctrl->thrval >= NPCX_ADC_VREF_VOL || + if (t_ctrl->chnsel >= config->channel_count || + t_ctrl->thrval >= api->ref_internal || t_ctrl->thrval == 0 || t_ctrl->work == 0) { adc_context_release(&data->ctx, 0); LOG_ERR("Threshold selected (%d) is not configured!", th_sel); @@ -576,6 +636,7 @@ static int adc_npcx_threshold_enable_irq(const struct device *dev, const uint8_t th_sel) { struct adc_reg *const inst = HAL_INSTANCE(dev); + struct adc_driver_api *api = (struct adc_driver_api *)dev->api; struct adc_npcx_data *const data = dev->data; const struct adc_npcx_config *config = dev->config; struct adc_npcx_threshold_data *const t_data = data->threshold_data; @@ -589,8 +650,8 @@ static int adc_npcx_threshold_enable_irq(const struct device *dev, } adc_context_lock(&data->ctx, false, NULL); - if (t_ctrl->chnsel >= NPCX_ADC_CH_COUNT || - t_ctrl->thrval >= NPCX_ADC_VREF_VOL || + if (t_ctrl->chnsel >= config->channel_count || + t_ctrl->thrval >= api->ref_internal || t_ctrl->thrval == 0 || t_ctrl->work == 0) { adc_context_release(&data->ctx, 0); LOG_ERR("Threshold selected (%d) is not configured!", th_sel); @@ -604,7 +665,7 @@ static int adc_npcx_threshold_enable_irq(const struct device *dev, thrcts = inst->THRCTS & ~GENMASK(config->threshold_count - 1, 0); /* Enable threshold detection */ - THRCTL(dev, (th_sel + 1)) |= BIT(NPCX_THRCTL_THEN); + adc_npcx_enable_threshold_detect(dev, th_sel, true); /* clear threshold status */ thrcts |= BIT(th_sel); @@ -652,7 +713,7 @@ int adc_npcx_threshold_disable_irq(const struct device *dev, inst->THRCTS = thrcts; /* Disable threshold detection */ - THRCTL(dev, (th_sel + 1)) &= ~BIT(NPCX_THRCTL_THEN); + adc_npcx_enable_threshold_detect(dev, th_sel, false); /* Update active threshold */ t_data->active_thresholds &= ~BIT(th_sel); @@ -687,53 +748,24 @@ int adc_npcx_threshold_ctrl_enable(const struct device *dev, uint8_t th_sel, return ret; } -int adc_npcx_threshold_mv_to_thrval(uint32_t val_mv, uint32_t *thrval) +int adc_npcx_threshold_mv_to_thrval(const struct device *dev, uint32_t val_mv, + uint32_t *thrval) { + struct adc_driver_api *api = (struct adc_driver_api *)dev->api; + if (!IS_ENABLED(CONFIG_ADC_CMP_NPCX)) { return -EOPNOTSUPP; } - if (val_mv >= NPCX_ADC_VREF_VOL) { + if (val_mv >= api->ref_internal) { return -EINVAL; } *thrval = (val_mv << ADC_NPCX_THRVAL_RESOLUTION) / - NPCX_ADC_VREF_VOL; + api->ref_internal; return 0; } -/* ADC driver registration */ -static const struct adc_driver_api adc_npcx_driver_api = { - .channel_setup = adc_npcx_channel_setup, - .read = adc_npcx_read, -#if defined(CONFIG_ADC_ASYNC) - .read_async = adc_npcx_read_async, -#endif - .ref_internal = NPCX_ADC_VREF_VOL, -}; - -static int adc_npcx_init(const struct device *dev); - -PINCTRL_DT_INST_DEFINE(0); -BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 1, - "only one 'nuvoton_npcx_adc' compatible node may be present"); - -static const struct adc_npcx_config adc_npcx_cfg_0 = { - .base = DT_INST_REG_ADDR(0), - .clk_cfg = NPCX_DT_CLK_CFG_ITEM(0), - .threshold_count = DT_INST_PROP(0, threshold_count), - .threshold_reg_offset = DT_INST_PROP(0, threshold_reg_offset), - .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(0), -}; - -static struct adc_npcx_threshold_data threshold_data_0; - -static struct adc_npcx_data adc_npcx_data_0 = { - ADC_CONTEXT_INIT_TIMER(adc_npcx_data_0, ctx), - ADC_CONTEXT_INIT_LOCK(adc_npcx_data_0, ctx), - ADC_CONTEXT_INIT_SYNC(adc_npcx_data_0, ctx), -}; - #if defined(CONFIG_ADC_CMP_NPCX_WORKQUEUE) struct k_work_q adc_npcx_work_q; @@ -752,20 +784,13 @@ static int adc_npcx_init_cmp_work_q(void) K_KERNEL_STACK_SIZEOF(adc_npcx_work_q_stack), CONFIG_ADC_CMP_NPCX_WORKQUEUE_PRIORITY, &cfg); - threshold_data_0.work_q = &adc_npcx_work_q; + work_q = &adc_npcx_work_q; return 0; } SYS_INIT(adc_npcx_init_cmp_work_q, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY); #endif -DEVICE_DT_INST_DEFINE(0, - adc_npcx_init, NULL, - &adc_npcx_data_0, &adc_npcx_cfg_0, - PRE_KERNEL_1, - CONFIG_ADC_INIT_PRIORITY, - &adc_npcx_driver_api); - static int adc_npcx_init(const struct device *dev) { const struct adc_npcx_config *const config = dev->config; @@ -814,14 +839,8 @@ static int adc_npcx_init(const struct device *dev) inst->GENDLY = ADC_REGULAR_GENDLY_VAL; inst->MEAST = ADC_REGULAR_MEAST_VAL; - if (IS_ENABLED(CONFIG_ADC_CMP_NPCX)) { - data->threshold_data = &threshold_data_0; - } - /* Configure ADC interrupt and enable it */ - IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), adc_npcx_isr, - DEVICE_DT_INST_GET(0), 0); - irq_enable(DT_INST_IRQN(0)); + config->irq_cfg_func(); /* Initialize mutex of ADC channels */ adc_context_unlock_unconditionally(&data->ctx); @@ -835,3 +854,46 @@ static int adc_npcx_init(const struct device *dev) return 0; } + +#define NPCX_ADC_INIT(n) \ + \ + static void adc_npcx_irq_cfg_func_##n(void) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), \ + adc_npcx_isr, DEVICE_DT_INST_GET(n), 0); \ + irq_enable(DT_INST_IRQN(n)); \ + } \ + \ + static const struct adc_driver_api adc_npcx_driver_api_##n = { \ + .channel_setup = adc_npcx_channel_setup, \ + .read = adc_npcx_read, \ + .ref_internal = DT_INST_PROP(n, vref_mv), \ + IF_ENABLED(CONFIG_ADC_ASYNC, \ + (.read_async = adc_npcx_read_async,)) \ + }; \ + \ + PINCTRL_DT_INST_DEFINE(n); \ + \ + static const struct adc_npcx_config adc_npcx_cfg_##n = { \ + .base = DT_INST_REG_ADDR(n), \ + .clk_cfg = NPCX_DT_CLK_CFG_ITEM(n), \ + .channel_count = DT_INST_PROP(n, channel_count), \ + .threshold_count = DT_INST_PROP(n, threshold_count), \ + .threshold_reg_offset = DT_INST_PROP(n, threshold_reg_offset), \ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + .irq_cfg_func = adc_npcx_irq_cfg_func_##n, \ + }; \ + static struct adc_npcx_threshold_data threshold_data_##n; \ + static struct adc_npcx_data adc_npcx_data_##n = { \ + ADC_CONTEXT_INIT_TIMER(adc_npcx_data_##n, ctx), \ + ADC_CONTEXT_INIT_LOCK(adc_npcx_data_##n, ctx), \ + ADC_CONTEXT_INIT_SYNC(adc_npcx_data_##n, ctx), \ + .threshold_data = &threshold_data_##n, \ + }; \ + DEVICE_DT_INST_DEFINE(n, \ + adc_npcx_init, NULL, \ + &adc_npcx_data_##n, &adc_npcx_cfg_##n, \ + PRE_KERNEL_1, CONFIG_ADC_INIT_PRIORITY, \ + &adc_npcx_driver_api_##n); + +DT_INST_FOREACH_STATUS_OKAY(NPCX_ADC_INIT) diff --git a/drivers/sensor/nuvoton_adc_cmp_npcx/adc_cmp_npcx.c b/drivers/sensor/nuvoton_adc_cmp_npcx/adc_cmp_npcx.c index 1aa694f6b4..5294c8fd3b 100644 --- a/drivers/sensor/nuvoton_adc_cmp_npcx/adc_cmp_npcx.c +++ b/drivers/sensor/nuvoton_adc_cmp_npcx/adc_cmp_npcx.c @@ -92,7 +92,7 @@ static int adc_cmp_npcx_init(const struct device *dev) if (config->thr_mv != ADC_CMP_NPCX_UNDEFINED) { param.type = ADC_NPCX_THRESHOLD_PARAM_THVAL; /* Convert from millivolts to ADC raw register value */ - ret = adc_npcx_threshold_mv_to_thrval(config->thr_mv, + ret = adc_npcx_threshold_mv_to_thrval(config->adc, config->thr_mv, ¶m.val); if (ret) { goto init_error; @@ -135,7 +135,7 @@ static int adc_cmp_npcx_set_threshold(const struct device *dev, bool is_upper, param.type = ADC_NPCX_THRESHOLD_PARAM_THVAL; if (is_mv) { - ret = adc_npcx_threshold_mv_to_thrval(value, ¶m.val); + ret = adc_npcx_threshold_mv_to_thrval(config->adc, value, ¶m.val); if (ret) { return ret; } diff --git a/dts/arm/nuvoton/npcx/npcx.dtsi b/dts/arm/nuvoton/npcx/npcx.dtsi index 46abbb44e8..c1a77c4fe6 100644 --- a/dts/arm/nuvoton/npcx/npcx.dtsi +++ b/dts/arm/nuvoton/npcx/npcx.dtsi @@ -350,6 +350,7 @@ reg = <0x400d1000 0x2000>; interrupts = <10 3>; clocks = <&pcc NPCX_CLOCK_BUS_APB1 NPCX_PWDWN_CTL4 4>; + vref-mv = <2816>; status = "disabled"; }; diff --git a/dts/arm/nuvoton/npcx/npcx4.dtsi b/dts/arm/nuvoton/npcx/npcx4.dtsi index d8c0307c4f..d1b5c7439e 100644 --- a/dts/arm/nuvoton/npcx/npcx4.dtsi +++ b/dts/arm/nuvoton/npcx/npcx4.dtsi @@ -263,6 +263,20 @@ threshold-count = <6>; }; + /* ADC1 which reference voltage is AVCC */ + adc1: adc@400d5000 { + compatible = "nuvoton,npcx-adc"; + #io-channel-cells = <1>; + reg = <0x400d5000 0x2000>; + interrupts = <22 3>; + clocks = <&pcc NPCX_CLOCK_BUS_APB1 NPCX_PWDWN_CTL4 3>; + vref-mv = <3300>; + channel-count = <26>; + threshold-reg-offset = <0x80>; + threshold-count = <6>; + status = "disabled"; + }; + /* FIU0 configuration in npcx4 series */ qspi_fiu0: quadspi@40020000 { clocks = <&pcc NPCX_CLOCK_BUS_FIU0 NPCX_PWDWN_CTL8 5>; diff --git a/dts/bindings/adc/nuvoton,npcx-adc.yaml b/dts/bindings/adc/nuvoton,npcx-adc.yaml index 78701bdc81..11c4d1c21d 100644 --- a/dts/bindings/adc/nuvoton,npcx-adc.yaml +++ b/dts/bindings/adc/nuvoton,npcx-adc.yaml @@ -16,6 +16,10 @@ properties: required: true pinctrl-names: required: true + vref-mv: + type: int + required: true + description: ADC reference voltage (Unit:mV) channel-count: type: int required: true diff --git a/include/zephyr/drivers/adc/adc_npcx_threshold.h b/include/zephyr/drivers/adc/adc_npcx_threshold.h index 0d2b3954a4..4254baa458 100644 --- a/include/zephyr/drivers/adc/adc_npcx_threshold.h +++ b/include/zephyr/drivers/adc/adc_npcx_threshold.h @@ -41,13 +41,15 @@ struct adc_npcx_threshold_param { * @note This function is available only if @kconfig{CONFIG_ADC_CMP_NPCX} * is selected. * + * @param dev Pointer to the device structure for the driver instance. * @param val_mv Input value in millivolts to be converted. * @param thrval Pointer of variable to hold the result of conversion. * * @returns 0 on success, negative result if input cannot be converted due to * overflow. */ -int adc_npcx_threshold_mv_to_thrval(uint32_t val_mv, uint32_t *thrval); +int adc_npcx_threshold_mv_to_thrval(const struct device *dev, uint32_t val_mv, + uint32_t *thrval); /** * @brief Set ADC threshold parameter. diff --git a/soc/arm/nuvoton_npcx/common/reg/reg_def.h b/soc/arm/nuvoton_npcx/common/reg/reg_def.h index afcb0597f1..3f50d36495 100644 --- a/soc/arm/nuvoton_npcx/common/reg/reg_def.h +++ b/soc/arm/nuvoton_npcx/common/reg/reg_def.h @@ -566,7 +566,9 @@ struct adc_reg { volatile uint16_t ASCADD; /* 0x008: ADC Scan Channels Select */ volatile uint16_t ADCCS; - volatile uint8_t reserved1[16]; + /* 0x00A: ADC Scan Channels Select 2 */ + volatile uint16_t ADCCS2; + volatile uint8_t reserved1[14]; /* 0x01A: Threshold Status */ volatile uint16_t THRCTS; volatile uint8_t reserved2[4]; @@ -604,10 +606,16 @@ static inline uint32_t npcx_chndat_offset(uint32_t ch) #define NPCX_ADCCNF_STOP 11 #define NPCX_CHNDAT_CHDAT_FIELD FIELD(0, 10) #define NPCX_CHNDAT_NEW 15 +#ifdef CONFIG_SOC_SERIES_NPCX4 +#define NPCX_THRCTL_L_H 15 +#define NPCX_THRCTL_CHNSEL FIELD(10, 5) +#define NPCX_THRCTL_THRVAL FIELD(0, 10) +#else #define NPCX_THRCTL_THEN 15 #define NPCX_THRCTL_L_H 14 #define NPCX_THRCTL_CHNSEL FIELD(10, 4) #define NPCX_THRCTL_THRVAL FIELD(0, 10) +#endif #define NPCX_THRCTS_ADC_WKEN 15 #define NPCX_THRCTS_THR3_IEN 10 #define NPCX_THRCTS_THR2_IEN 9