1 /*
2 * Arm SCP/MCP Software
3 * Copyright (c) 2018-2021, Arm Limited and Contributors. All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include "low_level_access.h"
9 #include "pik_scp.h"
10 #include "pik_system.h"
11 #include "synquacer_mmap.h"
12
13 #include <ppu_v0.h>
14
15 #include <fwk_macros.h>
16
17 #include <stdbool.h>
18 #include <stdint.h>
19
20 void fw_clk_init(void);
21 void fw_sysoc_init(void);
22 void fw_lpcm_init(void);
23
24 #define REG_ADDR_RSTSTA (0)
25 #define REG_ADDR_RSTSET (0x4U)
26 #define REG_ADDR_RSTCLR (0x8U)
27
28 #define LPCM_RESET_CTRL_ADDR UINT32_C(0x400)
29 #define LPCM_RESET_CTRL_OFFSET UINT32_C(0x8)
30
31 #define LPCM_RESET_STA_ADDR 0x404U
32 #define LPCM_RESET_CLR 0x1U
33
34 #define STATUS_WAIT true
35 #define STATUS_NO_WAIT false
36
37 #define REG_ADDR_RSTSTA (0)
38 #define REG_ADDR_RSTSET (0x4U)
39 #define REG_ADDR_RSTCLR (0x8U)
40
41 #define LPCM_RESET_CTRL_ADDR UINT32_C(0x400)
42 #define LPCM_RESET_CTRL_OFFSET UINT32_C(0x8)
43
44 #define LPCM_RESET_STA_ADDR 0x404U
45 #define LPCM_RESET_CLR 0x1U
46
fw_clock_pll_init(void)47 static void fw_clock_pll_init(void)
48 {
49 /* 1 bit for each cluster */
50 const uint32_t pll_mask = 0x00000FFF;
51
52 while ((PIK_SCP->PLL_STATUS[1] & pll_mask) != pll_mask ||
53 (PIK_SCP->PLL_STATUS[9] & pll_mask) != pll_mask)
54 continue;
55 }
56
pll_init(void)57 static void pll_init(void)
58 {
59 uint32_t pll_mask = PLL_STATUS_0_REFCLK | PLL_STATUS_0_SYSPLLLOCK;
60 /* Wait for PLL to lock */
61 while ((PIK_SCP->PLL_STATUS[0] & pll_mask) != pll_mask)
62 continue;
63 }
64
fw_sysoc_init(void)65 void fw_sysoc_init(void)
66 {
67 uint32_t i, value;
68
69 const uint32_t init_sysoc_addr_infos[] = {
70 CONFIG_SOC_REG_ADDR_SYSOC_DMA_TOP,
71 CONFIG_SOC_REG_ADDR_SYSOC_PCIE_TOP,
72 CONFIG_SOC_REG_ADDR_SYSOC_DDR_TOP
73 };
74
75 const uint32_t init_sysoc_reset_infos[] = { UINT32_C(0x3), /* DMA */
76 UINT32_C(0x3), /* PCIE */
77 UINT32_C(0xff),
78 /* DDR */ };
79
80 for (i = 0; i < FWK_ARRAY_SIZE(init_sysoc_addr_infos); i++) {
81 value = readl(init_sysoc_addr_infos[i] + REG_ADDR_RSTSTA);
82 if (value == 0)
83 continue; /* reset all not active */
84
85 /* reset set only active bit */
86 writel(
87 init_sysoc_addr_infos[i] + REG_ADDR_RSTCLR,
88 (init_sysoc_reset_infos[i] & value));
89
90 while ((readl(init_sysoc_addr_infos[i] + REG_ADDR_RSTSTA) &
91 init_sysoc_reset_infos[i]) != 0)
92 ;
93 }
94 }
95
fw_lpcm_init(void)96 void fw_lpcm_init(void)
97 {
98 uint32_t i, j;
99
100 const uint32_t lpcm_reset_addr_infos[] = {
101 CONFIG_SOC_LPCM_PCIE_TOP_ADDR + LPCM_RESET_CTRL_ADDR,
102 CONFIG_SOC_LPCM_DMAB_TOP_ADDR + LPCM_RESET_CTRL_ADDR
103 };
104
105 const uint32_t lpcm_reset_flag[] = { CONFIG_SOC_LPCM_PCIE_RESET_FLAG,
106 CONFIG_SOC_LPCM_DMAB_RESET_FLAG };
107
108 for (i = 0; i < FWK_ARRAY_SIZE(lpcm_reset_addr_infos); i++) {
109 for (j = 0; j < (sizeof(uint32_t) * 8); j++) {
110 if ((lpcm_reset_flag[i] & (0x1U << j)) == 0)
111 continue; /* no reset signal */
112
113 /* reset clr set lpcm reset_ctrl*/
114 writel(
115 lpcm_reset_addr_infos[i] + (LPCM_RESET_CTRL_OFFSET * j),
116 LPCM_RESET_CLR);
117 }
118 }
119 }
120
set_clkforce_set(void)121 static void set_clkforce_set(void)
122 {
123 /* 0x0A04 : CLKFORCE_SET HW BUG WORKAROUND bit8 bit6 bit 2 */
124 /* 0 = clock gated. 1 = Clock is forced to always operate. */
125 /* bit8 : SYSPLLCLKDBGFORCE*/
126 /* bit7 : DMCCLKFORCE */
127 /* bit6 : SYSPERCLKFORCE */
128 /* bit5 : PCLKSCPFORCE */
129 /* bit2 : CCNCLKFORCE */
130 /* bit0 : PPUCLKFORCE */
131 PIK_SYSTEM->CLKFORCE_SET = 0x00000144U;
132 }
133
fw_clear_clkforce(uint32_t value)134 void fw_clear_clkforce(uint32_t value)
135 {
136 /*
137 * Writing 1 to a bit enables dynamic hardware clock-gating.
138 * Writing 0 to a bit is ignored.
139 * bit8 : SYSPLLCLKDBGFORCE
140 * bit7 : DMCCLKFORCE
141 * bit6 : SYSPERCLKFORCE
142 * bit5 : PCLKSCPFORCE
143 * bit2 : CCNCLKFORCE
144 * bit0 : PPUCLKFORCE
145 */
146 PIK_SYSTEM->CLKFORCE_CLR = value;
147 }
148
fw_get_clkforce_status(void)149 uint32_t fw_get_clkforce_status(void)
150 {
151 return PIK_SYSTEM->CLKFORCE_STATUS;
152 }
153
154 static struct ppu_v0_reg *const ppu_reg_p[] = {
155 (struct ppu_v0_reg *)0x50041000, /* SYS-LOGIC-PPU0 */
156 (struct ppu_v0_reg *)0x50042000, /* SYS-L3RAM0-PPU0 */
157 (struct ppu_v0_reg *)0x50043000, /* SYS-L3RAM1-PPU0 */
158 (struct ppu_v0_reg *)0x50044000, /* SYS-SFRAM-PPU0 */
159 (struct ppu_v0_reg *)0x50045000, /* SYS-SRAM-PPU0 */
160 (struct ppu_v0_reg *)0x50021000, /* SYS-DEBUG-PPU0 */
161 };
162
peri_ppu_on(void)163 static void peri_ppu_on(void)
164 {
165 uint32_t i;
166
167 for (i = 0; i < FWK_ARRAY_SIZE(ppu_reg_p); i++)
168 ppu_reg_p[i]->POWER_POLICY = PPU_V0_MODE_ON;
169 }
170
peri_ppu_wait(void)171 static void peri_ppu_wait(void)
172 {
173 uint32_t i;
174
175 for (i = 0; i < FWK_ARRAY_SIZE(ppu_reg_p); i++) {
176 while ((ppu_reg_p[i]->POWER_STATUS & PPU_V0_PSR_POWSTAT) !=
177 PPU_V0_MODE_ON)
178 ;
179 }
180 }
181
fw_clk_init(void)182 void fw_clk_init(void)
183 {
184 pll_init();
185 set_clkforce_set();
186
187 peri_ppu_on();
188
189 fw_clock_pll_init();
190
191 peri_ppu_wait();
192 }
193
fw_sram_sysoc_init(void)194 static void fw_sram_sysoc_init(void)
195 {
196 uint32_t i, value;
197
198 const uint32_t init_sysoc_addr_infos[] = CONFIG_SOC_INIT_SYSOC_ADDR_INFOS;
199 const uint32_t init_sysoc_reset_infos[] = CONFIG_SOC_INIT_SYSOC_RESET_INFOS;
200
201 for (i = 0; i < FWK_ARRAY_SIZE(init_sysoc_addr_infos); i++) {
202 value = readl(init_sysoc_addr_infos[i] + REG_ADDR_RSTSTA);
203 if (value == 0)
204 continue; /* reset all not active */
205
206 /* reset set only active bit */
207 writel(
208 (init_sysoc_addr_infos[i] + REG_ADDR_RSTCLR),
209 (init_sysoc_reset_infos[i] & value));
210
211 while ((readl(init_sysoc_addr_infos[i] + REG_ADDR_RSTSTA) &
212 init_sysoc_reset_infos[i]) != 0)
213 ;
214 }
215 }
216
fw_sram_lpcm_init(void)217 static void fw_sram_lpcm_init(void)
218 {
219 /* reset clr set lpcm reset_ctrl*/
220 writel(CONFIG_SOC_LPCM_SCB_TOP_ADDR + LPCM_RESET_CTRL_ADDR, LPCM_RESET_CLR);
221 }
222
synquacer_system_init(void)223 void synquacer_system_init(void)
224 {
225 fw_sram_sysoc_init();
226
227 fw_sram_lpcm_init();
228
229 fw_clk_init();
230
231 fw_sysoc_init();
232
233 fw_lpcm_init();
234 }
235