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