• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 ASR Microelectronics (Shanghai) Co., Ltd. All rights reserved.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <string.h>
17 #include <stdlib.h>
18 #include "duet.h"
19 #include "duet_cm4.h"
20 #include "duet_rf_spi.h"
21 #include "duet_efuse.h"
22 
efuse_ldo25_open(void)23 void efuse_ldo25_open(void)
24 {
25     uint16_t tmp_16;
26     uint32_t tmp_32;
27     // ----- Change APLL clock to 80MHz -----
28     // SYS_CRM_WIFI_BLK_CLK = 0x1; // Enable WiFi core clock
29     // delay(5); // wait for a few cycles for WiFi core clock settle
30     // MDM_CLKGATEFCTRL0 = (0x1<<27);  // Force RC clock open
31 
32     // open 10uA current
33     tmp_16 = spi_mst_read(TRX_PD_CTRL1_REG_ADDR);
34     tmp_16 &= (~(0x0001 << 13)); // clear bit13 (D_PD_BG)
35     spi_mst_write(TRX_PD_CTRL1_REG_ADDR, tmp_16);
36 
37     tmp_16 = spi_mst_read(TRX_PD_CTRL2_REG_ADDR);
38     tmp_16 &= (~(0x0003 << 2)); // clear bit<3:2> (D_PD_TRXTOP_BIAS, D_PD_TRXTOP_LDO)
39     spi_mst_write(TRX_PD_CTRL2_REG_ADDR, tmp_16);
40 
41     // open PU LDO25: set D_AON_RCO32K_REG1<13> to 1
42     tmp_32 = RTC_REG_RCO32K;
43     RTC_REG_RCO32K = tmp_32 | (0x00000001 << (13 + 16));
44 
45     // adjust PU LDO25 voltage: set D_AON_RCO32K_REG1<12:9> to 4'b0011
46     tmp_32 = RTC_REG_RCO32K;
47     tmp_32 &= ~(0x0000000F << (9 + 16));
48     tmp_32 |= (0x00000003 << (9 + 16));
49     RTC_REG_RCO32K = tmp_32;
50 }
51 
52 /*
53     efuse init, must be called before read/write operation
54     if efuse write is needed, ldo25_open must be set to 1
55     if only efuse read is needed, then ldo25_open should be set to 0
56 */
duet_efuse_init(uint8_t ldo25_open)57 void duet_efuse_init(uint8_t ldo25_open)
58 {
59     EFUSE->RD_CNT = EFUSE_READ_OP_WAIT_CYCLE;
60     EFUSE->WR_CNT = EFUSE_WRITE_OP_WAIT_CYCLE;
61     EFUSE->DIV_CNT = EFUSE_DIV_OP_WAIT_CYCLE;
62     if (ldo25_open) {
63         efuse_ldo25_open();
64     }
65 }
66 
67 /*
68     read one efuse byte
69     param-addr: efuse addr, from 0x000 to 0x1FF
70 */
duet_efuse_byte_read(uint16_t addr)71 uint8_t duet_efuse_byte_read(uint16_t addr)
72 {
73     EFUSE->B_ADDR = addr;
74     EFUSE->CFG_TYPE = 0x0; // read type
75 
76     EFUSE->START = 0x1;
77     while (EFUSE->START & 0x1);
78     return EFUSE->RDBK_DATA;
79 }
80 
81 /*
82     read one efuse word
83     param-addr: efuse addr, from 0x000 to 0x1FC
84 */
duet_efuse_word_read(uint16_t addr)85 uint32_t duet_efuse_word_read(uint16_t addr)
86 {
87     uint32_t rd_word_data = 0;
88     uint8_t rd_byte_data = 0;
89     for (int i = 0; i < 4; i++) {
90         rd_byte_data = duet_efuse_byte_read(addr + i);
91         rd_word_data |= rd_byte_data << (i << 3);
92     }
93     return rd_word_data;
94 }
95 
96 /*
97     program one efuse byte
98     param-addr: efuse addr, from 0x000 to 0x1FF
99     param-data: data to be written
100 */
duet_efuse_byte_write(uint16_t addr,uint8_t data)101 void duet_efuse_byte_write(uint16_t addr, uint8_t data)
102 {
103     EFUSE->PGM_DATA = data;
104     EFUSE->B_ADDR = addr;
105     EFUSE->CFG_TYPE = 0x1; // program type
106     EFUSE->WR_TYPE = 0x0; // write type: byte
107     EFUSE->START = 0x1;
108     while (EFUSE->START & 0x1);
109 }
110 
111 /*
112     program one efuse word
113     param-addr: efuse addr, from 0x000 to 0x1FC
114     param-data: data to be written
115 */
duet_efuse_word_write(uint16_t addr,uint32_t data)116 void duet_efuse_word_write(uint16_t addr, uint32_t data)
117 {
118     EFUSE->PGM_DATA = data;
119     EFUSE->B_ADDR = addr;
120     EFUSE->CFG_TYPE = 0x1; // program type
121     EFUSE->WR_TYPE = 0x1; // write type: word
122     EFUSE->START = 0x1;
123     while (EFUSE->START & 0x1);
124 }
125 
126 /*
127     read multiple efuse bytes
128     param-start_addr: efuse addr, from 0x000 to 0x1FF
129     param-size_in_bytes: how many bytes to be read
130     param-pData: where efuse data is stored
131 */
duet_efuse_multi_read(uint16_t start_addr,uint16_t size_in_bytes,uint8_t * pData)132 void duet_efuse_multi_read(uint16_t start_addr, uint16_t size_in_bytes, uint8_t *pData)
133 {
134     uint16_t i;
135     // efuse init
136     duet_efuse_init(EFUSE_LDO25_CLOSE);
137 
138     // efuse byte read
139     for (i = 0; i < size_in_bytes; i++) {
140         *(pData + i) = duet_efuse_byte_read(start_addr + i);
141     }
142 }
143 
144