1 /*
2 * Arm SCP/MCP Software
3 * Copyright (c) 2015-2021, Arm Limited and Contributors. All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include "ppu_v0.h"
9
10 #include <fwk_assert.h>
11 #include <fwk_status.h>
12
13 #include <stddef.h>
14
15 struct set_power_status_check_params_v0 {
16 enum ppu_v0_mode mode;
17 struct ppu_v0_reg *reg;
18 };
19
ppu_v0_set_power_status_check(void * data)20 static bool ppu_v0_set_power_status_check(void *data)
21 {
22 struct set_power_status_check_params_v0 *params;
23
24 fwk_assert(data != NULL);
25 params = (struct set_power_status_check_params_v0 *)data;
26
27 return (
28 (params->reg->POWER_STATUS &
29 (PPU_V0_PSR_POWSTAT | PPU_V0_PSR_DYNAMIC)) == params->mode);
30 }
31
ppu_v0_init(struct ppu_v0_reg * ppu)32 void ppu_v0_init(struct ppu_v0_reg *ppu)
33 {
34 fwk_assert(ppu != NULL);
35
36 /* Set mode as masked to all input edge interrupts */
37 ppu->IESR = 0;
38
39 /* Mask all interrupts */
40 ppu->IMR = PPU_V0_IMR_MASK;
41
42 /* Acknowledge any interrupt left pending */
43 ppu->ISR = PPU_V0_ISR_MASK;
44 }
45
ppu_v0_request_power_mode(struct ppu_v0_reg * ppu,enum ppu_v0_mode mode)46 int ppu_v0_request_power_mode(struct ppu_v0_reg *ppu, enum ppu_v0_mode mode)
47 {
48 uint32_t power_policy;
49 fwk_assert(ppu != NULL);
50 fwk_assert(mode < PPU_V0_MODE_COUNT);
51
52 power_policy = ppu->POWER_POLICY &
53 ~(PPU_V0_PPR_POLICY | PPU_V0_PPR_DYNAMIC_EN);
54 ppu->POWER_POLICY = power_policy | mode;
55
56 return FWK_SUCCESS;
57 }
58
ppu_v0_set_power_mode(struct ppu_v0_reg * ppu,enum ppu_v0_mode mode,struct ppu_v0_timer_ctx * timer_ctx)59 int ppu_v0_set_power_mode(
60 struct ppu_v0_reg *ppu,
61 enum ppu_v0_mode mode,
62 struct ppu_v0_timer_ctx *timer_ctx)
63 {
64 int status;
65 fwk_assert(ppu != NULL);
66 struct set_power_status_check_params_v0 params;
67
68 status = ppu_v0_request_power_mode(ppu, mode);
69 if (status != FWK_SUCCESS)
70 return status;
71 if (timer_ctx == NULL) {
72 while ((ppu->POWER_STATUS &
73 (PPU_V0_PSR_POWSTAT | PPU_V0_PSR_DYNAMIC)) != mode)
74 continue;
75 } else {
76 params.mode = mode;
77 params.reg = ppu;
78 return timer_ctx->timer_api->wait(
79 timer_ctx->timer_id,
80 timer_ctx->delay_us,
81 ppu_v0_set_power_status_check,
82 ¶ms);
83 }
84
85 return FWK_SUCCESS;
86 }
87
ppu_v0_get_power_mode(struct ppu_v0_reg * ppu,enum ppu_v0_mode * mode)88 int ppu_v0_get_power_mode(struct ppu_v0_reg *ppu, enum ppu_v0_mode *mode)
89 {
90 fwk_assert(ppu != NULL);
91 fwk_assert(mode != NULL);
92
93 *mode = (enum ppu_v0_mode)(ppu->POWER_STATUS & PPU_V0_PSR_POWSTAT);
94
95 return FWK_SUCCESS;
96 }
97