Jelajahi Sumber

[bsp/cvitek]add adc driver (#8562)

flyingcys 1 tahun lalu
induk
melakukan
3816d9fba4

+ 3 - 2
bsp/cvitek/README.md

@@ -32,9 +32,10 @@
 
 | 驱动 | 支持情况 | 备注              |
 | :--- | :------- | :---------------- |
-| UART | 支持     | 默认波特率115200 |
+| uart | 支持     | 默认波特率115200 |
 | gpio | 支持 |  |
-
+| i2c  | 支持 |  |
+| adc | 支持 |  |
 
 ## 支持开发板
 - milk-v duo: [https://milkv.io/duo](https://milkv.io/duo)

+ 6 - 0
bsp/cvitek/c906_little/board/Kconfig

@@ -39,4 +39,10 @@ menu "General Drivers Configuration"
             int
             default 32
         endif
+
+    menuconfig BSP_USING_ADC
+        bool "Using ADC"
+        select RT_USING_ADC
+        default n
+
 endmenu

+ 5 - 0
bsp/cvitek/cv1800b/board/Kconfig

@@ -31,5 +31,10 @@ menu "General Drivers Configuration"
             default n
 
         endif
+        
+    menuconfig BSP_USING_ADC
+        bool "Using ADC"
+        select RT_USING_ADC
+        default n
 
 endmenu

+ 3 - 0
bsp/cvitek/drivers/SConscript

@@ -15,6 +15,9 @@ if GetDepend('BSP_USING_CV1800B'):
 if GetDepend('BSP_USING_I2C'):
     src += ['drv_hw_i2c.c']
 
+if GetDepend('BSP_USING_ADC'):
+    src += ['drv_adc.c']
+
 CPPDEFINES += ['-DCONFIG_64BIT']
 
 group = DefineGroup('drivers', src, depend = [''], CPPDEFINES = CPPDEFINES, CPPPATH = CPPPATH)

+ 121 - 0
bsp/cvitek/drivers/drv_adc.c

@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2006-2024, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2024/02/22     flyingcys    first version
+ */
+#include <rtthread.h>
+#include <rtdevice.h>
+#include "drv_adc.h"
+
+#ifdef BSP_USING_ADC
+
+#define DBG_LEVEL   DBG_LOG
+#include <rtdbg.h>
+#define LOG_TAG "DRV.ADC"
+
+struct cvi_adc_dev
+{
+    struct rt_adc_device device;
+    const char *name;
+    rt_ubase_t base;
+};
+
+static struct cvi_adc_dev adc_dev_config[] =
+{
+    {
+        .name = "adc1",
+        .base = SARADC_BASE
+    },
+};
+
+static rt_err_t _adc_enabled(struct rt_adc_device *device, rt_int8_t channel, rt_bool_t enabled)
+{
+    struct cvi_adc_dev *adc_dev = (struct cvi_adc_dev *)device->parent.user_data;
+    uint32_t value;
+
+    RT_ASSERT(adc_dev != RT_NULL);
+
+    if (channel > SARADC_CH_MAX)
+        return -RT_EINVAL;
+
+    if (enabled)
+    {
+        //set channel
+        cvi_set_saradc_ctrl(adc_dev->base, (rt_uint32_t)channel << (SARADC_CTRL_SEL_POS + 1));
+
+        //set saradc clock cycle
+        cvi_set_cyc(adc_dev->base);
+
+        //start
+        cvi_set_saradc_ctrl(adc_dev->base, SARADC_CTRL_START);
+        LOG_D("enable saradc...");
+    }
+    else
+    {
+        cvi_reset_saradc_ctrl(adc_dev->base, (rt_uint32_t)channel << (SARADC_CTRL_SEL_POS + 1));
+        LOG_D("disable saradc...");
+    }
+    return RT_EOK;
+}
+
+static rt_err_t _adc_convert(struct rt_adc_device *device, rt_int8_t channel, rt_uint32_t *value)
+{
+    struct cvi_adc_dev *adc_dev = (struct cvi_adc_dev *)device->parent.user_data;
+    rt_uint32_t result;
+    rt_uint32_t cnt = 0;
+
+    RT_ASSERT(adc_dev != RT_NULL);
+
+    if (channel > SARADC_CH_MAX)
+        return -RT_EINVAL;
+
+    while (cvi_get_saradc_status(adc_dev->base) & SARADC_STATUS_BUSY)
+    {
+        rt_thread_delay(10);
+        LOG_D("wait saradc ready");
+        cnt ++;
+        if (cnt > 100)
+            return -RT_ETIMEOUT;
+    }
+
+    result = mmio_read_32(adc_dev->base + SARADC_RESULT(channel - 1));
+    if (result & SARADC_RESULT_VALID)
+    {
+        *value = result & SARADC_RESULT_MASK;
+        LOG_D("saradc channel %d value: %04x", channel, *value);
+    }
+    else
+    {
+        LOG_E("saradc channel %d read failed. result:0x%04x", channel, result);
+        return -RT_ERROR;
+    }
+    return RT_EOK;
+}
+
+static const struct rt_adc_ops _adc_ops =
+{
+    .enabled = _adc_enabled,
+    .convert = _adc_convert,
+};
+
+int rt_hw_adc_init(void)
+{
+    rt_uint8_t i;
+    for (i = 0; i < sizeof(adc_dev_config) / sizeof(adc_dev_config[0]); i ++)
+    {
+        if (rt_hw_adc_register(&adc_dev_config[i].device, adc_dev_config[i].name, &_adc_ops, &adc_dev_config[i]) != RT_EOK)
+        {
+            LOG_E("%s register failed!", adc_dev_config[i].name);
+            return -RT_ERROR;
+        }
+    }
+
+    return RT_EOK;
+}
+INIT_BOARD_EXPORT(rt_hw_adc_init);
+
+#endif /* BSP_USING_ADC */

+ 83 - 0
bsp/cvitek/drivers/drv_adc.h

@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2006-2024, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2024/02/22     flyingcys    first version
+ */
+#ifndef __DRV_ADC_H__
+#define __DRV_ADC_H__
+
+#include "pinctrl.h"
+#include "mmio.h"
+
+#define SARADC_BASE                         0x030F0000
+#define SARADC_CH_MAX                       3
+
+#define SARADC_CTRL_OFFSET                  0x04
+#define SARADC_CTRL_START                   (1 << 0)
+#define SARADC_CTRL_SEL_POS                 0x04
+
+#define SARADC_STATUS_OFFSET                0x08
+#define SARADC_STATUS_BUSY                  (1 << 0)
+
+#define SARADC_CYC_SET_OFFSET               0x0C
+#define SARADC_CYC_CLKDIV_DIV_POS           (12U)
+#define SARADC_CYC_CLKDIV_DIV_MASK          (0xF << SARADC_CYC_CLKDIV_DIV_POS)
+#define SARADC_CYC_CLKDIV_DIV_1             (0U<< SARADC_CYC_CLKDIV_DIV_POS)
+#define SARADC_CYC_CLKDIV_DIV_2             (1U<< SARADC_CYC_CLKDIV_DIV_POS)
+#define SARADC_CYC_CLKDIV_DIV_3             (2U<< SARADC_CYC_CLKDIV_DIV_POS)
+#define SARADC_CYC_CLKDIV_DIV_4             (3U<< SARADC_CYC_CLKDIV_DIV_POS)
+#define SARADC_CYC_CLKDIV_DIV_5             (4U<< SARADC_CYC_CLKDIV_DIV_POS)
+#define SARADC_CYC_CLKDIV_DIV_6             (5U<< SARADC_CYC_CLKDIV_DIV_POS)
+#define SARADC_CYC_CLKDIV_DIV_7             (6U<< SARADC_CYC_CLKDIV_DIV_POS)
+#define SARADC_CYC_CLKDIV_DIV_8             (7U<< SARADC_CYC_CLKDIV_DIV_POS)
+#define SARADC_CYC_CLKDIV_DIV_9             (8U<< SARADC_CYC_CLKDIV_DIV_POS)
+#define SARADC_CYC_CLKDIV_DIV_10            (9U<< SARADC_CYC_CLKDIV_DIV_POS)
+#define SARADC_CYC_CLKDIV_DIV_11            (10U<< SARADC_CYC_CLKDIV_DIV_POS)
+#define SARADC_CYC_CLKDIV_DIV_12            (11U<< SARADC_CYC_CLKDIV_DIV_POS)
+#define SARADC_CYC_CLKDIV_DIV_13            (12U<< SARADC_CYC_CLKDIV_DIV_POS)
+#define SARADC_CYC_CLKDIV_DIV_14            (13U<< SARADC_CYC_CLKDIV_DIV_POS)
+#define SARADC_CYC_CLKDIV_DIV_15            (14U<< SARADC_CYC_CLKDIV_DIV_POS)
+#define SARADC_CYC_CLKDIV_DIV_16            (15U<< SARADC_CYC_CLKDIV_DIV_POS)
+
+#define SARADC_RESULT_OFFSET                0x014
+#define SARADC_RESULT(n)                    (SARADC_RESULT_OFFSET + (n) * 4)
+#define SARADC_RESULT_MASK                  0x0FFF
+#define SARADC_RESULT_VALID                 (1 << 15)
+
+rt_inline void cvi_set_saradc_ctrl(unsigned long reg_base, rt_uint32_t value)
+{
+    value |= mmio_read_32(reg_base + SARADC_CTRL_OFFSET);
+    mmio_write_32(reg_base + SARADC_CTRL_OFFSET, value);
+}
+
+rt_inline void cvi_reset_saradc_ctrl(unsigned long reg_base, rt_uint32_t value)
+{
+    value = mmio_read_32(reg_base + SARADC_CTRL_OFFSET) & ~value;
+    mmio_write_32(reg_base + SARADC_CTRL_OFFSET, value);
+}
+
+rt_inline rt_uint32_t cvi_get_saradc_status(unsigned long reg_base)
+{
+    return((rt_uint32_t)mmio_read_32(reg_base + SARADC_STATUS_OFFSET));
+}
+
+rt_inline void cvi_set_cyc(unsigned long reg_base)
+{
+    rt_uint32_t value;
+
+    value = mmio_read_32(reg_base + SARADC_CYC_SET_OFFSET);
+
+    value &= ~SARADC_CYC_CLKDIV_DIV_16;
+    mmio_write_32(reg_base + SARADC_CYC_SET_OFFSET, value);
+
+    value |= SARADC_CYC_CLKDIV_DIV_16;                                                               //set saradc clock cycle=840ns
+    mmio_write_32(reg_base + SARADC_CYC_SET_OFFSET, value);
+}
+
+int rt_hw_adc_init(void);
+
+#endif /* __DRV_ADC_H__ */