| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535 |
- /*
- * Copyright : (C) 2022 Phytium Information Technology, Inc.
- * All Rights Reserved.
- *
- * This program is OPEN SOURCE software: you can redistribute it and/or modify it
- * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
- * either version 1.0 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
- * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the Phytium Public License for more details.
- *
- *
- * FilePath: fadc.c
- * Date: 2022-02-10 14:53:42
- * LastEditTime: 2022-02-18 08:28:45
- * Description: This files is for
- *
- * Modify History:
- * Ver Who Date Changes
- * ----- ------ -------- --------------------------------------
- */
- #include <string.h>
- #include "fgeneric_timer.h"
- #include "fkernel.h"
- #include "ftypes.h"
- #include "ferror_code.h"
- #include "fdebug.h"
- #include "fadc.h"
- #include "fadc_hw.h"
- #include "fparameters.h"
- #include "fassert.h"
- #include "fsleep.h"
- #define FADC_DEBUG_TAG "FT_ADC"
- #define FADC_DEBUG(format, ...) FT_DEBUG_PRINT_D(FADC_DEBUG_TAG, format, ##__VA_ARGS__)
- #define FADC_INFO(format, ...) FT_DEBUG_PRINT_I(FADC_DEBUG_TAG, format, ##__VA_ARGS__)
- #define FADC_WARN(format, ...) FT_DEBUG_PRINT_W(FADC_DEBUG_TAG, format, ##__VA_ARGS__)
- #define FADC_ERROR(format, ...) FT_DEBUG_PRINT_E(FADC_DEBUG_TAG, format, ##__VA_ARGS__)
- #define FADC_MAX_CLOCK_PRESC 16
- #define FADC_MAX_THRESHOLD 0x400
- /**
- * @name: FAdcPowerDownControl
- * @msg: Set power down signal
- * @param {FAdcCtrl} *pctrl, pointer to a FAdcCtrl structure that contains
- * the configuration information for the specified adc module.
- * @param {u8} power_state, this parameter must be enable or disable.
- * @return err code information, FADC_SUCCESS indicates success,others indicates failed
- */
- static FError FAdcPowerDownControl(FAdcCtrl *pctrl, u8 power_state)
- {
- FASSERT(pctrl != NULL);
- FASSERT(FT_COMPONENT_IS_READY == pctrl->is_ready);
- u32 reg_val = 0;
- uintptr base_addr = pctrl->config.base_addr;
- reg_val = FADC_READ_REG32(base_addr, FADC_CTRL_REG_OFFSET);
- if (power_state == FADC_CTRL_PD_ENABLE)
- {
- reg_val |= FADC_CTRL_REG_PD_EN;
- }
- else
- {
- reg_val &= ~(FADC_CTRL_REG_PD_EN);
- }
- FADC_WRITE_REG32(base_addr, FADC_CTRL_REG_OFFSET, reg_val);
- return FADC_SUCCESS;
- }
- /**
- * @name: FAdcChannelEnable
- * @msg: enable channel, corresponding to fix channel mode or multi channel mode.
- * @param {FAdcCtrl} *pctrl, pointer to a FAdcCtrl structure that contains
- * the configuration information for the specified adc module.
- * @param {FAdcChannel} channel, adc channel number.
- * @param {boolean} state, TRUE-enable, FALSE-disable
- * @return void
- */
- void FAdcChannelEnable(FAdcCtrl *pctrl, FAdcChannel channel, boolean state)
- {
- FASSERT(pctrl != NULL);
- FASSERT(FT_COMPONENT_IS_READY == pctrl->is_ready);
- FASSERT(channel < FADC_CHANNEL_NUM);
- u32 reg_val = 0;
- uintptr base_addr = pctrl->config.base_addr;
- reg_val = FADC_READ_REG32(base_addr, FADC_CTRL_REG_OFFSET);
- if (state == TRUE)
- {
- if (reg_val & FADC_CTRL_REG_FIX_CHANNEL)
- {
- reg_val &= ~(FADC_CTRL_REG_FIX_CHANNEL_NUM_MASK);
- reg_val |= FADC_CTRL_REG_FIX_CHANNEL_NUM(channel);
- }
- else
- {
- reg_val |= FADC_CTRL_REG_CHANNEL_EN(channel);
- }
- }
- else
- {
- /* fix channel mode, disable means stop convert */
- if (reg_val & FADC_CTRL_REG_FIX_CHANNEL)
- {
- reg_val &= ~(FADC_CTRL_REG_SOC_EN);
- }
- else
- {
- reg_val &= ~(FADC_CTRL_REG_CHANNEL_EN(channel));
- }
- }
- FADC_WRITE_REG32(base_addr, FADC_CTRL_REG_OFFSET, reg_val);
- }
- /**
- * @name: FAdcChannelThresholdSet
- * @msg: Set adc channel high_threshold and low_threshold.
- * you need use this function after FAdcConvertSet. If you want to use this function to
- * add other channel enable when the adc conversion is started, you need to restart the
- * adc convert start signal(adc_soc_en) after use to make the operation valid.
- * @param {FAdcCtrl} *pctrl, pointer to a FAdcCtrl structure that contains
- * the configuration information for the specified adc module.
- * @param {FAdcChannel} channel, adc channel number.
- * @param {FAdcThresholdConfig} *threshold_config, pointer to adc channel threshold value struct.
- * @return err code information, FADC_SUCCESS indicates success,others indicates failed
- */
- FError FAdcChannelThresholdSet(FAdcCtrl *pctrl, FAdcChannel channel, FAdcThresholdConfig *threshold_config)
- {
- FASSERT(pctrl != NULL);
- FASSERT(FT_COMPONENT_IS_READY == pctrl->is_ready);
- FASSERT(channel < FADC_CHANNEL_NUM);
- u16 low_threshold = threshold_config->low_threshold;
- u16 high_threshold = threshold_config->high_threshold;
- FASSERT(high_threshold < FADC_MAX_THRESHOLD);
- FASSERT(low_threshold < high_threshold);
- uintptr base_addr = pctrl->config.base_addr;
- u32 threshold = (FADC_LEVEL_REG_HIGH_LEVEL(high_threshold)) |
- (FADC_LEVEL_REG_LOW_LEVEL(low_threshold));
- FADC_WRITE_REG32(base_addr, (FADC_LEVEL_REG_OFFSET(channel)), threshold);
- return FADC_SUCCESS;
- }
- /**
- * @name: FAdcConvertSet
- * @msg: config adc convert parameters.
- * @param {FAdcCtrl} *pctrl, pointer to a FAdcCtrl structure that contains
- * the configuration information for the specified adc module.
- * @param {FAdcConvertConfig} *convert_config, include convert mode,channel mode,
- * clock divider and convert_interval.
- * @return err code information, FADC_SUCCESS indicates success,others indicates failed
- */
- FError FAdcConvertSet(FAdcCtrl *pctrl, FAdcConvertConfig *convert_config)
- {
- FASSERT(pctrl != NULL);
- FASSERT(FT_COMPONENT_IS_READY == pctrl->is_ready);
- u32 reg_val = 0;
- uintptr base_addr = pctrl->config.base_addr;
- reg_val = FADC_READ_REG32(base_addr, FADC_CTRL_REG_OFFSET);
- /* clk_div config */
- u32 clk_div = convert_config->clk_div;
- FASSERT(clk_div < FADC_MAX_CLOCK_PRESC);
- if (clk_div % 2 == 1)
- {
- FADC_ERROR("clk_div is not even.");
- return FADC_ERR_INVAL_PARM;
- }
- reg_val &= (~FADC_CTRL_REG_CLK_DIV_MASK);
- reg_val |= FADC_CTRL_REG_CLK_DIV(clk_div);
- /* config convert mode */
- FAdcConvertMode convert_mode = convert_config->convert_mode;
- FASSERT(convert_mode < FADC_CONVERT_MODE_NUM);
- if (convert_mode == FADC_SINGLE_CONVERT)
- {
- reg_val |= FADC_CTRL_REG_SINGLE_CONVERT;
- }
- else
- {
- reg_val &= ~(FADC_CTRL_REG_SINGLE_CONVERT);
- }
- /* config channel mode */
- FAdcChannelMode channel_mode = convert_config->channel_mode;
- FASSERT(channel_mode < FADC_CHANNEL_MODE_NUM);
- if (channel_mode == FADC_FIXED_CHANNEL)
- {
- reg_val |= FADC_CTRL_REG_FIX_CHANNEL;
- }
- else
- {
- reg_val &= ~(FADC_CTRL_REG_FIX_CHANNEL);
- }
- FADC_WRITE_REG32(base_addr, FADC_CTRL_REG_OFFSET, reg_val);
- /* config time interval between two converts */
- FADC_WRITE_REG32(base_addr, FADC_INTER_REG_OFFSET, convert_config->convert_interval);
- return FADC_SUCCESS;
- }
- /**
- * @name: FAdcInterruptEnable
- * @msg: enable channel interrupt.
- * @param {FAdcCtrl} *pctrl, pointer to a FAdcCtrl structure that contains
- * the configuration information for the specified adc module.
- * @param {FAdcChannel} channel, adc channel number.
- * @param {FAdcIntrEvtType} event_type, interrupt event type
- * @return err code information, FADC_SUCCESS indicates success,others indicates failed
- */
- FError FAdcInterruptEnable(FAdcCtrl *pctrl, FAdcChannel channel, FAdcIntrEventType event_type)
- {
- FASSERT(pctrl != NULL);
- FASSERT(FT_COMPONENT_IS_READY == pctrl->is_ready);
- uintptr base_addr = pctrl->config.base_addr;
- u32 reg_val = 0;
- reg_val = FADC_READ_REG32(base_addr, FADC_INTRMASK_REG_OFFSET);
- switch (event_type)
- {
- case FADC_INTR_EVENT_COVFIN: /* enable channel convert complete irq */
- reg_val &= ~(FADC_INTRMASK_REG_COVFIN_MASK(channel));
- break;
- case FADC_INTR_EVENT_DLIMIT:
- reg_val &= ~(FADC_INTRMASK_REG_DLIMIT_MASK(channel));
- break;
- case FADC_INTR_EVENT_ULIMIT:
- reg_val &= ~(FADC_INTRMASK_REG_ULIMIT_MASK(channel));
- break;
- case FADC_INTR_EVENT_ERROR:
- reg_val &= ~(FADC_INTRMASK_REG_ERR_MASK);
- break;
- default:
- break;
- }
- FADC_WRITE_REG32(base_addr, FADC_INTRMASK_REG_OFFSET, reg_val);
- return FADC_SUCCESS;
- }
- /**
- * @name: FAdcInterruptDisable
- * @msg: disable channel interrupt.
- * @param {FAdcCtrl} *pctrl, pointer to a FAdcCtrl structure that contains
- * the configuration information for the specified adc module.
- * @param {FAdcChannel} channel, adc channel number.
- * @param {FAdcIntrEvtType} event_type, interrupt event type
- * @return err code information, FADC_SUCCESS indicates success,others indicates failed
- */
- FError FAdcInterruptDisable(FAdcCtrl *pctrl, FAdcChannel channel, FAdcIntrEventType event_type)
- {
- FASSERT(pctrl != NULL);
- FASSERT(FT_COMPONENT_IS_READY == pctrl->is_ready);
- FASSERT(channel < FADC_CHANNEL_NUM);
- uintptr base_addr = pctrl->config.base_addr;
- u32 reg_val = 0;
- reg_val = FADC_READ_REG32(base_addr, FADC_INTRMASK_REG_OFFSET);
- switch (event_type)
- {
- case FADC_INTR_EVENT_COVFIN: /* enable channel convert complete irq */
- reg_val |= (FADC_INTRMASK_REG_COVFIN_MASK(channel));
- break;
- case FADC_INTR_EVENT_DLIMIT:
- reg_val |= (FADC_INTRMASK_REG_DLIMIT_MASK(channel));
- break;
- case FADC_INTR_EVENT_ULIMIT:
- reg_val |= (FADC_INTRMASK_REG_ULIMIT_MASK(channel));
- break;
- case FADC_INTR_EVENT_ERROR:
- reg_val |= (FADC_INTRMASK_REG_ERR_MASK);
- break;
- default:
- break;
- }
- FADC_WRITE_REG32(base_addr, FADC_INTRMASK_REG_OFFSET, reg_val);
- return FADC_SUCCESS;
- }
- /**
- * @name: FAdcConvertStart
- * @msg: Start adc convert.
- * @param {FAdcCtrl} *pctrl, pointer to a FAdcCtrl structure that contains
- * the configuration information for the specified adc module.
- * @return
- */
- void FAdcConvertStart(FAdcCtrl *pctrl)
- {
- FASSERT(pctrl != NULL);
- FASSERT(FT_COMPONENT_IS_READY == pctrl->is_ready);
- u32 reg_val = 0;
- uintptr base_addr = pctrl->config.base_addr;
- reg_val = FADC_READ_REG32(base_addr, FADC_CTRL_REG_OFFSET);
- reg_val |= FADC_CTRL_REG_SOC_EN;
- FADC_WRITE_REG32(base_addr, FADC_CTRL_REG_OFFSET, reg_val);
- }
- /**
- * @name: FAdcConvertStop
- * @msg: Stop adc convert.
- * @param {FAdcCtrl} *pctrl, pointer to a FAdcCtrl structure that contains
- * the configuration information for the specified adc module.
- * @return
- */
- void FAdcConvertStop(FAdcCtrl *pctrl)
- {
- FASSERT(pctrl != NULL);
- FASSERT(FT_COMPONENT_IS_READY == pctrl->is_ready);
- u32 reg_val = 0;
- uintptr base_addr = pctrl->config.base_addr;
- reg_val = FADC_READ_REG32(base_addr, FADC_CTRL_REG_OFFSET);
- reg_val &= (~FADC_CTRL_REG_SOC_EN);
- FADC_WRITE_REG32(base_addr, FADC_CTRL_REG_OFFSET, reg_val);
- }
- /**
- * @name: FAdcInit
- * @msg: init adc variable configuration.
- * @param {FAdcCtrl} *pctrl, pointer to a FAdcCtrl structure that contains
- * the configuration information for the specified adc module.
- * @param {FAdcConvertConfig} *convert_config, pointer to adc convert configuration
- * @return err code information, FADC_SUCCESS indicates success,others indicates failed
- */
- FError FAdcVariableConfig(FAdcCtrl *pctrl, FAdcConvertConfig *convert_config)
- {
- FASSERT(pctrl != NULL);
- FASSERT(convert_config != NULL);
- FError ret = FADC_SUCCESS;
- /* disable power down signal */
- ret = FAdcPowerDownControl(pctrl, FADC_CTRL_PD_DISABLE);
- if (ret != FADC_SUCCESS)
- {
- FADC_ERROR("FAdcPowerDownControl failed.");
- return FADC_ERR_CMD_FAILED;
- }
- /* set time interval between two converts */
- ret = FAdcConvertSet(pctrl, convert_config);
- if (ret != FADC_SUCCESS)
- {
- FADC_ERROR("FAdcConvertSet failed.");
- return FADC_ERR_CMD_FAILED;
- }
- return ret;
- }
- /**
- * @name: FAdcSingleConvertEnable
- * @msg: Enable single convert signal, when convert mode is set to single conversion.
- * @param {FAdcCtrl} *pctrl, pointer to a FAdcCtrl structure that contains
- * the configuration information for the specified adc module.
- * @return err code information, FADC_SUCCESS indicates success,others indicates failed
- */
- static FError FAdcSingleConvertEnable(FAdcCtrl *pctrl)
- {
- FASSERT(pctrl != NULL);
- FASSERT(FT_COMPONENT_IS_READY == pctrl->is_ready);
- u32 reg_val = 0;
- uintptr base_addr = pctrl->config.base_addr;
- reg_val = FADC_READ_REG32(base_addr, FADC_CTRL_REG_OFFSET);
- reg_val |= FADC_CTRL_REG_SINGLE_CONVERT_EN;
- FADC_WRITE_REG32(base_addr, FADC_CTRL_REG_OFFSET, reg_val);
- return FADC_SUCCESS;
- }
- /**
- * @name: FAdcReadConvertResult
- * @msg: read adc channel convert result value.
- * @param {FAdcCtrl} *pctrl, pointer to a FAdcCtrl structure that contains
- * the configuration information for the specified adc module.
- * @param {FAdcChannel} channel, adc channel number.
- * @param {u16} *val, pointer to adc convert result value.
- * @return err code information, FADC_SUCCESS indicates success,others indicates failed.
- */
- FError FAdcReadConvertResult(FAdcCtrl *pctrl, FAdcChannel channel, u16 *val)
- {
- FASSERT(pctrl != NULL);
- FASSERT(channel < FADC_CHANNEL_NUM);
- FASSERT(FT_COMPONENT_IS_READY == pctrl->is_ready);
- int timeout = FADC_READ_DELAY;
- uintptr base_addr = pctrl->config.base_addr;
- u32 reg_val = FADC_READ_REG32(base_addr, FADC_CTRL_REG_OFFSET);
- /* single conversion */
- if (reg_val & FADC_CTRL_REG_SINGLE_CONVERT)
- {
- FAdcSingleConvertEnable(pctrl);
- }
- do
- {
- fsleep_millisec(10);
- }
- while ((!pctrl->convert_complete[channel]) && (0 <= --timeout));
- if (0 >= timeout)
- {
- FADC_ERROR("timeout when read adc data, convert is not completed.");
- *val = 0;
- return FADC_ERR_TIMEOUT;
- }
- FADC_CONVERT_UNCOMPLETE(pctrl->convert_complete[channel]);
- *val = pctrl->value[channel];
- return FADC_SUCCESS;
- }
- /**
- * @name: FAdcReadFinishCnt
- * @msg: read adc channel convert finish count.
- * @param {FAdcCtrl} *pctrl, pointer to a FAdcCtrl structure that contains
- * the configuration information for the specified adc module.
- * @param {FAdcChannel} channel, adc channel number.
- * @param {u32} *count, pointer to adc convert finish count.
- * @return err code information, FADC_SUCCESS indicates success,others indicates failed.
- */
- FError FAdcReadFinishCnt(FAdcCtrl *pctrl, FAdcChannel channel, u32 *count)
- {
- FASSERT(pctrl != NULL);
- FASSERT(FT_COMPONENT_IS_READY == pctrl->is_ready);
- uintptr base_addr = pctrl->config.base_addr;
- *count = FADC_READ_REG32(base_addr, FADC_FINISH_CNT_REG_OFFSET(channel));
- return FADC_SUCCESS;
- }
- /**
- * @name: FAdcReadHisLimit
- * @msg: read adc channel history limit value, include upper limit and lower limit.
- * @param {FAdcCtrl} *pctrl, pointer to a FAdcCtrl structure that contains
- * the configuration information for the specified adc module.
- * @param {FAdcChannel} channel, adc channel number.
- * @param {u16} *u_his_limit, pointer to adc convert history upper limit value.
- * @param {u16} *d_his_limit, pointer to adc convert history lower limit value.
- * @return err code information, FADC_SUCCESS indicates success,others indicates failed.
- */
- FError FAdcReadHisLimit(FAdcCtrl *pctrl, FAdcChannel channel, u16 *u_his_limit, u16 *d_his_limit)
- {
- FASSERT(pctrl != NULL);
- FASSERT(FT_COMPONENT_IS_READY == pctrl->is_ready);
- u32 reg_val = 0;
- uintptr base_addr = pctrl->config.base_addr;
- reg_val = FADC_READ_REG32(base_addr, FADC_HIS_LIMIT_REG_OFFSET(channel));
- *u_his_limit = (reg_val & FADC_HIS_LIMIT_REG_UMASK) >> 16;
- *d_his_limit = (reg_val & FADC_HIS_LIMIT_REG_DMASK) ;
- return FADC_SUCCESS;
- }
- /**
- * @name: FAdcDeInitialize
- * @msg: DeInitialization function for the device instance
- * @param {FAdcCtrl} *pctrl, instance of FADC controller
- * @return {*}
- */
- void FAdcDeInitialize(FAdcCtrl *pctrl)
- {
- FASSERT(pctrl);
- pctrl->is_ready = 0;
- memset(pctrl, 0, sizeof(*pctrl));
- return;
- }
- /**
- * @name: FAdcCfgInitialize
- * @msg: Initializes a specific instance such that it is ready to be used.
- * @param {FAdcCtrl} *pctrl, instance of FADC controller
- * @param {FAdcConfig} *input_config_p, Default configuration parameters of FADC
- * @return err code information, FADC_SUCCESS indicates success,others indicates failed
- */
- FError FAdcCfgInitialize(FAdcCtrl *pctrl, const FAdcConfig *input_config_p)
- {
- FASSERT(pctrl && input_config_p);
- FError ret = FADC_SUCCESS;
- /*
- * If the device is started, disallow the initialize and return a Status
- * indicating it is started. This allows the user to de-initialize the device
- * and reinitialize, but prevents a user from inadvertently
- * initializing.
- */
- if (FT_COMPONENT_IS_READY == pctrl->is_ready)
- {
- FADC_WARN("device is already initialized!!!");
- }
- /*Set default values and configuration data */
- FAdcDeInitialize(pctrl);
- pctrl->config = *input_config_p;
- pctrl->is_ready = FT_COMPONENT_IS_READY;
- return ret;
- }
|