1 /***************************************************************************//**
2 * \file ppu_v1.c
3 * \version 1.0
4 *
5 * This file provides the source code for ARM PPU driver
6 *
7 ********************************************************************************
8 * \copyright
9 * Copyright (c) (2020-2022), Cypress Semiconductor Corporation (an Infineon company) or
10 * an affiliate of Cypress Semiconductor Corporation.
11 *
12 * SPDX-License-Identifier: BSD-3-Clause
13 *
14 * Arm SCP/MCP Software
15 * Copyright (c) 2015-2021, Arm Limited and Contributors. All rights reserved.
16 *
17 * SPDX-License-Identifier: BSD-3-Clause
18 *******************************************************************************/
19
20 #include "cy_device.h"
21
22 #if defined (CY_IP_MXS28SRSS) || defined(CY_IP_MXS40SSRSS) || defined(CY_IP_MXS22SRSS)
23
24 #include <stddef.h>
25 #include <ppu_v1.h>
26
ppu_v1_init(struct ppu_v1_reg * ppu)27 void ppu_v1_init(struct ppu_v1_reg *ppu)
28 {
29 fwk_assert(ppu != NULL);
30
31 /* Set edge sensitivity to masked for all input edges */
32 ppu->IESR = 0;
33
34 /* Mask all interrupts */
35 ppu->IMR = PPU_V1_IMR_MASK;
36
37 /* Acknowledge any interrupt left pending */
38 ppu->ISR = PPU_V1_ISR_MASK;
39 }
40
41 /*
42 * PWPR and PWSR registers
43 */
ppu_v1_request_power_mode(struct ppu_v1_reg * ppu,enum ppu_v1_mode ppu_mode)44 int ppu_v1_request_power_mode(struct ppu_v1_reg *ppu, enum ppu_v1_mode ppu_mode)
45 {
46 uint32_t power_policy;
47 fwk_assert(ppu != NULL);
48 fwk_assert(ppu_mode < PPU_V1_MODE_COUNT);
49
50 power_policy = ppu->PWPR & ~(PPU_V1_PWPR_POLICY | PPU_V1_PWPR_DYNAMIC_EN);
51 ppu->PWPR = power_policy | ppu_mode;
52
53 return FWK_SUCCESS;
54 }
55
ppu_v1_set_power_mode(struct ppu_v1_reg * ppu,enum ppu_v1_mode ppu_mode)56 int ppu_v1_set_power_mode(struct ppu_v1_reg *ppu, enum ppu_v1_mode ppu_mode)
57 {
58 int status;
59
60 status = ppu_v1_request_power_mode(ppu, ppu_mode);
61 if (status != FWK_SUCCESS)
62 return status;
63
64 while ((ppu->PWSR & (PPU_V1_PWSR_PWR_STATUS | PPU_V1_PWSR_PWR_DYN_STATUS))
65 != ppu_mode)
66 continue;
67
68 return FWK_SUCCESS;
69 }
70
ppu_v1_request_operating_mode(struct ppu_v1_reg * ppu,enum ppu_v1_opmode op_mode)71 int ppu_v1_request_operating_mode(struct ppu_v1_reg *ppu,
72 enum ppu_v1_opmode op_mode)
73 {
74 uint32_t power_policy;
75 fwk_assert(ppu != NULL);
76 fwk_assert(op_mode < PPU_V1_OPMODE_COUNT);
77
78 power_policy = ppu->PWPR & ~(PPU_V1_PWPR_OP_POLICY | PPU_V1_PWPR_OP_DYN_EN);
79 ppu->PWPR = power_policy | (op_mode << PPU_V1_PWPR_OP_POLICY_POS);
80
81 return FWK_SUCCESS;
82 }
83
ppu_v1_opmode_dynamic_enable(struct ppu_v1_reg * ppu,enum ppu_v1_opmode min_dyn_mode)84 void ppu_v1_opmode_dynamic_enable(struct ppu_v1_reg *ppu,
85 enum ppu_v1_opmode min_dyn_mode)
86 {
87 uint32_t power_policy;
88
89 fwk_assert(ppu != NULL);
90 fwk_assert(min_dyn_mode < PPU_V1_OPMODE_COUNT);
91
92 power_policy = ppu->PWPR & ~PPU_V1_PWPR_OP_POLICY;
93 ppu->PWPR = power_policy |
94 PPU_V1_PWPR_OP_DYN_EN |
95 (min_dyn_mode << PPU_V1_PWPR_OP_POLICY_POS);
96 while ((ppu->PWSR & PPU_V1_PWSR_OP_DYN_STATUS) == 0)
97 continue;
98 }
99
ppu_v1_dynamic_enable(struct ppu_v1_reg * ppu,enum ppu_v1_mode min_dyn_state)100 void ppu_v1_dynamic_enable(struct ppu_v1_reg *ppu,
101 enum ppu_v1_mode min_dyn_state)
102 {
103 uint32_t power_policy;
104
105 fwk_assert(ppu != NULL);
106 fwk_assert(min_dyn_state < PPU_V1_MODE_COUNT);
107
108 power_policy = ppu->PWPR & ~PPU_V1_PWPR_POLICY;
109 ppu->PWPR = power_policy | PPU_V1_PWPR_DYNAMIC_EN | min_dyn_state;
110 while ((ppu->PWSR & PPU_V1_PWSR_PWR_DYN_STATUS) == 0)
111 continue;
112 }
113
ppu_v1_lock_off_enable(struct ppu_v1_reg * ppu)114 void ppu_v1_lock_off_enable(struct ppu_v1_reg *ppu)
115 {
116 fwk_assert(ppu != NULL);
117
118 ppu->PWPR |= PPU_V1_PWPR_OFF_LOCK_EN;
119 }
120
ppu_v1_lock_off_disable(struct ppu_v1_reg * ppu)121 void ppu_v1_lock_off_disable(struct ppu_v1_reg *ppu)
122 {
123 fwk_assert(ppu != NULL);
124
125 ppu->PWPR &= ~PPU_V1_PWPR_OFF_LOCK_EN;
126 }
127
ppu_v1_get_power_mode(struct ppu_v1_reg * ppu)128 enum ppu_v1_mode ppu_v1_get_power_mode(struct ppu_v1_reg *ppu)
129 {
130 fwk_assert(ppu != NULL);
131
132 return (enum ppu_v1_mode)(ppu->PWSR & PPU_V1_PWSR_PWR_STATUS);
133 }
134
ppu_v1_get_programmed_power_mode(struct ppu_v1_reg * ppu)135 enum ppu_v1_mode ppu_v1_get_programmed_power_mode(struct ppu_v1_reg *ppu)
136 {
137 fwk_assert(ppu != NULL);
138
139 return (enum ppu_v1_mode)(ppu->PWPR & PPU_V1_PWPR_POLICY);
140 }
141
ppu_v1_get_operating_mode(struct ppu_v1_reg * ppu)142 enum ppu_v1_opmode ppu_v1_get_operating_mode(struct ppu_v1_reg *ppu)
143 {
144 fwk_assert(ppu != NULL);
145
146 return (enum ppu_v1_opmode)
147 ((ppu->PWSR & PPU_V1_PWSR_OP_STATUS) >> PPU_V1_PWSR_OP_STATUS_POS);
148 }
149
ppu_v1_get_programmed_operating_mode(struct ppu_v1_reg * ppu)150 enum ppu_v1_opmode ppu_v1_get_programmed_operating_mode(struct ppu_v1_reg *ppu)
151 {
152 fwk_assert(ppu != NULL);
153
154 return (enum ppu_v1_opmode)
155 ((ppu->PWPR & PPU_V1_PWPR_OP_POLICY) >> PPU_V1_PWPR_OP_POLICY_POS);
156 }
157
ppu_v1_is_dynamic_enabled(struct ppu_v1_reg * ppu)158 bool ppu_v1_is_dynamic_enabled(struct ppu_v1_reg *ppu)
159 {
160 fwk_assert(ppu != NULL);
161
162 return ((ppu->PWSR & PPU_V1_PWSR_PWR_DYN_STATUS) != 0);
163 }
164
ppu_v1_is_locked(struct ppu_v1_reg * ppu)165 bool ppu_v1_is_locked(struct ppu_v1_reg *ppu)
166 {
167 fwk_assert(ppu != NULL);
168
169 return ((ppu->PWSR & PPU_V1_PWSR_OFF_LOCK_STATUS) != 0);
170 }
171
172 /*
173 * DISR register
174 */
ppu_v1_is_power_devactive_high(struct ppu_v1_reg * ppu,enum ppu_v1_mode ppu_mode)175 bool ppu_v1_is_power_devactive_high(struct ppu_v1_reg *ppu,
176 enum ppu_v1_mode ppu_mode)
177 {
178 fwk_assert(ppu != NULL);
179
180 return (ppu->DISR &
181 (1 << (ppu_mode + PPU_V1_DISR_PWR_DEVACTIVE_STATUS_POS))) != 0;
182 }
183
ppu_v1_is_op_devactive_high(struct ppu_v1_reg * ppu,enum ppu_v1_op_devactive op_devactive)184 bool ppu_v1_is_op_devactive_high(struct ppu_v1_reg *ppu,
185 enum ppu_v1_op_devactive op_devactive)
186 {
187 fwk_assert(ppu != NULL);
188
189 return (ppu->DISR &
190 (1 << (op_devactive + PPU_V1_DISR_OP_DEVACTIVE_STATUS_POS))) != 0;
191 }
192
193 /*
194 * UNLK register
195 */
ppu_v1_off_unlock(struct ppu_v1_reg * ppu)196 void ppu_v1_off_unlock(struct ppu_v1_reg *ppu)
197 {
198 fwk_assert(ppu != NULL);
199
200 ppu->UNLK = PPU_V1_UNLK_OFF_UNLOCK;
201 }
202
203 /*
204 * PWCR register
205 */
ppu_v1_disable_devactive(struct ppu_v1_reg * ppu)206 void ppu_v1_disable_devactive(struct ppu_v1_reg *ppu)
207 {
208 fwk_assert(ppu != NULL);
209
210 ppu->PWCR &= ~PPU_V1_PWCR_DEV_ACTIVE_EN;
211 }
212
ppu_v1_disable_handshake(struct ppu_v1_reg * ppu)213 void ppu_v1_disable_handshake(struct ppu_v1_reg *ppu)
214 {
215 fwk_assert(ppu != NULL);
216
217 ppu->PWCR &= ~PPU_V1_PWCR_DEV_REQ_EN;
218 }
219
220 /*
221 * Interrupt registers: IMR, AIMR, ISR, AISR, IESR, OPSR
222 */
ppu_v1_interrupt_mask(struct ppu_v1_reg * ppu,unsigned int mask)223 void ppu_v1_interrupt_mask(struct ppu_v1_reg *ppu, unsigned int mask)
224 {
225 fwk_assert(ppu != NULL);
226
227 ppu->IMR |= mask & PPU_V1_IMR_MASK;
228 }
229
ppu_v1_additional_interrupt_mask(struct ppu_v1_reg * ppu,unsigned int mask)230 void ppu_v1_additional_interrupt_mask(struct ppu_v1_reg *ppu, unsigned int mask)
231 {
232 fwk_assert(ppu != NULL);
233
234 ppu->AIMR |= mask & PPU_V1_AIMR_MASK;
235 }
236
ppu_v1_interrupt_unmask(struct ppu_v1_reg * ppu,unsigned int mask)237 void ppu_v1_interrupt_unmask(struct ppu_v1_reg *ppu, unsigned int mask)
238 {
239 fwk_assert(ppu != NULL);
240
241 ppu->IMR &= ~(mask & PPU_V1_IMR_MASK);
242 }
243
ppu_v1_additional_interrupt_unmask(struct ppu_v1_reg * ppu,unsigned int mask)244 void ppu_v1_additional_interrupt_unmask(struct ppu_v1_reg *ppu,
245 unsigned int mask)
246 {
247 fwk_assert(ppu != NULL);
248
249 ppu->AIMR &= ~(mask & PPU_V1_AIMR_MASK);
250 }
251
ppu_v1_is_additional_interrupt_pending(struct ppu_v1_reg * ppu,unsigned int mask)252 bool ppu_v1_is_additional_interrupt_pending(struct ppu_v1_reg *ppu,
253 unsigned int mask)
254 {
255 return (ppu->AISR & (mask & PPU_V1_AISR_MASK)) != 0;
256 }
257
ppu_v1_ack_interrupt(struct ppu_v1_reg * ppu,unsigned int mask)258 void ppu_v1_ack_interrupt(struct ppu_v1_reg *ppu, unsigned int mask)
259 {
260 fwk_assert(ppu != NULL);
261
262 ppu->ISR &= mask & PPU_V1_IMR_MASK;
263 }
264
ppu_v1_ack_additional_interrupt(struct ppu_v1_reg * ppu,unsigned int mask)265 void ppu_v1_ack_additional_interrupt(struct ppu_v1_reg *ppu, unsigned int mask)
266 {
267 fwk_assert(ppu != NULL);
268
269 ppu->AISR &= mask & PPU_V1_AIMR_MASK;
270 }
271
ppu_v1_set_input_edge_sensitivity(struct ppu_v1_reg * ppu,enum ppu_v1_mode ppu_mode,enum ppu_v1_edge_sensitivity edge_sensitivity)272 void ppu_v1_set_input_edge_sensitivity(struct ppu_v1_reg *ppu,
273 enum ppu_v1_mode ppu_mode, enum ppu_v1_edge_sensitivity edge_sensitivity)
274 {
275 fwk_assert(ppu != NULL);
276 fwk_assert(ppu_mode < PPU_V1_MODE_COUNT);
277 fwk_assert((edge_sensitivity & ~PPU_V1_EDGE_SENSITIVITY_MASK) == 0);
278
279 /* Clear current settings */
280 ppu->IESR &= ~(PPU_V1_EDGE_SENSITIVITY_MASK <<
281 (ppu_mode * PPU_V1_BITS_PER_EDGE_SENSITIVITY));
282
283 /* Update settings */
284 ppu->IESR |= edge_sensitivity <<
285 (ppu_mode * PPU_V1_BITS_PER_EDGE_SENSITIVITY);
286 }
287
ppu_v1_get_input_edge_sensitivity(struct ppu_v1_reg * ppu,enum ppu_v1_mode ppu_mode)288 enum ppu_v1_edge_sensitivity ppu_v1_get_input_edge_sensitivity(
289 struct ppu_v1_reg *ppu, enum ppu_v1_mode ppu_mode)
290 {
291 fwk_assert(ppu != NULL);
292 fwk_assert(ppu_mode < PPU_V1_MODE_COUNT);
293
294 return (enum ppu_v1_edge_sensitivity)(
295 (ppu->IESR >> (ppu_mode * PPU_V1_BITS_PER_EDGE_SENSITIVITY)) &
296 PPU_V1_EDGE_SENSITIVITY_MASK);
297 }
298
ppu_v1_ack_power_active_edge_interrupt(struct ppu_v1_reg * ppu,enum ppu_v1_mode ppu_mode)299 void ppu_v1_ack_power_active_edge_interrupt(struct ppu_v1_reg *ppu,
300 enum ppu_v1_mode ppu_mode)
301 {
302 ppu->ISR = 1 << (ppu_mode + PPU_V1_ISR_ACTIVE_EDGE_POS);
303 }
304
ppu_v1_is_power_active_edge_interrupt(struct ppu_v1_reg * ppu,enum ppu_v1_mode ppu_mode)305 bool ppu_v1_is_power_active_edge_interrupt(struct ppu_v1_reg *ppu,
306 enum ppu_v1_mode ppu_mode)
307 {
308 return ppu->ISR & (1 << (ppu_mode + PPU_V1_ISR_ACTIVE_EDGE_POS));
309 }
310
ppu_v1_set_op_active_edge_sensitivity(struct ppu_v1_reg * ppu,enum ppu_v1_op_devactive op_devactive,enum ppu_v1_edge_sensitivity edge_sensitivity)311 void ppu_v1_set_op_active_edge_sensitivity(struct ppu_v1_reg *ppu,
312 enum ppu_v1_op_devactive op_devactive,
313 enum ppu_v1_edge_sensitivity edge_sensitivity)
314 {
315 fwk_assert(ppu != NULL);
316 fwk_assert(op_devactive < PPU_V1_OP_DEVACTIVE_COUNT);
317 fwk_assert((edge_sensitivity & ~PPU_V1_EDGE_SENSITIVITY_MASK) == 0);
318
319 /* Clear current settings */
320 ppu->OPSR &= ~(PPU_V1_EDGE_SENSITIVITY_MASK <<
321 (op_devactive * PPU_V1_BITS_PER_EDGE_SENSITIVITY));
322
323 /* Update settings */
324 ppu->OPSR |= edge_sensitivity <<
325 (op_devactive * PPU_V1_BITS_PER_EDGE_SENSITIVITY);
326 }
327
ppu_v1_get_op_active_edge_sensitivity(struct ppu_v1_reg * ppu,enum ppu_v1_op_devactive op_devactive)328 enum ppu_v1_edge_sensitivity ppu_v1_get_op_active_edge_sensitivity(
329 struct ppu_v1_reg *ppu, enum ppu_v1_op_devactive op_devactive)
330 {
331 fwk_assert(ppu != NULL);
332 fwk_assert(op_devactive < PPU_V1_OP_DEVACTIVE_COUNT);
333
334 return (enum ppu_v1_edge_sensitivity)(
335 (ppu->OPSR >> (op_devactive * PPU_V1_BITS_PER_EDGE_SENSITIVITY)) &
336 PPU_V1_EDGE_SENSITIVITY_MASK);
337 }
338
ppu_v1_ack_op_active_edge_interrupt(struct ppu_v1_reg * ppu,enum ppu_v1_op_devactive op_devactive)339 void ppu_v1_ack_op_active_edge_interrupt(struct ppu_v1_reg *ppu,
340 enum ppu_v1_op_devactive op_devactive)
341 {
342 ppu->ISR = 1 << (op_devactive + PPU_V1_ISR_OP_ACTIVE_EDGE_POS);
343 }
344
ppu_v1_is_op_active_edge_interrupt(struct ppu_v1_reg * ppu,enum ppu_v1_op_devactive op_devactive)345 bool ppu_v1_is_op_active_edge_interrupt(struct ppu_v1_reg *ppu,
346 enum ppu_v1_op_devactive op_devactive)
347 {
348 return ppu->ISR & (1 << (op_devactive + PPU_V1_ISR_OP_ACTIVE_EDGE_POS));
349 }
350
ppu_v1_is_dyn_policy_min_interrupt(struct ppu_v1_reg * ppu)351 bool ppu_v1_is_dyn_policy_min_interrupt(struct ppu_v1_reg *ppu)
352 {
353 return ppu->ISR & PPU_V1_ISR_DYN_POLICY_MIN_IRQ;
354 }
355
356 /*
357 * IDR0 register
358 */
ppu_v1_get_num_opmode(struct ppu_v1_reg * ppu)359 unsigned int ppu_v1_get_num_opmode(struct ppu_v1_reg *ppu)
360 {
361 return ((ppu->IDR0 & PPU_V1_IDR0_NUM_OPMODE)
362 >> PPU_V1_IDR0_NUM_OPMODE_POS) + 1;
363 }
364
365 /*
366 * AIDR register
367 */
ppu_v1_get_arch_id(struct ppu_v1_reg * ppu)368 unsigned int ppu_v1_get_arch_id(struct ppu_v1_reg *ppu)
369 {
370 fwk_assert(ppu != NULL);
371
372 return (ppu->AIDR & (PPU_V1_AIDR_ARCH_REV_MINOR |
373 PPU_V1_AIDR_ARCH_REV_MAJOR));
374 }
375
376 /*
377 * MISR register
378 */
ppu_v1_get_failure_device_id(struct ppu_v1_reg * ppu)379 unsigned int ppu_v1_get_failure_device_id(struct ppu_v1_reg *ppu)
380 {
381 fwk_assert(ppu != NULL);
382
383 return (enum ppu_v1_mode)((ppu->MISR & PPU_V1_MISR_DEVDENY_STATUS_MASK) >> PPU_V1_MISR_DEVDENY_STATUS_POS);
384 }
385
386 #endif /* CY_IP_MXS28SRSS */
387