/** * @file analog_control.c * @brief Implementation of disabling analog mux of a channel/device/chip, * and enabling an analog mux of a channle. * * @copyright Copyright (c) 2025 Semidrive Semiconductor. * All rights reserved. */ #include #define ADC1_BASE APB_ADC1_BASE #define ADC2_BASE APB_ADC2_BASE #define ADC3_BASE APB_ADC3_BASE #define ACMP1_BASE APB_ACMP1_BASE #define ACMP2_BASE APB_ACMP2_BASE #define ACMP3_BASE APB_ACMP3_BASE #define ACMP4_BASE APB_ACMP4_BASE #define SCR_BASE APB_SCR_SF_BASE #include #include #define SCR_AMUX_DISABLE 1 #define SCR_AMUX_ENABLE 0 #define AMUX_CHNL_MIN 4 /* channel 0~3 has no mux on chip */ #define CHNL_MASK(chnl) ((chnl) & 0x7u) #define CHNL_2_POS(chnl) CHNL_MASK((chnl) >> 3) #define CHNL_2_NEG(chnl) CHNL_MASK(chnl) static struct chip_amux_scr *amux_scr_head = NULL; /* * Register a chip with its analog mux table to the chip list. */ void analog_chip_amux_register(struct chip_amux_scr *amux_scr) { struct chip_amux_scr **temp = &amux_scr_head; while (*temp) { if (*temp == amux_scr) { /* It is already registered. */ return; } temp = &(*temp)->next; } *temp = amux_scr; } /* * Disable all analog mux of a chip. */ void analog_chip_amux_init(struct chip_amux_scr *amux_scr) { sdrv_scr_t scr_ctrl; const struct channel_amux_scr *scr_array = NULL; uint32_t scr_len = 0; int i; int j; if (!amux_scr || !amux_scr->dev_amux) { return; } scr_ctrl.base = amux_scr->scr_base; for (i = 0; i < amux_scr->dev_amux_cnt; i++) { scr_array = amux_scr->dev_amux[i].chnl_amux; scr_len = amux_scr->dev_amux[i].chnl_amux_cnt; for (j = 0; j < scr_len; j++) { scr_set(&scr_ctrl, &scr_array[j].scr_sig, SCR_AMUX_DISABLE); } } } /* * Look for analog mux table and scr address of the specified device. */ static const struct device_amux_scr * analog_seek_dev_amux(uintptr_t ana_dev_base, sdrv_scr_t *scr_ctrl) { struct chip_amux_scr *chip = amux_scr_head; int i; while (chip) { for (i = 0; i < chip->dev_amux_cnt; i++) { if (chip->dev_amux[i].base == ana_dev_base) { scr_ctrl->base = chip->scr_base; return &chip->dev_amux[i]; } } chip = chip->next; } return NULL; } /* * Disable all analog mux of the specified device. */ void analog_dev_amux_init(uintptr_t ana_dev_base) { sdrv_scr_t scr_ctrl; const struct device_amux_scr *dev_amux; int i; dev_amux = analog_seek_dev_amux(ana_dev_base, &scr_ctrl); if (!dev_amux || !dev_amux->chnl_amux) { return; } for (i = 0; i < dev_amux->chnl_amux_cnt; i++) { scr_set(&scr_ctrl, &dev_amux->chnl_amux[i].scr_sig, SCR_AMUX_DISABLE); } } /* * Look for scr signal address of the specified channel. */ static const scr_signal_t * analog_seek_amux_scr(const struct device_amux_scr *dev_amux, uint16_t chnl) { int i; for (i = 0; i < dev_amux->chnl_amux_cnt; i++) { if (dev_amux->chnl_amux[i].chnl == chnl) { return &dev_amux->chnl_amux[i].scr_sig; } } return NULL; } /* * Enable or disable the analog mux which the channel belongs to. */ void analog_dev_chnl_amux_cfg(uintptr_t ana_dev_base, uint16_t chnl, bool enable) { sdrv_scr_t scr_ctrl; const struct device_amux_scr *dev_amux; const scr_signal_t *amux_scr; uint16_t chnl_pos = CHNL_2_POS(chnl); uint16_t chnl_neg = CHNL_2_NEG(chnl); uint32_t scr_val; if ((chnl_pos < AMUX_CHNL_MIN) && (chnl_neg < AMUX_CHNL_MIN)) { return; } dev_amux = analog_seek_dev_amux(ana_dev_base, &scr_ctrl); if (!dev_amux || !dev_amux->chnl_amux) { return; } scr_val = enable ? SCR_AMUX_ENABLE : SCR_AMUX_DISABLE; if (chnl_neg >= AMUX_CHNL_MIN) { /* Note: consider 6b'001xxx as a single positive channel. */ if (chnl_pos == SINGLE_CHNL_POSITIVE) { chnl_neg = ADC_ACMP_POS_CHNL(chnl_neg); } amux_scr = analog_seek_amux_scr(dev_amux, chnl_neg); if (amux_scr) { if (scr_get(&scr_ctrl, amux_scr) != scr_val) { scr_set(&scr_ctrl, amux_scr, scr_val); } } } if (chnl_pos >= AMUX_CHNL_MIN) { amux_scr = analog_seek_amux_scr(dev_amux, ADC_ACMP_POS_CHNL(chnl_pos)); if (amux_scr) { if (scr_get(&scr_ctrl, amux_scr) != scr_val) { scr_set(&scr_ctrl, amux_scr, scr_val); } } } } /* * Disable all analog mux of ADC/ACMP device. * And register their scr signals to the chip list. */ analog_init_func_def(analog_init) /* * Register all scr signals of a chip to the chip list. */ amux_register_func_def(analog_mux_register)