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