1 // Copyright (C) 2022 Beken Corporation
2 //
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 #include "efuse_hal.h"
16 #include "efuse_ll.h"
17 #include <driver/hal/hal_efuse_types.h>
18
efuse_hal_check_can_write(uint8_t old_byte,uint8_t new_byte)19 static int efuse_hal_check_can_write(uint8_t old_byte, uint8_t new_byte)
20 {
21 if (new_byte == old_byte) {
22 /* no need to read */
23 return -1;
24 }
25
26 for (int i = 0; i < 8; i++) {
27 uint8_t old_bit = ((old_byte >> i) & 0x01);
28 uint8_t new_bit = ((new_byte >> i) & 0x01);
29
30 if ((old_bit) && (!new_bit)) {
31 /* can not change old from 1 to 0 */
32 HAL_LOGW("[efuse] cannot change bit[%d] from 1 to 0\r\n", i);
33 return -2;
34 }
35 }
36
37 return 0;
38 }
39
efuse_hal_init(efuse_hal_t * hal)40 bk_err_t efuse_hal_init(efuse_hal_t *hal)
41 {
42 hal->hw = (efuse_hw_t *)EFUSE_LL_REG_BASE(hal->id);
43 efuse_ll_init(hal->hw);
44 return BK_OK;
45 }
46
47 /* 1. check if can write
48 * 2. enable efuse vdd2.5v
49 * 3. set dir, addr, data, enable
50 * 4. wait for operate finished
51 * 5. disable efuse vdd2.5v
52 * 6. check if write success
53 */
efuse_hal_write(efuse_hal_t * hal,uint8_t addr,uint8_t wr_data)54 bk_err_t efuse_hal_write(efuse_hal_t *hal, uint8_t addr, uint8_t wr_data)
55 {
56 /* read before write, ensure this byte and this bit no wrote */
57 uint8_t read_data = efuse_hal_read(hal, addr);
58 int ret = efuse_hal_check_can_write(read_data, wr_data);
59 if (ret == -1) {
60 return BK_OK;
61 }
62 if (ret == -2) {
63 return BK_ERR_EFUSE_CANNOT_WRTIE;
64 }
65
66 efuse_ll_enable_vdd25(hal->hw);
67
68 efuse_ll_set_direction_write(hal->hw);
69 efuse_ll_set_addr(hal->hw, addr);
70 efuse_ll_set_wr_data(hal->hw, wr_data);
71 efuse_ll_enable(hal->hw);
72
73 BK_WHILE (!efuse_ll_is_operate_finished(hal->hw));
74
75 efuse_ll_disable_vdd25(hal->hw);
76
77 read_data = efuse_hal_read(hal, addr);
78 if (read_data != wr_data) {
79 return BK_ERR_EFUSE_WRTIE_NOT_EQUAL;
80 }
81
82 return BK_OK;
83 }
84
85 /* 1. set addr & direction=read
86 * 2. enable efuse
87 * 3. wait for efuse operate finished
88 * 4. if rd_data valid, read data
89 */
efuse_hal_read(efuse_hal_t * hal,uint8_t addr)90 uint8_t efuse_hal_read(efuse_hal_t *hal, uint8_t addr)
91 {
92 efuse_ll_set_direction_read(hal->hw);
93 efuse_ll_set_addr(hal->hw, addr);
94 efuse_ll_enable(hal->hw);
95
96 /* wait for efuse operate finished */
97 BK_WHILE (!efuse_ll_is_operate_finished(hal->hw));
98
99 if (efuse_ll_is_rd_data_valid(hal->hw)) {
100 return efuse_ll_get_rd_data(hal->hw);
101 } else {
102 return 0xFF;
103 }
104 }
105
106