1 /******************************************************************************
2  *
3  * Copyright (C) 2022-2023 Maxim Integrated Products, Inc. (now owned by
4  * Analog Devices, Inc.),
5  * Copyright (C) 2023-2024 Analog Devices, Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  ******************************************************************************/
20 
21 /* **** Includes **** */
22 #include <stddef.h>
23 #include "mxc_device.h"
24 #include "mxc_assert.h"
25 #include "mxc_errors.h"
26 #include "mxc_sys.h"
27 #include "otp.h"
28 #include "otp_reva.h"
29 
30 /* **** Functions **** */
31 
MXC_OTP_RevA_Init(mxc_otp_reva_regs_t * otp,mxc_otp_clkdiv_t pclkdiv)32 int MXC_OTP_RevA_Init(mxc_otp_reva_regs_t *otp, mxc_otp_clkdiv_t pclkdiv)
33 {
34     MXC_SETFIELD(otp->clkdiv, MXC_F_OTP_REVA_CLKDIV_PCLKDIV,
35                  (pclkdiv << MXC_F_OTP_CLKDIV_PCLKDIV_POS));
36 
37     return E_NO_ERROR;
38 }
39 
MXC_OTP_RevA_IsLocked(mxc_otp_reva_regs_t * otp)40 int MXC_OTP_RevA_IsLocked(mxc_otp_reva_regs_t *otp)
41 {
42     return !(otp->status & MXC_F_OTP_REVA_STATUS_UNLOCK1);
43 }
44 
MXC_OTP_RevA_Unlock(mxc_otp_reva_regs_t * otp)45 void MXC_OTP_RevA_Unlock(mxc_otp_reva_regs_t *otp)
46 {
47     otp->actrl0 = 0xBEEFBA55;
48 }
49 
MXC_OTP_RevA_Lock(mxc_otp_reva_regs_t * otp)50 void MXC_OTP_RevA_Lock(mxc_otp_reva_regs_t *otp)
51 {
52     otp->actrl0 = 0;
53 }
54 
MXC_OTP_RevA_Write(mxc_otp_reva_regs_t * otp,uint16_t addr,uint32_t * data,uint16_t size)55 int MXC_OTP_RevA_Write(mxc_otp_reva_regs_t *otp, uint16_t addr, uint32_t *data, uint16_t size)
56 {
57     int i;
58     int error;
59 
60     // Don't write out of accessible user block space.
61     if (addr > (MXC_OTP_MEM_BASE + MXC_OTP_MEM_SIZE)) {
62         return E_BAD_PARAM;
63     }
64 
65     if ((addr + size) > (MXC_OTP_MEM_BASE + MXC_OTP_MEM_SIZE)) {
66         return E_BAD_PARAM;
67     }
68 
69     if (MXC_OTP_IsLocked()) {
70         MXC_OTP_Unlock();
71     }
72 
73     for (i = 0; i < size; i++) {
74         error = MXC_OTP_Write32(addr + i, data[i]);
75         if (error != E_NO_ERROR) {
76             MXC_OTP_Lock();
77             return error;
78         }
79     }
80 
81     MXC_OTP_Lock();
82 
83     return E_NO_ERROR;
84 }
85 
MXC_OTP_RevA_Write32(mxc_otp_reva_regs_t * otp,uint16_t addr,uint32_t data)86 int MXC_OTP_RevA_Write32(mxc_otp_reva_regs_t *otp, uint16_t addr, uint32_t data)
87 {
88     // Make sure OTP memory is unlocked.
89     if (MXC_OTP_IsLocked()) {
90         return E_BAD_STATE;
91     }
92 
93     // Check address range.
94     if (addr > (MXC_OTP_MEM_BASE + MXC_OTP_MEM_SIZE)) {
95         return E_BAD_PARAM;
96     }
97 
98     otp->wdata = data;
99 
100     MXC_SETFIELD(otp->ctrl, MXC_F_OTP_REVA_CTRL_ADDR, (addr << MXC_F_OTP_REVA_CTRL_ADDR_POS));
101 
102     // Start Write operation
103     otp->ctrl |= MXC_F_OTP_REVA_CTRL_WRITE;
104 
105     // Wait until operation is complete then verify it hasn't failed
106     while (otp->status & MXC_F_OTP_REVA_STATUS_BUSY) {}
107 
108     if (otp->status & MXC_F_OTP_REVA_STATUS_FAIL) {
109         return E_BAD_STATE;
110     }
111 
112     return E_NO_ERROR;
113 }
114 
MXC_OTP_RevA_Read(mxc_otp_reva_regs_t * otp,uint16_t addr,uint32_t * data,uint16_t size)115 int MXC_OTP_RevA_Read(mxc_otp_reva_regs_t *otp, uint16_t addr, uint32_t *data, uint16_t size)
116 {
117     int i;
118     int error;
119 
120     // Don't read out of accessible block space.
121     if (addr > MXC_OTP_MEM_SIZE) {
122         return E_BAD_PARAM;
123     }
124 
125     if ((addr + size) > MXC_OTP_MEM_SIZE) {
126         return E_BAD_PARAM;
127     }
128 
129     for (i = 0; i < size; i++) {
130         error = MXC_OTP_Read32(addr + i, data + i);
131         if (error != E_NO_ERROR) {
132             return error;
133         }
134     }
135 
136     return E_NO_ERROR;
137 }
138 
MXC_OTP_RevA_Read32(mxc_otp_reva_regs_t * otp,uint16_t addr,uint32_t * data)139 int MXC_OTP_RevA_Read32(mxc_otp_reva_regs_t *otp, uint16_t addr, uint32_t *data)
140 {
141     // User block (1k-2k) is readable in normal mode (without unlocking).
142     MXC_SETFIELD(otp->ctrl, MXC_F_OTP_REVA_CTRL_ADDR, (addr << MXC_F_OTP_REVA_CTRL_ADDR_POS));
143 
144     // Start Read Operation
145     otp->ctrl |= MXC_F_OTP_REVA_CTRL_READ;
146 
147     // Wait until operation is complete then verify it hasn't failed
148     while (otp->status & MXC_F_OTP_REVA_STATUS_BUSY) {}
149 
150     if (otp->status & MXC_F_OTP_REVA_STATUS_FAIL) {
151         return E_BAD_STATE;
152     }
153 
154     *data = otp->rdata;
155 
156     return E_NO_ERROR;
157 }
158