1 /*
2  * Arm SCP/MCP Software
3  * Copyright (c) 2019-2021, Arm Limited and Contributors. All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  *
7  * Description:
8  *     Utility functions for Juno.
9  */
10 
11 #include "pl35x.h"
12 #include "scp_config.h"
13 
14 #include <fwk_assert.h>
15 
16 #include <stdbool.h>
17 #include <stddef.h>
18 #include <stdint.h>
19 
20 #define SNOOP_CONTROL_L2ACCREQ      UINT32_C(0x00000001)
21 #define SNOOP_CONTROL_L2ACCACK      UINT32_C(0x00000002)
22 
23 #define SMC_INIT_SET_CYCLES         UINT32_C(0x000251FF)
24 #define SMC_INIT_SET_OP_MODE        UINT32_C(0x00000046)
25 #define SMC_INIT_CMD_SET_CS3        UINT32_C(3U << 23)
26 #define SMC_INIT_CMD_UPDATE_REG     UINT32_C(2U << 21)
27 
juno_utils_open_snoop_gate_and_wait(volatile uint32_t * snoop_ctrl)28 void juno_utils_open_snoop_gate_and_wait(volatile uint32_t *snoop_ctrl)
29 {
30     fwk_assert(snoop_ctrl != NULL);
31 
32     *snoop_ctrl = SNOOP_CONTROL_L2ACCREQ;
33     while ((*snoop_ctrl & SNOOP_CONTROL_L2ACCACK) == 0) {
34         continue;
35     }
36 }
37 
juno_utils_close_snoop_gate(volatile uint32_t * snoop_ctrl)38 void juno_utils_close_snoop_gate(volatile uint32_t *snoop_ctrl)
39 {
40     fwk_assert(snoop_ctrl != NULL);
41 
42     *snoop_ctrl &= ~SNOOP_CONTROL_L2ACCREQ;
43 }
44 
juno_utils_atclk_clock_div_set(uint32_t divider)45 void juno_utils_atclk_clock_div_set(uint32_t divider)
46 {
47     fwk_assert(divider <= 16);
48     fwk_assert(divider != 0);
49 
50     SCP_CONFIG->ATCLK_CONTROL =
51         (SCP_CONFIG->ATCLK_CONTROL & ~SCP_CONFIG_STDCLK_CONTROL_CLKDIV_MASK) |
52         ((divider - 1) << SCP_CONFIG_STDCLK_CONTROL_CLKDIV_POS);
53 }
54 
juno_utils_atclk_clock_div_set_check(uint32_t divider)55 bool juno_utils_atclk_clock_div_set_check(uint32_t divider)
56 {
57     fwk_assert(divider <= 16);
58     fwk_assert(divider != 0);
59 
60     return
61         ((SCP_CONFIG->ATCLK_CONTROL & SCP_CONFIG_STDCLK_CONTROL_CRNTCLKDIV_MASK)
62         == ((divider - 1) << SCP_CONFIG_STDCLK_CONTROL_CRNTCLKDIV_POS));
63 }
64 
juno_utils_atclk_clock_sel_set(uint32_t source)65 void juno_utils_atclk_clock_sel_set(uint32_t source)
66 {
67     fwk_assert(source <= 2);
68 
69     SCP_CONFIG->ATCLK_CONTROL =
70         (SCP_CONFIG->ATCLK_CONTROL & ~SCP_CONFIG_STDCLK_CONTROL_CLKSEL_MASK) |
71         (source << SCP_CONFIG_STDCLK_CONTROL_CLKSEL_POS);
72 }
73 
juno_utils_atclk_clock_sel_set_check(uint32_t source)74 bool juno_utils_atclk_clock_sel_set_check(uint32_t source)
75 {
76     fwk_assert(source <= 2);
77 
78     return
79         ((SCP_CONFIG->ATCLK_CONTROL & SCP_CONFIG_STDCLK_CONTROL_CRNTCLK_MASK) ==
80         (source << SCP_CONFIG_STDCLK_CONTROL_CRNTCLK_POS));
81 }
82 
juno_utils_traceclk_clock_div_set(uint32_t divider)83 void juno_utils_traceclk_clock_div_set(uint32_t divider)
84 {
85     fwk_assert(divider <= 16);
86     fwk_assert(divider != 0);
87 
88     SCP_CONFIG->TRACECLKIN_CONTROL =
89         (SCP_CONFIG->TRACECLKIN_CONTROL &
90         ~SCP_CONFIG_STDCLK_CONTROL_CLKDIV_MASK) |
91         ((divider - 1) << SCP_CONFIG_STDCLK_CONTROL_CLKDIV_POS);
92 }
93 
juno_utils_traceclk_clock_div_set_check(uint32_t divider)94 bool juno_utils_traceclk_clock_div_set_check(uint32_t divider)
95 {
96     fwk_assert(divider <= 16);
97     fwk_assert(divider != 0);
98 
99     return ((SCP_CONFIG->TRACECLKIN_CONTROL &
100         SCP_CONFIG_STDCLK_CONTROL_CRNTCLKDIV_MASK) ==
101         ((divider - 1) << SCP_CONFIG_STDCLK_CONTROL_CRNTCLKDIV_POS));
102 }
103 
juno_utils_traceclk_clock_sel_set(uint32_t source)104 void juno_utils_traceclk_clock_sel_set(uint32_t source)
105 {
106     fwk_assert(source <= 2);
107 
108     SCP_CONFIG->TRACECLKIN_CONTROL =
109         (SCP_CONFIG->TRACECLKIN_CONTROL &
110         ~SCP_CONFIG_STDCLK_CONTROL_CLKSEL_MASK) |
111         (source << SCP_CONFIG_STDCLK_CONTROL_CLKSEL_POS);
112 }
113 
juno_utils_traceclk_clock_sel_set_check(uint32_t source)114 bool juno_utils_traceclk_clock_sel_set_check(uint32_t source)
115 {
116     fwk_assert(source <= 2);
117 
118     return ((SCP_CONFIG->TRACECLKIN_CONTROL &
119         SCP_CONFIG_STDCLK_CONTROL_CRNTCLK_MASK) ==
120         (source << SCP_CONFIG_STDCLK_CONTROL_CRNTCLK_POS));
121 }
122 
juno_utils_pclkdbg_clock_div_set(uint32_t divider)123 void juno_utils_pclkdbg_clock_div_set(uint32_t divider)
124 {
125     fwk_assert(divider <= 16);
126     fwk_assert(divider != 0);
127 
128     SCP_CONFIG->PCLKDBG_CONTROL =
129         (SCP_CONFIG->PCLKDBG_CONTROL & ~SCP_CONFIG_STDCLK_CONTROL_CLKDIV_MASK) |
130         ((divider - 1) << SCP_CONFIG_STDCLK_CONTROL_CLKDIV_POS);
131 }
132 
juno_utils_pclkdbg_clock_div_set_check(uint32_t divider)133 bool juno_utils_pclkdbg_clock_div_set_check(uint32_t divider)
134 {
135     fwk_assert(divider <= 16);
136     fwk_assert(divider != 0);
137 
138     return ((SCP_CONFIG->PCLKDBG_CONTROL &
139         SCP_CONFIG_STDCLK_CONTROL_CRNTCLKDIV_MASK) ==
140         ((divider - 1) << SCP_CONFIG_STDCLK_CONTROL_CRNTCLKDIV_POS));
141 }
142 
juno_utils_system_clock_enable(uint32_t mask)143 void juno_utils_system_clock_enable(uint32_t mask)
144 {
145     fwk_assert((mask & ~SCP_CONFIG_CLOCK_ENABLE_ALL) == 0);
146 
147     SCP_CONFIG->CLOCK_ENABLE_SET |= mask;
148     while ((SCP_CONFIG->CLOCK_ENABLE_STATUS & mask) != mask) {
149         continue;
150     }
151 }
152 
juno_utils_smc_init(void)153 void juno_utils_smc_init(void)
154 {
155     /* Switch CS3 to 32 bit mode, with read and write sync */
156     SMC->SET_CYCLES = SMC_INIT_SET_CYCLES;
157     SMC->SET_OPMODE = SMC_INIT_SET_OP_MODE;
158     SMC->DIRECT_CMD = SMC_INIT_CMD_SET_CS3 | SMC_INIT_CMD_UPDATE_REG;
159 }
160