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 #include "pt.h"
22 #include "gcr_regs.h"
23 #include "pt_reva_regs.h"
24 #include "ptg_reva_regs.h"
25 #include "pt_reva.h"
26
MXC_PT_RevA_Init(mxc_ptg_reva_regs_t * ptg,mxc_clk_scale_t clk_scale)27 void MXC_PT_RevA_Init(mxc_ptg_reva_regs_t *ptg, mxc_clk_scale_t clk_scale)
28 {
29 //disable all pulse trains
30 ptg->enable = 0;
31
32 //clear all interrupts
33 ptg->stop_intfl = ptg->stop_intfl;
34 ptg->ready_intfl = ptg->ready_intfl;
35 }
36
MXC_PT_RevA_Shutdown(mxc_ptg_reva_regs_t * ptg,uint32_t pts)37 int MXC_PT_RevA_Shutdown(mxc_ptg_reva_regs_t *ptg, uint32_t pts)
38 {
39 MXC_PT_RevA_Stop(ptg, pts);
40 return (!(MXC_PT_RevA_IsActive(ptg, ptg->enable)));
41 }
42
MXC_PT_RevA_Config(mxc_ptg_reva_regs_t * ptg,mxc_pt_cfg_t * cfg)43 int MXC_PT_RevA_Config(mxc_ptg_reva_regs_t *ptg, mxc_pt_cfg_t *cfg)
44 {
45 uint32_t ptClock, rate;
46
47 if (cfg == NULL || cfg->bps == 0) {
48 return E_BAD_PARAM;
49 }
50
51 ptClock = PeripheralClock;
52
53 if (ptClock == 0) {
54 return E_UNINITIALIZED;
55 }
56
57 if (ptClock < (cfg->bps)) {
58 return E_BAD_STATE;
59 }
60
61 //disable pulse train
62 MXC_PT_RevA_Stop(ptg, 1 << cfg->channel);
63
64 rate = (ptClock / (cfg->bps));
65
66 if (cfg->bps > 1000000) { //To lessen the delta between generated and expected clock
67 rate += 2;
68 }
69
70 mxc_pt_reva_regs_t *temp = (mxc_pt_reva_regs_t *)MXC_PT_GET_PT(cfg->channel);
71
72 MXC_ASSERT(temp != NULL);
73
74 temp->rate_length =
75 ((rate << MXC_F_PT_REVA_RATE_LENGTH_RATE_CONTROL_POS) &
76 MXC_F_PT_REVA_RATE_LENGTH_RATE_CONTROL) |
77 ((cfg->ptLength << MXC_F_PT_REVA_RATE_LENGTH_MODE_POS) & MXC_F_PT_REVA_RATE_LENGTH_MODE);
78
79 temp->train = cfg->pattern;
80 temp->loop = ((cfg->loop << MXC_F_PT_REVA_LOOP_COUNT_POS) & MXC_F_PT_REVA_LOOP_COUNT) |
81 ((cfg->loopDelay << MXC_F_PT_REVA_LOOP_DELAY_POS) & MXC_F_PT_REVA_LOOP_DELAY);
82
83 return E_NO_ERROR;
84 }
85
MXC_PT_RevA_SqrWaveConfig(mxc_ptg_reva_regs_t * ptg,mxc_pt_cfg_t * sqwcfg,unsigned channel,uint32_t freq)86 int MXC_PT_RevA_SqrWaveConfig(mxc_ptg_reva_regs_t *ptg, mxc_pt_cfg_t *sqwcfg, unsigned channel,
87 uint32_t freq)
88 {
89 uint32_t rate;
90
91 rate = 2 * freq;
92
93 sqwcfg->channel = channel;
94 sqwcfg->bps = rate;
95 sqwcfg->pattern = 0;
96 sqwcfg->ptLength = MXC_V_PT_REVA_RATE_LENGTH_MODE_SQUARE_WAVE;
97 sqwcfg->loop = 0;
98 sqwcfg->loopDelay = 0;
99
100 return E_NO_ERROR;
101 }
102
MXC_PT_RevA_Start(mxc_ptg_reva_regs_t * ptg,unsigned pts)103 void MXC_PT_RevA_Start(mxc_ptg_reva_regs_t *ptg, unsigned pts)
104 {
105 ptg->enable |= pts;
106
107 //wait for PT to start
108 while ((ptg->enable & (pts)) != pts) {}
109 }
110
MXC_PT_RevA_Stop(mxc_ptg_reva_regs_t * ptg,unsigned pts)111 void MXC_PT_RevA_Stop(mxc_ptg_reva_regs_t *ptg, unsigned pts)
112 {
113 ptg->enable &= ~pts;
114 }
115
MXC_PT_RevA_IsActive(mxc_ptg_reva_regs_t * ptg,uint32_t pts)116 uint32_t MXC_PT_RevA_IsActive(mxc_ptg_reva_regs_t *ptg, uint32_t pts)
117 {
118 return !!(ptg->enable & pts);
119 }
120
MXC_PT_RevA_SetPattern(unsigned pts,uint32_t pattern)121 void MXC_PT_RevA_SetPattern(unsigned pts, uint32_t pattern)
122 {
123 mxc_pt_reva_regs_t *temp;
124 uint32_t pt;
125
126 for (uint8_t i = 0; i < 32 && (pts >> i) > 0; i++) {
127 pt = 1 << i;
128
129 if (pts & pt) {
130 temp = (mxc_pt_reva_regs_t *)MXC_PT_GET_PT(i);
131 MXC_ASSERT(temp);
132 temp->train = pattern;
133 }
134 }
135 }
136
MXC_PT_RevA_EnableInt(mxc_ptg_reva_regs_t * ptg,uint32_t pts)137 void MXC_PT_RevA_EnableInt(mxc_ptg_reva_regs_t *ptg, uint32_t pts)
138 {
139 MXC_PT_RevA_EnableStopInt(ptg, pts);
140 }
141
MXC_PT_RevA_DisableInt(mxc_ptg_reva_regs_t * ptg,uint32_t pts)142 void MXC_PT_RevA_DisableInt(mxc_ptg_reva_regs_t *ptg, uint32_t pts)
143 {
144 MXC_PT_RevA_DisableStopInt(ptg, pts);
145 }
146
MXC_PT_RevA_GetFlags(mxc_ptg_reva_regs_t * ptg)147 uint32_t MXC_PT_RevA_GetFlags(mxc_ptg_reva_regs_t *ptg)
148 {
149 return MXC_PT_RevA_GetStopFlags(ptg);
150 }
151
MXC_PT_RevA_ClearFlags(mxc_ptg_reva_regs_t * ptg,uint32_t flags)152 void MXC_PT_RevA_ClearFlags(mxc_ptg_reva_regs_t *ptg, uint32_t flags)
153 {
154 MXC_PT_RevA_ClearStopFlags(ptg, flags);
155 }
156
MXC_PT_RevA_EnableStopInt(mxc_ptg_reva_regs_t * ptg,uint32_t pts)157 void MXC_PT_RevA_EnableStopInt(mxc_ptg_reva_regs_t *ptg, uint32_t pts)
158 {
159 ptg->stop_inten |= pts;
160 }
161
MXC_PT_RevA_DisableStopInt(mxc_ptg_reva_regs_t * ptg,uint32_t pts)162 void MXC_PT_RevA_DisableStopInt(mxc_ptg_reva_regs_t *ptg, uint32_t pts)
163 {
164 ptg->stop_inten &= ~pts;
165 }
166
MXC_PT_RevA_GetStopFlags(mxc_ptg_reva_regs_t * ptg)167 uint32_t MXC_PT_RevA_GetStopFlags(mxc_ptg_reva_regs_t *ptg)
168 {
169 return ptg->stop_intfl;
170 }
171
MXC_PT_RevA_ClearStopFlags(mxc_ptg_reva_regs_t * ptg,uint32_t flags)172 void MXC_PT_RevA_ClearStopFlags(mxc_ptg_reva_regs_t *ptg, uint32_t flags)
173 {
174 ptg->stop_intfl = flags;
175 }
176
MXC_PT_RevA_EnableReadyInt(mxc_ptg_reva_regs_t * ptg,uint32_t pts)177 void MXC_PT_RevA_EnableReadyInt(mxc_ptg_reva_regs_t *ptg, uint32_t pts)
178 {
179 ptg->ready_inten |= pts;
180 }
181
MXC_PT_RevA_DisableReadyInt(mxc_ptg_reva_regs_t * ptg,uint32_t pts)182 void MXC_PT_RevA_DisableReadyInt(mxc_ptg_reva_regs_t *ptg, uint32_t pts)
183 {
184 ptg->ready_inten &= ~pts;
185 }
186
MXC_PT_RevA_GetReadyFlags(mxc_ptg_reva_regs_t * ptg)187 uint32_t MXC_PT_RevA_GetReadyFlags(mxc_ptg_reva_regs_t *ptg)
188 {
189 return ptg->ready_intfl;
190 }
191
MXC_PT_RevA_ClearReadyFlags(mxc_ptg_reva_regs_t * ptg,uint32_t flags)192 void MXC_PT_RevA_ClearReadyFlags(mxc_ptg_reva_regs_t *ptg, uint32_t flags)
193 {
194 ptg->ready_intfl = flags;
195 }
196
MXC_PT_RevA_EnableRestart(unsigned start,unsigned stop,uint8_t restartIndex)197 void MXC_PT_RevA_EnableRestart(unsigned start, unsigned stop, uint8_t restartIndex)
198 {
199 mxc_pt_reva_regs_t *temp = (mxc_pt_reva_regs_t *)MXC_PT_GET_PT(start);
200 MXC_ASSERT(temp);
201
202 if (restartIndex) {
203 temp->restart |= (stop << MXC_F_PT_REVA_RESTART_PT_Y_SELECT_POS) |
204 MXC_F_PT_REVA_RESTART_ON_PT_Y_LOOP_EXIT;
205 } else {
206 temp->restart |= (stop << MXC_F_PT_REVA_RESTART_PT_X_SELECT_POS) |
207 MXC_F_PT_REVA_RESTART_ON_PT_X_LOOP_EXIT;
208 }
209 }
210
MXC_PT_RevA_DisableRestart(unsigned channel,uint8_t restartIndex)211 void MXC_PT_RevA_DisableRestart(unsigned channel, uint8_t restartIndex)
212 {
213 mxc_pt_reva_regs_t *temp = (mxc_pt_reva_regs_t *)MXC_PT_GET_PT(channel);
214 MXC_ASSERT(temp);
215
216 if (restartIndex) {
217 temp->restart &= ~MXC_F_PT_REVA_RESTART_ON_PT_Y_LOOP_EXIT;
218 } else {
219 temp->restart &= ~MXC_F_PT_REVA_RESTART_ON_PT_X_LOOP_EXIT;
220 }
221 }
222
MXC_PT_RevA_Resync(mxc_ptg_reva_regs_t * ptg,uint32_t pts)223 void MXC_PT_RevA_Resync(mxc_ptg_reva_regs_t *ptg, uint32_t pts)
224 {
225 // Set the PT to be synced
226 ptg->resync |= pts;
227
228 // Wait for them to sync
229 while (ptg->resync & pts) {}
230 }
231