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