1 /* Copyright (c) 2023, Canaan Bright Sight Co., Ltd
2  *
3  * Redistribution and use in source and binary forms, with or without
4  * modification, are permitted provided that the following conditions are met:
5  * 1. Redistributions of source code must retain the above copyright
6  * notice, this list of conditions and the following disclaimer.
7  * 2. Redistributions in binary form must reproduce the above copyright
8  * notice, this list of conditions and the following disclaimer in the
9  * documentation and/or other materials provided with the distribution.
10  *
11  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
12  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
13  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
14  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
16  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
17  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
18  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
21  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
22  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 /*
27  * Copyright (c) 2006-2025 RT-Thread Development Team
28  *
29  * SPDX-License-Identifier: Apache-2.0
30  */
31 
32 #include <drivers/adc.h>
33 #include <ioremap.h>
34 #include <rtthread.h>
35 #include <rthw.h>
36 #include <rtdevice.h>
37 #include <riscv_io.h>
38 #include <string.h>
39 
40 #include "board.h"
41 #include "drv_adc.h"
42 
43 struct k230_adc adc_dev;
44 
k230_adc_hw_init(struct k230_adc_regs * adc_regs)45 static int k230_adc_hw_init(struct k230_adc_regs *adc_regs)
46 {
47     rt_uint32_t reg;
48 
49     reg = readl(&adc_regs->trim_reg);
50     reg &= (~(0x1));
51     writel(reg, &adc_regs->trim_reg);
52 
53     reg = readl(&adc_regs->trim_reg);
54     reg |= 0x1;
55     writel(reg, &adc_regs->trim_reg);
56 
57     reg = readl(&adc_regs->trim_reg);
58     reg |= (0x1 << 20);
59     writel(reg, &adc_regs->trim_reg);
60 
61     /* delay 150us */
62     rt_hw_us_delay(150);
63 
64     reg &= ~(0x1 << 20);
65     writel(reg, &adc_regs->trim_reg);
66 
67     writel(0x0, &adc_regs->mode_reg);
68 
69     return RT_EOK;
70 }
71 
k230_adc_init()72 static int k230_adc_init()
73 {
74     int i;
75 
76     adc_dev.adc_regs = (struct k230_adc_regs*)rt_ioremap((void *)ADC_BASE_ADDR, ADC_IO_SIZE);
77 
78     for (i = 0; i < ADC_MAX_DMA_CHN; i++)
79     {
80         adc_dev.chn[i].chn_num = i;
81         adc_dev.chn[i].enabled = 0;
82     }
83 
84     k230_adc_hw_init(adc_dev.adc_regs);
85 
86     return RT_EOK;
87 }
88 
k_adc_drv_enabled(struct k230_adc_regs * adc_regs)89 static int k_adc_drv_enabled(struct k230_adc_regs *adc_regs)
90 {
91     rt_uint32_t reg;
92 
93     reg = readl(&adc_regs->trim_reg);
94     reg |= 0x1;
95     writel(reg, &adc_regs->trim_reg);
96 
97     return RT_EOK;
98 }
99 
k_adc_drv_disabled(struct k230_adc_regs * adc_regs)100 static int k_adc_drv_disabled(struct k230_adc_regs *adc_regs)
101 {
102     rt_uint32_t reg;
103 
104     reg = readl(&adc_regs->trim_reg);
105     reg = reg & (~(0x1));
106     writel(reg, &adc_regs->trim_reg);
107 
108     return RT_EOK;
109 }
110 
k230_adc_enabled(struct rt_adc_device * device,rt_int8_t channel,rt_bool_t enabled)111 rt_err_t k230_adc_enabled(struct rt_adc_device *device, rt_int8_t channel, rt_bool_t enabled)
112 {
113     if (channel >= ADC_MAX_CHANNEL)
114         return -RT_ERROR;
115 
116     struct k230_adc *kd_adc = rt_container_of(device, struct k230_adc, dev);
117 
118     kd_adc->chn[channel].enabled = 1;
119     if (enabled)
120     {
121         kd_adc->chn[channel].enabled = 1;
122     }
123     else
124     {
125         kd_adc->chn[channel].enabled = 0;
126     }
127 
128     return RT_EOK;
129 }
130 
k230_get_adc_value(struct rt_adc_device * device,rt_int8_t channel,rt_uint32_t * value)131 rt_err_t k230_get_adc_value(struct rt_adc_device *device, rt_int8_t channel, rt_uint32_t *value)
132 {
133     if (channel >= ADC_MAX_CHANNEL)
134         return -RT_ERROR;
135 
136     struct k230_adc *kd_adc = rt_container_of(device, struct k230_adc, dev);
137 
138     if (!kd_adc->chn[channel].enabled)
139         return -RT_ERROR;
140 
141     writel(channel | 0x10, &kd_adc->adc_regs->cfg_reg);
142     while ((readl(&kd_adc->adc_regs->cfg_reg) & 0x10000) == 0);
143     *value = readl(&kd_adc->adc_regs->data_reg[channel]);
144 
145     return RT_EOK;
146 }
147 
148 static const struct rt_adc_ops k230_adc_ops =
149 {
150     .enabled = k230_adc_enabled,
151     .convert = k230_get_adc_value,
152 };
153 
rt_hw_adc_init(void)154 int rt_hw_adc_init(void)
155 {
156     k230_adc_init();
157 
158     rt_hw_adc_register(&adc_dev.dev, K230_ADC_NAME, &k230_adc_ops, NULL);
159 
160     return RT_EOK;
161 }
162 INIT_BOARD_EXPORT(rt_hw_adc_init);
163