1 /******************************************************************************
2 * Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
3 * All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *****************************************************************************/
18
19 /********************************************************************************************************
20 * @file analog.c
21 *
22 * @brief This is the source file for B91
23 *
24 * @author Driver Group
25 *
26 *******************************************************************************************************/
27 #include "analog.h"
28 #include "compiler.h"
29 #include "plic.h"
30 #include "stimer.h"
31 /**********************************************************************************************************************
32 * local constants *
33 *********************************************************************************************************************/
34
35
36 /**********************************************************************************************************************
37 * local macro *
38 *********************************************************************************************************************/
39
40
41 /**********************************************************************************************************************
42 * local data type *
43 *********************************************************************************************************************/
44
45
46 /**********************************************************************************************************************
47 * global variable *
48 *********************************************************************************************************************/
49
50
51
52 dma_config_t analog_tx_dma_config={
53 .dst_req_sel = DMA_REQ_ALGM_TX, /* < tx req */
54 .src_req_sel = 0,
55 .dst_addr_ctrl = DMA_ADDR_FIX,
56 .src_addr_ctrl = DMA_ADDR_INCREMENT, /* < increment */
57 .dstmode = DMA_HANDSHAKE_MODE, /* < handshake */
58 .srcmode = DMA_NORMAL_MODE,
59 .dstwidth = DMA_CTR_WORD_WIDTH,
60 .srcwidth = DMA_CTR_WORD_WIDTH,
61 .src_burst_size = 0, /* < must 0 */
62 .read_num_en = 0,
63 .priority = 0,
64 .write_num_en = 0,
65 .auto_en = 0, /* < must 0 */
66 };
67 dma_config_t analog_rx_dma_config={
68 .dst_req_sel = 0,//tx req
69 .src_req_sel = DMA_REQ_ALGM_RX,
70 .dst_addr_ctrl = DMA_ADDR_INCREMENT,
71 .src_addr_ctrl = DMA_ADDR_FIX,
72 .dstmode = DMA_NORMAL_MODE,
73 .srcmode = DMA_HANDSHAKE_MODE,
74 .dstwidth = DMA_CTR_WORD_WIDTH, /* < must word */
75 .srcwidth = DMA_CTR_WORD_WIDTH, /* < must word */
76 .src_burst_size = 0,
77 .read_num_en = 0,
78 .priority = 0,
79 .write_num_en = 0,
80 .auto_en = 0,//must 0
81 };
82 /**********************************************************************************************************************
83 * local variable *
84 *********************************************************************************************************************/
85 /**********************************************************************************************************************
86 * local function prototype *
87 *********************************************************************************************************************/
88
89
90 /**
91 * @brief This function serves to judge whether analog write/read is busy .
92 * @return none.
93 */
94 static inline void analog_wait();
95 /**********************************************************************************************************************
96 * global function implementation *
97 *********************************************************************************************************************/
98
99
100
101
102
103 /**
104 * @brief This function serves to analog register read by byte.
105 * @param[in] addr - address need to be read.
106 * @return the result of read.
107 */
analog_read_reg8(unsigned char addr)108 unsigned char analog_read_reg8(unsigned char addr){
109 unsigned int r=core_interrupt_disable();
110 reg_ana_addr = addr;
111 reg_ana_len=0x1;
112 reg_ana_ctrl = FLD_ANA_CYC;
113 analog_wait();
114 unsigned char data= reg_ana_data(0);
115 core_restore_interrupt(r);
116 return data;
117
118 }
119
120 /**
121 * @brief This function serves to analog register write by byte.
122 * @param[in] addr - address need to be write.
123 * @param[in] data - the value need to be write.
124 * @return none.
125 */
analog_write_reg8(unsigned char addr,unsigned char data)126 void analog_write_reg8(unsigned char addr, unsigned char data){
127 unsigned int r=core_interrupt_disable();
128 reg_ana_addr = addr;
129 reg_ana_data(0) = data;
130 reg_ana_ctrl = (FLD_ANA_CYC | FLD_ANA_RW);
131 analog_wait();
132 reg_ana_ctrl =0x00;
133 core_restore_interrupt(r);
134 }
135
136 /**
137 * @brief This function serves to analog register write by halfword.
138 * @param[in] addr - address need to be write.
139 * @param[in] data - the value need to be write.
140 * @return none.
141 */
analog_write_reg16(unsigned char addr,unsigned short data)142 void analog_write_reg16(unsigned char addr, unsigned short data)
143 {
144 unsigned int r=core_interrupt_disable();
145 reg_ana_addr = addr;
146 reg_ana_addr_data16 = data;
147 reg_ana_ctrl = (FLD_ANA_CYC | FLD_ANA_RW);
148 analog_wait();
149 core_restore_interrupt(r);
150 }
151
152 /**
153 * @brief This function serves to analog register read by halfword.
154 * @param[in] addr - address need to be read.
155 * @return the result of read.
156 */
analog_read_reg16(unsigned char addr)157 unsigned short analog_read_reg16(unsigned char addr)
158 {
159 unsigned int r=core_interrupt_disable();
160 reg_ana_len=2;
161 reg_ana_addr = addr;
162 reg_ana_ctrl = FLD_ANA_CYC;
163 analog_wait();
164 unsigned short data=reg_ana_addr_data16;
165 core_restore_interrupt(r);
166 return data;
167 }
168
169
170
171 /**
172 * @brief This function serves to analog register read by word.
173 * @param[in] addr - address need to be read.
174 * @return the result of read.
175 */
analog_read_reg32(unsigned char addr)176 unsigned int analog_read_reg32(unsigned char addr)
177 {
178 unsigned int r=core_interrupt_disable();
179 reg_ana_len = 4;
180 reg_ana_addr = addr;
181 reg_ana_ctrl = FLD_ANA_CYC;
182 analog_wait();
183 unsigned int data=reg_ana_addr_data32;
184 core_restore_interrupt(r);
185 return data;
186 }
187
188
189 /**
190 * @brief This function serves to analog register write by word.
191 * @param[in] addr - address need to be write.
192 * @param[in] data - the value need to be write.
193 * @return none.
194 */
analog_write_reg32(unsigned char addr,unsigned int data)195 void analog_write_reg32(unsigned char addr, unsigned int data)
196 {
197 unsigned int r=core_interrupt_disable();
198 reg_ana_addr = addr;
199 reg_ana_addr_data32 = data;
200 reg_ana_ctrl = (FLD_ANA_CYC | FLD_ANA_RW);
201 analog_wait();
202 core_restore_interrupt(r);
203 }
204
205 /**
206 * @brief This function serves to analog register write by word using dma.
207 * @param[in] chn - the dma channel.
208 * @param[in] addr - address need to be write.
209 * @param[in] pdat - the value need to be write.
210 * @return none.
211 */
analog_read_reg32_dma(dma_chn_e chn,unsigned char addr,void * pdat)212 void analog_read_reg32_dma(dma_chn_e chn, unsigned char addr, void *pdat)
213 {
214 unsigned int r=core_interrupt_disable();
215 reg_ana_len = 0x04;
216 reg_ana_addr = addr;
217 reg_ana_ctrl = FLD_ANA_CYC;
218 reg_dma_src_addr(chn) = 0x80140184;
219 reg_dma_dst_addr(chn) = convert_ram_addr_cpu2bus(pdat);
220 dma_set_size(chn, 4, DMA_WORD_WIDTH);
221 analog_rx_dma_config.dstwidth = DMA_CTR_WORD_WIDTH;
222 analog_rx_dma_config.srcwidth = DMA_CTR_WORD_WIDTH;
223 dma_config(chn, &analog_rx_dma_config);
224 dma_chn_en(chn);
225 analog_wait();
226 core_restore_interrupt(r);
227 }
228
229 /**
230 * @brief This function serves to analog register write by word using dma.
231 * @param[in] chn - the dma channel.
232 * @param[in] addr - address need to be write.
233 * @param[in] data - the value need to be write.
234 * @return none.
235 */
analog_write_reg32_dma(dma_chn_e chn,unsigned char addr,void * pdat)236 void analog_write_reg32_dma(dma_chn_e chn, unsigned char addr, void *pdat)
237 {
238 unsigned int r=core_interrupt_disable();
239 reg_ana_addr = addr;
240 reg_dma_src_addr(chn) = convert_ram_addr_cpu2bus(pdat);
241 reg_dma_dst_addr(chn) = 0x80140184;
242 dma_set_size(chn, 4, DMA_WORD_WIDTH);
243 analog_tx_dma_config.dstwidth = DMA_CTR_WORD_WIDTH;
244 analog_tx_dma_config.srcwidth = DMA_CTR_WORD_WIDTH;
245 dma_config(chn, &analog_tx_dma_config);
246 dma_chn_en(chn);
247 reg_ana_ctrl = FLD_ANA_CYC | FLD_ANA_RW;
248 analog_wait();
249 core_restore_interrupt(r);
250 }
251
252
253
254
255
256 /**
257 * @brief This function write buffer to analog register.
258 * @param[in] addr - address need to be write.
259 * @param[in] *buff - the buffer need to be write.
260 * @param[in] len - the length of buffer.
261 * @return none.
262 */
analog_write_buff(unsigned char addr,unsigned char * buff,int len)263 _attribute_ram_code_sec_noinline_ void analog_write_buff(unsigned char addr, unsigned char *buff, int len)
264 {
265 unsigned char wr_idx = 0;
266 unsigned char len_t = len;
267 unsigned int r =core_interrupt_disable();
268 reg_ana_len=len;
269 reg_ana_addr = addr;
270
271 if(len_t <= 4)
272 {
273 while(len_t--)
274 reg_ana_data(wr_idx++) = *(buff++);
275 reg_ana_ctrl = FLD_ANA_CYC | FLD_ANA_RW;
276 }
277 else
278 {
279 len_t = 4;
280 while(len_t--)
281 reg_ana_data(wr_idx++) = *(buff++);
282 reg_ana_ctrl = FLD_ANA_CYC | FLD_ANA_RW;
283 len_t = len - 4;
284 wr_idx = 0;
285 while(len_t--)
286 {
287 reg_ana_data(wr_idx++) = *(buff++);
288 if(wr_idx == 4)
289 {
290 wr_idx = 0;
291 while((reg_ana_irq_sta & FLD_ANA_TXBUFF_IRQ) == 0);//tx_buf_irq
292 }
293 }
294 }
295 analog_wait();//busy
296 reg_ana_ctrl = 0x00;
297 core_restore_interrupt(r);
298 }
299
300 /**
301 * @brief This function read data from analog register to buffer.
302 * @param[in] addr - address need to be read from.
303 * @param[in] *buff - the buffer need to be put data.
304 * @param[in] len - the length of read data.
305 * @return none.
306 */
analog_read_buff(unsigned char addr,unsigned char * buff,int len)307 _attribute_ram_code_sec_noinline_ void analog_read_buff(unsigned char addr, unsigned char *buff, int len)
308 {
309 unsigned int r=core_interrupt_disable();
310 unsigned char rd_idx = 0;
311 unsigned char len_t = len;
312 reg_ana_len=len;
313 reg_ana_addr = addr;
314 reg_ana_ctrl = FLD_ANA_CYC;
315 if (len_t > 4)
316 {
317 while((reg_ana_irq_sta & FLD_ANA_RXBUFF_IRQ) == 0);//rx_buf_irq
318 while(len_t--)
319 {
320 (*buff++) = reg_ana_data(rd_idx++);
321 if(rd_idx == 4)
322 {
323 rd_idx = 0;
324 if(len_t <= 4)
325 break;
326 else
327 while((reg_ana_irq_sta & FLD_ANA_RXBUFF_IRQ) == 0);//rx_buf_irq
328 }
329 }
330 }
331 analog_wait();
332 while(len_t--)
333 (*buff++) = reg_ana_data(rd_idx++);
334
335 reg_ana_ctrl = 0x00;
336 core_restore_interrupt(r);
337 }
338
339 /**
340 * @brief This function write buffer to analog register by dma channel.
341 * @param[in] chn - the dma channel.
342 * @param[in] addr - address need to be write.
343 * @param[in] *pdat - the buffer need to be write.
344 * @param[in] len - the length of buffer.
345 * @return none.
346 */
analog_write_buff_dma(dma_chn_e chn,unsigned char addr,unsigned char * pdat,unsigned int len)347 void analog_write_buff_dma(dma_chn_e chn, unsigned char addr, unsigned char * pdat, unsigned int len)
348 {
349 unsigned int r=core_interrupt_disable();
350 reg_ana_addr = addr;
351 reg_dma_src_addr(chn) = convert_ram_addr_cpu2bus(pdat);
352 reg_dma_dst_addr(chn) = 0x80140184;
353 dma_set_size(chn, len, DMA_WORD_WIDTH);
354 analog_tx_dma_config.dstwidth = DMA_CTR_WORD_WIDTH;
355 analog_tx_dma_config.srcwidth = DMA_CTR_WORD_WIDTH;
356 dma_config(chn, &analog_tx_dma_config);
357 dma_chn_en(chn);
358 reg_ana_ctrl = 0x60;
359 analog_wait();
360 core_restore_interrupt(r);
361 }
362
363 /**
364 * @brief This function write buffer to analog register by dma channel.
365 * @param[in] chn - the dma channel.
366 * @param[in] addr - address need to be read from.
367 * @param[in] *pdat - the buffer need to be put data.
368 * note: The size of array pdat must be a multiple of 4.
369 * For example, if you just need read 5 byte by dma, you should
370 * define the size of array pdat to be greater than 8 other than 5.
371 * Because the dma would return 4 byte data every time, 5 byte is
372 * not enough to store them.
373 * @param[in] len - the length of read data.
374 * @return none.
375 */
analog_read_buff_dma(dma_chn_e chn,unsigned char addr,unsigned char * pdat,unsigned int len)376 void analog_read_buff_dma(dma_chn_e chn, unsigned char addr, unsigned char *pdat, unsigned int len)
377 {
378 unsigned int r=core_interrupt_disable();
379 reg_ana_len = len;
380 reg_ana_addr = addr;
381
382 reg_dma_src_addr(chn) = 0x80140184;
383 reg_dma_dst_addr(chn) = convert_ram_addr_cpu2bus(pdat);
384 dma_set_size(chn, len, DMA_WORD_WIDTH);
385 analog_rx_dma_config.dstwidth = DMA_CTR_WORD_WIDTH;
386 analog_rx_dma_config.srcwidth = DMA_CTR_WORD_WIDTH;
387 dma_config(chn, &analog_rx_dma_config);
388 dma_chn_en(chn);
389 reg_ana_ctrl = FLD_ANA_CYC;
390 analog_wait();
391 core_restore_interrupt(r);
392 }
393
394 /**
395 * @brief This function write buffer to analog register by dma channel.
396 * @param[in] chn - the dma channel.
397 * @param[in] pdat - the buffer(addr & data) ptr need to be write,
398 * note: The array pdat should look like this,
399 * | pdat | | |
400 * | :------ | :----------| :---- |
401 * | pdat[0] | address | 0x3a |
402 * | pdat[1] | data | 0x11 |
403 * | pdat[2] | address | 0x3b |
404 * | pdat[3] | data | 0x22 |
405 * | ...... | | |
406 * It means write data 0x11 to address 0x3a,
407 * write data 0x22 to address 0x3b,
408 * ......
409 * @param[in] len - the length of read data.
410 * @return none.
411 */
analog_write_addr_data_dma(dma_chn_e chn,void * pdat,int len)412 void analog_write_addr_data_dma(dma_chn_e chn, void *pdat, int len)
413 {
414 unsigned int r=core_interrupt_disable();
415
416 reg_dma_src_addr(chn) = convert_ram_addr_cpu2bus(pdat);
417 reg_dma_dst_addr(chn) = 0x80140184;
418 dma_set_size(chn, len, DMA_WORD_WIDTH);
419 analog_tx_dma_config.dstwidth = DMA_CTR_WORD_WIDTH;
420 analog_tx_dma_config.srcwidth = DMA_CTR_WORD_WIDTH;
421 dma_config(chn, &analog_tx_dma_config);
422 dma_chn_en(chn);
423 delay_us(1);
424 reg_ana_ctrl = FLD_ANA_RW;
425 reg_ana_dma_ctl = FLD_ANA_CYC1|FLD_ANA_DMA_EN;
426 delay_us(1);
427 while(!(reg_ana_sta & BIT(3)));
428 reg_ana_ctrl = 0x00;
429 reg_ana_dma_ctl = 0;
430 core_restore_interrupt(r);
431
432 }
433
434 /**********************************************************************************************************************
435 * local function implementation *
436 *********************************************************************************************************************/
437 /**
438 * @brief This function serves to judge whether analog write/read is busy .
439 * @return none.
440 */
analog_wait()441 static inline void analog_wait(){
442 while(reg_ana_ctrl & FLD_ANA_BUSY){}
443 }
444
445
446
447