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